One-com / knockout-dragdrop

A drag and drop binding for Knockout.
BSD 3-Clause "New" or "Revised" License
85 stars 29 forks source link

Supporting touch events #19

Closed DenEwout closed 9 years ago

DenEwout commented 10 years ago

Hi,

I'm using knockout-dragdrop for a project of mine which requires support for touch-devices. This is sadly not supported by knockout-dragdrop.

I looked in the source code, would it be as easy to just add the correct events to the already present mouse events? (or perhaps create a simple mapping to have them map to one event?)

I'll fork to investigate/add this feature myself. But any help/tips would be appreciated.

Kind Regards,

@DenEwout

DenEwout commented 10 years ago

After checking this out in more detail, I'm a bit confused about the following things:

I'm talking about the "mouseup.startdrag" event.

// @ line 451
$(element).one('mouseup.startdrag click.startdrag mouseleave.startdrag', function (event) {
    $(element).off('mousemove.startdrag');
    $(document).off('selectstart.drag');
    return true;
});

and

// @ line 366
$(element).off('mouseup.startdrag click.startdrag mouseleave.startdrag mousemove.startdrag');

Also, would it be correct to ignore all "selectstart" code, since this is a text selection event?

IanYates commented 10 years ago

Which touch devices - Apple/WebKit or Microsoft? One uses touch events and the other has pointer events (and tends to fall back to mouse events fairly well). I've relied on hammer.js to sort out that mess for me... I hadn't tried this library with touch yet - I'm keen to see what problems/solutions are found.

DenEwout commented 10 years ago

Mainly targeting iPad, but should also work on other devices.

sunesimonsen commented 10 years ago

Sorry for the radio silence. I don't think it would be very complicated to add touch support and it is definitely something we are going to support at some point when we need it for one of our applications.

I think it should be done this way: long press starts the dragging operation, when you end the touch the item is dropped. If multiple touches are present the operation is cancelled.

You'll need to setup touch events to start the dragging operation parallel to what I do for mouse events. And update the coordinates for the drag element. You probably have to normalized events to have clientX, clientY, pageX, pageY if jquery not already done it for you.

What's the effect of using the following syntax? .on('mouseup.startdrag',function(){...})

It is just an event namespace in jquery eventType.namespace, you use that to make it easy to turn off the handler again.

Kind regards Sune

sunesimonsen commented 10 years ago

This Guy seems to have experimented with touch maybe there is something to learn: https://github.com/WinstonFassett/knockout-dragdrop/commits/dev

DenEwout commented 10 years ago

Hi, thanks for the reply. For now I implemented my own, using jQuery UI draggable/dropable and jQuery UI Touch Punch. The code to do this was fairly straightforward using the following bindingHandlers:

    ko.bindingHandlers.draggable = {
        init: function (element, valueAccessor) {
            var options = ko.utils.unwrapObservable(valueAccessor());
            $(element).draggable(options['options']);
        }
    }

    ko.bindingHandlers.droppable = {
        init: function (element, valueAccessor) {
            var options = ko.utils.unwrapObservable(valueAccessor());
            $(element).droppable({
                        drop: function (event, ui) {
                            var data = ko.dataFor(ui.draggable[0]);
                            options.drop(event,data,options['dropArguments']);
                        }
                    }
            )
            ;
        }
    }

And the following bindings in my html:

<div data-bind="droppable: {
                                        dropArguments : $data,
                                        drop: function(event,data,model){
                                                model.drop(event,data);
                                            }
                                        }">

<div data-bind="draggable: {options:{helper: 'clone'}}">

This code is very quick and hackish, so it's bound to contain bugs. If I have any spare time I'll look further into implementing in this project.

sunesimonsen commented 10 years ago

Great that you solved your problem. I'll try to remember to inform you if we implement touch support; otherwise jquery UI is probably a suitable match. Just be aware the jquery plugins usually have a hard time if the drop targets gets updated while you are dragging, that was the main reason for implementing a Knockout specific binding handler for us.

Kind regards Sune

stretch4x4 commented 9 years ago

Has anyone looked at this any further? Currently in chrome on a windows touchscreen we can't click and drag as it just scrolls the container instead. I guess I will have to have a closer look tomorrow..

sunesimonsen commented 9 years ago

No there has not been any attempts to support touch yet. At some point we will need it at One.com and implement it, but we are of cause open to pull request ;-)

Kind regards Sune On Jun 15, 2015 9:14 AM, "stretch4x4" notifications@github.com wrote:

Has anyone looked at this any further? Currently in chrome on a windows touchscreen we can't click and drag as it just scrolls the container instead. I guess I will have to have a closer look tomorrow..

— Reply to this email directly or view it on GitHub https://github.com/One-com/knockout-dragdrop/issues/19#issuecomment-111962395 .

sunesimonsen commented 9 years ago

26 added initial touch support, there are still some limitations where you stop getting move events when the element you started the drag on is removed from the dom.