2011-03-14 22:14:20 +01:00
|
|
|
/*
|
|
|
|
* Paper.js
|
2011-06-22 23:56:05 +01:00
|
|
|
*
|
2011-03-14 22:14:20 +01:00
|
|
|
* This file is part of Paper.js, a JavaScript Vector Graphics Library,
|
|
|
|
* based on Scriptographer.org and designed to be largely API compatible.
|
|
|
|
* http://paperjs.org/
|
|
|
|
* http://scriptographer.org/
|
2011-06-22 23:56:05 +01:00
|
|
|
*
|
2011-03-14 22:14:20 +01:00
|
|
|
* Distributed under the MIT license. See LICENSE file for details.
|
2011-06-22 23:56:05 +01:00
|
|
|
*
|
2011-03-14 22:14:20 +01:00
|
|
|
* Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
|
|
|
|
* http://lehni.org/ & http://jonathanpuckey.com/
|
2011-06-22 23:56:05 +01:00
|
|
|
*
|
2011-03-14 22:14:20 +01:00
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2011-05-08 10:16:11 +01:00
|
|
|
var DomEvent = {
|
2011-03-14 22:14:20 +01:00
|
|
|
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) {
|
2011-05-04 18:49:30 +01:00
|
|
|
var pos = event.targetTouches
|
|
|
|
? event.targetTouches.length
|
|
|
|
? event.targetTouches[0]
|
|
|
|
: event.changedTouches[0]
|
|
|
|
: event;
|
2011-03-14 22:14:20 +01:00
|
|
|
return Point.create(
|
2011-05-04 18:49:30 +01:00
|
|
|
pos.pageX || pos.clientX + document.documentElement.scrollLeft,
|
|
|
|
pos.pageY || pos.clientY + document.documentElement.scrollTop
|
2011-03-14 22:14:20 +01:00
|
|
|
);
|
|
|
|
},
|
|
|
|
|
2011-06-22 08:27:51 +01:00
|
|
|
getTarget: function(event) {
|
2011-03-14 22:14:20 +01:00
|
|
|
return event.target || event.srcElement;
|
|
|
|
},
|
|
|
|
|
2011-06-21 00:37:26 +01:00
|
|
|
getOffset: function(event, target) {
|
2011-03-14 22:14:20 +01:00
|
|
|
// Remove target offsets from page coordinates
|
2011-05-08 10:16:11 +01:00
|
|
|
return DomEvent.getPoint(event).subtract(
|
2011-06-22 08:27:51 +01:00
|
|
|
DomElement.getOffset(target || DomEvent.getTarget(event), true));
|
2011-05-08 13:43:52 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2011-06-21 00:37:03 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
stop: function(event) {
|
|
|
|
DomEvent.stopPropagation(event);
|
|
|
|
DomEvent.preventDefault(event);
|
|
|
|
},
|
2011-03-14 22:14:20 +01:00
|
|
|
};
|
|
|
|
|
2011-05-08 10:16:11 +01:00
|
|
|
DomEvent.requestAnimationFrame = new function() {
|
2011-03-14 22:14:20 +01:00
|
|
|
var part = 'equestAnimationFrame',
|
|
|
|
request = window['r' + part] || window['webkitR' + part]
|
|
|
|
|| window['mozR' + part] || window['oR' + part]
|
|
|
|
|| window['msR' + part];
|
|
|
|
if (request) {
|
2011-04-26 15:56:06 +01:00
|
|
|
// 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.
|
2011-03-14 22:14:20 +01:00
|
|
|
request(function(time) {
|
|
|
|
if (time == undefined)
|
|
|
|
request = null;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// So we need to fake it. Define helper functions first:
|
|
|
|
var callbacks = [],
|
2011-04-26 12:48:46 +01:00
|
|
|
focused = true,
|
2011-03-14 22:14:20 +01:00
|
|
|
timer;
|
|
|
|
|
2011-05-14 13:04:02 +03:00
|
|
|
DomEvent.add(window, {
|
|
|
|
focus: function() {
|
|
|
|
focused = true;
|
|
|
|
},
|
|
|
|
blur: function() {
|
|
|
|
focused = false;
|
|
|
|
}
|
|
|
|
});
|
2011-03-14 22:14:20 +01:00
|
|
|
|
|
|
|
return function(callback, element) {
|
2011-05-14 13:04:02 +03:00
|
|
|
// See if we can handle natively first
|
2011-03-14 22:14:20 +01:00
|
|
|
if (request)
|
|
|
|
return request(callback, element);
|
2011-05-14 13:04:02 +03:00
|
|
|
// If not, do the callback handling ourself:
|
2011-03-14 22:14:20 +01:00
|
|
|
callbacks.push([callback, element]);
|
2011-05-14 13:04:02 +03:00
|
|
|
if (!timer) {
|
|
|
|
// Installs interval timer that checks all callbacks. This results
|
|
|
|
// in faster animations than repeatedly installing timout timers.
|
|
|
|
timer = window.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],
|
|
|
|
element = entry[1];
|
2011-06-21 21:48:51 +01:00
|
|
|
if (!element || (element.getAttribute('keepalive') == 'true'
|
|
|
|
|| focused) && DomElement.isVisible(element)) {
|
2011-05-14 13:04:02 +03:00
|
|
|
// Handle callback and remove it from callbacks list.
|
|
|
|
callbacks.splice(i, 1);
|
2011-05-14 17:23:17 +01:00
|
|
|
func(Date.now());
|
2011-05-14 13:04:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}, 1000 / 60);
|
|
|
|
}
|
2011-03-14 22:14:20 +01:00
|
|
|
};
|
|
|
|
};
|