mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-05-10 06:44:44 +00:00
226 lines
6.6 KiB
JavaScript
226 lines
6.6 KiB
JavaScript
(function () {
|
|
|
|
var unknown = 'unknown';
|
|
|
|
/* EVENT HANDLING */
|
|
|
|
function areHostMethods(object) {
|
|
var methodNames = Array.prototype.slice.call(arguments, 1),
|
|
t, i, len = methodNames.length;
|
|
for (i = 0; i < len; i++) {
|
|
t = typeof object[methodNames[i]];
|
|
if (!(/^(?:function|object|unknown)$/).test(t)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/** @ignore */
|
|
var getElement,
|
|
setElement,
|
|
getUniqueId = (function () {
|
|
var uid = 0;
|
|
return function (element) {
|
|
return element.__uniqueID || (element.__uniqueID = 'uniqueID__' + uid++);
|
|
};
|
|
})();
|
|
|
|
(function () {
|
|
var elements = { };
|
|
/** @ignore */
|
|
getElement = function (uid) {
|
|
return elements[uid];
|
|
};
|
|
/** @ignore */
|
|
setElement = function (uid, element) {
|
|
elements[uid] = element;
|
|
};
|
|
})();
|
|
|
|
function createListener(uid, handler) {
|
|
return {
|
|
handler: handler,
|
|
wrappedHandler: createWrappedHandler(uid, handler)
|
|
};
|
|
}
|
|
|
|
function createWrappedHandler(uid, handler) {
|
|
return function (e) {
|
|
handler.call(getElement(uid), e || fabric.window.event);
|
|
};
|
|
}
|
|
|
|
function createDispatcher(uid, eventName) {
|
|
return function (e) {
|
|
if (handlers[uid] && handlers[uid][eventName]) {
|
|
var handlersForEvent = handlers[uid][eventName];
|
|
for (var i = 0, len = handlersForEvent.length; i < len; i++) {
|
|
handlersForEvent[i].call(this, e || fabric.window.event);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
var shouldUseAddListenerRemoveListener = (
|
|
areHostMethods(fabric.document.documentElement, 'addEventListener', 'removeEventListener') &&
|
|
areHostMethods(fabric.window, 'addEventListener', 'removeEventListener')),
|
|
|
|
shouldUseAttachEventDetachEvent = (
|
|
areHostMethods(fabric.document.documentElement, 'attachEvent', 'detachEvent') &&
|
|
areHostMethods(fabric.window, 'attachEvent', 'detachEvent')),
|
|
|
|
// IE branch
|
|
listeners = { },
|
|
|
|
// DOM L0 branch
|
|
handlers = { },
|
|
|
|
addListener, removeListener;
|
|
|
|
if (shouldUseAddListenerRemoveListener) {
|
|
/** @ignore */
|
|
addListener = function (element, eventName, handler) {
|
|
element.addEventListener(eventName, handler, false);
|
|
};
|
|
/** @ignore */
|
|
removeListener = function (element, eventName, handler) {
|
|
element.removeEventListener(eventName, handler, false);
|
|
};
|
|
}
|
|
|
|
else if (shouldUseAttachEventDetachEvent) {
|
|
/** @ignore */
|
|
addListener = function (element, eventName, handler) {
|
|
var uid = getUniqueId(element);
|
|
setElement(uid, element);
|
|
if (!listeners[uid]) {
|
|
listeners[uid] = { };
|
|
}
|
|
if (!listeners[uid][eventName]) {
|
|
listeners[uid][eventName] = [ ];
|
|
|
|
}
|
|
var listener = createListener(uid, handler);
|
|
listeners[uid][eventName].push(listener);
|
|
element.attachEvent('on' + eventName, listener.wrappedHandler);
|
|
};
|
|
/** @ignore */
|
|
removeListener = function (element, eventName, handler) {
|
|
var uid = getUniqueId(element), listener;
|
|
if (listeners[uid] && listeners[uid][eventName]) {
|
|
for (var i = 0, len = listeners[uid][eventName].length; i < len; i++) {
|
|
listener = listeners[uid][eventName][i];
|
|
if (listener && listener.handler === handler) {
|
|
element.detachEvent('on' + eventName, listener.wrappedHandler);
|
|
listeners[uid][eventName][i] = null;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
else {
|
|
/** @ignore */
|
|
addListener = function (element, eventName, handler) {
|
|
var uid = getUniqueId(element);
|
|
if (!handlers[uid]) {
|
|
handlers[uid] = { };
|
|
}
|
|
if (!handlers[uid][eventName]) {
|
|
handlers[uid][eventName] = [ ];
|
|
var existingHandler = element['on' + eventName];
|
|
if (existingHandler) {
|
|
handlers[uid][eventName].push(existingHandler);
|
|
}
|
|
element['on' + eventName] = createDispatcher(uid, eventName);
|
|
}
|
|
handlers[uid][eventName].push(handler);
|
|
};
|
|
/** @ignore */
|
|
removeListener = function (element, eventName, handler) {
|
|
var uid = getUniqueId(element);
|
|
if (handlers[uid] && handlers[uid][eventName]) {
|
|
var handlersForEvent = handlers[uid][eventName];
|
|
for (var i = 0, len = handlersForEvent.length; i < len; i++) {
|
|
if (handlersForEvent[i] === handler) {
|
|
handlersForEvent.splice(i, 1);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Adds an event listener to an element
|
|
* @function
|
|
* @memberOf fabric.util
|
|
* @param {HTMLElement} element
|
|
* @param {String} eventName
|
|
* @param {Function} handler
|
|
*/
|
|
fabric.util.addListener = addListener;
|
|
|
|
/**
|
|
* Removes an event listener from an element
|
|
* @function
|
|
* @memberOf fabric.util
|
|
* @param {HTMLElement} element
|
|
* @param {String} eventName
|
|
* @param {Function} handler
|
|
*/
|
|
fabric.util.removeListener = removeListener;
|
|
|
|
/**
|
|
* Cross-browser wrapper for getting event's coordinates
|
|
* @memberOf fabric.util
|
|
* @param {Event} event Event object
|
|
* @param {HTMLCanvasElement} upperCanvasEl <canvas> element on which object selection is drawn
|
|
*/
|
|
function getPointer(event, upperCanvasEl) {
|
|
event || (event = fabric.window.event);
|
|
|
|
var element = event.target ||
|
|
(typeof event.srcElement !== unknown ? event.srcElement : null),
|
|
|
|
scroll = fabric.util.getScrollLeftTop(element, upperCanvasEl);
|
|
|
|
return {
|
|
x: pointerX(event) + scroll.left,
|
|
y: pointerY(event) + scroll.top
|
|
};
|
|
}
|
|
|
|
var pointerX = function(event) {
|
|
// looks like in IE (<9) clientX at certain point (apparently when mouseup fires on VML element)
|
|
// is represented as COM object, with all the consequences, like "unknown" type and error on [[Get]]
|
|
// need to investigate later
|
|
return (typeof event.clientX !== unknown ? event.clientX : 0);
|
|
},
|
|
|
|
pointerY = function(event) {
|
|
return (typeof event.clientY !== unknown ? event.clientY : 0);
|
|
};
|
|
|
|
function _getPointer(event, pageProp, clientProp) {
|
|
var touchProp = event.type === 'touchend' ? 'changedTouches' : 'touches';
|
|
|
|
return (event[touchProp] && event[touchProp][0]
|
|
? (event[touchProp][0][pageProp] - (event[touchProp][0][pageProp] - event[touchProp][0][clientProp]))
|
|
|| event[clientProp]
|
|
: event[clientProp]);
|
|
}
|
|
|
|
if (fabric.isTouchSupported) {
|
|
pointerX = function(event) {
|
|
return _getPointer(event, 'pageX', 'clientX');
|
|
};
|
|
pointerY = function(event) {
|
|
return _getPointer(event, 'pageY', 'clientY');
|
|
};
|
|
}
|
|
|
|
fabric.util.getPointer = getPointer;
|
|
|
|
fabric.util.object.extend(fabric.util, fabric.Observable);
|
|
|
|
})();
|