Subversion-Projekte lars-tiefland.ci

Revision

Blame | Letzte Änderung | Log anzeigen | RSS feed

/**
* 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()
*/
(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;

                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);
                        });
                }
                return this;
        };

})(jQuery);