/* * Paper.js - The Swiss Army Knife of Vector Graphics Scripting. * http://paperjs.org/ * * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey * http://lehni.org/ & http://jonathanpuckey.com/ * * Distributed under the MIT license. See LICENSE file for details. * * All rights reserved. */ /** * @name DomEvent * @namespace * @private */ var DomEvent = { add: function(el, events) { for (var type in events) { var func = events[type]; if (el.addEventListener) { el.addEventListener(type, func, false); } else if (el.attachEvent) { // Make a bound closure that calls on the right object and // passes on the global event object as a parameter. el.attachEvent('on' + type, func.bound = function() { func.call(el, window.event); }); } } }, remove: function(el, events) { for (var type in events) { var func = events[type]; if (el.removeEventListener) { el.removeEventListener(type, func, false); } else if (el.detachEvent) { // Remove the bound closure instead of func itself el.detachEvent('on' + type, func.bound); } } }, getPoint: function(event) { var pos = event.targetTouches ? event.targetTouches.length ? event.targetTouches[0] : event.changedTouches[0] : event; return Point.create( pos.pageX || pos.clientX + document.documentElement.scrollLeft, pos.pageY || pos.clientY + document.documentElement.scrollTop ); }, getTarget: function(event) { return event.target || event.srcElement; }, getOffset: function(event, target) { // Remove target offsets from page coordinates return DomEvent.getPoint(event).subtract(DomElement.getOffset( target || DomEvent.getTarget(event))); }, preventDefault: function(event) { if (event.preventDefault) { event.preventDefault(); } else { // IE event.returnValue = false; } }, stopPropagation: function(event) { if (event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } }, stop: function(event) { DomEvent.stopPropagation(event); DomEvent.preventDefault(event); } }; DomEvent.requestAnimationFrame = new function() { var part = 'equestAnimationFrame', request = window['r' + part] || window['webkitR' + part] || window['mozR' + part] || window['oR' + part] || window['msR' + part]; if (request) { // Chrome shipped without the time arg in m10. We need to check if time // is defined in callbacks, and if not, clear request again so we won't // use the faulty method. request(function(time) { if (time == null) request = null; }); } // So we need to fake it. Define helper functions first: var callbacks = [], focused = true, timer; DomEvent.add(window, { focus: function() { focused = true; }, blur: function() { focused = false; } }); return function(callback, element) { // See if we can handle natively first if (request) return request(callback, element); // If not, do the callback handling ourself: callbacks.push([callback, element]); // We're done if there's already a timer installed if (timer) return; // Installs interval timer that checks all callbacks. This results // in faster animations than repeatedly installing timout timers. timer = setInterval(function() { // Checks all installed callbacks for element visibility and // execute if needed. for (var i = callbacks.length - 1; i >= 0; i--) { var entry = callbacks[i], func = entry[0], el = entry[1]; if (!el || (PaperScript.getAttribute(el, 'keepalive') == 'true' || focused) && DomElement.isInView(el)) { // Handle callback and remove it from callbacks list. callbacks.splice(i, 1); func(Date.now()); } } }, 1000 / 60); }; };