Extend jQuery's .on() to work with mobile touch events - javascript

I am attempting to use the jQuery mobile events without the rest of jQuery mobile.
https://github.com/jvduf/jquery-mobile-events/blob/master/jquery.mobile.events.js
That snippet enables them all, and works fine, but not with the .on() event handler. E.g:
$('a').on('tap',function(){
console.log('Hi there!');
});
However it does work with .live(), but that is now depreciated.
So my question; is there a a way to extend the .on() functionality to include the tap event and others? Full list below:
touchstart
touchmove
touchend
orientationchange
tap
taphold
swipe
swipeleft
swiperight
scrollstart
scrollstop
Thanks :)

However it does work with .live(), but that is now depreciated.
So I take it that you want to use event delegation to preserve those events on replaced elements. That would mean that this:
$('a').on('tap',function () {
console.log('Hi there!');
});
would need to change to something like:
$(document).on('tap', 'a', function () {
console.log('Hi there!');
});
in order for it to behave the same as $("a").live("tap", ...

Maybe it should be better to extend the JQuery event code for mobile and desktop.
One way to do this is to use the JQuery vmouse (virtual mouse) plugin.
From vmouse plugin comments:
// This plugin is an experiment for abstracting away the touch and mouse
// events so that developers don't have to worry about which method of input
// the device their document is loaded on supports.
//
// The idea here is to allow the developer to register listeners for the
// basic mouse events, such as mousedown, mousemove, mouseup, and click,
// and the plugin will take care of registering the correct listeners
// behind the scenes to invoke the listener at the fastest possible time
// for that device, while still retaining the order of event firing in
// the traditional mouse environment, should multiple handlers be registered
// on the same element for different events.
//
// The current version exposes the following virtual events to jQuery bind methods:
// "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel"
For a better explanation, see https://coderwall.com/p/bdxjzg
vmouse plugin: https://github.com/jquery/jquery-mobile/blob/master/js/jquery.mobile.vmouse.js
Also see this link about current state of (touch) events: http://blogs.adobe.com/adobeandjquery/2011/03/07/the-current-state-of-touch-events/

Related

jQuery and jQuery Mobile : tap vs touchstart, touchend, touchmove and click?

Does the jQuery Mobile Tap corresponds to adding an event listener to an element like this:
myElement.addEventListener("touchstart", touchStartHandler, false);
If so, what about the remaining normal events such as touchmove, touchend and so on? I mean what is their equivalent in jQuery Mobile?
Thank you for guiding me.
Internally tap makes use of vclick.
If you don't find an event in this list, they aren't exposed with the same name: https://api.jquerymobile.com/category/events/
This means, for example: if you need to handle touchstart, touchend and touchmove, as normally is, you will probably end up to use the set of virtualized mouse event handler: vmousedown, vmousemove, vmouseup and vclick but you may need to handle the status of the pointer (mouse or finger) by yourself. Do not forget to handle vmousecancel.
Moreover, you should note that there is a delay to wait for some events.
Following is a short extract for you, from the jQuery Mobile documentation with some critical concepts for touch devices (mobile or modern hybrid laptops) to pay attention to:
Webkit based browsers synthesize mousedown, mouseup, and click events
roughly 300ms after the touchend event is dispatched.
The jQuery Mobile taphold triggers after 750ms.
After 1500ms, then it is not a touch event. Scroll, TouchMove and
TouchEnd events use this. The block list is cleared.
We recommend using click instead of vclick anytime the action being
triggered has the possibility of changing the content underneath the
point that was touched on screen. This includes page transitions and
other behaviors such as collapse/expand that could result in the
screen shifting or content being completely replaced.
Have a nice day
I dont know if is exactly the same way they do the handle, but both of they wait for an action and then execute funciton.
in jquery mobile you can do
$("p").on("taphold",function(){
$(this).hide();
});
and
$(function(){
$( "div.box" ).bind( "tap", tapHandler );
function tapHandler( event ){
$( event.target ).addClass( "tap" );
}
});
list of events https://api.jquerymobile.com/category/events/

Famo.us attaching click and touchstart events

I'm wondering how to bind both events "click" and "touchstart" within a single line:
Engine.on("click"), function(){ aCode() }
Engine.on("touchstart", function(){ aCode() }
I expected something like this (as it is implemented in some other frameworks):
Engine.on("click touchstart", function(e){ aCode() });
My current workaround is chaining them:
Engine.on("click", function(){Engine.emit("touchstart")});
Engine.on("touchstart", function() { aCode() }
Is there a better practice for this ? The problem is that click is not caught on iOS nor the touchstart with a mouse on desktop… obviously I would like to handle the event the same way whatever the device.
[EDIT] For handling the click and touchstart->touchend in the same way, just use the FastClick override shim.
just add:
FastClick = require('famous/inputs/FastClick');
then this will also work on tablet:
anElement.on("click", function(){alert("Click caught")})
Another alternative is using this helper:
function onEvent(source, events, callback)
{
for (var event in events)
{
source.on(events[event], function(e) {
callback(e);
});
}
}
Then:
onEvent(Famous.Engine, ["click","touchstart"],function(){});
The on() method in Famo.us only accepts one event type. It doesn't do any jQuery style string processing to determine separate events. In theory you could have an event named get to the chopper
What I do when creating my custom views however is create a bindEvents() function which groups all the event listeners together. The only code in these handlers are other functions. If I wanted to react to two different events in the same way, I'd just use the same function for both of them.
// An example Class demonstrating events - some off-topic parts omitted
function myLovelyHorseButton() {
// Recomended Reading: https://famo.us/guides/dev/events.html
this._eventInput = new EventHandler();
this._eventOutput = new EventHandler();
this._eventInput.pipe(this.sync);
this.sync.pipe(this._eventInput);
EventHandler.setInputHandler(this, this._eventInput);
EventHandler.setOutputHandler(this, this._eventOutput);
/** Set options & variables
/* ...
*/
// create event listeners for this specific instance
_bindEvents.call(this);
};
// bind all the events for the button
function _bindEvents() {
//Call event handlers with this set to owner.
this._eventInput.bindThis(this);
// listen for events
this._eventInput.on('click', _handleClick);
this._eventInput.on('touchstart', _handleClick); //Same as 'click'
};
// Nay to the console on click/touch
function _handleClick(event) {
console.log('Nayyyyy!!!');
};
// create an instance of myLovelyHorseButton
var button = new myLovelyHorseButton;
// We would then add the button to the Render Tree
mainContext.add(button);
There is a big reason why you don't want to do the chaining pattern you're currently using. And that's because by emitting a touchstart event on a click, you're inferring that there's going to be some code there to act upon it. One day you might get drunk and decide "Nobody on touch devices is using this!" and delete the ontouchstart handler. And in an instant, your code doesn't work for anybody, touch or mouse.
TL;DR There is nothing wrong with using multiple on() calls.
I hope this helps.

jQuery $(window).blur vs native window.onblur

What are the advantages of using jQuery's
$(window).blur(function() { ... })
to attach an event handler versus setting it directly with
window.onblur = function() { ... }
It seems that the latter is less robust because it only supports one blur handler, and when used with other packages, other code might override the window.blur value with another function. However, couldn't this also happen with the jQuery implementation too, which presumably uses window.blur as its underlying implementation?
EDIT: Several people have also mentioned the window.addEventListener alternative, which can be used to add an 'onblur' event apart from the methods above.
$(window).blur(function() { ... })
Lets you add one or more event handlers.
window.onblur = function() { ... }
Lets you only have one event handler handling the blur event.
The former uses the jQuery's own event handle mechanism. The call to .blur() will delegate to jQuery.fn.on() which in turn will delegate to jQuery.event.add. This add() method will create it's own handler for the given event type and tell addEventListener() to call this handler whenever a event of given type is fired. So basically jQuery has it's own way of event handling which relies on addEventListener() to execute properly.
The latter is just an attribute which can only contain one value so queueing event handlers is impossible.
I wrote a little demonstration to prove this point: http://jsfiddle.net/GnNZm/1/
With the jQuery method, you can attach multiple event handlers. By setting window.onblur, you can only have a single handler.
Pure JavaScript also has this: window.addEventListener(). In fact, i'm sure jQuery uses this internally. (Yes they do.)
(EDIT)
The window.onblur property is basically a shortcut for setting a single handler. Using addEventListener() (or the jQuery wrapper) basically creates a list of event handlers, which all get fired when the event happens. I haven't tested, but i think you can even use the two together. Because it's a list, not a single value, multiple handlers shouldn't interfere with each other. They can also be removed separately or all at once.
jQuery's event handlers, using on(), also let you namespace your handlers, to prevent clashes if a plugin removes its handlers. Pure JS doesn't seem to have this easily.
For jquery blur
The blur event does not bubble in Internet Explorer. Therefore,
scripts that rely on event delegation with the blur event will not
work consistently across browsers. As of version 1.4.2, however,
jQuery works around this limitation by mapping blur to the focusout
event in its event delegation methods, .live() and .delegate().
taken from jquery doc https://api.jquery.com/blur/
Also jquery allows you bind multiple event handlers
When you attach an event there is the possibility of overwriting an event already attached to an event handler. This used to happen a lot with window.onload() where different scripts overwrote each others event handlers.
eg:
//lightbox.js
window.onload = function() { /* do lightbox stuff */ }
//carousel.js
window.onload = function() { /* do carousel stuff */ }
So the common practice used to be something like this:
var existing_event_handlers = window.onload;
window.onload = function(){
//my event code
alert('onready fired');
//call other event handlers after
existing_event_handlers();
}
Using window.onblur = function() { ... } still has an advantage because you can specifically dictate if you want your event fired before or after other attached events.
Like many other answers already pointed out jQuery abstracts you from most browser differences. Version before IE9 used attachEvent() rather than addEventListener().

Backbone.js - Adding keydown events when view is active?

I have a view called gallery that options. I want to listen and act on keydown events when the gallery is rendered (until it's closed).
How do I do this in backbone events? I've tried all variations of 'keydown X':function and none have worked.
I just tested the following and it worked flawlessly:
var view = Backbone.View.extend({
// ... snip ...
events: {
'keyup :input': 'logKey'
,'keypress :input': 'logKey'
}
,logKey: function(e) {
console.log(e.type, e.keyCode);
}
});
I'd go back and check your code. All events in Backbone are defined as delegates attached to the viewInstance.el element. To unbind the events, call viewInstance.remove() which calls $(viewInstance.el).remove() under the covers and cleans up all the delegated events.
Also note that in some browsers (Firefox I believe) there's a known issue that some keys (like arrow keys) don't bubble and will not work properly with delegated keypress events. If you're catching special keys, you're probably better off using keyup and keydown.

How to change all onClick events to TouchStart on iOS?

OnClick event has a timeout ~400ms before executing on iOS-browser (demo). And I want to change it to TouchStart event for all DOM-elements who have onClick. How can i make it?
I use jQuery and i tried check all elements for click function:
$('*').each(function() {
if($(this).click != null) {
// BUT all elements in DOM has click
}
})
I don't have an exact answer, but I think you should be able to make this do what you want.
For every element on your page that has an OnClick, add a class - say TouchTarget. Then use this in your startup function.
$('.TouchTarget').bind('touchstart', function (e) {
e.preventDefault();
touchStart(e, this);
});
Create a handler function that looks like this:
function touchStart(pEvent, pElement) {
//Do something with the touch.
}
If you only want to register if touch is available, then you can protect the bind call with
if (Modernizr.touch) {
}
I believe the reason for the delay in OnClick is because Safari is waiting to see if the touch is really a click or a drag, or some other gesture. This will recognize a simple touch quickly. I normally bind both touchstart and touchend when I need quick touches so that touchstart provides visual feedback and then touchend does something with the "click". This method does not have a delay built in.
Use a product like http://www.jqtouch.com/ or the code snipped provided here: http://cubiq.org/remove-onclick-delay-on-webkit-for-iphone.

Categories

Resources