Created
August 26, 2012 23:18
-
-
Save brendon/3484262 to your computer and use it in GitHub Desktop.
jsTree Touch Compatibility
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* jQuery.UI.iPad plugin | |
* Copyright (c) 2010 Stephen von Takach | |
* licensed under MIT. | |
* Date: 27/8/2010 | |
* | |
* Project Home: | |
* http://code.google.com/p/jquery-ui-for-ipad-and-iphone/ | |
* | |
* Modified: 19/01/2012 | |
* Organized as a proper plugin and added addTouch() | |
*/ | |
var tapValid = false; | |
(function ($) { | |
var lastTap = null, // Holds last tapped element (so we can compare for double tap) | |
tapValid = false, // Are we still in the .6 second window where a double tap can occur | |
tapTimeout = null, // The timeout reference | |
rightClickPending = false, // Is a right click still feasible | |
rightClickEvent = null, // the original event | |
holdTimeout = null, // timeout reference | |
cancelMouseUp = false, // prevents a click from occurring as we want the context menu | |
currentDOMElement = null; // the last DOM element that was seen during a drag. | |
function cancelTap() { | |
tapValid = false; | |
} | |
function cancelHold() { | |
if (rightClickPending) { | |
window.clearTimeout(holdTimeout); | |
rightClickPending = false; | |
rightClickEvent = null; | |
} | |
} | |
function startHold(event) { | |
if (rightClickPending) { | |
return; | |
} | |
rightClickPending = true; // We could be performing a right click | |
rightClickEvent = (event.changedTouches)[0]; | |
holdTimeout = window.setTimeout(doRightClick, 800); | |
} | |
function doRightClick() { | |
rightClickPending = false; | |
// We need to mouse up (as we were down) | |
var first = rightClickEvent, | |
simulatedEvent = document.createEvent("MouseEvent"); | |
simulatedEvent.initMouseEvent("mouseup", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 0, null); | |
first.target.dispatchEvent(simulatedEvent); | |
// Emulate a right click | |
simulatedEvent = document.createEvent("MouseEvent"); | |
simulatedEvent.initMouseEvent("mousedown", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 2, null); | |
first.target.dispatchEvent(simulatedEvent); | |
// Show a context menu | |
simulatedEvent = document.createEvent("MouseEvent"); | |
simulatedEvent.initMouseEvent("contextmenu", true, true, window, 1, first.screenX + 50, first.screenY + 5, first.clientX + 50, first.clientY + 5, false, false, false, false, 2, null); | |
first.target.dispatchEvent(simulatedEvent); | |
simulatedEvent = document.createEvent("MouseEvent"); | |
simulatedEvent.initMouseEvent("mouseup", true, true, window, 1, first.screenX + 50, first.screenY + 5, first.clientX + 50, first.clientY + 5, false, false, false, false, 2, null); | |
first.target.dispatchEvent(simulatedEvent); | |
cancelMouseUp = true; | |
rightClickEvent = null; // Release memory | |
} | |
// mouse over event then mouse down | |
function iPadTouchStart(event) { | |
var touches = event.changedTouches, | |
first = touches[0], | |
type = "mouseover", | |
simulatedEvent = document.createEvent("MouseEvent"); | |
// Mouse over first - I have live events attached on mouse over | |
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 0, null); | |
first.target.dispatchEvent(simulatedEvent); | |
type = "mousedown"; | |
simulatedEvent = document.createEvent("MouseEvent"); | |
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 0, null); | |
first.target.dispatchEvent(simulatedEvent); | |
if (!tapValid) { | |
lastTap = first.target; | |
tapValid = true; | |
tapTimeout = window.setTimeout(cancelTap, 600); | |
startHold(event); | |
} else { | |
window.clearTimeout(tapTimeout); | |
// If a double tap is still a possibility and the elements are the same then perform a double click | |
if (first.target == lastTap) { | |
lastTap = null; | |
tapValid = false; | |
type = "click"; | |
simulatedEvent = document.createEvent("MouseEvent"); | |
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 0, null); | |
first.target.dispatchEvent(simulatedEvent); | |
type = "dblclick"; | |
simulatedEvent = document.createEvent("MouseEvent"); | |
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 0, null); | |
first.target.dispatchEvent(simulatedEvent); | |
} else { | |
lastTap = first.target; | |
tapValid = true; | |
tapTimeout = window.setTimeout(cancelTap, 600); | |
startHold(event); | |
} | |
} | |
} | |
function getDOMElementFromEvent(event) { | |
if (event.targetTouches && event.targetTouches[0]) { | |
return document.elementFromPoint(event.targetTouches[0].pageX - window.pageXOffset, event.targetTouches[0].pageY - window.pageYOffset); | |
} | |
return null; | |
} | |
function iPadTouchHandler(event) { | |
var type = "", | |
button = 0; /*left*/ | |
if (event.touches.length > 1) { | |
return; | |
} | |
switch (event.type) { | |
case "touchstart": | |
if ($(event.changedTouches[0].target).is("select")) { | |
return; | |
} | |
iPadTouchStart(event); /*We need to trigger two events here to support one touch drag and drop*/ | |
event.preventDefault(); | |
currentDOMElement = getDOMElementFromEvent(event); | |
return false; | |
break; | |
case "touchmove": | |
cancelHold(); | |
type = "mousemove"; | |
event.preventDefault(); | |
currentDOMElement = getDOMElementFromEvent(event); | |
break; | |
case "touchend": | |
if (cancelMouseUp) { | |
cancelMouseUp = false; | |
event.preventDefault(); | |
return false; | |
} | |
cancelHold(); | |
type = "mouseup"; | |
break; | |
default: | |
return; | |
} | |
var touches = event.changedTouches, | |
first = touches[0], | |
simulatedEvent = document.createEvent("MouseEvent"); | |
simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, | |
false, false, false, false, button, null); | |
currentDOMElement.dispatchEvent(simulatedEvent); | |
if (type == "mouseup" && tapValid && first.target == lastTap) { // This actually emulates the ipad's default behavior (which we prevented) | |
simulatedEvent = document.createEvent("MouseEvent"); // This check avoids click being emulated on a double tap | |
simulatedEvent.initMouseEvent("click", true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, | |
false, false, false, false, button, null); | |
currentDOMElement.dispatchEvent(simulatedEvent); | |
} | |
} | |
$.extend($.support, { | |
touch: "ontouchend" in document | |
}); | |
$.fn.addTouch = function () { | |
if ($.support.touch) { | |
this.each(function (i, el) { | |
el.addEventListener("touchstart", iPadTouchHandler, false); | |
el.addEventListener("touchmove", iPadTouchHandler, false); | |
el.addEventListener("touchend", iPadTouchHandler, false); | |
el.addEventListener("touchcancel", iPadTouchHandler, false); | |
}); | |
} | |
} | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment