UNPKG

react-tinymce-mention

Version:

@Mention functionality for TinyMCE, built with React and Redux.

1,784 lines (1,502 loc) 1.07 MB
// 4.2.4 (2015-08-17) /** * Compiled inline version. (Library mode) */ /*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */ /*globals $code */ (function(exports, undefined) { "use strict"; var modules = {}; function require(ids, callback) { var module, defs = []; for (var i = 0; i < ids.length; ++i) { module = modules[ids[i]] || resolve(ids[i]); if (!module) { throw 'module definition dependecy not found: ' + ids[i]; } defs.push(module); } callback.apply(null, defs); } function define(id, dependencies, definition) { if (typeof id !== 'string') { throw 'invalid module definition, module id must be defined and be a string'; } if (dependencies === undefined) { throw 'invalid module definition, dependencies must be specified'; } if (definition === undefined) { throw 'invalid module definition, definition function must be specified'; } require(dependencies, function() { modules[id] = definition.apply(null, arguments); }); } function defined(id) { return !!modules[id]; } function resolve(id) { var target = exports; var fragments = id.split(/[.\/]/); for (var fi = 0; fi < fragments.length; ++fi) { if (!target[fragments[fi]]) { return; } target = target[fragments[fi]]; } return target; } function expose(ids) { for (var i = 0; i < ids.length; i++) { var target = exports; var id = ids[i]; var fragments = id.split(/[.\/]/); for (var fi = 0; fi < fragments.length - 1; ++fi) { if (target[fragments[fi]] === undefined) { target[fragments[fi]] = {}; } target = target[fragments[fi]]; } target[fragments[fragments.length - 1]] = modules[id]; } } // Included from: js/tinymce/classes/dom/EventUtils.js /** * EventUtils.js * * Released under LGPL License. * Copyright (c) 1999-2015 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/dom/EventUtils", [], function() { "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}; /** * Binds a native event to a callback on the speified target. */ function addEvent(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. */ function removeEvent(target, name, callback, capture) { if (target.removeEventListener) { target.removeEventListener(name, callback, capture || false); } else if (target.detachEvent) { target.detachEvent('on' + name, callback); } } /** * Normalizes a native event object or just adds the event specific methods on a custom event. */ function fix(originalEvent, data) { var name, event = data || {}, undef; // Dummy function that gets replaced on the delegation state functions function returnFalse() { return false; } // Dummy function that gets replaced on the delegation state functions function returnTrue() { return true; } // 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; } // 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 (!event.isDefaultPrevented) { 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. */ function bindOnReady(win, callback, eventUtils) { var doc = win.document, event = {type: 'ready'}; if (eventUtils.domLoaded) { callback(event); return; } // Gets called when the DOM is ready function readyHandler() { if (!eventUtils.domLoaded) { eventUtils.domLoaded = true; callback(event); } } function waitForDomLoaded() { // Check complete or interactive state if there is a body // element on some iframes IE 8 will produce a null body if (doc.readyState === "complete" || (doc.readyState === "interactive" && doc.body)) { removeEvent(doc, "readystatechange", waitForDomLoaded); readyHandler(); } } function tryScroll() { 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) { setTimeout(tryScroll, 0); return; } readyHandler(); } // Use W3C method if (doc.addEventListener) { if (doc.readyState === "complete") { 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. */ function EventUtils() { 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. */ function executeHandlers(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 function defaultNativeHandler(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 bubbeling 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 specificed 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; }); // Included from: js/tinymce/classes/dom/Sizzle.js /** * Sizzle.js * * Released under LGPL License. * Copyright (c) 1999-2015 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing * * @ignore-file */ /*jshint bitwise:false, expr:true, noempty:false, sub:true, eqnull:true, latedef:false, maxlen:255 */ /*eslint-disable */ /** * Sizzle CSS Selector Engine v@VERSION * http://sizzlejs.com/ * * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors * Released under the MIT license * http://jquery.org/license * * Date: @DATE */ define("tinymce/dom/Sizzle", [], function() { var i, support, Expr, getText, isXML, tokenize, compile, select, outermostContext, sortInput, hasDuplicate, // Local document vars setDocument, document, docElem, documentIsHTML, rbuggyQSA, rbuggyMatches, matches, contains, // Instance-specific data expando = "sizzle" + -(new Date()), preferredDoc = window.document, dirruns = 0, done = 0, classCache = createCache(), tokenCache = createCache(), compilerCache = createCache(), sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; } return 0; }, // General-purpose constants strundefined = typeof undefined, MAX_NEGATIVE = 1 << 31, // Instance methods hasOwn = ({}).hasOwnProperty, arr = [], pop = arr.pop, push_native = arr.push, push = arr.push, slice = arr.slice, // Use a stripped-down indexOf if we can't use a native one indexOf = arr.indexOf || function( elem ) { var i = 0, len = this.length; for ( ; i < len; i++ ) { if ( this[i] === elem ) { return i; } } return -1; }, booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", // Regular expressions // http://www.w3.org/TR/css3-selectors/#whitespace whitespace = "[\\x20\\t\\r\\n\\f]", // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + // Operator (capture 2) "*([*^$|!~]?=)" + whitespace + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]", pseudos = ":(" + identifier + ")(?:\\((" + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: // 1. quoted (capture 3; capture 4 or capture 5) "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + // 2. simple (capture 6) "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + // 3. anything else (capture 2) ".*" + ")\\)|)", // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), rpseudo = new RegExp( pseudos ), ridentifier = new RegExp( "^" + identifier + "$" ), matchExpr = { "ID": new RegExp( "^#(" + identifier + ")" ), "CLASS": new RegExp( "^\\.(" + identifier + ")" ), "TAG": new RegExp( "^(" + identifier + "|[*])" ), "ATTR": new RegExp( "^" + attributes ), "PSEUDO": new RegExp( "^" + pseudos ), "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), // For use in libraries implementing .is() // We use this for POS matching in `select` "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) }, rinputs = /^(?:input|select|textarea|button)$/i, rheader = /^h\d$/i, rnative = /^[^{]+\{\s*\[native \w/, // Easily-parseable/retrievable ID or TAG or CLASS selectors rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, rsibling = /[+~]/, rescape = /'|\\/g, // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), funescape = function( _, escaped, escapedWhitespace ) { var high = "0x" + escaped - 0x10000; // NaN means non-codepoint // Support: Firefox<24 // Workaround erroneous numeric interpretation of +"0x" return high !== high || escapedWhitespace ? escaped : high < 0 ? // BMP codepoint String.fromCharCode( high + 0x10000 ) : // Supplemental Plane codepoint (surrogate pair) String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); }; // Optimize for push.apply( _, NodeList ) try { push.apply( (arr = slice.call( preferredDoc.childNodes )), preferredDoc.childNodes ); // Support: Android<4.0 // Detect silently failing push.apply arr[ preferredDoc.childNodes.length ].nodeType; } catch ( e ) { push = { apply: arr.length ? // Leverage slice if possible function( target, els ) { push_native.apply( target, slice.call(els) ); } : // Support: IE<9 // Otherwise append directly function( target, els ) { var j = target.length, i = 0; // Can't trust NodeList.length while ( (target[j++] = els[i++]) ) {} target.length = j - 1; } }; } function Sizzle( selector, context, results, seed ) { var match, elem, m, nodeType, // QSA vars i, groups, old, nid, newContext, newSelector; if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { setDocument( context ); } context = context || document; results = results || []; if ( !selector || typeof selector !== "string" ) { return results; } if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { return []; } if ( documentIsHTML && !seed ) { // Shortcuts if ( (match = rquickExpr.exec( selector )) ) { // Speed-up: Sizzle("#ID") if ( (m = match[1]) ) { if ( nodeType === 9 ) { elem = context.getElementById( m ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document (jQuery #6963) if ( elem && elem.parentNode ) { // Handle the case where IE, Opera, and Webkit return items // by name instead of ID if ( elem.id === m ) { results.push( elem ); return results; } } else { return results; } } else { // Context is not a document if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && contains( context, elem ) && elem.id === m ) { results.push( elem ); return results; } } // Speed-up: Sizzle("TAG") } else if ( match[2] ) { push.apply( results, context.getElementsByTagName( selector ) ); return results; // Speed-up: Sizzle(".CLASS") } else if ( (m = match[3]) && support.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); return results; } } // QSA path if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { nid = old = expando; newContext = context; newSelector = nodeType === 9 && selector; // qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root // and working up from there (Thanks to Andrew Dupont for the technique) // IE 8 doesn't work on object elements if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { groups = tokenize( selector ); if ( (old = context.getAttribute("id")) ) { nid = old.replace( rescape, "\\$&" ); } else { context.setAttribute( "id", nid ); } nid = "[id='" + nid + "'] "; i = groups.length; while ( i-- ) { groups[i] = nid + toSelector( groups[i] ); } newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; newSelector = groups.join(","); } if ( newSelector ) { try { push.apply( results, newContext.querySelectorAll( newSelector ) ); return results; } catch(qsaError) { } finally { if ( !old ) { context.removeAttribute("id"); } } } } } // All others return select( selector.replace( rtrim, "$1" ), context, results, seed ); } /** * Create key-value caches of limited size * @returns {Function(string, Object)} Returns the Object data after storing it on itself with * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) * deleting the oldest entry */ function createCache() { var keys = []; function cache( key, value ) { // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) if ( keys.push( key + " " ) > Expr.cacheLength ) { // Only keep the most recent entries delete cache[ keys.shift() ]; } return (cache[ key + " " ] = value); } return cache; } /** * Mark a function for special use by Sizzle * @param {Function} fn The function to mark */ function markFunction( fn ) { fn[ expando ] = true; return fn; } /** * Support testing using an element * @param {Function} fn Passed the created div and expects a boolean result */ function assert( fn ) { var div = document.createElement("div"); try { return !!fn( div ); } catch (e) { return false; } finally { // Remove from its parent by default if ( div.parentNode ) { div.parentNode.removeChild( div ); } // release memory in IE div = null; } } /** * Adds the same handler for all of the specified attrs * @param {String} attrs Pipe-separated list of attributes * @param {Function} handler The method that will be applied */ function addHandle( attrs, handler ) { var arr = attrs.split("|"), i = attrs.length; while ( i-- ) { Expr.attrHandle[ arr[i] ] = handler; } } /** * Checks document order of two siblings * @param {Element} a * @param {Element} b * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b */ function siblingCheck( a, b ) { var cur = b && a, diff = cur && a.nodeType === 1 && b.nodeType === 1 && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE ); // Use IE sourceIndex if available on both nodes if ( diff ) { return diff; } // Check if b follows a if ( cur ) { while ( (cur = cur.nextSibling) ) { if ( cur === b ) { return -1; } } } return a ? 1 : -1; } /** * Returns a function to use in pseudos for input types * @param {String} type */ function createInputPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && elem.type === type; }; } /** * Returns a function to use in pseudos for buttons * @param {String} type */ function createButtonPseudo( type ) { return function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && elem.type === type; }; } /** * Returns a function to use in pseudos for positionals * @param {Function} fn */ function createPositionalPseudo( fn ) { return markFunction(function( argument ) { argument = +argument; return markFunction(function( seed, matches ) { var j, matchIndexes = fn( [], seed.length, argument ), i = matchIndexes.length; // Match elements found at the specified indexes while ( i-- ) { if ( seed[ (j = matchIndexes[i]) ] ) { seed[j] = !(matches[j] = seed[j]); } } }); }); } /** * Checks a node for validity as a Sizzle context * @param {Element|Object=} context * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value */ function testContext( context ) { return context && typeof context.getElementsByTagName !== strundefined && context; } // Expose support vars for convenience support = Sizzle.support = {}; /** * Detects XML nodes * @param {Element|Object} elem An element or a document * @returns {Boolean} True iff elem is a non-HTML XML node */ isXML = Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = elem && (elem.ownerDocument || elem).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; /** * Sets document-related variables once based on the current document * @param {Element|Object} [doc] An element or document object to use to set the document * @returns {Object} Returns the current document */ setDocument = Sizzle.setDocument = function( node ) { var hasCompare, doc = node ? node.ownerDocument || node : preferredDoc, parent = doc.defaultView; // If no document and documentElement is available, return if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { return document; } // Set our document document = doc; docElem = doc.documentElement; // Support tests documentIsHTML = !isXML( doc ); // Support: IE>8 // If iframe document is assigned to "document" variable and if iframe has been reloaded, // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 // IE6-8 do not support the defaultView property so parent will be undefined if ( parent && parent !== parent.top ) { // IE11 does not have attachEvent, so all must suffer if ( parent.addEventListener ) { parent.addEventListener( "unload", function() { setDocument(); }, false ); } else if ( parent.attachEvent ) { parent.attachEvent( "onunload", function() { setDocument(); }); } } /* Attributes ---------------------------------------------------------------------- */ // Support: IE<8 // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) support.attributes = assert(function( div ) { div.className = "i"; return !div.getAttribute("className"); }); /* getElement(s)By* ---------------------------------------------------------------------- */ // Check if getElementsByTagName("*") returns only elements support.getElementsByTagName = assert(function( div ) { div.appendChild( doc.createComment("") ); return !div.getElementsByTagName("*").length; }); // Support: IE<9 support.getElementsByClassName = rnative.test( doc.getElementsByClassName ); // Support: IE<10 // Check if getElementById returns elements by name // The broken getElementById methods don't pick up programatically-set names, // so use a roundabout getElementsByName test support.getById = assert(function( div ) { docElem.appendChild( div ).id = expando; return !doc.getElementsByName || !doc.getElementsByName( expando ).length; }); // ID find and filter if ( support.getById ) { Expr.find["ID"] = function( id, context ) { if ( typeof context.getElementById !== strundefined && documentIsHTML ) { var m = context.getElementById( id ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 return m && m.parentNode ? [ m ] : []; } }; Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { return elem.getAttribute("id") === attrId; }; }; } else { // Support: IE6/7 // getElementById is not reliable as a find shortcut delete Expr.find["ID"]; Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); return node && node.value === attrId; }; }; } // Tag Expr.find["TAG"] = support.getElementsByTagName ? function( tag, context ) { if ( typeof context.getElementsByTagName !== strundefined ) { return context.getElementsByTagName( tag ); } } : function( tag, context ) { var elem, tmp = [], i = 0, results = context.getElementsByTagName( tag ); // Filter out possible comments if ( tag === "*" ) { while ( (elem = results[i++]) ) { if ( elem.nodeType === 1 ) { tmp.push( elem ); } } return tmp; } return results; }; // Class Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { if ( documentIsHTML ) { return context.getElementsByClassName( className ); } }; /* QSA/matchesSelector ---------------------------------------------------------------------- */ // QSA and matchesSelector support // matchesSelector(:active) reports false when true (IE9/Opera 11.5) rbuggyMatches = []; // qSa(:focus) reports false when true (Chrome 21) // We allow this because of a bug in IE8/9 that throws an error // whenever `document.activeElement` is accessed on an iframe // So, we allow :focus to pass through QSA all the time to avoid the IE error // See http://bugs.jquery.com/ticket/13378 rbuggyQSA = []; if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { // Build QSA regex // Regex strategy adopted from Diego Perini assert(function( div ) { // Select is set to empty string on purpose // This is to test IE's treatment of not explicitly // setting a boolean content attribute, // since its presence should be enough // http://bugs.jquery.com/ticket/12359 div.innerHTML = "<select msallowcapture=''><option selected=''></option></select>"; // Support: IE8, Opera 11-12.16 // Nothing should be selected when empty strings follow ^= or $= or *= // The test attribute must be unknown in Opera but "safe" for WinRT // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section if ( div.querySelectorAll("[msallowcapture^='']").length ) { rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); } // Support: IE8 // Boolean attributes and "value" are not treated correctly if ( !div.querySelectorAll("[selected]").length ) { rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); } // Webkit/Opera - :checked should return selected option elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked // IE8 throws error here and will not see later tests if ( !div.querySelectorAll(":checked").length ) { rbuggyQSA.push(":checked"); } }); assert(function( div ) { // Support: Windows 8 Native Apps // The type and name attributes are restricted during .innerHTML assignment var input = doc.createElement("input"); input.setAttribute( "type", "hidden" ); div.appendChild( input ).setAttribute( "name", "D" ); // Support: IE8 // Enforce case-sensitivity of name attribute if ( div.querySelectorAll("[name=d]").length ) { rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); } // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) // IE8 throws error here and will not see later tests if ( !div.querySelectorAll(":enabled").length ) { rbuggyQSA.push( ":enabled", ":disabled" ); } // Opera 10-11 does not throw on post-comma invalid pseudos div.querySelectorAll("*,:x"); rbuggyQSA.push(",.*:"); }); } if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector) )) ) { assert(function( div ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9) support.disconnectedMatch = matches.call( div, "div" ); // This should fail with an exception // Gecko does not error, returns false instead matches.call( div, "[s!='']:x" ); rbuggyMatches.push( "!=", pseudos ); }); } rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); /* Contains ---------------------------------------------------------------------- */ hasCompare = rnative.test( docElem.compareDocumentPosition ); // Element contains another // Purposefully does not implement inclusive descendent // As in, an element does not contain itself contains = hasCompare || rnative.test( docElem.contains ) ? function( a, b ) { var adown = a.nodeType === 9 ? a.documentElement : a, bup = b && b.parentNode; return a === bup || !!( bup && bup.nodeType === 1 && ( adown.contains ? adown.contains( bup ) : a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 )); } : function( a, b ) { if ( b ) { while ( (b = b.parentNode) ) { if ( b === a ) { return true; } } } return false; }; /* Sorting ---------------------------------------------------------------------- */ // Document order sorting sortOrder = hasCompare ? function( a, b ) { // Flag for duplicate removal if ( a === b ) { hasDuplicate = true; return 0; } // Sort on method existence if only one input has compareDocumentPosition var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; if ( compare ) { return compare; } // Calculate position if both inputs belong to the same document compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? a.compareDocumentPosition( b ) : // Otherwise we know they are disconnected 1; // Disconnected nodes if ( compare & 1 || (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { // Choose the first element that is related to our preferred document if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { return -1; } if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { return 1; } // Maintain original order return sortInput ? ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : 0; } return compare & 4 ? -1 : 1; } : function( a, b ) { // Exit early if the nodes are identical if ( a === b ) { hasDuplicate = true; return 0; } var cur, i = 0, aup = a.parentNode, bup = b.parentNode, ap = [ a ], bp = [ b ]; // Parentless nodes are either documents or disconnected if ( !aup || !bup ) { return a === doc ? -1 : b === doc ? 1 : aup ? -1 : bup ? 1 : sortInput ? ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : 0; // If the nodes are siblings, we can do a quick check } else if ( aup === bup ) { return siblingCheck( a, b ); } // Otherwise we need full lists of their ancestors for comparison cur = a; while ( (cur = cur.parentNode) ) { ap.unshift( cur ); } cur = b; while ( (cur = cur.parentNode) ) { bp.unshift( cur ); } // Walk down the tree looking for a discrepancy while ( ap[i] === bp[i] ) { i++; } return i ? // Do a sibling check if the nodes have a common ancestor siblingCheck( ap[i], bp[i] ) : // Otherwise nodes in our document sort first ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0; }; return doc; }; Sizzle.matches = function( expr, elements ) { return Sizzle( expr, null, null, elements ); }; Sizzle.matchesSelector = function( elem, expr ) { // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) { setDocument( elem ); } // Make sure that attribute selectors are quoted expr = expr.replace( rattributeQuotes, "='$1']" ); if ( support.matchesSelector && documentIsHTML && ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { try { var ret = matches.call( elem, expr ); // IE 9's matchesSelector returns false on disconnected nodes if ( ret || support.disconnectedMatch || // As well, disconnected nodes are said to be in a document // fragment in IE 9 elem.document && elem.document.nodeType !== 11 ) { return ret; } } catch(e) {} } return Sizzle( expr, document, null, [ elem ] ).length > 0; }; Sizzle.contains = function( context, elem ) { // Set document vars if needed if ( ( context.ownerDocument || context ) !== document ) { setDocument( context ); } return contains( context, elem ); }; Sizzle.attr = function( elem, name ) { // Set document vars if needed if ( ( elem.ownerDocument || elem ) !== document ) { setDocument( elem ); } var fn = Expr.attrHandle[ name.toLowerCase() ], // Don't get fooled by Object.prototype properties (jQuery #13807) val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? fn( elem, name, !documentIsHTML ) : undefined; return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute( name ) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null; }; Sizzle.error = function( msg ) { throw new Error( "Syntax error, unrecognized expression: " + msg ); }; /** * Document sorting and removing duplicates * @param {ArrayLike} results */ Sizzle.uniqueSort = function( results ) { var elem, duplicates = [], j = 0, i = 0; // Unless we *know* we can detect duplicates, assume their presence hasDuplicate = !support.detectDuplicates; sortInput = !support.sortStable && results.slice( 0 ); results.sort( sortOrder ); if ( hasDuplicate ) { while ( (elem = results[i++]) ) { if ( elem === results[ i ] ) { j = duplicates.push( i ); } } while ( j-- ) { results.splice( duplicates[ j ], 1 ); } } // Clear input after sorting to release objects // See https://github.com/jquery/sizzle/pull/225 sortInput = null; return results; }; /** * Utility function for retrieving the text value of an array of DOM nodes * @param {Array|Element} elem */ getText = Sizzle.getText = function( elem ) { var node, ret = "", i = 0, nodeType = elem.nodeType; if ( !nodeType ) { // If no nodeType, this is expected to be an array while ( (node = elem[i++]) ) { // Do not traverse comment nodes ret += getText( node ); } } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { // Use textContent for elements // innerText usage removed for consistency of new lines (jQuery #11153) if ( typeof elem.textContent === "string" ) { return elem.textContent; } else { // Traverse its children for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { ret += getText( elem ); } } } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } // Do not include comment or processing instruction nodes return ret; }; Expr = Sizzle.selectors = { // Can be adjusted by the user cacheLength: 50, createPseudo: markFunction, match: matchExpr, attrHandle: {}, find: {}, relative: { ">": { dir: "parentNode", first: true }, " ": { dir: "parentNode" }, "+": { dir: "previousSibling", first: true }, "~": { dir: "previousSibling" } }, preFilter: { "ATTR": function( match ) { match[1] = match[1].replace( runescape, funescape ); // Move the given value to match[3] whether quoted or unquoted match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); if ( match[2] === "~=" ) { match[3] = " " + match[3] + " "; } return match.slice( 0, 4 ); }, "CHILD": function( match ) { /* matches from matchExpr["CHILD"] 1 type (only|nth|...) 2 what (child|of-type) 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 4 xn-component of xn+y argument ([+-]?\d*n|) 5 sign of xn-component 6 x of xn-component 7 sign of y-component 8 y of y-component */ match[1] = match[1].toLowerCase(); if ( match[1].slice( 0, 3 ) === "nth" ) { // nth-* requires argument if ( !match[3] ) { Sizzle.error( match[0] ); } // numeric x and y parameters for Expr.filter.CHILD // remember that false/true cast respectively to 0/1 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); // other types prohibit arguments } else if ( match[3] ) { Sizzle.error( match[0] ); } return match; }, "PSEUDO": function( match ) { var excess, unquoted = !match[6] && match[2]; if ( matchExpr["CHILD"].test( match[0] ) ) { return null; } // Accept quoted arguments as-is if ( match[3] ) { match[2] = match[4] || match[5] || ""; // Strip excess characters from unquoted arguments } else if ( unquoted && rpseudo.test( unquoted ) && // Get excess from tokenize (recursively) (excess = tokenize( unquoted, true )) && // advance to the next closing parenthesis (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { // excess is a negative index match[0] = match[0].slice( 0, excess ); match[2] = unquoted.slice( 0, excess ); } // Return only captures needed by the pseudo filter method (type and argument) return match.slice( 0, 3 ); } }, filter: { "TAG": function( nodeNameSelector ) { var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); return nodeNameSelector === "*" ? function() { return true; } : function( elem ) { return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; }; }, "CLASS": function( className ) { var pattern = classCache[ className + " " ]; return pattern || (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && classCache( className, function( elem ) { return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); }); }, "ATTR": function( name, operator, check ) { return function( elem ) { var result = Sizzle.attr( elem, name ); if ( result == null ) { return operator === "!="; } if ( !operator ) { return true; } result += ""; return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf( check ) === 0 : operator === "*=" ? check && result.indexOf( check ) > -1 : operator === "$=" ? check && result.slice( -check.length ) === check : operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : false; }; }, "CHILD": function( type, what, argument, first, last ) { var simple = type.slice( 0, 3 ) !== "nth", forward = type.slice( -4 ) !== "last", ofType = what === "of-type"; return first === 1 && last === 0 ? // Shortcut for :nth-*(n) function( elem ) { return !!elem.parentNode; } : function( elem, context, xml ) { var cache, outerCache, node, diff, nodeIndex, start, dir = simple !== forward ? "nextSibling" : "previousSibling", parent = elem.parentNode, name = ofType && elem.nodeName.toLowerCase(), useCache = !xml && !ofType; if ( parent ) { // :(first|last|only)-(child|of-type) if ( simple ) { while ( dir ) { node = elem; while ( (node = node[ dir ]) ) { if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {