im very new to jquery/javascript. So here goes, I found this js code for swipedown and swipeup. But don't know how to use it or call it.
The js code:
(function() {
// initializes touch and scroll events
var supportTouch = $.support.touch,
scrollEvent = "touchmove scroll",
touchStartEvent = supportTouch ? "touchstart" : "mousedown",
touchStopEvent = supportTouch ? "touchend" : "mouseup",
touchMoveEvent = supportTouch ? "touchmove" : "mousemove";
// handles swipeup and swipedown
$.event.special.swipeupdown = {
setup: function() {
var thisObject = this;
var $this = $(thisObject);
$this.bind(touchStartEvent, function(event) {
var data = event.originalEvent.touches ?
event.originalEvent.touches[ 0 ] :
event,
start = {
time: (new Date).getTime(),
coords: [ data.pageX, data.pageY ],
origin: $(event.target)
},
stop;
function moveHandler(event) {
if (!start) {
return;
}
var data = event.originalEvent.touches ?
event.originalEvent.touches[ 0 ] :
event;
stop = {
time: (new Date).getTime(),
coords: [ data.pageX, data.pageY ]
};
// prevent scrolling
if (Math.abs(start.coords[1] - stop.coords[1]) > 10) {
event.preventDefault();
}
}
$this
.bind(touchMoveEvent, moveHandler)
.one(touchStopEvent, function(event) {
$this.unbind(touchMoveEvent, moveHandler);
if (start && stop) {
if (stop.time - start.time < 1000 &&
Math.abs(start.coords[1] - stop.coords[1]) > 30 &&
Math.abs(start.coords[0] - stop.coords[0]) < 75) {
start.origin
.trigger("swipeupdown")
.trigger(start.coords[1] > stop.coords[1] ? "swipeup" : "swipedown");
}
}
start = stop = undefined;
});
});
}
};
//Adds the events to the jQuery events special collection
$.each({
swipedown: "swipeupdown",
swipeup: "swipeupdown"
}, function(event, sourceEvent){
$.event.special[event] = {
setup: function(){
$(this).bind(sourceEvent, $.noop);
}
};
});
})();
this is the anchor element that I want to trigger using the above code
tried call the function like this:
$('#swipedown').live('swipedown', function(event, data){
alert('swipes')
});
but it didn't prompt me the alert. >.<.
Any help will be much appreciated.
The last () are calling the funcion after it's created. The funcion adds a new possibility to jquery. So you can probably call it doing:
$('#swipedown').bind('swipedown', function(e){
alert('test');
});
Your code will be added (as documented) to the jQuery events special collection this means that you could call swipeup or swipedown as any other jQuery event.
example:
$("div p").live('swipedown',function() {
alert("swiped down");
});
That will be triggered on a swipedown action happening to a p element like:
<body>
<div>
<h1>hello world</h1>
<p>pull me down</p>
</div>
</body>
Related
My script loads data from other html pages when the user activates the mousewheel.
It should work like this. Scroll up, load contact.html into home.html, scroll up again, load legal.html into home.html. But right now it only loads one time because the mouse wheel event listener is only working once.
How do I make my script listen for the mousewheel again after new pages are loaded into home.html?
javascript
$(document).ready(function() {
bind_events();
$(window).resize(function() {
adjust_div_height();
});
adjust_div_height();
});
function bind_events() {
var elem = $('.div-scrollable')[0];
hammertime = new Hammer(elem);
hammertime.get('swipe').set({ direction: Hammer.DIRECTION_VERTICAL
});
hammertime.on("swipeup", function(ev) {
load_page('next');
adjust_div_height();
});
hammertime.on("swipedown", function(ev) {
load_page('previous');
adjust_div_height();
});
addWheelListener(elem, function(e) {
var scrollUp = e.deltaY > 0;
var scrollDown = e.deltaY < 0;
if (scrollUp) {
load_page('next');
} else if (scrollDown) {
load_page('previous');
}
});
}
function load_page(page_to_load) {
// load contact page data
var loadContactPage = $('#loaded_content').load('contact.html #contact');
var loadHomePage = $('#loaded_content').load('home.html #home');
var homeIsCurrentPage = "$('#home').length)";
var contactIsCurrentPage = "$('#contact').length)";
var legalIsCurrentPage = "$('#contact').length)";
if (homeIsCurrentPage) {
var next = loadContactPage;
update_url('contact.html');
console.log('contact page was loaded!');
}
if (contactIsCurrentPage) {
var next = loadLegalPage;
update_url('legal.html');
console.log('legal page was loaded!');
}
if (legalIsCurrentPage) {
var previous = loadContactPage;
update_url('contact.html');
console.log('contact page was loaded!');
}
wheel_listener.js
// creates a global "addWheelListener" method
// example: addWheelListener( elem, function( e ) { console.log(
e.deltaY ); e.preventDefault(); } );
(function(window, document) {
var prefix = "",
_addEventListener, support;
// detect event model
if (window.addEventListener) {
_addEventListener = "addEventListener";
} else {
_addEventListener = "attachEvent";
prefix = "on";
}
// detect available wheel event
support = "onwheel" in document.createElement("div") ? "wheel" : // Modern browsers support "wheel"
document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least "mousewheel"
"DOMMouseScroll"; // let's assume that remaining browsers are older Firefox
window.addWheelListener = function(elem, callback, useCapture) {
_addWheelListener(elem, support, callback, useCapture);
// handle MozMousePixelScroll in older Firefox
if (support == "DOMMouseScroll") {
_addWheelListener(elem, "MozMousePixelScroll", callback, useCapture);
}
};
function _addWheelListener(elem, eventName, callback, useCapture) {
elem[_addEventListener](prefix + eventName, support == "wheel" ? callback : function(originalEvent) {
!originalEvent && (originalEvent = window.event);
// create a normalized event object
var event = {
// keep a ref to the original event object
originalEvent: originalEvent,
target: originalEvent.target || originalEvent.srcElement,
type: "wheel",
deltaMode: originalEvent.type == "MozMousePixelScroll" ? 0 : 1,
deltaX: 0,
deltaY: 0,
deltaZ: 0,
preventDefault: function() {
originalEvent.preventDefault ?
originalEvent.preventDefault() :
originalEvent.returnValue = false;
}
};
// calculate deltaY (and deltaX) according to the event
if (support == "mousewheel") {
event.deltaY = -1 / 40 * originalEvent.wheelDelta;
// Webkit also support wheelDeltaX
originalEvent.wheelDeltaX && (event.deltaX = -1 / 40 * originalEvent.wheelDeltaX);
} else {
event.deltaY = originalEvent.deltaY || originalEvent.detail;
}
// it's time to fire the callback
return callback(event);
}, useCapture || false);
}
})(window, document);
I can understand what you tried on your code.
For a quick note, your code is not transparent for me. So, I can't simulate
addWheelListener function is defined but not used. I think you forgot to post it.
adjust_div_height function is used but not defined.
Same as for update_url, loadContactPage and loadLegalPage.
I tried to put as much as I can on Code Snippet as following.
Please check and let me know if you need more help.
Thanks
$(document).ready(function () {
bind_events();
$(window).resize(function () {
adjust_div_height();
});
adjust_div_height();
});
function bind_events() {
var elem = $('.div-scrollable')[0];
hammertime = new Hammer(elem);
hammertime.get('swipe').set({
direction: Hammer.DIRECTION_VERTICAL
});
hammertime.on("swipeup", function (ev) {
load_page('next');
adjust_div_height();
});
hammertime.on("swipedown", function (ev) {
load_page('previous');
adjust_div_height();
});
addWheelListener(elem, function (e) {
var scrollUp = e.deltaY > 0;
var scrollDown = e.deltaY < 0;
if (scrollUp) {
load_page('next');
} else if (scrollDown) {
load_page('previous');
}
});
}
function adjust_div_height() {
console.log('Adjust Div height function should be here.');
}
function addWheelListener(elem, callback) {
elem.addEventListener("wheel", callback);
}
function update_url(url) {
console.log('Update url to <' + url + '>');
}
function load_page(page_to_load) {
console.log('Scrolled to <' + page_to_load + '> page!');
// load contact page data
var loadContactPage = $('#loaded_content').load('contact.html #contact');
var loadHomePage = $('#loaded_content').load('home.html #home');
var homeIsCurrentPage = "$('#home').length)";
var contactIsCurrentPage = "$('#contact').length)";
var legalIsCurrentPage = "$('#contact').length)";
if (homeIsCurrentPage) {
var next = loadContactPage;
update_url('contact.html');
console.log('contact page was loaded!');
}
if (contactIsCurrentPage) {
var next = loadLegalPage;
update_url('legal.html');
console.log('legal page was loaded!');
}
if (legalIsCurrentPage) {
var previous = loadContactPage;
update_url('contact.html');
console.log('contact page was loaded!');
}
}
function loadContactPage() { /* Load Contact Page */ }
function loadLegalPage() { /* Load Legal Page */ }
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://hammerjs.github.io/dist/hammer.min.js"></script>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js"></script>
</head>
<body>
<div id="home">Home</div>
<div class="div-scrollable" style="height: 200px; background: red;">
This is scrollable Div
</div>
</body>
</html>
I've been trying to get mithril touch to work using a good code on github:
https://gist.github.com/webcss/debc7b60451f2ad2af41
import m from 'mithril'
/*****************************************
/* DOM touch support module
/*****************************************/
if (!window.CustomEvent) {
window.CustomEvent = function (event, params) {
params = params || { bubbles: false, cancelable: false, detail: undefined };
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
};
window.CustomEvent.prototype = window.Event.prototype;
}
(function(document) {
var TAPTRESHOLD = 200, // time within a double tap should have happend
TAPPRECISION = 60 / 2, // distance to identify a swipe gesture
touch = { },
tapCount = 0, // counts the number of touchstart events
tapTimer = 0, // timer to detect double tap
isTouchSwipe = false, // set to true whenever
absolute = Math.abs,
touchSupported = 'ontouchstart' in window;
function parentIfText (node) {
return 'tagName' in node ? node : node.parentNode;
}
function dispatchEvent(type, touch) {
if(touchSupported) {
touch.originalEvent.preventDefault();
touch.originalEvent.stopImmediatePropagation();
}
var event = new CustomEvent(type, {
detail: touch,
bubbles: true,
cancelable: true
});
touch.target.dispatchEvent(event);
console.log(type);
touch = { };
tapCount = 0;
return event;
}
function touchStart(e) {
if( !touchSupported || e.touches.length === 1) {
var coords = e.targetTouches ? e.targetTouches[0] : e;
touch = {
originalEvent: e,
target: parentIfText(e.target),
x1: coords.pageX,
y1: coords.pageY,
x2: coords.pageX,
y2: coords.pageY
};
isTouchSwipe = false;
tapCount++;
if (!e.button || e.button === 1) {
clearTimeout(tapTimer);
tapTimer = setTimeout(function() {
if(absolute(touch.x2 - touch.x1) < TAPPRECISION &&
absolute(touch.y2 - touch.y2) < TAPPRECISION &&
!isTouchSwipe) {
dispatchEvent((tapCount===2)? 'dbltap' : 'tap', touch);
clearTimeout(tapTimer);
}
tapCount = 0;
}, TAPTRESHOLD);
}
}
}
function touchMove(e) {
var coords = e.changedTouches ? e.changedTouches[0] : e;
isTouchSwipe = true;
touch.x2 = coords.pageX;
touch.y2 = coords.pageY;
/* the following is obsolete since at least chrome handles this
// if movement is detected within 200ms from start, preventDefault to preserve browser scroll etc.
// if (touch.target &&
// (absolute(touch.y2 - touch.y1) <= TAPPRECISION ||
// absolute(touch.x2 - touch.x1) <= TAPPRECISION)
// ) {
// e.preventDefault();
// touchCancel(e);
// }
*/
}
function touchCancel(e) {
touch = {};
tapCount = 0;
isTouchSwipe = false;
}
function touchEnd(e) {
var distX = touch.x2 - touch.x1,
distY = touch.y2 - touch.y1,
absX = absolute(distX),
absY = absolute(distY);
// use setTimeout here to register swipe over tap correctly,
// otherwise a tap would be fired immediatly after a swipe
setTimeout(function() {
isTouchSwipe = false;
},0);
// if there was swipe movement, resolve the direction of swipe
if(absX || absY) {
if(absX > absY) {
dispatchEvent((distX<0)? 'swipeleft': 'swiperight', touch);
} else {
dispatchEvent((distY<0)? 'swipeup': 'swipedown', touch);
}
}
}
document.addEventListener(touchSupported ? 'touchstart' : 'mousedown', touchStart, false);
document.addEventListener(touchSupported ? 'touchmove' : 'mousemove', touchMove, false);
document.addEventListener(touchSupported ? 'touchend' : 'mouseup', touchEnd, false);
// on touch devices, the taphold complies with contextmenu
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
e.stopImmediatePropagation();
dispatchEvent('taphold', {
originalEvent: e,
target: parentIfText(e.target)
});
}, false);
if (touchSupported) {
document.addEventListener('touchcancel', touchCancel, false);
}
}(window.document));
m.touchHelper = function(options) {
return function(element, initialized, context) {
if (!initialized) {
Object.keys(options).forEach(function(touchType) {
element.addEventListener(touchType, options[touchType], false);
});
context.onunload = function() {
Object.keys(options).forEach(function(touchType) {
element.removeEventListener(touchType, options[touchType], false);
});
};
}
};
};
The only thing I've added is import m from 'mithril'.
Launching the app I can see that everything is registering as should through the console, however, in my main code I want to use that touch data:
const app = {
view: vnode => {
return m('.main', {config: m.touchHelper({ 'tap': consoleLog})
}
}
function consoleLog() {
console.log('Triggered')
}
However, this function is not triggered.
I don't know how much Mithril has changed since February 2017 (I have only recently picked up Mithril), but that m.touchHelper seems weird. What are element, initialized and context? Why is a function returned; is it ever called?
Using m.touchHelper with the config attribute seems also weird. When you do this:
return m('.main', {config: m.touchHelper({'tap': consoleLog})})
the resulting DOM element looks like this:
<div config="function(element, initialized, context) {
if (!initialized) {
Object.keys(options).forEach(function(touchType) {
element.addEventListener(touchType, options[touchType], false);
});
context.onunload = function() {
Object.keys(options).forEach(function(touchType) {
element.removeEventListener(touchType, options[touchType], false);
});
};
}
}" class="main"></div>
See JSFiddle with your code. (Note that I added missing }) to the end of app's view method.)
I would change m.touchHelper to something like this:
m.touchHelper = function(vnode, options) {
if (vnode.state.initialized) return;
vnode.state.initialized = true;
Object.keys(options).forEach(function(touchType) {
vnode.dom.addEventListener(touchType, options[touchType], false);
});
// Note that I removed the `context.unload` part as I'm unsure what its purpose was
};
And call it in a component's oncreate lifecycle method:
const app = {
oncreate(vnode) {
m.touchHelper(vnode, {'tap': consoleLog});
},
view: vnode => {
return m('.main');
}
};
Then it seems to work. See JSFiddle with updated code.
I was using a jquery slide menu on my website just like:
http://www.dynamicdrive.com/style/csslibrary/item/jquery_multi_level_css_menu_2/
then when I started to renew my site I saw this:
http://osvaldas.info/drop-down-navigation-responsive-and-touch-friendly/tag/touch
which is nice on mobile devices but only has only one level depth.
I tried to merge them together but I couldn't. Is it possible to do it? If so how?
//jqueryslidemenu.js
//Specify full URL to down and right arrow images (23 is padding-right to add to top level LIswith drop downs):
var arrowimages={down:['downarrowclass', 'down.gif', 23], right:['rightarrowclass', 'right.gif']}
var jqueryslidemenu={
animateduration: { over: 200, out: 100 }, //duration of slide in/ out animation, in milliseconds
buildmenu:function(menuid, arrowsvar){
jQuery(document).ready(function($){
var $mainmenu=$("#"+menuid+">ul")
var $headers=$mainmenu.find("ul").parent()
$headers.each(function(i){
var $curobj=$(this)
var $subul=$(this).find('ul:eq(0)')
this._dimensions={w:this.offsetWidth, h:this.offsetHeight, subulw:$subul.outerWidth(), subulh:$subul.outerHeight()}
this.istopheader=$curobj.parents("ul").length==1? true : false
$subul.css({top:this.istopheader? this._dimensions.h+"px" : 0})
$curobj.children("a:eq(0)").css(this.istopheader? {paddingRight: arrowsvar.down[2]} : {}).append(
'<img src="'+ (this.istopheader? arrowsvar.down[1] : arrowsvar.right[1])
+'" class="' + (this.istopheader? arrowsvar.down[0] : arrowsvar.right[0])
+ '" style="border:0;" />'
)
$curobj.hover(
function(e){
var $targetul=$(this).children("ul:eq(0)")
this._offsets={left:$(this).offset().left, top:$(this).offset().top}
var menuleft=this.istopheader? 0 : this._dimensions.w
menuleft=(this._offsets.left+menuleft+this._dimensions.subulw>$(window).width())? (this.istopheader? -this._dimensions.subulw+this._dimensions.w : -this._dimensions.w) : menuleft
if ($targetul.queue().length<=1) //if 1 or less queued animations
$targetul.css({left:menuleft+"px", width:this._dimensions.subulw+'px'}).slideDown(jqueryslidemenu.animateduration.over)
},
function(e){
var $targetul=$(this).children("ul:eq(0)")
$targetul.slideUp(jqueryslidemenu.animateduration.out)
}
) //end hover
$curobj.click(function(){
$(this).children("ul:eq(0)").hide()
})
}) //end $headers.each()
$mainmenu.find("ul").css({display:'none', visibility:'visible'})
}) //end document.ready
}
}
//build menu with ID="myslidemenu" on page:
jqueryslidemenu.buildmenu("myslidemenu", arrowimages)
I want to merge this code with the one below. I tried but I couldn't make it. Where should I add it?
// Doubletaptogo.js
;(function ($, window, document, undefined) {
$.fn.doubleTapToGo = function (params) {
if (!('ontouchstart' in window) &&
!navigator.msMaxTouchPoints &&
!navigator.userAgent.toLowerCase().match(/windows phone os 7/i)) return false;
this.each(function () {
var curItem = false;
$(this).on('click', function (e) {
var item = $(this);
if (item[0] != curItem[0]) {
e.preventDefault();
curItem = item;
}
});
$(document).on('click touchstart MSPointerDown', function (e) {
var resetItem = true,
parents = $(e.target).parents();
for (var i = 0; i < parents.length; i++)
if (parents[i] == curItem[0])
resetItem = false;
if (resetItem)
curItem = false;
});
});
return this;
};
})(jQuery, window, document);
$(function () {
$('#myslidemenu li:has(ul)').doubleTapToGo();
});
Thanks
What i would do is register a timer on your first click, save that variable within your plugin scope, and access it again to determine if enough time has passed to determine it as a double click. I think double click by standard is 750ms.
Or I believe jQuery has a built in .dblclick() (which may only work on desktop using click events).
I found this snippet of code online:
(function($) {
$.fn.doubleTap = function(doubleTapCallback) {
return this.each(function(){
var elm = this;
var lastTap = 0;
$(elm).bind('vmousedown', function (e) {
var now = (new Date()).valueOf();
var diff = (now - lastTap);
lastTap = now ;
if (diff < 250) {
if($.isFunction( doubleTapCallback ))
{
doubleTapCallback.call(elm);
}
}
});
});
}
})(jQuery);
I want to play the songs only if the user press the button 'play',
without Waiting to load all the 21 songs.
when I press the button 'play' the page jump up like refreshing ,it is not normal.
what I can do to improve my code.
please try to play the songs in the example site and see the problem.
many thanks.
var Music = {
init:function(){
song = new Audio();
//speaKer = document.getElementById("imgSpeaker");
this.volume = 0.08;
this.isMute = false;
canPlayMP3 = (typeof song.canPlayType === "function" && song.canPlayType("audio/mpeg") !== "");
song.src = canPlayMP3 ? "http://rafih.co.il/wp-content/uploads/2013/07/1.mp3" : "http://rafih.co.il/wp-content/uploads/2013/07/1.ogg";
song.preload = 'auto';
},
/* start:function(){
song.src = canPlayMP3 ? "http://rafih.co.il/wp-content/uploads/2013/07/1.mp3" : "http://rafih.co.il/wp-content/uploads/2013/07/1.ogg";
song.volume = 0.08;
song.autoplay = true;
song.load();
},*/
play: function () {
song.volume = 0.08;
song.autoplay = true;
song.load();
// Music.speaker();
},
stop: function () {
if (!song.ended) {
song.pause();
}
},
next: function () {
if (curr < count) {
curr++;
}else curr = 1;
song.src = canPlayMP3 ? "http://rafih.co.il/wp-content/uploads/2013/07/" + curr + ".mp3" : "http://rafih.co.il/wp-content/uploads/2013/07/" + curr + ".ogg";
},
};
function load() {
Music.init();
}
You need to return false from the play buttons event handler, to prevent the page from scrolling to the top.
Change:
<div id="play" onclick='Music.play()'>
To:
<div id="play" onclick='Music.play(); return false;'>
That's because of the anchor in your link, such as href="#". A very simple fix would be to add return false; in to your inline handler attribute, such as onclick="Music.play(); return false;", however that isin't a good approach and is considered a bad practice.
Instead you could add your handlers programmatically, it will also make your code more modular and testable:
var Music = {
init: function (options) {
var playBtn = this.playBtn = document.querySelector(options.playBtn);
playBtn.addEventListener('click', this._onPlayBtnClick.bind(this));
//...
return this;
},
_onPlayBtnClick: function (e) {
e.preventDefault(); //prevents the browser's default behaviour
this.play();
},
//...
};
Then you could do something like:
function load() {
var musicController = Object.create(Music).init({
playBtn: '#play',
//...
});
}
You could also use it as a singleton like:
Music.init({ ... });
Is there a way to bind to a double-tap event (in a single line of code) for mobile safari? Or, the alternative is to implement it intercepting two single-tap events that happened in some short given time (example: http://appcropolis.com/blog/implementing-doubletap-on-iphones-and-ipads/)?
Short answer: you must implement via two clicks.
Actual answer: Here is a jQuery-free implementation of double-tap for mobile safari which only requires one line of code (to enable dblclick event):
https://gist.github.com/2927073
In addition, you will likely need to disable mobile Safari's default zoom with this meta tag:
<meta name="viewport" content="width=device-width,user-scalable=no" />
If you want to have working double click both on browser and IOS platform, you should have the following code:
jQuery.event.special.dblclick = {
setup: function(data, namespaces) {
var agent = navigator.userAgent.toLowerCase();
if (agent.indexOf('iphone') >= 0 || agent.indexOf('ipad') >= 0 || agent.indexOf('ipod') >= 0) {
var elem = this,
$elem = jQuery(elem);
$elem.bind('touchend.dblclick', jQuery.event.special.dblclick.handler);
} else {
var elem = this,
$elem = jQuery(elem);
$elem.bind('click.dblclick', jQuery.event.special.dblclick.handler);
}
},
teardown: function(namespaces) {
var agent = navigator.userAgent.toLowerCase();
if (agent.indexOf('iphone') >= 0 || agent.indexOf('ipad') >= 0 || agent.indexOf('ipod') >= 0) {
var elem = this,
$elem = jQuery(elem);
$elem.unbind('touchend.dblclick');
} else {
var elem = this,
$elem = jQuery(elem);
$elem.unbind('click.dblclick', jQuery.event.special.dblclick.handler);
}
},
handler: function(event) {
var elem = event.target,
$elem = jQuery(elem),
lastTouch = $elem.data('lastTouch') || 0,
now = new Date().getTime();
var delta = now - lastTouch;
if (delta > 20 && delta < 500) {
$elem.data('lastTouch', 0);
$elem.trigger('dblclick');
} else {
$elem.data('lastTouch', now);
}
}
};
Try it here:
http://jsfiddle.net/UXRF8/
Override dblclick event and use bind, live, on, delegate like for any other event:
jQuery.event.special.dblclick = {
setup: function(data, namespaces) {
var elem = this,
$elem = jQuery(elem);
$elem.bind('touchend.dblclick', jQuery.event.special.dblclick.handler);
},
teardown: function(namespaces) {
var elem = this,
$elem = jQuery(elem);
$elem.unbind('touchend.dblclick');
},
handler: function(event) {
var elem = event.target,
$elem = jQuery(elem),
lastTouch = $elem.data('lastTouch') || 0,
now = new Date().getTime();
var delta = now - lastTouch;
if(delta > 20 && delta<500){
$elem.data('lastTouch', 0);
$elem.trigger('dblclick');
}else
$elem.data('lastTouch', now);
}
};