funcunit
Version:
<!-- @hide title
302 lines • 273 kB
JavaScript
/*[system-bundles-config]*/
System.bundles = {};
/*semver*/
System.set('semver', System.newModule({}));
/*npm-extension*/
System.set('npm-extension', System.newModule({}));
/*npm*/
System.set('npm', System.newModule({}));
/*package.json!npm*/
define('pkg.json!npm', ['@loader'], function (loader) {
function createModuleName(descriptor, standard) {
if (standard) {
return descriptor.moduleName;
} else {
return descriptor.packageName + (descriptor.version ? '@' + descriptor.version : '') + (descriptor.modulePath ? '#' + descriptor.modulePath : '') + (descriptor.plugin ? '!' + descriptor.plugin : '');
}
}
function parseModuleName(moduleName, currentPackageName) {
var pluginParts = moduleName.split('!');
var modulePathParts = pluginParts[0].split('#');
var versionParts = modulePathParts[0].split('@');
if (!modulePathParts[1] && !versionParts[0]) {
versionParts = ['@' + versionParts[0]];
}
var packageName, modulePath;
if (currentPackageName && isRelative(moduleName)) {
packageName = currentPackageName;
modulePath = versionParts[0];
} else {
if (modulePathParts[1]) {
packageName = versionParts[0];
modulePath = modulePathParts[1];
} else {
var folderParts = versionParts[0].split('/');
packageName = folderParts.shift();
modulePath = folderParts.join('/');
}
}
return {
plugin: pluginParts[1],
version: versionParts[1],
modulePath: modulePath,
packageName: packageName,
moduleName: moduleName
};
}
function isRelative(path) {
return path.substr(0, 1) === '.';
}
function childPackageAddress(parentPackageAddress, childName) {
var packageFolderName = parentPackageAddress.replace(/\/package\.json.*/, '');
return (packageFolderName ? packageFolderName + '/' : '') + 'node_modules/' + childName + '/package.json';
}
function parentNodeModuleAddress(address) {
var nodeModules = '/node_modules/', nodeModulesIndex = address.lastIndexOf(nodeModules), prevModulesIndex = address.lastIndexOf(nodeModules, nodeModulesIndex - 1);
if (prevModulesIndex >= 0) {
return address.substr(0, prevModulesIndex + nodeModules.length - 1);
}
}
(function (System) {
var oldNormalize = System.normalize;
System.normalize = function (name, parentName, parentAddress) {
console.log('normalize', name, parentName, parentAddress);
var refPkg = findPackageByAddress(this, parentName, parentAddress);
if (!refPkg) {
return oldNormalize.call(this, name, parentName, parentAddress);
}
var parsedModuleName = parsedModuleNameFromPackage(this, refPkg, name, parentName);
var depPkg = findDepPackage(this, refPkg, parsedModuleName.packageName);
if (!depPkg) {
depPkg = findPackage(this, parsedModuleName.packageName);
}
if (!depPkg) {
var browserPackageName = this.globalBrowser[parsedModuleName.packageName];
if (browserPackageName) {
parsedModuleName.packageName = browserPackageName;
depPkg = findPackage(this, parsedModuleName.packageName);
}
}
if (depPkg) {
parsedModuleName.version = depPkg.version;
if (!parsedModuleName.modulePath) {
parsedModuleName.modulePath = typeof depPkg.browser === 'string' && depPkg.browser || depPkg.main || 'index';
}
return createModuleName(parsedModuleName);
} else {
return oldNormalize.call(this, createModuleName(parsedModuleName, true), parentName, parentAddress);
}
};
var oldLocate = System.locate;
System.locate = function (load) {
console.log('locate', load.name);
var parsedModuleName = parseModuleName(load.name);
if (parsedModuleName.version && this.npm) {
var pkg = this.npm[parsedModuleName.packageName];
if (pkg === this.npmPaths.__default) {
var loadCopy = extend({}, load);
loadCopy.name = parsedModuleName.modulePath;
return oldLocate.call(this, loadCopy);
} else if (pkg) {
if (parsedModuleName.modulePath) {
return joinURL(packageFolderAddress(pkg.fileUrl), addJS(parsedModuleName.modulePath));
}
}
}
return oldLocate.call(this, load);
};
function findPackageByAddress(loader, parentName, parentAddress) {
if (loader.npm) {
if (parentName) {
var parsed = parseModuleName(parentName);
if (parsed.version && parsed.packageName) {
var name = parsed.packageName + '@' + parsed.version;
if (name in loader.npm) {
return loader.npm[name];
}
}
}
if (parentAddress) {
var packageFolder = packageFolderAddress(parentAddress);
return packageFolder ? loader.npmPaths[packageFolder] : loader.npmPaths.__default;
} else {
return loader.npmPaths.__default;
}
}
}
function findPackage(loader, name) {
if (loader.npm && !startsWithDotSlash(name)) {
return loader.npm[name];
}
}
function findDepPackage(loader, refPackage, name) {
if (loader.npm && refPackage && !startsWithDotSlash(name)) {
var curPackage = childPackageAddress(refPackage.fileUrl, name).replace(/\/package\.json.*/, '');
while (curPackage) {
var pkg = loader.npmPaths[curPackage];
if (pkg) {
return pkg;
}
var parentAddress = parentNodeModuleAddress(curPackage);
if (!parentAddress) {
return;
}
curPackage = parentAddress + '/' + name;
}
}
}
function parsedModuleNameFromPackage(loader, refPkg, name, parentName) {
var packageName = refPkg.name, parsedModuleName = parseModuleName(name, packageName);
if (isRelative(parsedModuleName.modulePath)) {
var parentParsed = parseModuleName(parentName, packageName);
if (parentParsed.packageName === parsedModuleName.packageName && parentParsed.modulePath) {
parsedModuleName.modulePath = joinURIs(parentParsed.modulePath, parsedModuleName.modulePath);
}
}
var mapName = createModuleName(parsedModuleName), mappedName;
if (refPkg.browser && mapName in refPkg.browser) {
mappedName = refPkg.browser[mapName] === false ? '@empty' : refPkg.browser[mapName];
}
var global = loader && loader.globalBrowser && loader.globalBrowser[mapName];
if (global) {
mappedName = global.moduleName === false ? '@empty' : global.moduleName;
}
if (mappedName) {
return parseModuleName(mappedName, packageName);
} else {
return parsedModuleName;
}
}
function addJS(path) {
if (/\.\w+$/.test(path)) {
return path;
} else {
return path + '.js';
}
}
function packageFolderAddress(address) {
var nodeModules = '/node_modules/', nodeModulesIndex = address.lastIndexOf(nodeModules), nextSlash = address.indexOf('/', nodeModulesIndex + nodeModules.length);
if (nodeModulesIndex >= 0) {
return nextSlash >= 0 ? address.substr(0, nextSlash) : address;
}
}
function parseURI(url) {
var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
return m ? {
href: m[0] || '',
protocol: m[1] || '',
authority: m[2] || '',
host: m[3] || '',
hostname: m[4] || '',
port: m[5] || '',
pathname: m[6] || '',
search: m[7] || '',
hash: m[8] || ''
} : null;
}
function joinURIs(base, href) {
function removeDotSegments(input) {
var output = [];
input.replace(/^(\.\.?(\/|$))+/, '').replace(/\/(\.(\/|$))+/g, '/').replace(/\/\.\.$/, '/../').replace(/\/?[^\/]*/g, function (p) {
if (p === '/..') {
output.pop();
} else {
output.push(p);
}
});
return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
}
href = parseURI(href || '');
base = parseURI(base || '');
return !href || !base ? null : (href.protocol || base.protocol) + (href.protocol || href.authority ? href.authority : base.authority) + removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : href.pathname ? (base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname : base.pathname) + (href.protocol || href.authority || href.pathname ? href.search : href.search || base.search) + href.hash;
}
function startsWithDotSlash(path) {
return path.substr(0, 2) === './';
}
function endsWithSlash(path) {
return path[path.length - 1] === '/';
}
function removeTrailingSlash(path) {
if (endsWithSlash(path)) {
return path.substr(0, path.length - 1);
} else {
return path;
}
}
function removeLeadingDotSlash(path) {
if (startsWithDotSlash(path)) {
return path.substr(2);
} else {
return path;
}
}
function joinURL(baseURL, url) {
baseURL = removeTrailingSlash(baseURL);
url = removeLeadingDotSlash(url);
return baseURL + '/' + url;
}
}(loader));
if (!System.main) {
System.main = 'main';
}
(function (loader, packages) {
var g;
if (typeof window !== 'undefined') {
g = window;
} else {
g = global;
}
if (!g.process) {
g.process = {
cwd: function () {
}
};
}
if (!loader.npm) {
loader.npm = {};
loader.npmPaths = {};
loader.globalBrowser = {};
}
loader.npmPaths.__default = packages[0];
var setGlobalBrowser = function (globals, pkg) {
for (var name in globals) {
loader.globalBrowser[name] = {
pkg: pkg,
moduleName: globals[name]
};
}
};
packages.forEach(function (pkg) {
if (pkg.system) {
loader.config(pkg.system);
}
if (pkg.globalBrowser) {
setGlobalBrowser(pkg.globalBrowser, pkg);
}
if (!loader.npm[pkg.name]) {
loader.npm[pkg.name] = pkg;
}
loader.npm[pkg.name + '@' + pkg.version] = pkg;
var pkgAddress = pkg.fileUrl.replace(/\/package\.json.*/, '');
loader.npmPaths[pkgAddress] = pkg;
});
}(loader, [
{
'fileUrl': '/Users/justin/dev/steal-tools/test/npm/package.json',
'main': 'main',
'system': { 'meta': { 'jquery@2.1.3#dist/jquery.js': { 'format': 'global' } } },
'globalBrowser': {},
'browser': {}
},
{
'name': 'jquery',
'version': '2.1.3',
'fileUrl': '/Users/justin/dev/steal-tools/test/npm/node_modules/jquery/package.json',
'main': 'dist/jquery.js',
'globalBrowser': {},
'browser': {}
}
]));
});
/*jquery@2.1.3#dist/jquery.js*/
System.define('jquery@2.1.3#dist/jquery.js','/*!\n * jQuery JavaScript Library v2.1.3\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-18T15:11Z\n */\n\n(function( global, factory ) {\n\n if ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n // For CommonJS and CommonJS-like environments where a proper `window`\n // is present, execute the factory and get jQuery.\n // For environments that do not have a `window` with a `document`\n // (such as Node.js), expose a factory as module.exports.\n // This accentuates the need for the creation of a real `window`.\n // e.g. var jQuery = require(\"jquery\")(window);\n // See ticket #14549 for more info.\n module.exports = global.document ?\n factory( global, true ) :\n function( w ) {\n if ( !w.document ) {\n throw new Error( \"jQuery requires a window with a document\" );\n }\n return factory( w );\n };\n } else {\n factory( global );\n }\n\n// Pass this if window is not defined yet\n}(typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Support: Firefox 18+\n// Can\'t be in strict mode, several libs including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n//\n\nvar arr = [];\n\nvar slice = arr.slice;\n\nvar concat = arr.concat;\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar support = {};\n\n\n\nvar\n // Use the correct document accordingly with window argument (sandbox)\n document = window.document,\n\n version = \"2.1.3\",\n\n // Define a local copy of jQuery\n jQuery = function( selector, context ) {\n // The jQuery object is actually just the init constructor \'enhanced\'\n // Need init if jQuery is called (just allow error to be thrown if not included)\n return new jQuery.fn.init( selector, context );\n },\n\n // Support: Android<4.1\n // Make sure we trim BOM and NBSP\n rtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n // Matches dashed string for camelizing\n rmsPrefix = /^-ms-/,\n rdashAlpha = /-([\\da-z])/gi,\n\n // Used by jQuery.camelCase as callback to replace()\n fcamelCase = function( all, letter ) {\n return letter.toUpperCase();\n };\n\njQuery.fn = jQuery.prototype = {\n // The current version of jQuery being used\n jquery: version,\n\n constructor: jQuery,\n\n // Start with an empty selector\n selector: \"\",\n\n // The default length of a jQuery object is 0\n length: 0,\n\n toArray: function() {\n return slice.call( this );\n },\n\n // Get the Nth element in the matched element set OR\n // Get the whole matched element set as a clean array\n get: function( num ) {\n return num != null ?\n\n // Return just the one element from the set\n ( num < 0 ? this[ num + this.length ] : this[ num ] ) :\n\n // Return all the elements in a clean array\n slice.call( this );\n },\n\n // Take an array of elements and push it onto the stack\n // (returning the new matched element set)\n pushStack: function( elems ) {\n\n // Build a new jQuery matched element set\n var ret = jQuery.merge( this.constructor(), elems );\n\n // Add the old object onto the stack (as a reference)\n ret.prevObject = this;\n ret.context = this.context;\n\n // Return the newly-formed element set\n return ret;\n },\n\n // Execute a callback for every element in the matched set.\n // (You can seed the arguments with an array of args, but this is\n // only used internally.)\n each: function( callback, args ) {\n return jQuery.each( this, callback, args );\n },\n\n map: function( callback ) {\n return this.pushStack( jQuery.map(this, function( elem, i ) {\n return callback.call( elem, i, elem );\n }));\n },\n\n slice: function() {\n return this.pushStack( slice.apply( this, arguments ) );\n },\n\n first: function() {\n return this.eq( 0 );\n },\n\n last: function() {\n return this.eq( -1 );\n },\n\n eq: function( i ) {\n var len = this.length,\n j = +i + ( i < 0 ? len : 0 );\n return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n },\n\n end: function() {\n return this.prevObject || this.constructor(null);\n },\n\n // For internal use only.\n // Behaves like an Array\'s method, not like a jQuery method.\n push: push,\n sort: arr.sort,\n splice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n var options, name, src, copy, copyIsArray, clone,\n target = arguments[0] || {},\n i = 1,\n length = arguments.length,\n deep = false;\n\n // Handle a deep copy situation\n if ( typeof target === \"boolean\" ) {\n deep = target;\n\n // Skip the boolean and the target\n target = arguments[ i ] || {};\n i++;\n }\n\n // Handle case when target is a string or something (possible in deep copy)\n if ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n target = {};\n }\n\n // Extend jQuery itself if only one argument is passed\n if ( i === length ) {\n target = this;\n i--;\n }\n\n for ( ; i < length; i++ ) {\n // Only deal with non-null/undefined values\n if ( (options = arguments[ i ]) != null ) {\n // Extend the base object\n for ( name in options ) {\n src = target[ name ];\n copy = options[ name ];\n\n // Prevent never-ending loop\n if ( target === copy ) {\n continue;\n }\n\n // Recurse if we\'re merging plain objects or arrays\n if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n if ( copyIsArray ) {\n copyIsArray = false;\n clone = src && jQuery.isArray(src) ? src : [];\n\n } else {\n clone = src && jQuery.isPlainObject(src) ? src : {};\n }\n\n // Never move original objects, clone them\n target[ name ] = jQuery.extend( deep, clone, copy );\n\n // Don\'t bring in undefined values\n } else if ( copy !== undefined ) {\n target[ name ] = copy;\n }\n }\n }\n }\n\n // Return the modified object\n return target;\n};\n\njQuery.extend({\n // Unique for each copy of jQuery on the page\n expando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n // Assume jQuery is ready without the ready module\n isReady: true,\n\n error: function( msg ) {\n throw new Error( msg );\n },\n\n noop: function() {},\n\n isFunction: function( obj ) {\n return jQuery.type(obj) === \"function\";\n },\n\n isArray: Array.isArray,\n\n isWindow: function( obj ) {\n return obj != null && obj === obj.window;\n },\n\n isNumeric: function( obj ) {\n // parseFloat NaNs numeric-cast false positives (null|true|false|\"\")\n // ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n // subtraction forces infinities to NaN\n // adding 1 corrects loss of precision from parseFloat (#15100)\n return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;\n },\n\n isPlainObject: function( obj ) {\n // Not plain objects:\n // - Any object or value whose internal [[Class]] property is not \"[object Object]\"\n // - DOM nodes\n // - window\n if ( jQuery.type( obj ) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n return false;\n }\n\n if ( obj.constructor &&\n !hasOwn.call( obj.constructor.prototype, \"isPrototypeOf\" ) ) {\n return false;\n }\n\n // If the function hasn\'t returned already, we\'re confident that\n // |obj| is a plain object, created by {} or constructed with new Object\n return true;\n },\n\n isEmptyObject: function( obj ) {\n var name;\n for ( name in obj ) {\n return false;\n }\n return true;\n },\n\n type: function( obj ) {\n if ( obj == null ) {\n return obj + \"\";\n }\n // Support: Android<4.0, iOS<6 (functionish RegExp)\n return typeof obj === \"object\" || typeof obj === \"function\" ?\n class2type[ toString.call(obj) ] || \"object\" :\n typeof obj;\n },\n\n // Evaluates a script in a global context\n globalEval: function( code ) {\n var script,\n indirect = eval;\n\n code = jQuery.trim( code );\n\n if ( code ) {\n // If the code includes a valid, prologue position\n // strict mode pragma, execute code by injecting a\n // script tag into the document.\n if ( code.indexOf(\"use strict\") === 1 ) {\n script = document.createElement(\"script\");\n script.text = code;\n document.head.appendChild( script ).parentNode.removeChild( script );\n } else {\n // Otherwise, avoid the DOM node creation, insertion\n // and removal by using an indirect global eval\n indirect( code );\n }\n }\n },\n\n // Convert dashed to camelCase; used by the css and data modules\n // Support: IE9-11+\n // Microsoft forgot to hump their vendor prefix (#9572)\n camelCase: function( string ) {\n return string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n },\n\n nodeName: function( elem, name ) {\n return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n },\n\n // args is for internal usage only\n each: function( obj, callback, args ) {\n var value,\n i = 0,\n length = obj.length,\n isArray = isArraylike( obj );\n\n if ( args ) {\n if ( isArray ) {\n for ( ; i < length; i++ ) {\n value = callback.apply( obj[ i ], args );\n\n if ( value === false ) {\n break;\n }\n }\n } else {\n for ( i in obj ) {\n value = callback.apply( obj[ i ], args );\n\n if ( value === false ) {\n break;\n }\n }\n }\n\n // A special, fast, case for the most common use of each\n } else {\n if ( isArray ) {\n for ( ; i < length; i++ ) {\n value = callback.call( obj[ i ], i, obj[ i ] );\n\n if ( value === false ) {\n break;\n }\n }\n } else {\n for ( i in obj ) {\n value = callback.call( obj[ i ], i, obj[ i ] );\n\n if ( value === false ) {\n break;\n }\n }\n }\n }\n\n return obj;\n },\n\n // Support: Android<4.1\n trim: function( text ) {\n return text == null ?\n \"\" :\n ( text + \"\" ).replace( rtrim, \"\" );\n },\n\n // results is for internal usage only\n makeArray: function( arr, results ) {\n var ret = results || [];\n\n if ( arr != null ) {\n if ( isArraylike( Object(arr) ) ) {\n jQuery.merge( ret,\n typeof arr === \"string\" ?\n [ arr ] : arr\n );\n } else {\n push.call( ret, arr );\n }\n }\n\n return ret;\n },\n\n inArray: function( elem, arr, i ) {\n return arr == null ? -1 : indexOf.call( arr, elem, i );\n },\n\n merge: function( first, second ) {\n var len = +second.length,\n j = 0,\n i = first.length;\n\n for ( ; j < len; j++ ) {\n first[ i++ ] = second[ j ];\n }\n\n first.length = i;\n\n return first;\n },\n\n grep: function( elems, callback, invert ) {\n var callbackInverse,\n matches = [],\n i = 0,\n length = elems.length,\n callbackExpect = !invert;\n\n // Go through the array, only saving the items\n // that pass the validator function\n for ( ; i < length; i++ ) {\n callbackInverse = !callback( elems[ i ], i );\n if ( callbackInverse !== callbackExpect ) {\n matches.push( elems[ i ] );\n }\n }\n\n return matches;\n },\n\n // arg is for internal usage only\n map: function( elems, callback, arg ) {\n var value,\n i = 0,\n length = elems.length,\n isArray = isArraylike( elems ),\n ret = [];\n\n // Go through the array, translating each of the items to their new values\n if ( isArray ) {\n for ( ; i < length; i++ ) {\n value = callback( elems[ i ], i, arg );\n\n if ( value != null ) {\n ret.push( value );\n }\n }\n\n // Go through every key on the object,\n } else {\n for ( i in elems ) {\n value = callback( elems[ i ], i, arg );\n\n if ( value != null ) {\n ret.push( value );\n }\n }\n }\n\n // Flatten any nested arrays\n return concat.apply( [], ret );\n },\n\n // A global GUID counter for objects\n guid: 1,\n\n // Bind a function to a context, optionally partially applying any\n // arguments.\n proxy: function( fn, context ) {\n var tmp, args, proxy;\n\n if ( typeof context === \"string\" ) {\n tmp = fn[ context ];\n context = fn;\n fn = tmp;\n }\n\n // Quick check to determine if target is callable, in the spec\n // this throws a TypeError, but we will just return undefined.\n if ( !jQuery.isFunction( fn ) ) {\n return undefined;\n }\n\n // Simulated bind\n args = slice.call( arguments, 2 );\n proxy = function() {\n return fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n };\n\n // Set the guid of unique handler to the same of original handler, so it can be removed\n proxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n return proxy;\n },\n\n now: Date.now,\n\n // jQuery.support is not used in Core but other projects attach their\n // properties to it so it needs to exist.\n support: support\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n class2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n var length = obj.length,\n type = jQuery.type( obj );\n\n if ( type === \"function\" || jQuery.isWindow( obj ) ) {\n return false;\n }\n\n if ( obj.nodeType === 1 && length ) {\n return true;\n }\n\n return type === \"array\" || length === 0 ||\n typeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.2.0-pre\n * http://sizzlejs.com/\n *\n * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-16\n */\n(function( window ) {\n\nvar i,\n support,\n Expr,\n getText,\n isXML,\n tokenize,\n compile,\n select,\n outermostContext,\n sortInput,\n hasDuplicate,\n\n // Local document vars\n setDocument,\n document,\n docElem,\n documentIsHTML,\n rbuggyQSA,\n rbuggyMatches,\n matches,\n contains,\n\n // Instance-specific data\n expando = \"sizzle\" + 1 * new Date(),\n preferredDoc = window.document,\n dirruns = 0,\n done = 0,\n classCache = createCache(),\n tokenCache = createCache(),\n compilerCache = createCache(),\n sortOrder = function( a, b ) {\n if ( a === b ) {\n hasDuplicate = true;\n }\n return 0;\n },\n\n // General-purpose constants\n MAX_NEGATIVE = 1 << 31,\n\n // Instance methods\n hasOwn = ({}).hasOwnProperty,\n arr = [],\n pop = arr.pop,\n push_native = arr.push,\n push = arr.push,\n slice = arr.slice,\n // Use a stripped-down indexOf as it\'s faster than native\n // http://jsperf.com/thor-indexof-vs-for/5\n indexOf = function( list, elem ) {\n var i = 0,\n len = list.length;\n for ( ; i < len; i++ ) {\n if ( list[i] === elem ) {\n return i;\n }\n }\n return -1;\n },\n\n booleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n // Regular expressions\n\n // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n whitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n // http://www.w3.org/TR/css3-syntax/#characters\n characterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n // Loosely modeled on CSS identifier characters\n // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n identifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n attributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")(?:\" + whitespace +\n // Operator (capture 2)\n \"*([*^$|!~]?=)\" + whitespace +\n // \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n \"*(?:\'((?:\\\\\\\\.|[^\\\\\\\\\'])*)\'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n \"*\\\\]\",\n\n pseudos = \":(\" + characterEncoding + \")(?:\\\\((\" +\n // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n // 1. quoted (capture 3; capture 4 or capture 5)\n \"(\'((?:\\\\\\\\.|[^\\\\\\\\\'])*)\'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n // 2. simple (capture 6)\n \"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n // 3. anything else (capture 2)\n \".*\" +\n \")\\\\)|)\",\n\n // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n rwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n rtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n rcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n rcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n rattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]\'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n rpseudo = new RegExp( pseudos ),\n ridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n matchExpr = {\n \"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n \"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n \"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n \"ATTR\": new RegExp( \"^\" + attributes ),\n \"PSEUDO\": new RegExp( \"^\" + pseudos ),\n \"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n \"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n \"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n \"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n // For use in libraries implementing .is()\n // We use this for POS matching in `select`\n \"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n whitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n },\n\n rinputs = /^(?:input|select|textarea|button)$/i,\n rheader = /^h\\d$/i,\n\n rnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n // Easily-parseable/retrievable ID or TAG or CLASS selectors\n rquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n rsibling = /[+~]/,\n rescape = /\'|\\\\/g,\n\n // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n runescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n funescape = function( _, escaped, escapedWhitespace ) {\n var high = \"0x\" + escaped - 0x10000;\n // NaN means non-codepoint\n // Support: Firefox<24\n // Workaround erroneous numeric interpretation of +\"0x\"\n return high !== high || escapedWhitespace ?\n escaped :\n high < 0 ?\n // BMP codepoint\n String.fromCharCode( high + 0x10000 ) :\n // Supplemental Plane codepoint (surrogate pair)\n String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n },\n\n // Used for iframes\n // See setDocument()\n // Removing the function wrapper causes a \"Permission Denied\"\n // error in IE\n unloadHandler = function() {\n setDocument();\n };\n\n// Optimize for push.apply( _, NodeList )\ntry {\n push.apply(\n (arr = slice.call( preferredDoc.childNodes )),\n preferredDoc.childNodes\n );\n // Support: Android<4.0\n // Detect silently failing push.apply\n arr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n push = { apply: arr.length ?\n\n // Leverage slice if possible\n function( target, els ) {\n push_native.apply( target, slice.call(els) );\n } :\n\n // Support: IE<9\n // Otherwise append directly\n function( target, els ) {\n var j = target.length,\n i = 0;\n // Can\'t trust NodeList.length\n while ( (target[j++] = els[i++]) ) {}\n target.length = j - 1;\n }\n };\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n var match, elem, m, nodeType,\n // QSA vars\n i, groups, old, nid, newContext, newSelector;\n\n if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n setDocument( context );\n }\n\n context = context || document;\n results = results || [];\n nodeType = context.nodeType;\n\n if ( typeof selector !== \"string\" || !selector ||\n nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n return results;\n }\n\n if ( !seed && documentIsHTML ) {\n\n // Try to shortcut find operations when possible (e.g., not under DocumentFragment)\n if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n // Speed-up: Sizzle(\"#ID\")\n if ( (m = match[1]) ) {\n if ( nodeType === 9 ) {\n elem = context.getElementById( m );\n // Check parentNode to catch when Blackberry 4.6 returns\n // nodes that are no longer in the document (jQuery #6963)\n if ( elem && elem.parentNode ) {\n // Handle the case where IE, Opera, and Webkit return items\n // by name instead of ID\n if ( elem.id === m ) {\n results.push( elem );\n return results;\n }\n } else {\n return results;\n }\n } else {\n // Context is not a document\n if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n contains( context, elem ) && elem.id === m ) {\n results.push( elem );\n return results;\n }\n }\n\n // Speed-up: Sizzle(\"TAG\")\n } else if ( match[2] ) {\n push.apply( results, context.getElementsByTagName( selector ) );\n return results;\n\n // Speed-up: Sizzle(\".CLASS\")\n } else if ( (m = match[3]) && support.getElementsByClassName ) {\n push.apply( results, context.getElementsByClassName( m ) );\n return results;\n }\n }\n\n // QSA path\n if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n nid = old = expando;\n newContext = context;\n newSelector = nodeType !== 1 && selector;\n\n // qSA works strangely on Element-rooted queries\n // We can work around this by specifying an extra ID on the root\n // and working up from there (Thanks to Andrew Dupont for the technique)\n // IE 8 doesn\'t work on object elements\n if ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n groups = tokenize( selector );\n\n if ( (old = context.getAttribute(\"id\")) ) {\n nid = old.replace( rescape, \"\\\\$&\" );\n } else {\n context.setAttribute( \"id\", nid );\n }\n nid = \"[id=\'\" + nid + \"\'] \";\n\n i = groups.length;\n while ( i-- ) {\n groups[i] = nid + toSelector( groups[i] );\n }\n newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;\n newSelector = groups.join(\",\");\n }\n\n if ( newSelector ) {\n try {\n push.apply( results,\n newContext.querySelectorAll( newSelector )\n );\n return results;\n } catch(qsaError) {\n } finally {\n if ( !old ) {\n context.removeAttribute(\"id\");\n }\n }\n }\n }\n }\n\n // All others\n return select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n * deleting the oldest entry\n */\nfunction createCache() {\n var keys = [];\n\n function cache( key, value ) {\n // Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n if ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n // Only keep the most recent entries\n delete cache[ keys.shift() ];\n }\n return (cache[ key + \" \" ] = value);\n }\n return cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n fn[ expando ] = true;\n return fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n var div = document.createElement(\"div\");\n\n try {\n return !!fn( div );\n } catch (e) {\n return false;\n } finally {\n // Remove from its parent by default\n if ( div.parentNode ) {\n div.parentNode.removeChild( div );\n }\n // release memory in IE\n div = null;\n }\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n var arr = attrs.split(\"|\"),\n i = attrs.length;\n\n while ( i-- ) {\n Expr.attrHandle[ arr[i] ] = handler;\n }\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n var cur = b && a,\n diff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n ( ~b.sourceIndex || MAX_NEGATIVE ) -\n ( ~a.sourceIndex || MAX_NEGATIVE );\n\n // Use IE sourceIndex if available on both nodes\n if ( diff ) {\n return diff;\n }\n\n // Check if b follows a\n if ( cur ) {\n while ( (cur = cur.nextSibling) ) {\n if ( cur === b ) {\n return -1;\n }\n }\n }\n\n return a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n return function( elem ) {\n var name = elem.nodeName.toLowerCase();\n return name === \"input\" && elem.type === type;\n };\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n return function( elem ) {\n var name = elem.nodeName.toLowerCase();\n return (name === \"input\" || name === \"button\") && elem.type === type;\n };\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n return markFunction(function( argument ) {\n argument = +argument;\n return markFunction(function( seed, matches ) {\n var j,\n matchIndexes = fn( [], seed.length, argument ),\n i = matchIndexes.length;\n\n // Match elements found at the specified indexes\n while ( i-- ) {\n if ( seed[ (j = matchIndexes[i]) ] ) {\n seed[j] = !(matches[j] = seed[j]);\n }\n }\n });\n });\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n return context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n // documentElement is verified for cases where it doesn\'t yet exist\n // (such as loading iframes in IE - #4833)\n var documentElement = elem && (elem.ownerDocument || elem).documentElement;\n return documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n var hasCompare, parent,\n doc = node ? node.ownerDocument || node : preferredDoc;\n\n // If no document and documentElement is available, return\n if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n return document;\n }\n\n // Set our document\n document = doc;\n docElem = doc.documentElement;\n parent = doc.defaultView;\n\n // Support: IE>8\n // If iframe document is assigned to \"document\" variable and if iframe has been reloaded,\n // IE will throw \"permission denied\" error when accessing \"document\" variable, see jQuery #13936\n // IE6-8 do not support the defaultView property so parent will be undefined\n if ( parent && parent !== parent.top ) {\n // IE11 does not have attachEvent, so all must suffer\n if ( parent.addEventListener ) {\n parent.addEventListener( \"unload\", unloadHandler, false );\n } else if ( parent.attachEvent ) {\n parent.attachEvent( \"onunload\", unloadHandler );\n }\n }\n\n /* Support tests\n ---------------------------------------------------------------------- */\n documentIsHTML = !isXML( doc );\n\n /* Attributes\n ---------------------------------------------------------------------- */\n\n // Support: IE<8\n // Verify that getAttribute really returns attributes and not properties\n // (excepting IE8 booleans)\n support.attributes = assert(function( div ) {\n div.className = \"i\";\n return !div.getAttribute(\"className\");\n });\n\n /* getElement(s)By*\n ---------------------------------------------------------------------- */\n\n // Check if getElementsByTagName(\"*\") returns only elements\n support.getElementsByTagName = assert(function( div ) {\n div.appendChild( doc.createComment(\"\") );\n return !div.getElementsByTagName(\"*\").length;\n });\n\n // Support: IE<9\n support.getElementsByClassName = rnative.test( doc.getElementsByClassName );\n\n // Support: IE<10\n // Check if getElementById returns elements by name\n // The broken getElementById methods don\'t pick up programatically-set names,\n // so use a roundabout getElementsByName test\n support.getById = assert(function( div ) {\n docElem.appendChild( div ).id = expando;\n return !doc.getElementsByName || !doc.getElementsByName( expando ).length;\n });\n\n // ID find and filter\n if ( support.getById ) {\n Expr.find[\"ID\"] = function( id, context ) {\n if ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n var m = context.getElementById( id );\n // Check parentNode to catch when Blackberry 4.6 returns\n // nodes that are no longer in the document #6963\n return m && m.parentNode ? [ m ] : [];\n }\n };\n Expr.filter[\"ID\"] = function( id ) {\n var attrId = id.replace( runescape, funescape );\n return function( elem ) {\n return elem.getAttribute(\"id\") === attrId;\n };\n };\n } else {\n // Support: IE6/7\n // getElementById is not reliable as a find shortcut\n delete Expr.find[\"ID\"];\n\n Expr.filter[\"ID\"] = function( id ) {\n var attrId = id.replace( runescape, funescape );\n return function( elem ) {\n var node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n return node && node.value === attrId;\n };\n };\n }\n\n // Tag\n Expr.find[\"TAG\"] = support.getElementsByTagName ?\n function( tag, context ) {\n if ( typeof context.getElementsByTagName !== \"undefined\" ) {\n return context.getElementsByTagName( tag );\n\n // DocumentFragment nodes don\'t have gEBTN\n } else if ( support.qsa ) {\n return context.querySelectorAll( tag );\n }\n } :\n\n function( tag, context ) {\n var elem,\n tmp = [],\n i = 0,\n // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n results = context.getElementsByTagName( tag );\n\n // Filter out possible comments\n if ( tag === \"*\" ) {\n while ( (elem = results[i++]) ) {\n if ( elem.nodeType === 1 ) {\n tmp.push( elem );\n }\n }\n\n return tmp;\n }\n return results;\n };\n\n // Class\n Expr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n if ( documentIsHTML ) {\n return context.getElementsByClassName( className );\n }\n };\n\n /* QSA/matchesSelector\n ---------------------------------------------------------------------- */\n\n // QSA and matchesSelector support\n\n // matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n rbuggyMatches = [];\n\n // qSa(:focus) reports false when true (Chrome 21)\n // We allow this because of a bug in IE8/9 that throws an error\n // whenever `document.activeElement` is accessed on an iframe\n // So, we allow :focus to pass through QSA all the time to avoid the IE error\n // See http://bugs.jquery.com/ticket/13378\n rbuggyQSA = [];\n\n if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {\n // Build QSA regex\n // Regex strategy adopted from Diego Perini\n assert(function( div ) {\n // Select is set to empty string on purpose\n // This is to test IE\'s treatment of not explicitly\n // setting a boolean content attribute,\n // since its presence should be enough\n // http://bugs.jquery.com/ticket/12359\n docElem.appendChild( div ).innerHTML = \"<a id=\'\" + expando + \"\'></a>\" +\n \"<select id=\'\" + expando + \"-\\f]\' msallowcapture=\'\'>\" +\n \"<option selected=\'\'></option></select>\";\n\n // Support: IE8, Opera 11-12.16\n // Nothing should be selected when empty strings follow ^= or $= or *=\n // The test attribute must be unknown in Opera but \"safe\" for WinRT\n // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n if ( div.querySelectorAll(\"[msallowcapture^=\'\']\").length ) {\n rbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:\'\'|\\\"\\\")\" );\n }\n\n // Support: IE8\n // Boolean attributes and \"value\" are not treated correctly\n if ( !div.querySelectorAll(\"[selected]\").length ) {\n rbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n }\n\n // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+\n if ( !div.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n rbuggyQSA.push(\"~=\");\n }\n\n // Webkit/Opera - :checked should return selected option elements\n // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n // IE8 throws error here and will not see later tests\n if ( !div.querySelectorAll(\":checked\").length ) {\n rbuggyQSA.push(\":checked\");\n }\n\n // Support: Safari 8+, iOS 8+\n // https://bugs.webkit.org/show_bug.cgi?id=136851\n // In-page `selector#id sibing-combinator selector` fails\n if ( !div.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n rbuggyQSA.push(\".#.+[+~]\");\n }\n });\n\n assert(function( div ) {\n // Support: Windows 8 Native Apps\n // The type and name attributes are restricted during .innerHTML assignment\n var input = doc.createElement(\"input\");\n input.setAttribute( \"type\", \"hidden\" );\n div.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n // Support: IE8\n // Enforce case-sensitivity of name attribute\n if ( div.querySelectorAll(\"[name=d]\").length ) {\n rbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n }\n\n // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n // IE8 throws error here and will not see later tests\n if ( !div.querySelectorAll(\":enabled\").length ) {\n rbuggyQSA.push( \":enabled\", \":disabled\" );\n }\n\n // Opera 10-11 does not throw on post-comma invalid pseudos\n div.querySelectorAll(\"*,:x\");\n rbuggyQSA.push(\",.*:\");\n });\n }\n\n if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n docElem.webkitMatchesSelector ||\n docElem.mozMatchesSelector ||\n docElem.oMatchesSelector ||\n docElem.msMatchesSelector) )) ) {\n\n assert(function( div ) {\n // Check to see if it\'s possible to do matchesSelector\n // on a disconnected node (IE 9)\n support.disconnectedMatch = matches.call( div, \"div\" );\n\n // This should fail with an exception\n // Gecko does not error, returns false instead\n matches.call( div, \"[s!=\'\']:x\" );\n rbuggyMatches.push( \"!=\", pseudos );\n });\n }\n\n rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n /* Contains\n ---------------------------------------------------------------------- */\n hasCompare = rnative.test( docElem.compareDocumentPosition );\n\n // Element contains another\n // Purposefully does not implement inclusive descendent\n // As in, an element does not contain itself\n contains = hasCompare || rnative.test( docElem.contains ) ?\n function( a, b ) {\n var adown = a.nodeType === 9 ? a.documentElement : a,\n bup = b && b.parentNode;\n return a === bup || !!( bup && bup.nodeType === 1 && (\n adown.contains ?\n adown.contains( bup ) :\n a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n ));\n } :\n function( a, b ) {\n if ( b ) {\n while ( (b = b.parentNode) ) {\n if ( b === a ) {\n return true;\n }\n }\n }\n return false;\n };\n\n /* Sorting\n ---------------------------