PHP Classes

File: public/js/tinymce/src/core/src/main/js/dom/EventUtils.js

Recommend this page to a friend!
  Classes of Abed Nego Ragil Putra   GoLavaCMS   public/js/tinymce/src/core/src/main/js/dom/EventUtils.js   Download  
File: public/js/tinymce/src/core/src/main/js/dom/EventUtils.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: GoLavaCMS
Publish content on Web pages with SEO support
Author: By
Last change:
Date: 6 years ago
Size: 20,540 bytes
 

Contents

Class file image Download
/** * EventUtils.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ /*jshint loopfunc:true*/ /*eslint no-loop-func:0 */ /** * This class wraps the browsers native event logic with more convenient methods. * * @class tinymce.dom.EventUtils */ define( 'tinymce.core.dom.EventUtils', [ 'global!document', 'global!window', 'tinymce.core.Env', 'tinymce.core.util.Delay' ], function (document, window, Env, Delay) { "use strict"; var eventExpandoPrefix = "mce-data-"; var mouseEventRe = /^(?:mouse|contextmenu)|click/; var deprecated = { keyLocation: 1, layerX: 1, layerY: 1, returnValue: 1, webkitMovementX: 1, webkitMovementY: 1, keyIdentifier: 1 }; // Checks if it is our own isDefaultPrevented function var hasIsDefaultPrevented = function (event) { return event.isDefaultPrevented === returnTrue || event.isDefaultPrevented === returnFalse; }; // Dummy function that gets replaced on the delegation state functions var returnFalse = function () { return false; }; // Dummy function that gets replaced on the delegation state functions var returnTrue = function () { return true; }; /** * Binds a native event to a callback on the speified target. */ var addEvent = function (target, name, callback, capture) { if (target.addEventListener) { target.addEventListener(name, callback, capture || false); } else if (target.attachEvent) { target.attachEvent('on' + name, callback); } }; /** * Unbinds a native event callback on the specified target. */ var removeEvent = function (target, name, callback, capture) { if (target.removeEventListener) { target.removeEventListener(name, callback, capture || false); } else if (target.detachEvent) { target.detachEvent('on' + name, callback); } }; /** * Gets the event target based on shadow dom properties like path and deepPath. */ var getTargetFromShadowDom = function (event, defaultTarget) { var path, target = defaultTarget; // When target element is inside Shadow DOM we need to take first element from path // otherwise we'll get Shadow Root parent, not actual target element // Normalize target for WebComponents v0 implementation (in Chrome) path = event.path; if (path && path.length > 0) { target = path[0]; } // Normalize target for WebComponents v1 implementation (standard) if (event.deepPath) { path = event.deepPath(); if (path && path.length > 0) { target = path[0]; } } return target; }; /** * Normalizes a native event object or just adds the event specific methods on a custom event. */ var fix = function (originalEvent, data) { var name, event = data || {}, undef; // Copy all properties from the original event for (name in originalEvent) { // layerX/layerY is deprecated in Chrome and produces a warning if (!deprecated[name]) { event[name] = originalEvent[name]; } } // Normalize target IE uses srcElement if (!event.target) { event.target = event.srcElement || document; } // Experimental shadow dom support if (Env.experimentalShadowDom) { event.target = getTargetFromShadowDom(originalEvent, event.target); } // Calculate pageX/Y if missing and clientX/Y available if (originalEvent && mouseEventRe.test(originalEvent.type) && originalEvent.pageX === undef && originalEvent.clientX !== undef) { var eventDoc = event.target.ownerDocument || document; var doc = eventDoc.documentElement; var body = eventDoc.body; event.pageX = originalEvent.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); event.pageY = originalEvent.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); } // Add preventDefault method event.preventDefault = function () { event.isDefaultPrevented = returnTrue; // Execute preventDefault on the original event object if (originalEvent) { if (originalEvent.preventDefault) { originalEvent.preventDefault(); } else { originalEvent.returnValue = false; // IE } } }; // Add stopPropagation event.stopPropagation = function () { event.isPropagationStopped = returnTrue; // Execute stopPropagation on the original event object if (originalEvent) { if (originalEvent.stopPropagation) { originalEvent.stopPropagation(); } else { originalEvent.cancelBubble = true; // IE } } }; // Add stopImmediatePropagation event.stopImmediatePropagation = function () { event.isImmediatePropagationStopped = returnTrue; event.stopPropagation(); }; // Add event delegation states if (hasIsDefaultPrevented(event) === false) { event.isDefaultPrevented = returnFalse; event.isPropagationStopped = returnFalse; event.isImmediatePropagationStopped = returnFalse; } // Add missing metaKey for IE 8 if (typeof event.metaKey == 'undefined') { event.metaKey = false; } return event; }; /** * Bind a DOMContentLoaded event across browsers and executes the callback once the page DOM is initialized. * It will also set/check the domLoaded state of the event_utils instance so ready isn't called multiple times. */ var bindOnReady = function (win, callback, eventUtils) { var doc = win.document, event = { type: 'ready' }; if (eventUtils.domLoaded) { callback(event); return; } var isDocReady = function () { // Check complete or interactive state if there is a body // element on some iframes IE 8 will produce a null body return doc.readyState === "complete" || (doc.readyState === "interactive" && doc.body); }; // Gets called when the DOM is ready var readyHandler = function () { if (!eventUtils.domLoaded) { eventUtils.domLoaded = true; callback(event); } }; var waitForDomLoaded = function () { if (isDocReady()) { removeEvent(doc, "readystatechange", waitForDomLoaded); readyHandler(); } }; var tryScroll = function () { try { // If IE is used, use the trick by Diego Perini licensed under MIT by request to the author. // http://javascript.nwbox.com/IEContentLoaded/ doc.documentElement.doScroll("left"); } catch (ex) { Delay.setTimeout(tryScroll); return; } readyHandler(); }; // Use W3C method (exclude IE 9,10 - readyState "interactive" became valid only in IE 11) if (doc.addEventListener && !(Env.ie && Env.ie < 11)) { if (isDocReady()) { readyHandler(); } else { addEvent(win, 'DOMContentLoaded', readyHandler); } } else { // Use IE method addEvent(doc, "readystatechange", waitForDomLoaded); // Wait until we can scroll, when we can the DOM is initialized if (doc.documentElement.doScroll && win.self === win.top) { tryScroll(); } } // Fallback if any of the above methods should fail for some odd reason addEvent(win, 'load', readyHandler); }; /** * This class enables you to bind/unbind native events to elements and normalize it's behavior across browsers. */ var EventUtils = function () { var self = this, events = {}, count, expando, hasFocusIn, hasMouseEnterLeave, mouseEnterLeave; expando = eventExpandoPrefix + (+new Date()).toString(32); hasMouseEnterLeave = "onmouseenter" in document.documentElement; hasFocusIn = "onfocusin" in document.documentElement; mouseEnterLeave = { mouseenter: 'mouseover', mouseleave: 'mouseout' }; count = 1; // State if the DOMContentLoaded was executed or not self.domLoaded = false; self.events = events; /** * Executes all event handler callbacks for a specific event. * * @private * @param {Event} evt Event object. * @param {String} id Expando id value to look for. */ var executeHandlers = function (evt, id) { var callbackList, i, l, callback, container = events[id]; callbackList = container && container[evt.type]; if (callbackList) { for (i = 0, l = callbackList.length; i < l; i++) { callback = callbackList[i]; // Check if callback exists might be removed if a unbind is called inside the callback if (callback && callback.func.call(callback.scope, evt) === false) { evt.preventDefault(); } // Should we stop propagation to immediate listeners if (evt.isImmediatePropagationStopped()) { return; } } } }; /** * Binds a callback to an event on the specified target. * * @method bind * @param {Object} target Target node/window or custom object. * @param {String} names Name of the event to bind. * @param {function} callback Callback function to execute when the event occurs. * @param {Object} scope Scope to call the callback function on, defaults to target. * @return {function} Callback function that got bound. */ self.bind = function (target, names, callback, scope) { var id, callbackList, i, name, fakeName, nativeHandler, capture, win = window; // Native event handler function patches the event and executes the callbacks for the expando var defaultNativeHandler = function (evt) { executeHandlers(fix(evt || win.event), id); }; // Don't bind to text nodes or comments if (!target || target.nodeType === 3 || target.nodeType === 8) { return; } // Create or get events id for the target if (!target[expando]) { id = count++; target[expando] = id; events[id] = {}; } else { id = target[expando]; } // Setup the specified scope or use the target as a default scope = scope || target; // Split names and bind each event, enables you to bind multiple events with one call names = names.split(' '); i = names.length; while (i--) { name = names[i]; nativeHandler = defaultNativeHandler; fakeName = capture = false; // Use ready instead of DOMContentLoaded if (name === "DOMContentLoaded") { name = "ready"; } // DOM is already ready if (self.domLoaded && name === "ready" && target.readyState == 'complete') { callback.call(scope, fix({ type: name })); continue; } // Handle mouseenter/mouseleaver if (!hasMouseEnterLeave) { fakeName = mouseEnterLeave[name]; if (fakeName) { nativeHandler = function (evt) { var current, related; current = evt.currentTarget; related = evt.relatedTarget; // Check if related is inside the current target if it's not then the event should // be ignored since it's a mouseover/mouseout inside the element if (related && current.contains) { // Use contains for performance related = current.contains(related); } else { while (related && related !== current) { related = related.parentNode; } } // Fire fake event if (!related) { evt = fix(evt || win.event); evt.type = evt.type === 'mouseout' ? 'mouseleave' : 'mouseenter'; evt.target = current; executeHandlers(evt, id); } }; } } // Fake bubbling of focusin/focusout if (!hasFocusIn && (name === "focusin" || name === "focusout")) { capture = true; fakeName = name === "focusin" ? "focus" : "blur"; nativeHandler = function (evt) { evt = fix(evt || win.event); evt.type = evt.type === 'focus' ? 'focusin' : 'focusout'; executeHandlers(evt, id); }; } // Setup callback list and bind native event callbackList = events[id][name]; if (!callbackList) { events[id][name] = callbackList = [{ func: callback, scope: scope }]; callbackList.fakeName = fakeName; callbackList.capture = capture; //callbackList.callback = callback; // Add the nativeHandler to the callback list so that we can later unbind it callbackList.nativeHandler = nativeHandler; // Check if the target has native events support if (name === "ready") { bindOnReady(target, nativeHandler, self); } else { addEvent(target, fakeName || name, nativeHandler, capture); } } else { if (name === "ready" && self.domLoaded) { callback({ type: name }); } else { // If it already has an native handler then just push the callback callbackList.push({ func: callback, scope: scope }); } } } target = callbackList = 0; // Clean memory for IE return callback; }; /** * Unbinds the specified event by name, name and callback or all events on the target. * * @method unbind * @param {Object} target Target node/window or custom object. * @param {String} names Optional event name to unbind. * @param {function} callback Optional callback function to unbind. * @return {EventUtils} Event utils instance. */ self.unbind = function (target, names, callback) { var id, callbackList, i, ci, name, eventMap; // Don't bind to text nodes or comments if (!target || target.nodeType === 3 || target.nodeType === 8) { return self; } // Unbind event or events if the target has the expando id = target[expando]; if (id) { eventMap = events[id]; // Specific callback if (names) { names = names.split(' '); i = names.length; while (i--) { name = names[i]; callbackList = eventMap[name]; // Unbind the event if it exists in the map if (callbackList) { // Remove specified callback if (callback) { ci = callbackList.length; while (ci--) { if (callbackList[ci].func === callback) { var nativeHandler = callbackList.nativeHandler; var fakeName = callbackList.fakeName, capture = callbackList.capture; // Clone callbackList since unbind inside a callback would otherwise break the handlers loop callbackList = callbackList.slice(0, ci).concat(callbackList.slice(ci + 1)); callbackList.nativeHandler = nativeHandler; callbackList.fakeName = fakeName; callbackList.capture = capture; eventMap[name] = callbackList; } } } // Remove all callbacks if there isn't a specified callback or there is no callbacks left if (!callback || callbackList.length === 0) { delete eventMap[name]; removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture); } } } } else { // All events for a specific element for (name in eventMap) { callbackList = eventMap[name]; removeEvent(target, callbackList.fakeName || name, callbackList.nativeHandler, callbackList.capture); } eventMap = {}; } // Check if object is empty, if it isn't then we won't remove the expando map for (name in eventMap) { return self; } // Delete event object delete events[id]; // Remove expando from target try { // IE will fail here since it can't delete properties from window delete target[expando]; } catch (ex) { // IE will set it to null target[expando] = null; } } return self; }; /** * Fires the specified event on the specified target. * * @method fire * @param {Object} target Target node/window or custom object. * @param {String} name Event name to fire. * @param {Object} args Optional arguments to send to the observers. * @return {EventUtils} Event utils instance. */ self.fire = function (target, name, args) { var id; // Don't bind to text nodes or comments if (!target || target.nodeType === 3 || target.nodeType === 8) { return self; } // Build event object by patching the args args = fix(null, args); args.type = name; args.target = target; do { // Found an expando that means there is listeners to execute id = target[expando]; if (id) { executeHandlers(args, id); } // Walk up the DOM target = target.parentNode || target.ownerDocument || target.defaultView || target.parentWindow; } while (target && !args.isPropagationStopped()); return self; }; /** * Removes all bound event listeners for the specified target. This will also remove any bound * listeners to child nodes within that target. * * @method clean * @param {Object} target Target node/window object. * @return {EventUtils} Event utils instance. */ self.clean = function (target) { var i, children, unbind = self.unbind; // Don't bind to text nodes or comments if (!target || target.nodeType === 3 || target.nodeType === 8) { return self; } // Unbind any element on the specified target if (target[expando]) { unbind(target); } // Target doesn't have getElementsByTagName it's probably a window object then use it's document to find the children if (!target.getElementsByTagName) { target = target.document; } // Remove events from each child element if (target && target.getElementsByTagName) { unbind(target); children = target.getElementsByTagName('*'); i = children.length; while (i--) { target = children[i]; if (target[expando]) { unbind(target); } } } return self; }; /** * Destroys the event object. Call this on IE to remove memory leaks. */ self.destroy = function () { events = {}; }; // Legacy function for canceling events self.cancel = function (e) { if (e) { e.preventDefault(); e.stopImmediatePropagation(); } return false; }; }; EventUtils.Event = new EventUtils(); EventUtils.Event.bind(window, 'ready', function () { }); return EventUtils; } );