When you add drag and drop to a web page using JavaScript, such as jQuery UI draggable and droppable, how do you get this to work when viewed via a browser on a mobile device - where the touch-screen actions for dragging are intercepted by the phone for scrolling around the page etc?
All solutions welcome... my initial thoughts are:
Have a button for mobile devices that "lifts" the item to be dragged and then get them to click the zone they want to drop the item on.
Write an app that does this for mobile devices rather then try and get the web page to work on them!
Your suggestions and comments please.
jQuery UI Touch Punch just solves it all.
It's a Touch Event Support for jQuery UI. Basically, it just wires touch event back to jQuery UI.
Tested on iPad, iPhone, Android and other touch-enabled mobile devices.
I used jQuery UI sortable and it works like a charm.
http://touchpunch.furf.com/
There is a new polyfill for translating touch events to drag-and-drop, such that HTML5 Drag And Drop is utilizable on mobile.
The polyfill was introduced by Bernardo Castilho on this post.
Here's a demo from that post.
The post also presents several considerations of the folyfill design.
I needed to create a drag and drop + rotation that works on desktop, mobile, tablet including windows phone. The last one made it more complicated (mspointer vs. touch events).
The solution came from The great Greensock library
It took some jumping through hoops to make the same object draggable and rotatable but it works perfectly
The beta version of Sencha Touch has drag and drop support.
You can refer to their DnD Example. This only works on webkit browsers by the way.
Retrofitting that logic into a web page is probably going to be difficult. As I understand it they disable all browser panning and implement panning events entirely in javascript, allowing correct interpretation of drag and drop.
Update: the original example link is dead, but I found this alternative:
https://github.com/kostysh/Drag-Drop-example-for-Sencha-Touch
The Sortable JS library is compatible with touch screens and does not require jQuery.
The library size is 43KB.
The official website states in a video that this library is running faster than JQuery UI Sortable.
You might as well give a try to Tim Ruffle's drag-n-drop polyfill, certainly similar to Bernardo Castilho's one (see #remdevtec answer).
Simply do npm install mobile-drag-drop --save (other installation methods available, e.g. with bower)
Then, any element interface relying on touch detection should work on mobile (e.g. dragging only an element, instead of scrolling + dragging at the same time).
Jquery Touch Punch is great but what it also does is disable all the controls on the draggable div so to prevent this you have to alter the lines... (at the time of writing - line 75)
change
if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])){
to read
if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0]) || event.originalEvent.target.localName === 'textarea'
|| event.originalEvent.target.localName === 'input' || event.originalEvent.target.localName === 'button' || event.originalEvent.target.localName === 'li'
|| event.originalEvent.target.localName === 'a'
|| event.originalEvent.target.localName === 'select' || event.originalEvent.target.localName === 'img') {
add as many ors as you want for each of the elements you want to 'unlock'
Hope that helps someone
here is my solution:
$(el).on('touchstart', function(e) {
var link = $(e.target.parentNode).closest('a')
if(link.length > 0) {
window.location.href = link.attr('href');
}
});
For vue 3, there is https://github.com/SortableJS/vue.draggable.next
For vue 2, it's https://github.com/SortableJS/Vue.Draggable
The latter you can use like this:
<draggable v-model="myArray" group="people" #start="drag=true" #end="drag=false">
<div v-for="element in myArray" :key="element.id">{{element.name}}</div>
</draggable>
These are based on sortable.js
Related
How can I detect if the screen is inverted on at least iOS in Cordova? More specifically I’m looking to support the iOS 11 “smart invert” feature, however it doesn’t matter if this “invert detection” is also triggered by the “classic invert.”
I’ve seen the phonegap accessibility plugin, but I don’t see how to utilize it for this case without simply setting an interval to check it over and over again, which seems like too much of a hack to me. I’m looking for an event-based approach if possible.
Reading further, I missed the fact that the phonegap-mobile-accessibility plugin has events that you can listen to, including for invert colors. As such, using this plugin, you can bind an event as shown below:
window.addEventListener(
MobileAccessibilityNotifications.INVERT_COLORS_STATUS_CHANGED,
info => { // info.isInvertColorsEnabled });
As well, you can check the status at any time (e.g. on page load) like so:
MobileAccessibility.isInvertColorsEnabled(
b => { // typeof b == “boolean” });
I recently realized that the checkboxes take really long to respond to tapping. I am already using fastclick.js to remove the 300ms slowness caused by mobile devices waiting for double tapping.
I noticed that jQuery mobile uses some kind of technique to completely remove the lag when tapping multiple checkboxes very quickly. From what I have read elsewhere there seems to be a problem with mobiles when using click events rather than tap events, but haven't been able to find code to achieve this anywhere.
I would use a custom jQuery mobile build to take advantage of this, but what I am working on is already too heavy, so having the code that replaces click with tap for mobile, I would be really grateful!
The best approach is to use a library that handles touch events. There are many including these:
Hammer.js - 3kb gzipped
Zepto.js - 9.2kb gzipped
Quojs - 6kb gzipped
jGestures
Zepto is like a mini-jQuery and does a lot more than touch events, however it is designed in nice modules, one of which is the touch events module. One option if you don't want to include an entire library and you are using jQuery is to only include the touch module from zepto. Try using this code from github taking care to replace the last line from })(Zepto) to })(jQuery) and it should just work.
Some googling found this related SO question, with some good answers:
How to use jQuery Mobile for its touch event support only (no UI enhancements)?
I'm using this jQuery plugin to get a one-page scroll effect.
However, as you can see on this page, it doesn't work and instead just locks the scroll.
jQuery is working fine - I can run an alert for example. Might the CSS file that comes with the plugin be conflicting with my existing one?
Thanks in advance for your help!
If you want more compatibility with old browsers such as IE8, 9, Opera 12... and some more functionalities, here's another great plugin for it, is called fullPage.js:
Demo
Page
Some features it adds to the one you are using:
Use it over IE 8 and old browsers with no CSS 3 support.
Compatibility with touch devices
Plenty of more options and functions
Scroll bar for a better UX experience
Use of anchors in the URL
Add a live menu.
Slide throw the page using the keyboard shorcuts (arrows, spacebar, pageUp/pageDown, home, end...)
Add horizontal sliders.
please try to call these two files from your server
https://raw.github.com/peachananr/onepage-scroll/master/jquery.onepage-scroll.min.js
https://raw.github.com/peachananr/onepage-scroll/master/jquery.onepage-scroll.js
It is to prevent XSS (cross-site scripting) attacks Check more details about it
Ideally I can do $(document.body).on("tap", "#myElement", this.eventHandler);
But jQuery hasn't done that yet.
I see so many libraries -- https://github.com/bebraw/jswiki/wiki/Touch. There's a long list on that page.
They all seem to use old fashioned event listening. Such as, $("#element").touchLibraryThingy(); $("#element").bind("tap"). Equivalent to addEventListener.
That's great for an ID (Sorta), but when I have 50 list items that all have events on them, I don't want someone on an old Android to have 50 event listeners. For performance reasons!
Does anyone know of a library that uses event delegation that is finished?
This stackoverflow question is similar but doesn't come to truth -- Extend jQuery's .on() to work with mobile touch events
Looks like the blob mentioned in the post Extend jQuery's .on() to work with mobile touch events actually does the trick... almost.
Link to library! https://github.com/jvduf/jquery-mobile-events/blob/master/jquery.mobile.events.js
The gotcha
"tap" on desktop doesn't prevent default it seems. I had odd scrolling behavior and choppy menu animation in my web app.
To fix this I created a global property inside my app's namespace:
var R = window.R = window.R || {};
R.touchEvent = ('ontouchstart' in window') ? "tap" : "click";
window.$body = $(document.body);
Then all my event listeners do this:
$body.on(R.touchEvent, ".myHellaLongListItems", this.eventHandler);
Done! Now we all can have a really nice mobile website.
Better yet, now with jQuery Mobile custom builder, you can only select their mobile events and get the latest touch code, which has improvements over the example above.
http://jquerymobile.com/download-builder/
Is it standard practice to hold an entire project at a certain release of jQuery until I can fix one measly bug?
details:
I'm using an older version of qTip because that is what works with jQuery 1.4.2 (the current release when I started the project). It's important to note that the release candidate of qTip does not work with the currently stable jQuery.
A bug showed up in my qTip functionality where the tool-tips starting animating themselves in from off-screen whereas they should pop-up on the element on mouse-over.
Needless to say, I thought I had broke something but eventually noticed that jQuery had moved up a notch so I moved back to jQuery 1.4.2 and viola, tool-tips work as expected.
Now I don't know what to do; I want to keep the project at the current and stable jQuery library but I'm not sure how to debug for something like this.
Also, I don't feel I should be submitting bugs to an old version of an app, either, but maybe I am wrong.
Thanks in advance.
On qTip library replace the line
if(typeof $(this).data('qtip') == 'object')
with
if($(this).data('qtip') !== null && typeof $(this).data('qtip') == 'object')
Good Luck!