Using Angular touch with dragging on tablets

767 views
Skip to first unread message

si...@jsplumbtoolkit.com

unread,
May 9, 2014, 7:50:05 PM5/9/14
to jsp...@googlegroups.com
This is a placeholder...details to follow.

David Conlisk

unread,
May 13, 2014, 6:23:58 AM5/13/14
to jsp...@googlegroups.com
Hi Simon,

Firstly, I'm loving using jsPlumb. It's a great library and much respect to you for releasing it and for running such an active community - keep up the good work! :)

I was having serious problems getting click and drag events to work together on my tablet (Samsung Nexus 10 running Chrome) using angular and jsPlumb with jQuery and jQuery UI. I was using ng-click for the click event for the draggable objects, and calling jsPlumb.draggable to make them draggable. I was also using jquery.ui.touch-punch. Dragging worked fine, but the click wouldn't fire. If I removed the call to draggable, then the click fired fine, but obviously no dragging. After much trial and error with jQuery mobile, jGestures, and even StackOverflow (!) I reached the following solution:

- upgraded to jsPlumb v1.6.1 from 1.5.5 as you suggested (not sure if this had an effect or not)
- used angular-gestures (rather than ngTouch or hmTouchEvents) to implement hammer.js with angular (https://github.com/wzr1337/angular-gestures)
- replaced calls to ng-click with calls to hm-tap to implement the click events
- replaced calls to jsPlumb.draggable with calls to the standard jQuery draggable function. This means that I need to call jsPlumb's repaint function in the drag and stop events for the drag. This works, but the connections do lag behind the object visually when dragging, but this corrects itself when you stop dragging (not a serious issue, but looks less slick than on a desktop).

My issues now revolve around the following:

- when dragging a connection on the desktop and you get close to the edge of the visible area, the area will scroll. For some reason on the tablet the calls to ng-mousemove are not firing like they do on the desktop - but ONLY for connections, this works fine for objects
- on an iPhone or iPad when dragging objects the screen jumps to the top-left intermittently, which makes the system basically unusable (though frustratingly close to being usable!)

I'm not convinced the remaining issues have anything to do with jsPlumb, but any information, insight or best practices you might suggest here would be greatly appreciated! Maybe the conversation will be of use to other jsPlumb users as well. Also, it's possible that there is a better way to use jsPlumb with angular to work on mobile? If so I'm all ears, and willing to test and report back :)

Thanks,

David

Simon Porritt

unread,
May 13, 2014, 6:36:11 AM5/13/14
to jsp...@googlegroups.com
It wasn't just an upgrade to 1.6.1 I suggested, but to also switch from using the jQuery version to using the 'vanilla' version, which has built in support for touch events:


..and which also supports multiple element drag:




Message has been deleted

Simon Porritt

unread,
May 13, 2014, 6:42:51 AM5/13/14
to jsp...@googlegroups.com
What is the angular gestures stuff in there for?

David Conlisk

unread,
May 13, 2014, 6:43:20 AM5/13/14
to jsp...@googlegroups.com
Hi Simon,

Apologies, I'd forgotten to mention that part, but yes, I'm using dom.jsPlumb-1.6.1.js now instead of the jQuery version.

David

David Conlisk

unread,
May 13, 2014, 6:57:52 AM5/13/14
to jsp...@googlegroups.com
Hi Simon,

The angular-gestures stuff is in there to wrap hammer.js so I can use it with angular. That way I can use hm-tap instead of ng-click events, which seem to work. Do you think I shouldn't need to use that? If so, how would you suggest implementing the click events in angular?

Thanks!

David

Simon Porritt

unread,
May 13, 2014, 7:10:22 AM5/13/14
to jsp...@googlegroups.com

I think that it might be best to take as much stuff as possible out of the page and gradually re-introduce things, so, yes, I’d say take that out - and jQuery/jQuery UI, if you can - and test out the jsPlumb side of things.

If you get it going then you might want to then think about binding tap/click events through jsPlumb, because it uses a library (https://github.com/jsplumb/mottle) that offers tap events which fall back to click on non-touch devices.

this is not documented at the moment. i keep meaning to do a blog post about. basically you can do this:

jsPlumb.on(someSelector, "tap", function(e) {

});

it’s also not been tested by anyone outside of jsPlumb, so, er, your results may vary. I mention it only because the fewer things you have in your page, the better.

also, I should point out that the asynchronous nature of element rendering in Angular means that it’s not always clear when something is ready to have event listeners bound. But I assume you’ve already figured out a way around that.

David Conlisk

unread,
May 15, 2014, 6:54:01 AM5/15/14
to jsp...@googlegroups.com
I'm working around the asynchronous nature of angular successfully as you mentioned (so far at least!).

I don't want to remove jQuery entirely as I have a lot of existing code that depends on it ($.each loops, etc) and would be difficult and verbose to replace at this stage.

But I'm trying to get a minimal version as you suggested, so I've removed all javascript libraries except angular, jquery and jsplumb, and I'm trying to use jsPlumb.on to hook up the click events as you described.

A couple of questions:

- I was configuring the draggable call with functions like start(event, ui), stop(event, ui), etc. But now ui is undefined. How can I access the left and top co-ordinates of the tap event in these functions using vanilla jsPlumb?
- when calling the function 

    instance.on("#protocol-view", "tap", function (e) {
$scope.chartClicked(e);
});

What is e and what properties are available? Can I call e.preventDefault or e.stopPropagation for example? My problem is that I can't stop clicks on jsplumb draggable objects from propagating to the parent div behind the objects when the user clicks, where both the draggable objects and the container div have the tap events defined (as above code). 

Simon Porritt

unread,
May 15, 2014, 7:16:23 AM5/15/14
to jsp...@googlegroups.com
The library being used under the hood is katavorio:


At the bottom of the readme you'll see the params for the various callbacks.

David Conlisk

unread,
May 15, 2014, 9:29:55 AM5/15/14
to jsp...@googlegroups.com
Thanks Simon, that works for the draggable functions, but I can't seem to work out what object is passed to the function here (i.e. e):

instance.on(document.querySelectorAll("#test"), "tap", function (e) {
console.log("What is e here?");
});

I've also noticed that the tap and drag events both fire for a mouse click on the desktop when using the vanilla jsPlumb (I haven't tested on a device yet). I've created a fiddler here to illustrate: http://jsfiddle.net/LAGpW/3/ (I hope you don't mind but I've linked directly to jsplumb on your server). Actually, testing that jsfiddle page on my device and neither the click nor the drag works. Any ideas what I've done wrong here?

Simon Porritt

unread,
May 17, 2014, 12:11:54 AM5/17/14
to jsp...@googlegroups.com

I updated the fiddle a little and it works for me on the desktop now:

http://jsfiddle.net/LAGpW/13/

as well as on my android phone. but on the iPad the yellow div bleeds out over the page and tapping the blue div takes me variously to twitter or to facebook; somehow it’s trying to get me to like things or whatever.

The only real change I made was to use a string selector to the on call.

I saw on the desktop you get a drag start followed by a tap and then a drag end, but of course the element hasn’t actually moved. I’m not sure what effect it would have on jsPlumb if I were to change that behaviour in Katavorio.

In an earlier message I said the library being used under the hood is katavorio. That’s actually only for dragging. For event handling it’s https://github.com/sporritt/mottle.

David Conlisk

unread,
May 19, 2014, 6:31:27 AM5/19/14
to jsp...@googlegroups.com
Your fiddle works perfectly on desktop and on iPhone for me. Thanks for that.

In the mottle documentation there is no information on what the function signature is for aFunction? Does it take an event object as a parameter, and if so, what attributes does that object have? I need to get the x and y co-ordinates of the click events.

Simon Porritt

unread,
May 19, 2014, 7:55:15 AM5/19/14
to jsp...@googlegroups.com

I should probably update the Mottle docs if people are going to use the project...

The callback is given an Event. A browser Event.

Simon Porritt

unread,
May 19, 2014, 6:19:08 PM5/19/14
to jsp...@googlegroups.com

….I was writing that last reply on my phone. Whenever I do that I get frustrated quickly and end up writing far fewer words than I had intended.

Anyway so it’s a native browser Event, meaning it doesn’t have the layer of normalisation that jQuery and other libraries give you. In practise this is not much of a drama, in my experience, but there are a couple of small things that can catch you out. One such thing is the fact that in older versions of IE there is no stopPropagation or preventDefault method on the Event object; you have to use event.returnValue = false instead. To deal with that Mottle offers a static method:

Mottle.consume(someEvent);

another static method Mottle has is one that can get you the “page location” of some event (because the information used to determine this can vary amongst desktop browsers, and touch events introduce further differences):

Mottle.pageLocation(someEvent)

For touch events with multiple touches, the location of the first touch is the one that is used.

Reply all
Reply to author
Forward
0 new messages