58467 lines
1.6 MiB
58467 lines
1.6 MiB
/******/ (function(modules) { // webpackBootstrap
|
|
/******/ // The module cache
|
|
/******/ var installedModules = {};
|
|
/******/
|
|
/******/ // The require function
|
|
/******/ function __webpack_require__(moduleId) {
|
|
/******/
|
|
/******/ // Check if module is in cache
|
|
/******/ if(installedModules[moduleId]) {
|
|
/******/ return installedModules[moduleId].exports;
|
|
/******/ }
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = installedModules[moduleId] = {
|
|
/******/ i: moduleId,
|
|
/******/ l: false,
|
|
/******/ exports: {}
|
|
/******/ };
|
|
/******/
|
|
/******/ // Execute the module function
|
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
/******/
|
|
/******/ // Flag the module as loaded
|
|
/******/ module.l = true;
|
|
/******/
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
/******/
|
|
/******/
|
|
/******/ // expose the modules object (__webpack_modules__)
|
|
/******/ __webpack_require__.m = modules;
|
|
/******/
|
|
/******/ // expose the module cache
|
|
/******/ __webpack_require__.c = installedModules;
|
|
/******/
|
|
/******/ // define getter function for harmony exports
|
|
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
|
/******/ }
|
|
/******/ };
|
|
/******/
|
|
/******/ // define __esModule on exports
|
|
/******/ __webpack_require__.r = function(exports) {
|
|
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
/******/ }
|
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
/******/ };
|
|
/******/
|
|
/******/ // create a fake namespace object
|
|
/******/ // mode & 1: value is a module id, require it
|
|
/******/ // mode & 2: merge all properties of value into the ns
|
|
/******/ // mode & 4: return value when already ns object
|
|
/******/ // mode & 8|1: behave like require
|
|
/******/ __webpack_require__.t = function(value, mode) {
|
|
/******/ if(mode & 1) value = __webpack_require__(value);
|
|
/******/ if(mode & 8) return value;
|
|
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
|
/******/ var ns = Object.create(null);
|
|
/******/ __webpack_require__.r(ns);
|
|
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
|
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
|
/******/ return ns;
|
|
/******/ };
|
|
/******/
|
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
/******/ __webpack_require__.n = function(module) {
|
|
/******/ var getter = module && module.__esModule ?
|
|
/******/ function getDefault() { return module['default']; } :
|
|
/******/ function getModuleExports() { return module; };
|
|
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
/******/ return getter;
|
|
/******/ };
|
|
/******/
|
|
/******/ // Object.prototype.hasOwnProperty.call
|
|
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
/******/
|
|
/******/ // __webpack_public_path__
|
|
/******/ __webpack_require__.p = "";
|
|
/******/
|
|
/******/
|
|
/******/ // Load entry module and return exports
|
|
/******/ return __webpack_require__(__webpack_require__.s = 0);
|
|
/******/ })
|
|
/************************************************************************/
|
|
/******/ ([
|
|
/* 0 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* ---------------------------------------------------------------------
|
|
* GLPI - Gestionnaire Libre de Parc Informatique
|
|
* Copyright (C) 2015-2020 Teclib' and contributors.
|
|
*
|
|
* http://glpi-project.org
|
|
*
|
|
* based on GLPI - Gestionnaire Libre de Parc Informatique
|
|
* Copyright (C) 2003-2014 by the INDEPNET Development Team.
|
|
*
|
|
* ---------------------------------------------------------------------
|
|
*
|
|
* LICENSE
|
|
*
|
|
* This file is part of GLPI.
|
|
*
|
|
* GLPI is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* GLPI is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GLPI. If not, see <http://www.gnu.org/licenses/>.
|
|
* ---------------------------------------------------------------------
|
|
*/
|
|
|
|
// Font-Awesome
|
|
__webpack_require__(1);
|
|
|
|
// jQuery
|
|
// '$' and 'jQuery' objects have to be declared in global scope
|
|
window.$ = window.jQuery = __webpack_require__(2);
|
|
|
|
__webpack_require__(3);
|
|
window.$.migrateMute = true;
|
|
window.$.migrateTrace = false;
|
|
|
|
// jQuery UI
|
|
// Requirement order has been inspired by jquery-ui-dist build.
|
|
__webpack_require__(15);
|
|
__webpack_require__(16);
|
|
__webpack_require__(17);
|
|
__webpack_require__(18);
|
|
__webpack_require__(19);
|
|
__webpack_require__(20);
|
|
__webpack_require__(21);
|
|
__webpack_require__(22);
|
|
__webpack_require__(23);
|
|
__webpack_require__(24);
|
|
__webpack_require__(25);
|
|
__webpack_require__(26);
|
|
__webpack_require__(27);
|
|
__webpack_require__(28);
|
|
__webpack_require__(29);
|
|
__webpack_require__(30);
|
|
__webpack_require__(31);
|
|
__webpack_require__(32);
|
|
__webpack_require__(33);
|
|
__webpack_require__(36);
|
|
__webpack_require__(34);
|
|
__webpack_require__(37);
|
|
__webpack_require__(35);
|
|
__webpack_require__(38);
|
|
__webpack_require__(39);
|
|
__webpack_require__(40);
|
|
__webpack_require__(41);
|
|
__webpack_require__(42);
|
|
__webpack_require__(43);
|
|
__webpack_require__(44);
|
|
__webpack_require__(46);
|
|
__webpack_require__(47);
|
|
__webpack_require__(48);
|
|
__webpack_require__(49);
|
|
__webpack_require__(50);
|
|
__webpack_require__(51);
|
|
__webpack_require__(52);
|
|
__webpack_require__(53);
|
|
__webpack_require__(55);
|
|
__webpack_require__(56);
|
|
__webpack_require__(57);
|
|
__webpack_require__(58);
|
|
__webpack_require__(59);
|
|
__webpack_require__(60);
|
|
__webpack_require__(61);
|
|
__webpack_require__(62);
|
|
__webpack_require__(63);
|
|
__webpack_require__(64);
|
|
__webpack_require__(65);
|
|
__webpack_require__(66);
|
|
__webpack_require__(67);
|
|
__webpack_require__(68);
|
|
__webpack_require__(69);
|
|
|
|
// jQuery(UI) plugins
|
|
__webpack_require__(70);
|
|
__webpack_require__(71);
|
|
|
|
// qTip2
|
|
__webpack_require__(72);
|
|
__webpack_require__(73);
|
|
|
|
// Select2
|
|
// use full for compat; see https://select2.org/upgrading/migrating-from-35
|
|
__webpack_require__(74);
|
|
__webpack_require__(75);
|
|
|
|
//Loadash
|
|
//'_' object has to be declared in global scope
|
|
window._ = __webpack_require__(76);
|
|
|
|
// gettext.js
|
|
// add translation function into global scope
|
|
// signature is almost the same as for PHP functions, but accept extra arguments for string variables
|
|
window.i18n = __webpack_require__(78).default({domain: 'glpi'});
|
|
window.__ = function (msgid, domain /* , extra */) {
|
|
domain = typeof(domain) !== 'undefined' ? domain : 'glpi';
|
|
var text = i18n.dcnpgettext.apply(
|
|
i18n,
|
|
[domain, undefined, msgid, undefined, undefined].concat(Array.prototype.slice.call(arguments, 2))
|
|
);
|
|
return _.escape(text);
|
|
};
|
|
|
|
window._n = function (msgid, msgid_plural, n, domain /* , extra */) {
|
|
domain = typeof(domain) !== 'undefined' ? domain : 'glpi';
|
|
var text = i18n.dcnpgettext.apply(
|
|
i18n,
|
|
[domain, undefined, msgid, msgid_plural, n].concat(Array.prototype.slice.call(arguments, 4))
|
|
);
|
|
return _.escape(text);
|
|
};
|
|
window._x = function (msgctxt, msgid, domain /* , extra */) {
|
|
domain = typeof(domain) !== 'undefined' ? domain : 'glpi';
|
|
var text = i18n.dcnpgettext.apply(
|
|
i18n,
|
|
[domain, msgctxt, msgid, undefined, undefined].concat(Array.prototype.slice.call(arguments, 3))
|
|
);
|
|
return _.escape(text);
|
|
};
|
|
window._nx = function (msgctxt, msgid, msgid_plural, n, domain /* , extra */) {
|
|
domain = typeof(domain) !== 'undefined' ? domain : 'glpi';
|
|
var text = i18n.dcnpgettext.apply(
|
|
i18n,
|
|
[domain, msgctxt, msgid, msgid_plural, n].concat(Array.prototype.slice.call(arguments, 5))
|
|
);
|
|
return _.escape(text);
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 1 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// extracted by mini-css-extract-plugin
|
|
|
|
/***/ }),
|
|
/* 2 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery JavaScript Library v3.5.1
|
|
* https://jquery.com/
|
|
*
|
|
* Includes Sizzle.js
|
|
* https://sizzlejs.com/
|
|
*
|
|
* Copyright JS Foundation and other contributors
|
|
* Released under the MIT license
|
|
* https://jquery.org/license
|
|
*
|
|
* Date: 2020-05-04T22:49Z
|
|
*/
|
|
( function( global, factory ) {
|
|
|
|
"use strict";
|
|
|
|
if ( true && typeof module.exports === "object" ) {
|
|
|
|
// For CommonJS and CommonJS-like environments where a proper `window`
|
|
// is present, execute the factory and get jQuery.
|
|
// For environments that do not have a `window` with a `document`
|
|
// (such as Node.js), expose a factory as module.exports.
|
|
// This accentuates the need for the creation of a real `window`.
|
|
// e.g. var jQuery = require("jquery")(window);
|
|
// See ticket #14549 for more info.
|
|
module.exports = global.document ?
|
|
factory( global, true ) :
|
|
function( w ) {
|
|
if ( !w.document ) {
|
|
throw new Error( "jQuery requires a window with a document" );
|
|
}
|
|
return factory( w );
|
|
};
|
|
} else {
|
|
factory( global );
|
|
}
|
|
|
|
// Pass this if window is not defined yet
|
|
} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
|
|
|
|
// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
|
|
// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
|
|
// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
|
|
// enough that all such attempts are guarded in a try block.
|
|
"use strict";
|
|
|
|
var arr = [];
|
|
|
|
var getProto = Object.getPrototypeOf;
|
|
|
|
var slice = arr.slice;
|
|
|
|
var flat = arr.flat ? function( array ) {
|
|
return arr.flat.call( array );
|
|
} : function( array ) {
|
|
return arr.concat.apply( [], array );
|
|
};
|
|
|
|
|
|
var push = arr.push;
|
|
|
|
var indexOf = arr.indexOf;
|
|
|
|
var class2type = {};
|
|
|
|
var toString = class2type.toString;
|
|
|
|
var hasOwn = class2type.hasOwnProperty;
|
|
|
|
var fnToString = hasOwn.toString;
|
|
|
|
var ObjectFunctionString = fnToString.call( Object );
|
|
|
|
var support = {};
|
|
|
|
var isFunction = function isFunction( obj ) {
|
|
|
|
// Support: Chrome <=57, Firefox <=52
|
|
// In some browsers, typeof returns "function" for HTML <object> elements
|
|
// (i.e., `typeof document.createElement( "object" ) === "function"`).
|
|
// We don't want to classify *any* DOM node as a function.
|
|
return typeof obj === "function" && typeof obj.nodeType !== "number";
|
|
};
|
|
|
|
|
|
var isWindow = function isWindow( obj ) {
|
|
return obj != null && obj === obj.window;
|
|
};
|
|
|
|
|
|
var document = window.document;
|
|
|
|
|
|
|
|
var preservedScriptAttributes = {
|
|
type: true,
|
|
src: true,
|
|
nonce: true,
|
|
noModule: true
|
|
};
|
|
|
|
function DOMEval( code, node, doc ) {
|
|
doc = doc || document;
|
|
|
|
var i, val,
|
|
script = doc.createElement( "script" );
|
|
|
|
script.text = code;
|
|
if ( node ) {
|
|
for ( i in preservedScriptAttributes ) {
|
|
|
|
// Support: Firefox 64+, Edge 18+
|
|
// Some browsers don't support the "nonce" property on scripts.
|
|
// On the other hand, just using `getAttribute` is not enough as
|
|
// the `nonce` attribute is reset to an empty string whenever it
|
|
// becomes browsing-context connected.
|
|
// See https://github.com/whatwg/html/issues/2369
|
|
// See https://html.spec.whatwg.org/#nonce-attributes
|
|
// The `node.getAttribute` check was added for the sake of
|
|
// `jQuery.globalEval` so that it can fake a nonce-containing node
|
|
// via an object.
|
|
val = node[ i ] || node.getAttribute && node.getAttribute( i );
|
|
if ( val ) {
|
|
script.setAttribute( i, val );
|
|
}
|
|
}
|
|
}
|
|
doc.head.appendChild( script ).parentNode.removeChild( script );
|
|
}
|
|
|
|
|
|
function toType( obj ) {
|
|
if ( obj == null ) {
|
|
return obj + "";
|
|
}
|
|
|
|
// Support: Android <=2.3 only (functionish RegExp)
|
|
return typeof obj === "object" || typeof obj === "function" ?
|
|
class2type[ toString.call( obj ) ] || "object" :
|
|
typeof obj;
|
|
}
|
|
/* global Symbol */
|
|
// Defining this global in .eslintrc.json would create a danger of using the global
|
|
// unguarded in another place, it seems safer to define global only for this module
|
|
|
|
|
|
|
|
var
|
|
version = "3.5.1",
|
|
|
|
// Define a local copy of jQuery
|
|
jQuery = function( selector, context ) {
|
|
|
|
// The jQuery object is actually just the init constructor 'enhanced'
|
|
// Need init if jQuery is called (just allow error to be thrown if not included)
|
|
return new jQuery.fn.init( selector, context );
|
|
};
|
|
|
|
jQuery.fn = jQuery.prototype = {
|
|
|
|
// The current version of jQuery being used
|
|
jquery: version,
|
|
|
|
constructor: jQuery,
|
|
|
|
// The default length of a jQuery object is 0
|
|
length: 0,
|
|
|
|
toArray: function() {
|
|
return slice.call( this );
|
|
},
|
|
|
|
// Get the Nth element in the matched element set OR
|
|
// Get the whole matched element set as a clean array
|
|
get: function( num ) {
|
|
|
|
// Return all the elements in a clean array
|
|
if ( num == null ) {
|
|
return slice.call( this );
|
|
}
|
|
|
|
// Return just the one element from the set
|
|
return num < 0 ? this[ num + this.length ] : this[ num ];
|
|
},
|
|
|
|
// Take an array of elements and push it onto the stack
|
|
// (returning the new matched element set)
|
|
pushStack: function( elems ) {
|
|
|
|
// Build a new jQuery matched element set
|
|
var ret = jQuery.merge( this.constructor(), elems );
|
|
|
|
// Add the old object onto the stack (as a reference)
|
|
ret.prevObject = this;
|
|
|
|
// Return the newly-formed element set
|
|
return ret;
|
|
},
|
|
|
|
// Execute a callback for every element in the matched set.
|
|
each: function( callback ) {
|
|
return jQuery.each( this, callback );
|
|
},
|
|
|
|
map: function( callback ) {
|
|
return this.pushStack( jQuery.map( this, function( elem, i ) {
|
|
return callback.call( elem, i, elem );
|
|
} ) );
|
|
},
|
|
|
|
slice: function() {
|
|
return this.pushStack( slice.apply( this, arguments ) );
|
|
},
|
|
|
|
first: function() {
|
|
return this.eq( 0 );
|
|
},
|
|
|
|
last: function() {
|
|
return this.eq( -1 );
|
|
},
|
|
|
|
even: function() {
|
|
return this.pushStack( jQuery.grep( this, function( _elem, i ) {
|
|
return ( i + 1 ) % 2;
|
|
} ) );
|
|
},
|
|
|
|
odd: function() {
|
|
return this.pushStack( jQuery.grep( this, function( _elem, i ) {
|
|
return i % 2;
|
|
} ) );
|
|
},
|
|
|
|
eq: function( i ) {
|
|
var len = this.length,
|
|
j = +i + ( i < 0 ? len : 0 );
|
|
return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
|
|
},
|
|
|
|
end: function() {
|
|
return this.prevObject || this.constructor();
|
|
},
|
|
|
|
// For internal use only.
|
|
// Behaves like an Array's method, not like a jQuery method.
|
|
push: push,
|
|
sort: arr.sort,
|
|
splice: arr.splice
|
|
};
|
|
|
|
jQuery.extend = jQuery.fn.extend = function() {
|
|
var options, name, src, copy, copyIsArray, clone,
|
|
target = arguments[ 0 ] || {},
|
|
i = 1,
|
|
length = arguments.length,
|
|
deep = false;
|
|
|
|
// Handle a deep copy situation
|
|
if ( typeof target === "boolean" ) {
|
|
deep = target;
|
|
|
|
// Skip the boolean and the target
|
|
target = arguments[ i ] || {};
|
|
i++;
|
|
}
|
|
|
|
// Handle case when target is a string or something (possible in deep copy)
|
|
if ( typeof target !== "object" && !isFunction( target ) ) {
|
|
target = {};
|
|
}
|
|
|
|
// Extend jQuery itself if only one argument is passed
|
|
if ( i === length ) {
|
|
target = this;
|
|
i--;
|
|
}
|
|
|
|
for ( ; i < length; i++ ) {
|
|
|
|
// Only deal with non-null/undefined values
|
|
if ( ( options = arguments[ i ] ) != null ) {
|
|
|
|
// Extend the base object
|
|
for ( name in options ) {
|
|
copy = options[ name ];
|
|
|
|
// Prevent Object.prototype pollution
|
|
// Prevent never-ending loop
|
|
if ( name === "__proto__" || target === copy ) {
|
|
continue;
|
|
}
|
|
|
|
// Recurse if we're merging plain objects or arrays
|
|
if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
|
|
( copyIsArray = Array.isArray( copy ) ) ) ) {
|
|
src = target[ name ];
|
|
|
|
// Ensure proper type for the source value
|
|
if ( copyIsArray && !Array.isArray( src ) ) {
|
|
clone = [];
|
|
} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
|
|
clone = {};
|
|
} else {
|
|
clone = src;
|
|
}
|
|
copyIsArray = false;
|
|
|
|
// Never move original objects, clone them
|
|
target[ name ] = jQuery.extend( deep, clone, copy );
|
|
|
|
// Don't bring in undefined values
|
|
} else if ( copy !== undefined ) {
|
|
target[ name ] = copy;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return the modified object
|
|
return target;
|
|
};
|
|
|
|
jQuery.extend( {
|
|
|
|
// Unique for each copy of jQuery on the page
|
|
expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
|
|
|
|
// Assume jQuery is ready without the ready module
|
|
isReady: true,
|
|
|
|
error: function( msg ) {
|
|
throw new Error( msg );
|
|
},
|
|
|
|
noop: function() {},
|
|
|
|
isPlainObject: function( obj ) {
|
|
var proto, Ctor;
|
|
|
|
// Detect obvious negatives
|
|
// Use toString instead of jQuery.type to catch host objects
|
|
if ( !obj || toString.call( obj ) !== "[object Object]" ) {
|
|
return false;
|
|
}
|
|
|
|
proto = getProto( obj );
|
|
|
|
// Objects with no prototype (e.g., `Object.create( null )`) are plain
|
|
if ( !proto ) {
|
|
return true;
|
|
}
|
|
|
|
// Objects with prototype are plain iff they were constructed by a global Object function
|
|
Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
|
|
return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
|
|
},
|
|
|
|
isEmptyObject: function( obj ) {
|
|
var name;
|
|
|
|
for ( name in obj ) {
|
|
return false;
|
|
}
|
|
return true;
|
|
},
|
|
|
|
// Evaluates a script in a provided context; falls back to the global one
|
|
// if not specified.
|
|
globalEval: function( code, options, doc ) {
|
|
DOMEval( code, { nonce: options && options.nonce }, doc );
|
|
},
|
|
|
|
each: function( obj, callback ) {
|
|
var length, i = 0;
|
|
|
|
if ( isArrayLike( obj ) ) {
|
|
length = obj.length;
|
|
for ( ; i < length; i++ ) {
|
|
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
for ( i in obj ) {
|
|
if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
},
|
|
|
|
// results is for internal usage only
|
|
makeArray: function( arr, results ) {
|
|
var ret = results || [];
|
|
|
|
if ( arr != null ) {
|
|
if ( isArrayLike( Object( arr ) ) ) {
|
|
jQuery.merge( ret,
|
|
typeof arr === "string" ?
|
|
[ arr ] : arr
|
|
);
|
|
} else {
|
|
push.call( ret, arr );
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
},
|
|
|
|
inArray: function( elem, arr, i ) {
|
|
return arr == null ? -1 : indexOf.call( arr, elem, i );
|
|
},
|
|
|
|
// Support: Android <=4.0 only, PhantomJS 1 only
|
|
// push.apply(_, arraylike) throws on ancient WebKit
|
|
merge: function( first, second ) {
|
|
var len = +second.length,
|
|
j = 0,
|
|
i = first.length;
|
|
|
|
for ( ; j < len; j++ ) {
|
|
first[ i++ ] = second[ j ];
|
|
}
|
|
|
|
first.length = i;
|
|
|
|
return first;
|
|
},
|
|
|
|
grep: function( elems, callback, invert ) {
|
|
var callbackInverse,
|
|
matches = [],
|
|
i = 0,
|
|
length = elems.length,
|
|
callbackExpect = !invert;
|
|
|
|
// Go through the array, only saving the items
|
|
// that pass the validator function
|
|
for ( ; i < length; i++ ) {
|
|
callbackInverse = !callback( elems[ i ], i );
|
|
if ( callbackInverse !== callbackExpect ) {
|
|
matches.push( elems[ i ] );
|
|
}
|
|
}
|
|
|
|
return matches;
|
|
},
|
|
|
|
// arg is for internal usage only
|
|
map: function( elems, callback, arg ) {
|
|
var length, value,
|
|
i = 0,
|
|
ret = [];
|
|
|
|
// Go through the array, translating each of the items to their new values
|
|
if ( isArrayLike( elems ) ) {
|
|
length = elems.length;
|
|
for ( ; i < length; i++ ) {
|
|
value = callback( elems[ i ], i, arg );
|
|
|
|
if ( value != null ) {
|
|
ret.push( value );
|
|
}
|
|
}
|
|
|
|
// Go through every key on the object,
|
|
} else {
|
|
for ( i in elems ) {
|
|
value = callback( elems[ i ], i, arg );
|
|
|
|
if ( value != null ) {
|
|
ret.push( value );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Flatten any nested arrays
|
|
return flat( ret );
|
|
},
|
|
|
|
// A global GUID counter for objects
|
|
guid: 1,
|
|
|
|
// jQuery.support is not used in Core but other projects attach their
|
|
// properties to it so it needs to exist.
|
|
support: support
|
|
} );
|
|
|
|
if ( typeof Symbol === "function" ) {
|
|
jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
|
|
}
|
|
|
|
// Populate the class2type map
|
|
jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
|
|
function( _i, name ) {
|
|
class2type[ "[object " + name + "]" ] = name.toLowerCase();
|
|
} );
|
|
|
|
function isArrayLike( obj ) {
|
|
|
|
// Support: real iOS 8.2 only (not reproducible in simulator)
|
|
// `in` check used to prevent JIT error (gh-2145)
|
|
// hasOwn isn't used here due to false negatives
|
|
// regarding Nodelist length in IE
|
|
var length = !!obj && "length" in obj && obj.length,
|
|
type = toType( obj );
|
|
|
|
if ( isFunction( obj ) || isWindow( obj ) ) {
|
|
return false;
|
|
}
|
|
|
|
return type === "array" || length === 0 ||
|
|
typeof length === "number" && length > 0 && ( length - 1 ) in obj;
|
|
}
|
|
var Sizzle =
|
|
/*!
|
|
* Sizzle CSS Selector Engine v2.3.5
|
|
* https://sizzlejs.com/
|
|
*
|
|
* Copyright JS Foundation and other contributors
|
|
* Released under the MIT license
|
|
* https://js.foundation/
|
|
*
|
|
* Date: 2020-03-14
|
|
*/
|
|
( function( window ) {
|
|
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" + 1 * new Date(),
|
|
preferredDoc = window.document,
|
|
dirruns = 0,
|
|
done = 0,
|
|
classCache = createCache(),
|
|
tokenCache = createCache(),
|
|
compilerCache = createCache(),
|
|
nonnativeSelectorCache = createCache(),
|
|
sortOrder = function( a, b ) {
|
|
if ( a === b ) {
|
|
hasDuplicate = true;
|
|
}
|
|
return 0;
|
|
},
|
|
|
|
// Instance methods
|
|
hasOwn = ( {} ).hasOwnProperty,
|
|
arr = [],
|
|
pop = arr.pop,
|
|
pushNative = arr.push,
|
|
push = arr.push,
|
|
slice = arr.slice,
|
|
|
|
// Use a stripped-down indexOf as it's faster than native
|
|
// https://jsperf.com/thor-indexof-vs-for/5
|
|
indexOf = function( list, elem ) {
|
|
var i = 0,
|
|
len = list.length;
|
|
for ( ; i < len; i++ ) {
|
|
if ( list[ 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]",
|
|
|
|
// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram
|
|
identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace +
|
|
"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",
|
|
|
|
// 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
|
|
rwhitespace = new RegExp( whitespace + "+", "g" ),
|
|
rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" +
|
|
whitespace + "+$", "g" ),
|
|
|
|
rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
|
|
rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace +
|
|
"*" ),
|
|
rdescend = new RegExp( whitespace + "|>" ),
|
|
|
|
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" )
|
|
},
|
|
|
|
rhtml = /HTML$/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 = /[+~]/,
|
|
|
|
// CSS escapes
|
|
// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
|
|
runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ),
|
|
funescape = function( escape, nonHex ) {
|
|
var high = "0x" + escape.slice( 1 ) - 0x10000;
|
|
|
|
return nonHex ?
|
|
|
|
// Strip the backslash prefix from a non-hex escape sequence
|
|
nonHex :
|
|
|
|
// Replace a hexadecimal escape sequence with the encoded Unicode code point
|
|
// Support: IE <=11+
|
|
// For values outside the Basic Multilingual Plane (BMP), manually construct a
|
|
// surrogate pair
|
|
high < 0 ?
|
|
String.fromCharCode( high + 0x10000 ) :
|
|
String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
|
|
},
|
|
|
|
// CSS string/identifier serialization
|
|
// https://drafts.csswg.org/cssom/#common-serializing-idioms
|
|
rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
|
|
fcssescape = function( ch, asCodePoint ) {
|
|
if ( asCodePoint ) {
|
|
|
|
// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
|
|
if ( ch === "\0" ) {
|
|
return "\uFFFD";
|
|
}
|
|
|
|
// Control characters and (dependent upon position) numbers get escaped as code points
|
|
return ch.slice( 0, -1 ) + "\\" +
|
|
ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
|
|
}
|
|
|
|
// Other potentially-special ASCII characters get backslash-escaped
|
|
return "\\" + ch;
|
|
},
|
|
|
|
// Used for iframes
|
|
// See setDocument()
|
|
// Removing the function wrapper causes a "Permission Denied"
|
|
// error in IE
|
|
unloadHandler = function() {
|
|
setDocument();
|
|
},
|
|
|
|
inDisabledFieldset = addCombinator(
|
|
function( elem ) {
|
|
return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset";
|
|
},
|
|
{ dir: "parentNode", next: "legend" }
|
|
);
|
|
|
|
// Optimize for push.apply( _, NodeList )
|
|
try {
|
|
push.apply(
|
|
( arr = slice.call( preferredDoc.childNodes ) ),
|
|
preferredDoc.childNodes
|
|
);
|
|
|
|
// Support: Android<4.0
|
|
// Detect silently failing push.apply
|
|
// eslint-disable-next-line no-unused-expressions
|
|
arr[ preferredDoc.childNodes.length ].nodeType;
|
|
} catch ( e ) {
|
|
push = { apply: arr.length ?
|
|
|
|
// Leverage slice if possible
|
|
function( target, els ) {
|
|
pushNative.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 m, i, elem, nid, match, groups, newSelector,
|
|
newContext = context && context.ownerDocument,
|
|
|
|
// nodeType defaults to 9, since context defaults to document
|
|
nodeType = context ? context.nodeType : 9;
|
|
|
|
results = results || [];
|
|
|
|
// Return early from calls with invalid selector or context
|
|
if ( typeof selector !== "string" || !selector ||
|
|
nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
|
|
|
|
return results;
|
|
}
|
|
|
|
// Try to shortcut find operations (as opposed to filters) in HTML documents
|
|
if ( !seed ) {
|
|
setDocument( context );
|
|
context = context || document;
|
|
|
|
if ( documentIsHTML ) {
|
|
|
|
// If the selector is sufficiently simple, try using a "get*By*" DOM method
|
|
// (excepting DocumentFragment context, where the methods don't exist)
|
|
if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) {
|
|
|
|
// ID selector
|
|
if ( ( m = match[ 1 ] ) ) {
|
|
|
|
// Document context
|
|
if ( nodeType === 9 ) {
|
|
if ( ( elem = context.getElementById( m ) ) ) {
|
|
|
|
// Support: IE, Opera, Webkit
|
|
// TODO: identify versions
|
|
// getElementById can match elements by name instead of ID
|
|
if ( elem.id === m ) {
|
|
results.push( elem );
|
|
return results;
|
|
}
|
|
} else {
|
|
return results;
|
|
}
|
|
|
|
// Element context
|
|
} else {
|
|
|
|
// Support: IE, Opera, Webkit
|
|
// TODO: identify versions
|
|
// getElementById can match elements by name instead of ID
|
|
if ( newContext && ( elem = newContext.getElementById( m ) ) &&
|
|
contains( context, elem ) &&
|
|
elem.id === m ) {
|
|
|
|
results.push( elem );
|
|
return results;
|
|
}
|
|
}
|
|
|
|
// Type selector
|
|
} else if ( match[ 2 ] ) {
|
|
push.apply( results, context.getElementsByTagName( selector ) );
|
|
return results;
|
|
|
|
// Class selector
|
|
} else if ( ( m = match[ 3 ] ) && support.getElementsByClassName &&
|
|
context.getElementsByClassName ) {
|
|
|
|
push.apply( results, context.getElementsByClassName( m ) );
|
|
return results;
|
|
}
|
|
}
|
|
|
|
// Take advantage of querySelectorAll
|
|
if ( support.qsa &&
|
|
!nonnativeSelectorCache[ selector + " " ] &&
|
|
( !rbuggyQSA || !rbuggyQSA.test( selector ) ) &&
|
|
|
|
// Support: IE 8 only
|
|
// Exclude object elements
|
|
( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) {
|
|
|
|
newSelector = selector;
|
|
newContext = context;
|
|
|
|
// qSA considers elements outside a scoping root when evaluating child or
|
|
// descendant combinators, which is not what we want.
|
|
// In such cases, we work around the behavior by prefixing every selector in the
|
|
// list with an ID selector referencing the scope context.
|
|
// The technique has to be used as well when a leading combinator is used
|
|
// as such selectors are not recognized by querySelectorAll.
|
|
// Thanks to Andrew Dupont for this technique.
|
|
if ( nodeType === 1 &&
|
|
( rdescend.test( selector ) || rcombinators.test( selector ) ) ) {
|
|
|
|
// Expand context for sibling selectors
|
|
newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
|
|
context;
|
|
|
|
// We can use :scope instead of the ID hack if the browser
|
|
// supports it & if we're not changing the context.
|
|
if ( newContext !== context || !support.scope ) {
|
|
|
|
// Capture the context ID, setting it first if necessary
|
|
if ( ( nid = context.getAttribute( "id" ) ) ) {
|
|
nid = nid.replace( rcssescape, fcssescape );
|
|
} else {
|
|
context.setAttribute( "id", ( nid = expando ) );
|
|
}
|
|
}
|
|
|
|
// Prefix every selector in the list
|
|
groups = tokenize( selector );
|
|
i = groups.length;
|
|
while ( i-- ) {
|
|
groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " +
|
|
toSelector( groups[ i ] );
|
|
}
|
|
newSelector = groups.join( "," );
|
|
}
|
|
|
|
try {
|
|
push.apply( results,
|
|
newContext.querySelectorAll( newSelector )
|
|
);
|
|
return results;
|
|
} catch ( qsaError ) {
|
|
nonnativeSelectorCache( selector, true );
|
|
} finally {
|
|
if ( nid === expando ) {
|
|
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 element and returns a boolean result
|
|
*/
|
|
function assert( fn ) {
|
|
var el = document.createElement( "fieldset" );
|
|
|
|
try {
|
|
return !!fn( el );
|
|
} catch ( e ) {
|
|
return false;
|
|
} finally {
|
|
|
|
// Remove from its parent by default
|
|
if ( el.parentNode ) {
|
|
el.parentNode.removeChild( el );
|
|
}
|
|
|
|
// release memory in IE
|
|
el = 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 = arr.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 &&
|
|
a.sourceIndex - b.sourceIndex;
|
|
|
|
// 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 :enabled/:disabled
|
|
* @param {Boolean} disabled true for :disabled; false for :enabled
|
|
*/
|
|
function createDisabledPseudo( disabled ) {
|
|
|
|
// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
|
|
return function( elem ) {
|
|
|
|
// Only certain elements can match :enabled or :disabled
|
|
// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
|
|
// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
|
|
if ( "form" in elem ) {
|
|
|
|
// Check for inherited disabledness on relevant non-disabled elements:
|
|
// * listed form-associated elements in a disabled fieldset
|
|
// https://html.spec.whatwg.org/multipage/forms.html#category-listed
|
|
// https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
|
|
// * option elements in a disabled optgroup
|
|
// https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
|
|
// All such elements have a "form" property.
|
|
if ( elem.parentNode && elem.disabled === false ) {
|
|
|
|
// Option elements defer to a parent optgroup if present
|
|
if ( "label" in elem ) {
|
|
if ( "label" in elem.parentNode ) {
|
|
return elem.parentNode.disabled === disabled;
|
|
} else {
|
|
return elem.disabled === disabled;
|
|
}
|
|
}
|
|
|
|
// Support: IE 6 - 11
|
|
// Use the isDisabled shortcut property to check for disabled fieldset ancestors
|
|
return elem.isDisabled === disabled ||
|
|
|
|
// Where there is no isDisabled, check manually
|
|
/* jshint -W018 */
|
|
elem.isDisabled !== !disabled &&
|
|
inDisabledFieldset( elem ) === disabled;
|
|
}
|
|
|
|
return elem.disabled === disabled;
|
|
|
|
// Try to winnow out elements that can't be disabled before trusting the disabled property.
|
|
// Some victims get caught in our net (label, legend, menu, track), but it shouldn't
|
|
// even exist on them, let alone have a boolean value.
|
|
} else if ( "label" in elem ) {
|
|
return elem.disabled === disabled;
|
|
}
|
|
|
|
// Remaining elements are neither :enabled nor :disabled
|
|
return false;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 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 !== "undefined" && 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 ) {
|
|
var namespace = elem.namespaceURI,
|
|
docElem = ( elem.ownerDocument || elem ).documentElement;
|
|
|
|
// Support: IE <=8
|
|
// Assume HTML when documentElement doesn't yet exist, such as inside loading iframes
|
|
// https://bugs.jquery.com/ticket/4833
|
|
return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" );
|
|
};
|
|
|
|
/**
|
|
* 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, subWindow,
|
|
doc = node ? node.ownerDocument || node : preferredDoc;
|
|
|
|
// Return early if doc is invalid or already selected
|
|
// Support: IE 11+, Edge 17 - 18+
|
|
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
|
|
// two documents; shallow comparisons work.
|
|
// eslint-disable-next-line eqeqeq
|
|
if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) {
|
|
return document;
|
|
}
|
|
|
|
// Update global variables
|
|
document = doc;
|
|
docElem = document.documentElement;
|
|
documentIsHTML = !isXML( document );
|
|
|
|
// Support: IE 9 - 11+, Edge 12 - 18+
|
|
// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
|
|
// Support: IE 11+, Edge 17 - 18+
|
|
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
|
|
// two documents; shallow comparisons work.
|
|
// eslint-disable-next-line eqeqeq
|
|
if ( preferredDoc != document &&
|
|
( subWindow = document.defaultView ) && subWindow.top !== subWindow ) {
|
|
|
|
// Support: IE 11, Edge
|
|
if ( subWindow.addEventListener ) {
|
|
subWindow.addEventListener( "unload", unloadHandler, false );
|
|
|
|
// Support: IE 9 - 10 only
|
|
} else if ( subWindow.attachEvent ) {
|
|
subWindow.attachEvent( "onunload", unloadHandler );
|
|
}
|
|
}
|
|
|
|
// Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only,
|
|
// Safari 4 - 5 only, Opera <=11.6 - 12.x only
|
|
// IE/Edge & older browsers don't support the :scope pseudo-class.
|
|
// Support: Safari 6.0 only
|
|
// Safari 6.0 supports :scope but it's an alias of :root there.
|
|
support.scope = assert( function( el ) {
|
|
docElem.appendChild( el ).appendChild( document.createElement( "div" ) );
|
|
return typeof el.querySelectorAll !== "undefined" &&
|
|
!el.querySelectorAll( ":scope fieldset div" ).length;
|
|
} );
|
|
|
|
/* Attributes
|
|
---------------------------------------------------------------------- */
|
|
|
|
// Support: IE<8
|
|
// Verify that getAttribute really returns attributes and not properties
|
|
// (excepting IE8 booleans)
|
|
support.attributes = assert( function( el ) {
|
|
el.className = "i";
|
|
return !el.getAttribute( "className" );
|
|
} );
|
|
|
|
/* getElement(s)By*
|
|
---------------------------------------------------------------------- */
|
|
|
|
// Check if getElementsByTagName("*") returns only elements
|
|
support.getElementsByTagName = assert( function( el ) {
|
|
el.appendChild( document.createComment( "" ) );
|
|
return !el.getElementsByTagName( "*" ).length;
|
|
} );
|
|
|
|
// Support: IE<9
|
|
support.getElementsByClassName = rnative.test( document.getElementsByClassName );
|
|
|
|
// Support: IE<10
|
|
// Check if getElementById returns elements by name
|
|
// The broken getElementById methods don't pick up programmatically-set names,
|
|
// so use a roundabout getElementsByName test
|
|
support.getById = assert( function( el ) {
|
|
docElem.appendChild( el ).id = expando;
|
|
return !document.getElementsByName || !document.getElementsByName( expando ).length;
|
|
} );
|
|
|
|
// ID filter and find
|
|
if ( support.getById ) {
|
|
Expr.filter[ "ID" ] = function( id ) {
|
|
var attrId = id.replace( runescape, funescape );
|
|
return function( elem ) {
|
|
return elem.getAttribute( "id" ) === attrId;
|
|
};
|
|
};
|
|
Expr.find[ "ID" ] = function( id, context ) {
|
|
if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
|
|
var elem = context.getElementById( id );
|
|
return elem ? [ elem ] : [];
|
|
}
|
|
};
|
|
} else {
|
|
Expr.filter[ "ID" ] = function( id ) {
|
|
var attrId = id.replace( runescape, funescape );
|
|
return function( elem ) {
|
|
var node = typeof elem.getAttributeNode !== "undefined" &&
|
|
elem.getAttributeNode( "id" );
|
|
return node && node.value === attrId;
|
|
};
|
|
};
|
|
|
|
// Support: IE 6 - 7 only
|
|
// getElementById is not reliable as a find shortcut
|
|
Expr.find[ "ID" ] = function( id, context ) {
|
|
if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
|
|
var node, i, elems,
|
|
elem = context.getElementById( id );
|
|
|
|
if ( elem ) {
|
|
|
|
// Verify the id attribute
|
|
node = elem.getAttributeNode( "id" );
|
|
if ( node && node.value === id ) {
|
|
return [ elem ];
|
|
}
|
|
|
|
// Fall back on getElementsByName
|
|
elems = context.getElementsByName( id );
|
|
i = 0;
|
|
while ( ( elem = elems[ i++ ] ) ) {
|
|
node = elem.getAttributeNode( "id" );
|
|
if ( node && node.value === id ) {
|
|
return [ elem ];
|
|
}
|
|
}
|
|
}
|
|
|
|
return [];
|
|
}
|
|
};
|
|
}
|
|
|
|
// Tag
|
|
Expr.find[ "TAG" ] = support.getElementsByTagName ?
|
|
function( tag, context ) {
|
|
if ( typeof context.getElementsByTagName !== "undefined" ) {
|
|
return context.getElementsByTagName( tag );
|
|
|
|
// DocumentFragment nodes don't have gEBTN
|
|
} else if ( support.qsa ) {
|
|
return context.querySelectorAll( tag );
|
|
}
|
|
} :
|
|
|
|
function( tag, context ) {
|
|
var elem,
|
|
tmp = [],
|
|
i = 0,
|
|
|
|
// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
|
|
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 ( typeof context.getElementsByClassName !== "undefined" && 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 https://bugs.jquery.com/ticket/13378
|
|
rbuggyQSA = [];
|
|
|
|
if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) {
|
|
|
|
// Build QSA regex
|
|
// Regex strategy adopted from Diego Perini
|
|
assert( function( el ) {
|
|
|
|
var input;
|
|
|
|
// 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
|
|
// https://bugs.jquery.com/ticket/12359
|
|
docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
|
|
"<select id='" + expando + "-\r\\' 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
|
|
// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
|
|
if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) {
|
|
rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
|
|
}
|
|
|
|
// Support: IE8
|
|
// Boolean attributes and "value" are not treated correctly
|
|
if ( !el.querySelectorAll( "[selected]" ).length ) {
|
|
rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
|
|
}
|
|
|
|
// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
|
|
if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
|
|
rbuggyQSA.push( "~=" );
|
|
}
|
|
|
|
// Support: IE 11+, Edge 15 - 18+
|
|
// IE 11/Edge don't find elements on a `[name='']` query in some cases.
|
|
// Adding a temporary attribute to the document before the selection works
|
|
// around the issue.
|
|
// Interestingly, IE 10 & older don't seem to have the issue.
|
|
input = document.createElement( "input" );
|
|
input.setAttribute( "name", "" );
|
|
el.appendChild( input );
|
|
if ( !el.querySelectorAll( "[name='']" ).length ) {
|
|
rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" +
|
|
whitespace + "*(?:''|\"\")" );
|
|
}
|
|
|
|
// 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 ( !el.querySelectorAll( ":checked" ).length ) {
|
|
rbuggyQSA.push( ":checked" );
|
|
}
|
|
|
|
// Support: Safari 8+, iOS 8+
|
|
// https://bugs.webkit.org/show_bug.cgi?id=136851
|
|
// In-page `selector#id sibling-combinator selector` fails
|
|
if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
|
|
rbuggyQSA.push( ".#.+[+~]" );
|
|
}
|
|
|
|
// Support: Firefox <=3.6 - 5 only
|
|
// Old Firefox doesn't throw on a badly-escaped identifier.
|
|
el.querySelectorAll( "\\\f" );
|
|
rbuggyQSA.push( "[\\r\\n\\f]" );
|
|
} );
|
|
|
|
assert( function( el ) {
|
|
el.innerHTML = "<a href='' disabled='disabled'></a>" +
|
|
"<select disabled='disabled'><option/></select>";
|
|
|
|
// Support: Windows 8 Native Apps
|
|
// The type and name attributes are restricted during .innerHTML assignment
|
|
var input = document.createElement( "input" );
|
|
input.setAttribute( "type", "hidden" );
|
|
el.appendChild( input ).setAttribute( "name", "D" );
|
|
|
|
// Support: IE8
|
|
// Enforce case-sensitivity of name attribute
|
|
if ( el.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 ( el.querySelectorAll( ":enabled" ).length !== 2 ) {
|
|
rbuggyQSA.push( ":enabled", ":disabled" );
|
|
}
|
|
|
|
// Support: IE9-11+
|
|
// IE's :disabled selector does not pick up the children of disabled fieldsets
|
|
docElem.appendChild( el ).disabled = true;
|
|
if ( el.querySelectorAll( ":disabled" ).length !== 2 ) {
|
|
rbuggyQSA.push( ":enabled", ":disabled" );
|
|
}
|
|
|
|
// Support: Opera 10 - 11 only
|
|
// Opera 10-11 does not throw on post-comma invalid pseudos
|
|
el.querySelectorAll( "*,:x" );
|
|
rbuggyQSA.push( ",.*:" );
|
|
} );
|
|
}
|
|
|
|
if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches ||
|
|
docElem.webkitMatchesSelector ||
|
|
docElem.mozMatchesSelector ||
|
|
docElem.oMatchesSelector ||
|
|
docElem.msMatchesSelector ) ) ) ) {
|
|
|
|
assert( function( el ) {
|
|
|
|
// Check to see if it's possible to do matchesSelector
|
|
// on a disconnected node (IE 9)
|
|
support.disconnectedMatch = matches.call( el, "*" );
|
|
|
|
// This should fail with an exception
|
|
// Gecko does not error, returns false instead
|
|
matches.call( el, "[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 self-exclusive
|
|
// 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
|
|
// Support: IE 11+, Edge 17 - 18+
|
|
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
|
|
// two documents; shallow comparisons work.
|
|
// eslint-disable-next-line eqeqeq
|
|
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
|
|
// Support: IE 11+, Edge 17 - 18+
|
|
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
|
|
// two documents; shallow comparisons work.
|
|
// eslint-disable-next-line eqeqeq
|
|
if ( a == document || a.ownerDocument == preferredDoc &&
|
|
contains( preferredDoc, a ) ) {
|
|
return -1;
|
|
}
|
|
|
|
// Support: IE 11+, Edge 17 - 18+
|
|
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
|
|
// two documents; shallow comparisons work.
|
|
// eslint-disable-next-line eqeqeq
|
|
if ( b == document || b.ownerDocument == preferredDoc &&
|
|
contains( preferredDoc, b ) ) {
|
|
return 1;
|
|
}
|
|
|
|
// Maintain original order
|
|
return sortInput ?
|
|
( indexOf( sortInput, a ) - indexOf( 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 ) {
|
|
|
|
// Support: IE 11+, Edge 17 - 18+
|
|
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
|
|
// two documents; shallow comparisons work.
|
|
/* eslint-disable eqeqeq */
|
|
return a == document ? -1 :
|
|
b == document ? 1 :
|
|
/* eslint-enable eqeqeq */
|
|
aup ? -1 :
|
|
bup ? 1 :
|
|
sortInput ?
|
|
( indexOf( sortInput, a ) - indexOf( 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
|
|
// Support: IE 11+, Edge 17 - 18+
|
|
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
|
|
// two documents; shallow comparisons work.
|
|
/* eslint-disable eqeqeq */
|
|
ap[ i ] == preferredDoc ? -1 :
|
|
bp[ i ] == preferredDoc ? 1 :
|
|
/* eslint-enable eqeqeq */
|
|
0;
|
|
};
|
|
|
|
return document;
|
|
};
|
|
|
|
Sizzle.matches = function( expr, elements ) {
|
|
return Sizzle( expr, null, null, elements );
|
|
};
|
|
|
|
Sizzle.matchesSelector = function( elem, expr ) {
|
|
setDocument( elem );
|
|
|
|
if ( support.matchesSelector && documentIsHTML &&
|
|
!nonnativeSelectorCache[ expr + " " ] &&
|
|
( !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 ) {
|
|
nonnativeSelectorCache( expr, true );
|
|
}
|
|
}
|
|
|
|
return Sizzle( expr, document, null, [ elem ] ).length > 0;
|
|
};
|
|
|
|
Sizzle.contains = function( context, elem ) {
|
|
|
|
// Set document vars if needed
|
|
// Support: IE 11+, Edge 17 - 18+
|
|
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
|
|
// two documents; shallow comparisons work.
|
|
// eslint-disable-next-line eqeqeq
|
|
if ( ( context.ownerDocument || context ) != document ) {
|
|
setDocument( context );
|
|
}
|
|
return contains( context, elem );
|
|
};
|
|
|
|
Sizzle.attr = function( elem, name ) {
|
|
|
|
// Set document vars if needed
|
|
// Support: IE 11+, Edge 17 - 18+
|
|
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
|
|
// two documents; shallow comparisons work.
|
|
// eslint-disable-next-line eqeqeq
|
|
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.escape = function( sel ) {
|
|
return ( sel + "" ).replace( rcssescape, fcssescape );
|
|
};
|
|
|
|
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 !== "undefined" &&
|
|
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 += "";
|
|
|
|
/* eslint-disable max-len */
|
|
|
|
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.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
|
|
operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
|
|
false;
|
|
/* eslint-enable max-len */
|
|
|
|
};
|
|
},
|
|
|
|
"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, uniqueCache, outerCache, node, nodeIndex, start,
|
|
dir = simple !== forward ? "nextSibling" : "previousSibling",
|
|
parent = elem.parentNode,
|
|
name = ofType && elem.nodeName.toLowerCase(),
|
|
useCache = !xml && !ofType,
|
|
diff = false;
|
|
|
|
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 ) {
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Reverse direction for :only-* (if we haven't yet done so)
|
|
start = dir = type === "only" && !start && "nextSibling";
|
|
}
|
|
return true;
|
|
}
|
|
|
|
start = [ forward ? parent.firstChild : parent.lastChild ];
|
|
|
|
// non-xml :nth-child(...) stores cache data on `parent`
|
|
if ( forward && useCache ) {
|
|
|
|
// Seek `elem` from a previously-cached index
|
|
|
|
// ...in a gzip-friendly way
|
|
node = parent;
|
|
outerCache = node[ expando ] || ( node[ expando ] = {} );
|
|
|
|
// Support: IE <9 only
|
|
// Defend against cloned attroperties (jQuery gh-1709)
|
|
uniqueCache = outerCache[ node.uniqueID ] ||
|
|
( outerCache[ node.uniqueID ] = {} );
|
|
|
|
cache = uniqueCache[ type ] || [];
|
|
nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
|
|
diff = nodeIndex && cache[ 2 ];
|
|
node = nodeIndex && parent.childNodes[ nodeIndex ];
|
|
|
|
while ( ( node = ++nodeIndex && node && node[ dir ] ||
|
|
|
|
// Fallback to seeking `elem` from the start
|
|
( diff = nodeIndex = 0 ) || start.pop() ) ) {
|
|
|
|
// When found, cache indexes on `parent` and break
|
|
if ( node.nodeType === 1 && ++diff && node === elem ) {
|
|
uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
|
|
break;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
// Use previously-cached element index if available
|
|
if ( useCache ) {
|
|
|
|
// ...in a gzip-friendly way
|
|
node = elem;
|
|
outerCache = node[ expando ] || ( node[ expando ] = {} );
|
|
|
|
// Support: IE <9 only
|
|
// Defend against cloned attroperties (jQuery gh-1709)
|
|
uniqueCache = outerCache[ node.uniqueID ] ||
|
|
( outerCache[ node.uniqueID ] = {} );
|
|
|
|
cache = uniqueCache[ type ] || [];
|
|
nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
|
|
diff = nodeIndex;
|
|
}
|
|
|
|
// xml :nth-child(...)
|
|
// or :nth-last-child(...) or :nth(-last)?-of-type(...)
|
|
if ( diff === false ) {
|
|
|
|
// Use the same loop as above to seek `elem` from the start
|
|
while ( ( node = ++nodeIndex && node && node[ dir ] ||
|
|
( diff = nodeIndex = 0 ) || start.pop() ) ) {
|
|
|
|
if ( ( ofType ?
|
|
node.nodeName.toLowerCase() === name :
|
|
node.nodeType === 1 ) &&
|
|
++diff ) {
|
|
|
|
// Cache the index of each encountered element
|
|
if ( useCache ) {
|
|
outerCache = node[ expando ] ||
|
|
( node[ expando ] = {} );
|
|
|
|
// Support: IE <9 only
|
|
// Defend against cloned attroperties (jQuery gh-1709)
|
|
uniqueCache = outerCache[ node.uniqueID ] ||
|
|
( outerCache[ node.uniqueID ] = {} );
|
|
|
|
uniqueCache[ type ] = [ dirruns, diff ];
|
|
}
|
|
|
|
if ( node === elem ) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Incorporate the offset, then check against cycle size
|
|
diff -= last;
|
|
return diff === first || ( diff % first === 0 && diff / first >= 0 );
|
|
}
|
|
};
|
|
},
|
|
|
|
"PSEUDO": function( pseudo, argument ) {
|
|
|
|
// pseudo-class names are case-insensitive
|
|
// http://www.w3.org/TR/selectors/#pseudo-classes
|
|
// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
|
|
// Remember that setFilters inherits from pseudos
|
|
var args,
|
|
fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
|
|
Sizzle.error( "unsupported pseudo: " + pseudo );
|
|
|
|
// The user may use createPseudo to indicate that
|
|
// arguments are needed to create the filter function
|
|
// just as Sizzle does
|
|
if ( fn[ expando ] ) {
|
|
return fn( argument );
|
|
}
|
|
|
|
// But maintain support for old signatures
|
|
if ( fn.length > 1 ) {
|
|
args = [ pseudo, pseudo, "", argument ];
|
|
return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
|
|
markFunction( function( seed, matches ) {
|
|
var idx,
|
|
matched = fn( seed, argument ),
|
|
i = matched.length;
|
|
while ( i-- ) {
|
|
idx = indexOf( seed, matched[ i ] );
|
|
seed[ idx ] = !( matches[ idx ] = matched[ i ] );
|
|
}
|
|
} ) :
|
|
function( elem ) {
|
|
return fn( elem, 0, args );
|
|
};
|
|
}
|
|
|
|
return fn;
|
|
}
|
|
},
|
|
|
|
pseudos: {
|
|
|
|
// Potentially complex pseudos
|
|
"not": markFunction( function( selector ) {
|
|
|
|
// Trim the selector passed to compile
|
|
// to avoid treating leading and trailing
|
|
// spaces as combinators
|
|
var input = [],
|
|
results = [],
|
|
matcher = compile( selector.replace( rtrim, "$1" ) );
|
|
|
|
return matcher[ expando ] ?
|
|
markFunction( function( seed, matches, _context, xml ) {
|
|
var elem,
|
|
unmatched = matcher( seed, null, xml, [] ),
|
|
i = seed.length;
|
|
|
|
// Match elements unmatched by `matcher`
|
|
while ( i-- ) {
|
|
if ( ( elem = unmatched[ i ] ) ) {
|
|
seed[ i ] = !( matches[ i ] = elem );
|
|
}
|
|
}
|
|
} ) :
|
|
function( elem, _context, xml ) {
|
|
input[ 0 ] = elem;
|
|
matcher( input, null, xml, results );
|
|
|
|
// Don't keep the element (issue #299)
|
|
input[ 0 ] = null;
|
|
return !results.pop();
|
|
};
|
|
} ),
|
|
|
|
"has": markFunction( function( selector ) {
|
|
return function( elem ) {
|
|
return Sizzle( selector, elem ).length > 0;
|
|
};
|
|
} ),
|
|
|
|
"contains": markFunction( function( text ) {
|
|
text = text.replace( runescape, funescape );
|
|
return function( elem ) {
|
|
return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;
|
|
};
|
|
} ),
|
|
|
|
// "Whether an element is represented by a :lang() selector
|
|
// is based solely on the element's language value
|
|
// being equal to the identifier C,
|
|
// or beginning with the identifier C immediately followed by "-".
|
|
// The matching of C against the element's language value is performed case-insensitively.
|
|
// The identifier C does not have to be a valid language name."
|
|
// http://www.w3.org/TR/selectors/#lang-pseudo
|
|
"lang": markFunction( function( lang ) {
|
|
|
|
// lang value must be a valid identifier
|
|
if ( !ridentifier.test( lang || "" ) ) {
|
|
Sizzle.error( "unsupported lang: " + lang );
|
|
}
|
|
lang = lang.replace( runescape, funescape ).toLowerCase();
|
|
return function( elem ) {
|
|
var elemLang;
|
|
do {
|
|
if ( ( elemLang = documentIsHTML ?
|
|
elem.lang :
|
|
elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) {
|
|
|
|
elemLang = elemLang.toLowerCase();
|
|
return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
|
|
}
|
|
} while ( ( elem = elem.parentNode ) && elem.nodeType === 1 );
|
|
return false;
|
|
};
|
|
} ),
|
|
|
|
// Miscellaneous
|
|
"target": function( elem ) {
|
|
var hash = window.location && window.location.hash;
|
|
return hash && hash.slice( 1 ) === elem.id;
|
|
},
|
|
|
|
"root": function( elem ) {
|
|
return elem === docElem;
|
|
},
|
|
|
|
"focus": function( elem ) {
|
|
return elem === document.activeElement &&
|
|
( !document.hasFocus || document.hasFocus() ) &&
|
|
!!( elem.type || elem.href || ~elem.tabIndex );
|
|
},
|
|
|
|
// Boolean properties
|
|
"enabled": createDisabledPseudo( false ),
|
|
"disabled": createDisabledPseudo( true ),
|
|
|
|
"checked": function( elem ) {
|
|
|
|
// In CSS3, :checked should return both checked and selected elements
|
|
// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
|
|
var nodeName = elem.nodeName.toLowerCase();
|
|
return ( nodeName === "input" && !!elem.checked ) ||
|
|
( nodeName === "option" && !!elem.selected );
|
|
},
|
|
|
|
"selected": function( elem ) {
|
|
|
|
// Accessing this property makes selected-by-default
|
|
// options in Safari work properly
|
|
if ( elem.parentNode ) {
|
|
// eslint-disable-next-line no-unused-expressions
|
|
elem.parentNode.selectedIndex;
|
|
}
|
|
|
|
return elem.selected === true;
|
|
},
|
|
|
|
// Contents
|
|
"empty": function( elem ) {
|
|
|
|
// http://www.w3.org/TR/selectors/#empty-pseudo
|
|
// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
|
|
// but not by others (comment: 8; processing instruction: 7; etc.)
|
|
// nodeType < 6 works because attributes (2) do not appear as children
|
|
for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
|
|
if ( elem.nodeType < 6 ) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
},
|
|
|
|
"parent": function( elem ) {
|
|
return !Expr.pseudos[ "empty" ]( elem );
|
|
},
|
|
|
|
// Element/input types
|
|
"header": function( elem ) {
|
|
return rheader.test( elem.nodeName );
|
|
},
|
|
|
|
"input": function( elem ) {
|
|
return rinputs.test( elem.nodeName );
|
|
},
|
|
|
|
"button": function( elem ) {
|
|
var name = elem.nodeName.toLowerCase();
|
|
return name === "input" && elem.type === "button" || name === "button";
|
|
},
|
|
|
|
"text": function( elem ) {
|
|
var attr;
|
|
return elem.nodeName.toLowerCase() === "input" &&
|
|
elem.type === "text" &&
|
|
|
|
// Support: IE<8
|
|
// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
|
|
( ( attr = elem.getAttribute( "type" ) ) == null ||
|
|
attr.toLowerCase() === "text" );
|
|
},
|
|
|
|
// Position-in-collection
|
|
"first": createPositionalPseudo( function() {
|
|
return [ 0 ];
|
|
} ),
|
|
|
|
"last": createPositionalPseudo( function( _matchIndexes, length ) {
|
|
return [ length - 1 ];
|
|
} ),
|
|
|
|
"eq": createPositionalPseudo( function( _matchIndexes, length, argument ) {
|
|
return [ argument < 0 ? argument + length : argument ];
|
|
} ),
|
|
|
|
"even": createPositionalPseudo( function( matchIndexes, length ) {
|
|
var i = 0;
|
|
for ( ; i < length; i += 2 ) {
|
|
matchIndexes.push( i );
|
|
}
|
|
return matchIndexes;
|
|
} ),
|
|
|
|
"odd": createPositionalPseudo( function( matchIndexes, length ) {
|
|
var i = 1;
|
|
for ( ; i < length; i += 2 ) {
|
|
matchIndexes.push( i );
|
|
}
|
|
return matchIndexes;
|
|
} ),
|
|
|
|
"lt": createPositionalPseudo( function( matchIndexes, length, argument ) {
|
|
var i = argument < 0 ?
|
|
argument + length :
|
|
argument > length ?
|
|
length :
|
|
argument;
|
|
for ( ; --i >= 0; ) {
|
|
matchIndexes.push( i );
|
|
}
|
|
return matchIndexes;
|
|
} ),
|
|
|
|
"gt": createPositionalPseudo( function( matchIndexes, length, argument ) {
|
|
var i = argument < 0 ? argument + length : argument;
|
|
for ( ; ++i < length; ) {
|
|
matchIndexes.push( i );
|
|
}
|
|
return matchIndexes;
|
|
} )
|
|
}
|
|
};
|
|
|
|
Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ];
|
|
|
|
// Add button/input type pseudos
|
|
for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
|
|
Expr.pseudos[ i ] = createInputPseudo( i );
|
|
}
|
|
for ( i in { submit: true, reset: true } ) {
|
|
Expr.pseudos[ i ] = createButtonPseudo( i );
|
|
}
|
|
|
|
// Easy API for creating new setFilters
|
|
function setFilters() {}
|
|
setFilters.prototype = Expr.filters = Expr.pseudos;
|
|
Expr.setFilters = new setFilters();
|
|
|
|
tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
|
|
var matched, match, tokens, type,
|
|
soFar, groups, preFilters,
|
|
cached = tokenCache[ selector + " " ];
|
|
|
|
if ( cached ) {
|
|
return parseOnly ? 0 : cached.slice( 0 );
|
|
}
|
|
|
|
soFar = selector;
|
|
groups = [];
|
|
preFilters = Expr.preFilter;
|
|
|
|
while ( soFar ) {
|
|
|
|
// Comma and first run
|
|
if ( !matched || ( match = rcomma.exec( soFar ) ) ) {
|
|
if ( match ) {
|
|
|
|
// Don't consume trailing commas as valid
|
|
soFar = soFar.slice( match[ 0 ].length ) || soFar;
|
|
}
|
|
groups.push( ( tokens = [] ) );
|
|
}
|
|
|
|
matched = false;
|
|
|
|
// Combinators
|
|
if ( ( match = rcombinators.exec( soFar ) ) ) {
|
|
matched = match.shift();
|
|
tokens.push( {
|
|
value: matched,
|
|
|
|
// Cast descendant combinators to space
|
|
type: match[ 0 ].replace( rtrim, " " )
|
|
} );
|
|
soFar = soFar.slice( matched.length );
|
|
}
|
|
|
|
// Filters
|
|
for ( type in Expr.filter ) {
|
|
if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] ||
|
|
( match = preFilters[ type ]( match ) ) ) ) {
|
|
matched = match.shift();
|
|
tokens.push( {
|
|
value: matched,
|
|
type: type,
|
|
matches: match
|
|
} );
|
|
soFar = soFar.slice( matched.length );
|
|
}
|
|
}
|
|
|
|
if ( !matched ) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Return the length of the invalid excess
|
|
// if we're just parsing
|
|
// Otherwise, throw an error or return tokens
|
|
return parseOnly ?
|
|
soFar.length :
|
|
soFar ?
|
|
Sizzle.error( selector ) :
|
|
|
|
// Cache the tokens
|
|
tokenCache( selector, groups ).slice( 0 );
|
|
};
|
|
|
|
function toSelector( tokens ) {
|
|
var i = 0,
|
|
len = tokens.length,
|
|
selector = "";
|
|
for ( ; i < len; i++ ) {
|
|
selector += tokens[ i ].value;
|
|
}
|
|
return selector;
|
|
}
|
|
|
|
function addCombinator( matcher, combinator, base ) {
|
|
var dir = combinator.dir,
|
|
skip = combinator.next,
|
|
key = skip || dir,
|
|
checkNonElements = base && key === "parentNode",
|
|
doneName = done++;
|
|
|
|
return combinator.first ?
|
|
|
|
// Check against closest ancestor/preceding element
|
|
function( elem, context, xml ) {
|
|
while ( ( elem = elem[ dir ] ) ) {
|
|
if ( elem.nodeType === 1 || checkNonElements ) {
|
|
return matcher( elem, context, xml );
|
|
}
|
|
}
|
|
return false;
|
|
} :
|
|
|
|
// Check against all ancestor/preceding elements
|
|
function( elem, context, xml ) {
|
|
var oldCache, uniqueCache, outerCache,
|
|
newCache = [ dirruns, doneName ];
|
|
|
|
// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
|
|
if ( xml ) {
|
|
while ( ( elem = elem[ dir ] ) ) {
|
|
if ( elem.nodeType === 1 || checkNonElements ) {
|
|
if ( matcher( elem, context, xml ) ) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
while ( ( elem = elem[ dir ] ) ) {
|
|
if ( elem.nodeType === 1 || checkNonElements ) {
|
|
outerCache = elem[ expando ] || ( elem[ expando ] = {} );
|
|
|
|
// Support: IE <9 only
|
|
// Defend against cloned attroperties (jQuery gh-1709)
|
|
uniqueCache = outerCache[ elem.uniqueID ] ||
|
|
( outerCache[ elem.uniqueID ] = {} );
|
|
|
|
if ( skip && skip === elem.nodeName.toLowerCase() ) {
|
|
elem = elem[ dir ] || elem;
|
|
} else if ( ( oldCache = uniqueCache[ key ] ) &&
|
|
oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
|
|
|
|
// Assign to newCache so results back-propagate to previous elements
|
|
return ( newCache[ 2 ] = oldCache[ 2 ] );
|
|
} else {
|
|
|
|
// Reuse newcache so results back-propagate to previous elements
|
|
uniqueCache[ key ] = newCache;
|
|
|
|
// A match means we're done; a fail means we have to keep checking
|
|
if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
}
|
|
|
|
function elementMatcher( matchers ) {
|
|
return matchers.length > 1 ?
|
|
function( elem, context, xml ) {
|
|
var i = matchers.length;
|
|
while ( i-- ) {
|
|
if ( !matchers[ i ]( elem, context, xml ) ) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
} :
|
|
matchers[ 0 ];
|
|
}
|
|
|
|
function multipleContexts( selector, contexts, results ) {
|
|
var i = 0,
|
|
len = contexts.length;
|
|
for ( ; i < len; i++ ) {
|
|
Sizzle( selector, contexts[ i ], results );
|
|
}
|
|
return results;
|
|
}
|
|
|
|
function condense( unmatched, map, filter, context, xml ) {
|
|
var elem,
|
|
newUnmatched = [],
|
|
i = 0,
|
|
len = unmatched.length,
|
|
mapped = map != null;
|
|
|
|
for ( ; i < len; i++ ) {
|
|
if ( ( elem = unmatched[ i ] ) ) {
|
|
if ( !filter || filter( elem, context, xml ) ) {
|
|
newUnmatched.push( elem );
|
|
if ( mapped ) {
|
|
map.push( i );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return newUnmatched;
|
|
}
|
|
|
|
function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
|
|
if ( postFilter && !postFilter[ expando ] ) {
|
|
postFilter = setMatcher( postFilter );
|
|
}
|
|
if ( postFinder && !postFinder[ expando ] ) {
|
|
postFinder = setMatcher( postFinder, postSelector );
|
|
}
|
|
return markFunction( function( seed, results, context, xml ) {
|
|
var temp, i, elem,
|
|
preMap = [],
|
|
postMap = [],
|
|
preexisting = results.length,
|
|
|
|
// Get initial elements from seed or context
|
|
elems = seed || multipleContexts(
|
|
selector || "*",
|
|
context.nodeType ? [ context ] : context,
|
|
[]
|
|
),
|
|
|
|
// Prefilter to get matcher input, preserving a map for seed-results synchronization
|
|
matcherIn = preFilter && ( seed || !selector ) ?
|
|
condense( elems, preMap, preFilter, context, xml ) :
|
|
elems,
|
|
|
|
matcherOut = matcher ?
|
|
|
|
// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
|
|
postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
|
|
|
|
// ...intermediate processing is necessary
|
|
[] :
|
|
|
|
// ...otherwise use results directly
|
|
results :
|
|
matcherIn;
|
|
|
|
// Find primary matches
|
|
if ( matcher ) {
|
|
matcher( matcherIn, matcherOut, context, xml );
|
|
}
|
|
|
|
// Apply postFilter
|
|
if ( postFilter ) {
|
|
temp = condense( matcherOut, postMap );
|
|
postFilter( temp, [], context, xml );
|
|
|
|
// Un-match failing elements by moving them back to matcherIn
|
|
i = temp.length;
|
|
while ( i-- ) {
|
|
if ( ( elem = temp[ i ] ) ) {
|
|
matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( seed ) {
|
|
if ( postFinder || preFilter ) {
|
|
if ( postFinder ) {
|
|
|
|
// Get the final matcherOut by condensing this intermediate into postFinder contexts
|
|
temp = [];
|
|
i = matcherOut.length;
|
|
while ( i-- ) {
|
|
if ( ( elem = matcherOut[ i ] ) ) {
|
|
|
|
// Restore matcherIn since elem is not yet a final match
|
|
temp.push( ( matcherIn[ i ] = elem ) );
|
|
}
|
|
}
|
|
postFinder( null, ( matcherOut = [] ), temp, xml );
|
|
}
|
|
|
|
// Move matched elements from seed to results to keep them synchronized
|
|
i = matcherOut.length;
|
|
while ( i-- ) {
|
|
if ( ( elem = matcherOut[ i ] ) &&
|
|
( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) {
|
|
|
|
seed[ temp ] = !( results[ temp ] = elem );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add elements to results, through postFinder if defined
|
|
} else {
|
|
matcherOut = condense(
|
|
matcherOut === results ?
|
|
matcherOut.splice( preexisting, matcherOut.length ) :
|
|
matcherOut
|
|
);
|
|
if ( postFinder ) {
|
|
postFinder( null, results, matcherOut, xml );
|
|
} else {
|
|
push.apply( results, matcherOut );
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
|
|
function matcherFromTokens( tokens ) {
|
|
var checkContext, matcher, j,
|
|
len = tokens.length,
|
|
leadingRelative = Expr.relative[ tokens[ 0 ].type ],
|
|
implicitRelative = leadingRelative || Expr.relative[ " " ],
|
|
i = leadingRelative ? 1 : 0,
|
|
|
|
// The foundational matcher ensures that elements are reachable from top-level context(s)
|
|
matchContext = addCombinator( function( elem ) {
|
|
return elem === checkContext;
|
|
}, implicitRelative, true ),
|
|
matchAnyContext = addCombinator( function( elem ) {
|
|
return indexOf( checkContext, elem ) > -1;
|
|
}, implicitRelative, true ),
|
|
matchers = [ function( elem, context, xml ) {
|
|
var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
|
|
( checkContext = context ).nodeType ?
|
|
matchContext( elem, context, xml ) :
|
|
matchAnyContext( elem, context, xml ) );
|
|
|
|
// Avoid hanging onto element (issue #299)
|
|
checkContext = null;
|
|
return ret;
|
|
} ];
|
|
|
|
for ( ; i < len; i++ ) {
|
|
if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) {
|
|
matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ];
|
|
} else {
|
|
matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches );
|
|
|
|
// Return special upon seeing a positional matcher
|
|
if ( matcher[ expando ] ) {
|
|
|
|
// Find the next relative operator (if any) for proper handling
|
|
j = ++i;
|
|
for ( ; j < len; j++ ) {
|
|
if ( Expr.relative[ tokens[ j ].type ] ) {
|
|
break;
|
|
}
|
|
}
|
|
return setMatcher(
|
|
i > 1 && elementMatcher( matchers ),
|
|
i > 1 && toSelector(
|
|
|
|
// If the preceding token was a descendant combinator, insert an implicit any-element `*`
|
|
tokens
|
|
.slice( 0, i - 1 )
|
|
.concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } )
|
|
).replace( rtrim, "$1" ),
|
|
matcher,
|
|
i < j && matcherFromTokens( tokens.slice( i, j ) ),
|
|
j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ),
|
|
j < len && toSelector( tokens )
|
|
);
|
|
}
|
|
matchers.push( matcher );
|
|
}
|
|
}
|
|
|
|
return elementMatcher( matchers );
|
|
}
|
|
|
|
function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
|
|
var bySet = setMatchers.length > 0,
|
|
byElement = elementMatchers.length > 0,
|
|
superMatcher = function( seed, context, xml, results, outermost ) {
|
|
var elem, j, matcher,
|
|
matchedCount = 0,
|
|
i = "0",
|
|
unmatched = seed && [],
|
|
setMatched = [],
|
|
contextBackup = outermostContext,
|
|
|
|
// We must always have either seed elements or outermost context
|
|
elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ),
|
|
|
|
// Use integer dirruns iff this is the outermost matcher
|
|
dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ),
|
|
len = elems.length;
|
|
|
|
if ( outermost ) {
|
|
|
|
// Support: IE 11+, Edge 17 - 18+
|
|
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
|
|
// two documents; shallow comparisons work.
|
|
// eslint-disable-next-line eqeqeq
|
|
outermostContext = context == document || context || outermost;
|
|
}
|
|
|
|
// Add elements passing elementMatchers directly to results
|
|
// Support: IE<9, Safari
|
|
// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
|
|
for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) {
|
|
if ( byElement && elem ) {
|
|
j = 0;
|
|
|
|
// Support: IE 11+, Edge 17 - 18+
|
|
// IE/Edge sometimes throw a "Permission denied" error when strict-comparing
|
|
// two documents; shallow comparisons work.
|
|
// eslint-disable-next-line eqeqeq
|
|
if ( !context && elem.ownerDocument != document ) {
|
|
setDocument( elem );
|
|
xml = !documentIsHTML;
|
|
}
|
|
while ( ( matcher = elementMatchers[ j++ ] ) ) {
|
|
if ( matcher( elem, context || document, xml ) ) {
|
|
results.push( elem );
|
|
break;
|
|
}
|
|
}
|
|
if ( outermost ) {
|
|
dirruns = dirrunsUnique;
|
|
}
|
|
}
|
|
|
|
// Track unmatched elements for set filters
|
|
if ( bySet ) {
|
|
|
|
// They will have gone through all possible matchers
|
|
if ( ( elem = !matcher && elem ) ) {
|
|
matchedCount--;
|
|
}
|
|
|
|
// Lengthen the array for every element, matched or not
|
|
if ( seed ) {
|
|
unmatched.push( elem );
|
|
}
|
|
}
|
|
}
|
|
|
|
// `i` is now the count of elements visited above, and adding it to `matchedCount`
|
|
// makes the latter nonnegative.
|
|
matchedCount += i;
|
|
|
|
// Apply set filters to unmatched elements
|
|
// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
|
|
// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
|
|
// no element matchers and no seed.
|
|
// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
|
|
// case, which will result in a "00" `matchedCount` that differs from `i` but is also
|
|
// numerically zero.
|
|
if ( bySet && i !== matchedCount ) {
|
|
j = 0;
|
|
while ( ( matcher = setMatchers[ j++ ] ) ) {
|
|
matcher( unmatched, setMatched, context, xml );
|
|
}
|
|
|
|
if ( seed ) {
|
|
|
|
// Reintegrate element matches to eliminate the need for sorting
|
|
if ( matchedCount > 0 ) {
|
|
while ( i-- ) {
|
|
if ( !( unmatched[ i ] || setMatched[ i ] ) ) {
|
|
setMatched[ i ] = pop.call( results );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Discard index placeholder values to get only actual matches
|
|
setMatched = condense( setMatched );
|
|
}
|
|
|
|
// Add matches to results
|
|
push.apply( results, setMatched );
|
|
|
|
// Seedless set matches succeeding multiple successful matchers stipulate sorting
|
|
if ( outermost && !seed && setMatched.length > 0 &&
|
|
( matchedCount + setMatchers.length ) > 1 ) {
|
|
|
|
Sizzle.uniqueSort( results );
|
|
}
|
|
}
|
|
|
|
// Override manipulation of globals by nested matchers
|
|
if ( outermost ) {
|
|
dirruns = dirrunsUnique;
|
|
outermostContext = contextBackup;
|
|
}
|
|
|
|
return unmatched;
|
|
};
|
|
|
|
return bySet ?
|
|
markFunction( superMatcher ) :
|
|
superMatcher;
|
|
}
|
|
|
|
compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
|
|
var i,
|
|
setMatchers = [],
|
|
elementMatchers = [],
|
|
cached = compilerCache[ selector + " " ];
|
|
|
|
if ( !cached ) {
|
|
|
|
// Generate a function of recursive functions that can be used to check each element
|
|
if ( !match ) {
|
|
match = tokenize( selector );
|
|
}
|
|
i = match.length;
|
|
while ( i-- ) {
|
|
cached = matcherFromTokens( match[ i ] );
|
|
if ( cached[ expando ] ) {
|
|
setMatchers.push( cached );
|
|
} else {
|
|
elementMatchers.push( cached );
|
|
}
|
|
}
|
|
|
|
// Cache the compiled function
|
|
cached = compilerCache(
|
|
selector,
|
|
matcherFromGroupMatchers( elementMatchers, setMatchers )
|
|
);
|
|
|
|
// Save selector and tokenization
|
|
cached.selector = selector;
|
|
}
|
|
return cached;
|
|
};
|
|
|
|
/**
|
|
* A low-level selection function that works with Sizzle's compiled
|
|
* selector functions
|
|
* @param {String|Function} selector A selector or a pre-compiled
|
|
* selector function built with Sizzle.compile
|
|
* @param {Element} context
|
|
* @param {Array} [results]
|
|
* @param {Array} [seed] A set of elements to match against
|
|
*/
|
|
select = Sizzle.select = function( selector, context, results, seed ) {
|
|
var i, tokens, token, type, find,
|
|
compiled = typeof selector === "function" && selector,
|
|
match = !seed && tokenize( ( selector = compiled.selector || selector ) );
|
|
|
|
results = results || [];
|
|
|
|
// Try to minimize operations if there is only one selector in the list and no seed
|
|
// (the latter of which guarantees us context)
|
|
if ( match.length === 1 ) {
|
|
|
|
// Reduce context if the leading compound selector is an ID
|
|
tokens = match[ 0 ] = match[ 0 ].slice( 0 );
|
|
if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" &&
|
|
context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) {
|
|
|
|
context = ( Expr.find[ "ID" ]( token.matches[ 0 ]
|
|
.replace( runescape, funescape ), context ) || [] )[ 0 ];
|
|
if ( !context ) {
|
|
return results;
|
|
|
|
// Precompiled matchers will still verify ancestry, so step up a level
|
|
} else if ( compiled ) {
|
|
context = context.parentNode;
|
|
}
|
|
|
|
selector = selector.slice( tokens.shift().value.length );
|
|
}
|
|
|
|
// Fetch a seed set for right-to-left matching
|
|
i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length;
|
|
while ( i-- ) {
|
|
token = tokens[ i ];
|
|
|
|
// Abort if we hit a combinator
|
|
if ( Expr.relative[ ( type = token.type ) ] ) {
|
|
break;
|
|
}
|
|
if ( ( find = Expr.find[ type ] ) ) {
|
|
|
|
// Search, expanding context for leading sibling combinators
|
|
if ( ( seed = find(
|
|
token.matches[ 0 ].replace( runescape, funescape ),
|
|
rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) ||
|
|
context
|
|
) ) ) {
|
|
|
|
// If seed is empty or no tokens remain, we can return early
|
|
tokens.splice( i, 1 );
|
|
selector = seed.length && toSelector( tokens );
|
|
if ( !selector ) {
|
|
push.apply( results, seed );
|
|
return results;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Compile and execute a filtering function if one is not provided
|
|
// Provide `match` to avoid retokenization if we modified the selector above
|
|
( compiled || compile( selector, match ) )(
|
|
seed,
|
|
context,
|
|
!documentIsHTML,
|
|
results,
|
|
!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
|
|
);
|
|
return results;
|
|
};
|
|
|
|
// One-time assignments
|
|
|
|
// Sort stability
|
|
support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando;
|
|
|
|
// Support: Chrome 14-35+
|
|
// Always assume duplicates if they aren't passed to the comparison function
|
|
support.detectDuplicates = !!hasDuplicate;
|
|
|
|
// Initialize against the default document
|
|
setDocument();
|
|
|
|
// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
|
|
// Detached nodes confoundingly follow *each other*
|
|
support.sortDetached = assert( function( el ) {
|
|
|
|
// Should return 1, but returns 4 (following)
|
|
return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1;
|
|
} );
|
|
|
|
// Support: IE<8
|
|
// Prevent attribute/property "interpolation"
|
|
// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
|
|
if ( !assert( function( el ) {
|
|
el.innerHTML = "<a href='#'></a>";
|
|
return el.firstChild.getAttribute( "href" ) === "#";
|
|
} ) ) {
|
|
addHandle( "type|href|height|width", function( elem, name, isXML ) {
|
|
if ( !isXML ) {
|
|
return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
|
|
}
|
|
} );
|
|
}
|
|
|
|
// Support: IE<9
|
|
// Use defaultValue in place of getAttribute("value")
|
|
if ( !support.attributes || !assert( function( el ) {
|
|
el.innerHTML = "<input/>";
|
|
el.firstChild.setAttribute( "value", "" );
|
|
return el.firstChild.getAttribute( "value" ) === "";
|
|
} ) ) {
|
|
addHandle( "value", function( elem, _name, isXML ) {
|
|
if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
|
|
return elem.defaultValue;
|
|
}
|
|
} );
|
|
}
|
|
|
|
// Support: IE<9
|
|
// Use getAttributeNode to fetch booleans when getAttribute lies
|
|
if ( !assert( function( el ) {
|
|
return el.getAttribute( "disabled" ) == null;
|
|
} ) ) {
|
|
addHandle( booleans, function( elem, name, isXML ) {
|
|
var val;
|
|
if ( !isXML ) {
|
|
return elem[ name ] === true ? name.toLowerCase() :
|
|
( val = elem.getAttributeNode( name ) ) && val.specified ?
|
|
val.value :
|
|
null;
|
|
}
|
|
} );
|
|
}
|
|
|
|
return Sizzle;
|
|
|
|
} )( window );
|
|
|
|
|
|
|
|
jQuery.find = Sizzle;
|
|
jQuery.expr = Sizzle.selectors;
|
|
|
|
// Deprecated
|
|
jQuery.expr[ ":" ] = jQuery.expr.pseudos;
|
|
jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
|
|
jQuery.text = Sizzle.getText;
|
|
jQuery.isXMLDoc = Sizzle.isXML;
|
|
jQuery.contains = Sizzle.contains;
|
|
jQuery.escapeSelector = Sizzle.escape;
|
|
|
|
|
|
|
|
|
|
var dir = function( elem, dir, until ) {
|
|
var matched = [],
|
|
truncate = until !== undefined;
|
|
|
|
while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
|
|
if ( elem.nodeType === 1 ) {
|
|
if ( truncate && jQuery( elem ).is( until ) ) {
|
|
break;
|
|
}
|
|
matched.push( elem );
|
|
}
|
|
}
|
|
return matched;
|
|
};
|
|
|
|
|
|
var siblings = function( n, elem ) {
|
|
var matched = [];
|
|
|
|
for ( ; n; n = n.nextSibling ) {
|
|
if ( n.nodeType === 1 && n !== elem ) {
|
|
matched.push( n );
|
|
}
|
|
}
|
|
|
|
return matched;
|
|
};
|
|
|
|
|
|
var rneedsContext = jQuery.expr.match.needsContext;
|
|
|
|
|
|
|
|
function nodeName( elem, name ) {
|
|
|
|
return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
|
|
|
|
};
|
|
var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
|
|
|
|
|
|
|
|
// Implement the identical functionality for filter and not
|
|
function winnow( elements, qualifier, not ) {
|
|
if ( isFunction( qualifier ) ) {
|
|
return jQuery.grep( elements, function( elem, i ) {
|
|
return !!qualifier.call( elem, i, elem ) !== not;
|
|
} );
|
|
}
|
|
|
|
// Single element
|
|
if ( qualifier.nodeType ) {
|
|
return jQuery.grep( elements, function( elem ) {
|
|
return ( elem === qualifier ) !== not;
|
|
} );
|
|
}
|
|
|
|
// Arraylike of elements (jQuery, arguments, Array)
|
|
if ( typeof qualifier !== "string" ) {
|
|
return jQuery.grep( elements, function( elem ) {
|
|
return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
|
|
} );
|
|
}
|
|
|
|
// Filtered directly for both simple and complex selectors
|
|
return jQuery.filter( qualifier, elements, not );
|
|
}
|
|
|
|
jQuery.filter = function( expr, elems, not ) {
|
|
var elem = elems[ 0 ];
|
|
|
|
if ( not ) {
|
|
expr = ":not(" + expr + ")";
|
|
}
|
|
|
|
if ( elems.length === 1 && elem.nodeType === 1 ) {
|
|
return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
|
|
}
|
|
|
|
return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
|
|
return elem.nodeType === 1;
|
|
} ) );
|
|
};
|
|
|
|
jQuery.fn.extend( {
|
|
find: function( selector ) {
|
|
var i, ret,
|
|
len = this.length,
|
|
self = this;
|
|
|
|
if ( typeof selector !== "string" ) {
|
|
return this.pushStack( jQuery( selector ).filter( function() {
|
|
for ( i = 0; i < len; i++ ) {
|
|
if ( jQuery.contains( self[ i ], this ) ) {
|
|
return true;
|
|
}
|
|
}
|
|
} ) );
|
|
}
|
|
|
|
ret = this.pushStack( [] );
|
|
|
|
for ( i = 0; i < len; i++ ) {
|
|
jQuery.find( selector, self[ i ], ret );
|
|
}
|
|
|
|
return len > 1 ? jQuery.uniqueSort( ret ) : ret;
|
|
},
|
|
filter: function( selector ) {
|
|
return this.pushStack( winnow( this, selector || [], false ) );
|
|
},
|
|
not: function( selector ) {
|
|
return this.pushStack( winnow( this, selector || [], true ) );
|
|
},
|
|
is: function( selector ) {
|
|
return !!winnow(
|
|
this,
|
|
|
|
// If this is a positional/relative selector, check membership in the returned set
|
|
// so $("p:first").is("p:last") won't return true for a doc with two "p".
|
|
typeof selector === "string" && rneedsContext.test( selector ) ?
|
|
jQuery( selector ) :
|
|
selector || [],
|
|
false
|
|
).length;
|
|
}
|
|
} );
|
|
|
|
|
|
// Initialize a jQuery object
|
|
|
|
|
|
// A central reference to the root jQuery(document)
|
|
var rootjQuery,
|
|
|
|
// A simple way to check for HTML strings
|
|
// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
|
|
// Strict HTML recognition (#11290: must start with <)
|
|
// Shortcut simple #id case for speed
|
|
rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
|
|
|
|
init = jQuery.fn.init = function( selector, context, root ) {
|
|
var match, elem;
|
|
|
|
// HANDLE: $(""), $(null), $(undefined), $(false)
|
|
if ( !selector ) {
|
|
return this;
|
|
}
|
|
|
|
// Method init() accepts an alternate rootjQuery
|
|
// so migrate can support jQuery.sub (gh-2101)
|
|
root = root || rootjQuery;
|
|
|
|
// Handle HTML strings
|
|
if ( typeof selector === "string" ) {
|
|
if ( selector[ 0 ] === "<" &&
|
|
selector[ selector.length - 1 ] === ">" &&
|
|
selector.length >= 3 ) {
|
|
|
|
// Assume that strings that start and end with <> are HTML and skip the regex check
|
|
match = [ null, selector, null ];
|
|
|
|
} else {
|
|
match = rquickExpr.exec( selector );
|
|
}
|
|
|
|
// Match html or make sure no context is specified for #id
|
|
if ( match && ( match[ 1 ] || !context ) ) {
|
|
|
|
// HANDLE: $(html) -> $(array)
|
|
if ( match[ 1 ] ) {
|
|
context = context instanceof jQuery ? context[ 0 ] : context;
|
|
|
|
// Option to run scripts is true for back-compat
|
|
// Intentionally let the error be thrown if parseHTML is not present
|
|
jQuery.merge( this, jQuery.parseHTML(
|
|
match[ 1 ],
|
|
context && context.nodeType ? context.ownerDocument || context : document,
|
|
true
|
|
) );
|
|
|
|
// HANDLE: $(html, props)
|
|
if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
|
|
for ( match in context ) {
|
|
|
|
// Properties of context are called as methods if possible
|
|
if ( isFunction( this[ match ] ) ) {
|
|
this[ match ]( context[ match ] );
|
|
|
|
// ...and otherwise set as attributes
|
|
} else {
|
|
this.attr( match, context[ match ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
|
|
// HANDLE: $(#id)
|
|
} else {
|
|
elem = document.getElementById( match[ 2 ] );
|
|
|
|
if ( elem ) {
|
|
|
|
// Inject the element directly into the jQuery object
|
|
this[ 0 ] = elem;
|
|
this.length = 1;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
// HANDLE: $(expr, $(...))
|
|
} else if ( !context || context.jquery ) {
|
|
return ( context || root ).find( selector );
|
|
|
|
// HANDLE: $(expr, context)
|
|
// (which is just equivalent to: $(context).find(expr)
|
|
} else {
|
|
return this.constructor( context ).find( selector );
|
|
}
|
|
|
|
// HANDLE: $(DOMElement)
|
|
} else if ( selector.nodeType ) {
|
|
this[ 0 ] = selector;
|
|
this.length = 1;
|
|
return this;
|
|
|
|
// HANDLE: $(function)
|
|
// Shortcut for document ready
|
|
} else if ( isFunction( selector ) ) {
|
|
return root.ready !== undefined ?
|
|
root.ready( selector ) :
|
|
|
|
// Execute immediately if ready is not present
|
|
selector( jQuery );
|
|
}
|
|
|
|
return jQuery.makeArray( selector, this );
|
|
};
|
|
|
|
// Give the init function the jQuery prototype for later instantiation
|
|
init.prototype = jQuery.fn;
|
|
|
|
// Initialize central reference
|
|
rootjQuery = jQuery( document );
|
|
|
|
|
|
var rparentsprev = /^(?:parents|prev(?:Until|All))/,
|
|
|
|
// Methods guaranteed to produce a unique set when starting from a unique set
|
|
guaranteedUnique = {
|
|
children: true,
|
|
contents: true,
|
|
next: true,
|
|
prev: true
|
|
};
|
|
|
|
jQuery.fn.extend( {
|
|
has: function( target ) {
|
|
var targets = jQuery( target, this ),
|
|
l = targets.length;
|
|
|
|
return this.filter( function() {
|
|
var i = 0;
|
|
for ( ; i < l; i++ ) {
|
|
if ( jQuery.contains( this, targets[ i ] ) ) {
|
|
return true;
|
|
}
|
|
}
|
|
} );
|
|
},
|
|
|
|
closest: function( selectors, context ) {
|
|
var cur,
|
|
i = 0,
|
|
l = this.length,
|
|
matched = [],
|
|
targets = typeof selectors !== "string" && jQuery( selectors );
|
|
|
|
// Positional selectors never match, since there's no _selection_ context
|
|
if ( !rneedsContext.test( selectors ) ) {
|
|
for ( ; i < l; i++ ) {
|
|
for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
|
|
|
|
// Always skip document fragments
|
|
if ( cur.nodeType < 11 && ( targets ?
|
|
targets.index( cur ) > -1 :
|
|
|
|
// Don't pass non-elements to Sizzle
|
|
cur.nodeType === 1 &&
|
|
jQuery.find.matchesSelector( cur, selectors ) ) ) {
|
|
|
|
matched.push( cur );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
|
|
},
|
|
|
|
// Determine the position of an element within the set
|
|
index: function( elem ) {
|
|
|
|
// No argument, return index in parent
|
|
if ( !elem ) {
|
|
return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
|
|
}
|
|
|
|
// Index in selector
|
|
if ( typeof elem === "string" ) {
|
|
return indexOf.call( jQuery( elem ), this[ 0 ] );
|
|
}
|
|
|
|
// Locate the position of the desired element
|
|
return indexOf.call( this,
|
|
|
|
// If it receives a jQuery object, the first element is used
|
|
elem.jquery ? elem[ 0 ] : elem
|
|
);
|
|
},
|
|
|
|
add: function( selector, context ) {
|
|
return this.pushStack(
|
|
jQuery.uniqueSort(
|
|
jQuery.merge( this.get(), jQuery( selector, context ) )
|
|
)
|
|
);
|
|
},
|
|
|
|
addBack: function( selector ) {
|
|
return this.add( selector == null ?
|
|
this.prevObject : this.prevObject.filter( selector )
|
|
);
|
|
}
|
|
} );
|
|
|
|
function sibling( cur, dir ) {
|
|
while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
|
|
return cur;
|
|
}
|
|
|
|
jQuery.each( {
|
|
parent: function( elem ) {
|
|
var parent = elem.parentNode;
|
|
return parent && parent.nodeType !== 11 ? parent : null;
|
|
},
|
|
parents: function( elem ) {
|
|
return dir( elem, "parentNode" );
|
|
},
|
|
parentsUntil: function( elem, _i, until ) {
|
|
return dir( elem, "parentNode", until );
|
|
},
|
|
next: function( elem ) {
|
|
return sibling( elem, "nextSibling" );
|
|
},
|
|
prev: function( elem ) {
|
|
return sibling( elem, "previousSibling" );
|
|
},
|
|
nextAll: function( elem ) {
|
|
return dir( elem, "nextSibling" );
|
|
},
|
|
prevAll: function( elem ) {
|
|
return dir( elem, "previousSibling" );
|
|
},
|
|
nextUntil: function( elem, _i, until ) {
|
|
return dir( elem, "nextSibling", until );
|
|
},
|
|
prevUntil: function( elem, _i, until ) {
|
|
return dir( elem, "previousSibling", until );
|
|
},
|
|
siblings: function( elem ) {
|
|
return siblings( ( elem.parentNode || {} ).firstChild, elem );
|
|
},
|
|
children: function( elem ) {
|
|
return siblings( elem.firstChild );
|
|
},
|
|
contents: function( elem ) {
|
|
if ( elem.contentDocument != null &&
|
|
|
|
// Support: IE 11+
|
|
// <object> elements with no `data` attribute has an object
|
|
// `contentDocument` with a `null` prototype.
|
|
getProto( elem.contentDocument ) ) {
|
|
|
|
return elem.contentDocument;
|
|
}
|
|
|
|
// Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
|
|
// Treat the template element as a regular one in browsers that
|
|
// don't support it.
|
|
if ( nodeName( elem, "template" ) ) {
|
|
elem = elem.content || elem;
|
|
}
|
|
|
|
return jQuery.merge( [], elem.childNodes );
|
|
}
|
|
}, function( name, fn ) {
|
|
jQuery.fn[ name ] = function( until, selector ) {
|
|
var matched = jQuery.map( this, fn, until );
|
|
|
|
if ( name.slice( -5 ) !== "Until" ) {
|
|
selector = until;
|
|
}
|
|
|
|
if ( selector && typeof selector === "string" ) {
|
|
matched = jQuery.filter( selector, matched );
|
|
}
|
|
|
|
if ( this.length > 1 ) {
|
|
|
|
// Remove duplicates
|
|
if ( !guaranteedUnique[ name ] ) {
|
|
jQuery.uniqueSort( matched );
|
|
}
|
|
|
|
// Reverse order for parents* and prev-derivatives
|
|
if ( rparentsprev.test( name ) ) {
|
|
matched.reverse();
|
|
}
|
|
}
|
|
|
|
return this.pushStack( matched );
|
|
};
|
|
} );
|
|
var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
|
|
|
|
|
|
|
|
// Convert String-formatted options into Object-formatted ones
|
|
function createOptions( options ) {
|
|
var object = {};
|
|
jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
|
|
object[ flag ] = true;
|
|
} );
|
|
return object;
|
|
}
|
|
|
|
/*
|
|
* Create a callback list using the following parameters:
|
|
*
|
|
* options: an optional list of space-separated options that will change how
|
|
* the callback list behaves or a more traditional option object
|
|
*
|
|
* By default a callback list will act like an event callback list and can be
|
|
* "fired" multiple times.
|
|
*
|
|
* Possible options:
|
|
*
|
|
* once: will ensure the callback list can only be fired once (like a Deferred)
|
|
*
|
|
* memory: will keep track of previous values and will call any callback added
|
|
* after the list has been fired right away with the latest "memorized"
|
|
* values (like a Deferred)
|
|
*
|
|
* unique: will ensure a callback can only be added once (no duplicate in the list)
|
|
*
|
|
* stopOnFalse: interrupt callings when a callback returns false
|
|
*
|
|
*/
|
|
jQuery.Callbacks = function( options ) {
|
|
|
|
// Convert options from String-formatted to Object-formatted if needed
|
|
// (we check in cache first)
|
|
options = typeof options === "string" ?
|
|
createOptions( options ) :
|
|
jQuery.extend( {}, options );
|
|
|
|
var // Flag to know if list is currently firing
|
|
firing,
|
|
|
|
// Last fire value for non-forgettable lists
|
|
memory,
|
|
|
|
// Flag to know if list was already fired
|
|
fired,
|
|
|
|
// Flag to prevent firing
|
|
locked,
|
|
|
|
// Actual callback list
|
|
list = [],
|
|
|
|
// Queue of execution data for repeatable lists
|
|
queue = [],
|
|
|
|
// Index of currently firing callback (modified by add/remove as needed)
|
|
firingIndex = -1,
|
|
|
|
// Fire callbacks
|
|
fire = function() {
|
|
|
|
// Enforce single-firing
|
|
locked = locked || options.once;
|
|
|
|
// Execute callbacks for all pending executions,
|
|
// respecting firingIndex overrides and runtime changes
|
|
fired = firing = true;
|
|
for ( ; queue.length; firingIndex = -1 ) {
|
|
memory = queue.shift();
|
|
while ( ++firingIndex < list.length ) {
|
|
|
|
// Run callback and check for early termination
|
|
if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
|
|
options.stopOnFalse ) {
|
|
|
|
// Jump to end and forget the data so .add doesn't re-fire
|
|
firingIndex = list.length;
|
|
memory = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Forget the data if we're done with it
|
|
if ( !options.memory ) {
|
|
memory = false;
|
|
}
|
|
|
|
firing = false;
|
|
|
|
// Clean up if we're done firing for good
|
|
if ( locked ) {
|
|
|
|
// Keep an empty list if we have data for future add calls
|
|
if ( memory ) {
|
|
list = [];
|
|
|
|
// Otherwise, this object is spent
|
|
} else {
|
|
list = "";
|
|
}
|
|
}
|
|
},
|
|
|
|
// Actual Callbacks object
|
|
self = {
|
|
|
|
// Add a callback or a collection of callbacks to the list
|
|
add: function() {
|
|
if ( list ) {
|
|
|
|
// If we have memory from a past run, we should fire after adding
|
|
if ( memory && !firing ) {
|
|
firingIndex = list.length - 1;
|
|
queue.push( memory );
|
|
}
|
|
|
|
( function add( args ) {
|
|
jQuery.each( args, function( _, arg ) {
|
|
if ( isFunction( arg ) ) {
|
|
if ( !options.unique || !self.has( arg ) ) {
|
|
list.push( arg );
|
|
}
|
|
} else if ( arg && arg.length && toType( arg ) !== "string" ) {
|
|
|
|
// Inspect recursively
|
|
add( arg );
|
|
}
|
|
} );
|
|
} )( arguments );
|
|
|
|
if ( memory && !firing ) {
|
|
fire();
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
|
|
// Remove a callback from the list
|
|
remove: function() {
|
|
jQuery.each( arguments, function( _, arg ) {
|
|
var index;
|
|
while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
|
|
list.splice( index, 1 );
|
|
|
|
// Handle firing indexes
|
|
if ( index <= firingIndex ) {
|
|
firingIndex--;
|
|
}
|
|
}
|
|
} );
|
|
return this;
|
|
},
|
|
|
|
// Check if a given callback is in the list.
|
|
// If no argument is given, return whether or not list has callbacks attached.
|
|
has: function( fn ) {
|
|
return fn ?
|
|
jQuery.inArray( fn, list ) > -1 :
|
|
list.length > 0;
|
|
},
|
|
|
|
// Remove all callbacks from the list
|
|
empty: function() {
|
|
if ( list ) {
|
|
list = [];
|
|
}
|
|
return this;
|
|
},
|
|
|
|
// Disable .fire and .add
|
|
// Abort any current/pending executions
|
|
// Clear all callbacks and values
|
|
disable: function() {
|
|
locked = queue = [];
|
|
list = memory = "";
|
|
return this;
|
|
},
|
|
disabled: function() {
|
|
return !list;
|
|
},
|
|
|
|
// Disable .fire
|
|
// Also disable .add unless we have memory (since it would have no effect)
|
|
// Abort any pending executions
|
|
lock: function() {
|
|
locked = queue = [];
|
|
if ( !memory && !firing ) {
|
|
list = memory = "";
|
|
}
|
|
return this;
|
|
},
|
|
locked: function() {
|
|
return !!locked;
|
|
},
|
|
|
|
// Call all callbacks with the given context and arguments
|
|
fireWith: function( context, args ) {
|
|
if ( !locked ) {
|
|
args = args || [];
|
|
args = [ context, args.slice ? args.slice() : args ];
|
|
queue.push( args );
|
|
if ( !firing ) {
|
|
fire();
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
|
|
// Call all the callbacks with the given arguments
|
|
fire: function() {
|
|
self.fireWith( this, arguments );
|
|
return this;
|
|
},
|
|
|
|
// To know if the callbacks have already been called at least once
|
|
fired: function() {
|
|
return !!fired;
|
|
}
|
|
};
|
|
|
|
return self;
|
|
};
|
|
|
|
|
|
function Identity( v ) {
|
|
return v;
|
|
}
|
|
function Thrower( ex ) {
|
|
throw ex;
|
|
}
|
|
|
|
function adoptValue( value, resolve, reject, noValue ) {
|
|
var method;
|
|
|
|
try {
|
|
|
|
// Check for promise aspect first to privilege synchronous behavior
|
|
if ( value && isFunction( ( method = value.promise ) ) ) {
|
|
method.call( value ).done( resolve ).fail( reject );
|
|
|
|
// Other thenables
|
|
} else if ( value && isFunction( ( method = value.then ) ) ) {
|
|
method.call( value, resolve, reject );
|
|
|
|
// Other non-thenables
|
|
} else {
|
|
|
|
// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
|
|
// * false: [ value ].slice( 0 ) => resolve( value )
|
|
// * true: [ value ].slice( 1 ) => resolve()
|
|
resolve.apply( undefined, [ value ].slice( noValue ) );
|
|
}
|
|
|
|
// For Promises/A+, convert exceptions into rejections
|
|
// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
|
|
// Deferred#then to conditionally suppress rejection.
|
|
} catch ( value ) {
|
|
|
|
// Support: Android 4.0 only
|
|
// Strict mode functions invoked without .call/.apply get global-object context
|
|
reject.apply( undefined, [ value ] );
|
|
}
|
|
}
|
|
|
|
jQuery.extend( {
|
|
|
|
Deferred: function( func ) {
|
|
var tuples = [
|
|
|
|
// action, add listener, callbacks,
|
|
// ... .then handlers, argument index, [final state]
|
|
[ "notify", "progress", jQuery.Callbacks( "memory" ),
|
|
jQuery.Callbacks( "memory" ), 2 ],
|
|
[ "resolve", "done", jQuery.Callbacks( "once memory" ),
|
|
jQuery.Callbacks( "once memory" ), 0, "resolved" ],
|
|
[ "reject", "fail", jQuery.Callbacks( "once memory" ),
|
|
jQuery.Callbacks( "once memory" ), 1, "rejected" ]
|
|
],
|
|
state = "pending",
|
|
promise = {
|
|
state: function() {
|
|
return state;
|
|
},
|
|
always: function() {
|
|
deferred.done( arguments ).fail( arguments );
|
|
return this;
|
|
},
|
|
"catch": function( fn ) {
|
|
return promise.then( null, fn );
|
|
},
|
|
|
|
// Keep pipe for back-compat
|
|
pipe: function( /* fnDone, fnFail, fnProgress */ ) {
|
|
var fns = arguments;
|
|
|
|
return jQuery.Deferred( function( newDefer ) {
|
|
jQuery.each( tuples, function( _i, tuple ) {
|
|
|
|
// Map tuples (progress, done, fail) to arguments (done, fail, progress)
|
|
var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
|
|
|
|
// deferred.progress(function() { bind to newDefer or newDefer.notify })
|
|
// deferred.done(function() { bind to newDefer or newDefer.resolve })
|
|
// deferred.fail(function() { bind to newDefer or newDefer.reject })
|
|
deferred[ tuple[ 1 ] ]( function() {
|
|
var returned = fn && fn.apply( this, arguments );
|
|
if ( returned && isFunction( returned.promise ) ) {
|
|
returned.promise()
|
|
.progress( newDefer.notify )
|
|
.done( newDefer.resolve )
|
|
.fail( newDefer.reject );
|
|
} else {
|
|
newDefer[ tuple[ 0 ] + "With" ](
|
|
this,
|
|
fn ? [ returned ] : arguments
|
|
);
|
|
}
|
|
} );
|
|
} );
|
|
fns = null;
|
|
} ).promise();
|
|
},
|
|
then: function( onFulfilled, onRejected, onProgress ) {
|
|
var maxDepth = 0;
|
|
function resolve( depth, deferred, handler, special ) {
|
|
return function() {
|
|
var that = this,
|
|
args = arguments,
|
|
mightThrow = function() {
|
|
var returned, then;
|
|
|
|
// Support: Promises/A+ section 2.3.3.3.3
|
|
// https://promisesaplus.com/#point-59
|
|
// Ignore double-resolution attempts
|
|
if ( depth < maxDepth ) {
|
|
return;
|
|
}
|
|
|
|
returned = handler.apply( that, args );
|
|
|
|
// Support: Promises/A+ section 2.3.1
|
|
// https://promisesaplus.com/#point-48
|
|
if ( returned === deferred.promise() ) {
|
|
throw new TypeError( "Thenable self-resolution" );
|
|
}
|
|
|
|
// Support: Promises/A+ sections 2.3.3.1, 3.5
|
|
// https://promisesaplus.com/#point-54
|
|
// https://promisesaplus.com/#point-75
|
|
// Retrieve `then` only once
|
|
then = returned &&
|
|
|
|
// Support: Promises/A+ section 2.3.4
|
|
// https://promisesaplus.com/#point-64
|
|
// Only check objects and functions for thenability
|
|
( typeof returned === "object" ||
|
|
typeof returned === "function" ) &&
|
|
returned.then;
|
|
|
|
// Handle a returned thenable
|
|
if ( isFunction( then ) ) {
|
|
|
|
// Special processors (notify) just wait for resolution
|
|
if ( special ) {
|
|
then.call(
|
|
returned,
|
|
resolve( maxDepth, deferred, Identity, special ),
|
|
resolve( maxDepth, deferred, Thrower, special )
|
|
);
|
|
|
|
// Normal processors (resolve) also hook into progress
|
|
} else {
|
|
|
|
// ...and disregard older resolution values
|
|
maxDepth++;
|
|
|
|
then.call(
|
|
returned,
|
|
resolve( maxDepth, deferred, Identity, special ),
|
|
resolve( maxDepth, deferred, Thrower, special ),
|
|
resolve( maxDepth, deferred, Identity,
|
|
deferred.notifyWith )
|
|
);
|
|
}
|
|
|
|
// Handle all other returned values
|
|
} else {
|
|
|
|
// Only substitute handlers pass on context
|
|
// and multiple values (non-spec behavior)
|
|
if ( handler !== Identity ) {
|
|
that = undefined;
|
|
args = [ returned ];
|
|
}
|
|
|
|
// Process the value(s)
|
|
// Default process is resolve
|
|
( special || deferred.resolveWith )( that, args );
|
|
}
|
|
},
|
|
|
|
// Only normal processors (resolve) catch and reject exceptions
|
|
process = special ?
|
|
mightThrow :
|
|
function() {
|
|
try {
|
|
mightThrow();
|
|
} catch ( e ) {
|
|
|
|
if ( jQuery.Deferred.exceptionHook ) {
|
|
jQuery.Deferred.exceptionHook( e,
|
|
process.stackTrace );
|
|
}
|
|
|
|
// Support: Promises/A+ section 2.3.3.3.4.1
|
|
// https://promisesaplus.com/#point-61
|
|
// Ignore post-resolution exceptions
|
|
if ( depth + 1 >= maxDepth ) {
|
|
|
|
// Only substitute handlers pass on context
|
|
// and multiple values (non-spec behavior)
|
|
if ( handler !== Thrower ) {
|
|
that = undefined;
|
|
args = [ e ];
|
|
}
|
|
|
|
deferred.rejectWith( that, args );
|
|
}
|
|
}
|
|
};
|
|
|
|
// Support: Promises/A+ section 2.3.3.3.1
|
|
// https://promisesaplus.com/#point-57
|
|
// Re-resolve promises immediately to dodge false rejection from
|
|
// subsequent errors
|
|
if ( depth ) {
|
|
process();
|
|
} else {
|
|
|
|
// Call an optional hook to record the stack, in case of exception
|
|
// since it's otherwise lost when execution goes async
|
|
if ( jQuery.Deferred.getStackHook ) {
|
|
process.stackTrace = jQuery.Deferred.getStackHook();
|
|
}
|
|
window.setTimeout( process );
|
|
}
|
|
};
|
|
}
|
|
|
|
return jQuery.Deferred( function( newDefer ) {
|
|
|
|
// progress_handlers.add( ... )
|
|
tuples[ 0 ][ 3 ].add(
|
|
resolve(
|
|
0,
|
|
newDefer,
|
|
isFunction( onProgress ) ?
|
|
onProgress :
|
|
Identity,
|
|
newDefer.notifyWith
|
|
)
|
|
);
|
|
|
|
// fulfilled_handlers.add( ... )
|
|
tuples[ 1 ][ 3 ].add(
|
|
resolve(
|
|
0,
|
|
newDefer,
|
|
isFunction( onFulfilled ) ?
|
|
onFulfilled :
|
|
Identity
|
|
)
|
|
);
|
|
|
|
// rejected_handlers.add( ... )
|
|
tuples[ 2 ][ 3 ].add(
|
|
resolve(
|
|
0,
|
|
newDefer,
|
|
isFunction( onRejected ) ?
|
|
onRejected :
|
|
Thrower
|
|
)
|
|
);
|
|
} ).promise();
|
|
},
|
|
|
|
// Get a promise for this deferred
|
|
// If obj is provided, the promise aspect is added to the object
|
|
promise: function( obj ) {
|
|
return obj != null ? jQuery.extend( obj, promise ) : promise;
|
|
}
|
|
},
|
|
deferred = {};
|
|
|
|
// Add list-specific methods
|
|
jQuery.each( tuples, function( i, tuple ) {
|
|
var list = tuple[ 2 ],
|
|
stateString = tuple[ 5 ];
|
|
|
|
// promise.progress = list.add
|
|
// promise.done = list.add
|
|
// promise.fail = list.add
|
|
promise[ tuple[ 1 ] ] = list.add;
|
|
|
|
// Handle state
|
|
if ( stateString ) {
|
|
list.add(
|
|
function() {
|
|
|
|
// state = "resolved" (i.e., fulfilled)
|
|
// state = "rejected"
|
|
state = stateString;
|
|
},
|
|
|
|
// rejected_callbacks.disable
|
|
// fulfilled_callbacks.disable
|
|
tuples[ 3 - i ][ 2 ].disable,
|
|
|
|
// rejected_handlers.disable
|
|
// fulfilled_handlers.disable
|
|
tuples[ 3 - i ][ 3 ].disable,
|
|
|
|
// progress_callbacks.lock
|
|
tuples[ 0 ][ 2 ].lock,
|
|
|
|
// progress_handlers.lock
|
|
tuples[ 0 ][ 3 ].lock
|
|
);
|
|
}
|
|
|
|
// progress_handlers.fire
|
|
// fulfilled_handlers.fire
|
|
// rejected_handlers.fire
|
|
list.add( tuple[ 3 ].fire );
|
|
|
|
// deferred.notify = function() { deferred.notifyWith(...) }
|
|
// deferred.resolve = function() { deferred.resolveWith(...) }
|
|
// deferred.reject = function() { deferred.rejectWith(...) }
|
|
deferred[ tuple[ 0 ] ] = function() {
|
|
deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
|
|
return this;
|
|
};
|
|
|
|
// deferred.notifyWith = list.fireWith
|
|
// deferred.resolveWith = list.fireWith
|
|
// deferred.rejectWith = list.fireWith
|
|
deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
|
|
} );
|
|
|
|
// Make the deferred a promise
|
|
promise.promise( deferred );
|
|
|
|
// Call given func if any
|
|
if ( func ) {
|
|
func.call( deferred, deferred );
|
|
}
|
|
|
|
// All done!
|
|
return deferred;
|
|
},
|
|
|
|
// Deferred helper
|
|
when: function( singleValue ) {
|
|
var
|
|
|
|
// count of uncompleted subordinates
|
|
remaining = arguments.length,
|
|
|
|
// count of unprocessed arguments
|
|
i = remaining,
|
|
|
|
// subordinate fulfillment data
|
|
resolveContexts = Array( i ),
|
|
resolveValues = slice.call( arguments ),
|
|
|
|
// the master Deferred
|
|
master = jQuery.Deferred(),
|
|
|
|
// subordinate callback factory
|
|
updateFunc = function( i ) {
|
|
return function( value ) {
|
|
resolveContexts[ i ] = this;
|
|
resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
|
|
if ( !( --remaining ) ) {
|
|
master.resolveWith( resolveContexts, resolveValues );
|
|
}
|
|
};
|
|
};
|
|
|
|
// Single- and empty arguments are adopted like Promise.resolve
|
|
if ( remaining <= 1 ) {
|
|
adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
|
|
!remaining );
|
|
|
|
// Use .then() to unwrap secondary thenables (cf. gh-3000)
|
|
if ( master.state() === "pending" ||
|
|
isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
|
|
|
|
return master.then();
|
|
}
|
|
}
|
|
|
|
// Multiple arguments are aggregated like Promise.all array elements
|
|
while ( i-- ) {
|
|
adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
|
|
}
|
|
|
|
return master.promise();
|
|
}
|
|
} );
|
|
|
|
|
|
// These usually indicate a programmer mistake during development,
|
|
// warn about them ASAP rather than swallowing them by default.
|
|
var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
|
|
|
|
jQuery.Deferred.exceptionHook = function( error, stack ) {
|
|
|
|
// Support: IE 8 - 9 only
|
|
// Console exists when dev tools are open, which can happen at any time
|
|
if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
|
|
window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
jQuery.readyException = function( error ) {
|
|
window.setTimeout( function() {
|
|
throw error;
|
|
} );
|
|
};
|
|
|
|
|
|
|
|
|
|
// The deferred used on DOM ready
|
|
var readyList = jQuery.Deferred();
|
|
|
|
jQuery.fn.ready = function( fn ) {
|
|
|
|
readyList
|
|
.then( fn )
|
|
|
|
// Wrap jQuery.readyException in a function so that the lookup
|
|
// happens at the time of error handling instead of callback
|
|
// registration.
|
|
.catch( function( error ) {
|
|
jQuery.readyException( error );
|
|
} );
|
|
|
|
return this;
|
|
};
|
|
|
|
jQuery.extend( {
|
|
|
|
// Is the DOM ready to be used? Set to true once it occurs.
|
|
isReady: false,
|
|
|
|
// A counter to track how many items to wait for before
|
|
// the ready event fires. See #6781
|
|
readyWait: 1,
|
|
|
|
// Handle when the DOM is ready
|
|
ready: function( wait ) {
|
|
|
|
// Abort if there are pending holds or we're already ready
|
|
if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
|
|
return;
|
|
}
|
|
|
|
// Remember that the DOM is ready
|
|
jQuery.isReady = true;
|
|
|
|
// If a normal DOM Ready event fired, decrement, and wait if need be
|
|
if ( wait !== true && --jQuery.readyWait > 0 ) {
|
|
return;
|
|
}
|
|
|
|
// If there are functions bound, to execute
|
|
readyList.resolveWith( document, [ jQuery ] );
|
|
}
|
|
} );
|
|
|
|
jQuery.ready.then = readyList.then;
|
|
|
|
// The ready event handler and self cleanup method
|
|
function completed() {
|
|
document.removeEventListener( "DOMContentLoaded", completed );
|
|
window.removeEventListener( "load", completed );
|
|
jQuery.ready();
|
|
}
|
|
|
|
// Catch cases where $(document).ready() is called
|
|
// after the browser event has already occurred.
|
|
// Support: IE <=9 - 10 only
|
|
// Older IE sometimes signals "interactive" too soon
|
|
if ( document.readyState === "complete" ||
|
|
( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
|
|
|
|
// Handle it asynchronously to allow scripts the opportunity to delay ready
|
|
window.setTimeout( jQuery.ready );
|
|
|
|
} else {
|
|
|
|
// Use the handy event callback
|
|
document.addEventListener( "DOMContentLoaded", completed );
|
|
|
|
// A fallback to window.onload, that will always work
|
|
window.addEventListener( "load", completed );
|
|
}
|
|
|
|
|
|
|
|
|
|
// Multifunctional method to get and set values of a collection
|
|
// The value/s can optionally be executed if it's a function
|
|
var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
|
|
var i = 0,
|
|
len = elems.length,
|
|
bulk = key == null;
|
|
|
|
// Sets many values
|
|
if ( toType( key ) === "object" ) {
|
|
chainable = true;
|
|
for ( i in key ) {
|
|
access( elems, fn, i, key[ i ], true, emptyGet, raw );
|
|
}
|
|
|
|
// Sets one value
|
|
} else if ( value !== undefined ) {
|
|
chainable = true;
|
|
|
|
if ( !isFunction( value ) ) {
|
|
raw = true;
|
|
}
|
|
|
|
if ( bulk ) {
|
|
|
|
// Bulk operations run against the entire set
|
|
if ( raw ) {
|
|
fn.call( elems, value );
|
|
fn = null;
|
|
|
|
// ...except when executing function values
|
|
} else {
|
|
bulk = fn;
|
|
fn = function( elem, _key, value ) {
|
|
return bulk.call( jQuery( elem ), value );
|
|
};
|
|
}
|
|
}
|
|
|
|
if ( fn ) {
|
|
for ( ; i < len; i++ ) {
|
|
fn(
|
|
elems[ i ], key, raw ?
|
|
value :
|
|
value.call( elems[ i ], i, fn( elems[ i ], key ) )
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( chainable ) {
|
|
return elems;
|
|
}
|
|
|
|
// Gets
|
|
if ( bulk ) {
|
|
return fn.call( elems );
|
|
}
|
|
|
|
return len ? fn( elems[ 0 ], key ) : emptyGet;
|
|
};
|
|
|
|
|
|
// Matches dashed string for camelizing
|
|
var rmsPrefix = /^-ms-/,
|
|
rdashAlpha = /-([a-z])/g;
|
|
|
|
// Used by camelCase as callback to replace()
|
|
function fcamelCase( _all, letter ) {
|
|
return letter.toUpperCase();
|
|
}
|
|
|
|
// Convert dashed to camelCase; used by the css and data modules
|
|
// Support: IE <=9 - 11, Edge 12 - 15
|
|
// Microsoft forgot to hump their vendor prefix (#9572)
|
|
function camelCase( string ) {
|
|
return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
|
|
}
|
|
var acceptData = function( owner ) {
|
|
|
|
// Accepts only:
|
|
// - Node
|
|
// - Node.ELEMENT_NODE
|
|
// - Node.DOCUMENT_NODE
|
|
// - Object
|
|
// - Any
|
|
return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
|
|
};
|
|
|
|
|
|
|
|
|
|
function Data() {
|
|
this.expando = jQuery.expando + Data.uid++;
|
|
}
|
|
|
|
Data.uid = 1;
|
|
|
|
Data.prototype = {
|
|
|
|
cache: function( owner ) {
|
|
|
|
// Check if the owner object already has a cache
|
|
var value = owner[ this.expando ];
|
|
|
|
// If not, create one
|
|
if ( !value ) {
|
|
value = {};
|
|
|
|
// We can accept data for non-element nodes in modern browsers,
|
|
// but we should not, see #8335.
|
|
// Always return an empty object.
|
|
if ( acceptData( owner ) ) {
|
|
|
|
// If it is a node unlikely to be stringify-ed or looped over
|
|
// use plain assignment
|
|
if ( owner.nodeType ) {
|
|
owner[ this.expando ] = value;
|
|
|
|
// Otherwise secure it in a non-enumerable property
|
|
// configurable must be true to allow the property to be
|
|
// deleted when data is removed
|
|
} else {
|
|
Object.defineProperty( owner, this.expando, {
|
|
value: value,
|
|
configurable: true
|
|
} );
|
|
}
|
|
}
|
|
}
|
|
|
|
return value;
|
|
},
|
|
set: function( owner, data, value ) {
|
|
var prop,
|
|
cache = this.cache( owner );
|
|
|
|
// Handle: [ owner, key, value ] args
|
|
// Always use camelCase key (gh-2257)
|
|
if ( typeof data === "string" ) {
|
|
cache[ camelCase( data ) ] = value;
|
|
|
|
// Handle: [ owner, { properties } ] args
|
|
} else {
|
|
|
|
// Copy the properties one-by-one to the cache object
|
|
for ( prop in data ) {
|
|
cache[ camelCase( prop ) ] = data[ prop ];
|
|
}
|
|
}
|
|
return cache;
|
|
},
|
|
get: function( owner, key ) {
|
|
return key === undefined ?
|
|
this.cache( owner ) :
|
|
|
|
// Always use camelCase key (gh-2257)
|
|
owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
|
|
},
|
|
access: function( owner, key, value ) {
|
|
|
|
// In cases where either:
|
|
//
|
|
// 1. No key was specified
|
|
// 2. A string key was specified, but no value provided
|
|
//
|
|
// Take the "read" path and allow the get method to determine
|
|
// which value to return, respectively either:
|
|
//
|
|
// 1. The entire cache object
|
|
// 2. The data stored at the key
|
|
//
|
|
if ( key === undefined ||
|
|
( ( key && typeof key === "string" ) && value === undefined ) ) {
|
|
|
|
return this.get( owner, key );
|
|
}
|
|
|
|
// When the key is not a string, or both a key and value
|
|
// are specified, set or extend (existing objects) with either:
|
|
//
|
|
// 1. An object of properties
|
|
// 2. A key and value
|
|
//
|
|
this.set( owner, key, value );
|
|
|
|
// Since the "set" path can have two possible entry points
|
|
// return the expected data based on which path was taken[*]
|
|
return value !== undefined ? value : key;
|
|
},
|
|
remove: function( owner, key ) {
|
|
var i,
|
|
cache = owner[ this.expando ];
|
|
|
|
if ( cache === undefined ) {
|
|
return;
|
|
}
|
|
|
|
if ( key !== undefined ) {
|
|
|
|
// Support array or space separated string of keys
|
|
if ( Array.isArray( key ) ) {
|
|
|
|
// If key is an array of keys...
|
|
// We always set camelCase keys, so remove that.
|
|
key = key.map( camelCase );
|
|
} else {
|
|
key = camelCase( key );
|
|
|
|
// If a key with the spaces exists, use it.
|
|
// Otherwise, create an array by matching non-whitespace
|
|
key = key in cache ?
|
|
[ key ] :
|
|
( key.match( rnothtmlwhite ) || [] );
|
|
}
|
|
|
|
i = key.length;
|
|
|
|
while ( i-- ) {
|
|
delete cache[ key[ i ] ];
|
|
}
|
|
}
|
|
|
|
// Remove the expando if there's no more data
|
|
if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
|
|
|
|
// Support: Chrome <=35 - 45
|
|
// Webkit & Blink performance suffers when deleting properties
|
|
// from DOM nodes, so set to undefined instead
|
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
|
|
if ( owner.nodeType ) {
|
|
owner[ this.expando ] = undefined;
|
|
} else {
|
|
delete owner[ this.expando ];
|
|
}
|
|
}
|
|
},
|
|
hasData: function( owner ) {
|
|
var cache = owner[ this.expando ];
|
|
return cache !== undefined && !jQuery.isEmptyObject( cache );
|
|
}
|
|
};
|
|
var dataPriv = new Data();
|
|
|
|
var dataUser = new Data();
|
|
|
|
|
|
|
|
// Implementation Summary
|
|
//
|
|
// 1. Enforce API surface and semantic compatibility with 1.9.x branch
|
|
// 2. Improve the module's maintainability by reducing the storage
|
|
// paths to a single mechanism.
|
|
// 3. Use the same single mechanism to support "private" and "user" data.
|
|
// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
|
|
// 5. Avoid exposing implementation details on user objects (eg. expando properties)
|
|
// 6. Provide a clear path for implementation upgrade to WeakMap in 2014
|
|
|
|
var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
|
|
rmultiDash = /[A-Z]/g;
|
|
|
|
function getData( data ) {
|
|
if ( data === "true" ) {
|
|
return true;
|
|
}
|
|
|
|
if ( data === "false" ) {
|
|
return false;
|
|
}
|
|
|
|
if ( data === "null" ) {
|
|
return null;
|
|
}
|
|
|
|
// Only convert to a number if it doesn't change the string
|
|
if ( data === +data + "" ) {
|
|
return +data;
|
|
}
|
|
|
|
if ( rbrace.test( data ) ) {
|
|
return JSON.parse( data );
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
function dataAttr( elem, key, data ) {
|
|
var name;
|
|
|
|
// If nothing was found internally, try to fetch any
|
|
// data from the HTML5 data-* attribute
|
|
if ( data === undefined && elem.nodeType === 1 ) {
|
|
name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
|
|
data = elem.getAttribute( name );
|
|
|
|
if ( typeof data === "string" ) {
|
|
try {
|
|
data = getData( data );
|
|
} catch ( e ) {}
|
|
|
|
// Make sure we set the data so it isn't changed later
|
|
dataUser.set( elem, key, data );
|
|
} else {
|
|
data = undefined;
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
|
|
jQuery.extend( {
|
|
hasData: function( elem ) {
|
|
return dataUser.hasData( elem ) || dataPriv.hasData( elem );
|
|
},
|
|
|
|
data: function( elem, name, data ) {
|
|
return dataUser.access( elem, name, data );
|
|
},
|
|
|
|
removeData: function( elem, name ) {
|
|
dataUser.remove( elem, name );
|
|
},
|
|
|
|
// TODO: Now that all calls to _data and _removeData have been replaced
|
|
// with direct calls to dataPriv methods, these can be deprecated.
|
|
_data: function( elem, name, data ) {
|
|
return dataPriv.access( elem, name, data );
|
|
},
|
|
|
|
_removeData: function( elem, name ) {
|
|
dataPriv.remove( elem, name );
|
|
}
|
|
} );
|
|
|
|
jQuery.fn.extend( {
|
|
data: function( key, value ) {
|
|
var i, name, data,
|
|
elem = this[ 0 ],
|
|
attrs = elem && elem.attributes;
|
|
|
|
// Gets all values
|
|
if ( key === undefined ) {
|
|
if ( this.length ) {
|
|
data = dataUser.get( elem );
|
|
|
|
if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
|
|
i = attrs.length;
|
|
while ( i-- ) {
|
|
|
|
// Support: IE 11 only
|
|
// The attrs elements can be null (#14894)
|
|
if ( attrs[ i ] ) {
|
|
name = attrs[ i ].name;
|
|
if ( name.indexOf( "data-" ) === 0 ) {
|
|
name = camelCase( name.slice( 5 ) );
|
|
dataAttr( elem, name, data[ name ] );
|
|
}
|
|
}
|
|
}
|
|
dataPriv.set( elem, "hasDataAttrs", true );
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
// Sets multiple values
|
|
if ( typeof key === "object" ) {
|
|
return this.each( function() {
|
|
dataUser.set( this, key );
|
|
} );
|
|
}
|
|
|
|
return access( this, function( value ) {
|
|
var data;
|
|
|
|
// The calling jQuery object (element matches) is not empty
|
|
// (and therefore has an element appears at this[ 0 ]) and the
|
|
// `value` parameter was not undefined. An empty jQuery object
|
|
// will result in `undefined` for elem = this[ 0 ] which will
|
|
// throw an exception if an attempt to read a data cache is made.
|
|
if ( elem && value === undefined ) {
|
|
|
|
// Attempt to get data from the cache
|
|
// The key will always be camelCased in Data
|
|
data = dataUser.get( elem, key );
|
|
if ( data !== undefined ) {
|
|
return data;
|
|
}
|
|
|
|
// Attempt to "discover" the data in
|
|
// HTML5 custom data-* attrs
|
|
data = dataAttr( elem, key );
|
|
if ( data !== undefined ) {
|
|
return data;
|
|
}
|
|
|
|
// We tried really hard, but the data doesn't exist.
|
|
return;
|
|
}
|
|
|
|
// Set the data...
|
|
this.each( function() {
|
|
|
|
// We always store the camelCased key
|
|
dataUser.set( this, key, value );
|
|
} );
|
|
}, null, value, arguments.length > 1, null, true );
|
|
},
|
|
|
|
removeData: function( key ) {
|
|
return this.each( function() {
|
|
dataUser.remove( this, key );
|
|
} );
|
|
}
|
|
} );
|
|
|
|
|
|
jQuery.extend( {
|
|
queue: function( elem, type, data ) {
|
|
var queue;
|
|
|
|
if ( elem ) {
|
|
type = ( type || "fx" ) + "queue";
|
|
queue = dataPriv.get( elem, type );
|
|
|
|
// Speed up dequeue by getting out quickly if this is just a lookup
|
|
if ( data ) {
|
|
if ( !queue || Array.isArray( data ) ) {
|
|
queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
|
|
} else {
|
|
queue.push( data );
|
|
}
|
|
}
|
|
return queue || [];
|
|
}
|
|
},
|
|
|
|
dequeue: function( elem, type ) {
|
|
type = type || "fx";
|
|
|
|
var queue = jQuery.queue( elem, type ),
|
|
startLength = queue.length,
|
|
fn = queue.shift(),
|
|
hooks = jQuery._queueHooks( elem, type ),
|
|
next = function() {
|
|
jQuery.dequeue( elem, type );
|
|
};
|
|
|
|
// If the fx queue is dequeued, always remove the progress sentinel
|
|
if ( fn === "inprogress" ) {
|
|
fn = queue.shift();
|
|
startLength--;
|
|
}
|
|
|
|
if ( fn ) {
|
|
|
|
// Add a progress sentinel to prevent the fx queue from being
|
|
// automatically dequeued
|
|
if ( type === "fx" ) {
|
|
queue.unshift( "inprogress" );
|
|
}
|
|
|
|
// Clear up the last queue stop function
|
|
delete hooks.stop;
|
|
fn.call( elem, next, hooks );
|
|
}
|
|
|
|
if ( !startLength && hooks ) {
|
|
hooks.empty.fire();
|
|
}
|
|
},
|
|
|
|
// Not public - generate a queueHooks object, or return the current one
|
|
_queueHooks: function( elem, type ) {
|
|
var key = type + "queueHooks";
|
|
return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
|
|
empty: jQuery.Callbacks( "once memory" ).add( function() {
|
|
dataPriv.remove( elem, [ type + "queue", key ] );
|
|
} )
|
|
} );
|
|
}
|
|
} );
|
|
|
|
jQuery.fn.extend( {
|
|
queue: function( type, data ) {
|
|
var setter = 2;
|
|
|
|
if ( typeof type !== "string" ) {
|
|
data = type;
|
|
type = "fx";
|
|
setter--;
|
|
}
|
|
|
|
if ( arguments.length < setter ) {
|
|
return jQuery.queue( this[ 0 ], type );
|
|
}
|
|
|
|
return data === undefined ?
|
|
this :
|
|
this.each( function() {
|
|
var queue = jQuery.queue( this, type, data );
|
|
|
|
// Ensure a hooks for this queue
|
|
jQuery._queueHooks( this, type );
|
|
|
|
if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
|
|
jQuery.dequeue( this, type );
|
|
}
|
|
} );
|
|
},
|
|
dequeue: function( type ) {
|
|
return this.each( function() {
|
|
jQuery.dequeue( this, type );
|
|
} );
|
|
},
|
|
clearQueue: function( type ) {
|
|
return this.queue( type || "fx", [] );
|
|
},
|
|
|
|
// Get a promise resolved when queues of a certain type
|
|
// are emptied (fx is the type by default)
|
|
promise: function( type, obj ) {
|
|
var tmp,
|
|
count = 1,
|
|
defer = jQuery.Deferred(),
|
|
elements = this,
|
|
i = this.length,
|
|
resolve = function() {
|
|
if ( !( --count ) ) {
|
|
defer.resolveWith( elements, [ elements ] );
|
|
}
|
|
};
|
|
|
|
if ( typeof type !== "string" ) {
|
|
obj = type;
|
|
type = undefined;
|
|
}
|
|
type = type || "fx";
|
|
|
|
while ( i-- ) {
|
|
tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
|
|
if ( tmp && tmp.empty ) {
|
|
count++;
|
|
tmp.empty.add( resolve );
|
|
}
|
|
}
|
|
resolve();
|
|
return defer.promise( obj );
|
|
}
|
|
} );
|
|
var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
|
|
|
|
var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
|
|
|
|
|
|
var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
|
|
|
|
var documentElement = document.documentElement;
|
|
|
|
|
|
|
|
var isAttached = function( elem ) {
|
|
return jQuery.contains( elem.ownerDocument, elem );
|
|
},
|
|
composed = { composed: true };
|
|
|
|
// Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only
|
|
// Check attachment across shadow DOM boundaries when possible (gh-3504)
|
|
// Support: iOS 10.0-10.2 only
|
|
// Early iOS 10 versions support `attachShadow` but not `getRootNode`,
|
|
// leading to errors. We need to check for `getRootNode`.
|
|
if ( documentElement.getRootNode ) {
|
|
isAttached = function( elem ) {
|
|
return jQuery.contains( elem.ownerDocument, elem ) ||
|
|
elem.getRootNode( composed ) === elem.ownerDocument;
|
|
};
|
|
}
|
|
var isHiddenWithinTree = function( elem, el ) {
|
|
|
|
// isHiddenWithinTree might be called from jQuery#filter function;
|
|
// in that case, element will be second argument
|
|
elem = el || elem;
|
|
|
|
// Inline style trumps all
|
|
return elem.style.display === "none" ||
|
|
elem.style.display === "" &&
|
|
|
|
// Otherwise, check computed style
|
|
// Support: Firefox <=43 - 45
|
|
// Disconnected elements can have computed display: none, so first confirm that elem is
|
|
// in the document.
|
|
isAttached( elem ) &&
|
|
|
|
jQuery.css( elem, "display" ) === "none";
|
|
};
|
|
|
|
|
|
|
|
function adjustCSS( elem, prop, valueParts, tween ) {
|
|
var adjusted, scale,
|
|
maxIterations = 20,
|
|
currentValue = tween ?
|
|
function() {
|
|
return tween.cur();
|
|
} :
|
|
function() {
|
|
return jQuery.css( elem, prop, "" );
|
|
},
|
|
initial = currentValue(),
|
|
unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
|
|
|
|
// Starting value computation is required for potential unit mismatches
|
|
initialInUnit = elem.nodeType &&
|
|
( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
|
|
rcssNum.exec( jQuery.css( elem, prop ) );
|
|
|
|
if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
|
|
|
|
// Support: Firefox <=54
|
|
// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)
|
|
initial = initial / 2;
|
|
|
|
// Trust units reported by jQuery.css
|
|
unit = unit || initialInUnit[ 3 ];
|
|
|
|
// Iteratively approximate from a nonzero starting point
|
|
initialInUnit = +initial || 1;
|
|
|
|
while ( maxIterations-- ) {
|
|
|
|
// Evaluate and update our best guess (doubling guesses that zero out).
|
|
// Finish if the scale equals or crosses 1 (making the old*new product non-positive).
|
|
jQuery.style( elem, prop, initialInUnit + unit );
|
|
if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {
|
|
maxIterations = 0;
|
|
}
|
|
initialInUnit = initialInUnit / scale;
|
|
|
|
}
|
|
|
|
initialInUnit = initialInUnit * 2;
|
|
jQuery.style( elem, prop, initialInUnit + unit );
|
|
|
|
// Make sure we update the tween properties later on
|
|
valueParts = valueParts || [];
|
|
}
|
|
|
|
if ( valueParts ) {
|
|
initialInUnit = +initialInUnit || +initial || 0;
|
|
|
|
// Apply relative offset (+=/-=) if specified
|
|
adjusted = valueParts[ 1 ] ?
|
|
initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
|
|
+valueParts[ 2 ];
|
|
if ( tween ) {
|
|
tween.unit = unit;
|
|
tween.start = initialInUnit;
|
|
tween.end = adjusted;
|
|
}
|
|
}
|
|
return adjusted;
|
|
}
|
|
|
|
|
|
var defaultDisplayMap = {};
|
|
|
|
function getDefaultDisplay( elem ) {
|
|
var temp,
|
|
doc = elem.ownerDocument,
|
|
nodeName = elem.nodeName,
|
|
display = defaultDisplayMap[ nodeName ];
|
|
|
|
if ( display ) {
|
|
return display;
|
|
}
|
|
|
|
temp = doc.body.appendChild( doc.createElement( nodeName ) );
|
|
display = jQuery.css( temp, "display" );
|
|
|
|
temp.parentNode.removeChild( temp );
|
|
|
|
if ( display === "none" ) {
|
|
display = "block";
|
|
}
|
|
defaultDisplayMap[ nodeName ] = display;
|
|
|
|
return display;
|
|
}
|
|
|
|
function showHide( elements, show ) {
|
|
var display, elem,
|
|
values = [],
|
|
index = 0,
|
|
length = elements.length;
|
|
|
|
// Determine new display value for elements that need to change
|
|
for ( ; index < length; index++ ) {
|
|
elem = elements[ index ];
|
|
if ( !elem.style ) {
|
|
continue;
|
|
}
|
|
|
|
display = elem.style.display;
|
|
if ( show ) {
|
|
|
|
// Since we force visibility upon cascade-hidden elements, an immediate (and slow)
|
|
// check is required in this first loop unless we have a nonempty display value (either
|
|
// inline or about-to-be-restored)
|
|
if ( display === "none" ) {
|
|
values[ index ] = dataPriv.get( elem, "display" ) || null;
|
|
if ( !values[ index ] ) {
|
|
elem.style.display = "";
|
|
}
|
|
}
|
|
if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
|
|
values[ index ] = getDefaultDisplay( elem );
|
|
}
|
|
} else {
|
|
if ( display !== "none" ) {
|
|
values[ index ] = "none";
|
|
|
|
// Remember what we're overwriting
|
|
dataPriv.set( elem, "display", display );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set the display of the elements in a second loop to avoid constant reflow
|
|
for ( index = 0; index < length; index++ ) {
|
|
if ( values[ index ] != null ) {
|
|
elements[ index ].style.display = values[ index ];
|
|
}
|
|
}
|
|
|
|
return elements;
|
|
}
|
|
|
|
jQuery.fn.extend( {
|
|
show: function() {
|
|
return showHide( this, true );
|
|
},
|
|
hide: function() {
|
|
return showHide( this );
|
|
},
|
|
toggle: function( state ) {
|
|
if ( typeof state === "boolean" ) {
|
|
return state ? this.show() : this.hide();
|
|
}
|
|
|
|
return this.each( function() {
|
|
if ( isHiddenWithinTree( this ) ) {
|
|
jQuery( this ).show();
|
|
} else {
|
|
jQuery( this ).hide();
|
|
}
|
|
} );
|
|
}
|
|
} );
|
|
var rcheckableType = ( /^(?:checkbox|radio)$/i );
|
|
|
|
var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i );
|
|
|
|
var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i );
|
|
|
|
|
|
|
|
( function() {
|
|
var fragment = document.createDocumentFragment(),
|
|
div = fragment.appendChild( document.createElement( "div" ) ),
|
|
input = document.createElement( "input" );
|
|
|
|
// Support: Android 4.0 - 4.3 only
|
|
// Check state lost if the name is set (#11217)
|
|
// Support: Windows Web Apps (WWA)
|
|
// `name` and `type` must use .setAttribute for WWA (#14901)
|
|
input.setAttribute( "type", "radio" );
|
|
input.setAttribute( "checked", "checked" );
|
|
input.setAttribute( "name", "t" );
|
|
|
|
div.appendChild( input );
|
|
|
|
// Support: Android <=4.1 only
|
|
// Older WebKit doesn't clone checked state correctly in fragments
|
|
support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
|
|
|
|
// Support: IE <=11 only
|
|
// Make sure textarea (and checkbox) defaultValue is properly cloned
|
|
div.innerHTML = "<textarea>x</textarea>";
|
|
support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
|
|
|
|
// Support: IE <=9 only
|
|
// IE <=9 replaces <option> tags with their contents when inserted outside of
|
|
// the select element.
|
|
div.innerHTML = "<option></option>";
|
|
support.option = !!div.lastChild;
|
|
} )();
|
|
|
|
|
|
// We have to close these tags to support XHTML (#13200)
|
|
var wrapMap = {
|
|
|
|
// XHTML parsers do not magically insert elements in the
|
|
// same way that tag soup parsers do. So we cannot shorten
|
|
// this by omitting <tbody> or other required elements.
|
|
thead: [ 1, "<table>", "</table>" ],
|
|
col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
|
|
tr: [ 2, "<table><tbody>", "</tbody></table>" ],
|
|
td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
|
|
|
|
_default: [ 0, "", "" ]
|
|
};
|
|
|
|
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
|
|
wrapMap.th = wrapMap.td;
|
|
|
|
// Support: IE <=9 only
|
|
if ( !support.option ) {
|
|
wrapMap.optgroup = wrapMap.option = [ 1, "<select multiple='multiple'>", "</select>" ];
|
|
}
|
|
|
|
|
|
function getAll( context, tag ) {
|
|
|
|
// Support: IE <=9 - 11 only
|
|
// Use typeof to avoid zero-argument method invocation on host objects (#15151)
|
|
var ret;
|
|
|
|
if ( typeof context.getElementsByTagName !== "undefined" ) {
|
|
ret = context.getElementsByTagName( tag || "*" );
|
|
|
|
} else if ( typeof context.querySelectorAll !== "undefined" ) {
|
|
ret = context.querySelectorAll( tag || "*" );
|
|
|
|
} else {
|
|
ret = [];
|
|
}
|
|
|
|
if ( tag === undefined || tag && nodeName( context, tag ) ) {
|
|
return jQuery.merge( [ context ], ret );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
// Mark scripts as having already been evaluated
|
|
function setGlobalEval( elems, refElements ) {
|
|
var i = 0,
|
|
l = elems.length;
|
|
|
|
for ( ; i < l; i++ ) {
|
|
dataPriv.set(
|
|
elems[ i ],
|
|
"globalEval",
|
|
!refElements || dataPriv.get( refElements[ i ], "globalEval" )
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
var rhtml = /<|&#?\w+;/;
|
|
|
|
function buildFragment( elems, context, scripts, selection, ignored ) {
|
|
var elem, tmp, tag, wrap, attached, j,
|
|
fragment = context.createDocumentFragment(),
|
|
nodes = [],
|
|
i = 0,
|
|
l = elems.length;
|
|
|
|
for ( ; i < l; i++ ) {
|
|
elem = elems[ i ];
|
|
|
|
if ( elem || elem === 0 ) {
|
|
|
|
// Add nodes directly
|
|
if ( toType( elem ) === "object" ) {
|
|
|
|
// Support: Android <=4.0 only, PhantomJS 1 only
|
|
// push.apply(_, arraylike) throws on ancient WebKit
|
|
jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
|
|
|
|
// Convert non-html into a text node
|
|
} else if ( !rhtml.test( elem ) ) {
|
|
nodes.push( context.createTextNode( elem ) );
|
|
|
|
// Convert html into DOM nodes
|
|
} else {
|
|
tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
|
|
|
|
// Deserialize a standard representation
|
|
tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
|
|
wrap = wrapMap[ tag ] || wrapMap._default;
|
|
tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
|
|
|
|
// Descend through wrappers to the right content
|
|
j = wrap[ 0 ];
|
|
while ( j-- ) {
|
|
tmp = tmp.lastChild;
|
|
}
|
|
|
|
// Support: Android <=4.0 only, PhantomJS 1 only
|
|
// push.apply(_, arraylike) throws on ancient WebKit
|
|
jQuery.merge( nodes, tmp.childNodes );
|
|
|
|
// Remember the top-level container
|
|
tmp = fragment.firstChild;
|
|
|
|
// Ensure the created nodes are orphaned (#12392)
|
|
tmp.textContent = "";
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove wrapper from fragment
|
|
fragment.textContent = "";
|
|
|
|
i = 0;
|
|
while ( ( elem = nodes[ i++ ] ) ) {
|
|
|
|
// Skip elements already in the context collection (trac-4087)
|
|
if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
|
|
if ( ignored ) {
|
|
ignored.push( elem );
|
|
}
|
|
continue;
|
|
}
|
|
|
|
attached = isAttached( elem );
|
|
|
|
// Append to fragment
|
|
tmp = getAll( fragment.appendChild( elem ), "script" );
|
|
|
|
// Preserve script evaluation history
|
|
if ( attached ) {
|
|
setGlobalEval( tmp );
|
|
}
|
|
|
|
// Capture executables
|
|
if ( scripts ) {
|
|
j = 0;
|
|
while ( ( elem = tmp[ j++ ] ) ) {
|
|
if ( rscriptType.test( elem.type || "" ) ) {
|
|
scripts.push( elem );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return fragment;
|
|
}
|
|
|
|
|
|
var
|
|
rkeyEvent = /^key/,
|
|
rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
|
|
rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
|
|
|
|
function returnTrue() {
|
|
return true;
|
|
}
|
|
|
|
function returnFalse() {
|
|
return false;
|
|
}
|
|
|
|
// Support: IE <=9 - 11+
|
|
// focus() and blur() are asynchronous, except when they are no-op.
|
|
// So expect focus to be synchronous when the element is already active,
|
|
// and blur to be synchronous when the element is not already active.
|
|
// (focus and blur are always synchronous in other supported browsers,
|
|
// this just defines when we can count on it).
|
|
function expectSync( elem, type ) {
|
|
return ( elem === safeActiveElement() ) === ( type === "focus" );
|
|
}
|
|
|
|
// Support: IE <=9 only
|
|
// Accessing document.activeElement can throw unexpectedly
|
|
// https://bugs.jquery.com/ticket/13393
|
|
function safeActiveElement() {
|
|
try {
|
|
return document.activeElement;
|
|
} catch ( err ) { }
|
|
}
|
|
|
|
function on( elem, types, selector, data, fn, one ) {
|
|
var origFn, type;
|
|
|
|
// Types can be a map of types/handlers
|
|
if ( typeof types === "object" ) {
|
|
|
|
// ( types-Object, selector, data )
|
|
if ( typeof selector !== "string" ) {
|
|
|
|
// ( types-Object, data )
|
|
data = data || selector;
|
|
selector = undefined;
|
|
}
|
|
for ( type in types ) {
|
|
on( elem, type, selector, data, types[ type ], one );
|
|
}
|
|
return elem;
|
|
}
|
|
|
|
if ( data == null && fn == null ) {
|
|
|
|
// ( types, fn )
|
|
fn = selector;
|
|
data = selector = undefined;
|
|
} else if ( fn == null ) {
|
|
if ( typeof selector === "string" ) {
|
|
|
|
// ( types, selector, fn )
|
|
fn = data;
|
|
data = undefined;
|
|
} else {
|
|
|
|
// ( types, data, fn )
|
|
fn = data;
|
|
data = selector;
|
|
selector = undefined;
|
|
}
|
|
}
|
|
if ( fn === false ) {
|
|
fn = returnFalse;
|
|
} else if ( !fn ) {
|
|
return elem;
|
|
}
|
|
|
|
if ( one === 1 ) {
|
|
origFn = fn;
|
|
fn = function( event ) {
|
|
|
|
// Can use an empty set, since event contains the info
|
|
jQuery().off( event );
|
|
return origFn.apply( this, arguments );
|
|
};
|
|
|
|
// Use same guid so caller can remove using origFn
|
|
fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
|
|
}
|
|
return elem.each( function() {
|
|
jQuery.event.add( this, types, fn, data, selector );
|
|
} );
|
|
}
|
|
|
|
/*
|
|
* Helper functions for managing events -- not part of the public interface.
|
|
* Props to Dean Edwards' addEvent library for many of the ideas.
|
|
*/
|
|
jQuery.event = {
|
|
|
|
global: {},
|
|
|
|
add: function( elem, types, handler, data, selector ) {
|
|
|
|
var handleObjIn, eventHandle, tmp,
|
|
events, t, handleObj,
|
|
special, handlers, type, namespaces, origType,
|
|
elemData = dataPriv.get( elem );
|
|
|
|
// Only attach events to objects that accept data
|
|
if ( !acceptData( elem ) ) {
|
|
return;
|
|
}
|
|
|
|
// Caller can pass in an object of custom data in lieu of the handler
|
|
if ( handler.handler ) {
|
|
handleObjIn = handler;
|
|
handler = handleObjIn.handler;
|
|
selector = handleObjIn.selector;
|
|
}
|
|
|
|
// Ensure that invalid selectors throw exceptions at attach time
|
|
// Evaluate against documentElement in case elem is a non-element node (e.g., document)
|
|
if ( selector ) {
|
|
jQuery.find.matchesSelector( documentElement, selector );
|
|
}
|
|
|
|
// Make sure that the handler has a unique ID, used to find/remove it later
|
|
if ( !handler.guid ) {
|
|
handler.guid = jQuery.guid++;
|
|
}
|
|
|
|
// Init the element's event structure and main handler, if this is the first
|
|
if ( !( events = elemData.events ) ) {
|
|
events = elemData.events = Object.create( null );
|
|
}
|
|
if ( !( eventHandle = elemData.handle ) ) {
|
|
eventHandle = elemData.handle = function( e ) {
|
|
|
|
// Discard the second event of a jQuery.event.trigger() and
|
|
// when an event is called after a page has unloaded
|
|
return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
|
|
jQuery.event.dispatch.apply( elem, arguments ) : undefined;
|
|
};
|
|
}
|
|
|
|
// Handle multiple events separated by a space
|
|
types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
|
|
t = types.length;
|
|
while ( t-- ) {
|
|
tmp = rtypenamespace.exec( types[ t ] ) || [];
|
|
type = origType = tmp[ 1 ];
|
|
namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
|
|
|
|
// There *must* be a type, no attaching namespace-only handlers
|
|
if ( !type ) {
|
|
continue;
|
|
}
|
|
|
|
// If event changes its type, use the special event handlers for the changed type
|
|
special = jQuery.event.special[ type ] || {};
|
|
|
|
// If selector defined, determine special event api type, otherwise given type
|
|
type = ( selector ? special.delegateType : special.bindType ) || type;
|
|
|
|
// Update special based on newly reset type
|
|
special = jQuery.event.special[ type ] || {};
|
|
|
|
// handleObj is passed to all event handlers
|
|
handleObj = jQuery.extend( {
|
|
type: type,
|
|
origType: origType,
|
|
data: data,
|
|
handler: handler,
|
|
guid: handler.guid,
|
|
selector: selector,
|
|
needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
|
|
namespace: namespaces.join( "." )
|
|
}, handleObjIn );
|
|
|
|
// Init the event handler queue if we're the first
|
|
if ( !( handlers = events[ type ] ) ) {
|
|
handlers = events[ type ] = [];
|
|
handlers.delegateCount = 0;
|
|
|
|
// Only use addEventListener if the special events handler returns false
|
|
if ( !special.setup ||
|
|
special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
|
|
|
|
if ( elem.addEventListener ) {
|
|
elem.addEventListener( type, eventHandle );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( special.add ) {
|
|
special.add.call( elem, handleObj );
|
|
|
|
if ( !handleObj.handler.guid ) {
|
|
handleObj.handler.guid = handler.guid;
|
|
}
|
|
}
|
|
|
|
// Add to the element's handler list, delegates in front
|
|
if ( selector ) {
|
|
handlers.splice( handlers.delegateCount++, 0, handleObj );
|
|
} else {
|
|
handlers.push( handleObj );
|
|
}
|
|
|
|
// Keep track of which events have ever been used, for event optimization
|
|
jQuery.event.global[ type ] = true;
|
|
}
|
|
|
|
},
|
|
|
|
// Detach an event or set of events from an element
|
|
remove: function( elem, types, handler, selector, mappedTypes ) {
|
|
|
|
var j, origCount, tmp,
|
|
events, t, handleObj,
|
|
special, handlers, type, namespaces, origType,
|
|
elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
|
|
|
|
if ( !elemData || !( events = elemData.events ) ) {
|
|
return;
|
|
}
|
|
|
|
// Once for each type.namespace in types; type may be omitted
|
|
types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
|
|
t = types.length;
|
|
while ( t-- ) {
|
|
tmp = rtypenamespace.exec( types[ t ] ) || [];
|
|
type = origType = tmp[ 1 ];
|
|
namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
|
|
|
|
// Unbind all events (on this namespace, if provided) for the element
|
|
if ( !type ) {
|
|
for ( type in events ) {
|
|
jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
|
|
}
|
|
continue;
|
|
}
|
|
|
|
special = jQuery.event.special[ type ] || {};
|
|
type = ( selector ? special.delegateType : special.bindType ) || type;
|
|
handlers = events[ type ] || [];
|
|
tmp = tmp[ 2 ] &&
|
|
new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
|
|
|
|
// Remove matching events
|
|
origCount = j = handlers.length;
|
|
while ( j-- ) {
|
|
handleObj = handlers[ j ];
|
|
|
|
if ( ( mappedTypes || origType === handleObj.origType ) &&
|
|
( !handler || handler.guid === handleObj.guid ) &&
|
|
( !tmp || tmp.test( handleObj.namespace ) ) &&
|
|
( !selector || selector === handleObj.selector ||
|
|
selector === "**" && handleObj.selector ) ) {
|
|
handlers.splice( j, 1 );
|
|
|
|
if ( handleObj.selector ) {
|
|
handlers.delegateCount--;
|
|
}
|
|
if ( special.remove ) {
|
|
special.remove.call( elem, handleObj );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove generic event handler if we removed something and no more handlers exist
|
|
// (avoids potential for endless recursion during removal of special event handlers)
|
|
if ( origCount && !handlers.length ) {
|
|
if ( !special.teardown ||
|
|
special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
|
|
|
|
jQuery.removeEvent( elem, type, elemData.handle );
|
|
}
|
|
|
|
delete events[ type ];
|
|
}
|
|
}
|
|
|
|
// Remove data and the expando if it's no longer used
|
|
if ( jQuery.isEmptyObject( events ) ) {
|
|
dataPriv.remove( elem, "handle events" );
|
|
}
|
|
},
|
|
|
|
dispatch: function( nativeEvent ) {
|
|
|
|
var i, j, ret, matched, handleObj, handlerQueue,
|
|
args = new Array( arguments.length ),
|
|
|
|
// Make a writable jQuery.Event from the native event object
|
|
event = jQuery.event.fix( nativeEvent ),
|
|
|
|
handlers = (
|
|
dataPriv.get( this, "events" ) || Object.create( null )
|
|
)[ event.type ] || [],
|
|
special = jQuery.event.special[ event.type ] || {};
|
|
|
|
// Use the fix-ed jQuery.Event rather than the (read-only) native event
|
|
args[ 0 ] = event;
|
|
|
|
for ( i = 1; i < arguments.length; i++ ) {
|
|
args[ i ] = arguments[ i ];
|
|
}
|
|
|
|
event.delegateTarget = this;
|
|
|
|
// Call the preDispatch hook for the mapped type, and let it bail if desired
|
|
if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
|
|
return;
|
|
}
|
|
|
|
// Determine handlers
|
|
handlerQueue = jQuery.event.handlers.call( this, event, handlers );
|
|
|
|
// Run delegates first; they may want to stop propagation beneath us
|
|
i = 0;
|
|
while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
|
|
event.currentTarget = matched.elem;
|
|
|
|
j = 0;
|
|
while ( ( handleObj = matched.handlers[ j++ ] ) &&
|
|
!event.isImmediatePropagationStopped() ) {
|
|
|
|
// If the event is namespaced, then each handler is only invoked if it is
|
|
// specially universal or its namespaces are a superset of the event's.
|
|
if ( !event.rnamespace || handleObj.namespace === false ||
|
|
event.rnamespace.test( handleObj.namespace ) ) {
|
|
|
|
event.handleObj = handleObj;
|
|
event.data = handleObj.data;
|
|
|
|
ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
|
|
handleObj.handler ).apply( matched.elem, args );
|
|
|
|
if ( ret !== undefined ) {
|
|
if ( ( event.result = ret ) === false ) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Call the postDispatch hook for the mapped type
|
|
if ( special.postDispatch ) {
|
|
special.postDispatch.call( this, event );
|
|
}
|
|
|
|
return event.result;
|
|
},
|
|
|
|
handlers: function( event, handlers ) {
|
|
var i, handleObj, sel, matchedHandlers, matchedSelectors,
|
|
handlerQueue = [],
|
|
delegateCount = handlers.delegateCount,
|
|
cur = event.target;
|
|
|
|
// Find delegate handlers
|
|
if ( delegateCount &&
|
|
|
|
// Support: IE <=9
|
|
// Black-hole SVG <use> instance trees (trac-13180)
|
|
cur.nodeType &&
|
|
|
|
// Support: Firefox <=42
|
|
// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
|
|
// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
|
|
// Support: IE 11 only
|
|
// ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
|
|
!( event.type === "click" && event.button >= 1 ) ) {
|
|
|
|
for ( ; cur !== this; cur = cur.parentNode || this ) {
|
|
|
|
// Don't check non-elements (#13208)
|
|
// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
|
|
if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
|
|
matchedHandlers = [];
|
|
matchedSelectors = {};
|
|
for ( i = 0; i < delegateCount; i++ ) {
|
|
handleObj = handlers[ i ];
|
|
|
|
// Don't conflict with Object.prototype properties (#13203)
|
|
sel = handleObj.selector + " ";
|
|
|
|
if ( matchedSelectors[ sel ] === undefined ) {
|
|
matchedSelectors[ sel ] = handleObj.needsContext ?
|
|
jQuery( sel, this ).index( cur ) > -1 :
|
|
jQuery.find( sel, this, null, [ cur ] ).length;
|
|
}
|
|
if ( matchedSelectors[ sel ] ) {
|
|
matchedHandlers.push( handleObj );
|
|
}
|
|
}
|
|
if ( matchedHandlers.length ) {
|
|
handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add the remaining (directly-bound) handlers
|
|
cur = this;
|
|
if ( delegateCount < handlers.length ) {
|
|
handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
|
|
}
|
|
|
|
return handlerQueue;
|
|
},
|
|
|
|
addProp: function( name, hook ) {
|
|
Object.defineProperty( jQuery.Event.prototype, name, {
|
|
enumerable: true,
|
|
configurable: true,
|
|
|
|
get: isFunction( hook ) ?
|
|
function() {
|
|
if ( this.originalEvent ) {
|
|
return hook( this.originalEvent );
|
|
}
|
|
} :
|
|
function() {
|
|
if ( this.originalEvent ) {
|
|
return this.originalEvent[ name ];
|
|
}
|
|
},
|
|
|
|
set: function( value ) {
|
|
Object.defineProperty( this, name, {
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true,
|
|
value: value
|
|
} );
|
|
}
|
|
} );
|
|
},
|
|
|
|
fix: function( originalEvent ) {
|
|
return originalEvent[ jQuery.expando ] ?
|
|
originalEvent :
|
|
new jQuery.Event( originalEvent );
|
|
},
|
|
|
|
special: {
|
|
load: {
|
|
|
|
// Prevent triggered image.load events from bubbling to window.load
|
|
noBubble: true
|
|
},
|
|
click: {
|
|
|
|
// Utilize native event to ensure correct state for checkable inputs
|
|
setup: function( data ) {
|
|
|
|
// For mutual compressibility with _default, replace `this` access with a local var.
|
|
// `|| data` is dead code meant only to preserve the variable through minification.
|
|
var el = this || data;
|
|
|
|
// Claim the first handler
|
|
if ( rcheckableType.test( el.type ) &&
|
|
el.click && nodeName( el, "input" ) ) {
|
|
|
|
// dataPriv.set( el, "click", ... )
|
|
leverageNative( el, "click", returnTrue );
|
|
}
|
|
|
|
// Return false to allow normal processing in the caller
|
|
return false;
|
|
},
|
|
trigger: function( data ) {
|
|
|
|
// For mutual compressibility with _default, replace `this` access with a local var.
|
|
// `|| data` is dead code meant only to preserve the variable through minification.
|
|
var el = this || data;
|
|
|
|
// Force setup before triggering a click
|
|
if ( rcheckableType.test( el.type ) &&
|
|
el.click && nodeName( el, "input" ) ) {
|
|
|
|
leverageNative( el, "click" );
|
|
}
|
|
|
|
// Return non-false to allow normal event-path propagation
|
|
return true;
|
|
},
|
|
|
|
// For cross-browser consistency, suppress native .click() on links
|
|
// Also prevent it if we're currently inside a leveraged native-event stack
|
|
_default: function( event ) {
|
|
var target = event.target;
|
|
return rcheckableType.test( target.type ) &&
|
|
target.click && nodeName( target, "input" ) &&
|
|
dataPriv.get( target, "click" ) ||
|
|
nodeName( target, "a" );
|
|
}
|
|
},
|
|
|
|
beforeunload: {
|
|
postDispatch: function( event ) {
|
|
|
|
// Support: Firefox 20+
|
|
// Firefox doesn't alert if the returnValue field is not set.
|
|
if ( event.result !== undefined && event.originalEvent ) {
|
|
event.originalEvent.returnValue = event.result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Ensure the presence of an event listener that handles manually-triggered
|
|
// synthetic events by interrupting progress until reinvoked in response to
|
|
// *native* events that it fires directly, ensuring that state changes have
|
|
// already occurred before other listeners are invoked.
|
|
function leverageNative( el, type, expectSync ) {
|
|
|
|
// Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add
|
|
if ( !expectSync ) {
|
|
if ( dataPriv.get( el, type ) === undefined ) {
|
|
jQuery.event.add( el, type, returnTrue );
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Register the controller as a special universal handler for all event namespaces
|
|
dataPriv.set( el, type, false );
|
|
jQuery.event.add( el, type, {
|
|
namespace: false,
|
|
handler: function( event ) {
|
|
var notAsync, result,
|
|
saved = dataPriv.get( this, type );
|
|
|
|
if ( ( event.isTrigger & 1 ) && this[ type ] ) {
|
|
|
|
// Interrupt processing of the outer synthetic .trigger()ed event
|
|
// Saved data should be false in such cases, but might be a leftover capture object
|
|
// from an async native handler (gh-4350)
|
|
if ( !saved.length ) {
|
|
|
|
// Store arguments for use when handling the inner native event
|
|
// There will always be at least one argument (an event object), so this array
|
|
// will not be confused with a leftover capture object.
|
|
saved = slice.call( arguments );
|
|
dataPriv.set( this, type, saved );
|
|
|
|
// Trigger the native event and capture its result
|
|
// Support: IE <=9 - 11+
|
|
// focus() and blur() are asynchronous
|
|
notAsync = expectSync( this, type );
|
|
this[ type ]();
|
|
result = dataPriv.get( this, type );
|
|
if ( saved !== result || notAsync ) {
|
|
dataPriv.set( this, type, false );
|
|
} else {
|
|
result = {};
|
|
}
|
|
if ( saved !== result ) {
|
|
|
|
// Cancel the outer synthetic event
|
|
event.stopImmediatePropagation();
|
|
event.preventDefault();
|
|
return result.value;
|
|
}
|
|
|
|
// If this is an inner synthetic event for an event with a bubbling surrogate
|
|
// (focus or blur), assume that the surrogate already propagated from triggering the
|
|
// native event and prevent that from happening again here.
|
|
// This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
|
|
// bubbling surrogate propagates *after* the non-bubbling base), but that seems
|
|
// less bad than duplication.
|
|
} else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
|
|
event.stopPropagation();
|
|
}
|
|
|
|
// If this is a native event triggered above, everything is now in order
|
|
// Fire an inner synthetic event with the original arguments
|
|
} else if ( saved.length ) {
|
|
|
|
// ...and capture the result
|
|
dataPriv.set( this, type, {
|
|
value: jQuery.event.trigger(
|
|
|
|
// Support: IE <=9 - 11+
|
|
// Extend with the prototype to reset the above stopImmediatePropagation()
|
|
jQuery.extend( saved[ 0 ], jQuery.Event.prototype ),
|
|
saved.slice( 1 ),
|
|
this
|
|
)
|
|
} );
|
|
|
|
// Abort handling of the native event
|
|
event.stopImmediatePropagation();
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
|
|
jQuery.removeEvent = function( elem, type, handle ) {
|
|
|
|
// This "if" is needed for plain objects
|
|
if ( elem.removeEventListener ) {
|
|
elem.removeEventListener( type, handle );
|
|
}
|
|
};
|
|
|
|
jQuery.Event = function( src, props ) {
|
|
|
|
// Allow instantiation without the 'new' keyword
|
|
if ( !( this instanceof jQuery.Event ) ) {
|
|
return new jQuery.Event( src, props );
|
|
}
|
|
|
|
// Event object
|
|
if ( src && src.type ) {
|
|
this.originalEvent = src;
|
|
this.type = src.type;
|
|
|
|
// Events bubbling up the document may have been marked as prevented
|
|
// by a handler lower down the tree; reflect the correct value.
|
|
this.isDefaultPrevented = src.defaultPrevented ||
|
|
src.defaultPrevented === undefined &&
|
|
|
|
// Support: Android <=2.3 only
|
|
src.returnValue === false ?
|
|
returnTrue :
|
|
returnFalse;
|
|
|
|
// Create target properties
|
|
// Support: Safari <=6 - 7 only
|
|
// Target should not be a text node (#504, #13143)
|
|
this.target = ( src.target && src.target.nodeType === 3 ) ?
|
|
src.target.parentNode :
|
|
src.target;
|
|
|
|
this.currentTarget = src.currentTarget;
|
|
this.relatedTarget = src.relatedTarget;
|
|
|
|
// Event type
|
|
} else {
|
|
this.type = src;
|
|
}
|
|
|
|
// Put explicitly provided properties onto the event object
|
|
if ( props ) {
|
|
jQuery.extend( this, props );
|
|
}
|
|
|
|
// Create a timestamp if incoming event doesn't have one
|
|
this.timeStamp = src && src.timeStamp || Date.now();
|
|
|
|
// Mark it as fixed
|
|
this[ jQuery.expando ] = true;
|
|
};
|
|
|
|
// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
|
|
// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
|
|
jQuery.Event.prototype = {
|
|
constructor: jQuery.Event,
|
|
isDefaultPrevented: returnFalse,
|
|
isPropagationStopped: returnFalse,
|
|
isImmediatePropagationStopped: returnFalse,
|
|
isSimulated: false,
|
|
|
|
preventDefault: function() {
|
|
var e = this.originalEvent;
|
|
|
|
this.isDefaultPrevented = returnTrue;
|
|
|
|
if ( e && !this.isSimulated ) {
|
|
e.preventDefault();
|
|
}
|
|
},
|
|
stopPropagation: function() {
|
|
var e = this.originalEvent;
|
|
|
|
this.isPropagationStopped = returnTrue;
|
|
|
|
if ( e && !this.isSimulated ) {
|
|
e.stopPropagation();
|
|
}
|
|
},
|
|
stopImmediatePropagation: function() {
|
|
var e = this.originalEvent;
|
|
|
|
this.isImmediatePropagationStopped = returnTrue;
|
|
|
|
if ( e && !this.isSimulated ) {
|
|
e.stopImmediatePropagation();
|
|
}
|
|
|
|
this.stopPropagation();
|
|
}
|
|
};
|
|
|
|
// Includes all common event props including KeyEvent and MouseEvent specific props
|
|
jQuery.each( {
|
|
altKey: true,
|
|
bubbles: true,
|
|
cancelable: true,
|
|
changedTouches: true,
|
|
ctrlKey: true,
|
|
detail: true,
|
|
eventPhase: true,
|
|
metaKey: true,
|
|
pageX: true,
|
|
pageY: true,
|
|
shiftKey: true,
|
|
view: true,
|
|
"char": true,
|
|
code: true,
|
|
charCode: true,
|
|
key: true,
|
|
keyCode: true,
|
|
button: true,
|
|
buttons: true,
|
|
clientX: true,
|
|
clientY: true,
|
|
offsetX: true,
|
|
offsetY: true,
|
|
pointerId: true,
|
|
pointerType: true,
|
|
screenX: true,
|
|
screenY: true,
|
|
targetTouches: true,
|
|
toElement: true,
|
|
touches: true,
|
|
|
|
which: function( event ) {
|
|
var button = event.button;
|
|
|
|
// Add which for key events
|
|
if ( event.which == null && rkeyEvent.test( event.type ) ) {
|
|
return event.charCode != null ? event.charCode : event.keyCode;
|
|
}
|
|
|
|
// Add which for click: 1 === left; 2 === middle; 3 === right
|
|
if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
|
|
if ( button & 1 ) {
|
|
return 1;
|
|
}
|
|
|
|
if ( button & 2 ) {
|
|
return 3;
|
|
}
|
|
|
|
if ( button & 4 ) {
|
|
return 2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return event.which;
|
|
}
|
|
}, jQuery.event.addProp );
|
|
|
|
jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) {
|
|
jQuery.event.special[ type ] = {
|
|
|
|
// Utilize native event if possible so blur/focus sequence is correct
|
|
setup: function() {
|
|
|
|
// Claim the first handler
|
|
// dataPriv.set( this, "focus", ... )
|
|
// dataPriv.set( this, "blur", ... )
|
|
leverageNative( this, type, expectSync );
|
|
|
|
// Return false to allow normal processing in the caller
|
|
return false;
|
|
},
|
|
trigger: function() {
|
|
|
|
// Force setup before trigger
|
|
leverageNative( this, type );
|
|
|
|
// Return non-false to allow normal event-path propagation
|
|
return true;
|
|
},
|
|
|
|
delegateType: delegateType
|
|
};
|
|
} );
|
|
|
|
// Create mouseenter/leave events using mouseover/out and event-time checks
|
|
// so that event delegation works in jQuery.
|
|
// Do the same for pointerenter/pointerleave and pointerover/pointerout
|
|
//
|
|
// Support: Safari 7 only
|
|
// Safari sends mouseenter too often; see:
|
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
|
|
// for the description of the bug (it existed in older Chrome versions as well).
|
|
jQuery.each( {
|
|
mouseenter: "mouseover",
|
|
mouseleave: "mouseout",
|
|
pointerenter: "pointerover",
|
|
pointerleave: "pointerout"
|
|
}, function( orig, fix ) {
|
|
jQuery.event.special[ orig ] = {
|
|
delegateType: fix,
|
|
bindType: fix,
|
|
|
|
handle: function( event ) {
|
|
var ret,
|
|
target = this,
|
|
related = event.relatedTarget,
|
|
handleObj = event.handleObj;
|
|
|
|
// For mouseenter/leave call the handler if related is outside the target.
|
|
// NB: No relatedTarget if the mouse left/entered the browser window
|
|
if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
|
|
event.type = handleObj.origType;
|
|
ret = handleObj.handler.apply( this, arguments );
|
|
event.type = fix;
|
|
}
|
|
return ret;
|
|
}
|
|
};
|
|
} );
|
|
|
|
jQuery.fn.extend( {
|
|
|
|
on: function( types, selector, data, fn ) {
|
|
return on( this, types, selector, data, fn );
|
|
},
|
|
one: function( types, selector, data, fn ) {
|
|
return on( this, types, selector, data, fn, 1 );
|
|
},
|
|
off: function( types, selector, fn ) {
|
|
var handleObj, type;
|
|
if ( types && types.preventDefault && types.handleObj ) {
|
|
|
|
// ( event ) dispatched jQuery.Event
|
|
handleObj = types.handleObj;
|
|
jQuery( types.delegateTarget ).off(
|
|
handleObj.namespace ?
|
|
handleObj.origType + "." + handleObj.namespace :
|
|
handleObj.origType,
|
|
handleObj.selector,
|
|
handleObj.handler
|
|
);
|
|
return this;
|
|
}
|
|
if ( typeof types === "object" ) {
|
|
|
|
// ( types-object [, selector] )
|
|
for ( type in types ) {
|
|
this.off( type, selector, types[ type ] );
|
|
}
|
|
return this;
|
|
}
|
|
if ( selector === false || typeof selector === "function" ) {
|
|
|
|
// ( types [, fn] )
|
|
fn = selector;
|
|
selector = undefined;
|
|
}
|
|
if ( fn === false ) {
|
|
fn = returnFalse;
|
|
}
|
|
return this.each( function() {
|
|
jQuery.event.remove( this, types, fn, selector );
|
|
} );
|
|
}
|
|
} );
|
|
|
|
|
|
var
|
|
|
|
// Support: IE <=10 - 11, Edge 12 - 13 only
|
|
// In IE/Edge using regex groups here causes severe slowdowns.
|
|
// See https://connect.microsoft.com/IE/feedback/details/1736512/
|
|
rnoInnerhtml = /<script|<style|<link/i,
|
|
|
|
// checked="checked" or checked
|
|
rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
|
|
rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
|
|
|
|
// Prefer a tbody over its parent table for containing new rows
|
|
function manipulationTarget( elem, content ) {
|
|
if ( nodeName( elem, "table" ) &&
|
|
nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
|
|
|
|
return jQuery( elem ).children( "tbody" )[ 0 ] || elem;
|
|
}
|
|
|
|
return elem;
|
|
}
|
|
|
|
// Replace/restore the type attribute of script elements for safe DOM manipulation
|
|
function disableScript( elem ) {
|
|
elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
|
|
return elem;
|
|
}
|
|
function restoreScript( elem ) {
|
|
if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) {
|
|
elem.type = elem.type.slice( 5 );
|
|
} else {
|
|
elem.removeAttribute( "type" );
|
|
}
|
|
|
|
return elem;
|
|
}
|
|
|
|
function cloneCopyEvent( src, dest ) {
|
|
var i, l, type, pdataOld, udataOld, udataCur, events;
|
|
|
|
if ( dest.nodeType !== 1 ) {
|
|
return;
|
|
}
|
|
|
|
// 1. Copy private data: events, handlers, etc.
|
|
if ( dataPriv.hasData( src ) ) {
|
|
pdataOld = dataPriv.get( src );
|
|
events = pdataOld.events;
|
|
|
|
if ( events ) {
|
|
dataPriv.remove( dest, "handle events" );
|
|
|
|
for ( type in events ) {
|
|
for ( i = 0, l = events[ type ].length; i < l; i++ ) {
|
|
jQuery.event.add( dest, type, events[ type ][ i ] );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2. Copy user data
|
|
if ( dataUser.hasData( src ) ) {
|
|
udataOld = dataUser.access( src );
|
|
udataCur = jQuery.extend( {}, udataOld );
|
|
|
|
dataUser.set( dest, udataCur );
|
|
}
|
|
}
|
|
|
|
// Fix IE bugs, see support tests
|
|
function fixInput( src, dest ) {
|
|
var nodeName = dest.nodeName.toLowerCase();
|
|
|
|
// Fails to persist the checked state of a cloned checkbox or radio button.
|
|
if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
|
|
dest.checked = src.checked;
|
|
|
|
// Fails to return the selected option to the default selected state when cloning options
|
|
} else if ( nodeName === "input" || nodeName === "textarea" ) {
|
|
dest.defaultValue = src.defaultValue;
|
|
}
|
|
}
|
|
|
|
function domManip( collection, args, callback, ignored ) {
|
|
|
|
// Flatten any nested arrays
|
|
args = flat( args );
|
|
|
|
var fragment, first, scripts, hasScripts, node, doc,
|
|
i = 0,
|
|
l = collection.length,
|
|
iNoClone = l - 1,
|
|
value = args[ 0 ],
|
|
valueIsFunction = isFunction( value );
|
|
|
|
// We can't cloneNode fragments that contain checked, in WebKit
|
|
if ( valueIsFunction ||
|
|
( l > 1 && typeof value === "string" &&
|
|
!support.checkClone && rchecked.test( value ) ) ) {
|
|
return collection.each( function( index ) {
|
|
var self = collection.eq( index );
|
|
if ( valueIsFunction ) {
|
|
args[ 0 ] = value.call( this, index, self.html() );
|
|
}
|
|
domManip( self, args, callback, ignored );
|
|
} );
|
|
}
|
|
|
|
if ( l ) {
|
|
fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
|
|
first = fragment.firstChild;
|
|
|
|
if ( fragment.childNodes.length === 1 ) {
|
|
fragment = first;
|
|
}
|
|
|
|
// Require either new content or an interest in ignored elements to invoke the callback
|
|
if ( first || ignored ) {
|
|
scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
|
|
hasScripts = scripts.length;
|
|
|
|
// Use the original fragment for the last item
|
|
// instead of the first because it can end up
|
|
// being emptied incorrectly in certain situations (#8070).
|
|
for ( ; i < l; i++ ) {
|
|
node = fragment;
|
|
|
|
if ( i !== iNoClone ) {
|
|
node = jQuery.clone( node, true, true );
|
|
|
|
// Keep references to cloned scripts for later restoration
|
|
if ( hasScripts ) {
|
|
|
|
// Support: Android <=4.0 only, PhantomJS 1 only
|
|
// push.apply(_, arraylike) throws on ancient WebKit
|
|
jQuery.merge( scripts, getAll( node, "script" ) );
|
|
}
|
|
}
|
|
|
|
callback.call( collection[ i ], node, i );
|
|
}
|
|
|
|
if ( hasScripts ) {
|
|
doc = scripts[ scripts.length - 1 ].ownerDocument;
|
|
|
|
// Reenable scripts
|
|
jQuery.map( scripts, restoreScript );
|
|
|
|
// Evaluate executable scripts on first document insertion
|
|
for ( i = 0; i < hasScripts; i++ ) {
|
|
node = scripts[ i ];
|
|
if ( rscriptType.test( node.type || "" ) &&
|
|
!dataPriv.access( node, "globalEval" ) &&
|
|
jQuery.contains( doc, node ) ) {
|
|
|
|
if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) {
|
|
|
|
// Optional AJAX dependency, but won't run scripts if not present
|
|
if ( jQuery._evalUrl && !node.noModule ) {
|
|
jQuery._evalUrl( node.src, {
|
|
nonce: node.nonce || node.getAttribute( "nonce" )
|
|
}, doc );
|
|
}
|
|
} else {
|
|
DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return collection;
|
|
}
|
|
|
|
function remove( elem, selector, keepData ) {
|
|
var node,
|
|
nodes = selector ? jQuery.filter( selector, elem ) : elem,
|
|
i = 0;
|
|
|
|
for ( ; ( node = nodes[ i ] ) != null; i++ ) {
|
|
if ( !keepData && node.nodeType === 1 ) {
|
|
jQuery.cleanData( getAll( node ) );
|
|
}
|
|
|
|
if ( node.parentNode ) {
|
|
if ( keepData && isAttached( node ) ) {
|
|
setGlobalEval( getAll( node, "script" ) );
|
|
}
|
|
node.parentNode.removeChild( node );
|
|
}
|
|
}
|
|
|
|
return elem;
|
|
}
|
|
|
|
jQuery.extend( {
|
|
htmlPrefilter: function( html ) {
|
|
return html;
|
|
},
|
|
|
|
clone: function( elem, dataAndEvents, deepDataAndEvents ) {
|
|
var i, l, srcElements, destElements,
|
|
clone = elem.cloneNode( true ),
|
|
inPage = isAttached( elem );
|
|
|
|
// Fix IE cloning issues
|
|
if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
|
|
!jQuery.isXMLDoc( elem ) ) {
|
|
|
|
// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
|
|
destElements = getAll( clone );
|
|
srcElements = getAll( elem );
|
|
|
|
for ( i = 0, l = srcElements.length; i < l; i++ ) {
|
|
fixInput( srcElements[ i ], destElements[ i ] );
|
|
}
|
|
}
|
|
|
|
// Copy the events from the original to the clone
|
|
if ( dataAndEvents ) {
|
|
if ( deepDataAndEvents ) {
|
|
srcElements = srcElements || getAll( elem );
|
|
destElements = destElements || getAll( clone );
|
|
|
|
for ( i = 0, l = srcElements.length; i < l; i++ ) {
|
|
cloneCopyEvent( srcElements[ i ], destElements[ i ] );
|
|
}
|
|
} else {
|
|
cloneCopyEvent( elem, clone );
|
|
}
|
|
}
|
|
|
|
// Preserve script evaluation history
|
|
destElements = getAll( clone, "script" );
|
|
if ( destElements.length > 0 ) {
|
|
setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
|
|
}
|
|
|
|
// Return the cloned set
|
|
return clone;
|
|
},
|
|
|
|
cleanData: function( elems ) {
|
|
var data, elem, type,
|
|
special = jQuery.event.special,
|
|
i = 0;
|
|
|
|
for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
|
|
if ( acceptData( elem ) ) {
|
|
if ( ( data = elem[ dataPriv.expando ] ) ) {
|
|
if ( data.events ) {
|
|
for ( type in data.events ) {
|
|
if ( special[ type ] ) {
|
|
jQuery.event.remove( elem, type );
|
|
|
|
// This is a shortcut to avoid jQuery.event.remove's overhead
|
|
} else {
|
|
jQuery.removeEvent( elem, type, data.handle );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Support: Chrome <=35 - 45+
|
|
// Assign undefined instead of using delete, see Data#remove
|
|
elem[ dataPriv.expando ] = undefined;
|
|
}
|
|
if ( elem[ dataUser.expando ] ) {
|
|
|
|
// Support: Chrome <=35 - 45+
|
|
// Assign undefined instead of using delete, see Data#remove
|
|
elem[ dataUser.expando ] = undefined;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} );
|
|
|
|
jQuery.fn.extend( {
|
|
detach: function( selector ) {
|
|
return remove( this, selector, true );
|
|
},
|
|
|
|
remove: function( selector ) {
|
|
return remove( this, selector );
|
|
},
|
|
|
|
text: function( value ) {
|
|
return access( this, function( value ) {
|
|
return value === undefined ?
|
|
jQuery.text( this ) :
|
|
this.empty().each( function() {
|
|
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
|
|
this.textContent = value;
|
|
}
|
|
} );
|
|
}, null, value, arguments.length );
|
|
},
|
|
|
|
append: function() {
|
|
return domManip( this, arguments, function( elem ) {
|
|
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
|
|
var target = manipulationTarget( this, elem );
|
|
target.appendChild( elem );
|
|
}
|
|
} );
|
|
},
|
|
|
|
prepend: function() {
|
|
return domManip( this, arguments, function( elem ) {
|
|
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
|
|
var target = manipulationTarget( this, elem );
|
|
target.insertBefore( elem, target.firstChild );
|
|
}
|
|
} );
|
|
},
|
|
|
|
before: function() {
|
|
return domManip( this, arguments, function( elem ) {
|
|
if ( this.parentNode ) {
|
|
this.parentNode.insertBefore( elem, this );
|
|
}
|
|
} );
|
|
},
|
|
|
|
after: function() {
|
|
return domManip( this, arguments, function( elem ) {
|
|
if ( this.parentNode ) {
|
|
this.parentNode.insertBefore( elem, this.nextSibling );
|
|
}
|
|
} );
|
|
},
|
|
|
|
empty: function() {
|
|
var elem,
|
|
i = 0;
|
|
|
|
for ( ; ( elem = this[ i ] ) != null; i++ ) {
|
|
if ( elem.nodeType === 1 ) {
|
|
|
|
// Prevent memory leaks
|
|
jQuery.cleanData( getAll( elem, false ) );
|
|
|
|
// Remove any remaining nodes
|
|
elem.textContent = "";
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
clone: function( dataAndEvents, deepDataAndEvents ) {
|
|
dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
|
|
deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
|
|
|
|
return this.map( function() {
|
|
return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
|
|
} );
|
|
},
|
|
|
|
html: function( value ) {
|
|
return access( this, function( value ) {
|
|
var elem = this[ 0 ] || {},
|
|
i = 0,
|
|
l = this.length;
|
|
|
|
if ( value === undefined && elem.nodeType === 1 ) {
|
|
return elem.innerHTML;
|
|
}
|
|
|
|
// See if we can take a shortcut and just use innerHTML
|
|
if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
|
|
!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
|
|
|
|
value = jQuery.htmlPrefilter( value );
|
|
|
|
try {
|
|
for ( ; i < l; i++ ) {
|
|
elem = this[ i ] || {};
|
|
|
|
// Remove element nodes and prevent memory leaks
|
|
if ( elem.nodeType === 1 ) {
|
|
jQuery.cleanData( getAll( elem, false ) );
|
|
elem.innerHTML = value;
|
|
}
|
|
}
|
|
|
|
elem = 0;
|
|
|
|
// If using innerHTML throws an exception, use the fallback method
|
|
} catch ( e ) {}
|
|
}
|
|
|
|
if ( elem ) {
|
|
this.empty().append( value );
|
|
}
|
|
}, null, value, arguments.length );
|
|
},
|
|
|
|
replaceWith: function() {
|
|
var ignored = [];
|
|
|
|
// Make the changes, replacing each non-ignored context element with the new content
|
|
return domManip( this, arguments, function( elem ) {
|
|
var parent = this.parentNode;
|
|
|
|
if ( jQuery.inArray( this, ignored ) < 0 ) {
|
|
jQuery.cleanData( getAll( this ) );
|
|
if ( parent ) {
|
|
parent.replaceChild( elem, this );
|
|
}
|
|
}
|
|
|
|
// Force callback invocation
|
|
}, ignored );
|
|
}
|
|
} );
|
|
|
|
jQuery.each( {
|
|
appendTo: "append",
|
|
prependTo: "prepend",
|
|
insertBefore: "before",
|
|
insertAfter: "after",
|
|
replaceAll: "replaceWith"
|
|
}, function( name, original ) {
|
|
jQuery.fn[ name ] = function( selector ) {
|
|
var elems,
|
|
ret = [],
|
|
insert = jQuery( selector ),
|
|
last = insert.length - 1,
|
|
i = 0;
|
|
|
|
for ( ; i <= last; i++ ) {
|
|
elems = i === last ? this : this.clone( true );
|
|
jQuery( insert[ i ] )[ original ]( elems );
|
|
|
|
// Support: Android <=4.0 only, PhantomJS 1 only
|
|
// .get() because push.apply(_, arraylike) throws on ancient WebKit
|
|
push.apply( ret, elems.get() );
|
|
}
|
|
|
|
return this.pushStack( ret );
|
|
};
|
|
} );
|
|
var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
|
|
|
|
var getStyles = function( elem ) {
|
|
|
|
// Support: IE <=11 only, Firefox <=30 (#15098, #14150)
|
|
// IE throws on elements created in popups
|
|
// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
|
|
var view = elem.ownerDocument.defaultView;
|
|
|
|
if ( !view || !view.opener ) {
|
|
view = window;
|
|
}
|
|
|
|
return view.getComputedStyle( elem );
|
|
};
|
|
|
|
var swap = function( elem, options, callback ) {
|
|
var ret, name,
|
|
old = {};
|
|
|
|
// Remember the old values, and insert the new ones
|
|
for ( name in options ) {
|
|
old[ name ] = elem.style[ name ];
|
|
elem.style[ name ] = options[ name ];
|
|
}
|
|
|
|
ret = callback.call( elem );
|
|
|
|
// Revert the old values
|
|
for ( name in options ) {
|
|
elem.style[ name ] = old[ name ];
|
|
}
|
|
|
|
return ret;
|
|
};
|
|
|
|
|
|
var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" );
|
|
|
|
|
|
|
|
( function() {
|
|
|
|
// Executing both pixelPosition & boxSizingReliable tests require only one layout
|
|
// so they're executed at the same time to save the second computation.
|
|
function computeStyleTests() {
|
|
|
|
// This is a singleton, we need to execute it only once
|
|
if ( !div ) {
|
|
return;
|
|
}
|
|
|
|
container.style.cssText = "position:absolute;left:-11111px;width:60px;" +
|
|
"margin-top:1px;padding:0;border:0";
|
|
div.style.cssText =
|
|
"position:relative;display:block;box-sizing:border-box;overflow:scroll;" +
|
|
"margin:auto;border:1px;padding:1px;" +
|
|
"width:60%;top:1%";
|
|
documentElement.appendChild( container ).appendChild( div );
|
|
|
|
var divStyle = window.getComputedStyle( div );
|
|
pixelPositionVal = divStyle.top !== "1%";
|
|
|
|
// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
|
|
reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;
|
|
|
|
// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3
|
|
// Some styles come back with percentage values, even though they shouldn't
|
|
div.style.right = "60%";
|
|
pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;
|
|
|
|
// Support: IE 9 - 11 only
|
|
// Detect misreporting of content dimensions for box-sizing:border-box elements
|
|
boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;
|
|
|
|
// Support: IE 9 only
|
|
// Detect overflow:scroll screwiness (gh-3699)
|
|
// Support: Chrome <=64
|
|
// Don't get tricked when zoom affects offsetWidth (gh-4029)
|
|
div.style.position = "absolute";
|
|
scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;
|
|
|
|
documentElement.removeChild( container );
|
|
|
|
// Nullify the div so it wouldn't be stored in the memory and
|
|
// it will also be a sign that checks already performed
|
|
div = null;
|
|
}
|
|
|
|
function roundPixelMeasures( measure ) {
|
|
return Math.round( parseFloat( measure ) );
|
|
}
|
|
|
|
var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,
|
|
reliableTrDimensionsVal, reliableMarginLeftVal,
|
|
container = document.createElement( "div" ),
|
|
div = document.createElement( "div" );
|
|
|
|
// Finish early in limited (non-browser) environments
|
|
if ( !div.style ) {
|
|
return;
|
|
}
|
|
|
|
// Support: IE <=9 - 11 only
|
|
// Style of cloned element affects source element cloned (#8908)
|
|
div.style.backgroundClip = "content-box";
|
|
div.cloneNode( true ).style.backgroundClip = "";
|
|
support.clearCloneStyle = div.style.backgroundClip === "content-box";
|
|
|
|
jQuery.extend( support, {
|
|
boxSizingReliable: function() {
|
|
computeStyleTests();
|
|
return boxSizingReliableVal;
|
|
},
|
|
pixelBoxStyles: function() {
|
|
computeStyleTests();
|
|
return pixelBoxStylesVal;
|
|
},
|
|
pixelPosition: function() {
|
|
computeStyleTests();
|
|
return pixelPositionVal;
|
|
},
|
|
reliableMarginLeft: function() {
|
|
computeStyleTests();
|
|
return reliableMarginLeftVal;
|
|
},
|
|
scrollboxSize: function() {
|
|
computeStyleTests();
|
|
return scrollboxSizeVal;
|
|
},
|
|
|
|
// Support: IE 9 - 11+, Edge 15 - 18+
|
|
// IE/Edge misreport `getComputedStyle` of table rows with width/height
|
|
// set in CSS while `offset*` properties report correct values.
|
|
// Behavior in IE 9 is more subtle than in newer versions & it passes
|
|
// some versions of this test; make sure not to make it pass there!
|
|
reliableTrDimensions: function() {
|
|
var table, tr, trChild, trStyle;
|
|
if ( reliableTrDimensionsVal == null ) {
|
|
table = document.createElement( "table" );
|
|
tr = document.createElement( "tr" );
|
|
trChild = document.createElement( "div" );
|
|
|
|
table.style.cssText = "position:absolute;left:-11111px";
|
|
tr.style.height = "1px";
|
|
trChild.style.height = "9px";
|
|
|
|
documentElement
|
|
.appendChild( table )
|
|
.appendChild( tr )
|
|
.appendChild( trChild );
|
|
|
|
trStyle = window.getComputedStyle( tr );
|
|
reliableTrDimensionsVal = parseInt( trStyle.height ) > 3;
|
|
|
|
documentElement.removeChild( table );
|
|
}
|
|
return reliableTrDimensionsVal;
|
|
}
|
|
} );
|
|
} )();
|
|
|
|
|
|
function curCSS( elem, name, computed ) {
|
|
var width, minWidth, maxWidth, ret,
|
|
|
|
// Support: Firefox 51+
|
|
// Retrieving style before computed somehow
|
|
// fixes an issue with getting wrong values
|
|
// on detached elements
|
|
style = elem.style;
|
|
|
|
computed = computed || getStyles( elem );
|
|
|
|
// getPropertyValue is needed for:
|
|
// .css('filter') (IE 9 only, #12537)
|
|
// .css('--customProperty) (#3144)
|
|
if ( computed ) {
|
|
ret = computed.getPropertyValue( name ) || computed[ name ];
|
|
|
|
if ( ret === "" && !isAttached( elem ) ) {
|
|
ret = jQuery.style( elem, name );
|
|
}
|
|
|
|
// A tribute to the "awesome hack by Dean Edwards"
|
|
// Android Browser returns percentage for some values,
|
|
// but width seems to be reliably pixels.
|
|
// This is against the CSSOM draft spec:
|
|
// https://drafts.csswg.org/cssom/#resolved-values
|
|
if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {
|
|
|
|
// Remember the original values
|
|
width = style.width;
|
|
minWidth = style.minWidth;
|
|
maxWidth = style.maxWidth;
|
|
|
|
// Put in the new values to get a computed value out
|
|
style.minWidth = style.maxWidth = style.width = ret;
|
|
ret = computed.width;
|
|
|
|
// Revert the changed values
|
|
style.width = width;
|
|
style.minWidth = minWidth;
|
|
style.maxWidth = maxWidth;
|
|
}
|
|
}
|
|
|
|
return ret !== undefined ?
|
|
|
|
// Support: IE <=9 - 11 only
|
|
// IE returns zIndex value as an integer.
|
|
ret + "" :
|
|
ret;
|
|
}
|
|
|
|
|
|
function addGetHookIf( conditionFn, hookFn ) {
|
|
|
|
// Define the hook, we'll check on the first run if it's really needed.
|
|
return {
|
|
get: function() {
|
|
if ( conditionFn() ) {
|
|
|
|
// Hook not needed (or it's not possible to use it due
|
|
// to missing dependency), remove it.
|
|
delete this.get;
|
|
return;
|
|
}
|
|
|
|
// Hook needed; redefine it so that the support test is not executed again.
|
|
return ( this.get = hookFn ).apply( this, arguments );
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
var cssPrefixes = [ "Webkit", "Moz", "ms" ],
|
|
emptyStyle = document.createElement( "div" ).style,
|
|
vendorProps = {};
|
|
|
|
// Return a vendor-prefixed property or undefined
|
|
function vendorPropName( name ) {
|
|
|
|
// Check for vendor prefixed names
|
|
var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
|
|
i = cssPrefixes.length;
|
|
|
|
while ( i-- ) {
|
|
name = cssPrefixes[ i ] + capName;
|
|
if ( name in emptyStyle ) {
|
|
return name;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return a potentially-mapped jQuery.cssProps or vendor prefixed property
|
|
function finalPropName( name ) {
|
|
var final = jQuery.cssProps[ name ] || vendorProps[ name ];
|
|
|
|
if ( final ) {
|
|
return final;
|
|
}
|
|
if ( name in emptyStyle ) {
|
|
return name;
|
|
}
|
|
return vendorProps[ name ] = vendorPropName( name ) || name;
|
|
}
|
|
|
|
|
|
var
|
|
|
|
// Swappable if display is none or starts with table
|
|
// except "table", "table-cell", or "table-caption"
|
|
// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
|
|
rdisplayswap = /^(none|table(?!-c[ea]).+)/,
|
|
rcustomProp = /^--/,
|
|
cssShow = { position: "absolute", visibility: "hidden", display: "block" },
|
|
cssNormalTransform = {
|
|
letterSpacing: "0",
|
|
fontWeight: "400"
|
|
};
|
|
|
|
function setPositiveNumber( _elem, value, subtract ) {
|
|
|
|
// Any relative (+/-) values have already been
|
|
// normalized at this point
|
|
var matches = rcssNum.exec( value );
|
|
return matches ?
|
|
|
|
// Guard against undefined "subtract", e.g., when used as in cssHooks
|
|
Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
|
|
value;
|
|
}
|
|
|
|
function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {
|
|
var i = dimension === "width" ? 1 : 0,
|
|
extra = 0,
|
|
delta = 0;
|
|
|
|
// Adjustment may not be necessary
|
|
if ( box === ( isBorderBox ? "border" : "content" ) ) {
|
|
return 0;
|
|
}
|
|
|
|
for ( ; i < 4; i += 2 ) {
|
|
|
|
// Both box models exclude margin
|
|
if ( box === "margin" ) {
|
|
delta += jQuery.css( elem, box + cssExpand[ i ], true, styles );
|
|
}
|
|
|
|
// If we get here with a content-box, we're seeking "padding" or "border" or "margin"
|
|
if ( !isBorderBox ) {
|
|
|
|
// Add padding
|
|
delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
|
|
|
|
// For "border" or "margin", add border
|
|
if ( box !== "padding" ) {
|
|
delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
|
|
|
|
// But still keep track of it otherwise
|
|
} else {
|
|
extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
|
|
}
|
|
|
|
// If we get here with a border-box (content + padding + border), we're seeking "content" or
|
|
// "padding" or "margin"
|
|
} else {
|
|
|
|
// For "content", subtract padding
|
|
if ( box === "content" ) {
|
|
delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
|
|
}
|
|
|
|
// For "content" or "padding", subtract border
|
|
if ( box !== "margin" ) {
|
|
delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Account for positive content-box scroll gutter when requested by providing computedVal
|
|
if ( !isBorderBox && computedVal >= 0 ) {
|
|
|
|
// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
|
|
// Assuming integer scroll gutter, subtract the rest and round down
|
|
delta += Math.max( 0, Math.ceil(
|
|
elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
|
|
computedVal -
|
|
delta -
|
|
extra -
|
|
0.5
|
|
|
|
// If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter
|
|
// Use an explicit zero to avoid NaN (gh-3964)
|
|
) ) || 0;
|
|
}
|
|
|
|
return delta;
|
|
}
|
|
|
|
function getWidthOrHeight( elem, dimension, extra ) {
|
|
|
|
// Start with computed style
|
|
var styles = getStyles( elem ),
|
|
|
|
// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).
|
|
// Fake content-box until we know it's needed to know the true value.
|
|
boxSizingNeeded = !support.boxSizingReliable() || extra,
|
|
isBorderBox = boxSizingNeeded &&
|
|
jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
|
|
valueIsBorderBox = isBorderBox,
|
|
|
|
val = curCSS( elem, dimension, styles ),
|
|
offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );
|
|
|
|
// Support: Firefox <=54
|
|
// Return a confounding non-pixel value or feign ignorance, as appropriate.
|
|
if ( rnumnonpx.test( val ) ) {
|
|
if ( !extra ) {
|
|
return val;
|
|
}
|
|
val = "auto";
|
|
}
|
|
|
|
|
|
// Support: IE 9 - 11 only
|
|
// Use offsetWidth/offsetHeight for when box sizing is unreliable.
|
|
// In those cases, the computed value can be trusted to be border-box.
|
|
if ( ( !support.boxSizingReliable() && isBorderBox ||
|
|
|
|
// Support: IE 10 - 11+, Edge 15 - 18+
|
|
// IE/Edge misreport `getComputedStyle` of table rows with width/height
|
|
// set in CSS while `offset*` properties report correct values.
|
|
// Interestingly, in some cases IE 9 doesn't suffer from this issue.
|
|
!support.reliableTrDimensions() && nodeName( elem, "tr" ) ||
|
|
|
|
// Fall back to offsetWidth/offsetHeight when value is "auto"
|
|
// This happens for inline elements with no explicit setting (gh-3571)
|
|
val === "auto" ||
|
|
|
|
// Support: Android <=4.1 - 4.3 only
|
|
// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)
|
|
!parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) &&
|
|
|
|
// Make sure the element is visible & connected
|
|
elem.getClientRects().length ) {
|
|
|
|
isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
|
|
|
|
// Where available, offsetWidth/offsetHeight approximate border box dimensions.
|
|
// Where not available (e.g., SVG), assume unreliable box-sizing and interpret the
|
|
// retrieved value as a content box dimension.
|
|
valueIsBorderBox = offsetProp in elem;
|
|
if ( valueIsBorderBox ) {
|
|
val = elem[ offsetProp ];
|
|
}
|
|
}
|
|
|
|
// Normalize "" and auto
|
|
val = parseFloat( val ) || 0;
|
|
|
|
// Adjust for the element's box model
|
|
return ( val +
|
|
boxModelAdjustment(
|
|
elem,
|
|
dimension,
|
|
extra || ( isBorderBox ? "border" : "content" ),
|
|
valueIsBorderBox,
|
|
styles,
|
|
|
|
// Provide the current computed size to request scroll gutter calculation (gh-3589)
|
|
val
|
|
)
|
|
) + "px";
|
|
}
|
|
|
|
jQuery.extend( {
|
|
|
|
// Add in style property hooks for overriding the default
|
|
// behavior of getting and setting a style property
|
|
cssHooks: {
|
|
opacity: {
|
|
get: function( elem, computed ) {
|
|
if ( computed ) {
|
|
|
|
// We should always get a number back from opacity
|
|
var ret = curCSS( elem, "opacity" );
|
|
return ret === "" ? "1" : ret;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
// Don't automatically add "px" to these possibly-unitless properties
|
|
cssNumber: {
|
|
"animationIterationCount": true,
|
|
"columnCount": true,
|
|
"fillOpacity": true,
|
|
"flexGrow": true,
|
|
"flexShrink": true,
|
|
"fontWeight": true,
|
|
"gridArea": true,
|
|
"gridColumn": true,
|
|
"gridColumnEnd": true,
|
|
"gridColumnStart": true,
|
|
"gridRow": true,
|
|
"gridRowEnd": true,
|
|
"gridRowStart": true,
|
|
"lineHeight": true,
|
|
"opacity": true,
|
|
"order": true,
|
|
"orphans": true,
|
|
"widows": true,
|
|
"zIndex": true,
|
|
"zoom": true
|
|
},
|
|
|
|
// Add in properties whose names you wish to fix before
|
|
// setting or getting the value
|
|
cssProps: {},
|
|
|
|
// Get and set the style property on a DOM Node
|
|
style: function( elem, name, value, extra ) {
|
|
|
|
// Don't set styles on text and comment nodes
|
|
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
|
|
return;
|
|
}
|
|
|
|
// Make sure that we're working with the right name
|
|
var ret, type, hooks,
|
|
origName = camelCase( name ),
|
|
isCustomProp = rcustomProp.test( name ),
|
|
style = elem.style;
|
|
|
|
// Make sure that we're working with the right name. We don't
|
|
// want to query the value if it is a CSS custom property
|
|
// since they are user-defined.
|
|
if ( !isCustomProp ) {
|
|
name = finalPropName( origName );
|
|
}
|
|
|
|
// Gets hook for the prefixed version, then unprefixed version
|
|
hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
|
|
|
|
// Check if we're setting a value
|
|
if ( value !== undefined ) {
|
|
type = typeof value;
|
|
|
|
// Convert "+=" or "-=" to relative numbers (#7345)
|
|
if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
|
|
value = adjustCSS( elem, name, ret );
|
|
|
|
// Fixes bug #9237
|
|
type = "number";
|
|
}
|
|
|
|
// Make sure that null and NaN values aren't set (#7116)
|
|
if ( value == null || value !== value ) {
|
|
return;
|
|
}
|
|
|
|
// If a number was passed in, add the unit (except for certain CSS properties)
|
|
// The isCustomProp check can be removed in jQuery 4.0 when we only auto-append
|
|
// "px" to a few hardcoded values.
|
|
if ( type === "number" && !isCustomProp ) {
|
|
value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
|
|
}
|
|
|
|
// background-* props affect original clone's values
|
|
if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
|
|
style[ name ] = "inherit";
|
|
}
|
|
|
|
// If a hook was provided, use that value, otherwise just set the specified value
|
|
if ( !hooks || !( "set" in hooks ) ||
|
|
( value = hooks.set( elem, value, extra ) ) !== undefined ) {
|
|
|
|
if ( isCustomProp ) {
|
|
style.setProperty( name, value );
|
|
} else {
|
|
style[ name ] = value;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
// If a hook was provided get the non-computed value from there
|
|
if ( hooks && "get" in hooks &&
|
|
( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Otherwise just get the value from the style object
|
|
return style[ name ];
|
|
}
|
|
},
|
|
|
|
css: function( elem, name, extra, styles ) {
|
|
var val, num, hooks,
|
|
origName = camelCase( name ),
|
|
isCustomProp = rcustomProp.test( name );
|
|
|
|
// Make sure that we're working with the right name. We don't
|
|
// want to modify the value if it is a CSS custom property
|
|
// since they are user-defined.
|
|
if ( !isCustomProp ) {
|
|
name = finalPropName( origName );
|
|
}
|
|
|
|
// Try prefixed name followed by the unprefixed name
|
|
hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
|
|
|
|
// If a hook was provided get the computed value from there
|
|
if ( hooks && "get" in hooks ) {
|
|
val = hooks.get( elem, true, extra );
|
|
}
|
|
|
|
// Otherwise, if a way to get the computed value exists, use that
|
|
if ( val === undefined ) {
|
|
val = curCSS( elem, name, styles );
|
|
}
|
|
|
|
// Convert "normal" to computed value
|
|
if ( val === "normal" && name in cssNormalTransform ) {
|
|
val = cssNormalTransform[ name ];
|
|
}
|
|
|
|
// Make numeric if forced or a qualifier was provided and val looks numeric
|
|
if ( extra === "" || extra ) {
|
|
num = parseFloat( val );
|
|
return extra === true || isFinite( num ) ? num || 0 : val;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
} );
|
|
|
|
jQuery.each( [ "height", "width" ], function( _i, dimension ) {
|
|
jQuery.cssHooks[ dimension ] = {
|
|
get: function( elem, computed, extra ) {
|
|
if ( computed ) {
|
|
|
|
// Certain elements can have dimension info if we invisibly show them
|
|
// but it must have a current display style that would benefit
|
|
return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
|
|
|
|
// Support: Safari 8+
|
|
// Table columns in Safari have non-zero offsetWidth & zero
|
|
// getBoundingClientRect().width unless display is changed.
|
|
// Support: IE <=11 only
|
|
// Running getBoundingClientRect on a disconnected node
|
|
// in IE throws an error.
|
|
( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
|
|
swap( elem, cssShow, function() {
|
|
return getWidthOrHeight( elem, dimension, extra );
|
|
} ) :
|
|
getWidthOrHeight( elem, dimension, extra );
|
|
}
|
|
},
|
|
|
|
set: function( elem, value, extra ) {
|
|
var matches,
|
|
styles = getStyles( elem ),
|
|
|
|
// Only read styles.position if the test has a chance to fail
|
|
// to avoid forcing a reflow.
|
|
scrollboxSizeBuggy = !support.scrollboxSize() &&
|
|
styles.position === "absolute",
|
|
|
|
// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)
|
|
boxSizingNeeded = scrollboxSizeBuggy || extra,
|
|
isBorderBox = boxSizingNeeded &&
|
|
jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
|
|
subtract = extra ?
|
|
boxModelAdjustment(
|
|
elem,
|
|
dimension,
|
|
extra,
|
|
isBorderBox,
|
|
styles
|
|
) :
|
|
0;
|
|
|
|
// Account for unreliable border-box dimensions by comparing offset* to computed and
|
|
// faking a content-box to get border and padding (gh-3699)
|
|
if ( isBorderBox && scrollboxSizeBuggy ) {
|
|
subtract -= Math.ceil(
|
|
elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
|
|
parseFloat( styles[ dimension ] ) -
|
|
boxModelAdjustment( elem, dimension, "border", false, styles ) -
|
|
0.5
|
|
);
|
|
}
|
|
|
|
// Convert to pixels if value adjustment is needed
|
|
if ( subtract && ( matches = rcssNum.exec( value ) ) &&
|
|
( matches[ 3 ] || "px" ) !== "px" ) {
|
|
|
|
elem.style[ dimension ] = value;
|
|
value = jQuery.css( elem, dimension );
|
|
}
|
|
|
|
return setPositiveNumber( elem, value, subtract );
|
|
}
|
|
};
|
|
} );
|
|
|
|
jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
|
|
function( elem, computed ) {
|
|
if ( computed ) {
|
|
return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
|
|
elem.getBoundingClientRect().left -
|
|
swap( elem, { marginLeft: 0 }, function() {
|
|
return elem.getBoundingClientRect().left;
|
|
} )
|
|
) + "px";
|
|
}
|
|
}
|
|
);
|
|
|
|
// These hooks are used by animate to expand properties
|
|
jQuery.each( {
|
|
margin: "",
|
|
padding: "",
|
|
border: "Width"
|
|
}, function( prefix, suffix ) {
|
|
jQuery.cssHooks[ prefix + suffix ] = {
|
|
expand: function( value ) {
|
|
var i = 0,
|
|
expanded = {},
|
|
|
|
// Assumes a single number if not a string
|
|
parts = typeof value === "string" ? value.split( " " ) : [ value ];
|
|
|
|
for ( ; i < 4; i++ ) {
|
|
expanded[ prefix + cssExpand[ i ] + suffix ] =
|
|
parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
|
|
}
|
|
|
|
return expanded;
|
|
}
|
|
};
|
|
|
|
if ( prefix !== "margin" ) {
|
|
jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
|
|
}
|
|
} );
|
|
|
|
jQuery.fn.extend( {
|
|
css: function( name, value ) {
|
|
return access( this, function( elem, name, value ) {
|
|
var styles, len,
|
|
map = {},
|
|
i = 0;
|
|
|
|
if ( Array.isArray( name ) ) {
|
|
styles = getStyles( elem );
|
|
len = name.length;
|
|
|
|
for ( ; i < len; i++ ) {
|
|
map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
|
|
}
|
|
|
|
return map;
|
|
}
|
|
|
|
return value !== undefined ?
|
|
jQuery.style( elem, name, value ) :
|
|
jQuery.css( elem, name );
|
|
}, name, value, arguments.length > 1 );
|
|
}
|
|
} );
|
|
|
|
|
|
function Tween( elem, options, prop, end, easing ) {
|
|
return new Tween.prototype.init( elem, options, prop, end, easing );
|
|
}
|
|
jQuery.Tween = Tween;
|
|
|
|
Tween.prototype = {
|
|
constructor: Tween,
|
|
init: function( elem, options, prop, end, easing, unit ) {
|
|
this.elem = elem;
|
|
this.prop = prop;
|
|
this.easing = easing || jQuery.easing._default;
|
|
this.options = options;
|
|
this.start = this.now = this.cur();
|
|
this.end = end;
|
|
this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
|
|
},
|
|
cur: function() {
|
|
var hooks = Tween.propHooks[ this.prop ];
|
|
|
|
return hooks && hooks.get ?
|
|
hooks.get( this ) :
|
|
Tween.propHooks._default.get( this );
|
|
},
|
|
run: function( percent ) {
|
|
var eased,
|
|
hooks = Tween.propHooks[ this.prop ];
|
|
|
|
if ( this.options.duration ) {
|
|
this.pos = eased = jQuery.easing[ this.easing ](
|
|
percent, this.options.duration * percent, 0, 1, this.options.duration
|
|
);
|
|
} else {
|
|
this.pos = eased = percent;
|
|
}
|
|
this.now = ( this.end - this.start ) * eased + this.start;
|
|
|
|
if ( this.options.step ) {
|
|
this.options.step.call( this.elem, this.now, this );
|
|
}
|
|
|
|
if ( hooks && hooks.set ) {
|
|
hooks.set( this );
|
|
} else {
|
|
Tween.propHooks._default.set( this );
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
|
|
Tween.prototype.init.prototype = Tween.prototype;
|
|
|
|
Tween.propHooks = {
|
|
_default: {
|
|
get: function( tween ) {
|
|
var result;
|
|
|
|
// Use a property on the element directly when it is not a DOM element,
|
|
// or when there is no matching style property that exists.
|
|
if ( tween.elem.nodeType !== 1 ||
|
|
tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
|
|
return tween.elem[ tween.prop ];
|
|
}
|
|
|
|
// Passing an empty string as a 3rd parameter to .css will automatically
|
|
// attempt a parseFloat and fallback to a string if the parse fails.
|
|
// Simple values such as "10px" are parsed to Float;
|
|
// complex values such as "rotate(1rad)" are returned as-is.
|
|
result = jQuery.css( tween.elem, tween.prop, "" );
|
|
|
|
// Empty strings, null, undefined and "auto" are converted to 0.
|
|
return !result || result === "auto" ? 0 : result;
|
|
},
|
|
set: function( tween ) {
|
|
|
|
// Use step hook for back compat.
|
|
// Use cssHook if its there.
|
|
// Use .style if available and use plain properties where available.
|
|
if ( jQuery.fx.step[ tween.prop ] ) {
|
|
jQuery.fx.step[ tween.prop ]( tween );
|
|
} else if ( tween.elem.nodeType === 1 && (
|
|
jQuery.cssHooks[ tween.prop ] ||
|
|
tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) {
|
|
jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
|
|
} else {
|
|
tween.elem[ tween.prop ] = tween.now;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Support: IE <=9 only
|
|
// Panic based approach to setting things on disconnected nodes
|
|
Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
|
|
set: function( tween ) {
|
|
if ( tween.elem.nodeType && tween.elem.parentNode ) {
|
|
tween.elem[ tween.prop ] = tween.now;
|
|
}
|
|
}
|
|
};
|
|
|
|
jQuery.easing = {
|
|
linear: function( p ) {
|
|
return p;
|
|
},
|
|
swing: function( p ) {
|
|
return 0.5 - Math.cos( p * Math.PI ) / 2;
|
|
},
|
|
_default: "swing"
|
|
};
|
|
|
|
jQuery.fx = Tween.prototype.init;
|
|
|
|
// Back compat <1.8 extension point
|
|
jQuery.fx.step = {};
|
|
|
|
|
|
|
|
|
|
var
|
|
fxNow, inProgress,
|
|
rfxtypes = /^(?:toggle|show|hide)$/,
|
|
rrun = /queueHooks$/;
|
|
|
|
function schedule() {
|
|
if ( inProgress ) {
|
|
if ( document.hidden === false && window.requestAnimationFrame ) {
|
|
window.requestAnimationFrame( schedule );
|
|
} else {
|
|
window.setTimeout( schedule, jQuery.fx.interval );
|
|
}
|
|
|
|
jQuery.fx.tick();
|
|
}
|
|
}
|
|
|
|
// Animations created synchronously will run synchronously
|
|
function createFxNow() {
|
|
window.setTimeout( function() {
|
|
fxNow = undefined;
|
|
} );
|
|
return ( fxNow = Date.now() );
|
|
}
|
|
|
|
// Generate parameters to create a standard animation
|
|
function genFx( type, includeWidth ) {
|
|
var which,
|
|
i = 0,
|
|
attrs = { height: type };
|
|
|
|
// If we include width, step value is 1 to do all cssExpand values,
|
|
// otherwise step value is 2 to skip over Left and Right
|
|
includeWidth = includeWidth ? 1 : 0;
|
|
for ( ; i < 4; i += 2 - includeWidth ) {
|
|
which = cssExpand[ i ];
|
|
attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
|
|
}
|
|
|
|
if ( includeWidth ) {
|
|
attrs.opacity = attrs.width = type;
|
|
}
|
|
|
|
return attrs;
|
|
}
|
|
|
|
function createTween( value, prop, animation ) {
|
|
var tween,
|
|
collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
|
|
index = 0,
|
|
length = collection.length;
|
|
for ( ; index < length; index++ ) {
|
|
if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
|
|
|
|
// We're done with this property
|
|
return tween;
|
|
}
|
|
}
|
|
}
|
|
|
|
function defaultPrefilter( elem, props, opts ) {
|
|
var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
|
|
isBox = "width" in props || "height" in props,
|
|
anim = this,
|
|
orig = {},
|
|
style = elem.style,
|
|
hidden = elem.nodeType && isHiddenWithinTree( elem ),
|
|
dataShow = dataPriv.get( elem, "fxshow" );
|
|
|
|
// Queue-skipping animations hijack the fx hooks
|
|
if ( !opts.queue ) {
|
|
hooks = jQuery._queueHooks( elem, "fx" );
|
|
if ( hooks.unqueued == null ) {
|
|
hooks.unqueued = 0;
|
|
oldfire = hooks.empty.fire;
|
|
hooks.empty.fire = function() {
|
|
if ( !hooks.unqueued ) {
|
|
oldfire();
|
|
}
|
|
};
|
|
}
|
|
hooks.unqueued++;
|
|
|
|
anim.always( function() {
|
|
|
|
// Ensure the complete handler is called before this completes
|
|
anim.always( function() {
|
|
hooks.unqueued--;
|
|
if ( !jQuery.queue( elem, "fx" ).length ) {
|
|
hooks.empty.fire();
|
|
}
|
|
} );
|
|
} );
|
|
}
|
|
|
|
// Detect show/hide animations
|
|
for ( prop in props ) {
|
|
value = props[ prop ];
|
|
if ( rfxtypes.test( value ) ) {
|
|
delete props[ prop ];
|
|
toggle = toggle || value === "toggle";
|
|
if ( value === ( hidden ? "hide" : "show" ) ) {
|
|
|
|
// Pretend to be hidden if this is a "show" and
|
|
// there is still data from a stopped show/hide
|
|
if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
|
|
hidden = true;
|
|
|
|
// Ignore all other no-op show/hide data
|
|
} else {
|
|
continue;
|
|
}
|
|
}
|
|
orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
|
|
}
|
|
}
|
|
|
|
// Bail out if this is a no-op like .hide().hide()
|
|
propTween = !jQuery.isEmptyObject( props );
|
|
if ( !propTween && jQuery.isEmptyObject( orig ) ) {
|
|
return;
|
|
}
|
|
|
|
// Restrict "overflow" and "display" styles during box animations
|
|
if ( isBox && elem.nodeType === 1 ) {
|
|
|
|
// Support: IE <=9 - 11, Edge 12 - 15
|
|
// Record all 3 overflow attributes because IE does not infer the shorthand
|
|
// from identically-valued overflowX and overflowY and Edge just mirrors
|
|
// the overflowX value there.
|
|
opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
|
|
|
|
// Identify a display type, preferring old show/hide data over the CSS cascade
|
|
restoreDisplay = dataShow && dataShow.display;
|
|
if ( restoreDisplay == null ) {
|
|
restoreDisplay = dataPriv.get( elem, "display" );
|
|
}
|
|
display = jQuery.css( elem, "display" );
|
|
if ( display === "none" ) {
|
|
if ( restoreDisplay ) {
|
|
display = restoreDisplay;
|
|
} else {
|
|
|
|
// Get nonempty value(s) by temporarily forcing visibility
|
|
showHide( [ elem ], true );
|
|
restoreDisplay = elem.style.display || restoreDisplay;
|
|
display = jQuery.css( elem, "display" );
|
|
showHide( [ elem ] );
|
|
}
|
|
}
|
|
|
|
// Animate inline elements as inline-block
|
|
if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
|
|
if ( jQuery.css( elem, "float" ) === "none" ) {
|
|
|
|
// Restore the original display value at the end of pure show/hide animations
|
|
if ( !propTween ) {
|
|
anim.done( function() {
|
|
style.display = restoreDisplay;
|
|
} );
|
|
if ( restoreDisplay == null ) {
|
|
display = style.display;
|
|
restoreDisplay = display === "none" ? "" : display;
|
|
}
|
|
}
|
|
style.display = "inline-block";
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( opts.overflow ) {
|
|
style.overflow = "hidden";
|
|
anim.always( function() {
|
|
style.overflow = opts.overflow[ 0 ];
|
|
style.overflowX = opts.overflow[ 1 ];
|
|
style.overflowY = opts.overflow[ 2 ];
|
|
} );
|
|
}
|
|
|
|
// Implement show/hide animations
|
|
propTween = false;
|
|
for ( prop in orig ) {
|
|
|
|
// General show/hide setup for this element animation
|
|
if ( !propTween ) {
|
|
if ( dataShow ) {
|
|
if ( "hidden" in dataShow ) {
|
|
hidden = dataShow.hidden;
|
|
}
|
|
} else {
|
|
dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
|
|
}
|
|
|
|
// Store hidden/visible for toggle so `.stop().toggle()` "reverses"
|
|
if ( toggle ) {
|
|
dataShow.hidden = !hidden;
|
|
}
|
|
|
|
// Show elements before animating them
|
|
if ( hidden ) {
|
|
showHide( [ elem ], true );
|
|
}
|
|
|
|
/* eslint-disable no-loop-func */
|
|
|
|
anim.done( function() {
|
|
|
|
/* eslint-enable no-loop-func */
|
|
|
|
// The final step of a "hide" animation is actually hiding the element
|
|
if ( !hidden ) {
|
|
showHide( [ elem ] );
|
|
}
|
|
dataPriv.remove( elem, "fxshow" );
|
|
for ( prop in orig ) {
|
|
jQuery.style( elem, prop, orig[ prop ] );
|
|
}
|
|
} );
|
|
}
|
|
|
|
// Per-property setup
|
|
propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
|
|
if ( !( prop in dataShow ) ) {
|
|
dataShow[ prop ] = propTween.start;
|
|
if ( hidden ) {
|
|
propTween.end = propTween.start;
|
|
propTween.start = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function propFilter( props, specialEasing ) {
|
|
var index, name, easing, value, hooks;
|
|
|
|
// camelCase, specialEasing and expand cssHook pass
|
|
for ( index in props ) {
|
|
name = camelCase( index );
|
|
easing = specialEasing[ name ];
|
|
value = props[ index ];
|
|
if ( Array.isArray( value ) ) {
|
|
easing = value[ 1 ];
|
|
value = props[ index ] = value[ 0 ];
|
|
}
|
|
|
|
if ( index !== name ) {
|
|
props[ name ] = value;
|
|
delete props[ index ];
|
|
}
|
|
|
|
hooks = jQuery.cssHooks[ name ];
|
|
if ( hooks && "expand" in hooks ) {
|
|
value = hooks.expand( value );
|
|
delete props[ name ];
|
|
|
|
// Not quite $.extend, this won't overwrite existing keys.
|
|
// Reusing 'index' because we have the correct "name"
|
|
for ( index in value ) {
|
|
if ( !( index in props ) ) {
|
|
props[ index ] = value[ index ];
|
|
specialEasing[ index ] = easing;
|
|
}
|
|
}
|
|
} else {
|
|
specialEasing[ name ] = easing;
|
|
}
|
|
}
|
|
}
|
|
|
|
function Animation( elem, properties, options ) {
|
|
var result,
|
|
stopped,
|
|
index = 0,
|
|
length = Animation.prefilters.length,
|
|
deferred = jQuery.Deferred().always( function() {
|
|
|
|
// Don't match elem in the :animated selector
|
|
delete tick.elem;
|
|
} ),
|
|
tick = function() {
|
|
if ( stopped ) {
|
|
return false;
|
|
}
|
|
var currentTime = fxNow || createFxNow(),
|
|
remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
|
|
|
|
// Support: Android 2.3 only
|
|
// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
|
|
temp = remaining / animation.duration || 0,
|
|
percent = 1 - temp,
|
|
index = 0,
|
|
length = animation.tweens.length;
|
|
|
|
for ( ; index < length; index++ ) {
|
|
animation.tweens[ index ].run( percent );
|
|
}
|
|
|
|
deferred.notifyWith( elem, [ animation, percent, remaining ] );
|
|
|
|
// If there's more to do, yield
|
|
if ( percent < 1 && length ) {
|
|
return remaining;
|
|
}
|
|
|
|
// If this was an empty animation, synthesize a final progress notification
|
|
if ( !length ) {
|
|
deferred.notifyWith( elem, [ animation, 1, 0 ] );
|
|
}
|
|
|
|
// Resolve the animation and report its conclusion
|
|
deferred.resolveWith( elem, [ animation ] );
|
|
return false;
|
|
},
|
|
animation = deferred.promise( {
|
|
elem: elem,
|
|
props: jQuery.extend( {}, properties ),
|
|
opts: jQuery.extend( true, {
|
|
specialEasing: {},
|
|
easing: jQuery.easing._default
|
|
}, options ),
|
|
originalProperties: properties,
|
|
originalOptions: options,
|
|
startTime: fxNow || createFxNow(),
|
|
duration: options.duration,
|
|
tweens: [],
|
|
createTween: function( prop, end ) {
|
|
var tween = jQuery.Tween( elem, animation.opts, prop, end,
|
|
animation.opts.specialEasing[ prop ] || animation.opts.easing );
|
|
animation.tweens.push( tween );
|
|
return tween;
|
|
},
|
|
stop: function( gotoEnd ) {
|
|
var index = 0,
|
|
|
|
// If we are going to the end, we want to run all the tweens
|
|
// otherwise we skip this part
|
|
length = gotoEnd ? animation.tweens.length : 0;
|
|
if ( stopped ) {
|
|
return this;
|
|
}
|
|
stopped = true;
|
|
for ( ; index < length; index++ ) {
|
|
animation.tweens[ index ].run( 1 );
|
|
}
|
|
|
|
// Resolve when we played the last frame; otherwise, reject
|
|
if ( gotoEnd ) {
|
|
deferred.notifyWith( elem, [ animation, 1, 0 ] );
|
|
deferred.resolveWith( elem, [ animation, gotoEnd ] );
|
|
} else {
|
|
deferred.rejectWith( elem, [ animation, gotoEnd ] );
|
|
}
|
|
return this;
|
|
}
|
|
} ),
|
|
props = animation.props;
|
|
|
|
propFilter( props, animation.opts.specialEasing );
|
|
|
|
for ( ; index < length; index++ ) {
|
|
result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
|
|
if ( result ) {
|
|
if ( isFunction( result.stop ) ) {
|
|
jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
|
|
result.stop.bind( result );
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
jQuery.map( props, createTween, animation );
|
|
|
|
if ( isFunction( animation.opts.start ) ) {
|
|
animation.opts.start.call( elem, animation );
|
|
}
|
|
|
|
// Attach callbacks from options
|
|
animation
|
|
.progress( animation.opts.progress )
|
|
.done( animation.opts.done, animation.opts.complete )
|
|
.fail( animation.opts.fail )
|
|
.always( animation.opts.always );
|
|
|
|
jQuery.fx.timer(
|
|
jQuery.extend( tick, {
|
|
elem: elem,
|
|
anim: animation,
|
|
queue: animation.opts.queue
|
|
} )
|
|
);
|
|
|
|
return animation;
|
|
}
|
|
|
|
jQuery.Animation = jQuery.extend( Animation, {
|
|
|
|
tweeners: {
|
|
"*": [ function( prop, value ) {
|
|
var tween = this.createTween( prop, value );
|
|
adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
|
|
return tween;
|
|
} ]
|
|
},
|
|
|
|
tweener: function( props, callback ) {
|
|
if ( isFunction( props ) ) {
|
|
callback = props;
|
|
props = [ "*" ];
|
|
} else {
|
|
props = props.match( rnothtmlwhite );
|
|
}
|
|
|
|
var prop,
|
|
index = 0,
|
|
length = props.length;
|
|
|
|
for ( ; index < length; index++ ) {
|
|
prop = props[ index ];
|
|
Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
|
|
Animation.tweeners[ prop ].unshift( callback );
|
|
}
|
|
},
|
|
|
|
prefilters: [ defaultPrefilter ],
|
|
|
|
prefilter: function( callback, prepend ) {
|
|
if ( prepend ) {
|
|
Animation.prefilters.unshift( callback );
|
|
} else {
|
|
Animation.prefilters.push( callback );
|
|
}
|
|
}
|
|
} );
|
|
|
|
jQuery.speed = function( speed, easing, fn ) {
|
|
var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
|
|
complete: fn || !fn && easing ||
|
|
isFunction( speed ) && speed,
|
|
duration: speed,
|
|
easing: fn && easing || easing && !isFunction( easing ) && easing
|
|
};
|
|
|
|
// Go to the end state if fx are off
|
|
if ( jQuery.fx.off ) {
|
|
opt.duration = 0;
|
|
|
|
} else {
|
|
if ( typeof opt.duration !== "number" ) {
|
|
if ( opt.duration in jQuery.fx.speeds ) {
|
|
opt.duration = jQuery.fx.speeds[ opt.duration ];
|
|
|
|
} else {
|
|
opt.duration = jQuery.fx.speeds._default;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Normalize opt.queue - true/undefined/null -> "fx"
|
|
if ( opt.queue == null || opt.queue === true ) {
|
|
opt.queue = "fx";
|
|
}
|
|
|
|
// Queueing
|
|
opt.old = opt.complete;
|
|
|
|
opt.complete = function() {
|
|
if ( isFunction( opt.old ) ) {
|
|
opt.old.call( this );
|
|
}
|
|
|
|
if ( opt.queue ) {
|
|
jQuery.dequeue( this, opt.queue );
|
|
}
|
|
};
|
|
|
|
return opt;
|
|
};
|
|
|
|
jQuery.fn.extend( {
|
|
fadeTo: function( speed, to, easing, callback ) {
|
|
|
|
// Show any hidden elements after setting opacity to 0
|
|
return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
|
|
|
|
// Animate to the value specified
|
|
.end().animate( { opacity: to }, speed, easing, callback );
|
|
},
|
|
animate: function( prop, speed, easing, callback ) {
|
|
var empty = jQuery.isEmptyObject( prop ),
|
|
optall = jQuery.speed( speed, easing, callback ),
|
|
doAnimation = function() {
|
|
|
|
// Operate on a copy of prop so per-property easing won't be lost
|
|
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
|
|
|
|
// Empty animations, or finishing resolves immediately
|
|
if ( empty || dataPriv.get( this, "finish" ) ) {
|
|
anim.stop( true );
|
|
}
|
|
};
|
|
doAnimation.finish = doAnimation;
|
|
|
|
return empty || optall.queue === false ?
|
|
this.each( doAnimation ) :
|
|
this.queue( optall.queue, doAnimation );
|
|
},
|
|
stop: function( type, clearQueue, gotoEnd ) {
|
|
var stopQueue = function( hooks ) {
|
|
var stop = hooks.stop;
|
|
delete hooks.stop;
|
|
stop( gotoEnd );
|
|
};
|
|
|
|
if ( typeof type !== "string" ) {
|
|
gotoEnd = clearQueue;
|
|
clearQueue = type;
|
|
type = undefined;
|
|
}
|
|
if ( clearQueue ) {
|
|
this.queue( type || "fx", [] );
|
|
}
|
|
|
|
return this.each( function() {
|
|
var dequeue = true,
|
|
index = type != null && type + "queueHooks",
|
|
timers = jQuery.timers,
|
|
data = dataPriv.get( this );
|
|
|
|
if ( index ) {
|
|
if ( data[ index ] && data[ index ].stop ) {
|
|
stopQueue( data[ index ] );
|
|
}
|
|
} else {
|
|
for ( index in data ) {
|
|
if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
|
|
stopQueue( data[ index ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( index = timers.length; index--; ) {
|
|
if ( timers[ index ].elem === this &&
|
|
( type == null || timers[ index ].queue === type ) ) {
|
|
|
|
timers[ index ].anim.stop( gotoEnd );
|
|
dequeue = false;
|
|
timers.splice( index, 1 );
|
|
}
|
|
}
|
|
|
|
// Start the next in the queue if the last step wasn't forced.
|
|
// Timers currently will call their complete callbacks, which
|
|
// will dequeue but only if they were gotoEnd.
|
|
if ( dequeue || !gotoEnd ) {
|
|
jQuery.dequeue( this, type );
|
|
}
|
|
} );
|
|
},
|
|
finish: function( type ) {
|
|
if ( type !== false ) {
|
|
type = type || "fx";
|
|
}
|
|
return this.each( function() {
|
|
var index,
|
|
data = dataPriv.get( this ),
|
|
queue = data[ type + "queue" ],
|
|
hooks = data[ type + "queueHooks" ],
|
|
timers = jQuery.timers,
|
|
length = queue ? queue.length : 0;
|
|
|
|
// Enable finishing flag on private data
|
|
data.finish = true;
|
|
|
|
// Empty the queue first
|
|
jQuery.queue( this, type, [] );
|
|
|
|
if ( hooks && hooks.stop ) {
|
|
hooks.stop.call( this, true );
|
|
}
|
|
|
|
// Look for any active animations, and finish them
|
|
for ( index = timers.length; index--; ) {
|
|
if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
|
|
timers[ index ].anim.stop( true );
|
|
timers.splice( index, 1 );
|
|
}
|
|
}
|
|
|
|
// Look for any animations in the old queue and finish them
|
|
for ( index = 0; index < length; index++ ) {
|
|
if ( queue[ index ] && queue[ index ].finish ) {
|
|
queue[ index ].finish.call( this );
|
|
}
|
|
}
|
|
|
|
// Turn off finishing flag
|
|
delete data.finish;
|
|
} );
|
|
}
|
|
} );
|
|
|
|
jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) {
|
|
var cssFn = jQuery.fn[ name ];
|
|
jQuery.fn[ name ] = function( speed, easing, callback ) {
|
|
return speed == null || typeof speed === "boolean" ?
|
|
cssFn.apply( this, arguments ) :
|
|
this.animate( genFx( name, true ), speed, easing, callback );
|
|
};
|
|
} );
|
|
|
|
// Generate shortcuts for custom animations
|
|
jQuery.each( {
|
|
slideDown: genFx( "show" ),
|
|
slideUp: genFx( "hide" ),
|
|
slideToggle: genFx( "toggle" ),
|
|
fadeIn: { opacity: "show" },
|
|
fadeOut: { opacity: "hide" },
|
|
fadeToggle: { opacity: "toggle" }
|
|
}, function( name, props ) {
|
|
jQuery.fn[ name ] = function( speed, easing, callback ) {
|
|
return this.animate( props, speed, easing, callback );
|
|
};
|
|
} );
|
|
|
|
jQuery.timers = [];
|
|
jQuery.fx.tick = function() {
|
|
var timer,
|
|
i = 0,
|
|
timers = jQuery.timers;
|
|
|
|
fxNow = Date.now();
|
|
|
|
for ( ; i < timers.length; i++ ) {
|
|
timer = timers[ i ];
|
|
|
|
// Run the timer and safely remove it when done (allowing for external removal)
|
|
if ( !timer() && timers[ i ] === timer ) {
|
|
timers.splice( i--, 1 );
|
|
}
|
|
}
|
|
|
|
if ( !timers.length ) {
|
|
jQuery.fx.stop();
|
|
}
|
|
fxNow = undefined;
|
|
};
|
|
|
|
jQuery.fx.timer = function( timer ) {
|
|
jQuery.timers.push( timer );
|
|
jQuery.fx.start();
|
|
};
|
|
|
|
jQuery.fx.interval = 13;
|
|
jQuery.fx.start = function() {
|
|
if ( inProgress ) {
|
|
return;
|
|
}
|
|
|
|
inProgress = true;
|
|
schedule();
|
|
};
|
|
|
|
jQuery.fx.stop = function() {
|
|
inProgress = null;
|
|
};
|
|
|
|
jQuery.fx.speeds = {
|
|
slow: 600,
|
|
fast: 200,
|
|
|
|
// Default speed
|
|
_default: 400
|
|
};
|
|
|
|
|
|
// Based off of the plugin by Clint Helfers, with permission.
|
|
// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
|
|
jQuery.fn.delay = function( time, type ) {
|
|
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
|
|
type = type || "fx";
|
|
|
|
return this.queue( type, function( next, hooks ) {
|
|
var timeout = window.setTimeout( next, time );
|
|
hooks.stop = function() {
|
|
window.clearTimeout( timeout );
|
|
};
|
|
} );
|
|
};
|
|
|
|
|
|
( function() {
|
|
var input = document.createElement( "input" ),
|
|
select = document.createElement( "select" ),
|
|
opt = select.appendChild( document.createElement( "option" ) );
|
|
|
|
input.type = "checkbox";
|
|
|
|
// Support: Android <=4.3 only
|
|
// Default value for a checkbox should be "on"
|
|
support.checkOn = input.value !== "";
|
|
|
|
// Support: IE <=11 only
|
|
// Must access selectedIndex to make default options select
|
|
support.optSelected = opt.selected;
|
|
|
|
// Support: IE <=11 only
|
|
// An input loses its value after becoming a radio
|
|
input = document.createElement( "input" );
|
|
input.value = "t";
|
|
input.type = "radio";
|
|
support.radioValue = input.value === "t";
|
|
} )();
|
|
|
|
|
|
var boolHook,
|
|
attrHandle = jQuery.expr.attrHandle;
|
|
|
|
jQuery.fn.extend( {
|
|
attr: function( name, value ) {
|
|
return access( this, jQuery.attr, name, value, arguments.length > 1 );
|
|
},
|
|
|
|
removeAttr: function( name ) {
|
|
return this.each( function() {
|
|
jQuery.removeAttr( this, name );
|
|
} );
|
|
}
|
|
} );
|
|
|
|
jQuery.extend( {
|
|
attr: function( elem, name, value ) {
|
|
var ret, hooks,
|
|
nType = elem.nodeType;
|
|
|
|
// Don't get/set attributes on text, comment and attribute nodes
|
|
if ( nType === 3 || nType === 8 || nType === 2 ) {
|
|
return;
|
|
}
|
|
|
|
// Fallback to prop when attributes are not supported
|
|
if ( typeof elem.getAttribute === "undefined" ) {
|
|
return jQuery.prop( elem, name, value );
|
|
}
|
|
|
|
// Attribute hooks are determined by the lowercase version
|
|
// Grab necessary hook if one is defined
|
|
if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
|
|
hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
|
|
( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
|
|
}
|
|
|
|
if ( value !== undefined ) {
|
|
if ( value === null ) {
|
|
jQuery.removeAttr( elem, name );
|
|
return;
|
|
}
|
|
|
|
if ( hooks && "set" in hooks &&
|
|
( ret = hooks.set( elem, value, name ) ) !== undefined ) {
|
|
return ret;
|
|
}
|
|
|
|
elem.setAttribute( name, value + "" );
|
|
return value;
|
|
}
|
|
|
|
if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
|
|
return ret;
|
|
}
|
|
|
|
ret = jQuery.find.attr( elem, name );
|
|
|
|
// Non-existent attributes return null, we normalize to undefined
|
|
return ret == null ? undefined : ret;
|
|
},
|
|
|
|
attrHooks: {
|
|
type: {
|
|
set: function( elem, value ) {
|
|
if ( !support.radioValue && value === "radio" &&
|
|
nodeName( elem, "input" ) ) {
|
|
var val = elem.value;
|
|
elem.setAttribute( "type", value );
|
|
if ( val ) {
|
|
elem.value = val;
|
|
}
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
removeAttr: function( elem, value ) {
|
|
var name,
|
|
i = 0,
|
|
|
|
// Attribute names can contain non-HTML whitespace characters
|
|
// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
|
|
attrNames = value && value.match( rnothtmlwhite );
|
|
|
|
if ( attrNames && elem.nodeType === 1 ) {
|
|
while ( ( name = attrNames[ i++ ] ) ) {
|
|
elem.removeAttribute( name );
|
|
}
|
|
}
|
|
}
|
|
} );
|
|
|
|
// Hooks for boolean attributes
|
|
boolHook = {
|
|
set: function( elem, value, name ) {
|
|
if ( value === false ) {
|
|
|
|
// Remove boolean attributes when set to false
|
|
jQuery.removeAttr( elem, name );
|
|
} else {
|
|
elem.setAttribute( name, name );
|
|
}
|
|
return name;
|
|
}
|
|
};
|
|
|
|
jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) {
|
|
var getter = attrHandle[ name ] || jQuery.find.attr;
|
|
|
|
attrHandle[ name ] = function( elem, name, isXML ) {
|
|
var ret, handle,
|
|
lowercaseName = name.toLowerCase();
|
|
|
|
if ( !isXML ) {
|
|
|
|
// Avoid an infinite loop by temporarily removing this function from the getter
|
|
handle = attrHandle[ lowercaseName ];
|
|
attrHandle[ lowercaseName ] = ret;
|
|
ret = getter( elem, name, isXML ) != null ?
|
|
lowercaseName :
|
|
null;
|
|
attrHandle[ lowercaseName ] = handle;
|
|
}
|
|
return ret;
|
|
};
|
|
} );
|
|
|
|
|
|
|
|
|
|
var rfocusable = /^(?:input|select|textarea|button)$/i,
|
|
rclickable = /^(?:a|area)$/i;
|
|
|
|
jQuery.fn.extend( {
|
|
prop: function( name, value ) {
|
|
return access( this, jQuery.prop, name, value, arguments.length > 1 );
|
|
},
|
|
|
|
removeProp: function( name ) {
|
|
return this.each( function() {
|
|
delete this[ jQuery.propFix[ name ] || name ];
|
|
} );
|
|
}
|
|
} );
|
|
|
|
jQuery.extend( {
|
|
prop: function( elem, name, value ) {
|
|
var ret, hooks,
|
|
nType = elem.nodeType;
|
|
|
|
// Don't get/set properties on text, comment and attribute nodes
|
|
if ( nType === 3 || nType === 8 || nType === 2 ) {
|
|
return;
|
|
}
|
|
|
|
if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
|
|
|
|
// Fix name and attach hooks
|
|
name = jQuery.propFix[ name ] || name;
|
|
hooks = jQuery.propHooks[ name ];
|
|
}
|
|
|
|
if ( value !== undefined ) {
|
|
if ( hooks && "set" in hooks &&
|
|
( ret = hooks.set( elem, value, name ) ) !== undefined ) {
|
|
return ret;
|
|
}
|
|
|
|
return ( elem[ name ] = value );
|
|
}
|
|
|
|
if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
|
|
return ret;
|
|
}
|
|
|
|
return elem[ name ];
|
|
},
|
|
|
|
propHooks: {
|
|
tabIndex: {
|
|
get: function( elem ) {
|
|
|
|
// Support: IE <=9 - 11 only
|
|
// elem.tabIndex doesn't always return the
|
|
// correct value when it hasn't been explicitly set
|
|
// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
|
|
// Use proper attribute retrieval(#12072)
|
|
var tabindex = jQuery.find.attr( elem, "tabindex" );
|
|
|
|
if ( tabindex ) {
|
|
return parseInt( tabindex, 10 );
|
|
}
|
|
|
|
if (
|
|
rfocusable.test( elem.nodeName ) ||
|
|
rclickable.test( elem.nodeName ) &&
|
|
elem.href
|
|
) {
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
},
|
|
|
|
propFix: {
|
|
"for": "htmlFor",
|
|
"class": "className"
|
|
}
|
|
} );
|
|
|
|
// Support: IE <=11 only
|
|
// Accessing the selectedIndex property
|
|
// forces the browser to respect setting selected
|
|
// on the option
|
|
// The getter ensures a default option is selected
|
|
// when in an optgroup
|
|
// eslint rule "no-unused-expressions" is disabled for this code
|
|
// since it considers such accessions noop
|
|
if ( !support.optSelected ) {
|
|
jQuery.propHooks.selected = {
|
|
get: function( elem ) {
|
|
|
|
/* eslint no-unused-expressions: "off" */
|
|
|
|
var parent = elem.parentNode;
|
|
if ( parent && parent.parentNode ) {
|
|
parent.parentNode.selectedIndex;
|
|
}
|
|
return null;
|
|
},
|
|
set: function( elem ) {
|
|
|
|
/* eslint no-unused-expressions: "off" */
|
|
|
|
var parent = elem.parentNode;
|
|
if ( parent ) {
|
|
parent.selectedIndex;
|
|
|
|
if ( parent.parentNode ) {
|
|
parent.parentNode.selectedIndex;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
jQuery.each( [
|
|
"tabIndex",
|
|
"readOnly",
|
|
"maxLength",
|
|
"cellSpacing",
|
|
"cellPadding",
|
|
"rowSpan",
|
|
"colSpan",
|
|
"useMap",
|
|
"frameBorder",
|
|
"contentEditable"
|
|
], function() {
|
|
jQuery.propFix[ this.toLowerCase() ] = this;
|
|
} );
|
|
|
|
|
|
|
|
|
|
// Strip and collapse whitespace according to HTML spec
|
|
// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
|
|
function stripAndCollapse( value ) {
|
|
var tokens = value.match( rnothtmlwhite ) || [];
|
|
return tokens.join( " " );
|
|
}
|
|
|
|
|
|
function getClass( elem ) {
|
|
return elem.getAttribute && elem.getAttribute( "class" ) || "";
|
|
}
|
|
|
|
function classesToArray( value ) {
|
|
if ( Array.isArray( value ) ) {
|
|
return value;
|
|
}
|
|
if ( typeof value === "string" ) {
|
|
return value.match( rnothtmlwhite ) || [];
|
|
}
|
|
return [];
|
|
}
|
|
|
|
jQuery.fn.extend( {
|
|
addClass: function( value ) {
|
|
var classes, elem, cur, curValue, clazz, j, finalValue,
|
|
i = 0;
|
|
|
|
if ( isFunction( value ) ) {
|
|
return this.each( function( j ) {
|
|
jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
|
|
} );
|
|
}
|
|
|
|
classes = classesToArray( value );
|
|
|
|
if ( classes.length ) {
|
|
while ( ( elem = this[ i++ ] ) ) {
|
|
curValue = getClass( elem );
|
|
cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
|
|
|
|
if ( cur ) {
|
|
j = 0;
|
|
while ( ( clazz = classes[ j++ ] ) ) {
|
|
if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
|
|
cur += clazz + " ";
|
|
}
|
|
}
|
|
|
|
// Only assign if different to avoid unneeded rendering.
|
|
finalValue = stripAndCollapse( cur );
|
|
if ( curValue !== finalValue ) {
|
|
elem.setAttribute( "class", finalValue );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
removeClass: function( value ) {
|
|
var classes, elem, cur, curValue, clazz, j, finalValue,
|
|
i = 0;
|
|
|
|
if ( isFunction( value ) ) {
|
|
return this.each( function( j ) {
|
|
jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
|
|
} );
|
|
}
|
|
|
|
if ( !arguments.length ) {
|
|
return this.attr( "class", "" );
|
|
}
|
|
|
|
classes = classesToArray( value );
|
|
|
|
if ( classes.length ) {
|
|
while ( ( elem = this[ i++ ] ) ) {
|
|
curValue = getClass( elem );
|
|
|
|
// This expression is here for better compressibility (see addClass)
|
|
cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
|
|
|
|
if ( cur ) {
|
|
j = 0;
|
|
while ( ( clazz = classes[ j++ ] ) ) {
|
|
|
|
// Remove *all* instances
|
|
while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
|
|
cur = cur.replace( " " + clazz + " ", " " );
|
|
}
|
|
}
|
|
|
|
// Only assign if different to avoid unneeded rendering.
|
|
finalValue = stripAndCollapse( cur );
|
|
if ( curValue !== finalValue ) {
|
|
elem.setAttribute( "class", finalValue );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
toggleClass: function( value, stateVal ) {
|
|
var type = typeof value,
|
|
isValidValue = type === "string" || Array.isArray( value );
|
|
|
|
if ( typeof stateVal === "boolean" && isValidValue ) {
|
|
return stateVal ? this.addClass( value ) : this.removeClass( value );
|
|
}
|
|
|
|
if ( isFunction( value ) ) {
|
|
return this.each( function( i ) {
|
|
jQuery( this ).toggleClass(
|
|
value.call( this, i, getClass( this ), stateVal ),
|
|
stateVal
|
|
);
|
|
} );
|
|
}
|
|
|
|
return this.each( function() {
|
|
var className, i, self, classNames;
|
|
|
|
if ( isValidValue ) {
|
|
|
|
// Toggle individual class names
|
|
i = 0;
|
|
self = jQuery( this );
|
|
classNames = classesToArray( value );
|
|
|
|
while ( ( className = classNames[ i++ ] ) ) {
|
|
|
|
// Check each className given, space separated list
|
|
if ( self.hasClass( className ) ) {
|
|
self.removeClass( className );
|
|
} else {
|
|
self.addClass( className );
|
|
}
|
|
}
|
|
|
|
// Toggle whole class name
|
|
} else if ( value === undefined || type === "boolean" ) {
|
|
className = getClass( this );
|
|
if ( className ) {
|
|
|
|
// Store className if set
|
|
dataPriv.set( this, "__className__", className );
|
|
}
|
|
|
|
// If the element has a class name or if we're passed `false`,
|
|
// then remove the whole classname (if there was one, the above saved it).
|
|
// Otherwise bring back whatever was previously saved (if anything),
|
|
// falling back to the empty string if nothing was stored.
|
|
if ( this.setAttribute ) {
|
|
this.setAttribute( "class",
|
|
className || value === false ?
|
|
"" :
|
|
dataPriv.get( this, "__className__" ) || ""
|
|
);
|
|
}
|
|
}
|
|
} );
|
|
},
|
|
|
|
hasClass: function( selector ) {
|
|
var className, elem,
|
|
i = 0;
|
|
|
|
className = " " + selector + " ";
|
|
while ( ( elem = this[ i++ ] ) ) {
|
|
if ( elem.nodeType === 1 &&
|
|
( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
} );
|
|
|
|
|
|
|
|
|
|
var rreturn = /\r/g;
|
|
|
|
jQuery.fn.extend( {
|
|
val: function( value ) {
|
|
var hooks, ret, valueIsFunction,
|
|
elem = this[ 0 ];
|
|
|
|
if ( !arguments.length ) {
|
|
if ( elem ) {
|
|
hooks = jQuery.valHooks[ elem.type ] ||
|
|
jQuery.valHooks[ elem.nodeName.toLowerCase() ];
|
|
|
|
if ( hooks &&
|
|
"get" in hooks &&
|
|
( ret = hooks.get( elem, "value" ) ) !== undefined
|
|
) {
|
|
return ret;
|
|
}
|
|
|
|
ret = elem.value;
|
|
|
|
// Handle most common string cases
|
|
if ( typeof ret === "string" ) {
|
|
return ret.replace( rreturn, "" );
|
|
}
|
|
|
|
// Handle cases where value is null/undef or number
|
|
return ret == null ? "" : ret;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
valueIsFunction = isFunction( value );
|
|
|
|
return this.each( function( i ) {
|
|
var val;
|
|
|
|
if ( this.nodeType !== 1 ) {
|
|
return;
|
|
}
|
|
|
|
if ( valueIsFunction ) {
|
|
val = value.call( this, i, jQuery( this ).val() );
|
|
} else {
|
|
val = value;
|
|
}
|
|
|
|
// Treat null/undefined as ""; convert numbers to string
|
|
if ( val == null ) {
|
|
val = "";
|
|
|
|
} else if ( typeof val === "number" ) {
|
|
val += "";
|
|
|
|
} else if ( Array.isArray( val ) ) {
|
|
val = jQuery.map( val, function( value ) {
|
|
return value == null ? "" : value + "";
|
|
} );
|
|
}
|
|
|
|
hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
|
|
|
|
// If set returns undefined, fall back to normal setting
|
|
if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
|
|
this.value = val;
|
|
}
|
|
} );
|
|
}
|
|
} );
|
|
|
|
jQuery.extend( {
|
|
valHooks: {
|
|
option: {
|
|
get: function( elem ) {
|
|
|
|
var val = jQuery.find.attr( elem, "value" );
|
|
return val != null ?
|
|
val :
|
|
|
|
// Support: IE <=10 - 11 only
|
|
// option.text throws exceptions (#14686, #14858)
|
|
// Strip and collapse whitespace
|
|
// https://html.spec.whatwg.org/#strip-and-collapse-whitespace
|
|
stripAndCollapse( jQuery.text( elem ) );
|
|
}
|
|
},
|
|
select: {
|
|
get: function( elem ) {
|
|
var value, option, i,
|
|
options = elem.options,
|
|
index = elem.selectedIndex,
|
|
one = elem.type === "select-one",
|
|
values = one ? null : [],
|
|
max = one ? index + 1 : options.length;
|
|
|
|
if ( index < 0 ) {
|
|
i = max;
|
|
|
|
} else {
|
|
i = one ? index : 0;
|
|
}
|
|
|
|
// Loop through all the selected options
|
|
for ( ; i < max; i++ ) {
|
|
option = options[ i ];
|
|
|
|
// Support: IE <=9 only
|
|
// IE8-9 doesn't update selected after form reset (#2551)
|
|
if ( ( option.selected || i === index ) &&
|
|
|
|
// Don't return options that are disabled or in a disabled optgroup
|
|
!option.disabled &&
|
|
( !option.parentNode.disabled ||
|
|
!nodeName( option.parentNode, "optgroup" ) ) ) {
|
|
|
|
// Get the specific value for the option
|
|
value = jQuery( option ).val();
|
|
|
|
// We don't need an array for one selects
|
|
if ( one ) {
|
|
return value;
|
|
}
|
|
|
|
// Multi-Selects return an array
|
|
values.push( value );
|
|
}
|
|
}
|
|
|
|
return values;
|
|
},
|
|
|
|
set: function( elem, value ) {
|
|
var optionSet, option,
|
|
options = elem.options,
|
|
values = jQuery.makeArray( value ),
|
|
i = options.length;
|
|
|
|
while ( i-- ) {
|
|
option = options[ i ];
|
|
|
|
/* eslint-disable no-cond-assign */
|
|
|
|
if ( option.selected =
|
|
jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
|
|
) {
|
|
optionSet = true;
|
|
}
|
|
|
|
/* eslint-enable no-cond-assign */
|
|
}
|
|
|
|
// Force browsers to behave consistently when non-matching value is set
|
|
if ( !optionSet ) {
|
|
elem.selectedIndex = -1;
|
|
}
|
|
return values;
|
|
}
|
|
}
|
|
}
|
|
} );
|
|
|
|
// Radios and checkboxes getter/setter
|
|
jQuery.each( [ "radio", "checkbox" ], function() {
|
|
jQuery.valHooks[ this ] = {
|
|
set: function( elem, value ) {
|
|
if ( Array.isArray( value ) ) {
|
|
return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
|
|
}
|
|
}
|
|
};
|
|
if ( !support.checkOn ) {
|
|
jQuery.valHooks[ this ].get = function( elem ) {
|
|
return elem.getAttribute( "value" ) === null ? "on" : elem.value;
|
|
};
|
|
}
|
|
} );
|
|
|
|
|
|
|
|
|
|
// Return jQuery for attributes-only inclusion
|
|
|
|
|
|
support.focusin = "onfocusin" in window;
|
|
|
|
|
|
var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
|
|
stopPropagationCallback = function( e ) {
|
|
e.stopPropagation();
|
|
};
|
|
|
|
jQuery.extend( jQuery.event, {
|
|
|
|
trigger: function( event, data, elem, onlyHandlers ) {
|
|
|
|
var i, cur, tmp, bubbleType, ontype, handle, special, lastElement,
|
|
eventPath = [ elem || document ],
|
|
type = hasOwn.call( event, "type" ) ? event.type : event,
|
|
namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
|
|
|
|
cur = lastElement = tmp = elem = elem || document;
|
|
|
|
// Don't do events on text and comment nodes
|
|
if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
|
|
return;
|
|
}
|
|
|
|
// focus/blur morphs to focusin/out; ensure we're not firing them right now
|
|
if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( type.indexOf( "." ) > -1 ) {
|
|
|
|
// Namespaced trigger; create a regexp to match event type in handle()
|
|
namespaces = type.split( "." );
|
|
type = namespaces.shift();
|
|
namespaces.sort();
|
|
}
|
|
ontype = type.indexOf( ":" ) < 0 && "on" + type;
|
|
|
|
// Caller can pass in a jQuery.Event object, Object, or just an event type string
|
|
event = event[ jQuery.expando ] ?
|
|
event :
|
|
new jQuery.Event( type, typeof event === "object" && event );
|
|
|
|
// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
|
|
event.isTrigger = onlyHandlers ? 2 : 3;
|
|
event.namespace = namespaces.join( "." );
|
|
event.rnamespace = event.namespace ?
|
|
new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
|
|
null;
|
|
|
|
// Clean up the event in case it is being reused
|
|
event.result = undefined;
|
|
if ( !event.target ) {
|
|
event.target = elem;
|
|
}
|
|
|
|
// Clone any incoming data and prepend the event, creating the handler arg list
|
|
data = data == null ?
|
|
[ event ] :
|
|
jQuery.makeArray( data, [ event ] );
|
|
|
|
// Allow special events to draw outside the lines
|
|
special = jQuery.event.special[ type ] || {};
|
|
if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
|
|
return;
|
|
}
|
|
|
|
// Determine event propagation path in advance, per W3C events spec (#9951)
|
|
// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
|
|
if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {
|
|
|
|
bubbleType = special.delegateType || type;
|
|
if ( !rfocusMorph.test( bubbleType + type ) ) {
|
|
cur = cur.parentNode;
|
|
}
|
|
for ( ; cur; cur = cur.parentNode ) {
|
|
eventPath.push( cur );
|
|
tmp = cur;
|
|
}
|
|
|
|
// Only add window if we got to document (e.g., not plain obj or detached DOM)
|
|
if ( tmp === ( elem.ownerDocument || document ) ) {
|
|
eventPath.push( tmp.defaultView || tmp.parentWindow || window );
|
|
}
|
|
}
|
|
|
|
// Fire handlers on the event path
|
|
i = 0;
|
|
while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
|
|
lastElement = cur;
|
|
event.type = i > 1 ?
|
|
bubbleType :
|
|
special.bindType || type;
|
|
|
|
// jQuery handler
|
|
handle = (
|
|
dataPriv.get( cur, "events" ) || Object.create( null )
|
|
)[ event.type ] &&
|
|
dataPriv.get( cur, "handle" );
|
|
if ( handle ) {
|
|
handle.apply( cur, data );
|
|
}
|
|
|
|
// Native handler
|
|
handle = ontype && cur[ ontype ];
|
|
if ( handle && handle.apply && acceptData( cur ) ) {
|
|
event.result = handle.apply( cur, data );
|
|
if ( event.result === false ) {
|
|
event.preventDefault();
|
|
}
|
|
}
|
|
}
|
|
event.type = type;
|
|
|
|
// If nobody prevented the default action, do it now
|
|
if ( !onlyHandlers && !event.isDefaultPrevented() ) {
|
|
|
|
if ( ( !special._default ||
|
|
special._default.apply( eventPath.pop(), data ) === false ) &&
|
|
acceptData( elem ) ) {
|
|
|
|
// Call a native DOM method on the target with the same name as the event.
|
|
// Don't do default actions on window, that's where global variables be (#6170)
|
|
if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {
|
|
|
|
// Don't re-trigger an onFOO event when we call its FOO() method
|
|
tmp = elem[ ontype ];
|
|
|
|
if ( tmp ) {
|
|
elem[ ontype ] = null;
|
|
}
|
|
|
|
// Prevent re-triggering of the same event, since we already bubbled it above
|
|
jQuery.event.triggered = type;
|
|
|
|
if ( event.isPropagationStopped() ) {
|
|
lastElement.addEventListener( type, stopPropagationCallback );
|
|
}
|
|
|
|
elem[ type ]();
|
|
|
|
if ( event.isPropagationStopped() ) {
|
|
lastElement.removeEventListener( type, stopPropagationCallback );
|
|
}
|
|
|
|
jQuery.event.triggered = undefined;
|
|
|
|
if ( tmp ) {
|
|
elem[ ontype ] = tmp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return event.result;
|
|
},
|
|
|
|
// Piggyback on a donor event to simulate a different one
|
|
// Used only for `focus(in | out)` events
|
|
simulate: function( type, elem, event ) {
|
|
var e = jQuery.extend(
|
|
new jQuery.Event(),
|
|
event,
|
|
{
|
|
type: type,
|
|
isSimulated: true
|
|
}
|
|
);
|
|
|
|
jQuery.event.trigger( e, null, elem );
|
|
}
|
|
|
|
} );
|
|
|
|
jQuery.fn.extend( {
|
|
|
|
trigger: function( type, data ) {
|
|
return this.each( function() {
|
|
jQuery.event.trigger( type, data, this );
|
|
} );
|
|
},
|
|
triggerHandler: function( type, data ) {
|
|
var elem = this[ 0 ];
|
|
if ( elem ) {
|
|
return jQuery.event.trigger( type, data, elem, true );
|
|
}
|
|
}
|
|
} );
|
|
|
|
|
|
// Support: Firefox <=44
|
|
// Firefox doesn't have focus(in | out) events
|
|
// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
|
|
//
|
|
// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
|
|
// focus(in | out) events fire after focus & blur events,
|
|
// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
|
|
// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
|
|
if ( !support.focusin ) {
|
|
jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
|
|
|
|
// Attach a single capturing handler on the document while someone wants focusin/focusout
|
|
var handler = function( event ) {
|
|
jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
|
|
};
|
|
|
|
jQuery.event.special[ fix ] = {
|
|
setup: function() {
|
|
|
|
// Handle: regular nodes (via `this.ownerDocument`), window
|
|
// (via `this.document`) & document (via `this`).
|
|
var doc = this.ownerDocument || this.document || this,
|
|
attaches = dataPriv.access( doc, fix );
|
|
|
|
if ( !attaches ) {
|
|
doc.addEventListener( orig, handler, true );
|
|
}
|
|
dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
|
|
},
|
|
teardown: function() {
|
|
var doc = this.ownerDocument || this.document || this,
|
|
attaches = dataPriv.access( doc, fix ) - 1;
|
|
|
|
if ( !attaches ) {
|
|
doc.removeEventListener( orig, handler, true );
|
|
dataPriv.remove( doc, fix );
|
|
|
|
} else {
|
|
dataPriv.access( doc, fix, attaches );
|
|
}
|
|
}
|
|
};
|
|
} );
|
|
}
|
|
var location = window.location;
|
|
|
|
var nonce = { guid: Date.now() };
|
|
|
|
var rquery = ( /\?/ );
|
|
|
|
|
|
|
|
// Cross-browser xml parsing
|
|
jQuery.parseXML = function( data ) {
|
|
var xml;
|
|
if ( !data || typeof data !== "string" ) {
|
|
return null;
|
|
}
|
|
|
|
// Support: IE 9 - 11 only
|
|
// IE throws on parseFromString with invalid input.
|
|
try {
|
|
xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
|
|
} catch ( e ) {
|
|
xml = undefined;
|
|
}
|
|
|
|
if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
|
|
jQuery.error( "Invalid XML: " + data );
|
|
}
|
|
return xml;
|
|
};
|
|
|
|
|
|
var
|
|
rbracket = /\[\]$/,
|
|
rCRLF = /\r?\n/g,
|
|
rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
|
|
rsubmittable = /^(?:input|select|textarea|keygen)/i;
|
|
|
|
function buildParams( prefix, obj, traditional, add ) {
|
|
var name;
|
|
|
|
if ( Array.isArray( obj ) ) {
|
|
|
|
// Serialize array item.
|
|
jQuery.each( obj, function( i, v ) {
|
|
if ( traditional || rbracket.test( prefix ) ) {
|
|
|
|
// Treat each array item as a scalar.
|
|
add( prefix, v );
|
|
|
|
} else {
|
|
|
|
// Item is non-scalar (array or object), encode its numeric index.
|
|
buildParams(
|
|
prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
|
|
v,
|
|
traditional,
|
|
add
|
|
);
|
|
}
|
|
} );
|
|
|
|
} else if ( !traditional && toType( obj ) === "object" ) {
|
|
|
|
// Serialize object item.
|
|
for ( name in obj ) {
|
|
buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
|
|
}
|
|
|
|
} else {
|
|
|
|
// Serialize scalar item.
|
|
add( prefix, obj );
|
|
}
|
|
}
|
|
|
|
// Serialize an array of form elements or a set of
|
|
// key/values into a query string
|
|
jQuery.param = function( a, traditional ) {
|
|
var prefix,
|
|
s = [],
|
|
add = function( key, valueOrFunction ) {
|
|
|
|
// If value is a function, invoke it and use its return value
|
|
var value = isFunction( valueOrFunction ) ?
|
|
valueOrFunction() :
|
|
valueOrFunction;
|
|
|
|
s[ s.length ] = encodeURIComponent( key ) + "=" +
|
|
encodeURIComponent( value == null ? "" : value );
|
|
};
|
|
|
|
if ( a == null ) {
|
|
return "";
|
|
}
|
|
|
|
// If an array was passed in, assume that it is an array of form elements.
|
|
if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
|
|
|
|
// Serialize the form elements
|
|
jQuery.each( a, function() {
|
|
add( this.name, this.value );
|
|
} );
|
|
|
|
} else {
|
|
|
|
// If traditional, encode the "old" way (the way 1.3.2 or older
|
|
// did it), otherwise encode params recursively.
|
|
for ( prefix in a ) {
|
|
buildParams( prefix, a[ prefix ], traditional, add );
|
|
}
|
|
}
|
|
|
|
// Return the resulting serialization
|
|
return s.join( "&" );
|
|
};
|
|
|
|
jQuery.fn.extend( {
|
|
serialize: function() {
|
|
return jQuery.param( this.serializeArray() );
|
|
},
|
|
serializeArray: function() {
|
|
return this.map( function() {
|
|
|
|
// Can add propHook for "elements" to filter or add form elements
|
|
var elements = jQuery.prop( this, "elements" );
|
|
return elements ? jQuery.makeArray( elements ) : this;
|
|
} )
|
|
.filter( function() {
|
|
var type = this.type;
|
|
|
|
// Use .is( ":disabled" ) so that fieldset[disabled] works
|
|
return this.name && !jQuery( this ).is( ":disabled" ) &&
|
|
rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
|
|
( this.checked || !rcheckableType.test( type ) );
|
|
} )
|
|
.map( function( _i, elem ) {
|
|
var val = jQuery( this ).val();
|
|
|
|
if ( val == null ) {
|
|
return null;
|
|
}
|
|
|
|
if ( Array.isArray( val ) ) {
|
|
return jQuery.map( val, function( val ) {
|
|
return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
|
|
} );
|
|
}
|
|
|
|
return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
|
|
} ).get();
|
|
}
|
|
} );
|
|
|
|
|
|
var
|
|
r20 = /%20/g,
|
|
rhash = /#.*$/,
|
|
rantiCache = /([?&])_=[^&]*/,
|
|
rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
|
|
|
|
// #7653, #8125, #8152: local protocol detection
|
|
rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
|
|
rnoContent = /^(?:GET|HEAD)$/,
|
|
rprotocol = /^\/\//,
|
|
|
|
/* Prefilters
|
|
* 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
|
|
* 2) These are called:
|
|
* - BEFORE asking for a transport
|
|
* - AFTER param serialization (s.data is a string if s.processData is true)
|
|
* 3) key is the dataType
|
|
* 4) the catchall symbol "*" can be used
|
|
* 5) execution will start with transport dataType and THEN continue down to "*" if needed
|
|
*/
|
|
prefilters = {},
|
|
|
|
/* Transports bindings
|
|
* 1) key is the dataType
|
|
* 2) the catchall symbol "*" can be used
|
|
* 3) selection will start with transport dataType and THEN go to "*" if needed
|
|
*/
|
|
transports = {},
|
|
|
|
// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
|
|
allTypes = "*/".concat( "*" ),
|
|
|
|
// Anchor tag for parsing the document origin
|
|
originAnchor = document.createElement( "a" );
|
|
originAnchor.href = location.href;
|
|
|
|
// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
|
|
function addToPrefiltersOrTransports( structure ) {
|
|
|
|
// dataTypeExpression is optional and defaults to "*"
|
|
return function( dataTypeExpression, func ) {
|
|
|
|
if ( typeof dataTypeExpression !== "string" ) {
|
|
func = dataTypeExpression;
|
|
dataTypeExpression = "*";
|
|
}
|
|
|
|
var dataType,
|
|
i = 0,
|
|
dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
|
|
|
|
if ( isFunction( func ) ) {
|
|
|
|
// For each dataType in the dataTypeExpression
|
|
while ( ( dataType = dataTypes[ i++ ] ) ) {
|
|
|
|
// Prepend if requested
|
|
if ( dataType[ 0 ] === "+" ) {
|
|
dataType = dataType.slice( 1 ) || "*";
|
|
( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
|
|
|
|
// Otherwise append
|
|
} else {
|
|
( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
// Base inspection function for prefilters and transports
|
|
function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
|
|
|
|
var inspected = {},
|
|
seekingTransport = ( structure === transports );
|
|
|
|
function inspect( dataType ) {
|
|
var selected;
|
|
inspected[ dataType ] = true;
|
|
jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
|
|
var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
|
|
if ( typeof dataTypeOrTransport === "string" &&
|
|
!seekingTransport && !inspected[ dataTypeOrTransport ] ) {
|
|
|
|
options.dataTypes.unshift( dataTypeOrTransport );
|
|
inspect( dataTypeOrTransport );
|
|
return false;
|
|
} else if ( seekingTransport ) {
|
|
return !( selected = dataTypeOrTransport );
|
|
}
|
|
} );
|
|
return selected;
|
|
}
|
|
|
|
return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
|
|
}
|
|
|
|
// A special extend for ajax options
|
|
// that takes "flat" options (not to be deep extended)
|
|
// Fixes #9887
|
|
function ajaxExtend( target, src ) {
|
|
var key, deep,
|
|
flatOptions = jQuery.ajaxSettings.flatOptions || {};
|
|
|
|
for ( key in src ) {
|
|
if ( src[ key ] !== undefined ) {
|
|
( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
|
|
}
|
|
}
|
|
if ( deep ) {
|
|
jQuery.extend( true, target, deep );
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
/* Handles responses to an ajax request:
|
|
* - finds the right dataType (mediates between content-type and expected dataType)
|
|
* - returns the corresponding response
|
|
*/
|
|
function ajaxHandleResponses( s, jqXHR, responses ) {
|
|
|
|
var ct, type, finalDataType, firstDataType,
|
|
contents = s.contents,
|
|
dataTypes = s.dataTypes;
|
|
|
|
// Remove auto dataType and get content-type in the process
|
|
while ( dataTypes[ 0 ] === "*" ) {
|
|
dataTypes.shift();
|
|
if ( ct === undefined ) {
|
|
ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
|
|
}
|
|
}
|
|
|
|
// Check if we're dealing with a known content-type
|
|
if ( ct ) {
|
|
for ( type in contents ) {
|
|
if ( contents[ type ] && contents[ type ].test( ct ) ) {
|
|
dataTypes.unshift( type );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check to see if we have a response for the expected dataType
|
|
if ( dataTypes[ 0 ] in responses ) {
|
|
finalDataType = dataTypes[ 0 ];
|
|
} else {
|
|
|
|
// Try convertible dataTypes
|
|
for ( type in responses ) {
|
|
if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
|
|
finalDataType = type;
|
|
break;
|
|
}
|
|
if ( !firstDataType ) {
|
|
firstDataType = type;
|
|
}
|
|
}
|
|
|
|
// Or just use first one
|
|
finalDataType = finalDataType || firstDataType;
|
|
}
|
|
|
|
// If we found a dataType
|
|
// We add the dataType to the list if needed
|
|
// and return the corresponding response
|
|
if ( finalDataType ) {
|
|
if ( finalDataType !== dataTypes[ 0 ] ) {
|
|
dataTypes.unshift( finalDataType );
|
|
}
|
|
return responses[ finalDataType ];
|
|
}
|
|
}
|
|
|
|
/* Chain conversions given the request and the original response
|
|
* Also sets the responseXXX fields on the jqXHR instance
|
|
*/
|
|
function ajaxConvert( s, response, jqXHR, isSuccess ) {
|
|
var conv2, current, conv, tmp, prev,
|
|
converters = {},
|
|
|
|
// Work with a copy of dataTypes in case we need to modify it for conversion
|
|
dataTypes = s.dataTypes.slice();
|
|
|
|
// Create converters map with lowercased keys
|
|
if ( dataTypes[ 1 ] ) {
|
|
for ( conv in s.converters ) {
|
|
converters[ conv.toLowerCase() ] = s.converters[ conv ];
|
|
}
|
|
}
|
|
|
|
current = dataTypes.shift();
|
|
|
|
// Convert to each sequential dataType
|
|
while ( current ) {
|
|
|
|
if ( s.responseFields[ current ] ) {
|
|
jqXHR[ s.responseFields[ current ] ] = response;
|
|
}
|
|
|
|
// Apply the dataFilter if provided
|
|
if ( !prev && isSuccess && s.dataFilter ) {
|
|
response = s.dataFilter( response, s.dataType );
|
|
}
|
|
|
|
prev = current;
|
|
current = dataTypes.shift();
|
|
|
|
if ( current ) {
|
|
|
|
// There's only work to do if current dataType is non-auto
|
|
if ( current === "*" ) {
|
|
|
|
current = prev;
|
|
|
|
// Convert response if prev dataType is non-auto and differs from current
|
|
} else if ( prev !== "*" && prev !== current ) {
|
|
|
|
// Seek a direct converter
|
|
conv = converters[ prev + " " + current ] || converters[ "* " + current ];
|
|
|
|
// If none found, seek a pair
|
|
if ( !conv ) {
|
|
for ( conv2 in converters ) {
|
|
|
|
// If conv2 outputs current
|
|
tmp = conv2.split( " " );
|
|
if ( tmp[ 1 ] === current ) {
|
|
|
|
// If prev can be converted to accepted input
|
|
conv = converters[ prev + " " + tmp[ 0 ] ] ||
|
|
converters[ "* " + tmp[ 0 ] ];
|
|
if ( conv ) {
|
|
|
|
// Condense equivalence converters
|
|
if ( conv === true ) {
|
|
conv = converters[ conv2 ];
|
|
|
|
// Otherwise, insert the intermediate dataType
|
|
} else if ( converters[ conv2 ] !== true ) {
|
|
current = tmp[ 0 ];
|
|
dataTypes.unshift( tmp[ 1 ] );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Apply converter (if not an equivalence)
|
|
if ( conv !== true ) {
|
|
|
|
// Unless errors are allowed to bubble, catch and return them
|
|
if ( conv && s.throws ) {
|
|
response = conv( response );
|
|
} else {
|
|
try {
|
|
response = conv( response );
|
|
} catch ( e ) {
|
|
return {
|
|
state: "parsererror",
|
|
error: conv ? e : "No conversion from " + prev + " to " + current
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return { state: "success", data: response };
|
|
}
|
|
|
|
jQuery.extend( {
|
|
|
|
// Counter for holding the number of active queries
|
|
active: 0,
|
|
|
|
// Last-Modified header cache for next request
|
|
lastModified: {},
|
|
etag: {},
|
|
|
|
ajaxSettings: {
|
|
url: location.href,
|
|
type: "GET",
|
|
isLocal: rlocalProtocol.test( location.protocol ),
|
|
global: true,
|
|
processData: true,
|
|
async: true,
|
|
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
|
|
|
|
/*
|
|
timeout: 0,
|
|
data: null,
|
|
dataType: null,
|
|
username: null,
|
|
password: null,
|
|
cache: null,
|
|
throws: false,
|
|
traditional: false,
|
|
headers: {},
|
|
*/
|
|
|
|
accepts: {
|
|
"*": allTypes,
|
|
text: "text/plain",
|
|
html: "text/html",
|
|
xml: "application/xml, text/xml",
|
|
json: "application/json, text/javascript"
|
|
},
|
|
|
|
contents: {
|
|
xml: /\bxml\b/,
|
|
html: /\bhtml/,
|
|
json: /\bjson\b/
|
|
},
|
|
|
|
responseFields: {
|
|
xml: "responseXML",
|
|
text: "responseText",
|
|
json: "responseJSON"
|
|
},
|
|
|
|
// Data converters
|
|
// Keys separate source (or catchall "*") and destination types with a single space
|
|
converters: {
|
|
|
|
// Convert anything to text
|
|
"* text": String,
|
|
|
|
// Text to html (true = no transformation)
|
|
"text html": true,
|
|
|
|
// Evaluate text as a json expression
|
|
"text json": JSON.parse,
|
|
|
|
// Parse text as xml
|
|
"text xml": jQuery.parseXML
|
|
},
|
|
|
|
// For options that shouldn't be deep extended:
|
|
// you can add your own custom options here if
|
|
// and when you create one that shouldn't be
|
|
// deep extended (see ajaxExtend)
|
|
flatOptions: {
|
|
url: true,
|
|
context: true
|
|
}
|
|
},
|
|
|
|
// Creates a full fledged settings object into target
|
|
// with both ajaxSettings and settings fields.
|
|
// If target is omitted, writes into ajaxSettings.
|
|
ajaxSetup: function( target, settings ) {
|
|
return settings ?
|
|
|
|
// Building a settings object
|
|
ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
|
|
|
|
// Extending ajaxSettings
|
|
ajaxExtend( jQuery.ajaxSettings, target );
|
|
},
|
|
|
|
ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
|
|
ajaxTransport: addToPrefiltersOrTransports( transports ),
|
|
|
|
// Main method
|
|
ajax: function( url, options ) {
|
|
|
|
// If url is an object, simulate pre-1.5 signature
|
|
if ( typeof url === "object" ) {
|
|
options = url;
|
|
url = undefined;
|
|
}
|
|
|
|
// Force options to be an object
|
|
options = options || {};
|
|
|
|
var transport,
|
|
|
|
// URL without anti-cache param
|
|
cacheURL,
|
|
|
|
// Response headers
|
|
responseHeadersString,
|
|
responseHeaders,
|
|
|
|
// timeout handle
|
|
timeoutTimer,
|
|
|
|
// Url cleanup var
|
|
urlAnchor,
|
|
|
|
// Request state (becomes false upon send and true upon completion)
|
|
completed,
|
|
|
|
// To know if global events are to be dispatched
|
|
fireGlobals,
|
|
|
|
// Loop variable
|
|
i,
|
|
|
|
// uncached part of the url
|
|
uncached,
|
|
|
|
// Create the final options object
|
|
s = jQuery.ajaxSetup( {}, options ),
|
|
|
|
// Callbacks context
|
|
callbackContext = s.context || s,
|
|
|
|
// Context for global events is callbackContext if it is a DOM node or jQuery collection
|
|
globalEventContext = s.context &&
|
|
( callbackContext.nodeType || callbackContext.jquery ) ?
|
|
jQuery( callbackContext ) :
|
|
jQuery.event,
|
|
|
|
// Deferreds
|
|
deferred = jQuery.Deferred(),
|
|
completeDeferred = jQuery.Callbacks( "once memory" ),
|
|
|
|
// Status-dependent callbacks
|
|
statusCode = s.statusCode || {},
|
|
|
|
// Headers (they are sent all at once)
|
|
requestHeaders = {},
|
|
requestHeadersNames = {},
|
|
|
|
// Default abort message
|
|
strAbort = "canceled",
|
|
|
|
// Fake xhr
|
|
jqXHR = {
|
|
readyState: 0,
|
|
|
|
// Builds headers hashtable if needed
|
|
getResponseHeader: function( key ) {
|
|
var match;
|
|
if ( completed ) {
|
|
if ( !responseHeaders ) {
|
|
responseHeaders = {};
|
|
while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
|
|
responseHeaders[ match[ 1 ].toLowerCase() + " " ] =
|
|
( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] )
|
|
.concat( match[ 2 ] );
|
|
}
|
|
}
|
|
match = responseHeaders[ key.toLowerCase() + " " ];
|
|
}
|
|
return match == null ? null : match.join( ", " );
|
|
},
|
|
|
|
// Raw string
|
|
getAllResponseHeaders: function() {
|
|
return completed ? responseHeadersString : null;
|
|
},
|
|
|
|
// Caches the header
|
|
setRequestHeader: function( name, value ) {
|
|
if ( completed == null ) {
|
|
name = requestHeadersNames[ name.toLowerCase() ] =
|
|
requestHeadersNames[ name.toLowerCase() ] || name;
|
|
requestHeaders[ name ] = value;
|
|
}
|
|
return this;
|
|
},
|
|
|
|
// Overrides response content-type header
|
|
overrideMimeType: function( type ) {
|
|
if ( completed == null ) {
|
|
s.mimeType = type;
|
|
}
|
|
return this;
|
|
},
|
|
|
|
// Status-dependent callbacks
|
|
statusCode: function( map ) {
|
|
var code;
|
|
if ( map ) {
|
|
if ( completed ) {
|
|
|
|
// Execute the appropriate callbacks
|
|
jqXHR.always( map[ jqXHR.status ] );
|
|
} else {
|
|
|
|
// Lazy-add the new callbacks in a way that preserves old ones
|
|
for ( code in map ) {
|
|
statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
|
|
// Cancel the request
|
|
abort: function( statusText ) {
|
|
var finalText = statusText || strAbort;
|
|
if ( transport ) {
|
|
transport.abort( finalText );
|
|
}
|
|
done( 0, finalText );
|
|
return this;
|
|
}
|
|
};
|
|
|
|
// Attach deferreds
|
|
deferred.promise( jqXHR );
|
|
|
|
// Add protocol if not provided (prefilters might expect it)
|
|
// Handle falsy url in the settings object (#10093: consistency with old signature)
|
|
// We also use the url parameter if available
|
|
s.url = ( ( url || s.url || location.href ) + "" )
|
|
.replace( rprotocol, location.protocol + "//" );
|
|
|
|
// Alias method option to type as per ticket #12004
|
|
s.type = options.method || options.type || s.method || s.type;
|
|
|
|
// Extract dataTypes list
|
|
s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
|
|
|
|
// A cross-domain request is in order when the origin doesn't match the current origin.
|
|
if ( s.crossDomain == null ) {
|
|
urlAnchor = document.createElement( "a" );
|
|
|
|
// Support: IE <=8 - 11, Edge 12 - 15
|
|
// IE throws exception on accessing the href property if url is malformed,
|
|
// e.g. http://example.com:80x/
|
|
try {
|
|
urlAnchor.href = s.url;
|
|
|
|
// Support: IE <=8 - 11 only
|
|
// Anchor's host property isn't correctly set when s.url is relative
|
|
urlAnchor.href = urlAnchor.href;
|
|
s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
|
|
urlAnchor.protocol + "//" + urlAnchor.host;
|
|
} catch ( e ) {
|
|
|
|
// If there is an error parsing the URL, assume it is crossDomain,
|
|
// it can be rejected by the transport if it is invalid
|
|
s.crossDomain = true;
|
|
}
|
|
}
|
|
|
|
// Convert data if not already a string
|
|
if ( s.data && s.processData && typeof s.data !== "string" ) {
|
|
s.data = jQuery.param( s.data, s.traditional );
|
|
}
|
|
|
|
// Apply prefilters
|
|
inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
|
|
|
|
// If request was aborted inside a prefilter, stop there
|
|
if ( completed ) {
|
|
return jqXHR;
|
|
}
|
|
|
|
// We can fire global events as of now if asked to
|
|
// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
|
|
fireGlobals = jQuery.event && s.global;
|
|
|
|
// Watch for a new set of requests
|
|
if ( fireGlobals && jQuery.active++ === 0 ) {
|
|
jQuery.event.trigger( "ajaxStart" );
|
|
}
|
|
|
|
// Uppercase the type
|
|
s.type = s.type.toUpperCase();
|
|
|
|
// Determine if request has content
|
|
s.hasContent = !rnoContent.test( s.type );
|
|
|
|
// Save the URL in case we're toying with the If-Modified-Since
|
|
// and/or If-None-Match header later on
|
|
// Remove hash to simplify url manipulation
|
|
cacheURL = s.url.replace( rhash, "" );
|
|
|
|
// More options handling for requests with no content
|
|
if ( !s.hasContent ) {
|
|
|
|
// Remember the hash so we can put it back
|
|
uncached = s.url.slice( cacheURL.length );
|
|
|
|
// If data is available and should be processed, append data to url
|
|
if ( s.data && ( s.processData || typeof s.data === "string" ) ) {
|
|
cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
|
|
|
|
// #9682: remove data so that it's not used in an eventual retry
|
|
delete s.data;
|
|
}
|
|
|
|
// Add or update anti-cache param if needed
|
|
if ( s.cache === false ) {
|
|
cacheURL = cacheURL.replace( rantiCache, "$1" );
|
|
uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) +
|
|
uncached;
|
|
}
|
|
|
|
// Put hash and anti-cache on the URL that will be requested (gh-1732)
|
|
s.url = cacheURL + uncached;
|
|
|
|
// Change '%20' to '+' if this is encoded form body content (gh-2658)
|
|
} else if ( s.data && s.processData &&
|
|
( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
|
|
s.data = s.data.replace( r20, "+" );
|
|
}
|
|
|
|
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
|
|
if ( s.ifModified ) {
|
|
if ( jQuery.lastModified[ cacheURL ] ) {
|
|
jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
|
|
}
|
|
if ( jQuery.etag[ cacheURL ] ) {
|
|
jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
|
|
}
|
|
}
|
|
|
|
// Set the correct header, if data is being sent
|
|
if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
|
|
jqXHR.setRequestHeader( "Content-Type", s.contentType );
|
|
}
|
|
|
|
// Set the Accepts header for the server, depending on the dataType
|
|
jqXHR.setRequestHeader(
|
|
"Accept",
|
|
s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
|
|
s.accepts[ s.dataTypes[ 0 ] ] +
|
|
( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
|
|
s.accepts[ "*" ]
|
|
);
|
|
|
|
// Check for headers option
|
|
for ( i in s.headers ) {
|
|
jqXHR.setRequestHeader( i, s.headers[ i ] );
|
|
}
|
|
|
|
// Allow custom headers/mimetypes and early abort
|
|
if ( s.beforeSend &&
|
|
( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
|
|
|
|
// Abort if not done already and return
|
|
return jqXHR.abort();
|
|
}
|
|
|
|
// Aborting is no longer a cancellation
|
|
strAbort = "abort";
|
|
|
|
// Install callbacks on deferreds
|
|
completeDeferred.add( s.complete );
|
|
jqXHR.done( s.success );
|
|
jqXHR.fail( s.error );
|
|
|
|
// Get transport
|
|
transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
|
|
|
|
// If no transport, we auto-abort
|
|
if ( !transport ) {
|
|
done( -1, "No Transport" );
|
|
} else {
|
|
jqXHR.readyState = 1;
|
|
|
|
// Send global event
|
|
if ( fireGlobals ) {
|
|
globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
|
|
}
|
|
|
|
// If request was aborted inside ajaxSend, stop there
|
|
if ( completed ) {
|
|
return jqXHR;
|
|
}
|
|
|
|
// Timeout
|
|
if ( s.async && s.timeout > 0 ) {
|
|
timeoutTimer = window.setTimeout( function() {
|
|
jqXHR.abort( "timeout" );
|
|
}, s.timeout );
|
|
}
|
|
|
|
try {
|
|
completed = false;
|
|
transport.send( requestHeaders, done );
|
|
} catch ( e ) {
|
|
|
|
// Rethrow post-completion exceptions
|
|
if ( completed ) {
|
|
throw e;
|
|
}
|
|
|
|
// Propagate others as results
|
|
done( -1, e );
|
|
}
|
|
}
|
|
|
|
// Callback for when everything is done
|
|
function done( status, nativeStatusText, responses, headers ) {
|
|
var isSuccess, success, error, response, modified,
|
|
statusText = nativeStatusText;
|
|
|
|
// Ignore repeat invocations
|
|
if ( completed ) {
|
|
return;
|
|
}
|
|
|
|
completed = true;
|
|
|
|
// Clear timeout if it exists
|
|
if ( timeoutTimer ) {
|
|
window.clearTimeout( timeoutTimer );
|
|
}
|
|
|
|
// Dereference transport for early garbage collection
|
|
// (no matter how long the jqXHR object will be used)
|
|
transport = undefined;
|
|
|
|
// Cache response headers
|
|
responseHeadersString = headers || "";
|
|
|
|
// Set readyState
|
|
jqXHR.readyState = status > 0 ? 4 : 0;
|
|
|
|
// Determine if successful
|
|
isSuccess = status >= 200 && status < 300 || status === 304;
|
|
|
|
// Get response data
|
|
if ( responses ) {
|
|
response = ajaxHandleResponses( s, jqXHR, responses );
|
|
}
|
|
|
|
// Use a noop converter for missing script
|
|
if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) {
|
|
s.converters[ "text script" ] = function() {};
|
|
}
|
|
|
|
// Convert no matter what (that way responseXXX fields are always set)
|
|
response = ajaxConvert( s, response, jqXHR, isSuccess );
|
|
|
|
// If successful, handle type chaining
|
|
if ( isSuccess ) {
|
|
|
|
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
|
|
if ( s.ifModified ) {
|
|
modified = jqXHR.getResponseHeader( "Last-Modified" );
|
|
if ( modified ) {
|
|
jQuery.lastModified[ cacheURL ] = modified;
|
|
}
|
|
modified = jqXHR.getResponseHeader( "etag" );
|
|
if ( modified ) {
|
|
jQuery.etag[ cacheURL ] = modified;
|
|
}
|
|
}
|
|
|
|
// if no content
|
|
if ( status === 204 || s.type === "HEAD" ) {
|
|
statusText = "nocontent";
|
|
|
|
// if not modified
|
|
} else if ( status === 304 ) {
|
|
statusText = "notmodified";
|
|
|
|
// If we have data, let's convert it
|
|
} else {
|
|
statusText = response.state;
|
|
success = response.data;
|
|
error = response.error;
|
|
isSuccess = !error;
|
|
}
|
|
} else {
|
|
|
|
// Extract error from statusText and normalize for non-aborts
|
|
error = statusText;
|
|
if ( status || !statusText ) {
|
|
statusText = "error";
|
|
if ( status < 0 ) {
|
|
status = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set data for the fake xhr object
|
|
jqXHR.status = status;
|
|
jqXHR.statusText = ( nativeStatusText || statusText ) + "";
|
|
|
|
// Success/Error
|
|
if ( isSuccess ) {
|
|
deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
|
|
} else {
|
|
deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
|
|
}
|
|
|
|
// Status-dependent callbacks
|
|
jqXHR.statusCode( statusCode );
|
|
statusCode = undefined;
|
|
|
|
if ( fireGlobals ) {
|
|
globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
|
|
[ jqXHR, s, isSuccess ? success : error ] );
|
|
}
|
|
|
|
// Complete
|
|
completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
|
|
|
|
if ( fireGlobals ) {
|
|
globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
|
|
|
|
// Handle the global AJAX counter
|
|
if ( !( --jQuery.active ) ) {
|
|
jQuery.event.trigger( "ajaxStop" );
|
|
}
|
|
}
|
|
}
|
|
|
|
return jqXHR;
|
|
},
|
|
|
|
getJSON: function( url, data, callback ) {
|
|
return jQuery.get( url, data, callback, "json" );
|
|
},
|
|
|
|
getScript: function( url, callback ) {
|
|
return jQuery.get( url, undefined, callback, "script" );
|
|
}
|
|
} );
|
|
|
|
jQuery.each( [ "get", "post" ], function( _i, method ) {
|
|
jQuery[ method ] = function( url, data, callback, type ) {
|
|
|
|
// Shift arguments if data argument was omitted
|
|
if ( isFunction( data ) ) {
|
|
type = type || callback;
|
|
callback = data;
|
|
data = undefined;
|
|
}
|
|
|
|
// The url can be an options object (which then must have .url)
|
|
return jQuery.ajax( jQuery.extend( {
|
|
url: url,
|
|
type: method,
|
|
dataType: type,
|
|
data: data,
|
|
success: callback
|
|
}, jQuery.isPlainObject( url ) && url ) );
|
|
};
|
|
} );
|
|
|
|
jQuery.ajaxPrefilter( function( s ) {
|
|
var i;
|
|
for ( i in s.headers ) {
|
|
if ( i.toLowerCase() === "content-type" ) {
|
|
s.contentType = s.headers[ i ] || "";
|
|
}
|
|
}
|
|
} );
|
|
|
|
|
|
jQuery._evalUrl = function( url, options, doc ) {
|
|
return jQuery.ajax( {
|
|
url: url,
|
|
|
|
// Make this explicit, since user can override this through ajaxSetup (#11264)
|
|
type: "GET",
|
|
dataType: "script",
|
|
cache: true,
|
|
async: false,
|
|
global: false,
|
|
|
|
// Only evaluate the response if it is successful (gh-4126)
|
|
// dataFilter is not invoked for failure responses, so using it instead
|
|
// of the default converter is kludgy but it works.
|
|
converters: {
|
|
"text script": function() {}
|
|
},
|
|
dataFilter: function( response ) {
|
|
jQuery.globalEval( response, options, doc );
|
|
}
|
|
} );
|
|
};
|
|
|
|
|
|
jQuery.fn.extend( {
|
|
wrapAll: function( html ) {
|
|
var wrap;
|
|
|
|
if ( this[ 0 ] ) {
|
|
if ( isFunction( html ) ) {
|
|
html = html.call( this[ 0 ] );
|
|
}
|
|
|
|
// The elements to wrap the target around
|
|
wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
|
|
|
|
if ( this[ 0 ].parentNode ) {
|
|
wrap.insertBefore( this[ 0 ] );
|
|
}
|
|
|
|
wrap.map( function() {
|
|
var elem = this;
|
|
|
|
while ( elem.firstElementChild ) {
|
|
elem = elem.firstElementChild;
|
|
}
|
|
|
|
return elem;
|
|
} ).append( this );
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
wrapInner: function( html ) {
|
|
if ( isFunction( html ) ) {
|
|
return this.each( function( i ) {
|
|
jQuery( this ).wrapInner( html.call( this, i ) );
|
|
} );
|
|
}
|
|
|
|
return this.each( function() {
|
|
var self = jQuery( this ),
|
|
contents = self.contents();
|
|
|
|
if ( contents.length ) {
|
|
contents.wrapAll( html );
|
|
|
|
} else {
|
|
self.append( html );
|
|
}
|
|
} );
|
|
},
|
|
|
|
wrap: function( html ) {
|
|
var htmlIsFunction = isFunction( html );
|
|
|
|
return this.each( function( i ) {
|
|
jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );
|
|
} );
|
|
},
|
|
|
|
unwrap: function( selector ) {
|
|
this.parent( selector ).not( "body" ).each( function() {
|
|
jQuery( this ).replaceWith( this.childNodes );
|
|
} );
|
|
return this;
|
|
}
|
|
} );
|
|
|
|
|
|
jQuery.expr.pseudos.hidden = function( elem ) {
|
|
return !jQuery.expr.pseudos.visible( elem );
|
|
};
|
|
jQuery.expr.pseudos.visible = function( elem ) {
|
|
return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
|
|
};
|
|
|
|
|
|
|
|
|
|
jQuery.ajaxSettings.xhr = function() {
|
|
try {
|
|
return new window.XMLHttpRequest();
|
|
} catch ( e ) {}
|
|
};
|
|
|
|
var xhrSuccessStatus = {
|
|
|
|
// File protocol always yields status code 0, assume 200
|
|
0: 200,
|
|
|
|
// Support: IE <=9 only
|
|
// #1450: sometimes IE returns 1223 when it should be 204
|
|
1223: 204
|
|
},
|
|
xhrSupported = jQuery.ajaxSettings.xhr();
|
|
|
|
support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
|
|
support.ajax = xhrSupported = !!xhrSupported;
|
|
|
|
jQuery.ajaxTransport( function( options ) {
|
|
var callback, errorCallback;
|
|
|
|
// Cross domain only allowed if supported through XMLHttpRequest
|
|
if ( support.cors || xhrSupported && !options.crossDomain ) {
|
|
return {
|
|
send: function( headers, complete ) {
|
|
var i,
|
|
xhr = options.xhr();
|
|
|
|
xhr.open(
|
|
options.type,
|
|
options.url,
|
|
options.async,
|
|
options.username,
|
|
options.password
|
|
);
|
|
|
|
// Apply custom fields if provided
|
|
if ( options.xhrFields ) {
|
|
for ( i in options.xhrFields ) {
|
|
xhr[ i ] = options.xhrFields[ i ];
|
|
}
|
|
}
|
|
|
|
// Override mime type if needed
|
|
if ( options.mimeType && xhr.overrideMimeType ) {
|
|
xhr.overrideMimeType( options.mimeType );
|
|
}
|
|
|
|
// X-Requested-With header
|
|
// For cross-domain requests, seeing as conditions for a preflight are
|
|
// akin to a jigsaw puzzle, we simply never set it to be sure.
|
|
// (it can always be set on a per-request basis or even using ajaxSetup)
|
|
// For same-domain requests, won't change header if already provided.
|
|
if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
|
|
headers[ "X-Requested-With" ] = "XMLHttpRequest";
|
|
}
|
|
|
|
// Set headers
|
|
for ( i in headers ) {
|
|
xhr.setRequestHeader( i, headers[ i ] );
|
|
}
|
|
|
|
// Callback
|
|
callback = function( type ) {
|
|
return function() {
|
|
if ( callback ) {
|
|
callback = errorCallback = xhr.onload =
|
|
xhr.onerror = xhr.onabort = xhr.ontimeout =
|
|
xhr.onreadystatechange = null;
|
|
|
|
if ( type === "abort" ) {
|
|
xhr.abort();
|
|
} else if ( type === "error" ) {
|
|
|
|
// Support: IE <=9 only
|
|
// On a manual native abort, IE9 throws
|
|
// errors on any property access that is not readyState
|
|
if ( typeof xhr.status !== "number" ) {
|
|
complete( 0, "error" );
|
|
} else {
|
|
complete(
|
|
|
|
// File: protocol always yields status 0; see #8605, #14207
|
|
xhr.status,
|
|
xhr.statusText
|
|
);
|
|
}
|
|
} else {
|
|
complete(
|
|
xhrSuccessStatus[ xhr.status ] || xhr.status,
|
|
xhr.statusText,
|
|
|
|
// Support: IE <=9 only
|
|
// IE9 has no XHR2 but throws on binary (trac-11426)
|
|
// For XHR2 non-text, let the caller handle it (gh-2498)
|
|
( xhr.responseType || "text" ) !== "text" ||
|
|
typeof xhr.responseText !== "string" ?
|
|
{ binary: xhr.response } :
|
|
{ text: xhr.responseText },
|
|
xhr.getAllResponseHeaders()
|
|
);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
// Listen to events
|
|
xhr.onload = callback();
|
|
errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" );
|
|
|
|
// Support: IE 9 only
|
|
// Use onreadystatechange to replace onabort
|
|
// to handle uncaught aborts
|
|
if ( xhr.onabort !== undefined ) {
|
|
xhr.onabort = errorCallback;
|
|
} else {
|
|
xhr.onreadystatechange = function() {
|
|
|
|
// Check readyState before timeout as it changes
|
|
if ( xhr.readyState === 4 ) {
|
|
|
|
// Allow onerror to be called first,
|
|
// but that will not handle a native abort
|
|
// Also, save errorCallback to a variable
|
|
// as xhr.onerror cannot be accessed
|
|
window.setTimeout( function() {
|
|
if ( callback ) {
|
|
errorCallback();
|
|
}
|
|
} );
|
|
}
|
|
};
|
|
}
|
|
|
|
// Create the abort callback
|
|
callback = callback( "abort" );
|
|
|
|
try {
|
|
|
|
// Do send the request (this may raise an exception)
|
|
xhr.send( options.hasContent && options.data || null );
|
|
} catch ( e ) {
|
|
|
|
// #14683: Only rethrow if this hasn't been notified as an error yet
|
|
if ( callback ) {
|
|
throw e;
|
|
}
|
|
}
|
|
},
|
|
|
|
abort: function() {
|
|
if ( callback ) {
|
|
callback();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
} );
|
|
|
|
|
|
|
|
|
|
// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
|
|
jQuery.ajaxPrefilter( function( s ) {
|
|
if ( s.crossDomain ) {
|
|
s.contents.script = false;
|
|
}
|
|
} );
|
|
|
|
// Install script dataType
|
|
jQuery.ajaxSetup( {
|
|
accepts: {
|
|
script: "text/javascript, application/javascript, " +
|
|
"application/ecmascript, application/x-ecmascript"
|
|
},
|
|
contents: {
|
|
script: /\b(?:java|ecma)script\b/
|
|
},
|
|
converters: {
|
|
"text script": function( text ) {
|
|
jQuery.globalEval( text );
|
|
return text;
|
|
}
|
|
}
|
|
} );
|
|
|
|
// Handle cache's special case and crossDomain
|
|
jQuery.ajaxPrefilter( "script", function( s ) {
|
|
if ( s.cache === undefined ) {
|
|
s.cache = false;
|
|
}
|
|
if ( s.crossDomain ) {
|
|
s.type = "GET";
|
|
}
|
|
} );
|
|
|
|
// Bind script tag hack transport
|
|
jQuery.ajaxTransport( "script", function( s ) {
|
|
|
|
// This transport only deals with cross domain or forced-by-attrs requests
|
|
if ( s.crossDomain || s.scriptAttrs ) {
|
|
var script, callback;
|
|
return {
|
|
send: function( _, complete ) {
|
|
script = jQuery( "<script>" )
|
|
.attr( s.scriptAttrs || {} )
|
|
.prop( { charset: s.scriptCharset, src: s.url } )
|
|
.on( "load error", callback = function( evt ) {
|
|
script.remove();
|
|
callback = null;
|
|
if ( evt ) {
|
|
complete( evt.type === "error" ? 404 : 200, evt.type );
|
|
}
|
|
} );
|
|
|
|
// Use native DOM manipulation to avoid our domManip AJAX trickery
|
|
document.head.appendChild( script[ 0 ] );
|
|
},
|
|
abort: function() {
|
|
if ( callback ) {
|
|
callback();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
} );
|
|
|
|
|
|
|
|
|
|
var oldCallbacks = [],
|
|
rjsonp = /(=)\?(?=&|$)|\?\?/;
|
|
|
|
// Default jsonp settings
|
|
jQuery.ajaxSetup( {
|
|
jsonp: "callback",
|
|
jsonpCallback: function() {
|
|
var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce.guid++ ) );
|
|
this[ callback ] = true;
|
|
return callback;
|
|
}
|
|
} );
|
|
|
|
// Detect, normalize options and install callbacks for jsonp requests
|
|
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
|
|
|
|
var callbackName, overwritten, responseContainer,
|
|
jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
|
|
"url" :
|
|
typeof s.data === "string" &&
|
|
( s.contentType || "" )
|
|
.indexOf( "application/x-www-form-urlencoded" ) === 0 &&
|
|
rjsonp.test( s.data ) && "data"
|
|
);
|
|
|
|
// Handle iff the expected data type is "jsonp" or we have a parameter to set
|
|
if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
|
|
|
|
// Get callback name, remembering preexisting value associated with it
|
|
callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?
|
|
s.jsonpCallback() :
|
|
s.jsonpCallback;
|
|
|
|
// Insert callback into url or form data
|
|
if ( jsonProp ) {
|
|
s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
|
|
} else if ( s.jsonp !== false ) {
|
|
s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
|
|
}
|
|
|
|
// Use data converter to retrieve json after script execution
|
|
s.converters[ "script json" ] = function() {
|
|
if ( !responseContainer ) {
|
|
jQuery.error( callbackName + " was not called" );
|
|
}
|
|
return responseContainer[ 0 ];
|
|
};
|
|
|
|
// Force json dataType
|
|
s.dataTypes[ 0 ] = "json";
|
|
|
|
// Install callback
|
|
overwritten = window[ callbackName ];
|
|
window[ callbackName ] = function() {
|
|
responseContainer = arguments;
|
|
};
|
|
|
|
// Clean-up function (fires after converters)
|
|
jqXHR.always( function() {
|
|
|
|
// If previous value didn't exist - remove it
|
|
if ( overwritten === undefined ) {
|
|
jQuery( window ).removeProp( callbackName );
|
|
|
|
// Otherwise restore preexisting value
|
|
} else {
|
|
window[ callbackName ] = overwritten;
|
|
}
|
|
|
|
// Save back as free
|
|
if ( s[ callbackName ] ) {
|
|
|
|
// Make sure that re-using the options doesn't screw things around
|
|
s.jsonpCallback = originalSettings.jsonpCallback;
|
|
|
|
// Save the callback name for future use
|
|
oldCallbacks.push( callbackName );
|
|
}
|
|
|
|
// Call if it was a function and we have a response
|
|
if ( responseContainer && isFunction( overwritten ) ) {
|
|
overwritten( responseContainer[ 0 ] );
|
|
}
|
|
|
|
responseContainer = overwritten = undefined;
|
|
} );
|
|
|
|
// Delegate to script
|
|
return "script";
|
|
}
|
|
} );
|
|
|
|
|
|
|
|
|
|
// Support: Safari 8 only
|
|
// In Safari 8 documents created via document.implementation.createHTMLDocument
|
|
// collapse sibling forms: the second one becomes a child of the first one.
|
|
// Because of that, this security measure has to be disabled in Safari 8.
|
|
// https://bugs.webkit.org/show_bug.cgi?id=137337
|
|
support.createHTMLDocument = ( function() {
|
|
var body = document.implementation.createHTMLDocument( "" ).body;
|
|
body.innerHTML = "<form></form><form></form>";
|
|
return body.childNodes.length === 2;
|
|
} )();
|
|
|
|
|
|
// Argument "data" should be string of html
|
|
// context (optional): If specified, the fragment will be created in this context,
|
|
// defaults to document
|
|
// keepScripts (optional): If true, will include scripts passed in the html string
|
|
jQuery.parseHTML = function( data, context, keepScripts ) {
|
|
if ( typeof data !== "string" ) {
|
|
return [];
|
|
}
|
|
if ( typeof context === "boolean" ) {
|
|
keepScripts = context;
|
|
context = false;
|
|
}
|
|
|
|
var base, parsed, scripts;
|
|
|
|
if ( !context ) {
|
|
|
|
// Stop scripts or inline event handlers from being executed immediately
|
|
// by using document.implementation
|
|
if ( support.createHTMLDocument ) {
|
|
context = document.implementation.createHTMLDocument( "" );
|
|
|
|
// Set the base href for the created document
|
|
// so any parsed elements with URLs
|
|
// are based on the document's URL (gh-2965)
|
|
base = context.createElement( "base" );
|
|
base.href = document.location.href;
|
|
context.head.appendChild( base );
|
|
} else {
|
|
context = document;
|
|
}
|
|
}
|
|
|
|
parsed = rsingleTag.exec( data );
|
|
scripts = !keepScripts && [];
|
|
|
|
// Single tag
|
|
if ( parsed ) {
|
|
return [ context.createElement( parsed[ 1 ] ) ];
|
|
}
|
|
|
|
parsed = buildFragment( [ data ], context, scripts );
|
|
|
|
if ( scripts && scripts.length ) {
|
|
jQuery( scripts ).remove();
|
|
}
|
|
|
|
return jQuery.merge( [], parsed.childNodes );
|
|
};
|
|
|
|
|
|
/**
|
|
* Load a url into a page
|
|
*/
|
|
jQuery.fn.load = function( url, params, callback ) {
|
|
var selector, type, response,
|
|
self = this,
|
|
off = url.indexOf( " " );
|
|
|
|
if ( off > -1 ) {
|
|
selector = stripAndCollapse( url.slice( off ) );
|
|
url = url.slice( 0, off );
|
|
}
|
|
|
|
// If it's a function
|
|
if ( isFunction( params ) ) {
|
|
|
|
// We assume that it's the callback
|
|
callback = params;
|
|
params = undefined;
|
|
|
|
// Otherwise, build a param string
|
|
} else if ( params && typeof params === "object" ) {
|
|
type = "POST";
|
|
}
|
|
|
|
// If we have elements to modify, make the request
|
|
if ( self.length > 0 ) {
|
|
jQuery.ajax( {
|
|
url: url,
|
|
|
|
// If "type" variable is undefined, then "GET" method will be used.
|
|
// Make value of this field explicit since
|
|
// user can override it through ajaxSetup method
|
|
type: type || "GET",
|
|
dataType: "html",
|
|
data: params
|
|
} ).done( function( responseText ) {
|
|
|
|
// Save response for use in complete callback
|
|
response = arguments;
|
|
|
|
self.html( selector ?
|
|
|
|
// If a selector was specified, locate the right elements in a dummy div
|
|
// Exclude scripts to avoid IE 'Permission Denied' errors
|
|
jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
|
|
|
|
// Otherwise use the full result
|
|
responseText );
|
|
|
|
// If the request succeeds, this function gets "data", "status", "jqXHR"
|
|
// but they are ignored because response was set above.
|
|
// If it fails, this function gets "jqXHR", "status", "error"
|
|
} ).always( callback && function( jqXHR, status ) {
|
|
self.each( function() {
|
|
callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
|
|
} );
|
|
} );
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
|
|
|
|
|
|
jQuery.expr.pseudos.animated = function( elem ) {
|
|
return jQuery.grep( jQuery.timers, function( fn ) {
|
|
return elem === fn.elem;
|
|
} ).length;
|
|
};
|
|
|
|
|
|
|
|
|
|
jQuery.offset = {
|
|
setOffset: function( elem, options, i ) {
|
|
var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
|
|
position = jQuery.css( elem, "position" ),
|
|
curElem = jQuery( elem ),
|
|
props = {};
|
|
|
|
// Set position first, in-case top/left are set even on static elem
|
|
if ( position === "static" ) {
|
|
elem.style.position = "relative";
|
|
}
|
|
|
|
curOffset = curElem.offset();
|
|
curCSSTop = jQuery.css( elem, "top" );
|
|
curCSSLeft = jQuery.css( elem, "left" );
|
|
calculatePosition = ( position === "absolute" || position === "fixed" ) &&
|
|
( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
|
|
|
|
// Need to be able to calculate position if either
|
|
// top or left is auto and position is either absolute or fixed
|
|
if ( calculatePosition ) {
|
|
curPosition = curElem.position();
|
|
curTop = curPosition.top;
|
|
curLeft = curPosition.left;
|
|
|
|
} else {
|
|
curTop = parseFloat( curCSSTop ) || 0;
|
|
curLeft = parseFloat( curCSSLeft ) || 0;
|
|
}
|
|
|
|
if ( isFunction( options ) ) {
|
|
|
|
// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
|
|
options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
|
|
}
|
|
|
|
if ( options.top != null ) {
|
|
props.top = ( options.top - curOffset.top ) + curTop;
|
|
}
|
|
if ( options.left != null ) {
|
|
props.left = ( options.left - curOffset.left ) + curLeft;
|
|
}
|
|
|
|
if ( "using" in options ) {
|
|
options.using.call( elem, props );
|
|
|
|
} else {
|
|
if ( typeof props.top === "number" ) {
|
|
props.top += "px";
|
|
}
|
|
if ( typeof props.left === "number" ) {
|
|
props.left += "px";
|
|
}
|
|
curElem.css( props );
|
|
}
|
|
}
|
|
};
|
|
|
|
jQuery.fn.extend( {
|
|
|
|
// offset() relates an element's border box to the document origin
|
|
offset: function( options ) {
|
|
|
|
// Preserve chaining for setter
|
|
if ( arguments.length ) {
|
|
return options === undefined ?
|
|
this :
|
|
this.each( function( i ) {
|
|
jQuery.offset.setOffset( this, options, i );
|
|
} );
|
|
}
|
|
|
|
var rect, win,
|
|
elem = this[ 0 ];
|
|
|
|
if ( !elem ) {
|
|
return;
|
|
}
|
|
|
|
// Return zeros for disconnected and hidden (display: none) elements (gh-2310)
|
|
// Support: IE <=11 only
|
|
// Running getBoundingClientRect on a
|
|
// disconnected node in IE throws an error
|
|
if ( !elem.getClientRects().length ) {
|
|
return { top: 0, left: 0 };
|
|
}
|
|
|
|
// Get document-relative position by adding viewport scroll to viewport-relative gBCR
|
|
rect = elem.getBoundingClientRect();
|
|
win = elem.ownerDocument.defaultView;
|
|
return {
|
|
top: rect.top + win.pageYOffset,
|
|
left: rect.left + win.pageXOffset
|
|
};
|
|
},
|
|
|
|
// position() relates an element's margin box to its offset parent's padding box
|
|
// This corresponds to the behavior of CSS absolute positioning
|
|
position: function() {
|
|
if ( !this[ 0 ] ) {
|
|
return;
|
|
}
|
|
|
|
var offsetParent, offset, doc,
|
|
elem = this[ 0 ],
|
|
parentOffset = { top: 0, left: 0 };
|
|
|
|
// position:fixed elements are offset from the viewport, which itself always has zero offset
|
|
if ( jQuery.css( elem, "position" ) === "fixed" ) {
|
|
|
|
// Assume position:fixed implies availability of getBoundingClientRect
|
|
offset = elem.getBoundingClientRect();
|
|
|
|
} else {
|
|
offset = this.offset();
|
|
|
|
// Account for the *real* offset parent, which can be the document or its root element
|
|
// when a statically positioned element is identified
|
|
doc = elem.ownerDocument;
|
|
offsetParent = elem.offsetParent || doc.documentElement;
|
|
while ( offsetParent &&
|
|
( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
|
|
jQuery.css( offsetParent, "position" ) === "static" ) {
|
|
|
|
offsetParent = offsetParent.parentNode;
|
|
}
|
|
if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {
|
|
|
|
// Incorporate borders into its offset, since they are outside its content origin
|
|
parentOffset = jQuery( offsetParent ).offset();
|
|
parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );
|
|
parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
|
|
}
|
|
}
|
|
|
|
// Subtract parent offsets and element margins
|
|
return {
|
|
top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
|
|
left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
|
|
};
|
|
},
|
|
|
|
// This method will return documentElement in the following cases:
|
|
// 1) For the element inside the iframe without offsetParent, this method will return
|
|
// documentElement of the parent window
|
|
// 2) For the hidden or detached element
|
|
// 3) For body or html element, i.e. in case of the html node - it will return itself
|
|
//
|
|
// but those exceptions were never presented as a real life use-cases
|
|
// and might be considered as more preferable results.
|
|
//
|
|
// This logic, however, is not guaranteed and can change at any point in the future
|
|
offsetParent: function() {
|
|
return this.map( function() {
|
|
var offsetParent = this.offsetParent;
|
|
|
|
while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
|
|
offsetParent = offsetParent.offsetParent;
|
|
}
|
|
|
|
return offsetParent || documentElement;
|
|
} );
|
|
}
|
|
} );
|
|
|
|
// Create scrollLeft and scrollTop methods
|
|
jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
|
|
var top = "pageYOffset" === prop;
|
|
|
|
jQuery.fn[ method ] = function( val ) {
|
|
return access( this, function( elem, method, val ) {
|
|
|
|
// Coalesce documents and windows
|
|
var win;
|
|
if ( isWindow( elem ) ) {
|
|
win = elem;
|
|
} else if ( elem.nodeType === 9 ) {
|
|
win = elem.defaultView;
|
|
}
|
|
|
|
if ( val === undefined ) {
|
|
return win ? win[ prop ] : elem[ method ];
|
|
}
|
|
|
|
if ( win ) {
|
|
win.scrollTo(
|
|
!top ? val : win.pageXOffset,
|
|
top ? val : win.pageYOffset
|
|
);
|
|
|
|
} else {
|
|
elem[ method ] = val;
|
|
}
|
|
}, method, val, arguments.length );
|
|
};
|
|
} );
|
|
|
|
// Support: Safari <=7 - 9.1, Chrome <=37 - 49
|
|
// Add the top/left cssHooks using jQuery.fn.position
|
|
// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
|
|
// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
|
|
// getComputedStyle returns percent when specified for top/left/bottom/right;
|
|
// rather than make the css module depend on the offset module, just check for it here
|
|
jQuery.each( [ "top", "left" ], function( _i, prop ) {
|
|
jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
|
|
function( elem, computed ) {
|
|
if ( computed ) {
|
|
computed = curCSS( elem, prop );
|
|
|
|
// If curCSS returns percentage, fallback to offset
|
|
return rnumnonpx.test( computed ) ?
|
|
jQuery( elem ).position()[ prop ] + "px" :
|
|
computed;
|
|
}
|
|
}
|
|
);
|
|
} );
|
|
|
|
|
|
// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
|
|
jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
|
|
jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
|
|
function( defaultExtra, funcName ) {
|
|
|
|
// Margin is only for outerHeight, outerWidth
|
|
jQuery.fn[ funcName ] = function( margin, value ) {
|
|
var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
|
|
extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
|
|
|
|
return access( this, function( elem, type, value ) {
|
|
var doc;
|
|
|
|
if ( isWindow( elem ) ) {
|
|
|
|
// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
|
|
return funcName.indexOf( "outer" ) === 0 ?
|
|
elem[ "inner" + name ] :
|
|
elem.document.documentElement[ "client" + name ];
|
|
}
|
|
|
|
// Get document width or height
|
|
if ( elem.nodeType === 9 ) {
|
|
doc = elem.documentElement;
|
|
|
|
// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
|
|
// whichever is greatest
|
|
return Math.max(
|
|
elem.body[ "scroll" + name ], doc[ "scroll" + name ],
|
|
elem.body[ "offset" + name ], doc[ "offset" + name ],
|
|
doc[ "client" + name ]
|
|
);
|
|
}
|
|
|
|
return value === undefined ?
|
|
|
|
// Get width or height on the element, requesting but not forcing parseFloat
|
|
jQuery.css( elem, type, extra ) :
|
|
|
|
// Set width or height on the element
|
|
jQuery.style( elem, type, value, extra );
|
|
}, type, chainable ? margin : undefined, chainable );
|
|
};
|
|
} );
|
|
} );
|
|
|
|
|
|
jQuery.each( [
|
|
"ajaxStart",
|
|
"ajaxStop",
|
|
"ajaxComplete",
|
|
"ajaxError",
|
|
"ajaxSuccess",
|
|
"ajaxSend"
|
|
], function( _i, type ) {
|
|
jQuery.fn[ type ] = function( fn ) {
|
|
return this.on( type, fn );
|
|
};
|
|
} );
|
|
|
|
|
|
|
|
|
|
jQuery.fn.extend( {
|
|
|
|
bind: function( types, data, fn ) {
|
|
return this.on( types, null, data, fn );
|
|
},
|
|
unbind: function( types, fn ) {
|
|
return this.off( types, null, fn );
|
|
},
|
|
|
|
delegate: function( selector, types, data, fn ) {
|
|
return this.on( types, selector, data, fn );
|
|
},
|
|
undelegate: function( selector, types, fn ) {
|
|
|
|
// ( namespace ) or ( selector, types [, fn] )
|
|
return arguments.length === 1 ?
|
|
this.off( selector, "**" ) :
|
|
this.off( types, selector || "**", fn );
|
|
},
|
|
|
|
hover: function( fnOver, fnOut ) {
|
|
return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
|
|
}
|
|
} );
|
|
|
|
jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
|
|
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
|
|
"change select submit keydown keypress keyup contextmenu" ).split( " " ),
|
|
function( _i, name ) {
|
|
|
|
// Handle event binding
|
|
jQuery.fn[ name ] = function( data, fn ) {
|
|
return arguments.length > 0 ?
|
|
this.on( name, null, data, fn ) :
|
|
this.trigger( name );
|
|
};
|
|
} );
|
|
|
|
|
|
|
|
|
|
// Support: Android <=4.0 only
|
|
// Make sure we trim BOM and NBSP
|
|
var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
|
|
|
|
// Bind a function to a context, optionally partially applying any
|
|
// arguments.
|
|
// jQuery.proxy is deprecated to promote standards (specifically Function#bind)
|
|
// However, it is not slated for removal any time soon
|
|
jQuery.proxy = function( fn, context ) {
|
|
var tmp, args, proxy;
|
|
|
|
if ( typeof context === "string" ) {
|
|
tmp = fn[ context ];
|
|
context = fn;
|
|
fn = tmp;
|
|
}
|
|
|
|
// Quick check to determine if target is callable, in the spec
|
|
// this throws a TypeError, but we will just return undefined.
|
|
if ( !isFunction( fn ) ) {
|
|
return undefined;
|
|
}
|
|
|
|
// Simulated bind
|
|
args = slice.call( arguments, 2 );
|
|
proxy = function() {
|
|
return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
|
|
};
|
|
|
|
// Set the guid of unique handler to the same of original handler, so it can be removed
|
|
proxy.guid = fn.guid = fn.guid || jQuery.guid++;
|
|
|
|
return proxy;
|
|
};
|
|
|
|
jQuery.holdReady = function( hold ) {
|
|
if ( hold ) {
|
|
jQuery.readyWait++;
|
|
} else {
|
|
jQuery.ready( true );
|
|
}
|
|
};
|
|
jQuery.isArray = Array.isArray;
|
|
jQuery.parseJSON = JSON.parse;
|
|
jQuery.nodeName = nodeName;
|
|
jQuery.isFunction = isFunction;
|
|
jQuery.isWindow = isWindow;
|
|
jQuery.camelCase = camelCase;
|
|
jQuery.type = toType;
|
|
|
|
jQuery.now = Date.now;
|
|
|
|
jQuery.isNumeric = function( obj ) {
|
|
|
|
// As of jQuery 3.0, isNumeric is limited to
|
|
// strings and numbers (primitives or objects)
|
|
// that can be coerced to finite numbers (gh-2662)
|
|
var type = jQuery.type( obj );
|
|
return ( type === "number" || type === "string" ) &&
|
|
|
|
// parseFloat NaNs numeric-cast false positives ("")
|
|
// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
|
|
// subtraction forces infinities to NaN
|
|
!isNaN( obj - parseFloat( obj ) );
|
|
};
|
|
|
|
jQuery.trim = function( text ) {
|
|
return text == null ?
|
|
"" :
|
|
( text + "" ).replace( rtrim, "" );
|
|
};
|
|
|
|
|
|
|
|
// Register as a named AMD module, since jQuery can be concatenated with other
|
|
// files that may use define, but not via a proper concatenation script that
|
|
// understands anonymous AMD modules. A named AMD is safest and most robust
|
|
// way to register. Lowercase jquery is used because AMD module names are
|
|
// derived from file names, and jQuery is normally delivered in a lowercase
|
|
// file name. Do this after creating the global so that if an AMD module wants
|
|
// to call noConflict to hide this version of jQuery, it will work.
|
|
|
|
// Note that for maximum portability, libraries that are not jQuery should
|
|
// declare themselves as anonymous modules, and avoid setting a global if an
|
|
// AMD loader is present. jQuery is a special case. For more information, see
|
|
// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
|
|
|
|
if ( true ) {
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() {
|
|
return jQuery;
|
|
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
}
|
|
|
|
|
|
|
|
|
|
var
|
|
|
|
// Map over jQuery in case of overwrite
|
|
_jQuery = window.jQuery,
|
|
|
|
// Map over the $ in case of overwrite
|
|
_$ = window.$;
|
|
|
|
jQuery.noConflict = function( deep ) {
|
|
if ( window.$ === jQuery ) {
|
|
window.$ = _$;
|
|
}
|
|
|
|
if ( deep && window.jQuery === jQuery ) {
|
|
window.jQuery = _jQuery;
|
|
}
|
|
|
|
return jQuery;
|
|
};
|
|
|
|
// Expose jQuery and $ identifiers, even in AMD
|
|
// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
|
|
// and CommonJS for browser emulators (#13566)
|
|
if ( typeof noGlobal === "undefined" ) {
|
|
window.jQuery = window.$ = jQuery;
|
|
}
|
|
|
|
|
|
|
|
|
|
return jQuery;
|
|
} );
|
|
|
|
|
|
/***/ }),
|
|
/* 3 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
__webpack_require__(4)(__webpack_require__(14))
|
|
|
|
/***/ }),
|
|
/* 4 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* WEBPACK VAR INJECTION */(function(console) {/*
|
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
Author Tobias Koppers @sokra
|
|
*/
|
|
module.exports = function(src) {
|
|
function log(error) {
|
|
(typeof console !== "undefined")
|
|
&& (console.error || console.log)("[Script Loader]", error);
|
|
}
|
|
|
|
// Check for IE =< 8
|
|
function isIE() {
|
|
return typeof attachEvent !== "undefined" && typeof addEventListener === "undefined";
|
|
}
|
|
|
|
try {
|
|
if (typeof execScript !== "undefined" && isIE()) {
|
|
execScript(src);
|
|
} else if (typeof eval !== "undefined") {
|
|
eval.call(null, src);
|
|
} else {
|
|
log("EvalError: No eval function available");
|
|
}
|
|
} catch (error) {
|
|
log(error);
|
|
}
|
|
}
|
|
|
|
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))
|
|
|
|
/***/ }),
|
|
/* 5 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* WEBPACK VAR INJECTION */(function(global) {/*global window, global*/
|
|
var util = __webpack_require__(7)
|
|
var assert = __webpack_require__(12)
|
|
function now() { return new Date().getTime() }
|
|
|
|
var slice = Array.prototype.slice
|
|
var console
|
|
var times = {}
|
|
|
|
if (typeof global !== "undefined" && global.console) {
|
|
console = global.console
|
|
} else if (typeof window !== "undefined" && window.console) {
|
|
console = window.console
|
|
} else {
|
|
console = {}
|
|
}
|
|
|
|
var functions = [
|
|
[log, "log"],
|
|
[info, "info"],
|
|
[warn, "warn"],
|
|
[error, "error"],
|
|
[time, "time"],
|
|
[timeEnd, "timeEnd"],
|
|
[trace, "trace"],
|
|
[dir, "dir"],
|
|
[consoleAssert, "assert"]
|
|
]
|
|
|
|
for (var i = 0; i < functions.length; i++) {
|
|
var tuple = functions[i]
|
|
var f = tuple[0]
|
|
var name = tuple[1]
|
|
|
|
if (!console[name]) {
|
|
console[name] = f
|
|
}
|
|
}
|
|
|
|
module.exports = console
|
|
|
|
function log() {}
|
|
|
|
function info() {
|
|
console.log.apply(console, arguments)
|
|
}
|
|
|
|
function warn() {
|
|
console.log.apply(console, arguments)
|
|
}
|
|
|
|
function error() {
|
|
console.warn.apply(console, arguments)
|
|
}
|
|
|
|
function time(label) {
|
|
times[label] = now()
|
|
}
|
|
|
|
function timeEnd(label) {
|
|
var time = times[label]
|
|
if (!time) {
|
|
throw new Error("No such label: " + label)
|
|
}
|
|
|
|
delete times[label]
|
|
var duration = now() - time
|
|
console.log(label + ": " + duration + "ms")
|
|
}
|
|
|
|
function trace() {
|
|
var err = new Error()
|
|
err.name = "Trace"
|
|
err.message = util.format.apply(null, arguments)
|
|
console.error(err.stack)
|
|
}
|
|
|
|
function dir(object) {
|
|
console.log(util.inspect(object) + "\n")
|
|
}
|
|
|
|
function consoleAssert(expression) {
|
|
if (!expression) {
|
|
var arr = slice.call(arguments, 1)
|
|
assert.ok(false, util.format.apply(null, arr))
|
|
}
|
|
}
|
|
|
|
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(6)))
|
|
|
|
/***/ }),
|
|
/* 6 */
|
|
/***/ (function(module, exports) {
|
|
|
|
var g;
|
|
|
|
// This works in non-strict mode
|
|
g = (function() {
|
|
return this;
|
|
})();
|
|
|
|
try {
|
|
// This works if eval is allowed (see CSP)
|
|
g = g || new Function("return this")();
|
|
} catch (e) {
|
|
// This works if the window reference is available
|
|
if (typeof window === "object") g = window;
|
|
}
|
|
|
|
// g can still be undefined, but nothing to do about it...
|
|
// We return undefined, instead of nothing here, so it's
|
|
// easier to handle this case. if(!global) { ...}
|
|
|
|
module.exports = g;
|
|
|
|
|
|
/***/ }),
|
|
/* 7 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* WEBPACK VAR INJECTION */(function(process, console) {// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors ||
|
|
function getOwnPropertyDescriptors(obj) {
|
|
var keys = Object.keys(obj);
|
|
var descriptors = {};
|
|
for (var i = 0; i < keys.length; i++) {
|
|
descriptors[keys[i]] = Object.getOwnPropertyDescriptor(obj, keys[i]);
|
|
}
|
|
return descriptors;
|
|
};
|
|
|
|
var formatRegExp = /%[sdj%]/g;
|
|
exports.format = function(f) {
|
|
if (!isString(f)) {
|
|
var objects = [];
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
objects.push(inspect(arguments[i]));
|
|
}
|
|
return objects.join(' ');
|
|
}
|
|
|
|
var i = 1;
|
|
var args = arguments;
|
|
var len = args.length;
|
|
var str = String(f).replace(formatRegExp, function(x) {
|
|
if (x === '%%') return '%';
|
|
if (i >= len) return x;
|
|
switch (x) {
|
|
case '%s': return String(args[i++]);
|
|
case '%d': return Number(args[i++]);
|
|
case '%j':
|
|
try {
|
|
return JSON.stringify(args[i++]);
|
|
} catch (_) {
|
|
return '[Circular]';
|
|
}
|
|
default:
|
|
return x;
|
|
}
|
|
});
|
|
for (var x = args[i]; i < len; x = args[++i]) {
|
|
if (isNull(x) || !isObject(x)) {
|
|
str += ' ' + x;
|
|
} else {
|
|
str += ' ' + inspect(x);
|
|
}
|
|
}
|
|
return str;
|
|
};
|
|
|
|
|
|
// Mark that a method should not be used.
|
|
// Returns a modified function which warns once by default.
|
|
// If --no-deprecation is set, then it is a no-op.
|
|
exports.deprecate = function(fn, msg) {
|
|
if (typeof process !== 'undefined' && process.noDeprecation === true) {
|
|
return fn;
|
|
}
|
|
|
|
// Allow for deprecating things in the process of starting up.
|
|
if (typeof process === 'undefined') {
|
|
return function() {
|
|
return exports.deprecate(fn, msg).apply(this, arguments);
|
|
};
|
|
}
|
|
|
|
var warned = false;
|
|
function deprecated() {
|
|
if (!warned) {
|
|
if (process.throwDeprecation) {
|
|
throw new Error(msg);
|
|
} else if (process.traceDeprecation) {
|
|
console.trace(msg);
|
|
} else {
|
|
console.error(msg);
|
|
}
|
|
warned = true;
|
|
}
|
|
return fn.apply(this, arguments);
|
|
}
|
|
|
|
return deprecated;
|
|
};
|
|
|
|
|
|
var debugs = {};
|
|
var debugEnviron;
|
|
exports.debuglog = function(set) {
|
|
if (isUndefined(debugEnviron))
|
|
debugEnviron = process.env.NODE_DEBUG || '';
|
|
set = set.toUpperCase();
|
|
if (!debugs[set]) {
|
|
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
|
|
var pid = process.pid;
|
|
debugs[set] = function() {
|
|
var msg = exports.format.apply(exports, arguments);
|
|
console.error('%s %d: %s', set, pid, msg);
|
|
};
|
|
} else {
|
|
debugs[set] = function() {};
|
|
}
|
|
}
|
|
return debugs[set];
|
|
};
|
|
|
|
|
|
/**
|
|
* Echos the value of a value. Trys to print the value out
|
|
* in the best way possible given the different types.
|
|
*
|
|
* @param {Object} obj The object to print out.
|
|
* @param {Object} opts Optional options object that alters the output.
|
|
*/
|
|
/* legacy: obj, showHidden, depth, colors*/
|
|
function inspect(obj, opts) {
|
|
// default options
|
|
var ctx = {
|
|
seen: [],
|
|
stylize: stylizeNoColor
|
|
};
|
|
// legacy...
|
|
if (arguments.length >= 3) ctx.depth = arguments[2];
|
|
if (arguments.length >= 4) ctx.colors = arguments[3];
|
|
if (isBoolean(opts)) {
|
|
// legacy...
|
|
ctx.showHidden = opts;
|
|
} else if (opts) {
|
|
// got an "options" object
|
|
exports._extend(ctx, opts);
|
|
}
|
|
// set default options
|
|
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
|
|
if (isUndefined(ctx.depth)) ctx.depth = 2;
|
|
if (isUndefined(ctx.colors)) ctx.colors = false;
|
|
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
|
|
if (ctx.colors) ctx.stylize = stylizeWithColor;
|
|
return formatValue(ctx, obj, ctx.depth);
|
|
}
|
|
exports.inspect = inspect;
|
|
|
|
|
|
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
|
inspect.colors = {
|
|
'bold' : [1, 22],
|
|
'italic' : [3, 23],
|
|
'underline' : [4, 24],
|
|
'inverse' : [7, 27],
|
|
'white' : [37, 39],
|
|
'grey' : [90, 39],
|
|
'black' : [30, 39],
|
|
'blue' : [34, 39],
|
|
'cyan' : [36, 39],
|
|
'green' : [32, 39],
|
|
'magenta' : [35, 39],
|
|
'red' : [31, 39],
|
|
'yellow' : [33, 39]
|
|
};
|
|
|
|
// Don't use 'blue' not visible on cmd.exe
|
|
inspect.styles = {
|
|
'special': 'cyan',
|
|
'number': 'yellow',
|
|
'boolean': 'yellow',
|
|
'undefined': 'grey',
|
|
'null': 'bold',
|
|
'string': 'green',
|
|
'date': 'magenta',
|
|
// "name": intentionally not styling
|
|
'regexp': 'red'
|
|
};
|
|
|
|
|
|
function stylizeWithColor(str, styleType) {
|
|
var style = inspect.styles[styleType];
|
|
|
|
if (style) {
|
|
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
|
|
'\u001b[' + inspect.colors[style][1] + 'm';
|
|
} else {
|
|
return str;
|
|
}
|
|
}
|
|
|
|
|
|
function stylizeNoColor(str, styleType) {
|
|
return str;
|
|
}
|
|
|
|
|
|
function arrayToHash(array) {
|
|
var hash = {};
|
|
|
|
array.forEach(function(val, idx) {
|
|
hash[val] = true;
|
|
});
|
|
|
|
return hash;
|
|
}
|
|
|
|
|
|
function formatValue(ctx, value, recurseTimes) {
|
|
// Provide a hook for user-specified inspect functions.
|
|
// Check that value is an object with an inspect function on it
|
|
if (ctx.customInspect &&
|
|
value &&
|
|
isFunction(value.inspect) &&
|
|
// Filter out the util module, it's inspect function is special
|
|
value.inspect !== exports.inspect &&
|
|
// Also filter out any prototype objects using the circular check.
|
|
!(value.constructor && value.constructor.prototype === value)) {
|
|
var ret = value.inspect(recurseTimes, ctx);
|
|
if (!isString(ret)) {
|
|
ret = formatValue(ctx, ret, recurseTimes);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// Primitive types cannot have properties
|
|
var primitive = formatPrimitive(ctx, value);
|
|
if (primitive) {
|
|
return primitive;
|
|
}
|
|
|
|
// Look up the keys of the object.
|
|
var keys = Object.keys(value);
|
|
var visibleKeys = arrayToHash(keys);
|
|
|
|
if (ctx.showHidden) {
|
|
keys = Object.getOwnPropertyNames(value);
|
|
}
|
|
|
|
// IE doesn't make error fields non-enumerable
|
|
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
|
|
if (isError(value)
|
|
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
|
|
return formatError(value);
|
|
}
|
|
|
|
// Some type of object without properties can be shortcutted.
|
|
if (keys.length === 0) {
|
|
if (isFunction(value)) {
|
|
var name = value.name ? ': ' + value.name : '';
|
|
return ctx.stylize('[Function' + name + ']', 'special');
|
|
}
|
|
if (isRegExp(value)) {
|
|
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
|
}
|
|
if (isDate(value)) {
|
|
return ctx.stylize(Date.prototype.toString.call(value), 'date');
|
|
}
|
|
if (isError(value)) {
|
|
return formatError(value);
|
|
}
|
|
}
|
|
|
|
var base = '', array = false, braces = ['{', '}'];
|
|
|
|
// Make Array say that they are Array
|
|
if (isArray(value)) {
|
|
array = true;
|
|
braces = ['[', ']'];
|
|
}
|
|
|
|
// Make functions say that they are functions
|
|
if (isFunction(value)) {
|
|
var n = value.name ? ': ' + value.name : '';
|
|
base = ' [Function' + n + ']';
|
|
}
|
|
|
|
// Make RegExps say that they are RegExps
|
|
if (isRegExp(value)) {
|
|
base = ' ' + RegExp.prototype.toString.call(value);
|
|
}
|
|
|
|
// Make dates with properties first say the date
|
|
if (isDate(value)) {
|
|
base = ' ' + Date.prototype.toUTCString.call(value);
|
|
}
|
|
|
|
// Make error with message first say the error
|
|
if (isError(value)) {
|
|
base = ' ' + formatError(value);
|
|
}
|
|
|
|
if (keys.length === 0 && (!array || value.length == 0)) {
|
|
return braces[0] + base + braces[1];
|
|
}
|
|
|
|
if (recurseTimes < 0) {
|
|
if (isRegExp(value)) {
|
|
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
|
} else {
|
|
return ctx.stylize('[Object]', 'special');
|
|
}
|
|
}
|
|
|
|
ctx.seen.push(value);
|
|
|
|
var output;
|
|
if (array) {
|
|
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
|
|
} else {
|
|
output = keys.map(function(key) {
|
|
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
|
|
});
|
|
}
|
|
|
|
ctx.seen.pop();
|
|
|
|
return reduceToSingleString(output, base, braces);
|
|
}
|
|
|
|
|
|
function formatPrimitive(ctx, value) {
|
|
if (isUndefined(value))
|
|
return ctx.stylize('undefined', 'undefined');
|
|
if (isString(value)) {
|
|
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
|
.replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"') + '\'';
|
|
return ctx.stylize(simple, 'string');
|
|
}
|
|
if (isNumber(value))
|
|
return ctx.stylize('' + value, 'number');
|
|
if (isBoolean(value))
|
|
return ctx.stylize('' + value, 'boolean');
|
|
// For some reason typeof null is "object", so special case here.
|
|
if (isNull(value))
|
|
return ctx.stylize('null', 'null');
|
|
}
|
|
|
|
|
|
function formatError(value) {
|
|
return '[' + Error.prototype.toString.call(value) + ']';
|
|
}
|
|
|
|
|
|
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
|
|
var output = [];
|
|
for (var i = 0, l = value.length; i < l; ++i) {
|
|
if (hasOwnProperty(value, String(i))) {
|
|
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
|
String(i), true));
|
|
} else {
|
|
output.push('');
|
|
}
|
|
}
|
|
keys.forEach(function(key) {
|
|
if (!key.match(/^\d+$/)) {
|
|
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
|
key, true));
|
|
}
|
|
});
|
|
return output;
|
|
}
|
|
|
|
|
|
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
|
|
var name, str, desc;
|
|
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
|
|
if (desc.get) {
|
|
if (desc.set) {
|
|
str = ctx.stylize('[Getter/Setter]', 'special');
|
|
} else {
|
|
str = ctx.stylize('[Getter]', 'special');
|
|
}
|
|
} else {
|
|
if (desc.set) {
|
|
str = ctx.stylize('[Setter]', 'special');
|
|
}
|
|
}
|
|
if (!hasOwnProperty(visibleKeys, key)) {
|
|
name = '[' + key + ']';
|
|
}
|
|
if (!str) {
|
|
if (ctx.seen.indexOf(desc.value) < 0) {
|
|
if (isNull(recurseTimes)) {
|
|
str = formatValue(ctx, desc.value, null);
|
|
} else {
|
|
str = formatValue(ctx, desc.value, recurseTimes - 1);
|
|
}
|
|
if (str.indexOf('\n') > -1) {
|
|
if (array) {
|
|
str = str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n').substr(2);
|
|
} else {
|
|
str = '\n' + str.split('\n').map(function(line) {
|
|
return ' ' + line;
|
|
}).join('\n');
|
|
}
|
|
}
|
|
} else {
|
|
str = ctx.stylize('[Circular]', 'special');
|
|
}
|
|
}
|
|
if (isUndefined(name)) {
|
|
if (array && key.match(/^\d+$/)) {
|
|
return str;
|
|
}
|
|
name = JSON.stringify('' + key);
|
|
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
|
name = name.substr(1, name.length - 2);
|
|
name = ctx.stylize(name, 'name');
|
|
} else {
|
|
name = name.replace(/'/g, "\\'")
|
|
.replace(/\\"/g, '"')
|
|
.replace(/(^"|"$)/g, "'");
|
|
name = ctx.stylize(name, 'string');
|
|
}
|
|
}
|
|
|
|
return name + ': ' + str;
|
|
}
|
|
|
|
|
|
function reduceToSingleString(output, base, braces) {
|
|
var numLinesEst = 0;
|
|
var length = output.reduce(function(prev, cur) {
|
|
numLinesEst++;
|
|
if (cur.indexOf('\n') >= 0) numLinesEst++;
|
|
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
|
|
}, 0);
|
|
|
|
if (length > 60) {
|
|
return braces[0] +
|
|
(base === '' ? '' : base + '\n ') +
|
|
' ' +
|
|
output.join(',\n ') +
|
|
' ' +
|
|
braces[1];
|
|
}
|
|
|
|
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
|
}
|
|
|
|
|
|
// NOTE: These type checking functions intentionally don't use `instanceof`
|
|
// because it is fragile and can be easily faked with `Object.create()`.
|
|
function isArray(ar) {
|
|
return Array.isArray(ar);
|
|
}
|
|
exports.isArray = isArray;
|
|
|
|
function isBoolean(arg) {
|
|
return typeof arg === 'boolean';
|
|
}
|
|
exports.isBoolean = isBoolean;
|
|
|
|
function isNull(arg) {
|
|
return arg === null;
|
|
}
|
|
exports.isNull = isNull;
|
|
|
|
function isNullOrUndefined(arg) {
|
|
return arg == null;
|
|
}
|
|
exports.isNullOrUndefined = isNullOrUndefined;
|
|
|
|
function isNumber(arg) {
|
|
return typeof arg === 'number';
|
|
}
|
|
exports.isNumber = isNumber;
|
|
|
|
function isString(arg) {
|
|
return typeof arg === 'string';
|
|
}
|
|
exports.isString = isString;
|
|
|
|
function isSymbol(arg) {
|
|
return typeof arg === 'symbol';
|
|
}
|
|
exports.isSymbol = isSymbol;
|
|
|
|
function isUndefined(arg) {
|
|
return arg === void 0;
|
|
}
|
|
exports.isUndefined = isUndefined;
|
|
|
|
function isRegExp(re) {
|
|
return isObject(re) && objectToString(re) === '[object RegExp]';
|
|
}
|
|
exports.isRegExp = isRegExp;
|
|
|
|
function isObject(arg) {
|
|
return typeof arg === 'object' && arg !== null;
|
|
}
|
|
exports.isObject = isObject;
|
|
|
|
function isDate(d) {
|
|
return isObject(d) && objectToString(d) === '[object Date]';
|
|
}
|
|
exports.isDate = isDate;
|
|
|
|
function isError(e) {
|
|
return isObject(e) &&
|
|
(objectToString(e) === '[object Error]' || e instanceof Error);
|
|
}
|
|
exports.isError = isError;
|
|
|
|
function isFunction(arg) {
|
|
return typeof arg === 'function';
|
|
}
|
|
exports.isFunction = isFunction;
|
|
|
|
function isPrimitive(arg) {
|
|
return arg === null ||
|
|
typeof arg === 'boolean' ||
|
|
typeof arg === 'number' ||
|
|
typeof arg === 'string' ||
|
|
typeof arg === 'symbol' || // ES6 symbol
|
|
typeof arg === 'undefined';
|
|
}
|
|
exports.isPrimitive = isPrimitive;
|
|
|
|
exports.isBuffer = __webpack_require__(9);
|
|
|
|
function objectToString(o) {
|
|
return Object.prototype.toString.call(o);
|
|
}
|
|
|
|
|
|
function pad(n) {
|
|
return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
|
}
|
|
|
|
|
|
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
|
'Oct', 'Nov', 'Dec'];
|
|
|
|
// 26 Feb 16:19:34
|
|
function timestamp() {
|
|
var d = new Date();
|
|
var time = [pad(d.getHours()),
|
|
pad(d.getMinutes()),
|
|
pad(d.getSeconds())].join(':');
|
|
return [d.getDate(), months[d.getMonth()], time].join(' ');
|
|
}
|
|
|
|
|
|
// log is just a thin wrapper to console.log that prepends a timestamp
|
|
exports.log = function() {
|
|
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
|
|
};
|
|
|
|
|
|
/**
|
|
* Inherit the prototype methods from one constructor into another.
|
|
*
|
|
* The Function.prototype.inherits from lang.js rewritten as a standalone
|
|
* function (not on Function.prototype). NOTE: If this file is to be loaded
|
|
* during bootstrapping this function needs to be rewritten using some native
|
|
* functions as prototype setup using normal JavaScript does not work as
|
|
* expected during bootstrapping (see mirror.js in r114903).
|
|
*
|
|
* @param {function} ctor Constructor function which needs to inherit the
|
|
* prototype.
|
|
* @param {function} superCtor Constructor function to inherit prototype from.
|
|
*/
|
|
exports.inherits = __webpack_require__(10);
|
|
|
|
exports._extend = function(origin, add) {
|
|
// Don't do anything if add isn't an object
|
|
if (!add || !isObject(add)) return origin;
|
|
|
|
var keys = Object.keys(add);
|
|
var i = keys.length;
|
|
while (i--) {
|
|
origin[keys[i]] = add[keys[i]];
|
|
}
|
|
return origin;
|
|
};
|
|
|
|
function hasOwnProperty(obj, prop) {
|
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
}
|
|
|
|
var kCustomPromisifiedSymbol = typeof Symbol !== 'undefined' ? Symbol('util.promisify.custom') : undefined;
|
|
|
|
exports.promisify = function promisify(original) {
|
|
if (typeof original !== 'function')
|
|
throw new TypeError('The "original" argument must be of type Function');
|
|
|
|
if (kCustomPromisifiedSymbol && original[kCustomPromisifiedSymbol]) {
|
|
var fn = original[kCustomPromisifiedSymbol];
|
|
if (typeof fn !== 'function') {
|
|
throw new TypeError('The "util.promisify.custom" argument must be of type Function');
|
|
}
|
|
Object.defineProperty(fn, kCustomPromisifiedSymbol, {
|
|
value: fn, enumerable: false, writable: false, configurable: true
|
|
});
|
|
return fn;
|
|
}
|
|
|
|
function fn() {
|
|
var promiseResolve, promiseReject;
|
|
var promise = new Promise(function (resolve, reject) {
|
|
promiseResolve = resolve;
|
|
promiseReject = reject;
|
|
});
|
|
|
|
var args = [];
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
args.push(arguments[i]);
|
|
}
|
|
args.push(function (err, value) {
|
|
if (err) {
|
|
promiseReject(err);
|
|
} else {
|
|
promiseResolve(value);
|
|
}
|
|
});
|
|
|
|
try {
|
|
original.apply(this, args);
|
|
} catch (err) {
|
|
promiseReject(err);
|
|
}
|
|
|
|
return promise;
|
|
}
|
|
|
|
Object.setPrototypeOf(fn, Object.getPrototypeOf(original));
|
|
|
|
if (kCustomPromisifiedSymbol) Object.defineProperty(fn, kCustomPromisifiedSymbol, {
|
|
value: fn, enumerable: false, writable: false, configurable: true
|
|
});
|
|
return Object.defineProperties(
|
|
fn,
|
|
getOwnPropertyDescriptors(original)
|
|
);
|
|
}
|
|
|
|
exports.promisify.custom = kCustomPromisifiedSymbol
|
|
|
|
function callbackifyOnRejected(reason, cb) {
|
|
// `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M).
|
|
// Because `null` is a special error value in callbacks which means "no error
|
|
// occurred", we error-wrap so the callback consumer can distinguish between
|
|
// "the promise rejected with null" or "the promise fulfilled with undefined".
|
|
if (!reason) {
|
|
var newReason = new Error('Promise was rejected with a falsy value');
|
|
newReason.reason = reason;
|
|
reason = newReason;
|
|
}
|
|
return cb(reason);
|
|
}
|
|
|
|
function callbackify(original) {
|
|
if (typeof original !== 'function') {
|
|
throw new TypeError('The "original" argument must be of type Function');
|
|
}
|
|
|
|
// We DO NOT return the promise as it gives the user a false sense that
|
|
// the promise is actually somehow related to the callback's execution
|
|
// and that the callback throwing will reject the promise.
|
|
function callbackified() {
|
|
var args = [];
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
args.push(arguments[i]);
|
|
}
|
|
|
|
var maybeCb = args.pop();
|
|
if (typeof maybeCb !== 'function') {
|
|
throw new TypeError('The last argument must be of type Function');
|
|
}
|
|
var self = this;
|
|
var cb = function() {
|
|
return maybeCb.apply(self, arguments);
|
|
};
|
|
// In true node style we process the callback on `nextTick` with all the
|
|
// implications (stack, `uncaughtException`, `async_hooks`)
|
|
original.apply(this, args)
|
|
.then(function(ret) { process.nextTick(cb, null, ret) },
|
|
function(rej) { process.nextTick(callbackifyOnRejected, rej, cb) });
|
|
}
|
|
|
|
Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original));
|
|
Object.defineProperties(callbackified,
|
|
getOwnPropertyDescriptors(original));
|
|
return callbackified;
|
|
}
|
|
exports.callbackify = callbackify;
|
|
|
|
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(8), __webpack_require__(5)))
|
|
|
|
/***/ }),
|
|
/* 8 */
|
|
/***/ (function(module, exports) {
|
|
|
|
// shim for using process in browser
|
|
var process = module.exports = {};
|
|
|
|
// cached from whatever global is present so that test runners that stub it
|
|
// don't break things. But we need to wrap it in a try catch in case it is
|
|
// wrapped in strict mode code which doesn't define any globals. It's inside a
|
|
// function because try/catches deoptimize in certain engines.
|
|
|
|
var cachedSetTimeout;
|
|
var cachedClearTimeout;
|
|
|
|
function defaultSetTimout() {
|
|
throw new Error('setTimeout has not been defined');
|
|
}
|
|
function defaultClearTimeout () {
|
|
throw new Error('clearTimeout has not been defined');
|
|
}
|
|
(function () {
|
|
try {
|
|
if (typeof setTimeout === 'function') {
|
|
cachedSetTimeout = setTimeout;
|
|
} else {
|
|
cachedSetTimeout = defaultSetTimout;
|
|
}
|
|
} catch (e) {
|
|
cachedSetTimeout = defaultSetTimout;
|
|
}
|
|
try {
|
|
if (typeof clearTimeout === 'function') {
|
|
cachedClearTimeout = clearTimeout;
|
|
} else {
|
|
cachedClearTimeout = defaultClearTimeout;
|
|
}
|
|
} catch (e) {
|
|
cachedClearTimeout = defaultClearTimeout;
|
|
}
|
|
} ())
|
|
function runTimeout(fun) {
|
|
if (cachedSetTimeout === setTimeout) {
|
|
//normal enviroments in sane situations
|
|
return setTimeout(fun, 0);
|
|
}
|
|
// if setTimeout wasn't available but was latter defined
|
|
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
|
|
cachedSetTimeout = setTimeout;
|
|
return setTimeout(fun, 0);
|
|
}
|
|
try {
|
|
// when when somebody has screwed with setTimeout but no I.E. maddness
|
|
return cachedSetTimeout(fun, 0);
|
|
} catch(e){
|
|
try {
|
|
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
|
return cachedSetTimeout.call(null, fun, 0);
|
|
} catch(e){
|
|
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
|
|
return cachedSetTimeout.call(this, fun, 0);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
function runClearTimeout(marker) {
|
|
if (cachedClearTimeout === clearTimeout) {
|
|
//normal enviroments in sane situations
|
|
return clearTimeout(marker);
|
|
}
|
|
// if clearTimeout wasn't available but was latter defined
|
|
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
|
|
cachedClearTimeout = clearTimeout;
|
|
return clearTimeout(marker);
|
|
}
|
|
try {
|
|
// when when somebody has screwed with setTimeout but no I.E. maddness
|
|
return cachedClearTimeout(marker);
|
|
} catch (e){
|
|
try {
|
|
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
|
return cachedClearTimeout.call(null, marker);
|
|
} catch (e){
|
|
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
|
|
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
|
|
return cachedClearTimeout.call(this, marker);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
var queue = [];
|
|
var draining = false;
|
|
var currentQueue;
|
|
var queueIndex = -1;
|
|
|
|
function cleanUpNextTick() {
|
|
if (!draining || !currentQueue) {
|
|
return;
|
|
}
|
|
draining = false;
|
|
if (currentQueue.length) {
|
|
queue = currentQueue.concat(queue);
|
|
} else {
|
|
queueIndex = -1;
|
|
}
|
|
if (queue.length) {
|
|
drainQueue();
|
|
}
|
|
}
|
|
|
|
function drainQueue() {
|
|
if (draining) {
|
|
return;
|
|
}
|
|
var timeout = runTimeout(cleanUpNextTick);
|
|
draining = true;
|
|
|
|
var len = queue.length;
|
|
while(len) {
|
|
currentQueue = queue;
|
|
queue = [];
|
|
while (++queueIndex < len) {
|
|
if (currentQueue) {
|
|
currentQueue[queueIndex].run();
|
|
}
|
|
}
|
|
queueIndex = -1;
|
|
len = queue.length;
|
|
}
|
|
currentQueue = null;
|
|
draining = false;
|
|
runClearTimeout(timeout);
|
|
}
|
|
|
|
process.nextTick = function (fun) {
|
|
var args = new Array(arguments.length - 1);
|
|
if (arguments.length > 1) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
args[i - 1] = arguments[i];
|
|
}
|
|
}
|
|
queue.push(new Item(fun, args));
|
|
if (queue.length === 1 && !draining) {
|
|
runTimeout(drainQueue);
|
|
}
|
|
};
|
|
|
|
// v8 likes predictible objects
|
|
function Item(fun, array) {
|
|
this.fun = fun;
|
|
this.array = array;
|
|
}
|
|
Item.prototype.run = function () {
|
|
this.fun.apply(null, this.array);
|
|
};
|
|
process.title = 'browser';
|
|
process.browser = true;
|
|
process.env = {};
|
|
process.argv = [];
|
|
process.version = ''; // empty string to avoid regexp issues
|
|
process.versions = {};
|
|
|
|
function noop() {}
|
|
|
|
process.on = noop;
|
|
process.addListener = noop;
|
|
process.once = noop;
|
|
process.off = noop;
|
|
process.removeListener = noop;
|
|
process.removeAllListeners = noop;
|
|
process.emit = noop;
|
|
process.prependListener = noop;
|
|
process.prependOnceListener = noop;
|
|
|
|
process.listeners = function (name) { return [] }
|
|
|
|
process.binding = function (name) {
|
|
throw new Error('process.binding is not supported');
|
|
};
|
|
|
|
process.cwd = function () { return '/' };
|
|
process.chdir = function (dir) {
|
|
throw new Error('process.chdir is not supported');
|
|
};
|
|
process.umask = function() { return 0; };
|
|
|
|
|
|
/***/ }),
|
|
/* 9 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = function isBuffer(arg) {
|
|
return arg && typeof arg === 'object'
|
|
&& typeof arg.copy === 'function'
|
|
&& typeof arg.fill === 'function'
|
|
&& typeof arg.readUInt8 === 'function';
|
|
}
|
|
|
|
/***/ }),
|
|
/* 10 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
try {
|
|
var util = __webpack_require__(7);
|
|
if (typeof util.inherits !== 'function') throw '';
|
|
module.exports = util.inherits;
|
|
} catch (e) {
|
|
module.exports = __webpack_require__(11);
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 11 */
|
|
/***/ (function(module, exports) {
|
|
|
|
if (typeof Object.create === 'function') {
|
|
// implementation from standard node.js 'util' module
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
ctor.super_ = superCtor
|
|
ctor.prototype = Object.create(superCtor.prototype, {
|
|
constructor: {
|
|
value: ctor,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
};
|
|
} else {
|
|
// old school shim for old browsers
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
ctor.super_ = superCtor
|
|
var TempCtor = function () {}
|
|
TempCtor.prototype = superCtor.prototype
|
|
ctor.prototype = new TempCtor()
|
|
ctor.prototype.constructor = ctor
|
|
}
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 12 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
/* WEBPACK VAR INJECTION */(function(global) {
|
|
|
|
var objectAssign = __webpack_require__(13);
|
|
|
|
// compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js
|
|
// original notice:
|
|
|
|
/*!
|
|
* The buffer module from node.js, for the browser.
|
|
*
|
|
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
|
* @license MIT
|
|
*/
|
|
function compare(a, b) {
|
|
if (a === b) {
|
|
return 0;
|
|
}
|
|
|
|
var x = a.length;
|
|
var y = b.length;
|
|
|
|
for (var i = 0, len = Math.min(x, y); i < len; ++i) {
|
|
if (a[i] !== b[i]) {
|
|
x = a[i];
|
|
y = b[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (x < y) {
|
|
return -1;
|
|
}
|
|
if (y < x) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
function isBuffer(b) {
|
|
if (global.Buffer && typeof global.Buffer.isBuffer === 'function') {
|
|
return global.Buffer.isBuffer(b);
|
|
}
|
|
return !!(b != null && b._isBuffer);
|
|
}
|
|
|
|
// based on node assert, original notice:
|
|
// NB: The URL to the CommonJS spec is kept just for tradition.
|
|
// node-assert has evolved a lot since then, both in API and behavior.
|
|
|
|
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
|
|
//
|
|
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
|
|
//
|
|
// Originally from narwhal.js (http://narwhaljs.org)
|
|
// Copyright (c) 2009 Thomas Robinson <280north.com>
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the 'Software'), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
var util = __webpack_require__(7);
|
|
var hasOwn = Object.prototype.hasOwnProperty;
|
|
var pSlice = Array.prototype.slice;
|
|
var functionsHaveNames = (function () {
|
|
return function foo() {}.name === 'foo';
|
|
}());
|
|
function pToString (obj) {
|
|
return Object.prototype.toString.call(obj);
|
|
}
|
|
function isView(arrbuf) {
|
|
if (isBuffer(arrbuf)) {
|
|
return false;
|
|
}
|
|
if (typeof global.ArrayBuffer !== 'function') {
|
|
return false;
|
|
}
|
|
if (typeof ArrayBuffer.isView === 'function') {
|
|
return ArrayBuffer.isView(arrbuf);
|
|
}
|
|
if (!arrbuf) {
|
|
return false;
|
|
}
|
|
if (arrbuf instanceof DataView) {
|
|
return true;
|
|
}
|
|
if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
// 1. The assert module provides functions that throw
|
|
// AssertionError's when particular conditions are not met. The
|
|
// assert module must conform to the following interface.
|
|
|
|
var assert = module.exports = ok;
|
|
|
|
// 2. The AssertionError is defined in assert.
|
|
// new assert.AssertionError({ message: message,
|
|
// actual: actual,
|
|
// expected: expected })
|
|
|
|
var regex = /\s*function\s+([^\(\s]*)\s*/;
|
|
// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js
|
|
function getName(func) {
|
|
if (!util.isFunction(func)) {
|
|
return;
|
|
}
|
|
if (functionsHaveNames) {
|
|
return func.name;
|
|
}
|
|
var str = func.toString();
|
|
var match = str.match(regex);
|
|
return match && match[1];
|
|
}
|
|
assert.AssertionError = function AssertionError(options) {
|
|
this.name = 'AssertionError';
|
|
this.actual = options.actual;
|
|
this.expected = options.expected;
|
|
this.operator = options.operator;
|
|
if (options.message) {
|
|
this.message = options.message;
|
|
this.generatedMessage = false;
|
|
} else {
|
|
this.message = getMessage(this);
|
|
this.generatedMessage = true;
|
|
}
|
|
var stackStartFunction = options.stackStartFunction || fail;
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, stackStartFunction);
|
|
} else {
|
|
// non v8 browsers so we can have a stacktrace
|
|
var err = new Error();
|
|
if (err.stack) {
|
|
var out = err.stack;
|
|
|
|
// try to strip useless frames
|
|
var fn_name = getName(stackStartFunction);
|
|
var idx = out.indexOf('\n' + fn_name);
|
|
if (idx >= 0) {
|
|
// once we have located the function frame
|
|
// we need to strip out everything before it (and its line)
|
|
var next_line = out.indexOf('\n', idx + 1);
|
|
out = out.substring(next_line + 1);
|
|
}
|
|
|
|
this.stack = out;
|
|
}
|
|
}
|
|
};
|
|
|
|
// assert.AssertionError instanceof Error
|
|
util.inherits(assert.AssertionError, Error);
|
|
|
|
function truncate(s, n) {
|
|
if (typeof s === 'string') {
|
|
return s.length < n ? s : s.slice(0, n);
|
|
} else {
|
|
return s;
|
|
}
|
|
}
|
|
function inspect(something) {
|
|
if (functionsHaveNames || !util.isFunction(something)) {
|
|
return util.inspect(something);
|
|
}
|
|
var rawname = getName(something);
|
|
var name = rawname ? ': ' + rawname : '';
|
|
return '[Function' + name + ']';
|
|
}
|
|
function getMessage(self) {
|
|
return truncate(inspect(self.actual), 128) + ' ' +
|
|
self.operator + ' ' +
|
|
truncate(inspect(self.expected), 128);
|
|
}
|
|
|
|
// At present only the three keys mentioned above are used and
|
|
// understood by the spec. Implementations or sub modules can pass
|
|
// other keys to the AssertionError's constructor - they will be
|
|
// ignored.
|
|
|
|
// 3. All of the following functions must throw an AssertionError
|
|
// when a corresponding condition is not met, with a message that
|
|
// may be undefined if not provided. All assertion methods provide
|
|
// both the actual and expected values to the assertion error for
|
|
// display purposes.
|
|
|
|
function fail(actual, expected, message, operator, stackStartFunction) {
|
|
throw new assert.AssertionError({
|
|
message: message,
|
|
actual: actual,
|
|
expected: expected,
|
|
operator: operator,
|
|
stackStartFunction: stackStartFunction
|
|
});
|
|
}
|
|
|
|
// EXTENSION! allows for well behaved errors defined elsewhere.
|
|
assert.fail = fail;
|
|
|
|
// 4. Pure assertion tests whether a value is truthy, as determined
|
|
// by !!guard.
|
|
// assert.ok(guard, message_opt);
|
|
// This statement is equivalent to assert.equal(true, !!guard,
|
|
// message_opt);. To test strictly for the value true, use
|
|
// assert.strictEqual(true, guard, message_opt);.
|
|
|
|
function ok(value, message) {
|
|
if (!value) fail(value, true, message, '==', assert.ok);
|
|
}
|
|
assert.ok = ok;
|
|
|
|
// 5. The equality assertion tests shallow, coercive equality with
|
|
// ==.
|
|
// assert.equal(actual, expected, message_opt);
|
|
|
|
assert.equal = function equal(actual, expected, message) {
|
|
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
|
|
};
|
|
|
|
// 6. The non-equality assertion tests for whether two objects are not equal
|
|
// with != assert.notEqual(actual, expected, message_opt);
|
|
|
|
assert.notEqual = function notEqual(actual, expected, message) {
|
|
if (actual == expected) {
|
|
fail(actual, expected, message, '!=', assert.notEqual);
|
|
}
|
|
};
|
|
|
|
// 7. The equivalence assertion tests a deep equality relation.
|
|
// assert.deepEqual(actual, expected, message_opt);
|
|
|
|
assert.deepEqual = function deepEqual(actual, expected, message) {
|
|
if (!_deepEqual(actual, expected, false)) {
|
|
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
|
|
}
|
|
};
|
|
|
|
assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
|
|
if (!_deepEqual(actual, expected, true)) {
|
|
fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual);
|
|
}
|
|
};
|
|
|
|
function _deepEqual(actual, expected, strict, memos) {
|
|
// 7.1. All identical values are equivalent, as determined by ===.
|
|
if (actual === expected) {
|
|
return true;
|
|
} else if (isBuffer(actual) && isBuffer(expected)) {
|
|
return compare(actual, expected) === 0;
|
|
|
|
// 7.2. If the expected value is a Date object, the actual value is
|
|
// equivalent if it is also a Date object that refers to the same time.
|
|
} else if (util.isDate(actual) && util.isDate(expected)) {
|
|
return actual.getTime() === expected.getTime();
|
|
|
|
// 7.3 If the expected value is a RegExp object, the actual value is
|
|
// equivalent if it is also a RegExp object with the same source and
|
|
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
|
|
} else if (util.isRegExp(actual) && util.isRegExp(expected)) {
|
|
return actual.source === expected.source &&
|
|
actual.global === expected.global &&
|
|
actual.multiline === expected.multiline &&
|
|
actual.lastIndex === expected.lastIndex &&
|
|
actual.ignoreCase === expected.ignoreCase;
|
|
|
|
// 7.4. Other pairs that do not both pass typeof value == 'object',
|
|
// equivalence is determined by ==.
|
|
} else if ((actual === null || typeof actual !== 'object') &&
|
|
(expected === null || typeof expected !== 'object')) {
|
|
return strict ? actual === expected : actual == expected;
|
|
|
|
// If both values are instances of typed arrays, wrap their underlying
|
|
// ArrayBuffers in a Buffer each to increase performance
|
|
// This optimization requires the arrays to have the same type as checked by
|
|
// Object.prototype.toString (aka pToString). Never perform binary
|
|
// comparisons for Float*Arrays, though, since e.g. +0 === -0 but their
|
|
// bit patterns are not identical.
|
|
} else if (isView(actual) && isView(expected) &&
|
|
pToString(actual) === pToString(expected) &&
|
|
!(actual instanceof Float32Array ||
|
|
actual instanceof Float64Array)) {
|
|
return compare(new Uint8Array(actual.buffer),
|
|
new Uint8Array(expected.buffer)) === 0;
|
|
|
|
// 7.5 For all other Object pairs, including Array objects, equivalence is
|
|
// determined by having the same number of owned properties (as verified
|
|
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
|
// (although not necessarily the same order), equivalent values for every
|
|
// corresponding key, and an identical 'prototype' property. Note: this
|
|
// accounts for both named and indexed properties on Arrays.
|
|
} else if (isBuffer(actual) !== isBuffer(expected)) {
|
|
return false;
|
|
} else {
|
|
memos = memos || {actual: [], expected: []};
|
|
|
|
var actualIndex = memos.actual.indexOf(actual);
|
|
if (actualIndex !== -1) {
|
|
if (actualIndex === memos.expected.indexOf(expected)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
memos.actual.push(actual);
|
|
memos.expected.push(expected);
|
|
|
|
return objEquiv(actual, expected, strict, memos);
|
|
}
|
|
}
|
|
|
|
function isArguments(object) {
|
|
return Object.prototype.toString.call(object) == '[object Arguments]';
|
|
}
|
|
|
|
function objEquiv(a, b, strict, actualVisitedObjects) {
|
|
if (a === null || a === undefined || b === null || b === undefined)
|
|
return false;
|
|
// if one is a primitive, the other must be same
|
|
if (util.isPrimitive(a) || util.isPrimitive(b))
|
|
return a === b;
|
|
if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b))
|
|
return false;
|
|
var aIsArgs = isArguments(a);
|
|
var bIsArgs = isArguments(b);
|
|
if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
|
|
return false;
|
|
if (aIsArgs) {
|
|
a = pSlice.call(a);
|
|
b = pSlice.call(b);
|
|
return _deepEqual(a, b, strict);
|
|
}
|
|
var ka = objectKeys(a);
|
|
var kb = objectKeys(b);
|
|
var key, i;
|
|
// having the same number of owned properties (keys incorporates
|
|
// hasOwnProperty)
|
|
if (ka.length !== kb.length)
|
|
return false;
|
|
//the same set of keys (although not necessarily the same order),
|
|
ka.sort();
|
|
kb.sort();
|
|
//~~~cheap key test
|
|
for (i = ka.length - 1; i >= 0; i--) {
|
|
if (ka[i] !== kb[i])
|
|
return false;
|
|
}
|
|
//equivalent values for every corresponding key, and
|
|
//~~~possibly expensive deep test
|
|
for (i = ka.length - 1; i >= 0; i--) {
|
|
key = ka[i];
|
|
if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// 8. The non-equivalence assertion tests for any deep inequality.
|
|
// assert.notDeepEqual(actual, expected, message_opt);
|
|
|
|
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
|
if (_deepEqual(actual, expected, false)) {
|
|
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
|
|
}
|
|
};
|
|
|
|
assert.notDeepStrictEqual = notDeepStrictEqual;
|
|
function notDeepStrictEqual(actual, expected, message) {
|
|
if (_deepEqual(actual, expected, true)) {
|
|
fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual);
|
|
}
|
|
}
|
|
|
|
|
|
// 9. The strict equality assertion tests strict equality, as determined by ===.
|
|
// assert.strictEqual(actual, expected, message_opt);
|
|
|
|
assert.strictEqual = function strictEqual(actual, expected, message) {
|
|
if (actual !== expected) {
|
|
fail(actual, expected, message, '===', assert.strictEqual);
|
|
}
|
|
};
|
|
|
|
// 10. The strict non-equality assertion tests for strict inequality, as
|
|
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
|
|
|
|
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
|
if (actual === expected) {
|
|
fail(actual, expected, message, '!==', assert.notStrictEqual);
|
|
}
|
|
};
|
|
|
|
function expectedException(actual, expected) {
|
|
if (!actual || !expected) {
|
|
return false;
|
|
}
|
|
|
|
if (Object.prototype.toString.call(expected) == '[object RegExp]') {
|
|
return expected.test(actual);
|
|
}
|
|
|
|
try {
|
|
if (actual instanceof expected) {
|
|
return true;
|
|
}
|
|
} catch (e) {
|
|
// Ignore. The instanceof check doesn't work for arrow functions.
|
|
}
|
|
|
|
if (Error.isPrototypeOf(expected)) {
|
|
return false;
|
|
}
|
|
|
|
return expected.call({}, actual) === true;
|
|
}
|
|
|
|
function _tryBlock(block) {
|
|
var error;
|
|
try {
|
|
block();
|
|
} catch (e) {
|
|
error = e;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
function _throws(shouldThrow, block, expected, message) {
|
|
var actual;
|
|
|
|
if (typeof block !== 'function') {
|
|
throw new TypeError('"block" argument must be a function');
|
|
}
|
|
|
|
if (typeof expected === 'string') {
|
|
message = expected;
|
|
expected = null;
|
|
}
|
|
|
|
actual = _tryBlock(block);
|
|
|
|
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
|
|
(message ? ' ' + message : '.');
|
|
|
|
if (shouldThrow && !actual) {
|
|
fail(actual, expected, 'Missing expected exception' + message);
|
|
}
|
|
|
|
var userProvidedMessage = typeof message === 'string';
|
|
var isUnwantedException = !shouldThrow && util.isError(actual);
|
|
var isUnexpectedException = !shouldThrow && actual && !expected;
|
|
|
|
if ((isUnwantedException &&
|
|
userProvidedMessage &&
|
|
expectedException(actual, expected)) ||
|
|
isUnexpectedException) {
|
|
fail(actual, expected, 'Got unwanted exception' + message);
|
|
}
|
|
|
|
if ((shouldThrow && actual && expected &&
|
|
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
|
|
throw actual;
|
|
}
|
|
}
|
|
|
|
// 11. Expected to throw an error:
|
|
// assert.throws(block, Error_opt, message_opt);
|
|
|
|
assert.throws = function(block, /*optional*/error, /*optional*/message) {
|
|
_throws(true, block, error, message);
|
|
};
|
|
|
|
// EXTENSION! This is annoying to write outside this module.
|
|
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
|
|
_throws(false, block, error, message);
|
|
};
|
|
|
|
assert.ifError = function(err) { if (err) throw err; };
|
|
|
|
// Expose a strict only variant of assert
|
|
function strict(value, message) {
|
|
if (!value) fail(value, true, message, '==', strict);
|
|
}
|
|
assert.strict = objectAssign(strict, assert, {
|
|
equal: assert.strictEqual,
|
|
deepEqual: assert.deepStrictEqual,
|
|
notEqual: assert.notStrictEqual,
|
|
notDeepEqual: assert.notDeepStrictEqual
|
|
});
|
|
assert.strict.strict = assert.strict;
|
|
|
|
var objectKeys = Object.keys || function (obj) {
|
|
var keys = [];
|
|
for (var key in obj) {
|
|
if (hasOwn.call(obj, key)) keys.push(key);
|
|
}
|
|
return keys;
|
|
};
|
|
|
|
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(6)))
|
|
|
|
/***/ }),
|
|
/* 13 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
/*
|
|
object-assign
|
|
(c) Sindre Sorhus
|
|
@license MIT
|
|
*/
|
|
|
|
|
|
/* eslint-disable no-unused-vars */
|
|
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
|
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
|
|
function toObject(val) {
|
|
if (val === null || val === undefined) {
|
|
throw new TypeError('Object.assign cannot be called with null or undefined');
|
|
}
|
|
|
|
return Object(val);
|
|
}
|
|
|
|
function shouldUseNative() {
|
|
try {
|
|
if (!Object.assign) {
|
|
return false;
|
|
}
|
|
|
|
// Detect buggy property enumeration order in older V8 versions.
|
|
|
|
// https://bugs.chromium.org/p/v8/issues/detail?id=4118
|
|
var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
|
|
test1[5] = 'de';
|
|
if (Object.getOwnPropertyNames(test1)[0] === '5') {
|
|
return false;
|
|
}
|
|
|
|
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
|
var test2 = {};
|
|
for (var i = 0; i < 10; i++) {
|
|
test2['_' + String.fromCharCode(i)] = i;
|
|
}
|
|
var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
|
|
return test2[n];
|
|
});
|
|
if (order2.join('') !== '0123456789') {
|
|
return false;
|
|
}
|
|
|
|
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
|
var test3 = {};
|
|
'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
|
|
test3[letter] = letter;
|
|
});
|
|
if (Object.keys(Object.assign({}, test3)).join('') !==
|
|
'abcdefghijklmnopqrst') {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
} catch (err) {
|
|
// We don't expect any of the above to throw, but better to be safe.
|
|
return false;
|
|
}
|
|
}
|
|
|
|
module.exports = shouldUseNative() ? Object.assign : function (target, source) {
|
|
var from;
|
|
var to = toObject(target);
|
|
var symbols;
|
|
|
|
for (var s = 1; s < arguments.length; s++) {
|
|
from = Object(arguments[s]);
|
|
|
|
for (var key in from) {
|
|
if (hasOwnProperty.call(from, key)) {
|
|
to[key] = from[key];
|
|
}
|
|
}
|
|
|
|
if (getOwnPropertySymbols) {
|
|
symbols = getOwnPropertySymbols(from);
|
|
for (var i = 0; i < symbols.length; i++) {
|
|
if (propIsEnumerable.call(from, symbols[i])) {
|
|
to[symbols[i]] = from[symbols[i]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return to;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 14 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = "/*!\n * jQuery Migrate - v3.3.1 - 2020-06-25T01:07Z\n * Copyright OpenJS Foundation and other contributors\n */\n( function( factory ) {\n\t\"use strict\";\n\n\tif ( typeof define === \"function\" && define.amd ) {\n\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine( [ \"jquery\" ], function( jQuery ) {\n\t\t\treturn factory( jQuery, window );\n\t\t} );\n\t} else if ( typeof module === \"object\" && module.exports ) {\n\n\t\t// Node/CommonJS\n\t\t// eslint-disable-next-line no-undef\n\t\tmodule.exports = factory( require( \"jquery\" ), window );\n\t} else {\n\n\t\t// Browser globals\n\t\tfactory( jQuery, window );\n\t}\n} )( function( jQuery, window ) {\n\"use strict\";\n\njQuery.migrateVersion = \"3.3.1\";\n\n// Returns 0 if v1 == v2, -1 if v1 < v2, 1 if v1 > v2\nfunction compareVersions( v1, v2 ) {\n\tvar i,\n\t\trVersionParts = /^(\\d+)\\.(\\d+)\\.(\\d+)/,\n\t\tv1p = rVersionParts.exec( v1 ) || [ ],\n\t\tv2p = rVersionParts.exec( v2 ) || [ ];\n\n\tfor ( i = 1; i <= 3; i++ ) {\n\t\tif ( +v1p[ i ] > +v2p[ i ] ) {\n\t\t\treturn 1;\n\t\t}\n\t\tif ( +v1p[ i ] < +v2p[ i ] ) {\n\t\t\treturn -1;\n\t\t}\n\t}\n\treturn 0;\n}\n\nfunction jQueryVersionSince( version ) {\n\treturn compareVersions( jQuery.fn.jquery, version ) >= 0;\n}\n\n( function() {\n\n\t// Support: IE9 only\n\t// IE9 only creates console object when dev tools are first opened\n\t// IE9 console is a host object, callable but doesn't have .apply()\n\tif ( !window.console || !window.console.log ) {\n\t\treturn;\n\t}\n\n\t// Need jQuery 3.0.0+ and no older Migrate loaded\n\tif ( !jQuery || !jQueryVersionSince( \"3.0.0\" ) ) {\n\t\twindow.console.log( \"JQMIGRATE: jQuery 3.0.0+ REQUIRED\" );\n\t}\n\tif ( jQuery.migrateWarnings ) {\n\t\twindow.console.log( \"JQMIGRATE: Migrate plugin loaded multiple times\" );\n\t}\n\n\t// Show a message on the console so devs know we're active\n\twindow.console.log( \"JQMIGRATE: Migrate is installed\" +\n\t\t( jQuery.migrateMute ? \"\" : \" with logging active\" ) +\n\t\t\", version \" + jQuery.migrateVersion );\n\n} )();\n\nvar warnedAbout = {};\n\n// By default each warning is only reported once.\njQuery.migrateDeduplicateWarnings = true;\n\n// List of warnings already given; public read only\njQuery.migrateWarnings = [];\n\n// Set to false to disable traces that appear with warnings\nif ( jQuery.migrateTrace === undefined ) {\n\tjQuery.migrateTrace = true;\n}\n\n// Forget any warnings we've already given; public\njQuery.migrateReset = function() {\n\twarnedAbout = {};\n\tjQuery.migrateWarnings.length = 0;\n};\n\nfunction migrateWarn( msg ) {\n\tvar console = window.console;\n\tif ( !jQuery.migrateDeduplicateWarnings || !warnedAbout[ msg ] ) {\n\t\twarnedAbout[ msg ] = true;\n\t\tjQuery.migrateWarnings.push( msg );\n\t\tif ( console && console.warn && !jQuery.migrateMute ) {\n\t\t\tconsole.warn( \"JQMIGRATE: \" + msg );\n\t\t\tif ( jQuery.migrateTrace && console.trace ) {\n\t\t\t\tconsole.trace();\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction migrateWarnProp( obj, prop, value, msg ) {\n\tObject.defineProperty( obj, prop, {\n\t\tconfigurable: true,\n\t\tenumerable: true,\n\t\tget: function() {\n\t\t\tmigrateWarn( msg );\n\t\t\treturn value;\n\t\t},\n\t\tset: function( newValue ) {\n\t\t\tmigrateWarn( msg );\n\t\t\tvalue = newValue;\n\t\t}\n\t} );\n}\n\nfunction migrateWarnFunc( obj, prop, newFunc, msg ) {\n\tobj[ prop ] = function() {\n\t\tmigrateWarn( msg );\n\t\treturn newFunc.apply( this, arguments );\n\t};\n}\n\nif ( window.document.compatMode === \"BackCompat\" ) {\n\n\t// JQuery has never supported or tested Quirks Mode\n\tmigrateWarn( \"jQuery is not compatible with Quirks Mode\" );\n}\n\nvar findProp,\n\tclass2type = {},\n\toldInit = jQuery.fn.init,\n\toldFind = jQuery.find,\n\n\trattrHashTest = /\\[(\\s*[-\\w]+\\s*)([~|^$*]?=)\\s*([-\\w#]*?#[-\\w#]*)\\s*\\]/,\n\trattrHashGlob = /\\[(\\s*[-\\w]+\\s*)([~|^$*]?=)\\s*([-\\w#]*?#[-\\w#]*)\\s*\\]/g,\n\n\t// Support: Android <=4.0 only\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;\n\njQuery.fn.init = function( arg1 ) {\n\tvar args = Array.prototype.slice.call( arguments );\n\n\tif ( typeof arg1 === \"string\" && arg1 === \"#\" ) {\n\n\t\t// JQuery( \"#\" ) is a bogus ID selector, but it returned an empty set before jQuery 3.0\n\t\tmigrateWarn( \"jQuery( '#' ) is not a valid selector\" );\n\t\targs[ 0 ] = [];\n\t}\n\n\treturn oldInit.apply( this, args );\n};\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.find = function( selector ) {\n\tvar args = Array.prototype.slice.call( arguments );\n\n\t// Support: PhantomJS 1.x\n\t// String#match fails to match when used with a //g RegExp, only on some strings\n\tif ( typeof selector === \"string\" && rattrHashTest.test( selector ) ) {\n\n\t\t// The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0\n\t\t// First see if qS thinks it's a valid selector, if so avoid a false positive\n\t\ttry {\n\t\t\twindow.document.querySelector( selector );\n\t\t} catch ( err1 ) {\n\n\t\t\t// Didn't *look* valid to qSA, warn and try quoting what we think is the value\n\t\t\tselector = selector.replace( rattrHashGlob, function( _, attr, op, value ) {\n\t\t\t\treturn \"[\" + attr + op + \"\\\"\" + value + \"\\\"]\";\n\t\t\t} );\n\n\t\t\t// If the regexp *may* have created an invalid selector, don't update it\n\t\t\t// Note that there may be false alarms if selector uses jQuery extensions\n\t\t\ttry {\n\t\t\t\twindow.document.querySelector( selector );\n\t\t\t\tmigrateWarn( \"Attribute selector with '#' must be quoted: \" + args[ 0 ] );\n\t\t\t\targs[ 0 ] = selector;\n\t\t\t} catch ( err2 ) {\n\t\t\t\tmigrateWarn( \"Attribute selector with '#' was not fixed: \" + args[ 0 ] );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn oldFind.apply( this, args );\n};\n\n// Copy properties attached to original jQuery.find method (e.g. .attr, .isXML)\nfor ( findProp in oldFind ) {\n\tif ( Object.prototype.hasOwnProperty.call( oldFind, findProp ) ) {\n\t\tjQuery.find[ findProp ] = oldFind[ findProp ];\n\t}\n}\n\n// The number of elements contained in the matched element set\nmigrateWarnFunc( jQuery.fn, \"size\", function() {\n\treturn this.length;\n},\n\"jQuery.fn.size() is deprecated and removed; use the .length property\" );\n\nmigrateWarnFunc( jQuery, \"parseJSON\", function() {\n\treturn JSON.parse.apply( null, arguments );\n},\n\"jQuery.parseJSON is deprecated; use JSON.parse\" );\n\nmigrateWarnFunc( jQuery, \"holdReady\", jQuery.holdReady,\n\t\"jQuery.holdReady is deprecated\" );\n\nmigrateWarnFunc( jQuery, \"unique\", jQuery.uniqueSort,\n\t\"jQuery.unique is deprecated; use jQuery.uniqueSort\" );\n\n// Now jQuery.expr.pseudos is the standard incantation\nmigrateWarnProp( jQuery.expr, \"filters\", jQuery.expr.pseudos,\n\t\"jQuery.expr.filters is deprecated; use jQuery.expr.pseudos\" );\nmigrateWarnProp( jQuery.expr, \":\", jQuery.expr.pseudos,\n\t\"jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos\" );\n\n// Prior to jQuery 3.1.1 there were internal refs so we don't warn there\nif ( jQueryVersionSince( \"3.1.1\" ) ) {\n\tmigrateWarnFunc( jQuery, \"trim\", function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\t\"jQuery.trim is deprecated; use String.prototype.trim\" );\n}\n\n// Prior to jQuery 3.2 there were internal refs so we don't warn there\nif ( jQueryVersionSince( \"3.2.0\" ) ) {\n\tmigrateWarnFunc( jQuery, \"nodeName\", function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\t\"jQuery.nodeName is deprecated\" );\n}\n\nif ( jQueryVersionSince( \"3.3.0\" ) ) {\n\n\tmigrateWarnFunc( jQuery, \"isNumeric\", function( obj ) {\n\n\t\t\t// As of jQuery 3.0, isNumeric is limited to\n\t\t\t// strings and numbers (primitives or objects)\n\t\t\t// that can be coerced to finite numbers (gh-2662)\n\t\t\tvar type = typeof obj;\n\t\t\treturn ( type === \"number\" || type === \"string\" ) &&\n\n\t\t\t\t// parseFloat NaNs numeric-cast false positives (\"\")\n\t\t\t\t// ...but misinterprets leading-number strings, e.g. hex literals (\"0x...\")\n\t\t\t\t// subtraction forces infinities to NaN\n\t\t\t\t!isNaN( obj - parseFloat( obj ) );\n\t\t},\n\t\t\"jQuery.isNumeric() is deprecated\"\n\t);\n\n\t// Populate the class2type map\n\tjQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".\n\t\tsplit( \" \" ),\n\tfunction( _, name ) {\n\t\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n\t} );\n\n\tmigrateWarnFunc( jQuery, \"type\", function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\n\n\t\t// Support: Android <=2.3 only (functionish RegExp)\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ Object.prototype.toString.call( obj ) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\t\"jQuery.type is deprecated\" );\n\n\tmigrateWarnFunc( jQuery, \"isFunction\",\n\t\tfunction( obj ) {\n\t\t\treturn typeof obj === \"function\";\n\t\t},\n\t\t\"jQuery.isFunction() is deprecated\" );\n\n\tmigrateWarnFunc( jQuery, \"isWindow\",\n\t\tfunction( obj ) {\n\t\t\treturn obj != null && obj === obj.window;\n\t\t},\n\t\t\"jQuery.isWindow() is deprecated\"\n\t);\n\n\tmigrateWarnFunc( jQuery, \"isArray\", Array.isArray,\n\t\t\"jQuery.isArray is deprecated; use Array.isArray\"\n\t);\n}\n\n// Support jQuery slim which excludes the ajax module\nif ( jQuery.ajax ) {\n\nvar oldAjax = jQuery.ajax;\n\njQuery.ajax = function( ) {\n\tvar jQXHR = oldAjax.apply( this, arguments );\n\n\t// Be sure we got a jQXHR (e.g., not sync)\n\tif ( jQXHR.promise ) {\n\t\tmigrateWarnFunc( jQXHR, \"success\", jQXHR.done,\n\t\t\t\"jQXHR.success is deprecated and removed\" );\n\t\tmigrateWarnFunc( jQXHR, \"error\", jQXHR.fail,\n\t\t\t\"jQXHR.error is deprecated and removed\" );\n\t\tmigrateWarnFunc( jQXHR, \"complete\", jQXHR.always,\n\t\t\t\"jQXHR.complete is deprecated and removed\" );\n\t}\n\n\treturn jQXHR;\n};\n\n}\n\nvar oldRemoveAttr = jQuery.fn.removeAttr,\n\toldToggleClass = jQuery.fn.toggleClass,\n\trmatchNonSpace = /\\S+/g;\n\njQuery.fn.removeAttr = function( name ) {\n\tvar self = this;\n\n\tjQuery.each( name.match( rmatchNonSpace ), function( _i, attr ) {\n\t\tif ( jQuery.expr.match.bool.test( attr ) ) {\n\t\t\tmigrateWarn( \"jQuery.fn.removeAttr no longer sets boolean properties: \" + attr );\n\t\t\tself.prop( attr, false );\n\t\t}\n\t} );\n\n\treturn oldRemoveAttr.apply( this, arguments );\n};\n\njQuery.fn.toggleClass = function( state ) {\n\n\t// Only deprecating no-args or single boolean arg\n\tif ( state !== undefined && typeof state !== \"boolean\" ) {\n\t\treturn oldToggleClass.apply( this, arguments );\n\t}\n\n\tmigrateWarn( \"jQuery.fn.toggleClass( boolean ) is deprecated\" );\n\n\t// Toggle entire class name of each element\n\treturn this.each( function() {\n\t\tvar className = this.getAttribute && this.getAttribute( \"class\" ) || \"\";\n\n\t\tif ( className ) {\n\t\t\tjQuery.data( this, \"__className__\", className );\n\t\t}\n\n\t\t// If the element has a class name or if we're passed `false`,\n\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t// falling back to the empty string if nothing was stored.\n\t\tif ( this.setAttribute ) {\n\t\t\tthis.setAttribute( \"class\",\n\t\t\t\tclassName || state === false ?\n\t\t\t\t\"\" :\n\t\t\t\tjQuery.data( this, \"__className__\" ) || \"\"\n\t\t\t);\n\t\t}\n\t} );\n};\n\nfunction camelCase( string ) {\n\treturn string.replace( /-([a-z])/g, function( _, letter ) {\n\t\treturn letter.toUpperCase();\n\t} );\n}\n\nvar oldFnCss,\n\tinternalSwapCall = false,\n\tralphaStart = /^[a-z]/,\n\n\t// The regex visualized:\n\t//\n\t// /----------\\\n\t// | | /-------\\\n\t// | / Top \\ | | |\n\t// /--- Border ---+-| Right |-+---+- Width -+---\\\n\t// | | Bottom | |\n\t// | \\ Left / |\n\t// | |\n\t// | /----------\\ |\n\t// | /-------------\\ | | |- END\n\t// | | | | / Top \\ | |\n\t// | | / Margin \\ | | | Right | | |\n\t// |---------+-| |-+---+-| Bottom |-+----|\n\t// | \\ Padding / \\ Left / |\n\t// BEGIN -| |\n\t// | /---------\\ |\n\t// | | | |\n\t// | | / Min \\ | / Width \\ |\n\t// \\--------------+-| |-+---| |---/\n\t// \\ Max / \\ Height /\n\trautoPx = /^(?:Border(?:Top|Right|Bottom|Left)?(?:Width|)|(?:Margin|Padding)?(?:Top|Right|Bottom|Left)?|(?:Min|Max)?(?:Width|Height))$/;\n\n// If this version of jQuery has .swap(), don't false-alarm on internal uses\nif ( jQuery.swap ) {\n\tjQuery.each( [ \"height\", \"width\", \"reliableMarginRight\" ], function( _, name ) {\n\t\tvar oldHook = jQuery.cssHooks[ name ] && jQuery.cssHooks[ name ].get;\n\n\t\tif ( oldHook ) {\n\t\t\tjQuery.cssHooks[ name ].get = function() {\n\t\t\t\tvar ret;\n\n\t\t\t\tinternalSwapCall = true;\n\t\t\t\tret = oldHook.apply( this, arguments );\n\t\t\t\tinternalSwapCall = false;\n\t\t\t\treturn ret;\n\t\t\t};\n\t\t}\n\t} );\n}\n\njQuery.swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\tif ( !internalSwapCall ) {\n\t\tmigrateWarn( \"jQuery.swap() is undocumented and deprecated\" );\n\t}\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\nif ( jQueryVersionSince( \"3.4.0\" ) && typeof Proxy !== \"undefined\" ) {\n\n\tjQuery.cssProps = new Proxy( jQuery.cssProps || {}, {\n\t\tset: function() {\n\t\t\tmigrateWarn( \"JQMIGRATE: jQuery.cssProps is deprecated\" );\n\t\t\treturn Reflect.set.apply( this, arguments );\n\t\t}\n\t} );\n}\n\n// Create a dummy jQuery.cssNumber if missing. It won't be used by jQuery but\n// it will prevent code adding new keys to it unconditionally from crashing.\nif ( !jQuery.cssNumber ) {\n\tjQuery.cssNumber = {};\n}\n\nfunction isAutoPx( prop ) {\n\n\t// The first test is used to ensure that:\n\t// 1. The prop starts with a lowercase letter (as we uppercase it for the second regex).\n\t// 2. The prop is not empty.\n\treturn ralphaStart.test( prop ) &&\n\t\trautoPx.test( prop[ 0 ].toUpperCase() + prop.slice( 1 ) );\n}\n\noldFnCss = jQuery.fn.css;\n\njQuery.fn.css = function( name, value ) {\n\tvar camelName,\n\t\torigThis = this;\n\tif ( name && typeof name === \"object\" && !Array.isArray( name ) ) {\n\t\tjQuery.each( name, function( n, v ) {\n\t\t\tjQuery.fn.css.call( origThis, n, v );\n\t\t} );\n\t}\n\tif ( typeof value === \"number\" ) {\n\t\tcamelName = camelCase( name );\n\t\tif ( !isAutoPx( camelName ) && !jQuery.cssNumber[ camelName ] ) {\n\t\t\tmigrateWarn( \"Number-typed values are deprecated for jQuery.fn.css( \\\"\" +\n\t\t\t\tname + \"\\\", value )\" );\n\t\t}\n\t}\n\n\treturn oldFnCss.apply( this, arguments );\n};\n\nvar oldData = jQuery.data;\n\njQuery.data = function( elem, name, value ) {\n\tvar curData, sameKeys, key;\n\n\t// Name can be an object, and each entry in the object is meant to be set as data\n\tif ( name && typeof name === \"object\" && arguments.length === 2 ) {\n\t\tcurData = jQuery.hasData( elem ) && oldData.call( this, elem );\n\t\tsameKeys = {};\n\t\tfor ( key in name ) {\n\t\t\tif ( key !== camelCase( key ) ) {\n\t\t\t\tmigrateWarn( \"jQuery.data() always sets/gets camelCased names: \" + key );\n\t\t\t\tcurData[ key ] = name[ key ];\n\t\t\t} else {\n\t\t\t\tsameKeys[ key ] = name[ key ];\n\t\t\t}\n\t\t}\n\n\t\toldData.call( this, elem, sameKeys );\n\n\t\treturn name;\n\t}\n\n\t// If the name is transformed, look for the un-transformed name in the data object\n\tif ( name && typeof name === \"string\" && name !== camelCase( name ) ) {\n\t\tcurData = jQuery.hasData( elem ) && oldData.call( this, elem );\n\t\tif ( curData && name in curData ) {\n\t\t\tmigrateWarn( \"jQuery.data() always sets/gets camelCased names: \" + name );\n\t\t\tif ( arguments.length > 2 ) {\n\t\t\t\tcurData[ name ] = value;\n\t\t\t}\n\t\t\treturn curData[ name ];\n\t\t}\n\t}\n\n\treturn oldData.apply( this, arguments );\n};\n\n// Support jQuery slim which excludes the effects module\nif ( jQuery.fx ) {\n\nvar intervalValue, intervalMsg,\n\toldTweenRun = jQuery.Tween.prototype.run,\n\tlinearEasing = function( pct ) {\n\t\treturn pct;\n\t};\n\njQuery.Tween.prototype.run = function( ) {\n\tif ( jQuery.easing[ this.easing ].length > 1 ) {\n\t\tmigrateWarn(\n\t\t\t\"'jQuery.easing.\" + this.easing.toString() + \"' should use only one argument\"\n\t\t);\n\n\t\tjQuery.easing[ this.easing ] = linearEasing;\n\t}\n\n\toldTweenRun.apply( this, arguments );\n};\n\nintervalValue = jQuery.fx.interval || 13;\nintervalMsg = \"jQuery.fx.interval is deprecated\";\n\n// Support: IE9, Android <=4.4\n// Avoid false positives on browsers that lack rAF\n// Don't warn if document is hidden, jQuery uses setTimeout (#292)\nif ( window.requestAnimationFrame ) {\n\tObject.defineProperty( jQuery.fx, \"interval\", {\n\t\tconfigurable: true,\n\t\tenumerable: true,\n\t\tget: function() {\n\t\t\tif ( !window.document.hidden ) {\n\t\t\t\tmigrateWarn( intervalMsg );\n\t\t\t}\n\t\t\treturn intervalValue;\n\t\t},\n\t\tset: function( newValue ) {\n\t\t\tmigrateWarn( intervalMsg );\n\t\t\tintervalValue = newValue;\n\t\t}\n\t} );\n}\n\n}\n\nvar oldLoad = jQuery.fn.load,\n\toldEventAdd = jQuery.event.add,\n\toriginalFix = jQuery.event.fix;\n\njQuery.event.props = [];\njQuery.event.fixHooks = {};\n\nmigrateWarnProp( jQuery.event.props, \"concat\", jQuery.event.props.concat,\n\t\"jQuery.event.props.concat() is deprecated and removed\" );\n\njQuery.event.fix = function( originalEvent ) {\n\tvar event,\n\t\ttype = originalEvent.type,\n\t\tfixHook = this.fixHooks[ type ],\n\t\tprops = jQuery.event.props;\n\n\tif ( props.length ) {\n\t\tmigrateWarn( \"jQuery.event.props are deprecated and removed: \" + props.join() );\n\t\twhile ( props.length ) {\n\t\t\tjQuery.event.addProp( props.pop() );\n\t\t}\n\t}\n\n\tif ( fixHook && !fixHook._migrated_ ) {\n\t\tfixHook._migrated_ = true;\n\t\tmigrateWarn( \"jQuery.event.fixHooks are deprecated and removed: \" + type );\n\t\tif ( ( props = fixHook.props ) && props.length ) {\n\t\t\twhile ( props.length ) {\n\t\t\t\tjQuery.event.addProp( props.pop() );\n\t\t\t}\n\t\t}\n\t}\n\n\tevent = originalFix.call( this, originalEvent );\n\n\treturn fixHook && fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n};\n\njQuery.event.add = function( elem, types ) {\n\n\t// This misses the multiple-types case but that seems awfully rare\n\tif ( elem === window && types === \"load\" && window.document.readyState === \"complete\" ) {\n\t\tmigrateWarn( \"jQuery(window).on('load'...) called after load event occurred\" );\n\t}\n\treturn oldEventAdd.apply( this, arguments );\n};\n\njQuery.each( [ \"load\", \"unload\", \"error\" ], function( _, name ) {\n\n\tjQuery.fn[ name ] = function() {\n\t\tvar args = Array.prototype.slice.call( arguments, 0 );\n\n\t\t// If this is an ajax load() the first arg should be the string URL;\n\t\t// technically this could also be the \"Anything\" arg of the event .load()\n\t\t// which just goes to show why this dumb signature has been deprecated!\n\t\t// jQuery custom builds that exclude the Ajax module justifiably die here.\n\t\tif ( name === \"load\" && typeof args[ 0 ] === \"string\" ) {\n\t\t\treturn oldLoad.apply( this, args );\n\t\t}\n\n\t\tmigrateWarn( \"jQuery.fn.\" + name + \"() is deprecated\" );\n\n\t\targs.splice( 0, 0, name );\n\t\tif ( arguments.length ) {\n\t\t\treturn this.on.apply( this, args );\n\t\t}\n\n\t\t// Use .triggerHandler here because:\n\t\t// - load and unload events don't need to bubble, only applied to window or image\n\t\t// - error event should not bubble to window, although it does pre-1.7\n\t\t// See http://bugs.jquery.com/ticket/11820\n\t\tthis.triggerHandler.apply( this, args );\n\t\treturn this;\n\t};\n\n} );\n\njQuery.each( ( \"blur focus focusin focusout resize scroll click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup contextmenu\" ).split( \" \" ),\n\tfunction( _i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\tmigrateWarn( \"jQuery.fn.\" + name + \"() event shorthand is deprecated\" );\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n} );\n\n// Trigger \"ready\" event only once, on document ready\njQuery( function() {\n\tjQuery( window.document ).triggerHandler( \"ready\" );\n} );\n\njQuery.event.special.ready = {\n\tsetup: function() {\n\t\tif ( this === window.document ) {\n\t\t\tmigrateWarn( \"'ready' event is deprecated\" );\n\t\t}\n\t}\n};\n\njQuery.fn.extend( {\n\n\tbind: function( types, data, fn ) {\n\t\tmigrateWarn( \"jQuery.fn.bind() is deprecated\" );\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\tmigrateWarn( \"jQuery.fn.unbind() is deprecated\" );\n\t\treturn this.off( types, null, fn );\n\t},\n\tdelegate: function( selector, types, data, fn ) {\n\t\tmigrateWarn( \"jQuery.fn.delegate() is deprecated\" );\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\tmigrateWarn( \"jQuery.fn.undelegate() is deprecated\" );\n\t\treturn arguments.length === 1 ?\n\t\t\tthis.off( selector, \"**\" ) :\n\t\t\tthis.off( types, selector || \"**\", fn );\n\t},\n\thover: function( fnOver, fnOut ) {\n\t\tmigrateWarn( \"jQuery.fn.hover() is deprecated\" );\n\t\treturn this.on( \"mouseenter\", fnOver ).on( \"mouseleave\", fnOut || fnOver );\n\t}\n} );\n\nvar rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)[^>]*)\\/>/gi,\n\torigHtmlPrefilter = jQuery.htmlPrefilter,\n\tmakeMarkup = function( html ) {\n\t\tvar doc = window.document.implementation.createHTMLDocument( \"\" );\n\t\tdoc.body.innerHTML = html;\n\t\treturn doc.body && doc.body.innerHTML;\n\t},\n\twarnIfChanged = function( html ) {\n\t\tvar changed = html.replace( rxhtmlTag, \"<$1></$2>\" );\n\t\tif ( changed !== html && makeMarkup( html ) !== makeMarkup( changed ) ) {\n\t\t\tmigrateWarn( \"HTML tags must be properly nested and closed: \" + html );\n\t\t}\n\t};\n\njQuery.UNSAFE_restoreLegacyHtmlPrefilter = function() {\n\tjQuery.htmlPrefilter = function( html ) {\n\t\twarnIfChanged( html );\n\t\treturn html.replace( rxhtmlTag, \"<$1></$2>\" );\n\t};\n};\n\njQuery.htmlPrefilter = function( html ) {\n\twarnIfChanged( html );\n\treturn origHtmlPrefilter( html );\n};\n\nvar oldOffset = jQuery.fn.offset;\n\njQuery.fn.offset = function() {\n\tvar elem = this[ 0 ];\n\n\tif ( elem && ( !elem.nodeType || !elem.getBoundingClientRect ) ) {\n\t\tmigrateWarn( \"jQuery.fn.offset() requires a valid DOM element\" );\n\t\treturn arguments.length ? this : undefined;\n\t}\n\n\treturn oldOffset.apply( this, arguments );\n};\n\n// Support jQuery slim which excludes the ajax module\n// The jQuery.param patch is about respecting `jQuery.ajaxSettings.traditional`\n// so it doesn't make sense for the slim build.\nif ( jQuery.ajax ) {\n\nvar oldParam = jQuery.param;\n\njQuery.param = function( data, traditional ) {\n\tvar ajaxTraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\n\tif ( traditional === undefined && ajaxTraditional ) {\n\n\t\tmigrateWarn( \"jQuery.param() no longer uses jQuery.ajaxSettings.traditional\" );\n\t\ttraditional = ajaxTraditional;\n\t}\n\n\treturn oldParam.call( this, data, traditional );\n};\n\n}\n\nvar oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack;\n\njQuery.fn.andSelf = function() {\n\tmigrateWarn( \"jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()\" );\n\treturn oldSelf.apply( this, arguments );\n};\n\n// Support jQuery slim which excludes the deferred module in jQuery 4.0+\nif ( jQuery.Deferred ) {\n\nvar oldDeferred = jQuery.Deferred,\n\ttuples = [\n\n\t\t// Action, add listener, callbacks, .then handlers, final state\n\t\t[ \"resolve\", \"done\", jQuery.Callbacks( \"once memory\" ),\n\t\t\tjQuery.Callbacks( \"once memory\" ), \"resolved\" ],\n\t\t[ \"reject\", \"fail\", jQuery.Callbacks( \"once memory\" ),\n\t\t\tjQuery.Callbacks( \"once memory\" ), \"rejected\" ],\n\t\t[ \"notify\", \"progress\", jQuery.Callbacks( \"memory\" ),\n\t\t\tjQuery.Callbacks( \"memory\" ) ]\n\t];\n\njQuery.Deferred = function( func ) {\n\tvar deferred = oldDeferred(),\n\t\tpromise = deferred.promise();\n\n\tdeferred.pipe = promise.pipe = function( /* fnDone, fnFail, fnProgress */ ) {\n\t\tvar fns = arguments;\n\n\t\tmigrateWarn( \"deferred.pipe() is deprecated\" );\n\n\t\treturn jQuery.Deferred( function( newDefer ) {\n\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\tvar fn = typeof fns[ i ] === \"function\" && fns[ i ];\n\n\t\t\t\t// Deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\n\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\tdeferred[ tuple[ 1 ] ]( function() {\n\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\tif ( returned && typeof returned.promise === \"function\" ) {\n\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\tthis === promise ? newDefer.promise() : this,\n\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} );\n\t\t\tfns = null;\n\t\t} ).promise();\n\n\t};\n\n\tif ( func ) {\n\t\tfunc.call( deferred, deferred );\n\t}\n\n\treturn deferred;\n};\n\n// Preserve handler of uncaught exceptions in promise chains\njQuery.Deferred.exceptionHook = oldDeferred.exceptionHook;\n\n}\n\nreturn jQuery;\n} );\n"
|
|
|
|
/***/ }),
|
|
/* 15 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
|
|
$.ui = $.ui || {};
|
|
|
|
return $.ui.version = "1.12.1";
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 16 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
|
|
// This file is deprecated
|
|
return $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 17 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
|
|
// $.ui.plugin is deprecated. Use $.widget() extensions instead.
|
|
return $.ui.plugin = {
|
|
add: function( module, option, set ) {
|
|
var i,
|
|
proto = $.ui[ module ].prototype;
|
|
for ( i in set ) {
|
|
proto.plugins[ i ] = proto.plugins[ i ] || [];
|
|
proto.plugins[ i ].push( [ option, set[ i ] ] );
|
|
}
|
|
},
|
|
call: function( instance, name, args, allowDisconnected ) {
|
|
var i,
|
|
set = instance.plugins[ name ];
|
|
|
|
if ( !set ) {
|
|
return;
|
|
}
|
|
|
|
if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
|
|
instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
|
|
return;
|
|
}
|
|
|
|
for ( i = 0; i < set.length; i++ ) {
|
|
if ( instance.options[ set[ i ][ 0 ] ] ) {
|
|
set[ i ][ 1 ].apply( instance.element, args );
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 18 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
return $.ui.safeActiveElement = function( document ) {
|
|
var activeElement;
|
|
|
|
// Support: IE 9 only
|
|
// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
|
|
try {
|
|
activeElement = document.activeElement;
|
|
} catch ( error ) {
|
|
activeElement = document.body;
|
|
}
|
|
|
|
// Support: IE 9 - 11 only
|
|
// IE may return null instead of an element
|
|
// Interestingly, this only seems to occur when NOT in an iframe
|
|
if ( !activeElement ) {
|
|
activeElement = document.body;
|
|
}
|
|
|
|
// Support: IE 11 only
|
|
// IE11 returns a seemingly empty object in some cases when accessing
|
|
// document.activeElement from an <iframe>
|
|
if ( !activeElement.nodeName ) {
|
|
activeElement = document.body;
|
|
}
|
|
|
|
return activeElement;
|
|
};
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 19 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
return $.ui.safeBlur = function( element ) {
|
|
|
|
// Support: IE9 - 10 only
|
|
// If the <body> is blurred, IE will switch windows, see #9420
|
|
if ( element && element.nodeName.toLowerCase() !== "body" ) {
|
|
$( element ).trigger( "blur" );
|
|
}
|
|
};
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 20 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Widget 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Widget
|
|
//>>group: Core
|
|
//>>description: Provides a factory for creating stateful widgets with a common API.
|
|
//>>docs: http://api.jqueryui.com/jQuery.widget/
|
|
//>>demos: http://jqueryui.com/widget/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
var widgetUuid = 0;
|
|
var widgetSlice = Array.prototype.slice;
|
|
|
|
$.cleanData = ( function( orig ) {
|
|
return function( elems ) {
|
|
var events, elem, i;
|
|
for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
|
|
try {
|
|
|
|
// Only trigger remove when necessary to save time
|
|
events = $._data( elem, "events" );
|
|
if ( events && events.remove ) {
|
|
$( elem ).triggerHandler( "remove" );
|
|
}
|
|
|
|
// Http://bugs.jquery.com/ticket/8235
|
|
} catch ( e ) {}
|
|
}
|
|
orig( elems );
|
|
};
|
|
} )( $.cleanData );
|
|
|
|
$.widget = function( name, base, prototype ) {
|
|
var existingConstructor, constructor, basePrototype;
|
|
|
|
// ProxiedPrototype allows the provided prototype to remain unmodified
|
|
// so that it can be used as a mixin for multiple widgets (#8876)
|
|
var proxiedPrototype = {};
|
|
|
|
var namespace = name.split( "." )[ 0 ];
|
|
name = name.split( "." )[ 1 ];
|
|
var fullName = namespace + "-" + name;
|
|
|
|
if ( !prototype ) {
|
|
prototype = base;
|
|
base = $.Widget;
|
|
}
|
|
|
|
if ( $.isArray( prototype ) ) {
|
|
prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
|
|
}
|
|
|
|
// Create selector for plugin
|
|
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
|
|
return !!$.data( elem, fullName );
|
|
};
|
|
|
|
$[ namespace ] = $[ namespace ] || {};
|
|
existingConstructor = $[ namespace ][ name ];
|
|
constructor = $[ namespace ][ name ] = function( options, element ) {
|
|
|
|
// Allow instantiation without "new" keyword
|
|
if ( !this._createWidget ) {
|
|
return new constructor( options, element );
|
|
}
|
|
|
|
// Allow instantiation without initializing for simple inheritance
|
|
// must use "new" keyword (the code above always passes args)
|
|
if ( arguments.length ) {
|
|
this._createWidget( options, element );
|
|
}
|
|
};
|
|
|
|
// Extend with the existing constructor to carry over any static properties
|
|
$.extend( constructor, existingConstructor, {
|
|
version: prototype.version,
|
|
|
|
// Copy the object used to create the prototype in case we need to
|
|
// redefine the widget later
|
|
_proto: $.extend( {}, prototype ),
|
|
|
|
// Track widgets that inherit from this widget in case this widget is
|
|
// redefined after a widget inherits from it
|
|
_childConstructors: []
|
|
} );
|
|
|
|
basePrototype = new base();
|
|
|
|
// We need to make the options hash a property directly on the new instance
|
|
// otherwise we'll modify the options hash on the prototype that we're
|
|
// inheriting from
|
|
basePrototype.options = $.widget.extend( {}, basePrototype.options );
|
|
$.each( prototype, function( prop, value ) {
|
|
if ( !$.isFunction( value ) ) {
|
|
proxiedPrototype[ prop ] = value;
|
|
return;
|
|
}
|
|
proxiedPrototype[ prop ] = ( function() {
|
|
function _super() {
|
|
return base.prototype[ prop ].apply( this, arguments );
|
|
}
|
|
|
|
function _superApply( args ) {
|
|
return base.prototype[ prop ].apply( this, args );
|
|
}
|
|
|
|
return function() {
|
|
var __super = this._super;
|
|
var __superApply = this._superApply;
|
|
var returnValue;
|
|
|
|
this._super = _super;
|
|
this._superApply = _superApply;
|
|
|
|
returnValue = value.apply( this, arguments );
|
|
|
|
this._super = __super;
|
|
this._superApply = __superApply;
|
|
|
|
return returnValue;
|
|
};
|
|
} )();
|
|
} );
|
|
constructor.prototype = $.widget.extend( basePrototype, {
|
|
|
|
// TODO: remove support for widgetEventPrefix
|
|
// always use the name + a colon as the prefix, e.g., draggable:start
|
|
// don't prefix for widgets that aren't DOM-based
|
|
widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
|
|
}, proxiedPrototype, {
|
|
constructor: constructor,
|
|
namespace: namespace,
|
|
widgetName: name,
|
|
widgetFullName: fullName
|
|
} );
|
|
|
|
// If this widget is being redefined then we need to find all widgets that
|
|
// are inheriting from it and redefine all of them so that they inherit from
|
|
// the new version of this widget. We're essentially trying to replace one
|
|
// level in the prototype chain.
|
|
if ( existingConstructor ) {
|
|
$.each( existingConstructor._childConstructors, function( i, child ) {
|
|
var childPrototype = child.prototype;
|
|
|
|
// Redefine the child widget using the same prototype that was
|
|
// originally used, but inherit from the new version of the base
|
|
$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
|
|
child._proto );
|
|
} );
|
|
|
|
// Remove the list of existing child constructors from the old constructor
|
|
// so the old child constructors can be garbage collected
|
|
delete existingConstructor._childConstructors;
|
|
} else {
|
|
base._childConstructors.push( constructor );
|
|
}
|
|
|
|
$.widget.bridge( name, constructor );
|
|
|
|
return constructor;
|
|
};
|
|
|
|
$.widget.extend = function( target ) {
|
|
var input = widgetSlice.call( arguments, 1 );
|
|
var inputIndex = 0;
|
|
var inputLength = input.length;
|
|
var key;
|
|
var value;
|
|
|
|
for ( ; inputIndex < inputLength; inputIndex++ ) {
|
|
for ( key in input[ inputIndex ] ) {
|
|
value = input[ inputIndex ][ key ];
|
|
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
|
|
|
|
// Clone objects
|
|
if ( $.isPlainObject( value ) ) {
|
|
target[ key ] = $.isPlainObject( target[ key ] ) ?
|
|
$.widget.extend( {}, target[ key ], value ) :
|
|
|
|
// Don't extend strings, arrays, etc. with objects
|
|
$.widget.extend( {}, value );
|
|
|
|
// Copy everything else by reference
|
|
} else {
|
|
target[ key ] = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return target;
|
|
};
|
|
|
|
$.widget.bridge = function( name, object ) {
|
|
var fullName = object.prototype.widgetFullName || name;
|
|
$.fn[ name ] = function( options ) {
|
|
var isMethodCall = typeof options === "string";
|
|
var args = widgetSlice.call( arguments, 1 );
|
|
var returnValue = this;
|
|
|
|
if ( isMethodCall ) {
|
|
|
|
// If this is an empty collection, we need to have the instance method
|
|
// return undefined instead of the jQuery instance
|
|
if ( !this.length && options === "instance" ) {
|
|
returnValue = undefined;
|
|
} else {
|
|
this.each( function() {
|
|
var methodValue;
|
|
var instance = $.data( this, fullName );
|
|
|
|
if ( options === "instance" ) {
|
|
returnValue = instance;
|
|
return false;
|
|
}
|
|
|
|
if ( !instance ) {
|
|
return $.error( "cannot call methods on " + name +
|
|
" prior to initialization; " +
|
|
"attempted to call method '" + options + "'" );
|
|
}
|
|
|
|
if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
|
|
return $.error( "no such method '" + options + "' for " + name +
|
|
" widget instance" );
|
|
}
|
|
|
|
methodValue = instance[ options ].apply( instance, args );
|
|
|
|
if ( methodValue !== instance && methodValue !== undefined ) {
|
|
returnValue = methodValue && methodValue.jquery ?
|
|
returnValue.pushStack( methodValue.get() ) :
|
|
methodValue;
|
|
return false;
|
|
}
|
|
} );
|
|
}
|
|
} else {
|
|
|
|
// Allow multiple hashes to be passed on init
|
|
if ( args.length ) {
|
|
options = $.widget.extend.apply( null, [ options ].concat( args ) );
|
|
}
|
|
|
|
this.each( function() {
|
|
var instance = $.data( this, fullName );
|
|
if ( instance ) {
|
|
instance.option( options || {} );
|
|
if ( instance._init ) {
|
|
instance._init();
|
|
}
|
|
} else {
|
|
$.data( this, fullName, new object( options, this ) );
|
|
}
|
|
} );
|
|
}
|
|
|
|
return returnValue;
|
|
};
|
|
};
|
|
|
|
$.Widget = function( /* options, element */ ) {};
|
|
$.Widget._childConstructors = [];
|
|
|
|
$.Widget.prototype = {
|
|
widgetName: "widget",
|
|
widgetEventPrefix: "",
|
|
defaultElement: "<div>",
|
|
|
|
options: {
|
|
classes: {},
|
|
disabled: false,
|
|
|
|
// Callbacks
|
|
create: null
|
|
},
|
|
|
|
_createWidget: function( options, element ) {
|
|
element = $( element || this.defaultElement || this )[ 0 ];
|
|
this.element = $( element );
|
|
this.uuid = widgetUuid++;
|
|
this.eventNamespace = "." + this.widgetName + this.uuid;
|
|
|
|
this.bindings = $();
|
|
this.hoverable = $();
|
|
this.focusable = $();
|
|
this.classesElementLookup = {};
|
|
|
|
if ( element !== this ) {
|
|
$.data( element, this.widgetFullName, this );
|
|
this._on( true, this.element, {
|
|
remove: function( event ) {
|
|
if ( event.target === element ) {
|
|
this.destroy();
|
|
}
|
|
}
|
|
} );
|
|
this.document = $( element.style ?
|
|
|
|
// Element within the document
|
|
element.ownerDocument :
|
|
|
|
// Element is window or document
|
|
element.document || element );
|
|
this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
|
|
}
|
|
|
|
this.options = $.widget.extend( {},
|
|
this.options,
|
|
this._getCreateOptions(),
|
|
options );
|
|
|
|
this._create();
|
|
|
|
if ( this.options.disabled ) {
|
|
this._setOptionDisabled( this.options.disabled );
|
|
}
|
|
|
|
this._trigger( "create", null, this._getCreateEventData() );
|
|
this._init();
|
|
},
|
|
|
|
_getCreateOptions: function() {
|
|
return {};
|
|
},
|
|
|
|
_getCreateEventData: $.noop,
|
|
|
|
_create: $.noop,
|
|
|
|
_init: $.noop,
|
|
|
|
destroy: function() {
|
|
var that = this;
|
|
|
|
this._destroy();
|
|
$.each( this.classesElementLookup, function( key, value ) {
|
|
that._removeClass( value, key );
|
|
} );
|
|
|
|
// We can probably remove the unbind calls in 2.0
|
|
// all event bindings should go through this._on()
|
|
this.element
|
|
.off( this.eventNamespace )
|
|
.removeData( this.widgetFullName );
|
|
this.widget()
|
|
.off( this.eventNamespace )
|
|
.removeAttr( "aria-disabled" );
|
|
|
|
// Clean up events and states
|
|
this.bindings.off( this.eventNamespace );
|
|
},
|
|
|
|
_destroy: $.noop,
|
|
|
|
widget: function() {
|
|
return this.element;
|
|
},
|
|
|
|
option: function( key, value ) {
|
|
var options = key;
|
|
var parts;
|
|
var curOption;
|
|
var i;
|
|
|
|
if ( arguments.length === 0 ) {
|
|
|
|
// Don't return a reference to the internal hash
|
|
return $.widget.extend( {}, this.options );
|
|
}
|
|
|
|
if ( typeof key === "string" ) {
|
|
|
|
// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
|
|
options = {};
|
|
parts = key.split( "." );
|
|
key = parts.shift();
|
|
if ( parts.length ) {
|
|
curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
|
|
for ( i = 0; i < parts.length - 1; i++ ) {
|
|
curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
|
|
curOption = curOption[ parts[ i ] ];
|
|
}
|
|
key = parts.pop();
|
|
if ( arguments.length === 1 ) {
|
|
return curOption[ key ] === undefined ? null : curOption[ key ];
|
|
}
|
|
curOption[ key ] = value;
|
|
} else {
|
|
if ( arguments.length === 1 ) {
|
|
return this.options[ key ] === undefined ? null : this.options[ key ];
|
|
}
|
|
options[ key ] = value;
|
|
}
|
|
}
|
|
|
|
this._setOptions( options );
|
|
|
|
return this;
|
|
},
|
|
|
|
_setOptions: function( options ) {
|
|
var key;
|
|
|
|
for ( key in options ) {
|
|
this._setOption( key, options[ key ] );
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
if ( key === "classes" ) {
|
|
this._setOptionClasses( value );
|
|
}
|
|
|
|
this.options[ key ] = value;
|
|
|
|
if ( key === "disabled" ) {
|
|
this._setOptionDisabled( value );
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
_setOptionClasses: function( value ) {
|
|
var classKey, elements, currentElements;
|
|
|
|
for ( classKey in value ) {
|
|
currentElements = this.classesElementLookup[ classKey ];
|
|
if ( value[ classKey ] === this.options.classes[ classKey ] ||
|
|
!currentElements ||
|
|
!currentElements.length ) {
|
|
continue;
|
|
}
|
|
|
|
// We are doing this to create a new jQuery object because the _removeClass() call
|
|
// on the next line is going to destroy the reference to the current elements being
|
|
// tracked. We need to save a copy of this collection so that we can add the new classes
|
|
// below.
|
|
elements = $( currentElements.get() );
|
|
this._removeClass( currentElements, classKey );
|
|
|
|
// We don't use _addClass() here, because that uses this.options.classes
|
|
// for generating the string of classes. We want to use the value passed in from
|
|
// _setOption(), this is the new value of the classes option which was passed to
|
|
// _setOption(). We pass this value directly to _classes().
|
|
elements.addClass( this._classes( {
|
|
element: elements,
|
|
keys: classKey,
|
|
classes: value,
|
|
add: true
|
|
} ) );
|
|
}
|
|
},
|
|
|
|
_setOptionDisabled: function( value ) {
|
|
this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
|
|
|
|
// If the widget is becoming disabled, then nothing is interactive
|
|
if ( value ) {
|
|
this._removeClass( this.hoverable, null, "ui-state-hover" );
|
|
this._removeClass( this.focusable, null, "ui-state-focus" );
|
|
}
|
|
},
|
|
|
|
enable: function() {
|
|
return this._setOptions( { disabled: false } );
|
|
},
|
|
|
|
disable: function() {
|
|
return this._setOptions( { disabled: true } );
|
|
},
|
|
|
|
_classes: function( options ) {
|
|
var full = [];
|
|
var that = this;
|
|
|
|
options = $.extend( {
|
|
element: this.element,
|
|
classes: this.options.classes || {}
|
|
}, options );
|
|
|
|
function processClassString( classes, checkOption ) {
|
|
var current, i;
|
|
for ( i = 0; i < classes.length; i++ ) {
|
|
current = that.classesElementLookup[ classes[ i ] ] || $();
|
|
if ( options.add ) {
|
|
current = $( $.unique( current.get().concat( options.element.get() ) ) );
|
|
} else {
|
|
current = $( current.not( options.element ).get() );
|
|
}
|
|
that.classesElementLookup[ classes[ i ] ] = current;
|
|
full.push( classes[ i ] );
|
|
if ( checkOption && options.classes[ classes[ i ] ] ) {
|
|
full.push( options.classes[ classes[ i ] ] );
|
|
}
|
|
}
|
|
}
|
|
|
|
this._on( options.element, {
|
|
"remove": "_untrackClassesElement"
|
|
} );
|
|
|
|
if ( options.keys ) {
|
|
processClassString( options.keys.match( /\S+/g ) || [], true );
|
|
}
|
|
if ( options.extra ) {
|
|
processClassString( options.extra.match( /\S+/g ) || [] );
|
|
}
|
|
|
|
return full.join( " " );
|
|
},
|
|
|
|
_untrackClassesElement: function( event ) {
|
|
var that = this;
|
|
$.each( that.classesElementLookup, function( key, value ) {
|
|
if ( $.inArray( event.target, value ) !== -1 ) {
|
|
that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
|
|
}
|
|
} );
|
|
},
|
|
|
|
_removeClass: function( element, keys, extra ) {
|
|
return this._toggleClass( element, keys, extra, false );
|
|
},
|
|
|
|
_addClass: function( element, keys, extra ) {
|
|
return this._toggleClass( element, keys, extra, true );
|
|
},
|
|
|
|
_toggleClass: function( element, keys, extra, add ) {
|
|
add = ( typeof add === "boolean" ) ? add : extra;
|
|
var shift = ( typeof element === "string" || element === null ),
|
|
options = {
|
|
extra: shift ? keys : extra,
|
|
keys: shift ? element : keys,
|
|
element: shift ? this.element : element,
|
|
add: add
|
|
};
|
|
options.element.toggleClass( this._classes( options ), add );
|
|
return this;
|
|
},
|
|
|
|
_on: function( suppressDisabledCheck, element, handlers ) {
|
|
var delegateElement;
|
|
var instance = this;
|
|
|
|
// No suppressDisabledCheck flag, shuffle arguments
|
|
if ( typeof suppressDisabledCheck !== "boolean" ) {
|
|
handlers = element;
|
|
element = suppressDisabledCheck;
|
|
suppressDisabledCheck = false;
|
|
}
|
|
|
|
// No element argument, shuffle and use this.element
|
|
if ( !handlers ) {
|
|
handlers = element;
|
|
element = this.element;
|
|
delegateElement = this.widget();
|
|
} else {
|
|
element = delegateElement = $( element );
|
|
this.bindings = this.bindings.add( element );
|
|
}
|
|
|
|
$.each( handlers, function( event, handler ) {
|
|
function handlerProxy() {
|
|
|
|
// Allow widgets to customize the disabled handling
|
|
// - disabled as an array instead of boolean
|
|
// - disabled class as method for disabling individual parts
|
|
if ( !suppressDisabledCheck &&
|
|
( instance.options.disabled === true ||
|
|
$( this ).hasClass( "ui-state-disabled" ) ) ) {
|
|
return;
|
|
}
|
|
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
|
.apply( instance, arguments );
|
|
}
|
|
|
|
// Copy the guid so direct unbinding works
|
|
if ( typeof handler !== "string" ) {
|
|
handlerProxy.guid = handler.guid =
|
|
handler.guid || handlerProxy.guid || $.guid++;
|
|
}
|
|
|
|
var match = event.match( /^([\w:-]*)\s*(.*)$/ );
|
|
var eventName = match[ 1 ] + instance.eventNamespace;
|
|
var selector = match[ 2 ];
|
|
|
|
if ( selector ) {
|
|
delegateElement.on( eventName, selector, handlerProxy );
|
|
} else {
|
|
element.on( eventName, handlerProxy );
|
|
}
|
|
} );
|
|
},
|
|
|
|
_off: function( element, eventName ) {
|
|
eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
|
|
this.eventNamespace;
|
|
element.off( eventName ).off( eventName );
|
|
|
|
// Clear the stack to avoid memory leaks (#10056)
|
|
this.bindings = $( this.bindings.not( element ).get() );
|
|
this.focusable = $( this.focusable.not( element ).get() );
|
|
this.hoverable = $( this.hoverable.not( element ).get() );
|
|
},
|
|
|
|
_delay: function( handler, delay ) {
|
|
function handlerProxy() {
|
|
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
|
.apply( instance, arguments );
|
|
}
|
|
var instance = this;
|
|
return setTimeout( handlerProxy, delay || 0 );
|
|
},
|
|
|
|
_hoverable: function( element ) {
|
|
this.hoverable = this.hoverable.add( element );
|
|
this._on( element, {
|
|
mouseenter: function( event ) {
|
|
this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
|
|
},
|
|
mouseleave: function( event ) {
|
|
this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
|
|
}
|
|
} );
|
|
},
|
|
|
|
_focusable: function( element ) {
|
|
this.focusable = this.focusable.add( element );
|
|
this._on( element, {
|
|
focusin: function( event ) {
|
|
this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
|
|
},
|
|
focusout: function( event ) {
|
|
this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
|
|
}
|
|
} );
|
|
},
|
|
|
|
_trigger: function( type, event, data ) {
|
|
var prop, orig;
|
|
var callback = this.options[ type ];
|
|
|
|
data = data || {};
|
|
event = $.Event( event );
|
|
event.type = ( type === this.widgetEventPrefix ?
|
|
type :
|
|
this.widgetEventPrefix + type ).toLowerCase();
|
|
|
|
// The original event may come from any element
|
|
// so we need to reset the target on the new event
|
|
event.target = this.element[ 0 ];
|
|
|
|
// Copy original event properties over to the new event
|
|
orig = event.originalEvent;
|
|
if ( orig ) {
|
|
for ( prop in orig ) {
|
|
if ( !( prop in event ) ) {
|
|
event[ prop ] = orig[ prop ];
|
|
}
|
|
}
|
|
}
|
|
|
|
this.element.trigger( event, data );
|
|
return !( $.isFunction( callback ) &&
|
|
callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
|
|
event.isDefaultPrevented() );
|
|
}
|
|
};
|
|
|
|
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
|
|
$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
|
|
if ( typeof options === "string" ) {
|
|
options = { effect: options };
|
|
}
|
|
|
|
var hasOptions;
|
|
var effectName = !options ?
|
|
method :
|
|
options === true || typeof options === "number" ?
|
|
defaultEffect :
|
|
options.effect || defaultEffect;
|
|
|
|
options = options || {};
|
|
if ( typeof options === "number" ) {
|
|
options = { duration: options };
|
|
}
|
|
|
|
hasOptions = !$.isEmptyObject( options );
|
|
options.complete = callback;
|
|
|
|
if ( options.delay ) {
|
|
element.delay( options.delay );
|
|
}
|
|
|
|
if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
|
|
element[ method ]( options );
|
|
} else if ( effectName !== method && element[ effectName ] ) {
|
|
element[ effectName ]( options.duration, options.easing, callback );
|
|
} else {
|
|
element.queue( function( next ) {
|
|
$( this )[ method ]();
|
|
if ( callback ) {
|
|
callback.call( element[ 0 ] );
|
|
}
|
|
next();
|
|
} );
|
|
}
|
|
};
|
|
} );
|
|
|
|
return $.widget;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 21 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Position 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*
|
|
* http://api.jqueryui.com/position/
|
|
*/
|
|
|
|
//>>label: Position
|
|
//>>group: Core
|
|
//>>description: Positions elements relative to other elements.
|
|
//>>docs: http://api.jqueryui.com/position/
|
|
//>>demos: http://jqueryui.com/position/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
( function() {
|
|
var cachedScrollbarWidth,
|
|
max = Math.max,
|
|
abs = Math.abs,
|
|
rhorizontal = /left|center|right/,
|
|
rvertical = /top|center|bottom/,
|
|
roffset = /[\+\-]\d+(\.[\d]+)?%?/,
|
|
rposition = /^\w+/,
|
|
rpercent = /%$/,
|
|
_position = $.fn.position;
|
|
|
|
function getOffsets( offsets, width, height ) {
|
|
return [
|
|
parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
|
|
parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
|
|
];
|
|
}
|
|
|
|
function parseCss( element, property ) {
|
|
return parseInt( $.css( element, property ), 10 ) || 0;
|
|
}
|
|
|
|
function getDimensions( elem ) {
|
|
var raw = elem[ 0 ];
|
|
if ( raw.nodeType === 9 ) {
|
|
return {
|
|
width: elem.width(),
|
|
height: elem.height(),
|
|
offset: { top: 0, left: 0 }
|
|
};
|
|
}
|
|
if ( $.isWindow( raw ) ) {
|
|
return {
|
|
width: elem.width(),
|
|
height: elem.height(),
|
|
offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
|
|
};
|
|
}
|
|
if ( raw.preventDefault ) {
|
|
return {
|
|
width: 0,
|
|
height: 0,
|
|
offset: { top: raw.pageY, left: raw.pageX }
|
|
};
|
|
}
|
|
return {
|
|
width: elem.outerWidth(),
|
|
height: elem.outerHeight(),
|
|
offset: elem.offset()
|
|
};
|
|
}
|
|
|
|
$.position = {
|
|
scrollbarWidth: function() {
|
|
if ( cachedScrollbarWidth !== undefined ) {
|
|
return cachedScrollbarWidth;
|
|
}
|
|
var w1, w2,
|
|
div = $( "<div " +
|
|
"style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" +
|
|
"<div style='height:100px;width:auto;'></div></div>" ),
|
|
innerDiv = div.children()[ 0 ];
|
|
|
|
$( "body" ).append( div );
|
|
w1 = innerDiv.offsetWidth;
|
|
div.css( "overflow", "scroll" );
|
|
|
|
w2 = innerDiv.offsetWidth;
|
|
|
|
if ( w1 === w2 ) {
|
|
w2 = div[ 0 ].clientWidth;
|
|
}
|
|
|
|
div.remove();
|
|
|
|
return ( cachedScrollbarWidth = w1 - w2 );
|
|
},
|
|
getScrollInfo: function( within ) {
|
|
var overflowX = within.isWindow || within.isDocument ? "" :
|
|
within.element.css( "overflow-x" ),
|
|
overflowY = within.isWindow || within.isDocument ? "" :
|
|
within.element.css( "overflow-y" ),
|
|
hasOverflowX = overflowX === "scroll" ||
|
|
( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
|
|
hasOverflowY = overflowY === "scroll" ||
|
|
( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
|
|
return {
|
|
width: hasOverflowY ? $.position.scrollbarWidth() : 0,
|
|
height: hasOverflowX ? $.position.scrollbarWidth() : 0
|
|
};
|
|
},
|
|
getWithinInfo: function( element ) {
|
|
var withinElement = $( element || window ),
|
|
isWindow = $.isWindow( withinElement[ 0 ] ),
|
|
isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
|
|
hasOffset = !isWindow && !isDocument;
|
|
return {
|
|
element: withinElement,
|
|
isWindow: isWindow,
|
|
isDocument: isDocument,
|
|
offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
|
|
scrollLeft: withinElement.scrollLeft(),
|
|
scrollTop: withinElement.scrollTop(),
|
|
width: withinElement.outerWidth(),
|
|
height: withinElement.outerHeight()
|
|
};
|
|
}
|
|
};
|
|
|
|
$.fn.position = function( options ) {
|
|
if ( !options || !options.of ) {
|
|
return _position.apply( this, arguments );
|
|
}
|
|
|
|
// Make a copy, we don't want to modify arguments
|
|
options = $.extend( {}, options );
|
|
|
|
var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
|
|
target = $( options.of ),
|
|
within = $.position.getWithinInfo( options.within ),
|
|
scrollInfo = $.position.getScrollInfo( within ),
|
|
collision = ( options.collision || "flip" ).split( " " ),
|
|
offsets = {};
|
|
|
|
dimensions = getDimensions( target );
|
|
if ( target[ 0 ].preventDefault ) {
|
|
|
|
// Force left top to allow flipping
|
|
options.at = "left top";
|
|
}
|
|
targetWidth = dimensions.width;
|
|
targetHeight = dimensions.height;
|
|
targetOffset = dimensions.offset;
|
|
|
|
// Clone to reuse original targetOffset later
|
|
basePosition = $.extend( {}, targetOffset );
|
|
|
|
// Force my and at to have valid horizontal and vertical positions
|
|
// if a value is missing or invalid, it will be converted to center
|
|
$.each( [ "my", "at" ], function() {
|
|
var pos = ( options[ this ] || "" ).split( " " ),
|
|
horizontalOffset,
|
|
verticalOffset;
|
|
|
|
if ( pos.length === 1 ) {
|
|
pos = rhorizontal.test( pos[ 0 ] ) ?
|
|
pos.concat( [ "center" ] ) :
|
|
rvertical.test( pos[ 0 ] ) ?
|
|
[ "center" ].concat( pos ) :
|
|
[ "center", "center" ];
|
|
}
|
|
pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
|
|
pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
|
|
|
|
// Calculate offsets
|
|
horizontalOffset = roffset.exec( pos[ 0 ] );
|
|
verticalOffset = roffset.exec( pos[ 1 ] );
|
|
offsets[ this ] = [
|
|
horizontalOffset ? horizontalOffset[ 0 ] : 0,
|
|
verticalOffset ? verticalOffset[ 0 ] : 0
|
|
];
|
|
|
|
// Reduce to just the positions without the offsets
|
|
options[ this ] = [
|
|
rposition.exec( pos[ 0 ] )[ 0 ],
|
|
rposition.exec( pos[ 1 ] )[ 0 ]
|
|
];
|
|
} );
|
|
|
|
// Normalize collision option
|
|
if ( collision.length === 1 ) {
|
|
collision[ 1 ] = collision[ 0 ];
|
|
}
|
|
|
|
if ( options.at[ 0 ] === "right" ) {
|
|
basePosition.left += targetWidth;
|
|
} else if ( options.at[ 0 ] === "center" ) {
|
|
basePosition.left += targetWidth / 2;
|
|
}
|
|
|
|
if ( options.at[ 1 ] === "bottom" ) {
|
|
basePosition.top += targetHeight;
|
|
} else if ( options.at[ 1 ] === "center" ) {
|
|
basePosition.top += targetHeight / 2;
|
|
}
|
|
|
|
atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
|
|
basePosition.left += atOffset[ 0 ];
|
|
basePosition.top += atOffset[ 1 ];
|
|
|
|
return this.each( function() {
|
|
var collisionPosition, using,
|
|
elem = $( this ),
|
|
elemWidth = elem.outerWidth(),
|
|
elemHeight = elem.outerHeight(),
|
|
marginLeft = parseCss( this, "marginLeft" ),
|
|
marginTop = parseCss( this, "marginTop" ),
|
|
collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
|
|
scrollInfo.width,
|
|
collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
|
|
scrollInfo.height,
|
|
position = $.extend( {}, basePosition ),
|
|
myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
|
|
|
|
if ( options.my[ 0 ] === "right" ) {
|
|
position.left -= elemWidth;
|
|
} else if ( options.my[ 0 ] === "center" ) {
|
|
position.left -= elemWidth / 2;
|
|
}
|
|
|
|
if ( options.my[ 1 ] === "bottom" ) {
|
|
position.top -= elemHeight;
|
|
} else if ( options.my[ 1 ] === "center" ) {
|
|
position.top -= elemHeight / 2;
|
|
}
|
|
|
|
position.left += myOffset[ 0 ];
|
|
position.top += myOffset[ 1 ];
|
|
|
|
collisionPosition = {
|
|
marginLeft: marginLeft,
|
|
marginTop: marginTop
|
|
};
|
|
|
|
$.each( [ "left", "top" ], function( i, dir ) {
|
|
if ( $.ui.position[ collision[ i ] ] ) {
|
|
$.ui.position[ collision[ i ] ][ dir ]( position, {
|
|
targetWidth: targetWidth,
|
|
targetHeight: targetHeight,
|
|
elemWidth: elemWidth,
|
|
elemHeight: elemHeight,
|
|
collisionPosition: collisionPosition,
|
|
collisionWidth: collisionWidth,
|
|
collisionHeight: collisionHeight,
|
|
offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
|
|
my: options.my,
|
|
at: options.at,
|
|
within: within,
|
|
elem: elem
|
|
} );
|
|
}
|
|
} );
|
|
|
|
if ( options.using ) {
|
|
|
|
// Adds feedback as second argument to using callback, if present
|
|
using = function( props ) {
|
|
var left = targetOffset.left - position.left,
|
|
right = left + targetWidth - elemWidth,
|
|
top = targetOffset.top - position.top,
|
|
bottom = top + targetHeight - elemHeight,
|
|
feedback = {
|
|
target: {
|
|
element: target,
|
|
left: targetOffset.left,
|
|
top: targetOffset.top,
|
|
width: targetWidth,
|
|
height: targetHeight
|
|
},
|
|
element: {
|
|
element: elem,
|
|
left: position.left,
|
|
top: position.top,
|
|
width: elemWidth,
|
|
height: elemHeight
|
|
},
|
|
horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
|
|
vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
|
|
};
|
|
if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
|
|
feedback.horizontal = "center";
|
|
}
|
|
if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
|
|
feedback.vertical = "middle";
|
|
}
|
|
if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
|
|
feedback.important = "horizontal";
|
|
} else {
|
|
feedback.important = "vertical";
|
|
}
|
|
options.using.call( this, props, feedback );
|
|
};
|
|
}
|
|
|
|
elem.offset( $.extend( position, { using: using } ) );
|
|
} );
|
|
};
|
|
|
|
$.ui.position = {
|
|
fit: {
|
|
left: function( position, data ) {
|
|
var within = data.within,
|
|
withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
|
|
outerWidth = within.width,
|
|
collisionPosLeft = position.left - data.collisionPosition.marginLeft,
|
|
overLeft = withinOffset - collisionPosLeft,
|
|
overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
|
|
newOverRight;
|
|
|
|
// Element is wider than within
|
|
if ( data.collisionWidth > outerWidth ) {
|
|
|
|
// Element is initially over the left side of within
|
|
if ( overLeft > 0 && overRight <= 0 ) {
|
|
newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
|
|
withinOffset;
|
|
position.left += overLeft - newOverRight;
|
|
|
|
// Element is initially over right side of within
|
|
} else if ( overRight > 0 && overLeft <= 0 ) {
|
|
position.left = withinOffset;
|
|
|
|
// Element is initially over both left and right sides of within
|
|
} else {
|
|
if ( overLeft > overRight ) {
|
|
position.left = withinOffset + outerWidth - data.collisionWidth;
|
|
} else {
|
|
position.left = withinOffset;
|
|
}
|
|
}
|
|
|
|
// Too far left -> align with left edge
|
|
} else if ( overLeft > 0 ) {
|
|
position.left += overLeft;
|
|
|
|
// Too far right -> align with right edge
|
|
} else if ( overRight > 0 ) {
|
|
position.left -= overRight;
|
|
|
|
// Adjust based on position and margin
|
|
} else {
|
|
position.left = max( position.left - collisionPosLeft, position.left );
|
|
}
|
|
},
|
|
top: function( position, data ) {
|
|
var within = data.within,
|
|
withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
|
|
outerHeight = data.within.height,
|
|
collisionPosTop = position.top - data.collisionPosition.marginTop,
|
|
overTop = withinOffset - collisionPosTop,
|
|
overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
|
|
newOverBottom;
|
|
|
|
// Element is taller than within
|
|
if ( data.collisionHeight > outerHeight ) {
|
|
|
|
// Element is initially over the top of within
|
|
if ( overTop > 0 && overBottom <= 0 ) {
|
|
newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
|
|
withinOffset;
|
|
position.top += overTop - newOverBottom;
|
|
|
|
// Element is initially over bottom of within
|
|
} else if ( overBottom > 0 && overTop <= 0 ) {
|
|
position.top = withinOffset;
|
|
|
|
// Element is initially over both top and bottom of within
|
|
} else {
|
|
if ( overTop > overBottom ) {
|
|
position.top = withinOffset + outerHeight - data.collisionHeight;
|
|
} else {
|
|
position.top = withinOffset;
|
|
}
|
|
}
|
|
|
|
// Too far up -> align with top
|
|
} else if ( overTop > 0 ) {
|
|
position.top += overTop;
|
|
|
|
// Too far down -> align with bottom edge
|
|
} else if ( overBottom > 0 ) {
|
|
position.top -= overBottom;
|
|
|
|
// Adjust based on position and margin
|
|
} else {
|
|
position.top = max( position.top - collisionPosTop, position.top );
|
|
}
|
|
}
|
|
},
|
|
flip: {
|
|
left: function( position, data ) {
|
|
var within = data.within,
|
|
withinOffset = within.offset.left + within.scrollLeft,
|
|
outerWidth = within.width,
|
|
offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
|
|
collisionPosLeft = position.left - data.collisionPosition.marginLeft,
|
|
overLeft = collisionPosLeft - offsetLeft,
|
|
overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
|
|
myOffset = data.my[ 0 ] === "left" ?
|
|
-data.elemWidth :
|
|
data.my[ 0 ] === "right" ?
|
|
data.elemWidth :
|
|
0,
|
|
atOffset = data.at[ 0 ] === "left" ?
|
|
data.targetWidth :
|
|
data.at[ 0 ] === "right" ?
|
|
-data.targetWidth :
|
|
0,
|
|
offset = -2 * data.offset[ 0 ],
|
|
newOverRight,
|
|
newOverLeft;
|
|
|
|
if ( overLeft < 0 ) {
|
|
newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
|
|
outerWidth - withinOffset;
|
|
if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
|
|
position.left += myOffset + atOffset + offset;
|
|
}
|
|
} else if ( overRight > 0 ) {
|
|
newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
|
|
atOffset + offset - offsetLeft;
|
|
if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
|
|
position.left += myOffset + atOffset + offset;
|
|
}
|
|
}
|
|
},
|
|
top: function( position, data ) {
|
|
var within = data.within,
|
|
withinOffset = within.offset.top + within.scrollTop,
|
|
outerHeight = within.height,
|
|
offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
|
|
collisionPosTop = position.top - data.collisionPosition.marginTop,
|
|
overTop = collisionPosTop - offsetTop,
|
|
overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
|
|
top = data.my[ 1 ] === "top",
|
|
myOffset = top ?
|
|
-data.elemHeight :
|
|
data.my[ 1 ] === "bottom" ?
|
|
data.elemHeight :
|
|
0,
|
|
atOffset = data.at[ 1 ] === "top" ?
|
|
data.targetHeight :
|
|
data.at[ 1 ] === "bottom" ?
|
|
-data.targetHeight :
|
|
0,
|
|
offset = -2 * data.offset[ 1 ],
|
|
newOverTop,
|
|
newOverBottom;
|
|
if ( overTop < 0 ) {
|
|
newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
|
|
outerHeight - withinOffset;
|
|
if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
|
|
position.top += myOffset + atOffset + offset;
|
|
}
|
|
} else if ( overBottom > 0 ) {
|
|
newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
|
|
offset - offsetTop;
|
|
if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
|
|
position.top += myOffset + atOffset + offset;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
flipfit: {
|
|
left: function() {
|
|
$.ui.position.flip.left.apply( this, arguments );
|
|
$.ui.position.fit.left.apply( this, arguments );
|
|
},
|
|
top: function() {
|
|
$.ui.position.flip.top.apply( this, arguments );
|
|
$.ui.position.fit.top.apply( this, arguments );
|
|
}
|
|
}
|
|
};
|
|
|
|
} )();
|
|
|
|
return $.ui.position;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 22 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI :data 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: :data Selector
|
|
//>>group: Core
|
|
//>>description: Selects elements which have data stored under the specified key.
|
|
//>>docs: http://api.jqueryui.com/data-selector/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
return $.extend( $.expr[ ":" ], {
|
|
data: $.expr.createPseudo ?
|
|
$.expr.createPseudo( function( dataName ) {
|
|
return function( elem ) {
|
|
return !!$.data( elem, dataName );
|
|
};
|
|
} ) :
|
|
|
|
// Support: jQuery <1.8
|
|
function( elem, i, match ) {
|
|
return !!$.data( elem, match[ 3 ] );
|
|
}
|
|
} );
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 23 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Disable Selection 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: disableSelection
|
|
//>>group: Core
|
|
//>>description: Disable selection of text content within the set of matched elements.
|
|
//>>docs: http://api.jqueryui.com/disableSelection/
|
|
|
|
// This file is deprecated
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
|
|
return $.fn.extend( {
|
|
disableSelection: ( function() {
|
|
var eventType = "onselectstart" in document.createElement( "div" ) ?
|
|
"selectstart" :
|
|
"mousedown";
|
|
|
|
return function() {
|
|
return this.on( eventType + ".ui-disableSelection", function( event ) {
|
|
event.preventDefault();
|
|
} );
|
|
};
|
|
} )(),
|
|
|
|
enableSelection: function() {
|
|
return this.off( ".ui-disableSelection" );
|
|
}
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 24 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Effects Core
|
|
//>>group: Effects
|
|
// jscs:disable maximumLineLength
|
|
//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
|
|
// jscs:enable maximumLineLength
|
|
//>>docs: http://api.jqueryui.com/category/effects-core/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
var dataSpace = "ui-effects-",
|
|
dataSpaceStyle = "ui-effects-style",
|
|
dataSpaceAnimated = "ui-effects-animated",
|
|
|
|
// Create a local jQuery because jQuery Color relies on it and the
|
|
// global may not exist with AMD and a custom build (#10199)
|
|
jQuery = $;
|
|
|
|
$.effects = {
|
|
effect: {}
|
|
};
|
|
|
|
/*!
|
|
* jQuery Color Animations v2.1.2
|
|
* https://github.com/jquery/jquery-color
|
|
*
|
|
* Copyright 2014 jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*
|
|
* Date: Wed Jan 16 08:47:09 2013 -0600
|
|
*/
|
|
( function( jQuery, undefined ) {
|
|
|
|
var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
|
|
"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
|
|
|
|
// Plusequals test for += 100 -= 100
|
|
rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
|
|
|
|
// A set of RE's that can match strings and generate color tuples.
|
|
stringParsers = [ {
|
|
re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
|
|
parse: function( execResult ) {
|
|
return [
|
|
execResult[ 1 ],
|
|
execResult[ 2 ],
|
|
execResult[ 3 ],
|
|
execResult[ 4 ]
|
|
];
|
|
}
|
|
}, {
|
|
re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
|
|
parse: function( execResult ) {
|
|
return [
|
|
execResult[ 1 ] * 2.55,
|
|
execResult[ 2 ] * 2.55,
|
|
execResult[ 3 ] * 2.55,
|
|
execResult[ 4 ]
|
|
];
|
|
}
|
|
}, {
|
|
|
|
// This regex ignores A-F because it's compared against an already lowercased string
|
|
re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
|
|
parse: function( execResult ) {
|
|
return [
|
|
parseInt( execResult[ 1 ], 16 ),
|
|
parseInt( execResult[ 2 ], 16 ),
|
|
parseInt( execResult[ 3 ], 16 )
|
|
];
|
|
}
|
|
}, {
|
|
|
|
// This regex ignores A-F because it's compared against an already lowercased string
|
|
re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
|
|
parse: function( execResult ) {
|
|
return [
|
|
parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
|
|
parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
|
|
parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
|
|
];
|
|
}
|
|
}, {
|
|
re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
|
|
space: "hsla",
|
|
parse: function( execResult ) {
|
|
return [
|
|
execResult[ 1 ],
|
|
execResult[ 2 ] / 100,
|
|
execResult[ 3 ] / 100,
|
|
execResult[ 4 ]
|
|
];
|
|
}
|
|
} ],
|
|
|
|
// JQuery.Color( )
|
|
color = jQuery.Color = function( color, green, blue, alpha ) {
|
|
return new jQuery.Color.fn.parse( color, green, blue, alpha );
|
|
},
|
|
spaces = {
|
|
rgba: {
|
|
props: {
|
|
red: {
|
|
idx: 0,
|
|
type: "byte"
|
|
},
|
|
green: {
|
|
idx: 1,
|
|
type: "byte"
|
|
},
|
|
blue: {
|
|
idx: 2,
|
|
type: "byte"
|
|
}
|
|
}
|
|
},
|
|
|
|
hsla: {
|
|
props: {
|
|
hue: {
|
|
idx: 0,
|
|
type: "degrees"
|
|
},
|
|
saturation: {
|
|
idx: 1,
|
|
type: "percent"
|
|
},
|
|
lightness: {
|
|
idx: 2,
|
|
type: "percent"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
propTypes = {
|
|
"byte": {
|
|
floor: true,
|
|
max: 255
|
|
},
|
|
"percent": {
|
|
max: 1
|
|
},
|
|
"degrees": {
|
|
mod: 360,
|
|
floor: true
|
|
}
|
|
},
|
|
support = color.support = {},
|
|
|
|
// Element for support tests
|
|
supportElem = jQuery( "<p>" )[ 0 ],
|
|
|
|
// Colors = jQuery.Color.names
|
|
colors,
|
|
|
|
// Local aliases of functions called often
|
|
each = jQuery.each;
|
|
|
|
// Determine rgba support immediately
|
|
supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
|
|
support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
|
|
|
|
// Define cache name and alpha properties
|
|
// for rgba and hsla spaces
|
|
each( spaces, function( spaceName, space ) {
|
|
space.cache = "_" + spaceName;
|
|
space.props.alpha = {
|
|
idx: 3,
|
|
type: "percent",
|
|
def: 1
|
|
};
|
|
} );
|
|
|
|
function clamp( value, prop, allowEmpty ) {
|
|
var type = propTypes[ prop.type ] || {};
|
|
|
|
if ( value == null ) {
|
|
return ( allowEmpty || !prop.def ) ? null : prop.def;
|
|
}
|
|
|
|
// ~~ is an short way of doing floor for positive numbers
|
|
value = type.floor ? ~~value : parseFloat( value );
|
|
|
|
// IE will pass in empty strings as value for alpha,
|
|
// which will hit this case
|
|
if ( isNaN( value ) ) {
|
|
return prop.def;
|
|
}
|
|
|
|
if ( type.mod ) {
|
|
|
|
// We add mod before modding to make sure that negatives values
|
|
// get converted properly: -10 -> 350
|
|
return ( value + type.mod ) % type.mod;
|
|
}
|
|
|
|
// For now all property types without mod have min and max
|
|
return 0 > value ? 0 : type.max < value ? type.max : value;
|
|
}
|
|
|
|
function stringParse( string ) {
|
|
var inst = color(),
|
|
rgba = inst._rgba = [];
|
|
|
|
string = string.toLowerCase();
|
|
|
|
each( stringParsers, function( i, parser ) {
|
|
var parsed,
|
|
match = parser.re.exec( string ),
|
|
values = match && parser.parse( match ),
|
|
spaceName = parser.space || "rgba";
|
|
|
|
if ( values ) {
|
|
parsed = inst[ spaceName ]( values );
|
|
|
|
// If this was an rgba parse the assignment might happen twice
|
|
// oh well....
|
|
inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
|
|
rgba = inst._rgba = parsed._rgba;
|
|
|
|
// Exit each( stringParsers ) here because we matched
|
|
return false;
|
|
}
|
|
} );
|
|
|
|
// Found a stringParser that handled it
|
|
if ( rgba.length ) {
|
|
|
|
// If this came from a parsed string, force "transparent" when alpha is 0
|
|
// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
|
|
if ( rgba.join() === "0,0,0,0" ) {
|
|
jQuery.extend( rgba, colors.transparent );
|
|
}
|
|
return inst;
|
|
}
|
|
|
|
// Named colors
|
|
return colors[ string ];
|
|
}
|
|
|
|
color.fn = jQuery.extend( color.prototype, {
|
|
parse: function( red, green, blue, alpha ) {
|
|
if ( red === undefined ) {
|
|
this._rgba = [ null, null, null, null ];
|
|
return this;
|
|
}
|
|
if ( red.jquery || red.nodeType ) {
|
|
red = jQuery( red ).css( green );
|
|
green = undefined;
|
|
}
|
|
|
|
var inst = this,
|
|
type = jQuery.type( red ),
|
|
rgba = this._rgba = [];
|
|
|
|
// More than 1 argument specified - assume ( red, green, blue, alpha )
|
|
if ( green !== undefined ) {
|
|
red = [ red, green, blue, alpha ];
|
|
type = "array";
|
|
}
|
|
|
|
if ( type === "string" ) {
|
|
return this.parse( stringParse( red ) || colors._default );
|
|
}
|
|
|
|
if ( type === "array" ) {
|
|
each( spaces.rgba.props, function( key, prop ) {
|
|
rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
|
|
} );
|
|
return this;
|
|
}
|
|
|
|
if ( type === "object" ) {
|
|
if ( red instanceof color ) {
|
|
each( spaces, function( spaceName, space ) {
|
|
if ( red[ space.cache ] ) {
|
|
inst[ space.cache ] = red[ space.cache ].slice();
|
|
}
|
|
} );
|
|
} else {
|
|
each( spaces, function( spaceName, space ) {
|
|
var cache = space.cache;
|
|
each( space.props, function( key, prop ) {
|
|
|
|
// If the cache doesn't exist, and we know how to convert
|
|
if ( !inst[ cache ] && space.to ) {
|
|
|
|
// If the value was null, we don't need to copy it
|
|
// if the key was alpha, we don't need to copy it either
|
|
if ( key === "alpha" || red[ key ] == null ) {
|
|
return;
|
|
}
|
|
inst[ cache ] = space.to( inst._rgba );
|
|
}
|
|
|
|
// This is the only case where we allow nulls for ALL properties.
|
|
// call clamp with alwaysAllowEmpty
|
|
inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
|
|
} );
|
|
|
|
// Everything defined but alpha?
|
|
if ( inst[ cache ] &&
|
|
jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
|
|
|
|
// Use the default of 1
|
|
inst[ cache ][ 3 ] = 1;
|
|
if ( space.from ) {
|
|
inst._rgba = space.from( inst[ cache ] );
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
return this;
|
|
}
|
|
},
|
|
is: function( compare ) {
|
|
var is = color( compare ),
|
|
same = true,
|
|
inst = this;
|
|
|
|
each( spaces, function( _, space ) {
|
|
var localCache,
|
|
isCache = is[ space.cache ];
|
|
if ( isCache ) {
|
|
localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
|
|
each( space.props, function( _, prop ) {
|
|
if ( isCache[ prop.idx ] != null ) {
|
|
same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
|
|
return same;
|
|
}
|
|
} );
|
|
}
|
|
return same;
|
|
} );
|
|
return same;
|
|
},
|
|
_space: function() {
|
|
var used = [],
|
|
inst = this;
|
|
each( spaces, function( spaceName, space ) {
|
|
if ( inst[ space.cache ] ) {
|
|
used.push( spaceName );
|
|
}
|
|
} );
|
|
return used.pop();
|
|
},
|
|
transition: function( other, distance ) {
|
|
var end = color( other ),
|
|
spaceName = end._space(),
|
|
space = spaces[ spaceName ],
|
|
startColor = this.alpha() === 0 ? color( "transparent" ) : this,
|
|
start = startColor[ space.cache ] || space.to( startColor._rgba ),
|
|
result = start.slice();
|
|
|
|
end = end[ space.cache ];
|
|
each( space.props, function( key, prop ) {
|
|
var index = prop.idx,
|
|
startValue = start[ index ],
|
|
endValue = end[ index ],
|
|
type = propTypes[ prop.type ] || {};
|
|
|
|
// If null, don't override start value
|
|
if ( endValue === null ) {
|
|
return;
|
|
}
|
|
|
|
// If null - use end
|
|
if ( startValue === null ) {
|
|
result[ index ] = endValue;
|
|
} else {
|
|
if ( type.mod ) {
|
|
if ( endValue - startValue > type.mod / 2 ) {
|
|
startValue += type.mod;
|
|
} else if ( startValue - endValue > type.mod / 2 ) {
|
|
startValue -= type.mod;
|
|
}
|
|
}
|
|
result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
|
|
}
|
|
} );
|
|
return this[ spaceName ]( result );
|
|
},
|
|
blend: function( opaque ) {
|
|
|
|
// If we are already opaque - return ourself
|
|
if ( this._rgba[ 3 ] === 1 ) {
|
|
return this;
|
|
}
|
|
|
|
var rgb = this._rgba.slice(),
|
|
a = rgb.pop(),
|
|
blend = color( opaque )._rgba;
|
|
|
|
return color( jQuery.map( rgb, function( v, i ) {
|
|
return ( 1 - a ) * blend[ i ] + a * v;
|
|
} ) );
|
|
},
|
|
toRgbaString: function() {
|
|
var prefix = "rgba(",
|
|
rgba = jQuery.map( this._rgba, function( v, i ) {
|
|
return v == null ? ( i > 2 ? 1 : 0 ) : v;
|
|
} );
|
|
|
|
if ( rgba[ 3 ] === 1 ) {
|
|
rgba.pop();
|
|
prefix = "rgb(";
|
|
}
|
|
|
|
return prefix + rgba.join() + ")";
|
|
},
|
|
toHslaString: function() {
|
|
var prefix = "hsla(",
|
|
hsla = jQuery.map( this.hsla(), function( v, i ) {
|
|
if ( v == null ) {
|
|
v = i > 2 ? 1 : 0;
|
|
}
|
|
|
|
// Catch 1 and 2
|
|
if ( i && i < 3 ) {
|
|
v = Math.round( v * 100 ) + "%";
|
|
}
|
|
return v;
|
|
} );
|
|
|
|
if ( hsla[ 3 ] === 1 ) {
|
|
hsla.pop();
|
|
prefix = "hsl(";
|
|
}
|
|
return prefix + hsla.join() + ")";
|
|
},
|
|
toHexString: function( includeAlpha ) {
|
|
var rgba = this._rgba.slice(),
|
|
alpha = rgba.pop();
|
|
|
|
if ( includeAlpha ) {
|
|
rgba.push( ~~( alpha * 255 ) );
|
|
}
|
|
|
|
return "#" + jQuery.map( rgba, function( v ) {
|
|
|
|
// Default to 0 when nulls exist
|
|
v = ( v || 0 ).toString( 16 );
|
|
return v.length === 1 ? "0" + v : v;
|
|
} ).join( "" );
|
|
},
|
|
toString: function() {
|
|
return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
|
|
}
|
|
} );
|
|
color.fn.parse.prototype = color.fn;
|
|
|
|
// Hsla conversions adapted from:
|
|
// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
|
|
|
|
function hue2rgb( p, q, h ) {
|
|
h = ( h + 1 ) % 1;
|
|
if ( h * 6 < 1 ) {
|
|
return p + ( q - p ) * h * 6;
|
|
}
|
|
if ( h * 2 < 1 ) {
|
|
return q;
|
|
}
|
|
if ( h * 3 < 2 ) {
|
|
return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
spaces.hsla.to = function( rgba ) {
|
|
if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
|
|
return [ null, null, null, rgba[ 3 ] ];
|
|
}
|
|
var r = rgba[ 0 ] / 255,
|
|
g = rgba[ 1 ] / 255,
|
|
b = rgba[ 2 ] / 255,
|
|
a = rgba[ 3 ],
|
|
max = Math.max( r, g, b ),
|
|
min = Math.min( r, g, b ),
|
|
diff = max - min,
|
|
add = max + min,
|
|
l = add * 0.5,
|
|
h, s;
|
|
|
|
if ( min === max ) {
|
|
h = 0;
|
|
} else if ( r === max ) {
|
|
h = ( 60 * ( g - b ) / diff ) + 360;
|
|
} else if ( g === max ) {
|
|
h = ( 60 * ( b - r ) / diff ) + 120;
|
|
} else {
|
|
h = ( 60 * ( r - g ) / diff ) + 240;
|
|
}
|
|
|
|
// Chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
|
|
// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
|
|
if ( diff === 0 ) {
|
|
s = 0;
|
|
} else if ( l <= 0.5 ) {
|
|
s = diff / add;
|
|
} else {
|
|
s = diff / ( 2 - add );
|
|
}
|
|
return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
|
|
};
|
|
|
|
spaces.hsla.from = function( hsla ) {
|
|
if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
|
|
return [ null, null, null, hsla[ 3 ] ];
|
|
}
|
|
var h = hsla[ 0 ] / 360,
|
|
s = hsla[ 1 ],
|
|
l = hsla[ 2 ],
|
|
a = hsla[ 3 ],
|
|
q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
|
|
p = 2 * l - q;
|
|
|
|
return [
|
|
Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
|
|
Math.round( hue2rgb( p, q, h ) * 255 ),
|
|
Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
|
|
a
|
|
];
|
|
};
|
|
|
|
each( spaces, function( spaceName, space ) {
|
|
var props = space.props,
|
|
cache = space.cache,
|
|
to = space.to,
|
|
from = space.from;
|
|
|
|
// Makes rgba() and hsla()
|
|
color.fn[ spaceName ] = function( value ) {
|
|
|
|
// Generate a cache for this space if it doesn't exist
|
|
if ( to && !this[ cache ] ) {
|
|
this[ cache ] = to( this._rgba );
|
|
}
|
|
if ( value === undefined ) {
|
|
return this[ cache ].slice();
|
|
}
|
|
|
|
var ret,
|
|
type = jQuery.type( value ),
|
|
arr = ( type === "array" || type === "object" ) ? value : arguments,
|
|
local = this[ cache ].slice();
|
|
|
|
each( props, function( key, prop ) {
|
|
var val = arr[ type === "object" ? key : prop.idx ];
|
|
if ( val == null ) {
|
|
val = local[ prop.idx ];
|
|
}
|
|
local[ prop.idx ] = clamp( val, prop );
|
|
} );
|
|
|
|
if ( from ) {
|
|
ret = color( from( local ) );
|
|
ret[ cache ] = local;
|
|
return ret;
|
|
} else {
|
|
return color( local );
|
|
}
|
|
};
|
|
|
|
// Makes red() green() blue() alpha() hue() saturation() lightness()
|
|
each( props, function( key, prop ) {
|
|
|
|
// Alpha is included in more than one space
|
|
if ( color.fn[ key ] ) {
|
|
return;
|
|
}
|
|
color.fn[ key ] = function( value ) {
|
|
var vtype = jQuery.type( value ),
|
|
fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
|
|
local = this[ fn ](),
|
|
cur = local[ prop.idx ],
|
|
match;
|
|
|
|
if ( vtype === "undefined" ) {
|
|
return cur;
|
|
}
|
|
|
|
if ( vtype === "function" ) {
|
|
value = value.call( this, cur );
|
|
vtype = jQuery.type( value );
|
|
}
|
|
if ( value == null && prop.empty ) {
|
|
return this;
|
|
}
|
|
if ( vtype === "string" ) {
|
|
match = rplusequals.exec( value );
|
|
if ( match ) {
|
|
value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
|
|
}
|
|
}
|
|
local[ prop.idx ] = value;
|
|
return this[ fn ]( local );
|
|
};
|
|
} );
|
|
} );
|
|
|
|
// Add cssHook and .fx.step function for each named hook.
|
|
// accept a space separated string of properties
|
|
color.hook = function( hook ) {
|
|
var hooks = hook.split( " " );
|
|
each( hooks, function( i, hook ) {
|
|
jQuery.cssHooks[ hook ] = {
|
|
set: function( elem, value ) {
|
|
var parsed, curElem,
|
|
backgroundColor = "";
|
|
|
|
if ( value !== "transparent" && ( jQuery.type( value ) !== "string" ||
|
|
( parsed = stringParse( value ) ) ) ) {
|
|
value = color( parsed || value );
|
|
if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
|
|
curElem = hook === "backgroundColor" ? elem.parentNode : elem;
|
|
while (
|
|
( backgroundColor === "" || backgroundColor === "transparent" ) &&
|
|
curElem && curElem.style
|
|
) {
|
|
try {
|
|
backgroundColor = jQuery.css( curElem, "backgroundColor" );
|
|
curElem = curElem.parentNode;
|
|
} catch ( e ) {
|
|
}
|
|
}
|
|
|
|
value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
|
|
backgroundColor :
|
|
"_default" );
|
|
}
|
|
|
|
value = value.toRgbaString();
|
|
}
|
|
try {
|
|
elem.style[ hook ] = value;
|
|
} catch ( e ) {
|
|
|
|
// Wrapped to prevent IE from throwing errors on "invalid" values like
|
|
// 'auto' or 'inherit'
|
|
}
|
|
}
|
|
};
|
|
jQuery.fx.step[ hook ] = function( fx ) {
|
|
if ( !fx.colorInit ) {
|
|
fx.start = color( fx.elem, hook );
|
|
fx.end = color( fx.end );
|
|
fx.colorInit = true;
|
|
}
|
|
jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
|
|
};
|
|
} );
|
|
|
|
};
|
|
|
|
color.hook( stepHooks );
|
|
|
|
jQuery.cssHooks.borderColor = {
|
|
expand: function( value ) {
|
|
var expanded = {};
|
|
|
|
each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
|
|
expanded[ "border" + part + "Color" ] = value;
|
|
} );
|
|
return expanded;
|
|
}
|
|
};
|
|
|
|
// Basic color names only.
|
|
// Usage of any of the other color names requires adding yourself or including
|
|
// jquery.color.svg-names.js.
|
|
colors = jQuery.Color.names = {
|
|
|
|
// 4.1. Basic color keywords
|
|
aqua: "#00ffff",
|
|
black: "#000000",
|
|
blue: "#0000ff",
|
|
fuchsia: "#ff00ff",
|
|
gray: "#808080",
|
|
green: "#008000",
|
|
lime: "#00ff00",
|
|
maroon: "#800000",
|
|
navy: "#000080",
|
|
olive: "#808000",
|
|
purple: "#800080",
|
|
red: "#ff0000",
|
|
silver: "#c0c0c0",
|
|
teal: "#008080",
|
|
white: "#ffffff",
|
|
yellow: "#ffff00",
|
|
|
|
// 4.2.3. "transparent" color keyword
|
|
transparent: [ null, null, null, 0 ],
|
|
|
|
_default: "#ffffff"
|
|
};
|
|
|
|
} )( jQuery );
|
|
|
|
/******************************************************************************/
|
|
/****************************** CLASS ANIMATIONS ******************************/
|
|
/******************************************************************************/
|
|
( function() {
|
|
|
|
var classAnimationActions = [ "add", "remove", "toggle" ],
|
|
shorthandStyles = {
|
|
border: 1,
|
|
borderBottom: 1,
|
|
borderColor: 1,
|
|
borderLeft: 1,
|
|
borderRight: 1,
|
|
borderTop: 1,
|
|
borderWidth: 1,
|
|
margin: 1,
|
|
padding: 1
|
|
};
|
|
|
|
$.each(
|
|
[ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
|
|
function( _, prop ) {
|
|
$.fx.step[ prop ] = function( fx ) {
|
|
if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
|
|
jQuery.style( fx.elem, prop, fx.end );
|
|
fx.setAttr = true;
|
|
}
|
|
};
|
|
}
|
|
);
|
|
|
|
function getElementStyles( elem ) {
|
|
var key, len,
|
|
style = elem.ownerDocument.defaultView ?
|
|
elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
|
|
elem.currentStyle,
|
|
styles = {};
|
|
|
|
if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
|
|
len = style.length;
|
|
while ( len-- ) {
|
|
key = style[ len ];
|
|
if ( typeof style[ key ] === "string" ) {
|
|
styles[ $.camelCase( key ) ] = style[ key ];
|
|
}
|
|
}
|
|
|
|
// Support: Opera, IE <9
|
|
} else {
|
|
for ( key in style ) {
|
|
if ( typeof style[ key ] === "string" ) {
|
|
styles[ key ] = style[ key ];
|
|
}
|
|
}
|
|
}
|
|
|
|
return styles;
|
|
}
|
|
|
|
function styleDifference( oldStyle, newStyle ) {
|
|
var diff = {},
|
|
name, value;
|
|
|
|
for ( name in newStyle ) {
|
|
value = newStyle[ name ];
|
|
if ( oldStyle[ name ] !== value ) {
|
|
if ( !shorthandStyles[ name ] ) {
|
|
if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
|
|
diff[ name ] = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return diff;
|
|
}
|
|
|
|
// Support: jQuery <1.8
|
|
if ( !$.fn.addBack ) {
|
|
$.fn.addBack = function( selector ) {
|
|
return this.add( selector == null ?
|
|
this.prevObject : this.prevObject.filter( selector )
|
|
);
|
|
};
|
|
}
|
|
|
|
$.effects.animateClass = function( value, duration, easing, callback ) {
|
|
var o = $.speed( duration, easing, callback );
|
|
|
|
return this.queue( function() {
|
|
var animated = $( this ),
|
|
baseClass = animated.attr( "class" ) || "",
|
|
applyClassChange,
|
|
allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
|
|
|
|
// Map the animated objects to store the original styles.
|
|
allAnimations = allAnimations.map( function() {
|
|
var el = $( this );
|
|
return {
|
|
el: el,
|
|
start: getElementStyles( this )
|
|
};
|
|
} );
|
|
|
|
// Apply class change
|
|
applyClassChange = function() {
|
|
$.each( classAnimationActions, function( i, action ) {
|
|
if ( value[ action ] ) {
|
|
animated[ action + "Class" ]( value[ action ] );
|
|
}
|
|
} );
|
|
};
|
|
applyClassChange();
|
|
|
|
// Map all animated objects again - calculate new styles and diff
|
|
allAnimations = allAnimations.map( function() {
|
|
this.end = getElementStyles( this.el[ 0 ] );
|
|
this.diff = styleDifference( this.start, this.end );
|
|
return this;
|
|
} );
|
|
|
|
// Apply original class
|
|
animated.attr( "class", baseClass );
|
|
|
|
// Map all animated objects again - this time collecting a promise
|
|
allAnimations = allAnimations.map( function() {
|
|
var styleInfo = this,
|
|
dfd = $.Deferred(),
|
|
opts = $.extend( {}, o, {
|
|
queue: false,
|
|
complete: function() {
|
|
dfd.resolve( styleInfo );
|
|
}
|
|
} );
|
|
|
|
this.el.animate( this.diff, opts );
|
|
return dfd.promise();
|
|
} );
|
|
|
|
// Once all animations have completed:
|
|
$.when.apply( $, allAnimations.get() ).done( function() {
|
|
|
|
// Set the final class
|
|
applyClassChange();
|
|
|
|
// For each animated element,
|
|
// clear all css properties that were animated
|
|
$.each( arguments, function() {
|
|
var el = this.el;
|
|
$.each( this.diff, function( key ) {
|
|
el.css( key, "" );
|
|
} );
|
|
} );
|
|
|
|
// This is guarnteed to be there if you use jQuery.speed()
|
|
// it also handles dequeuing the next anim...
|
|
o.complete.call( animated[ 0 ] );
|
|
} );
|
|
} );
|
|
};
|
|
|
|
$.fn.extend( {
|
|
addClass: ( function( orig ) {
|
|
return function( classNames, speed, easing, callback ) {
|
|
return speed ?
|
|
$.effects.animateClass.call( this,
|
|
{ add: classNames }, speed, easing, callback ) :
|
|
orig.apply( this, arguments );
|
|
};
|
|
} )( $.fn.addClass ),
|
|
|
|
removeClass: ( function( orig ) {
|
|
return function( classNames, speed, easing, callback ) {
|
|
return arguments.length > 1 ?
|
|
$.effects.animateClass.call( this,
|
|
{ remove: classNames }, speed, easing, callback ) :
|
|
orig.apply( this, arguments );
|
|
};
|
|
} )( $.fn.removeClass ),
|
|
|
|
toggleClass: ( function( orig ) {
|
|
return function( classNames, force, speed, easing, callback ) {
|
|
if ( typeof force === "boolean" || force === undefined ) {
|
|
if ( !speed ) {
|
|
|
|
// Without speed parameter
|
|
return orig.apply( this, arguments );
|
|
} else {
|
|
return $.effects.animateClass.call( this,
|
|
( force ? { add: classNames } : { remove: classNames } ),
|
|
speed, easing, callback );
|
|
}
|
|
} else {
|
|
|
|
// Without force parameter
|
|
return $.effects.animateClass.call( this,
|
|
{ toggle: classNames }, force, speed, easing );
|
|
}
|
|
};
|
|
} )( $.fn.toggleClass ),
|
|
|
|
switchClass: function( remove, add, speed, easing, callback ) {
|
|
return $.effects.animateClass.call( this, {
|
|
add: add,
|
|
remove: remove
|
|
}, speed, easing, callback );
|
|
}
|
|
} );
|
|
|
|
} )();
|
|
|
|
/******************************************************************************/
|
|
/*********************************** EFFECTS **********************************/
|
|
/******************************************************************************/
|
|
|
|
( function() {
|
|
|
|
if ( $.expr && $.expr.filters && $.expr.filters.animated ) {
|
|
$.expr.filters.animated = ( function( orig ) {
|
|
return function( elem ) {
|
|
return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
|
|
};
|
|
} )( $.expr.filters.animated );
|
|
}
|
|
|
|
if ( $.uiBackCompat !== false ) {
|
|
$.extend( $.effects, {
|
|
|
|
// Saves a set of properties in a data storage
|
|
save: function( element, set ) {
|
|
var i = 0, length = set.length;
|
|
for ( ; i < length; i++ ) {
|
|
if ( set[ i ] !== null ) {
|
|
element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
|
|
}
|
|
}
|
|
},
|
|
|
|
// Restores a set of previously saved properties from a data storage
|
|
restore: function( element, set ) {
|
|
var val, i = 0, length = set.length;
|
|
for ( ; i < length; i++ ) {
|
|
if ( set[ i ] !== null ) {
|
|
val = element.data( dataSpace + set[ i ] );
|
|
element.css( set[ i ], val );
|
|
}
|
|
}
|
|
},
|
|
|
|
setMode: function( el, mode ) {
|
|
if ( mode === "toggle" ) {
|
|
mode = el.is( ":hidden" ) ? "show" : "hide";
|
|
}
|
|
return mode;
|
|
},
|
|
|
|
// Wraps the element around a wrapper that copies position properties
|
|
createWrapper: function( element ) {
|
|
|
|
// If the element is already wrapped, return it
|
|
if ( element.parent().is( ".ui-effects-wrapper" ) ) {
|
|
return element.parent();
|
|
}
|
|
|
|
// Wrap the element
|
|
var props = {
|
|
width: element.outerWidth( true ),
|
|
height: element.outerHeight( true ),
|
|
"float": element.css( "float" )
|
|
},
|
|
wrapper = $( "<div></div>" )
|
|
.addClass( "ui-effects-wrapper" )
|
|
.css( {
|
|
fontSize: "100%",
|
|
background: "transparent",
|
|
border: "none",
|
|
margin: 0,
|
|
padding: 0
|
|
} ),
|
|
|
|
// Store the size in case width/height are defined in % - Fixes #5245
|
|
size = {
|
|
width: element.width(),
|
|
height: element.height()
|
|
},
|
|
active = document.activeElement;
|
|
|
|
// Support: Firefox
|
|
// Firefox incorrectly exposes anonymous content
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
|
|
try {
|
|
active.id;
|
|
} catch ( e ) {
|
|
active = document.body;
|
|
}
|
|
|
|
element.wrap( wrapper );
|
|
|
|
// Fixes #7595 - Elements lose focus when wrapped.
|
|
if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
|
|
$( active ).trigger( "focus" );
|
|
}
|
|
|
|
// Hotfix for jQuery 1.4 since some change in wrap() seems to actually
|
|
// lose the reference to the wrapped element
|
|
wrapper = element.parent();
|
|
|
|
// Transfer positioning properties to the wrapper
|
|
if ( element.css( "position" ) === "static" ) {
|
|
wrapper.css( { position: "relative" } );
|
|
element.css( { position: "relative" } );
|
|
} else {
|
|
$.extend( props, {
|
|
position: element.css( "position" ),
|
|
zIndex: element.css( "z-index" )
|
|
} );
|
|
$.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
|
|
props[ pos ] = element.css( pos );
|
|
if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
|
|
props[ pos ] = "auto";
|
|
}
|
|
} );
|
|
element.css( {
|
|
position: "relative",
|
|
top: 0,
|
|
left: 0,
|
|
right: "auto",
|
|
bottom: "auto"
|
|
} );
|
|
}
|
|
element.css( size );
|
|
|
|
return wrapper.css( props ).show();
|
|
},
|
|
|
|
removeWrapper: function( element ) {
|
|
var active = document.activeElement;
|
|
|
|
if ( element.parent().is( ".ui-effects-wrapper" ) ) {
|
|
element.parent().replaceWith( element );
|
|
|
|
// Fixes #7595 - Elements lose focus when wrapped.
|
|
if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
|
|
$( active ).trigger( "focus" );
|
|
}
|
|
}
|
|
|
|
return element;
|
|
}
|
|
} );
|
|
}
|
|
|
|
$.extend( $.effects, {
|
|
version: "1.12.1",
|
|
|
|
define: function( name, mode, effect ) {
|
|
if ( !effect ) {
|
|
effect = mode;
|
|
mode = "effect";
|
|
}
|
|
|
|
$.effects.effect[ name ] = effect;
|
|
$.effects.effect[ name ].mode = mode;
|
|
|
|
return effect;
|
|
},
|
|
|
|
scaledDimensions: function( element, percent, direction ) {
|
|
if ( percent === 0 ) {
|
|
return {
|
|
height: 0,
|
|
width: 0,
|
|
outerHeight: 0,
|
|
outerWidth: 0
|
|
};
|
|
}
|
|
|
|
var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
|
|
y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
|
|
|
|
return {
|
|
height: element.height() * y,
|
|
width: element.width() * x,
|
|
outerHeight: element.outerHeight() * y,
|
|
outerWidth: element.outerWidth() * x
|
|
};
|
|
|
|
},
|
|
|
|
clipToBox: function( animation ) {
|
|
return {
|
|
width: animation.clip.right - animation.clip.left,
|
|
height: animation.clip.bottom - animation.clip.top,
|
|
left: animation.clip.left,
|
|
top: animation.clip.top
|
|
};
|
|
},
|
|
|
|
// Injects recently queued functions to be first in line (after "inprogress")
|
|
unshift: function( element, queueLength, count ) {
|
|
var queue = element.queue();
|
|
|
|
if ( queueLength > 1 ) {
|
|
queue.splice.apply( queue,
|
|
[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
|
|
}
|
|
element.dequeue();
|
|
},
|
|
|
|
saveStyle: function( element ) {
|
|
element.data( dataSpaceStyle, element[ 0 ].style.cssText );
|
|
},
|
|
|
|
restoreStyle: function( element ) {
|
|
element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
|
|
element.removeData( dataSpaceStyle );
|
|
},
|
|
|
|
mode: function( element, mode ) {
|
|
var hidden = element.is( ":hidden" );
|
|
|
|
if ( mode === "toggle" ) {
|
|
mode = hidden ? "show" : "hide";
|
|
}
|
|
if ( hidden ? mode === "hide" : mode === "show" ) {
|
|
mode = "none";
|
|
}
|
|
return mode;
|
|
},
|
|
|
|
// Translates a [top,left] array into a baseline value
|
|
getBaseline: function( origin, original ) {
|
|
var y, x;
|
|
|
|
switch ( origin[ 0 ] ) {
|
|
case "top":
|
|
y = 0;
|
|
break;
|
|
case "middle":
|
|
y = 0.5;
|
|
break;
|
|
case "bottom":
|
|
y = 1;
|
|
break;
|
|
default:
|
|
y = origin[ 0 ] / original.height;
|
|
}
|
|
|
|
switch ( origin[ 1 ] ) {
|
|
case "left":
|
|
x = 0;
|
|
break;
|
|
case "center":
|
|
x = 0.5;
|
|
break;
|
|
case "right":
|
|
x = 1;
|
|
break;
|
|
default:
|
|
x = origin[ 1 ] / original.width;
|
|
}
|
|
|
|
return {
|
|
x: x,
|
|
y: y
|
|
};
|
|
},
|
|
|
|
// Creates a placeholder element so that the original element can be made absolute
|
|
createPlaceholder: function( element ) {
|
|
var placeholder,
|
|
cssPosition = element.css( "position" ),
|
|
position = element.position();
|
|
|
|
// Lock in margins first to account for form elements, which
|
|
// will change margin if you explicitly set height
|
|
// see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
|
|
// Support: Safari
|
|
element.css( {
|
|
marginTop: element.css( "marginTop" ),
|
|
marginBottom: element.css( "marginBottom" ),
|
|
marginLeft: element.css( "marginLeft" ),
|
|
marginRight: element.css( "marginRight" )
|
|
} )
|
|
.outerWidth( element.outerWidth() )
|
|
.outerHeight( element.outerHeight() );
|
|
|
|
if ( /^(static|relative)/.test( cssPosition ) ) {
|
|
cssPosition = "absolute";
|
|
|
|
placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
|
|
|
|
// Convert inline to inline block to account for inline elements
|
|
// that turn to inline block based on content (like img)
|
|
display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
|
|
"inline-block" :
|
|
"block",
|
|
visibility: "hidden",
|
|
|
|
// Margins need to be set to account for margin collapse
|
|
marginTop: element.css( "marginTop" ),
|
|
marginBottom: element.css( "marginBottom" ),
|
|
marginLeft: element.css( "marginLeft" ),
|
|
marginRight: element.css( "marginRight" ),
|
|
"float": element.css( "float" )
|
|
} )
|
|
.outerWidth( element.outerWidth() )
|
|
.outerHeight( element.outerHeight() )
|
|
.addClass( "ui-effects-placeholder" );
|
|
|
|
element.data( dataSpace + "placeholder", placeholder );
|
|
}
|
|
|
|
element.css( {
|
|
position: cssPosition,
|
|
left: position.left,
|
|
top: position.top
|
|
} );
|
|
|
|
return placeholder;
|
|
},
|
|
|
|
removePlaceholder: function( element ) {
|
|
var dataKey = dataSpace + "placeholder",
|
|
placeholder = element.data( dataKey );
|
|
|
|
if ( placeholder ) {
|
|
placeholder.remove();
|
|
element.removeData( dataKey );
|
|
}
|
|
},
|
|
|
|
// Removes a placeholder if it exists and restores
|
|
// properties that were modified during placeholder creation
|
|
cleanUp: function( element ) {
|
|
$.effects.restoreStyle( element );
|
|
$.effects.removePlaceholder( element );
|
|
},
|
|
|
|
setTransition: function( element, list, factor, value ) {
|
|
value = value || {};
|
|
$.each( list, function( i, x ) {
|
|
var unit = element.cssUnit( x );
|
|
if ( unit[ 0 ] > 0 ) {
|
|
value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
|
|
}
|
|
} );
|
|
return value;
|
|
}
|
|
} );
|
|
|
|
// Return an effect options object for the given parameters:
|
|
function _normalizeArguments( effect, options, speed, callback ) {
|
|
|
|
// Allow passing all options as the first parameter
|
|
if ( $.isPlainObject( effect ) ) {
|
|
options = effect;
|
|
effect = effect.effect;
|
|
}
|
|
|
|
// Convert to an object
|
|
effect = { effect: effect };
|
|
|
|
// Catch (effect, null, ...)
|
|
if ( options == null ) {
|
|
options = {};
|
|
}
|
|
|
|
// Catch (effect, callback)
|
|
if ( $.isFunction( options ) ) {
|
|
callback = options;
|
|
speed = null;
|
|
options = {};
|
|
}
|
|
|
|
// Catch (effect, speed, ?)
|
|
if ( typeof options === "number" || $.fx.speeds[ options ] ) {
|
|
callback = speed;
|
|
speed = options;
|
|
options = {};
|
|
}
|
|
|
|
// Catch (effect, options, callback)
|
|
if ( $.isFunction( speed ) ) {
|
|
callback = speed;
|
|
speed = null;
|
|
}
|
|
|
|
// Add options to effect
|
|
if ( options ) {
|
|
$.extend( effect, options );
|
|
}
|
|
|
|
speed = speed || options.duration;
|
|
effect.duration = $.fx.off ? 0 :
|
|
typeof speed === "number" ? speed :
|
|
speed in $.fx.speeds ? $.fx.speeds[ speed ] :
|
|
$.fx.speeds._default;
|
|
|
|
effect.complete = callback || options.complete;
|
|
|
|
return effect;
|
|
}
|
|
|
|
function standardAnimationOption( option ) {
|
|
|
|
// Valid standard speeds (nothing, number, named speed)
|
|
if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
|
|
return true;
|
|
}
|
|
|
|
// Invalid strings - treat as "normal" speed
|
|
if ( typeof option === "string" && !$.effects.effect[ option ] ) {
|
|
return true;
|
|
}
|
|
|
|
// Complete callback
|
|
if ( $.isFunction( option ) ) {
|
|
return true;
|
|
}
|
|
|
|
// Options hash (but not naming an effect)
|
|
if ( typeof option === "object" && !option.effect ) {
|
|
return true;
|
|
}
|
|
|
|
// Didn't match any standard API
|
|
return false;
|
|
}
|
|
|
|
$.fn.extend( {
|
|
effect: function( /* effect, options, speed, callback */ ) {
|
|
var args = _normalizeArguments.apply( this, arguments ),
|
|
effectMethod = $.effects.effect[ args.effect ],
|
|
defaultMode = effectMethod.mode,
|
|
queue = args.queue,
|
|
queueName = queue || "fx",
|
|
complete = args.complete,
|
|
mode = args.mode,
|
|
modes = [],
|
|
prefilter = function( next ) {
|
|
var el = $( this ),
|
|
normalizedMode = $.effects.mode( el, mode ) || defaultMode;
|
|
|
|
// Sentinel for duck-punching the :animated psuedo-selector
|
|
el.data( dataSpaceAnimated, true );
|
|
|
|
// Save effect mode for later use,
|
|
// we can't just call $.effects.mode again later,
|
|
// as the .show() below destroys the initial state
|
|
modes.push( normalizedMode );
|
|
|
|
// See $.uiBackCompat inside of run() for removal of defaultMode in 1.13
|
|
if ( defaultMode && ( normalizedMode === "show" ||
|
|
( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
|
|
el.show();
|
|
}
|
|
|
|
if ( !defaultMode || normalizedMode !== "none" ) {
|
|
$.effects.saveStyle( el );
|
|
}
|
|
|
|
if ( $.isFunction( next ) ) {
|
|
next();
|
|
}
|
|
};
|
|
|
|
if ( $.fx.off || !effectMethod ) {
|
|
|
|
// Delegate to the original method (e.g., .show()) if possible
|
|
if ( mode ) {
|
|
return this[ mode ]( args.duration, complete );
|
|
} else {
|
|
return this.each( function() {
|
|
if ( complete ) {
|
|
complete.call( this );
|
|
}
|
|
} );
|
|
}
|
|
}
|
|
|
|
function run( next ) {
|
|
var elem = $( this );
|
|
|
|
function cleanup() {
|
|
elem.removeData( dataSpaceAnimated );
|
|
|
|
$.effects.cleanUp( elem );
|
|
|
|
if ( args.mode === "hide" ) {
|
|
elem.hide();
|
|
}
|
|
|
|
done();
|
|
}
|
|
|
|
function done() {
|
|
if ( $.isFunction( complete ) ) {
|
|
complete.call( elem[ 0 ] );
|
|
}
|
|
|
|
if ( $.isFunction( next ) ) {
|
|
next();
|
|
}
|
|
}
|
|
|
|
// Override mode option on a per element basis,
|
|
// as toggle can be either show or hide depending on element state
|
|
args.mode = modes.shift();
|
|
|
|
if ( $.uiBackCompat !== false && !defaultMode ) {
|
|
if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
|
|
|
|
// Call the core method to track "olddisplay" properly
|
|
elem[ mode ]();
|
|
done();
|
|
} else {
|
|
effectMethod.call( elem[ 0 ], args, done );
|
|
}
|
|
} else {
|
|
if ( args.mode === "none" ) {
|
|
|
|
// Call the core method to track "olddisplay" properly
|
|
elem[ mode ]();
|
|
done();
|
|
} else {
|
|
effectMethod.call( elem[ 0 ], args, cleanup );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Run prefilter on all elements first to ensure that
|
|
// any showing or hiding happens before placeholder creation,
|
|
// which ensures that any layout changes are correctly captured.
|
|
return queue === false ?
|
|
this.each( prefilter ).each( run ) :
|
|
this.queue( queueName, prefilter ).queue( queueName, run );
|
|
},
|
|
|
|
show: ( function( orig ) {
|
|
return function( option ) {
|
|
if ( standardAnimationOption( option ) ) {
|
|
return orig.apply( this, arguments );
|
|
} else {
|
|
var args = _normalizeArguments.apply( this, arguments );
|
|
args.mode = "show";
|
|
return this.effect.call( this, args );
|
|
}
|
|
};
|
|
} )( $.fn.show ),
|
|
|
|
hide: ( function( orig ) {
|
|
return function( option ) {
|
|
if ( standardAnimationOption( option ) ) {
|
|
return orig.apply( this, arguments );
|
|
} else {
|
|
var args = _normalizeArguments.apply( this, arguments );
|
|
args.mode = "hide";
|
|
return this.effect.call( this, args );
|
|
}
|
|
};
|
|
} )( $.fn.hide ),
|
|
|
|
toggle: ( function( orig ) {
|
|
return function( option ) {
|
|
if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
|
|
return orig.apply( this, arguments );
|
|
} else {
|
|
var args = _normalizeArguments.apply( this, arguments );
|
|
args.mode = "toggle";
|
|
return this.effect.call( this, args );
|
|
}
|
|
};
|
|
} )( $.fn.toggle ),
|
|
|
|
cssUnit: function( key ) {
|
|
var style = this.css( key ),
|
|
val = [];
|
|
|
|
$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
|
|
if ( style.indexOf( unit ) > 0 ) {
|
|
val = [ parseFloat( style ), unit ];
|
|
}
|
|
} );
|
|
return val;
|
|
},
|
|
|
|
cssClip: function( clipObj ) {
|
|
if ( clipObj ) {
|
|
return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
|
|
clipObj.bottom + "px " + clipObj.left + "px)" );
|
|
}
|
|
return parseClip( this.css( "clip" ), this );
|
|
},
|
|
|
|
transfer: function( options, done ) {
|
|
var element = $( this ),
|
|
target = $( options.to ),
|
|
targetFixed = target.css( "position" ) === "fixed",
|
|
body = $( "body" ),
|
|
fixTop = targetFixed ? body.scrollTop() : 0,
|
|
fixLeft = targetFixed ? body.scrollLeft() : 0,
|
|
endPosition = target.offset(),
|
|
animation = {
|
|
top: endPosition.top - fixTop,
|
|
left: endPosition.left - fixLeft,
|
|
height: target.innerHeight(),
|
|
width: target.innerWidth()
|
|
},
|
|
startPosition = element.offset(),
|
|
transfer = $( "<div class='ui-effects-transfer'></div>" )
|
|
.appendTo( "body" )
|
|
.addClass( options.className )
|
|
.css( {
|
|
top: startPosition.top - fixTop,
|
|
left: startPosition.left - fixLeft,
|
|
height: element.innerHeight(),
|
|
width: element.innerWidth(),
|
|
position: targetFixed ? "fixed" : "absolute"
|
|
} )
|
|
.animate( animation, options.duration, options.easing, function() {
|
|
transfer.remove();
|
|
if ( $.isFunction( done ) ) {
|
|
done();
|
|
}
|
|
} );
|
|
}
|
|
} );
|
|
|
|
function parseClip( str, element ) {
|
|
var outerWidth = element.outerWidth(),
|
|
outerHeight = element.outerHeight(),
|
|
clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,
|
|
values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
|
|
|
|
return {
|
|
top: parseFloat( values[ 1 ] ) || 0,
|
|
right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
|
|
bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
|
|
left: parseFloat( values[ 4 ] ) || 0
|
|
};
|
|
}
|
|
|
|
$.fx.step.clip = function( fx ) {
|
|
if ( !fx.clipInit ) {
|
|
fx.start = $( fx.elem ).cssClip();
|
|
if ( typeof fx.end === "string" ) {
|
|
fx.end = parseClip( fx.end, fx.elem );
|
|
}
|
|
fx.clipInit = true;
|
|
}
|
|
|
|
$( fx.elem ).cssClip( {
|
|
top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
|
|
right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
|
|
bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
|
|
left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
|
|
} );
|
|
};
|
|
|
|
} )();
|
|
|
|
/******************************************************************************/
|
|
/*********************************** EASING ***********************************/
|
|
/******************************************************************************/
|
|
|
|
( function() {
|
|
|
|
// Based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
|
|
|
|
var baseEasings = {};
|
|
|
|
$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
|
|
baseEasings[ name ] = function( p ) {
|
|
return Math.pow( p, i + 2 );
|
|
};
|
|
} );
|
|
|
|
$.extend( baseEasings, {
|
|
Sine: function( p ) {
|
|
return 1 - Math.cos( p * Math.PI / 2 );
|
|
},
|
|
Circ: function( p ) {
|
|
return 1 - Math.sqrt( 1 - p * p );
|
|
},
|
|
Elastic: function( p ) {
|
|
return p === 0 || p === 1 ? p :
|
|
-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
|
|
},
|
|
Back: function( p ) {
|
|
return p * p * ( 3 * p - 2 );
|
|
},
|
|
Bounce: function( p ) {
|
|
var pow2,
|
|
bounce = 4;
|
|
|
|
while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
|
|
return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
|
|
}
|
|
} );
|
|
|
|
$.each( baseEasings, function( name, easeIn ) {
|
|
$.easing[ "easeIn" + name ] = easeIn;
|
|
$.easing[ "easeOut" + name ] = function( p ) {
|
|
return 1 - easeIn( 1 - p );
|
|
};
|
|
$.easing[ "easeInOut" + name ] = function( p ) {
|
|
return p < 0.5 ?
|
|
easeIn( p * 2 ) / 2 :
|
|
1 - easeIn( p * -2 + 2 ) / 2;
|
|
};
|
|
} );
|
|
|
|
} )();
|
|
|
|
return $.effects;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 25 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Blind 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Blind Effect
|
|
//>>group: Effects
|
|
//>>description: Blinds the element.
|
|
//>>docs: http://api.jqueryui.com/blind-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "blind", "hide", function( options, done ) {
|
|
var map = {
|
|
up: [ "bottom", "top" ],
|
|
vertical: [ "bottom", "top" ],
|
|
down: [ "top", "bottom" ],
|
|
left: [ "right", "left" ],
|
|
horizontal: [ "right", "left" ],
|
|
right: [ "left", "right" ]
|
|
},
|
|
element = $( this ),
|
|
direction = options.direction || "up",
|
|
start = element.cssClip(),
|
|
animate = { clip: $.extend( {}, start ) },
|
|
placeholder = $.effects.createPlaceholder( element );
|
|
|
|
animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
|
|
|
|
if ( options.mode === "show" ) {
|
|
element.cssClip( animate.clip );
|
|
if ( placeholder ) {
|
|
placeholder.css( $.effects.clipToBox( animate ) );
|
|
}
|
|
|
|
animate.clip = start;
|
|
}
|
|
|
|
if ( placeholder ) {
|
|
placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
|
|
}
|
|
|
|
element.animate( animate, {
|
|
queue: false,
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
complete: done
|
|
} );
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 26 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Bounce 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Bounce Effect
|
|
//>>group: Effects
|
|
//>>description: Bounces an element horizontally or vertically n times.
|
|
//>>docs: http://api.jqueryui.com/bounce-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "bounce", function( options, done ) {
|
|
var upAnim, downAnim, refValue,
|
|
element = $( this ),
|
|
|
|
// Defaults:
|
|
mode = options.mode,
|
|
hide = mode === "hide",
|
|
show = mode === "show",
|
|
direction = options.direction || "up",
|
|
distance = options.distance,
|
|
times = options.times || 5,
|
|
|
|
// Number of internal animations
|
|
anims = times * 2 + ( show || hide ? 1 : 0 ),
|
|
speed = options.duration / anims,
|
|
easing = options.easing,
|
|
|
|
// Utility:
|
|
ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
|
|
motion = ( direction === "up" || direction === "left" ),
|
|
i = 0,
|
|
|
|
queuelen = element.queue().length;
|
|
|
|
$.effects.createPlaceholder( element );
|
|
|
|
refValue = element.css( ref );
|
|
|
|
// Default distance for the BIGGEST bounce is the outer Distance / 3
|
|
if ( !distance ) {
|
|
distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
|
|
}
|
|
|
|
if ( show ) {
|
|
downAnim = { opacity: 1 };
|
|
downAnim[ ref ] = refValue;
|
|
|
|
// If we are showing, force opacity 0 and set the initial position
|
|
// then do the "first" animation
|
|
element
|
|
.css( "opacity", 0 )
|
|
.css( ref, motion ? -distance * 2 : distance * 2 )
|
|
.animate( downAnim, speed, easing );
|
|
}
|
|
|
|
// Start at the smallest distance if we are hiding
|
|
if ( hide ) {
|
|
distance = distance / Math.pow( 2, times - 1 );
|
|
}
|
|
|
|
downAnim = {};
|
|
downAnim[ ref ] = refValue;
|
|
|
|
// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
|
|
for ( ; i < times; i++ ) {
|
|
upAnim = {};
|
|
upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
|
|
|
|
element
|
|
.animate( upAnim, speed, easing )
|
|
.animate( downAnim, speed, easing );
|
|
|
|
distance = hide ? distance * 2 : distance / 2;
|
|
}
|
|
|
|
// Last Bounce when Hiding
|
|
if ( hide ) {
|
|
upAnim = { opacity: 0 };
|
|
upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
|
|
|
|
element.animate( upAnim, speed, easing );
|
|
}
|
|
|
|
element.queue( done );
|
|
|
|
$.effects.unshift( element, queuelen, anims + 1 );
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 27 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Clip 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Clip Effect
|
|
//>>group: Effects
|
|
//>>description: Clips the element on and off like an old TV.
|
|
//>>docs: http://api.jqueryui.com/clip-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "clip", "hide", function( options, done ) {
|
|
var start,
|
|
animate = {},
|
|
element = $( this ),
|
|
direction = options.direction || "vertical",
|
|
both = direction === "both",
|
|
horizontal = both || direction === "horizontal",
|
|
vertical = both || direction === "vertical";
|
|
|
|
start = element.cssClip();
|
|
animate.clip = {
|
|
top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
|
|
right: horizontal ? ( start.right - start.left ) / 2 : start.right,
|
|
bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
|
|
left: horizontal ? ( start.right - start.left ) / 2 : start.left
|
|
};
|
|
|
|
$.effects.createPlaceholder( element );
|
|
|
|
if ( options.mode === "show" ) {
|
|
element.cssClip( animate.clip );
|
|
animate.clip = start;
|
|
}
|
|
|
|
element.animate( animate, {
|
|
queue: false,
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
complete: done
|
|
} );
|
|
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 28 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Drop 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Drop Effect
|
|
//>>group: Effects
|
|
//>>description: Moves an element in one direction and hides it at the same time.
|
|
//>>docs: http://api.jqueryui.com/drop-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "drop", "hide", function( options, done ) {
|
|
|
|
var distance,
|
|
element = $( this ),
|
|
mode = options.mode,
|
|
show = mode === "show",
|
|
direction = options.direction || "left",
|
|
ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
|
|
motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
|
|
oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
|
|
animation = {
|
|
opacity: 0
|
|
};
|
|
|
|
$.effects.createPlaceholder( element );
|
|
|
|
distance = options.distance ||
|
|
element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
|
|
|
|
animation[ ref ] = motion + distance;
|
|
|
|
if ( show ) {
|
|
element.css( animation );
|
|
|
|
animation[ ref ] = oppositeMotion + distance;
|
|
animation.opacity = 1;
|
|
}
|
|
|
|
// Animate
|
|
element.animate( animation, {
|
|
queue: false,
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
complete: done
|
|
} );
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 29 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Explode 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Explode Effect
|
|
//>>group: Effects
|
|
// jscs:disable maximumLineLength
|
|
//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
|
|
// jscs:enable maximumLineLength
|
|
//>>docs: http://api.jqueryui.com/explode-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "explode", "hide", function( options, done ) {
|
|
|
|
var i, j, left, top, mx, my,
|
|
rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
|
|
cells = rows,
|
|
element = $( this ),
|
|
mode = options.mode,
|
|
show = mode === "show",
|
|
|
|
// Show and then visibility:hidden the element before calculating offset
|
|
offset = element.show().css( "visibility", "hidden" ).offset(),
|
|
|
|
// Width and height of a piece
|
|
width = Math.ceil( element.outerWidth() / cells ),
|
|
height = Math.ceil( element.outerHeight() / rows ),
|
|
pieces = [];
|
|
|
|
// Children animate complete:
|
|
function childComplete() {
|
|
pieces.push( this );
|
|
if ( pieces.length === rows * cells ) {
|
|
animComplete();
|
|
}
|
|
}
|
|
|
|
// Clone the element for each row and cell.
|
|
for ( i = 0; i < rows; i++ ) { // ===>
|
|
top = offset.top + i * height;
|
|
my = i - ( rows - 1 ) / 2;
|
|
|
|
for ( j = 0; j < cells; j++ ) { // |||
|
|
left = offset.left + j * width;
|
|
mx = j - ( cells - 1 ) / 2;
|
|
|
|
// Create a clone of the now hidden main element that will be absolute positioned
|
|
// within a wrapper div off the -left and -top equal to size of our pieces
|
|
element
|
|
.clone()
|
|
.appendTo( "body" )
|
|
.wrap( "<div></div>" )
|
|
.css( {
|
|
position: "absolute",
|
|
visibility: "visible",
|
|
left: -j * width,
|
|
top: -i * height
|
|
} )
|
|
|
|
// Select the wrapper - make it overflow: hidden and absolute positioned based on
|
|
// where the original was located +left and +top equal to the size of pieces
|
|
.parent()
|
|
.addClass( "ui-effects-explode" )
|
|
.css( {
|
|
position: "absolute",
|
|
overflow: "hidden",
|
|
width: width,
|
|
height: height,
|
|
left: left + ( show ? mx * width : 0 ),
|
|
top: top + ( show ? my * height : 0 ),
|
|
opacity: show ? 0 : 1
|
|
} )
|
|
.animate( {
|
|
left: left + ( show ? 0 : mx * width ),
|
|
top: top + ( show ? 0 : my * height ),
|
|
opacity: show ? 1 : 0
|
|
}, options.duration || 500, options.easing, childComplete );
|
|
}
|
|
}
|
|
|
|
function animComplete() {
|
|
element.css( {
|
|
visibility: "visible"
|
|
} );
|
|
$( pieces ).remove();
|
|
done();
|
|
}
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 30 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Fade 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Fade Effect
|
|
//>>group: Effects
|
|
//>>description: Fades the element.
|
|
//>>docs: http://api.jqueryui.com/fade-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "fade", "toggle", function( options, done ) {
|
|
var show = options.mode === "show";
|
|
|
|
$( this )
|
|
.css( "opacity", show ? 0 : 1 )
|
|
.animate( {
|
|
opacity: show ? 1 : 0
|
|
}, {
|
|
queue: false,
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
complete: done
|
|
} );
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 31 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Fold 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Fold Effect
|
|
//>>group: Effects
|
|
//>>description: Folds an element first horizontally and then vertically.
|
|
//>>docs: http://api.jqueryui.com/fold-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "fold", "hide", function( options, done ) {
|
|
|
|
// Create element
|
|
var element = $( this ),
|
|
mode = options.mode,
|
|
show = mode === "show",
|
|
hide = mode === "hide",
|
|
size = options.size || 15,
|
|
percent = /([0-9]+)%/.exec( size ),
|
|
horizFirst = !!options.horizFirst,
|
|
ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
|
|
duration = options.duration / 2,
|
|
|
|
placeholder = $.effects.createPlaceholder( element ),
|
|
|
|
start = element.cssClip(),
|
|
animation1 = { clip: $.extend( {}, start ) },
|
|
animation2 = { clip: $.extend( {}, start ) },
|
|
|
|
distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
|
|
|
|
queuelen = element.queue().length;
|
|
|
|
if ( percent ) {
|
|
size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
|
|
}
|
|
animation1.clip[ ref[ 0 ] ] = size;
|
|
animation2.clip[ ref[ 0 ] ] = size;
|
|
animation2.clip[ ref[ 1 ] ] = 0;
|
|
|
|
if ( show ) {
|
|
element.cssClip( animation2.clip );
|
|
if ( placeholder ) {
|
|
placeholder.css( $.effects.clipToBox( animation2 ) );
|
|
}
|
|
|
|
animation2.clip = start;
|
|
}
|
|
|
|
// Animate
|
|
element
|
|
.queue( function( next ) {
|
|
if ( placeholder ) {
|
|
placeholder
|
|
.animate( $.effects.clipToBox( animation1 ), duration, options.easing )
|
|
.animate( $.effects.clipToBox( animation2 ), duration, options.easing );
|
|
}
|
|
|
|
next();
|
|
} )
|
|
.animate( animation1, duration, options.easing )
|
|
.animate( animation2, duration, options.easing )
|
|
.queue( done );
|
|
|
|
$.effects.unshift( element, queuelen, 4 );
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 32 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Highlight 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Highlight Effect
|
|
//>>group: Effects
|
|
//>>description: Highlights the background of an element in a defined color for a custom duration.
|
|
//>>docs: http://api.jqueryui.com/highlight-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "highlight", "show", function( options, done ) {
|
|
var element = $( this ),
|
|
animation = {
|
|
backgroundColor: element.css( "backgroundColor" )
|
|
};
|
|
|
|
if ( options.mode === "hide" ) {
|
|
animation.opacity = 0;
|
|
}
|
|
|
|
$.effects.saveStyle( element );
|
|
|
|
element
|
|
.css( {
|
|
backgroundImage: "none",
|
|
backgroundColor: options.color || "#ffff99"
|
|
} )
|
|
.animate( animation, {
|
|
queue: false,
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
complete: done
|
|
} );
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 33 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Puff 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Puff Effect
|
|
//>>group: Effects
|
|
//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
|
|
//>>docs: http://api.jqueryui.com/puff-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24),
|
|
__webpack_require__(34)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "puff", "hide", function( options, done ) {
|
|
var newOptions = $.extend( true, {}, options, {
|
|
fade: true,
|
|
percent: parseInt( options.percent, 10 ) || 150
|
|
} );
|
|
|
|
$.effects.effect.scale.call( this, newOptions, done );
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 34 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Scale 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Scale Effect
|
|
//>>group: Effects
|
|
//>>description: Grows or shrinks an element and its content.
|
|
//>>docs: http://api.jqueryui.com/scale-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24),
|
|
__webpack_require__(35)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "scale", function( options, done ) {
|
|
|
|
// Create element
|
|
var el = $( this ),
|
|
mode = options.mode,
|
|
percent = parseInt( options.percent, 10 ) ||
|
|
( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
|
|
|
|
newOptions = $.extend( true, {
|
|
from: $.effects.scaledDimensions( el ),
|
|
to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
|
|
origin: options.origin || [ "middle", "center" ]
|
|
}, options );
|
|
|
|
// Fade option to support puff
|
|
if ( options.fade ) {
|
|
newOptions.from.opacity = 1;
|
|
newOptions.to.opacity = 0;
|
|
}
|
|
|
|
$.effects.effect.size.call( this, newOptions, done );
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 35 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Size 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Size Effect
|
|
//>>group: Effects
|
|
//>>description: Resize an element to a specified width and height.
|
|
//>>docs: http://api.jqueryui.com/size-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "size", function( options, done ) {
|
|
|
|
// Create element
|
|
var baseline, factor, temp,
|
|
element = $( this ),
|
|
|
|
// Copy for children
|
|
cProps = [ "fontSize" ],
|
|
vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
|
|
hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
|
|
|
|
// Set options
|
|
mode = options.mode,
|
|
restore = mode !== "effect",
|
|
scale = options.scale || "both",
|
|
origin = options.origin || [ "middle", "center" ],
|
|
position = element.css( "position" ),
|
|
pos = element.position(),
|
|
original = $.effects.scaledDimensions( element ),
|
|
from = options.from || original,
|
|
to = options.to || $.effects.scaledDimensions( element, 0 );
|
|
|
|
$.effects.createPlaceholder( element );
|
|
|
|
if ( mode === "show" ) {
|
|
temp = from;
|
|
from = to;
|
|
to = temp;
|
|
}
|
|
|
|
// Set scaling factor
|
|
factor = {
|
|
from: {
|
|
y: from.height / original.height,
|
|
x: from.width / original.width
|
|
},
|
|
to: {
|
|
y: to.height / original.height,
|
|
x: to.width / original.width
|
|
}
|
|
};
|
|
|
|
// Scale the css box
|
|
if ( scale === "box" || scale === "both" ) {
|
|
|
|
// Vertical props scaling
|
|
if ( factor.from.y !== factor.to.y ) {
|
|
from = $.effects.setTransition( element, vProps, factor.from.y, from );
|
|
to = $.effects.setTransition( element, vProps, factor.to.y, to );
|
|
}
|
|
|
|
// Horizontal props scaling
|
|
if ( factor.from.x !== factor.to.x ) {
|
|
from = $.effects.setTransition( element, hProps, factor.from.x, from );
|
|
to = $.effects.setTransition( element, hProps, factor.to.x, to );
|
|
}
|
|
}
|
|
|
|
// Scale the content
|
|
if ( scale === "content" || scale === "both" ) {
|
|
|
|
// Vertical props scaling
|
|
if ( factor.from.y !== factor.to.y ) {
|
|
from = $.effects.setTransition( element, cProps, factor.from.y, from );
|
|
to = $.effects.setTransition( element, cProps, factor.to.y, to );
|
|
}
|
|
}
|
|
|
|
// Adjust the position properties based on the provided origin points
|
|
if ( origin ) {
|
|
baseline = $.effects.getBaseline( origin, original );
|
|
from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
|
|
from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
|
|
to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
|
|
to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
|
|
}
|
|
element.css( from );
|
|
|
|
// Animate the children if desired
|
|
if ( scale === "content" || scale === "both" ) {
|
|
|
|
vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
|
|
hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
|
|
|
|
// Only animate children with width attributes specified
|
|
// TODO: is this right? should we include anything with css width specified as well
|
|
element.find( "*[width]" ).each( function() {
|
|
var child = $( this ),
|
|
childOriginal = $.effects.scaledDimensions( child ),
|
|
childFrom = {
|
|
height: childOriginal.height * factor.from.y,
|
|
width: childOriginal.width * factor.from.x,
|
|
outerHeight: childOriginal.outerHeight * factor.from.y,
|
|
outerWidth: childOriginal.outerWidth * factor.from.x
|
|
},
|
|
childTo = {
|
|
height: childOriginal.height * factor.to.y,
|
|
width: childOriginal.width * factor.to.x,
|
|
outerHeight: childOriginal.height * factor.to.y,
|
|
outerWidth: childOriginal.width * factor.to.x
|
|
};
|
|
|
|
// Vertical props scaling
|
|
if ( factor.from.y !== factor.to.y ) {
|
|
childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
|
|
childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
|
|
}
|
|
|
|
// Horizontal props scaling
|
|
if ( factor.from.x !== factor.to.x ) {
|
|
childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
|
|
childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
|
|
}
|
|
|
|
if ( restore ) {
|
|
$.effects.saveStyle( child );
|
|
}
|
|
|
|
// Animate children
|
|
child.css( childFrom );
|
|
child.animate( childTo, options.duration, options.easing, function() {
|
|
|
|
// Restore children
|
|
if ( restore ) {
|
|
$.effects.restoreStyle( child );
|
|
}
|
|
} );
|
|
} );
|
|
}
|
|
|
|
// Animate
|
|
element.animate( to, {
|
|
queue: false,
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
complete: function() {
|
|
|
|
var offset = element.offset();
|
|
|
|
if ( to.opacity === 0 ) {
|
|
element.css( "opacity", from.opacity );
|
|
}
|
|
|
|
if ( !restore ) {
|
|
element
|
|
.css( "position", position === "static" ? "relative" : position )
|
|
.offset( offset );
|
|
|
|
// Need to save style here so that automatic style restoration
|
|
// doesn't restore to the original styles from before the animation.
|
|
$.effects.saveStyle( element );
|
|
}
|
|
|
|
done();
|
|
}
|
|
} );
|
|
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 36 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Pulsate 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Pulsate Effect
|
|
//>>group: Effects
|
|
//>>description: Pulsates an element n times by changing the opacity to zero and back.
|
|
//>>docs: http://api.jqueryui.com/pulsate-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "pulsate", "show", function( options, done ) {
|
|
var element = $( this ),
|
|
mode = options.mode,
|
|
show = mode === "show",
|
|
hide = mode === "hide",
|
|
showhide = show || hide,
|
|
|
|
// Showing or hiding leaves off the "last" animation
|
|
anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
|
|
duration = options.duration / anims,
|
|
animateTo = 0,
|
|
i = 1,
|
|
queuelen = element.queue().length;
|
|
|
|
if ( show || !element.is( ":visible" ) ) {
|
|
element.css( "opacity", 0 ).show();
|
|
animateTo = 1;
|
|
}
|
|
|
|
// Anims - 1 opacity "toggles"
|
|
for ( ; i < anims; i++ ) {
|
|
element.animate( { opacity: animateTo }, duration, options.easing );
|
|
animateTo = 1 - animateTo;
|
|
}
|
|
|
|
element.animate( { opacity: animateTo }, duration, options.easing );
|
|
|
|
element.queue( done );
|
|
|
|
$.effects.unshift( element, queuelen, anims + 1 );
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 37 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Shake 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Shake Effect
|
|
//>>group: Effects
|
|
//>>description: Shakes an element horizontally or vertically n times.
|
|
//>>docs: http://api.jqueryui.com/shake-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "shake", function( options, done ) {
|
|
|
|
var i = 1,
|
|
element = $( this ),
|
|
direction = options.direction || "left",
|
|
distance = options.distance || 20,
|
|
times = options.times || 3,
|
|
anims = times * 2 + 1,
|
|
speed = Math.round( options.duration / anims ),
|
|
ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
|
|
positiveMotion = ( direction === "up" || direction === "left" ),
|
|
animation = {},
|
|
animation1 = {},
|
|
animation2 = {},
|
|
|
|
queuelen = element.queue().length;
|
|
|
|
$.effects.createPlaceholder( element );
|
|
|
|
// Animation
|
|
animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
|
|
animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
|
|
animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
|
|
|
|
// Animate
|
|
element.animate( animation, speed, options.easing );
|
|
|
|
// Shakes
|
|
for ( ; i < times; i++ ) {
|
|
element
|
|
.animate( animation1, speed, options.easing )
|
|
.animate( animation2, speed, options.easing );
|
|
}
|
|
|
|
element
|
|
.animate( animation1, speed, options.easing )
|
|
.animate( animation, speed / 2, options.easing )
|
|
.queue( done );
|
|
|
|
$.effects.unshift( element, queuelen, anims + 1 );
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 38 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Slide 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Slide Effect
|
|
//>>group: Effects
|
|
//>>description: Slides an element in and out of the viewport.
|
|
//>>docs: http://api.jqueryui.com/slide-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.effects.define( "slide", "show", function( options, done ) {
|
|
var startClip, startRef,
|
|
element = $( this ),
|
|
map = {
|
|
up: [ "bottom", "top" ],
|
|
down: [ "top", "bottom" ],
|
|
left: [ "right", "left" ],
|
|
right: [ "left", "right" ]
|
|
},
|
|
mode = options.mode,
|
|
direction = options.direction || "left",
|
|
ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
|
|
positiveMotion = ( direction === "up" || direction === "left" ),
|
|
distance = options.distance ||
|
|
element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
|
|
animation = {};
|
|
|
|
$.effects.createPlaceholder( element );
|
|
|
|
startClip = element.cssClip();
|
|
startRef = element.position()[ ref ];
|
|
|
|
// Define hide animation
|
|
animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
|
|
animation.clip = element.cssClip();
|
|
animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
|
|
|
|
// Reverse the animation if we're showing
|
|
if ( mode === "show" ) {
|
|
element.cssClip( animation.clip );
|
|
element.css( ref, animation[ ref ] );
|
|
animation.clip = startClip;
|
|
animation[ ref ] = startRef;
|
|
}
|
|
|
|
// Actually animate
|
|
element.animate( animation, {
|
|
queue: false,
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
complete: done
|
|
} );
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 39 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Effects Transfer 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Transfer Effect
|
|
//>>group: Effects
|
|
//>>description: Displays a transfer effect from one element to another.
|
|
//>>docs: http://api.jqueryui.com/transfer-effect/
|
|
//>>demos: http://jqueryui.com/effect/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(24)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
var effect;
|
|
if ( $.uiBackCompat !== false ) {
|
|
effect = $.effects.define( "transfer", function( options, done ) {
|
|
$( this ).transfer( options, done );
|
|
} );
|
|
}
|
|
return effect;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 40 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Focusable 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: :focusable Selector
|
|
//>>group: Core
|
|
//>>description: Selects elements which can be focused.
|
|
//>>docs: http://api.jqueryui.com/focusable-selector/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
|
|
// Selectors
|
|
$.ui.focusable = function( element, hasTabindex ) {
|
|
var map, mapName, img, focusableIfVisible, fieldset,
|
|
nodeName = element.nodeName.toLowerCase();
|
|
|
|
if ( "area" === nodeName ) {
|
|
map = element.parentNode;
|
|
mapName = map.name;
|
|
if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
|
|
return false;
|
|
}
|
|
img = $( "img[usemap='#" + mapName + "']" );
|
|
return img.length > 0 && img.is( ":visible" );
|
|
}
|
|
|
|
if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
|
|
focusableIfVisible = !element.disabled;
|
|
|
|
if ( focusableIfVisible ) {
|
|
|
|
// Form controls within a disabled fieldset are disabled.
|
|
// However, controls within the fieldset's legend do not get disabled.
|
|
// Since controls generally aren't placed inside legends, we skip
|
|
// this portion of the check.
|
|
fieldset = $( element ).closest( "fieldset" )[ 0 ];
|
|
if ( fieldset ) {
|
|
focusableIfVisible = !fieldset.disabled;
|
|
}
|
|
}
|
|
} else if ( "a" === nodeName ) {
|
|
focusableIfVisible = element.href || hasTabindex;
|
|
} else {
|
|
focusableIfVisible = hasTabindex;
|
|
}
|
|
|
|
return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
|
|
};
|
|
|
|
// Support: IE 8 only
|
|
// IE 8 doesn't resolve inherit to visible/hidden for computed values
|
|
function visible( element ) {
|
|
var visibility = element.css( "visibility" );
|
|
while ( visibility === "inherit" ) {
|
|
element = element.parent();
|
|
visibility = element.css( "visibility" );
|
|
}
|
|
return visibility !== "hidden";
|
|
}
|
|
|
|
$.extend( $.expr[ ":" ], {
|
|
focusable: function( element ) {
|
|
return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
|
|
}
|
|
} );
|
|
|
|
return $.ui.focusable;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 41 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
|
|
// Support: IE8 Only
|
|
// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
|
|
// with a string, so we need to find the proper form.
|
|
return $.fn.form = function() {
|
|
return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
|
|
};
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 42 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Support for jQuery core 1.7.x 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*
|
|
*/
|
|
|
|
//>>label: jQuery 1.7 Support
|
|
//>>group: Core
|
|
//>>description: Support version 1.7.x of jQuery core
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
// Support: jQuery 1.7 only
|
|
// Not a great way to check versions, but since we only support 1.7+ and only
|
|
// need to detect <1.8, this is a simple check that should suffice. Checking
|
|
// for "1.7." would be a bit safer, but the version string is 1.7, not 1.7.0
|
|
// and we'll never reach 1.70.0 (if we do, we certainly won't be supporting
|
|
// 1.7 anymore). See #11197 for why we're not using feature detection.
|
|
if ( $.fn.jquery.substring( 0, 3 ) === "1.7" ) {
|
|
|
|
// Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight()
|
|
// Unlike jQuery Core 1.8+, these only support numeric values to set the
|
|
// dimensions in pixels
|
|
$.each( [ "Width", "Height" ], function( i, name ) {
|
|
var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
|
|
type = name.toLowerCase(),
|
|
orig = {
|
|
innerWidth: $.fn.innerWidth,
|
|
innerHeight: $.fn.innerHeight,
|
|
outerWidth: $.fn.outerWidth,
|
|
outerHeight: $.fn.outerHeight
|
|
};
|
|
|
|
function reduce( elem, size, border, margin ) {
|
|
$.each( side, function() {
|
|
size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
|
|
if ( border ) {
|
|
size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
|
|
}
|
|
if ( margin ) {
|
|
size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
|
|
}
|
|
} );
|
|
return size;
|
|
}
|
|
|
|
$.fn[ "inner" + name ] = function( size ) {
|
|
if ( size === undefined ) {
|
|
return orig[ "inner" + name ].call( this );
|
|
}
|
|
|
|
return this.each( function() {
|
|
$( this ).css( type, reduce( this, size ) + "px" );
|
|
} );
|
|
};
|
|
|
|
$.fn[ "outer" + name ] = function( size, margin ) {
|
|
if ( typeof size !== "number" ) {
|
|
return orig[ "outer" + name ].call( this, size );
|
|
}
|
|
|
|
return this.each( function() {
|
|
$( this ).css( type, reduce( this, size, true, margin ) + "px" );
|
|
} );
|
|
};
|
|
} );
|
|
|
|
$.fn.addBack = function( selector ) {
|
|
return this.add( selector == null ?
|
|
this.prevObject : this.prevObject.filter( selector )
|
|
);
|
|
};
|
|
}
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 43 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Keycode 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Keycode
|
|
//>>group: Core
|
|
//>>description: Provide keycodes as keynames
|
|
//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
return $.ui.keyCode = {
|
|
BACKSPACE: 8,
|
|
COMMA: 188,
|
|
DELETE: 46,
|
|
DOWN: 40,
|
|
END: 35,
|
|
ENTER: 13,
|
|
ESCAPE: 27,
|
|
HOME: 36,
|
|
LEFT: 37,
|
|
PAGE_DOWN: 34,
|
|
PAGE_UP: 33,
|
|
PERIOD: 190,
|
|
RIGHT: 39,
|
|
SPACE: 32,
|
|
TAB: 9,
|
|
UP: 38
|
|
};
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 44 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Labels 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: labels
|
|
//>>group: Core
|
|
//>>description: Find all the labels associated with a given input
|
|
//>>docs: http://api.jqueryui.com/labels/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15), __webpack_require__(45) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
|
|
return $.fn.labels = function() {
|
|
var ancestor, selector, id, labels, ancestors;
|
|
|
|
// Check control.labels first
|
|
if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
|
|
return this.pushStack( this[ 0 ].labels );
|
|
}
|
|
|
|
// Support: IE <= 11, FF <= 37, Android <= 2.3 only
|
|
// Above browsers do not support control.labels. Everything below is to support them
|
|
// as well as document fragments. control.labels does not work on document fragments
|
|
labels = this.eq( 0 ).parents( "label" );
|
|
|
|
// Look for the label based on the id
|
|
id = this.attr( "id" );
|
|
if ( id ) {
|
|
|
|
// We don't search against the document in case the element
|
|
// is disconnected from the DOM
|
|
ancestor = this.eq( 0 ).parents().last();
|
|
|
|
// Get a full set of top level ancestors
|
|
ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
|
|
|
|
// Create a selector for the label based on the id
|
|
selector = "label[for='" + $.ui.escapeSelector( id ) + "']";
|
|
|
|
labels = labels.add( ancestors.find( selector ).addBack( selector ) );
|
|
|
|
}
|
|
|
|
// Return whatever we have found for labels
|
|
return this.pushStack( labels );
|
|
};
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 45 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
|
|
// Internal use only
|
|
return $.ui.escapeSelector = ( function() {
|
|
var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;
|
|
return function( selector ) {
|
|
return selector.replace( selectorEscape, "\\$1" );
|
|
};
|
|
} )();
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 46 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Scroll Parent 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: scrollParent
|
|
//>>group: Core
|
|
//>>description: Get the closest ancestor element that is scrollable.
|
|
//>>docs: http://api.jqueryui.com/scrollParent/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
|
|
return $.fn.scrollParent = function( includeHidden ) {
|
|
var position = this.css( "position" ),
|
|
excludeStaticParent = position === "absolute",
|
|
overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
|
|
scrollParent = this.parents().filter( function() {
|
|
var parent = $( this );
|
|
if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
|
|
return false;
|
|
}
|
|
return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
|
|
parent.css( "overflow-x" ) );
|
|
} ).eq( 0 );
|
|
|
|
return position === "fixed" || !scrollParent.length ?
|
|
$( this[ 0 ].ownerDocument || document ) :
|
|
scrollParent;
|
|
};
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 47 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Tabbable 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: :tabbable Selector
|
|
//>>group: Core
|
|
//>>description: Selects elements which can be tabbed to.
|
|
//>>docs: http://api.jqueryui.com/tabbable-selector/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15), __webpack_require__(40) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
|
|
return $.extend( $.expr[ ":" ], {
|
|
tabbable: function( element ) {
|
|
var tabIndex = $.attr( element, "tabindex" ),
|
|
hasTabindex = tabIndex != null;
|
|
return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
|
|
}
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 48 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Unique ID 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: uniqueId
|
|
//>>group: Core
|
|
//>>description: Functions to generate and remove uniqueId's
|
|
//>>docs: http://api.jqueryui.com/uniqueId/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2), __webpack_require__(15) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} ( function( $ ) {
|
|
|
|
return $.fn.extend( {
|
|
uniqueId: ( function() {
|
|
var uuid = 0;
|
|
|
|
return function() {
|
|
return this.each( function() {
|
|
if ( !this.id ) {
|
|
this.id = "ui-id-" + ( ++uuid );
|
|
}
|
|
} );
|
|
};
|
|
} )(),
|
|
|
|
removeUniqueId: function() {
|
|
return this.each( function() {
|
|
if ( /^ui-id-\d+$/.test( this.id ) ) {
|
|
$( this ).removeAttr( "id" );
|
|
}
|
|
} );
|
|
}
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 49 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Accordion 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Accordion
|
|
//>>group: Widgets
|
|
// jscs:disable maximumLineLength
|
|
//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
|
|
// jscs:enable maximumLineLength
|
|
//>>docs: http://api.jqueryui.com/accordion/
|
|
//>>demos: http://jqueryui.com/accordion/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/accordion.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(43),
|
|
__webpack_require__(48),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.widget( "ui.accordion", {
|
|
version: "1.12.1",
|
|
options: {
|
|
active: 0,
|
|
animate: {},
|
|
classes: {
|
|
"ui-accordion-header": "ui-corner-top",
|
|
"ui-accordion-header-collapsed": "ui-corner-all",
|
|
"ui-accordion-content": "ui-corner-bottom"
|
|
},
|
|
collapsible: false,
|
|
event: "click",
|
|
header: "> li > :first-child, > :not(li):even",
|
|
heightStyle: "auto",
|
|
icons: {
|
|
activeHeader: "ui-icon-triangle-1-s",
|
|
header: "ui-icon-triangle-1-e"
|
|
},
|
|
|
|
// Callbacks
|
|
activate: null,
|
|
beforeActivate: null
|
|
},
|
|
|
|
hideProps: {
|
|
borderTopWidth: "hide",
|
|
borderBottomWidth: "hide",
|
|
paddingTop: "hide",
|
|
paddingBottom: "hide",
|
|
height: "hide"
|
|
},
|
|
|
|
showProps: {
|
|
borderTopWidth: "show",
|
|
borderBottomWidth: "show",
|
|
paddingTop: "show",
|
|
paddingBottom: "show",
|
|
height: "show"
|
|
},
|
|
|
|
_create: function() {
|
|
var options = this.options;
|
|
|
|
this.prevShow = this.prevHide = $();
|
|
this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
|
|
this.element.attr( "role", "tablist" );
|
|
|
|
// Don't allow collapsible: false and active: false / null
|
|
if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
|
|
options.active = 0;
|
|
}
|
|
|
|
this._processPanels();
|
|
|
|
// handle negative values
|
|
if ( options.active < 0 ) {
|
|
options.active += this.headers.length;
|
|
}
|
|
this._refresh();
|
|
},
|
|
|
|
_getCreateEventData: function() {
|
|
return {
|
|
header: this.active,
|
|
panel: !this.active.length ? $() : this.active.next()
|
|
};
|
|
},
|
|
|
|
_createIcons: function() {
|
|
var icon, children,
|
|
icons = this.options.icons;
|
|
|
|
if ( icons ) {
|
|
icon = $( "<span>" );
|
|
this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
|
|
icon.prependTo( this.headers );
|
|
children = this.active.children( ".ui-accordion-header-icon" );
|
|
this._removeClass( children, icons.header )
|
|
._addClass( children, null, icons.activeHeader )
|
|
._addClass( this.headers, "ui-accordion-icons" );
|
|
}
|
|
},
|
|
|
|
_destroyIcons: function() {
|
|
this._removeClass( this.headers, "ui-accordion-icons" );
|
|
this.headers.children( ".ui-accordion-header-icon" ).remove();
|
|
},
|
|
|
|
_destroy: function() {
|
|
var contents;
|
|
|
|
// Clean up main element
|
|
this.element.removeAttr( "role" );
|
|
|
|
// Clean up headers
|
|
this.headers
|
|
.removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
|
|
.removeUniqueId();
|
|
|
|
this._destroyIcons();
|
|
|
|
// Clean up content panels
|
|
contents = this.headers.next()
|
|
.css( "display", "" )
|
|
.removeAttr( "role aria-hidden aria-labelledby" )
|
|
.removeUniqueId();
|
|
|
|
if ( this.options.heightStyle !== "content" ) {
|
|
contents.css( "height", "" );
|
|
}
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
if ( key === "active" ) {
|
|
|
|
// _activate() will handle invalid values and update this.options
|
|
this._activate( value );
|
|
return;
|
|
}
|
|
|
|
if ( key === "event" ) {
|
|
if ( this.options.event ) {
|
|
this._off( this.headers, this.options.event );
|
|
}
|
|
this._setupEvents( value );
|
|
}
|
|
|
|
this._super( key, value );
|
|
|
|
// Setting collapsible: false while collapsed; open first panel
|
|
if ( key === "collapsible" && !value && this.options.active === false ) {
|
|
this._activate( 0 );
|
|
}
|
|
|
|
if ( key === "icons" ) {
|
|
this._destroyIcons();
|
|
if ( value ) {
|
|
this._createIcons();
|
|
}
|
|
}
|
|
},
|
|
|
|
_setOptionDisabled: function( value ) {
|
|
this._super( value );
|
|
|
|
this.element.attr( "aria-disabled", value );
|
|
|
|
// Support: IE8 Only
|
|
// #5332 / #6059 - opacity doesn't cascade to positioned elements in IE
|
|
// so we need to add the disabled class to the headers and panels
|
|
this._toggleClass( null, "ui-state-disabled", !!value );
|
|
this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled",
|
|
!!value );
|
|
},
|
|
|
|
_keydown: function( event ) {
|
|
if ( event.altKey || event.ctrlKey ) {
|
|
return;
|
|
}
|
|
|
|
var keyCode = $.ui.keyCode,
|
|
length = this.headers.length,
|
|
currentIndex = this.headers.index( event.target ),
|
|
toFocus = false;
|
|
|
|
switch ( event.keyCode ) {
|
|
case keyCode.RIGHT:
|
|
case keyCode.DOWN:
|
|
toFocus = this.headers[ ( currentIndex + 1 ) % length ];
|
|
break;
|
|
case keyCode.LEFT:
|
|
case keyCode.UP:
|
|
toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
|
|
break;
|
|
case keyCode.SPACE:
|
|
case keyCode.ENTER:
|
|
this._eventHandler( event );
|
|
break;
|
|
case keyCode.HOME:
|
|
toFocus = this.headers[ 0 ];
|
|
break;
|
|
case keyCode.END:
|
|
toFocus = this.headers[ length - 1 ];
|
|
break;
|
|
}
|
|
|
|
if ( toFocus ) {
|
|
$( event.target ).attr( "tabIndex", -1 );
|
|
$( toFocus ).attr( "tabIndex", 0 );
|
|
$( toFocus ).trigger( "focus" );
|
|
event.preventDefault();
|
|
}
|
|
},
|
|
|
|
_panelKeyDown: function( event ) {
|
|
if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
|
|
$( event.currentTarget ).prev().trigger( "focus" );
|
|
}
|
|
},
|
|
|
|
refresh: function() {
|
|
var options = this.options;
|
|
this._processPanels();
|
|
|
|
// Was collapsed or no panel
|
|
if ( ( options.active === false && options.collapsible === true ) ||
|
|
!this.headers.length ) {
|
|
options.active = false;
|
|
this.active = $();
|
|
|
|
// active false only when collapsible is true
|
|
} else if ( options.active === false ) {
|
|
this._activate( 0 );
|
|
|
|
// was active, but active panel is gone
|
|
} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
|
|
|
|
// all remaining panel are disabled
|
|
if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
|
|
options.active = false;
|
|
this.active = $();
|
|
|
|
// activate previous panel
|
|
} else {
|
|
this._activate( Math.max( 0, options.active - 1 ) );
|
|
}
|
|
|
|
// was active, active panel still exists
|
|
} else {
|
|
|
|
// make sure active index is correct
|
|
options.active = this.headers.index( this.active );
|
|
}
|
|
|
|
this._destroyIcons();
|
|
|
|
this._refresh();
|
|
},
|
|
|
|
_processPanels: function() {
|
|
var prevHeaders = this.headers,
|
|
prevPanels = this.panels;
|
|
|
|
this.headers = this.element.find( this.options.header );
|
|
this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
|
|
"ui-state-default" );
|
|
|
|
this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
|
|
this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
|
|
|
|
// Avoid memory leaks (#10056)
|
|
if ( prevPanels ) {
|
|
this._off( prevHeaders.not( this.headers ) );
|
|
this._off( prevPanels.not( this.panels ) );
|
|
}
|
|
},
|
|
|
|
_refresh: function() {
|
|
var maxHeight,
|
|
options = this.options,
|
|
heightStyle = options.heightStyle,
|
|
parent = this.element.parent();
|
|
|
|
this.active = this._findActive( options.active );
|
|
this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
|
|
._removeClass( this.active, "ui-accordion-header-collapsed" );
|
|
this._addClass( this.active.next(), "ui-accordion-content-active" );
|
|
this.active.next().show();
|
|
|
|
this.headers
|
|
.attr( "role", "tab" )
|
|
.each( function() {
|
|
var header = $( this ),
|
|
headerId = header.uniqueId().attr( "id" ),
|
|
panel = header.next(),
|
|
panelId = panel.uniqueId().attr( "id" );
|
|
header.attr( "aria-controls", panelId );
|
|
panel.attr( "aria-labelledby", headerId );
|
|
} )
|
|
.next()
|
|
.attr( "role", "tabpanel" );
|
|
|
|
this.headers
|
|
.not( this.active )
|
|
.attr( {
|
|
"aria-selected": "false",
|
|
"aria-expanded": "false",
|
|
tabIndex: -1
|
|
} )
|
|
.next()
|
|
.attr( {
|
|
"aria-hidden": "true"
|
|
} )
|
|
.hide();
|
|
|
|
// Make sure at least one header is in the tab order
|
|
if ( !this.active.length ) {
|
|
this.headers.eq( 0 ).attr( "tabIndex", 0 );
|
|
} else {
|
|
this.active.attr( {
|
|
"aria-selected": "true",
|
|
"aria-expanded": "true",
|
|
tabIndex: 0
|
|
} )
|
|
.next()
|
|
.attr( {
|
|
"aria-hidden": "false"
|
|
} );
|
|
}
|
|
|
|
this._createIcons();
|
|
|
|
this._setupEvents( options.event );
|
|
|
|
if ( heightStyle === "fill" ) {
|
|
maxHeight = parent.height();
|
|
this.element.siblings( ":visible" ).each( function() {
|
|
var elem = $( this ),
|
|
position = elem.css( "position" );
|
|
|
|
if ( position === "absolute" || position === "fixed" ) {
|
|
return;
|
|
}
|
|
maxHeight -= elem.outerHeight( true );
|
|
} );
|
|
|
|
this.headers.each( function() {
|
|
maxHeight -= $( this ).outerHeight( true );
|
|
} );
|
|
|
|
this.headers.next()
|
|
.each( function() {
|
|
$( this ).height( Math.max( 0, maxHeight -
|
|
$( this ).innerHeight() + $( this ).height() ) );
|
|
} )
|
|
.css( "overflow", "auto" );
|
|
} else if ( heightStyle === "auto" ) {
|
|
maxHeight = 0;
|
|
this.headers.next()
|
|
.each( function() {
|
|
var isVisible = $( this ).is( ":visible" );
|
|
if ( !isVisible ) {
|
|
$( this ).show();
|
|
}
|
|
maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
|
|
if ( !isVisible ) {
|
|
$( this ).hide();
|
|
}
|
|
} )
|
|
.height( maxHeight );
|
|
}
|
|
},
|
|
|
|
_activate: function( index ) {
|
|
var active = this._findActive( index )[ 0 ];
|
|
|
|
// Trying to activate the already active panel
|
|
if ( active === this.active[ 0 ] ) {
|
|
return;
|
|
}
|
|
|
|
// Trying to collapse, simulate a click on the currently active header
|
|
active = active || this.active[ 0 ];
|
|
|
|
this._eventHandler( {
|
|
target: active,
|
|
currentTarget: active,
|
|
preventDefault: $.noop
|
|
} );
|
|
},
|
|
|
|
_findActive: function( selector ) {
|
|
return typeof selector === "number" ? this.headers.eq( selector ) : $();
|
|
},
|
|
|
|
_setupEvents: function( event ) {
|
|
var events = {
|
|
keydown: "_keydown"
|
|
};
|
|
if ( event ) {
|
|
$.each( event.split( " " ), function( index, eventName ) {
|
|
events[ eventName ] = "_eventHandler";
|
|
} );
|
|
}
|
|
|
|
this._off( this.headers.add( this.headers.next() ) );
|
|
this._on( this.headers, events );
|
|
this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
|
|
this._hoverable( this.headers );
|
|
this._focusable( this.headers );
|
|
},
|
|
|
|
_eventHandler: function( event ) {
|
|
var activeChildren, clickedChildren,
|
|
options = this.options,
|
|
active = this.active,
|
|
clicked = $( event.currentTarget ),
|
|
clickedIsActive = clicked[ 0 ] === active[ 0 ],
|
|
collapsing = clickedIsActive && options.collapsible,
|
|
toShow = collapsing ? $() : clicked.next(),
|
|
toHide = active.next(),
|
|
eventData = {
|
|
oldHeader: active,
|
|
oldPanel: toHide,
|
|
newHeader: collapsing ? $() : clicked,
|
|
newPanel: toShow
|
|
};
|
|
|
|
event.preventDefault();
|
|
|
|
if (
|
|
|
|
// click on active header, but not collapsible
|
|
( clickedIsActive && !options.collapsible ) ||
|
|
|
|
// allow canceling activation
|
|
( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
|
|
return;
|
|
}
|
|
|
|
options.active = collapsing ? false : this.headers.index( clicked );
|
|
|
|
// When the call to ._toggle() comes after the class changes
|
|
// it causes a very odd bug in IE 8 (see #6720)
|
|
this.active = clickedIsActive ? $() : clicked;
|
|
this._toggle( eventData );
|
|
|
|
// Switch classes
|
|
// corner classes on the previously active header stay after the animation
|
|
this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
|
|
if ( options.icons ) {
|
|
activeChildren = active.children( ".ui-accordion-header-icon" );
|
|
this._removeClass( activeChildren, null, options.icons.activeHeader )
|
|
._addClass( activeChildren, null, options.icons.header );
|
|
}
|
|
|
|
if ( !clickedIsActive ) {
|
|
this._removeClass( clicked, "ui-accordion-header-collapsed" )
|
|
._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
|
|
if ( options.icons ) {
|
|
clickedChildren = clicked.children( ".ui-accordion-header-icon" );
|
|
this._removeClass( clickedChildren, null, options.icons.header )
|
|
._addClass( clickedChildren, null, options.icons.activeHeader );
|
|
}
|
|
|
|
this._addClass( clicked.next(), "ui-accordion-content-active" );
|
|
}
|
|
},
|
|
|
|
_toggle: function( data ) {
|
|
var toShow = data.newPanel,
|
|
toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
|
|
|
|
// Handle activating a panel during the animation for another activation
|
|
this.prevShow.add( this.prevHide ).stop( true, true );
|
|
this.prevShow = toShow;
|
|
this.prevHide = toHide;
|
|
|
|
if ( this.options.animate ) {
|
|
this._animate( toShow, toHide, data );
|
|
} else {
|
|
toHide.hide();
|
|
toShow.show();
|
|
this._toggleComplete( data );
|
|
}
|
|
|
|
toHide.attr( {
|
|
"aria-hidden": "true"
|
|
} );
|
|
toHide.prev().attr( {
|
|
"aria-selected": "false",
|
|
"aria-expanded": "false"
|
|
} );
|
|
|
|
// if we're switching panels, remove the old header from the tab order
|
|
// if we're opening from collapsed state, remove the previous header from the tab order
|
|
// if we're collapsing, then keep the collapsing header in the tab order
|
|
if ( toShow.length && toHide.length ) {
|
|
toHide.prev().attr( {
|
|
"tabIndex": -1,
|
|
"aria-expanded": "false"
|
|
} );
|
|
} else if ( toShow.length ) {
|
|
this.headers.filter( function() {
|
|
return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
|
|
} )
|
|
.attr( "tabIndex", -1 );
|
|
}
|
|
|
|
toShow
|
|
.attr( "aria-hidden", "false" )
|
|
.prev()
|
|
.attr( {
|
|
"aria-selected": "true",
|
|
"aria-expanded": "true",
|
|
tabIndex: 0
|
|
} );
|
|
},
|
|
|
|
_animate: function( toShow, toHide, data ) {
|
|
var total, easing, duration,
|
|
that = this,
|
|
adjust = 0,
|
|
boxSizing = toShow.css( "box-sizing" ),
|
|
down = toShow.length &&
|
|
( !toHide.length || ( toShow.index() < toHide.index() ) ),
|
|
animate = this.options.animate || {},
|
|
options = down && animate.down || animate,
|
|
complete = function() {
|
|
that._toggleComplete( data );
|
|
};
|
|
|
|
if ( typeof options === "number" ) {
|
|
duration = options;
|
|
}
|
|
if ( typeof options === "string" ) {
|
|
easing = options;
|
|
}
|
|
|
|
// fall back from options to animation in case of partial down settings
|
|
easing = easing || options.easing || animate.easing;
|
|
duration = duration || options.duration || animate.duration;
|
|
|
|
if ( !toHide.length ) {
|
|
return toShow.animate( this.showProps, duration, easing, complete );
|
|
}
|
|
if ( !toShow.length ) {
|
|
return toHide.animate( this.hideProps, duration, easing, complete );
|
|
}
|
|
|
|
total = toShow.show().outerHeight();
|
|
toHide.animate( this.hideProps, {
|
|
duration: duration,
|
|
easing: easing,
|
|
step: function( now, fx ) {
|
|
fx.now = Math.round( now );
|
|
}
|
|
} );
|
|
toShow
|
|
.hide()
|
|
.animate( this.showProps, {
|
|
duration: duration,
|
|
easing: easing,
|
|
complete: complete,
|
|
step: function( now, fx ) {
|
|
fx.now = Math.round( now );
|
|
if ( fx.prop !== "height" ) {
|
|
if ( boxSizing === "content-box" ) {
|
|
adjust += fx.now;
|
|
}
|
|
} else if ( that.options.heightStyle !== "content" ) {
|
|
fx.now = Math.round( total - toHide.outerHeight() - adjust );
|
|
adjust = 0;
|
|
}
|
|
}
|
|
} );
|
|
},
|
|
|
|
_toggleComplete: function( data ) {
|
|
var toHide = data.oldPanel,
|
|
prev = toHide.prev();
|
|
|
|
this._removeClass( toHide, "ui-accordion-content-active" );
|
|
this._removeClass( prev, "ui-accordion-header-active" )
|
|
._addClass( prev, "ui-accordion-header-collapsed" );
|
|
|
|
// Work around for rendering bug in IE (#5421)
|
|
if ( toHide.length ) {
|
|
toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
|
|
}
|
|
this._trigger( "activate", null, data );
|
|
}
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 50 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Menu 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Menu
|
|
//>>group: Widgets
|
|
//>>description: Creates nestable menus.
|
|
//>>docs: http://api.jqueryui.com/menu/
|
|
//>>demos: http://jqueryui.com/menu/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/menu.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(43),
|
|
__webpack_require__(21),
|
|
__webpack_require__(18),
|
|
__webpack_require__(48),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.widget( "ui.menu", {
|
|
version: "1.12.1",
|
|
defaultElement: "<ul>",
|
|
delay: 300,
|
|
options: {
|
|
icons: {
|
|
submenu: "ui-icon-caret-1-e"
|
|
},
|
|
items: "> *",
|
|
menus: "ul",
|
|
position: {
|
|
my: "left top",
|
|
at: "right top"
|
|
},
|
|
role: "menu",
|
|
|
|
// Callbacks
|
|
blur: null,
|
|
focus: null,
|
|
select: null
|
|
},
|
|
|
|
_create: function() {
|
|
this.activeMenu = this.element;
|
|
|
|
// Flag used to prevent firing of the click handler
|
|
// as the event bubbles up through nested menus
|
|
this.mouseHandled = false;
|
|
this.element
|
|
.uniqueId()
|
|
.attr( {
|
|
role: this.options.role,
|
|
tabIndex: 0
|
|
} );
|
|
|
|
this._addClass( "ui-menu", "ui-widget ui-widget-content" );
|
|
this._on( {
|
|
|
|
// Prevent focus from sticking to links inside menu after clicking
|
|
// them (focus should always stay on UL during navigation).
|
|
"mousedown .ui-menu-item": function( event ) {
|
|
event.preventDefault();
|
|
},
|
|
"click .ui-menu-item": function( event ) {
|
|
var target = $( event.target );
|
|
var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
|
|
if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
|
|
this.select( event );
|
|
|
|
// Only set the mouseHandled flag if the event will bubble, see #9469.
|
|
if ( !event.isPropagationStopped() ) {
|
|
this.mouseHandled = true;
|
|
}
|
|
|
|
// Open submenu on click
|
|
if ( target.has( ".ui-menu" ).length ) {
|
|
this.expand( event );
|
|
} else if ( !this.element.is( ":focus" ) &&
|
|
active.closest( ".ui-menu" ).length ) {
|
|
|
|
// Redirect focus to the menu
|
|
this.element.trigger( "focus", [ true ] );
|
|
|
|
// If the active item is on the top level, let it stay active.
|
|
// Otherwise, blur the active item since it is no longer visible.
|
|
if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
|
|
clearTimeout( this.timer );
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"mouseenter .ui-menu-item": function( event ) {
|
|
|
|
// Ignore mouse events while typeahead is active, see #10458.
|
|
// Prevents focusing the wrong item when typeahead causes a scroll while the mouse
|
|
// is over an item in the menu
|
|
if ( this.previousFilter ) {
|
|
return;
|
|
}
|
|
|
|
var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
|
|
target = $( event.currentTarget );
|
|
|
|
// Ignore bubbled events on parent items, see #11641
|
|
if ( actualTarget[ 0 ] !== target[ 0 ] ) {
|
|
return;
|
|
}
|
|
|
|
// Remove ui-state-active class from siblings of the newly focused menu item
|
|
// to avoid a jump caused by adjacent elements both having a class with a border
|
|
this._removeClass( target.siblings().children( ".ui-state-active" ),
|
|
null, "ui-state-active" );
|
|
this.focus( event, target );
|
|
},
|
|
mouseleave: "collapseAll",
|
|
"mouseleave .ui-menu": "collapseAll",
|
|
focus: function( event, keepActiveItem ) {
|
|
|
|
// If there's already an active item, keep it active
|
|
// If not, activate the first item
|
|
var item = this.active || this.element.find( this.options.items ).eq( 0 );
|
|
|
|
if ( !keepActiveItem ) {
|
|
this.focus( event, item );
|
|
}
|
|
},
|
|
blur: function( event ) {
|
|
this._delay( function() {
|
|
var notContained = !$.contains(
|
|
this.element[ 0 ],
|
|
$.ui.safeActiveElement( this.document[ 0 ] )
|
|
);
|
|
if ( notContained ) {
|
|
this.collapseAll( event );
|
|
}
|
|
} );
|
|
},
|
|
keydown: "_keydown"
|
|
} );
|
|
|
|
this.refresh();
|
|
|
|
// Clicks outside of a menu collapse any open menus
|
|
this._on( this.document, {
|
|
click: function( event ) {
|
|
if ( this._closeOnDocumentClick( event ) ) {
|
|
this.collapseAll( event );
|
|
}
|
|
|
|
// Reset the mouseHandled flag
|
|
this.mouseHandled = false;
|
|
}
|
|
} );
|
|
},
|
|
|
|
_destroy: function() {
|
|
var items = this.element.find( ".ui-menu-item" )
|
|
.removeAttr( "role aria-disabled" ),
|
|
submenus = items.children( ".ui-menu-item-wrapper" )
|
|
.removeUniqueId()
|
|
.removeAttr( "tabIndex role aria-haspopup" );
|
|
|
|
// Destroy (sub)menus
|
|
this.element
|
|
.removeAttr( "aria-activedescendant" )
|
|
.find( ".ui-menu" ).addBack()
|
|
.removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
|
|
"tabIndex" )
|
|
.removeUniqueId()
|
|
.show();
|
|
|
|
submenus.children().each( function() {
|
|
var elem = $( this );
|
|
if ( elem.data( "ui-menu-submenu-caret" ) ) {
|
|
elem.remove();
|
|
}
|
|
} );
|
|
},
|
|
|
|
_keydown: function( event ) {
|
|
var match, prev, character, skip,
|
|
preventDefault = true;
|
|
|
|
switch ( event.keyCode ) {
|
|
case $.ui.keyCode.PAGE_UP:
|
|
this.previousPage( event );
|
|
break;
|
|
case $.ui.keyCode.PAGE_DOWN:
|
|
this.nextPage( event );
|
|
break;
|
|
case $.ui.keyCode.HOME:
|
|
this._move( "first", "first", event );
|
|
break;
|
|
case $.ui.keyCode.END:
|
|
this._move( "last", "last", event );
|
|
break;
|
|
case $.ui.keyCode.UP:
|
|
this.previous( event );
|
|
break;
|
|
case $.ui.keyCode.DOWN:
|
|
this.next( event );
|
|
break;
|
|
case $.ui.keyCode.LEFT:
|
|
this.collapse( event );
|
|
break;
|
|
case $.ui.keyCode.RIGHT:
|
|
if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
|
|
this.expand( event );
|
|
}
|
|
break;
|
|
case $.ui.keyCode.ENTER:
|
|
case $.ui.keyCode.SPACE:
|
|
this._activate( event );
|
|
break;
|
|
case $.ui.keyCode.ESCAPE:
|
|
this.collapse( event );
|
|
break;
|
|
default:
|
|
preventDefault = false;
|
|
prev = this.previousFilter || "";
|
|
skip = false;
|
|
|
|
// Support number pad values
|
|
character = event.keyCode >= 96 && event.keyCode <= 105 ?
|
|
( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
|
|
|
|
clearTimeout( this.filterTimer );
|
|
|
|
if ( character === prev ) {
|
|
skip = true;
|
|
} else {
|
|
character = prev + character;
|
|
}
|
|
|
|
match = this._filterMenuItems( character );
|
|
match = skip && match.index( this.active.next() ) !== -1 ?
|
|
this.active.nextAll( ".ui-menu-item" ) :
|
|
match;
|
|
|
|
// If no matches on the current filter, reset to the last character pressed
|
|
// to move down the menu to the first item that starts with that character
|
|
if ( !match.length ) {
|
|
character = String.fromCharCode( event.keyCode );
|
|
match = this._filterMenuItems( character );
|
|
}
|
|
|
|
if ( match.length ) {
|
|
this.focus( event, match );
|
|
this.previousFilter = character;
|
|
this.filterTimer = this._delay( function() {
|
|
delete this.previousFilter;
|
|
}, 1000 );
|
|
} else {
|
|
delete this.previousFilter;
|
|
}
|
|
}
|
|
|
|
if ( preventDefault ) {
|
|
event.preventDefault();
|
|
}
|
|
},
|
|
|
|
_activate: function( event ) {
|
|
if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
|
|
if ( this.active.children( "[aria-haspopup='true']" ).length ) {
|
|
this.expand( event );
|
|
} else {
|
|
this.select( event );
|
|
}
|
|
}
|
|
},
|
|
|
|
refresh: function() {
|
|
var menus, items, newSubmenus, newItems, newWrappers,
|
|
that = this,
|
|
icon = this.options.icons.submenu,
|
|
submenus = this.element.find( this.options.menus );
|
|
|
|
this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
|
|
|
|
// Initialize nested menus
|
|
newSubmenus = submenus.filter( ":not(.ui-menu)" )
|
|
.hide()
|
|
.attr( {
|
|
role: this.options.role,
|
|
"aria-hidden": "true",
|
|
"aria-expanded": "false"
|
|
} )
|
|
.each( function() {
|
|
var menu = $( this ),
|
|
item = menu.prev(),
|
|
submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
|
|
|
|
that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
|
|
item
|
|
.attr( "aria-haspopup", "true" )
|
|
.prepend( submenuCaret );
|
|
menu.attr( "aria-labelledby", item.attr( "id" ) );
|
|
} );
|
|
|
|
this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
|
|
|
|
menus = submenus.add( this.element );
|
|
items = menus.find( this.options.items );
|
|
|
|
// Initialize menu-items containing spaces and/or dashes only as dividers
|
|
items.not( ".ui-menu-item" ).each( function() {
|
|
var item = $( this );
|
|
if ( that._isDivider( item ) ) {
|
|
that._addClass( item, "ui-menu-divider", "ui-widget-content" );
|
|
}
|
|
} );
|
|
|
|
// Don't refresh list items that are already adapted
|
|
newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
|
|
newWrappers = newItems.children()
|
|
.not( ".ui-menu" )
|
|
.uniqueId()
|
|
.attr( {
|
|
tabIndex: -1,
|
|
role: this._itemRole()
|
|
} );
|
|
this._addClass( newItems, "ui-menu-item" )
|
|
._addClass( newWrappers, "ui-menu-item-wrapper" );
|
|
|
|
// Add aria-disabled attribute to any disabled menu item
|
|
items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
|
|
|
|
// If the active item has been removed, blur the menu
|
|
if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
|
|
this.blur();
|
|
}
|
|
},
|
|
|
|
_itemRole: function() {
|
|
return {
|
|
menu: "menuitem",
|
|
listbox: "option"
|
|
}[ this.options.role ];
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
if ( key === "icons" ) {
|
|
var icons = this.element.find( ".ui-menu-icon" );
|
|
this._removeClass( icons, null, this.options.icons.submenu )
|
|
._addClass( icons, null, value.submenu );
|
|
}
|
|
this._super( key, value );
|
|
},
|
|
|
|
_setOptionDisabled: function( value ) {
|
|
this._super( value );
|
|
|
|
this.element.attr( "aria-disabled", String( value ) );
|
|
this._toggleClass( null, "ui-state-disabled", !!value );
|
|
},
|
|
|
|
focus: function( event, item ) {
|
|
var nested, focused, activeParent;
|
|
this.blur( event, event && event.type === "focus" );
|
|
|
|
this._scrollIntoView( item );
|
|
|
|
this.active = item.first();
|
|
|
|
focused = this.active.children( ".ui-menu-item-wrapper" );
|
|
this._addClass( focused, null, "ui-state-active" );
|
|
|
|
// Only update aria-activedescendant if there's a role
|
|
// otherwise we assume focus is managed elsewhere
|
|
if ( this.options.role ) {
|
|
this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
|
|
}
|
|
|
|
// Highlight active parent menu item, if any
|
|
activeParent = this.active
|
|
.parent()
|
|
.closest( ".ui-menu-item" )
|
|
.children( ".ui-menu-item-wrapper" );
|
|
this._addClass( activeParent, null, "ui-state-active" );
|
|
|
|
if ( event && event.type === "keydown" ) {
|
|
this._close();
|
|
} else {
|
|
this.timer = this._delay( function() {
|
|
this._close();
|
|
}, this.delay );
|
|
}
|
|
|
|
nested = item.children( ".ui-menu" );
|
|
if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
|
|
this._startOpening( nested );
|
|
}
|
|
this.activeMenu = item.parent();
|
|
|
|
this._trigger( "focus", event, { item: item } );
|
|
},
|
|
|
|
_scrollIntoView: function( item ) {
|
|
var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
|
|
if ( this._hasScroll() ) {
|
|
borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
|
|
paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
|
|
offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
|
|
scroll = this.activeMenu.scrollTop();
|
|
elementHeight = this.activeMenu.height();
|
|
itemHeight = item.outerHeight();
|
|
|
|
if ( offset < 0 ) {
|
|
this.activeMenu.scrollTop( scroll + offset );
|
|
} else if ( offset + itemHeight > elementHeight ) {
|
|
this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
|
|
}
|
|
}
|
|
},
|
|
|
|
blur: function( event, fromFocus ) {
|
|
if ( !fromFocus ) {
|
|
clearTimeout( this.timer );
|
|
}
|
|
|
|
if ( !this.active ) {
|
|
return;
|
|
}
|
|
|
|
this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
|
|
null, "ui-state-active" );
|
|
|
|
this._trigger( "blur", event, { item: this.active } );
|
|
this.active = null;
|
|
},
|
|
|
|
_startOpening: function( submenu ) {
|
|
clearTimeout( this.timer );
|
|
|
|
// Don't open if already open fixes a Firefox bug that caused a .5 pixel
|
|
// shift in the submenu position when mousing over the caret icon
|
|
if ( submenu.attr( "aria-hidden" ) !== "true" ) {
|
|
return;
|
|
}
|
|
|
|
this.timer = this._delay( function() {
|
|
this._close();
|
|
this._open( submenu );
|
|
}, this.delay );
|
|
},
|
|
|
|
_open: function( submenu ) {
|
|
var position = $.extend( {
|
|
of: this.active
|
|
}, this.options.position );
|
|
|
|
clearTimeout( this.timer );
|
|
this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
|
|
.hide()
|
|
.attr( "aria-hidden", "true" );
|
|
|
|
submenu
|
|
.show()
|
|
.removeAttr( "aria-hidden" )
|
|
.attr( "aria-expanded", "true" )
|
|
.position( position );
|
|
},
|
|
|
|
collapseAll: function( event, all ) {
|
|
clearTimeout( this.timer );
|
|
this.timer = this._delay( function() {
|
|
|
|
// If we were passed an event, look for the submenu that contains the event
|
|
var currentMenu = all ? this.element :
|
|
$( event && event.target ).closest( this.element.find( ".ui-menu" ) );
|
|
|
|
// If we found no valid submenu ancestor, use the main menu to close all
|
|
// sub menus anyway
|
|
if ( !currentMenu.length ) {
|
|
currentMenu = this.element;
|
|
}
|
|
|
|
this._close( currentMenu );
|
|
|
|
this.blur( event );
|
|
|
|
// Work around active item staying active after menu is blurred
|
|
this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
|
|
|
|
this.activeMenu = currentMenu;
|
|
}, this.delay );
|
|
},
|
|
|
|
// With no arguments, closes the currently active menu - if nothing is active
|
|
// it closes all menus. If passed an argument, it will search for menus BELOW
|
|
_close: function( startMenu ) {
|
|
if ( !startMenu ) {
|
|
startMenu = this.active ? this.active.parent() : this.element;
|
|
}
|
|
|
|
startMenu.find( ".ui-menu" )
|
|
.hide()
|
|
.attr( "aria-hidden", "true" )
|
|
.attr( "aria-expanded", "false" );
|
|
},
|
|
|
|
_closeOnDocumentClick: function( event ) {
|
|
return !$( event.target ).closest( ".ui-menu" ).length;
|
|
},
|
|
|
|
_isDivider: function( item ) {
|
|
|
|
// Match hyphen, em dash, en dash
|
|
return !/[^\-\u2014\u2013\s]/.test( item.text() );
|
|
},
|
|
|
|
collapse: function( event ) {
|
|
var newItem = this.active &&
|
|
this.active.parent().closest( ".ui-menu-item", this.element );
|
|
if ( newItem && newItem.length ) {
|
|
this._close();
|
|
this.focus( event, newItem );
|
|
}
|
|
},
|
|
|
|
expand: function( event ) {
|
|
var newItem = this.active &&
|
|
this.active
|
|
.children( ".ui-menu " )
|
|
.find( this.options.items )
|
|
.first();
|
|
|
|
if ( newItem && newItem.length ) {
|
|
this._open( newItem.parent() );
|
|
|
|
// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
|
|
this._delay( function() {
|
|
this.focus( event, newItem );
|
|
} );
|
|
}
|
|
},
|
|
|
|
next: function( event ) {
|
|
this._move( "next", "first", event );
|
|
},
|
|
|
|
previous: function( event ) {
|
|
this._move( "prev", "last", event );
|
|
},
|
|
|
|
isFirstItem: function() {
|
|
return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
|
|
},
|
|
|
|
isLastItem: function() {
|
|
return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
|
|
},
|
|
|
|
_move: function( direction, filter, event ) {
|
|
var next;
|
|
if ( this.active ) {
|
|
if ( direction === "first" || direction === "last" ) {
|
|
next = this.active
|
|
[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
|
|
.eq( -1 );
|
|
} else {
|
|
next = this.active
|
|
[ direction + "All" ]( ".ui-menu-item" )
|
|
.eq( 0 );
|
|
}
|
|
}
|
|
if ( !next || !next.length || !this.active ) {
|
|
next = this.activeMenu.find( this.options.items )[ filter ]();
|
|
}
|
|
|
|
this.focus( event, next );
|
|
},
|
|
|
|
nextPage: function( event ) {
|
|
var item, base, height;
|
|
|
|
if ( !this.active ) {
|
|
this.next( event );
|
|
return;
|
|
}
|
|
if ( this.isLastItem() ) {
|
|
return;
|
|
}
|
|
if ( this._hasScroll() ) {
|
|
base = this.active.offset().top;
|
|
height = this.element.height();
|
|
this.active.nextAll( ".ui-menu-item" ).each( function() {
|
|
item = $( this );
|
|
return item.offset().top - base - height < 0;
|
|
} );
|
|
|
|
this.focus( event, item );
|
|
} else {
|
|
this.focus( event, this.activeMenu.find( this.options.items )
|
|
[ !this.active ? "first" : "last" ]() );
|
|
}
|
|
},
|
|
|
|
previousPage: function( event ) {
|
|
var item, base, height;
|
|
if ( !this.active ) {
|
|
this.next( event );
|
|
return;
|
|
}
|
|
if ( this.isFirstItem() ) {
|
|
return;
|
|
}
|
|
if ( this._hasScroll() ) {
|
|
base = this.active.offset().top;
|
|
height = this.element.height();
|
|
this.active.prevAll( ".ui-menu-item" ).each( function() {
|
|
item = $( this );
|
|
return item.offset().top - base + height > 0;
|
|
} );
|
|
|
|
this.focus( event, item );
|
|
} else {
|
|
this.focus( event, this.activeMenu.find( this.options.items ).first() );
|
|
}
|
|
},
|
|
|
|
_hasScroll: function() {
|
|
return this.element.outerHeight() < this.element.prop( "scrollHeight" );
|
|
},
|
|
|
|
select: function( event ) {
|
|
|
|
// TODO: It should never be possible to not have an active item at this
|
|
// point, but the tests don't trigger mouseenter before click.
|
|
this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
|
|
var ui = { item: this.active };
|
|
if ( !this.active.has( ".ui-menu" ).length ) {
|
|
this.collapseAll( event, true );
|
|
}
|
|
this._trigger( "select", event, ui );
|
|
},
|
|
|
|
_filterMenuItems: function( character ) {
|
|
var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
|
|
regex = new RegExp( "^" + escapedCharacter, "i" );
|
|
|
|
return this.activeMenu
|
|
.find( this.options.items )
|
|
|
|
// Only match on items, not dividers or other content (#10571)
|
|
.filter( ".ui-menu-item" )
|
|
.filter( function() {
|
|
return regex.test(
|
|
$.trim( $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
|
|
} );
|
|
}
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 51 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Autocomplete 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Autocomplete
|
|
//>>group: Widgets
|
|
//>>description: Lists suggested words as the user is typing.
|
|
//>>docs: http://api.jqueryui.com/autocomplete/
|
|
//>>demos: http://jqueryui.com/autocomplete/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/autocomplete.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(50),
|
|
__webpack_require__(43),
|
|
__webpack_require__(21),
|
|
__webpack_require__(18),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
$.widget( "ui.autocomplete", {
|
|
version: "1.12.1",
|
|
defaultElement: "<input>",
|
|
options: {
|
|
appendTo: null,
|
|
autoFocus: false,
|
|
delay: 300,
|
|
minLength: 1,
|
|
position: {
|
|
my: "left top",
|
|
at: "left bottom",
|
|
collision: "none"
|
|
},
|
|
source: null,
|
|
|
|
// Callbacks
|
|
change: null,
|
|
close: null,
|
|
focus: null,
|
|
open: null,
|
|
response: null,
|
|
search: null,
|
|
select: null
|
|
},
|
|
|
|
requestIndex: 0,
|
|
pending: 0,
|
|
|
|
_create: function() {
|
|
|
|
// Some browsers only repeat keydown events, not keypress events,
|
|
// so we use the suppressKeyPress flag to determine if we've already
|
|
// handled the keydown event. #7269
|
|
// Unfortunately the code for & in keypress is the same as the up arrow,
|
|
// so we use the suppressKeyPressRepeat flag to avoid handling keypress
|
|
// events when we know the keydown event was used to modify the
|
|
// search term. #7799
|
|
var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
|
|
nodeName = this.element[ 0 ].nodeName.toLowerCase(),
|
|
isTextarea = nodeName === "textarea",
|
|
isInput = nodeName === "input";
|
|
|
|
// Textareas are always multi-line
|
|
// Inputs are always single-line, even if inside a contentEditable element
|
|
// IE also treats inputs as contentEditable
|
|
// All other element types are determined by whether or not they're contentEditable
|
|
this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
|
|
|
|
this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
|
|
this.isNewMenu = true;
|
|
|
|
this._addClass( "ui-autocomplete-input" );
|
|
this.element.attr( "autocomplete", "off" );
|
|
|
|
this._on( this.element, {
|
|
keydown: function( event ) {
|
|
if ( this.element.prop( "readOnly" ) ) {
|
|
suppressKeyPress = true;
|
|
suppressInput = true;
|
|
suppressKeyPressRepeat = true;
|
|
return;
|
|
}
|
|
|
|
suppressKeyPress = false;
|
|
suppressInput = false;
|
|
suppressKeyPressRepeat = false;
|
|
var keyCode = $.ui.keyCode;
|
|
switch ( event.keyCode ) {
|
|
case keyCode.PAGE_UP:
|
|
suppressKeyPress = true;
|
|
this._move( "previousPage", event );
|
|
break;
|
|
case keyCode.PAGE_DOWN:
|
|
suppressKeyPress = true;
|
|
this._move( "nextPage", event );
|
|
break;
|
|
case keyCode.UP:
|
|
suppressKeyPress = true;
|
|
this._keyEvent( "previous", event );
|
|
break;
|
|
case keyCode.DOWN:
|
|
suppressKeyPress = true;
|
|
this._keyEvent( "next", event );
|
|
break;
|
|
case keyCode.ENTER:
|
|
|
|
// when menu is open and has focus
|
|
if ( this.menu.active ) {
|
|
|
|
// #6055 - Opera still allows the keypress to occur
|
|
// which causes forms to submit
|
|
suppressKeyPress = true;
|
|
event.preventDefault();
|
|
this.menu.select( event );
|
|
}
|
|
break;
|
|
case keyCode.TAB:
|
|
if ( this.menu.active ) {
|
|
this.menu.select( event );
|
|
}
|
|
break;
|
|
case keyCode.ESCAPE:
|
|
if ( this.menu.element.is( ":visible" ) ) {
|
|
if ( !this.isMultiLine ) {
|
|
this._value( this.term );
|
|
}
|
|
this.close( event );
|
|
|
|
// Different browsers have different default behavior for escape
|
|
// Single press can mean undo or clear
|
|
// Double press in IE means clear the whole form
|
|
event.preventDefault();
|
|
}
|
|
break;
|
|
default:
|
|
suppressKeyPressRepeat = true;
|
|
|
|
// search timeout should be triggered before the input value is changed
|
|
this._searchTimeout( event );
|
|
break;
|
|
}
|
|
},
|
|
keypress: function( event ) {
|
|
if ( suppressKeyPress ) {
|
|
suppressKeyPress = false;
|
|
if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
|
|
event.preventDefault();
|
|
}
|
|
return;
|
|
}
|
|
if ( suppressKeyPressRepeat ) {
|
|
return;
|
|
}
|
|
|
|
// Replicate some key handlers to allow them to repeat in Firefox and Opera
|
|
var keyCode = $.ui.keyCode;
|
|
switch ( event.keyCode ) {
|
|
case keyCode.PAGE_UP:
|
|
this._move( "previousPage", event );
|
|
break;
|
|
case keyCode.PAGE_DOWN:
|
|
this._move( "nextPage", event );
|
|
break;
|
|
case keyCode.UP:
|
|
this._keyEvent( "previous", event );
|
|
break;
|
|
case keyCode.DOWN:
|
|
this._keyEvent( "next", event );
|
|
break;
|
|
}
|
|
},
|
|
input: function( event ) {
|
|
if ( suppressInput ) {
|
|
suppressInput = false;
|
|
event.preventDefault();
|
|
return;
|
|
}
|
|
this._searchTimeout( event );
|
|
},
|
|
focus: function() {
|
|
this.selectedItem = null;
|
|
this.previous = this._value();
|
|
},
|
|
blur: function( event ) {
|
|
if ( this.cancelBlur ) {
|
|
delete this.cancelBlur;
|
|
return;
|
|
}
|
|
|
|
clearTimeout( this.searching );
|
|
this.close( event );
|
|
this._change( event );
|
|
}
|
|
} );
|
|
|
|
this._initSource();
|
|
this.menu = $( "<ul>" )
|
|
.appendTo( this._appendTo() )
|
|
.menu( {
|
|
|
|
// disable ARIA support, the live region takes care of that
|
|
role: null
|
|
} )
|
|
.hide()
|
|
.menu( "instance" );
|
|
|
|
this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
|
|
this._on( this.menu.element, {
|
|
mousedown: function( event ) {
|
|
|
|
// prevent moving focus out of the text field
|
|
event.preventDefault();
|
|
|
|
// IE doesn't prevent moving focus even with event.preventDefault()
|
|
// so we set a flag to know when we should ignore the blur event
|
|
this.cancelBlur = true;
|
|
this._delay( function() {
|
|
delete this.cancelBlur;
|
|
|
|
// Support: IE 8 only
|
|
// Right clicking a menu item or selecting text from the menu items will
|
|
// result in focus moving out of the input. However, we've already received
|
|
// and ignored the blur event because of the cancelBlur flag set above. So
|
|
// we restore focus to ensure that the menu closes properly based on the user's
|
|
// next actions.
|
|
if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
|
|
this.element.trigger( "focus" );
|
|
}
|
|
} );
|
|
},
|
|
menufocus: function( event, ui ) {
|
|
var label, item;
|
|
|
|
// support: Firefox
|
|
// Prevent accidental activation of menu items in Firefox (#7024 #9118)
|
|
if ( this.isNewMenu ) {
|
|
this.isNewMenu = false;
|
|
if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
|
|
this.menu.blur();
|
|
|
|
this.document.one( "mousemove", function() {
|
|
$( event.target ).trigger( event.originalEvent );
|
|
} );
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
item = ui.item.data( "ui-autocomplete-item" );
|
|
if ( false !== this._trigger( "focus", event, { item: item } ) ) {
|
|
|
|
// use value to match what will end up in the input, if it was a key event
|
|
if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
|
|
this._value( item.value );
|
|
}
|
|
}
|
|
|
|
// Announce the value in the liveRegion
|
|
label = ui.item.attr( "aria-label" ) || item.value;
|
|
if ( label && $.trim( label ).length ) {
|
|
this.liveRegion.children().hide();
|
|
$( "<div>" ).text( label ).appendTo( this.liveRegion );
|
|
}
|
|
},
|
|
menuselect: function( event, ui ) {
|
|
var item = ui.item.data( "ui-autocomplete-item" ),
|
|
previous = this.previous;
|
|
|
|
// Only trigger when focus was lost (click on menu)
|
|
if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
|
|
this.element.trigger( "focus" );
|
|
this.previous = previous;
|
|
|
|
// #6109 - IE triggers two focus events and the second
|
|
// is asynchronous, so we need to reset the previous
|
|
// term synchronously and asynchronously :-(
|
|
this._delay( function() {
|
|
this.previous = previous;
|
|
this.selectedItem = item;
|
|
} );
|
|
}
|
|
|
|
if ( false !== this._trigger( "select", event, { item: item } ) ) {
|
|
this._value( item.value );
|
|
}
|
|
|
|
// reset the term after the select event
|
|
// this allows custom select handling to work properly
|
|
this.term = this._value();
|
|
|
|
this.close( event );
|
|
this.selectedItem = item;
|
|
}
|
|
} );
|
|
|
|
this.liveRegion = $( "<div>", {
|
|
role: "status",
|
|
"aria-live": "assertive",
|
|
"aria-relevant": "additions"
|
|
} )
|
|
.appendTo( this.document[ 0 ].body );
|
|
|
|
this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
|
|
|
|
// Turning off autocomplete prevents the browser from remembering the
|
|
// value when navigating through history, so we re-enable autocomplete
|
|
// if the page is unloaded before the widget is destroyed. #7790
|
|
this._on( this.window, {
|
|
beforeunload: function() {
|
|
this.element.removeAttr( "autocomplete" );
|
|
}
|
|
} );
|
|
},
|
|
|
|
_destroy: function() {
|
|
clearTimeout( this.searching );
|
|
this.element.removeAttr( "autocomplete" );
|
|
this.menu.element.remove();
|
|
this.liveRegion.remove();
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
this._super( key, value );
|
|
if ( key === "source" ) {
|
|
this._initSource();
|
|
}
|
|
if ( key === "appendTo" ) {
|
|
this.menu.element.appendTo( this._appendTo() );
|
|
}
|
|
if ( key === "disabled" && value && this.xhr ) {
|
|
this.xhr.abort();
|
|
}
|
|
},
|
|
|
|
_isEventTargetInWidget: function( event ) {
|
|
var menuElement = this.menu.element[ 0 ];
|
|
|
|
return event.target === this.element[ 0 ] ||
|
|
event.target === menuElement ||
|
|
$.contains( menuElement, event.target );
|
|
},
|
|
|
|
_closeOnClickOutside: function( event ) {
|
|
if ( !this._isEventTargetInWidget( event ) ) {
|
|
this.close();
|
|
}
|
|
},
|
|
|
|
_appendTo: function() {
|
|
var element = this.options.appendTo;
|
|
|
|
if ( element ) {
|
|
element = element.jquery || element.nodeType ?
|
|
$( element ) :
|
|
this.document.find( element ).eq( 0 );
|
|
}
|
|
|
|
if ( !element || !element[ 0 ] ) {
|
|
element = this.element.closest( ".ui-front, dialog" );
|
|
}
|
|
|
|
if ( !element.length ) {
|
|
element = this.document[ 0 ].body;
|
|
}
|
|
|
|
return element;
|
|
},
|
|
|
|
_initSource: function() {
|
|
var array, url,
|
|
that = this;
|
|
if ( $.isArray( this.options.source ) ) {
|
|
array = this.options.source;
|
|
this.source = function( request, response ) {
|
|
response( $.ui.autocomplete.filter( array, request.term ) );
|
|
};
|
|
} else if ( typeof this.options.source === "string" ) {
|
|
url = this.options.source;
|
|
this.source = function( request, response ) {
|
|
if ( that.xhr ) {
|
|
that.xhr.abort();
|
|
}
|
|
that.xhr = $.ajax( {
|
|
url: url,
|
|
data: request,
|
|
dataType: "json",
|
|
success: function( data ) {
|
|
response( data );
|
|
},
|
|
error: function() {
|
|
response( [] );
|
|
}
|
|
} );
|
|
};
|
|
} else {
|
|
this.source = this.options.source;
|
|
}
|
|
},
|
|
|
|
_searchTimeout: function( event ) {
|
|
clearTimeout( this.searching );
|
|
this.searching = this._delay( function() {
|
|
|
|
// Search if the value has changed, or if the user retypes the same value (see #7434)
|
|
var equalValues = this.term === this._value(),
|
|
menuVisible = this.menu.element.is( ":visible" ),
|
|
modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
|
|
|
|
if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
|
|
this.selectedItem = null;
|
|
this.search( null, event );
|
|
}
|
|
}, this.options.delay );
|
|
},
|
|
|
|
search: function( value, event ) {
|
|
value = value != null ? value : this._value();
|
|
|
|
// Always save the actual value, not the one passed as an argument
|
|
this.term = this._value();
|
|
|
|
if ( value.length < this.options.minLength ) {
|
|
return this.close( event );
|
|
}
|
|
|
|
if ( this._trigger( "search", event ) === false ) {
|
|
return;
|
|
}
|
|
|
|
return this._search( value );
|
|
},
|
|
|
|
_search: function( value ) {
|
|
this.pending++;
|
|
this._addClass( "ui-autocomplete-loading" );
|
|
this.cancelSearch = false;
|
|
|
|
this.source( { term: value }, this._response() );
|
|
},
|
|
|
|
_response: function() {
|
|
var index = ++this.requestIndex;
|
|
|
|
return $.proxy( function( content ) {
|
|
if ( index === this.requestIndex ) {
|
|
this.__response( content );
|
|
}
|
|
|
|
this.pending--;
|
|
if ( !this.pending ) {
|
|
this._removeClass( "ui-autocomplete-loading" );
|
|
}
|
|
}, this );
|
|
},
|
|
|
|
__response: function( content ) {
|
|
if ( content ) {
|
|
content = this._normalize( content );
|
|
}
|
|
this._trigger( "response", null, { content: content } );
|
|
if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
|
|
this._suggest( content );
|
|
this._trigger( "open" );
|
|
} else {
|
|
|
|
// use ._close() instead of .close() so we don't cancel future searches
|
|
this._close();
|
|
}
|
|
},
|
|
|
|
close: function( event ) {
|
|
this.cancelSearch = true;
|
|
this._close( event );
|
|
},
|
|
|
|
_close: function( event ) {
|
|
|
|
// Remove the handler that closes the menu on outside clicks
|
|
this._off( this.document, "mousedown" );
|
|
|
|
if ( this.menu.element.is( ":visible" ) ) {
|
|
this.menu.element.hide();
|
|
this.menu.blur();
|
|
this.isNewMenu = true;
|
|
this._trigger( "close", event );
|
|
}
|
|
},
|
|
|
|
_change: function( event ) {
|
|
if ( this.previous !== this._value() ) {
|
|
this._trigger( "change", event, { item: this.selectedItem } );
|
|
}
|
|
},
|
|
|
|
_normalize: function( items ) {
|
|
|
|
// assume all items have the right format when the first item is complete
|
|
if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
|
|
return items;
|
|
}
|
|
return $.map( items, function( item ) {
|
|
if ( typeof item === "string" ) {
|
|
return {
|
|
label: item,
|
|
value: item
|
|
};
|
|
}
|
|
return $.extend( {}, item, {
|
|
label: item.label || item.value,
|
|
value: item.value || item.label
|
|
} );
|
|
} );
|
|
},
|
|
|
|
_suggest: function( items ) {
|
|
var ul = this.menu.element.empty();
|
|
this._renderMenu( ul, items );
|
|
this.isNewMenu = true;
|
|
this.menu.refresh();
|
|
|
|
// Size and position menu
|
|
ul.show();
|
|
this._resizeMenu();
|
|
ul.position( $.extend( {
|
|
of: this.element
|
|
}, this.options.position ) );
|
|
|
|
if ( this.options.autoFocus ) {
|
|
this.menu.next();
|
|
}
|
|
|
|
// Listen for interactions outside of the widget (#6642)
|
|
this._on( this.document, {
|
|
mousedown: "_closeOnClickOutside"
|
|
} );
|
|
},
|
|
|
|
_resizeMenu: function() {
|
|
var ul = this.menu.element;
|
|
ul.outerWidth( Math.max(
|
|
|
|
// Firefox wraps long text (possibly a rounding bug)
|
|
// so we add 1px to avoid the wrapping (#7513)
|
|
ul.width( "" ).outerWidth() + 1,
|
|
this.element.outerWidth()
|
|
) );
|
|
},
|
|
|
|
_renderMenu: function( ul, items ) {
|
|
var that = this;
|
|
$.each( items, function( index, item ) {
|
|
that._renderItemData( ul, item );
|
|
} );
|
|
},
|
|
|
|
_renderItemData: function( ul, item ) {
|
|
return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
|
|
},
|
|
|
|
_renderItem: function( ul, item ) {
|
|
return $( "<li>" )
|
|
.append( $( "<div>" ).text( item.label ) )
|
|
.appendTo( ul );
|
|
},
|
|
|
|
_move: function( direction, event ) {
|
|
if ( !this.menu.element.is( ":visible" ) ) {
|
|
this.search( null, event );
|
|
return;
|
|
}
|
|
if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
|
|
this.menu.isLastItem() && /^next/.test( direction ) ) {
|
|
|
|
if ( !this.isMultiLine ) {
|
|
this._value( this.term );
|
|
}
|
|
|
|
this.menu.blur();
|
|
return;
|
|
}
|
|
this.menu[ direction ]( event );
|
|
},
|
|
|
|
widget: function() {
|
|
return this.menu.element;
|
|
},
|
|
|
|
_value: function() {
|
|
return this.valueMethod.apply( this.element, arguments );
|
|
},
|
|
|
|
_keyEvent: function( keyEvent, event ) {
|
|
if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
|
|
this._move( keyEvent, event );
|
|
|
|
// Prevents moving cursor to beginning/end of the text field in some browsers
|
|
event.preventDefault();
|
|
}
|
|
},
|
|
|
|
// Support: Chrome <=50
|
|
// We should be able to just use this.element.prop( "isContentEditable" )
|
|
// but hidden elements always report false in Chrome.
|
|
// https://code.google.com/p/chromium/issues/detail?id=313082
|
|
_isContentEditable: function( element ) {
|
|
if ( !element.length ) {
|
|
return false;
|
|
}
|
|
|
|
var editable = element.prop( "contentEditable" );
|
|
|
|
if ( editable === "inherit" ) {
|
|
return this._isContentEditable( element.parent() );
|
|
}
|
|
|
|
return editable === "true";
|
|
}
|
|
} );
|
|
|
|
$.extend( $.ui.autocomplete, {
|
|
escapeRegex: function( value ) {
|
|
return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
|
|
},
|
|
filter: function( array, term ) {
|
|
var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
|
|
return $.grep( array, function( value ) {
|
|
return matcher.test( value.label || value.value || value );
|
|
} );
|
|
}
|
|
} );
|
|
|
|
// Live region extension, adding a `messages` option
|
|
// NOTE: This is an experimental API. We are still investigating
|
|
// a full solution for string manipulation and internationalization.
|
|
$.widget( "ui.autocomplete", $.ui.autocomplete, {
|
|
options: {
|
|
messages: {
|
|
noResults: "No search results.",
|
|
results: function( amount ) {
|
|
return amount + ( amount > 1 ? " results are" : " result is" ) +
|
|
" available, use up and down arrow keys to navigate.";
|
|
}
|
|
}
|
|
},
|
|
|
|
__response: function( content ) {
|
|
var message;
|
|
this._superApply( arguments );
|
|
if ( this.options.disabled || this.cancelSearch ) {
|
|
return;
|
|
}
|
|
if ( content && content.length ) {
|
|
message = this.options.messages.results( content.length );
|
|
} else {
|
|
message = this.options.messages.noResults;
|
|
}
|
|
this.liveRegion.children().hide();
|
|
$( "<div>" ).text( message ).appendTo( this.liveRegion );
|
|
}
|
|
} );
|
|
|
|
return $.ui.autocomplete;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 52 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Controlgroup 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Controlgroup
|
|
//>>group: Widgets
|
|
//>>description: Visually groups form control widgets
|
|
//>>docs: http://api.jqueryui.com/controlgroup/
|
|
//>>demos: http://jqueryui.com/controlgroup/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/controlgroup.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
|
|
|
|
return $.widget( "ui.controlgroup", {
|
|
version: "1.12.1",
|
|
defaultElement: "<div>",
|
|
options: {
|
|
direction: "horizontal",
|
|
disabled: null,
|
|
onlyVisible: true,
|
|
items: {
|
|
"button": "input[type=button], input[type=submit], input[type=reset], button, a",
|
|
"controlgroupLabel": ".ui-controlgroup-label",
|
|
"checkboxradio": "input[type='checkbox'], input[type='radio']",
|
|
"selectmenu": "select",
|
|
"spinner": ".ui-spinner-input"
|
|
}
|
|
},
|
|
|
|
_create: function() {
|
|
this._enhance();
|
|
},
|
|
|
|
// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
|
|
_enhance: function() {
|
|
this.element.attr( "role", "toolbar" );
|
|
this.refresh();
|
|
},
|
|
|
|
_destroy: function() {
|
|
this._callChildMethod( "destroy" );
|
|
this.childWidgets.removeData( "ui-controlgroup-data" );
|
|
this.element.removeAttr( "role" );
|
|
if ( this.options.items.controlgroupLabel ) {
|
|
this.element
|
|
.find( this.options.items.controlgroupLabel )
|
|
.find( ".ui-controlgroup-label-contents" )
|
|
.contents().unwrap();
|
|
}
|
|
},
|
|
|
|
_initWidgets: function() {
|
|
var that = this,
|
|
childWidgets = [];
|
|
|
|
// First we iterate over each of the items options
|
|
$.each( this.options.items, function( widget, selector ) {
|
|
var labels;
|
|
var options = {};
|
|
|
|
// Make sure the widget has a selector set
|
|
if ( !selector ) {
|
|
return;
|
|
}
|
|
|
|
if ( widget === "controlgroupLabel" ) {
|
|
labels = that.element.find( selector );
|
|
labels.each( function() {
|
|
var element = $( this );
|
|
|
|
if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
|
|
return;
|
|
}
|
|
element.contents()
|
|
.wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
|
|
} );
|
|
that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
|
|
childWidgets = childWidgets.concat( labels.get() );
|
|
return;
|
|
}
|
|
|
|
// Make sure the widget actually exists
|
|
if ( !$.fn[ widget ] ) {
|
|
return;
|
|
}
|
|
|
|
// We assume everything is in the middle to start because we can't determine
|
|
// first / last elements until all enhancments are done.
|
|
if ( that[ "_" + widget + "Options" ] ) {
|
|
options = that[ "_" + widget + "Options" ]( "middle" );
|
|
} else {
|
|
options = { classes: {} };
|
|
}
|
|
|
|
// Find instances of this widget inside controlgroup and init them
|
|
that.element
|
|
.find( selector )
|
|
.each( function() {
|
|
var element = $( this );
|
|
var instance = element[ widget ]( "instance" );
|
|
|
|
// We need to clone the default options for this type of widget to avoid
|
|
// polluting the variable options which has a wider scope than a single widget.
|
|
var instanceOptions = $.widget.extend( {}, options );
|
|
|
|
// If the button is the child of a spinner ignore it
|
|
// TODO: Find a more generic solution
|
|
if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
|
|
return;
|
|
}
|
|
|
|
// Create the widget if it doesn't exist
|
|
if ( !instance ) {
|
|
instance = element[ widget ]()[ widget ]( "instance" );
|
|
}
|
|
if ( instance ) {
|
|
instanceOptions.classes =
|
|
that._resolveClassesValues( instanceOptions.classes, instance );
|
|
}
|
|
element[ widget ]( instanceOptions );
|
|
|
|
// Store an instance of the controlgroup to be able to reference
|
|
// from the outermost element for changing options and refresh
|
|
var widgetElement = element[ widget ]( "widget" );
|
|
$.data( widgetElement[ 0 ], "ui-controlgroup-data",
|
|
instance ? instance : element[ widget ]( "instance" ) );
|
|
|
|
childWidgets.push( widgetElement[ 0 ] );
|
|
} );
|
|
} );
|
|
|
|
this.childWidgets = $( $.unique( childWidgets ) );
|
|
this._addClass( this.childWidgets, "ui-controlgroup-item" );
|
|
},
|
|
|
|
_callChildMethod: function( method ) {
|
|
this.childWidgets.each( function() {
|
|
var element = $( this ),
|
|
data = element.data( "ui-controlgroup-data" );
|
|
if ( data && data[ method ] ) {
|
|
data[ method ]();
|
|
}
|
|
} );
|
|
},
|
|
|
|
_updateCornerClass: function( element, position ) {
|
|
var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
|
|
var add = this._buildSimpleOptions( position, "label" ).classes.label;
|
|
|
|
this._removeClass( element, null, remove );
|
|
this._addClass( element, null, add );
|
|
},
|
|
|
|
_buildSimpleOptions: function( position, key ) {
|
|
var direction = this.options.direction === "vertical";
|
|
var result = {
|
|
classes: {}
|
|
};
|
|
result.classes[ key ] = {
|
|
"middle": "",
|
|
"first": "ui-corner-" + ( direction ? "top" : "left" ),
|
|
"last": "ui-corner-" + ( direction ? "bottom" : "right" ),
|
|
"only": "ui-corner-all"
|
|
}[ position ];
|
|
|
|
return result;
|
|
},
|
|
|
|
_spinnerOptions: function( position ) {
|
|
var options = this._buildSimpleOptions( position, "ui-spinner" );
|
|
|
|
options.classes[ "ui-spinner-up" ] = "";
|
|
options.classes[ "ui-spinner-down" ] = "";
|
|
|
|
return options;
|
|
},
|
|
|
|
_buttonOptions: function( position ) {
|
|
return this._buildSimpleOptions( position, "ui-button" );
|
|
},
|
|
|
|
_checkboxradioOptions: function( position ) {
|
|
return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
|
|
},
|
|
|
|
_selectmenuOptions: function( position ) {
|
|
var direction = this.options.direction === "vertical";
|
|
return {
|
|
width: direction ? "auto" : false,
|
|
classes: {
|
|
middle: {
|
|
"ui-selectmenu-button-open": "",
|
|
"ui-selectmenu-button-closed": ""
|
|
},
|
|
first: {
|
|
"ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
|
|
"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
|
|
},
|
|
last: {
|
|
"ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
|
|
"ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
|
|
},
|
|
only: {
|
|
"ui-selectmenu-button-open": "ui-corner-top",
|
|
"ui-selectmenu-button-closed": "ui-corner-all"
|
|
}
|
|
|
|
}[ position ]
|
|
};
|
|
},
|
|
|
|
_resolveClassesValues: function( classes, instance ) {
|
|
var result = {};
|
|
$.each( classes, function( key ) {
|
|
var current = instance.options.classes[ key ] || "";
|
|
current = $.trim( current.replace( controlgroupCornerRegex, "" ) );
|
|
result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
|
|
} );
|
|
return result;
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
if ( key === "direction" ) {
|
|
this._removeClass( "ui-controlgroup-" + this.options.direction );
|
|
}
|
|
|
|
this._super( key, value );
|
|
if ( key === "disabled" ) {
|
|
this._callChildMethod( value ? "disable" : "enable" );
|
|
return;
|
|
}
|
|
|
|
this.refresh();
|
|
},
|
|
|
|
refresh: function() {
|
|
var children,
|
|
that = this;
|
|
|
|
this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
|
|
|
|
if ( this.options.direction === "horizontal" ) {
|
|
this._addClass( null, "ui-helper-clearfix" );
|
|
}
|
|
this._initWidgets();
|
|
|
|
children = this.childWidgets;
|
|
|
|
// We filter here because we need to track all childWidgets not just the visible ones
|
|
if ( this.options.onlyVisible ) {
|
|
children = children.filter( ":visible" );
|
|
}
|
|
|
|
if ( children.length ) {
|
|
|
|
// We do this last because we need to make sure all enhancment is done
|
|
// before determining first and last
|
|
$.each( [ "first", "last" ], function( index, value ) {
|
|
var instance = children[ value ]().data( "ui-controlgroup-data" );
|
|
|
|
if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
|
|
var options = that[ "_" + instance.widgetName + "Options" ](
|
|
children.length === 1 ? "only" : value
|
|
);
|
|
options.classes = that._resolveClassesValues( options.classes, instance );
|
|
instance.element[ instance.widgetName ]( options );
|
|
} else {
|
|
that._updateCornerClass( children[ value ](), value );
|
|
}
|
|
} );
|
|
|
|
// Finally call the refresh method on each of the child widgets.
|
|
this._callChildMethod( "refresh" );
|
|
}
|
|
}
|
|
} );
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 53 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Checkboxradio 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Checkboxradio
|
|
//>>group: Widgets
|
|
//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
|
|
//>>docs: http://api.jqueryui.com/checkboxradio/
|
|
//>>demos: http://jqueryui.com/checkboxradio/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/button.css
|
|
//>>css.structure: ../../themes/base/checkboxradio.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(45),
|
|
__webpack_require__(54),
|
|
__webpack_require__(44),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
|
|
version: "1.12.1",
|
|
options: {
|
|
disabled: null,
|
|
label: null,
|
|
icon: true,
|
|
classes: {
|
|
"ui-checkboxradio-label": "ui-corner-all",
|
|
"ui-checkboxradio-icon": "ui-corner-all"
|
|
}
|
|
},
|
|
|
|
_getCreateOptions: function() {
|
|
var disabled, labels;
|
|
var that = this;
|
|
var options = this._super() || {};
|
|
|
|
// We read the type here, because it makes more sense to throw a element type error first,
|
|
// rather then the error for lack of a label. Often if its the wrong type, it
|
|
// won't have a label (e.g. calling on a div, btn, etc)
|
|
this._readType();
|
|
|
|
labels = this.element.labels();
|
|
|
|
// If there are multiple labels, use the last one
|
|
this.label = $( labels[ labels.length - 1 ] );
|
|
if ( !this.label.length ) {
|
|
$.error( "No label found for checkboxradio widget" );
|
|
}
|
|
|
|
this.originalLabel = "";
|
|
|
|
// We need to get the label text but this may also need to make sure it does not contain the
|
|
// input itself.
|
|
this.label.contents().not( this.element[ 0 ] ).each( function() {
|
|
|
|
// The label contents could be text, html, or a mix. We concat each element to get a
|
|
// string representation of the label, without the input as part of it.
|
|
that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML;
|
|
} );
|
|
|
|
// Set the label option if we found label text
|
|
if ( this.originalLabel ) {
|
|
options.label = this.originalLabel;
|
|
}
|
|
|
|
disabled = this.element[ 0 ].disabled;
|
|
if ( disabled != null ) {
|
|
options.disabled = disabled;
|
|
}
|
|
return options;
|
|
},
|
|
|
|
_create: function() {
|
|
var checked = this.element[ 0 ].checked;
|
|
|
|
this._bindFormResetHandler();
|
|
|
|
if ( this.options.disabled == null ) {
|
|
this.options.disabled = this.element[ 0 ].disabled;
|
|
}
|
|
|
|
this._setOption( "disabled", this.options.disabled );
|
|
this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
|
|
this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
|
|
|
|
if ( this.type === "radio" ) {
|
|
this._addClass( this.label, "ui-checkboxradio-radio-label" );
|
|
}
|
|
|
|
if ( this.options.label && this.options.label !== this.originalLabel ) {
|
|
this._updateLabel();
|
|
} else if ( this.originalLabel ) {
|
|
this.options.label = this.originalLabel;
|
|
}
|
|
|
|
this._enhance();
|
|
|
|
if ( checked ) {
|
|
this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
|
|
if ( this.icon ) {
|
|
this._addClass( this.icon, null, "ui-state-hover" );
|
|
}
|
|
}
|
|
|
|
this._on( {
|
|
change: "_toggleClasses",
|
|
focus: function() {
|
|
this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
|
|
},
|
|
blur: function() {
|
|
this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
|
|
}
|
|
} );
|
|
},
|
|
|
|
_readType: function() {
|
|
var nodeName = this.element[ 0 ].nodeName.toLowerCase();
|
|
this.type = this.element[ 0 ].type;
|
|
if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
|
|
$.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
|
|
" and element.type=" + this.type );
|
|
}
|
|
},
|
|
|
|
// Support jQuery Mobile enhanced option
|
|
_enhance: function() {
|
|
this._updateIcon( this.element[ 0 ].checked );
|
|
},
|
|
|
|
widget: function() {
|
|
return this.label;
|
|
},
|
|
|
|
_getRadioGroup: function() {
|
|
var group;
|
|
var name = this.element[ 0 ].name;
|
|
var nameSelector = "input[name='" + $.ui.escapeSelector( name ) + "']";
|
|
|
|
if ( !name ) {
|
|
return $( [] );
|
|
}
|
|
|
|
if ( this.form.length ) {
|
|
group = $( this.form[ 0 ].elements ).filter( nameSelector );
|
|
} else {
|
|
|
|
// Not inside a form, check all inputs that also are not inside a form
|
|
group = $( nameSelector ).filter( function() {
|
|
return $( this ).form().length === 0;
|
|
} );
|
|
}
|
|
|
|
return group.not( this.element );
|
|
},
|
|
|
|
_toggleClasses: function() {
|
|
var checked = this.element[ 0 ].checked;
|
|
this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
|
|
|
|
if ( this.options.icon && this.type === "checkbox" ) {
|
|
this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
|
|
._toggleClass( this.icon, null, "ui-icon-blank", !checked );
|
|
}
|
|
|
|
if ( this.type === "radio" ) {
|
|
this._getRadioGroup()
|
|
.each( function() {
|
|
var instance = $( this ).checkboxradio( "instance" );
|
|
|
|
if ( instance ) {
|
|
instance._removeClass( instance.label,
|
|
"ui-checkboxradio-checked", "ui-state-active" );
|
|
}
|
|
} );
|
|
}
|
|
},
|
|
|
|
_destroy: function() {
|
|
this._unbindFormResetHandler();
|
|
|
|
if ( this.icon ) {
|
|
this.icon.remove();
|
|
this.iconSpace.remove();
|
|
}
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
|
|
// We don't allow the value to be set to nothing
|
|
if ( key === "label" && !value ) {
|
|
return;
|
|
}
|
|
|
|
this._super( key, value );
|
|
|
|
if ( key === "disabled" ) {
|
|
this._toggleClass( this.label, null, "ui-state-disabled", value );
|
|
this.element[ 0 ].disabled = value;
|
|
|
|
// Don't refresh when setting disabled
|
|
return;
|
|
}
|
|
this.refresh();
|
|
},
|
|
|
|
_updateIcon: function( checked ) {
|
|
var toAdd = "ui-icon ui-icon-background ";
|
|
|
|
if ( this.options.icon ) {
|
|
if ( !this.icon ) {
|
|
this.icon = $( "<span>" );
|
|
this.iconSpace = $( "<span> </span>" );
|
|
this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
|
|
}
|
|
|
|
if ( this.type === "checkbox" ) {
|
|
toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
|
|
this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
|
|
} else {
|
|
toAdd += "ui-icon-blank";
|
|
}
|
|
this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
|
|
if ( !checked ) {
|
|
this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
|
|
}
|
|
this.icon.prependTo( this.label ).after( this.iconSpace );
|
|
} else if ( this.icon !== undefined ) {
|
|
this.icon.remove();
|
|
this.iconSpace.remove();
|
|
delete this.icon;
|
|
}
|
|
},
|
|
|
|
_updateLabel: function() {
|
|
|
|
// Remove the contents of the label ( minus the icon, icon space, and input )
|
|
var contents = this.label.contents().not( this.element[ 0 ] );
|
|
if ( this.icon ) {
|
|
contents = contents.not( this.icon[ 0 ] );
|
|
}
|
|
if ( this.iconSpace ) {
|
|
contents = contents.not( this.iconSpace[ 0 ] );
|
|
}
|
|
contents.remove();
|
|
|
|
this.label.append( this.options.label );
|
|
},
|
|
|
|
refresh: function() {
|
|
var checked = this.element[ 0 ].checked,
|
|
isDisabled = this.element[ 0 ].disabled;
|
|
|
|
this._updateIcon( checked );
|
|
this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
|
|
if ( this.options.label !== null ) {
|
|
this._updateLabel();
|
|
}
|
|
|
|
if ( isDisabled !== this.options.disabled ) {
|
|
this._setOptions( { "disabled": isDisabled } );
|
|
}
|
|
}
|
|
|
|
} ] );
|
|
|
|
return $.ui.checkboxradio;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 54 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Form Reset Mixin 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Form Reset Mixin
|
|
//>>group: Core
|
|
//>>description: Refresh input widgets when their form is reset
|
|
//>>docs: http://api.jqueryui.com/form-reset-mixin/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(41),
|
|
__webpack_require__(15)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.ui.formResetMixin = {
|
|
_formResetHandler: function() {
|
|
var form = $( this );
|
|
|
|
// Wait for the form reset to actually happen before refreshing
|
|
setTimeout( function() {
|
|
var instances = form.data( "ui-form-reset-instances" );
|
|
$.each( instances, function() {
|
|
this.refresh();
|
|
} );
|
|
} );
|
|
},
|
|
|
|
_bindFormResetHandler: function() {
|
|
this.form = this.element.form();
|
|
if ( !this.form.length ) {
|
|
return;
|
|
}
|
|
|
|
var instances = this.form.data( "ui-form-reset-instances" ) || [];
|
|
if ( !instances.length ) {
|
|
|
|
// We don't use _on() here because we use a single event handler per form
|
|
this.form.on( "reset.ui-form-reset", this._formResetHandler );
|
|
}
|
|
instances.push( this );
|
|
this.form.data( "ui-form-reset-instances", instances );
|
|
},
|
|
|
|
_unbindFormResetHandler: function() {
|
|
if ( !this.form.length ) {
|
|
return;
|
|
}
|
|
|
|
var instances = this.form.data( "ui-form-reset-instances" );
|
|
instances.splice( $.inArray( this, instances ), 1 );
|
|
if ( instances.length ) {
|
|
this.form.data( "ui-form-reset-instances", instances );
|
|
} else {
|
|
this.form
|
|
.removeData( "ui-form-reset-instances" )
|
|
.off( "reset.ui-form-reset" );
|
|
}
|
|
}
|
|
};
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 55 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Button 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Button
|
|
//>>group: Widgets
|
|
//>>description: Enhances a form with themeable buttons.
|
|
//>>docs: http://api.jqueryui.com/button/
|
|
//>>demos: http://jqueryui.com/button/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/button.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
|
|
// These are only for backcompat
|
|
// TODO: Remove after 1.12
|
|
__webpack_require__(52),
|
|
__webpack_require__(53),
|
|
|
|
__webpack_require__(43),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
$.widget( "ui.button", {
|
|
version: "1.12.1",
|
|
defaultElement: "<button>",
|
|
options: {
|
|
classes: {
|
|
"ui-button": "ui-corner-all"
|
|
},
|
|
disabled: null,
|
|
icon: null,
|
|
iconPosition: "beginning",
|
|
label: null,
|
|
showLabel: true
|
|
},
|
|
|
|
_getCreateOptions: function() {
|
|
var disabled,
|
|
|
|
// This is to support cases like in jQuery Mobile where the base widget does have
|
|
// an implementation of _getCreateOptions
|
|
options = this._super() || {};
|
|
|
|
this.isInput = this.element.is( "input" );
|
|
|
|
disabled = this.element[ 0 ].disabled;
|
|
if ( disabled != null ) {
|
|
options.disabled = disabled;
|
|
}
|
|
|
|
this.originalLabel = this.isInput ? this.element.val() : this.element.html();
|
|
if ( this.originalLabel ) {
|
|
options.label = this.originalLabel;
|
|
}
|
|
|
|
return options;
|
|
},
|
|
|
|
_create: function() {
|
|
if ( !this.option.showLabel & !this.options.icon ) {
|
|
this.options.showLabel = true;
|
|
}
|
|
|
|
// We have to check the option again here even though we did in _getCreateOptions,
|
|
// because null may have been passed on init which would override what was set in
|
|
// _getCreateOptions
|
|
if ( this.options.disabled == null ) {
|
|
this.options.disabled = this.element[ 0 ].disabled || false;
|
|
}
|
|
|
|
this.hasTitle = !!this.element.attr( "title" );
|
|
|
|
// Check to see if the label needs to be set or if its already correct
|
|
if ( this.options.label && this.options.label !== this.originalLabel ) {
|
|
if ( this.isInput ) {
|
|
this.element.val( this.options.label );
|
|
} else {
|
|
this.element.html( this.options.label );
|
|
}
|
|
}
|
|
this._addClass( "ui-button", "ui-widget" );
|
|
this._setOption( "disabled", this.options.disabled );
|
|
this._enhance();
|
|
|
|
if ( this.element.is( "a" ) ) {
|
|
this._on( {
|
|
"keyup": function( event ) {
|
|
if ( event.keyCode === $.ui.keyCode.SPACE ) {
|
|
event.preventDefault();
|
|
|
|
// Support: PhantomJS <= 1.9, IE 8 Only
|
|
// If a native click is available use it so we actually cause navigation
|
|
// otherwise just trigger a click event
|
|
if ( this.element[ 0 ].click ) {
|
|
this.element[ 0 ].click();
|
|
} else {
|
|
this.element.trigger( "click" );
|
|
}
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
},
|
|
|
|
_enhance: function() {
|
|
if ( !this.element.is( "button" ) ) {
|
|
this.element.attr( "role", "button" );
|
|
}
|
|
|
|
if ( this.options.icon ) {
|
|
this._updateIcon( "icon", this.options.icon );
|
|
this._updateTooltip();
|
|
}
|
|
},
|
|
|
|
_updateTooltip: function() {
|
|
this.title = this.element.attr( "title" );
|
|
|
|
if ( !this.options.showLabel && !this.title ) {
|
|
this.element.attr( "title", this.options.label );
|
|
}
|
|
},
|
|
|
|
_updateIcon: function( option, value ) {
|
|
var icon = option !== "iconPosition",
|
|
position = icon ? this.options.iconPosition : value,
|
|
displayBlock = position === "top" || position === "bottom";
|
|
|
|
// Create icon
|
|
if ( !this.icon ) {
|
|
this.icon = $( "<span>" );
|
|
|
|
this._addClass( this.icon, "ui-button-icon", "ui-icon" );
|
|
|
|
if ( !this.options.showLabel ) {
|
|
this._addClass( "ui-button-icon-only" );
|
|
}
|
|
} else if ( icon ) {
|
|
|
|
// If we are updating the icon remove the old icon class
|
|
this._removeClass( this.icon, null, this.options.icon );
|
|
}
|
|
|
|
// If we are updating the icon add the new icon class
|
|
if ( icon ) {
|
|
this._addClass( this.icon, null, value );
|
|
}
|
|
|
|
this._attachIcon( position );
|
|
|
|
// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
|
|
// the iconSpace if there is one.
|
|
if ( displayBlock ) {
|
|
this._addClass( this.icon, null, "ui-widget-icon-block" );
|
|
if ( this.iconSpace ) {
|
|
this.iconSpace.remove();
|
|
}
|
|
} else {
|
|
|
|
// Position is beginning or end so remove the ui-widget-icon-block class and add the
|
|
// space if it does not exist
|
|
if ( !this.iconSpace ) {
|
|
this.iconSpace = $( "<span> </span>" );
|
|
this._addClass( this.iconSpace, "ui-button-icon-space" );
|
|
}
|
|
this._removeClass( this.icon, null, "ui-wiget-icon-block" );
|
|
this._attachIconSpace( position );
|
|
}
|
|
},
|
|
|
|
_destroy: function() {
|
|
this.element.removeAttr( "role" );
|
|
|
|
if ( this.icon ) {
|
|
this.icon.remove();
|
|
}
|
|
if ( this.iconSpace ) {
|
|
this.iconSpace.remove();
|
|
}
|
|
if ( !this.hasTitle ) {
|
|
this.element.removeAttr( "title" );
|
|
}
|
|
},
|
|
|
|
_attachIconSpace: function( iconPosition ) {
|
|
this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
|
|
},
|
|
|
|
_attachIcon: function( iconPosition ) {
|
|
this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
|
|
},
|
|
|
|
_setOptions: function( options ) {
|
|
var newShowLabel = options.showLabel === undefined ?
|
|
this.options.showLabel :
|
|
options.showLabel,
|
|
newIcon = options.icon === undefined ? this.options.icon : options.icon;
|
|
|
|
if ( !newShowLabel && !newIcon ) {
|
|
options.showLabel = true;
|
|
}
|
|
this._super( options );
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
if ( key === "icon" ) {
|
|
if ( value ) {
|
|
this._updateIcon( key, value );
|
|
} else if ( this.icon ) {
|
|
this.icon.remove();
|
|
if ( this.iconSpace ) {
|
|
this.iconSpace.remove();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( key === "iconPosition" ) {
|
|
this._updateIcon( key, value );
|
|
}
|
|
|
|
// Make sure we can't end up with a button that has neither text nor icon
|
|
if ( key === "showLabel" ) {
|
|
this._toggleClass( "ui-button-icon-only", null, !value );
|
|
this._updateTooltip();
|
|
}
|
|
|
|
if ( key === "label" ) {
|
|
if ( this.isInput ) {
|
|
this.element.val( value );
|
|
} else {
|
|
|
|
// If there is an icon, append it, else nothing then append the value
|
|
// this avoids removal of the icon when setting label text
|
|
this.element.html( value );
|
|
if ( this.icon ) {
|
|
this._attachIcon( this.options.iconPosition );
|
|
this._attachIconSpace( this.options.iconPosition );
|
|
}
|
|
}
|
|
}
|
|
|
|
this._super( key, value );
|
|
|
|
if ( key === "disabled" ) {
|
|
this._toggleClass( null, "ui-state-disabled", value );
|
|
this.element[ 0 ].disabled = value;
|
|
if ( value ) {
|
|
this.element.blur();
|
|
}
|
|
}
|
|
},
|
|
|
|
refresh: function() {
|
|
|
|
// Make sure to only check disabled if its an element that supports this otherwise
|
|
// check for the disabled class to determine state
|
|
var isDisabled = this.element.is( "input, button" ) ?
|
|
this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
|
|
|
|
if ( isDisabled !== this.options.disabled ) {
|
|
this._setOptions( { disabled: isDisabled } );
|
|
}
|
|
|
|
this._updateTooltip();
|
|
}
|
|
} );
|
|
|
|
// DEPRECATED
|
|
if ( $.uiBackCompat !== false ) {
|
|
|
|
// Text and Icons options
|
|
$.widget( "ui.button", $.ui.button, {
|
|
options: {
|
|
text: true,
|
|
icons: {
|
|
primary: null,
|
|
secondary: null
|
|
}
|
|
},
|
|
|
|
_create: function() {
|
|
if ( this.options.showLabel && !this.options.text ) {
|
|
this.options.showLabel = this.options.text;
|
|
}
|
|
if ( !this.options.showLabel && this.options.text ) {
|
|
this.options.text = this.options.showLabel;
|
|
}
|
|
if ( !this.options.icon && ( this.options.icons.primary ||
|
|
this.options.icons.secondary ) ) {
|
|
if ( this.options.icons.primary ) {
|
|
this.options.icon = this.options.icons.primary;
|
|
} else {
|
|
this.options.icon = this.options.icons.secondary;
|
|
this.options.iconPosition = "end";
|
|
}
|
|
} else if ( this.options.icon ) {
|
|
this.options.icons.primary = this.options.icon;
|
|
}
|
|
this._super();
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
if ( key === "text" ) {
|
|
this._super( "showLabel", value );
|
|
return;
|
|
}
|
|
if ( key === "showLabel" ) {
|
|
this.options.text = value;
|
|
}
|
|
if ( key === "icon" ) {
|
|
this.options.icons.primary = value;
|
|
}
|
|
if ( key === "icons" ) {
|
|
if ( value.primary ) {
|
|
this._super( "icon", value.primary );
|
|
this._super( "iconPosition", "beginning" );
|
|
} else if ( value.secondary ) {
|
|
this._super( "icon", value.secondary );
|
|
this._super( "iconPosition", "end" );
|
|
}
|
|
}
|
|
this._superApply( arguments );
|
|
}
|
|
} );
|
|
|
|
$.fn.button = ( function( orig ) {
|
|
return function() {
|
|
if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) ||
|
|
( this.length && this[ 0 ].tagName === "INPUT" && (
|
|
this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio"
|
|
) ) ) {
|
|
return orig.apply( this, arguments );
|
|
}
|
|
if ( !$.ui.checkboxradio ) {
|
|
$.error( "Checkboxradio widget missing" );
|
|
}
|
|
if ( arguments.length === 0 ) {
|
|
return this.checkboxradio( {
|
|
"icon": false
|
|
} );
|
|
}
|
|
return this.checkboxradio.apply( this, arguments );
|
|
};
|
|
} )( $.fn.button );
|
|
|
|
$.fn.buttonset = function() {
|
|
if ( !$.ui.controlgroup ) {
|
|
$.error( "Controlgroup widget missing" );
|
|
}
|
|
if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
|
|
return this.controlgroup.apply( this,
|
|
[ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
|
|
}
|
|
if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
|
|
return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
|
|
}
|
|
if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
|
|
arguments[ 0 ].items = {
|
|
button: arguments[ 0 ].items
|
|
};
|
|
}
|
|
return this.controlgroup.apply( this, arguments );
|
|
};
|
|
}
|
|
|
|
return $.ui.button;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 56 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Mouse 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Mouse
|
|
//>>group: Widgets
|
|
//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
|
|
//>>docs: http://api.jqueryui.com/mouse/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(16),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
var mouseHandled = false;
|
|
$( document ).on( "mouseup", function() {
|
|
mouseHandled = false;
|
|
} );
|
|
|
|
return $.widget( "ui.mouse", {
|
|
version: "1.12.1",
|
|
options: {
|
|
cancel: "input, textarea, button, select, option",
|
|
distance: 1,
|
|
delay: 0
|
|
},
|
|
_mouseInit: function() {
|
|
var that = this;
|
|
|
|
this.element
|
|
.on( "mousedown." + this.widgetName, function( event ) {
|
|
return that._mouseDown( event );
|
|
} )
|
|
.on( "click." + this.widgetName, function( event ) {
|
|
if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
|
|
$.removeData( event.target, that.widgetName + ".preventClickEvent" );
|
|
event.stopImmediatePropagation();
|
|
return false;
|
|
}
|
|
} );
|
|
|
|
this.started = false;
|
|
},
|
|
|
|
// TODO: make sure destroying one instance of mouse doesn't mess with
|
|
// other instances of mouse
|
|
_mouseDestroy: function() {
|
|
this.element.off( "." + this.widgetName );
|
|
if ( this._mouseMoveDelegate ) {
|
|
this.document
|
|
.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
|
|
.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
|
|
}
|
|
},
|
|
|
|
_mouseDown: function( event ) {
|
|
|
|
// don't let more than one widget handle mouseStart
|
|
if ( mouseHandled ) {
|
|
return;
|
|
}
|
|
|
|
this._mouseMoved = false;
|
|
|
|
// We may have missed mouseup (out of window)
|
|
( this._mouseStarted && this._mouseUp( event ) );
|
|
|
|
this._mouseDownEvent = event;
|
|
|
|
var that = this,
|
|
btnIsLeft = ( event.which === 1 ),
|
|
|
|
// event.target.nodeName works around a bug in IE 8 with
|
|
// disabled inputs (#7620)
|
|
elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
|
|
$( event.target ).closest( this.options.cancel ).length : false );
|
|
if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
|
|
return true;
|
|
}
|
|
|
|
this.mouseDelayMet = !this.options.delay;
|
|
if ( !this.mouseDelayMet ) {
|
|
this._mouseDelayTimer = setTimeout( function() {
|
|
that.mouseDelayMet = true;
|
|
}, this.options.delay );
|
|
}
|
|
|
|
if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
|
|
this._mouseStarted = ( this._mouseStart( event ) !== false );
|
|
if ( !this._mouseStarted ) {
|
|
event.preventDefault();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Click event may never have fired (Gecko & Opera)
|
|
if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
|
|
$.removeData( event.target, this.widgetName + ".preventClickEvent" );
|
|
}
|
|
|
|
// These delegates are required to keep context
|
|
this._mouseMoveDelegate = function( event ) {
|
|
return that._mouseMove( event );
|
|
};
|
|
this._mouseUpDelegate = function( event ) {
|
|
return that._mouseUp( event );
|
|
};
|
|
|
|
this.document
|
|
.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
|
|
.on( "mouseup." + this.widgetName, this._mouseUpDelegate );
|
|
|
|
event.preventDefault();
|
|
|
|
mouseHandled = true;
|
|
return true;
|
|
},
|
|
|
|
_mouseMove: function( event ) {
|
|
|
|
// Only check for mouseups outside the document if you've moved inside the document
|
|
// at least once. This prevents the firing of mouseup in the case of IE<9, which will
|
|
// fire a mousemove event if content is placed under the cursor. See #7778
|
|
// Support: IE <9
|
|
if ( this._mouseMoved ) {
|
|
|
|
// IE mouseup check - mouseup happened when mouse was out of window
|
|
if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&
|
|
!event.button ) {
|
|
return this._mouseUp( event );
|
|
|
|
// Iframe mouseup check - mouseup occurred in another document
|
|
} else if ( !event.which ) {
|
|
|
|
// Support: Safari <=8 - 9
|
|
// Safari sets which to 0 if you press any of the following keys
|
|
// during a drag (#14461)
|
|
if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
|
|
event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
|
|
this.ignoreMissingWhich = true;
|
|
} else if ( !this.ignoreMissingWhich ) {
|
|
return this._mouseUp( event );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( event.which || event.button ) {
|
|
this._mouseMoved = true;
|
|
}
|
|
|
|
if ( this._mouseStarted ) {
|
|
this._mouseDrag( event );
|
|
return event.preventDefault();
|
|
}
|
|
|
|
if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
|
|
this._mouseStarted =
|
|
( this._mouseStart( this._mouseDownEvent, event ) !== false );
|
|
( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) );
|
|
}
|
|
|
|
return !this._mouseStarted;
|
|
},
|
|
|
|
_mouseUp: function( event ) {
|
|
this.document
|
|
.off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
|
|
.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
|
|
|
|
if ( this._mouseStarted ) {
|
|
this._mouseStarted = false;
|
|
|
|
if ( event.target === this._mouseDownEvent.target ) {
|
|
$.data( event.target, this.widgetName + ".preventClickEvent", true );
|
|
}
|
|
|
|
this._mouseStop( event );
|
|
}
|
|
|
|
if ( this._mouseDelayTimer ) {
|
|
clearTimeout( this._mouseDelayTimer );
|
|
delete this._mouseDelayTimer;
|
|
}
|
|
|
|
this.ignoreMissingWhich = false;
|
|
mouseHandled = false;
|
|
event.preventDefault();
|
|
},
|
|
|
|
_mouseDistanceMet: function( event ) {
|
|
return ( Math.max(
|
|
Math.abs( this._mouseDownEvent.pageX - event.pageX ),
|
|
Math.abs( this._mouseDownEvent.pageY - event.pageY )
|
|
) >= this.options.distance
|
|
);
|
|
},
|
|
|
|
_mouseDelayMet: function( /* event */ ) {
|
|
return this.mouseDelayMet;
|
|
},
|
|
|
|
// These are placeholder methods, to be overriden by extending plugin
|
|
_mouseStart: function( /* event */ ) {},
|
|
_mouseDrag: function( /* event */ ) {},
|
|
_mouseStop: function( /* event */ ) {},
|
|
_mouseCapture: function( /* event */ ) { return true; }
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 57 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Draggable 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Draggable
|
|
//>>group: Interactions
|
|
//>>description: Enables dragging functionality for any element.
|
|
//>>docs: http://api.jqueryui.com/draggable/
|
|
//>>demos: http://jqueryui.com/draggable/
|
|
//>>css.structure: ../../themes/base/draggable.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(56),
|
|
__webpack_require__(22),
|
|
__webpack_require__(17),
|
|
__webpack_require__(18),
|
|
__webpack_require__(19),
|
|
__webpack_require__(46),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
$.widget( "ui.draggable", $.ui.mouse, {
|
|
version: "1.12.1",
|
|
widgetEventPrefix: "drag",
|
|
options: {
|
|
addClasses: true,
|
|
appendTo: "parent",
|
|
axis: false,
|
|
connectToSortable: false,
|
|
containment: false,
|
|
cursor: "auto",
|
|
cursorAt: false,
|
|
grid: false,
|
|
handle: false,
|
|
helper: "original",
|
|
iframeFix: false,
|
|
opacity: false,
|
|
refreshPositions: false,
|
|
revert: false,
|
|
revertDuration: 500,
|
|
scope: "default",
|
|
scroll: true,
|
|
scrollSensitivity: 20,
|
|
scrollSpeed: 20,
|
|
snap: false,
|
|
snapMode: "both",
|
|
snapTolerance: 20,
|
|
stack: false,
|
|
zIndex: false,
|
|
|
|
// Callbacks
|
|
drag: null,
|
|
start: null,
|
|
stop: null
|
|
},
|
|
_create: function() {
|
|
|
|
if ( this.options.helper === "original" ) {
|
|
this._setPositionRelative();
|
|
}
|
|
if ( this.options.addClasses ) {
|
|
this._addClass( "ui-draggable" );
|
|
}
|
|
this._setHandleClassName();
|
|
|
|
this._mouseInit();
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
this._super( key, value );
|
|
if ( key === "handle" ) {
|
|
this._removeHandleClassName();
|
|
this._setHandleClassName();
|
|
}
|
|
},
|
|
|
|
_destroy: function() {
|
|
if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
|
|
this.destroyOnClear = true;
|
|
return;
|
|
}
|
|
this._removeHandleClassName();
|
|
this._mouseDestroy();
|
|
},
|
|
|
|
_mouseCapture: function( event ) {
|
|
var o = this.options;
|
|
|
|
// Among others, prevent a drag on a resizable-handle
|
|
if ( this.helper || o.disabled ||
|
|
$( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
|
|
return false;
|
|
}
|
|
|
|
//Quit if we're not on a valid handle
|
|
this.handle = this._getHandle( event );
|
|
if ( !this.handle ) {
|
|
return false;
|
|
}
|
|
|
|
this._blurActiveElement( event );
|
|
|
|
this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
_blockFrames: function( selector ) {
|
|
this.iframeBlocks = this.document.find( selector ).map( function() {
|
|
var iframe = $( this );
|
|
|
|
return $( "<div>" )
|
|
.css( "position", "absolute" )
|
|
.appendTo( iframe.parent() )
|
|
.outerWidth( iframe.outerWidth() )
|
|
.outerHeight( iframe.outerHeight() )
|
|
.offset( iframe.offset() )[ 0 ];
|
|
} );
|
|
},
|
|
|
|
_unblockFrames: function() {
|
|
if ( this.iframeBlocks ) {
|
|
this.iframeBlocks.remove();
|
|
delete this.iframeBlocks;
|
|
}
|
|
},
|
|
|
|
_blurActiveElement: function( event ) {
|
|
var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
|
|
target = $( event.target );
|
|
|
|
// Don't blur if the event occurred on an element that is within
|
|
// the currently focused element
|
|
// See #10527, #12472
|
|
if ( target.closest( activeElement ).length ) {
|
|
return;
|
|
}
|
|
|
|
// Blur any element that currently has focus, see #4261
|
|
$.ui.safeBlur( activeElement );
|
|
},
|
|
|
|
_mouseStart: function( event ) {
|
|
|
|
var o = this.options;
|
|
|
|
//Create and append the visible helper
|
|
this.helper = this._createHelper( event );
|
|
|
|
this._addClass( this.helper, "ui-draggable-dragging" );
|
|
|
|
//Cache the helper size
|
|
this._cacheHelperProportions();
|
|
|
|
//If ddmanager is used for droppables, set the global draggable
|
|
if ( $.ui.ddmanager ) {
|
|
$.ui.ddmanager.current = this;
|
|
}
|
|
|
|
/*
|
|
* - Position generation -
|
|
* This block generates everything position related - it's the core of draggables.
|
|
*/
|
|
|
|
//Cache the margins of the original element
|
|
this._cacheMargins();
|
|
|
|
//Store the helper's css position
|
|
this.cssPosition = this.helper.css( "position" );
|
|
this.scrollParent = this.helper.scrollParent( true );
|
|
this.offsetParent = this.helper.offsetParent();
|
|
this.hasFixedAncestor = this.helper.parents().filter( function() {
|
|
return $( this ).css( "position" ) === "fixed";
|
|
} ).length > 0;
|
|
|
|
//The element's absolute position on the page minus margins
|
|
this.positionAbs = this.element.offset();
|
|
this._refreshOffsets( event );
|
|
|
|
//Generate the original position
|
|
this.originalPosition = this.position = this._generatePosition( event, false );
|
|
this.originalPageX = event.pageX;
|
|
this.originalPageY = event.pageY;
|
|
|
|
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
|
|
( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );
|
|
|
|
//Set a containment if given in the options
|
|
this._setContainment();
|
|
|
|
//Trigger event + callbacks
|
|
if ( this._trigger( "start", event ) === false ) {
|
|
this._clear();
|
|
return false;
|
|
}
|
|
|
|
//Recache the helper size
|
|
this._cacheHelperProportions();
|
|
|
|
//Prepare the droppable offsets
|
|
if ( $.ui.ddmanager && !o.dropBehaviour ) {
|
|
$.ui.ddmanager.prepareOffsets( this, event );
|
|
}
|
|
|
|
// Execute the drag once - this causes the helper not to be visible before getting its
|
|
// correct position
|
|
this._mouseDrag( event, true );
|
|
|
|
// If the ddmanager is used for droppables, inform the manager that dragging has started
|
|
// (see #5003)
|
|
if ( $.ui.ddmanager ) {
|
|
$.ui.ddmanager.dragStart( this, event );
|
|
}
|
|
|
|
return true;
|
|
},
|
|
|
|
_refreshOffsets: function( event ) {
|
|
this.offset = {
|
|
top: this.positionAbs.top - this.margins.top,
|
|
left: this.positionAbs.left - this.margins.left,
|
|
scroll: false,
|
|
parent: this._getParentOffset(),
|
|
relative: this._getRelativeOffset()
|
|
};
|
|
|
|
this.offset.click = {
|
|
left: event.pageX - this.offset.left,
|
|
top: event.pageY - this.offset.top
|
|
};
|
|
},
|
|
|
|
_mouseDrag: function( event, noPropagation ) {
|
|
|
|
// reset any necessary cached properties (see #5009)
|
|
if ( this.hasFixedAncestor ) {
|
|
this.offset.parent = this._getParentOffset();
|
|
}
|
|
|
|
//Compute the helpers position
|
|
this.position = this._generatePosition( event, true );
|
|
this.positionAbs = this._convertPositionTo( "absolute" );
|
|
|
|
//Call plugins and callbacks and use the resulting position if something is returned
|
|
if ( !noPropagation ) {
|
|
var ui = this._uiHash();
|
|
if ( this._trigger( "drag", event, ui ) === false ) {
|
|
this._mouseUp( new $.Event( "mouseup", event ) );
|
|
return false;
|
|
}
|
|
this.position = ui.position;
|
|
}
|
|
|
|
this.helper[ 0 ].style.left = this.position.left + "px";
|
|
this.helper[ 0 ].style.top = this.position.top + "px";
|
|
|
|
if ( $.ui.ddmanager ) {
|
|
$.ui.ddmanager.drag( this, event );
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
_mouseStop: function( event ) {
|
|
|
|
//If we are using droppables, inform the manager about the drop
|
|
var that = this,
|
|
dropped = false;
|
|
if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
|
|
dropped = $.ui.ddmanager.drop( this, event );
|
|
}
|
|
|
|
//if a drop comes from outside (a sortable)
|
|
if ( this.dropped ) {
|
|
dropped = this.dropped;
|
|
this.dropped = false;
|
|
}
|
|
|
|
if ( ( this.options.revert === "invalid" && !dropped ) ||
|
|
( this.options.revert === "valid" && dropped ) ||
|
|
this.options.revert === true || ( $.isFunction( this.options.revert ) &&
|
|
this.options.revert.call( this.element, dropped ) )
|
|
) {
|
|
$( this.helper ).animate(
|
|
this.originalPosition,
|
|
parseInt( this.options.revertDuration, 10 ),
|
|
function() {
|
|
if ( that._trigger( "stop", event ) !== false ) {
|
|
that._clear();
|
|
}
|
|
}
|
|
);
|
|
} else {
|
|
if ( this._trigger( "stop", event ) !== false ) {
|
|
this._clear();
|
|
}
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
_mouseUp: function( event ) {
|
|
this._unblockFrames();
|
|
|
|
// If the ddmanager is used for droppables, inform the manager that dragging has stopped
|
|
// (see #5003)
|
|
if ( $.ui.ddmanager ) {
|
|
$.ui.ddmanager.dragStop( this, event );
|
|
}
|
|
|
|
// Only need to focus if the event occurred on the draggable itself, see #10527
|
|
if ( this.handleElement.is( event.target ) ) {
|
|
|
|
// The interaction is over; whether or not the click resulted in a drag,
|
|
// focus the element
|
|
this.element.trigger( "focus" );
|
|
}
|
|
|
|
return $.ui.mouse.prototype._mouseUp.call( this, event );
|
|
},
|
|
|
|
cancel: function() {
|
|
|
|
if ( this.helper.is( ".ui-draggable-dragging" ) ) {
|
|
this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
|
|
} else {
|
|
this._clear();
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
_getHandle: function( event ) {
|
|
return this.options.handle ?
|
|
!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
|
|
true;
|
|
},
|
|
|
|
_setHandleClassName: function() {
|
|
this.handleElement = this.options.handle ?
|
|
this.element.find( this.options.handle ) : this.element;
|
|
this._addClass( this.handleElement, "ui-draggable-handle" );
|
|
},
|
|
|
|
_removeHandleClassName: function() {
|
|
this._removeClass( this.handleElement, "ui-draggable-handle" );
|
|
},
|
|
|
|
_createHelper: function( event ) {
|
|
|
|
var o = this.options,
|
|
helperIsFunction = $.isFunction( o.helper ),
|
|
helper = helperIsFunction ?
|
|
$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
|
|
( o.helper === "clone" ?
|
|
this.element.clone().removeAttr( "id" ) :
|
|
this.element );
|
|
|
|
if ( !helper.parents( "body" ).length ) {
|
|
helper.appendTo( ( o.appendTo === "parent" ?
|
|
this.element[ 0 ].parentNode :
|
|
o.appendTo ) );
|
|
}
|
|
|
|
// Http://bugs.jqueryui.com/ticket/9446
|
|
// a helper function can return the original element
|
|
// which wouldn't have been set to relative in _create
|
|
if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
|
|
this._setPositionRelative();
|
|
}
|
|
|
|
if ( helper[ 0 ] !== this.element[ 0 ] &&
|
|
!( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
|
|
helper.css( "position", "absolute" );
|
|
}
|
|
|
|
return helper;
|
|
|
|
},
|
|
|
|
_setPositionRelative: function() {
|
|
if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
|
|
this.element[ 0 ].style.position = "relative";
|
|
}
|
|
},
|
|
|
|
_adjustOffsetFromHelper: function( obj ) {
|
|
if ( typeof obj === "string" ) {
|
|
obj = obj.split( " " );
|
|
}
|
|
if ( $.isArray( obj ) ) {
|
|
obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
|
|
}
|
|
if ( "left" in obj ) {
|
|
this.offset.click.left = obj.left + this.margins.left;
|
|
}
|
|
if ( "right" in obj ) {
|
|
this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
|
|
}
|
|
if ( "top" in obj ) {
|
|
this.offset.click.top = obj.top + this.margins.top;
|
|
}
|
|
if ( "bottom" in obj ) {
|
|
this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
|
|
}
|
|
},
|
|
|
|
_isRootNode: function( element ) {
|
|
return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
|
|
},
|
|
|
|
_getParentOffset: function() {
|
|
|
|
//Get the offsetParent and cache its position
|
|
var po = this.offsetParent.offset(),
|
|
document = this.document[ 0 ];
|
|
|
|
// This is a special case where we need to modify a offset calculated on start, since the
|
|
// following happened:
|
|
// 1. The position of the helper is absolute, so it's position is calculated based on the
|
|
// next positioned parent
|
|
// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
|
|
// the document, which means that the scroll is included in the initial calculation of the
|
|
// offset of the parent, and never recalculated upon drag
|
|
if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
|
|
$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
|
|
po.left += this.scrollParent.scrollLeft();
|
|
po.top += this.scrollParent.scrollTop();
|
|
}
|
|
|
|
if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
|
|
po = { top: 0, left: 0 };
|
|
}
|
|
|
|
return {
|
|
top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
|
|
left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
|
|
};
|
|
|
|
},
|
|
|
|
_getRelativeOffset: function() {
|
|
if ( this.cssPosition !== "relative" ) {
|
|
return { top: 0, left: 0 };
|
|
}
|
|
|
|
var p = this.element.position(),
|
|
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
|
|
|
|
return {
|
|
top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
|
|
( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
|
|
left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
|
|
( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
|
|
};
|
|
|
|
},
|
|
|
|
_cacheMargins: function() {
|
|
this.margins = {
|
|
left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
|
|
top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
|
|
right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
|
|
bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
|
|
};
|
|
},
|
|
|
|
_cacheHelperProportions: function() {
|
|
this.helperProportions = {
|
|
width: this.helper.outerWidth(),
|
|
height: this.helper.outerHeight()
|
|
};
|
|
},
|
|
|
|
_setContainment: function() {
|
|
|
|
var isUserScrollable, c, ce,
|
|
o = this.options,
|
|
document = this.document[ 0 ];
|
|
|
|
this.relativeContainer = null;
|
|
|
|
if ( !o.containment ) {
|
|
this.containment = null;
|
|
return;
|
|
}
|
|
|
|
if ( o.containment === "window" ) {
|
|
this.containment = [
|
|
$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
|
|
$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
|
|
$( window ).scrollLeft() + $( window ).width() -
|
|
this.helperProportions.width - this.margins.left,
|
|
$( window ).scrollTop() +
|
|
( $( window ).height() || document.body.parentNode.scrollHeight ) -
|
|
this.helperProportions.height - this.margins.top
|
|
];
|
|
return;
|
|
}
|
|
|
|
if ( o.containment === "document" ) {
|
|
this.containment = [
|
|
0,
|
|
0,
|
|
$( document ).width() - this.helperProportions.width - this.margins.left,
|
|
( $( document ).height() || document.body.parentNode.scrollHeight ) -
|
|
this.helperProportions.height - this.margins.top
|
|
];
|
|
return;
|
|
}
|
|
|
|
if ( o.containment.constructor === Array ) {
|
|
this.containment = o.containment;
|
|
return;
|
|
}
|
|
|
|
if ( o.containment === "parent" ) {
|
|
o.containment = this.helper[ 0 ].parentNode;
|
|
}
|
|
|
|
c = $( o.containment );
|
|
ce = c[ 0 ];
|
|
|
|
if ( !ce ) {
|
|
return;
|
|
}
|
|
|
|
isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
|
|
|
|
this.containment = [
|
|
( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
|
|
( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
|
|
( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
|
|
( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
|
|
( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
|
|
( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
|
|
( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
|
|
this.helperProportions.width -
|
|
this.margins.left -
|
|
this.margins.right,
|
|
( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
|
|
( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
|
|
( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
|
|
this.helperProportions.height -
|
|
this.margins.top -
|
|
this.margins.bottom
|
|
];
|
|
this.relativeContainer = c;
|
|
},
|
|
|
|
_convertPositionTo: function( d, pos ) {
|
|
|
|
if ( !pos ) {
|
|
pos = this.position;
|
|
}
|
|
|
|
var mod = d === "absolute" ? 1 : -1,
|
|
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
|
|
|
|
return {
|
|
top: (
|
|
|
|
// The absolute mouse position
|
|
pos.top +
|
|
|
|
// Only for relative positioned nodes: Relative offset from element to offset parent
|
|
this.offset.relative.top * mod +
|
|
|
|
// The offsetParent's offset without borders (offset + border)
|
|
this.offset.parent.top * mod -
|
|
( ( this.cssPosition === "fixed" ?
|
|
-this.offset.scroll.top :
|
|
( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
|
|
),
|
|
left: (
|
|
|
|
// The absolute mouse position
|
|
pos.left +
|
|
|
|
// Only for relative positioned nodes: Relative offset from element to offset parent
|
|
this.offset.relative.left * mod +
|
|
|
|
// The offsetParent's offset without borders (offset + border)
|
|
this.offset.parent.left * mod -
|
|
( ( this.cssPosition === "fixed" ?
|
|
-this.offset.scroll.left :
|
|
( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
|
|
)
|
|
};
|
|
|
|
},
|
|
|
|
_generatePosition: function( event, constrainPosition ) {
|
|
|
|
var containment, co, top, left,
|
|
o = this.options,
|
|
scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
|
|
pageX = event.pageX,
|
|
pageY = event.pageY;
|
|
|
|
// Cache the scroll
|
|
if ( !scrollIsRootNode || !this.offset.scroll ) {
|
|
this.offset.scroll = {
|
|
top: this.scrollParent.scrollTop(),
|
|
left: this.scrollParent.scrollLeft()
|
|
};
|
|
}
|
|
|
|
/*
|
|
* - Position constraining -
|
|
* Constrain the position to a mix of grid, containment.
|
|
*/
|
|
|
|
// If we are not dragging yet, we won't check for options
|
|
if ( constrainPosition ) {
|
|
if ( this.containment ) {
|
|
if ( this.relativeContainer ) {
|
|
co = this.relativeContainer.offset();
|
|
containment = [
|
|
this.containment[ 0 ] + co.left,
|
|
this.containment[ 1 ] + co.top,
|
|
this.containment[ 2 ] + co.left,
|
|
this.containment[ 3 ] + co.top
|
|
];
|
|
} else {
|
|
containment = this.containment;
|
|
}
|
|
|
|
if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
|
|
pageX = containment[ 0 ] + this.offset.click.left;
|
|
}
|
|
if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
|
|
pageY = containment[ 1 ] + this.offset.click.top;
|
|
}
|
|
if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
|
|
pageX = containment[ 2 ] + this.offset.click.left;
|
|
}
|
|
if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
|
|
pageY = containment[ 3 ] + this.offset.click.top;
|
|
}
|
|
}
|
|
|
|
if ( o.grid ) {
|
|
|
|
//Check for grid elements set to 0 to prevent divide by 0 error causing invalid
|
|
// argument errors in IE (see ticket #6950)
|
|
top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
|
|
this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
|
|
pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
|
|
top - this.offset.click.top > containment[ 3 ] ) ?
|
|
top :
|
|
( ( top - this.offset.click.top >= containment[ 1 ] ) ?
|
|
top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
|
|
|
|
left = o.grid[ 0 ] ? this.originalPageX +
|
|
Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
|
|
this.originalPageX;
|
|
pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
|
|
left - this.offset.click.left > containment[ 2 ] ) ?
|
|
left :
|
|
( ( left - this.offset.click.left >= containment[ 0 ] ) ?
|
|
left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
|
|
}
|
|
|
|
if ( o.axis === "y" ) {
|
|
pageX = this.originalPageX;
|
|
}
|
|
|
|
if ( o.axis === "x" ) {
|
|
pageY = this.originalPageY;
|
|
}
|
|
}
|
|
|
|
return {
|
|
top: (
|
|
|
|
// The absolute mouse position
|
|
pageY -
|
|
|
|
// Click offset (relative to the element)
|
|
this.offset.click.top -
|
|
|
|
// Only for relative positioned nodes: Relative offset from element to offset parent
|
|
this.offset.relative.top -
|
|
|
|
// The offsetParent's offset without borders (offset + border)
|
|
this.offset.parent.top +
|
|
( this.cssPosition === "fixed" ?
|
|
-this.offset.scroll.top :
|
|
( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
|
|
),
|
|
left: (
|
|
|
|
// The absolute mouse position
|
|
pageX -
|
|
|
|
// Click offset (relative to the element)
|
|
this.offset.click.left -
|
|
|
|
// Only for relative positioned nodes: Relative offset from element to offset parent
|
|
this.offset.relative.left -
|
|
|
|
// The offsetParent's offset without borders (offset + border)
|
|
this.offset.parent.left +
|
|
( this.cssPosition === "fixed" ?
|
|
-this.offset.scroll.left :
|
|
( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
|
|
)
|
|
};
|
|
|
|
},
|
|
|
|
_clear: function() {
|
|
this._removeClass( this.helper, "ui-draggable-dragging" );
|
|
if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
|
|
this.helper.remove();
|
|
}
|
|
this.helper = null;
|
|
this.cancelHelperRemoval = false;
|
|
if ( this.destroyOnClear ) {
|
|
this.destroy();
|
|
}
|
|
},
|
|
|
|
// From now on bulk stuff - mainly helpers
|
|
|
|
_trigger: function( type, event, ui ) {
|
|
ui = ui || this._uiHash();
|
|
$.ui.plugin.call( this, type, [ event, ui, this ], true );
|
|
|
|
// Absolute position and offset (see #6884 ) have to be recalculated after plugins
|
|
if ( /^(drag|start|stop)/.test( type ) ) {
|
|
this.positionAbs = this._convertPositionTo( "absolute" );
|
|
ui.offset = this.positionAbs;
|
|
}
|
|
return $.Widget.prototype._trigger.call( this, type, event, ui );
|
|
},
|
|
|
|
plugins: {},
|
|
|
|
_uiHash: function() {
|
|
return {
|
|
helper: this.helper,
|
|
position: this.position,
|
|
originalPosition: this.originalPosition,
|
|
offset: this.positionAbs
|
|
};
|
|
}
|
|
|
|
} );
|
|
|
|
$.ui.plugin.add( "draggable", "connectToSortable", {
|
|
start: function( event, ui, draggable ) {
|
|
var uiSortable = $.extend( {}, ui, {
|
|
item: draggable.element
|
|
} );
|
|
|
|
draggable.sortables = [];
|
|
$( draggable.options.connectToSortable ).each( function() {
|
|
var sortable = $( this ).sortable( "instance" );
|
|
|
|
if ( sortable && !sortable.options.disabled ) {
|
|
draggable.sortables.push( sortable );
|
|
|
|
// RefreshPositions is called at drag start to refresh the containerCache
|
|
// which is used in drag. This ensures it's initialized and synchronized
|
|
// with any changes that might have happened on the page since initialization.
|
|
sortable.refreshPositions();
|
|
sortable._trigger( "activate", event, uiSortable );
|
|
}
|
|
} );
|
|
},
|
|
stop: function( event, ui, draggable ) {
|
|
var uiSortable = $.extend( {}, ui, {
|
|
item: draggable.element
|
|
} );
|
|
|
|
draggable.cancelHelperRemoval = false;
|
|
|
|
$.each( draggable.sortables, function() {
|
|
var sortable = this;
|
|
|
|
if ( sortable.isOver ) {
|
|
sortable.isOver = 0;
|
|
|
|
// Allow this sortable to handle removing the helper
|
|
draggable.cancelHelperRemoval = true;
|
|
sortable.cancelHelperRemoval = false;
|
|
|
|
// Use _storedCSS To restore properties in the sortable,
|
|
// as this also handles revert (#9675) since the draggable
|
|
// may have modified them in unexpected ways (#8809)
|
|
sortable._storedCSS = {
|
|
position: sortable.placeholder.css( "position" ),
|
|
top: sortable.placeholder.css( "top" ),
|
|
left: sortable.placeholder.css( "left" )
|
|
};
|
|
|
|
sortable._mouseStop( event );
|
|
|
|
// Once drag has ended, the sortable should return to using
|
|
// its original helper, not the shared helper from draggable
|
|
sortable.options.helper = sortable.options._helper;
|
|
} else {
|
|
|
|
// Prevent this Sortable from removing the helper.
|
|
// However, don't set the draggable to remove the helper
|
|
// either as another connected Sortable may yet handle the removal.
|
|
sortable.cancelHelperRemoval = true;
|
|
|
|
sortable._trigger( "deactivate", event, uiSortable );
|
|
}
|
|
} );
|
|
},
|
|
drag: function( event, ui, draggable ) {
|
|
$.each( draggable.sortables, function() {
|
|
var innermostIntersecting = false,
|
|
sortable = this;
|
|
|
|
// Copy over variables that sortable's _intersectsWith uses
|
|
sortable.positionAbs = draggable.positionAbs;
|
|
sortable.helperProportions = draggable.helperProportions;
|
|
sortable.offset.click = draggable.offset.click;
|
|
|
|
if ( sortable._intersectsWith( sortable.containerCache ) ) {
|
|
innermostIntersecting = true;
|
|
|
|
$.each( draggable.sortables, function() {
|
|
|
|
// Copy over variables that sortable's _intersectsWith uses
|
|
this.positionAbs = draggable.positionAbs;
|
|
this.helperProportions = draggable.helperProportions;
|
|
this.offset.click = draggable.offset.click;
|
|
|
|
if ( this !== sortable &&
|
|
this._intersectsWith( this.containerCache ) &&
|
|
$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
|
|
innermostIntersecting = false;
|
|
}
|
|
|
|
return innermostIntersecting;
|
|
} );
|
|
}
|
|
|
|
if ( innermostIntersecting ) {
|
|
|
|
// If it intersects, we use a little isOver variable and set it once,
|
|
// so that the move-in stuff gets fired only once.
|
|
if ( !sortable.isOver ) {
|
|
sortable.isOver = 1;
|
|
|
|
// Store draggable's parent in case we need to reappend to it later.
|
|
draggable._parent = ui.helper.parent();
|
|
|
|
sortable.currentItem = ui.helper
|
|
.appendTo( sortable.element )
|
|
.data( "ui-sortable-item", true );
|
|
|
|
// Store helper option to later restore it
|
|
sortable.options._helper = sortable.options.helper;
|
|
|
|
sortable.options.helper = function() {
|
|
return ui.helper[ 0 ];
|
|
};
|
|
|
|
// Fire the start events of the sortable with our passed browser event,
|
|
// and our own helper (so it doesn't create a new one)
|
|
event.target = sortable.currentItem[ 0 ];
|
|
sortable._mouseCapture( event, true );
|
|
sortable._mouseStart( event, true, true );
|
|
|
|
// Because the browser event is way off the new appended portlet,
|
|
// modify necessary variables to reflect the changes
|
|
sortable.offset.click.top = draggable.offset.click.top;
|
|
sortable.offset.click.left = draggable.offset.click.left;
|
|
sortable.offset.parent.left -= draggable.offset.parent.left -
|
|
sortable.offset.parent.left;
|
|
sortable.offset.parent.top -= draggable.offset.parent.top -
|
|
sortable.offset.parent.top;
|
|
|
|
draggable._trigger( "toSortable", event );
|
|
|
|
// Inform draggable that the helper is in a valid drop zone,
|
|
// used solely in the revert option to handle "valid/invalid".
|
|
draggable.dropped = sortable.element;
|
|
|
|
// Need to refreshPositions of all sortables in the case that
|
|
// adding to one sortable changes the location of the other sortables (#9675)
|
|
$.each( draggable.sortables, function() {
|
|
this.refreshPositions();
|
|
} );
|
|
|
|
// Hack so receive/update callbacks work (mostly)
|
|
draggable.currentItem = draggable.element;
|
|
sortable.fromOutside = draggable;
|
|
}
|
|
|
|
if ( sortable.currentItem ) {
|
|
sortable._mouseDrag( event );
|
|
|
|
// Copy the sortable's position because the draggable's can potentially reflect
|
|
// a relative position, while sortable is always absolute, which the dragged
|
|
// element has now become. (#8809)
|
|
ui.position = sortable.position;
|
|
}
|
|
} else {
|
|
|
|
// If it doesn't intersect with the sortable, and it intersected before,
|
|
// we fake the drag stop of the sortable, but make sure it doesn't remove
|
|
// the helper by using cancelHelperRemoval.
|
|
if ( sortable.isOver ) {
|
|
|
|
sortable.isOver = 0;
|
|
sortable.cancelHelperRemoval = true;
|
|
|
|
// Calling sortable's mouseStop would trigger a revert,
|
|
// so revert must be temporarily false until after mouseStop is called.
|
|
sortable.options._revert = sortable.options.revert;
|
|
sortable.options.revert = false;
|
|
|
|
sortable._trigger( "out", event, sortable._uiHash( sortable ) );
|
|
sortable._mouseStop( event, true );
|
|
|
|
// Restore sortable behaviors that were modfied
|
|
// when the draggable entered the sortable area (#9481)
|
|
sortable.options.revert = sortable.options._revert;
|
|
sortable.options.helper = sortable.options._helper;
|
|
|
|
if ( sortable.placeholder ) {
|
|
sortable.placeholder.remove();
|
|
}
|
|
|
|
// Restore and recalculate the draggable's offset considering the sortable
|
|
// may have modified them in unexpected ways. (#8809, #10669)
|
|
ui.helper.appendTo( draggable._parent );
|
|
draggable._refreshOffsets( event );
|
|
ui.position = draggable._generatePosition( event, true );
|
|
|
|
draggable._trigger( "fromSortable", event );
|
|
|
|
// Inform draggable that the helper is no longer in a valid drop zone
|
|
draggable.dropped = false;
|
|
|
|
// Need to refreshPositions of all sortables just in case removing
|
|
// from one sortable changes the location of other sortables (#9675)
|
|
$.each( draggable.sortables, function() {
|
|
this.refreshPositions();
|
|
} );
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
} );
|
|
|
|
$.ui.plugin.add( "draggable", "cursor", {
|
|
start: function( event, ui, instance ) {
|
|
var t = $( "body" ),
|
|
o = instance.options;
|
|
|
|
if ( t.css( "cursor" ) ) {
|
|
o._cursor = t.css( "cursor" );
|
|
}
|
|
t.css( "cursor", o.cursor );
|
|
},
|
|
stop: function( event, ui, instance ) {
|
|
var o = instance.options;
|
|
if ( o._cursor ) {
|
|
$( "body" ).css( "cursor", o._cursor );
|
|
}
|
|
}
|
|
} );
|
|
|
|
$.ui.plugin.add( "draggable", "opacity", {
|
|
start: function( event, ui, instance ) {
|
|
var t = $( ui.helper ),
|
|
o = instance.options;
|
|
if ( t.css( "opacity" ) ) {
|
|
o._opacity = t.css( "opacity" );
|
|
}
|
|
t.css( "opacity", o.opacity );
|
|
},
|
|
stop: function( event, ui, instance ) {
|
|
var o = instance.options;
|
|
if ( o._opacity ) {
|
|
$( ui.helper ).css( "opacity", o._opacity );
|
|
}
|
|
}
|
|
} );
|
|
|
|
$.ui.plugin.add( "draggable", "scroll", {
|
|
start: function( event, ui, i ) {
|
|
if ( !i.scrollParentNotHidden ) {
|
|
i.scrollParentNotHidden = i.helper.scrollParent( false );
|
|
}
|
|
|
|
if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
|
|
i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
|
|
i.overflowOffset = i.scrollParentNotHidden.offset();
|
|
}
|
|
},
|
|
drag: function( event, ui, i ) {
|
|
|
|
var o = i.options,
|
|
scrolled = false,
|
|
scrollParent = i.scrollParentNotHidden[ 0 ],
|
|
document = i.document[ 0 ];
|
|
|
|
if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
|
|
if ( !o.axis || o.axis !== "x" ) {
|
|
if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
|
|
o.scrollSensitivity ) {
|
|
scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
|
|
} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
|
|
scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
|
|
}
|
|
}
|
|
|
|
if ( !o.axis || o.axis !== "y" ) {
|
|
if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
|
|
o.scrollSensitivity ) {
|
|
scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
|
|
} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
|
|
scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
if ( !o.axis || o.axis !== "x" ) {
|
|
if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
|
|
scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
|
|
} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
|
|
o.scrollSensitivity ) {
|
|
scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
|
|
}
|
|
}
|
|
|
|
if ( !o.axis || o.axis !== "y" ) {
|
|
if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
|
|
scrolled = $( document ).scrollLeft(
|
|
$( document ).scrollLeft() - o.scrollSpeed
|
|
);
|
|
} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
|
|
o.scrollSensitivity ) {
|
|
scrolled = $( document ).scrollLeft(
|
|
$( document ).scrollLeft() + o.scrollSpeed
|
|
);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
|
|
$.ui.ddmanager.prepareOffsets( i, event );
|
|
}
|
|
|
|
}
|
|
} );
|
|
|
|
$.ui.plugin.add( "draggable", "snap", {
|
|
start: function( event, ui, i ) {
|
|
|
|
var o = i.options;
|
|
|
|
i.snapElements = [];
|
|
|
|
$( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
|
|
.each( function() {
|
|
var $t = $( this ),
|
|
$o = $t.offset();
|
|
if ( this !== i.element[ 0 ] ) {
|
|
i.snapElements.push( {
|
|
item: this,
|
|
width: $t.outerWidth(), height: $t.outerHeight(),
|
|
top: $o.top, left: $o.left
|
|
} );
|
|
}
|
|
} );
|
|
|
|
},
|
|
drag: function( event, ui, inst ) {
|
|
|
|
var ts, bs, ls, rs, l, r, t, b, i, first,
|
|
o = inst.options,
|
|
d = o.snapTolerance,
|
|
x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
|
|
y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
|
|
|
|
for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
|
|
|
|
l = inst.snapElements[ i ].left - inst.margins.left;
|
|
r = l + inst.snapElements[ i ].width;
|
|
t = inst.snapElements[ i ].top - inst.margins.top;
|
|
b = t + inst.snapElements[ i ].height;
|
|
|
|
if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
|
|
!$.contains( inst.snapElements[ i ].item.ownerDocument,
|
|
inst.snapElements[ i ].item ) ) {
|
|
if ( inst.snapElements[ i ].snapping ) {
|
|
( inst.options.snap.release &&
|
|
inst.options.snap.release.call(
|
|
inst.element,
|
|
event,
|
|
$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
|
|
) );
|
|
}
|
|
inst.snapElements[ i ].snapping = false;
|
|
continue;
|
|
}
|
|
|
|
if ( o.snapMode !== "inner" ) {
|
|
ts = Math.abs( t - y2 ) <= d;
|
|
bs = Math.abs( b - y1 ) <= d;
|
|
ls = Math.abs( l - x2 ) <= d;
|
|
rs = Math.abs( r - x1 ) <= d;
|
|
if ( ts ) {
|
|
ui.position.top = inst._convertPositionTo( "relative", {
|
|
top: t - inst.helperProportions.height,
|
|
left: 0
|
|
} ).top;
|
|
}
|
|
if ( bs ) {
|
|
ui.position.top = inst._convertPositionTo( "relative", {
|
|
top: b,
|
|
left: 0
|
|
} ).top;
|
|
}
|
|
if ( ls ) {
|
|
ui.position.left = inst._convertPositionTo( "relative", {
|
|
top: 0,
|
|
left: l - inst.helperProportions.width
|
|
} ).left;
|
|
}
|
|
if ( rs ) {
|
|
ui.position.left = inst._convertPositionTo( "relative", {
|
|
top: 0,
|
|
left: r
|
|
} ).left;
|
|
}
|
|
}
|
|
|
|
first = ( ts || bs || ls || rs );
|
|
|
|
if ( o.snapMode !== "outer" ) {
|
|
ts = Math.abs( t - y1 ) <= d;
|
|
bs = Math.abs( b - y2 ) <= d;
|
|
ls = Math.abs( l - x1 ) <= d;
|
|
rs = Math.abs( r - x2 ) <= d;
|
|
if ( ts ) {
|
|
ui.position.top = inst._convertPositionTo( "relative", {
|
|
top: t,
|
|
left: 0
|
|
} ).top;
|
|
}
|
|
if ( bs ) {
|
|
ui.position.top = inst._convertPositionTo( "relative", {
|
|
top: b - inst.helperProportions.height,
|
|
left: 0
|
|
} ).top;
|
|
}
|
|
if ( ls ) {
|
|
ui.position.left = inst._convertPositionTo( "relative", {
|
|
top: 0,
|
|
left: l
|
|
} ).left;
|
|
}
|
|
if ( rs ) {
|
|
ui.position.left = inst._convertPositionTo( "relative", {
|
|
top: 0,
|
|
left: r - inst.helperProportions.width
|
|
} ).left;
|
|
}
|
|
}
|
|
|
|
if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
|
|
( inst.options.snap.snap &&
|
|
inst.options.snap.snap.call(
|
|
inst.element,
|
|
event,
|
|
$.extend( inst._uiHash(), {
|
|
snapItem: inst.snapElements[ i ].item
|
|
} ) ) );
|
|
}
|
|
inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
|
|
|
|
}
|
|
|
|
}
|
|
} );
|
|
|
|
$.ui.plugin.add( "draggable", "stack", {
|
|
start: function( event, ui, instance ) {
|
|
var min,
|
|
o = instance.options,
|
|
group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
|
|
return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
|
|
( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
|
|
} );
|
|
|
|
if ( !group.length ) { return; }
|
|
|
|
min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
|
|
$( group ).each( function( i ) {
|
|
$( this ).css( "zIndex", min + i );
|
|
} );
|
|
this.css( "zIndex", ( min + group.length ) );
|
|
}
|
|
} );
|
|
|
|
$.ui.plugin.add( "draggable", "zIndex", {
|
|
start: function( event, ui, instance ) {
|
|
var t = $( ui.helper ),
|
|
o = instance.options;
|
|
|
|
if ( t.css( "zIndex" ) ) {
|
|
o._zIndex = t.css( "zIndex" );
|
|
}
|
|
t.css( "zIndex", o.zIndex );
|
|
},
|
|
stop: function( event, ui, instance ) {
|
|
var o = instance.options;
|
|
|
|
if ( o._zIndex ) {
|
|
$( ui.helper ).css( "zIndex", o._zIndex );
|
|
}
|
|
}
|
|
} );
|
|
|
|
return $.ui.draggable;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 58 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Resizable 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Resizable
|
|
//>>group: Interactions
|
|
//>>description: Enables resize functionality for any element.
|
|
//>>docs: http://api.jqueryui.com/resizable/
|
|
//>>demos: http://jqueryui.com/resizable/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/resizable.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(56),
|
|
__webpack_require__(23),
|
|
__webpack_require__(17),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
$.widget( "ui.resizable", $.ui.mouse, {
|
|
version: "1.12.1",
|
|
widgetEventPrefix: "resize",
|
|
options: {
|
|
alsoResize: false,
|
|
animate: false,
|
|
animateDuration: "slow",
|
|
animateEasing: "swing",
|
|
aspectRatio: false,
|
|
autoHide: false,
|
|
classes: {
|
|
"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
|
|
},
|
|
containment: false,
|
|
ghost: false,
|
|
grid: false,
|
|
handles: "e,s,se",
|
|
helper: false,
|
|
maxHeight: null,
|
|
maxWidth: null,
|
|
minHeight: 10,
|
|
minWidth: 10,
|
|
|
|
// See #7960
|
|
zIndex: 90,
|
|
|
|
// Callbacks
|
|
resize: null,
|
|
start: null,
|
|
stop: null
|
|
},
|
|
|
|
_num: function( value ) {
|
|
return parseFloat( value ) || 0;
|
|
},
|
|
|
|
_isNumber: function( value ) {
|
|
return !isNaN( parseFloat( value ) );
|
|
},
|
|
|
|
_hasScroll: function( el, a ) {
|
|
|
|
if ( $( el ).css( "overflow" ) === "hidden" ) {
|
|
return false;
|
|
}
|
|
|
|
var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
|
|
has = false;
|
|
|
|
if ( el[ scroll ] > 0 ) {
|
|
return true;
|
|
}
|
|
|
|
// TODO: determine which cases actually cause this to happen
|
|
// if the element doesn't have the scroll set, see if it's possible to
|
|
// set the scroll
|
|
el[ scroll ] = 1;
|
|
has = ( el[ scroll ] > 0 );
|
|
el[ scroll ] = 0;
|
|
return has;
|
|
},
|
|
|
|
_create: function() {
|
|
|
|
var margins,
|
|
o = this.options,
|
|
that = this;
|
|
this._addClass( "ui-resizable" );
|
|
|
|
$.extend( this, {
|
|
_aspectRatio: !!( o.aspectRatio ),
|
|
aspectRatio: o.aspectRatio,
|
|
originalElement: this.element,
|
|
_proportionallyResizeElements: [],
|
|
_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
|
|
} );
|
|
|
|
// Wrap the element if it cannot hold child nodes
|
|
if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
|
|
|
|
this.element.wrap(
|
|
$( "<div class='ui-wrapper' style='overflow: hidden;'></div>" ).css( {
|
|
position: this.element.css( "position" ),
|
|
width: this.element.outerWidth(),
|
|
height: this.element.outerHeight(),
|
|
top: this.element.css( "top" ),
|
|
left: this.element.css( "left" )
|
|
} )
|
|
);
|
|
|
|
this.element = this.element.parent().data(
|
|
"ui-resizable", this.element.resizable( "instance" )
|
|
);
|
|
|
|
this.elementIsWrapper = true;
|
|
|
|
margins = {
|
|
marginTop: this.originalElement.css( "marginTop" ),
|
|
marginRight: this.originalElement.css( "marginRight" ),
|
|
marginBottom: this.originalElement.css( "marginBottom" ),
|
|
marginLeft: this.originalElement.css( "marginLeft" )
|
|
};
|
|
|
|
this.element.css( margins );
|
|
this.originalElement.css( "margin", 0 );
|
|
|
|
// support: Safari
|
|
// Prevent Safari textarea resize
|
|
this.originalResizeStyle = this.originalElement.css( "resize" );
|
|
this.originalElement.css( "resize", "none" );
|
|
|
|
this._proportionallyResizeElements.push( this.originalElement.css( {
|
|
position: "static",
|
|
zoom: 1,
|
|
display: "block"
|
|
} ) );
|
|
|
|
// Support: IE9
|
|
// avoid IE jump (hard set the margin)
|
|
this.originalElement.css( margins );
|
|
|
|
this._proportionallyResize();
|
|
}
|
|
|
|
this._setupHandles();
|
|
|
|
if ( o.autoHide ) {
|
|
$( this.element )
|
|
.on( "mouseenter", function() {
|
|
if ( o.disabled ) {
|
|
return;
|
|
}
|
|
that._removeClass( "ui-resizable-autohide" );
|
|
that._handles.show();
|
|
} )
|
|
.on( "mouseleave", function() {
|
|
if ( o.disabled ) {
|
|
return;
|
|
}
|
|
if ( !that.resizing ) {
|
|
that._addClass( "ui-resizable-autohide" );
|
|
that._handles.hide();
|
|
}
|
|
} );
|
|
}
|
|
|
|
this._mouseInit();
|
|
},
|
|
|
|
_destroy: function() {
|
|
|
|
this._mouseDestroy();
|
|
|
|
var wrapper,
|
|
_destroy = function( exp ) {
|
|
$( exp )
|
|
.removeData( "resizable" )
|
|
.removeData( "ui-resizable" )
|
|
.off( ".resizable" )
|
|
.find( ".ui-resizable-handle" )
|
|
.remove();
|
|
};
|
|
|
|
// TODO: Unwrap at same DOM position
|
|
if ( this.elementIsWrapper ) {
|
|
_destroy( this.element );
|
|
wrapper = this.element;
|
|
this.originalElement.css( {
|
|
position: wrapper.css( "position" ),
|
|
width: wrapper.outerWidth(),
|
|
height: wrapper.outerHeight(),
|
|
top: wrapper.css( "top" ),
|
|
left: wrapper.css( "left" )
|
|
} ).insertAfter( wrapper );
|
|
wrapper.remove();
|
|
}
|
|
|
|
this.originalElement.css( "resize", this.originalResizeStyle );
|
|
_destroy( this.originalElement );
|
|
|
|
return this;
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
this._super( key, value );
|
|
|
|
switch ( key ) {
|
|
case "handles":
|
|
this._removeHandles();
|
|
this._setupHandles();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
},
|
|
|
|
_setupHandles: function() {
|
|
var o = this.options, handle, i, n, hname, axis, that = this;
|
|
this.handles = o.handles ||
|
|
( !$( ".ui-resizable-handle", this.element ).length ?
|
|
"e,s,se" : {
|
|
n: ".ui-resizable-n",
|
|
e: ".ui-resizable-e",
|
|
s: ".ui-resizable-s",
|
|
w: ".ui-resizable-w",
|
|
se: ".ui-resizable-se",
|
|
sw: ".ui-resizable-sw",
|
|
ne: ".ui-resizable-ne",
|
|
nw: ".ui-resizable-nw"
|
|
} );
|
|
|
|
this._handles = $();
|
|
if ( this.handles.constructor === String ) {
|
|
|
|
if ( this.handles === "all" ) {
|
|
this.handles = "n,e,s,w,se,sw,ne,nw";
|
|
}
|
|
|
|
n = this.handles.split( "," );
|
|
this.handles = {};
|
|
|
|
for ( i = 0; i < n.length; i++ ) {
|
|
|
|
handle = $.trim( n[ i ] );
|
|
hname = "ui-resizable-" + handle;
|
|
axis = $( "<div>" );
|
|
this._addClass( axis, "ui-resizable-handle " + hname );
|
|
|
|
axis.css( { zIndex: o.zIndex } );
|
|
|
|
this.handles[ handle ] = ".ui-resizable-" + handle;
|
|
this.element.append( axis );
|
|
}
|
|
|
|
}
|
|
|
|
this._renderAxis = function( target ) {
|
|
|
|
var i, axis, padPos, padWrapper;
|
|
|
|
target = target || this.element;
|
|
|
|
for ( i in this.handles ) {
|
|
|
|
if ( this.handles[ i ].constructor === String ) {
|
|
this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
|
|
} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
|
|
this.handles[ i ] = $( this.handles[ i ] );
|
|
this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
|
|
}
|
|
|
|
if ( this.elementIsWrapper &&
|
|
this.originalElement[ 0 ]
|
|
.nodeName
|
|
.match( /^(textarea|input|select|button)$/i ) ) {
|
|
axis = $( this.handles[ i ], this.element );
|
|
|
|
padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
|
|
axis.outerHeight() :
|
|
axis.outerWidth();
|
|
|
|
padPos = [ "padding",
|
|
/ne|nw|n/.test( i ) ? "Top" :
|
|
/se|sw|s/.test( i ) ? "Bottom" :
|
|
/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
|
|
|
|
target.css( padPos, padWrapper );
|
|
|
|
this._proportionallyResize();
|
|
}
|
|
|
|
this._handles = this._handles.add( this.handles[ i ] );
|
|
}
|
|
};
|
|
|
|
// TODO: make renderAxis a prototype function
|
|
this._renderAxis( this.element );
|
|
|
|
this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
|
|
this._handles.disableSelection();
|
|
|
|
this._handles.on( "mouseover", function() {
|
|
if ( !that.resizing ) {
|
|
if ( this.className ) {
|
|
axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
|
|
}
|
|
that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
|
|
}
|
|
} );
|
|
|
|
if ( o.autoHide ) {
|
|
this._handles.hide();
|
|
this._addClass( "ui-resizable-autohide" );
|
|
}
|
|
},
|
|
|
|
_removeHandles: function() {
|
|
this._handles.remove();
|
|
},
|
|
|
|
_mouseCapture: function( event ) {
|
|
var i, handle,
|
|
capture = false;
|
|
|
|
for ( i in this.handles ) {
|
|
handle = $( this.handles[ i ] )[ 0 ];
|
|
if ( handle === event.target || $.contains( handle, event.target ) ) {
|
|
capture = true;
|
|
}
|
|
}
|
|
|
|
return !this.options.disabled && capture;
|
|
},
|
|
|
|
_mouseStart: function( event ) {
|
|
|
|
var curleft, curtop, cursor,
|
|
o = this.options,
|
|
el = this.element;
|
|
|
|
this.resizing = true;
|
|
|
|
this._renderProxy();
|
|
|
|
curleft = this._num( this.helper.css( "left" ) );
|
|
curtop = this._num( this.helper.css( "top" ) );
|
|
|
|
if ( o.containment ) {
|
|
curleft += $( o.containment ).scrollLeft() || 0;
|
|
curtop += $( o.containment ).scrollTop() || 0;
|
|
}
|
|
|
|
this.offset = this.helper.offset();
|
|
this.position = { left: curleft, top: curtop };
|
|
|
|
this.size = this._helper ? {
|
|
width: this.helper.width(),
|
|
height: this.helper.height()
|
|
} : {
|
|
width: el.width(),
|
|
height: el.height()
|
|
};
|
|
|
|
this.originalSize = this._helper ? {
|
|
width: el.outerWidth(),
|
|
height: el.outerHeight()
|
|
} : {
|
|
width: el.width(),
|
|
height: el.height()
|
|
};
|
|
|
|
this.sizeDiff = {
|
|
width: el.outerWidth() - el.width(),
|
|
height: el.outerHeight() - el.height()
|
|
};
|
|
|
|
this.originalPosition = { left: curleft, top: curtop };
|
|
this.originalMousePosition = { left: event.pageX, top: event.pageY };
|
|
|
|
this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
|
|
o.aspectRatio :
|
|
( ( this.originalSize.width / this.originalSize.height ) || 1 );
|
|
|
|
cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
|
|
$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
|
|
|
|
this._addClass( "ui-resizable-resizing" );
|
|
this._propagate( "start", event );
|
|
return true;
|
|
},
|
|
|
|
_mouseDrag: function( event ) {
|
|
|
|
var data, props,
|
|
smp = this.originalMousePosition,
|
|
a = this.axis,
|
|
dx = ( event.pageX - smp.left ) || 0,
|
|
dy = ( event.pageY - smp.top ) || 0,
|
|
trigger = this._change[ a ];
|
|
|
|
this._updatePrevProperties();
|
|
|
|
if ( !trigger ) {
|
|
return false;
|
|
}
|
|
|
|
data = trigger.apply( this, [ event, dx, dy ] );
|
|
|
|
this._updateVirtualBoundaries( event.shiftKey );
|
|
if ( this._aspectRatio || event.shiftKey ) {
|
|
data = this._updateRatio( data, event );
|
|
}
|
|
|
|
data = this._respectSize( data, event );
|
|
|
|
this._updateCache( data );
|
|
|
|
this._propagate( "resize", event );
|
|
|
|
props = this._applyChanges();
|
|
|
|
if ( !this._helper && this._proportionallyResizeElements.length ) {
|
|
this._proportionallyResize();
|
|
}
|
|
|
|
if ( !$.isEmptyObject( props ) ) {
|
|
this._updatePrevProperties();
|
|
this._trigger( "resize", event, this.ui() );
|
|
this._applyChanges();
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
_mouseStop: function( event ) {
|
|
|
|
this.resizing = false;
|
|
var pr, ista, soffseth, soffsetw, s, left, top,
|
|
o = this.options, that = this;
|
|
|
|
if ( this._helper ) {
|
|
|
|
pr = this._proportionallyResizeElements;
|
|
ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
|
|
soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
|
|
soffsetw = ista ? 0 : that.sizeDiff.width;
|
|
|
|
s = {
|
|
width: ( that.helper.width() - soffsetw ),
|
|
height: ( that.helper.height() - soffseth )
|
|
};
|
|
left = ( parseFloat( that.element.css( "left" ) ) +
|
|
( that.position.left - that.originalPosition.left ) ) || null;
|
|
top = ( parseFloat( that.element.css( "top" ) ) +
|
|
( that.position.top - that.originalPosition.top ) ) || null;
|
|
|
|
if ( !o.animate ) {
|
|
this.element.css( $.extend( s, { top: top, left: left } ) );
|
|
}
|
|
|
|
that.helper.height( that.size.height );
|
|
that.helper.width( that.size.width );
|
|
|
|
if ( this._helper && !o.animate ) {
|
|
this._proportionallyResize();
|
|
}
|
|
}
|
|
|
|
$( "body" ).css( "cursor", "auto" );
|
|
|
|
this._removeClass( "ui-resizable-resizing" );
|
|
|
|
this._propagate( "stop", event );
|
|
|
|
if ( this._helper ) {
|
|
this.helper.remove();
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
_updatePrevProperties: function() {
|
|
this.prevPosition = {
|
|
top: this.position.top,
|
|
left: this.position.left
|
|
};
|
|
this.prevSize = {
|
|
width: this.size.width,
|
|
height: this.size.height
|
|
};
|
|
},
|
|
|
|
_applyChanges: function() {
|
|
var props = {};
|
|
|
|
if ( this.position.top !== this.prevPosition.top ) {
|
|
props.top = this.position.top + "px";
|
|
}
|
|
if ( this.position.left !== this.prevPosition.left ) {
|
|
props.left = this.position.left + "px";
|
|
}
|
|
if ( this.size.width !== this.prevSize.width ) {
|
|
props.width = this.size.width + "px";
|
|
}
|
|
if ( this.size.height !== this.prevSize.height ) {
|
|
props.height = this.size.height + "px";
|
|
}
|
|
|
|
this.helper.css( props );
|
|
|
|
return props;
|
|
},
|
|
|
|
_updateVirtualBoundaries: function( forceAspectRatio ) {
|
|
var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
|
|
o = this.options;
|
|
|
|
b = {
|
|
minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
|
|
maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
|
|
minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
|
|
maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
|
|
};
|
|
|
|
if ( this._aspectRatio || forceAspectRatio ) {
|
|
pMinWidth = b.minHeight * this.aspectRatio;
|
|
pMinHeight = b.minWidth / this.aspectRatio;
|
|
pMaxWidth = b.maxHeight * this.aspectRatio;
|
|
pMaxHeight = b.maxWidth / this.aspectRatio;
|
|
|
|
if ( pMinWidth > b.minWidth ) {
|
|
b.minWidth = pMinWidth;
|
|
}
|
|
if ( pMinHeight > b.minHeight ) {
|
|
b.minHeight = pMinHeight;
|
|
}
|
|
if ( pMaxWidth < b.maxWidth ) {
|
|
b.maxWidth = pMaxWidth;
|
|
}
|
|
if ( pMaxHeight < b.maxHeight ) {
|
|
b.maxHeight = pMaxHeight;
|
|
}
|
|
}
|
|
this._vBoundaries = b;
|
|
},
|
|
|
|
_updateCache: function( data ) {
|
|
this.offset = this.helper.offset();
|
|
if ( this._isNumber( data.left ) ) {
|
|
this.position.left = data.left;
|
|
}
|
|
if ( this._isNumber( data.top ) ) {
|
|
this.position.top = data.top;
|
|
}
|
|
if ( this._isNumber( data.height ) ) {
|
|
this.size.height = data.height;
|
|
}
|
|
if ( this._isNumber( data.width ) ) {
|
|
this.size.width = data.width;
|
|
}
|
|
},
|
|
|
|
_updateRatio: function( data ) {
|
|
|
|
var cpos = this.position,
|
|
csize = this.size,
|
|
a = this.axis;
|
|
|
|
if ( this._isNumber( data.height ) ) {
|
|
data.width = ( data.height * this.aspectRatio );
|
|
} else if ( this._isNumber( data.width ) ) {
|
|
data.height = ( data.width / this.aspectRatio );
|
|
}
|
|
|
|
if ( a === "sw" ) {
|
|
data.left = cpos.left + ( csize.width - data.width );
|
|
data.top = null;
|
|
}
|
|
if ( a === "nw" ) {
|
|
data.top = cpos.top + ( csize.height - data.height );
|
|
data.left = cpos.left + ( csize.width - data.width );
|
|
}
|
|
|
|
return data;
|
|
},
|
|
|
|
_respectSize: function( data ) {
|
|
|
|
var o = this._vBoundaries,
|
|
a = this.axis,
|
|
ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
|
|
ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
|
|
isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
|
|
isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
|
|
dw = this.originalPosition.left + this.originalSize.width,
|
|
dh = this.originalPosition.top + this.originalSize.height,
|
|
cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
|
|
if ( isminw ) {
|
|
data.width = o.minWidth;
|
|
}
|
|
if ( isminh ) {
|
|
data.height = o.minHeight;
|
|
}
|
|
if ( ismaxw ) {
|
|
data.width = o.maxWidth;
|
|
}
|
|
if ( ismaxh ) {
|
|
data.height = o.maxHeight;
|
|
}
|
|
|
|
if ( isminw && cw ) {
|
|
data.left = dw - o.minWidth;
|
|
}
|
|
if ( ismaxw && cw ) {
|
|
data.left = dw - o.maxWidth;
|
|
}
|
|
if ( isminh && ch ) {
|
|
data.top = dh - o.minHeight;
|
|
}
|
|
if ( ismaxh && ch ) {
|
|
data.top = dh - o.maxHeight;
|
|
}
|
|
|
|
// Fixing jump error on top/left - bug #2330
|
|
if ( !data.width && !data.height && !data.left && data.top ) {
|
|
data.top = null;
|
|
} else if ( !data.width && !data.height && !data.top && data.left ) {
|
|
data.left = null;
|
|
}
|
|
|
|
return data;
|
|
},
|
|
|
|
_getPaddingPlusBorderDimensions: function( element ) {
|
|
var i = 0,
|
|
widths = [],
|
|
borders = [
|
|
element.css( "borderTopWidth" ),
|
|
element.css( "borderRightWidth" ),
|
|
element.css( "borderBottomWidth" ),
|
|
element.css( "borderLeftWidth" )
|
|
],
|
|
paddings = [
|
|
element.css( "paddingTop" ),
|
|
element.css( "paddingRight" ),
|
|
element.css( "paddingBottom" ),
|
|
element.css( "paddingLeft" )
|
|
];
|
|
|
|
for ( ; i < 4; i++ ) {
|
|
widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
|
|
widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
|
|
}
|
|
|
|
return {
|
|
height: widths[ 0 ] + widths[ 2 ],
|
|
width: widths[ 1 ] + widths[ 3 ]
|
|
};
|
|
},
|
|
|
|
_proportionallyResize: function() {
|
|
|
|
if ( !this._proportionallyResizeElements.length ) {
|
|
return;
|
|
}
|
|
|
|
var prel,
|
|
i = 0,
|
|
element = this.helper || this.element;
|
|
|
|
for ( ; i < this._proportionallyResizeElements.length; i++ ) {
|
|
|
|
prel = this._proportionallyResizeElements[ i ];
|
|
|
|
// TODO: Seems like a bug to cache this.outerDimensions
|
|
// considering that we are in a loop.
|
|
if ( !this.outerDimensions ) {
|
|
this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
|
|
}
|
|
|
|
prel.css( {
|
|
height: ( element.height() - this.outerDimensions.height ) || 0,
|
|
width: ( element.width() - this.outerDimensions.width ) || 0
|
|
} );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_renderProxy: function() {
|
|
|
|
var el = this.element, o = this.options;
|
|
this.elementOffset = el.offset();
|
|
|
|
if ( this._helper ) {
|
|
|
|
this.helper = this.helper || $( "<div style='overflow:hidden;'></div>" );
|
|
|
|
this._addClass( this.helper, this._helper );
|
|
this.helper.css( {
|
|
width: this.element.outerWidth(),
|
|
height: this.element.outerHeight(),
|
|
position: "absolute",
|
|
left: this.elementOffset.left + "px",
|
|
top: this.elementOffset.top + "px",
|
|
zIndex: ++o.zIndex //TODO: Don't modify option
|
|
} );
|
|
|
|
this.helper
|
|
.appendTo( "body" )
|
|
.disableSelection();
|
|
|
|
} else {
|
|
this.helper = this.element;
|
|
}
|
|
|
|
},
|
|
|
|
_change: {
|
|
e: function( event, dx ) {
|
|
return { width: this.originalSize.width + dx };
|
|
},
|
|
w: function( event, dx ) {
|
|
var cs = this.originalSize, sp = this.originalPosition;
|
|
return { left: sp.left + dx, width: cs.width - dx };
|
|
},
|
|
n: function( event, dx, dy ) {
|
|
var cs = this.originalSize, sp = this.originalPosition;
|
|
return { top: sp.top + dy, height: cs.height - dy };
|
|
},
|
|
s: function( event, dx, dy ) {
|
|
return { height: this.originalSize.height + dy };
|
|
},
|
|
se: function( event, dx, dy ) {
|
|
return $.extend( this._change.s.apply( this, arguments ),
|
|
this._change.e.apply( this, [ event, dx, dy ] ) );
|
|
},
|
|
sw: function( event, dx, dy ) {
|
|
return $.extend( this._change.s.apply( this, arguments ),
|
|
this._change.w.apply( this, [ event, dx, dy ] ) );
|
|
},
|
|
ne: function( event, dx, dy ) {
|
|
return $.extend( this._change.n.apply( this, arguments ),
|
|
this._change.e.apply( this, [ event, dx, dy ] ) );
|
|
},
|
|
nw: function( event, dx, dy ) {
|
|
return $.extend( this._change.n.apply( this, arguments ),
|
|
this._change.w.apply( this, [ event, dx, dy ] ) );
|
|
}
|
|
},
|
|
|
|
_propagate: function( n, event ) {
|
|
$.ui.plugin.call( this, n, [ event, this.ui() ] );
|
|
( n !== "resize" && this._trigger( n, event, this.ui() ) );
|
|
},
|
|
|
|
plugins: {},
|
|
|
|
ui: function() {
|
|
return {
|
|
originalElement: this.originalElement,
|
|
element: this.element,
|
|
helper: this.helper,
|
|
position: this.position,
|
|
size: this.size,
|
|
originalSize: this.originalSize,
|
|
originalPosition: this.originalPosition
|
|
};
|
|
}
|
|
|
|
} );
|
|
|
|
/*
|
|
* Resizable Extensions
|
|
*/
|
|
|
|
$.ui.plugin.add( "resizable", "animate", {
|
|
|
|
stop: function( event ) {
|
|
var that = $( this ).resizable( "instance" ),
|
|
o = that.options,
|
|
pr = that._proportionallyResizeElements,
|
|
ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
|
|
soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
|
|
soffsetw = ista ? 0 : that.sizeDiff.width,
|
|
style = {
|
|
width: ( that.size.width - soffsetw ),
|
|
height: ( that.size.height - soffseth )
|
|
},
|
|
left = ( parseFloat( that.element.css( "left" ) ) +
|
|
( that.position.left - that.originalPosition.left ) ) || null,
|
|
top = ( parseFloat( that.element.css( "top" ) ) +
|
|
( that.position.top - that.originalPosition.top ) ) || null;
|
|
|
|
that.element.animate(
|
|
$.extend( style, top && left ? { top: top, left: left } : {} ), {
|
|
duration: o.animateDuration,
|
|
easing: o.animateEasing,
|
|
step: function() {
|
|
|
|
var data = {
|
|
width: parseFloat( that.element.css( "width" ) ),
|
|
height: parseFloat( that.element.css( "height" ) ),
|
|
top: parseFloat( that.element.css( "top" ) ),
|
|
left: parseFloat( that.element.css( "left" ) )
|
|
};
|
|
|
|
if ( pr && pr.length ) {
|
|
$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
|
|
}
|
|
|
|
// Propagating resize, and updating values for each animation step
|
|
that._updateCache( data );
|
|
that._propagate( "resize", event );
|
|
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
} );
|
|
|
|
$.ui.plugin.add( "resizable", "containment", {
|
|
|
|
start: function() {
|
|
var element, p, co, ch, cw, width, height,
|
|
that = $( this ).resizable( "instance" ),
|
|
o = that.options,
|
|
el = that.element,
|
|
oc = o.containment,
|
|
ce = ( oc instanceof $ ) ?
|
|
oc.get( 0 ) :
|
|
( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
|
|
|
|
if ( !ce ) {
|
|
return;
|
|
}
|
|
|
|
that.containerElement = $( ce );
|
|
|
|
if ( /document/.test( oc ) || oc === document ) {
|
|
that.containerOffset = {
|
|
left: 0,
|
|
top: 0
|
|
};
|
|
that.containerPosition = {
|
|
left: 0,
|
|
top: 0
|
|
};
|
|
|
|
that.parentData = {
|
|
element: $( document ),
|
|
left: 0,
|
|
top: 0,
|
|
width: $( document ).width(),
|
|
height: $( document ).height() || document.body.parentNode.scrollHeight
|
|
};
|
|
} else {
|
|
element = $( ce );
|
|
p = [];
|
|
$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
|
|
p[ i ] = that._num( element.css( "padding" + name ) );
|
|
} );
|
|
|
|
that.containerOffset = element.offset();
|
|
that.containerPosition = element.position();
|
|
that.containerSize = {
|
|
height: ( element.innerHeight() - p[ 3 ] ),
|
|
width: ( element.innerWidth() - p[ 1 ] )
|
|
};
|
|
|
|
co = that.containerOffset;
|
|
ch = that.containerSize.height;
|
|
cw = that.containerSize.width;
|
|
width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
|
|
height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
|
|
|
|
that.parentData = {
|
|
element: ce,
|
|
left: co.left,
|
|
top: co.top,
|
|
width: width,
|
|
height: height
|
|
};
|
|
}
|
|
},
|
|
|
|
resize: function( event ) {
|
|
var woset, hoset, isParent, isOffsetRelative,
|
|
that = $( this ).resizable( "instance" ),
|
|
o = that.options,
|
|
co = that.containerOffset,
|
|
cp = that.position,
|
|
pRatio = that._aspectRatio || event.shiftKey,
|
|
cop = {
|
|
top: 0,
|
|
left: 0
|
|
},
|
|
ce = that.containerElement,
|
|
continueResize = true;
|
|
|
|
if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
|
|
cop = co;
|
|
}
|
|
|
|
if ( cp.left < ( that._helper ? co.left : 0 ) ) {
|
|
that.size.width = that.size.width +
|
|
( that._helper ?
|
|
( that.position.left - co.left ) :
|
|
( that.position.left - cop.left ) );
|
|
|
|
if ( pRatio ) {
|
|
that.size.height = that.size.width / that.aspectRatio;
|
|
continueResize = false;
|
|
}
|
|
that.position.left = o.helper ? co.left : 0;
|
|
}
|
|
|
|
if ( cp.top < ( that._helper ? co.top : 0 ) ) {
|
|
that.size.height = that.size.height +
|
|
( that._helper ?
|
|
( that.position.top - co.top ) :
|
|
that.position.top );
|
|
|
|
if ( pRatio ) {
|
|
that.size.width = that.size.height * that.aspectRatio;
|
|
continueResize = false;
|
|
}
|
|
that.position.top = that._helper ? co.top : 0;
|
|
}
|
|
|
|
isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
|
|
isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
|
|
|
|
if ( isParent && isOffsetRelative ) {
|
|
that.offset.left = that.parentData.left + that.position.left;
|
|
that.offset.top = that.parentData.top + that.position.top;
|
|
} else {
|
|
that.offset.left = that.element.offset().left;
|
|
that.offset.top = that.element.offset().top;
|
|
}
|
|
|
|
woset = Math.abs( that.sizeDiff.width +
|
|
( that._helper ?
|
|
that.offset.left - cop.left :
|
|
( that.offset.left - co.left ) ) );
|
|
|
|
hoset = Math.abs( that.sizeDiff.height +
|
|
( that._helper ?
|
|
that.offset.top - cop.top :
|
|
( that.offset.top - co.top ) ) );
|
|
|
|
if ( woset + that.size.width >= that.parentData.width ) {
|
|
that.size.width = that.parentData.width - woset;
|
|
if ( pRatio ) {
|
|
that.size.height = that.size.width / that.aspectRatio;
|
|
continueResize = false;
|
|
}
|
|
}
|
|
|
|
if ( hoset + that.size.height >= that.parentData.height ) {
|
|
that.size.height = that.parentData.height - hoset;
|
|
if ( pRatio ) {
|
|
that.size.width = that.size.height * that.aspectRatio;
|
|
continueResize = false;
|
|
}
|
|
}
|
|
|
|
if ( !continueResize ) {
|
|
that.position.left = that.prevPosition.left;
|
|
that.position.top = that.prevPosition.top;
|
|
that.size.width = that.prevSize.width;
|
|
that.size.height = that.prevSize.height;
|
|
}
|
|
},
|
|
|
|
stop: function() {
|
|
var that = $( this ).resizable( "instance" ),
|
|
o = that.options,
|
|
co = that.containerOffset,
|
|
cop = that.containerPosition,
|
|
ce = that.containerElement,
|
|
helper = $( that.helper ),
|
|
ho = helper.offset(),
|
|
w = helper.outerWidth() - that.sizeDiff.width,
|
|
h = helper.outerHeight() - that.sizeDiff.height;
|
|
|
|
if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
|
|
$( this ).css( {
|
|
left: ho.left - cop.left - co.left,
|
|
width: w,
|
|
height: h
|
|
} );
|
|
}
|
|
|
|
if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
|
|
$( this ).css( {
|
|
left: ho.left - cop.left - co.left,
|
|
width: w,
|
|
height: h
|
|
} );
|
|
}
|
|
}
|
|
} );
|
|
|
|
$.ui.plugin.add( "resizable", "alsoResize", {
|
|
|
|
start: function() {
|
|
var that = $( this ).resizable( "instance" ),
|
|
o = that.options;
|
|
|
|
$( o.alsoResize ).each( function() {
|
|
var el = $( this );
|
|
el.data( "ui-resizable-alsoresize", {
|
|
width: parseFloat( el.width() ), height: parseFloat( el.height() ),
|
|
left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
|
|
} );
|
|
} );
|
|
},
|
|
|
|
resize: function( event, ui ) {
|
|
var that = $( this ).resizable( "instance" ),
|
|
o = that.options,
|
|
os = that.originalSize,
|
|
op = that.originalPosition,
|
|
delta = {
|
|
height: ( that.size.height - os.height ) || 0,
|
|
width: ( that.size.width - os.width ) || 0,
|
|
top: ( that.position.top - op.top ) || 0,
|
|
left: ( that.position.left - op.left ) || 0
|
|
};
|
|
|
|
$( o.alsoResize ).each( function() {
|
|
var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
|
|
css = el.parents( ui.originalElement[ 0 ] ).length ?
|
|
[ "width", "height" ] :
|
|
[ "width", "height", "top", "left" ];
|
|
|
|
$.each( css, function( i, prop ) {
|
|
var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
|
|
if ( sum && sum >= 0 ) {
|
|
style[ prop ] = sum || null;
|
|
}
|
|
} );
|
|
|
|
el.css( style );
|
|
} );
|
|
},
|
|
|
|
stop: function() {
|
|
$( this ).removeData( "ui-resizable-alsoresize" );
|
|
}
|
|
} );
|
|
|
|
$.ui.plugin.add( "resizable", "ghost", {
|
|
|
|
start: function() {
|
|
|
|
var that = $( this ).resizable( "instance" ), cs = that.size;
|
|
|
|
that.ghost = that.originalElement.clone();
|
|
that.ghost.css( {
|
|
opacity: 0.25,
|
|
display: "block",
|
|
position: "relative",
|
|
height: cs.height,
|
|
width: cs.width,
|
|
margin: 0,
|
|
left: 0,
|
|
top: 0
|
|
} );
|
|
|
|
that._addClass( that.ghost, "ui-resizable-ghost" );
|
|
|
|
// DEPRECATED
|
|
// TODO: remove after 1.12
|
|
if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {
|
|
|
|
// Ghost option
|
|
that.ghost.addClass( this.options.ghost );
|
|
}
|
|
|
|
that.ghost.appendTo( that.helper );
|
|
|
|
},
|
|
|
|
resize: function() {
|
|
var that = $( this ).resizable( "instance" );
|
|
if ( that.ghost ) {
|
|
that.ghost.css( {
|
|
position: "relative",
|
|
height: that.size.height,
|
|
width: that.size.width
|
|
} );
|
|
}
|
|
},
|
|
|
|
stop: function() {
|
|
var that = $( this ).resizable( "instance" );
|
|
if ( that.ghost && that.helper ) {
|
|
that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
|
|
}
|
|
}
|
|
|
|
} );
|
|
|
|
$.ui.plugin.add( "resizable", "grid", {
|
|
|
|
resize: function() {
|
|
var outerDimensions,
|
|
that = $( this ).resizable( "instance" ),
|
|
o = that.options,
|
|
cs = that.size,
|
|
os = that.originalSize,
|
|
op = that.originalPosition,
|
|
a = that.axis,
|
|
grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
|
|
gridX = ( grid[ 0 ] || 1 ),
|
|
gridY = ( grid[ 1 ] || 1 ),
|
|
ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
|
|
oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
|
|
newWidth = os.width + ox,
|
|
newHeight = os.height + oy,
|
|
isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
|
|
isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
|
|
isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
|
|
isMinHeight = o.minHeight && ( o.minHeight > newHeight );
|
|
|
|
o.grid = grid;
|
|
|
|
if ( isMinWidth ) {
|
|
newWidth += gridX;
|
|
}
|
|
if ( isMinHeight ) {
|
|
newHeight += gridY;
|
|
}
|
|
if ( isMaxWidth ) {
|
|
newWidth -= gridX;
|
|
}
|
|
if ( isMaxHeight ) {
|
|
newHeight -= gridY;
|
|
}
|
|
|
|
if ( /^(se|s|e)$/.test( a ) ) {
|
|
that.size.width = newWidth;
|
|
that.size.height = newHeight;
|
|
} else if ( /^(ne)$/.test( a ) ) {
|
|
that.size.width = newWidth;
|
|
that.size.height = newHeight;
|
|
that.position.top = op.top - oy;
|
|
} else if ( /^(sw)$/.test( a ) ) {
|
|
that.size.width = newWidth;
|
|
that.size.height = newHeight;
|
|
that.position.left = op.left - ox;
|
|
} else {
|
|
if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
|
|
outerDimensions = that._getPaddingPlusBorderDimensions( this );
|
|
}
|
|
|
|
if ( newHeight - gridY > 0 ) {
|
|
that.size.height = newHeight;
|
|
that.position.top = op.top - oy;
|
|
} else {
|
|
newHeight = gridY - outerDimensions.height;
|
|
that.size.height = newHeight;
|
|
that.position.top = op.top + os.height - newHeight;
|
|
}
|
|
if ( newWidth - gridX > 0 ) {
|
|
that.size.width = newWidth;
|
|
that.position.left = op.left - ox;
|
|
} else {
|
|
newWidth = gridX - outerDimensions.width;
|
|
that.size.width = newWidth;
|
|
that.position.left = op.left + os.width - newWidth;
|
|
}
|
|
}
|
|
}
|
|
|
|
} );
|
|
|
|
return $.ui.resizable;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 59 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Dialog 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Dialog
|
|
//>>group: Widgets
|
|
//>>description: Displays customizable dialog windows.
|
|
//>>docs: http://api.jqueryui.com/dialog/
|
|
//>>demos: http://jqueryui.com/dialog/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/dialog.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(55),
|
|
__webpack_require__(57),
|
|
__webpack_require__(56),
|
|
__webpack_require__(58),
|
|
__webpack_require__(40),
|
|
__webpack_require__(43),
|
|
__webpack_require__(21),
|
|
__webpack_require__(18),
|
|
__webpack_require__(19),
|
|
__webpack_require__(47),
|
|
__webpack_require__(48),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
$.widget( "ui.dialog", {
|
|
version: "1.12.1",
|
|
options: {
|
|
appendTo: "body",
|
|
autoOpen: true,
|
|
buttons: [],
|
|
classes: {
|
|
"ui-dialog": "ui-corner-all",
|
|
"ui-dialog-titlebar": "ui-corner-all"
|
|
},
|
|
closeOnEscape: true,
|
|
closeText: "Close",
|
|
draggable: true,
|
|
hide: null,
|
|
height: "auto",
|
|
maxHeight: null,
|
|
maxWidth: null,
|
|
minHeight: 150,
|
|
minWidth: 150,
|
|
modal: false,
|
|
position: {
|
|
my: "center",
|
|
at: "center",
|
|
of: window,
|
|
collision: "fit",
|
|
|
|
// Ensure the titlebar is always visible
|
|
using: function( pos ) {
|
|
var topOffset = $( this ).css( pos ).offset().top;
|
|
if ( topOffset < 0 ) {
|
|
$( this ).css( "top", pos.top - topOffset );
|
|
}
|
|
}
|
|
},
|
|
resizable: true,
|
|
show: null,
|
|
title: null,
|
|
width: 300,
|
|
|
|
// Callbacks
|
|
beforeClose: null,
|
|
close: null,
|
|
drag: null,
|
|
dragStart: null,
|
|
dragStop: null,
|
|
focus: null,
|
|
open: null,
|
|
resize: null,
|
|
resizeStart: null,
|
|
resizeStop: null
|
|
},
|
|
|
|
sizeRelatedOptions: {
|
|
buttons: true,
|
|
height: true,
|
|
maxHeight: true,
|
|
maxWidth: true,
|
|
minHeight: true,
|
|
minWidth: true,
|
|
width: true
|
|
},
|
|
|
|
resizableRelatedOptions: {
|
|
maxHeight: true,
|
|
maxWidth: true,
|
|
minHeight: true,
|
|
minWidth: true
|
|
},
|
|
|
|
_create: function() {
|
|
this.originalCss = {
|
|
display: this.element[ 0 ].style.display,
|
|
width: this.element[ 0 ].style.width,
|
|
minHeight: this.element[ 0 ].style.minHeight,
|
|
maxHeight: this.element[ 0 ].style.maxHeight,
|
|
height: this.element[ 0 ].style.height
|
|
};
|
|
this.originalPosition = {
|
|
parent: this.element.parent(),
|
|
index: this.element.parent().children().index( this.element )
|
|
};
|
|
this.originalTitle = this.element.attr( "title" );
|
|
if ( this.options.title == null && this.originalTitle != null ) {
|
|
this.options.title = this.originalTitle;
|
|
}
|
|
|
|
// Dialogs can't be disabled
|
|
if ( this.options.disabled ) {
|
|
this.options.disabled = false;
|
|
}
|
|
|
|
this._createWrapper();
|
|
|
|
this.element
|
|
.show()
|
|
.removeAttr( "title" )
|
|
.appendTo( this.uiDialog );
|
|
|
|
this._addClass( "ui-dialog-content", "ui-widget-content" );
|
|
|
|
this._createTitlebar();
|
|
this._createButtonPane();
|
|
|
|
if ( this.options.draggable && $.fn.draggable ) {
|
|
this._makeDraggable();
|
|
}
|
|
if ( this.options.resizable && $.fn.resizable ) {
|
|
this._makeResizable();
|
|
}
|
|
|
|
this._isOpen = false;
|
|
|
|
this._trackFocus();
|
|
},
|
|
|
|
_init: function() {
|
|
if ( this.options.autoOpen ) {
|
|
this.open();
|
|
}
|
|
},
|
|
|
|
_appendTo: function() {
|
|
var element = this.options.appendTo;
|
|
if ( element && ( element.jquery || element.nodeType ) ) {
|
|
return $( element );
|
|
}
|
|
return this.document.find( element || "body" ).eq( 0 );
|
|
},
|
|
|
|
_destroy: function() {
|
|
var next,
|
|
originalPosition = this.originalPosition;
|
|
|
|
this._untrackInstance();
|
|
this._destroyOverlay();
|
|
|
|
this.element
|
|
.removeUniqueId()
|
|
.css( this.originalCss )
|
|
|
|
// Without detaching first, the following becomes really slow
|
|
.detach();
|
|
|
|
this.uiDialog.remove();
|
|
|
|
if ( this.originalTitle ) {
|
|
this.element.attr( "title", this.originalTitle );
|
|
}
|
|
|
|
next = originalPosition.parent.children().eq( originalPosition.index );
|
|
|
|
// Don't try to place the dialog next to itself (#8613)
|
|
if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
|
|
next.before( this.element );
|
|
} else {
|
|
originalPosition.parent.append( this.element );
|
|
}
|
|
},
|
|
|
|
widget: function() {
|
|
return this.uiDialog;
|
|
},
|
|
|
|
disable: $.noop,
|
|
enable: $.noop,
|
|
|
|
close: function( event ) {
|
|
var that = this;
|
|
|
|
if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
|
|
return;
|
|
}
|
|
|
|
this._isOpen = false;
|
|
this._focusedElement = null;
|
|
this._destroyOverlay();
|
|
this._untrackInstance();
|
|
|
|
if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
|
|
|
|
// Hiding a focused element doesn't trigger blur in WebKit
|
|
// so in case we have nothing to focus on, explicitly blur the active element
|
|
// https://bugs.webkit.org/show_bug.cgi?id=47182
|
|
$.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );
|
|
}
|
|
|
|
this._hide( this.uiDialog, this.options.hide, function() {
|
|
that._trigger( "close", event );
|
|
} );
|
|
},
|
|
|
|
isOpen: function() {
|
|
return this._isOpen;
|
|
},
|
|
|
|
moveToTop: function() {
|
|
this._moveToTop();
|
|
},
|
|
|
|
_moveToTop: function( event, silent ) {
|
|
var moved = false,
|
|
zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
|
|
return +$( this ).css( "z-index" );
|
|
} ).get(),
|
|
zIndexMax = Math.max.apply( null, zIndices );
|
|
|
|
if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
|
|
this.uiDialog.css( "z-index", zIndexMax + 1 );
|
|
moved = true;
|
|
}
|
|
|
|
if ( moved && !silent ) {
|
|
this._trigger( "focus", event );
|
|
}
|
|
return moved;
|
|
},
|
|
|
|
open: function() {
|
|
var that = this;
|
|
if ( this._isOpen ) {
|
|
if ( this._moveToTop() ) {
|
|
this._focusTabbable();
|
|
}
|
|
return;
|
|
}
|
|
|
|
this._isOpen = true;
|
|
this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
|
|
|
|
this._size();
|
|
this._position();
|
|
this._createOverlay();
|
|
this._moveToTop( null, true );
|
|
|
|
// Ensure the overlay is moved to the top with the dialog, but only when
|
|
// opening. The overlay shouldn't move after the dialog is open so that
|
|
// modeless dialogs opened after the modal dialog stack properly.
|
|
if ( this.overlay ) {
|
|
this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
|
|
}
|
|
|
|
this._show( this.uiDialog, this.options.show, function() {
|
|
that._focusTabbable();
|
|
that._trigger( "focus" );
|
|
} );
|
|
|
|
// Track the dialog immediately upon openening in case a focus event
|
|
// somehow occurs outside of the dialog before an element inside the
|
|
// dialog is focused (#10152)
|
|
this._makeFocusTarget();
|
|
|
|
this._trigger( "open" );
|
|
},
|
|
|
|
_focusTabbable: function() {
|
|
|
|
// Set focus to the first match:
|
|
// 1. An element that was focused previously
|
|
// 2. First element inside the dialog matching [autofocus]
|
|
// 3. Tabbable element inside the content element
|
|
// 4. Tabbable element inside the buttonpane
|
|
// 5. The close button
|
|
// 6. The dialog itself
|
|
var hasFocus = this._focusedElement;
|
|
if ( !hasFocus ) {
|
|
hasFocus = this.element.find( "[autofocus]" );
|
|
}
|
|
if ( !hasFocus.length ) {
|
|
hasFocus = this.element.find( ":tabbable" );
|
|
}
|
|
if ( !hasFocus.length ) {
|
|
hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
|
|
}
|
|
if ( !hasFocus.length ) {
|
|
hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
|
|
}
|
|
if ( !hasFocus.length ) {
|
|
hasFocus = this.uiDialog;
|
|
}
|
|
hasFocus.eq( 0 ).trigger( "focus" );
|
|
},
|
|
|
|
_keepFocus: function( event ) {
|
|
function checkFocus() {
|
|
var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
|
|
isActive = this.uiDialog[ 0 ] === activeElement ||
|
|
$.contains( this.uiDialog[ 0 ], activeElement );
|
|
if ( !isActive ) {
|
|
this._focusTabbable();
|
|
}
|
|
}
|
|
event.preventDefault();
|
|
checkFocus.call( this );
|
|
|
|
// support: IE
|
|
// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
|
|
// so we check again later
|
|
this._delay( checkFocus );
|
|
},
|
|
|
|
_createWrapper: function() {
|
|
this.uiDialog = $( "<div>" )
|
|
.hide()
|
|
.attr( {
|
|
|
|
// Setting tabIndex makes the div focusable
|
|
tabIndex: -1,
|
|
role: "dialog"
|
|
} )
|
|
.appendTo( this._appendTo() );
|
|
|
|
this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
|
|
this._on( this.uiDialog, {
|
|
keydown: function( event ) {
|
|
if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
|
|
event.keyCode === $.ui.keyCode.ESCAPE ) {
|
|
event.preventDefault();
|
|
this.close( event );
|
|
return;
|
|
}
|
|
|
|
// Prevent tabbing out of dialogs
|
|
if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
|
|
return;
|
|
}
|
|
var tabbables = this.uiDialog.find( ":tabbable" ),
|
|
first = tabbables.filter( ":first" ),
|
|
last = tabbables.filter( ":last" );
|
|
|
|
if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
|
|
!event.shiftKey ) {
|
|
this._delay( function() {
|
|
first.trigger( "focus" );
|
|
} );
|
|
event.preventDefault();
|
|
} else if ( ( event.target === first[ 0 ] ||
|
|
event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
|
|
this._delay( function() {
|
|
last.trigger( "focus" );
|
|
} );
|
|
event.preventDefault();
|
|
}
|
|
},
|
|
mousedown: function( event ) {
|
|
if ( this._moveToTop( event ) ) {
|
|
this._focusTabbable();
|
|
}
|
|
}
|
|
} );
|
|
|
|
// We assume that any existing aria-describedby attribute means
|
|
// that the dialog content is marked up properly
|
|
// otherwise we brute force the content as the description
|
|
if ( !this.element.find( "[aria-describedby]" ).length ) {
|
|
this.uiDialog.attr( {
|
|
"aria-describedby": this.element.uniqueId().attr( "id" )
|
|
} );
|
|
}
|
|
},
|
|
|
|
_createTitlebar: function() {
|
|
var uiDialogTitle;
|
|
|
|
this.uiDialogTitlebar = $( "<div>" );
|
|
this._addClass( this.uiDialogTitlebar,
|
|
"ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
|
|
this._on( this.uiDialogTitlebar, {
|
|
mousedown: function( event ) {
|
|
|
|
// Don't prevent click on close button (#8838)
|
|
// Focusing a dialog that is partially scrolled out of view
|
|
// causes the browser to scroll it into view, preventing the click event
|
|
if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
|
|
|
|
// Dialog isn't getting focus when dragging (#8063)
|
|
this.uiDialog.trigger( "focus" );
|
|
}
|
|
}
|
|
} );
|
|
|
|
// Support: IE
|
|
// Use type="button" to prevent enter keypresses in textboxes from closing the
|
|
// dialog in IE (#9312)
|
|
this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
|
|
.button( {
|
|
label: $( "<a>" ).text( this.options.closeText ).html(),
|
|
icon: "ui-icon-closethick",
|
|
showLabel: false
|
|
} )
|
|
.appendTo( this.uiDialogTitlebar );
|
|
|
|
this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
|
|
this._on( this.uiDialogTitlebarClose, {
|
|
click: function( event ) {
|
|
event.preventDefault();
|
|
this.close( event );
|
|
}
|
|
} );
|
|
|
|
uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
|
|
this._addClass( uiDialogTitle, "ui-dialog-title" );
|
|
this._title( uiDialogTitle );
|
|
|
|
this.uiDialogTitlebar.prependTo( this.uiDialog );
|
|
|
|
this.uiDialog.attr( {
|
|
"aria-labelledby": uiDialogTitle.attr( "id" )
|
|
} );
|
|
},
|
|
|
|
_title: function( title ) {
|
|
if ( this.options.title ) {
|
|
title.text( this.options.title );
|
|
} else {
|
|
title.html( " " );
|
|
}
|
|
},
|
|
|
|
_createButtonPane: function() {
|
|
this.uiDialogButtonPane = $( "<div>" );
|
|
this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
|
|
"ui-widget-content ui-helper-clearfix" );
|
|
|
|
this.uiButtonSet = $( "<div>" )
|
|
.appendTo( this.uiDialogButtonPane );
|
|
this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
|
|
|
|
this._createButtons();
|
|
},
|
|
|
|
_createButtons: function() {
|
|
var that = this,
|
|
buttons = this.options.buttons;
|
|
|
|
// If we already have a button pane, remove it
|
|
this.uiDialogButtonPane.remove();
|
|
this.uiButtonSet.empty();
|
|
|
|
if ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) {
|
|
this._removeClass( this.uiDialog, "ui-dialog-buttons" );
|
|
return;
|
|
}
|
|
|
|
$.each( buttons, function( name, props ) {
|
|
var click, buttonOptions;
|
|
props = $.isFunction( props ) ?
|
|
{ click: props, text: name } :
|
|
props;
|
|
|
|
// Default to a non-submitting button
|
|
props = $.extend( { type: "button" }, props );
|
|
|
|
// Change the context for the click callback to be the main element
|
|
click = props.click;
|
|
buttonOptions = {
|
|
icon: props.icon,
|
|
iconPosition: props.iconPosition,
|
|
showLabel: props.showLabel,
|
|
|
|
// Deprecated options
|
|
icons: props.icons,
|
|
text: props.text
|
|
};
|
|
|
|
delete props.click;
|
|
delete props.icon;
|
|
delete props.iconPosition;
|
|
delete props.showLabel;
|
|
|
|
// Deprecated options
|
|
delete props.icons;
|
|
if ( typeof props.text === "boolean" ) {
|
|
delete props.text;
|
|
}
|
|
|
|
$( "<button></button>", props )
|
|
.button( buttonOptions )
|
|
.appendTo( that.uiButtonSet )
|
|
.on( "click", function() {
|
|
click.apply( that.element[ 0 ], arguments );
|
|
} );
|
|
} );
|
|
this._addClass( this.uiDialog, "ui-dialog-buttons" );
|
|
this.uiDialogButtonPane.appendTo( this.uiDialog );
|
|
},
|
|
|
|
_makeDraggable: function() {
|
|
var that = this,
|
|
options = this.options;
|
|
|
|
function filteredUi( ui ) {
|
|
return {
|
|
position: ui.position,
|
|
offset: ui.offset
|
|
};
|
|
}
|
|
|
|
this.uiDialog.draggable( {
|
|
cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
|
|
handle: ".ui-dialog-titlebar",
|
|
containment: "document",
|
|
start: function( event, ui ) {
|
|
that._addClass( $( this ), "ui-dialog-dragging" );
|
|
that._blockFrames();
|
|
that._trigger( "dragStart", event, filteredUi( ui ) );
|
|
},
|
|
drag: function( event, ui ) {
|
|
that._trigger( "drag", event, filteredUi( ui ) );
|
|
},
|
|
stop: function( event, ui ) {
|
|
var left = ui.offset.left - that.document.scrollLeft(),
|
|
top = ui.offset.top - that.document.scrollTop();
|
|
|
|
options.position = {
|
|
my: "left top",
|
|
at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
|
|
"top" + ( top >= 0 ? "+" : "" ) + top,
|
|
of: that.window
|
|
};
|
|
that._removeClass( $( this ), "ui-dialog-dragging" );
|
|
that._unblockFrames();
|
|
that._trigger( "dragStop", event, filteredUi( ui ) );
|
|
}
|
|
} );
|
|
},
|
|
|
|
_makeResizable: function() {
|
|
var that = this,
|
|
options = this.options,
|
|
handles = options.resizable,
|
|
|
|
// .ui-resizable has position: relative defined in the stylesheet
|
|
// but dialogs have to use absolute or fixed positioning
|
|
position = this.uiDialog.css( "position" ),
|
|
resizeHandles = typeof handles === "string" ?
|
|
handles :
|
|
"n,e,s,w,se,sw,ne,nw";
|
|
|
|
function filteredUi( ui ) {
|
|
return {
|
|
originalPosition: ui.originalPosition,
|
|
originalSize: ui.originalSize,
|
|
position: ui.position,
|
|
size: ui.size
|
|
};
|
|
}
|
|
|
|
this.uiDialog.resizable( {
|
|
cancel: ".ui-dialog-content",
|
|
containment: "document",
|
|
alsoResize: this.element,
|
|
maxWidth: options.maxWidth,
|
|
maxHeight: options.maxHeight,
|
|
minWidth: options.minWidth,
|
|
minHeight: this._minHeight(),
|
|
handles: resizeHandles,
|
|
start: function( event, ui ) {
|
|
that._addClass( $( this ), "ui-dialog-resizing" );
|
|
that._blockFrames();
|
|
that._trigger( "resizeStart", event, filteredUi( ui ) );
|
|
},
|
|
resize: function( event, ui ) {
|
|
that._trigger( "resize", event, filteredUi( ui ) );
|
|
},
|
|
stop: function( event, ui ) {
|
|
var offset = that.uiDialog.offset(),
|
|
left = offset.left - that.document.scrollLeft(),
|
|
top = offset.top - that.document.scrollTop();
|
|
|
|
options.height = that.uiDialog.height();
|
|
options.width = that.uiDialog.width();
|
|
options.position = {
|
|
my: "left top",
|
|
at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
|
|
"top" + ( top >= 0 ? "+" : "" ) + top,
|
|
of: that.window
|
|
};
|
|
that._removeClass( $( this ), "ui-dialog-resizing" );
|
|
that._unblockFrames();
|
|
that._trigger( "resizeStop", event, filteredUi( ui ) );
|
|
}
|
|
} )
|
|
.css( "position", position );
|
|
},
|
|
|
|
_trackFocus: function() {
|
|
this._on( this.widget(), {
|
|
focusin: function( event ) {
|
|
this._makeFocusTarget();
|
|
this._focusedElement = $( event.target );
|
|
}
|
|
} );
|
|
},
|
|
|
|
_makeFocusTarget: function() {
|
|
this._untrackInstance();
|
|
this._trackingInstances().unshift( this );
|
|
},
|
|
|
|
_untrackInstance: function() {
|
|
var instances = this._trackingInstances(),
|
|
exists = $.inArray( this, instances );
|
|
if ( exists !== -1 ) {
|
|
instances.splice( exists, 1 );
|
|
}
|
|
},
|
|
|
|
_trackingInstances: function() {
|
|
var instances = this.document.data( "ui-dialog-instances" );
|
|
if ( !instances ) {
|
|
instances = [];
|
|
this.document.data( "ui-dialog-instances", instances );
|
|
}
|
|
return instances;
|
|
},
|
|
|
|
_minHeight: function() {
|
|
var options = this.options;
|
|
|
|
return options.height === "auto" ?
|
|
options.minHeight :
|
|
Math.min( options.minHeight, options.height );
|
|
},
|
|
|
|
_position: function() {
|
|
|
|
// Need to show the dialog to get the actual offset in the position plugin
|
|
var isVisible = this.uiDialog.is( ":visible" );
|
|
if ( !isVisible ) {
|
|
this.uiDialog.show();
|
|
}
|
|
this.uiDialog.position( this.options.position );
|
|
if ( !isVisible ) {
|
|
this.uiDialog.hide();
|
|
}
|
|
},
|
|
|
|
_setOptions: function( options ) {
|
|
var that = this,
|
|
resize = false,
|
|
resizableOptions = {};
|
|
|
|
$.each( options, function( key, value ) {
|
|
that._setOption( key, value );
|
|
|
|
if ( key in that.sizeRelatedOptions ) {
|
|
resize = true;
|
|
}
|
|
if ( key in that.resizableRelatedOptions ) {
|
|
resizableOptions[ key ] = value;
|
|
}
|
|
} );
|
|
|
|
if ( resize ) {
|
|
this._size();
|
|
this._position();
|
|
}
|
|
if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
|
|
this.uiDialog.resizable( "option", resizableOptions );
|
|
}
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
var isDraggable, isResizable,
|
|
uiDialog = this.uiDialog;
|
|
|
|
if ( key === "disabled" ) {
|
|
return;
|
|
}
|
|
|
|
this._super( key, value );
|
|
|
|
if ( key === "appendTo" ) {
|
|
this.uiDialog.appendTo( this._appendTo() );
|
|
}
|
|
|
|
if ( key === "buttons" ) {
|
|
this._createButtons();
|
|
}
|
|
|
|
if ( key === "closeText" ) {
|
|
this.uiDialogTitlebarClose.button( {
|
|
|
|
// Ensure that we always pass a string
|
|
label: $( "<a>" ).text( "" + this.options.closeText ).html()
|
|
} );
|
|
}
|
|
|
|
if ( key === "draggable" ) {
|
|
isDraggable = uiDialog.is( ":data(ui-draggable)" );
|
|
if ( isDraggable && !value ) {
|
|
uiDialog.draggable( "destroy" );
|
|
}
|
|
|
|
if ( !isDraggable && value ) {
|
|
this._makeDraggable();
|
|
}
|
|
}
|
|
|
|
if ( key === "position" ) {
|
|
this._position();
|
|
}
|
|
|
|
if ( key === "resizable" ) {
|
|
|
|
// currently resizable, becoming non-resizable
|
|
isResizable = uiDialog.is( ":data(ui-resizable)" );
|
|
if ( isResizable && !value ) {
|
|
uiDialog.resizable( "destroy" );
|
|
}
|
|
|
|
// Currently resizable, changing handles
|
|
if ( isResizable && typeof value === "string" ) {
|
|
uiDialog.resizable( "option", "handles", value );
|
|
}
|
|
|
|
// Currently non-resizable, becoming resizable
|
|
if ( !isResizable && value !== false ) {
|
|
this._makeResizable();
|
|
}
|
|
}
|
|
|
|
if ( key === "title" ) {
|
|
this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
|
|
}
|
|
},
|
|
|
|
_size: function() {
|
|
|
|
// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
|
|
// divs will both have width and height set, so we need to reset them
|
|
var nonContentHeight, minContentHeight, maxContentHeight,
|
|
options = this.options;
|
|
|
|
// Reset content sizing
|
|
this.element.show().css( {
|
|
width: "auto",
|
|
minHeight: 0,
|
|
maxHeight: "none",
|
|
height: 0
|
|
} );
|
|
|
|
if ( options.minWidth > options.width ) {
|
|
options.width = options.minWidth;
|
|
}
|
|
|
|
// Reset wrapper sizing
|
|
// determine the height of all the non-content elements
|
|
nonContentHeight = this.uiDialog.css( {
|
|
height: "auto",
|
|
width: options.width
|
|
} )
|
|
.outerHeight();
|
|
minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
|
|
maxContentHeight = typeof options.maxHeight === "number" ?
|
|
Math.max( 0, options.maxHeight - nonContentHeight ) :
|
|
"none";
|
|
|
|
if ( options.height === "auto" ) {
|
|
this.element.css( {
|
|
minHeight: minContentHeight,
|
|
maxHeight: maxContentHeight,
|
|
height: "auto"
|
|
} );
|
|
} else {
|
|
this.element.height( Math.max( 0, options.height - nonContentHeight ) );
|
|
}
|
|
|
|
if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
|
|
this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
|
|
}
|
|
},
|
|
|
|
_blockFrames: function() {
|
|
this.iframeBlocks = this.document.find( "iframe" ).map( function() {
|
|
var iframe = $( this );
|
|
|
|
return $( "<div>" )
|
|
.css( {
|
|
position: "absolute",
|
|
width: iframe.outerWidth(),
|
|
height: iframe.outerHeight()
|
|
} )
|
|
.appendTo( iframe.parent() )
|
|
.offset( iframe.offset() )[ 0 ];
|
|
} );
|
|
},
|
|
|
|
_unblockFrames: function() {
|
|
if ( this.iframeBlocks ) {
|
|
this.iframeBlocks.remove();
|
|
delete this.iframeBlocks;
|
|
}
|
|
},
|
|
|
|
_allowInteraction: function( event ) {
|
|
if ( $( event.target ).closest( ".ui-dialog" ).length ) {
|
|
return true;
|
|
}
|
|
|
|
// TODO: Remove hack when datepicker implements
|
|
// the .ui-front logic (#8989)
|
|
return !!$( event.target ).closest( ".ui-datepicker" ).length;
|
|
},
|
|
|
|
_createOverlay: function() {
|
|
if ( !this.options.modal ) {
|
|
return;
|
|
}
|
|
|
|
// We use a delay in case the overlay is created from an
|
|
// event that we're going to be cancelling (#2804)
|
|
var isOpening = true;
|
|
this._delay( function() {
|
|
isOpening = false;
|
|
} );
|
|
|
|
if ( !this.document.data( "ui-dialog-overlays" ) ) {
|
|
|
|
// Prevent use of anchors and inputs
|
|
// Using _on() for an event handler shared across many instances is
|
|
// safe because the dialogs stack and must be closed in reverse order
|
|
this._on( this.document, {
|
|
focusin: function( event ) {
|
|
if ( isOpening ) {
|
|
return;
|
|
}
|
|
|
|
if ( !this._allowInteraction( event ) ) {
|
|
event.preventDefault();
|
|
this._trackingInstances()[ 0 ]._focusTabbable();
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
|
|
this.overlay = $( "<div>" )
|
|
.appendTo( this._appendTo() );
|
|
|
|
this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
|
|
this._on( this.overlay, {
|
|
mousedown: "_keepFocus"
|
|
} );
|
|
this.document.data( "ui-dialog-overlays",
|
|
( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
|
|
},
|
|
|
|
_destroyOverlay: function() {
|
|
if ( !this.options.modal ) {
|
|
return;
|
|
}
|
|
|
|
if ( this.overlay ) {
|
|
var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
|
|
|
|
if ( !overlays ) {
|
|
this._off( this.document, "focusin" );
|
|
this.document.removeData( "ui-dialog-overlays" );
|
|
} else {
|
|
this.document.data( "ui-dialog-overlays", overlays );
|
|
}
|
|
|
|
this.overlay.remove();
|
|
this.overlay = null;
|
|
}
|
|
}
|
|
} );
|
|
|
|
// DEPRECATED
|
|
// TODO: switch return back to widget declaration at top of file when this is removed
|
|
if ( $.uiBackCompat !== false ) {
|
|
|
|
// Backcompat for dialogClass option
|
|
$.widget( "ui.dialog", $.ui.dialog, {
|
|
options: {
|
|
dialogClass: ""
|
|
},
|
|
_createWrapper: function() {
|
|
this._super();
|
|
this.uiDialog.addClass( this.options.dialogClass );
|
|
},
|
|
_setOption: function( key, value ) {
|
|
if ( key === "dialogClass" ) {
|
|
this.uiDialog
|
|
.removeClass( this.options.dialogClass )
|
|
.addClass( value );
|
|
}
|
|
this._superApply( arguments );
|
|
}
|
|
} );
|
|
}
|
|
|
|
return $.ui.dialog;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 60 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Droppable 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Droppable
|
|
//>>group: Interactions
|
|
//>>description: Enables drop targets for draggable elements.
|
|
//>>docs: http://api.jqueryui.com/droppable/
|
|
//>>demos: http://jqueryui.com/droppable/
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(57),
|
|
__webpack_require__(56),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
$.widget( "ui.droppable", {
|
|
version: "1.12.1",
|
|
widgetEventPrefix: "drop",
|
|
options: {
|
|
accept: "*",
|
|
addClasses: true,
|
|
greedy: false,
|
|
scope: "default",
|
|
tolerance: "intersect",
|
|
|
|
// Callbacks
|
|
activate: null,
|
|
deactivate: null,
|
|
drop: null,
|
|
out: null,
|
|
over: null
|
|
},
|
|
_create: function() {
|
|
|
|
var proportions,
|
|
o = this.options,
|
|
accept = o.accept;
|
|
|
|
this.isover = false;
|
|
this.isout = true;
|
|
|
|
this.accept = $.isFunction( accept ) ? accept : function( d ) {
|
|
return d.is( accept );
|
|
};
|
|
|
|
this.proportions = function( /* valueToWrite */ ) {
|
|
if ( arguments.length ) {
|
|
|
|
// Store the droppable's proportions
|
|
proportions = arguments[ 0 ];
|
|
} else {
|
|
|
|
// Retrieve or derive the droppable's proportions
|
|
return proportions ?
|
|
proportions :
|
|
proportions = {
|
|
width: this.element[ 0 ].offsetWidth,
|
|
height: this.element[ 0 ].offsetHeight
|
|
};
|
|
}
|
|
};
|
|
|
|
this._addToManager( o.scope );
|
|
|
|
o.addClasses && this._addClass( "ui-droppable" );
|
|
|
|
},
|
|
|
|
_addToManager: function( scope ) {
|
|
|
|
// Add the reference and positions to the manager
|
|
$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
|
|
$.ui.ddmanager.droppables[ scope ].push( this );
|
|
},
|
|
|
|
_splice: function( drop ) {
|
|
var i = 0;
|
|
for ( ; i < drop.length; i++ ) {
|
|
if ( drop[ i ] === this ) {
|
|
drop.splice( i, 1 );
|
|
}
|
|
}
|
|
},
|
|
|
|
_destroy: function() {
|
|
var drop = $.ui.ddmanager.droppables[ this.options.scope ];
|
|
|
|
this._splice( drop );
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
|
|
if ( key === "accept" ) {
|
|
this.accept = $.isFunction( value ) ? value : function( d ) {
|
|
return d.is( value );
|
|
};
|
|
} else if ( key === "scope" ) {
|
|
var drop = $.ui.ddmanager.droppables[ this.options.scope ];
|
|
|
|
this._splice( drop );
|
|
this._addToManager( value );
|
|
}
|
|
|
|
this._super( key, value );
|
|
},
|
|
|
|
_activate: function( event ) {
|
|
var draggable = $.ui.ddmanager.current;
|
|
|
|
this._addActiveClass();
|
|
if ( draggable ) {
|
|
this._trigger( "activate", event, this.ui( draggable ) );
|
|
}
|
|
},
|
|
|
|
_deactivate: function( event ) {
|
|
var draggable = $.ui.ddmanager.current;
|
|
|
|
this._removeActiveClass();
|
|
if ( draggable ) {
|
|
this._trigger( "deactivate", event, this.ui( draggable ) );
|
|
}
|
|
},
|
|
|
|
_over: function( event ) {
|
|
|
|
var draggable = $.ui.ddmanager.current;
|
|
|
|
// Bail if draggable and droppable are same element
|
|
if ( !draggable || ( draggable.currentItem ||
|
|
draggable.element )[ 0 ] === this.element[ 0 ] ) {
|
|
return;
|
|
}
|
|
|
|
if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
|
|
draggable.element ) ) ) {
|
|
this._addHoverClass();
|
|
this._trigger( "over", event, this.ui( draggable ) );
|
|
}
|
|
|
|
},
|
|
|
|
_out: function( event ) {
|
|
|
|
var draggable = $.ui.ddmanager.current;
|
|
|
|
// Bail if draggable and droppable are same element
|
|
if ( !draggable || ( draggable.currentItem ||
|
|
draggable.element )[ 0 ] === this.element[ 0 ] ) {
|
|
return;
|
|
}
|
|
|
|
if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
|
|
draggable.element ) ) ) {
|
|
this._removeHoverClass();
|
|
this._trigger( "out", event, this.ui( draggable ) );
|
|
}
|
|
|
|
},
|
|
|
|
_drop: function( event, custom ) {
|
|
|
|
var draggable = custom || $.ui.ddmanager.current,
|
|
childrenIntersection = false;
|
|
|
|
// Bail if draggable and droppable are same element
|
|
if ( !draggable || ( draggable.currentItem ||
|
|
draggable.element )[ 0 ] === this.element[ 0 ] ) {
|
|
return false;
|
|
}
|
|
|
|
this.element
|
|
.find( ":data(ui-droppable)" )
|
|
.not( ".ui-draggable-dragging" )
|
|
.each( function() {
|
|
var inst = $( this ).droppable( "instance" );
|
|
if (
|
|
inst.options.greedy &&
|
|
!inst.options.disabled &&
|
|
inst.options.scope === draggable.options.scope &&
|
|
inst.accept.call(
|
|
inst.element[ 0 ], ( draggable.currentItem || draggable.element )
|
|
) &&
|
|
intersect(
|
|
draggable,
|
|
$.extend( inst, { offset: inst.element.offset() } ),
|
|
inst.options.tolerance, event
|
|
)
|
|
) {
|
|
childrenIntersection = true;
|
|
return false; }
|
|
} );
|
|
if ( childrenIntersection ) {
|
|
return false;
|
|
}
|
|
|
|
if ( this.accept.call( this.element[ 0 ],
|
|
( draggable.currentItem || draggable.element ) ) ) {
|
|
this._removeActiveClass();
|
|
this._removeHoverClass();
|
|
|
|
this._trigger( "drop", event, this.ui( draggable ) );
|
|
return this.element;
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
ui: function( c ) {
|
|
return {
|
|
draggable: ( c.currentItem || c.element ),
|
|
helper: c.helper,
|
|
position: c.position,
|
|
offset: c.positionAbs
|
|
};
|
|
},
|
|
|
|
// Extension points just to make backcompat sane and avoid duplicating logic
|
|
// TODO: Remove in 1.13 along with call to it below
|
|
_addHoverClass: function() {
|
|
this._addClass( "ui-droppable-hover" );
|
|
},
|
|
|
|
_removeHoverClass: function() {
|
|
this._removeClass( "ui-droppable-hover" );
|
|
},
|
|
|
|
_addActiveClass: function() {
|
|
this._addClass( "ui-droppable-active" );
|
|
},
|
|
|
|
_removeActiveClass: function() {
|
|
this._removeClass( "ui-droppable-active" );
|
|
}
|
|
} );
|
|
|
|
var intersect = $.ui.intersect = ( function() {
|
|
function isOverAxis( x, reference, size ) {
|
|
return ( x >= reference ) && ( x < ( reference + size ) );
|
|
}
|
|
|
|
return function( draggable, droppable, toleranceMode, event ) {
|
|
|
|
if ( !droppable.offset ) {
|
|
return false;
|
|
}
|
|
|
|
var x1 = ( draggable.positionAbs ||
|
|
draggable.position.absolute ).left + draggable.margins.left,
|
|
y1 = ( draggable.positionAbs ||
|
|
draggable.position.absolute ).top + draggable.margins.top,
|
|
x2 = x1 + draggable.helperProportions.width,
|
|
y2 = y1 + draggable.helperProportions.height,
|
|
l = droppable.offset.left,
|
|
t = droppable.offset.top,
|
|
r = l + droppable.proportions().width,
|
|
b = t + droppable.proportions().height;
|
|
|
|
switch ( toleranceMode ) {
|
|
case "fit":
|
|
return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
|
|
case "intersect":
|
|
return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
|
|
x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
|
|
t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
|
|
y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
|
|
case "pointer":
|
|
return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
|
|
isOverAxis( event.pageX, l, droppable.proportions().width );
|
|
case "touch":
|
|
return (
|
|
( y1 >= t && y1 <= b ) || // Top edge touching
|
|
( y2 >= t && y2 <= b ) || // Bottom edge touching
|
|
( y1 < t && y2 > b ) // Surrounded vertically
|
|
) && (
|
|
( x1 >= l && x1 <= r ) || // Left edge touching
|
|
( x2 >= l && x2 <= r ) || // Right edge touching
|
|
( x1 < l && x2 > r ) // Surrounded horizontally
|
|
);
|
|
default:
|
|
return false;
|
|
}
|
|
};
|
|
} )();
|
|
|
|
/*
|
|
This manager tracks offsets of draggables and droppables
|
|
*/
|
|
$.ui.ddmanager = {
|
|
current: null,
|
|
droppables: { "default": [] },
|
|
prepareOffsets: function( t, event ) {
|
|
|
|
var i, j,
|
|
m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
|
|
type = event ? event.type : null, // workaround for #2317
|
|
list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
|
|
|
|
droppablesLoop: for ( i = 0; i < m.length; i++ ) {
|
|
|
|
// No disabled and non-accepted
|
|
if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
|
|
( t.currentItem || t.element ) ) ) ) {
|
|
continue;
|
|
}
|
|
|
|
// Filter out elements in the current dragged item
|
|
for ( j = 0; j < list.length; j++ ) {
|
|
if ( list[ j ] === m[ i ].element[ 0 ] ) {
|
|
m[ i ].proportions().height = 0;
|
|
continue droppablesLoop;
|
|
}
|
|
}
|
|
|
|
m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
|
|
if ( !m[ i ].visible ) {
|
|
continue;
|
|
}
|
|
|
|
// Activate the droppable if used directly from draggables
|
|
if ( type === "mousedown" ) {
|
|
m[ i ]._activate.call( m[ i ], event );
|
|
}
|
|
|
|
m[ i ].offset = m[ i ].element.offset();
|
|
m[ i ].proportions( {
|
|
width: m[ i ].element[ 0 ].offsetWidth,
|
|
height: m[ i ].element[ 0 ].offsetHeight
|
|
} );
|
|
|
|
}
|
|
|
|
},
|
|
drop: function( draggable, event ) {
|
|
|
|
var dropped = false;
|
|
|
|
// Create a copy of the droppables in case the list changes during the drop (#9116)
|
|
$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
|
|
|
|
if ( !this.options ) {
|
|
return;
|
|
}
|
|
if ( !this.options.disabled && this.visible &&
|
|
intersect( draggable, this, this.options.tolerance, event ) ) {
|
|
dropped = this._drop.call( this, event ) || dropped;
|
|
}
|
|
|
|
if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
|
|
( draggable.currentItem || draggable.element ) ) ) {
|
|
this.isout = true;
|
|
this.isover = false;
|
|
this._deactivate.call( this, event );
|
|
}
|
|
|
|
} );
|
|
return dropped;
|
|
|
|
},
|
|
dragStart: function( draggable, event ) {
|
|
|
|
// Listen for scrolling so that if the dragging causes scrolling the position of the
|
|
// droppables can be recalculated (see #5003)
|
|
draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
|
|
if ( !draggable.options.refreshPositions ) {
|
|
$.ui.ddmanager.prepareOffsets( draggable, event );
|
|
}
|
|
} );
|
|
},
|
|
drag: function( draggable, event ) {
|
|
|
|
// If you have a highly dynamic page, you might try this option. It renders positions
|
|
// every time you move the mouse.
|
|
if ( draggable.options.refreshPositions ) {
|
|
$.ui.ddmanager.prepareOffsets( draggable, event );
|
|
}
|
|
|
|
// Run through all droppables and check their positions based on specific tolerance options
|
|
$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
|
|
|
|
if ( this.options.disabled || this.greedyChild || !this.visible ) {
|
|
return;
|
|
}
|
|
|
|
var parentInstance, scope, parent,
|
|
intersects = intersect( draggable, this, this.options.tolerance, event ),
|
|
c = !intersects && this.isover ?
|
|
"isout" :
|
|
( intersects && !this.isover ? "isover" : null );
|
|
if ( !c ) {
|
|
return;
|
|
}
|
|
|
|
if ( this.options.greedy ) {
|
|
|
|
// find droppable parents with same scope
|
|
scope = this.options.scope;
|
|
parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
|
|
return $( this ).droppable( "instance" ).options.scope === scope;
|
|
} );
|
|
|
|
if ( parent.length ) {
|
|
parentInstance = $( parent[ 0 ] ).droppable( "instance" );
|
|
parentInstance.greedyChild = ( c === "isover" );
|
|
}
|
|
}
|
|
|
|
// We just moved into a greedy child
|
|
if ( parentInstance && c === "isover" ) {
|
|
parentInstance.isover = false;
|
|
parentInstance.isout = true;
|
|
parentInstance._out.call( parentInstance, event );
|
|
}
|
|
|
|
this[ c ] = true;
|
|
this[ c === "isout" ? "isover" : "isout" ] = false;
|
|
this[ c === "isover" ? "_over" : "_out" ].call( this, event );
|
|
|
|
// We just moved out of a greedy child
|
|
if ( parentInstance && c === "isout" ) {
|
|
parentInstance.isout = false;
|
|
parentInstance.isover = true;
|
|
parentInstance._over.call( parentInstance, event );
|
|
}
|
|
} );
|
|
|
|
},
|
|
dragStop: function( draggable, event ) {
|
|
draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
|
|
|
|
// Call prepareOffsets one final time since IE does not fire return scroll events when
|
|
// overflow was caused by drag (see #5003)
|
|
if ( !draggable.options.refreshPositions ) {
|
|
$.ui.ddmanager.prepareOffsets( draggable, event );
|
|
}
|
|
}
|
|
};
|
|
|
|
// DEPRECATED
|
|
// TODO: switch return back to widget declaration at top of file when this is removed
|
|
if ( $.uiBackCompat !== false ) {
|
|
|
|
// Backcompat for activeClass and hoverClass options
|
|
$.widget( "ui.droppable", $.ui.droppable, {
|
|
options: {
|
|
hoverClass: false,
|
|
activeClass: false
|
|
},
|
|
_addActiveClass: function() {
|
|
this._super();
|
|
if ( this.options.activeClass ) {
|
|
this.element.addClass( this.options.activeClass );
|
|
}
|
|
},
|
|
_removeActiveClass: function() {
|
|
this._super();
|
|
if ( this.options.activeClass ) {
|
|
this.element.removeClass( this.options.activeClass );
|
|
}
|
|
},
|
|
_addHoverClass: function() {
|
|
this._super();
|
|
if ( this.options.hoverClass ) {
|
|
this.element.addClass( this.options.hoverClass );
|
|
}
|
|
},
|
|
_removeHoverClass: function() {
|
|
this._super();
|
|
if ( this.options.hoverClass ) {
|
|
this.element.removeClass( this.options.hoverClass );
|
|
}
|
|
}
|
|
} );
|
|
}
|
|
|
|
return $.ui.droppable;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 61 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Progressbar 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Progressbar
|
|
//>>group: Widgets
|
|
// jscs:disable maximumLineLength
|
|
//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
|
|
// jscs:enable maximumLineLength
|
|
//>>docs: http://api.jqueryui.com/progressbar/
|
|
//>>demos: http://jqueryui.com/progressbar/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/progressbar.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.widget( "ui.progressbar", {
|
|
version: "1.12.1",
|
|
options: {
|
|
classes: {
|
|
"ui-progressbar": "ui-corner-all",
|
|
"ui-progressbar-value": "ui-corner-left",
|
|
"ui-progressbar-complete": "ui-corner-right"
|
|
},
|
|
max: 100,
|
|
value: 0,
|
|
|
|
change: null,
|
|
complete: null
|
|
},
|
|
|
|
min: 0,
|
|
|
|
_create: function() {
|
|
|
|
// Constrain initial value
|
|
this.oldValue = this.options.value = this._constrainedValue();
|
|
|
|
this.element.attr( {
|
|
|
|
// Only set static values; aria-valuenow and aria-valuemax are
|
|
// set inside _refreshValue()
|
|
role: "progressbar",
|
|
"aria-valuemin": this.min
|
|
} );
|
|
this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
|
|
|
|
this.valueDiv = $( "<div>" ).appendTo( this.element );
|
|
this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
|
|
this._refreshValue();
|
|
},
|
|
|
|
_destroy: function() {
|
|
this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
|
|
|
|
this.valueDiv.remove();
|
|
},
|
|
|
|
value: function( newValue ) {
|
|
if ( newValue === undefined ) {
|
|
return this.options.value;
|
|
}
|
|
|
|
this.options.value = this._constrainedValue( newValue );
|
|
this._refreshValue();
|
|
},
|
|
|
|
_constrainedValue: function( newValue ) {
|
|
if ( newValue === undefined ) {
|
|
newValue = this.options.value;
|
|
}
|
|
|
|
this.indeterminate = newValue === false;
|
|
|
|
// Sanitize value
|
|
if ( typeof newValue !== "number" ) {
|
|
newValue = 0;
|
|
}
|
|
|
|
return this.indeterminate ? false :
|
|
Math.min( this.options.max, Math.max( this.min, newValue ) );
|
|
},
|
|
|
|
_setOptions: function( options ) {
|
|
|
|
// Ensure "value" option is set after other values (like max)
|
|
var value = options.value;
|
|
delete options.value;
|
|
|
|
this._super( options );
|
|
|
|
this.options.value = this._constrainedValue( value );
|
|
this._refreshValue();
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
if ( key === "max" ) {
|
|
|
|
// Don't allow a max less than min
|
|
value = Math.max( this.min, value );
|
|
}
|
|
this._super( key, value );
|
|
},
|
|
|
|
_setOptionDisabled: function( value ) {
|
|
this._super( value );
|
|
|
|
this.element.attr( "aria-disabled", value );
|
|
this._toggleClass( null, "ui-state-disabled", !!value );
|
|
},
|
|
|
|
_percentage: function() {
|
|
return this.indeterminate ?
|
|
100 :
|
|
100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
|
|
},
|
|
|
|
_refreshValue: function() {
|
|
var value = this.options.value,
|
|
percentage = this._percentage();
|
|
|
|
this.valueDiv
|
|
.toggle( this.indeterminate || value > this.min )
|
|
.width( percentage.toFixed( 0 ) + "%" );
|
|
|
|
this
|
|
._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
|
|
value === this.options.max )
|
|
._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
|
|
|
|
if ( this.indeterminate ) {
|
|
this.element.removeAttr( "aria-valuenow" );
|
|
if ( !this.overlayDiv ) {
|
|
this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
|
|
this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
|
|
}
|
|
} else {
|
|
this.element.attr( {
|
|
"aria-valuemax": this.options.max,
|
|
"aria-valuenow": value
|
|
} );
|
|
if ( this.overlayDiv ) {
|
|
this.overlayDiv.remove();
|
|
this.overlayDiv = null;
|
|
}
|
|
}
|
|
|
|
if ( this.oldValue !== value ) {
|
|
this.oldValue = value;
|
|
this._trigger( "change" );
|
|
}
|
|
if ( value === this.options.max ) {
|
|
this._trigger( "complete" );
|
|
}
|
|
}
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 62 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Selectable 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Selectable
|
|
//>>group: Interactions
|
|
//>>description: Allows groups of elements to be selected with the mouse.
|
|
//>>docs: http://api.jqueryui.com/selectable/
|
|
//>>demos: http://jqueryui.com/selectable/
|
|
//>>css.structure: ../../themes/base/selectable.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(56),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.widget( "ui.selectable", $.ui.mouse, {
|
|
version: "1.12.1",
|
|
options: {
|
|
appendTo: "body",
|
|
autoRefresh: true,
|
|
distance: 0,
|
|
filter: "*",
|
|
tolerance: "touch",
|
|
|
|
// Callbacks
|
|
selected: null,
|
|
selecting: null,
|
|
start: null,
|
|
stop: null,
|
|
unselected: null,
|
|
unselecting: null
|
|
},
|
|
_create: function() {
|
|
var that = this;
|
|
|
|
this._addClass( "ui-selectable" );
|
|
|
|
this.dragged = false;
|
|
|
|
// Cache selectee children based on filter
|
|
this.refresh = function() {
|
|
that.elementPos = $( that.element[ 0 ] ).offset();
|
|
that.selectees = $( that.options.filter, that.element[ 0 ] );
|
|
that._addClass( that.selectees, "ui-selectee" );
|
|
that.selectees.each( function() {
|
|
var $this = $( this ),
|
|
selecteeOffset = $this.offset(),
|
|
pos = {
|
|
left: selecteeOffset.left - that.elementPos.left,
|
|
top: selecteeOffset.top - that.elementPos.top
|
|
};
|
|
$.data( this, "selectable-item", {
|
|
element: this,
|
|
$element: $this,
|
|
left: pos.left,
|
|
top: pos.top,
|
|
right: pos.left + $this.outerWidth(),
|
|
bottom: pos.top + $this.outerHeight(),
|
|
startselected: false,
|
|
selected: $this.hasClass( "ui-selected" ),
|
|
selecting: $this.hasClass( "ui-selecting" ),
|
|
unselecting: $this.hasClass( "ui-unselecting" )
|
|
} );
|
|
} );
|
|
};
|
|
this.refresh();
|
|
|
|
this._mouseInit();
|
|
|
|
this.helper = $( "<div>" );
|
|
this._addClass( this.helper, "ui-selectable-helper" );
|
|
},
|
|
|
|
_destroy: function() {
|
|
this.selectees.removeData( "selectable-item" );
|
|
this._mouseDestroy();
|
|
},
|
|
|
|
_mouseStart: function( event ) {
|
|
var that = this,
|
|
options = this.options;
|
|
|
|
this.opos = [ event.pageX, event.pageY ];
|
|
this.elementPos = $( this.element[ 0 ] ).offset();
|
|
|
|
if ( this.options.disabled ) {
|
|
return;
|
|
}
|
|
|
|
this.selectees = $( options.filter, this.element[ 0 ] );
|
|
|
|
this._trigger( "start", event );
|
|
|
|
$( options.appendTo ).append( this.helper );
|
|
|
|
// position helper (lasso)
|
|
this.helper.css( {
|
|
"left": event.pageX,
|
|
"top": event.pageY,
|
|
"width": 0,
|
|
"height": 0
|
|
} );
|
|
|
|
if ( options.autoRefresh ) {
|
|
this.refresh();
|
|
}
|
|
|
|
this.selectees.filter( ".ui-selected" ).each( function() {
|
|
var selectee = $.data( this, "selectable-item" );
|
|
selectee.startselected = true;
|
|
if ( !event.metaKey && !event.ctrlKey ) {
|
|
that._removeClass( selectee.$element, "ui-selected" );
|
|
selectee.selected = false;
|
|
that._addClass( selectee.$element, "ui-unselecting" );
|
|
selectee.unselecting = true;
|
|
|
|
// selectable UNSELECTING callback
|
|
that._trigger( "unselecting", event, {
|
|
unselecting: selectee.element
|
|
} );
|
|
}
|
|
} );
|
|
|
|
$( event.target ).parents().addBack().each( function() {
|
|
var doSelect,
|
|
selectee = $.data( this, "selectable-item" );
|
|
if ( selectee ) {
|
|
doSelect = ( !event.metaKey && !event.ctrlKey ) ||
|
|
!selectee.$element.hasClass( "ui-selected" );
|
|
that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
|
|
._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
|
|
selectee.unselecting = !doSelect;
|
|
selectee.selecting = doSelect;
|
|
selectee.selected = doSelect;
|
|
|
|
// selectable (UN)SELECTING callback
|
|
if ( doSelect ) {
|
|
that._trigger( "selecting", event, {
|
|
selecting: selectee.element
|
|
} );
|
|
} else {
|
|
that._trigger( "unselecting", event, {
|
|
unselecting: selectee.element
|
|
} );
|
|
}
|
|
return false;
|
|
}
|
|
} );
|
|
|
|
},
|
|
|
|
_mouseDrag: function( event ) {
|
|
|
|
this.dragged = true;
|
|
|
|
if ( this.options.disabled ) {
|
|
return;
|
|
}
|
|
|
|
var tmp,
|
|
that = this,
|
|
options = this.options,
|
|
x1 = this.opos[ 0 ],
|
|
y1 = this.opos[ 1 ],
|
|
x2 = event.pageX,
|
|
y2 = event.pageY;
|
|
|
|
if ( x1 > x2 ) { tmp = x2; x2 = x1; x1 = tmp; }
|
|
if ( y1 > y2 ) { tmp = y2; y2 = y1; y1 = tmp; }
|
|
this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
|
|
|
|
this.selectees.each( function() {
|
|
var selectee = $.data( this, "selectable-item" ),
|
|
hit = false,
|
|
offset = {};
|
|
|
|
//prevent helper from being selected if appendTo: selectable
|
|
if ( !selectee || selectee.element === that.element[ 0 ] ) {
|
|
return;
|
|
}
|
|
|
|
offset.left = selectee.left + that.elementPos.left;
|
|
offset.right = selectee.right + that.elementPos.left;
|
|
offset.top = selectee.top + that.elementPos.top;
|
|
offset.bottom = selectee.bottom + that.elementPos.top;
|
|
|
|
if ( options.tolerance === "touch" ) {
|
|
hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
|
|
offset.bottom < y1 ) );
|
|
} else if ( options.tolerance === "fit" ) {
|
|
hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
|
|
offset.bottom < y2 );
|
|
}
|
|
|
|
if ( hit ) {
|
|
|
|
// SELECT
|
|
if ( selectee.selected ) {
|
|
that._removeClass( selectee.$element, "ui-selected" );
|
|
selectee.selected = false;
|
|
}
|
|
if ( selectee.unselecting ) {
|
|
that._removeClass( selectee.$element, "ui-unselecting" );
|
|
selectee.unselecting = false;
|
|
}
|
|
if ( !selectee.selecting ) {
|
|
that._addClass( selectee.$element, "ui-selecting" );
|
|
selectee.selecting = true;
|
|
|
|
// selectable SELECTING callback
|
|
that._trigger( "selecting", event, {
|
|
selecting: selectee.element
|
|
} );
|
|
}
|
|
} else {
|
|
|
|
// UNSELECT
|
|
if ( selectee.selecting ) {
|
|
if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
|
|
that._removeClass( selectee.$element, "ui-selecting" );
|
|
selectee.selecting = false;
|
|
that._addClass( selectee.$element, "ui-selected" );
|
|
selectee.selected = true;
|
|
} else {
|
|
that._removeClass( selectee.$element, "ui-selecting" );
|
|
selectee.selecting = false;
|
|
if ( selectee.startselected ) {
|
|
that._addClass( selectee.$element, "ui-unselecting" );
|
|
selectee.unselecting = true;
|
|
}
|
|
|
|
// selectable UNSELECTING callback
|
|
that._trigger( "unselecting", event, {
|
|
unselecting: selectee.element
|
|
} );
|
|
}
|
|
}
|
|
if ( selectee.selected ) {
|
|
if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
|
|
that._removeClass( selectee.$element, "ui-selected" );
|
|
selectee.selected = false;
|
|
|
|
that._addClass( selectee.$element, "ui-unselecting" );
|
|
selectee.unselecting = true;
|
|
|
|
// selectable UNSELECTING callback
|
|
that._trigger( "unselecting", event, {
|
|
unselecting: selectee.element
|
|
} );
|
|
}
|
|
}
|
|
}
|
|
} );
|
|
|
|
return false;
|
|
},
|
|
|
|
_mouseStop: function( event ) {
|
|
var that = this;
|
|
|
|
this.dragged = false;
|
|
|
|
$( ".ui-unselecting", this.element[ 0 ] ).each( function() {
|
|
var selectee = $.data( this, "selectable-item" );
|
|
that._removeClass( selectee.$element, "ui-unselecting" );
|
|
selectee.unselecting = false;
|
|
selectee.startselected = false;
|
|
that._trigger( "unselected", event, {
|
|
unselected: selectee.element
|
|
} );
|
|
} );
|
|
$( ".ui-selecting", this.element[ 0 ] ).each( function() {
|
|
var selectee = $.data( this, "selectable-item" );
|
|
that._removeClass( selectee.$element, "ui-selecting" )
|
|
._addClass( selectee.$element, "ui-selected" );
|
|
selectee.selecting = false;
|
|
selectee.selected = true;
|
|
selectee.startselected = true;
|
|
that._trigger( "selected", event, {
|
|
selected: selectee.element
|
|
} );
|
|
} );
|
|
this._trigger( "stop", event );
|
|
|
|
this.helper.remove();
|
|
|
|
return false;
|
|
}
|
|
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 63 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Selectmenu 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Selectmenu
|
|
//>>group: Widgets
|
|
// jscs:disable maximumLineLength
|
|
//>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select.
|
|
// jscs:enable maximumLineLength
|
|
//>>docs: http://api.jqueryui.com/selectmenu/
|
|
//>>demos: http://jqueryui.com/selectmenu/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(50),
|
|
__webpack_require__(45),
|
|
__webpack_require__(54),
|
|
__webpack_require__(43),
|
|
__webpack_require__(44),
|
|
__webpack_require__(21),
|
|
__webpack_require__(48),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
|
|
version: "1.12.1",
|
|
defaultElement: "<select>",
|
|
options: {
|
|
appendTo: null,
|
|
classes: {
|
|
"ui-selectmenu-button-open": "ui-corner-top",
|
|
"ui-selectmenu-button-closed": "ui-corner-all"
|
|
},
|
|
disabled: null,
|
|
icons: {
|
|
button: "ui-icon-triangle-1-s"
|
|
},
|
|
position: {
|
|
my: "left top",
|
|
at: "left bottom",
|
|
collision: "none"
|
|
},
|
|
width: false,
|
|
|
|
// Callbacks
|
|
change: null,
|
|
close: null,
|
|
focus: null,
|
|
open: null,
|
|
select: null
|
|
},
|
|
|
|
_create: function() {
|
|
var selectmenuId = this.element.uniqueId().attr( "id" );
|
|
this.ids = {
|
|
element: selectmenuId,
|
|
button: selectmenuId + "-button",
|
|
menu: selectmenuId + "-menu"
|
|
};
|
|
|
|
this._drawButton();
|
|
this._drawMenu();
|
|
this._bindFormResetHandler();
|
|
|
|
this._rendered = false;
|
|
this.menuItems = $();
|
|
},
|
|
|
|
_drawButton: function() {
|
|
var icon,
|
|
that = this,
|
|
item = this._parseOption(
|
|
this.element.find( "option:selected" ),
|
|
this.element[ 0 ].selectedIndex
|
|
);
|
|
|
|
// Associate existing label with the new button
|
|
this.labels = this.element.labels().attr( "for", this.ids.button );
|
|
this._on( this.labels, {
|
|
click: function( event ) {
|
|
this.button.focus();
|
|
event.preventDefault();
|
|
}
|
|
} );
|
|
|
|
// Hide original select element
|
|
this.element.hide();
|
|
|
|
// Create button
|
|
this.button = $( "<span>", {
|
|
tabindex: this.options.disabled ? -1 : 0,
|
|
id: this.ids.button,
|
|
role: "combobox",
|
|
"aria-expanded": "false",
|
|
"aria-autocomplete": "list",
|
|
"aria-owns": this.ids.menu,
|
|
"aria-haspopup": "true",
|
|
title: this.element.attr( "title" )
|
|
} )
|
|
.insertAfter( this.element );
|
|
|
|
this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
|
|
"ui-button ui-widget" );
|
|
|
|
icon = $( "<span>" ).appendTo( this.button );
|
|
this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
|
|
this.buttonItem = this._renderButtonItem( item )
|
|
.appendTo( this.button );
|
|
|
|
if ( this.options.width !== false ) {
|
|
this._resizeButton();
|
|
}
|
|
|
|
this._on( this.button, this._buttonEvents );
|
|
this.button.one( "focusin", function() {
|
|
|
|
// Delay rendering the menu items until the button receives focus.
|
|
// The menu may have already been rendered via a programmatic open.
|
|
if ( !that._rendered ) {
|
|
that._refreshMenu();
|
|
}
|
|
} );
|
|
},
|
|
|
|
_drawMenu: function() {
|
|
var that = this;
|
|
|
|
// Create menu
|
|
this.menu = $( "<ul>", {
|
|
"aria-hidden": "true",
|
|
"aria-labelledby": this.ids.button,
|
|
id: this.ids.menu
|
|
} );
|
|
|
|
// Wrap menu
|
|
this.menuWrap = $( "<div>" ).append( this.menu );
|
|
this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
|
|
this.menuWrap.appendTo( this._appendTo() );
|
|
|
|
// Initialize menu widget
|
|
this.menuInstance = this.menu
|
|
.menu( {
|
|
classes: {
|
|
"ui-menu": "ui-corner-bottom"
|
|
},
|
|
role: "listbox",
|
|
select: function( event, ui ) {
|
|
event.preventDefault();
|
|
|
|
// Support: IE8
|
|
// If the item was selected via a click, the text selection
|
|
// will be destroyed in IE
|
|
that._setSelection();
|
|
|
|
that._select( ui.item.data( "ui-selectmenu-item" ), event );
|
|
},
|
|
focus: function( event, ui ) {
|
|
var item = ui.item.data( "ui-selectmenu-item" );
|
|
|
|
// Prevent inital focus from firing and check if its a newly focused item
|
|
if ( that.focusIndex != null && item.index !== that.focusIndex ) {
|
|
that._trigger( "focus", event, { item: item } );
|
|
if ( !that.isOpen ) {
|
|
that._select( item, event );
|
|
}
|
|
}
|
|
that.focusIndex = item.index;
|
|
|
|
that.button.attr( "aria-activedescendant",
|
|
that.menuItems.eq( item.index ).attr( "id" ) );
|
|
}
|
|
} )
|
|
.menu( "instance" );
|
|
|
|
// Don't close the menu on mouseleave
|
|
this.menuInstance._off( this.menu, "mouseleave" );
|
|
|
|
// Cancel the menu's collapseAll on document click
|
|
this.menuInstance._closeOnDocumentClick = function() {
|
|
return false;
|
|
};
|
|
|
|
// Selects often contain empty items, but never contain dividers
|
|
this.menuInstance._isDivider = function() {
|
|
return false;
|
|
};
|
|
},
|
|
|
|
refresh: function() {
|
|
this._refreshMenu();
|
|
this.buttonItem.replaceWith(
|
|
this.buttonItem = this._renderButtonItem(
|
|
|
|
// Fall back to an empty object in case there are no options
|
|
this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
|
|
)
|
|
);
|
|
if ( this.options.width === null ) {
|
|
this._resizeButton();
|
|
}
|
|
},
|
|
|
|
_refreshMenu: function() {
|
|
var item,
|
|
options = this.element.find( "option" );
|
|
|
|
this.menu.empty();
|
|
|
|
this._parseOptions( options );
|
|
this._renderMenu( this.menu, this.items );
|
|
|
|
this.menuInstance.refresh();
|
|
this.menuItems = this.menu.find( "li" )
|
|
.not( ".ui-selectmenu-optgroup" )
|
|
.find( ".ui-menu-item-wrapper" );
|
|
|
|
this._rendered = true;
|
|
|
|
if ( !options.length ) {
|
|
return;
|
|
}
|
|
|
|
item = this._getSelectedItem();
|
|
|
|
// Update the menu to have the correct item focused
|
|
this.menuInstance.focus( null, item );
|
|
this._setAria( item.data( "ui-selectmenu-item" ) );
|
|
|
|
// Set disabled state
|
|
this._setOption( "disabled", this.element.prop( "disabled" ) );
|
|
},
|
|
|
|
open: function( event ) {
|
|
if ( this.options.disabled ) {
|
|
return;
|
|
}
|
|
|
|
// If this is the first time the menu is being opened, render the items
|
|
if ( !this._rendered ) {
|
|
this._refreshMenu();
|
|
} else {
|
|
|
|
// Menu clears focus on close, reset focus to selected item
|
|
this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
|
|
this.menuInstance.focus( null, this._getSelectedItem() );
|
|
}
|
|
|
|
// If there are no options, don't open the menu
|
|
if ( !this.menuItems.length ) {
|
|
return;
|
|
}
|
|
|
|
this.isOpen = true;
|
|
this._toggleAttr();
|
|
this._resizeMenu();
|
|
this._position();
|
|
|
|
this._on( this.document, this._documentClick );
|
|
|
|
this._trigger( "open", event );
|
|
},
|
|
|
|
_position: function() {
|
|
this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
|
|
},
|
|
|
|
close: function( event ) {
|
|
if ( !this.isOpen ) {
|
|
return;
|
|
}
|
|
|
|
this.isOpen = false;
|
|
this._toggleAttr();
|
|
|
|
this.range = null;
|
|
this._off( this.document );
|
|
|
|
this._trigger( "close", event );
|
|
},
|
|
|
|
widget: function() {
|
|
return this.button;
|
|
},
|
|
|
|
menuWidget: function() {
|
|
return this.menu;
|
|
},
|
|
|
|
_renderButtonItem: function( item ) {
|
|
var buttonItem = $( "<span>" );
|
|
|
|
this._setText( buttonItem, item.label );
|
|
this._addClass( buttonItem, "ui-selectmenu-text" );
|
|
|
|
return buttonItem;
|
|
},
|
|
|
|
_renderMenu: function( ul, items ) {
|
|
var that = this,
|
|
currentOptgroup = "";
|
|
|
|
$.each( items, function( index, item ) {
|
|
var li;
|
|
|
|
if ( item.optgroup !== currentOptgroup ) {
|
|
li = $( "<li>", {
|
|
text: item.optgroup
|
|
} );
|
|
that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
|
|
( item.element.parent( "optgroup" ).prop( "disabled" ) ?
|
|
" ui-state-disabled" :
|
|
"" ) );
|
|
|
|
li.appendTo( ul );
|
|
|
|
currentOptgroup = item.optgroup;
|
|
}
|
|
|
|
that._renderItemData( ul, item );
|
|
} );
|
|
},
|
|
|
|
_renderItemData: function( ul, item ) {
|
|
return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
|
|
},
|
|
|
|
_renderItem: function( ul, item ) {
|
|
var li = $( "<li>" ),
|
|
wrapper = $( "<div>", {
|
|
title: item.element.attr( "title" )
|
|
} );
|
|
|
|
if ( item.disabled ) {
|
|
this._addClass( li, null, "ui-state-disabled" );
|
|
}
|
|
this._setText( wrapper, item.label );
|
|
|
|
return li.append( wrapper ).appendTo( ul );
|
|
},
|
|
|
|
_setText: function( element, value ) {
|
|
if ( value ) {
|
|
element.text( value );
|
|
} else {
|
|
element.html( " " );
|
|
}
|
|
},
|
|
|
|
_move: function( direction, event ) {
|
|
var item, next,
|
|
filter = ".ui-menu-item";
|
|
|
|
if ( this.isOpen ) {
|
|
item = this.menuItems.eq( this.focusIndex ).parent( "li" );
|
|
} else {
|
|
item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
|
|
filter += ":not(.ui-state-disabled)";
|
|
}
|
|
|
|
if ( direction === "first" || direction === "last" ) {
|
|
next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
|
|
} else {
|
|
next = item[ direction + "All" ]( filter ).eq( 0 );
|
|
}
|
|
|
|
if ( next.length ) {
|
|
this.menuInstance.focus( event, next );
|
|
}
|
|
},
|
|
|
|
_getSelectedItem: function() {
|
|
return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
|
|
},
|
|
|
|
_toggle: function( event ) {
|
|
this[ this.isOpen ? "close" : "open" ]( event );
|
|
},
|
|
|
|
_setSelection: function() {
|
|
var selection;
|
|
|
|
if ( !this.range ) {
|
|
return;
|
|
}
|
|
|
|
if ( window.getSelection ) {
|
|
selection = window.getSelection();
|
|
selection.removeAllRanges();
|
|
selection.addRange( this.range );
|
|
|
|
// Support: IE8
|
|
} else {
|
|
this.range.select();
|
|
}
|
|
|
|
// Support: IE
|
|
// Setting the text selection kills the button focus in IE, but
|
|
// restoring the focus doesn't kill the selection.
|
|
this.button.focus();
|
|
},
|
|
|
|
_documentClick: {
|
|
mousedown: function( event ) {
|
|
if ( !this.isOpen ) {
|
|
return;
|
|
}
|
|
|
|
if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
|
|
$.ui.escapeSelector( this.ids.button ) ).length ) {
|
|
this.close( event );
|
|
}
|
|
}
|
|
},
|
|
|
|
_buttonEvents: {
|
|
|
|
// Prevent text selection from being reset when interacting with the selectmenu (#10144)
|
|
mousedown: function() {
|
|
var selection;
|
|
|
|
if ( window.getSelection ) {
|
|
selection = window.getSelection();
|
|
if ( selection.rangeCount ) {
|
|
this.range = selection.getRangeAt( 0 );
|
|
}
|
|
|
|
// Support: IE8
|
|
} else {
|
|
this.range = document.selection.createRange();
|
|
}
|
|
},
|
|
|
|
click: function( event ) {
|
|
this._setSelection();
|
|
this._toggle( event );
|
|
},
|
|
|
|
keydown: function( event ) {
|
|
var preventDefault = true;
|
|
switch ( event.keyCode ) {
|
|
case $.ui.keyCode.TAB:
|
|
case $.ui.keyCode.ESCAPE:
|
|
this.close( event );
|
|
preventDefault = false;
|
|
break;
|
|
case $.ui.keyCode.ENTER:
|
|
if ( this.isOpen ) {
|
|
this._selectFocusedItem( event );
|
|
}
|
|
break;
|
|
case $.ui.keyCode.UP:
|
|
if ( event.altKey ) {
|
|
this._toggle( event );
|
|
} else {
|
|
this._move( "prev", event );
|
|
}
|
|
break;
|
|
case $.ui.keyCode.DOWN:
|
|
if ( event.altKey ) {
|
|
this._toggle( event );
|
|
} else {
|
|
this._move( "next", event );
|
|
}
|
|
break;
|
|
case $.ui.keyCode.SPACE:
|
|
if ( this.isOpen ) {
|
|
this._selectFocusedItem( event );
|
|
} else {
|
|
this._toggle( event );
|
|
}
|
|
break;
|
|
case $.ui.keyCode.LEFT:
|
|
this._move( "prev", event );
|
|
break;
|
|
case $.ui.keyCode.RIGHT:
|
|
this._move( "next", event );
|
|
break;
|
|
case $.ui.keyCode.HOME:
|
|
case $.ui.keyCode.PAGE_UP:
|
|
this._move( "first", event );
|
|
break;
|
|
case $.ui.keyCode.END:
|
|
case $.ui.keyCode.PAGE_DOWN:
|
|
this._move( "last", event );
|
|
break;
|
|
default:
|
|
this.menu.trigger( event );
|
|
preventDefault = false;
|
|
}
|
|
|
|
if ( preventDefault ) {
|
|
event.preventDefault();
|
|
}
|
|
}
|
|
},
|
|
|
|
_selectFocusedItem: function( event ) {
|
|
var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
|
|
if ( !item.hasClass( "ui-state-disabled" ) ) {
|
|
this._select( item.data( "ui-selectmenu-item" ), event );
|
|
}
|
|
},
|
|
|
|
_select: function( item, event ) {
|
|
var oldIndex = this.element[ 0 ].selectedIndex;
|
|
|
|
// Change native select element
|
|
this.element[ 0 ].selectedIndex = item.index;
|
|
this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
|
|
this._setAria( item );
|
|
this._trigger( "select", event, { item: item } );
|
|
|
|
if ( item.index !== oldIndex ) {
|
|
this._trigger( "change", event, { item: item } );
|
|
}
|
|
|
|
this.close( event );
|
|
},
|
|
|
|
_setAria: function( item ) {
|
|
var id = this.menuItems.eq( item.index ).attr( "id" );
|
|
|
|
this.button.attr( {
|
|
"aria-labelledby": id,
|
|
"aria-activedescendant": id
|
|
} );
|
|
this.menu.attr( "aria-activedescendant", id );
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
if ( key === "icons" ) {
|
|
var icon = this.button.find( "span.ui-icon" );
|
|
this._removeClass( icon, null, this.options.icons.button )
|
|
._addClass( icon, null, value.button );
|
|
}
|
|
|
|
this._super( key, value );
|
|
|
|
if ( key === "appendTo" ) {
|
|
this.menuWrap.appendTo( this._appendTo() );
|
|
}
|
|
|
|
if ( key === "width" ) {
|
|
this._resizeButton();
|
|
}
|
|
},
|
|
|
|
_setOptionDisabled: function( value ) {
|
|
this._super( value );
|
|
|
|
this.menuInstance.option( "disabled", value );
|
|
this.button.attr( "aria-disabled", value );
|
|
this._toggleClass( this.button, null, "ui-state-disabled", value );
|
|
|
|
this.element.prop( "disabled", value );
|
|
if ( value ) {
|
|
this.button.attr( "tabindex", -1 );
|
|
this.close();
|
|
} else {
|
|
this.button.attr( "tabindex", 0 );
|
|
}
|
|
},
|
|
|
|
_appendTo: function() {
|
|
var element = this.options.appendTo;
|
|
|
|
if ( element ) {
|
|
element = element.jquery || element.nodeType ?
|
|
$( element ) :
|
|
this.document.find( element ).eq( 0 );
|
|
}
|
|
|
|
if ( !element || !element[ 0 ] ) {
|
|
element = this.element.closest( ".ui-front, dialog" );
|
|
}
|
|
|
|
if ( !element.length ) {
|
|
element = this.document[ 0 ].body;
|
|
}
|
|
|
|
return element;
|
|
},
|
|
|
|
_toggleAttr: function() {
|
|
this.button.attr( "aria-expanded", this.isOpen );
|
|
|
|
// We can't use two _toggleClass() calls here, because we need to make sure
|
|
// we always remove classes first and add them second, otherwise if both classes have the
|
|
// same theme class, it will be removed after we add it.
|
|
this._removeClass( this.button, "ui-selectmenu-button-" +
|
|
( this.isOpen ? "closed" : "open" ) )
|
|
._addClass( this.button, "ui-selectmenu-button-" +
|
|
( this.isOpen ? "open" : "closed" ) )
|
|
._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
|
|
|
|
this.menu.attr( "aria-hidden", !this.isOpen );
|
|
},
|
|
|
|
_resizeButton: function() {
|
|
var width = this.options.width;
|
|
|
|
// For `width: false`, just remove inline style and stop
|
|
if ( width === false ) {
|
|
this.button.css( "width", "" );
|
|
return;
|
|
}
|
|
|
|
// For `width: null`, match the width of the original element
|
|
if ( width === null ) {
|
|
width = this.element.show().outerWidth();
|
|
this.element.hide();
|
|
}
|
|
|
|
this.button.outerWidth( width );
|
|
},
|
|
|
|
_resizeMenu: function() {
|
|
this.menu.outerWidth( Math.max(
|
|
this.button.outerWidth(),
|
|
|
|
// Support: IE10
|
|
// IE10 wraps long text (possibly a rounding bug)
|
|
// so we add 1px to avoid the wrapping
|
|
this.menu.width( "" ).outerWidth() + 1
|
|
) );
|
|
},
|
|
|
|
_getCreateOptions: function() {
|
|
var options = this._super();
|
|
|
|
options.disabled = this.element.prop( "disabled" );
|
|
|
|
return options;
|
|
},
|
|
|
|
_parseOptions: function( options ) {
|
|
var that = this,
|
|
data = [];
|
|
options.each( function( index, item ) {
|
|
data.push( that._parseOption( $( item ), index ) );
|
|
} );
|
|
this.items = data;
|
|
},
|
|
|
|
_parseOption: function( option, index ) {
|
|
var optgroup = option.parent( "optgroup" );
|
|
|
|
return {
|
|
element: option,
|
|
index: index,
|
|
value: option.val(),
|
|
label: option.text(),
|
|
optgroup: optgroup.attr( "label" ) || "",
|
|
disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
|
|
};
|
|
},
|
|
|
|
_destroy: function() {
|
|
this._unbindFormResetHandler();
|
|
this.menuWrap.remove();
|
|
this.button.remove();
|
|
this.element.show();
|
|
this.element.removeUniqueId();
|
|
this.labels.attr( "for", this.ids.element );
|
|
}
|
|
} ] );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 64 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Slider 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Slider
|
|
//>>group: Widgets
|
|
//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
|
|
//>>docs: http://api.jqueryui.com/slider/
|
|
//>>demos: http://jqueryui.com/slider/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/slider.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(56),
|
|
__webpack_require__(43),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.widget( "ui.slider", $.ui.mouse, {
|
|
version: "1.12.1",
|
|
widgetEventPrefix: "slide",
|
|
|
|
options: {
|
|
animate: false,
|
|
classes: {
|
|
"ui-slider": "ui-corner-all",
|
|
"ui-slider-handle": "ui-corner-all",
|
|
|
|
// Note: ui-widget-header isn't the most fittingly semantic framework class for this
|
|
// element, but worked best visually with a variety of themes
|
|
"ui-slider-range": "ui-corner-all ui-widget-header"
|
|
},
|
|
distance: 0,
|
|
max: 100,
|
|
min: 0,
|
|
orientation: "horizontal",
|
|
range: false,
|
|
step: 1,
|
|
value: 0,
|
|
values: null,
|
|
|
|
// Callbacks
|
|
change: null,
|
|
slide: null,
|
|
start: null,
|
|
stop: null
|
|
},
|
|
|
|
// Number of pages in a slider
|
|
// (how many times can you page up/down to go through the whole range)
|
|
numPages: 5,
|
|
|
|
_create: function() {
|
|
this._keySliding = false;
|
|
this._mouseSliding = false;
|
|
this._animateOff = true;
|
|
this._handleIndex = null;
|
|
this._detectOrientation();
|
|
this._mouseInit();
|
|
this._calculateNewMax();
|
|
|
|
this._addClass( "ui-slider ui-slider-" + this.orientation,
|
|
"ui-widget ui-widget-content" );
|
|
|
|
this._refresh();
|
|
|
|
this._animateOff = false;
|
|
},
|
|
|
|
_refresh: function() {
|
|
this._createRange();
|
|
this._createHandles();
|
|
this._setupEvents();
|
|
this._refreshValue();
|
|
},
|
|
|
|
_createHandles: function() {
|
|
var i, handleCount,
|
|
options = this.options,
|
|
existingHandles = this.element.find( ".ui-slider-handle" ),
|
|
handle = "<span tabindex='0'></span>",
|
|
handles = [];
|
|
|
|
handleCount = ( options.values && options.values.length ) || 1;
|
|
|
|
if ( existingHandles.length > handleCount ) {
|
|
existingHandles.slice( handleCount ).remove();
|
|
existingHandles = existingHandles.slice( 0, handleCount );
|
|
}
|
|
|
|
for ( i = existingHandles.length; i < handleCount; i++ ) {
|
|
handles.push( handle );
|
|
}
|
|
|
|
this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
|
|
|
|
this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
|
|
|
|
this.handle = this.handles.eq( 0 );
|
|
|
|
this.handles.each( function( i ) {
|
|
$( this )
|
|
.data( "ui-slider-handle-index", i )
|
|
.attr( "tabIndex", 0 );
|
|
} );
|
|
},
|
|
|
|
_createRange: function() {
|
|
var options = this.options;
|
|
|
|
if ( options.range ) {
|
|
if ( options.range === true ) {
|
|
if ( !options.values ) {
|
|
options.values = [ this._valueMin(), this._valueMin() ];
|
|
} else if ( options.values.length && options.values.length !== 2 ) {
|
|
options.values = [ options.values[ 0 ], options.values[ 0 ] ];
|
|
} else if ( $.isArray( options.values ) ) {
|
|
options.values = options.values.slice( 0 );
|
|
}
|
|
}
|
|
|
|
if ( !this.range || !this.range.length ) {
|
|
this.range = $( "<div>" )
|
|
.appendTo( this.element );
|
|
|
|
this._addClass( this.range, "ui-slider-range" );
|
|
} else {
|
|
this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
|
|
|
|
// Handle range switching from true to min/max
|
|
this.range.css( {
|
|
"left": "",
|
|
"bottom": ""
|
|
} );
|
|
}
|
|
if ( options.range === "min" || options.range === "max" ) {
|
|
this._addClass( this.range, "ui-slider-range-" + options.range );
|
|
}
|
|
} else {
|
|
if ( this.range ) {
|
|
this.range.remove();
|
|
}
|
|
this.range = null;
|
|
}
|
|
},
|
|
|
|
_setupEvents: function() {
|
|
this._off( this.handles );
|
|
this._on( this.handles, this._handleEvents );
|
|
this._hoverable( this.handles );
|
|
this._focusable( this.handles );
|
|
},
|
|
|
|
_destroy: function() {
|
|
this.handles.remove();
|
|
if ( this.range ) {
|
|
this.range.remove();
|
|
}
|
|
|
|
this._mouseDestroy();
|
|
},
|
|
|
|
_mouseCapture: function( event ) {
|
|
var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
|
|
that = this,
|
|
o = this.options;
|
|
|
|
if ( o.disabled ) {
|
|
return false;
|
|
}
|
|
|
|
this.elementSize = {
|
|
width: this.element.outerWidth(),
|
|
height: this.element.outerHeight()
|
|
};
|
|
this.elementOffset = this.element.offset();
|
|
|
|
position = { x: event.pageX, y: event.pageY };
|
|
normValue = this._normValueFromMouse( position );
|
|
distance = this._valueMax() - this._valueMin() + 1;
|
|
this.handles.each( function( i ) {
|
|
var thisDistance = Math.abs( normValue - that.values( i ) );
|
|
if ( ( distance > thisDistance ) ||
|
|
( distance === thisDistance &&
|
|
( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
|
|
distance = thisDistance;
|
|
closestHandle = $( this );
|
|
index = i;
|
|
}
|
|
} );
|
|
|
|
allowed = this._start( event, index );
|
|
if ( allowed === false ) {
|
|
return false;
|
|
}
|
|
this._mouseSliding = true;
|
|
|
|
this._handleIndex = index;
|
|
|
|
this._addClass( closestHandle, null, "ui-state-active" );
|
|
closestHandle.trigger( "focus" );
|
|
|
|
offset = closestHandle.offset();
|
|
mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
|
|
this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
|
|
left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
|
|
top: event.pageY - offset.top -
|
|
( closestHandle.height() / 2 ) -
|
|
( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
|
|
( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
|
|
( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
|
|
};
|
|
|
|
if ( !this.handles.hasClass( "ui-state-hover" ) ) {
|
|
this._slide( event, index, normValue );
|
|
}
|
|
this._animateOff = true;
|
|
return true;
|
|
},
|
|
|
|
_mouseStart: function() {
|
|
return true;
|
|
},
|
|
|
|
_mouseDrag: function( event ) {
|
|
var position = { x: event.pageX, y: event.pageY },
|
|
normValue = this._normValueFromMouse( position );
|
|
|
|
this._slide( event, this._handleIndex, normValue );
|
|
|
|
return false;
|
|
},
|
|
|
|
_mouseStop: function( event ) {
|
|
this._removeClass( this.handles, null, "ui-state-active" );
|
|
this._mouseSliding = false;
|
|
|
|
this._stop( event, this._handleIndex );
|
|
this._change( event, this._handleIndex );
|
|
|
|
this._handleIndex = null;
|
|
this._clickOffset = null;
|
|
this._animateOff = false;
|
|
|
|
return false;
|
|
},
|
|
|
|
_detectOrientation: function() {
|
|
this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
|
|
},
|
|
|
|
_normValueFromMouse: function( position ) {
|
|
var pixelTotal,
|
|
pixelMouse,
|
|
percentMouse,
|
|
valueTotal,
|
|
valueMouse;
|
|
|
|
if ( this.orientation === "horizontal" ) {
|
|
pixelTotal = this.elementSize.width;
|
|
pixelMouse = position.x - this.elementOffset.left -
|
|
( this._clickOffset ? this._clickOffset.left : 0 );
|
|
} else {
|
|
pixelTotal = this.elementSize.height;
|
|
pixelMouse = position.y - this.elementOffset.top -
|
|
( this._clickOffset ? this._clickOffset.top : 0 );
|
|
}
|
|
|
|
percentMouse = ( pixelMouse / pixelTotal );
|
|
if ( percentMouse > 1 ) {
|
|
percentMouse = 1;
|
|
}
|
|
if ( percentMouse < 0 ) {
|
|
percentMouse = 0;
|
|
}
|
|
if ( this.orientation === "vertical" ) {
|
|
percentMouse = 1 - percentMouse;
|
|
}
|
|
|
|
valueTotal = this._valueMax() - this._valueMin();
|
|
valueMouse = this._valueMin() + percentMouse * valueTotal;
|
|
|
|
return this._trimAlignValue( valueMouse );
|
|
},
|
|
|
|
_uiHash: function( index, value, values ) {
|
|
var uiHash = {
|
|
handle: this.handles[ index ],
|
|
handleIndex: index,
|
|
value: value !== undefined ? value : this.value()
|
|
};
|
|
|
|
if ( this._hasMultipleValues() ) {
|
|
uiHash.value = value !== undefined ? value : this.values( index );
|
|
uiHash.values = values || this.values();
|
|
}
|
|
|
|
return uiHash;
|
|
},
|
|
|
|
_hasMultipleValues: function() {
|
|
return this.options.values && this.options.values.length;
|
|
},
|
|
|
|
_start: function( event, index ) {
|
|
return this._trigger( "start", event, this._uiHash( index ) );
|
|
},
|
|
|
|
_slide: function( event, index, newVal ) {
|
|
var allowed, otherVal,
|
|
currentValue = this.value(),
|
|
newValues = this.values();
|
|
|
|
if ( this._hasMultipleValues() ) {
|
|
otherVal = this.values( index ? 0 : 1 );
|
|
currentValue = this.values( index );
|
|
|
|
if ( this.options.values.length === 2 && this.options.range === true ) {
|
|
newVal = index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
|
|
}
|
|
|
|
newValues[ index ] = newVal;
|
|
}
|
|
|
|
if ( newVal === currentValue ) {
|
|
return;
|
|
}
|
|
|
|
allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
|
|
|
|
// A slide can be canceled by returning false from the slide callback
|
|
if ( allowed === false ) {
|
|
return;
|
|
}
|
|
|
|
if ( this._hasMultipleValues() ) {
|
|
this.values( index, newVal );
|
|
} else {
|
|
this.value( newVal );
|
|
}
|
|
},
|
|
|
|
_stop: function( event, index ) {
|
|
this._trigger( "stop", event, this._uiHash( index ) );
|
|
},
|
|
|
|
_change: function( event, index ) {
|
|
if ( !this._keySliding && !this._mouseSliding ) {
|
|
|
|
//store the last changed value index for reference when handles overlap
|
|
this._lastChangedValue = index;
|
|
this._trigger( "change", event, this._uiHash( index ) );
|
|
}
|
|
},
|
|
|
|
value: function( newValue ) {
|
|
if ( arguments.length ) {
|
|
this.options.value = this._trimAlignValue( newValue );
|
|
this._refreshValue();
|
|
this._change( null, 0 );
|
|
return;
|
|
}
|
|
|
|
return this._value();
|
|
},
|
|
|
|
values: function( index, newValue ) {
|
|
var vals,
|
|
newValues,
|
|
i;
|
|
|
|
if ( arguments.length > 1 ) {
|
|
this.options.values[ index ] = this._trimAlignValue( newValue );
|
|
this._refreshValue();
|
|
this._change( null, index );
|
|
return;
|
|
}
|
|
|
|
if ( arguments.length ) {
|
|
if ( $.isArray( arguments[ 0 ] ) ) {
|
|
vals = this.options.values;
|
|
newValues = arguments[ 0 ];
|
|
for ( i = 0; i < vals.length; i += 1 ) {
|
|
vals[ i ] = this._trimAlignValue( newValues[ i ] );
|
|
this._change( null, i );
|
|
}
|
|
this._refreshValue();
|
|
} else {
|
|
if ( this._hasMultipleValues() ) {
|
|
return this._values( index );
|
|
} else {
|
|
return this.value();
|
|
}
|
|
}
|
|
} else {
|
|
return this._values();
|
|
}
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
var i,
|
|
valsLength = 0;
|
|
|
|
if ( key === "range" && this.options.range === true ) {
|
|
if ( value === "min" ) {
|
|
this.options.value = this._values( 0 );
|
|
this.options.values = null;
|
|
} else if ( value === "max" ) {
|
|
this.options.value = this._values( this.options.values.length - 1 );
|
|
this.options.values = null;
|
|
}
|
|
}
|
|
|
|
if ( $.isArray( this.options.values ) ) {
|
|
valsLength = this.options.values.length;
|
|
}
|
|
|
|
this._super( key, value );
|
|
|
|
switch ( key ) {
|
|
case "orientation":
|
|
this._detectOrientation();
|
|
this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
|
|
._addClass( "ui-slider-" + this.orientation );
|
|
this._refreshValue();
|
|
if ( this.options.range ) {
|
|
this._refreshRange( value );
|
|
}
|
|
|
|
// Reset positioning from previous orientation
|
|
this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
|
|
break;
|
|
case "value":
|
|
this._animateOff = true;
|
|
this._refreshValue();
|
|
this._change( null, 0 );
|
|
this._animateOff = false;
|
|
break;
|
|
case "values":
|
|
this._animateOff = true;
|
|
this._refreshValue();
|
|
|
|
// Start from the last handle to prevent unreachable handles (#9046)
|
|
for ( i = valsLength - 1; i >= 0; i-- ) {
|
|
this._change( null, i );
|
|
}
|
|
this._animateOff = false;
|
|
break;
|
|
case "step":
|
|
case "min":
|
|
case "max":
|
|
this._animateOff = true;
|
|
this._calculateNewMax();
|
|
this._refreshValue();
|
|
this._animateOff = false;
|
|
break;
|
|
case "range":
|
|
this._animateOff = true;
|
|
this._refresh();
|
|
this._animateOff = false;
|
|
break;
|
|
}
|
|
},
|
|
|
|
_setOptionDisabled: function( value ) {
|
|
this._super( value );
|
|
|
|
this._toggleClass( null, "ui-state-disabled", !!value );
|
|
},
|
|
|
|
//internal value getter
|
|
// _value() returns value trimmed by min and max, aligned by step
|
|
_value: function() {
|
|
var val = this.options.value;
|
|
val = this._trimAlignValue( val );
|
|
|
|
return val;
|
|
},
|
|
|
|
//internal values getter
|
|
// _values() returns array of values trimmed by min and max, aligned by step
|
|
// _values( index ) returns single value trimmed by min and max, aligned by step
|
|
_values: function( index ) {
|
|
var val,
|
|
vals,
|
|
i;
|
|
|
|
if ( arguments.length ) {
|
|
val = this.options.values[ index ];
|
|
val = this._trimAlignValue( val );
|
|
|
|
return val;
|
|
} else if ( this._hasMultipleValues() ) {
|
|
|
|
// .slice() creates a copy of the array
|
|
// this copy gets trimmed by min and max and then returned
|
|
vals = this.options.values.slice();
|
|
for ( i = 0; i < vals.length; i += 1 ) {
|
|
vals[ i ] = this._trimAlignValue( vals[ i ] );
|
|
}
|
|
|
|
return vals;
|
|
} else {
|
|
return [];
|
|
}
|
|
},
|
|
|
|
// Returns the step-aligned value that val is closest to, between (inclusive) min and max
|
|
_trimAlignValue: function( val ) {
|
|
if ( val <= this._valueMin() ) {
|
|
return this._valueMin();
|
|
}
|
|
if ( val >= this._valueMax() ) {
|
|
return this._valueMax();
|
|
}
|
|
var step = ( this.options.step > 0 ) ? this.options.step : 1,
|
|
valModStep = ( val - this._valueMin() ) % step,
|
|
alignValue = val - valModStep;
|
|
|
|
if ( Math.abs( valModStep ) * 2 >= step ) {
|
|
alignValue += ( valModStep > 0 ) ? step : ( -step );
|
|
}
|
|
|
|
// Since JavaScript has problems with large floats, round
|
|
// the final value to 5 digits after the decimal point (see #4124)
|
|
return parseFloat( alignValue.toFixed( 5 ) );
|
|
},
|
|
|
|
_calculateNewMax: function() {
|
|
var max = this.options.max,
|
|
min = this._valueMin(),
|
|
step = this.options.step,
|
|
aboveMin = Math.round( ( max - min ) / step ) * step;
|
|
max = aboveMin + min;
|
|
if ( max > this.options.max ) {
|
|
|
|
//If max is not divisible by step, rounding off may increase its value
|
|
max -= step;
|
|
}
|
|
this.max = parseFloat( max.toFixed( this._precision() ) );
|
|
},
|
|
|
|
_precision: function() {
|
|
var precision = this._precisionOf( this.options.step );
|
|
if ( this.options.min !== null ) {
|
|
precision = Math.max( precision, this._precisionOf( this.options.min ) );
|
|
}
|
|
return precision;
|
|
},
|
|
|
|
_precisionOf: function( num ) {
|
|
var str = num.toString(),
|
|
decimal = str.indexOf( "." );
|
|
return decimal === -1 ? 0 : str.length - decimal - 1;
|
|
},
|
|
|
|
_valueMin: function() {
|
|
return this.options.min;
|
|
},
|
|
|
|
_valueMax: function() {
|
|
return this.max;
|
|
},
|
|
|
|
_refreshRange: function( orientation ) {
|
|
if ( orientation === "vertical" ) {
|
|
this.range.css( { "width": "", "left": "" } );
|
|
}
|
|
if ( orientation === "horizontal" ) {
|
|
this.range.css( { "height": "", "bottom": "" } );
|
|
}
|
|
},
|
|
|
|
_refreshValue: function() {
|
|
var lastValPercent, valPercent, value, valueMin, valueMax,
|
|
oRange = this.options.range,
|
|
o = this.options,
|
|
that = this,
|
|
animate = ( !this._animateOff ) ? o.animate : false,
|
|
_set = {};
|
|
|
|
if ( this._hasMultipleValues() ) {
|
|
this.handles.each( function( i ) {
|
|
valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
|
|
that._valueMin() ) * 100;
|
|
_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
|
|
$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
|
|
if ( that.options.range === true ) {
|
|
if ( that.orientation === "horizontal" ) {
|
|
if ( i === 0 ) {
|
|
that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
|
|
left: valPercent + "%"
|
|
}, o.animate );
|
|
}
|
|
if ( i === 1 ) {
|
|
that.range[ animate ? "animate" : "css" ]( {
|
|
width: ( valPercent - lastValPercent ) + "%"
|
|
}, {
|
|
queue: false,
|
|
duration: o.animate
|
|
} );
|
|
}
|
|
} else {
|
|
if ( i === 0 ) {
|
|
that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
|
|
bottom: ( valPercent ) + "%"
|
|
}, o.animate );
|
|
}
|
|
if ( i === 1 ) {
|
|
that.range[ animate ? "animate" : "css" ]( {
|
|
height: ( valPercent - lastValPercent ) + "%"
|
|
}, {
|
|
queue: false,
|
|
duration: o.animate
|
|
} );
|
|
}
|
|
}
|
|
}
|
|
lastValPercent = valPercent;
|
|
} );
|
|
} else {
|
|
value = this.value();
|
|
valueMin = this._valueMin();
|
|
valueMax = this._valueMax();
|
|
valPercent = ( valueMax !== valueMin ) ?
|
|
( value - valueMin ) / ( valueMax - valueMin ) * 100 :
|
|
0;
|
|
_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
|
|
this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
|
|
|
|
if ( oRange === "min" && this.orientation === "horizontal" ) {
|
|
this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
|
|
width: valPercent + "%"
|
|
}, o.animate );
|
|
}
|
|
if ( oRange === "max" && this.orientation === "horizontal" ) {
|
|
this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
|
|
width: ( 100 - valPercent ) + "%"
|
|
}, o.animate );
|
|
}
|
|
if ( oRange === "min" && this.orientation === "vertical" ) {
|
|
this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
|
|
height: valPercent + "%"
|
|
}, o.animate );
|
|
}
|
|
if ( oRange === "max" && this.orientation === "vertical" ) {
|
|
this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
|
|
height: ( 100 - valPercent ) + "%"
|
|
}, o.animate );
|
|
}
|
|
}
|
|
},
|
|
|
|
_handleEvents: {
|
|
keydown: function( event ) {
|
|
var allowed, curVal, newVal, step,
|
|
index = $( event.target ).data( "ui-slider-handle-index" );
|
|
|
|
switch ( event.keyCode ) {
|
|
case $.ui.keyCode.HOME:
|
|
case $.ui.keyCode.END:
|
|
case $.ui.keyCode.PAGE_UP:
|
|
case $.ui.keyCode.PAGE_DOWN:
|
|
case $.ui.keyCode.UP:
|
|
case $.ui.keyCode.RIGHT:
|
|
case $.ui.keyCode.DOWN:
|
|
case $.ui.keyCode.LEFT:
|
|
event.preventDefault();
|
|
if ( !this._keySliding ) {
|
|
this._keySliding = true;
|
|
this._addClass( $( event.target ), null, "ui-state-active" );
|
|
allowed = this._start( event, index );
|
|
if ( allowed === false ) {
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
step = this.options.step;
|
|
if ( this._hasMultipleValues() ) {
|
|
curVal = newVal = this.values( index );
|
|
} else {
|
|
curVal = newVal = this.value();
|
|
}
|
|
|
|
switch ( event.keyCode ) {
|
|
case $.ui.keyCode.HOME:
|
|
newVal = this._valueMin();
|
|
break;
|
|
case $.ui.keyCode.END:
|
|
newVal = this._valueMax();
|
|
break;
|
|
case $.ui.keyCode.PAGE_UP:
|
|
newVal = this._trimAlignValue(
|
|
curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
|
|
);
|
|
break;
|
|
case $.ui.keyCode.PAGE_DOWN:
|
|
newVal = this._trimAlignValue(
|
|
curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
|
|
break;
|
|
case $.ui.keyCode.UP:
|
|
case $.ui.keyCode.RIGHT:
|
|
if ( curVal === this._valueMax() ) {
|
|
return;
|
|
}
|
|
newVal = this._trimAlignValue( curVal + step );
|
|
break;
|
|
case $.ui.keyCode.DOWN:
|
|
case $.ui.keyCode.LEFT:
|
|
if ( curVal === this._valueMin() ) {
|
|
return;
|
|
}
|
|
newVal = this._trimAlignValue( curVal - step );
|
|
break;
|
|
}
|
|
|
|
this._slide( event, index, newVal );
|
|
},
|
|
keyup: function( event ) {
|
|
var index = $( event.target ).data( "ui-slider-handle-index" );
|
|
|
|
if ( this._keySliding ) {
|
|
this._keySliding = false;
|
|
this._stop( event, index );
|
|
this._change( event, index );
|
|
this._removeClass( $( event.target ), null, "ui-state-active" );
|
|
}
|
|
}
|
|
}
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 65 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Sortable 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Sortable
|
|
//>>group: Interactions
|
|
//>>description: Enables items in a list to be sorted using the mouse.
|
|
//>>docs: http://api.jqueryui.com/sortable/
|
|
//>>demos: http://jqueryui.com/sortable/
|
|
//>>css.structure: ../../themes/base/sortable.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(56),
|
|
__webpack_require__(22),
|
|
__webpack_require__(16),
|
|
__webpack_require__(46),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
return $.widget( "ui.sortable", $.ui.mouse, {
|
|
version: "1.12.1",
|
|
widgetEventPrefix: "sort",
|
|
ready: false,
|
|
options: {
|
|
appendTo: "parent",
|
|
axis: false,
|
|
connectWith: false,
|
|
containment: false,
|
|
cursor: "auto",
|
|
cursorAt: false,
|
|
dropOnEmpty: true,
|
|
forcePlaceholderSize: false,
|
|
forceHelperSize: false,
|
|
grid: false,
|
|
handle: false,
|
|
helper: "original",
|
|
items: "> *",
|
|
opacity: false,
|
|
placeholder: false,
|
|
revert: false,
|
|
scroll: true,
|
|
scrollSensitivity: 20,
|
|
scrollSpeed: 20,
|
|
scope: "default",
|
|
tolerance: "intersect",
|
|
zIndex: 1000,
|
|
|
|
// Callbacks
|
|
activate: null,
|
|
beforeStop: null,
|
|
change: null,
|
|
deactivate: null,
|
|
out: null,
|
|
over: null,
|
|
receive: null,
|
|
remove: null,
|
|
sort: null,
|
|
start: null,
|
|
stop: null,
|
|
update: null
|
|
},
|
|
|
|
_isOverAxis: function( x, reference, size ) {
|
|
return ( x >= reference ) && ( x < ( reference + size ) );
|
|
},
|
|
|
|
_isFloating: function( item ) {
|
|
return ( /left|right/ ).test( item.css( "float" ) ) ||
|
|
( /inline|table-cell/ ).test( item.css( "display" ) );
|
|
},
|
|
|
|
_create: function() {
|
|
this.containerCache = {};
|
|
this._addClass( "ui-sortable" );
|
|
|
|
//Get the items
|
|
this.refresh();
|
|
|
|
//Let's determine the parent's offset
|
|
this.offset = this.element.offset();
|
|
|
|
//Initialize mouse events for interaction
|
|
this._mouseInit();
|
|
|
|
this._setHandleClassName();
|
|
|
|
//We're ready to go
|
|
this.ready = true;
|
|
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
this._super( key, value );
|
|
|
|
if ( key === "handle" ) {
|
|
this._setHandleClassName();
|
|
}
|
|
},
|
|
|
|
_setHandleClassName: function() {
|
|
var that = this;
|
|
this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
|
|
$.each( this.items, function() {
|
|
that._addClass(
|
|
this.instance.options.handle ?
|
|
this.item.find( this.instance.options.handle ) :
|
|
this.item,
|
|
"ui-sortable-handle"
|
|
);
|
|
} );
|
|
},
|
|
|
|
_destroy: function() {
|
|
this._mouseDestroy();
|
|
|
|
for ( var i = this.items.length - 1; i >= 0; i-- ) {
|
|
this.items[ i ].item.removeData( this.widgetName + "-item" );
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
_mouseCapture: function( event, overrideHandle ) {
|
|
var currentItem = null,
|
|
validHandle = false,
|
|
that = this;
|
|
|
|
if ( this.reverting ) {
|
|
return false;
|
|
}
|
|
|
|
if ( this.options.disabled || this.options.type === "static" ) {
|
|
return false;
|
|
}
|
|
|
|
//We have to refresh the items data once first
|
|
this._refreshItems( event );
|
|
|
|
//Find out if the clicked node (or one of its parents) is a actual item in this.items
|
|
$( event.target ).parents().each( function() {
|
|
if ( $.data( this, that.widgetName + "-item" ) === that ) {
|
|
currentItem = $( this );
|
|
return false;
|
|
}
|
|
} );
|
|
if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
|
|
currentItem = $( event.target );
|
|
}
|
|
|
|
if ( !currentItem ) {
|
|
return false;
|
|
}
|
|
if ( this.options.handle && !overrideHandle ) {
|
|
$( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
|
|
if ( this === event.target ) {
|
|
validHandle = true;
|
|
}
|
|
} );
|
|
if ( !validHandle ) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
this.currentItem = currentItem;
|
|
this._removeCurrentsFromItems();
|
|
return true;
|
|
|
|
},
|
|
|
|
_mouseStart: function( event, overrideHandle, noActivation ) {
|
|
|
|
var i, body,
|
|
o = this.options;
|
|
|
|
this.currentContainer = this;
|
|
|
|
//We only need to call refreshPositions, because the refreshItems call has been moved to
|
|
// mouseCapture
|
|
this.refreshPositions();
|
|
|
|
//Create and append the visible helper
|
|
this.helper = this._createHelper( event );
|
|
|
|
//Cache the helper size
|
|
this._cacheHelperProportions();
|
|
|
|
/*
|
|
* - Position generation -
|
|
* This block generates everything position related - it's the core of draggables.
|
|
*/
|
|
|
|
//Cache the margins of the original element
|
|
this._cacheMargins();
|
|
|
|
//Get the next scrolling parent
|
|
this.scrollParent = this.helper.scrollParent();
|
|
|
|
//The element's absolute position on the page minus margins
|
|
this.offset = this.currentItem.offset();
|
|
this.offset = {
|
|
top: this.offset.top - this.margins.top,
|
|
left: this.offset.left - this.margins.left
|
|
};
|
|
|
|
$.extend( this.offset, {
|
|
click: { //Where the click happened, relative to the element
|
|
left: event.pageX - this.offset.left,
|
|
top: event.pageY - this.offset.top
|
|
},
|
|
parent: this._getParentOffset(),
|
|
|
|
// This is a relative to absolute position minus the actual position calculation -
|
|
// only used for relative positioned helper
|
|
relative: this._getRelativeOffset()
|
|
} );
|
|
|
|
// Only after we got the offset, we can change the helper's position to absolute
|
|
// TODO: Still need to figure out a way to make relative sorting possible
|
|
this.helper.css( "position", "absolute" );
|
|
this.cssPosition = this.helper.css( "position" );
|
|
|
|
//Generate the original position
|
|
this.originalPosition = this._generatePosition( event );
|
|
this.originalPageX = event.pageX;
|
|
this.originalPageY = event.pageY;
|
|
|
|
//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
|
|
( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );
|
|
|
|
//Cache the former DOM position
|
|
this.domPosition = {
|
|
prev: this.currentItem.prev()[ 0 ],
|
|
parent: this.currentItem.parent()[ 0 ]
|
|
};
|
|
|
|
// If the helper is not the original, hide the original so it's not playing any role during
|
|
// the drag, won't cause anything bad this way
|
|
if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
|
|
this.currentItem.hide();
|
|
}
|
|
|
|
//Create the placeholder
|
|
this._createPlaceholder();
|
|
|
|
//Set a containment if given in the options
|
|
if ( o.containment ) {
|
|
this._setContainment();
|
|
}
|
|
|
|
if ( o.cursor && o.cursor !== "auto" ) { // cursor option
|
|
body = this.document.find( "body" );
|
|
|
|
// Support: IE
|
|
this.storedCursor = body.css( "cursor" );
|
|
body.css( "cursor", o.cursor );
|
|
|
|
this.storedStylesheet =
|
|
$( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
|
|
}
|
|
|
|
if ( o.opacity ) { // opacity option
|
|
if ( this.helper.css( "opacity" ) ) {
|
|
this._storedOpacity = this.helper.css( "opacity" );
|
|
}
|
|
this.helper.css( "opacity", o.opacity );
|
|
}
|
|
|
|
if ( o.zIndex ) { // zIndex option
|
|
if ( this.helper.css( "zIndex" ) ) {
|
|
this._storedZIndex = this.helper.css( "zIndex" );
|
|
}
|
|
this.helper.css( "zIndex", o.zIndex );
|
|
}
|
|
|
|
//Prepare scrolling
|
|
if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
|
|
this.scrollParent[ 0 ].tagName !== "HTML" ) {
|
|
this.overflowOffset = this.scrollParent.offset();
|
|
}
|
|
|
|
//Call callbacks
|
|
this._trigger( "start", event, this._uiHash() );
|
|
|
|
//Recache the helper size
|
|
if ( !this._preserveHelperProportions ) {
|
|
this._cacheHelperProportions();
|
|
}
|
|
|
|
//Post "activate" events to possible containers
|
|
if ( !noActivation ) {
|
|
for ( i = this.containers.length - 1; i >= 0; i-- ) {
|
|
this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
|
|
}
|
|
}
|
|
|
|
//Prepare possible droppables
|
|
if ( $.ui.ddmanager ) {
|
|
$.ui.ddmanager.current = this;
|
|
}
|
|
|
|
if ( $.ui.ddmanager && !o.dropBehaviour ) {
|
|
$.ui.ddmanager.prepareOffsets( this, event );
|
|
}
|
|
|
|
this.dragging = true;
|
|
|
|
this._addClass( this.helper, "ui-sortable-helper" );
|
|
|
|
// Execute the drag once - this causes the helper not to be visiblebefore getting its
|
|
// correct position
|
|
this._mouseDrag( event );
|
|
return true;
|
|
|
|
},
|
|
|
|
_mouseDrag: function( event ) {
|
|
var i, item, itemElement, intersection,
|
|
o = this.options,
|
|
scrolled = false;
|
|
|
|
//Compute the helpers position
|
|
this.position = this._generatePosition( event );
|
|
this.positionAbs = this._convertPositionTo( "absolute" );
|
|
|
|
if ( !this.lastPositionAbs ) {
|
|
this.lastPositionAbs = this.positionAbs;
|
|
}
|
|
|
|
//Do scrolling
|
|
if ( this.options.scroll ) {
|
|
if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
|
|
this.scrollParent[ 0 ].tagName !== "HTML" ) {
|
|
|
|
if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
|
|
event.pageY < o.scrollSensitivity ) {
|
|
this.scrollParent[ 0 ].scrollTop =
|
|
scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
|
|
} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
|
|
this.scrollParent[ 0 ].scrollTop =
|
|
scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
|
|
}
|
|
|
|
if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
|
|
event.pageX < o.scrollSensitivity ) {
|
|
this.scrollParent[ 0 ].scrollLeft = scrolled =
|
|
this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
|
|
} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
|
|
this.scrollParent[ 0 ].scrollLeft = scrolled =
|
|
this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
|
|
}
|
|
|
|
} else {
|
|
|
|
if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
|
|
scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
|
|
} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
|
|
o.scrollSensitivity ) {
|
|
scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
|
|
}
|
|
|
|
if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
|
|
scrolled = this.document.scrollLeft(
|
|
this.document.scrollLeft() - o.scrollSpeed
|
|
);
|
|
} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
|
|
o.scrollSensitivity ) {
|
|
scrolled = this.document.scrollLeft(
|
|
this.document.scrollLeft() + o.scrollSpeed
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
|
|
$.ui.ddmanager.prepareOffsets( this, event );
|
|
}
|
|
}
|
|
|
|
//Regenerate the absolute position used for position checks
|
|
this.positionAbs = this._convertPositionTo( "absolute" );
|
|
|
|
//Set the helper position
|
|
if ( !this.options.axis || this.options.axis !== "y" ) {
|
|
this.helper[ 0 ].style.left = this.position.left + "px";
|
|
}
|
|
if ( !this.options.axis || this.options.axis !== "x" ) {
|
|
this.helper[ 0 ].style.top = this.position.top + "px";
|
|
}
|
|
|
|
//Rearrange
|
|
for ( i = this.items.length - 1; i >= 0; i-- ) {
|
|
|
|
//Cache variables and intersection, continue if no intersection
|
|
item = this.items[ i ];
|
|
itemElement = item.item[ 0 ];
|
|
intersection = this._intersectsWithPointer( item );
|
|
if ( !intersection ) {
|
|
continue;
|
|
}
|
|
|
|
// Only put the placeholder inside the current Container, skip all
|
|
// items from other containers. This works because when moving
|
|
// an item from one container to another the
|
|
// currentContainer is switched before the placeholder is moved.
|
|
//
|
|
// Without this, moving items in "sub-sortables" can cause
|
|
// the placeholder to jitter between the outer and inner container.
|
|
if ( item.instance !== this.currentContainer ) {
|
|
continue;
|
|
}
|
|
|
|
// Cannot intersect with itself
|
|
// no useless actions that have been done before
|
|
// no action if the item moved is the parent of the item checked
|
|
if ( itemElement !== this.currentItem[ 0 ] &&
|
|
this.placeholder[ intersection === 1 ? "next" : "prev" ]()[ 0 ] !== itemElement &&
|
|
!$.contains( this.placeholder[ 0 ], itemElement ) &&
|
|
( this.options.type === "semi-dynamic" ?
|
|
!$.contains( this.element[ 0 ], itemElement ) :
|
|
true
|
|
)
|
|
) {
|
|
|
|
this.direction = intersection === 1 ? "down" : "up";
|
|
|
|
if ( this.options.tolerance === "pointer" || this._intersectsWithSides( item ) ) {
|
|
this._rearrange( event, item );
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
this._trigger( "change", event, this._uiHash() );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Post events to containers
|
|
this._contactContainers( event );
|
|
|
|
//Interconnect with droppables
|
|
if ( $.ui.ddmanager ) {
|
|
$.ui.ddmanager.drag( this, event );
|
|
}
|
|
|
|
//Call callbacks
|
|
this._trigger( "sort", event, this._uiHash() );
|
|
|
|
this.lastPositionAbs = this.positionAbs;
|
|
return false;
|
|
|
|
},
|
|
|
|
_mouseStop: function( event, noPropagation ) {
|
|
|
|
if ( !event ) {
|
|
return;
|
|
}
|
|
|
|
//If we are using droppables, inform the manager about the drop
|
|
if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
|
|
$.ui.ddmanager.drop( this, event );
|
|
}
|
|
|
|
if ( this.options.revert ) {
|
|
var that = this,
|
|
cur = this.placeholder.offset(),
|
|
axis = this.options.axis,
|
|
animation = {};
|
|
|
|
if ( !axis || axis === "x" ) {
|
|
animation.left = cur.left - this.offset.parent.left - this.margins.left +
|
|
( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
|
|
0 :
|
|
this.offsetParent[ 0 ].scrollLeft
|
|
);
|
|
}
|
|
if ( !axis || axis === "y" ) {
|
|
animation.top = cur.top - this.offset.parent.top - this.margins.top +
|
|
( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
|
|
0 :
|
|
this.offsetParent[ 0 ].scrollTop
|
|
);
|
|
}
|
|
this.reverting = true;
|
|
$( this.helper ).animate(
|
|
animation,
|
|
parseInt( this.options.revert, 10 ) || 500,
|
|
function() {
|
|
that._clear( event );
|
|
}
|
|
);
|
|
} else {
|
|
this._clear( event, noPropagation );
|
|
}
|
|
|
|
return false;
|
|
|
|
},
|
|
|
|
cancel: function() {
|
|
|
|
if ( this.dragging ) {
|
|
|
|
this._mouseUp( new $.Event( "mouseup", { target: null } ) );
|
|
|
|
if ( this.options.helper === "original" ) {
|
|
this.currentItem.css( this._storedCSS );
|
|
this._removeClass( this.currentItem, "ui-sortable-helper" );
|
|
} else {
|
|
this.currentItem.show();
|
|
}
|
|
|
|
//Post deactivating events to containers
|
|
for ( var i = this.containers.length - 1; i >= 0; i-- ) {
|
|
this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
|
|
if ( this.containers[ i ].containerCache.over ) {
|
|
this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
|
|
this.containers[ i ].containerCache.over = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if ( this.placeholder ) {
|
|
|
|
//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
|
|
// it unbinds ALL events from the original node!
|
|
if ( this.placeholder[ 0 ].parentNode ) {
|
|
this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
|
|
}
|
|
if ( this.options.helper !== "original" && this.helper &&
|
|
this.helper[ 0 ].parentNode ) {
|
|
this.helper.remove();
|
|
}
|
|
|
|
$.extend( this, {
|
|
helper: null,
|
|
dragging: false,
|
|
reverting: false,
|
|
_noFinalSort: null
|
|
} );
|
|
|
|
if ( this.domPosition.prev ) {
|
|
$( this.domPosition.prev ).after( this.currentItem );
|
|
} else {
|
|
$( this.domPosition.parent ).prepend( this.currentItem );
|
|
}
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
serialize: function( o ) {
|
|
|
|
var items = this._getItemsAsjQuery( o && o.connected ),
|
|
str = [];
|
|
o = o || {};
|
|
|
|
$( items ).each( function() {
|
|
var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
|
|
.match( o.expression || ( /(.+)[\-=_](.+)/ ) );
|
|
if ( res ) {
|
|
str.push(
|
|
( o.key || res[ 1 ] + "[]" ) +
|
|
"=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
|
|
}
|
|
} );
|
|
|
|
if ( !str.length && o.key ) {
|
|
str.push( o.key + "=" );
|
|
}
|
|
|
|
return str.join( "&" );
|
|
|
|
},
|
|
|
|
toArray: function( o ) {
|
|
|
|
var items = this._getItemsAsjQuery( o && o.connected ),
|
|
ret = [];
|
|
|
|
o = o || {};
|
|
|
|
items.each( function() {
|
|
ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
|
|
} );
|
|
return ret;
|
|
|
|
},
|
|
|
|
/* Be careful with the following core functions */
|
|
_intersectsWith: function( item ) {
|
|
|
|
var x1 = this.positionAbs.left,
|
|
x2 = x1 + this.helperProportions.width,
|
|
y1 = this.positionAbs.top,
|
|
y2 = y1 + this.helperProportions.height,
|
|
l = item.left,
|
|
r = l + item.width,
|
|
t = item.top,
|
|
b = t + item.height,
|
|
dyClick = this.offset.click.top,
|
|
dxClick = this.offset.click.left,
|
|
isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
|
|
( y1 + dyClick ) < b ),
|
|
isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
|
|
( x1 + dxClick ) < r ),
|
|
isOverElement = isOverElementHeight && isOverElementWidth;
|
|
|
|
if ( this.options.tolerance === "pointer" ||
|
|
this.options.forcePointerForContainers ||
|
|
( this.options.tolerance !== "pointer" &&
|
|
this.helperProportions[ this.floating ? "width" : "height" ] >
|
|
item[ this.floating ? "width" : "height" ] )
|
|
) {
|
|
return isOverElement;
|
|
} else {
|
|
|
|
return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
|
|
x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
|
|
t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
|
|
y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
|
|
|
|
}
|
|
},
|
|
|
|
_intersectsWithPointer: function( item ) {
|
|
var verticalDirection, horizontalDirection,
|
|
isOverElementHeight = ( this.options.axis === "x" ) ||
|
|
this._isOverAxis(
|
|
this.positionAbs.top + this.offset.click.top, item.top, item.height ),
|
|
isOverElementWidth = ( this.options.axis === "y" ) ||
|
|
this._isOverAxis(
|
|
this.positionAbs.left + this.offset.click.left, item.left, item.width ),
|
|
isOverElement = isOverElementHeight && isOverElementWidth;
|
|
|
|
if ( !isOverElement ) {
|
|
return false;
|
|
}
|
|
|
|
verticalDirection = this._getDragVerticalDirection();
|
|
horizontalDirection = this._getDragHorizontalDirection();
|
|
|
|
return this.floating ?
|
|
( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 )
|
|
: ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
|
|
|
|
},
|
|
|
|
_intersectsWithSides: function( item ) {
|
|
|
|
var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
|
|
this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
|
|
isOverRightHalf = this._isOverAxis( this.positionAbs.left +
|
|
this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
|
|
verticalDirection = this._getDragVerticalDirection(),
|
|
horizontalDirection = this._getDragHorizontalDirection();
|
|
|
|
if ( this.floating && horizontalDirection ) {
|
|
return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
|
|
( horizontalDirection === "left" && !isOverRightHalf ) );
|
|
} else {
|
|
return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
|
|
( verticalDirection === "up" && !isOverBottomHalf ) );
|
|
}
|
|
|
|
},
|
|
|
|
_getDragVerticalDirection: function() {
|
|
var delta = this.positionAbs.top - this.lastPositionAbs.top;
|
|
return delta !== 0 && ( delta > 0 ? "down" : "up" );
|
|
},
|
|
|
|
_getDragHorizontalDirection: function() {
|
|
var delta = this.positionAbs.left - this.lastPositionAbs.left;
|
|
return delta !== 0 && ( delta > 0 ? "right" : "left" );
|
|
},
|
|
|
|
refresh: function( event ) {
|
|
this._refreshItems( event );
|
|
this._setHandleClassName();
|
|
this.refreshPositions();
|
|
return this;
|
|
},
|
|
|
|
_connectWith: function() {
|
|
var options = this.options;
|
|
return options.connectWith.constructor === String ?
|
|
[ options.connectWith ] :
|
|
options.connectWith;
|
|
},
|
|
|
|
_getItemsAsjQuery: function( connected ) {
|
|
|
|
var i, j, cur, inst,
|
|
items = [],
|
|
queries = [],
|
|
connectWith = this._connectWith();
|
|
|
|
if ( connectWith && connected ) {
|
|
for ( i = connectWith.length - 1; i >= 0; i-- ) {
|
|
cur = $( connectWith[ i ], this.document[ 0 ] );
|
|
for ( j = cur.length - 1; j >= 0; j-- ) {
|
|
inst = $.data( cur[ j ], this.widgetFullName );
|
|
if ( inst && inst !== this && !inst.options.disabled ) {
|
|
queries.push( [ $.isFunction( inst.options.items ) ?
|
|
inst.options.items.call( inst.element ) :
|
|
$( inst.options.items, inst.element )
|
|
.not( ".ui-sortable-helper" )
|
|
.not( ".ui-sortable-placeholder" ), inst ] );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
queries.push( [ $.isFunction( this.options.items ) ?
|
|
this.options.items
|
|
.call( this.element, null, { options: this.options, item: this.currentItem } ) :
|
|
$( this.options.items, this.element )
|
|
.not( ".ui-sortable-helper" )
|
|
.not( ".ui-sortable-placeholder" ), this ] );
|
|
|
|
function addItems() {
|
|
items.push( this );
|
|
}
|
|
for ( i = queries.length - 1; i >= 0; i-- ) {
|
|
queries[ i ][ 0 ].each( addItems );
|
|
}
|
|
|
|
return $( items );
|
|
|
|
},
|
|
|
|
_removeCurrentsFromItems: function() {
|
|
|
|
var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
|
|
|
|
this.items = $.grep( this.items, function( item ) {
|
|
for ( var j = 0; j < list.length; j++ ) {
|
|
if ( list[ j ] === item.item[ 0 ] ) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
} );
|
|
|
|
},
|
|
|
|
_refreshItems: function( event ) {
|
|
|
|
this.items = [];
|
|
this.containers = [ this ];
|
|
|
|
var i, j, cur, inst, targetData, _queries, item, queriesLength,
|
|
items = this.items,
|
|
queries = [ [ $.isFunction( this.options.items ) ?
|
|
this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
|
|
$( this.options.items, this.element ), this ] ],
|
|
connectWith = this._connectWith();
|
|
|
|
//Shouldn't be run the first time through due to massive slow-down
|
|
if ( connectWith && this.ready ) {
|
|
for ( i = connectWith.length - 1; i >= 0; i-- ) {
|
|
cur = $( connectWith[ i ], this.document[ 0 ] );
|
|
for ( j = cur.length - 1; j >= 0; j-- ) {
|
|
inst = $.data( cur[ j ], this.widgetFullName );
|
|
if ( inst && inst !== this && !inst.options.disabled ) {
|
|
queries.push( [ $.isFunction( inst.options.items ) ?
|
|
inst.options.items
|
|
.call( inst.element[ 0 ], event, { item: this.currentItem } ) :
|
|
$( inst.options.items, inst.element ), inst ] );
|
|
this.containers.push( inst );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( i = queries.length - 1; i >= 0; i-- ) {
|
|
targetData = queries[ i ][ 1 ];
|
|
_queries = queries[ i ][ 0 ];
|
|
|
|
for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
|
|
item = $( _queries[ j ] );
|
|
|
|
// Data for target checking (mouse manager)
|
|
item.data( this.widgetName + "-item", targetData );
|
|
|
|
items.push( {
|
|
item: item,
|
|
instance: targetData,
|
|
width: 0, height: 0,
|
|
left: 0, top: 0
|
|
} );
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
refreshPositions: function( fast ) {
|
|
|
|
// Determine whether items are being displayed horizontally
|
|
this.floating = this.items.length ?
|
|
this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
|
|
false;
|
|
|
|
//This has to be redone because due to the item being moved out/into the offsetParent,
|
|
// the offsetParent's position will change
|
|
if ( this.offsetParent && this.helper ) {
|
|
this.offset.parent = this._getParentOffset();
|
|
}
|
|
|
|
var i, item, t, p;
|
|
|
|
for ( i = this.items.length - 1; i >= 0; i-- ) {
|
|
item = this.items[ i ];
|
|
|
|
//We ignore calculating positions of all connected containers when we're not over them
|
|
if ( item.instance !== this.currentContainer && this.currentContainer &&
|
|
item.item[ 0 ] !== this.currentItem[ 0 ] ) {
|
|
continue;
|
|
}
|
|
|
|
t = this.options.toleranceElement ?
|
|
$( this.options.toleranceElement, item.item ) :
|
|
item.item;
|
|
|
|
if ( !fast ) {
|
|
item.width = t.outerWidth();
|
|
item.height = t.outerHeight();
|
|
}
|
|
|
|
p = t.offset();
|
|
item.left = p.left;
|
|
item.top = p.top;
|
|
}
|
|
|
|
if ( this.options.custom && this.options.custom.refreshContainers ) {
|
|
this.options.custom.refreshContainers.call( this );
|
|
} else {
|
|
for ( i = this.containers.length - 1; i >= 0; i-- ) {
|
|
p = this.containers[ i ].element.offset();
|
|
this.containers[ i ].containerCache.left = p.left;
|
|
this.containers[ i ].containerCache.top = p.top;
|
|
this.containers[ i ].containerCache.width =
|
|
this.containers[ i ].element.outerWidth();
|
|
this.containers[ i ].containerCache.height =
|
|
this.containers[ i ].element.outerHeight();
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
_createPlaceholder: function( that ) {
|
|
that = that || this;
|
|
var className,
|
|
o = that.options;
|
|
|
|
if ( !o.placeholder || o.placeholder.constructor === String ) {
|
|
className = o.placeholder;
|
|
o.placeholder = {
|
|
element: function() {
|
|
|
|
var nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(),
|
|
element = $( "<" + nodeName + ">", that.document[ 0 ] );
|
|
|
|
that._addClass( element, "ui-sortable-placeholder",
|
|
className || that.currentItem[ 0 ].className )
|
|
._removeClass( element, "ui-sortable-helper" );
|
|
|
|
if ( nodeName === "tbody" ) {
|
|
that._createTrPlaceholder(
|
|
that.currentItem.find( "tr" ).eq( 0 ),
|
|
$( "<tr>", that.document[ 0 ] ).appendTo( element )
|
|
);
|
|
} else if ( nodeName === "tr" ) {
|
|
that._createTrPlaceholder( that.currentItem, element );
|
|
} else if ( nodeName === "img" ) {
|
|
element.attr( "src", that.currentItem.attr( "src" ) );
|
|
}
|
|
|
|
if ( !className ) {
|
|
element.css( "visibility", "hidden" );
|
|
}
|
|
|
|
return element;
|
|
},
|
|
update: function( container, p ) {
|
|
|
|
// 1. If a className is set as 'placeholder option, we don't force sizes -
|
|
// the class is responsible for that
|
|
// 2. The option 'forcePlaceholderSize can be enabled to force it even if a
|
|
// class name is specified
|
|
if ( className && !o.forcePlaceholderSize ) {
|
|
return;
|
|
}
|
|
|
|
//If the element doesn't have a actual height by itself (without styles coming
|
|
// from a stylesheet), it receives the inline height from the dragged item
|
|
if ( !p.height() ) {
|
|
p.height(
|
|
that.currentItem.innerHeight() -
|
|
parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
|
|
parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
|
|
}
|
|
if ( !p.width() ) {
|
|
p.width(
|
|
that.currentItem.innerWidth() -
|
|
parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
|
|
parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
//Create the placeholder
|
|
that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
|
|
|
|
//Append it after the actual current item
|
|
that.currentItem.after( that.placeholder );
|
|
|
|
//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
|
|
o.placeholder.update( that, that.placeholder );
|
|
|
|
},
|
|
|
|
_createTrPlaceholder: function( sourceTr, targetTr ) {
|
|
var that = this;
|
|
|
|
sourceTr.children().each( function() {
|
|
$( "<td> </td>", that.document[ 0 ] )
|
|
.attr( "colspan", $( this ).attr( "colspan" ) || 1 )
|
|
.appendTo( targetTr );
|
|
} );
|
|
},
|
|
|
|
_contactContainers: function( event ) {
|
|
var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
|
|
floating, axis,
|
|
innermostContainer = null,
|
|
innermostIndex = null;
|
|
|
|
// Get innermost container that intersects with item
|
|
for ( i = this.containers.length - 1; i >= 0; i-- ) {
|
|
|
|
// Never consider a container that's located within the item itself
|
|
if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
|
|
continue;
|
|
}
|
|
|
|
if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
|
|
|
|
// If we've already found a container and it's more "inner" than this, then continue
|
|
if ( innermostContainer &&
|
|
$.contains(
|
|
this.containers[ i ].element[ 0 ],
|
|
innermostContainer.element[ 0 ] ) ) {
|
|
continue;
|
|
}
|
|
|
|
innermostContainer = this.containers[ i ];
|
|
innermostIndex = i;
|
|
|
|
} else {
|
|
|
|
// container doesn't intersect. trigger "out" event if necessary
|
|
if ( this.containers[ i ].containerCache.over ) {
|
|
this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
|
|
this.containers[ i ].containerCache.over = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// If no intersecting containers found, return
|
|
if ( !innermostContainer ) {
|
|
return;
|
|
}
|
|
|
|
// Move the item into the container if it's not there already
|
|
if ( this.containers.length === 1 ) {
|
|
if ( !this.containers[ innermostIndex ].containerCache.over ) {
|
|
this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
|
|
this.containers[ innermostIndex ].containerCache.over = 1;
|
|
}
|
|
} else {
|
|
|
|
// When entering a new container, we will find the item with the least distance and
|
|
// append our item near it
|
|
dist = 10000;
|
|
itemWithLeastDistance = null;
|
|
floating = innermostContainer.floating || this._isFloating( this.currentItem );
|
|
posProperty = floating ? "left" : "top";
|
|
sizeProperty = floating ? "width" : "height";
|
|
axis = floating ? "pageX" : "pageY";
|
|
|
|
for ( j = this.items.length - 1; j >= 0; j-- ) {
|
|
if ( !$.contains(
|
|
this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
|
|
) {
|
|
continue;
|
|
}
|
|
if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
|
|
continue;
|
|
}
|
|
|
|
cur = this.items[ j ].item.offset()[ posProperty ];
|
|
nearBottom = false;
|
|
if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
|
|
nearBottom = true;
|
|
}
|
|
|
|
if ( Math.abs( event[ axis ] - cur ) < dist ) {
|
|
dist = Math.abs( event[ axis ] - cur );
|
|
itemWithLeastDistance = this.items[ j ];
|
|
this.direction = nearBottom ? "up" : "down";
|
|
}
|
|
}
|
|
|
|
//Check if dropOnEmpty is enabled
|
|
if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
|
|
return;
|
|
}
|
|
|
|
if ( this.currentContainer === this.containers[ innermostIndex ] ) {
|
|
if ( !this.currentContainer.containerCache.over ) {
|
|
this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
|
|
this.currentContainer.containerCache.over = 1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
itemWithLeastDistance ?
|
|
this._rearrange( event, itemWithLeastDistance, null, true ) :
|
|
this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
|
|
this._trigger( "change", event, this._uiHash() );
|
|
this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
|
|
this.currentContainer = this.containers[ innermostIndex ];
|
|
|
|
//Update the placeholder
|
|
this.options.placeholder.update( this.currentContainer, this.placeholder );
|
|
|
|
this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
|
|
this.containers[ innermostIndex ].containerCache.over = 1;
|
|
}
|
|
|
|
},
|
|
|
|
_createHelper: function( event ) {
|
|
|
|
var o = this.options,
|
|
helper = $.isFunction( o.helper ) ?
|
|
$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
|
|
( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
|
|
|
|
//Add the helper to the DOM if that didn't happen already
|
|
if ( !helper.parents( "body" ).length ) {
|
|
$( o.appendTo !== "parent" ?
|
|
o.appendTo :
|
|
this.currentItem[ 0 ].parentNode )[ 0 ].appendChild( helper[ 0 ] );
|
|
}
|
|
|
|
if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
|
|
this._storedCSS = {
|
|
width: this.currentItem[ 0 ].style.width,
|
|
height: this.currentItem[ 0 ].style.height,
|
|
position: this.currentItem.css( "position" ),
|
|
top: this.currentItem.css( "top" ),
|
|
left: this.currentItem.css( "left" )
|
|
};
|
|
}
|
|
|
|
if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
|
|
helper.width( this.currentItem.width() );
|
|
}
|
|
if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
|
|
helper.height( this.currentItem.height() );
|
|
}
|
|
|
|
return helper;
|
|
|
|
},
|
|
|
|
_adjustOffsetFromHelper: function( obj ) {
|
|
if ( typeof obj === "string" ) {
|
|
obj = obj.split( " " );
|
|
}
|
|
if ( $.isArray( obj ) ) {
|
|
obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
|
|
}
|
|
if ( "left" in obj ) {
|
|
this.offset.click.left = obj.left + this.margins.left;
|
|
}
|
|
if ( "right" in obj ) {
|
|
this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
|
|
}
|
|
if ( "top" in obj ) {
|
|
this.offset.click.top = obj.top + this.margins.top;
|
|
}
|
|
if ( "bottom" in obj ) {
|
|
this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
|
|
}
|
|
},
|
|
|
|
_getParentOffset: function() {
|
|
|
|
//Get the offsetParent and cache its position
|
|
this.offsetParent = this.helper.offsetParent();
|
|
var po = this.offsetParent.offset();
|
|
|
|
// This is a special case where we need to modify a offset calculated on start, since the
|
|
// following happened:
|
|
// 1. The position of the helper is absolute, so it's position is calculated based on the
|
|
// next positioned parent
|
|
// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
|
|
// the document, which means that the scroll is included in the initial calculation of the
|
|
// offset of the parent, and never recalculated upon drag
|
|
if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
|
|
$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
|
|
po.left += this.scrollParent.scrollLeft();
|
|
po.top += this.scrollParent.scrollTop();
|
|
}
|
|
|
|
// This needs to be actually done for all browsers, since pageX/pageY includes this
|
|
// information with an ugly IE fix
|
|
if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||
|
|
( this.offsetParent[ 0 ].tagName &&
|
|
this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) {
|
|
po = { top: 0, left: 0 };
|
|
}
|
|
|
|
return {
|
|
top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
|
|
left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
|
|
};
|
|
|
|
},
|
|
|
|
_getRelativeOffset: function() {
|
|
|
|
if ( this.cssPosition === "relative" ) {
|
|
var p = this.currentItem.position();
|
|
return {
|
|
top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
|
|
this.scrollParent.scrollTop(),
|
|
left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
|
|
this.scrollParent.scrollLeft()
|
|
};
|
|
} else {
|
|
return { top: 0, left: 0 };
|
|
}
|
|
|
|
},
|
|
|
|
_cacheMargins: function() {
|
|
this.margins = {
|
|
left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
|
|
top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
|
|
};
|
|
},
|
|
|
|
_cacheHelperProportions: function() {
|
|
this.helperProportions = {
|
|
width: this.helper.outerWidth(),
|
|
height: this.helper.outerHeight()
|
|
};
|
|
},
|
|
|
|
_setContainment: function() {
|
|
|
|
var ce, co, over,
|
|
o = this.options;
|
|
if ( o.containment === "parent" ) {
|
|
o.containment = this.helper[ 0 ].parentNode;
|
|
}
|
|
if ( o.containment === "document" || o.containment === "window" ) {
|
|
this.containment = [
|
|
0 - this.offset.relative.left - this.offset.parent.left,
|
|
0 - this.offset.relative.top - this.offset.parent.top,
|
|
o.containment === "document" ?
|
|
this.document.width() :
|
|
this.window.width() - this.helperProportions.width - this.margins.left,
|
|
( o.containment === "document" ?
|
|
( this.document.height() || document.body.parentNode.scrollHeight ) :
|
|
this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
|
|
) - this.helperProportions.height - this.margins.top
|
|
];
|
|
}
|
|
|
|
if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
|
|
ce = $( o.containment )[ 0 ];
|
|
co = $( o.containment ).offset();
|
|
over = ( $( ce ).css( "overflow" ) !== "hidden" );
|
|
|
|
this.containment = [
|
|
co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
|
|
( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
|
|
co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
|
|
( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
|
|
co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
|
|
( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
|
|
( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
|
|
this.helperProportions.width - this.margins.left,
|
|
co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
|
|
( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
|
|
( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
|
|
this.helperProportions.height - this.margins.top
|
|
];
|
|
}
|
|
|
|
},
|
|
|
|
_convertPositionTo: function( d, pos ) {
|
|
|
|
if ( !pos ) {
|
|
pos = this.position;
|
|
}
|
|
var mod = d === "absolute" ? 1 : -1,
|
|
scroll = this.cssPosition === "absolute" &&
|
|
!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
|
|
$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
|
|
this.offsetParent :
|
|
this.scrollParent,
|
|
scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
|
|
|
|
return {
|
|
top: (
|
|
|
|
// The absolute mouse position
|
|
pos.top +
|
|
|
|
// Only for relative positioned nodes: Relative offset from element to offset parent
|
|
this.offset.relative.top * mod +
|
|
|
|
// The offsetParent's offset without borders (offset + border)
|
|
this.offset.parent.top * mod -
|
|
( ( this.cssPosition === "fixed" ?
|
|
-this.scrollParent.scrollTop() :
|
|
( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
|
|
),
|
|
left: (
|
|
|
|
// The absolute mouse position
|
|
pos.left +
|
|
|
|
// Only for relative positioned nodes: Relative offset from element to offset parent
|
|
this.offset.relative.left * mod +
|
|
|
|
// The offsetParent's offset without borders (offset + border)
|
|
this.offset.parent.left * mod -
|
|
( ( this.cssPosition === "fixed" ?
|
|
-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
|
|
scroll.scrollLeft() ) * mod )
|
|
)
|
|
};
|
|
|
|
},
|
|
|
|
_generatePosition: function( event ) {
|
|
|
|
var top, left,
|
|
o = this.options,
|
|
pageX = event.pageX,
|
|
pageY = event.pageY,
|
|
scroll = this.cssPosition === "absolute" &&
|
|
!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
|
|
$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
|
|
this.offsetParent :
|
|
this.scrollParent,
|
|
scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
|
|
|
|
// This is another very weird special case that only happens for relative elements:
|
|
// 1. If the css position is relative
|
|
// 2. and the scroll parent is the document or similar to the offset parent
|
|
// we have to refresh the relative offset during the scroll so there are no jumps
|
|
if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
|
|
this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
|
|
this.offset.relative = this._getRelativeOffset();
|
|
}
|
|
|
|
/*
|
|
* - Position constraining -
|
|
* Constrain the position to a mix of grid, containment.
|
|
*/
|
|
|
|
if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
|
|
|
|
if ( this.containment ) {
|
|
if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
|
|
pageX = this.containment[ 0 ] + this.offset.click.left;
|
|
}
|
|
if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
|
|
pageY = this.containment[ 1 ] + this.offset.click.top;
|
|
}
|
|
if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
|
|
pageX = this.containment[ 2 ] + this.offset.click.left;
|
|
}
|
|
if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
|
|
pageY = this.containment[ 3 ] + this.offset.click.top;
|
|
}
|
|
}
|
|
|
|
if ( o.grid ) {
|
|
top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
|
|
o.grid[ 1 ] ) * o.grid[ 1 ];
|
|
pageY = this.containment ?
|
|
( ( top - this.offset.click.top >= this.containment[ 1 ] &&
|
|
top - this.offset.click.top <= this.containment[ 3 ] ) ?
|
|
top :
|
|
( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
|
|
top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
|
|
top;
|
|
|
|
left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
|
|
o.grid[ 0 ] ) * o.grid[ 0 ];
|
|
pageX = this.containment ?
|
|
( ( left - this.offset.click.left >= this.containment[ 0 ] &&
|
|
left - this.offset.click.left <= this.containment[ 2 ] ) ?
|
|
left :
|
|
( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
|
|
left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
|
|
left;
|
|
}
|
|
|
|
}
|
|
|
|
return {
|
|
top: (
|
|
|
|
// The absolute mouse position
|
|
pageY -
|
|
|
|
// Click offset (relative to the element)
|
|
this.offset.click.top -
|
|
|
|
// Only for relative positioned nodes: Relative offset from element to offset parent
|
|
this.offset.relative.top -
|
|
|
|
// The offsetParent's offset without borders (offset + border)
|
|
this.offset.parent.top +
|
|
( ( this.cssPosition === "fixed" ?
|
|
-this.scrollParent.scrollTop() :
|
|
( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
|
|
),
|
|
left: (
|
|
|
|
// The absolute mouse position
|
|
pageX -
|
|
|
|
// Click offset (relative to the element)
|
|
this.offset.click.left -
|
|
|
|
// Only for relative positioned nodes: Relative offset from element to offset parent
|
|
this.offset.relative.left -
|
|
|
|
// The offsetParent's offset without borders (offset + border)
|
|
this.offset.parent.left +
|
|
( ( this.cssPosition === "fixed" ?
|
|
-this.scrollParent.scrollLeft() :
|
|
scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
|
|
)
|
|
};
|
|
|
|
},
|
|
|
|
_rearrange: function( event, i, a, hardRefresh ) {
|
|
|
|
a ? a[ 0 ].appendChild( this.placeholder[ 0 ] ) :
|
|
i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
|
|
( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
|
|
|
|
//Various things done here to improve the performance:
|
|
// 1. we create a setTimeout, that calls refreshPositions
|
|
// 2. on the instance, we have a counter variable, that get's higher after every append
|
|
// 3. on the local scope, we copy the counter variable, and check in the timeout,
|
|
// if it's still the same
|
|
// 4. this lets only the last addition to the timeout stack through
|
|
this.counter = this.counter ? ++this.counter : 1;
|
|
var counter = this.counter;
|
|
|
|
this._delay( function() {
|
|
if ( counter === this.counter ) {
|
|
|
|
//Precompute after each DOM insertion, NOT on mousemove
|
|
this.refreshPositions( !hardRefresh );
|
|
}
|
|
} );
|
|
|
|
},
|
|
|
|
_clear: function( event, noPropagation ) {
|
|
|
|
this.reverting = false;
|
|
|
|
// We delay all events that have to be triggered to after the point where the placeholder
|
|
// has been removed and everything else normalized again
|
|
var i,
|
|
delayedTriggers = [];
|
|
|
|
// We first have to update the dom position of the actual currentItem
|
|
// Note: don't do it if the current item is already removed (by a user), or it gets
|
|
// reappended (see #4088)
|
|
if ( !this._noFinalSort && this.currentItem.parent().length ) {
|
|
this.placeholder.before( this.currentItem );
|
|
}
|
|
this._noFinalSort = null;
|
|
|
|
if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
|
|
for ( i in this._storedCSS ) {
|
|
if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
|
|
this._storedCSS[ i ] = "";
|
|
}
|
|
}
|
|
this.currentItem.css( this._storedCSS );
|
|
this._removeClass( this.currentItem, "ui-sortable-helper" );
|
|
} else {
|
|
this.currentItem.show();
|
|
}
|
|
|
|
if ( this.fromOutside && !noPropagation ) {
|
|
delayedTriggers.push( function( event ) {
|
|
this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
|
|
} );
|
|
}
|
|
if ( ( this.fromOutside ||
|
|
this.domPosition.prev !==
|
|
this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
|
|
this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
|
|
|
|
// Trigger update callback if the DOM position has changed
|
|
delayedTriggers.push( function( event ) {
|
|
this._trigger( "update", event, this._uiHash() );
|
|
} );
|
|
}
|
|
|
|
// Check if the items Container has Changed and trigger appropriate
|
|
// events.
|
|
if ( this !== this.currentContainer ) {
|
|
if ( !noPropagation ) {
|
|
delayedTriggers.push( function( event ) {
|
|
this._trigger( "remove", event, this._uiHash() );
|
|
} );
|
|
delayedTriggers.push( ( function( c ) {
|
|
return function( event ) {
|
|
c._trigger( "receive", event, this._uiHash( this ) );
|
|
};
|
|
} ).call( this, this.currentContainer ) );
|
|
delayedTriggers.push( ( function( c ) {
|
|
return function( event ) {
|
|
c._trigger( "update", event, this._uiHash( this ) );
|
|
};
|
|
} ).call( this, this.currentContainer ) );
|
|
}
|
|
}
|
|
|
|
//Post events to containers
|
|
function delayEvent( type, instance, container ) {
|
|
return function( event ) {
|
|
container._trigger( type, event, instance._uiHash( instance ) );
|
|
};
|
|
}
|
|
for ( i = this.containers.length - 1; i >= 0; i-- ) {
|
|
if ( !noPropagation ) {
|
|
delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
|
|
}
|
|
if ( this.containers[ i ].containerCache.over ) {
|
|
delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
|
|
this.containers[ i ].containerCache.over = 0;
|
|
}
|
|
}
|
|
|
|
//Do what was originally in plugins
|
|
if ( this.storedCursor ) {
|
|
this.document.find( "body" ).css( "cursor", this.storedCursor );
|
|
this.storedStylesheet.remove();
|
|
}
|
|
if ( this._storedOpacity ) {
|
|
this.helper.css( "opacity", this._storedOpacity );
|
|
}
|
|
if ( this._storedZIndex ) {
|
|
this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
|
|
}
|
|
|
|
this.dragging = false;
|
|
|
|
if ( !noPropagation ) {
|
|
this._trigger( "beforeStop", event, this._uiHash() );
|
|
}
|
|
|
|
//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
|
|
// it unbinds ALL events from the original node!
|
|
this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
|
|
|
|
if ( !this.cancelHelperRemoval ) {
|
|
if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
|
|
this.helper.remove();
|
|
}
|
|
this.helper = null;
|
|
}
|
|
|
|
if ( !noPropagation ) {
|
|
for ( i = 0; i < delayedTriggers.length; i++ ) {
|
|
|
|
// Trigger all delayed events
|
|
delayedTriggers[ i ].call( this, event );
|
|
}
|
|
this._trigger( "stop", event, this._uiHash() );
|
|
}
|
|
|
|
this.fromOutside = false;
|
|
return !this.cancelHelperRemoval;
|
|
|
|
},
|
|
|
|
_trigger: function() {
|
|
if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
|
|
this.cancel();
|
|
}
|
|
},
|
|
|
|
_uiHash: function( _inst ) {
|
|
var inst = _inst || this;
|
|
return {
|
|
helper: inst.helper,
|
|
placeholder: inst.placeholder || $( [] ),
|
|
position: inst.position,
|
|
originalPosition: inst.originalPosition,
|
|
offset: inst.positionAbs,
|
|
item: inst.currentItem,
|
|
sender: _inst ? _inst.element : null
|
|
};
|
|
}
|
|
|
|
} );
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 66 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Spinner 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Spinner
|
|
//>>group: Widgets
|
|
//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
|
|
//>>docs: http://api.jqueryui.com/spinner/
|
|
//>>demos: http://jqueryui.com/spinner/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/spinner.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(55),
|
|
__webpack_require__(15),
|
|
__webpack_require__(43),
|
|
__webpack_require__(18),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
function spinnerModifer( fn ) {
|
|
return function() {
|
|
var previous = this.element.val();
|
|
fn.apply( this, arguments );
|
|
this._refresh();
|
|
if ( previous !== this.element.val() ) {
|
|
this._trigger( "change" );
|
|
}
|
|
};
|
|
}
|
|
|
|
$.widget( "ui.spinner", {
|
|
version: "1.12.1",
|
|
defaultElement: "<input>",
|
|
widgetEventPrefix: "spin",
|
|
options: {
|
|
classes: {
|
|
"ui-spinner": "ui-corner-all",
|
|
"ui-spinner-down": "ui-corner-br",
|
|
"ui-spinner-up": "ui-corner-tr"
|
|
},
|
|
culture: null,
|
|
icons: {
|
|
down: "ui-icon-triangle-1-s",
|
|
up: "ui-icon-triangle-1-n"
|
|
},
|
|
incremental: true,
|
|
max: null,
|
|
min: null,
|
|
numberFormat: null,
|
|
page: 10,
|
|
step: 1,
|
|
|
|
change: null,
|
|
spin: null,
|
|
start: null,
|
|
stop: null
|
|
},
|
|
|
|
_create: function() {
|
|
|
|
// handle string values that need to be parsed
|
|
this._setOption( "max", this.options.max );
|
|
this._setOption( "min", this.options.min );
|
|
this._setOption( "step", this.options.step );
|
|
|
|
// Only format if there is a value, prevents the field from being marked
|
|
// as invalid in Firefox, see #9573.
|
|
if ( this.value() !== "" ) {
|
|
|
|
// Format the value, but don't constrain.
|
|
this._value( this.element.val(), true );
|
|
}
|
|
|
|
this._draw();
|
|
this._on( this._events );
|
|
this._refresh();
|
|
|
|
// Turning off autocomplete prevents the browser from remembering the
|
|
// value when navigating through history, so we re-enable autocomplete
|
|
// if the page is unloaded before the widget is destroyed. #7790
|
|
this._on( this.window, {
|
|
beforeunload: function() {
|
|
this.element.removeAttr( "autocomplete" );
|
|
}
|
|
} );
|
|
},
|
|
|
|
_getCreateOptions: function() {
|
|
var options = this._super();
|
|
var element = this.element;
|
|
|
|
$.each( [ "min", "max", "step" ], function( i, option ) {
|
|
var value = element.attr( option );
|
|
if ( value != null && value.length ) {
|
|
options[ option ] = value;
|
|
}
|
|
} );
|
|
|
|
return options;
|
|
},
|
|
|
|
_events: {
|
|
keydown: function( event ) {
|
|
if ( this._start( event ) && this._keydown( event ) ) {
|
|
event.preventDefault();
|
|
}
|
|
},
|
|
keyup: "_stop",
|
|
focus: function() {
|
|
this.previous = this.element.val();
|
|
},
|
|
blur: function( event ) {
|
|
if ( this.cancelBlur ) {
|
|
delete this.cancelBlur;
|
|
return;
|
|
}
|
|
|
|
this._stop();
|
|
this._refresh();
|
|
if ( this.previous !== this.element.val() ) {
|
|
this._trigger( "change", event );
|
|
}
|
|
},
|
|
mousewheel: function( event, delta ) {
|
|
if ( !delta ) {
|
|
return;
|
|
}
|
|
if ( !this.spinning && !this._start( event ) ) {
|
|
return false;
|
|
}
|
|
|
|
this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
|
|
clearTimeout( this.mousewheelTimer );
|
|
this.mousewheelTimer = this._delay( function() {
|
|
if ( this.spinning ) {
|
|
this._stop( event );
|
|
}
|
|
}, 100 );
|
|
event.preventDefault();
|
|
},
|
|
"mousedown .ui-spinner-button": function( event ) {
|
|
var previous;
|
|
|
|
// We never want the buttons to have focus; whenever the user is
|
|
// interacting with the spinner, the focus should be on the input.
|
|
// If the input is focused then this.previous is properly set from
|
|
// when the input first received focus. If the input is not focused
|
|
// then we need to set this.previous based on the value before spinning.
|
|
previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?
|
|
this.previous : this.element.val();
|
|
function checkFocus() {
|
|
var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );
|
|
if ( !isActive ) {
|
|
this.element.trigger( "focus" );
|
|
this.previous = previous;
|
|
|
|
// support: IE
|
|
// IE sets focus asynchronously, so we need to check if focus
|
|
// moved off of the input because the user clicked on the button.
|
|
this._delay( function() {
|
|
this.previous = previous;
|
|
} );
|
|
}
|
|
}
|
|
|
|
// Ensure focus is on (or stays on) the text field
|
|
event.preventDefault();
|
|
checkFocus.call( this );
|
|
|
|
// Support: IE
|
|
// IE doesn't prevent moving focus even with event.preventDefault()
|
|
// so we set a flag to know when we should ignore the blur event
|
|
// and check (again) if focus moved off of the input.
|
|
this.cancelBlur = true;
|
|
this._delay( function() {
|
|
delete this.cancelBlur;
|
|
checkFocus.call( this );
|
|
} );
|
|
|
|
if ( this._start( event ) === false ) {
|
|
return;
|
|
}
|
|
|
|
this._repeat( null, $( event.currentTarget )
|
|
.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
|
|
},
|
|
"mouseup .ui-spinner-button": "_stop",
|
|
"mouseenter .ui-spinner-button": function( event ) {
|
|
|
|
// button will add ui-state-active if mouse was down while mouseleave and kept down
|
|
if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( this._start( event ) === false ) {
|
|
return false;
|
|
}
|
|
this._repeat( null, $( event.currentTarget )
|
|
.hasClass( "ui-spinner-up" ) ? 1 : -1, event );
|
|
},
|
|
|
|
// TODO: do we really want to consider this a stop?
|
|
// shouldn't we just stop the repeater and wait until mouseup before
|
|
// we trigger the stop event?
|
|
"mouseleave .ui-spinner-button": "_stop"
|
|
},
|
|
|
|
// Support mobile enhanced option and make backcompat more sane
|
|
_enhance: function() {
|
|
this.uiSpinner = this.element
|
|
.attr( "autocomplete", "off" )
|
|
.wrap( "<span>" )
|
|
.parent()
|
|
|
|
// Add buttons
|
|
.append(
|
|
"<a></a><a></a>"
|
|
);
|
|
},
|
|
|
|
_draw: function() {
|
|
this._enhance();
|
|
|
|
this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
|
|
this._addClass( "ui-spinner-input" );
|
|
|
|
this.element.attr( "role", "spinbutton" );
|
|
|
|
// Button bindings
|
|
this.buttons = this.uiSpinner.children( "a" )
|
|
.attr( "tabIndex", -1 )
|
|
.attr( "aria-hidden", true )
|
|
.button( {
|
|
classes: {
|
|
"ui-button": ""
|
|
}
|
|
} );
|
|
|
|
// TODO: Right now button does not support classes this is already updated in button PR
|
|
this._removeClass( this.buttons, "ui-corner-all" );
|
|
|
|
this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
|
|
this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
|
|
this.buttons.first().button( {
|
|
"icon": this.options.icons.up,
|
|
"showLabel": false
|
|
} );
|
|
this.buttons.last().button( {
|
|
"icon": this.options.icons.down,
|
|
"showLabel": false
|
|
} );
|
|
|
|
// IE 6 doesn't understand height: 50% for the buttons
|
|
// unless the wrapper has an explicit height
|
|
if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
|
|
this.uiSpinner.height() > 0 ) {
|
|
this.uiSpinner.height( this.uiSpinner.height() );
|
|
}
|
|
},
|
|
|
|
_keydown: function( event ) {
|
|
var options = this.options,
|
|
keyCode = $.ui.keyCode;
|
|
|
|
switch ( event.keyCode ) {
|
|
case keyCode.UP:
|
|
this._repeat( null, 1, event );
|
|
return true;
|
|
case keyCode.DOWN:
|
|
this._repeat( null, -1, event );
|
|
return true;
|
|
case keyCode.PAGE_UP:
|
|
this._repeat( null, options.page, event );
|
|
return true;
|
|
case keyCode.PAGE_DOWN:
|
|
this._repeat( null, -options.page, event );
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
_start: function( event ) {
|
|
if ( !this.spinning && this._trigger( "start", event ) === false ) {
|
|
return false;
|
|
}
|
|
|
|
if ( !this.counter ) {
|
|
this.counter = 1;
|
|
}
|
|
this.spinning = true;
|
|
return true;
|
|
},
|
|
|
|
_repeat: function( i, steps, event ) {
|
|
i = i || 500;
|
|
|
|
clearTimeout( this.timer );
|
|
this.timer = this._delay( function() {
|
|
this._repeat( 40, steps, event );
|
|
}, i );
|
|
|
|
this._spin( steps * this.options.step, event );
|
|
},
|
|
|
|
_spin: function( step, event ) {
|
|
var value = this.value() || 0;
|
|
|
|
if ( !this.counter ) {
|
|
this.counter = 1;
|
|
}
|
|
|
|
value = this._adjustValue( value + step * this._increment( this.counter ) );
|
|
|
|
if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
|
|
this._value( value );
|
|
this.counter++;
|
|
}
|
|
},
|
|
|
|
_increment: function( i ) {
|
|
var incremental = this.options.incremental;
|
|
|
|
if ( incremental ) {
|
|
return $.isFunction( incremental ) ?
|
|
incremental( i ) :
|
|
Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
|
|
}
|
|
|
|
return 1;
|
|
},
|
|
|
|
_precision: function() {
|
|
var precision = this._precisionOf( this.options.step );
|
|
if ( this.options.min !== null ) {
|
|
precision = Math.max( precision, this._precisionOf( this.options.min ) );
|
|
}
|
|
return precision;
|
|
},
|
|
|
|
_precisionOf: function( num ) {
|
|
var str = num.toString(),
|
|
decimal = str.indexOf( "." );
|
|
return decimal === -1 ? 0 : str.length - decimal - 1;
|
|
},
|
|
|
|
_adjustValue: function( value ) {
|
|
var base, aboveMin,
|
|
options = this.options;
|
|
|
|
// Make sure we're at a valid step
|
|
// - find out where we are relative to the base (min or 0)
|
|
base = options.min !== null ? options.min : 0;
|
|
aboveMin = value - base;
|
|
|
|
// - round to the nearest step
|
|
aboveMin = Math.round( aboveMin / options.step ) * options.step;
|
|
|
|
// - rounding is based on 0, so adjust back to our base
|
|
value = base + aboveMin;
|
|
|
|
// Fix precision from bad JS floating point math
|
|
value = parseFloat( value.toFixed( this._precision() ) );
|
|
|
|
// Clamp the value
|
|
if ( options.max !== null && value > options.max ) {
|
|
return options.max;
|
|
}
|
|
if ( options.min !== null && value < options.min ) {
|
|
return options.min;
|
|
}
|
|
|
|
return value;
|
|
},
|
|
|
|
_stop: function( event ) {
|
|
if ( !this.spinning ) {
|
|
return;
|
|
}
|
|
|
|
clearTimeout( this.timer );
|
|
clearTimeout( this.mousewheelTimer );
|
|
this.counter = 0;
|
|
this.spinning = false;
|
|
this._trigger( "stop", event );
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
var prevValue, first, last;
|
|
|
|
if ( key === "culture" || key === "numberFormat" ) {
|
|
prevValue = this._parse( this.element.val() );
|
|
this.options[ key ] = value;
|
|
this.element.val( this._format( prevValue ) );
|
|
return;
|
|
}
|
|
|
|
if ( key === "max" || key === "min" || key === "step" ) {
|
|
if ( typeof value === "string" ) {
|
|
value = this._parse( value );
|
|
}
|
|
}
|
|
if ( key === "icons" ) {
|
|
first = this.buttons.first().find( ".ui-icon" );
|
|
this._removeClass( first, null, this.options.icons.up );
|
|
this._addClass( first, null, value.up );
|
|
last = this.buttons.last().find( ".ui-icon" );
|
|
this._removeClass( last, null, this.options.icons.down );
|
|
this._addClass( last, null, value.down );
|
|
}
|
|
|
|
this._super( key, value );
|
|
},
|
|
|
|
_setOptionDisabled: function( value ) {
|
|
this._super( value );
|
|
|
|
this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
|
|
this.element.prop( "disabled", !!value );
|
|
this.buttons.button( value ? "disable" : "enable" );
|
|
},
|
|
|
|
_setOptions: spinnerModifer( function( options ) {
|
|
this._super( options );
|
|
} ),
|
|
|
|
_parse: function( val ) {
|
|
if ( typeof val === "string" && val !== "" ) {
|
|
val = window.Globalize && this.options.numberFormat ?
|
|
Globalize.parseFloat( val, 10, this.options.culture ) : +val;
|
|
}
|
|
return val === "" || isNaN( val ) ? null : val;
|
|
},
|
|
|
|
_format: function( value ) {
|
|
if ( value === "" ) {
|
|
return "";
|
|
}
|
|
return window.Globalize && this.options.numberFormat ?
|
|
Globalize.format( value, this.options.numberFormat, this.options.culture ) :
|
|
value;
|
|
},
|
|
|
|
_refresh: function() {
|
|
this.element.attr( {
|
|
"aria-valuemin": this.options.min,
|
|
"aria-valuemax": this.options.max,
|
|
|
|
// TODO: what should we do with values that can't be parsed?
|
|
"aria-valuenow": this._parse( this.element.val() )
|
|
} );
|
|
},
|
|
|
|
isValid: function() {
|
|
var value = this.value();
|
|
|
|
// Null is invalid
|
|
if ( value === null ) {
|
|
return false;
|
|
}
|
|
|
|
// If value gets adjusted, it's invalid
|
|
return value === this._adjustValue( value );
|
|
},
|
|
|
|
// Update the value without triggering change
|
|
_value: function( value, allowAny ) {
|
|
var parsed;
|
|
if ( value !== "" ) {
|
|
parsed = this._parse( value );
|
|
if ( parsed !== null ) {
|
|
if ( !allowAny ) {
|
|
parsed = this._adjustValue( parsed );
|
|
}
|
|
value = this._format( parsed );
|
|
}
|
|
}
|
|
this.element.val( value );
|
|
this._refresh();
|
|
},
|
|
|
|
_destroy: function() {
|
|
this.element
|
|
.prop( "disabled", false )
|
|
.removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
|
|
|
|
this.uiSpinner.replaceWith( this.element );
|
|
},
|
|
|
|
stepUp: spinnerModifer( function( steps ) {
|
|
this._stepUp( steps );
|
|
} ),
|
|
_stepUp: function( steps ) {
|
|
if ( this._start() ) {
|
|
this._spin( ( steps || 1 ) * this.options.step );
|
|
this._stop();
|
|
}
|
|
},
|
|
|
|
stepDown: spinnerModifer( function( steps ) {
|
|
this._stepDown( steps );
|
|
} ),
|
|
_stepDown: function( steps ) {
|
|
if ( this._start() ) {
|
|
this._spin( ( steps || 1 ) * -this.options.step );
|
|
this._stop();
|
|
}
|
|
},
|
|
|
|
pageUp: spinnerModifer( function( pages ) {
|
|
this._stepUp( ( pages || 1 ) * this.options.page );
|
|
} ),
|
|
|
|
pageDown: spinnerModifer( function( pages ) {
|
|
this._stepDown( ( pages || 1 ) * this.options.page );
|
|
} ),
|
|
|
|
value: function( newVal ) {
|
|
if ( !arguments.length ) {
|
|
return this._parse( this.element.val() );
|
|
}
|
|
spinnerModifer( this._value ).call( this, newVal );
|
|
},
|
|
|
|
widget: function() {
|
|
return this.uiSpinner;
|
|
}
|
|
} );
|
|
|
|
// DEPRECATED
|
|
// TODO: switch return back to widget declaration at top of file when this is removed
|
|
if ( $.uiBackCompat !== false ) {
|
|
|
|
// Backcompat for spinner html extension points
|
|
$.widget( "ui.spinner", $.ui.spinner, {
|
|
_enhance: function() {
|
|
this.uiSpinner = this.element
|
|
.attr( "autocomplete", "off" )
|
|
.wrap( this._uiSpinnerHtml() )
|
|
.parent()
|
|
|
|
// Add buttons
|
|
.append( this._buttonHtml() );
|
|
},
|
|
_uiSpinnerHtml: function() {
|
|
return "<span>";
|
|
},
|
|
|
|
_buttonHtml: function() {
|
|
return "<a></a><a></a>";
|
|
}
|
|
} );
|
|
}
|
|
|
|
return $.ui.spinner;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 67 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Tabs 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Tabs
|
|
//>>group: Widgets
|
|
//>>description: Transforms a set of container elements into a tab structure.
|
|
//>>docs: http://api.jqueryui.com/tabs/
|
|
//>>demos: http://jqueryui.com/tabs/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/tabs.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(45),
|
|
__webpack_require__(43),
|
|
__webpack_require__(18),
|
|
__webpack_require__(48),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
$.widget( "ui.tabs", {
|
|
version: "1.12.1",
|
|
delay: 300,
|
|
options: {
|
|
active: null,
|
|
classes: {
|
|
"ui-tabs": "ui-corner-all",
|
|
"ui-tabs-nav": "ui-corner-all",
|
|
"ui-tabs-panel": "ui-corner-bottom",
|
|
"ui-tabs-tab": "ui-corner-top"
|
|
},
|
|
collapsible: false,
|
|
event: "click",
|
|
heightStyle: "content",
|
|
hide: null,
|
|
show: null,
|
|
|
|
// Callbacks
|
|
activate: null,
|
|
beforeActivate: null,
|
|
beforeLoad: null,
|
|
load: null
|
|
},
|
|
|
|
_isLocal: ( function() {
|
|
var rhash = /#.*$/;
|
|
|
|
return function( anchor ) {
|
|
var anchorUrl, locationUrl;
|
|
|
|
anchorUrl = anchor.href.replace( rhash, "" );
|
|
locationUrl = location.href.replace( rhash, "" );
|
|
|
|
// Decoding may throw an error if the URL isn't UTF-8 (#9518)
|
|
try {
|
|
anchorUrl = decodeURIComponent( anchorUrl );
|
|
} catch ( error ) {}
|
|
try {
|
|
locationUrl = decodeURIComponent( locationUrl );
|
|
} catch ( error ) {}
|
|
|
|
return anchor.hash.length > 1 && anchorUrl === locationUrl;
|
|
};
|
|
} )(),
|
|
|
|
_create: function() {
|
|
var that = this,
|
|
options = this.options;
|
|
|
|
this.running = false;
|
|
|
|
this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
|
|
this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
|
|
|
|
this._processTabs();
|
|
options.active = this._initialActive();
|
|
|
|
// Take disabling tabs via class attribute from HTML
|
|
// into account and update option properly.
|
|
if ( $.isArray( options.disabled ) ) {
|
|
options.disabled = $.unique( options.disabled.concat(
|
|
$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
|
|
return that.tabs.index( li );
|
|
} )
|
|
) ).sort();
|
|
}
|
|
|
|
// Check for length avoids error when initializing empty list
|
|
if ( this.options.active !== false && this.anchors.length ) {
|
|
this.active = this._findActive( options.active );
|
|
} else {
|
|
this.active = $();
|
|
}
|
|
|
|
this._refresh();
|
|
|
|
if ( this.active.length ) {
|
|
this.load( options.active );
|
|
}
|
|
},
|
|
|
|
_initialActive: function() {
|
|
var active = this.options.active,
|
|
collapsible = this.options.collapsible,
|
|
locationHash = location.hash.substring( 1 );
|
|
|
|
if ( active === null ) {
|
|
|
|
// check the fragment identifier in the URL
|
|
if ( locationHash ) {
|
|
this.tabs.each( function( i, tab ) {
|
|
if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
|
|
active = i;
|
|
return false;
|
|
}
|
|
} );
|
|
}
|
|
|
|
// Check for a tab marked active via a class
|
|
if ( active === null ) {
|
|
active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
|
|
}
|
|
|
|
// No active tab, set to false
|
|
if ( active === null || active === -1 ) {
|
|
active = this.tabs.length ? 0 : false;
|
|
}
|
|
}
|
|
|
|
// Handle numbers: negative, out of range
|
|
if ( active !== false ) {
|
|
active = this.tabs.index( this.tabs.eq( active ) );
|
|
if ( active === -1 ) {
|
|
active = collapsible ? false : 0;
|
|
}
|
|
}
|
|
|
|
// Don't allow collapsible: false and active: false
|
|
if ( !collapsible && active === false && this.anchors.length ) {
|
|
active = 0;
|
|
}
|
|
|
|
return active;
|
|
},
|
|
|
|
_getCreateEventData: function() {
|
|
return {
|
|
tab: this.active,
|
|
panel: !this.active.length ? $() : this._getPanelForTab( this.active )
|
|
};
|
|
},
|
|
|
|
_tabKeydown: function( event ) {
|
|
var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ),
|
|
selectedIndex = this.tabs.index( focusedTab ),
|
|
goingForward = true;
|
|
|
|
if ( this._handlePageNav( event ) ) {
|
|
return;
|
|
}
|
|
|
|
switch ( event.keyCode ) {
|
|
case $.ui.keyCode.RIGHT:
|
|
case $.ui.keyCode.DOWN:
|
|
selectedIndex++;
|
|
break;
|
|
case $.ui.keyCode.UP:
|
|
case $.ui.keyCode.LEFT:
|
|
goingForward = false;
|
|
selectedIndex--;
|
|
break;
|
|
case $.ui.keyCode.END:
|
|
selectedIndex = this.anchors.length - 1;
|
|
break;
|
|
case $.ui.keyCode.HOME:
|
|
selectedIndex = 0;
|
|
break;
|
|
case $.ui.keyCode.SPACE:
|
|
|
|
// Activate only, no collapsing
|
|
event.preventDefault();
|
|
clearTimeout( this.activating );
|
|
this._activate( selectedIndex );
|
|
return;
|
|
case $.ui.keyCode.ENTER:
|
|
|
|
// Toggle (cancel delayed activation, allow collapsing)
|
|
event.preventDefault();
|
|
clearTimeout( this.activating );
|
|
|
|
// Determine if we should collapse or activate
|
|
this._activate( selectedIndex === this.options.active ? false : selectedIndex );
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
// Focus the appropriate tab, based on which key was pressed
|
|
event.preventDefault();
|
|
clearTimeout( this.activating );
|
|
selectedIndex = this._focusNextTab( selectedIndex, goingForward );
|
|
|
|
// Navigating with control/command key will prevent automatic activation
|
|
if ( !event.ctrlKey && !event.metaKey ) {
|
|
|
|
// Update aria-selected immediately so that AT think the tab is already selected.
|
|
// Otherwise AT may confuse the user by stating that they need to activate the tab,
|
|
// but the tab will already be activated by the time the announcement finishes.
|
|
focusedTab.attr( "aria-selected", "false" );
|
|
this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
|
|
|
|
this.activating = this._delay( function() {
|
|
this.option( "active", selectedIndex );
|
|
}, this.delay );
|
|
}
|
|
},
|
|
|
|
_panelKeydown: function( event ) {
|
|
if ( this._handlePageNav( event ) ) {
|
|
return;
|
|
}
|
|
|
|
// Ctrl+up moves focus to the current tab
|
|
if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
|
|
event.preventDefault();
|
|
this.active.trigger( "focus" );
|
|
}
|
|
},
|
|
|
|
// Alt+page up/down moves focus to the previous/next tab (and activates)
|
|
_handlePageNav: function( event ) {
|
|
if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
|
|
this._activate( this._focusNextTab( this.options.active - 1, false ) );
|
|
return true;
|
|
}
|
|
if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
|
|
this._activate( this._focusNextTab( this.options.active + 1, true ) );
|
|
return true;
|
|
}
|
|
},
|
|
|
|
_findNextTab: function( index, goingForward ) {
|
|
var lastTabIndex = this.tabs.length - 1;
|
|
|
|
function constrain() {
|
|
if ( index > lastTabIndex ) {
|
|
index = 0;
|
|
}
|
|
if ( index < 0 ) {
|
|
index = lastTabIndex;
|
|
}
|
|
return index;
|
|
}
|
|
|
|
while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
|
|
index = goingForward ? index + 1 : index - 1;
|
|
}
|
|
|
|
return index;
|
|
},
|
|
|
|
_focusNextTab: function( index, goingForward ) {
|
|
index = this._findNextTab( index, goingForward );
|
|
this.tabs.eq( index ).trigger( "focus" );
|
|
return index;
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
if ( key === "active" ) {
|
|
|
|
// _activate() will handle invalid values and update this.options
|
|
this._activate( value );
|
|
return;
|
|
}
|
|
|
|
this._super( key, value );
|
|
|
|
if ( key === "collapsible" ) {
|
|
this._toggleClass( "ui-tabs-collapsible", null, value );
|
|
|
|
// Setting collapsible: false while collapsed; open first panel
|
|
if ( !value && this.options.active === false ) {
|
|
this._activate( 0 );
|
|
}
|
|
}
|
|
|
|
if ( key === "event" ) {
|
|
this._setupEvents( value );
|
|
}
|
|
|
|
if ( key === "heightStyle" ) {
|
|
this._setupHeightStyle( value );
|
|
}
|
|
},
|
|
|
|
_sanitizeSelector: function( hash ) {
|
|
return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
|
|
},
|
|
|
|
refresh: function() {
|
|
var options = this.options,
|
|
lis = this.tablist.children( ":has(a[href])" );
|
|
|
|
// Get disabled tabs from class attribute from HTML
|
|
// this will get converted to a boolean if needed in _refresh()
|
|
options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
|
|
return lis.index( tab );
|
|
} );
|
|
|
|
this._processTabs();
|
|
|
|
// Was collapsed or no tabs
|
|
if ( options.active === false || !this.anchors.length ) {
|
|
options.active = false;
|
|
this.active = $();
|
|
|
|
// was active, but active tab is gone
|
|
} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
|
|
|
|
// all remaining tabs are disabled
|
|
if ( this.tabs.length === options.disabled.length ) {
|
|
options.active = false;
|
|
this.active = $();
|
|
|
|
// activate previous tab
|
|
} else {
|
|
this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
|
|
}
|
|
|
|
// was active, active tab still exists
|
|
} else {
|
|
|
|
// make sure active index is correct
|
|
options.active = this.tabs.index( this.active );
|
|
}
|
|
|
|
this._refresh();
|
|
},
|
|
|
|
_refresh: function() {
|
|
this._setOptionDisabled( this.options.disabled );
|
|
this._setupEvents( this.options.event );
|
|
this._setupHeightStyle( this.options.heightStyle );
|
|
|
|
this.tabs.not( this.active ).attr( {
|
|
"aria-selected": "false",
|
|
"aria-expanded": "false",
|
|
tabIndex: -1
|
|
} );
|
|
this.panels.not( this._getPanelForTab( this.active ) )
|
|
.hide()
|
|
.attr( {
|
|
"aria-hidden": "true"
|
|
} );
|
|
|
|
// Make sure one tab is in the tab order
|
|
if ( !this.active.length ) {
|
|
this.tabs.eq( 0 ).attr( "tabIndex", 0 );
|
|
} else {
|
|
this.active
|
|
.attr( {
|
|
"aria-selected": "true",
|
|
"aria-expanded": "true",
|
|
tabIndex: 0
|
|
} );
|
|
this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
|
|
this._getPanelForTab( this.active )
|
|
.show()
|
|
.attr( {
|
|
"aria-hidden": "false"
|
|
} );
|
|
}
|
|
},
|
|
|
|
_processTabs: function() {
|
|
var that = this,
|
|
prevTabs = this.tabs,
|
|
prevAnchors = this.anchors,
|
|
prevPanels = this.panels;
|
|
|
|
this.tablist = this._getList().attr( "role", "tablist" );
|
|
this._addClass( this.tablist, "ui-tabs-nav",
|
|
"ui-helper-reset ui-helper-clearfix ui-widget-header" );
|
|
|
|
// Prevent users from focusing disabled tabs via click
|
|
this.tablist
|
|
.on( "mousedown" + this.eventNamespace, "> li", function( event ) {
|
|
if ( $( this ).is( ".ui-state-disabled" ) ) {
|
|
event.preventDefault();
|
|
}
|
|
} )
|
|
|
|
// Support: IE <9
|
|
// Preventing the default action in mousedown doesn't prevent IE
|
|
// from focusing the element, so if the anchor gets focused, blur.
|
|
// We don't have to worry about focusing the previously focused
|
|
// element since clicking on a non-focusable element should focus
|
|
// the body anyway.
|
|
.on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() {
|
|
if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
|
|
this.blur();
|
|
}
|
|
} );
|
|
|
|
this.tabs = this.tablist.find( "> li:has(a[href])" )
|
|
.attr( {
|
|
role: "tab",
|
|
tabIndex: -1
|
|
} );
|
|
this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
|
|
|
|
this.anchors = this.tabs.map( function() {
|
|
return $( "a", this )[ 0 ];
|
|
} )
|
|
.attr( {
|
|
role: "presentation",
|
|
tabIndex: -1
|
|
} );
|
|
this._addClass( this.anchors, "ui-tabs-anchor" );
|
|
|
|
this.panels = $();
|
|
|
|
this.anchors.each( function( i, anchor ) {
|
|
var selector, panel, panelId,
|
|
anchorId = $( anchor ).uniqueId().attr( "id" ),
|
|
tab = $( anchor ).closest( "li" ),
|
|
originalAriaControls = tab.attr( "aria-controls" );
|
|
|
|
// Inline tab
|
|
if ( that._isLocal( anchor ) ) {
|
|
selector = anchor.hash;
|
|
panelId = selector.substring( 1 );
|
|
panel = that.element.find( that._sanitizeSelector( selector ) );
|
|
|
|
// remote tab
|
|
} else {
|
|
|
|
// If the tab doesn't already have aria-controls,
|
|
// generate an id by using a throw-away element
|
|
panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
|
|
selector = "#" + panelId;
|
|
panel = that.element.find( selector );
|
|
if ( !panel.length ) {
|
|
panel = that._createPanel( panelId );
|
|
panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
|
|
}
|
|
panel.attr( "aria-live", "polite" );
|
|
}
|
|
|
|
if ( panel.length ) {
|
|
that.panels = that.panels.add( panel );
|
|
}
|
|
if ( originalAriaControls ) {
|
|
tab.data( "ui-tabs-aria-controls", originalAriaControls );
|
|
}
|
|
tab.attr( {
|
|
"aria-controls": panelId,
|
|
"aria-labelledby": anchorId
|
|
} );
|
|
panel.attr( "aria-labelledby", anchorId );
|
|
} );
|
|
|
|
this.panels.attr( "role", "tabpanel" );
|
|
this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
|
|
|
|
// Avoid memory leaks (#10056)
|
|
if ( prevTabs ) {
|
|
this._off( prevTabs.not( this.tabs ) );
|
|
this._off( prevAnchors.not( this.anchors ) );
|
|
this._off( prevPanels.not( this.panels ) );
|
|
}
|
|
},
|
|
|
|
// Allow overriding how to find the list for rare usage scenarios (#7715)
|
|
_getList: function() {
|
|
return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
|
|
},
|
|
|
|
_createPanel: function( id ) {
|
|
return $( "<div>" )
|
|
.attr( "id", id )
|
|
.data( "ui-tabs-destroy", true );
|
|
},
|
|
|
|
_setOptionDisabled: function( disabled ) {
|
|
var currentItem, li, i;
|
|
|
|
if ( $.isArray( disabled ) ) {
|
|
if ( !disabled.length ) {
|
|
disabled = false;
|
|
} else if ( disabled.length === this.anchors.length ) {
|
|
disabled = true;
|
|
}
|
|
}
|
|
|
|
// Disable tabs
|
|
for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
|
|
currentItem = $( li );
|
|
if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
|
|
currentItem.attr( "aria-disabled", "true" );
|
|
this._addClass( currentItem, null, "ui-state-disabled" );
|
|
} else {
|
|
currentItem.removeAttr( "aria-disabled" );
|
|
this._removeClass( currentItem, null, "ui-state-disabled" );
|
|
}
|
|
}
|
|
|
|
this.options.disabled = disabled;
|
|
|
|
this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
|
|
disabled === true );
|
|
},
|
|
|
|
_setupEvents: function( event ) {
|
|
var events = {};
|
|
if ( event ) {
|
|
$.each( event.split( " " ), function( index, eventName ) {
|
|
events[ eventName ] = "_eventHandler";
|
|
} );
|
|
}
|
|
|
|
this._off( this.anchors.add( this.tabs ).add( this.panels ) );
|
|
|
|
// Always prevent the default action, even when disabled
|
|
this._on( true, this.anchors, {
|
|
click: function( event ) {
|
|
event.preventDefault();
|
|
}
|
|
} );
|
|
this._on( this.anchors, events );
|
|
this._on( this.tabs, { keydown: "_tabKeydown" } );
|
|
this._on( this.panels, { keydown: "_panelKeydown" } );
|
|
|
|
this._focusable( this.tabs );
|
|
this._hoverable( this.tabs );
|
|
},
|
|
|
|
_setupHeightStyle: function( heightStyle ) {
|
|
var maxHeight,
|
|
parent = this.element.parent();
|
|
|
|
if ( heightStyle === "fill" ) {
|
|
maxHeight = parent.height();
|
|
maxHeight -= this.element.outerHeight() - this.element.height();
|
|
|
|
this.element.siblings( ":visible" ).each( function() {
|
|
var elem = $( this ),
|
|
position = elem.css( "position" );
|
|
|
|
if ( position === "absolute" || position === "fixed" ) {
|
|
return;
|
|
}
|
|
maxHeight -= elem.outerHeight( true );
|
|
} );
|
|
|
|
this.element.children().not( this.panels ).each( function() {
|
|
maxHeight -= $( this ).outerHeight( true );
|
|
} );
|
|
|
|
this.panels.each( function() {
|
|
$( this ).height( Math.max( 0, maxHeight -
|
|
$( this ).innerHeight() + $( this ).height() ) );
|
|
} )
|
|
.css( "overflow", "auto" );
|
|
} else if ( heightStyle === "auto" ) {
|
|
maxHeight = 0;
|
|
this.panels.each( function() {
|
|
maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
|
|
} ).height( maxHeight );
|
|
}
|
|
},
|
|
|
|
_eventHandler: function( event ) {
|
|
var options = this.options,
|
|
active = this.active,
|
|
anchor = $( event.currentTarget ),
|
|
tab = anchor.closest( "li" ),
|
|
clickedIsActive = tab[ 0 ] === active[ 0 ],
|
|
collapsing = clickedIsActive && options.collapsible,
|
|
toShow = collapsing ? $() : this._getPanelForTab( tab ),
|
|
toHide = !active.length ? $() : this._getPanelForTab( active ),
|
|
eventData = {
|
|
oldTab: active,
|
|
oldPanel: toHide,
|
|
newTab: collapsing ? $() : tab,
|
|
newPanel: toShow
|
|
};
|
|
|
|
event.preventDefault();
|
|
|
|
if ( tab.hasClass( "ui-state-disabled" ) ||
|
|
|
|
// tab is already loading
|
|
tab.hasClass( "ui-tabs-loading" ) ||
|
|
|
|
// can't switch durning an animation
|
|
this.running ||
|
|
|
|
// click on active header, but not collapsible
|
|
( clickedIsActive && !options.collapsible ) ||
|
|
|
|
// allow canceling activation
|
|
( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
|
|
return;
|
|
}
|
|
|
|
options.active = collapsing ? false : this.tabs.index( tab );
|
|
|
|
this.active = clickedIsActive ? $() : tab;
|
|
if ( this.xhr ) {
|
|
this.xhr.abort();
|
|
}
|
|
|
|
if ( !toHide.length && !toShow.length ) {
|
|
$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
|
|
}
|
|
|
|
if ( toShow.length ) {
|
|
this.load( this.tabs.index( tab ), event );
|
|
}
|
|
this._toggle( event, eventData );
|
|
},
|
|
|
|
// Handles show/hide for selecting tabs
|
|
_toggle: function( event, eventData ) {
|
|
var that = this,
|
|
toShow = eventData.newPanel,
|
|
toHide = eventData.oldPanel;
|
|
|
|
this.running = true;
|
|
|
|
function complete() {
|
|
that.running = false;
|
|
that._trigger( "activate", event, eventData );
|
|
}
|
|
|
|
function show() {
|
|
that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
|
|
|
|
if ( toShow.length && that.options.show ) {
|
|
that._show( toShow, that.options.show, complete );
|
|
} else {
|
|
toShow.show();
|
|
complete();
|
|
}
|
|
}
|
|
|
|
// Start out by hiding, then showing, then completing
|
|
if ( toHide.length && this.options.hide ) {
|
|
this._hide( toHide, this.options.hide, function() {
|
|
that._removeClass( eventData.oldTab.closest( "li" ),
|
|
"ui-tabs-active", "ui-state-active" );
|
|
show();
|
|
} );
|
|
} else {
|
|
this._removeClass( eventData.oldTab.closest( "li" ),
|
|
"ui-tabs-active", "ui-state-active" );
|
|
toHide.hide();
|
|
show();
|
|
}
|
|
|
|
toHide.attr( "aria-hidden", "true" );
|
|
eventData.oldTab.attr( {
|
|
"aria-selected": "false",
|
|
"aria-expanded": "false"
|
|
} );
|
|
|
|
// If we're switching tabs, remove the old tab from the tab order.
|
|
// If we're opening from collapsed state, remove the previous tab from the tab order.
|
|
// If we're collapsing, then keep the collapsing tab in the tab order.
|
|
if ( toShow.length && toHide.length ) {
|
|
eventData.oldTab.attr( "tabIndex", -1 );
|
|
} else if ( toShow.length ) {
|
|
this.tabs.filter( function() {
|
|
return $( this ).attr( "tabIndex" ) === 0;
|
|
} )
|
|
.attr( "tabIndex", -1 );
|
|
}
|
|
|
|
toShow.attr( "aria-hidden", "false" );
|
|
eventData.newTab.attr( {
|
|
"aria-selected": "true",
|
|
"aria-expanded": "true",
|
|
tabIndex: 0
|
|
} );
|
|
},
|
|
|
|
_activate: function( index ) {
|
|
var anchor,
|
|
active = this._findActive( index );
|
|
|
|
// Trying to activate the already active panel
|
|
if ( active[ 0 ] === this.active[ 0 ] ) {
|
|
return;
|
|
}
|
|
|
|
// Trying to collapse, simulate a click on the current active header
|
|
if ( !active.length ) {
|
|
active = this.active;
|
|
}
|
|
|
|
anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
|
|
this._eventHandler( {
|
|
target: anchor,
|
|
currentTarget: anchor,
|
|
preventDefault: $.noop
|
|
} );
|
|
},
|
|
|
|
_findActive: function( index ) {
|
|
return index === false ? $() : this.tabs.eq( index );
|
|
},
|
|
|
|
_getIndex: function( index ) {
|
|
|
|
// meta-function to give users option to provide a href string instead of a numerical index.
|
|
if ( typeof index === "string" ) {
|
|
index = this.anchors.index( this.anchors.filter( "[href$='" +
|
|
$.ui.escapeSelector( index ) + "']" ) );
|
|
}
|
|
|
|
return index;
|
|
},
|
|
|
|
_destroy: function() {
|
|
if ( this.xhr ) {
|
|
this.xhr.abort();
|
|
}
|
|
|
|
this.tablist
|
|
.removeAttr( "role" )
|
|
.off( this.eventNamespace );
|
|
|
|
this.anchors
|
|
.removeAttr( "role tabIndex" )
|
|
.removeUniqueId();
|
|
|
|
this.tabs.add( this.panels ).each( function() {
|
|
if ( $.data( this, "ui-tabs-destroy" ) ) {
|
|
$( this ).remove();
|
|
} else {
|
|
$( this ).removeAttr( "role tabIndex " +
|
|
"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
|
|
}
|
|
} );
|
|
|
|
this.tabs.each( function() {
|
|
var li = $( this ),
|
|
prev = li.data( "ui-tabs-aria-controls" );
|
|
if ( prev ) {
|
|
li
|
|
.attr( "aria-controls", prev )
|
|
.removeData( "ui-tabs-aria-controls" );
|
|
} else {
|
|
li.removeAttr( "aria-controls" );
|
|
}
|
|
} );
|
|
|
|
this.panels.show();
|
|
|
|
if ( this.options.heightStyle !== "content" ) {
|
|
this.panels.css( "height", "" );
|
|
}
|
|
},
|
|
|
|
enable: function( index ) {
|
|
var disabled = this.options.disabled;
|
|
if ( disabled === false ) {
|
|
return;
|
|
}
|
|
|
|
if ( index === undefined ) {
|
|
disabled = false;
|
|
} else {
|
|
index = this._getIndex( index );
|
|
if ( $.isArray( disabled ) ) {
|
|
disabled = $.map( disabled, function( num ) {
|
|
return num !== index ? num : null;
|
|
} );
|
|
} else {
|
|
disabled = $.map( this.tabs, function( li, num ) {
|
|
return num !== index ? num : null;
|
|
} );
|
|
}
|
|
}
|
|
this._setOptionDisabled( disabled );
|
|
},
|
|
|
|
disable: function( index ) {
|
|
var disabled = this.options.disabled;
|
|
if ( disabled === true ) {
|
|
return;
|
|
}
|
|
|
|
if ( index === undefined ) {
|
|
disabled = true;
|
|
} else {
|
|
index = this._getIndex( index );
|
|
if ( $.inArray( index, disabled ) !== -1 ) {
|
|
return;
|
|
}
|
|
if ( $.isArray( disabled ) ) {
|
|
disabled = $.merge( [ index ], disabled ).sort();
|
|
} else {
|
|
disabled = [ index ];
|
|
}
|
|
}
|
|
this._setOptionDisabled( disabled );
|
|
},
|
|
|
|
load: function( index, event ) {
|
|
index = this._getIndex( index );
|
|
var that = this,
|
|
tab = this.tabs.eq( index ),
|
|
anchor = tab.find( ".ui-tabs-anchor" ),
|
|
panel = this._getPanelForTab( tab ),
|
|
eventData = {
|
|
tab: tab,
|
|
panel: panel
|
|
},
|
|
complete = function( jqXHR, status ) {
|
|
if ( status === "abort" ) {
|
|
that.panels.stop( false, true );
|
|
}
|
|
|
|
that._removeClass( tab, "ui-tabs-loading" );
|
|
panel.removeAttr( "aria-busy" );
|
|
|
|
if ( jqXHR === that.xhr ) {
|
|
delete that.xhr;
|
|
}
|
|
};
|
|
|
|
// Not remote
|
|
if ( this._isLocal( anchor[ 0 ] ) ) {
|
|
return;
|
|
}
|
|
|
|
this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
|
|
|
|
// Support: jQuery <1.8
|
|
// jQuery <1.8 returns false if the request is canceled in beforeSend,
|
|
// but as of 1.8, $.ajax() always returns a jqXHR object.
|
|
if ( this.xhr && this.xhr.statusText !== "canceled" ) {
|
|
this._addClass( tab, "ui-tabs-loading" );
|
|
panel.attr( "aria-busy", "true" );
|
|
|
|
this.xhr
|
|
.done( function( response, status, jqXHR ) {
|
|
|
|
// support: jQuery <1.8
|
|
// http://bugs.jquery.com/ticket/11778
|
|
setTimeout( function() {
|
|
panel.html( response );
|
|
that._trigger( "load", event, eventData );
|
|
|
|
complete( jqXHR, status );
|
|
}, 1 );
|
|
} )
|
|
.fail( function( jqXHR, status ) {
|
|
|
|
// support: jQuery <1.8
|
|
// http://bugs.jquery.com/ticket/11778
|
|
setTimeout( function() {
|
|
complete( jqXHR, status );
|
|
}, 1 );
|
|
} );
|
|
}
|
|
},
|
|
|
|
_ajaxSettings: function( anchor, event, eventData ) {
|
|
var that = this;
|
|
return {
|
|
|
|
// Support: IE <11 only
|
|
// Strip any hash that exists to prevent errors with the Ajax request
|
|
url: anchor.attr( "href" ).replace( /#.*$/, "" ),
|
|
beforeSend: function( jqXHR, settings ) {
|
|
return that._trigger( "beforeLoad", event,
|
|
$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
|
|
}
|
|
};
|
|
},
|
|
|
|
_getPanelForTab: function( tab ) {
|
|
var id = $( tab ).attr( "aria-controls" );
|
|
return this.element.find( this._sanitizeSelector( "#" + id ) );
|
|
}
|
|
} );
|
|
|
|
// DEPRECATED
|
|
// TODO: Switch return back to widget declaration at top of file when this is removed
|
|
if ( $.uiBackCompat !== false ) {
|
|
|
|
// Backcompat for ui-tab class (now ui-tabs-tab)
|
|
$.widget( "ui.tabs", $.ui.tabs, {
|
|
_processTabs: function() {
|
|
this._superApply( arguments );
|
|
this._addClass( this.tabs, "ui-tab" );
|
|
}
|
|
} );
|
|
}
|
|
|
|
return $.ui.tabs;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 68 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
|
* jQuery UI Tooltip 1.12.1
|
|
* http://jqueryui.com
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license.
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
//>>label: Tooltip
|
|
//>>group: Widgets
|
|
//>>description: Shows additional information for any element on hover or focus.
|
|
//>>docs: http://api.jqueryui.com/tooltip/
|
|
//>>demos: http://jqueryui.com/tooltip/
|
|
//>>css.structure: ../../themes/base/core.css
|
|
//>>css.structure: ../../themes/base/tooltip.css
|
|
//>>css.theme: ../../themes/base/theme.css
|
|
|
|
( function( factory ) {
|
|
if ( true ) {
|
|
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [
|
|
__webpack_require__(2),
|
|
__webpack_require__(43),
|
|
__webpack_require__(21),
|
|
__webpack_require__(48),
|
|
__webpack_require__(15),
|
|
__webpack_require__(20)
|
|
], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
$.widget( "ui.tooltip", {
|
|
version: "1.12.1",
|
|
options: {
|
|
classes: {
|
|
"ui-tooltip": "ui-corner-all ui-widget-shadow"
|
|
},
|
|
content: function() {
|
|
|
|
// support: IE<9, Opera in jQuery <1.7
|
|
// .text() can't accept undefined, so coerce to a string
|
|
var title = $( this ).attr( "title" ) || "";
|
|
|
|
// Escape title, since we're going from an attribute to raw HTML
|
|
return $( "<a>" ).text( title ).html();
|
|
},
|
|
hide: true,
|
|
|
|
// Disabled elements have inconsistent behavior across browsers (#8661)
|
|
items: "[title]:not([disabled])",
|
|
position: {
|
|
my: "left top+15",
|
|
at: "left bottom",
|
|
collision: "flipfit flip"
|
|
},
|
|
show: true,
|
|
track: false,
|
|
|
|
// Callbacks
|
|
close: null,
|
|
open: null
|
|
},
|
|
|
|
_addDescribedBy: function( elem, id ) {
|
|
var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
|
|
describedby.push( id );
|
|
elem
|
|
.data( "ui-tooltip-id", id )
|
|
.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
|
|
},
|
|
|
|
_removeDescribedBy: function( elem ) {
|
|
var id = elem.data( "ui-tooltip-id" ),
|
|
describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
|
|
index = $.inArray( id, describedby );
|
|
|
|
if ( index !== -1 ) {
|
|
describedby.splice( index, 1 );
|
|
}
|
|
|
|
elem.removeData( "ui-tooltip-id" );
|
|
describedby = $.trim( describedby.join( " " ) );
|
|
if ( describedby ) {
|
|
elem.attr( "aria-describedby", describedby );
|
|
} else {
|
|
elem.removeAttr( "aria-describedby" );
|
|
}
|
|
},
|
|
|
|
_create: function() {
|
|
this._on( {
|
|
mouseover: "open",
|
|
focusin: "open"
|
|
} );
|
|
|
|
// IDs of generated tooltips, needed for destroy
|
|
this.tooltips = {};
|
|
|
|
// IDs of parent tooltips where we removed the title attribute
|
|
this.parents = {};
|
|
|
|
// Append the aria-live region so tooltips announce correctly
|
|
this.liveRegion = $( "<div>" )
|
|
.attr( {
|
|
role: "log",
|
|
"aria-live": "assertive",
|
|
"aria-relevant": "additions"
|
|
} )
|
|
.appendTo( this.document[ 0 ].body );
|
|
this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
|
|
|
|
this.disabledTitles = $( [] );
|
|
},
|
|
|
|
_setOption: function( key, value ) {
|
|
var that = this;
|
|
|
|
this._super( key, value );
|
|
|
|
if ( key === "content" ) {
|
|
$.each( this.tooltips, function( id, tooltipData ) {
|
|
that._updateContent( tooltipData.element );
|
|
} );
|
|
}
|
|
},
|
|
|
|
_setOptionDisabled: function( value ) {
|
|
this[ value ? "_disable" : "_enable" ]();
|
|
},
|
|
|
|
_disable: function() {
|
|
var that = this;
|
|
|
|
// Close open tooltips
|
|
$.each( this.tooltips, function( id, tooltipData ) {
|
|
var event = $.Event( "blur" );
|
|
event.target = event.currentTarget = tooltipData.element[ 0 ];
|
|
that.close( event, true );
|
|
} );
|
|
|
|
// Remove title attributes to prevent native tooltips
|
|
this.disabledTitles = this.disabledTitles.add(
|
|
this.element.find( this.options.items ).addBack()
|
|
.filter( function() {
|
|
var element = $( this );
|
|
if ( element.is( "[title]" ) ) {
|
|
return element
|
|
.data( "ui-tooltip-title", element.attr( "title" ) )
|
|
.removeAttr( "title" );
|
|
}
|
|
} )
|
|
);
|
|
},
|
|
|
|
_enable: function() {
|
|
|
|
// restore title attributes
|
|
this.disabledTitles.each( function() {
|
|
var element = $( this );
|
|
if ( element.data( "ui-tooltip-title" ) ) {
|
|
element.attr( "title", element.data( "ui-tooltip-title" ) );
|
|
}
|
|
} );
|
|
this.disabledTitles = $( [] );
|
|
},
|
|
|
|
open: function( event ) {
|
|
var that = this,
|
|
target = $( event ? event.target : this.element )
|
|
|
|
// we need closest here due to mouseover bubbling,
|
|
// but always pointing at the same event target
|
|
.closest( this.options.items );
|
|
|
|
// No element to show a tooltip for or the tooltip is already open
|
|
if ( !target.length || target.data( "ui-tooltip-id" ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( target.attr( "title" ) ) {
|
|
target.data( "ui-tooltip-title", target.attr( "title" ) );
|
|
}
|
|
|
|
target.data( "ui-tooltip-open", true );
|
|
|
|
// Kill parent tooltips, custom or native, for hover
|
|
if ( event && event.type === "mouseover" ) {
|
|
target.parents().each( function() {
|
|
var parent = $( this ),
|
|
blurEvent;
|
|
if ( parent.data( "ui-tooltip-open" ) ) {
|
|
blurEvent = $.Event( "blur" );
|
|
blurEvent.target = blurEvent.currentTarget = this;
|
|
that.close( blurEvent, true );
|
|
}
|
|
if ( parent.attr( "title" ) ) {
|
|
parent.uniqueId();
|
|
that.parents[ this.id ] = {
|
|
element: this,
|
|
title: parent.attr( "title" )
|
|
};
|
|
parent.attr( "title", "" );
|
|
}
|
|
} );
|
|
}
|
|
|
|
this._registerCloseHandlers( event, target );
|
|
this._updateContent( target, event );
|
|
},
|
|
|
|
_updateContent: function( target, event ) {
|
|
var content,
|
|
contentOption = this.options.content,
|
|
that = this,
|
|
eventType = event ? event.type : null;
|
|
|
|
if ( typeof contentOption === "string" || contentOption.nodeType ||
|
|
contentOption.jquery ) {
|
|
return this._open( event, target, contentOption );
|
|
}
|
|
|
|
content = contentOption.call( target[ 0 ], function( response ) {
|
|
|
|
// IE may instantly serve a cached response for ajax requests
|
|
// delay this call to _open so the other call to _open runs first
|
|
that._delay( function() {
|
|
|
|
// Ignore async response if tooltip was closed already
|
|
if ( !target.data( "ui-tooltip-open" ) ) {
|
|
return;
|
|
}
|
|
|
|
// JQuery creates a special event for focusin when it doesn't
|
|
// exist natively. To improve performance, the native event
|
|
// object is reused and the type is changed. Therefore, we can't
|
|
// rely on the type being correct after the event finished
|
|
// bubbling, so we set it back to the previous value. (#8740)
|
|
if ( event ) {
|
|
event.type = eventType;
|
|
}
|
|
this._open( event, target, response );
|
|
} );
|
|
} );
|
|
if ( content ) {
|
|
this._open( event, target, content );
|
|
}
|
|
},
|
|
|
|
_open: function( event, target, content ) {
|
|
var tooltipData, tooltip, delayedShow, a11yContent,
|
|
positionOption = $.extend( {}, this.options.position );
|
|
|
|
if ( !content ) {
|
|
return;
|
|
}
|
|
|
|
// Content can be updated multiple times. If the tooltip already
|
|
// exists, then just update the content and bail.
|
|
tooltipData = this._find( target );
|
|
if ( tooltipData ) {
|
|
tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
|
|
return;
|
|
}
|
|
|
|
// If we have a title, clear it to prevent the native tooltip
|
|
// we have to check first to avoid defining a title if none exists
|
|
// (we don't want to cause an element to start matching [title])
|
|
//
|
|
// We use removeAttr only for key events, to allow IE to export the correct
|
|
// accessible attributes. For mouse events, set to empty string to avoid
|
|
// native tooltip showing up (happens only when removing inside mouseover).
|
|
if ( target.is( "[title]" ) ) {
|
|
if ( event && event.type === "mouseover" ) {
|
|
target.attr( "title", "" );
|
|
} else {
|
|
target.removeAttr( "title" );
|
|
}
|
|
}
|
|
|
|
tooltipData = this._tooltip( target );
|
|
tooltip = tooltipData.tooltip;
|
|
this._addDescribedBy( target, tooltip.attr( "id" ) );
|
|
tooltip.find( ".ui-tooltip-content" ).html( content );
|
|
|
|
// Support: Voiceover on OS X, JAWS on IE <= 9
|
|
// JAWS announces deletions even when aria-relevant="additions"
|
|
// Voiceover will sometimes re-read the entire log region's contents from the beginning
|
|
this.liveRegion.children().hide();
|
|
a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
|
|
a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
|
|
a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
|
|
a11yContent.appendTo( this.liveRegion );
|
|
|
|
function position( event ) {
|
|
positionOption.of = event;
|
|
if ( tooltip.is( ":hidden" ) ) {
|
|
return;
|
|
}
|
|
tooltip.position( positionOption );
|
|
}
|
|
if ( this.options.track && event && /^mouse/.test( event.type ) ) {
|
|
this._on( this.document, {
|
|
mousemove: position
|
|
} );
|
|
|
|
// trigger once to override element-relative positioning
|
|
position( event );
|
|
} else {
|
|
tooltip.position( $.extend( {
|
|
of: target
|
|
}, this.options.position ) );
|
|
}
|
|
|
|
tooltip.hide();
|
|
|
|
this._show( tooltip, this.options.show );
|
|
|
|
// Handle tracking tooltips that are shown with a delay (#8644). As soon
|
|
// as the tooltip is visible, position the tooltip using the most recent
|
|
// event.
|
|
// Adds the check to add the timers only when both delay and track options are set (#14682)
|
|
if ( this.options.track && this.options.show && this.options.show.delay ) {
|
|
delayedShow = this.delayedShow = setInterval( function() {
|
|
if ( tooltip.is( ":visible" ) ) {
|
|
position( positionOption.of );
|
|
clearInterval( delayedShow );
|
|
}
|
|
}, $.fx.interval );
|
|
}
|
|
|
|
this._trigger( "open", event, { tooltip: tooltip } );
|
|
},
|
|
|
|
_registerCloseHandlers: function( event, target ) {
|
|
var events = {
|
|
keyup: function( event ) {
|
|
if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
|
|
var fakeEvent = $.Event( event );
|
|
fakeEvent.currentTarget = target[ 0 ];
|
|
this.close( fakeEvent, true );
|
|
}
|
|
}
|
|
};
|
|
|
|
// Only bind remove handler for delegated targets. Non-delegated
|
|
// tooltips will handle this in destroy.
|
|
if ( target[ 0 ] !== this.element[ 0 ] ) {
|
|
events.remove = function() {
|
|
this._removeTooltip( this._find( target ).tooltip );
|
|
};
|
|
}
|
|
|
|
if ( !event || event.type === "mouseover" ) {
|
|
events.mouseleave = "close";
|
|
}
|
|
if ( !event || event.type === "focusin" ) {
|
|
events.focusout = "close";
|
|
}
|
|
this._on( true, target, events );
|
|
},
|
|
|
|
close: function( event ) {
|
|
var tooltip,
|
|
that = this,
|
|
target = $( event ? event.currentTarget : this.element ),
|
|
tooltipData = this._find( target );
|
|
|
|
// The tooltip may already be closed
|
|
if ( !tooltipData ) {
|
|
|
|
// We set ui-tooltip-open immediately upon open (in open()), but only set the
|
|
// additional data once there's actually content to show (in _open()). So even if the
|
|
// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
|
|
// the period between open() and _open().
|
|
target.removeData( "ui-tooltip-open" );
|
|
return;
|
|
}
|
|
|
|
tooltip = tooltipData.tooltip;
|
|
|
|
// Disabling closes the tooltip, so we need to track when we're closing
|
|
// to avoid an infinite loop in case the tooltip becomes disabled on close
|
|
if ( tooltipData.closing ) {
|
|
return;
|
|
}
|
|
|
|
// Clear the interval for delayed tracking tooltips
|
|
clearInterval( this.delayedShow );
|
|
|
|
// Only set title if we had one before (see comment in _open())
|
|
// If the title attribute has changed since open(), don't restore
|
|
if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
|
|
target.attr( "title", target.data( "ui-tooltip-title" ) );
|
|
}
|
|
|
|
this._removeDescribedBy( target );
|
|
|
|
tooltipData.hiding = true;
|
|
tooltip.stop( true );
|
|
this._hide( tooltip, this.options.hide, function() {
|
|
that._removeTooltip( $( this ) );
|
|
} );
|
|
|
|
target.removeData( "ui-tooltip-open" );
|
|
this._off( target, "mouseleave focusout keyup" );
|
|
|
|
// Remove 'remove' binding only on delegated targets
|
|
if ( target[ 0 ] !== this.element[ 0 ] ) {
|
|
this._off( target, "remove" );
|
|
}
|
|
this._off( this.document, "mousemove" );
|
|
|
|
if ( event && event.type === "mouseleave" ) {
|
|
$.each( this.parents, function( id, parent ) {
|
|
$( parent.element ).attr( "title", parent.title );
|
|
delete that.parents[ id ];
|
|
} );
|
|
}
|
|
|
|
tooltipData.closing = true;
|
|
this._trigger( "close", event, { tooltip: tooltip } );
|
|
if ( !tooltipData.hiding ) {
|
|
tooltipData.closing = false;
|
|
}
|
|
},
|
|
|
|
_tooltip: function( element ) {
|
|
var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
|
|
content = $( "<div>" ).appendTo( tooltip ),
|
|
id = tooltip.uniqueId().attr( "id" );
|
|
|
|
this._addClass( content, "ui-tooltip-content" );
|
|
this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
|
|
|
|
tooltip.appendTo( this._appendTo( element ) );
|
|
|
|
return this.tooltips[ id ] = {
|
|
element: element,
|
|
tooltip: tooltip
|
|
};
|
|
},
|
|
|
|
_find: function( target ) {
|
|
var id = target.data( "ui-tooltip-id" );
|
|
return id ? this.tooltips[ id ] : null;
|
|
},
|
|
|
|
_removeTooltip: function( tooltip ) {
|
|
tooltip.remove();
|
|
delete this.tooltips[ tooltip.attr( "id" ) ];
|
|
},
|
|
|
|
_appendTo: function( target ) {
|
|
var element = target.closest( ".ui-front, dialog" );
|
|
|
|
if ( !element.length ) {
|
|
element = this.document[ 0 ].body;
|
|
}
|
|
|
|
return element;
|
|
},
|
|
|
|
_destroy: function() {
|
|
var that = this;
|
|
|
|
// Close open tooltips
|
|
$.each( this.tooltips, function( id, tooltipData ) {
|
|
|
|
// Delegate to close method to handle common cleanup
|
|
var event = $.Event( "blur" ),
|
|
element = tooltipData.element;
|
|
event.target = event.currentTarget = element[ 0 ];
|
|
that.close( event, true );
|
|
|
|
// Remove immediately; destroying an open tooltip doesn't use the
|
|
// hide animation
|
|
$( "#" + id ).remove();
|
|
|
|
// Restore the title
|
|
if ( element.data( "ui-tooltip-title" ) ) {
|
|
|
|
// If the title attribute has changed since open(), don't restore
|
|
if ( !element.attr( "title" ) ) {
|
|
element.attr( "title", element.data( "ui-tooltip-title" ) );
|
|
}
|
|
element.removeData( "ui-tooltip-title" );
|
|
}
|
|
} );
|
|
this.liveRegion.remove();
|
|
}
|
|
} );
|
|
|
|
// DEPRECATED
|
|
// TODO: Switch return back to widget declaration at top of file when this is removed
|
|
if ( $.uiBackCompat !== false ) {
|
|
|
|
// Backcompat for tooltipClass option
|
|
$.widget( "ui.tooltip", $.ui.tooltip, {
|
|
options: {
|
|
tooltipClass: null
|
|
},
|
|
_tooltip: function() {
|
|
var tooltipData = this._superApply( arguments );
|
|
if ( this.options.tooltipClass ) {
|
|
tooltipData.tooltip.addClass( this.options.tooltipClass );
|
|
}
|
|
return tooltipData;
|
|
}
|
|
} );
|
|
}
|
|
|
|
return $.ui.tooltip;
|
|
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 69 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// extracted by mini-css-extract-plugin
|
|
|
|
/***/ }),
|
|
/* 70 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Based off https://code.google.com/p/gaequery/source/browse/trunk/src/static/scripts/jquery.autogrow-textarea.js?r=2
|
|
// Modified by David Beck
|
|
|
|
( function( factory ) {
|
|
// UMD wrapper
|
|
if ( true ) {
|
|
// AMD
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
}( function( $ ) {
|
|
|
|
/*
|
|
* Auto-growing textareas; technique ripped from Facebook
|
|
*/
|
|
$.fn.autogrow = function(options) {
|
|
|
|
options = $.extend( {
|
|
vertical: true,
|
|
horizontal: false,
|
|
characterSlop: 0
|
|
}, options);
|
|
|
|
this.filter('textarea,input').each(function() {
|
|
|
|
var $this = $(this),
|
|
borderBox = $this.css( 'box-sizing' ) === 'border-box',
|
|
// minHeight = borderBox ? $this.outerHeight() : $this.height(),
|
|
maxHeight = $this.attr( "maxHeight" ),
|
|
minWidth = typeof( $this.attr( "minWidth" ) ) == "undefined" ? 0 : $this.attr( "minWidth" );
|
|
|
|
if( typeof( maxHeight ) == "undefined" ) maxHeight = 1000000;
|
|
|
|
var shadow = $('<div class="autogrow-shadow"></div>').css( {
|
|
position: 'absolute',
|
|
top: -10000,
|
|
left: -10000,
|
|
fontSize: $this.css('fontSize'),
|
|
fontFamily: $this.css('fontFamily'),
|
|
fontWeight: $this.css('fontWeight'),
|
|
lineHeight: $this.css('lineHeight'),
|
|
paddingLeft: $this.css('paddingLeft'),
|
|
paddingRight: $this.css('paddingRight'),
|
|
paddingTop: $this.css('paddingTop'),
|
|
paddingBottom: $this.css('paddingBottom'),
|
|
borderTop: $this.css('borderTop'),
|
|
borderBottom: $this.css('borderBottom'),
|
|
borderLeft: $this.css('borderLeft'),
|
|
borderRight: $this.css('borderRight'),
|
|
resize: 'none'
|
|
} ).appendTo(document.body);
|
|
|
|
shadow.html( 'a' );
|
|
var characterWidth = shadow.width();
|
|
shadow.html( '' );
|
|
|
|
var update = function( val ) {
|
|
|
|
var times = function(string, number) {
|
|
for (var i = 0, r = ''; i < number; i ++) r += string;
|
|
return r;
|
|
};
|
|
|
|
if( typeof val === 'undefined' ) val = this.value;
|
|
if( val === '' && $(this).attr("placeholder") ) val = $(this).attr("placeholder");
|
|
|
|
if( options.vertical )
|
|
val = val.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/\n$/, '<br/> ')
|
|
.replace(/\n/g, '<br/>')
|
|
.replace(/ {2,}/g, function(space) { return times(' ', space.length -1) + ' '; });
|
|
else
|
|
val = escapeHtml( val );
|
|
|
|
//if( options.horizontal )
|
|
// val = $.trim( val );
|
|
|
|
// if( $(this).prop( 'tagName' ).toUpperCase() === 'INPUT' )
|
|
// shadow.text(val).css( "width", "auto" );
|
|
// else
|
|
shadow.html( val ).css( "width", "auto" ); // need to use html here otherwise no way to count spaces (with html we can use )
|
|
|
|
if( options.horizontal )
|
|
{
|
|
var slopWidth = options.characterSlop * characterWidth + 2;
|
|
|
|
var newWidth = Math.max( shadow.width() + slopWidth, minWidth );
|
|
var maxWidth = options.maxWidth;
|
|
//if( typeof( maxWidth ) === "undefined" ) maxWidth = $this.parent().width() - 12; // not sure why we were doing this but seems like a bad idea. doesn't work with inline-block parents for one thing, since it is the text area that should be "pushing" them to be wider
|
|
if( maxWidth ) newWidth = Math.min( newWidth, maxWidth );
|
|
$(this).css( "width", newWidth );
|
|
}
|
|
|
|
if( options.vertical )
|
|
{
|
|
var shadowWidth = $(this).width();
|
|
if( ! borderBox ) shadowWidth = shadowWidth - parseInt($this.css('paddingLeft'),10) - parseInt($this.css('paddingRight'),10);
|
|
shadow.css( "width", shadowWidth );
|
|
var shadowHeight = borderBox ? shadow.outerHeight() : shadow.height();
|
|
|
|
$(this).css( "height", "auto" );
|
|
minHeight = borderBox ? $this.outerHeight() : $this.height();
|
|
|
|
var newHeight = Math.min( Math.max( shadowHeight, minHeight ), maxHeight );
|
|
$(this).css( "height", newHeight );
|
|
$(this).css( "overflow", newHeight == maxHeight ? "auto" : "hidden" );
|
|
}
|
|
};
|
|
|
|
$(this)
|
|
.change(function(){update.call( this );return true;})
|
|
.keyup(function(){update.call( this );return true;})
|
|
.keypress(function( event ) {
|
|
if( event.ctrlKey || event.metaKey ) return;
|
|
|
|
var val = this.value;
|
|
var caretInfo = _getCaretInfo( this );
|
|
|
|
var typedChar = event.which === 13 ? "\n" : String.fromCharCode( event.which );
|
|
var valAfterKeypress = val.slice( 0, caretInfo.start ) + typedChar + val.slice( caretInfo.end );
|
|
update.call( this, valAfterKeypress );
|
|
return true;
|
|
})
|
|
.bind( "update.autogrow", function(){ update.apply(this); } )
|
|
.bind( "remove.autogrow", function() {
|
|
shadow.remove();
|
|
} );
|
|
|
|
update.apply(this);
|
|
|
|
});
|
|
|
|
return this;
|
|
};
|
|
|
|
// comes from https://github.com/madapaja/jquery.selection/blob/master/src/jquery.selection.js
|
|
var _getCaretInfo = function(element){
|
|
var res = {
|
|
text: '',
|
|
start: 0,
|
|
end: 0
|
|
};
|
|
|
|
if (!element.value) {
|
|
/* no value or empty string */
|
|
return res;
|
|
}
|
|
|
|
try {
|
|
if (window.getSelection) {
|
|
/* except IE */
|
|
res.start = element.selectionStart;
|
|
res.end = element.selectionEnd;
|
|
res.text = element.value.slice(res.start, res.end);
|
|
} else if (doc.selection) {
|
|
/* for IE */
|
|
element.focus();
|
|
|
|
var range = doc.selection.createRange(),
|
|
range2 = doc.body.createTextRange();
|
|
|
|
res.text = range.text;
|
|
|
|
try {
|
|
range2.moveToElementText(element);
|
|
range2.setEndPoint('StartToStart', range);
|
|
} catch (e) {
|
|
range2 = element.createTextRange();
|
|
range2.setEndPoint('StartToStart', range);
|
|
}
|
|
|
|
res.start = element.value.length - range2.text.length;
|
|
res.end = res.start + range.text.length;
|
|
}
|
|
} catch (e) {
|
|
/* give up */
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
var entityMap = {
|
|
"&": "&",
|
|
"<": "<",
|
|
">": ">",
|
|
'"': '"',
|
|
"'": ''',
|
|
"/": '/',
|
|
" ": ' '
|
|
};
|
|
|
|
function escapeHtml(string) {
|
|
return String(string).replace(/[&<>"'\/\ ]/g, function (s) {
|
|
return entityMap[s];
|
|
} );
|
|
}
|
|
} ) );
|
|
|
|
|
|
/***/ }),
|
|
/* 71 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/*global jQuery */
|
|
/*!
|
|
* FitText.js 1.2
|
|
*
|
|
* Copyright 2011, Dave Rupert http://daverupert.com
|
|
* Released under the WTFPL license
|
|
* http://sam.zoy.org/wtfpl/
|
|
*
|
|
* Date: Thu May 05 14:23:00 2011 -0600
|
|
*/
|
|
|
|
(function( $ ){
|
|
|
|
$.fn.fitText = function( kompressor, options ) {
|
|
|
|
// Setup options
|
|
var compressor = kompressor || 1,
|
|
settings = $.extend({
|
|
'minFontSize' : Number.NEGATIVE_INFINITY,
|
|
'maxFontSize' : Number.POSITIVE_INFINITY
|
|
}, options);
|
|
|
|
return this.each(function(){
|
|
|
|
// Store the object
|
|
var $this = $(this);
|
|
|
|
// Resizer() resizes items based on the object width divided by the compressor * 10
|
|
var resizer = function () {
|
|
$this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)));
|
|
};
|
|
|
|
// Call once to set.
|
|
resizer();
|
|
|
|
// Call on resize. Opera debounces their resize by default.
|
|
$(window).on('resize.fittext orientationchange.fittext', resizer);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
})( jQuery );
|
|
|
|
|
|
/***/ }),
|
|
/* 72 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*
|
|
* qTip2 - Pretty powerful tooltips - v3.0.3
|
|
* http://qtip2.com
|
|
*
|
|
* Copyright (c) 2016
|
|
* Released under the MIT licenses
|
|
* http://jquery.org/license
|
|
*
|
|
* Date: Wed May 11 2016 10:31 GMT+0100+0100
|
|
* Plugins: tips modal viewport svg imagemap ie6
|
|
* Styles: core basic css3
|
|
*/
|
|
/*global window: false, jQuery: false, console: false, define: false */
|
|
|
|
/* Cache window, document, undefined */
|
|
(function( window, document, undefined ) {
|
|
|
|
// Uses AMD or browser globals to create a jQuery plugin.
|
|
(function( factory ) {
|
|
"use strict";
|
|
if(true) {
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(2)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
}
|
|
else {}
|
|
}
|
|
(function($) {
|
|
"use strict"; // Enable ECMAScript "strict" operation for this function. See more: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
|
|
;// Munge the primitives - Paul Irish tip
|
|
var TRUE = true,
|
|
FALSE = false,
|
|
NULL = null,
|
|
|
|
// Common variables
|
|
X = 'x', Y = 'y',
|
|
WIDTH = 'width',
|
|
HEIGHT = 'height',
|
|
|
|
// Positioning sides
|
|
TOP = 'top',
|
|
LEFT = 'left',
|
|
BOTTOM = 'bottom',
|
|
RIGHT = 'right',
|
|
CENTER = 'center',
|
|
|
|
// Position adjustment types
|
|
FLIP = 'flip',
|
|
FLIPINVERT = 'flipinvert',
|
|
SHIFT = 'shift',
|
|
|
|
// Shortcut vars
|
|
QTIP, PROTOTYPE, CORNER, CHECKS,
|
|
PLUGINS = {},
|
|
NAMESPACE = 'qtip',
|
|
ATTR_HAS = 'data-hasqtip',
|
|
ATTR_ID = 'data-qtip-id',
|
|
WIDGET = ['ui-widget', 'ui-tooltip'],
|
|
SELECTOR = '.'+NAMESPACE,
|
|
INACTIVE_EVENTS = 'click dblclick mousedown mouseup mousemove mouseleave mouseenter'.split(' '),
|
|
|
|
CLASS_FIXED = NAMESPACE+'-fixed',
|
|
CLASS_DEFAULT = NAMESPACE + '-default',
|
|
CLASS_FOCUS = NAMESPACE + '-focus',
|
|
CLASS_HOVER = NAMESPACE + '-hover',
|
|
CLASS_DISABLED = NAMESPACE+'-disabled',
|
|
|
|
replaceSuffix = '_replacedByqTip',
|
|
oldtitle = 'oldtitle',
|
|
trackingBound,
|
|
|
|
// Browser detection
|
|
BROWSER = {
|
|
/*
|
|
* IE version detection
|
|
*
|
|
* Adapted from: http://ajaxian.com/archives/attack-of-the-ie-conditional-comment
|
|
* Credit to James Padolsey for the original implemntation!
|
|
*/
|
|
ie: (function() {
|
|
/* eslint-disable no-empty */
|
|
var v, i;
|
|
for (
|
|
v = 4, i = document.createElement('div');
|
|
(i.innerHTML = '<!--[if gt IE ' + v + ']><i></i><![endif]-->') && i.getElementsByTagName('i')[0];
|
|
v+=1
|
|
) {}
|
|
return v > 4 ? v : NaN;
|
|
/* eslint-enable no-empty */
|
|
})(),
|
|
|
|
/*
|
|
* iOS version detection
|
|
*/
|
|
iOS: parseFloat(
|
|
('' + (/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0,''])[1])
|
|
.replace('undefined', '3_2').replace('_', '.').replace('_', '')
|
|
) || FALSE
|
|
};
|
|
;function QTip(target, options, id, attr) {
|
|
// Elements and ID
|
|
this.id = id;
|
|
this.target = target;
|
|
this.tooltip = NULL;
|
|
this.elements = { target: target };
|
|
|
|
// Internal constructs
|
|
this._id = NAMESPACE + '-' + id;
|
|
this.timers = { img: {} };
|
|
this.options = options;
|
|
this.plugins = {};
|
|
|
|
// Cache object
|
|
this.cache = {
|
|
event: {},
|
|
target: $(),
|
|
disabled: FALSE,
|
|
attr: attr,
|
|
onTooltip: FALSE,
|
|
lastClass: ''
|
|
};
|
|
|
|
// Set the initial flags
|
|
this.rendered = this.destroyed = this.disabled = this.waiting =
|
|
this.hiddenDuringWait = this.positioning = this.triggering = FALSE;
|
|
}
|
|
PROTOTYPE = QTip.prototype;
|
|
|
|
PROTOTYPE._when = function(deferreds) {
|
|
return $.when.apply($, deferreds);
|
|
};
|
|
|
|
PROTOTYPE.render = function(show) {
|
|
if(this.rendered || this.destroyed) { return this; } // If tooltip has already been rendered, exit
|
|
|
|
var self = this,
|
|
options = this.options,
|
|
cache = this.cache,
|
|
elements = this.elements,
|
|
text = options.content.text,
|
|
title = options.content.title,
|
|
button = options.content.button,
|
|
posOptions = options.position,
|
|
deferreds = [];
|
|
|
|
// Add ARIA attributes to target
|
|
$.attr(this.target[0], 'aria-describedby', this._id);
|
|
|
|
// Create public position object that tracks current position corners
|
|
cache.posClass = this._createPosClass(
|
|
(this.position = { my: posOptions.my, at: posOptions.at }).my
|
|
);
|
|
|
|
// Create tooltip element
|
|
this.tooltip = elements.tooltip = $('<div/>', {
|
|
'id': this._id,
|
|
'class': [ NAMESPACE, CLASS_DEFAULT, options.style.classes, cache.posClass ].join(' '),
|
|
'width': options.style.width || '',
|
|
'height': options.style.height || '',
|
|
'tracking': posOptions.target === 'mouse' && posOptions.adjust.mouse,
|
|
|
|
/* ARIA specific attributes */
|
|
'role': 'alert',
|
|
'aria-live': 'polite',
|
|
'aria-atomic': FALSE,
|
|
'aria-describedby': this._id + '-content',
|
|
'aria-hidden': TRUE
|
|
})
|
|
.toggleClass(CLASS_DISABLED, this.disabled)
|
|
.attr(ATTR_ID, this.id)
|
|
.data(NAMESPACE, this)
|
|
.appendTo(posOptions.container)
|
|
.append(
|
|
// Create content element
|
|
elements.content = $('<div />', {
|
|
'class': NAMESPACE + '-content',
|
|
'id': this._id + '-content',
|
|
'aria-atomic': TRUE
|
|
})
|
|
);
|
|
|
|
// Set rendered flag and prevent redundant reposition calls for now
|
|
this.rendered = -1;
|
|
this.positioning = TRUE;
|
|
|
|
// Create title...
|
|
if(title) {
|
|
this._createTitle();
|
|
|
|
// Update title only if its not a callback (called in toggle if so)
|
|
if(!$.isFunction(title)) {
|
|
deferreds.push( this._updateTitle(title, FALSE) );
|
|
}
|
|
}
|
|
|
|
// Create button
|
|
if(button) { this._createButton(); }
|
|
|
|
// Set proper rendered flag and update content if not a callback function (called in toggle)
|
|
if(!$.isFunction(text)) {
|
|
deferreds.push( this._updateContent(text, FALSE) );
|
|
}
|
|
this.rendered = TRUE;
|
|
|
|
// Setup widget classes
|
|
this._setWidget();
|
|
|
|
// Initialize 'render' plugins
|
|
$.each(PLUGINS, function(name) {
|
|
var instance;
|
|
if(this.initialize === 'render' && (instance = this(self))) {
|
|
self.plugins[name] = instance;
|
|
}
|
|
});
|
|
|
|
// Unassign initial events and assign proper events
|
|
this._unassignEvents();
|
|
this._assignEvents();
|
|
|
|
// When deferreds have completed
|
|
this._when(deferreds).then(function() {
|
|
// tooltiprender event
|
|
self._trigger('render');
|
|
|
|
// Reset flags
|
|
self.positioning = FALSE;
|
|
|
|
// Show tooltip if not hidden during wait period
|
|
if(!self.hiddenDuringWait && (options.show.ready || show)) {
|
|
self.toggle(TRUE, cache.event, FALSE);
|
|
}
|
|
self.hiddenDuringWait = FALSE;
|
|
});
|
|
|
|
// Expose API
|
|
QTIP.api[this.id] = this;
|
|
|
|
return this;
|
|
};
|
|
|
|
PROTOTYPE.destroy = function(immediate) {
|
|
// Set flag the signify destroy is taking place to plugins
|
|
// and ensure it only gets destroyed once!
|
|
if(this.destroyed) { return this.target; }
|
|
|
|
function process() {
|
|
if(this.destroyed) { return; }
|
|
this.destroyed = TRUE;
|
|
|
|
var target = this.target,
|
|
title = target.attr(oldtitle),
|
|
timer;
|
|
|
|
// Destroy tooltip if rendered
|
|
if(this.rendered) {
|
|
this.tooltip.stop(1,0).find('*').remove().end().remove();
|
|
}
|
|
|
|
// Destroy all plugins
|
|
$.each(this.plugins, function() {
|
|
this.destroy && this.destroy();
|
|
});
|
|
|
|
// Clear timers
|
|
for (timer in this.timers) {
|
|
if (this.timers.hasOwnProperty(timer)) {
|
|
clearTimeout(this.timers[timer]);
|
|
}
|
|
}
|
|
|
|
// Remove api object and ARIA attributes
|
|
target.removeData(NAMESPACE)
|
|
.removeAttr(ATTR_ID)
|
|
.removeAttr(ATTR_HAS)
|
|
.removeAttr('aria-describedby');
|
|
|
|
// Reset old title attribute if removed
|
|
if(this.options.suppress && title) {
|
|
target.attr('title', title).removeAttr(oldtitle);
|
|
}
|
|
|
|
// Remove qTip events associated with this API
|
|
this._unassignEvents();
|
|
|
|
// Remove ID from used id objects, and delete object references
|
|
// for better garbage collection and leak protection
|
|
this.options = this.elements = this.cache = this.timers =
|
|
this.plugins = this.mouse = NULL;
|
|
|
|
// Delete epoxsed API object
|
|
delete QTIP.api[this.id];
|
|
}
|
|
|
|
// If an immediate destroy is needed
|
|
if((immediate !== TRUE || this.triggering === 'hide') && this.rendered) {
|
|
this.tooltip.one('tooltiphidden', $.proxy(process, this));
|
|
!this.triggering && this.hide();
|
|
}
|
|
|
|
// If we're not in the process of hiding... process
|
|
else { process.call(this); }
|
|
|
|
return this.target;
|
|
};
|
|
;function invalidOpt(a) {
|
|
return a === NULL || $.type(a) !== 'object';
|
|
}
|
|
|
|
function invalidContent(c) {
|
|
return !($.isFunction(c) ||
|
|
c && c.attr ||
|
|
c.length ||
|
|
$.type(c) === 'object' && (c.jquery || c.then));
|
|
}
|
|
|
|
// Option object sanitizer
|
|
function sanitizeOptions(opts) {
|
|
var content, text, ajax, once;
|
|
|
|
if(invalidOpt(opts)) { return FALSE; }
|
|
|
|
if(invalidOpt(opts.metadata)) {
|
|
opts.metadata = { type: opts.metadata };
|
|
}
|
|
|
|
if('content' in opts) {
|
|
content = opts.content;
|
|
|
|
if(invalidOpt(content) || content.jquery || content.done) {
|
|
text = invalidContent(content) ? FALSE : content;
|
|
content = opts.content = {
|
|
text: text
|
|
};
|
|
}
|
|
else { text = content.text; }
|
|
|
|
// DEPRECATED - Old content.ajax plugin functionality
|
|
// Converts it into the proper Deferred syntax
|
|
if('ajax' in content) {
|
|
ajax = content.ajax;
|
|
once = ajax && ajax.once !== FALSE;
|
|
delete content.ajax;
|
|
|
|
content.text = function(event, api) {
|
|
var loading = text || $(this).attr(api.options.content.attr) || 'Loading...',
|
|
|
|
deferred = $.ajax(
|
|
$.extend({}, ajax, { context: api })
|
|
)
|
|
.then(ajax.success, NULL, ajax.error)
|
|
.then(function(newContent) {
|
|
if(newContent && once) { api.set('content.text', newContent); }
|
|
return newContent;
|
|
},
|
|
function(xhr, status, error) {
|
|
if(api.destroyed || xhr.status === 0) { return; }
|
|
api.set('content.text', status + ': ' + error);
|
|
});
|
|
|
|
return !once ? (api.set('content.text', loading), deferred) : loading;
|
|
};
|
|
}
|
|
|
|
if('title' in content) {
|
|
if($.isPlainObject(content.title)) {
|
|
content.button = content.title.button;
|
|
content.title = content.title.text;
|
|
}
|
|
|
|
if(invalidContent(content.title || FALSE)) {
|
|
content.title = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if('position' in opts && invalidOpt(opts.position)) {
|
|
opts.position = { my: opts.position, at: opts.position };
|
|
}
|
|
|
|
if('show' in opts && invalidOpt(opts.show)) {
|
|
opts.show = opts.show.jquery ? { target: opts.show } :
|
|
opts.show === TRUE ? { ready: TRUE } : { event: opts.show };
|
|
}
|
|
|
|
if('hide' in opts && invalidOpt(opts.hide)) {
|
|
opts.hide = opts.hide.jquery ? { target: opts.hide } : { event: opts.hide };
|
|
}
|
|
|
|
if('style' in opts && invalidOpt(opts.style)) {
|
|
opts.style = { classes: opts.style };
|
|
}
|
|
|
|
// Sanitize plugin options
|
|
$.each(PLUGINS, function() {
|
|
this.sanitize && this.sanitize(opts);
|
|
});
|
|
|
|
return opts;
|
|
}
|
|
|
|
// Setup builtin .set() option checks
|
|
CHECKS = PROTOTYPE.checks = {
|
|
builtin: {
|
|
// Core checks
|
|
'^id$': function(obj, o, v, prev) {
|
|
var id = v === TRUE ? QTIP.nextid : v,
|
|
newId = NAMESPACE + '-' + id;
|
|
|
|
if(id !== FALSE && id.length > 0 && !$('#'+newId).length) {
|
|
this._id = newId;
|
|
|
|
if(this.rendered) {
|
|
this.tooltip[0].id = this._id;
|
|
this.elements.content[0].id = this._id + '-content';
|
|
this.elements.title[0].id = this._id + '-title';
|
|
}
|
|
}
|
|
else { obj[o] = prev; }
|
|
},
|
|
'^prerender': function(obj, o, v) {
|
|
v && !this.rendered && this.render(this.options.show.ready);
|
|
},
|
|
|
|
// Content checks
|
|
'^content.text$': function(obj, o, v) {
|
|
this._updateContent(v);
|
|
},
|
|
'^content.attr$': function(obj, o, v, prev) {
|
|
if(this.options.content.text === this.target.attr(prev)) {
|
|
this._updateContent( this.target.attr(v) );
|
|
}
|
|
},
|
|
'^content.title$': function(obj, o, v) {
|
|
// Remove title if content is null
|
|
if(!v) { return this._removeTitle(); }
|
|
|
|
// If title isn't already created, create it now and update
|
|
v && !this.elements.title && this._createTitle();
|
|
this._updateTitle(v);
|
|
},
|
|
'^content.button$': function(obj, o, v) {
|
|
this._updateButton(v);
|
|
},
|
|
'^content.title.(text|button)$': function(obj, o, v) {
|
|
this.set('content.'+o, v); // Backwards title.text/button compat
|
|
},
|
|
|
|
// Position checks
|
|
'^position.(my|at)$': function(obj, o, v){
|
|
if('string' === typeof v) {
|
|
this.position[o] = obj[o] = new CORNER(v, o === 'at');
|
|
}
|
|
},
|
|
'^position.container$': function(obj, o, v){
|
|
this.rendered && this.tooltip.appendTo(v);
|
|
},
|
|
|
|
// Show checks
|
|
'^show.ready$': function(obj, o, v) {
|
|
v && (!this.rendered && this.render(TRUE) || this.toggle(TRUE));
|
|
},
|
|
|
|
// Style checks
|
|
'^style.classes$': function(obj, o, v, p) {
|
|
this.rendered && this.tooltip.removeClass(p).addClass(v);
|
|
},
|
|
'^style.(width|height)': function(obj, o, v) {
|
|
this.rendered && this.tooltip.css(o, v);
|
|
},
|
|
'^style.widget|content.title': function() {
|
|
this.rendered && this._setWidget();
|
|
},
|
|
'^style.def': function(obj, o, v) {
|
|
this.rendered && this.tooltip.toggleClass(CLASS_DEFAULT, !!v);
|
|
},
|
|
|
|
// Events check
|
|
'^events.(render|show|move|hide|focus|blur)$': function(obj, o, v) {
|
|
this.rendered && this.tooltip[($.isFunction(v) ? '' : 'un') + 'bind']('tooltip'+o, v);
|
|
},
|
|
|
|
// Properties which require event reassignment
|
|
'^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)': function() {
|
|
if(!this.rendered) { return; }
|
|
|
|
// Set tracking flag
|
|
var posOptions = this.options.position;
|
|
this.tooltip.attr('tracking', posOptions.target === 'mouse' && posOptions.adjust.mouse);
|
|
|
|
// Reassign events
|
|
this._unassignEvents();
|
|
this._assignEvents();
|
|
}
|
|
}
|
|
};
|
|
|
|
// Dot notation converter
|
|
function convertNotation(options, notation) {
|
|
var i = 0, obj, option = options,
|
|
|
|
// Split notation into array
|
|
levels = notation.split('.');
|
|
|
|
// Loop through
|
|
while(option = option[ levels[i++] ]) {
|
|
if(i < levels.length) { obj = option; }
|
|
}
|
|
|
|
return [obj || options, levels.pop()];
|
|
}
|
|
|
|
PROTOTYPE.get = function(notation) {
|
|
if(this.destroyed) { return this; }
|
|
|
|
var o = convertNotation(this.options, notation.toLowerCase()),
|
|
result = o[0][ o[1] ];
|
|
|
|
return result.precedance ? result.string() : result;
|
|
};
|
|
|
|
function setCallback(notation, args) {
|
|
var category, rule, match;
|
|
|
|
for(category in this.checks) {
|
|
if (!this.checks.hasOwnProperty(category)) { continue; }
|
|
|
|
for(rule in this.checks[category]) {
|
|
if (!this.checks[category].hasOwnProperty(rule)) { continue; }
|
|
|
|
if(match = (new RegExp(rule, 'i')).exec(notation)) {
|
|
args.push(match);
|
|
|
|
if(category === 'builtin' || this.plugins[category]) {
|
|
this.checks[category][rule].apply(
|
|
this.plugins[category] || this, args
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var rmove = /^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i,
|
|
rrender = /^prerender|show\.ready/i;
|
|
|
|
PROTOTYPE.set = function(option, value) {
|
|
if(this.destroyed) { return this; }
|
|
|
|
var rendered = this.rendered,
|
|
reposition = FALSE,
|
|
options = this.options,
|
|
name;
|
|
|
|
// Convert singular option/value pair into object form
|
|
if('string' === typeof option) {
|
|
name = option; option = {}; option[name] = value;
|
|
}
|
|
else { option = $.extend({}, option); }
|
|
|
|
// Set all of the defined options to their new values
|
|
$.each(option, function(notation, val) {
|
|
if(rendered && rrender.test(notation)) {
|
|
delete option[notation]; return;
|
|
}
|
|
|
|
// Set new obj value
|
|
var obj = convertNotation(options, notation.toLowerCase()), previous;
|
|
previous = obj[0][ obj[1] ];
|
|
obj[0][ obj[1] ] = val && val.nodeType ? $(val) : val;
|
|
|
|
// Also check if we need to reposition
|
|
reposition = rmove.test(notation) || reposition;
|
|
|
|
// Set the new params for the callback
|
|
option[notation] = [obj[0], obj[1], val, previous];
|
|
});
|
|
|
|
// Re-sanitize options
|
|
sanitizeOptions(options);
|
|
|
|
/*
|
|
* Execute any valid callbacks for the set options
|
|
* Also set positioning flag so we don't get loads of redundant repositioning calls.
|
|
*/
|
|
this.positioning = TRUE;
|
|
$.each(option, $.proxy(setCallback, this));
|
|
this.positioning = FALSE;
|
|
|
|
// Update position if needed
|
|
if(this.rendered && this.tooltip[0].offsetWidth > 0 && reposition) {
|
|
this.reposition( options.position.target === 'mouse' ? NULL : this.cache.event );
|
|
}
|
|
|
|
return this;
|
|
};
|
|
;PROTOTYPE._update = function(content, element) {
|
|
var self = this,
|
|
cache = this.cache;
|
|
|
|
// Make sure tooltip is rendered and content is defined. If not return
|
|
if(!this.rendered || !content) { return FALSE; }
|
|
|
|
// Use function to parse content
|
|
if($.isFunction(content)) {
|
|
content = content.call(this.elements.target, cache.event, this) || '';
|
|
}
|
|
|
|
// Handle deferred content
|
|
if($.isFunction(content.then)) {
|
|
cache.waiting = TRUE;
|
|
return content.then(function(c) {
|
|
cache.waiting = FALSE;
|
|
return self._update(c, element);
|
|
}, NULL, function(e) {
|
|
return self._update(e, element);
|
|
});
|
|
}
|
|
|
|
// If content is null... return false
|
|
if(content === FALSE || !content && content !== '') { return FALSE; }
|
|
|
|
// Append new content if its a DOM array and show it if hidden
|
|
if(content.jquery && content.length > 0) {
|
|
element.empty().append(
|
|
content.css({ display: 'block', visibility: 'visible' })
|
|
);
|
|
}
|
|
|
|
// Content is a regular string, insert the new content
|
|
else { element.html(content); }
|
|
|
|
// Wait for content to be loaded, and reposition
|
|
return this._waitForContent(element).then(function(images) {
|
|
if(self.rendered && self.tooltip[0].offsetWidth > 0) {
|
|
self.reposition(cache.event, !images.length);
|
|
}
|
|
});
|
|
};
|
|
|
|
PROTOTYPE._waitForContent = function(element) {
|
|
var cache = this.cache;
|
|
|
|
// Set flag
|
|
cache.waiting = TRUE;
|
|
|
|
// If imagesLoaded is included, ensure images have loaded and return promise
|
|
return ( $.fn.imagesLoaded ? element.imagesLoaded() : new $.Deferred().resolve([]) )
|
|
.done(function() { cache.waiting = FALSE; })
|
|
.promise();
|
|
};
|
|
|
|
PROTOTYPE._updateContent = function(content, reposition) {
|
|
this._update(content, this.elements.content, reposition);
|
|
};
|
|
|
|
PROTOTYPE._updateTitle = function(content, reposition) {
|
|
if(this._update(content, this.elements.title, reposition) === FALSE) {
|
|
this._removeTitle(FALSE);
|
|
}
|
|
};
|
|
|
|
PROTOTYPE._createTitle = function()
|
|
{
|
|
var elements = this.elements,
|
|
id = this._id+'-title';
|
|
|
|
// Destroy previous title element, if present
|
|
if(elements.titlebar) { this._removeTitle(); }
|
|
|
|
// Create title bar and title elements
|
|
elements.titlebar = $('<div />', {
|
|
'class': NAMESPACE + '-titlebar ' + (this.options.style.widget ? createWidgetClass('header') : '')
|
|
})
|
|
.append(
|
|
elements.title = $('<div />', {
|
|
'id': id,
|
|
'class': NAMESPACE + '-title',
|
|
'aria-atomic': TRUE
|
|
})
|
|
)
|
|
.insertBefore(elements.content)
|
|
|
|
// Button-specific events
|
|
.delegate('.qtip-close', 'mousedown keydown mouseup keyup mouseout', function(event) {
|
|
$(this).toggleClass('ui-state-active ui-state-focus', event.type.substr(-4) === 'down');
|
|
})
|
|
.delegate('.qtip-close', 'mouseover mouseout', function(event){
|
|
$(this).toggleClass('ui-state-hover', event.type === 'mouseover');
|
|
});
|
|
|
|
// Create button if enabled
|
|
if(this.options.content.button) { this._createButton(); }
|
|
};
|
|
|
|
PROTOTYPE._removeTitle = function(reposition)
|
|
{
|
|
var elements = this.elements;
|
|
|
|
if(elements.title) {
|
|
elements.titlebar.remove();
|
|
elements.titlebar = elements.title = elements.button = NULL;
|
|
|
|
// Reposition if enabled
|
|
if(reposition !== FALSE) { this.reposition(); }
|
|
}
|
|
};
|
|
;PROTOTYPE._createPosClass = function(my) {
|
|
return NAMESPACE + '-pos-' + (my || this.options.position.my).abbrev();
|
|
};
|
|
|
|
PROTOTYPE.reposition = function(event, effect) {
|
|
if(!this.rendered || this.positioning || this.destroyed) { return this; }
|
|
|
|
// Set positioning flag
|
|
this.positioning = TRUE;
|
|
|
|
var cache = this.cache,
|
|
tooltip = this.tooltip,
|
|
posOptions = this.options.position,
|
|
target = posOptions.target,
|
|
my = posOptions.my,
|
|
at = posOptions.at,
|
|
viewport = posOptions.viewport,
|
|
container = posOptions.container,
|
|
adjust = posOptions.adjust,
|
|
method = adjust.method.split(' '),
|
|
tooltipWidth = tooltip.outerWidth(FALSE),
|
|
tooltipHeight = tooltip.outerHeight(FALSE),
|
|
targetWidth = 0,
|
|
targetHeight = 0,
|
|
type = tooltip.css('position'),
|
|
position = { left: 0, top: 0 },
|
|
visible = tooltip[0].offsetWidth > 0,
|
|
isScroll = event && event.type === 'scroll',
|
|
win = $(window),
|
|
doc = container[0].ownerDocument,
|
|
mouse = this.mouse,
|
|
pluginCalculations, offset, adjusted, newClass;
|
|
|
|
// Check if absolute position was passed
|
|
if($.isArray(target) && target.length === 2) {
|
|
// Force left top and set position
|
|
at = { x: LEFT, y: TOP };
|
|
position = { left: target[0], top: target[1] };
|
|
}
|
|
|
|
// Check if mouse was the target
|
|
else if(target === 'mouse') {
|
|
// Force left top to allow flipping
|
|
at = { x: LEFT, y: TOP };
|
|
|
|
// Use the mouse origin that caused the show event, if distance hiding is enabled
|
|
if((!adjust.mouse || this.options.hide.distance) && cache.origin && cache.origin.pageX) {
|
|
event = cache.origin;
|
|
}
|
|
|
|
// Use cached event for resize/scroll events
|
|
else if(!event || event && (event.type === 'resize' || event.type === 'scroll')) {
|
|
event = cache.event;
|
|
}
|
|
|
|
// Otherwise, use the cached mouse coordinates if available
|
|
else if(mouse && mouse.pageX) {
|
|
event = mouse;
|
|
}
|
|
|
|
// Calculate body and container offset and take them into account below
|
|
if(type !== 'static') { position = container.offset(); }
|
|
if(doc.body.offsetWidth !== (window.innerWidth || doc.documentElement.clientWidth)) {
|
|
offset = $(document.body).offset();
|
|
}
|
|
|
|
// Use event coordinates for position
|
|
position = {
|
|
left: event.pageX - position.left + (offset && offset.left || 0),
|
|
top: event.pageY - position.top + (offset && offset.top || 0)
|
|
};
|
|
|
|
// Scroll events are a pain, some browsers
|
|
if(adjust.mouse && isScroll && mouse) {
|
|
position.left -= (mouse.scrollX || 0) - win.scrollLeft();
|
|
position.top -= (mouse.scrollY || 0) - win.scrollTop();
|
|
}
|
|
}
|
|
|
|
// Target wasn't mouse or absolute...
|
|
else {
|
|
// Check if event targetting is being used
|
|
if(target === 'event') {
|
|
if(event && event.target && event.type !== 'scroll' && event.type !== 'resize') {
|
|
cache.target = $(event.target);
|
|
}
|
|
else if(!event.target) {
|
|
cache.target = this.elements.target;
|
|
}
|
|
}
|
|
else if(target !== 'event'){
|
|
cache.target = $(target.jquery ? target : this.elements.target);
|
|
}
|
|
target = cache.target;
|
|
|
|
// Parse the target into a jQuery object and make sure there's an element present
|
|
target = $(target).eq(0);
|
|
if(target.length === 0) { return this; }
|
|
|
|
// Check if window or document is the target
|
|
else if(target[0] === document || target[0] === window) {
|
|
targetWidth = BROWSER.iOS ? window.innerWidth : target.width();
|
|
targetHeight = BROWSER.iOS ? window.innerHeight : target.height();
|
|
|
|
if(target[0] === window) {
|
|
position = {
|
|
top: (viewport || target).scrollTop(),
|
|
left: (viewport || target).scrollLeft()
|
|
};
|
|
}
|
|
}
|
|
|
|
// Check if the target is an <AREA> element
|
|
else if(PLUGINS.imagemap && target.is('area')) {
|
|
pluginCalculations = PLUGINS.imagemap(this, target, at, PLUGINS.viewport ? method : FALSE);
|
|
}
|
|
|
|
// Check if the target is an SVG element
|
|
else if(PLUGINS.svg && target && target[0].ownerSVGElement) {
|
|
pluginCalculations = PLUGINS.svg(this, target, at, PLUGINS.viewport ? method : FALSE);
|
|
}
|
|
|
|
// Otherwise use regular jQuery methods
|
|
else {
|
|
targetWidth = target.outerWidth(FALSE);
|
|
targetHeight = target.outerHeight(FALSE);
|
|
position = target.offset();
|
|
}
|
|
|
|
// Parse returned plugin values into proper variables
|
|
if(pluginCalculations) {
|
|
targetWidth = pluginCalculations.width;
|
|
targetHeight = pluginCalculations.height;
|
|
offset = pluginCalculations.offset;
|
|
position = pluginCalculations.position;
|
|
}
|
|
|
|
// Adjust position to take into account offset parents
|
|
position = this.reposition.offset(target, position, container);
|
|
|
|
// Adjust for position.fixed tooltips (and also iOS scroll bug in v3.2-4.0 & v4.3-4.3.2)
|
|
if(BROWSER.iOS > 3.1 && BROWSER.iOS < 4.1 ||
|
|
BROWSER.iOS >= 4.3 && BROWSER.iOS < 4.33 ||
|
|
!BROWSER.iOS && type === 'fixed'
|
|
){
|
|
position.left -= win.scrollLeft();
|
|
position.top -= win.scrollTop();
|
|
}
|
|
|
|
// Adjust position relative to target
|
|
if(!pluginCalculations || pluginCalculations && pluginCalculations.adjustable !== FALSE) {
|
|
position.left += at.x === RIGHT ? targetWidth : at.x === CENTER ? targetWidth / 2 : 0;
|
|
position.top += at.y === BOTTOM ? targetHeight : at.y === CENTER ? targetHeight / 2 : 0;
|
|
}
|
|
}
|
|
|
|
// Adjust position relative to tooltip
|
|
position.left += adjust.x + (my.x === RIGHT ? -tooltipWidth : my.x === CENTER ? -tooltipWidth / 2 : 0);
|
|
position.top += adjust.y + (my.y === BOTTOM ? -tooltipHeight : my.y === CENTER ? -tooltipHeight / 2 : 0);
|
|
|
|
// Use viewport adjustment plugin if enabled
|
|
if(PLUGINS.viewport) {
|
|
adjusted = position.adjusted = PLUGINS.viewport(
|
|
this, position, posOptions, targetWidth, targetHeight, tooltipWidth, tooltipHeight
|
|
);
|
|
|
|
// Apply offsets supplied by positioning plugin (if used)
|
|
if(offset && adjusted.left) { position.left += offset.left; }
|
|
if(offset && adjusted.top) { position.top += offset.top; }
|
|
|
|
// Apply any new 'my' position
|
|
if(adjusted.my) { this.position.my = adjusted.my; }
|
|
}
|
|
|
|
// Viewport adjustment is disabled, set values to zero
|
|
else { position.adjusted = { left: 0, top: 0 }; }
|
|
|
|
// Set tooltip position class if it's changed
|
|
if(cache.posClass !== (newClass = this._createPosClass(this.position.my))) {
|
|
cache.posClass = newClass;
|
|
tooltip.removeClass(cache.posClass).addClass(newClass);
|
|
}
|
|
|
|
// tooltipmove event
|
|
if(!this._trigger('move', [position, viewport.elem || viewport], event)) { return this; }
|
|
delete position.adjusted;
|
|
|
|
// If effect is disabled, target it mouse, no animation is defined or positioning gives NaN out, set CSS directly
|
|
if(effect === FALSE || !visible || isNaN(position.left) || isNaN(position.top) || target === 'mouse' || !$.isFunction(posOptions.effect)) {
|
|
tooltip.css(position);
|
|
}
|
|
|
|
// Use custom function if provided
|
|
else if($.isFunction(posOptions.effect)) {
|
|
posOptions.effect.call(tooltip, this, $.extend({}, position));
|
|
tooltip.queue(function(next) {
|
|
// Reset attributes to avoid cross-browser rendering bugs
|
|
$(this).css({ opacity: '', height: '' });
|
|
if(BROWSER.ie) { this.style.removeAttribute('filter'); }
|
|
|
|
next();
|
|
});
|
|
}
|
|
|
|
// Set positioning flag
|
|
this.positioning = FALSE;
|
|
|
|
return this;
|
|
};
|
|
|
|
// Custom (more correct for qTip!) offset calculator
|
|
PROTOTYPE.reposition.offset = function(elem, pos, container) {
|
|
if(!container[0]) { return pos; }
|
|
|
|
var ownerDocument = $(elem[0].ownerDocument),
|
|
quirks = !!BROWSER.ie && document.compatMode !== 'CSS1Compat',
|
|
parent = container[0],
|
|
scrolled, position, parentOffset, overflow;
|
|
|
|
function scroll(e, i) {
|
|
pos.left += i * e.scrollLeft();
|
|
pos.top += i * e.scrollTop();
|
|
}
|
|
|
|
// Compensate for non-static containers offset
|
|
do {
|
|
if((position = $.css(parent, 'position')) !== 'static') {
|
|
if(position === 'fixed') {
|
|
parentOffset = parent.getBoundingClientRect();
|
|
scroll(ownerDocument, -1);
|
|
}
|
|
else {
|
|
parentOffset = $(parent).position();
|
|
parentOffset.left += parseFloat($.css(parent, 'borderLeftWidth')) || 0;
|
|
parentOffset.top += parseFloat($.css(parent, 'borderTopWidth')) || 0;
|
|
}
|
|
|
|
pos.left -= parentOffset.left + (parseFloat($.css(parent, 'marginLeft')) || 0);
|
|
pos.top -= parentOffset.top + (parseFloat($.css(parent, 'marginTop')) || 0);
|
|
|
|
// If this is the first parent element with an overflow of "scroll" or "auto", store it
|
|
if(!scrolled && (overflow = $.css(parent, 'overflow')) !== 'hidden' && overflow !== 'visible') { scrolled = $(parent); }
|
|
}
|
|
}
|
|
while(parent = parent.offsetParent);
|
|
|
|
// Compensate for containers scroll if it also has an offsetParent (or in IE quirks mode)
|
|
if(scrolled && (scrolled[0] !== ownerDocument[0] || quirks)) {
|
|
scroll(scrolled, 1);
|
|
}
|
|
|
|
return pos;
|
|
};
|
|
|
|
// Corner class
|
|
var C = (CORNER = PROTOTYPE.reposition.Corner = function(corner, forceY) {
|
|
corner = ('' + corner).replace(/([A-Z])/, ' $1').replace(/middle/gi, CENTER).toLowerCase();
|
|
this.x = (corner.match(/left|right/i) || corner.match(/center/) || ['inherit'])[0].toLowerCase();
|
|
this.y = (corner.match(/top|bottom|center/i) || ['inherit'])[0].toLowerCase();
|
|
this.forceY = !!forceY;
|
|
|
|
var f = corner.charAt(0);
|
|
this.precedance = f === 't' || f === 'b' ? Y : X;
|
|
}).prototype;
|
|
|
|
C.invert = function(z, center) {
|
|
this[z] = this[z] === LEFT ? RIGHT : this[z] === RIGHT ? LEFT : center || this[z];
|
|
};
|
|
|
|
C.string = function(join) {
|
|
var x = this.x, y = this.y;
|
|
|
|
var result = x !== y ?
|
|
x === 'center' || y !== 'center' && (this.precedance === Y || this.forceY) ?
|
|
[y,x] :
|
|
[x,y] :
|
|
[x];
|
|
|
|
return join !== false ? result.join(' ') : result;
|
|
};
|
|
|
|
C.abbrev = function() {
|
|
var result = this.string(false);
|
|
return result[0].charAt(0) + (result[1] && result[1].charAt(0) || '');
|
|
};
|
|
|
|
C.clone = function() {
|
|
return new CORNER( this.string(), this.forceY );
|
|
};
|
|
|
|
;
|
|
PROTOTYPE.toggle = function(state, event) {
|
|
var cache = this.cache,
|
|
options = this.options,
|
|
tooltip = this.tooltip;
|
|
|
|
// Try to prevent flickering when tooltip overlaps show element
|
|
if(event) {
|
|
if((/over|enter/).test(event.type) && cache.event && (/out|leave/).test(cache.event.type) &&
|
|
options.show.target.add(event.target).length === options.show.target.length &&
|
|
tooltip.has(event.relatedTarget).length) {
|
|
return this;
|
|
}
|
|
|
|
// Cache event
|
|
cache.event = $.event.fix(event);
|
|
}
|
|
|
|
// If we're currently waiting and we've just hidden... stop it
|
|
this.waiting && !state && (this.hiddenDuringWait = TRUE);
|
|
|
|
// Render the tooltip if showing and it isn't already
|
|
if(!this.rendered) { return state ? this.render(1) : this; }
|
|
else if(this.destroyed || this.disabled) { return this; }
|
|
|
|
var type = state ? 'show' : 'hide',
|
|
opts = this.options[type],
|
|
posOptions = this.options.position,
|
|
contentOptions = this.options.content,
|
|
width = this.tooltip.css('width'),
|
|
visible = this.tooltip.is(':visible'),
|
|
animate = state || opts.target.length === 1,
|
|
sameTarget = !event || opts.target.length < 2 || cache.target[0] === event.target,
|
|
identicalState, allow, after;
|
|
|
|
// Detect state if valid one isn't provided
|
|
if((typeof state).search('boolean|number')) { state = !visible; }
|
|
|
|
// Check if the tooltip is in an identical state to the new would-be state
|
|
identicalState = !tooltip.is(':animated') && visible === state && sameTarget;
|
|
|
|
// Fire tooltip(show/hide) event and check if destroyed
|
|
allow = !identicalState ? !!this._trigger(type, [90]) : NULL;
|
|
|
|
// Check to make sure the tooltip wasn't destroyed in the callback
|
|
if(this.destroyed) { return this; }
|
|
|
|
// If the user didn't stop the method prematurely and we're showing the tooltip, focus it
|
|
if(allow !== FALSE && state) { this.focus(event); }
|
|
|
|
// If the state hasn't changed or the user stopped it, return early
|
|
if(!allow || identicalState) { return this; }
|
|
|
|
// Set ARIA hidden attribute
|
|
$.attr(tooltip[0], 'aria-hidden', !!!state);
|
|
|
|
// Execute state specific properties
|
|
if(state) {
|
|
// Store show origin coordinates
|
|
this.mouse && (cache.origin = $.event.fix(this.mouse));
|
|
|
|
// Update tooltip content & title if it's a dynamic function
|
|
if($.isFunction(contentOptions.text)) { this._updateContent(contentOptions.text, FALSE); }
|
|
if($.isFunction(contentOptions.title)) { this._updateTitle(contentOptions.title, FALSE); }
|
|
|
|
// Cache mousemove events for positioning purposes (if not already tracking)
|
|
if(!trackingBound && posOptions.target === 'mouse' && posOptions.adjust.mouse) {
|
|
$(document).bind('mousemove.'+NAMESPACE, this._storeMouse);
|
|
trackingBound = TRUE;
|
|
}
|
|
|
|
// Update the tooltip position (set width first to prevent viewport/max-width issues)
|
|
if(!width) { tooltip.css('width', tooltip.outerWidth(FALSE)); }
|
|
this.reposition(event, arguments[2]);
|
|
if(!width) { tooltip.css('width', ''); }
|
|
|
|
// Hide other tooltips if tooltip is solo
|
|
if(!!opts.solo) {
|
|
(typeof opts.solo === 'string' ? $(opts.solo) : $(SELECTOR, opts.solo))
|
|
.not(tooltip).not(opts.target).qtip('hide', new $.Event('tooltipsolo'));
|
|
}
|
|
}
|
|
else {
|
|
// Clear show timer if we're hiding
|
|
clearTimeout(this.timers.show);
|
|
|
|
// Remove cached origin on hide
|
|
delete cache.origin;
|
|
|
|
// Remove mouse tracking event if not needed (all tracking qTips are hidden)
|
|
if(trackingBound && !$(SELECTOR+'[tracking="true"]:visible', opts.solo).not(tooltip).length) {
|
|
$(document).unbind('mousemove.'+NAMESPACE);
|
|
trackingBound = FALSE;
|
|
}
|
|
|
|
// Blur the tooltip
|
|
this.blur(event);
|
|
}
|
|
|
|
// Define post-animation, state specific properties
|
|
after = $.proxy(function() {
|
|
if(state) {
|
|
// Prevent antialias from disappearing in IE by removing filter
|
|
if(BROWSER.ie) { tooltip[0].style.removeAttribute('filter'); }
|
|
|
|
// Remove overflow setting to prevent tip bugs
|
|
tooltip.css('overflow', '');
|
|
|
|
// Autofocus elements if enabled
|
|
if('string' === typeof opts.autofocus) {
|
|
$(this.options.show.autofocus, tooltip).focus();
|
|
}
|
|
|
|
// If set, hide tooltip when inactive for delay period
|
|
this.options.show.target.trigger('qtip-'+this.id+'-inactive');
|
|
}
|
|
else {
|
|
// Reset CSS states
|
|
tooltip.css({
|
|
display: '',
|
|
visibility: '',
|
|
opacity: '',
|
|
left: '',
|
|
top: ''
|
|
});
|
|
}
|
|
|
|
// tooltipvisible/tooltiphidden events
|
|
this._trigger(state ? 'visible' : 'hidden');
|
|
}, this);
|
|
|
|
// If no effect type is supplied, use a simple toggle
|
|
if(opts.effect === FALSE || animate === FALSE) {
|
|
tooltip[ type ]();
|
|
after();
|
|
}
|
|
|
|
// Use custom function if provided
|
|
else if($.isFunction(opts.effect)) {
|
|
tooltip.stop(1, 1);
|
|
opts.effect.call(tooltip, this);
|
|
tooltip.queue('fx', function(n) {
|
|
after(); n();
|
|
});
|
|
}
|
|
|
|
// Use basic fade function by default
|
|
else { tooltip.fadeTo(90, state ? 1 : 0, after); }
|
|
|
|
// If inactive hide method is set, active it
|
|
if(state) { opts.target.trigger('qtip-'+this.id+'-inactive'); }
|
|
|
|
return this;
|
|
};
|
|
|
|
PROTOTYPE.show = function(event) { return this.toggle(TRUE, event); };
|
|
|
|
PROTOTYPE.hide = function(event) { return this.toggle(FALSE, event); };
|
|
;PROTOTYPE.focus = function(event) {
|
|
if(!this.rendered || this.destroyed) { return this; }
|
|
|
|
var qtips = $(SELECTOR),
|
|
tooltip = this.tooltip,
|
|
curIndex = parseInt(tooltip[0].style.zIndex, 10),
|
|
newIndex = QTIP.zindex + qtips.length;
|
|
|
|
// Only update the z-index if it has changed and tooltip is not already focused
|
|
if(!tooltip.hasClass(CLASS_FOCUS)) {
|
|
// tooltipfocus event
|
|
if(this._trigger('focus', [newIndex], event)) {
|
|
// Only update z-index's if they've changed
|
|
if(curIndex !== newIndex) {
|
|
// Reduce our z-index's and keep them properly ordered
|
|
qtips.each(function() {
|
|
if(this.style.zIndex > curIndex) {
|
|
this.style.zIndex = this.style.zIndex - 1;
|
|
}
|
|
});
|
|
|
|
// Fire blur event for focused tooltip
|
|
qtips.filter('.' + CLASS_FOCUS).qtip('blur', event);
|
|
}
|
|
|
|
// Set the new z-index
|
|
tooltip.addClass(CLASS_FOCUS)[0].style.zIndex = newIndex;
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
PROTOTYPE.blur = function(event) {
|
|
if(!this.rendered || this.destroyed) { return this; }
|
|
|
|
// Set focused status to FALSE
|
|
this.tooltip.removeClass(CLASS_FOCUS);
|
|
|
|
// tooltipblur event
|
|
this._trigger('blur', [ this.tooltip.css('zIndex') ], event);
|
|
|
|
return this;
|
|
};
|
|
;PROTOTYPE.disable = function(state) {
|
|
if(this.destroyed) { return this; }
|
|
|
|
// If 'toggle' is passed, toggle the current state
|
|
if(state === 'toggle') {
|
|
state = !(this.rendered ? this.tooltip.hasClass(CLASS_DISABLED) : this.disabled);
|
|
}
|
|
|
|
// Disable if no state passed
|
|
else if('boolean' !== typeof state) {
|
|
state = TRUE;
|
|
}
|
|
|
|
if(this.rendered) {
|
|
this.tooltip.toggleClass(CLASS_DISABLED, state)
|
|
.attr('aria-disabled', state);
|
|
}
|
|
|
|
this.disabled = !!state;
|
|
|
|
return this;
|
|
};
|
|
|
|
PROTOTYPE.enable = function() { return this.disable(FALSE); };
|
|
;PROTOTYPE._createButton = function()
|
|
{
|
|
var self = this,
|
|
elements = this.elements,
|
|
tooltip = elements.tooltip,
|
|
button = this.options.content.button,
|
|
isString = typeof button === 'string',
|
|
close = isString ? button : 'Close tooltip';
|
|
|
|
if(elements.button) { elements.button.remove(); }
|
|
|
|
// Use custom button if one was supplied by user, else use default
|
|
if(button.jquery) {
|
|
elements.button = button;
|
|
}
|
|
else {
|
|
elements.button = $('<a />', {
|
|
'class': 'qtip-close ' + (this.options.style.widget ? '' : NAMESPACE+'-icon'),
|
|
'title': close,
|
|
'aria-label': close
|
|
})
|
|
.prepend(
|
|
$('<span />', {
|
|
'class': 'ui-icon ui-icon-close',
|
|
'html': '×'
|
|
})
|
|
);
|
|
}
|
|
|
|
// Create button and setup attributes
|
|
elements.button.appendTo(elements.titlebar || tooltip)
|
|
.attr('role', 'button')
|
|
.click(function(event) {
|
|
if(!tooltip.hasClass(CLASS_DISABLED)) { self.hide(event); }
|
|
return FALSE;
|
|
});
|
|
};
|
|
|
|
PROTOTYPE._updateButton = function(button)
|
|
{
|
|
// Make sure tooltip is rendered and if not, return
|
|
if(!this.rendered) { return FALSE; }
|
|
|
|
var elem = this.elements.button;
|
|
if(button) { this._createButton(); }
|
|
else { elem.remove(); }
|
|
};
|
|
;// Widget class creator
|
|
function createWidgetClass(cls) {
|
|
return WIDGET.concat('').join(cls ? '-'+cls+' ' : ' ');
|
|
}
|
|
|
|
// Widget class setter method
|
|
PROTOTYPE._setWidget = function()
|
|
{
|
|
var on = this.options.style.widget,
|
|
elements = this.elements,
|
|
tooltip = elements.tooltip,
|
|
disabled = tooltip.hasClass(CLASS_DISABLED);
|
|
|
|
tooltip.removeClass(CLASS_DISABLED);
|
|
CLASS_DISABLED = on ? 'ui-state-disabled' : 'qtip-disabled';
|
|
tooltip.toggleClass(CLASS_DISABLED, disabled);
|
|
|
|
tooltip.toggleClass('ui-helper-reset '+createWidgetClass(), on).toggleClass(CLASS_DEFAULT, this.options.style.def && !on);
|
|
|
|
if(elements.content) {
|
|
elements.content.toggleClass( createWidgetClass('content'), on);
|
|
}
|
|
if(elements.titlebar) {
|
|
elements.titlebar.toggleClass( createWidgetClass('header'), on);
|
|
}
|
|
if(elements.button) {
|
|
elements.button.toggleClass(NAMESPACE+'-icon', !on);
|
|
}
|
|
};
|
|
;function delay(callback, duration) {
|
|
// If tooltip has displayed, start hide timer
|
|
if(duration > 0) {
|
|
return setTimeout(
|
|
$.proxy(callback, this), duration
|
|
);
|
|
}
|
|
else{ callback.call(this); }
|
|
}
|
|
|
|
function showMethod(event) {
|
|
if(this.tooltip.hasClass(CLASS_DISABLED)) { return; }
|
|
|
|
// Clear hide timers
|
|
clearTimeout(this.timers.show);
|
|
clearTimeout(this.timers.hide);
|
|
|
|
// Start show timer
|
|
this.timers.show = delay.call(this,
|
|
function() { this.toggle(TRUE, event); },
|
|
this.options.show.delay
|
|
);
|
|
}
|
|
|
|
function hideMethod(event) {
|
|
if(this.tooltip.hasClass(CLASS_DISABLED) || this.destroyed) { return; }
|
|
|
|
// Check if new target was actually the tooltip element
|
|
var relatedTarget = $(event.relatedTarget),
|
|
ontoTooltip = relatedTarget.closest(SELECTOR)[0] === this.tooltip[0],
|
|
ontoTarget = relatedTarget[0] === this.options.show.target[0];
|
|
|
|
// Clear timers and stop animation queue
|
|
clearTimeout(this.timers.show);
|
|
clearTimeout(this.timers.hide);
|
|
|
|
// Prevent hiding if tooltip is fixed and event target is the tooltip.
|
|
// Or if mouse positioning is enabled and cursor momentarily overlaps
|
|
if(this !== relatedTarget[0] &&
|
|
(this.options.position.target === 'mouse' && ontoTooltip) ||
|
|
this.options.hide.fixed && (
|
|
(/mouse(out|leave|move)/).test(event.type) && (ontoTooltip || ontoTarget))
|
|
)
|
|
{
|
|
/* eslint-disable no-empty */
|
|
try {
|
|
event.preventDefault();
|
|
event.stopImmediatePropagation();
|
|
} catch(e) {}
|
|
/* eslint-enable no-empty */
|
|
|
|
return;
|
|
}
|
|
|
|
// If tooltip has displayed, start hide timer
|
|
this.timers.hide = delay.call(this,
|
|
function() { this.toggle(FALSE, event); },
|
|
this.options.hide.delay,
|
|
this
|
|
);
|
|
}
|
|
|
|
function inactiveMethod(event) {
|
|
if(this.tooltip.hasClass(CLASS_DISABLED) || !this.options.hide.inactive) { return; }
|
|
|
|
// Clear timer
|
|
clearTimeout(this.timers.inactive);
|
|
|
|
this.timers.inactive = delay.call(this,
|
|
function(){ this.hide(event); },
|
|
this.options.hide.inactive
|
|
);
|
|
}
|
|
|
|
function repositionMethod(event) {
|
|
if(this.rendered && this.tooltip[0].offsetWidth > 0) { this.reposition(event); }
|
|
}
|
|
|
|
// Store mouse coordinates
|
|
PROTOTYPE._storeMouse = function(event) {
|
|
(this.mouse = $.event.fix(event)).type = 'mousemove';
|
|
return this;
|
|
};
|
|
|
|
// Bind events
|
|
PROTOTYPE._bind = function(targets, events, method, suffix, context) {
|
|
if(!targets || !method || !events.length) { return; }
|
|
var ns = '.' + this._id + (suffix ? '-'+suffix : '');
|
|
$(targets).bind(
|
|
(events.split ? events : events.join(ns + ' ')) + ns,
|
|
$.proxy(method, context || this)
|
|
);
|
|
return this;
|
|
};
|
|
PROTOTYPE._unbind = function(targets, suffix) {
|
|
targets && $(targets).unbind('.' + this._id + (suffix ? '-'+suffix : ''));
|
|
return this;
|
|
};
|
|
|
|
// Global delegation helper
|
|
function delegate(selector, events, method) {
|
|
$(document.body).delegate(selector,
|
|
(events.split ? events : events.join('.'+NAMESPACE + ' ')) + '.'+NAMESPACE,
|
|
function() {
|
|
var api = QTIP.api[ $.attr(this, ATTR_ID) ];
|
|
api && !api.disabled && method.apply(api, arguments);
|
|
}
|
|
);
|
|
}
|
|
// Event trigger
|
|
PROTOTYPE._trigger = function(type, args, event) {
|
|
var callback = new $.Event('tooltip'+type);
|
|
callback.originalEvent = event && $.extend({}, event) || this.cache.event || NULL;
|
|
|
|
this.triggering = type;
|
|
this.tooltip.trigger(callback, [this].concat(args || []));
|
|
this.triggering = FALSE;
|
|
|
|
return !callback.isDefaultPrevented();
|
|
};
|
|
|
|
PROTOTYPE._bindEvents = function(showEvents, hideEvents, showTargets, hideTargets, showCallback, hideCallback) {
|
|
// Get tasrgets that lye within both
|
|
var similarTargets = showTargets.filter( hideTargets ).add( hideTargets.filter(showTargets) ),
|
|
toggleEvents = [];
|
|
|
|
// If hide and show targets are the same...
|
|
if(similarTargets.length) {
|
|
|
|
// Filter identical show/hide events
|
|
$.each(hideEvents, function(i, type) {
|
|
var showIndex = $.inArray(type, showEvents);
|
|
|
|
// Both events are identical, remove from both hide and show events
|
|
// and append to toggleEvents
|
|
showIndex > -1 && toggleEvents.push( showEvents.splice( showIndex, 1 )[0] );
|
|
});
|
|
|
|
// Toggle events are special case of identical show/hide events, which happen in sequence
|
|
if(toggleEvents.length) {
|
|
// Bind toggle events to the similar targets
|
|
this._bind(similarTargets, toggleEvents, function(event) {
|
|
var state = this.rendered ? this.tooltip[0].offsetWidth > 0 : false;
|
|
(state ? hideCallback : showCallback).call(this, event);
|
|
});
|
|
|
|
// Remove the similar targets from the regular show/hide bindings
|
|
showTargets = showTargets.not(similarTargets);
|
|
hideTargets = hideTargets.not(similarTargets);
|
|
}
|
|
}
|
|
|
|
// Apply show/hide/toggle events
|
|
this._bind(showTargets, showEvents, showCallback);
|
|
this._bind(hideTargets, hideEvents, hideCallback);
|
|
};
|
|
|
|
PROTOTYPE._assignInitialEvents = function(event) {
|
|
var options = this.options,
|
|
showTarget = options.show.target,
|
|
hideTarget = options.hide.target,
|
|
showEvents = options.show.event ? $.trim('' + options.show.event).split(' ') : [],
|
|
hideEvents = options.hide.event ? $.trim('' + options.hide.event).split(' ') : [];
|
|
|
|
// Catch remove/removeqtip events on target element to destroy redundant tooltips
|
|
this._bind(this.elements.target, ['remove', 'removeqtip'], function() {
|
|
this.destroy(true);
|
|
}, 'destroy');
|
|
|
|
/*
|
|
* Make sure hoverIntent functions properly by using mouseleave as a hide event if
|
|
* mouseenter/mouseout is used for show.event, even if it isn't in the users options.
|
|
*/
|
|
if(/mouse(over|enter)/i.test(options.show.event) && !/mouse(out|leave)/i.test(options.hide.event)) {
|
|
hideEvents.push('mouseleave');
|
|
}
|
|
|
|
/*
|
|
* Also make sure initial mouse targetting works correctly by caching mousemove coords
|
|
* on show targets before the tooltip has rendered. Also set onTarget when triggered to
|
|
* keep mouse tracking working.
|
|
*/
|
|
this._bind(showTarget, 'mousemove', function(moveEvent) {
|
|
this._storeMouse(moveEvent);
|
|
this.cache.onTarget = TRUE;
|
|
});
|
|
|
|
// Define hoverIntent function
|
|
function hoverIntent(hoverEvent) {
|
|
// Only continue if tooltip isn't disabled
|
|
if(this.disabled || this.destroyed) { return FALSE; }
|
|
|
|
// Cache the event data
|
|
this.cache.event = hoverEvent && $.event.fix(hoverEvent);
|
|
this.cache.target = hoverEvent && $(hoverEvent.target);
|
|
|
|
// Start the event sequence
|
|
clearTimeout(this.timers.show);
|
|
this.timers.show = delay.call(this,
|
|
function() { this.render(typeof hoverEvent === 'object' || options.show.ready); },
|
|
options.prerender ? 0 : options.show.delay
|
|
);
|
|
}
|
|
|
|
// Filter and bind events
|
|
this._bindEvents(showEvents, hideEvents, showTarget, hideTarget, hoverIntent, function() {
|
|
if(!this.timers) { return FALSE; }
|
|
clearTimeout(this.timers.show);
|
|
});
|
|
|
|
// Prerendering is enabled, create tooltip now
|
|
if(options.show.ready || options.prerender) { hoverIntent.call(this, event); }
|
|
};
|
|
|
|
// Event assignment method
|
|
PROTOTYPE._assignEvents = function() {
|
|
var self = this,
|
|
options = this.options,
|
|
posOptions = options.position,
|
|
|
|
tooltip = this.tooltip,
|
|
showTarget = options.show.target,
|
|
hideTarget = options.hide.target,
|
|
containerTarget = posOptions.container,
|
|
viewportTarget = posOptions.viewport,
|
|
documentTarget = $(document),
|
|
windowTarget = $(window),
|
|
|
|
showEvents = options.show.event ? $.trim('' + options.show.event).split(' ') : [],
|
|
hideEvents = options.hide.event ? $.trim('' + options.hide.event).split(' ') : [];
|
|
|
|
|
|
// Assign passed event callbacks
|
|
$.each(options.events, function(name, callback) {
|
|
self._bind(tooltip, name === 'toggle' ? ['tooltipshow','tooltiphide'] : ['tooltip'+name], callback, null, tooltip);
|
|
});
|
|
|
|
// Hide tooltips when leaving current window/frame (but not select/option elements)
|
|
if(/mouse(out|leave)/i.test(options.hide.event) && options.hide.leave === 'window') {
|
|
this._bind(documentTarget, ['mouseout', 'blur'], function(event) {
|
|
if(!/select|option/.test(event.target.nodeName) && !event.relatedTarget) {
|
|
this.hide(event);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Enable hide.fixed by adding appropriate class
|
|
if(options.hide.fixed) {
|
|
hideTarget = hideTarget.add( tooltip.addClass(CLASS_FIXED) );
|
|
}
|
|
|
|
/*
|
|
* Make sure hoverIntent functions properly by using mouseleave to clear show timer if
|
|
* mouseenter/mouseout is used for show.event, even if it isn't in the users options.
|
|
*/
|
|
else if(/mouse(over|enter)/i.test(options.show.event)) {
|
|
this._bind(hideTarget, 'mouseleave', function() {
|
|
clearTimeout(this.timers.show);
|
|
});
|
|
}
|
|
|
|
// Hide tooltip on document mousedown if unfocus events are enabled
|
|
if(('' + options.hide.event).indexOf('unfocus') > -1) {
|
|
this._bind(containerTarget.closest('html'), ['mousedown', 'touchstart'], function(event) {
|
|
var elem = $(event.target),
|
|
enabled = this.rendered && !this.tooltip.hasClass(CLASS_DISABLED) && this.tooltip[0].offsetWidth > 0,
|
|
isAncestor = elem.parents(SELECTOR).filter(this.tooltip[0]).length > 0;
|
|
|
|
if(elem[0] !== this.target[0] && elem[0] !== this.tooltip[0] && !isAncestor &&
|
|
!this.target.has(elem[0]).length && enabled
|
|
) {
|
|
this.hide(event);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Check if the tooltip hides when inactive
|
|
if('number' === typeof options.hide.inactive) {
|
|
// Bind inactive method to show target(s) as a custom event
|
|
this._bind(showTarget, 'qtip-'+this.id+'-inactive', inactiveMethod, 'inactive');
|
|
|
|
// Define events which reset the 'inactive' event handler
|
|
this._bind(hideTarget.add(tooltip), QTIP.inactiveEvents, inactiveMethod);
|
|
}
|
|
|
|
// Filter and bind events
|
|
this._bindEvents(showEvents, hideEvents, showTarget, hideTarget, showMethod, hideMethod);
|
|
|
|
// Mouse movement bindings
|
|
this._bind(showTarget.add(tooltip), 'mousemove', function(event) {
|
|
// Check if the tooltip hides when mouse is moved a certain distance
|
|
if('number' === typeof options.hide.distance) {
|
|
var origin = this.cache.origin || {},
|
|
limit = this.options.hide.distance,
|
|
abs = Math.abs;
|
|
|
|
// Check if the movement has gone beyond the limit, and hide it if so
|
|
if(abs(event.pageX - origin.pageX) >= limit || abs(event.pageY - origin.pageY) >= limit) {
|
|
this.hide(event);
|
|
}
|
|
}
|
|
|
|
// Cache mousemove coords on show targets
|
|
this._storeMouse(event);
|
|
});
|
|
|
|
// Mouse positioning events
|
|
if(posOptions.target === 'mouse') {
|
|
// If mouse adjustment is on...
|
|
if(posOptions.adjust.mouse) {
|
|
// Apply a mouseleave event so we don't get problems with overlapping
|
|
if(options.hide.event) {
|
|
// Track if we're on the target or not
|
|
this._bind(showTarget, ['mouseenter', 'mouseleave'], function(event) {
|
|
if(!this.cache) {return FALSE; }
|
|
this.cache.onTarget = event.type === 'mouseenter';
|
|
});
|
|
}
|
|
|
|
// Update tooltip position on mousemove
|
|
this._bind(documentTarget, 'mousemove', function(event) {
|
|
// Update the tooltip position only if the tooltip is visible and adjustment is enabled
|
|
if(this.rendered && this.cache.onTarget && !this.tooltip.hasClass(CLASS_DISABLED) && this.tooltip[0].offsetWidth > 0) {
|
|
this.reposition(event);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Adjust positions of the tooltip on window resize if enabled
|
|
if(posOptions.adjust.resize || viewportTarget.length) {
|
|
this._bind( $.event.special.resize ? viewportTarget : windowTarget, 'resize', repositionMethod );
|
|
}
|
|
|
|
// Adjust tooltip position on scroll of the window or viewport element if present
|
|
if(posOptions.adjust.scroll) {
|
|
this._bind( windowTarget.add(posOptions.container), 'scroll', repositionMethod );
|
|
}
|
|
};
|
|
|
|
// Un-assignment method
|
|
PROTOTYPE._unassignEvents = function() {
|
|
var options = this.options,
|
|
showTargets = options.show.target,
|
|
hideTargets = options.hide.target,
|
|
targets = $.grep([
|
|
this.elements.target[0],
|
|
this.rendered && this.tooltip[0],
|
|
options.position.container[0],
|
|
options.position.viewport[0],
|
|
options.position.container.closest('html')[0], // unfocus
|
|
window,
|
|
document
|
|
], function(i) {
|
|
return typeof i === 'object';
|
|
});
|
|
|
|
// Add show and hide targets if they're valid
|
|
if(showTargets && showTargets.toArray) {
|
|
targets = targets.concat(showTargets.toArray());
|
|
}
|
|
if(hideTargets && hideTargets.toArray) {
|
|
targets = targets.concat(hideTargets.toArray());
|
|
}
|
|
|
|
// Unbind the events
|
|
this._unbind(targets)
|
|
._unbind(targets, 'destroy')
|
|
._unbind(targets, 'inactive');
|
|
};
|
|
|
|
// Apply common event handlers using delegate (avoids excessive .bind calls!)
|
|
$(function() {
|
|
delegate(SELECTOR, ['mouseenter', 'mouseleave'], function(event) {
|
|
var state = event.type === 'mouseenter',
|
|
tooltip = $(event.currentTarget),
|
|
target = $(event.relatedTarget || event.target),
|
|
options = this.options;
|
|
|
|
// On mouseenter...
|
|
if(state) {
|
|
// Focus the tooltip on mouseenter (z-index stacking)
|
|
this.focus(event);
|
|
|
|
// Clear hide timer on tooltip hover to prevent it from closing
|
|
tooltip.hasClass(CLASS_FIXED) && !tooltip.hasClass(CLASS_DISABLED) && clearTimeout(this.timers.hide);
|
|
}
|
|
|
|
// On mouseleave...
|
|
else {
|
|
// When mouse tracking is enabled, hide when we leave the tooltip and not onto the show target (if a hide event is set)
|
|
if(options.position.target === 'mouse' && options.position.adjust.mouse &&
|
|
options.hide.event && options.show.target && !target.closest(options.show.target[0]).length) {
|
|
this.hide(event);
|
|
}
|
|
}
|
|
|
|
// Add hover class
|
|
tooltip.toggleClass(CLASS_HOVER, state);
|
|
});
|
|
|
|
// Define events which reset the 'inactive' event handler
|
|
delegate('['+ATTR_ID+']', INACTIVE_EVENTS, inactiveMethod);
|
|
});
|
|
;// Initialization method
|
|
function init(elem, id, opts) {
|
|
var obj, posOptions, attr, config, title,
|
|
|
|
// Setup element references
|
|
docBody = $(document.body),
|
|
|
|
// Use document body instead of document element if needed
|
|
newTarget = elem[0] === document ? docBody : elem,
|
|
|
|
// Grab metadata from element if plugin is present
|
|
metadata = elem.metadata ? elem.metadata(opts.metadata) : NULL,
|
|
|
|
// If metadata type if HTML5, grab 'name' from the object instead, or use the regular data object otherwise
|
|
metadata5 = opts.metadata.type === 'html5' && metadata ? metadata[opts.metadata.name] : NULL,
|
|
|
|
// Grab data from metadata.name (or data-qtipopts as fallback) using .data() method,
|
|
html5 = elem.data(opts.metadata.name || 'qtipopts');
|
|
|
|
// If we don't get an object returned attempt to parse it manualyl without parseJSON
|
|
/* eslint-disable no-empty */
|
|
try { html5 = typeof html5 === 'string' ? $.parseJSON(html5) : html5; }
|
|
catch(e) {}
|
|
/* eslint-enable no-empty */
|
|
|
|
// Merge in and sanitize metadata
|
|
config = $.extend(TRUE, {}, QTIP.defaults, opts,
|
|
typeof html5 === 'object' ? sanitizeOptions(html5) : NULL,
|
|
sanitizeOptions(metadata5 || metadata));
|
|
|
|
// Re-grab our positioning options now we've merged our metadata and set id to passed value
|
|
posOptions = config.position;
|
|
config.id = id;
|
|
|
|
// Setup missing content if none is detected
|
|
if('boolean' === typeof config.content.text) {
|
|
attr = elem.attr(config.content.attr);
|
|
|
|
// Grab from supplied attribute if available
|
|
if(config.content.attr !== FALSE && attr) { config.content.text = attr; }
|
|
|
|
// No valid content was found, abort render
|
|
else { return FALSE; }
|
|
}
|
|
|
|
// Setup target options
|
|
if(!posOptions.container.length) { posOptions.container = docBody; }
|
|
if(posOptions.target === FALSE) { posOptions.target = newTarget; }
|
|
if(config.show.target === FALSE) { config.show.target = newTarget; }
|
|
if(config.show.solo === TRUE) { config.show.solo = posOptions.container.closest('body'); }
|
|
if(config.hide.target === FALSE) { config.hide.target = newTarget; }
|
|
if(config.position.viewport === TRUE) { config.position.viewport = posOptions.container; }
|
|
|
|
// Ensure we only use a single container
|
|
posOptions.container = posOptions.container.eq(0);
|
|
|
|
// Convert position corner values into x and y strings
|
|
posOptions.at = new CORNER(posOptions.at, TRUE);
|
|
posOptions.my = new CORNER(posOptions.my);
|
|
|
|
// Destroy previous tooltip if overwrite is enabled, or skip element if not
|
|
if(elem.data(NAMESPACE)) {
|
|
if(config.overwrite) {
|
|
elem.qtip('destroy', true);
|
|
}
|
|
else if(config.overwrite === FALSE) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// Add has-qtip attribute
|
|
elem.attr(ATTR_HAS, id);
|
|
|
|
// Remove title attribute and store it if present
|
|
if(config.suppress && (title = elem.attr('title'))) {
|
|
// Final attr call fixes event delegatiom and IE default tooltip showing problem
|
|
elem.removeAttr('title').attr(oldtitle, title).attr('title', '');
|
|
}
|
|
|
|
// Initialize the tooltip and add API reference
|
|
obj = new QTip(elem, config, id, !!attr);
|
|
elem.data(NAMESPACE, obj);
|
|
|
|
return obj;
|
|
}
|
|
|
|
// jQuery $.fn extension method
|
|
QTIP = $.fn.qtip = function(options, notation, newValue)
|
|
{
|
|
var command = ('' + options).toLowerCase(), // Parse command
|
|
returned = NULL,
|
|
args = $.makeArray(arguments).slice(1),
|
|
event = args[args.length - 1],
|
|
opts = this[0] ? $.data(this[0], NAMESPACE) : NULL;
|
|
|
|
// Check for API request
|
|
if(!arguments.length && opts || command === 'api') {
|
|
return opts;
|
|
}
|
|
|
|
// Execute API command if present
|
|
else if('string' === typeof options) {
|
|
this.each(function() {
|
|
var api = $.data(this, NAMESPACE);
|
|
if(!api) { return TRUE; }
|
|
|
|
// Cache the event if possible
|
|
if(event && event.timeStamp) { api.cache.event = event; }
|
|
|
|
// Check for specific API commands
|
|
if(notation && (command === 'option' || command === 'options')) {
|
|
if(newValue !== undefined || $.isPlainObject(notation)) {
|
|
api.set(notation, newValue);
|
|
}
|
|
else {
|
|
returned = api.get(notation);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// Execute API command
|
|
else if(api[command]) {
|
|
api[command].apply(api, args);
|
|
}
|
|
});
|
|
|
|
return returned !== NULL ? returned : this;
|
|
}
|
|
|
|
// No API commands. validate provided options and setup qTips
|
|
else if('object' === typeof options || !arguments.length) {
|
|
// Sanitize options first
|
|
opts = sanitizeOptions($.extend(TRUE, {}, options));
|
|
|
|
return this.each(function(i) {
|
|
var api, id;
|
|
|
|
// Find next available ID, or use custom ID if provided
|
|
id = $.isArray(opts.id) ? opts.id[i] : opts.id;
|
|
id = !id || id === FALSE || id.length < 1 || QTIP.api[id] ? QTIP.nextid++ : id;
|
|
|
|
// Initialize the qTip and re-grab newly sanitized options
|
|
api = init($(this), id, opts);
|
|
if(api === FALSE) { return TRUE; }
|
|
else { QTIP.api[id] = api; }
|
|
|
|
// Initialize plugins
|
|
$.each(PLUGINS, function() {
|
|
if(this.initialize === 'initialize') { this(api); }
|
|
});
|
|
|
|
// Assign initial pre-render events
|
|
api._assignInitialEvents(event);
|
|
});
|
|
}
|
|
};
|
|
|
|
// Expose class
|
|
$.qtip = QTip;
|
|
|
|
// Populated in render method
|
|
QTIP.api = {};
|
|
;$.each({
|
|
/* Allow other plugins to successfully retrieve the title of an element with a qTip applied */
|
|
attr: function(attr, val) {
|
|
if(this.length) {
|
|
var self = this[0],
|
|
title = 'title',
|
|
api = $.data(self, 'qtip');
|
|
|
|
if(attr === title && api && api.options && 'object' === typeof api && 'object' === typeof api.options && api.options.suppress) {
|
|
if(arguments.length < 2) {
|
|
return $.attr(self, oldtitle);
|
|
}
|
|
|
|
// If qTip is rendered and title was originally used as content, update it
|
|
if(api && api.options.content.attr === title && api.cache.attr) {
|
|
api.set('content.text', val);
|
|
}
|
|
|
|
// Use the regular attr method to set, then cache the result
|
|
return this.attr(oldtitle, val);
|
|
}
|
|
}
|
|
|
|
return $.fn['attr'+replaceSuffix].apply(this, arguments);
|
|
},
|
|
|
|
/* Allow clone to correctly retrieve cached title attributes */
|
|
clone: function(keepData) {
|
|
// Clone our element using the real clone method
|
|
var elems = $.fn['clone'+replaceSuffix].apply(this, arguments);
|
|
|
|
// Grab all elements with an oldtitle set, and change it to regular title attribute, if keepData is false
|
|
if(!keepData) {
|
|
elems.filter('['+oldtitle+']').attr('title', function() {
|
|
return $.attr(this, oldtitle);
|
|
})
|
|
.removeAttr(oldtitle);
|
|
}
|
|
|
|
return elems;
|
|
}
|
|
}, function(name, func) {
|
|
if(!func || $.fn[name+replaceSuffix]) { return TRUE; }
|
|
|
|
var old = $.fn[name+replaceSuffix] = $.fn[name];
|
|
$.fn[name] = function() {
|
|
return func.apply(this, arguments) || old.apply(this, arguments);
|
|
};
|
|
});
|
|
|
|
/* Fire off 'removeqtip' handler in $.cleanData if jQuery UI not present (it already does similar).
|
|
* This snippet is taken directly from jQuery UI source code found here:
|
|
* http://code.jquery.com/ui/jquery-ui-git.js
|
|
*/
|
|
if(!$.ui) {
|
|
$['cleanData'+replaceSuffix] = $.cleanData;
|
|
$.cleanData = function( elems ) {
|
|
for(var i = 0, elem; (elem = $( elems[i] )).length; i++) {
|
|
if(elem.attr(ATTR_HAS)) {
|
|
/* eslint-disable no-empty */
|
|
try { elem.triggerHandler('removeqtip'); }
|
|
catch( e ) {}
|
|
/* eslint-enable no-empty */
|
|
}
|
|
}
|
|
$['cleanData'+replaceSuffix].apply(this, arguments);
|
|
};
|
|
}
|
|
;// qTip version
|
|
QTIP.version = '3.0.3';
|
|
|
|
// Base ID for all qTips
|
|
QTIP.nextid = 0;
|
|
|
|
// Inactive events array
|
|
QTIP.inactiveEvents = INACTIVE_EVENTS;
|
|
|
|
// Base z-index for all qTips
|
|
QTIP.zindex = 15000;
|
|
|
|
// Define configuration defaults
|
|
QTIP.defaults = {
|
|
prerender: FALSE,
|
|
id: FALSE,
|
|
overwrite: TRUE,
|
|
suppress: TRUE,
|
|
content: {
|
|
text: TRUE,
|
|
attr: 'title',
|
|
title: FALSE,
|
|
button: FALSE
|
|
},
|
|
position: {
|
|
my: 'top left',
|
|
at: 'bottom right',
|
|
target: FALSE,
|
|
container: FALSE,
|
|
viewport: FALSE,
|
|
adjust: {
|
|
x: 0, y: 0,
|
|
mouse: TRUE,
|
|
scroll: TRUE,
|
|
resize: TRUE,
|
|
method: 'flipinvert flipinvert'
|
|
},
|
|
effect: function(api, pos) {
|
|
$(this).animate(pos, {
|
|
duration: 200,
|
|
queue: FALSE
|
|
});
|
|
}
|
|
},
|
|
show: {
|
|
target: FALSE,
|
|
event: 'mouseenter',
|
|
effect: TRUE,
|
|
delay: 90,
|
|
solo: FALSE,
|
|
ready: FALSE,
|
|
autofocus: FALSE
|
|
},
|
|
hide: {
|
|
target: FALSE,
|
|
event: 'mouseleave',
|
|
effect: TRUE,
|
|
delay: 0,
|
|
fixed: FALSE,
|
|
inactive: FALSE,
|
|
leave: 'window',
|
|
distance: FALSE
|
|
},
|
|
style: {
|
|
classes: '',
|
|
widget: FALSE,
|
|
width: FALSE,
|
|
height: FALSE,
|
|
def: TRUE
|
|
},
|
|
events: {
|
|
render: NULL,
|
|
move: NULL,
|
|
show: NULL,
|
|
hide: NULL,
|
|
toggle: NULL,
|
|
visible: NULL,
|
|
hidden: NULL,
|
|
focus: NULL,
|
|
blur: NULL
|
|
}
|
|
};
|
|
;var TIP,
|
|
createVML,
|
|
SCALE,
|
|
PIXEL_RATIO,
|
|
BACKING_STORE_RATIO,
|
|
|
|
// Common CSS strings
|
|
MARGIN = 'margin',
|
|
BORDER = 'border',
|
|
COLOR = 'color',
|
|
BG_COLOR = 'background-color',
|
|
TRANSPARENT = 'transparent',
|
|
IMPORTANT = ' !important',
|
|
|
|
// Check if the browser supports <canvas/> elements
|
|
HASCANVAS = !!document.createElement('canvas').getContext,
|
|
|
|
// Invalid colour values used in parseColours()
|
|
INVALID = /rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i;
|
|
|
|
// Camel-case method, taken from jQuery source
|
|
// http://code.jquery.com/jquery-1.8.0.js
|
|
function camel(s) { return s.charAt(0).toUpperCase() + s.slice(1); }
|
|
|
|
/*
|
|
* Modified from Modernizr's testPropsAll()
|
|
* http://modernizr.com/downloads/modernizr-latest.js
|
|
*/
|
|
var cssProps = {}, cssPrefixes = ['Webkit', 'O', 'Moz', 'ms'];
|
|
function vendorCss(elem, prop) {
|
|
var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
|
|
props = (prop + ' ' + cssPrefixes.join(ucProp + ' ') + ucProp).split(' '),
|
|
cur, val, i = 0;
|
|
|
|
// If the property has already been mapped...
|
|
if(cssProps[prop]) { return elem.css(cssProps[prop]); }
|
|
|
|
while(cur = props[i++]) {
|
|
if((val = elem.css(cur)) !== undefined) {
|
|
cssProps[prop] = cur;
|
|
return val;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Parse a given elements CSS property into an int
|
|
function intCss(elem, prop) {
|
|
return Math.ceil(parseFloat(vendorCss(elem, prop)));
|
|
}
|
|
|
|
|
|
// VML creation (for IE only)
|
|
if(!HASCANVAS) {
|
|
createVML = function(tag, props, style) {
|
|
return '<qtipvml:'+tag+' xmlns="urn:schemas-microsoft.com:vml" class="qtip-vml" '+(props||'')+
|
|
' style="behavior: url(#default#VML); '+(style||'')+ '" />';
|
|
};
|
|
}
|
|
|
|
// Canvas only definitions
|
|
else {
|
|
PIXEL_RATIO = window.devicePixelRatio || 1;
|
|
BACKING_STORE_RATIO = (function() {
|
|
var context = document.createElement('canvas').getContext('2d');
|
|
return context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio ||
|
|
context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || 1;
|
|
})();
|
|
SCALE = PIXEL_RATIO / BACKING_STORE_RATIO;
|
|
}
|
|
|
|
|
|
function Tip(qtip, options) {
|
|
this._ns = 'tip';
|
|
this.options = options;
|
|
this.offset = options.offset;
|
|
this.size = [ options.width, options.height ];
|
|
|
|
// Initialize
|
|
this.qtip = qtip;
|
|
this.init(qtip);
|
|
}
|
|
|
|
$.extend(Tip.prototype, {
|
|
init: function(qtip) {
|
|
var context, tip;
|
|
|
|
// Create tip element and prepend to the tooltip
|
|
tip = this.element = qtip.elements.tip = $('<div />', { 'class': NAMESPACE+'-tip' }).prependTo(qtip.tooltip);
|
|
|
|
// Create tip drawing element(s)
|
|
if(HASCANVAS) {
|
|
// save() as soon as we create the canvas element so FF2 doesn't bork on our first restore()!
|
|
context = $('<canvas />').appendTo(this.element)[0].getContext('2d');
|
|
|
|
// Setup constant parameters
|
|
context.lineJoin = 'miter';
|
|
context.miterLimit = 100000;
|
|
context.save();
|
|
}
|
|
else {
|
|
context = createVML('shape', 'coordorigin="0,0"', 'position:absolute;');
|
|
this.element.html(context + context);
|
|
|
|
// Prevent mousing down on the tip since it causes problems with .live() handling in IE due to VML
|
|
qtip._bind( $('*', tip).add(tip), ['click', 'mousedown'], function(event) { event.stopPropagation(); }, this._ns);
|
|
}
|
|
|
|
// Bind update events
|
|
qtip._bind(qtip.tooltip, 'tooltipmove', this.reposition, this._ns, this);
|
|
|
|
// Create it
|
|
this.create();
|
|
},
|
|
|
|
_swapDimensions: function() {
|
|
this.size[0] = this.options.height;
|
|
this.size[1] = this.options.width;
|
|
},
|
|
_resetDimensions: function() {
|
|
this.size[0] = this.options.width;
|
|
this.size[1] = this.options.height;
|
|
},
|
|
|
|
_useTitle: function(corner) {
|
|
var titlebar = this.qtip.elements.titlebar;
|
|
return titlebar && (
|
|
corner.y === TOP || corner.y === CENTER && this.element.position().top + this.size[1] / 2 + this.options.offset < titlebar.outerHeight(TRUE)
|
|
);
|
|
},
|
|
|
|
_parseCorner: function(corner) {
|
|
var my = this.qtip.options.position.my;
|
|
|
|
// Detect corner and mimic properties
|
|
if(corner === FALSE || my === FALSE) {
|
|
corner = FALSE;
|
|
}
|
|
else if(corner === TRUE) {
|
|
corner = new CORNER( my.string() );
|
|
}
|
|
else if(!corner.string) {
|
|
corner = new CORNER(corner);
|
|
corner.fixed = TRUE;
|
|
}
|
|
|
|
return corner;
|
|
},
|
|
|
|
_parseWidth: function(corner, side, use) {
|
|
var elements = this.qtip.elements,
|
|
prop = BORDER + camel(side) + 'Width';
|
|
|
|
return (use ? intCss(use, prop) :
|
|
intCss(elements.content, prop) ||
|
|
intCss(this._useTitle(corner) && elements.titlebar || elements.content, prop) ||
|
|
intCss(elements.tooltip, prop)
|
|
) || 0;
|
|
},
|
|
|
|
_parseRadius: function(corner) {
|
|
var elements = this.qtip.elements,
|
|
prop = BORDER + camel(corner.y) + camel(corner.x) + 'Radius';
|
|
|
|
return BROWSER.ie < 9 ? 0 :
|
|
intCss(this._useTitle(corner) && elements.titlebar || elements.content, prop) ||
|
|
intCss(elements.tooltip, prop) || 0;
|
|
},
|
|
|
|
_invalidColour: function(elem, prop, compare) {
|
|
var val = elem.css(prop);
|
|
return !val || compare && val === elem.css(compare) || INVALID.test(val) ? FALSE : val;
|
|
},
|
|
|
|
_parseColours: function(corner) {
|
|
var elements = this.qtip.elements,
|
|
tip = this.element.css('cssText', ''),
|
|
borderSide = BORDER + camel(corner[ corner.precedance ]) + camel(COLOR),
|
|
colorElem = this._useTitle(corner) && elements.titlebar || elements.content,
|
|
css = this._invalidColour, color = [];
|
|
|
|
// Attempt to detect the background colour from various elements, left-to-right precedance
|
|
color[0] = css(tip, BG_COLOR) || css(colorElem, BG_COLOR) || css(elements.content, BG_COLOR) ||
|
|
css(elements.tooltip, BG_COLOR) || tip.css(BG_COLOR);
|
|
|
|
// Attempt to detect the correct border side colour from various elements, left-to-right precedance
|
|
color[1] = css(tip, borderSide, COLOR) || css(colorElem, borderSide, COLOR) ||
|
|
css(elements.content, borderSide, COLOR) || css(elements.tooltip, borderSide, COLOR) || elements.tooltip.css(borderSide);
|
|
|
|
// Reset background and border colours
|
|
$('*', tip).add(tip).css('cssText', BG_COLOR+':'+TRANSPARENT+IMPORTANT+';'+BORDER+':0'+IMPORTANT+';');
|
|
|
|
return color;
|
|
},
|
|
|
|
_calculateSize: function(corner) {
|
|
var y = corner.precedance === Y,
|
|
width = this.options.width,
|
|
height = this.options.height,
|
|
isCenter = corner.abbrev() === 'c',
|
|
base = (y ? width: height) * (isCenter ? 0.5 : 1),
|
|
pow = Math.pow,
|
|
round = Math.round,
|
|
bigHyp, ratio, result,
|
|
|
|
smallHyp = Math.sqrt( pow(base, 2) + pow(height, 2) ),
|
|
hyp = [
|
|
this.border / base * smallHyp,
|
|
this.border / height * smallHyp
|
|
];
|
|
|
|
hyp[2] = Math.sqrt( pow(hyp[0], 2) - pow(this.border, 2) );
|
|
hyp[3] = Math.sqrt( pow(hyp[1], 2) - pow(this.border, 2) );
|
|
|
|
bigHyp = smallHyp + hyp[2] + hyp[3] + (isCenter ? 0 : hyp[0]);
|
|
ratio = bigHyp / smallHyp;
|
|
|
|
result = [ round(ratio * width), round(ratio * height) ];
|
|
return y ? result : result.reverse();
|
|
},
|
|
|
|
// Tip coordinates calculator
|
|
_calculateTip: function(corner, size, scale) {
|
|
scale = scale || 1;
|
|
size = size || this.size;
|
|
|
|
var width = size[0] * scale,
|
|
height = size[1] * scale,
|
|
width2 = Math.ceil(width / 2), height2 = Math.ceil(height / 2),
|
|
|
|
// Define tip coordinates in terms of height and width values
|
|
tips = {
|
|
br: [0,0, width,height, width,0],
|
|
bl: [0,0, width,0, 0,height],
|
|
tr: [0,height, width,0, width,height],
|
|
tl: [0,0, 0,height, width,height],
|
|
tc: [0,height, width2,0, width,height],
|
|
bc: [0,0, width,0, width2,height],
|
|
rc: [0,0, width,height2, 0,height],
|
|
lc: [width,0, width,height, 0,height2]
|
|
};
|
|
|
|
// Set common side shapes
|
|
tips.lt = tips.br; tips.rt = tips.bl;
|
|
tips.lb = tips.tr; tips.rb = tips.tl;
|
|
|
|
return tips[ corner.abbrev() ];
|
|
},
|
|
|
|
// Tip coordinates drawer (canvas)
|
|
_drawCoords: function(context, coords) {
|
|
context.beginPath();
|
|
context.moveTo(coords[0], coords[1]);
|
|
context.lineTo(coords[2], coords[3]);
|
|
context.lineTo(coords[4], coords[5]);
|
|
context.closePath();
|
|
},
|
|
|
|
create: function() {
|
|
// Determine tip corner
|
|
var c = this.corner = (HASCANVAS || BROWSER.ie) && this._parseCorner(this.options.corner);
|
|
|
|
// If we have a tip corner...
|
|
this.enabled = !!this.corner && this.corner.abbrev() !== 'c';
|
|
if(this.enabled) {
|
|
// Cache it
|
|
this.qtip.cache.corner = c.clone();
|
|
|
|
// Create it
|
|
this.update();
|
|
}
|
|
|
|
// Toggle tip element
|
|
this.element.toggle(this.enabled);
|
|
|
|
return this.corner;
|
|
},
|
|
|
|
update: function(corner, position) {
|
|
if(!this.enabled) { return this; }
|
|
|
|
var elements = this.qtip.elements,
|
|
tip = this.element,
|
|
inner = tip.children(),
|
|
options = this.options,
|
|
curSize = this.size,
|
|
mimic = options.mimic,
|
|
round = Math.round,
|
|
color, precedance, context,
|
|
coords, bigCoords, translate, newSize, border;
|
|
|
|
// Re-determine tip if not already set
|
|
if(!corner) { corner = this.qtip.cache.corner || this.corner; }
|
|
|
|
// Use corner property if we detect an invalid mimic value
|
|
if(mimic === FALSE) { mimic = corner; }
|
|
|
|
// Otherwise inherit mimic properties from the corner object as necessary
|
|
else {
|
|
mimic = new CORNER(mimic);
|
|
mimic.precedance = corner.precedance;
|
|
|
|
if(mimic.x === 'inherit') { mimic.x = corner.x; }
|
|
else if(mimic.y === 'inherit') { mimic.y = corner.y; }
|
|
else if(mimic.x === mimic.y) {
|
|
mimic[ corner.precedance ] = corner[ corner.precedance ];
|
|
}
|
|
}
|
|
precedance = mimic.precedance;
|
|
|
|
// Ensure the tip width.height are relative to the tip position
|
|
if(corner.precedance === X) { this._swapDimensions(); }
|
|
else { this._resetDimensions(); }
|
|
|
|
// Update our colours
|
|
color = this.color = this._parseColours(corner);
|
|
|
|
// Detect border width, taking into account colours
|
|
if(color[1] !== TRANSPARENT) {
|
|
// Grab border width
|
|
border = this.border = this._parseWidth(corner, corner[corner.precedance]);
|
|
|
|
// If border width isn't zero, use border color as fill if it's not invalid (1.0 style tips)
|
|
if(options.border && border < 1 && !INVALID.test(color[1])) { color[0] = color[1]; }
|
|
|
|
// Set border width (use detected border width if options.border is true)
|
|
this.border = border = options.border !== TRUE ? options.border : border;
|
|
}
|
|
|
|
// Border colour was invalid, set border to zero
|
|
else { this.border = border = 0; }
|
|
|
|
// Determine tip size
|
|
newSize = this.size = this._calculateSize(corner);
|
|
tip.css({
|
|
width: newSize[0],
|
|
height: newSize[1],
|
|
lineHeight: newSize[1]+'px'
|
|
});
|
|
|
|
// Calculate tip translation
|
|
if(corner.precedance === Y) {
|
|
translate = [
|
|
round(mimic.x === LEFT ? border : mimic.x === RIGHT ? newSize[0] - curSize[0] - border : (newSize[0] - curSize[0]) / 2),
|
|
round(mimic.y === TOP ? newSize[1] - curSize[1] : 0)
|
|
];
|
|
}
|
|
else {
|
|
translate = [
|
|
round(mimic.x === LEFT ? newSize[0] - curSize[0] : 0),
|
|
round(mimic.y === TOP ? border : mimic.y === BOTTOM ? newSize[1] - curSize[1] - border : (newSize[1] - curSize[1]) / 2)
|
|
];
|
|
}
|
|
|
|
// Canvas drawing implementation
|
|
if(HASCANVAS) {
|
|
// Grab canvas context and clear/save it
|
|
context = inner[0].getContext('2d');
|
|
context.restore(); context.save();
|
|
context.clearRect(0,0,6000,6000);
|
|
|
|
// Calculate coordinates
|
|
coords = this._calculateTip(mimic, curSize, SCALE);
|
|
bigCoords = this._calculateTip(mimic, this.size, SCALE);
|
|
|
|
// Set the canvas size using calculated size
|
|
inner.attr(WIDTH, newSize[0] * SCALE).attr(HEIGHT, newSize[1] * SCALE);
|
|
inner.css(WIDTH, newSize[0]).css(HEIGHT, newSize[1]);
|
|
|
|
// Draw the outer-stroke tip
|
|
this._drawCoords(context, bigCoords);
|
|
context.fillStyle = color[1];
|
|
context.fill();
|
|
|
|
// Draw the actual tip
|
|
context.translate(translate[0] * SCALE, translate[1] * SCALE);
|
|
this._drawCoords(context, coords);
|
|
context.fillStyle = color[0];
|
|
context.fill();
|
|
}
|
|
|
|
// VML (IE Proprietary implementation)
|
|
else {
|
|
// Calculate coordinates
|
|
coords = this._calculateTip(mimic);
|
|
|
|
// Setup coordinates string
|
|
coords = 'm' + coords[0] + ',' + coords[1] + ' l' + coords[2] +
|
|
',' + coords[3] + ' ' + coords[4] + ',' + coords[5] + ' xe';
|
|
|
|
// Setup VML-specific offset for pixel-perfection
|
|
translate[2] = border && /^(r|b)/i.test(corner.string()) ?
|
|
BROWSER.ie === 8 ? 2 : 1 : 0;
|
|
|
|
// Set initial CSS
|
|
inner.css({
|
|
coordsize: newSize[0]+border + ' ' + newSize[1]+border,
|
|
antialias: ''+(mimic.string().indexOf(CENTER) > -1),
|
|
left: translate[0] - translate[2] * Number(precedance === X),
|
|
top: translate[1] - translate[2] * Number(precedance === Y),
|
|
width: newSize[0] + border,
|
|
height: newSize[1] + border
|
|
})
|
|
.each(function(i) {
|
|
var $this = $(this);
|
|
|
|
// Set shape specific attributes
|
|
$this[ $this.prop ? 'prop' : 'attr' ]({
|
|
coordsize: newSize[0]+border + ' ' + newSize[1]+border,
|
|
path: coords,
|
|
fillcolor: color[0],
|
|
filled: !!i,
|
|
stroked: !i
|
|
})
|
|
.toggle(!!(border || i));
|
|
|
|
// Check if border is enabled and add stroke element
|
|
!i && $this.html( createVML(
|
|
'stroke', 'weight="'+border*2+'px" color="'+color[1]+'" miterlimit="1000" joinstyle="miter"'
|
|
) );
|
|
});
|
|
}
|
|
|
|
// Opera bug #357 - Incorrect tip position
|
|
// https://github.com/Craga89/qTip2/issues/367
|
|
window.opera && setTimeout(function() {
|
|
elements.tip.css({
|
|
display: 'inline-block',
|
|
visibility: 'visible'
|
|
});
|
|
}, 1);
|
|
|
|
// Position if needed
|
|
if(position !== FALSE) { this.calculate(corner, newSize); }
|
|
},
|
|
|
|
calculate: function(corner, size) {
|
|
if(!this.enabled) { return FALSE; }
|
|
|
|
var self = this,
|
|
elements = this.qtip.elements,
|
|
tip = this.element,
|
|
userOffset = this.options.offset,
|
|
position = {},
|
|
precedance, corners;
|
|
|
|
// Inherit corner if not provided
|
|
corner = corner || this.corner;
|
|
precedance = corner.precedance;
|
|
|
|
// Determine which tip dimension to use for adjustment
|
|
size = size || this._calculateSize(corner);
|
|
|
|
// Setup corners and offset array
|
|
corners = [ corner.x, corner.y ];
|
|
if(precedance === X) { corners.reverse(); }
|
|
|
|
// Calculate tip position
|
|
$.each(corners, function(i, side) {
|
|
var b, bc, br;
|
|
|
|
if(side === CENTER) {
|
|
b = precedance === Y ? LEFT : TOP;
|
|
position[ b ] = '50%';
|
|
position[MARGIN+'-' + b] = -Math.round(size[ precedance === Y ? 0 : 1 ] / 2) + userOffset;
|
|
}
|
|
else {
|
|
b = self._parseWidth(corner, side, elements.tooltip);
|
|
bc = self._parseWidth(corner, side, elements.content);
|
|
br = self._parseRadius(corner);
|
|
|
|
position[ side ] = Math.max(-self.border, i ? bc : userOffset + (br > b ? br : -b));
|
|
}
|
|
});
|
|
|
|
// Adjust for tip size
|
|
position[ corner[precedance] ] -= size[ precedance === X ? 0 : 1 ];
|
|
|
|
// Set and return new position
|
|
tip.css({ margin: '', top: '', bottom: '', left: '', right: '' }).css(position);
|
|
return position;
|
|
},
|
|
|
|
reposition: function(event, api, pos) {
|
|
if(!this.enabled) { return; }
|
|
|
|
var cache = api.cache,
|
|
newCorner = this.corner.clone(),
|
|
adjust = pos.adjusted,
|
|
method = api.options.position.adjust.method.split(' '),
|
|
horizontal = method[0],
|
|
vertical = method[1] || method[0],
|
|
shift = { left: FALSE, top: FALSE, x: 0, y: 0 },
|
|
offset, css = {}, props;
|
|
|
|
function shiftflip(direction, precedance, popposite, side, opposite) {
|
|
// Horizontal - Shift or flip method
|
|
if(direction === SHIFT && newCorner.precedance === precedance && adjust[side] && newCorner[popposite] !== CENTER) {
|
|
newCorner.precedance = newCorner.precedance === X ? Y : X;
|
|
}
|
|
else if(direction !== SHIFT && adjust[side]){
|
|
newCorner[precedance] = newCorner[precedance] === CENTER ?
|
|
adjust[side] > 0 ? side : opposite :
|
|
newCorner[precedance] === side ? opposite : side;
|
|
}
|
|
}
|
|
|
|
function shiftonly(xy, side, opposite) {
|
|
if(newCorner[xy] === CENTER) {
|
|
css[MARGIN+'-'+side] = shift[xy] = offset[MARGIN+'-'+side] - adjust[side];
|
|
}
|
|
else {
|
|
props = offset[opposite] !== undefined ?
|
|
[ adjust[side], -offset[side] ] : [ -adjust[side], offset[side] ];
|
|
|
|
if( (shift[xy] = Math.max(props[0], props[1])) > props[0] ) {
|
|
pos[side] -= adjust[side];
|
|
shift[side] = FALSE;
|
|
}
|
|
|
|
css[ offset[opposite] !== undefined ? opposite : side ] = shift[xy];
|
|
}
|
|
}
|
|
|
|
// If our tip position isn't fixed e.g. doesn't adjust with viewport...
|
|
if(this.corner.fixed !== TRUE) {
|
|
// Perform shift/flip adjustments
|
|
shiftflip(horizontal, X, Y, LEFT, RIGHT);
|
|
shiftflip(vertical, Y, X, TOP, BOTTOM);
|
|
|
|
// Update and redraw the tip if needed (check cached details of last drawn tip)
|
|
if(newCorner.string() !== cache.corner.string() || cache.cornerTop !== adjust.top || cache.cornerLeft !== adjust.left) {
|
|
this.update(newCorner, FALSE);
|
|
}
|
|
}
|
|
|
|
// Setup tip offset properties
|
|
offset = this.calculate(newCorner);
|
|
|
|
// Readjust offset object to make it left/top
|
|
if(offset.right !== undefined) { offset.left = -offset.right; }
|
|
if(offset.bottom !== undefined) { offset.top = -offset.bottom; }
|
|
offset.user = this.offset;
|
|
|
|
// Perform shift adjustments
|
|
shift.left = horizontal === SHIFT && !!adjust.left;
|
|
if(shift.left) {
|
|
shiftonly(X, LEFT, RIGHT);
|
|
}
|
|
shift.top = vertical === SHIFT && !!adjust.top;
|
|
if(shift.top) {
|
|
shiftonly(Y, TOP, BOTTOM);
|
|
}
|
|
|
|
/*
|
|
* If the tip is adjusted in both dimensions, or in a
|
|
* direction that would cause it to be anywhere but the
|
|
* outer border, hide it!
|
|
*/
|
|
this.element.css(css).toggle(
|
|
!(shift.x && shift.y || newCorner.x === CENTER && shift.y || newCorner.y === CENTER && shift.x)
|
|
);
|
|
|
|
// Adjust position to accomodate tip dimensions
|
|
pos.left -= offset.left.charAt ? offset.user :
|
|
horizontal !== SHIFT || shift.top || !shift.left && !shift.top ? offset.left + this.border : 0;
|
|
pos.top -= offset.top.charAt ? offset.user :
|
|
vertical !== SHIFT || shift.left || !shift.left && !shift.top ? offset.top + this.border : 0;
|
|
|
|
// Cache details
|
|
cache.cornerLeft = adjust.left; cache.cornerTop = adjust.top;
|
|
cache.corner = newCorner.clone();
|
|
},
|
|
|
|
destroy: function() {
|
|
// Unbind events
|
|
this.qtip._unbind(this.qtip.tooltip, this._ns);
|
|
|
|
// Remove the tip element(s)
|
|
if(this.qtip.elements.tip) {
|
|
this.qtip.elements.tip.find('*')
|
|
.remove().end().remove();
|
|
}
|
|
}
|
|
});
|
|
|
|
TIP = PLUGINS.tip = function(api) {
|
|
return new Tip(api, api.options.style.tip);
|
|
};
|
|
|
|
// Initialize tip on render
|
|
TIP.initialize = 'render';
|
|
|
|
// Setup plugin sanitization options
|
|
TIP.sanitize = function(options) {
|
|
if(options.style && 'tip' in options.style) {
|
|
var opts = options.style.tip;
|
|
if(typeof opts !== 'object') { opts = options.style.tip = { corner: opts }; }
|
|
if(!(/string|boolean/i).test(typeof opts.corner)) { opts.corner = TRUE; }
|
|
}
|
|
};
|
|
|
|
// Add new option checks for the plugin
|
|
CHECKS.tip = {
|
|
'^position.my|style.tip.(corner|mimic|border)$': function() {
|
|
// Make sure a tip can be drawn
|
|
this.create();
|
|
|
|
// Reposition the tooltip
|
|
this.qtip.reposition();
|
|
},
|
|
'^style.tip.(height|width)$': function(obj) {
|
|
// Re-set dimensions and redraw the tip
|
|
this.size = [ obj.width, obj.height ];
|
|
this.update();
|
|
|
|
// Reposition the tooltip
|
|
this.qtip.reposition();
|
|
},
|
|
'^content.title|style.(classes|widget)$': function() {
|
|
this.update();
|
|
}
|
|
};
|
|
|
|
// Extend original qTip defaults
|
|
$.extend(TRUE, QTIP.defaults, {
|
|
style: {
|
|
tip: {
|
|
corner: TRUE,
|
|
mimic: FALSE,
|
|
width: 6,
|
|
height: 6,
|
|
border: TRUE,
|
|
offset: 0
|
|
}
|
|
}
|
|
});
|
|
;var MODAL, OVERLAY,
|
|
MODALCLASS = 'qtip-modal',
|
|
MODALSELECTOR = '.'+MODALCLASS;
|
|
|
|
OVERLAY = function()
|
|
{
|
|
var self = this,
|
|
focusableElems = {},
|
|
current,
|
|
prevState,
|
|
elem;
|
|
|
|
// Modified code from jQuery UI 1.10.0 source
|
|
// http://code.jquery.com/ui/1.10.0/jquery-ui.js
|
|
function focusable(element) {
|
|
// Use the defined focusable checker when possible
|
|
if($.expr[':'].focusable) { return $.expr[':'].focusable; }
|
|
|
|
var isTabIndexNotNaN = !isNaN($.attr(element, 'tabindex')),
|
|
nodeName = element.nodeName && element.nodeName.toLowerCase(),
|
|
map, mapName, img;
|
|
|
|
if('area' === nodeName) {
|
|
map = element.parentNode;
|
|
mapName = map.name;
|
|
if(!element.href || !mapName || map.nodeName.toLowerCase() !== 'map') {
|
|
return false;
|
|
}
|
|
img = $('img[usemap=#' + mapName + ']')[0];
|
|
return !!img && img.is(':visible');
|
|
}
|
|
|
|
return /input|select|textarea|button|object/.test( nodeName ) ?
|
|
!element.disabled :
|
|
'a' === nodeName ?
|
|
element.href || isTabIndexNotNaN :
|
|
isTabIndexNotNaN
|
|
;
|
|
}
|
|
|
|
// Focus inputs using cached focusable elements (see update())
|
|
function focusInputs(blurElems) {
|
|
// Blurring body element in IE causes window.open windows to unfocus!
|
|
if(focusableElems.length < 1 && blurElems.length) { blurElems.not('body').blur(); }
|
|
|
|
// Focus the inputs
|
|
else { focusableElems.first().focus(); }
|
|
}
|
|
|
|
// Steal focus from elements outside tooltip
|
|
function stealFocus(event) {
|
|
if(!elem.is(':visible')) { return; }
|
|
|
|
var target = $(event.target),
|
|
tooltip = current.tooltip,
|
|
container = target.closest(SELECTOR),
|
|
targetOnTop;
|
|
|
|
// Determine if input container target is above this
|
|
targetOnTop = container.length < 1 ? FALSE :
|
|
parseInt(container[0].style.zIndex, 10) > parseInt(tooltip[0].style.zIndex, 10);
|
|
|
|
// If we're showing a modal, but focus has landed on an input below
|
|
// this modal, divert focus to the first visible input in this modal
|
|
// or if we can't find one... the tooltip itself
|
|
if(!targetOnTop && target.closest(SELECTOR)[0] !== tooltip[0]) {
|
|
focusInputs(target);
|
|
}
|
|
}
|
|
|
|
$.extend(self, {
|
|
init: function() {
|
|
// Create document overlay
|
|
elem = self.elem = $('<div />', {
|
|
id: 'qtip-overlay',
|
|
html: '<div></div>',
|
|
mousedown: function() { return FALSE; }
|
|
})
|
|
.hide();
|
|
|
|
// Make sure we can't focus anything outside the tooltip
|
|
$(document.body).bind('focusin'+MODALSELECTOR, stealFocus);
|
|
|
|
// Apply keyboard "Escape key" close handler
|
|
$(document).bind('keydown'+MODALSELECTOR, function(event) {
|
|
if(current && current.options.show.modal.escape && event.keyCode === 27) {
|
|
current.hide(event);
|
|
}
|
|
});
|
|
|
|
// Apply click handler for blur option
|
|
elem.bind('click'+MODALSELECTOR, function(event) {
|
|
if(current && current.options.show.modal.blur) {
|
|
current.hide(event);
|
|
}
|
|
});
|
|
|
|
return self;
|
|
},
|
|
|
|
update: function(api) {
|
|
// Update current API reference
|
|
current = api;
|
|
|
|
// Update focusable elements if enabled
|
|
if(api.options.show.modal.stealfocus !== FALSE) {
|
|
focusableElems = api.tooltip.find('*').filter(function() {
|
|
return focusable(this);
|
|
});
|
|
}
|
|
else { focusableElems = []; }
|
|
},
|
|
|
|
toggle: function(api, state, duration) {
|
|
var tooltip = api.tooltip,
|
|
options = api.options.show.modal,
|
|
effect = options.effect,
|
|
type = state ? 'show': 'hide',
|
|
visible = elem.is(':visible'),
|
|
visibleModals = $(MODALSELECTOR).filter(':visible:not(:animated)').not(tooltip);
|
|
|
|
// Set active tooltip API reference
|
|
self.update(api);
|
|
|
|
// If the modal can steal the focus...
|
|
// Blur the current item and focus anything in the modal we an
|
|
if(state && options.stealfocus !== FALSE) {
|
|
focusInputs( $(':focus') );
|
|
}
|
|
|
|
// Toggle backdrop cursor style on show
|
|
elem.toggleClass('blurs', options.blur);
|
|
|
|
// Append to body on show
|
|
if(state) {
|
|
elem.appendTo(document.body);
|
|
}
|
|
|
|
// Prevent modal from conflicting with show.solo, and don't hide backdrop is other modals are visible
|
|
if(elem.is(':animated') && visible === state && prevState !== FALSE || !state && visibleModals.length) {
|
|
return self;
|
|
}
|
|
|
|
// Stop all animations
|
|
elem.stop(TRUE, FALSE);
|
|
|
|
// Use custom function if provided
|
|
if($.isFunction(effect)) {
|
|
effect.call(elem, state);
|
|
}
|
|
|
|
// If no effect type is supplied, use a simple toggle
|
|
else if(effect === FALSE) {
|
|
elem[ type ]();
|
|
}
|
|
|
|
// Use basic fade function
|
|
else {
|
|
elem.fadeTo( parseInt(duration, 10) || 90, state ? 1 : 0, function() {
|
|
if(!state) { elem.hide(); }
|
|
});
|
|
}
|
|
|
|
// Reset position and detach from body on hide
|
|
if(!state) {
|
|
elem.queue(function(next) {
|
|
elem.css({ left: '', top: '' });
|
|
if(!$(MODALSELECTOR).length) { elem.detach(); }
|
|
next();
|
|
});
|
|
}
|
|
|
|
// Cache the state
|
|
prevState = state;
|
|
|
|
// If the tooltip is destroyed, set reference to null
|
|
if(current.destroyed) { current = NULL; }
|
|
|
|
return self;
|
|
}
|
|
});
|
|
|
|
self.init();
|
|
};
|
|
OVERLAY = new OVERLAY();
|
|
|
|
function Modal(api, options) {
|
|
this.options = options;
|
|
this._ns = '-modal';
|
|
|
|
this.qtip = api;
|
|
this.init(api);
|
|
}
|
|
|
|
$.extend(Modal.prototype, {
|
|
init: function(qtip) {
|
|
var tooltip = qtip.tooltip;
|
|
|
|
// If modal is disabled... return
|
|
if(!this.options.on) { return this; }
|
|
|
|
// Set overlay reference
|
|
qtip.elements.overlay = OVERLAY.elem;
|
|
|
|
// Add unique attribute so we can grab modal tooltips easily via a SELECTOR, and set z-index
|
|
tooltip.addClass(MODALCLASS).css('z-index', QTIP.modal_zindex + $(MODALSELECTOR).length);
|
|
|
|
// Apply our show/hide/focus modal events
|
|
qtip._bind(tooltip, ['tooltipshow', 'tooltiphide'], function(event, api, duration) {
|
|
var oEvent = event.originalEvent;
|
|
|
|
// Make sure mouseout doesn't trigger a hide when showing the modal and mousing onto backdrop
|
|
if(event.target === tooltip[0]) {
|
|
if(oEvent && event.type === 'tooltiphide' && /mouse(leave|enter)/.test(oEvent.type) && $(oEvent.relatedTarget).closest(OVERLAY.elem[0]).length) {
|
|
/* eslint-disable no-empty */
|
|
try { event.preventDefault(); }
|
|
catch(e) {}
|
|
/* eslint-enable no-empty */
|
|
}
|
|
else if(!oEvent || oEvent && oEvent.type !== 'tooltipsolo') {
|
|
this.toggle(event, event.type === 'tooltipshow', duration);
|
|
}
|
|
}
|
|
}, this._ns, this);
|
|
|
|
// Adjust modal z-index on tooltip focus
|
|
qtip._bind(tooltip, 'tooltipfocus', function(event, api) {
|
|
// If focus was cancelled before it reached us, don't do anything
|
|
if(event.isDefaultPrevented() || event.target !== tooltip[0]) { return; }
|
|
|
|
var qtips = $(MODALSELECTOR),
|
|
|
|
// Keep the modal's lower than other, regular qtips
|
|
newIndex = QTIP.modal_zindex + qtips.length,
|
|
curIndex = parseInt(tooltip[0].style.zIndex, 10);
|
|
|
|
// Set overlay z-index
|
|
OVERLAY.elem[0].style.zIndex = newIndex - 1;
|
|
|
|
// Reduce modal z-index's and keep them properly ordered
|
|
qtips.each(function() {
|
|
if(this.style.zIndex > curIndex) {
|
|
this.style.zIndex -= 1;
|
|
}
|
|
});
|
|
|
|
// Fire blur event for focused tooltip
|
|
qtips.filter('.' + CLASS_FOCUS).qtip('blur', event.originalEvent);
|
|
|
|
// Set the new z-index
|
|
tooltip.addClass(CLASS_FOCUS)[0].style.zIndex = newIndex;
|
|
|
|
// Set current
|
|
OVERLAY.update(api);
|
|
|
|
// Prevent default handling
|
|
/* eslint-disable no-empty */
|
|
try { event.preventDefault(); }
|
|
catch(e) {}
|
|
/* eslint-enable no-empty */
|
|
}, this._ns, this);
|
|
|
|
// Focus any other visible modals when this one hides
|
|
qtip._bind(tooltip, 'tooltiphide', function(event) {
|
|
if(event.target === tooltip[0]) {
|
|
$(MODALSELECTOR).filter(':visible').not(tooltip).last().qtip('focus', event);
|
|
}
|
|
}, this._ns, this);
|
|
},
|
|
|
|
toggle: function(event, state, duration) {
|
|
// Make sure default event hasn't been prevented
|
|
if(event && event.isDefaultPrevented()) { return this; }
|
|
|
|
// Toggle it
|
|
OVERLAY.toggle(this.qtip, !!state, duration);
|
|
},
|
|
|
|
destroy: function() {
|
|
// Remove modal class
|
|
this.qtip.tooltip.removeClass(MODALCLASS);
|
|
|
|
// Remove bound events
|
|
this.qtip._unbind(this.qtip.tooltip, this._ns);
|
|
|
|
// Delete element reference
|
|
OVERLAY.toggle(this.qtip, FALSE);
|
|
delete this.qtip.elements.overlay;
|
|
}
|
|
});
|
|
|
|
|
|
MODAL = PLUGINS.modal = function(api) {
|
|
return new Modal(api, api.options.show.modal);
|
|
};
|
|
|
|
// Setup sanitiztion rules
|
|
MODAL.sanitize = function(opts) {
|
|
if(opts.show) {
|
|
if(typeof opts.show.modal !== 'object') { opts.show.modal = { on: !!opts.show.modal }; }
|
|
else if(typeof opts.show.modal.on === 'undefined') { opts.show.modal.on = TRUE; }
|
|
}
|
|
};
|
|
|
|
// Base z-index for all modal tooltips (use qTip core z-index as a base)
|
|
/* eslint-disable camelcase */
|
|
QTIP.modal_zindex = QTIP.zindex - 200;
|
|
/* eslint-enable camelcase */
|
|
|
|
// Plugin needs to be initialized on render
|
|
MODAL.initialize = 'render';
|
|
|
|
// Setup option set checks
|
|
CHECKS.modal = {
|
|
'^show.modal.(on|blur)$': function() {
|
|
// Initialise
|
|
this.destroy();
|
|
this.init();
|
|
|
|
// Show the modal if not visible already and tooltip is visible
|
|
this.qtip.elems.overlay.toggle(
|
|
this.qtip.tooltip[0].offsetWidth > 0
|
|
);
|
|
}
|
|
};
|
|
|
|
// Extend original api defaults
|
|
$.extend(TRUE, QTIP.defaults, {
|
|
show: {
|
|
modal: {
|
|
on: FALSE,
|
|
effect: TRUE,
|
|
blur: TRUE,
|
|
stealfocus: TRUE,
|
|
escape: TRUE
|
|
}
|
|
}
|
|
});
|
|
;PLUGINS.viewport = function(api, position, posOptions, targetWidth, targetHeight, elemWidth, elemHeight)
|
|
{
|
|
var target = posOptions.target,
|
|
tooltip = api.elements.tooltip,
|
|
my = posOptions.my,
|
|
at = posOptions.at,
|
|
adjust = posOptions.adjust,
|
|
method = adjust.method.split(' '),
|
|
methodX = method[0],
|
|
methodY = method[1] || method[0],
|
|
viewport = posOptions.viewport,
|
|
container = posOptions.container,
|
|
adjusted = { left: 0, top: 0 },
|
|
fixed, newMy, containerOffset, containerStatic,
|
|
viewportWidth, viewportHeight, viewportScroll, viewportOffset;
|
|
|
|
// If viewport is not a jQuery element, or it's the window/document, or no adjustment method is used... return
|
|
if(!viewport.jquery || target[0] === window || target[0] === document.body || adjust.method === 'none') {
|
|
return adjusted;
|
|
}
|
|
|
|
// Cach container details
|
|
containerOffset = container.offset() || adjusted;
|
|
containerStatic = container.css('position') === 'static';
|
|
|
|
// Cache our viewport details
|
|
fixed = tooltip.css('position') === 'fixed';
|
|
viewportWidth = viewport[0] === window ? viewport.width() : viewport.outerWidth(FALSE);
|
|
viewportHeight = viewport[0] === window ? viewport.height() : viewport.outerHeight(FALSE);
|
|
viewportScroll = { left: fixed ? 0 : viewport.scrollLeft(), top: fixed ? 0 : viewport.scrollTop() };
|
|
viewportOffset = viewport.offset() || adjusted;
|
|
|
|
// Generic calculation method
|
|
function calculate(side, otherSide, type, adjustment, side1, side2, lengthName, targetLength, elemLength) {
|
|
var initialPos = position[side1],
|
|
mySide = my[side],
|
|
atSide = at[side],
|
|
isShift = type === SHIFT,
|
|
myLength = mySide === side1 ? elemLength : mySide === side2 ? -elemLength : -elemLength / 2,
|
|
atLength = atSide === side1 ? targetLength : atSide === side2 ? -targetLength : -targetLength / 2,
|
|
sideOffset = viewportScroll[side1] + viewportOffset[side1] - (containerStatic ? 0 : containerOffset[side1]),
|
|
overflow1 = sideOffset - initialPos,
|
|
overflow2 = initialPos + elemLength - (lengthName === WIDTH ? viewportWidth : viewportHeight) - sideOffset,
|
|
offset = myLength - (my.precedance === side || mySide === my[otherSide] ? atLength : 0) - (atSide === CENTER ? targetLength / 2 : 0);
|
|
|
|
// shift
|
|
if(isShift) {
|
|
offset = (mySide === side1 ? 1 : -1) * myLength;
|
|
|
|
// Adjust position but keep it within viewport dimensions
|
|
position[side1] += overflow1 > 0 ? overflow1 : overflow2 > 0 ? -overflow2 : 0;
|
|
position[side1] = Math.max(
|
|
-containerOffset[side1] + viewportOffset[side1],
|
|
initialPos - offset,
|
|
Math.min(
|
|
Math.max(
|
|
-containerOffset[side1] + viewportOffset[side1] + (lengthName === WIDTH ? viewportWidth : viewportHeight),
|
|
initialPos + offset
|
|
),
|
|
position[side1],
|
|
|
|
// Make sure we don't adjust complete off the element when using 'center'
|
|
mySide === 'center' ? initialPos - myLength : 1E9
|
|
)
|
|
);
|
|
|
|
}
|
|
|
|
// flip/flipinvert
|
|
else {
|
|
// Update adjustment amount depending on if using flipinvert or flip
|
|
adjustment *= type === FLIPINVERT ? 2 : 0;
|
|
|
|
// Check for overflow on the left/top
|
|
if(overflow1 > 0 && (mySide !== side1 || overflow2 > 0)) {
|
|
position[side1] -= offset + adjustment;
|
|
newMy.invert(side, side1);
|
|
}
|
|
|
|
// Check for overflow on the bottom/right
|
|
else if(overflow2 > 0 && (mySide !== side2 || overflow1 > 0) ) {
|
|
position[side1] -= (mySide === CENTER ? -offset : offset) + adjustment;
|
|
newMy.invert(side, side2);
|
|
}
|
|
|
|
// Make sure we haven't made things worse with the adjustment and reset if so
|
|
if(position[side1] < viewportScroll[side1] && -position[side1] > overflow2) {
|
|
position[side1] = initialPos; newMy = my.clone();
|
|
}
|
|
}
|
|
|
|
return position[side1] - initialPos;
|
|
}
|
|
|
|
// Set newMy if using flip or flipinvert methods
|
|
if(methodX !== 'shift' || methodY !== 'shift') { newMy = my.clone(); }
|
|
|
|
// Adjust position based onviewport and adjustment options
|
|
adjusted = {
|
|
left: methodX !== 'none' ? calculate( X, Y, methodX, adjust.x, LEFT, RIGHT, WIDTH, targetWidth, elemWidth ) : 0,
|
|
top: methodY !== 'none' ? calculate( Y, X, methodY, adjust.y, TOP, BOTTOM, HEIGHT, targetHeight, elemHeight ) : 0,
|
|
my: newMy
|
|
};
|
|
|
|
return adjusted;
|
|
};
|
|
;PLUGINS.polys = {
|
|
// POLY area coordinate calculator
|
|
// Special thanks to Ed Cradock for helping out with this.
|
|
// Uses a binary search algorithm to find suitable coordinates.
|
|
polygon: function(baseCoords, corner) {
|
|
var result = {
|
|
width: 0, height: 0,
|
|
position: {
|
|
top: 1e10, right: 0,
|
|
bottom: 0, left: 1e10
|
|
},
|
|
adjustable: FALSE
|
|
},
|
|
i = 0, next,
|
|
coords = [],
|
|
compareX = 1, compareY = 1,
|
|
realX = 0, realY = 0,
|
|
newWidth, newHeight;
|
|
|
|
// First pass, sanitize coords and determine outer edges
|
|
i = baseCoords.length;
|
|
while(i--) {
|
|
next = [ parseInt(baseCoords[--i], 10), parseInt(baseCoords[i+1], 10) ];
|
|
|
|
if(next[0] > result.position.right){ result.position.right = next[0]; }
|
|
if(next[0] < result.position.left){ result.position.left = next[0]; }
|
|
if(next[1] > result.position.bottom){ result.position.bottom = next[1]; }
|
|
if(next[1] < result.position.top){ result.position.top = next[1]; }
|
|
|
|
coords.push(next);
|
|
}
|
|
|
|
// Calculate height and width from outer edges
|
|
newWidth = result.width = Math.abs(result.position.right - result.position.left);
|
|
newHeight = result.height = Math.abs(result.position.bottom - result.position.top);
|
|
|
|
// If it's the center corner...
|
|
if(corner.abbrev() === 'c') {
|
|
result.position = {
|
|
left: result.position.left + result.width / 2,
|
|
top: result.position.top + result.height / 2
|
|
};
|
|
}
|
|
else {
|
|
// Second pass, use a binary search algorithm to locate most suitable coordinate
|
|
while(newWidth > 0 && newHeight > 0 && compareX > 0 && compareY > 0)
|
|
{
|
|
newWidth = Math.floor(newWidth / 2);
|
|
newHeight = Math.floor(newHeight / 2);
|
|
|
|
if(corner.x === LEFT){ compareX = newWidth; }
|
|
else if(corner.x === RIGHT){ compareX = result.width - newWidth; }
|
|
else{ compareX += Math.floor(newWidth / 2); }
|
|
|
|
if(corner.y === TOP){ compareY = newHeight; }
|
|
else if(corner.y === BOTTOM){ compareY = result.height - newHeight; }
|
|
else{ compareY += Math.floor(newHeight / 2); }
|
|
|
|
i = coords.length;
|
|
while(i--)
|
|
{
|
|
if(coords.length < 2){ break; }
|
|
|
|
realX = coords[i][0] - result.position.left;
|
|
realY = coords[i][1] - result.position.top;
|
|
|
|
if(
|
|
corner.x === LEFT && realX >= compareX ||
|
|
corner.x === RIGHT && realX <= compareX ||
|
|
corner.x === CENTER && (realX < compareX || realX > result.width - compareX) ||
|
|
corner.y === TOP && realY >= compareY ||
|
|
corner.y === BOTTOM && realY <= compareY ||
|
|
corner.y === CENTER && (realY < compareY || realY > result.height - compareY)) {
|
|
coords.splice(i, 1);
|
|
}
|
|
}
|
|
}
|
|
result.position = { left: coords[0][0], top: coords[0][1] };
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
rect: function(ax, ay, bx, by) {
|
|
return {
|
|
width: Math.abs(bx - ax),
|
|
height: Math.abs(by - ay),
|
|
position: {
|
|
left: Math.min(ax, bx),
|
|
top: Math.min(ay, by)
|
|
}
|
|
};
|
|
},
|
|
|
|
_angles: {
|
|
tc: 3 / 2, tr: 7 / 4, tl: 5 / 4,
|
|
bc: 1 / 2, br: 1 / 4, bl: 3 / 4,
|
|
rc: 2, lc: 1, c: 0
|
|
},
|
|
ellipse: function(cx, cy, rx, ry, corner) {
|
|
var c = PLUGINS.polys._angles[ corner.abbrev() ],
|
|
rxc = c === 0 ? 0 : rx * Math.cos( c * Math.PI ),
|
|
rys = ry * Math.sin( c * Math.PI );
|
|
|
|
return {
|
|
width: rx * 2 - Math.abs(rxc),
|
|
height: ry * 2 - Math.abs(rys),
|
|
position: {
|
|
left: cx + rxc,
|
|
top: cy + rys
|
|
},
|
|
adjustable: FALSE
|
|
};
|
|
},
|
|
circle: function(cx, cy, r, corner) {
|
|
return PLUGINS.polys.ellipse(cx, cy, r, r, corner);
|
|
}
|
|
};
|
|
;PLUGINS.svg = function(api, svg, corner)
|
|
{
|
|
var elem = svg[0],
|
|
root = $(elem.ownerSVGElement),
|
|
ownerDocument = elem.ownerDocument,
|
|
strokeWidth2 = (parseInt(svg.css('stroke-width'), 10) || 0) / 2,
|
|
frameOffset, mtx, transformed,
|
|
len, next, i, points,
|
|
result, position;
|
|
|
|
// Ascend the parentNode chain until we find an element with getBBox()
|
|
while(!elem.getBBox) { elem = elem.parentNode; }
|
|
if(!elem.getBBox || !elem.parentNode) { return FALSE; }
|
|
|
|
// Determine which shape calculation to use
|
|
switch(elem.nodeName) {
|
|
case 'ellipse':
|
|
case 'circle':
|
|
result = PLUGINS.polys.ellipse(
|
|
elem.cx.baseVal.value,
|
|
elem.cy.baseVal.value,
|
|
(elem.rx || elem.r).baseVal.value + strokeWidth2,
|
|
(elem.ry || elem.r).baseVal.value + strokeWidth2,
|
|
corner
|
|
);
|
|
break;
|
|
|
|
case 'line':
|
|
case 'polygon':
|
|
case 'polyline':
|
|
// Determine points object (line has none, so mimic using array)
|
|
points = elem.points || [
|
|
{ x: elem.x1.baseVal.value, y: elem.y1.baseVal.value },
|
|
{ x: elem.x2.baseVal.value, y: elem.y2.baseVal.value }
|
|
];
|
|
|
|
for(result = [], i = -1, len = points.numberOfItems || points.length; ++i < len;) {
|
|
next = points.getItem ? points.getItem(i) : points[i];
|
|
result.push.apply(result, [next.x, next.y]);
|
|
}
|
|
|
|
result = PLUGINS.polys.polygon(result, corner);
|
|
break;
|
|
|
|
// Unknown shape or rectangle? Use bounding box
|
|
default:
|
|
result = elem.getBBox();
|
|
result = {
|
|
width: result.width,
|
|
height: result.height,
|
|
position: {
|
|
left: result.x,
|
|
top: result.y
|
|
}
|
|
};
|
|
break;
|
|
}
|
|
|
|
// Shortcut assignments
|
|
position = result.position;
|
|
root = root[0];
|
|
|
|
// Convert position into a pixel value
|
|
if(root.createSVGPoint) {
|
|
mtx = elem.getScreenCTM();
|
|
points = root.createSVGPoint();
|
|
|
|
points.x = position.left;
|
|
points.y = position.top;
|
|
transformed = points.matrixTransform( mtx );
|
|
position.left = transformed.x;
|
|
position.top = transformed.y;
|
|
}
|
|
|
|
// Check the element is not in a child document, and if so, adjust for frame elements offset
|
|
if(ownerDocument !== document && api.position.target !== 'mouse') {
|
|
frameOffset = $((ownerDocument.defaultView || ownerDocument.parentWindow).frameElement).offset();
|
|
if(frameOffset) {
|
|
position.left += frameOffset.left;
|
|
position.top += frameOffset.top;
|
|
}
|
|
}
|
|
|
|
// Adjust by scroll offset of owner document
|
|
ownerDocument = $(ownerDocument);
|
|
position.left += ownerDocument.scrollLeft();
|
|
position.top += ownerDocument.scrollTop();
|
|
|
|
return result;
|
|
};
|
|
;PLUGINS.imagemap = function(api, area, corner)
|
|
{
|
|
if(!area.jquery) { area = $(area); }
|
|
|
|
var shape = (area.attr('shape') || 'rect').toLowerCase().replace('poly', 'polygon'),
|
|
image = $('img[usemap="#'+area.parent('map').attr('name')+'"]'),
|
|
coordsString = $.trim(area.attr('coords')),
|
|
coordsArray = coordsString.replace(/,$/, '').split(','),
|
|
imageOffset, coords, i, result, len;
|
|
|
|
// If we can't find the image using the map...
|
|
if(!image.length) { return FALSE; }
|
|
|
|
// Pass coordinates string if polygon
|
|
if(shape === 'polygon') {
|
|
result = PLUGINS.polys.polygon(coordsArray, corner);
|
|
}
|
|
|
|
// Otherwise parse the coordinates and pass them as arguments
|
|
else if(PLUGINS.polys[shape]) {
|
|
for(i = -1, len = coordsArray.length, coords = []; ++i < len;) {
|
|
coords.push( parseInt(coordsArray[i], 10) );
|
|
}
|
|
|
|
result = PLUGINS.polys[shape].apply(
|
|
this, coords.concat(corner)
|
|
);
|
|
}
|
|
|
|
// If no shapre calculation method was found, return false
|
|
else { return FALSE; }
|
|
|
|
// Make sure we account for padding and borders on the image
|
|
imageOffset = image.offset();
|
|
imageOffset.left += Math.ceil((image.outerWidth(FALSE) - image.width()) / 2);
|
|
imageOffset.top += Math.ceil((image.outerHeight(FALSE) - image.height()) / 2);
|
|
|
|
// Add image position to offset coordinates
|
|
result.position.left += imageOffset.left;
|
|
result.position.top += imageOffset.top;
|
|
|
|
return result;
|
|
};
|
|
;var IE6,
|
|
|
|
/*
|
|
* BGIFrame adaption (http://plugins.jquery.com/project/bgiframe)
|
|
* Special thanks to Brandon Aaron
|
|
*/
|
|
BGIFRAME = '<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:\'\';" ' +
|
|
' style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=0); ' +
|
|
'-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";"></iframe>';
|
|
|
|
function Ie6(api) {
|
|
this._ns = 'ie6';
|
|
|
|
this.qtip = api;
|
|
this.init(api);
|
|
}
|
|
|
|
$.extend(Ie6.prototype, {
|
|
_scroll : function() {
|
|
var overlay = this.qtip.elements.overlay;
|
|
overlay && (overlay[0].style.top = $(window).scrollTop() + 'px');
|
|
},
|
|
|
|
init: function(qtip) {
|
|
var tooltip = qtip.tooltip;
|
|
|
|
// Create the BGIFrame element if needed
|
|
if($('select, object').length < 1) {
|
|
this.bgiframe = qtip.elements.bgiframe = $(BGIFRAME).appendTo(tooltip);
|
|
|
|
// Update BGIFrame on tooltip move
|
|
qtip._bind(tooltip, 'tooltipmove', this.adjustBGIFrame, this._ns, this);
|
|
}
|
|
|
|
// redraw() container for width/height calculations
|
|
this.redrawContainer = $('<div/>', { id: NAMESPACE+'-rcontainer' })
|
|
.appendTo(document.body);
|
|
|
|
// Fixup modal plugin if present too
|
|
if( qtip.elements.overlay && qtip.elements.overlay.addClass('qtipmodal-ie6fix') ) {
|
|
qtip._bind(window, ['scroll', 'resize'], this._scroll, this._ns, this);
|
|
qtip._bind(tooltip, ['tooltipshow'], this._scroll, this._ns, this);
|
|
}
|
|
|
|
// Set dimensions
|
|
this.redraw();
|
|
},
|
|
|
|
adjustBGIFrame: function() {
|
|
var tooltip = this.qtip.tooltip,
|
|
dimensions = {
|
|
height: tooltip.outerHeight(FALSE),
|
|
width: tooltip.outerWidth(FALSE)
|
|
},
|
|
plugin = this.qtip.plugins.tip,
|
|
tip = this.qtip.elements.tip,
|
|
tipAdjust, offset;
|
|
|
|
// Adjust border offset
|
|
offset = parseInt(tooltip.css('borderLeftWidth'), 10) || 0;
|
|
offset = { left: -offset, top: -offset };
|
|
|
|
// Adjust for tips plugin
|
|
if(plugin && tip) {
|
|
tipAdjust = plugin.corner.precedance === 'x' ? [WIDTH, LEFT] : [HEIGHT, TOP];
|
|
offset[ tipAdjust[1] ] -= tip[ tipAdjust[0] ]();
|
|
}
|
|
|
|
// Update bgiframe
|
|
this.bgiframe.css(offset).css(dimensions);
|
|
},
|
|
|
|
// Max/min width simulator function
|
|
redraw: function() {
|
|
if(this.qtip.rendered < 1 || this.drawing) { return this; }
|
|
|
|
var tooltip = this.qtip.tooltip,
|
|
style = this.qtip.options.style,
|
|
container = this.qtip.options.position.container,
|
|
perc, width, max, min;
|
|
|
|
// Set drawing flag
|
|
this.qtip.drawing = 1;
|
|
|
|
// If tooltip has a set height/width, just set it... like a boss!
|
|
if(style.height) { tooltip.css(HEIGHT, style.height); }
|
|
if(style.width) { tooltip.css(WIDTH, style.width); }
|
|
|
|
// Simulate max/min width if not set width present...
|
|
else {
|
|
// Reset width and add fluid class
|
|
tooltip.css(WIDTH, '').appendTo(this.redrawContainer);
|
|
|
|
// Grab our tooltip width (add 1 if odd so we don't get wrapping problems.. huzzah!)
|
|
width = tooltip.width();
|
|
if(width % 2 < 1) { width += 1; }
|
|
|
|
// Grab our max/min properties
|
|
max = tooltip.css('maxWidth') || '';
|
|
min = tooltip.css('minWidth') || '';
|
|
|
|
// Parse into proper pixel values
|
|
perc = (max + min).indexOf('%') > -1 ? container.width() / 100 : 0;
|
|
max = (max.indexOf('%') > -1 ? perc : 1 * parseInt(max, 10)) || width;
|
|
min = (min.indexOf('%') > -1 ? perc : 1 * parseInt(min, 10)) || 0;
|
|
|
|
// Determine new dimension size based on max/min/current values
|
|
width = max + min ? Math.min(Math.max(width, min), max) : width;
|
|
|
|
// Set the newly calculated width and remvoe fluid class
|
|
tooltip.css(WIDTH, Math.round(width)).appendTo(container);
|
|
}
|
|
|
|
// Set drawing flag
|
|
this.drawing = 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
destroy: function() {
|
|
// Remove iframe
|
|
this.bgiframe && this.bgiframe.remove();
|
|
|
|
// Remove bound events
|
|
this.qtip._unbind([window, this.qtip.tooltip], this._ns);
|
|
}
|
|
});
|
|
|
|
IE6 = PLUGINS.ie6 = function(api) {
|
|
// Proceed only if the browser is IE6
|
|
return BROWSER.ie === 6 ? new Ie6(api) : FALSE;
|
|
};
|
|
|
|
IE6.initialize = 'render';
|
|
|
|
CHECKS.ie6 = {
|
|
'^content|style$': function() {
|
|
this.redraw();
|
|
}
|
|
};
|
|
;}));
|
|
}( window, document ));
|
|
|
|
|
|
/***/ }),
|
|
/* 73 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// extracted by mini-css-extract-plugin
|
|
|
|
/***/ }),
|
|
/* 74 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* WEBPACK VAR INJECTION */(function(console) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var require;var require;/*!
|
|
* Select2 4.0.13
|
|
* https://select2.github.io
|
|
*
|
|
* Released under the MIT license
|
|
* https://github.com/select2/select2/blob/master/LICENSE.md
|
|
*/
|
|
;(function (factory) {
|
|
if (true) {
|
|
// AMD. Register as an anonymous module.
|
|
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(2)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
} else {}
|
|
} (function (jQuery) {
|
|
// This is needed so we can catch the AMD loader configuration and use it
|
|
// The inner file should be wrapped (by `banner.start.js`) in a function that
|
|
// returns the AMD loader references.
|
|
var S2 =(function () {
|
|
// Restore the Select2 AMD loader so it can be used
|
|
// Needed mostly in the language files, where the loader is not inserted
|
|
if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
|
|
var S2 = jQuery.fn.select2.amd;
|
|
}
|
|
var S2;(function () { if (!S2 || !S2.requirejs) {
|
|
if (!S2) { S2 = {}; } else { require = S2; }
|
|
/**
|
|
* @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
|
|
* Released under MIT license, http://github.com/requirejs/almond/LICENSE
|
|
*/
|
|
//Going sloppy to avoid 'use strict' string cost, but strict practices should
|
|
//be followed.
|
|
/*global setTimeout: false */
|
|
|
|
var requirejs, require, define;
|
|
(function (undef) {
|
|
var main, req, makeMap, handlers,
|
|
defined = {},
|
|
waiting = {},
|
|
config = {},
|
|
defining = {},
|
|
hasOwn = Object.prototype.hasOwnProperty,
|
|
aps = [].slice,
|
|
jsSuffixRegExp = /\.js$/;
|
|
|
|
function hasProp(obj, prop) {
|
|
return hasOwn.call(obj, prop);
|
|
}
|
|
|
|
/**
|
|
* Given a relative module name, like ./something, normalize it to
|
|
* a real name that can be mapped to a path.
|
|
* @param {String} name the relative name
|
|
* @param {String} baseName a real name that the name arg is relative
|
|
* to.
|
|
* @returns {String} normalized name
|
|
*/
|
|
function normalize(name, baseName) {
|
|
var nameParts, nameSegment, mapValue, foundMap, lastIndex,
|
|
foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
|
|
baseParts = baseName && baseName.split("/"),
|
|
map = config.map,
|
|
starMap = (map && map['*']) || {};
|
|
|
|
//Adjust any relative paths.
|
|
if (name) {
|
|
name = name.split('/');
|
|
lastIndex = name.length - 1;
|
|
|
|
// If wanting node ID compatibility, strip .js from end
|
|
// of IDs. Have to do this here, and not in nameToUrl
|
|
// because node allows either .js or non .js to map
|
|
// to same file.
|
|
if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
|
|
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
|
|
}
|
|
|
|
// Starts with a '.' so need the baseName
|
|
if (name[0].charAt(0) === '.' && baseParts) {
|
|
//Convert baseName to array, and lop off the last part,
|
|
//so that . matches that 'directory' and not name of the baseName's
|
|
//module. For instance, baseName of 'one/two/three', maps to
|
|
//'one/two/three.js', but we want the directory, 'one/two' for
|
|
//this normalization.
|
|
normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
|
|
name = normalizedBaseParts.concat(name);
|
|
}
|
|
|
|
//start trimDots
|
|
for (i = 0; i < name.length; i++) {
|
|
part = name[i];
|
|
if (part === '.') {
|
|
name.splice(i, 1);
|
|
i -= 1;
|
|
} else if (part === '..') {
|
|
// If at the start, or previous value is still ..,
|
|
// keep them so that when converted to a path it may
|
|
// still work when converted to a path, even though
|
|
// as an ID it is less than ideal. In larger point
|
|
// releases, may be better to just kick out an error.
|
|
if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
|
|
continue;
|
|
} else if (i > 0) {
|
|
name.splice(i - 1, 2);
|
|
i -= 2;
|
|
}
|
|
}
|
|
}
|
|
//end trimDots
|
|
|
|
name = name.join('/');
|
|
}
|
|
|
|
//Apply map config if available.
|
|
if ((baseParts || starMap) && map) {
|
|
nameParts = name.split('/');
|
|
|
|
for (i = nameParts.length; i > 0; i -= 1) {
|
|
nameSegment = nameParts.slice(0, i).join("/");
|
|
|
|
if (baseParts) {
|
|
//Find the longest baseName segment match in the config.
|
|
//So, do joins on the biggest to smallest lengths of baseParts.
|
|
for (j = baseParts.length; j > 0; j -= 1) {
|
|
mapValue = map[baseParts.slice(0, j).join('/')];
|
|
|
|
//baseName segment has config, find if it has one for
|
|
//this name.
|
|
if (mapValue) {
|
|
mapValue = mapValue[nameSegment];
|
|
if (mapValue) {
|
|
//Match, update name to the new value.
|
|
foundMap = mapValue;
|
|
foundI = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (foundMap) {
|
|
break;
|
|
}
|
|
|
|
//Check for a star map match, but just hold on to it,
|
|
//if there is a shorter segment match later in a matching
|
|
//config, then favor over this star map.
|
|
if (!foundStarMap && starMap && starMap[nameSegment]) {
|
|
foundStarMap = starMap[nameSegment];
|
|
starI = i;
|
|
}
|
|
}
|
|
|
|
if (!foundMap && foundStarMap) {
|
|
foundMap = foundStarMap;
|
|
foundI = starI;
|
|
}
|
|
|
|
if (foundMap) {
|
|
nameParts.splice(0, foundI, foundMap);
|
|
name = nameParts.join('/');
|
|
}
|
|
}
|
|
|
|
return name;
|
|
}
|
|
|
|
function makeRequire(relName, forceSync) {
|
|
return function () {
|
|
//A version of a require function that passes a moduleName
|
|
//value for items that may need to
|
|
//look up paths relative to the moduleName
|
|
var args = aps.call(arguments, 0);
|
|
|
|
//If first arg is not require('string'), and there is only
|
|
//one arg, it is the array form without a callback. Insert
|
|
//a null so that the following concat is correct.
|
|
if (typeof args[0] !== 'string' && args.length === 1) {
|
|
args.push(null);
|
|
}
|
|
return req.apply(undef, args.concat([relName, forceSync]));
|
|
};
|
|
}
|
|
|
|
function makeNormalize(relName) {
|
|
return function (name) {
|
|
return normalize(name, relName);
|
|
};
|
|
}
|
|
|
|
function makeLoad(depName) {
|
|
return function (value) {
|
|
defined[depName] = value;
|
|
};
|
|
}
|
|
|
|
function callDep(name) {
|
|
if (hasProp(waiting, name)) {
|
|
var args = waiting[name];
|
|
delete waiting[name];
|
|
defining[name] = true;
|
|
main.apply(undef, args);
|
|
}
|
|
|
|
if (!hasProp(defined, name) && !hasProp(defining, name)) {
|
|
throw new Error('No ' + name);
|
|
}
|
|
return defined[name];
|
|
}
|
|
|
|
//Turns a plugin!resource to [plugin, resource]
|
|
//with the plugin being undefined if the name
|
|
//did not have a plugin prefix.
|
|
function splitPrefix(name) {
|
|
var prefix,
|
|
index = name ? name.indexOf('!') : -1;
|
|
if (index > -1) {
|
|
prefix = name.substring(0, index);
|
|
name = name.substring(index + 1, name.length);
|
|
}
|
|
return [prefix, name];
|
|
}
|
|
|
|
//Creates a parts array for a relName where first part is plugin ID,
|
|
//second part is resource ID. Assumes relName has already been normalized.
|
|
function makeRelParts(relName) {
|
|
return relName ? splitPrefix(relName) : [];
|
|
}
|
|
|
|
/**
|
|
* Makes a name map, normalizing the name, and using a plugin
|
|
* for normalization if necessary. Grabs a ref to plugin
|
|
* too, as an optimization.
|
|
*/
|
|
makeMap = function (name, relParts) {
|
|
var plugin,
|
|
parts = splitPrefix(name),
|
|
prefix = parts[0],
|
|
relResourceName = relParts[1];
|
|
|
|
name = parts[1];
|
|
|
|
if (prefix) {
|
|
prefix = normalize(prefix, relResourceName);
|
|
plugin = callDep(prefix);
|
|
}
|
|
|
|
//Normalize according
|
|
if (prefix) {
|
|
if (plugin && plugin.normalize) {
|
|
name = plugin.normalize(name, makeNormalize(relResourceName));
|
|
} else {
|
|
name = normalize(name, relResourceName);
|
|
}
|
|
} else {
|
|
name = normalize(name, relResourceName);
|
|
parts = splitPrefix(name);
|
|
prefix = parts[0];
|
|
name = parts[1];
|
|
if (prefix) {
|
|
plugin = callDep(prefix);
|
|
}
|
|
}
|
|
|
|
//Using ridiculous property names for space reasons
|
|
return {
|
|
f: prefix ? prefix + '!' + name : name, //fullName
|
|
n: name,
|
|
pr: prefix,
|
|
p: plugin
|
|
};
|
|
};
|
|
|
|
function makeConfig(name) {
|
|
return function () {
|
|
return (config && config.config && config.config[name]) || {};
|
|
};
|
|
}
|
|
|
|
handlers = {
|
|
require: function (name) {
|
|
return makeRequire(name);
|
|
},
|
|
exports: function (name) {
|
|
var e = defined[name];
|
|
if (typeof e !== 'undefined') {
|
|
return e;
|
|
} else {
|
|
return (defined[name] = {});
|
|
}
|
|
},
|
|
module: function (name) {
|
|
return {
|
|
id: name,
|
|
uri: '',
|
|
exports: defined[name],
|
|
config: makeConfig(name)
|
|
};
|
|
}
|
|
};
|
|
|
|
main = function (name, deps, callback, relName) {
|
|
var cjsModule, depName, ret, map, i, relParts,
|
|
args = [],
|
|
callbackType = typeof callback,
|
|
usingExports;
|
|
|
|
//Use name if no relName
|
|
relName = relName || name;
|
|
relParts = makeRelParts(relName);
|
|
|
|
//Call the callback to define the module, if necessary.
|
|
if (callbackType === 'undefined' || callbackType === 'function') {
|
|
//Pull out the defined dependencies and pass the ordered
|
|
//values to the callback.
|
|
//Default to [require, exports, module] if no deps
|
|
deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
|
|
for (i = 0; i < deps.length; i += 1) {
|
|
map = makeMap(deps[i], relParts);
|
|
depName = map.f;
|
|
|
|
//Fast path CommonJS standard dependencies.
|
|
if (depName === "require") {
|
|
args[i] = handlers.require(name);
|
|
} else if (depName === "exports") {
|
|
//CommonJS module spec 1.1
|
|
args[i] = handlers.exports(name);
|
|
usingExports = true;
|
|
} else if (depName === "module") {
|
|
//CommonJS module spec 1.1
|
|
cjsModule = args[i] = handlers.module(name);
|
|
} else if (hasProp(defined, depName) ||
|
|
hasProp(waiting, depName) ||
|
|
hasProp(defining, depName)) {
|
|
args[i] = callDep(depName);
|
|
} else if (map.p) {
|
|
map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
|
|
args[i] = defined[depName];
|
|
} else {
|
|
throw new Error(name + ' missing ' + depName);
|
|
}
|
|
}
|
|
|
|
ret = callback ? callback.apply(defined[name], args) : undefined;
|
|
|
|
if (name) {
|
|
//If setting exports via "module" is in play,
|
|
//favor that over return value and exports. After that,
|
|
//favor a non-undefined return value over exports use.
|
|
if (cjsModule && cjsModule.exports !== undef &&
|
|
cjsModule.exports !== defined[name]) {
|
|
defined[name] = cjsModule.exports;
|
|
} else if (ret !== undef || !usingExports) {
|
|
//Use the return value from the function.
|
|
defined[name] = ret;
|
|
}
|
|
}
|
|
} else if (name) {
|
|
//May just be an object definition for the module. Only
|
|
//worry about defining if have a module name.
|
|
defined[name] = callback;
|
|
}
|
|
};
|
|
|
|
requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
|
|
if (typeof deps === "string") {
|
|
if (handlers[deps]) {
|
|
//callback in this case is really relName
|
|
return handlers[deps](callback);
|
|
}
|
|
//Just return the module wanted. In this scenario, the
|
|
//deps arg is the module name, and second arg (if passed)
|
|
//is just the relName.
|
|
//Normalize module name, if it contains . or ..
|
|
return callDep(makeMap(deps, makeRelParts(callback)).f);
|
|
} else if (!deps.splice) {
|
|
//deps is a config object, not an array.
|
|
config = deps;
|
|
if (config.deps) {
|
|
req(config.deps, config.callback);
|
|
}
|
|
if (!callback) {
|
|
return;
|
|
}
|
|
|
|
if (callback.splice) {
|
|
//callback is an array, which means it is a dependency list.
|
|
//Adjust args if there are dependencies
|
|
deps = callback;
|
|
callback = relName;
|
|
relName = null;
|
|
} else {
|
|
deps = undef;
|
|
}
|
|
}
|
|
|
|
//Support require(['a'])
|
|
callback = callback || function () {};
|
|
|
|
//If relName is a function, it is an errback handler,
|
|
//so remove it.
|
|
if (typeof relName === 'function') {
|
|
relName = forceSync;
|
|
forceSync = alt;
|
|
}
|
|
|
|
//Simulate async callback;
|
|
if (forceSync) {
|
|
main(undef, deps, callback, relName);
|
|
} else {
|
|
//Using a non-zero value because of concern for what old browsers
|
|
//do, and latest browsers "upgrade" to 4 if lower value is used:
|
|
//http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
|
|
//If want a value immediately, use require('id') instead -- something
|
|
//that works in almond on the global level, but not guaranteed and
|
|
//unlikely to work in other AMD implementations.
|
|
setTimeout(function () {
|
|
main(undef, deps, callback, relName);
|
|
}, 4);
|
|
}
|
|
|
|
return req;
|
|
};
|
|
|
|
/**
|
|
* Just drops the config on the floor, but returns req in case
|
|
* the config return value is used.
|
|
*/
|
|
req.config = function (cfg) {
|
|
return req(cfg);
|
|
};
|
|
|
|
/**
|
|
* Expose module registry for debugging and tooling
|
|
*/
|
|
requirejs._defined = defined;
|
|
|
|
define = function (name, deps, callback) {
|
|
if (typeof name !== 'string') {
|
|
throw new Error('See almond README: incorrect module build, no module name');
|
|
}
|
|
|
|
//This module may not have dependencies
|
|
if (!deps.splice) {
|
|
//deps is not an array, so probably means
|
|
//an object literal or factory function for
|
|
//the value. Adjust args.
|
|
callback = deps;
|
|
deps = [];
|
|
}
|
|
|
|
if (!hasProp(defined, name) && !hasProp(waiting, name)) {
|
|
waiting[name] = [name, deps, callback];
|
|
}
|
|
};
|
|
|
|
define.amd = {
|
|
jQuery: true
|
|
};
|
|
}());
|
|
|
|
S2.requirejs = requirejs;S2.require = require;S2.define = define;
|
|
}
|
|
}());
|
|
S2.define("almond", function(){});
|
|
|
|
/* global jQuery:false, $:false */
|
|
S2.define('jquery',[],function () {
|
|
var _$ = jQuery || $;
|
|
|
|
if (_$ == null && console && console.error) {
|
|
console.error(
|
|
'Select2: An instance of jQuery or a jQuery-compatible library was not ' +
|
|
'found. Make sure that you are including jQuery before Select2 on your ' +
|
|
'web page.'
|
|
);
|
|
}
|
|
|
|
return _$;
|
|
});
|
|
|
|
S2.define('select2/utils',[
|
|
'jquery'
|
|
], function ($) {
|
|
var Utils = {};
|
|
|
|
Utils.Extend = function (ChildClass, SuperClass) {
|
|
var __hasProp = {}.hasOwnProperty;
|
|
|
|
function BaseConstructor () {
|
|
this.constructor = ChildClass;
|
|
}
|
|
|
|
for (var key in SuperClass) {
|
|
if (__hasProp.call(SuperClass, key)) {
|
|
ChildClass[key] = SuperClass[key];
|
|
}
|
|
}
|
|
|
|
BaseConstructor.prototype = SuperClass.prototype;
|
|
ChildClass.prototype = new BaseConstructor();
|
|
ChildClass.__super__ = SuperClass.prototype;
|
|
|
|
return ChildClass;
|
|
};
|
|
|
|
function getMethods (theClass) {
|
|
var proto = theClass.prototype;
|
|
|
|
var methods = [];
|
|
|
|
for (var methodName in proto) {
|
|
var m = proto[methodName];
|
|
|
|
if (typeof m !== 'function') {
|
|
continue;
|
|
}
|
|
|
|
if (methodName === 'constructor') {
|
|
continue;
|
|
}
|
|
|
|
methods.push(methodName);
|
|
}
|
|
|
|
return methods;
|
|
}
|
|
|
|
Utils.Decorate = function (SuperClass, DecoratorClass) {
|
|
var decoratedMethods = getMethods(DecoratorClass);
|
|
var superMethods = getMethods(SuperClass);
|
|
|
|
function DecoratedClass () {
|
|
var unshift = Array.prototype.unshift;
|
|
|
|
var argCount = DecoratorClass.prototype.constructor.length;
|
|
|
|
var calledConstructor = SuperClass.prototype.constructor;
|
|
|
|
if (argCount > 0) {
|
|
unshift.call(arguments, SuperClass.prototype.constructor);
|
|
|
|
calledConstructor = DecoratorClass.prototype.constructor;
|
|
}
|
|
|
|
calledConstructor.apply(this, arguments);
|
|
}
|
|
|
|
DecoratorClass.displayName = SuperClass.displayName;
|
|
|
|
function ctr () {
|
|
this.constructor = DecoratedClass;
|
|
}
|
|
|
|
DecoratedClass.prototype = new ctr();
|
|
|
|
for (var m = 0; m < superMethods.length; m++) {
|
|
var superMethod = superMethods[m];
|
|
|
|
DecoratedClass.prototype[superMethod] =
|
|
SuperClass.prototype[superMethod];
|
|
}
|
|
|
|
var calledMethod = function (methodName) {
|
|
// Stub out the original method if it's not decorating an actual method
|
|
var originalMethod = function () {};
|
|
|
|
if (methodName in DecoratedClass.prototype) {
|
|
originalMethod = DecoratedClass.prototype[methodName];
|
|
}
|
|
|
|
var decoratedMethod = DecoratorClass.prototype[methodName];
|
|
|
|
return function () {
|
|
var unshift = Array.prototype.unshift;
|
|
|
|
unshift.call(arguments, originalMethod);
|
|
|
|
return decoratedMethod.apply(this, arguments);
|
|
};
|
|
};
|
|
|
|
for (var d = 0; d < decoratedMethods.length; d++) {
|
|
var decoratedMethod = decoratedMethods[d];
|
|
|
|
DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);
|
|
}
|
|
|
|
return DecoratedClass;
|
|
};
|
|
|
|
var Observable = function () {
|
|
this.listeners = {};
|
|
};
|
|
|
|
Observable.prototype.on = function (event, callback) {
|
|
this.listeners = this.listeners || {};
|
|
|
|
if (event in this.listeners) {
|
|
this.listeners[event].push(callback);
|
|
} else {
|
|
this.listeners[event] = [callback];
|
|
}
|
|
};
|
|
|
|
Observable.prototype.trigger = function (event) {
|
|
var slice = Array.prototype.slice;
|
|
var params = slice.call(arguments, 1);
|
|
|
|
this.listeners = this.listeners || {};
|
|
|
|
// Params should always come in as an array
|
|
if (params == null) {
|
|
params = [];
|
|
}
|
|
|
|
// If there are no arguments to the event, use a temporary object
|
|
if (params.length === 0) {
|
|
params.push({});
|
|
}
|
|
|
|
// Set the `_type` of the first object to the event
|
|
params[0]._type = event;
|
|
|
|
if (event in this.listeners) {
|
|
this.invoke(this.listeners[event], slice.call(arguments, 1));
|
|
}
|
|
|
|
if ('*' in this.listeners) {
|
|
this.invoke(this.listeners['*'], arguments);
|
|
}
|
|
};
|
|
|
|
Observable.prototype.invoke = function (listeners, params) {
|
|
for (var i = 0, len = listeners.length; i < len; i++) {
|
|
listeners[i].apply(this, params);
|
|
}
|
|
};
|
|
|
|
Utils.Observable = Observable;
|
|
|
|
Utils.generateChars = function (length) {
|
|
var chars = '';
|
|
|
|
for (var i = 0; i < length; i++) {
|
|
var randomChar = Math.floor(Math.random() * 36);
|
|
chars += randomChar.toString(36);
|
|
}
|
|
|
|
return chars;
|
|
};
|
|
|
|
Utils.bind = function (func, context) {
|
|
return function () {
|
|
func.apply(context, arguments);
|
|
};
|
|
};
|
|
|
|
Utils._convertData = function (data) {
|
|
for (var originalKey in data) {
|
|
var keys = originalKey.split('-');
|
|
|
|
var dataLevel = data;
|
|
|
|
if (keys.length === 1) {
|
|
continue;
|
|
}
|
|
|
|
for (var k = 0; k < keys.length; k++) {
|
|
var key = keys[k];
|
|
|
|
// Lowercase the first letter
|
|
// By default, dash-separated becomes camelCase
|
|
key = key.substring(0, 1).toLowerCase() + key.substring(1);
|
|
|
|
if (!(key in dataLevel)) {
|
|
dataLevel[key] = {};
|
|
}
|
|
|
|
if (k == keys.length - 1) {
|
|
dataLevel[key] = data[originalKey];
|
|
}
|
|
|
|
dataLevel = dataLevel[key];
|
|
}
|
|
|
|
delete data[originalKey];
|
|
}
|
|
|
|
return data;
|
|
};
|
|
|
|
Utils.hasScroll = function (index, el) {
|
|
// Adapted from the function created by @ShadowScripter
|
|
// and adapted by @BillBarry on the Stack Exchange Code Review website.
|
|
// The original code can be found at
|
|
// http://codereview.stackexchange.com/q/13338
|
|
// and was designed to be used with the Sizzle selector engine.
|
|
|
|
var $el = $(el);
|
|
var overflowX = el.style.overflowX;
|
|
var overflowY = el.style.overflowY;
|
|
|
|
//Check both x and y declarations
|
|
if (overflowX === overflowY &&
|
|
(overflowY === 'hidden' || overflowY === 'visible')) {
|
|
return false;
|
|
}
|
|
|
|
if (overflowX === 'scroll' || overflowY === 'scroll') {
|
|
return true;
|
|
}
|
|
|
|
return ($el.innerHeight() < el.scrollHeight ||
|
|
$el.innerWidth() < el.scrollWidth);
|
|
};
|
|
|
|
Utils.escapeMarkup = function (markup) {
|
|
var replaceMap = {
|
|
'\\': '\',
|
|
'&': '&',
|
|
'<': '<',
|
|
'>': '>',
|
|
'"': '"',
|
|
'\'': ''',
|
|
'/': '/'
|
|
};
|
|
|
|
// Do not try to escape the markup if it's not a string
|
|
if (typeof markup !== 'string') {
|
|
return markup;
|
|
}
|
|
|
|
return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
|
|
return replaceMap[match];
|
|
});
|
|
};
|
|
|
|
// Append an array of jQuery nodes to a given element.
|
|
Utils.appendMany = function ($element, $nodes) {
|
|
// jQuery 1.7.x does not support $.fn.append() with an array
|
|
// Fall back to a jQuery object collection using $.fn.add()
|
|
if ($.fn.jquery.substr(0, 3) === '1.7') {
|
|
var $jqNodes = $();
|
|
|
|
$.map($nodes, function (node) {
|
|
$jqNodes = $jqNodes.add(node);
|
|
});
|
|
|
|
$nodes = $jqNodes;
|
|
}
|
|
|
|
$element.append($nodes);
|
|
};
|
|
|
|
// Cache objects in Utils.__cache instead of $.data (see #4346)
|
|
Utils.__cache = {};
|
|
|
|
var id = 0;
|
|
Utils.GetUniqueElementId = function (element) {
|
|
// Get a unique element Id. If element has no id,
|
|
// creates a new unique number, stores it in the id
|
|
// attribute and returns the new id.
|
|
// If an id already exists, it simply returns it.
|
|
|
|
var select2Id = element.getAttribute('data-select2-id');
|
|
if (select2Id == null) {
|
|
// If element has id, use it.
|
|
if (element.id) {
|
|
select2Id = element.id;
|
|
element.setAttribute('data-select2-id', select2Id);
|
|
} else {
|
|
element.setAttribute('data-select2-id', ++id);
|
|
select2Id = id.toString();
|
|
}
|
|
}
|
|
return select2Id;
|
|
};
|
|
|
|
Utils.StoreData = function (element, name, value) {
|
|
// Stores an item in the cache for a specified element.
|
|
// name is the cache key.
|
|
var id = Utils.GetUniqueElementId(element);
|
|
if (!Utils.__cache[id]) {
|
|
Utils.__cache[id] = {};
|
|
}
|
|
|
|
Utils.__cache[id][name] = value;
|
|
};
|
|
|
|
Utils.GetData = function (element, name) {
|
|
// Retrieves a value from the cache by its key (name)
|
|
// name is optional. If no name specified, return
|
|
// all cache items for the specified element.
|
|
// and for a specified element.
|
|
var id = Utils.GetUniqueElementId(element);
|
|
if (name) {
|
|
if (Utils.__cache[id]) {
|
|
if (Utils.__cache[id][name] != null) {
|
|
return Utils.__cache[id][name];
|
|
}
|
|
return $(element).data(name); // Fallback to HTML5 data attribs.
|
|
}
|
|
return $(element).data(name); // Fallback to HTML5 data attribs.
|
|
} else {
|
|
return Utils.__cache[id];
|
|
}
|
|
};
|
|
|
|
Utils.RemoveData = function (element) {
|
|
// Removes all cached items for a specified element.
|
|
var id = Utils.GetUniqueElementId(element);
|
|
if (Utils.__cache[id] != null) {
|
|
delete Utils.__cache[id];
|
|
}
|
|
|
|
element.removeAttribute('data-select2-id');
|
|
};
|
|
|
|
return Utils;
|
|
});
|
|
|
|
S2.define('select2/results',[
|
|
'jquery',
|
|
'./utils'
|
|
], function ($, Utils) {
|
|
function Results ($element, options, dataAdapter) {
|
|
this.$element = $element;
|
|
this.data = dataAdapter;
|
|
this.options = options;
|
|
|
|
Results.__super__.constructor.call(this);
|
|
}
|
|
|
|
Utils.Extend(Results, Utils.Observable);
|
|
|
|
Results.prototype.render = function () {
|
|
var $results = $(
|
|
'<ul class="select2-results__options" role="listbox"></ul>'
|
|
);
|
|
|
|
if (this.options.get('multiple')) {
|
|
$results.attr('aria-multiselectable', 'true');
|
|
}
|
|
|
|
this.$results = $results;
|
|
|
|
return $results;
|
|
};
|
|
|
|
Results.prototype.clear = function () {
|
|
this.$results.empty();
|
|
};
|
|
|
|
Results.prototype.displayMessage = function (params) {
|
|
var escapeMarkup = this.options.get('escapeMarkup');
|
|
|
|
this.clear();
|
|
this.hideLoading();
|
|
|
|
var $message = $(
|
|
'<li role="alert" aria-live="assertive"' +
|
|
' class="select2-results__option"></li>'
|
|
);
|
|
|
|
var message = this.options.get('translations').get(params.message);
|
|
|
|
$message.append(
|
|
escapeMarkup(
|
|
message(params.args)
|
|
)
|
|
);
|
|
|
|
$message[0].className += ' select2-results__message';
|
|
|
|
this.$results.append($message);
|
|
};
|
|
|
|
Results.prototype.hideMessages = function () {
|
|
this.$results.find('.select2-results__message').remove();
|
|
};
|
|
|
|
Results.prototype.append = function (data) {
|
|
this.hideLoading();
|
|
|
|
var $options = [];
|
|
|
|
if (data.results == null || data.results.length === 0) {
|
|
if (this.$results.children().length === 0) {
|
|
this.trigger('results:message', {
|
|
message: 'noResults'
|
|
});
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
data.results = this.sort(data.results);
|
|
|
|
for (var d = 0; d < data.results.length; d++) {
|
|
var item = data.results[d];
|
|
|
|
var $option = this.option(item);
|
|
|
|
$options.push($option);
|
|
}
|
|
|
|
this.$results.append($options);
|
|
};
|
|
|
|
Results.prototype.position = function ($results, $dropdown) {
|
|
var $resultsContainer = $dropdown.find('.select2-results');
|
|
$resultsContainer.append($results);
|
|
};
|
|
|
|
Results.prototype.sort = function (data) {
|
|
var sorter = this.options.get('sorter');
|
|
|
|
return sorter(data);
|
|
};
|
|
|
|
Results.prototype.highlightFirstItem = function () {
|
|
var $options = this.$results
|
|
.find('.select2-results__option[aria-selected]');
|
|
|
|
var $selected = $options.filter('[aria-selected=true]');
|
|
|
|
// Check if there are any selected options
|
|
if ($selected.length > 0) {
|
|
// If there are selected options, highlight the first
|
|
$selected.first().trigger('mouseenter');
|
|
} else {
|
|
// If there are no selected options, highlight the first option
|
|
// in the dropdown
|
|
$options.first().trigger('mouseenter');
|
|
}
|
|
|
|
this.ensureHighlightVisible();
|
|
};
|
|
|
|
Results.prototype.setClasses = function () {
|
|
var self = this;
|
|
|
|
this.data.current(function (selected) {
|
|
var selectedIds = $.map(selected, function (s) {
|
|
return s.id.toString();
|
|
});
|
|
|
|
var $options = self.$results
|
|
.find('.select2-results__option[aria-selected]');
|
|
|
|
$options.each(function () {
|
|
var $option = $(this);
|
|
|
|
var item = Utils.GetData(this, 'data');
|
|
|
|
// id needs to be converted to a string when comparing
|
|
var id = '' + item.id;
|
|
|
|
if ((item.element != null && item.element.selected) ||
|
|
(item.element == null && $.inArray(id, selectedIds) > -1)) {
|
|
$option.attr('aria-selected', 'true');
|
|
} else {
|
|
$option.attr('aria-selected', 'false');
|
|
}
|
|
});
|
|
|
|
});
|
|
};
|
|
|
|
Results.prototype.showLoading = function (params) {
|
|
this.hideLoading();
|
|
|
|
var loadingMore = this.options.get('translations').get('searching');
|
|
|
|
var loading = {
|
|
disabled: true,
|
|
loading: true,
|
|
text: loadingMore(params)
|
|
};
|
|
var $loading = this.option(loading);
|
|
$loading.className += ' loading-results';
|
|
|
|
this.$results.prepend($loading);
|
|
};
|
|
|
|
Results.prototype.hideLoading = function () {
|
|
this.$results.find('.loading-results').remove();
|
|
};
|
|
|
|
Results.prototype.option = function (data) {
|
|
var option = document.createElement('li');
|
|
option.className = 'select2-results__option';
|
|
|
|
var attrs = {
|
|
'role': 'option',
|
|
'aria-selected': 'false'
|
|
};
|
|
|
|
var matches = window.Element.prototype.matches ||
|
|
window.Element.prototype.msMatchesSelector ||
|
|
window.Element.prototype.webkitMatchesSelector;
|
|
|
|
if ((data.element != null && matches.call(data.element, ':disabled')) ||
|
|
(data.element == null && data.disabled)) {
|
|
delete attrs['aria-selected'];
|
|
attrs['aria-disabled'] = 'true';
|
|
}
|
|
|
|
if (data.id == null) {
|
|
delete attrs['aria-selected'];
|
|
}
|
|
|
|
if (data._resultId != null) {
|
|
option.id = data._resultId;
|
|
}
|
|
|
|
if (data.title) {
|
|
option.title = data.title;
|
|
}
|
|
|
|
if (data.children) {
|
|
attrs.role = 'group';
|
|
attrs['aria-label'] = data.text;
|
|
delete attrs['aria-selected'];
|
|
}
|
|
|
|
for (var attr in attrs) {
|
|
var val = attrs[attr];
|
|
|
|
option.setAttribute(attr, val);
|
|
}
|
|
|
|
if (data.children) {
|
|
var $option = $(option);
|
|
|
|
var label = document.createElement('strong');
|
|
label.className = 'select2-results__group';
|
|
|
|
var $label = $(label);
|
|
this.template(data, label);
|
|
|
|
var $children = [];
|
|
|
|
for (var c = 0; c < data.children.length; c++) {
|
|
var child = data.children[c];
|
|
|
|
var $child = this.option(child);
|
|
|
|
$children.push($child);
|
|
}
|
|
|
|
var $childrenContainer = $('<ul></ul>', {
|
|
'class': 'select2-results__options select2-results__options--nested'
|
|
});
|
|
|
|
$childrenContainer.append($children);
|
|
|
|
$option.append(label);
|
|
$option.append($childrenContainer);
|
|
} else {
|
|
this.template(data, option);
|
|
}
|
|
|
|
Utils.StoreData(option, 'data', data);
|
|
|
|
return option;
|
|
};
|
|
|
|
Results.prototype.bind = function (container, $container) {
|
|
var self = this;
|
|
|
|
var id = container.id + '-results';
|
|
|
|
this.$results.attr('id', id);
|
|
|
|
container.on('results:all', function (params) {
|
|
self.clear();
|
|
self.append(params.data);
|
|
|
|
if (container.isOpen()) {
|
|
self.setClasses();
|
|
self.highlightFirstItem();
|
|
}
|
|
});
|
|
|
|
container.on('results:append', function (params) {
|
|
self.append(params.data);
|
|
|
|
if (container.isOpen()) {
|
|
self.setClasses();
|
|
}
|
|
});
|
|
|
|
container.on('query', function (params) {
|
|
self.hideMessages();
|
|
self.showLoading(params);
|
|
});
|
|
|
|
container.on('select', function () {
|
|
if (!container.isOpen()) {
|
|
return;
|
|
}
|
|
|
|
self.setClasses();
|
|
|
|
if (self.options.get('scrollAfterSelect')) {
|
|
self.highlightFirstItem();
|
|
}
|
|
});
|
|
|
|
container.on('unselect', function () {
|
|
if (!container.isOpen()) {
|
|
return;
|
|
}
|
|
|
|
self.setClasses();
|
|
|
|
if (self.options.get('scrollAfterSelect')) {
|
|
self.highlightFirstItem();
|
|
}
|
|
});
|
|
|
|
container.on('open', function () {
|
|
// When the dropdown is open, aria-expended="true"
|
|
self.$results.attr('aria-expanded', 'true');
|
|
self.$results.attr('aria-hidden', 'false');
|
|
|
|
self.setClasses();
|
|
self.ensureHighlightVisible();
|
|
});
|
|
|
|
container.on('close', function () {
|
|
// When the dropdown is closed, aria-expended="false"
|
|
self.$results.attr('aria-expanded', 'false');
|
|
self.$results.attr('aria-hidden', 'true');
|
|
self.$results.removeAttr('aria-activedescendant');
|
|
});
|
|
|
|
container.on('results:toggle', function () {
|
|
var $highlighted = self.getHighlightedResults();
|
|
|
|
if ($highlighted.length === 0) {
|
|
return;
|
|
}
|
|
|
|
$highlighted.trigger('mouseup');
|
|
});
|
|
|
|
container.on('results:select', function () {
|
|
var $highlighted = self.getHighlightedResults();
|
|
|
|
if ($highlighted.length === 0) {
|
|
return;
|
|
}
|
|
|
|
var data = Utils.GetData($highlighted[0], 'data');
|
|
|
|
if ($highlighted.attr('aria-selected') == 'true') {
|
|
self.trigger('close', {});
|
|
} else {
|
|
self.trigger('select', {
|
|
data: data
|
|
});
|
|
}
|
|
});
|
|
|
|
container.on('results:previous', function () {
|
|
var $highlighted = self.getHighlightedResults();
|
|
|
|
var $options = self.$results.find('[aria-selected]');
|
|
|
|
var currentIndex = $options.index($highlighted);
|
|
|
|
// If we are already at the top, don't move further
|
|
// If no options, currentIndex will be -1
|
|
if (currentIndex <= 0) {
|
|
return;
|
|
}
|
|
|
|
var nextIndex = currentIndex - 1;
|
|
|
|
// If none are highlighted, highlight the first
|
|
if ($highlighted.length === 0) {
|
|
nextIndex = 0;
|
|
}
|
|
|
|
var $next = $options.eq(nextIndex);
|
|
|
|
$next.trigger('mouseenter');
|
|
|
|
var currentOffset = self.$results.offset().top;
|
|
var nextTop = $next.offset().top;
|
|
var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);
|
|
|
|
if (nextIndex === 0) {
|
|
self.$results.scrollTop(0);
|
|
} else if (nextTop - currentOffset < 0) {
|
|
self.$results.scrollTop(nextOffset);
|
|
}
|
|
});
|
|
|
|
container.on('results:next', function () {
|
|
var $highlighted = self.getHighlightedResults();
|
|
|
|
var $options = self.$results.find('[aria-selected]');
|
|
|
|
var currentIndex = $options.index($highlighted);
|
|
|
|
var nextIndex = currentIndex + 1;
|
|
|
|
// If we are at the last option, stay there
|
|
if (nextIndex >= $options.length) {
|
|
return;
|
|
}
|
|
|
|
var $next = $options.eq(nextIndex);
|
|
|
|
$next.trigger('mouseenter');
|
|
|
|
var currentOffset = self.$results.offset().top +
|
|
self.$results.outerHeight(false);
|
|
var nextBottom = $next.offset().top + $next.outerHeight(false);
|
|
var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;
|
|
|
|
if (nextIndex === 0) {
|
|
self.$results.scrollTop(0);
|
|
} else if (nextBottom > currentOffset) {
|
|
self.$results.scrollTop(nextOffset);
|
|
}
|
|
});
|
|
|
|
container.on('results:focus', function (params) {
|
|
params.element.addClass('select2-results__option--highlighted');
|
|
});
|
|
|
|
container.on('results:message', function (params) {
|
|
self.displayMessage(params);
|
|
});
|
|
|
|
if ($.fn.mousewheel) {
|
|
this.$results.on('mousewheel', function (e) {
|
|
var top = self.$results.scrollTop();
|
|
|
|
var bottom = self.$results.get(0).scrollHeight - top + e.deltaY;
|
|
|
|
var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;
|
|
var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();
|
|
|
|
if (isAtTop) {
|
|
self.$results.scrollTop(0);
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
} else if (isAtBottom) {
|
|
self.$results.scrollTop(
|
|
self.$results.get(0).scrollHeight - self.$results.height()
|
|
);
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
}
|
|
});
|
|
}
|
|
|
|
this.$results.on('mouseup', '.select2-results__option[aria-selected]',
|
|
function (evt) {
|
|
var $this = $(this);
|
|
|
|
var data = Utils.GetData(this, 'data');
|
|
|
|
if ($this.attr('aria-selected') === 'true') {
|
|
if (self.options.get('multiple')) {
|
|
self.trigger('unselect', {
|
|
originalEvent: evt,
|
|
data: data
|
|
});
|
|
} else {
|
|
self.trigger('close', {});
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
self.trigger('select', {
|
|
originalEvent: evt,
|
|
data: data
|
|
});
|
|
});
|
|
|
|
this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
|
|
function (evt) {
|
|
var data = Utils.GetData(this, 'data');
|
|
|
|
self.getHighlightedResults()
|
|
.removeClass('select2-results__option--highlighted');
|
|
|
|
self.trigger('results:focus', {
|
|
data: data,
|
|
element: $(this)
|
|
});
|
|
});
|
|
};
|
|
|
|
Results.prototype.getHighlightedResults = function () {
|
|
var $highlighted = this.$results
|
|
.find('.select2-results__option--highlighted');
|
|
|
|
return $highlighted;
|
|
};
|
|
|
|
Results.prototype.destroy = function () {
|
|
this.$results.remove();
|
|
};
|
|
|
|
Results.prototype.ensureHighlightVisible = function () {
|
|
var $highlighted = this.getHighlightedResults();
|
|
|
|
if ($highlighted.length === 0) {
|
|
return;
|
|
}
|
|
|
|
var $options = this.$results.find('[aria-selected]');
|
|
|
|
var currentIndex = $options.index($highlighted);
|
|
|
|
var currentOffset = this.$results.offset().top;
|
|
var nextTop = $highlighted.offset().top;
|
|
var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);
|
|
|
|
var offsetDelta = nextTop - currentOffset;
|
|
nextOffset -= $highlighted.outerHeight(false) * 2;
|
|
|
|
if (currentIndex <= 2) {
|
|
this.$results.scrollTop(0);
|
|
} else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {
|
|
this.$results.scrollTop(nextOffset);
|
|
}
|
|
};
|
|
|
|
Results.prototype.template = function (result, container) {
|
|
var template = this.options.get('templateResult');
|
|
var escapeMarkup = this.options.get('escapeMarkup');
|
|
|
|
var content = template(result, container);
|
|
|
|
if (content == null) {
|
|
container.style.display = 'none';
|
|
} else if (typeof content === 'string') {
|
|
container.innerHTML = escapeMarkup(content);
|
|
} else {
|
|
$(container).append(content);
|
|
}
|
|
};
|
|
|
|
return Results;
|
|
});
|
|
|
|
S2.define('select2/keys',[
|
|
|
|
], function () {
|
|
var KEYS = {
|
|
BACKSPACE: 8,
|
|
TAB: 9,
|
|
ENTER: 13,
|
|
SHIFT: 16,
|
|
CTRL: 17,
|
|
ALT: 18,
|
|
ESC: 27,
|
|
SPACE: 32,
|
|
PAGE_UP: 33,
|
|
PAGE_DOWN: 34,
|
|
END: 35,
|
|
HOME: 36,
|
|
LEFT: 37,
|
|
UP: 38,
|
|
RIGHT: 39,
|
|
DOWN: 40,
|
|
DELETE: 46
|
|
};
|
|
|
|
return KEYS;
|
|
});
|
|
|
|
S2.define('select2/selection/base',[
|
|
'jquery',
|
|
'../utils',
|
|
'../keys'
|
|
], function ($, Utils, KEYS) {
|
|
function BaseSelection ($element, options) {
|
|
this.$element = $element;
|
|
this.options = options;
|
|
|
|
BaseSelection.__super__.constructor.call(this);
|
|
}
|
|
|
|
Utils.Extend(BaseSelection, Utils.Observable);
|
|
|
|
BaseSelection.prototype.render = function () {
|
|
var $selection = $(
|
|
'<span class="select2-selection" role="combobox" ' +
|
|
' aria-haspopup="true" aria-expanded="false">' +
|
|
'</span>'
|
|
);
|
|
|
|
this._tabindex = 0;
|
|
|
|
if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
|
|
this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
|
|
} else if (this.$element.attr('tabindex') != null) {
|
|
this._tabindex = this.$element.attr('tabindex');
|
|
}
|
|
|
|
$selection.attr('title', this.$element.attr('title'));
|
|
$selection.attr('tabindex', this._tabindex);
|
|
$selection.attr('aria-disabled', 'false');
|
|
|
|
this.$selection = $selection;
|
|
|
|
return $selection;
|
|
};
|
|
|
|
BaseSelection.prototype.bind = function (container, $container) {
|
|
var self = this;
|
|
|
|
var resultsId = container.id + '-results';
|
|
|
|
this.container = container;
|
|
|
|
this.$selection.on('focus', function (evt) {
|
|
self.trigger('focus', evt);
|
|
});
|
|
|
|
this.$selection.on('blur', function (evt) {
|
|
self._handleBlur(evt);
|
|
});
|
|
|
|
this.$selection.on('keydown', function (evt) {
|
|
self.trigger('keypress', evt);
|
|
|
|
if (evt.which === KEYS.SPACE) {
|
|
evt.preventDefault();
|
|
}
|
|
});
|
|
|
|
container.on('results:focus', function (params) {
|
|
self.$selection.attr('aria-activedescendant', params.data._resultId);
|
|
});
|
|
|
|
container.on('selection:update', function (params) {
|
|
self.update(params.data);
|
|
});
|
|
|
|
container.on('open', function () {
|
|
// When the dropdown is open, aria-expanded="true"
|
|
self.$selection.attr('aria-expanded', 'true');
|
|
self.$selection.attr('aria-owns', resultsId);
|
|
|
|
self._attachCloseHandler(container);
|
|
});
|
|
|
|
container.on('close', function () {
|
|
// When the dropdown is closed, aria-expanded="false"
|
|
self.$selection.attr('aria-expanded', 'false');
|
|
self.$selection.removeAttr('aria-activedescendant');
|
|
self.$selection.removeAttr('aria-owns');
|
|
|
|
self.$selection.trigger('focus');
|
|
|
|
self._detachCloseHandler(container);
|
|
});
|
|
|
|
container.on('enable', function () {
|
|
self.$selection.attr('tabindex', self._tabindex);
|
|
self.$selection.attr('aria-disabled', 'false');
|
|
});
|
|
|
|
container.on('disable', function () {
|
|
self.$selection.attr('tabindex', '-1');
|
|
self.$selection.attr('aria-disabled', 'true');
|
|
});
|
|
};
|
|
|
|
BaseSelection.prototype._handleBlur = function (evt) {
|
|
var self = this;
|
|
|
|
// This needs to be delayed as the active element is the body when the tab
|
|
// key is pressed, possibly along with others.
|
|
window.setTimeout(function () {
|
|
// Don't trigger `blur` if the focus is still in the selection
|
|
if (
|
|
(document.activeElement == self.$selection[0]) ||
|
|
($.contains(self.$selection[0], document.activeElement))
|
|
) {
|
|
return;
|
|
}
|
|
|
|
self.trigger('blur', evt);
|
|
}, 1);
|
|
};
|
|
|
|
BaseSelection.prototype._attachCloseHandler = function (container) {
|
|
|
|
$(document.body).on('mousedown.select2.' + container.id, function (e) {
|
|
var $target = $(e.target);
|
|
|
|
var $select = $target.closest('.select2');
|
|
|
|
var $all = $('.select2.select2-container--open');
|
|
|
|
$all.each(function () {
|
|
if (this == $select[0]) {
|
|
return;
|
|
}
|
|
|
|
var $element = Utils.GetData(this, 'element');
|
|
|
|
$element.select2('close');
|
|
});
|
|
});
|
|
};
|
|
|
|
BaseSelection.prototype._detachCloseHandler = function (container) {
|
|
$(document.body).off('mousedown.select2.' + container.id);
|
|
};
|
|
|
|
BaseSelection.prototype.position = function ($selection, $container) {
|
|
var $selectionContainer = $container.find('.selection');
|
|
$selectionContainer.append($selection);
|
|
};
|
|
|
|
BaseSelection.prototype.destroy = function () {
|
|
this._detachCloseHandler(this.container);
|
|
};
|
|
|
|
BaseSelection.prototype.update = function (data) {
|
|
throw new Error('The `update` method must be defined in child classes.');
|
|
};
|
|
|
|
/**
|
|
* Helper method to abstract the "enabled" (not "disabled") state of this
|
|
* object.
|
|
*
|
|
* @return {true} if the instance is not disabled.
|
|
* @return {false} if the instance is disabled.
|
|
*/
|
|
BaseSelection.prototype.isEnabled = function () {
|
|
return !this.isDisabled();
|
|
};
|
|
|
|
/**
|
|
* Helper method to abstract the "disabled" state of this object.
|
|
*
|
|
* @return {true} if the disabled option is true.
|
|
* @return {false} if the disabled option is false.
|
|
*/
|
|
BaseSelection.prototype.isDisabled = function () {
|
|
return this.options.get('disabled');
|
|
};
|
|
|
|
return BaseSelection;
|
|
});
|
|
|
|
S2.define('select2/selection/single',[
|
|
'jquery',
|
|
'./base',
|
|
'../utils',
|
|
'../keys'
|
|
], function ($, BaseSelection, Utils, KEYS) {
|
|
function SingleSelection () {
|
|
SingleSelection.__super__.constructor.apply(this, arguments);
|
|
}
|
|
|
|
Utils.Extend(SingleSelection, BaseSelection);
|
|
|
|
SingleSelection.prototype.render = function () {
|
|
var $selection = SingleSelection.__super__.render.call(this);
|
|
|
|
$selection.addClass('select2-selection--single');
|
|
|
|
$selection.html(
|
|
'<span class="select2-selection__rendered"></span>' +
|
|
'<span class="select2-selection__arrow" role="presentation">' +
|
|
'<b role="presentation"></b>' +
|
|
'</span>'
|
|
);
|
|
|
|
return $selection;
|
|
};
|
|
|
|
SingleSelection.prototype.bind = function (container, $container) {
|
|
var self = this;
|
|
|
|
SingleSelection.__super__.bind.apply(this, arguments);
|
|
|
|
var id = container.id + '-container';
|
|
|
|
this.$selection.find('.select2-selection__rendered')
|
|
.attr('id', id)
|
|
.attr('role', 'textbox')
|
|
.attr('aria-readonly', 'true');
|
|
this.$selection.attr('aria-labelledby', id);
|
|
|
|
this.$selection.on('mousedown', function (evt) {
|
|
// Only respond to left clicks
|
|
if (evt.which !== 1) {
|
|
return;
|
|
}
|
|
|
|
self.trigger('toggle', {
|
|
originalEvent: evt
|
|
});
|
|
});
|
|
|
|
this.$selection.on('focus', function (evt) {
|
|
// User focuses on the container
|
|
});
|
|
|
|
this.$selection.on('blur', function (evt) {
|
|
// User exits the container
|
|
});
|
|
|
|
container.on('focus', function (evt) {
|
|
if (!container.isOpen()) {
|
|
self.$selection.trigger('focus');
|
|
}
|
|
});
|
|
};
|
|
|
|
SingleSelection.prototype.clear = function () {
|
|
var $rendered = this.$selection.find('.select2-selection__rendered');
|
|
$rendered.empty();
|
|
$rendered.removeAttr('title'); // clear tooltip on empty
|
|
};
|
|
|
|
SingleSelection.prototype.display = function (data, container) {
|
|
var template = this.options.get('templateSelection');
|
|
var escapeMarkup = this.options.get('escapeMarkup');
|
|
|
|
return escapeMarkup(template(data, container));
|
|
};
|
|
|
|
SingleSelection.prototype.selectionContainer = function () {
|
|
return $('<span></span>');
|
|
};
|
|
|
|
SingleSelection.prototype.update = function (data) {
|
|
if (data.length === 0) {
|
|
this.clear();
|
|
return;
|
|
}
|
|
|
|
var selection = data[0];
|
|
|
|
var $rendered = this.$selection.find('.select2-selection__rendered');
|
|
var formatted = this.display(selection, $rendered);
|
|
|
|
$rendered.empty().append(formatted);
|
|
|
|
var title = selection.title || selection.text;
|
|
|
|
if (title) {
|
|
$rendered.attr('title', title);
|
|
} else {
|
|
$rendered.removeAttr('title');
|
|
}
|
|
};
|
|
|
|
return SingleSelection;
|
|
});
|
|
|
|
S2.define('select2/selection/multiple',[
|
|
'jquery',
|
|
'./base',
|
|
'../utils'
|
|
], function ($, BaseSelection, Utils) {
|
|
function MultipleSelection ($element, options) {
|
|
MultipleSelection.__super__.constructor.apply(this, arguments);
|
|
}
|
|
|
|
Utils.Extend(MultipleSelection, BaseSelection);
|
|
|
|
MultipleSelection.prototype.render = function () {
|
|
var $selection = MultipleSelection.__super__.render.call(this);
|
|
|
|
$selection.addClass('select2-selection--multiple');
|
|
|
|
$selection.html(
|
|
'<ul class="select2-selection__rendered"></ul>'
|
|
);
|
|
|
|
return $selection;
|
|
};
|
|
|
|
MultipleSelection.prototype.bind = function (container, $container) {
|
|
var self = this;
|
|
|
|
MultipleSelection.__super__.bind.apply(this, arguments);
|
|
|
|
this.$selection.on('click', function (evt) {
|
|
self.trigger('toggle', {
|
|
originalEvent: evt
|
|
});
|
|
});
|
|
|
|
this.$selection.on(
|
|
'click',
|
|
'.select2-selection__choice__remove',
|
|
function (evt) {
|
|
// Ignore the event if it is disabled
|
|
if (self.isDisabled()) {
|
|
return;
|
|
}
|
|
|
|
var $remove = $(this);
|
|
var $selection = $remove.parent();
|
|
|
|
var data = Utils.GetData($selection[0], 'data');
|
|
|
|
self.trigger('unselect', {
|
|
originalEvent: evt,
|
|
data: data
|
|
});
|
|
}
|
|
);
|
|
};
|
|
|
|
MultipleSelection.prototype.clear = function () {
|
|
var $rendered = this.$selection.find('.select2-selection__rendered');
|
|
$rendered.empty();
|
|
$rendered.removeAttr('title');
|
|
};
|
|
|
|
MultipleSelection.prototype.display = function (data, container) {
|
|
var template = this.options.get('templateSelection');
|
|
var escapeMarkup = this.options.get('escapeMarkup');
|
|
|
|
return escapeMarkup(template(data, container));
|
|
};
|
|
|
|
MultipleSelection.prototype.selectionContainer = function () {
|
|
var $container = $(
|
|
'<li class="select2-selection__choice">' +
|
|
'<span class="select2-selection__choice__remove" role="presentation">' +
|
|
'×' +
|
|
'</span>' +
|
|
'</li>'
|
|
);
|
|
|
|
return $container;
|
|
};
|
|
|
|
MultipleSelection.prototype.update = function (data) {
|
|
this.clear();
|
|
|
|
if (data.length === 0) {
|
|
return;
|
|
}
|
|
|
|
var $selections = [];
|
|
|
|
for (var d = 0; d < data.length; d++) {
|
|
var selection = data[d];
|
|
|
|
var $selection = this.selectionContainer();
|
|
var formatted = this.display(selection, $selection);
|
|
|
|
$selection.append(formatted);
|
|
|
|
var title = selection.title || selection.text;
|
|
|
|
if (title) {
|
|
$selection.attr('title', title);
|
|
}
|
|
|
|
Utils.StoreData($selection[0], 'data', selection);
|
|
|
|
$selections.push($selection);
|
|
}
|
|
|
|
var $rendered = this.$selection.find('.select2-selection__rendered');
|
|
|
|
Utils.appendMany($rendered, $selections);
|
|
};
|
|
|
|
return MultipleSelection;
|
|
});
|
|
|
|
S2.define('select2/selection/placeholder',[
|
|
'../utils'
|
|
], function (Utils) {
|
|
function Placeholder (decorated, $element, options) {
|
|
this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
|
|
|
|
decorated.call(this, $element, options);
|
|
}
|
|
|
|
Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {
|
|
if (typeof placeholder === 'string') {
|
|
placeholder = {
|
|
id: '',
|
|
text: placeholder
|
|
};
|
|
}
|
|
|
|
return placeholder;
|
|
};
|
|
|
|
Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
|
|
var $placeholder = this.selectionContainer();
|
|
|
|
$placeholder.html(this.display(placeholder));
|
|
$placeholder.addClass('select2-selection__placeholder')
|
|
.removeClass('select2-selection__choice');
|
|
|
|
return $placeholder;
|
|
};
|
|
|
|
Placeholder.prototype.update = function (decorated, data) {
|
|
var singlePlaceholder = (
|
|
data.length == 1 && data[0].id != this.placeholder.id
|
|
);
|
|
var multipleSelections = data.length > 1;
|
|
|
|
if (multipleSelections || singlePlaceholder) {
|
|
return decorated.call(this, data);
|
|
}
|
|
|
|
this.clear();
|
|
|
|
var $placeholder = this.createPlaceholder(this.placeholder);
|
|
|
|
this.$selection.find('.select2-selection__rendered').append($placeholder);
|
|
};
|
|
|
|
return Placeholder;
|
|
});
|
|
|
|
S2.define('select2/selection/allowClear',[
|
|
'jquery',
|
|
'../keys',
|
|
'../utils'
|
|
], function ($, KEYS, Utils) {
|
|
function AllowClear () { }
|
|
|
|
AllowClear.prototype.bind = function (decorated, container, $container) {
|
|
var self = this;
|
|
|
|
decorated.call(this, container, $container);
|
|
|
|
if (this.placeholder == null) {
|
|
if (this.options.get('debug') && window.console && console.error) {
|
|
console.error(
|
|
'Select2: The `allowClear` option should be used in combination ' +
|
|
'with the `placeholder` option.'
|
|
);
|
|
}
|
|
}
|
|
|
|
this.$selection.on('mousedown', '.select2-selection__clear',
|
|
function (evt) {
|
|
self._handleClear(evt);
|
|
});
|
|
|
|
container.on('keypress', function (evt) {
|
|
self._handleKeyboardClear(evt, container);
|
|
});
|
|
};
|
|
|
|
AllowClear.prototype._handleClear = function (_, evt) {
|
|
// Ignore the event if it is disabled
|
|
if (this.isDisabled()) {
|
|
return;
|
|
}
|
|
|
|
var $clear = this.$selection.find('.select2-selection__clear');
|
|
|
|
// Ignore the event if nothing has been selected
|
|
if ($clear.length === 0) {
|
|
return;
|
|
}
|
|
|
|
evt.stopPropagation();
|
|
|
|
var data = Utils.GetData($clear[0], 'data');
|
|
|
|
var previousVal = this.$element.val();
|
|
this.$element.val(this.placeholder.id);
|
|
|
|
var unselectData = {
|
|
data: data
|
|
};
|
|
this.trigger('clear', unselectData);
|
|
if (unselectData.prevented) {
|
|
this.$element.val(previousVal);
|
|
return;
|
|
}
|
|
|
|
for (var d = 0; d < data.length; d++) {
|
|
unselectData = {
|
|
data: data[d]
|
|
};
|
|
|
|
// Trigger the `unselect` event, so people can prevent it from being
|
|
// cleared.
|
|
this.trigger('unselect', unselectData);
|
|
|
|
// If the event was prevented, don't clear it out.
|
|
if (unselectData.prevented) {
|
|
this.$element.val(previousVal);
|
|
return;
|
|
}
|
|
}
|
|
|
|
this.$element.trigger('input').trigger('change');
|
|
|
|
this.trigger('toggle', {});
|
|
};
|
|
|
|
AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
|
|
if (container.isOpen()) {
|
|
return;
|
|
}
|
|
|
|
if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
|
|
this._handleClear(evt);
|
|
}
|
|
};
|
|
|
|
AllowClear.prototype.update = function (decorated, data) {
|
|
decorated.call(this, data);
|
|
|
|
if (this.$selection.find('.select2-selection__placeholder').length > 0 ||
|
|
data.length === 0) {
|
|
return;
|
|
}
|
|
|
|
var removeAll = this.options.get('translations').get('removeAllItems');
|
|
|
|
var $remove = $(
|
|
'<span class="select2-selection__clear" title="' + removeAll() +'">' +
|
|
'×' +
|
|
'</span>'
|
|
);
|
|
Utils.StoreData($remove[0], 'data', data);
|
|
|
|
this.$selection.find('.select2-selection__rendered').prepend($remove);
|
|
};
|
|
|
|
return AllowClear;
|
|
});
|
|
|
|
S2.define('select2/selection/search',[
|
|
'jquery',
|
|
'../utils',
|
|
'../keys'
|
|
], function ($, Utils, KEYS) {
|
|
function Search (decorated, $element, options) {
|
|
decorated.call(this, $element, options);
|
|
}
|
|
|
|
Search.prototype.render = function (decorated) {
|
|
var $search = $(
|
|
'<li class="select2-search select2-search--inline">' +
|
|
'<input class="select2-search__field" type="search" tabindex="-1"' +
|
|
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
|
|
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
|
|
'</li>'
|
|
);
|
|
|
|
this.$searchContainer = $search;
|
|
this.$search = $search.find('input');
|
|
|
|
var $rendered = decorated.call(this);
|
|
|
|
this._transferTabIndex();
|
|
|
|
return $rendered;
|
|
};
|
|
|
|
Search.prototype.bind = function (decorated, container, $container) {
|
|
var self = this;
|
|
|
|
var resultsId = container.id + '-results';
|
|
|
|
decorated.call(this, container, $container);
|
|
|
|
container.on('open', function () {
|
|
self.$search.attr('aria-controls', resultsId);
|
|
self.$search.trigger('focus');
|
|
});
|
|
|
|
container.on('close', function () {
|
|
self.$search.val('');
|
|
self.$search.removeAttr('aria-controls');
|
|
self.$search.removeAttr('aria-activedescendant');
|
|
self.$search.trigger('focus');
|
|
});
|
|
|
|
container.on('enable', function () {
|
|
self.$search.prop('disabled', false);
|
|
|
|
self._transferTabIndex();
|
|
});
|
|
|
|
container.on('disable', function () {
|
|
self.$search.prop('disabled', true);
|
|
});
|
|
|
|
container.on('focus', function (evt) {
|
|
self.$search.trigger('focus');
|
|
});
|
|
|
|
container.on('results:focus', function (params) {
|
|
if (params.data._resultId) {
|
|
self.$search.attr('aria-activedescendant', params.data._resultId);
|
|
} else {
|
|
self.$search.removeAttr('aria-activedescendant');
|
|
}
|
|
});
|
|
|
|
this.$selection.on('focusin', '.select2-search--inline', function (evt) {
|
|
self.trigger('focus', evt);
|
|
});
|
|
|
|
this.$selection.on('focusout', '.select2-search--inline', function (evt) {
|
|
self._handleBlur(evt);
|
|
});
|
|
|
|
this.$selection.on('keydown', '.select2-search--inline', function (evt) {
|
|
evt.stopPropagation();
|
|
|
|
self.trigger('keypress', evt);
|
|
|
|
self._keyUpPrevented = evt.isDefaultPrevented();
|
|
|
|
var key = evt.which;
|
|
|
|
if (key === KEYS.BACKSPACE && self.$search.val() === '') {
|
|
var $previousChoice = self.$searchContainer
|
|
.prev('.select2-selection__choice');
|
|
|
|
if ($previousChoice.length > 0) {
|
|
var item = Utils.GetData($previousChoice[0], 'data');
|
|
|
|
self.searchRemoveChoice(item);
|
|
|
|
evt.preventDefault();
|
|
}
|
|
}
|
|
});
|
|
|
|
this.$selection.on('click', '.select2-search--inline', function (evt) {
|
|
if (self.$search.val()) {
|
|
evt.stopPropagation();
|
|
}
|
|
});
|
|
|
|
// Try to detect the IE version should the `documentMode` property that
|
|
// is stored on the document. This is only implemented in IE and is
|
|
// slightly cleaner than doing a user agent check.
|
|
// This property is not available in Edge, but Edge also doesn't have
|
|
// this bug.
|
|
var msie = document.documentMode;
|
|
var disableInputEvents = msie && msie <= 11;
|
|
|
|
// Workaround for browsers which do not support the `input` event
|
|
// This will prevent double-triggering of events for browsers which support
|
|
// both the `keyup` and `input` events.
|
|
this.$selection.on(
|
|
'input.searchcheck',
|
|
'.select2-search--inline',
|
|
function (evt) {
|
|
// IE will trigger the `input` event when a placeholder is used on a
|
|
// search box. To get around this issue, we are forced to ignore all
|
|
// `input` events in IE and keep using `keyup`.
|
|
if (disableInputEvents) {
|
|
self.$selection.off('input.search input.searchcheck');
|
|
return;
|
|
}
|
|
|
|
// Unbind the duplicated `keyup` event
|
|
self.$selection.off('keyup.search');
|
|
}
|
|
);
|
|
|
|
this.$selection.on(
|
|
'keyup.search input.search',
|
|
'.select2-search--inline',
|
|
function (evt) {
|
|
// IE will trigger the `input` event when a placeholder is used on a
|
|
// search box. To get around this issue, we are forced to ignore all
|
|
// `input` events in IE and keep using `keyup`.
|
|
if (disableInputEvents && evt.type === 'input') {
|
|
self.$selection.off('input.search input.searchcheck');
|
|
return;
|
|
}
|
|
|
|
var key = evt.which;
|
|
|
|
// We can freely ignore events from modifier keys
|
|
if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
|
|
return;
|
|
}
|
|
|
|
// Tabbing will be handled during the `keydown` phase
|
|
if (key == KEYS.TAB) {
|
|
return;
|
|
}
|
|
|
|
self.handleSearch(evt);
|
|
}
|
|
);
|
|
};
|
|
|
|
/**
|
|
* This method will transfer the tabindex attribute from the rendered
|
|
* selection to the search box. This allows for the search box to be used as
|
|
* the primary focus instead of the selection container.
|
|
*
|
|
* @private
|
|
*/
|
|
Search.prototype._transferTabIndex = function (decorated) {
|
|
this.$search.attr('tabindex', this.$selection.attr('tabindex'));
|
|
this.$selection.attr('tabindex', '-1');
|
|
};
|
|
|
|
Search.prototype.createPlaceholder = function (decorated, placeholder) {
|
|
this.$search.attr('placeholder', placeholder.text);
|
|
};
|
|
|
|
Search.prototype.update = function (decorated, data) {
|
|
var searchHadFocus = this.$search[0] == document.activeElement;
|
|
|
|
this.$search.attr('placeholder', '');
|
|
|
|
decorated.call(this, data);
|
|
|
|
this.$selection.find('.select2-selection__rendered')
|
|
.append(this.$searchContainer);
|
|
|
|
this.resizeSearch();
|
|
if (searchHadFocus) {
|
|
this.$search.trigger('focus');
|
|
}
|
|
};
|
|
|
|
Search.prototype.handleSearch = function () {
|
|
this.resizeSearch();
|
|
|
|
if (!this._keyUpPrevented) {
|
|
var input = this.$search.val();
|
|
|
|
this.trigger('query', {
|
|
term: input
|
|
});
|
|
}
|
|
|
|
this._keyUpPrevented = false;
|
|
};
|
|
|
|
Search.prototype.searchRemoveChoice = function (decorated, item) {
|
|
this.trigger('unselect', {
|
|
data: item
|
|
});
|
|
|
|
this.$search.val(item.text);
|
|
this.handleSearch();
|
|
};
|
|
|
|
Search.prototype.resizeSearch = function () {
|
|
this.$search.css('width', '25px');
|
|
|
|
var width = '';
|
|
|
|
if (this.$search.attr('placeholder') !== '') {
|
|
width = this.$selection.find('.select2-selection__rendered').width();
|
|
} else {
|
|
var minimumWidth = this.$search.val().length + 1;
|
|
|
|
width = (minimumWidth * 0.75) + 'em';
|
|
}
|
|
|
|
this.$search.css('width', width);
|
|
};
|
|
|
|
return Search;
|
|
});
|
|
|
|
S2.define('select2/selection/eventRelay',[
|
|
'jquery'
|
|
], function ($) {
|
|
function EventRelay () { }
|
|
|
|
EventRelay.prototype.bind = function (decorated, container, $container) {
|
|
var self = this;
|
|
var relayEvents = [
|
|
'open', 'opening',
|
|
'close', 'closing',
|
|
'select', 'selecting',
|
|
'unselect', 'unselecting',
|
|
'clear', 'clearing'
|
|
];
|
|
|
|
var preventableEvents = [
|
|
'opening', 'closing', 'selecting', 'unselecting', 'clearing'
|
|
];
|
|
|
|
decorated.call(this, container, $container);
|
|
|
|
container.on('*', function (name, params) {
|
|
// Ignore events that should not be relayed
|
|
if ($.inArray(name, relayEvents) === -1) {
|
|
return;
|
|
}
|
|
|
|
// The parameters should always be an object
|
|
params = params || {};
|
|
|
|
// Generate the jQuery event for the Select2 event
|
|
var evt = $.Event('select2:' + name, {
|
|
params: params
|
|
});
|
|
|
|
self.$element.trigger(evt);
|
|
|
|
// Only handle preventable events if it was one
|
|
if ($.inArray(name, preventableEvents) === -1) {
|
|
return;
|
|
}
|
|
|
|
params.prevented = evt.isDefaultPrevented();
|
|
});
|
|
};
|
|
|
|
return EventRelay;
|
|
});
|
|
|
|
S2.define('select2/translation',[
|
|
'jquery',
|
|
'require'
|
|
], function ($, require) {
|
|
function Translation (dict) {
|
|
this.dict = dict || {};
|
|
}
|
|
|
|
Translation.prototype.all = function () {
|
|
return this.dict;
|
|
};
|
|
|
|
Translation.prototype.get = function (key) {
|
|
return this.dict[key];
|
|
};
|
|
|
|
Translation.prototype.extend = function (translation) {
|
|
this.dict = $.extend({}, translation.all(), this.dict);
|
|
};
|
|
|
|
// Static functions
|
|
|
|
Translation._cache = {};
|
|
|
|
Translation.loadPath = function (path) {
|
|
if (!(path in Translation._cache)) {
|
|
var translations = require(path);
|
|
|
|
Translation._cache[path] = translations;
|
|
}
|
|
|
|
return new Translation(Translation._cache[path]);
|
|
};
|
|
|
|
return Translation;
|
|
});
|
|
|
|
S2.define('select2/diacritics',[
|
|
|
|
], function () {
|
|
var diacritics = {
|
|
'\u24B6': 'A',
|
|
'\uFF21': 'A',
|
|
'\u00C0': 'A',
|
|
'\u00C1': 'A',
|
|
'\u00C2': 'A',
|
|
'\u1EA6': 'A',
|
|
'\u1EA4': 'A',
|
|
'\u1EAA': 'A',
|
|
'\u1EA8': 'A',
|
|
'\u00C3': 'A',
|
|
'\u0100': 'A',
|
|
'\u0102': 'A',
|
|
'\u1EB0': 'A',
|
|
'\u1EAE': 'A',
|
|
'\u1EB4': 'A',
|
|
'\u1EB2': 'A',
|
|
'\u0226': 'A',
|
|
'\u01E0': 'A',
|
|
'\u00C4': 'A',
|
|
'\u01DE': 'A',
|
|
'\u1EA2': 'A',
|
|
'\u00C5': 'A',
|
|
'\u01FA': 'A',
|
|
'\u01CD': 'A',
|
|
'\u0200': 'A',
|
|
'\u0202': 'A',
|
|
'\u1EA0': 'A',
|
|
'\u1EAC': 'A',
|
|
'\u1EB6': 'A',
|
|
'\u1E00': 'A',
|
|
'\u0104': 'A',
|
|
'\u023A': 'A',
|
|
'\u2C6F': 'A',
|
|
'\uA732': 'AA',
|
|
'\u00C6': 'AE',
|
|
'\u01FC': 'AE',
|
|
'\u01E2': 'AE',
|
|
'\uA734': 'AO',
|
|
'\uA736': 'AU',
|
|
'\uA738': 'AV',
|
|
'\uA73A': 'AV',
|
|
'\uA73C': 'AY',
|
|
'\u24B7': 'B',
|
|
'\uFF22': 'B',
|
|
'\u1E02': 'B',
|
|
'\u1E04': 'B',
|
|
'\u1E06': 'B',
|
|
'\u0243': 'B',
|
|
'\u0182': 'B',
|
|
'\u0181': 'B',
|
|
'\u24B8': 'C',
|
|
'\uFF23': 'C',
|
|
'\u0106': 'C',
|
|
'\u0108': 'C',
|
|
'\u010A': 'C',
|
|
'\u010C': 'C',
|
|
'\u00C7': 'C',
|
|
'\u1E08': 'C',
|
|
'\u0187': 'C',
|
|
'\u023B': 'C',
|
|
'\uA73E': 'C',
|
|
'\u24B9': 'D',
|
|
'\uFF24': 'D',
|
|
'\u1E0A': 'D',
|
|
'\u010E': 'D',
|
|
'\u1E0C': 'D',
|
|
'\u1E10': 'D',
|
|
'\u1E12': 'D',
|
|
'\u1E0E': 'D',
|
|
'\u0110': 'D',
|
|
'\u018B': 'D',
|
|
'\u018A': 'D',
|
|
'\u0189': 'D',
|
|
'\uA779': 'D',
|
|
'\u01F1': 'DZ',
|
|
'\u01C4': 'DZ',
|
|
'\u01F2': 'Dz',
|
|
'\u01C5': 'Dz',
|
|
'\u24BA': 'E',
|
|
'\uFF25': 'E',
|
|
'\u00C8': 'E',
|
|
'\u00C9': 'E',
|
|
'\u00CA': 'E',
|
|
'\u1EC0': 'E',
|
|
'\u1EBE': 'E',
|
|
'\u1EC4': 'E',
|
|
'\u1EC2': 'E',
|
|
'\u1EBC': 'E',
|
|
'\u0112': 'E',
|
|
'\u1E14': 'E',
|
|
'\u1E16': 'E',
|
|
'\u0114': 'E',
|
|
'\u0116': 'E',
|
|
'\u00CB': 'E',
|
|
'\u1EBA': 'E',
|
|
'\u011A': 'E',
|
|
'\u0204': 'E',
|
|
'\u0206': 'E',
|
|
'\u1EB8': 'E',
|
|
'\u1EC6': 'E',
|
|
'\u0228': 'E',
|
|
'\u1E1C': 'E',
|
|
'\u0118': 'E',
|
|
'\u1E18': 'E',
|
|
'\u1E1A': 'E',
|
|
'\u0190': 'E',
|
|
'\u018E': 'E',
|
|
'\u24BB': 'F',
|
|
'\uFF26': 'F',
|
|
'\u1E1E': 'F',
|
|
'\u0191': 'F',
|
|
'\uA77B': 'F',
|
|
'\u24BC': 'G',
|
|
'\uFF27': 'G',
|
|
'\u01F4': 'G',
|
|
'\u011C': 'G',
|
|
'\u1E20': 'G',
|
|
'\u011E': 'G',
|
|
'\u0120': 'G',
|
|
'\u01E6': 'G',
|
|
'\u0122': 'G',
|
|
'\u01E4': 'G',
|
|
'\u0193': 'G',
|
|
'\uA7A0': 'G',
|
|
'\uA77D': 'G',
|
|
'\uA77E': 'G',
|
|
'\u24BD': 'H',
|
|
'\uFF28': 'H',
|
|
'\u0124': 'H',
|
|
'\u1E22': 'H',
|
|
'\u1E26': 'H',
|
|
'\u021E': 'H',
|
|
'\u1E24': 'H',
|
|
'\u1E28': 'H',
|
|
'\u1E2A': 'H',
|
|
'\u0126': 'H',
|
|
'\u2C67': 'H',
|
|
'\u2C75': 'H',
|
|
'\uA78D': 'H',
|
|
'\u24BE': 'I',
|
|
'\uFF29': 'I',
|
|
'\u00CC': 'I',
|
|
'\u00CD': 'I',
|
|
'\u00CE': 'I',
|
|
'\u0128': 'I',
|
|
'\u012A': 'I',
|
|
'\u012C': 'I',
|
|
'\u0130': 'I',
|
|
'\u00CF': 'I',
|
|
'\u1E2E': 'I',
|
|
'\u1EC8': 'I',
|
|
'\u01CF': 'I',
|
|
'\u0208': 'I',
|
|
'\u020A': 'I',
|
|
'\u1ECA': 'I',
|
|
'\u012E': 'I',
|
|
'\u1E2C': 'I',
|
|
'\u0197': 'I',
|
|
'\u24BF': 'J',
|
|
'\uFF2A': 'J',
|
|
'\u0134': 'J',
|
|
'\u0248': 'J',
|
|
'\u24C0': 'K',
|
|
'\uFF2B': 'K',
|
|
'\u1E30': 'K',
|
|
'\u01E8': 'K',
|
|
'\u1E32': 'K',
|
|
'\u0136': 'K',
|
|
'\u1E34': 'K',
|
|
'\u0198': 'K',
|
|
'\u2C69': 'K',
|
|
'\uA740': 'K',
|
|
'\uA742': 'K',
|
|
'\uA744': 'K',
|
|
'\uA7A2': 'K',
|
|
'\u24C1': 'L',
|
|
'\uFF2C': 'L',
|
|
'\u013F': 'L',
|
|
'\u0139': 'L',
|
|
'\u013D': 'L',
|
|
'\u1E36': 'L',
|
|
'\u1E38': 'L',
|
|
'\u013B': 'L',
|
|
'\u1E3C': 'L',
|
|
'\u1E3A': 'L',
|
|
'\u0141': 'L',
|
|
'\u023D': 'L',
|
|
'\u2C62': 'L',
|
|
'\u2C60': 'L',
|
|
'\uA748': 'L',
|
|
'\uA746': 'L',
|
|
'\uA780': 'L',
|
|
'\u01C7': 'LJ',
|
|
'\u01C8': 'Lj',
|
|
'\u24C2': 'M',
|
|
'\uFF2D': 'M',
|
|
'\u1E3E': 'M',
|
|
'\u1E40': 'M',
|
|
'\u1E42': 'M',
|
|
'\u2C6E': 'M',
|
|
'\u019C': 'M',
|
|
'\u24C3': 'N',
|
|
'\uFF2E': 'N',
|
|
'\u01F8': 'N',
|
|
'\u0143': 'N',
|
|
'\u00D1': 'N',
|
|
'\u1E44': 'N',
|
|
'\u0147': 'N',
|
|
'\u1E46': 'N',
|
|
'\u0145': 'N',
|
|
'\u1E4A': 'N',
|
|
'\u1E48': 'N',
|
|
'\u0220': 'N',
|
|
'\u019D': 'N',
|
|
'\uA790': 'N',
|
|
'\uA7A4': 'N',
|
|
'\u01CA': 'NJ',
|
|
'\u01CB': 'Nj',
|
|
'\u24C4': 'O',
|
|
'\uFF2F': 'O',
|
|
'\u00D2': 'O',
|
|
'\u00D3': 'O',
|
|
'\u00D4': 'O',
|
|
'\u1ED2': 'O',
|
|
'\u1ED0': 'O',
|
|
'\u1ED6': 'O',
|
|
'\u1ED4': 'O',
|
|
'\u00D5': 'O',
|
|
'\u1E4C': 'O',
|
|
'\u022C': 'O',
|
|
'\u1E4E': 'O',
|
|
'\u014C': 'O',
|
|
'\u1E50': 'O',
|
|
'\u1E52': 'O',
|
|
'\u014E': 'O',
|
|
'\u022E': 'O',
|
|
'\u0230': 'O',
|
|
'\u00D6': 'O',
|
|
'\u022A': 'O',
|
|
'\u1ECE': 'O',
|
|
'\u0150': 'O',
|
|
'\u01D1': 'O',
|
|
'\u020C': 'O',
|
|
'\u020E': 'O',
|
|
'\u01A0': 'O',
|
|
'\u1EDC': 'O',
|
|
'\u1EDA': 'O',
|
|
'\u1EE0': 'O',
|
|
'\u1EDE': 'O',
|
|
'\u1EE2': 'O',
|
|
'\u1ECC': 'O',
|
|
'\u1ED8': 'O',
|
|
'\u01EA': 'O',
|
|
'\u01EC': 'O',
|
|
'\u00D8': 'O',
|
|
'\u01FE': 'O',
|
|
'\u0186': 'O',
|
|
'\u019F': 'O',
|
|
'\uA74A': 'O',
|
|
'\uA74C': 'O',
|
|
'\u0152': 'OE',
|
|
'\u01A2': 'OI',
|
|
'\uA74E': 'OO',
|
|
'\u0222': 'OU',
|
|
'\u24C5': 'P',
|
|
'\uFF30': 'P',
|
|
'\u1E54': 'P',
|
|
'\u1E56': 'P',
|
|
'\u01A4': 'P',
|
|
'\u2C63': 'P',
|
|
'\uA750': 'P',
|
|
'\uA752': 'P',
|
|
'\uA754': 'P',
|
|
'\u24C6': 'Q',
|
|
'\uFF31': 'Q',
|
|
'\uA756': 'Q',
|
|
'\uA758': 'Q',
|
|
'\u024A': 'Q',
|
|
'\u24C7': 'R',
|
|
'\uFF32': 'R',
|
|
'\u0154': 'R',
|
|
'\u1E58': 'R',
|
|
'\u0158': 'R',
|
|
'\u0210': 'R',
|
|
'\u0212': 'R',
|
|
'\u1E5A': 'R',
|
|
'\u1E5C': 'R',
|
|
'\u0156': 'R',
|
|
'\u1E5E': 'R',
|
|
'\u024C': 'R',
|
|
'\u2C64': 'R',
|
|
'\uA75A': 'R',
|
|
'\uA7A6': 'R',
|
|
'\uA782': 'R',
|
|
'\u24C8': 'S',
|
|
'\uFF33': 'S',
|
|
'\u1E9E': 'S',
|
|
'\u015A': 'S',
|
|
'\u1E64': 'S',
|
|
'\u015C': 'S',
|
|
'\u1E60': 'S',
|
|
'\u0160': 'S',
|
|
'\u1E66': 'S',
|
|
'\u1E62': 'S',
|
|
'\u1E68': 'S',
|
|
'\u0218': 'S',
|
|
'\u015E': 'S',
|
|
'\u2C7E': 'S',
|
|
'\uA7A8': 'S',
|
|
'\uA784': 'S',
|
|
'\u24C9': 'T',
|
|
'\uFF34': 'T',
|
|
'\u1E6A': 'T',
|
|
'\u0164': 'T',
|
|
'\u1E6C': 'T',
|
|
'\u021A': 'T',
|
|
'\u0162': 'T',
|
|
'\u1E70': 'T',
|
|
'\u1E6E': 'T',
|
|
'\u0166': 'T',
|
|
'\u01AC': 'T',
|
|
'\u01AE': 'T',
|
|
'\u023E': 'T',
|
|
'\uA786': 'T',
|
|
'\uA728': 'TZ',
|
|
'\u24CA': 'U',
|
|
'\uFF35': 'U',
|
|
'\u00D9': 'U',
|
|
'\u00DA': 'U',
|
|
'\u00DB': 'U',
|
|
'\u0168': 'U',
|
|
'\u1E78': 'U',
|
|
'\u016A': 'U',
|
|
'\u1E7A': 'U',
|
|
'\u016C': 'U',
|
|
'\u00DC': 'U',
|
|
'\u01DB': 'U',
|
|
'\u01D7': 'U',
|
|
'\u01D5': 'U',
|
|
'\u01D9': 'U',
|
|
'\u1EE6': 'U',
|
|
'\u016E': 'U',
|
|
'\u0170': 'U',
|
|
'\u01D3': 'U',
|
|
'\u0214': 'U',
|
|
'\u0216': 'U',
|
|
'\u01AF': 'U',
|
|
'\u1EEA': 'U',
|
|
'\u1EE8': 'U',
|
|
'\u1EEE': 'U',
|
|
'\u1EEC': 'U',
|
|
'\u1EF0': 'U',
|
|
'\u1EE4': 'U',
|
|
'\u1E72': 'U',
|
|
'\u0172': 'U',
|
|
'\u1E76': 'U',
|
|
'\u1E74': 'U',
|
|
'\u0244': 'U',
|
|
'\u24CB': 'V',
|
|
'\uFF36': 'V',
|
|
'\u1E7C': 'V',
|
|
'\u1E7E': 'V',
|
|
'\u01B2': 'V',
|
|
'\uA75E': 'V',
|
|
'\u0245': 'V',
|
|
'\uA760': 'VY',
|
|
'\u24CC': 'W',
|
|
'\uFF37': 'W',
|
|
'\u1E80': 'W',
|
|
'\u1E82': 'W',
|
|
'\u0174': 'W',
|
|
'\u1E86': 'W',
|
|
'\u1E84': 'W',
|
|
'\u1E88': 'W',
|
|
'\u2C72': 'W',
|
|
'\u24CD': 'X',
|
|
'\uFF38': 'X',
|
|
'\u1E8A': 'X',
|
|
'\u1E8C': 'X',
|
|
'\u24CE': 'Y',
|
|
'\uFF39': 'Y',
|
|
'\u1EF2': 'Y',
|
|
'\u00DD': 'Y',
|
|
'\u0176': 'Y',
|
|
'\u1EF8': 'Y',
|
|
'\u0232': 'Y',
|
|
'\u1E8E': 'Y',
|
|
'\u0178': 'Y',
|
|
'\u1EF6': 'Y',
|
|
'\u1EF4': 'Y',
|
|
'\u01B3': 'Y',
|
|
'\u024E': 'Y',
|
|
'\u1EFE': 'Y',
|
|
'\u24CF': 'Z',
|
|
'\uFF3A': 'Z',
|
|
'\u0179': 'Z',
|
|
'\u1E90': 'Z',
|
|
'\u017B': 'Z',
|
|
'\u017D': 'Z',
|
|
'\u1E92': 'Z',
|
|
'\u1E94': 'Z',
|
|
'\u01B5': 'Z',
|
|
'\u0224': 'Z',
|
|
'\u2C7F': 'Z',
|
|
'\u2C6B': 'Z',
|
|
'\uA762': 'Z',
|
|
'\u24D0': 'a',
|
|
'\uFF41': 'a',
|
|
'\u1E9A': 'a',
|
|
'\u00E0': 'a',
|
|
'\u00E1': 'a',
|
|
'\u00E2': 'a',
|
|
'\u1EA7': 'a',
|
|
'\u1EA5': 'a',
|
|
'\u1EAB': 'a',
|
|
'\u1EA9': 'a',
|
|
'\u00E3': 'a',
|
|
'\u0101': 'a',
|
|
'\u0103': 'a',
|
|
'\u1EB1': 'a',
|
|
'\u1EAF': 'a',
|
|
'\u1EB5': 'a',
|
|
'\u1EB3': 'a',
|
|
'\u0227': 'a',
|
|
'\u01E1': 'a',
|
|
'\u00E4': 'a',
|
|
'\u01DF': 'a',
|
|
'\u1EA3': 'a',
|
|
'\u00E5': 'a',
|
|
'\u01FB': 'a',
|
|
'\u01CE': 'a',
|
|
'\u0201': 'a',
|
|
'\u0203': 'a',
|
|
'\u1EA1': 'a',
|
|
'\u1EAD': 'a',
|
|
'\u1EB7': 'a',
|
|
'\u1E01': 'a',
|
|
'\u0105': 'a',
|
|
'\u2C65': 'a',
|
|
'\u0250': 'a',
|
|
'\uA733': 'aa',
|
|
'\u00E6': 'ae',
|
|
'\u01FD': 'ae',
|
|
'\u01E3': 'ae',
|
|
'\uA735': 'ao',
|
|
'\uA737': 'au',
|
|
'\uA739': 'av',
|
|
'\uA73B': 'av',
|
|
'\uA73D': 'ay',
|
|
'\u24D1': 'b',
|
|
'\uFF42': 'b',
|
|
'\u1E03': 'b',
|
|
'\u1E05': 'b',
|
|
'\u1E07': 'b',
|
|
'\u0180': 'b',
|
|
'\u0183': 'b',
|
|
'\u0253': 'b',
|
|
'\u24D2': 'c',
|
|
'\uFF43': 'c',
|
|
'\u0107': 'c',
|
|
'\u0109': 'c',
|
|
'\u010B': 'c',
|
|
'\u010D': 'c',
|
|
'\u00E7': 'c',
|
|
'\u1E09': 'c',
|
|
'\u0188': 'c',
|
|
'\u023C': 'c',
|
|
'\uA73F': 'c',
|
|
'\u2184': 'c',
|
|
'\u24D3': 'd',
|
|
'\uFF44': 'd',
|
|
'\u1E0B': 'd',
|
|
'\u010F': 'd',
|
|
'\u1E0D': 'd',
|
|
'\u1E11': 'd',
|
|
'\u1E13': 'd',
|
|
'\u1E0F': 'd',
|
|
'\u0111': 'd',
|
|
'\u018C': 'd',
|
|
'\u0256': 'd',
|
|
'\u0257': 'd',
|
|
'\uA77A': 'd',
|
|
'\u01F3': 'dz',
|
|
'\u01C6': 'dz',
|
|
'\u24D4': 'e',
|
|
'\uFF45': 'e',
|
|
'\u00E8': 'e',
|
|
'\u00E9': 'e',
|
|
'\u00EA': 'e',
|
|
'\u1EC1': 'e',
|
|
'\u1EBF': 'e',
|
|
'\u1EC5': 'e',
|
|
'\u1EC3': 'e',
|
|
'\u1EBD': 'e',
|
|
'\u0113': 'e',
|
|
'\u1E15': 'e',
|
|
'\u1E17': 'e',
|
|
'\u0115': 'e',
|
|
'\u0117': 'e',
|
|
'\u00EB': 'e',
|
|
'\u1EBB': 'e',
|
|
'\u011B': 'e',
|
|
'\u0205': 'e',
|
|
'\u0207': 'e',
|
|
'\u1EB9': 'e',
|
|
'\u1EC7': 'e',
|
|
'\u0229': 'e',
|
|
'\u1E1D': 'e',
|
|
'\u0119': 'e',
|
|
'\u1E19': 'e',
|
|
'\u1E1B': 'e',
|
|
'\u0247': 'e',
|
|
'\u025B': 'e',
|
|
'\u01DD': 'e',
|
|
'\u24D5': 'f',
|
|
'\uFF46': 'f',
|
|
'\u1E1F': 'f',
|
|
'\u0192': 'f',
|
|
'\uA77C': 'f',
|
|
'\u24D6': 'g',
|
|
'\uFF47': 'g',
|
|
'\u01F5': 'g',
|
|
'\u011D': 'g',
|
|
'\u1E21': 'g',
|
|
'\u011F': 'g',
|
|
'\u0121': 'g',
|
|
'\u01E7': 'g',
|
|
'\u0123': 'g',
|
|
'\u01E5': 'g',
|
|
'\u0260': 'g',
|
|
'\uA7A1': 'g',
|
|
'\u1D79': 'g',
|
|
'\uA77F': 'g',
|
|
'\u24D7': 'h',
|
|
'\uFF48': 'h',
|
|
'\u0125': 'h',
|
|
'\u1E23': 'h',
|
|
'\u1E27': 'h',
|
|
'\u021F': 'h',
|
|
'\u1E25': 'h',
|
|
'\u1E29': 'h',
|
|
'\u1E2B': 'h',
|
|
'\u1E96': 'h',
|
|
'\u0127': 'h',
|
|
'\u2C68': 'h',
|
|
'\u2C76': 'h',
|
|
'\u0265': 'h',
|
|
'\u0195': 'hv',
|
|
'\u24D8': 'i',
|
|
'\uFF49': 'i',
|
|
'\u00EC': 'i',
|
|
'\u00ED': 'i',
|
|
'\u00EE': 'i',
|
|
'\u0129': 'i',
|
|
'\u012B': 'i',
|
|
'\u012D': 'i',
|
|
'\u00EF': 'i',
|
|
'\u1E2F': 'i',
|
|
'\u1EC9': 'i',
|
|
'\u01D0': 'i',
|
|
'\u0209': 'i',
|
|
'\u020B': 'i',
|
|
'\u1ECB': 'i',
|
|
'\u012F': 'i',
|
|
'\u1E2D': 'i',
|
|
'\u0268': 'i',
|
|
'\u0131': 'i',
|
|
'\u24D9': 'j',
|
|
'\uFF4A': 'j',
|
|
'\u0135': 'j',
|
|
'\u01F0': 'j',
|
|
'\u0249': 'j',
|
|
'\u24DA': 'k',
|
|
'\uFF4B': 'k',
|
|
'\u1E31': 'k',
|
|
'\u01E9': 'k',
|
|
'\u1E33': 'k',
|
|
'\u0137': 'k',
|
|
'\u1E35': 'k',
|
|
'\u0199': 'k',
|
|
'\u2C6A': 'k',
|
|
'\uA741': 'k',
|
|
'\uA743': 'k',
|
|
'\uA745': 'k',
|
|
'\uA7A3': 'k',
|
|
'\u24DB': 'l',
|
|
'\uFF4C': 'l',
|
|
'\u0140': 'l',
|
|
'\u013A': 'l',
|
|
'\u013E': 'l',
|
|
'\u1E37': 'l',
|
|
'\u1E39': 'l',
|
|
'\u013C': 'l',
|
|
'\u1E3D': 'l',
|
|
'\u1E3B': 'l',
|
|
'\u017F': 'l',
|
|
'\u0142': 'l',
|
|
'\u019A': 'l',
|
|
'\u026B': 'l',
|
|
'\u2C61': 'l',
|
|
'\uA749': 'l',
|
|
'\uA781': 'l',
|
|
'\uA747': 'l',
|
|
'\u01C9': 'lj',
|
|
'\u24DC': 'm',
|
|
'\uFF4D': 'm',
|
|
'\u1E3F': 'm',
|
|
'\u1E41': 'm',
|
|
'\u1E43': 'm',
|
|
'\u0271': 'm',
|
|
'\u026F': 'm',
|
|
'\u24DD': 'n',
|
|
'\uFF4E': 'n',
|
|
'\u01F9': 'n',
|
|
'\u0144': 'n',
|
|
'\u00F1': 'n',
|
|
'\u1E45': 'n',
|
|
'\u0148': 'n',
|
|
'\u1E47': 'n',
|
|
'\u0146': 'n',
|
|
'\u1E4B': 'n',
|
|
'\u1E49': 'n',
|
|
'\u019E': 'n',
|
|
'\u0272': 'n',
|
|
'\u0149': 'n',
|
|
'\uA791': 'n',
|
|
'\uA7A5': 'n',
|
|
'\u01CC': 'nj',
|
|
'\u24DE': 'o',
|
|
'\uFF4F': 'o',
|
|
'\u00F2': 'o',
|
|
'\u00F3': 'o',
|
|
'\u00F4': 'o',
|
|
'\u1ED3': 'o',
|
|
'\u1ED1': 'o',
|
|
'\u1ED7': 'o',
|
|
'\u1ED5': 'o',
|
|
'\u00F5': 'o',
|
|
'\u1E4D': 'o',
|
|
'\u022D': 'o',
|
|
'\u1E4F': 'o',
|
|
'\u014D': 'o',
|
|
'\u1E51': 'o',
|
|
'\u1E53': 'o',
|
|
'\u014F': 'o',
|
|
'\u022F': 'o',
|
|
'\u0231': 'o',
|
|
'\u00F6': 'o',
|
|
'\u022B': 'o',
|
|
'\u1ECF': 'o',
|
|
'\u0151': 'o',
|
|
'\u01D2': 'o',
|
|
'\u020D': 'o',
|
|
'\u020F': 'o',
|
|
'\u01A1': 'o',
|
|
'\u1EDD': 'o',
|
|
'\u1EDB': 'o',
|
|
'\u1EE1': 'o',
|
|
'\u1EDF': 'o',
|
|
'\u1EE3': 'o',
|
|
'\u1ECD': 'o',
|
|
'\u1ED9': 'o',
|
|
'\u01EB': 'o',
|
|
'\u01ED': 'o',
|
|
'\u00F8': 'o',
|
|
'\u01FF': 'o',
|
|
'\u0254': 'o',
|
|
'\uA74B': 'o',
|
|
'\uA74D': 'o',
|
|
'\u0275': 'o',
|
|
'\u0153': 'oe',
|
|
'\u01A3': 'oi',
|
|
'\u0223': 'ou',
|
|
'\uA74F': 'oo',
|
|
'\u24DF': 'p',
|
|
'\uFF50': 'p',
|
|
'\u1E55': 'p',
|
|
'\u1E57': 'p',
|
|
'\u01A5': 'p',
|
|
'\u1D7D': 'p',
|
|
'\uA751': 'p',
|
|
'\uA753': 'p',
|
|
'\uA755': 'p',
|
|
'\u24E0': 'q',
|
|
'\uFF51': 'q',
|
|
'\u024B': 'q',
|
|
'\uA757': 'q',
|
|
'\uA759': 'q',
|
|
'\u24E1': 'r',
|
|
'\uFF52': 'r',
|
|
'\u0155': 'r',
|
|
'\u1E59': 'r',
|
|
'\u0159': 'r',
|
|
'\u0211': 'r',
|
|
'\u0213': 'r',
|
|
'\u1E5B': 'r',
|
|
'\u1E5D': 'r',
|
|
'\u0157': 'r',
|
|
'\u1E5F': 'r',
|
|
'\u024D': 'r',
|
|
'\u027D': 'r',
|
|
'\uA75B': 'r',
|
|
'\uA7A7': 'r',
|
|
'\uA783': 'r',
|
|
'\u24E2': 's',
|
|
'\uFF53': 's',
|
|
'\u00DF': 's',
|
|
'\u015B': 's',
|
|
'\u1E65': 's',
|
|
'\u015D': 's',
|
|
'\u1E61': 's',
|
|
'\u0161': 's',
|
|
'\u1E67': 's',
|
|
'\u1E63': 's',
|
|
'\u1E69': 's',
|
|
'\u0219': 's',
|
|
'\u015F': 's',
|
|
'\u023F': 's',
|
|
'\uA7A9': 's',
|
|
'\uA785': 's',
|
|
'\u1E9B': 's',
|
|
'\u24E3': 't',
|
|
'\uFF54': 't',
|
|
'\u1E6B': 't',
|
|
'\u1E97': 't',
|
|
'\u0165': 't',
|
|
'\u1E6D': 't',
|
|
'\u021B': 't',
|
|
'\u0163': 't',
|
|
'\u1E71': 't',
|
|
'\u1E6F': 't',
|
|
'\u0167': 't',
|
|
'\u01AD': 't',
|
|
'\u0288': 't',
|
|
'\u2C66': 't',
|
|
'\uA787': 't',
|
|
'\uA729': 'tz',
|
|
'\u24E4': 'u',
|
|
'\uFF55': 'u',
|
|
'\u00F9': 'u',
|
|
'\u00FA': 'u',
|
|
'\u00FB': 'u',
|
|
'\u0169': 'u',
|
|
'\u1E79': 'u',
|
|
'\u016B': 'u',
|
|
'\u1E7B': 'u',
|
|
'\u016D': 'u',
|
|
'\u00FC': 'u',
|
|
'\u01DC': 'u',
|
|
'\u01D8': 'u',
|
|
'\u01D6': 'u',
|
|
'\u01DA': 'u',
|
|
'\u1EE7': 'u',
|
|
'\u016F': 'u',
|
|
'\u0171': 'u',
|
|
'\u01D4': 'u',
|
|
'\u0215': 'u',
|
|
'\u0217': 'u',
|
|
'\u01B0': 'u',
|
|
'\u1EEB': 'u',
|
|
'\u1EE9': 'u',
|
|
'\u1EEF': 'u',
|
|
'\u1EED': 'u',
|
|
'\u1EF1': 'u',
|
|
'\u1EE5': 'u',
|
|
'\u1E73': 'u',
|
|
'\u0173': 'u',
|
|
'\u1E77': 'u',
|
|
'\u1E75': 'u',
|
|
'\u0289': 'u',
|
|
'\u24E5': 'v',
|
|
'\uFF56': 'v',
|
|
'\u1E7D': 'v',
|
|
'\u1E7F': 'v',
|
|
'\u028B': 'v',
|
|
'\uA75F': 'v',
|
|
'\u028C': 'v',
|
|
'\uA761': 'vy',
|
|
'\u24E6': 'w',
|
|
'\uFF57': 'w',
|
|
'\u1E81': 'w',
|
|
'\u1E83': 'w',
|
|
'\u0175': 'w',
|
|
'\u1E87': 'w',
|
|
'\u1E85': 'w',
|
|
'\u1E98': 'w',
|
|
'\u1E89': 'w',
|
|
'\u2C73': 'w',
|
|
'\u24E7': 'x',
|
|
'\uFF58': 'x',
|
|
'\u1E8B': 'x',
|
|
'\u1E8D': 'x',
|
|
'\u24E8': 'y',
|
|
'\uFF59': 'y',
|
|
'\u1EF3': 'y',
|
|
'\u00FD': 'y',
|
|
'\u0177': 'y',
|
|
'\u1EF9': 'y',
|
|
'\u0233': 'y',
|
|
'\u1E8F': 'y',
|
|
'\u00FF': 'y',
|
|
'\u1EF7': 'y',
|
|
'\u1E99': 'y',
|
|
'\u1EF5': 'y',
|
|
'\u01B4': 'y',
|
|
'\u024F': 'y',
|
|
'\u1EFF': 'y',
|
|
'\u24E9': 'z',
|
|
'\uFF5A': 'z',
|
|
'\u017A': 'z',
|
|
'\u1E91': 'z',
|
|
'\u017C': 'z',
|
|
'\u017E': 'z',
|
|
'\u1E93': 'z',
|
|
'\u1E95': 'z',
|
|
'\u01B6': 'z',
|
|
'\u0225': 'z',
|
|
'\u0240': 'z',
|
|
'\u2C6C': 'z',
|
|
'\uA763': 'z',
|
|
'\u0386': '\u0391',
|
|
'\u0388': '\u0395',
|
|
'\u0389': '\u0397',
|
|
'\u038A': '\u0399',
|
|
'\u03AA': '\u0399',
|
|
'\u038C': '\u039F',
|
|
'\u038E': '\u03A5',
|
|
'\u03AB': '\u03A5',
|
|
'\u038F': '\u03A9',
|
|
'\u03AC': '\u03B1',
|
|
'\u03AD': '\u03B5',
|
|
'\u03AE': '\u03B7',
|
|
'\u03AF': '\u03B9',
|
|
'\u03CA': '\u03B9',
|
|
'\u0390': '\u03B9',
|
|
'\u03CC': '\u03BF',
|
|
'\u03CD': '\u03C5',
|
|
'\u03CB': '\u03C5',
|
|
'\u03B0': '\u03C5',
|
|
'\u03CE': '\u03C9',
|
|
'\u03C2': '\u03C3',
|
|
'\u2019': '\''
|
|
};
|
|
|
|
return diacritics;
|
|
});
|
|
|
|
S2.define('select2/data/base',[
|
|
'../utils'
|
|
], function (Utils) {
|
|
function BaseAdapter ($element, options) {
|
|
BaseAdapter.__super__.constructor.call(this);
|
|
}
|
|
|
|
Utils.Extend(BaseAdapter, Utils.Observable);
|
|
|
|
BaseAdapter.prototype.current = function (callback) {
|
|
throw new Error('The `current` method must be defined in child classes.');
|
|
};
|
|
|
|
BaseAdapter.prototype.query = function (params, callback) {
|
|
throw new Error('The `query` method must be defined in child classes.');
|
|
};
|
|
|
|
BaseAdapter.prototype.bind = function (container, $container) {
|
|
// Can be implemented in subclasses
|
|
};
|
|
|
|
BaseAdapter.prototype.destroy = function () {
|
|
// Can be implemented in subclasses
|
|
};
|
|
|
|
BaseAdapter.prototype.generateResultId = function (container, data) {
|
|
var id = container.id + '-result-';
|
|
|
|
id += Utils.generateChars(4);
|
|
|
|
if (data.id != null) {
|
|
id += '-' + data.id.toString();
|
|
} else {
|
|
id += '-' + Utils.generateChars(4);
|
|
}
|
|
return id;
|
|
};
|
|
|
|
return BaseAdapter;
|
|
});
|
|
|
|
S2.define('select2/data/select',[
|
|
'./base',
|
|
'../utils',
|
|
'jquery'
|
|
], function (BaseAdapter, Utils, $) {
|
|
function SelectAdapter ($element, options) {
|
|
this.$element = $element;
|
|
this.options = options;
|
|
|
|
SelectAdapter.__super__.constructor.call(this);
|
|
}
|
|
|
|
Utils.Extend(SelectAdapter, BaseAdapter);
|
|
|
|
SelectAdapter.prototype.current = function (callback) {
|
|
var data = [];
|
|
var self = this;
|
|
|
|
this.$element.find(':selected').each(function () {
|
|
var $option = $(this);
|
|
|
|
var option = self.item($option);
|
|
|
|
data.push(option);
|
|
});
|
|
|
|
callback(data);
|
|
};
|
|
|
|
SelectAdapter.prototype.select = function (data) {
|
|
var self = this;
|
|
|
|
data.selected = true;
|
|
|
|
// If data.element is a DOM node, use it instead
|
|
if ($(data.element).is('option')) {
|
|
data.element.selected = true;
|
|
|
|
this.$element.trigger('input').trigger('change');
|
|
|
|
return;
|
|
}
|
|
|
|
if (this.$element.prop('multiple')) {
|
|
this.current(function (currentData) {
|
|
var val = [];
|
|
|
|
data = [data];
|
|
data.push.apply(data, currentData);
|
|
|
|
for (var d = 0; d < data.length; d++) {
|
|
var id = data[d].id;
|
|
|
|
if ($.inArray(id, val) === -1) {
|
|
val.push(id);
|
|
}
|
|
}
|
|
|
|
self.$element.val(val);
|
|
self.$element.trigger('input').trigger('change');
|
|
});
|
|
} else {
|
|
var val = data.id;
|
|
|
|
this.$element.val(val);
|
|
this.$element.trigger('input').trigger('change');
|
|
}
|
|
};
|
|
|
|
SelectAdapter.prototype.unselect = function (data) {
|
|
var self = this;
|
|
|
|
if (!this.$element.prop('multiple')) {
|
|
return;
|
|
}
|
|
|
|
data.selected = false;
|
|
|
|
if ($(data.element).is('option')) {
|
|
data.element.selected = false;
|
|
|
|
this.$element.trigger('input').trigger('change');
|
|
|
|
return;
|
|
}
|
|
|
|
this.current(function (currentData) {
|
|
var val = [];
|
|
|
|
for (var d = 0; d < currentData.length; d++) {
|
|
var id = currentData[d].id;
|
|
|
|
if (id !== data.id && $.inArray(id, val) === -1) {
|
|
val.push(id);
|
|
}
|
|
}
|
|
|
|
self.$element.val(val);
|
|
|
|
self.$element.trigger('input').trigger('change');
|
|
});
|
|
};
|
|
|
|
SelectAdapter.prototype.bind = function (container, $container) {
|
|
var self = this;
|
|
|
|
this.container = container;
|
|
|
|
container.on('select', function (params) {
|
|
self.select(params.data);
|
|
});
|
|
|
|
container.on('unselect', function (params) {
|
|
self.unselect(params.data);
|
|
});
|
|
};
|
|
|
|
SelectAdapter.prototype.destroy = function () {
|
|
// Remove anything added to child elements
|
|
this.$element.find('*').each(function () {
|
|
// Remove any custom data set by Select2
|
|
Utils.RemoveData(this);
|
|
});
|
|
};
|
|
|
|
SelectAdapter.prototype.query = function (params, callback) {
|
|
var data = [];
|
|
var self = this;
|
|
|
|
var $options = this.$element.children();
|
|
|
|
$options.each(function () {
|
|
var $option = $(this);
|
|
|
|
if (!$option.is('option') && !$option.is('optgroup')) {
|
|
return;
|
|
}
|
|
|
|
var option = self.item($option);
|
|
|
|
var matches = self.matches(params, option);
|
|
|
|
if (matches !== null) {
|
|
data.push(matches);
|
|
}
|
|
});
|
|
|
|
callback({
|
|
results: data
|
|
});
|
|
};
|
|
|
|
SelectAdapter.prototype.addOptions = function ($options) {
|
|
Utils.appendMany(this.$element, $options);
|
|
};
|
|
|
|
SelectAdapter.prototype.option = function (data) {
|
|
var option;
|
|
|
|
if (data.children) {
|
|
option = document.createElement('optgroup');
|
|
option.label = data.text;
|
|
} else {
|
|
option = document.createElement('option');
|
|
|
|
if (option.textContent !== undefined) {
|
|
option.textContent = data.text;
|
|
} else {
|
|
option.innerText = data.text;
|
|
}
|
|
}
|
|
|
|
if (data.id !== undefined) {
|
|
option.value = data.id;
|
|
}
|
|
|
|
if (data.disabled) {
|
|
option.disabled = true;
|
|
}
|
|
|
|
if (data.selected) {
|
|
option.selected = true;
|
|
}
|
|
|
|
if (data.title) {
|
|
option.title = data.title;
|
|
}
|
|
|
|
var $option = $(option);
|
|
|
|
var normalizedData = this._normalizeItem(data);
|
|
normalizedData.element = option;
|
|
|
|
// Override the option's data with the combined data
|
|
Utils.StoreData(option, 'data', normalizedData);
|
|
|
|
return $option;
|
|
};
|
|
|
|
SelectAdapter.prototype.item = function ($option) {
|
|
var data = {};
|
|
|
|
data = Utils.GetData($option[0], 'data');
|
|
|
|
if (data != null) {
|
|
return data;
|
|
}
|
|
|
|
if ($option.is('option')) {
|
|
data = {
|
|
id: $option.val(),
|
|
text: $option.text(),
|
|
disabled: $option.prop('disabled'),
|
|
selected: $option.prop('selected'),
|
|
title: $option.prop('title')
|
|
};
|
|
} else if ($option.is('optgroup')) {
|
|
data = {
|
|
text: $option.prop('label'),
|
|
children: [],
|
|
title: $option.prop('title')
|
|
};
|
|
|
|
var $children = $option.children('option');
|
|
var children = [];
|
|
|
|
for (var c = 0; c < $children.length; c++) {
|
|
var $child = $($children[c]);
|
|
|
|
var child = this.item($child);
|
|
|
|
children.push(child);
|
|
}
|
|
|
|
data.children = children;
|
|
}
|
|
|
|
data = this._normalizeItem(data);
|
|
data.element = $option[0];
|
|
|
|
Utils.StoreData($option[0], 'data', data);
|
|
|
|
return data;
|
|
};
|
|
|
|
SelectAdapter.prototype._normalizeItem = function (item) {
|
|
if (item !== Object(item)) {
|
|
item = {
|
|
id: item,
|
|
text: item
|
|
};
|
|
}
|
|
|
|
item = $.extend({}, {
|
|
text: ''
|
|
}, item);
|
|
|
|
var defaults = {
|
|
selected: false,
|
|
disabled: false
|
|
};
|
|
|
|
if (item.id != null) {
|
|
item.id = item.id.toString();
|
|
}
|
|
|
|
if (item.text != null) {
|
|
item.text = item.text.toString();
|
|
}
|
|
|
|
if (item._resultId == null && item.id && this.container != null) {
|
|
item._resultId = this.generateResultId(this.container, item);
|
|
}
|
|
|
|
return $.extend({}, defaults, item);
|
|
};
|
|
|
|
SelectAdapter.prototype.matches = function (params, data) {
|
|
var matcher = this.options.get('matcher');
|
|
|
|
return matcher(params, data);
|
|
};
|
|
|
|
return SelectAdapter;
|
|
});
|
|
|
|
S2.define('select2/data/array',[
|
|
'./select',
|
|
'../utils',
|
|
'jquery'
|
|
], function (SelectAdapter, Utils, $) {
|
|
function ArrayAdapter ($element, options) {
|
|
this._dataToConvert = options.get('data') || [];
|
|
|
|
ArrayAdapter.__super__.constructor.call(this, $element, options);
|
|
}
|
|
|
|
Utils.Extend(ArrayAdapter, SelectAdapter);
|
|
|
|
ArrayAdapter.prototype.bind = function (container, $container) {
|
|
ArrayAdapter.__super__.bind.call(this, container, $container);
|
|
|
|
this.addOptions(this.convertToOptions(this._dataToConvert));
|
|
};
|
|
|
|
ArrayAdapter.prototype.select = function (data) {
|
|
var $option = this.$element.find('option').filter(function (i, elm) {
|
|
return elm.value == data.id.toString();
|
|
});
|
|
|
|
if ($option.length === 0) {
|
|
$option = this.option(data);
|
|
|
|
this.addOptions($option);
|
|
}
|
|
|
|
ArrayAdapter.__super__.select.call(this, data);
|
|
};
|
|
|
|
ArrayAdapter.prototype.convertToOptions = function (data) {
|
|
var self = this;
|
|
|
|
var $existing = this.$element.find('option');
|
|
var existingIds = $existing.map(function () {
|
|
return self.item($(this)).id;
|
|
}).get();
|
|
|
|
var $options = [];
|
|
|
|
// Filter out all items except for the one passed in the argument
|
|
function onlyItem (item) {
|
|
return function () {
|
|
return $(this).val() == item.id;
|
|
};
|
|
}
|
|
|
|
for (var d = 0; d < data.length; d++) {
|
|
var item = this._normalizeItem(data[d]);
|
|
|
|
// Skip items which were pre-loaded, only merge the data
|
|
if ($.inArray(item.id, existingIds) >= 0) {
|
|
var $existingOption = $existing.filter(onlyItem(item));
|
|
|
|
var existingData = this.item($existingOption);
|
|
var newData = $.extend(true, {}, item, existingData);
|
|
|
|
var $newOption = this.option(newData);
|
|
|
|
$existingOption.replaceWith($newOption);
|
|
|
|
continue;
|
|
}
|
|
|
|
var $option = this.option(item);
|
|
|
|
if (item.children) {
|
|
var $children = this.convertToOptions(item.children);
|
|
|
|
Utils.appendMany($option, $children);
|
|
}
|
|
|
|
$options.push($option);
|
|
}
|
|
|
|
return $options;
|
|
};
|
|
|
|
return ArrayAdapter;
|
|
});
|
|
|
|
S2.define('select2/data/ajax',[
|
|
'./array',
|
|
'../utils',
|
|
'jquery'
|
|
], function (ArrayAdapter, Utils, $) {
|
|
function AjaxAdapter ($element, options) {
|
|
this.ajaxOptions = this._applyDefaults(options.get('ajax'));
|
|
|
|
if (this.ajaxOptions.processResults != null) {
|
|
this.processResults = this.ajaxOptions.processResults;
|
|
}
|
|
|
|
AjaxAdapter.__super__.constructor.call(this, $element, options);
|
|
}
|
|
|
|
Utils.Extend(AjaxAdapter, ArrayAdapter);
|
|
|
|
AjaxAdapter.prototype._applyDefaults = function (options) {
|
|
var defaults = {
|
|
data: function (params) {
|
|
return $.extend({}, params, {
|
|
q: params.term
|
|
});
|
|
},
|
|
transport: function (params, success, failure) {
|
|
var $request = $.ajax(params);
|
|
|
|
$request.then(success);
|
|
$request.fail(failure);
|
|
|
|
return $request;
|
|
}
|
|
};
|
|
|
|
return $.extend({}, defaults, options, true);
|
|
};
|
|
|
|
AjaxAdapter.prototype.processResults = function (results) {
|
|
return results;
|
|
};
|
|
|
|
AjaxAdapter.prototype.query = function (params, callback) {
|
|
var matches = [];
|
|
var self = this;
|
|
|
|
if (this._request != null) {
|
|
// JSONP requests cannot always be aborted
|
|
if ($.isFunction(this._request.abort)) {
|
|
this._request.abort();
|
|
}
|
|
|
|
this._request = null;
|
|
}
|
|
|
|
var options = $.extend({
|
|
type: 'GET'
|
|
}, this.ajaxOptions);
|
|
|
|
if (typeof options.url === 'function') {
|
|
options.url = options.url.call(this.$element, params);
|
|
}
|
|
|
|
if (typeof options.data === 'function') {
|
|
options.data = options.data.call(this.$element, params);
|
|
}
|
|
|
|
function request () {
|
|
var $request = options.transport(options, function (data) {
|
|
var results = self.processResults(data, params);
|
|
|
|
if (self.options.get('debug') && window.console && console.error) {
|
|
// Check to make sure that the response included a `results` key.
|
|
if (!results || !results.results || !$.isArray(results.results)) {
|
|
console.error(
|
|
'Select2: The AJAX results did not return an array in the ' +
|
|
'`results` key of the response.'
|
|
);
|
|
}
|
|
}
|
|
|
|
callback(results);
|
|
}, function () {
|
|
// Attempt to detect if a request was aborted
|
|
// Only works if the transport exposes a status property
|
|
if ('status' in $request &&
|
|
($request.status === 0 || $request.status === '0')) {
|
|
return;
|
|
}
|
|
|
|
self.trigger('results:message', {
|
|
message: 'errorLoading'
|
|
});
|
|
});
|
|
|
|
self._request = $request;
|
|
}
|
|
|
|
if (this.ajaxOptions.delay && params.term != null) {
|
|
if (this._queryTimeout) {
|
|
window.clearTimeout(this._queryTimeout);
|
|
}
|
|
|
|
this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);
|
|
} else {
|
|
request();
|
|
}
|
|
};
|
|
|
|
return AjaxAdapter;
|
|
});
|
|
|
|
S2.define('select2/data/tags',[
|
|
'jquery'
|
|
], function ($) {
|
|
function Tags (decorated, $element, options) {
|
|
var tags = options.get('tags');
|
|
|
|
var createTag = options.get('createTag');
|
|
|
|
if (createTag !== undefined) {
|
|
this.createTag = createTag;
|
|
}
|
|
|
|
var insertTag = options.get('insertTag');
|
|
|
|
if (insertTag !== undefined) {
|
|
this.insertTag = insertTag;
|
|
}
|
|
|
|
decorated.call(this, $element, options);
|
|
|
|
if ($.isArray(tags)) {
|
|
for (var t = 0; t < tags.length; t++) {
|
|
var tag = tags[t];
|
|
var item = this._normalizeItem(tag);
|
|
|
|
var $option = this.option(item);
|
|
|
|
this.$element.append($option);
|
|
}
|
|
}
|
|
}
|
|
|
|
Tags.prototype.query = function (decorated, params, callback) {
|
|
var self = this;
|
|
|
|
this._removeOldTags();
|
|
|
|
if (params.term == null || params.page != null) {
|
|
decorated.call(this, params, callback);
|
|
return;
|
|
}
|
|
|
|
function wrapper (obj, child) {
|
|
var data = obj.results;
|
|
|
|
for (var i = 0; i < data.length; i++) {
|
|
var option = data[i];
|
|
|
|
var checkChildren = (
|
|
option.children != null &&
|
|
!wrapper({
|
|
results: option.children
|
|
}, true)
|
|
);
|
|
|
|
var optionText = (option.text || '').toUpperCase();
|
|
var paramsTerm = (params.term || '').toUpperCase();
|
|
|
|
var checkText = optionText === paramsTerm;
|
|
|
|
if (checkText || checkChildren) {
|
|
if (child) {
|
|
return false;
|
|
}
|
|
|
|
obj.data = data;
|
|
callback(obj);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (child) {
|
|
return true;
|
|
}
|
|
|
|
var tag = self.createTag(params);
|
|
|
|
if (tag != null) {
|
|
var $option = self.option(tag);
|
|
$option.attr('data-select2-tag', true);
|
|
|
|
self.addOptions([$option]);
|
|
|
|
self.insertTag(data, tag);
|
|
}
|
|
|
|
obj.results = data;
|
|
|
|
callback(obj);
|
|
}
|
|
|
|
decorated.call(this, params, wrapper);
|
|
};
|
|
|
|
Tags.prototype.createTag = function (decorated, params) {
|
|
var term = $.trim(params.term);
|
|
|
|
if (term === '') {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
id: term,
|
|
text: term
|
|
};
|
|
};
|
|
|
|
Tags.prototype.insertTag = function (_, data, tag) {
|
|
data.unshift(tag);
|
|
};
|
|
|
|
Tags.prototype._removeOldTags = function (_) {
|
|
var $options = this.$element.find('option[data-select2-tag]');
|
|
|
|
$options.each(function () {
|
|
if (this.selected) {
|
|
return;
|
|
}
|
|
|
|
$(this).remove();
|
|
});
|
|
};
|
|
|
|
return Tags;
|
|
});
|
|
|
|
S2.define('select2/data/tokenizer',[
|
|
'jquery'
|
|
], function ($) {
|
|
function Tokenizer (decorated, $element, options) {
|
|
var tokenizer = options.get('tokenizer');
|
|
|
|
if (tokenizer !== undefined) {
|
|
this.tokenizer = tokenizer;
|
|
}
|
|
|
|
decorated.call(this, $element, options);
|
|
}
|
|
|
|
Tokenizer.prototype.bind = function (decorated, container, $container) {
|
|
decorated.call(this, container, $container);
|
|
|
|
this.$search = container.dropdown.$search || container.selection.$search ||
|
|
$container.find('.select2-search__field');
|
|
};
|
|
|
|
Tokenizer.prototype.query = function (decorated, params, callback) {
|
|
var self = this;
|
|
|
|
function createAndSelect (data) {
|
|
// Normalize the data object so we can use it for checks
|
|
var item = self._normalizeItem(data);
|
|
|
|
// Check if the data object already exists as a tag
|
|
// Select it if it doesn't
|
|
var $existingOptions = self.$element.find('option').filter(function () {
|
|
return $(this).val() === item.id;
|
|
});
|
|
|
|
// If an existing option wasn't found for it, create the option
|
|
if (!$existingOptions.length) {
|
|
var $option = self.option(item);
|
|
$option.attr('data-select2-tag', true);
|
|
|
|
self._removeOldTags();
|
|
self.addOptions([$option]);
|
|
}
|
|
|
|
// Select the item, now that we know there is an option for it
|
|
select(item);
|
|
}
|
|
|
|
function select (data) {
|
|
self.trigger('select', {
|
|
data: data
|
|
});
|
|
}
|
|
|
|
params.term = params.term || '';
|
|
|
|
var tokenData = this.tokenizer(params, this.options, createAndSelect);
|
|
|
|
if (tokenData.term !== params.term) {
|
|
// Replace the search term if we have the search box
|
|
if (this.$search.length) {
|
|
this.$search.val(tokenData.term);
|
|
this.$search.trigger('focus');
|
|
}
|
|
|
|
params.term = tokenData.term;
|
|
}
|
|
|
|
decorated.call(this, params, callback);
|
|
};
|
|
|
|
Tokenizer.prototype.tokenizer = function (_, params, options, callback) {
|
|
var separators = options.get('tokenSeparators') || [];
|
|
var term = params.term;
|
|
var i = 0;
|
|
|
|
var createTag = this.createTag || function (params) {
|
|
return {
|
|
id: params.term,
|
|
text: params.term
|
|
};
|
|
};
|
|
|
|
while (i < term.length) {
|
|
var termChar = term[i];
|
|
|
|
if ($.inArray(termChar, separators) === -1) {
|
|
i++;
|
|
|
|
continue;
|
|
}
|
|
|
|
var part = term.substr(0, i);
|
|
var partParams = $.extend({}, params, {
|
|
term: part
|
|
});
|
|
|
|
var data = createTag(partParams);
|
|
|
|
if (data == null) {
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
callback(data);
|
|
|
|
// Reset the term to not include the tokenized portion
|
|
term = term.substr(i + 1) || '';
|
|
i = 0;
|
|
}
|
|
|
|
return {
|
|
term: term
|
|
};
|
|
};
|
|
|
|
return Tokenizer;
|
|
});
|
|
|
|
S2.define('select2/data/minimumInputLength',[
|
|
|
|
], function () {
|
|
function MinimumInputLength (decorated, $e, options) {
|
|
this.minimumInputLength = options.get('minimumInputLength');
|
|
|
|
decorated.call(this, $e, options);
|
|
}
|
|
|
|
MinimumInputLength.prototype.query = function (decorated, params, callback) {
|
|
params.term = params.term || '';
|
|
|
|
if (params.term.length < this.minimumInputLength) {
|
|
this.trigger('results:message', {
|
|
message: 'inputTooShort',
|
|
args: {
|
|
minimum: this.minimumInputLength,
|
|
input: params.term,
|
|
params: params
|
|
}
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
decorated.call(this, params, callback);
|
|
};
|
|
|
|
return MinimumInputLength;
|
|
});
|
|
|
|
S2.define('select2/data/maximumInputLength',[
|
|
|
|
], function () {
|
|
function MaximumInputLength (decorated, $e, options) {
|
|
this.maximumInputLength = options.get('maximumInputLength');
|
|
|
|
decorated.call(this, $e, options);
|
|
}
|
|
|
|
MaximumInputLength.prototype.query = function (decorated, params, callback) {
|
|
params.term = params.term || '';
|
|
|
|
if (this.maximumInputLength > 0 &&
|
|
params.term.length > this.maximumInputLength) {
|
|
this.trigger('results:message', {
|
|
message: 'inputTooLong',
|
|
args: {
|
|
maximum: this.maximumInputLength,
|
|
input: params.term,
|
|
params: params
|
|
}
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
decorated.call(this, params, callback);
|
|
};
|
|
|
|
return MaximumInputLength;
|
|
});
|
|
|
|
S2.define('select2/data/maximumSelectionLength',[
|
|
|
|
], function (){
|
|
function MaximumSelectionLength (decorated, $e, options) {
|
|
this.maximumSelectionLength = options.get('maximumSelectionLength');
|
|
|
|
decorated.call(this, $e, options);
|
|
}
|
|
|
|
MaximumSelectionLength.prototype.bind =
|
|
function (decorated, container, $container) {
|
|
var self = this;
|
|
|
|
decorated.call(this, container, $container);
|
|
|
|
container.on('select', function () {
|
|
self._checkIfMaximumSelected();
|
|
});
|
|
};
|
|
|
|
MaximumSelectionLength.prototype.query =
|
|
function (decorated, params, callback) {
|
|
var self = this;
|
|
|
|
this._checkIfMaximumSelected(function () {
|
|
decorated.call(self, params, callback);
|
|
});
|
|
};
|
|
|
|
MaximumSelectionLength.prototype._checkIfMaximumSelected =
|
|
function (_, successCallback) {
|
|
var self = this;
|
|
|
|
this.current(function (currentData) {
|
|
var count = currentData != null ? currentData.length : 0;
|
|
if (self.maximumSelectionLength > 0 &&
|
|
count >= self.maximumSelectionLength) {
|
|
self.trigger('results:message', {
|
|
message: 'maximumSelected',
|
|
args: {
|
|
maximum: self.maximumSelectionLength
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (successCallback) {
|
|
successCallback();
|
|
}
|
|
});
|
|
};
|
|
|
|
return MaximumSelectionLength;
|
|
});
|
|
|
|
S2.define('select2/dropdown',[
|
|
'jquery',
|
|
'./utils'
|
|
], function ($, Utils) {
|
|
function Dropdown ($element, options) {
|
|
this.$element = $element;
|
|
this.options = options;
|
|
|
|
Dropdown.__super__.constructor.call(this);
|
|
}
|
|
|
|
Utils.Extend(Dropdown, Utils.Observable);
|
|
|
|
Dropdown.prototype.render = function () {
|
|
var $dropdown = $(
|
|
'<span class="select2-dropdown">' +
|
|
'<span class="select2-results"></span>' +
|
|
'</span>'
|
|
);
|
|
|
|
$dropdown.attr('dir', this.options.get('dir'));
|
|
|
|
this.$dropdown = $dropdown;
|
|
|
|
return $dropdown;
|
|
};
|
|
|
|
Dropdown.prototype.bind = function () {
|
|
// Should be implemented in subclasses
|
|
};
|
|
|
|
Dropdown.prototype.position = function ($dropdown, $container) {
|
|
// Should be implemented in subclasses
|
|
};
|
|
|
|
Dropdown.prototype.destroy = function () {
|
|
// Remove the dropdown from the DOM
|
|
this.$dropdown.remove();
|
|
};
|
|
|
|
return Dropdown;
|
|
});
|
|
|
|
S2.define('select2/dropdown/search',[
|
|
'jquery',
|
|
'../utils'
|
|
], function ($, Utils) {
|
|
function Search () { }
|
|
|
|
Search.prototype.render = function (decorated) {
|
|
var $rendered = decorated.call(this);
|
|
|
|
var $search = $(
|
|
'<span class="select2-search select2-search--dropdown">' +
|
|
'<input class="select2-search__field" type="search" tabindex="-1"' +
|
|
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
|
|
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
|
|
'</span>'
|
|
);
|
|
|
|
this.$searchContainer = $search;
|
|
this.$search = $search.find('input');
|
|
|
|
$rendered.prepend($search);
|
|
|
|
return $rendered;
|
|
};
|
|
|
|
Search.prototype.bind = function (decorated, container, $container) {
|
|
var self = this;
|
|
|
|
var resultsId = container.id + '-results';
|
|
|
|
decorated.call(this, container, $container);
|
|
|
|
this.$search.on('keydown', function (evt) {
|
|
self.trigger('keypress', evt);
|
|
|
|
self._keyUpPrevented = evt.isDefaultPrevented();
|
|
});
|
|
|
|
// Workaround for browsers which do not support the `input` event
|
|
// This will prevent double-triggering of events for browsers which support
|
|
// both the `keyup` and `input` events.
|
|
this.$search.on('input', function (evt) {
|
|
// Unbind the duplicated `keyup` event
|
|
$(this).off('keyup');
|
|
});
|
|
|
|
this.$search.on('keyup input', function (evt) {
|
|
self.handleSearch(evt);
|
|
});
|
|
|
|
container.on('open', function () {
|
|
self.$search.attr('tabindex', 0);
|
|
self.$search.attr('aria-controls', resultsId);
|
|
|
|
self.$search.trigger('focus');
|
|
|
|
window.setTimeout(function () {
|
|
self.$search.trigger('focus');
|
|
}, 0);
|
|
});
|
|
|
|
container.on('close', function () {
|
|
self.$search.attr('tabindex', -1);
|
|
self.$search.removeAttr('aria-controls');
|
|
self.$search.removeAttr('aria-activedescendant');
|
|
|
|
self.$search.val('');
|
|
self.$search.trigger('blur');
|
|
});
|
|
|
|
container.on('focus', function () {
|
|
if (!container.isOpen()) {
|
|
self.$search.trigger('focus');
|
|
}
|
|
});
|
|
|
|
container.on('results:all', function (params) {
|
|
if (params.query.term == null || params.query.term === '') {
|
|
var showSearch = self.showSearch(params);
|
|
|
|
if (showSearch) {
|
|
self.$searchContainer.removeClass('select2-search--hide');
|
|
} else {
|
|
self.$searchContainer.addClass('select2-search--hide');
|
|
}
|
|
}
|
|
});
|
|
|
|
container.on('results:focus', function (params) {
|
|
if (params.data._resultId) {
|
|
self.$search.attr('aria-activedescendant', params.data._resultId);
|
|
} else {
|
|
self.$search.removeAttr('aria-activedescendant');
|
|
}
|
|
});
|
|
};
|
|
|
|
Search.prototype.handleSearch = function (evt) {
|
|
if (!this._keyUpPrevented) {
|
|
var input = this.$search.val();
|
|
|
|
this.trigger('query', {
|
|
term: input
|
|
});
|
|
}
|
|
|
|
this._keyUpPrevented = false;
|
|
};
|
|
|
|
Search.prototype.showSearch = function (_, params) {
|
|
return true;
|
|
};
|
|
|
|
return Search;
|
|
});
|
|
|
|
S2.define('select2/dropdown/hidePlaceholder',[
|
|
|
|
], function () {
|
|
function HidePlaceholder (decorated, $element, options, dataAdapter) {
|
|
this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
|
|
|
|
decorated.call(this, $element, options, dataAdapter);
|
|
}
|
|
|
|
HidePlaceholder.prototype.append = function (decorated, data) {
|
|
data.results = this.removePlaceholder(data.results);
|
|
|
|
decorated.call(this, data);
|
|
};
|
|
|
|
HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {
|
|
if (typeof placeholder === 'string') {
|
|
placeholder = {
|
|
id: '',
|
|
text: placeholder
|
|
};
|
|
}
|
|
|
|
return placeholder;
|
|
};
|
|
|
|
HidePlaceholder.prototype.removePlaceholder = function (_, data) {
|
|
var modifiedData = data.slice(0);
|
|
|
|
for (var d = data.length - 1; d >= 0; d--) {
|
|
var item = data[d];
|
|
|
|
if (this.placeholder.id === item.id) {
|
|
modifiedData.splice(d, 1);
|
|
}
|
|
}
|
|
|
|
return modifiedData;
|
|
};
|
|
|
|
return HidePlaceholder;
|
|
});
|
|
|
|
S2.define('select2/dropdown/infiniteScroll',[
|
|
'jquery'
|
|
], function ($) {
|
|
function InfiniteScroll (decorated, $element, options, dataAdapter) {
|
|
this.lastParams = {};
|
|
|
|
decorated.call(this, $element, options, dataAdapter);
|
|
|
|
this.$loadingMore = this.createLoadingMore();
|
|
this.loading = false;
|
|
}
|
|
|
|
InfiniteScroll.prototype.append = function (decorated, data) {
|
|
this.$loadingMore.remove();
|
|
this.loading = false;
|
|
|
|
decorated.call(this, data);
|
|
|
|
if (this.showLoadingMore(data)) {
|
|
this.$results.append(this.$loadingMore);
|
|
this.loadMoreIfNeeded();
|
|
}
|
|
};
|
|
|
|
InfiniteScroll.prototype.bind = function (decorated, container, $container) {
|
|
var self = this;
|
|
|
|
decorated.call(this, container, $container);
|
|
|
|
container.on('query', function (params) {
|
|
self.lastParams = params;
|
|
self.loading = true;
|
|
});
|
|
|
|
container.on('query:append', function (params) {
|
|
self.lastParams = params;
|
|
self.loading = true;
|
|
});
|
|
|
|
this.$results.on('scroll', this.loadMoreIfNeeded.bind(this));
|
|
};
|
|
|
|
InfiniteScroll.prototype.loadMoreIfNeeded = function () {
|
|
var isLoadMoreVisible = $.contains(
|
|
document.documentElement,
|
|
this.$loadingMore[0]
|
|
);
|
|
|
|
if (this.loading || !isLoadMoreVisible) {
|
|
return;
|
|
}
|
|
|
|
var currentOffset = this.$results.offset().top +
|
|
this.$results.outerHeight(false);
|
|
var loadingMoreOffset = this.$loadingMore.offset().top +
|
|
this.$loadingMore.outerHeight(false);
|
|
|
|
if (currentOffset + 50 >= loadingMoreOffset) {
|
|
this.loadMore();
|
|
}
|
|
};
|
|
|
|
InfiniteScroll.prototype.loadMore = function () {
|
|
this.loading = true;
|
|
|
|
var params = $.extend({}, {page: 1}, this.lastParams);
|
|
|
|
params.page++;
|
|
|
|
this.trigger('query:append', params);
|
|
};
|
|
|
|
InfiniteScroll.prototype.showLoadingMore = function (_, data) {
|
|
return data.pagination && data.pagination.more;
|
|
};
|
|
|
|
InfiniteScroll.prototype.createLoadingMore = function () {
|
|
var $option = $(
|
|
'<li ' +
|
|
'class="select2-results__option select2-results__option--load-more"' +
|
|
'role="option" aria-disabled="true"></li>'
|
|
);
|
|
|
|
var message = this.options.get('translations').get('loadingMore');
|
|
|
|
$option.html(message(this.lastParams));
|
|
|
|
return $option;
|
|
};
|
|
|
|
return InfiniteScroll;
|
|
});
|
|
|
|
S2.define('select2/dropdown/attachBody',[
|
|
'jquery',
|
|
'../utils'
|
|
], function ($, Utils) {
|
|
function AttachBody (decorated, $element, options) {
|
|
this.$dropdownParent = $(options.get('dropdownParent') || document.body);
|
|
|
|
decorated.call(this, $element, options);
|
|
}
|
|
|
|
AttachBody.prototype.bind = function (decorated, container, $container) {
|
|
var self = this;
|
|
|
|
decorated.call(this, container, $container);
|
|
|
|
container.on('open', function () {
|
|
self._showDropdown();
|
|
self._attachPositioningHandler(container);
|
|
|
|
// Must bind after the results handlers to ensure correct sizing
|
|
self._bindContainerResultHandlers(container);
|
|
});
|
|
|
|
container.on('close', function () {
|
|
self._hideDropdown();
|
|
self._detachPositioningHandler(container);
|
|
});
|
|
|
|
this.$dropdownContainer.on('mousedown', function (evt) {
|
|
evt.stopPropagation();
|
|
});
|
|
};
|
|
|
|
AttachBody.prototype.destroy = function (decorated) {
|
|
decorated.call(this);
|
|
|
|
this.$dropdownContainer.remove();
|
|
};
|
|
|
|
AttachBody.prototype.position = function (decorated, $dropdown, $container) {
|
|
// Clone all of the container classes
|
|
$dropdown.attr('class', $container.attr('class'));
|
|
|
|
$dropdown.removeClass('select2');
|
|
$dropdown.addClass('select2-container--open');
|
|
|
|
$dropdown.css({
|
|
position: 'absolute',
|
|
top: -999999
|
|
});
|
|
|
|
this.$container = $container;
|
|
};
|
|
|
|
AttachBody.prototype.render = function (decorated) {
|
|
var $container = $('<span></span>');
|
|
|
|
var $dropdown = decorated.call(this);
|
|
$container.append($dropdown);
|
|
|
|
this.$dropdownContainer = $container;
|
|
|
|
return $container;
|
|
};
|
|
|
|
AttachBody.prototype._hideDropdown = function (decorated) {
|
|
this.$dropdownContainer.detach();
|
|
};
|
|
|
|
AttachBody.prototype._bindContainerResultHandlers =
|
|
function (decorated, container) {
|
|
|
|
// These should only be bound once
|
|
if (this._containerResultsHandlersBound) {
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
|
|
container.on('results:all', function () {
|
|
self._positionDropdown();
|
|
self._resizeDropdown();
|
|
});
|
|
|
|
container.on('results:append', function () {
|
|
self._positionDropdown();
|
|
self._resizeDropdown();
|
|
});
|
|
|
|
container.on('results:message', function () {
|
|
self._positionDropdown();
|
|
self._resizeDropdown();
|
|
});
|
|
|
|
container.on('select', function () {
|
|
self._positionDropdown();
|
|
self._resizeDropdown();
|
|
});
|
|
|
|
container.on('unselect', function () {
|
|
self._positionDropdown();
|
|
self._resizeDropdown();
|
|
});
|
|
|
|
this._containerResultsHandlersBound = true;
|
|
};
|
|
|
|
AttachBody.prototype._attachPositioningHandler =
|
|
function (decorated, container) {
|
|
var self = this;
|
|
|
|
var scrollEvent = 'scroll.select2.' + container.id;
|
|
var resizeEvent = 'resize.select2.' + container.id;
|
|
var orientationEvent = 'orientationchange.select2.' + container.id;
|
|
|
|
var $watchers = this.$container.parents().filter(Utils.hasScroll);
|
|
$watchers.each(function () {
|
|
Utils.StoreData(this, 'select2-scroll-position', {
|
|
x: $(this).scrollLeft(),
|
|
y: $(this).scrollTop()
|
|
});
|
|
});
|
|
|
|
$watchers.on(scrollEvent, function (ev) {
|
|
var position = Utils.GetData(this, 'select2-scroll-position');
|
|
$(this).scrollTop(position.y);
|
|
});
|
|
|
|
$(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,
|
|
function (e) {
|
|
self._positionDropdown();
|
|
self._resizeDropdown();
|
|
});
|
|
};
|
|
|
|
AttachBody.prototype._detachPositioningHandler =
|
|
function (decorated, container) {
|
|
var scrollEvent = 'scroll.select2.' + container.id;
|
|
var resizeEvent = 'resize.select2.' + container.id;
|
|
var orientationEvent = 'orientationchange.select2.' + container.id;
|
|
|
|
var $watchers = this.$container.parents().filter(Utils.hasScroll);
|
|
$watchers.off(scrollEvent);
|
|
|
|
$(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);
|
|
};
|
|
|
|
AttachBody.prototype._positionDropdown = function () {
|
|
var $window = $(window);
|
|
|
|
var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
|
|
var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');
|
|
|
|
var newDirection = null;
|
|
|
|
var offset = this.$container.offset();
|
|
|
|
offset.bottom = offset.top + this.$container.outerHeight(false);
|
|
|
|
var container = {
|
|
height: this.$container.outerHeight(false)
|
|
};
|
|
|
|
container.top = offset.top;
|
|
container.bottom = offset.top + container.height;
|
|
|
|
var dropdown = {
|
|
height: this.$dropdown.outerHeight(false)
|
|
};
|
|
|
|
var viewport = {
|
|
top: $window.scrollTop(),
|
|
bottom: $window.scrollTop() + $window.height()
|
|
};
|
|
|
|
var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
|
|
var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
|
|
|
|
var css = {
|
|
left: offset.left,
|
|
top: container.bottom
|
|
};
|
|
|
|
// Determine what the parent element is to use for calculating the offset
|
|
var $offsetParent = this.$dropdownParent;
|
|
|
|
// For statically positioned elements, we need to get the element
|
|
// that is determining the offset
|
|
if ($offsetParent.css('position') === 'static') {
|
|
$offsetParent = $offsetParent.offsetParent();
|
|
}
|
|
|
|
var parentOffset = {
|
|
top: 0,
|
|
left: 0
|
|
};
|
|
|
|
if (
|
|
$.contains(document.body, $offsetParent[0]) ||
|
|
$offsetParent[0].isConnected
|
|
) {
|
|
parentOffset = $offsetParent.offset();
|
|
}
|
|
|
|
css.top -= parentOffset.top;
|
|
css.left -= parentOffset.left;
|
|
|
|
if (!isCurrentlyAbove && !isCurrentlyBelow) {
|
|
newDirection = 'below';
|
|
}
|
|
|
|
if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
|
|
newDirection = 'above';
|
|
} else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
|
|
newDirection = 'below';
|
|
}
|
|
|
|
if (newDirection == 'above' ||
|
|
(isCurrentlyAbove && newDirection !== 'below')) {
|
|
css.top = container.top - parentOffset.top - dropdown.height;
|
|
}
|
|
|
|
if (newDirection != null) {
|
|
this.$dropdown
|
|
.removeClass('select2-dropdown--below select2-dropdown--above')
|
|
.addClass('select2-dropdown--' + newDirection);
|
|
this.$container
|
|
.removeClass('select2-container--below select2-container--above')
|
|
.addClass('select2-container--' + newDirection);
|
|
}
|
|
|
|
this.$dropdownContainer.css(css);
|
|
};
|
|
|
|
AttachBody.prototype._resizeDropdown = function () {
|
|
var css = {
|
|
width: this.$container.outerWidth(false) + 'px'
|
|
};
|
|
|
|
if (this.options.get('dropdownAutoWidth')) {
|
|
css.minWidth = css.width;
|
|
css.position = 'relative';
|
|
css.width = 'auto';
|
|
}
|
|
|
|
this.$dropdown.css(css);
|
|
};
|
|
|
|
AttachBody.prototype._showDropdown = function (decorated) {
|
|
this.$dropdownContainer.appendTo(this.$dropdownParent);
|
|
|
|
this._positionDropdown();
|
|
this._resizeDropdown();
|
|
};
|
|
|
|
return AttachBody;
|
|
});
|
|
|
|
S2.define('select2/dropdown/minimumResultsForSearch',[
|
|
|
|
], function () {
|
|
function countResults (data) {
|
|
var count = 0;
|
|
|
|
for (var d = 0; d < data.length; d++) {
|
|
var item = data[d];
|
|
|
|
if (item.children) {
|
|
count += countResults(item.children);
|
|
} else {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
function MinimumResultsForSearch (decorated, $element, options, dataAdapter) {
|
|
this.minimumResultsForSearch = options.get('minimumResultsForSearch');
|
|
|
|
if (this.minimumResultsForSearch < 0) {
|
|
this.minimumResultsForSearch = Infinity;
|
|
}
|
|
|
|
decorated.call(this, $element, options, dataAdapter);
|
|
}
|
|
|
|
MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {
|
|
if (countResults(params.data.results) < this.minimumResultsForSearch) {
|
|
return false;
|
|
}
|
|
|
|
return decorated.call(this, params);
|
|
};
|
|
|
|
return MinimumResultsForSearch;
|
|
});
|
|
|
|
S2.define('select2/dropdown/selectOnClose',[
|
|
'../utils'
|
|
], function (Utils) {
|
|
function SelectOnClose () { }
|
|
|
|
SelectOnClose.prototype.bind = function (decorated, container, $container) {
|
|
var self = this;
|
|
|
|
decorated.call(this, container, $container);
|
|
|
|
container.on('close', function (params) {
|
|
self._handleSelectOnClose(params);
|
|
});
|
|
};
|
|
|
|
SelectOnClose.prototype._handleSelectOnClose = function (_, params) {
|
|
if (params && params.originalSelect2Event != null) {
|
|
var event = params.originalSelect2Event;
|
|
|
|
// Don't select an item if the close event was triggered from a select or
|
|
// unselect event
|
|
if (event._type === 'select' || event._type === 'unselect') {
|
|
return;
|
|
}
|
|
}
|
|
|
|
var $highlightedResults = this.getHighlightedResults();
|
|
|
|
// Only select highlighted results
|
|
if ($highlightedResults.length < 1) {
|
|
return;
|
|
}
|
|
|
|
var data = Utils.GetData($highlightedResults[0], 'data');
|
|
|
|
// Don't re-select already selected resulte
|
|
if (
|
|
(data.element != null && data.element.selected) ||
|
|
(data.element == null && data.selected)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
this.trigger('select', {
|
|
data: data
|
|
});
|
|
};
|
|
|
|
return SelectOnClose;
|
|
});
|
|
|
|
S2.define('select2/dropdown/closeOnSelect',[
|
|
|
|
], function () {
|
|
function CloseOnSelect () { }
|
|
|
|
CloseOnSelect.prototype.bind = function (decorated, container, $container) {
|
|
var self = this;
|
|
|
|
decorated.call(this, container, $container);
|
|
|
|
container.on('select', function (evt) {
|
|
self._selectTriggered(evt);
|
|
});
|
|
|
|
container.on('unselect', function (evt) {
|
|
self._selectTriggered(evt);
|
|
});
|
|
};
|
|
|
|
CloseOnSelect.prototype._selectTriggered = function (_, evt) {
|
|
var originalEvent = evt.originalEvent;
|
|
|
|
// Don't close if the control key is being held
|
|
if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) {
|
|
return;
|
|
}
|
|
|
|
this.trigger('close', {
|
|
originalEvent: originalEvent,
|
|
originalSelect2Event: evt
|
|
});
|
|
};
|
|
|
|
return CloseOnSelect;
|
|
});
|
|
|
|
S2.define('select2/i18n/en',[],function () {
|
|
// English
|
|
return {
|
|
errorLoading: function () {
|
|
return 'The results could not be loaded.';
|
|
},
|
|
inputTooLong: function (args) {
|
|
var overChars = args.input.length - args.maximum;
|
|
|
|
var message = 'Please delete ' + overChars + ' character';
|
|
|
|
if (overChars != 1) {
|
|
message += 's';
|
|
}
|
|
|
|
return message;
|
|
},
|
|
inputTooShort: function (args) {
|
|
var remainingChars = args.minimum - args.input.length;
|
|
|
|
var message = 'Please enter ' + remainingChars + ' or more characters';
|
|
|
|
return message;
|
|
},
|
|
loadingMore: function () {
|
|
return 'Loading more results…';
|
|
},
|
|
maximumSelected: function (args) {
|
|
var message = 'You can only select ' + args.maximum + ' item';
|
|
|
|
if (args.maximum != 1) {
|
|
message += 's';
|
|
}
|
|
|
|
return message;
|
|
},
|
|
noResults: function () {
|
|
return 'No results found';
|
|
},
|
|
searching: function () {
|
|
return 'Searching…';
|
|
},
|
|
removeAllItems: function () {
|
|
return 'Remove all items';
|
|
}
|
|
};
|
|
});
|
|
|
|
S2.define('select2/defaults',[
|
|
'jquery',
|
|
'require',
|
|
|
|
'./results',
|
|
|
|
'./selection/single',
|
|
'./selection/multiple',
|
|
'./selection/placeholder',
|
|
'./selection/allowClear',
|
|
'./selection/search',
|
|
'./selection/eventRelay',
|
|
|
|
'./utils',
|
|
'./translation',
|
|
'./diacritics',
|
|
|
|
'./data/select',
|
|
'./data/array',
|
|
'./data/ajax',
|
|
'./data/tags',
|
|
'./data/tokenizer',
|
|
'./data/minimumInputLength',
|
|
'./data/maximumInputLength',
|
|
'./data/maximumSelectionLength',
|
|
|
|
'./dropdown',
|
|
'./dropdown/search',
|
|
'./dropdown/hidePlaceholder',
|
|
'./dropdown/infiniteScroll',
|
|
'./dropdown/attachBody',
|
|
'./dropdown/minimumResultsForSearch',
|
|
'./dropdown/selectOnClose',
|
|
'./dropdown/closeOnSelect',
|
|
|
|
'./i18n/en'
|
|
], function ($, require,
|
|
|
|
ResultsList,
|
|
|
|
SingleSelection, MultipleSelection, Placeholder, AllowClear,
|
|
SelectionSearch, EventRelay,
|
|
|
|
Utils, Translation, DIACRITICS,
|
|
|
|
SelectData, ArrayData, AjaxData, Tags, Tokenizer,
|
|
MinimumInputLength, MaximumInputLength, MaximumSelectionLength,
|
|
|
|
Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
|
|
AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,
|
|
|
|
EnglishTranslation) {
|
|
function Defaults () {
|
|
this.reset();
|
|
}
|
|
|
|
Defaults.prototype.apply = function (options) {
|
|
options = $.extend(true, {}, this.defaults, options);
|
|
|
|
if (options.dataAdapter == null) {
|
|
if (options.ajax != null) {
|
|
options.dataAdapter = AjaxData;
|
|
} else if (options.data != null) {
|
|
options.dataAdapter = ArrayData;
|
|
} else {
|
|
options.dataAdapter = SelectData;
|
|
}
|
|
|
|
if (options.minimumInputLength > 0) {
|
|
options.dataAdapter = Utils.Decorate(
|
|
options.dataAdapter,
|
|
MinimumInputLength
|
|
);
|
|
}
|
|
|
|
if (options.maximumInputLength > 0) {
|
|
options.dataAdapter = Utils.Decorate(
|
|
options.dataAdapter,
|
|
MaximumInputLength
|
|
);
|
|
}
|
|
|
|
if (options.maximumSelectionLength > 0) {
|
|
options.dataAdapter = Utils.Decorate(
|
|
options.dataAdapter,
|
|
MaximumSelectionLength
|
|
);
|
|
}
|
|
|
|
if (options.tags) {
|
|
options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);
|
|
}
|
|
|
|
if (options.tokenSeparators != null || options.tokenizer != null) {
|
|
options.dataAdapter = Utils.Decorate(
|
|
options.dataAdapter,
|
|
Tokenizer
|
|
);
|
|
}
|
|
|
|
if (options.query != null) {
|
|
var Query = require(options.amdBase + 'compat/query');
|
|
|
|
options.dataAdapter = Utils.Decorate(
|
|
options.dataAdapter,
|
|
Query
|
|
);
|
|
}
|
|
|
|
if (options.initSelection != null) {
|
|
var InitSelection = require(options.amdBase + 'compat/initSelection');
|
|
|
|
options.dataAdapter = Utils.Decorate(
|
|
options.dataAdapter,
|
|
InitSelection
|
|
);
|
|
}
|
|
}
|
|
|
|
if (options.resultsAdapter == null) {
|
|
options.resultsAdapter = ResultsList;
|
|
|
|
if (options.ajax != null) {
|
|
options.resultsAdapter = Utils.Decorate(
|
|
options.resultsAdapter,
|
|
InfiniteScroll
|
|
);
|
|
}
|
|
|
|
if (options.placeholder != null) {
|
|
options.resultsAdapter = Utils.Decorate(
|
|
options.resultsAdapter,
|
|
HidePlaceholder
|
|
);
|
|
}
|
|
|
|
if (options.selectOnClose) {
|
|
options.resultsAdapter = Utils.Decorate(
|
|
options.resultsAdapter,
|
|
SelectOnClose
|
|
);
|
|
}
|
|
}
|
|
|
|
if (options.dropdownAdapter == null) {
|
|
if (options.multiple) {
|
|
options.dropdownAdapter = Dropdown;
|
|
} else {
|
|
var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);
|
|
|
|
options.dropdownAdapter = SearchableDropdown;
|
|
}
|
|
|
|
if (options.minimumResultsForSearch !== 0) {
|
|
options.dropdownAdapter = Utils.Decorate(
|
|
options.dropdownAdapter,
|
|
MinimumResultsForSearch
|
|
);
|
|
}
|
|
|
|
if (options.closeOnSelect) {
|
|
options.dropdownAdapter = Utils.Decorate(
|
|
options.dropdownAdapter,
|
|
CloseOnSelect
|
|
);
|
|
}
|
|
|
|
if (
|
|
options.dropdownCssClass != null ||
|
|
options.dropdownCss != null ||
|
|
options.adaptDropdownCssClass != null
|
|
) {
|
|
var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');
|
|
|
|
options.dropdownAdapter = Utils.Decorate(
|
|
options.dropdownAdapter,
|
|
DropdownCSS
|
|
);
|
|
}
|
|
|
|
options.dropdownAdapter = Utils.Decorate(
|
|
options.dropdownAdapter,
|
|
AttachBody
|
|
);
|
|
}
|
|
|
|
if (options.selectionAdapter == null) {
|
|
if (options.multiple) {
|
|
options.selectionAdapter = MultipleSelection;
|
|
} else {
|
|
options.selectionAdapter = SingleSelection;
|
|
}
|
|
|
|
// Add the placeholder mixin if a placeholder was specified
|
|
if (options.placeholder != null) {
|
|
options.selectionAdapter = Utils.Decorate(
|
|
options.selectionAdapter,
|
|
Placeholder
|
|
);
|
|
}
|
|
|
|
if (options.allowClear) {
|
|
options.selectionAdapter = Utils.Decorate(
|
|
options.selectionAdapter,
|
|
AllowClear
|
|
);
|
|
}
|
|
|
|
if (options.multiple) {
|
|
options.selectionAdapter = Utils.Decorate(
|
|
options.selectionAdapter,
|
|
SelectionSearch
|
|
);
|
|
}
|
|
|
|
if (
|
|
options.containerCssClass != null ||
|
|
options.containerCss != null ||
|
|
options.adaptContainerCssClass != null
|
|
) {
|
|
var ContainerCSS = require(options.amdBase + 'compat/containerCss');
|
|
|
|
options.selectionAdapter = Utils.Decorate(
|
|
options.selectionAdapter,
|
|
ContainerCSS
|
|
);
|
|
}
|
|
|
|
options.selectionAdapter = Utils.Decorate(
|
|
options.selectionAdapter,
|
|
EventRelay
|
|
);
|
|
}
|
|
|
|
// If the defaults were not previously applied from an element, it is
|
|
// possible for the language option to have not been resolved
|
|
options.language = this._resolveLanguage(options.language);
|
|
|
|
// Always fall back to English since it will always be complete
|
|
options.language.push('en');
|
|
|
|
var uniqueLanguages = [];
|
|
|
|
for (var l = 0; l < options.language.length; l++) {
|
|
var language = options.language[l];
|
|
|
|
if (uniqueLanguages.indexOf(language) === -1) {
|
|
uniqueLanguages.push(language);
|
|
}
|
|
}
|
|
|
|
options.language = uniqueLanguages;
|
|
|
|
options.translations = this._processTranslations(
|
|
options.language,
|
|
options.debug
|
|
);
|
|
|
|
return options;
|
|
};
|
|
|
|
Defaults.prototype.reset = function () {
|
|
function stripDiacritics (text) {
|
|
// Used 'uni range + named function' from http://jsperf.com/diacritics/18
|
|
function match(a) {
|
|
return DIACRITICS[a] || a;
|
|
}
|
|
|
|
return text.replace(/[^\u0000-\u007E]/g, match);
|
|
}
|
|
|
|
function matcher (params, data) {
|
|
// Always return the object if there is nothing to compare
|
|
if ($.trim(params.term) === '') {
|
|
return data;
|
|
}
|
|
|
|
// Do a recursive check for options with children
|
|
if (data.children && data.children.length > 0) {
|
|
// Clone the data object if there are children
|
|
// This is required as we modify the object to remove any non-matches
|
|
var match = $.extend(true, {}, data);
|
|
|
|
// Check each child of the option
|
|
for (var c = data.children.length - 1; c >= 0; c--) {
|
|
var child = data.children[c];
|
|
|
|
var matches = matcher(params, child);
|
|
|
|
// If there wasn't a match, remove the object in the array
|
|
if (matches == null) {
|
|
match.children.splice(c, 1);
|
|
}
|
|
}
|
|
|
|
// If any children matched, return the new object
|
|
if (match.children.length > 0) {
|
|
return match;
|
|
}
|
|
|
|
// If there were no matching children, check just the plain object
|
|
return matcher(params, match);
|
|
}
|
|
|
|
var original = stripDiacritics(data.text).toUpperCase();
|
|
var term = stripDiacritics(params.term).toUpperCase();
|
|
|
|
// Check if the text contains the term
|
|
if (original.indexOf(term) > -1) {
|
|
return data;
|
|
}
|
|
|
|
// If it doesn't contain the term, don't return anything
|
|
return null;
|
|
}
|
|
|
|
this.defaults = {
|
|
amdBase: './',
|
|
amdLanguageBase: './i18n/',
|
|
closeOnSelect: true,
|
|
debug: false,
|
|
dropdownAutoWidth: false,
|
|
escapeMarkup: Utils.escapeMarkup,
|
|
language: {},
|
|
matcher: matcher,
|
|
minimumInputLength: 0,
|
|
maximumInputLength: 0,
|
|
maximumSelectionLength: 0,
|
|
minimumResultsForSearch: 0,
|
|
selectOnClose: false,
|
|
scrollAfterSelect: false,
|
|
sorter: function (data) {
|
|
return data;
|
|
},
|
|
templateResult: function (result) {
|
|
return result.text;
|
|
},
|
|
templateSelection: function (selection) {
|
|
return selection.text;
|
|
},
|
|
theme: 'default',
|
|
width: 'resolve'
|
|
};
|
|
};
|
|
|
|
Defaults.prototype.applyFromElement = function (options, $element) {
|
|
var optionLanguage = options.language;
|
|
var defaultLanguage = this.defaults.language;
|
|
var elementLanguage = $element.prop('lang');
|
|
var parentLanguage = $element.closest('[lang]').prop('lang');
|
|
|
|
var languages = Array.prototype.concat.call(
|
|
this._resolveLanguage(elementLanguage),
|
|
this._resolveLanguage(optionLanguage),
|
|
this._resolveLanguage(defaultLanguage),
|
|
this._resolveLanguage(parentLanguage)
|
|
);
|
|
|
|
options.language = languages;
|
|
|
|
return options;
|
|
};
|
|
|
|
Defaults.prototype._resolveLanguage = function (language) {
|
|
if (!language) {
|
|
return [];
|
|
}
|
|
|
|
if ($.isEmptyObject(language)) {
|
|
return [];
|
|
}
|
|
|
|
if ($.isPlainObject(language)) {
|
|
return [language];
|
|
}
|
|
|
|
var languages;
|
|
|
|
if (!$.isArray(language)) {
|
|
languages = [language];
|
|
} else {
|
|
languages = language;
|
|
}
|
|
|
|
var resolvedLanguages = [];
|
|
|
|
for (var l = 0; l < languages.length; l++) {
|
|
resolvedLanguages.push(languages[l]);
|
|
|
|
if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
|
|
// Extract the region information if it is included
|
|
var languageParts = languages[l].split('-');
|
|
var baseLanguage = languageParts[0];
|
|
|
|
resolvedLanguages.push(baseLanguage);
|
|
}
|
|
}
|
|
|
|
return resolvedLanguages;
|
|
};
|
|
|
|
Defaults.prototype._processTranslations = function (languages, debug) {
|
|
var translations = new Translation();
|
|
|
|
for (var l = 0; l < languages.length; l++) {
|
|
var languageData = new Translation();
|
|
|
|
var language = languages[l];
|
|
|
|
if (typeof language === 'string') {
|
|
try {
|
|
// Try to load it with the original name
|
|
languageData = Translation.loadPath(language);
|
|
} catch (e) {
|
|
try {
|
|
// If we couldn't load it, check if it wasn't the full path
|
|
language = this.defaults.amdLanguageBase + language;
|
|
languageData = Translation.loadPath(language);
|
|
} catch (ex) {
|
|
// The translation could not be loaded at all. Sometimes this is
|
|
// because of a configuration problem, other times this can be
|
|
// because of how Select2 helps load all possible translation files
|
|
if (debug && window.console && console.warn) {
|
|
console.warn(
|
|
'Select2: The language file for "' + language + '" could ' +
|
|
'not be automatically loaded. A fallback will be used instead.'
|
|
);
|
|
}
|
|
}
|
|
}
|
|
} else if ($.isPlainObject(language)) {
|
|
languageData = new Translation(language);
|
|
} else {
|
|
languageData = language;
|
|
}
|
|
|
|
translations.extend(languageData);
|
|
}
|
|
|
|
return translations;
|
|
};
|
|
|
|
Defaults.prototype.set = function (key, value) {
|
|
var camelKey = $.camelCase(key);
|
|
|
|
var data = {};
|
|
data[camelKey] = value;
|
|
|
|
var convertedData = Utils._convertData(data);
|
|
|
|
$.extend(true, this.defaults, convertedData);
|
|
};
|
|
|
|
var defaults = new Defaults();
|
|
|
|
return defaults;
|
|
});
|
|
|
|
S2.define('select2/options',[
|
|
'require',
|
|
'jquery',
|
|
'./defaults',
|
|
'./utils'
|
|
], function (require, $, Defaults, Utils) {
|
|
function Options (options, $element) {
|
|
this.options = options;
|
|
|
|
if ($element != null) {
|
|
this.fromElement($element);
|
|
}
|
|
|
|
if ($element != null) {
|
|
this.options = Defaults.applyFromElement(this.options, $element);
|
|
}
|
|
|
|
this.options = Defaults.apply(this.options);
|
|
|
|
if ($element && $element.is('input')) {
|
|
var InputCompat = require(this.get('amdBase') + 'compat/inputData');
|
|
|
|
this.options.dataAdapter = Utils.Decorate(
|
|
this.options.dataAdapter,
|
|
InputCompat
|
|
);
|
|
}
|
|
}
|
|
|
|
Options.prototype.fromElement = function ($e) {
|
|
var excludedData = ['select2'];
|
|
|
|
if (this.options.multiple == null) {
|
|
this.options.multiple = $e.prop('multiple');
|
|
}
|
|
|
|
if (this.options.disabled == null) {
|
|
this.options.disabled = $e.prop('disabled');
|
|
}
|
|
|
|
if (this.options.dir == null) {
|
|
if ($e.prop('dir')) {
|
|
this.options.dir = $e.prop('dir');
|
|
} else if ($e.closest('[dir]').prop('dir')) {
|
|
this.options.dir = $e.closest('[dir]').prop('dir');
|
|
} else {
|
|
this.options.dir = 'ltr';
|
|
}
|
|
}
|
|
|
|
$e.prop('disabled', this.options.disabled);
|
|
$e.prop('multiple', this.options.multiple);
|
|
|
|
if (Utils.GetData($e[0], 'select2Tags')) {
|
|
if (this.options.debug && window.console && console.warn) {
|
|
console.warn(
|
|
'Select2: The `data-select2-tags` attribute has been changed to ' +
|
|
'use the `data-data` and `data-tags="true"` attributes and will be ' +
|
|
'removed in future versions of Select2.'
|
|
);
|
|
}
|
|
|
|
Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
|
|
Utils.StoreData($e[0], 'tags', true);
|
|
}
|
|
|
|
if (Utils.GetData($e[0], 'ajaxUrl')) {
|
|
if (this.options.debug && window.console && console.warn) {
|
|
console.warn(
|
|
'Select2: The `data-ajax-url` attribute has been changed to ' +
|
|
'`data-ajax--url` and support for the old attribute will be removed' +
|
|
' in future versions of Select2.'
|
|
);
|
|
}
|
|
|
|
$e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
|
|
Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
|
|
}
|
|
|
|
var dataset = {};
|
|
|
|
function upperCaseLetter(_, letter) {
|
|
return letter.toUpperCase();
|
|
}
|
|
|
|
// Pre-load all of the attributes which are prefixed with `data-`
|
|
for (var attr = 0; attr < $e[0].attributes.length; attr++) {
|
|
var attributeName = $e[0].attributes[attr].name;
|
|
var prefix = 'data-';
|
|
|
|
if (attributeName.substr(0, prefix.length) == prefix) {
|
|
// Get the contents of the attribute after `data-`
|
|
var dataName = attributeName.substring(prefix.length);
|
|
|
|
// Get the data contents from the consistent source
|
|
// This is more than likely the jQuery data helper
|
|
var dataValue = Utils.GetData($e[0], dataName);
|
|
|
|
// camelCase the attribute name to match the spec
|
|
var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter);
|
|
|
|
// Store the data attribute contents into the dataset since
|
|
dataset[camelDataName] = dataValue;
|
|
}
|
|
}
|
|
|
|
// Prefer the element's `dataset` attribute if it exists
|
|
// jQuery 1.x does not correctly handle data attributes with multiple dashes
|
|
if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
|
|
dataset = $.extend(true, {}, $e[0].dataset, dataset);
|
|
}
|
|
|
|
// Prefer our internal data cache if it exists
|
|
var data = $.extend(true, {}, Utils.GetData($e[0]), dataset);
|
|
|
|
data = Utils._convertData(data);
|
|
|
|
for (var key in data) {
|
|
if ($.inArray(key, excludedData) > -1) {
|
|
continue;
|
|
}
|
|
|
|
if ($.isPlainObject(this.options[key])) {
|
|
$.extend(this.options[key], data[key]);
|
|
} else {
|
|
this.options[key] = data[key];
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
Options.prototype.get = function (key) {
|
|
return this.options[key];
|
|
};
|
|
|
|
Options.prototype.set = function (key, val) {
|
|
this.options[key] = val;
|
|
};
|
|
|
|
return Options;
|
|
});
|
|
|
|
S2.define('select2/core',[
|
|
'jquery',
|
|
'./options',
|
|
'./utils',
|
|
'./keys'
|
|
], function ($, Options, Utils, KEYS) {
|
|
var Select2 = function ($element, options) {
|
|
if (Utils.GetData($element[0], 'select2') != null) {
|
|
Utils.GetData($element[0], 'select2').destroy();
|
|
}
|
|
|
|
this.$element = $element;
|
|
|
|
this.id = this._generateId($element);
|
|
|
|
options = options || {};
|
|
|
|
this.options = new Options(options, $element);
|
|
|
|
Select2.__super__.constructor.call(this);
|
|
|
|
// Set up the tabindex
|
|
|
|
var tabindex = $element.attr('tabindex') || 0;
|
|
Utils.StoreData($element[0], 'old-tabindex', tabindex);
|
|
$element.attr('tabindex', '-1');
|
|
|
|
// Set up containers and adapters
|
|
|
|
var DataAdapter = this.options.get('dataAdapter');
|
|
this.dataAdapter = new DataAdapter($element, this.options);
|
|
|
|
var $container = this.render();
|
|
|
|
this._placeContainer($container);
|
|
|
|
var SelectionAdapter = this.options.get('selectionAdapter');
|
|
this.selection = new SelectionAdapter($element, this.options);
|
|
this.$selection = this.selection.render();
|
|
|
|
this.selection.position(this.$selection, $container);
|
|
|
|
var DropdownAdapter = this.options.get('dropdownAdapter');
|
|
this.dropdown = new DropdownAdapter($element, this.options);
|
|
this.$dropdown = this.dropdown.render();
|
|
|
|
this.dropdown.position(this.$dropdown, $container);
|
|
|
|
var ResultsAdapter = this.options.get('resultsAdapter');
|
|
this.results = new ResultsAdapter($element, this.options, this.dataAdapter);
|
|
this.$results = this.results.render();
|
|
|
|
this.results.position(this.$results, this.$dropdown);
|
|
|
|
// Bind events
|
|
|
|
var self = this;
|
|
|
|
// Bind the container to all of the adapters
|
|
this._bindAdapters();
|
|
|
|
// Register any DOM event handlers
|
|
this._registerDomEvents();
|
|
|
|
// Register any internal event handlers
|
|
this._registerDataEvents();
|
|
this._registerSelectionEvents();
|
|
this._registerDropdownEvents();
|
|
this._registerResultsEvents();
|
|
this._registerEvents();
|
|
|
|
// Set the initial state
|
|
this.dataAdapter.current(function (initialData) {
|
|
self.trigger('selection:update', {
|
|
data: initialData
|
|
});
|
|
});
|
|
|
|
// Hide the original select
|
|
$element.addClass('select2-hidden-accessible');
|
|
$element.attr('aria-hidden', 'true');
|
|
|
|
// Synchronize any monitored attributes
|
|
this._syncAttributes();
|
|
|
|
Utils.StoreData($element[0], 'select2', this);
|
|
|
|
// Ensure backwards compatibility with $element.data('select2').
|
|
$element.data('select2', this);
|
|
};
|
|
|
|
Utils.Extend(Select2, Utils.Observable);
|
|
|
|
Select2.prototype._generateId = function ($element) {
|
|
var id = '';
|
|
|
|
if ($element.attr('id') != null) {
|
|
id = $element.attr('id');
|
|
} else if ($element.attr('name') != null) {
|
|
id = $element.attr('name') + '-' + Utils.generateChars(2);
|
|
} else {
|
|
id = Utils.generateChars(4);
|
|
}
|
|
|
|
id = id.replace(/(:|\.|\[|\]|,)/g, '');
|
|
id = 'select2-' + id;
|
|
|
|
return id;
|
|
};
|
|
|
|
Select2.prototype._placeContainer = function ($container) {
|
|
$container.insertAfter(this.$element);
|
|
|
|
var width = this._resolveWidth(this.$element, this.options.get('width'));
|
|
|
|
if (width != null) {
|
|
$container.css('width', width);
|
|
}
|
|
};
|
|
|
|
Select2.prototype._resolveWidth = function ($element, method) {
|
|
var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;
|
|
|
|
if (method == 'resolve') {
|
|
var styleWidth = this._resolveWidth($element, 'style');
|
|
|
|
if (styleWidth != null) {
|
|
return styleWidth;
|
|
}
|
|
|
|
return this._resolveWidth($element, 'element');
|
|
}
|
|
|
|
if (method == 'element') {
|
|
var elementWidth = $element.outerWidth(false);
|
|
|
|
if (elementWidth <= 0) {
|
|
return 'auto';
|
|
}
|
|
|
|
return elementWidth + 'px';
|
|
}
|
|
|
|
if (method == 'style') {
|
|
var style = $element.attr('style');
|
|
|
|
if (typeof(style) !== 'string') {
|
|
return null;
|
|
}
|
|
|
|
var attrs = style.split(';');
|
|
|
|
for (var i = 0, l = attrs.length; i < l; i = i + 1) {
|
|
var attr = attrs[i].replace(/\s/g, '');
|
|
var matches = attr.match(WIDTH);
|
|
|
|
if (matches !== null && matches.length >= 1) {
|
|
return matches[1];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
if (method == 'computedstyle') {
|
|
var computedStyle = window.getComputedStyle($element[0]);
|
|
|
|
return computedStyle.width;
|
|
}
|
|
|
|
return method;
|
|
};
|
|
|
|
Select2.prototype._bindAdapters = function () {
|
|
this.dataAdapter.bind(this, this.$container);
|
|
this.selection.bind(this, this.$container);
|
|
|
|
this.dropdown.bind(this, this.$container);
|
|
this.results.bind(this, this.$container);
|
|
};
|
|
|
|
Select2.prototype._registerDomEvents = function () {
|
|
var self = this;
|
|
|
|
this.$element.on('change.select2', function () {
|
|
self.dataAdapter.current(function (data) {
|
|
self.trigger('selection:update', {
|
|
data: data
|
|
});
|
|
});
|
|
});
|
|
|
|
this.$element.on('focus.select2', function (evt) {
|
|
self.trigger('focus', evt);
|
|
});
|
|
|
|
this._syncA = Utils.bind(this._syncAttributes, this);
|
|
this._syncS = Utils.bind(this._syncSubtree, this);
|
|
|
|
if (this.$element[0].attachEvent) {
|
|
this.$element[0].attachEvent('onpropertychange', this._syncA);
|
|
}
|
|
|
|
var observer = window.MutationObserver ||
|
|
window.WebKitMutationObserver ||
|
|
window.MozMutationObserver
|
|
;
|
|
|
|
if (observer != null) {
|
|
this._observer = new observer(function (mutations) {
|
|
self._syncA();
|
|
self._syncS(null, mutations);
|
|
});
|
|
this._observer.observe(this.$element[0], {
|
|
attributes: true,
|
|
childList: true,
|
|
subtree: false
|
|
});
|
|
} else if (this.$element[0].addEventListener) {
|
|
this.$element[0].addEventListener(
|
|
'DOMAttrModified',
|
|
self._syncA,
|
|
false
|
|
);
|
|
this.$element[0].addEventListener(
|
|
'DOMNodeInserted',
|
|
self._syncS,
|
|
false
|
|
);
|
|
this.$element[0].addEventListener(
|
|
'DOMNodeRemoved',
|
|
self._syncS,
|
|
false
|
|
);
|
|
}
|
|
};
|
|
|
|
Select2.prototype._registerDataEvents = function () {
|
|
var self = this;
|
|
|
|
this.dataAdapter.on('*', function (name, params) {
|
|
self.trigger(name, params);
|
|
});
|
|
};
|
|
|
|
Select2.prototype._registerSelectionEvents = function () {
|
|
var self = this;
|
|
var nonRelayEvents = ['toggle', 'focus'];
|
|
|
|
this.selection.on('toggle', function () {
|
|
self.toggleDropdown();
|
|
});
|
|
|
|
this.selection.on('focus', function (params) {
|
|
self.focus(params);
|
|
});
|
|
|
|
this.selection.on('*', function (name, params) {
|
|
if ($.inArray(name, nonRelayEvents) !== -1) {
|
|
return;
|
|
}
|
|
|
|
self.trigger(name, params);
|
|
});
|
|
};
|
|
|
|
Select2.prototype._registerDropdownEvents = function () {
|
|
var self = this;
|
|
|
|
this.dropdown.on('*', function (name, params) {
|
|
self.trigger(name, params);
|
|
});
|
|
};
|
|
|
|
Select2.prototype._registerResultsEvents = function () {
|
|
var self = this;
|
|
|
|
this.results.on('*', function (name, params) {
|
|
self.trigger(name, params);
|
|
});
|
|
};
|
|
|
|
Select2.prototype._registerEvents = function () {
|
|
var self = this;
|
|
|
|
this.on('open', function () {
|
|
self.$container.addClass('select2-container--open');
|
|
});
|
|
|
|
this.on('close', function () {
|
|
self.$container.removeClass('select2-container--open');
|
|
});
|
|
|
|
this.on('enable', function () {
|
|
self.$container.removeClass('select2-container--disabled');
|
|
});
|
|
|
|
this.on('disable', function () {
|
|
self.$container.addClass('select2-container--disabled');
|
|
});
|
|
|
|
this.on('blur', function () {
|
|
self.$container.removeClass('select2-container--focus');
|
|
});
|
|
|
|
this.on('query', function (params) {
|
|
if (!self.isOpen()) {
|
|
self.trigger('open', {});
|
|
}
|
|
|
|
this.dataAdapter.query(params, function (data) {
|
|
self.trigger('results:all', {
|
|
data: data,
|
|
query: params
|
|
});
|
|
});
|
|
});
|
|
|
|
this.on('query:append', function (params) {
|
|
this.dataAdapter.query(params, function (data) {
|
|
self.trigger('results:append', {
|
|
data: data,
|
|
query: params
|
|
});
|
|
});
|
|
});
|
|
|
|
this.on('keypress', function (evt) {
|
|
var key = evt.which;
|
|
|
|
if (self.isOpen()) {
|
|
if (key === KEYS.ESC || key === KEYS.TAB ||
|
|
(key === KEYS.UP && evt.altKey)) {
|
|
self.close(evt);
|
|
|
|
evt.preventDefault();
|
|
} else if (key === KEYS.ENTER) {
|
|
self.trigger('results:select', {});
|
|
|
|
evt.preventDefault();
|
|
} else if ((key === KEYS.SPACE && evt.ctrlKey)) {
|
|
self.trigger('results:toggle', {});
|
|
|
|
evt.preventDefault();
|
|
} else if (key === KEYS.UP) {
|
|
self.trigger('results:previous', {});
|
|
|
|
evt.preventDefault();
|
|
} else if (key === KEYS.DOWN) {
|
|
self.trigger('results:next', {});
|
|
|
|
evt.preventDefault();
|
|
}
|
|
} else {
|
|
if (key === KEYS.ENTER || key === KEYS.SPACE ||
|
|
(key === KEYS.DOWN && evt.altKey)) {
|
|
self.open();
|
|
|
|
evt.preventDefault();
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
Select2.prototype._syncAttributes = function () {
|
|
this.options.set('disabled', this.$element.prop('disabled'));
|
|
|
|
if (this.isDisabled()) {
|
|
if (this.isOpen()) {
|
|
this.close();
|
|
}
|
|
|
|
this.trigger('disable', {});
|
|
} else {
|
|
this.trigger('enable', {});
|
|
}
|
|
};
|
|
|
|
Select2.prototype._isChangeMutation = function (evt, mutations) {
|
|
var changed = false;
|
|
var self = this;
|
|
|
|
// Ignore any mutation events raised for elements that aren't options or
|
|
// optgroups. This handles the case when the select element is destroyed
|
|
if (
|
|
evt && evt.target && (
|
|
evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP'
|
|
)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
if (!mutations) {
|
|
// If mutation events aren't supported, then we can only assume that the
|
|
// change affected the selections
|
|
changed = true;
|
|
} else if (mutations.addedNodes && mutations.addedNodes.length > 0) {
|
|
for (var n = 0; n < mutations.addedNodes.length; n++) {
|
|
var node = mutations.addedNodes[n];
|
|
|
|
if (node.selected) {
|
|
changed = true;
|
|
}
|
|
}
|
|
} else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
|
|
changed = true;
|
|
} else if ($.isArray(mutations)) {
|
|
$.each(mutations, function(evt, mutation) {
|
|
if (self._isChangeMutation(evt, mutation)) {
|
|
// We've found a change mutation.
|
|
// Let's escape from the loop and continue
|
|
changed = true;
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
return changed;
|
|
};
|
|
|
|
Select2.prototype._syncSubtree = function (evt, mutations) {
|
|
var changed = this._isChangeMutation(evt, mutations);
|
|
var self = this;
|
|
|
|
// Only re-pull the data if we think there is a change
|
|
if (changed) {
|
|
this.dataAdapter.current(function (currentData) {
|
|
self.trigger('selection:update', {
|
|
data: currentData
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Override the trigger method to automatically trigger pre-events when
|
|
* there are events that can be prevented.
|
|
*/
|
|
Select2.prototype.trigger = function (name, args) {
|
|
var actualTrigger = Select2.__super__.trigger;
|
|
var preTriggerMap = {
|
|
'open': 'opening',
|
|
'close': 'closing',
|
|
'select': 'selecting',
|
|
'unselect': 'unselecting',
|
|
'clear': 'clearing'
|
|
};
|
|
|
|
if (args === undefined) {
|
|
args = {};
|
|
}
|
|
|
|
if (name in preTriggerMap) {
|
|
var preTriggerName = preTriggerMap[name];
|
|
var preTriggerArgs = {
|
|
prevented: false,
|
|
name: name,
|
|
args: args
|
|
};
|
|
|
|
actualTrigger.call(this, preTriggerName, preTriggerArgs);
|
|
|
|
if (preTriggerArgs.prevented) {
|
|
args.prevented = true;
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
actualTrigger.call(this, name, args);
|
|
};
|
|
|
|
Select2.prototype.toggleDropdown = function () {
|
|
if (this.isDisabled()) {
|
|
return;
|
|
}
|
|
|
|
if (this.isOpen()) {
|
|
this.close();
|
|
} else {
|
|
this.open();
|
|
}
|
|
};
|
|
|
|
Select2.prototype.open = function () {
|
|
if (this.isOpen()) {
|
|
return;
|
|
}
|
|
|
|
if (this.isDisabled()) {
|
|
return;
|
|
}
|
|
|
|
this.trigger('query', {});
|
|
};
|
|
|
|
Select2.prototype.close = function (evt) {
|
|
if (!this.isOpen()) {
|
|
return;
|
|
}
|
|
|
|
this.trigger('close', { originalEvent : evt });
|
|
};
|
|
|
|
/**
|
|
* Helper method to abstract the "enabled" (not "disabled") state of this
|
|
* object.
|
|
*
|
|
* @return {true} if the instance is not disabled.
|
|
* @return {false} if the instance is disabled.
|
|
*/
|
|
Select2.prototype.isEnabled = function () {
|
|
return !this.isDisabled();
|
|
};
|
|
|
|
/**
|
|
* Helper method to abstract the "disabled" state of this object.
|
|
*
|
|
* @return {true} if the disabled option is true.
|
|
* @return {false} if the disabled option is false.
|
|
*/
|
|
Select2.prototype.isDisabled = function () {
|
|
return this.options.get('disabled');
|
|
};
|
|
|
|
Select2.prototype.isOpen = function () {
|
|
return this.$container.hasClass('select2-container--open');
|
|
};
|
|
|
|
Select2.prototype.hasFocus = function () {
|
|
return this.$container.hasClass('select2-container--focus');
|
|
};
|
|
|
|
Select2.prototype.focus = function (data) {
|
|
// No need to re-trigger focus events if we are already focused
|
|
if (this.hasFocus()) {
|
|
return;
|
|
}
|
|
|
|
this.$container.addClass('select2-container--focus');
|
|
this.trigger('focus', {});
|
|
};
|
|
|
|
Select2.prototype.enable = function (args) {
|
|
if (this.options.get('debug') && window.console && console.warn) {
|
|
console.warn(
|
|
'Select2: The `select2("enable")` method has been deprecated and will' +
|
|
' be removed in later Select2 versions. Use $element.prop("disabled")' +
|
|
' instead.'
|
|
);
|
|
}
|
|
|
|
if (args == null || args.length === 0) {
|
|
args = [true];
|
|
}
|
|
|
|
var disabled = !args[0];
|
|
|
|
this.$element.prop('disabled', disabled);
|
|
};
|
|
|
|
Select2.prototype.data = function () {
|
|
if (this.options.get('debug') &&
|
|
arguments.length > 0 && window.console && console.warn) {
|
|
console.warn(
|
|
'Select2: Data can no longer be set using `select2("data")`. You ' +
|
|
'should consider setting the value instead using `$element.val()`.'
|
|
);
|
|
}
|
|
|
|
var data = [];
|
|
|
|
this.dataAdapter.current(function (currentData) {
|
|
data = currentData;
|
|
});
|
|
|
|
return data;
|
|
};
|
|
|
|
Select2.prototype.val = function (args) {
|
|
if (this.options.get('debug') && window.console && console.warn) {
|
|
console.warn(
|
|
'Select2: The `select2("val")` method has been deprecated and will be' +
|
|
' removed in later Select2 versions. Use $element.val() instead.'
|
|
);
|
|
}
|
|
|
|
if (args == null || args.length === 0) {
|
|
return this.$element.val();
|
|
}
|
|
|
|
var newVal = args[0];
|
|
|
|
if ($.isArray(newVal)) {
|
|
newVal = $.map(newVal, function (obj) {
|
|
return obj.toString();
|
|
});
|
|
}
|
|
|
|
this.$element.val(newVal).trigger('input').trigger('change');
|
|
};
|
|
|
|
Select2.prototype.destroy = function () {
|
|
this.$container.remove();
|
|
|
|
if (this.$element[0].detachEvent) {
|
|
this.$element[0].detachEvent('onpropertychange', this._syncA);
|
|
}
|
|
|
|
if (this._observer != null) {
|
|
this._observer.disconnect();
|
|
this._observer = null;
|
|
} else if (this.$element[0].removeEventListener) {
|
|
this.$element[0]
|
|
.removeEventListener('DOMAttrModified', this._syncA, false);
|
|
this.$element[0]
|
|
.removeEventListener('DOMNodeInserted', this._syncS, false);
|
|
this.$element[0]
|
|
.removeEventListener('DOMNodeRemoved', this._syncS, false);
|
|
}
|
|
|
|
this._syncA = null;
|
|
this._syncS = null;
|
|
|
|
this.$element.off('.select2');
|
|
this.$element.attr('tabindex',
|
|
Utils.GetData(this.$element[0], 'old-tabindex'));
|
|
|
|
this.$element.removeClass('select2-hidden-accessible');
|
|
this.$element.attr('aria-hidden', 'false');
|
|
Utils.RemoveData(this.$element[0]);
|
|
this.$element.removeData('select2');
|
|
|
|
this.dataAdapter.destroy();
|
|
this.selection.destroy();
|
|
this.dropdown.destroy();
|
|
this.results.destroy();
|
|
|
|
this.dataAdapter = null;
|
|
this.selection = null;
|
|
this.dropdown = null;
|
|
this.results = null;
|
|
};
|
|
|
|
Select2.prototype.render = function () {
|
|
var $container = $(
|
|
'<span class="select2 select2-container">' +
|
|
'<span class="selection"></span>' +
|
|
'<span class="dropdown-wrapper" aria-hidden="true"></span>' +
|
|
'</span>'
|
|
);
|
|
|
|
$container.attr('dir', this.options.get('dir'));
|
|
|
|
this.$container = $container;
|
|
|
|
this.$container.addClass('select2-container--' + this.options.get('theme'));
|
|
|
|
Utils.StoreData($container[0], 'element', this.$element);
|
|
|
|
return $container;
|
|
};
|
|
|
|
return Select2;
|
|
});
|
|
|
|
S2.define('select2/compat/utils',[
|
|
'jquery'
|
|
], function ($) {
|
|
function syncCssClasses ($dest, $src, adapter) {
|
|
var classes, replacements = [], adapted;
|
|
|
|
classes = $.trim($dest.attr('class'));
|
|
|
|
if (classes) {
|
|
classes = '' + classes; // for IE which returns object
|
|
|
|
$(classes.split(/\s+/)).each(function () {
|
|
// Save all Select2 classes
|
|
if (this.indexOf('select2-') === 0) {
|
|
replacements.push(this);
|
|
}
|
|
});
|
|
}
|
|
|
|
classes = $.trim($src.attr('class'));
|
|
|
|
if (classes) {
|
|
classes = '' + classes; // for IE which returns object
|
|
|
|
$(classes.split(/\s+/)).each(function () {
|
|
// Only adapt non-Select2 classes
|
|
if (this.indexOf('select2-') !== 0) {
|
|
adapted = adapter(this);
|
|
|
|
if (adapted != null) {
|
|
replacements.push(adapted);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
$dest.attr('class', replacements.join(' '));
|
|
}
|
|
|
|
return {
|
|
syncCssClasses: syncCssClasses
|
|
};
|
|
});
|
|
|
|
S2.define('select2/compat/containerCss',[
|
|
'jquery',
|
|
'./utils'
|
|
], function ($, CompatUtils) {
|
|
// No-op CSS adapter that discards all classes by default
|
|
function _containerAdapter (clazz) {
|
|
return null;
|
|
}
|
|
|
|
function ContainerCSS () { }
|
|
|
|
ContainerCSS.prototype.render = function (decorated) {
|
|
var $container = decorated.call(this);
|
|
|
|
var containerCssClass = this.options.get('containerCssClass') || '';
|
|
|
|
if ($.isFunction(containerCssClass)) {
|
|
containerCssClass = containerCssClass(this.$element);
|
|
}
|
|
|
|
var containerCssAdapter = this.options.get('adaptContainerCssClass');
|
|
containerCssAdapter = containerCssAdapter || _containerAdapter;
|
|
|
|
if (containerCssClass.indexOf(':all:') !== -1) {
|
|
containerCssClass = containerCssClass.replace(':all:', '');
|
|
|
|
var _cssAdapter = containerCssAdapter;
|
|
|
|
containerCssAdapter = function (clazz) {
|
|
var adapted = _cssAdapter(clazz);
|
|
|
|
if (adapted != null) {
|
|
// Append the old one along with the adapted one
|
|
return adapted + ' ' + clazz;
|
|
}
|
|
|
|
return clazz;
|
|
};
|
|
}
|
|
|
|
var containerCss = this.options.get('containerCss') || {};
|
|
|
|
if ($.isFunction(containerCss)) {
|
|
containerCss = containerCss(this.$element);
|
|
}
|
|
|
|
CompatUtils.syncCssClasses($container, this.$element, containerCssAdapter);
|
|
|
|
$container.css(containerCss);
|
|
$container.addClass(containerCssClass);
|
|
|
|
return $container;
|
|
};
|
|
|
|
return ContainerCSS;
|
|
});
|
|
|
|
S2.define('select2/compat/dropdownCss',[
|
|
'jquery',
|
|
'./utils'
|
|
], function ($, CompatUtils) {
|
|
// No-op CSS adapter that discards all classes by default
|
|
function _dropdownAdapter (clazz) {
|
|
return null;
|
|
}
|
|
|
|
function DropdownCSS () { }
|
|
|
|
DropdownCSS.prototype.render = function (decorated) {
|
|
var $dropdown = decorated.call(this);
|
|
|
|
var dropdownCssClass = this.options.get('dropdownCssClass') || '';
|
|
|
|
if ($.isFunction(dropdownCssClass)) {
|
|
dropdownCssClass = dropdownCssClass(this.$element);
|
|
}
|
|
|
|
var dropdownCssAdapter = this.options.get('adaptDropdownCssClass');
|
|
dropdownCssAdapter = dropdownCssAdapter || _dropdownAdapter;
|
|
|
|
if (dropdownCssClass.indexOf(':all:') !== -1) {
|
|
dropdownCssClass = dropdownCssClass.replace(':all:', '');
|
|
|
|
var _cssAdapter = dropdownCssAdapter;
|
|
|
|
dropdownCssAdapter = function (clazz) {
|
|
var adapted = _cssAdapter(clazz);
|
|
|
|
if (adapted != null) {
|
|
// Append the old one along with the adapted one
|
|
return adapted + ' ' + clazz;
|
|
}
|
|
|
|
return clazz;
|
|
};
|
|
}
|
|
|
|
var dropdownCss = this.options.get('dropdownCss') || {};
|
|
|
|
if ($.isFunction(dropdownCss)) {
|
|
dropdownCss = dropdownCss(this.$element);
|
|
}
|
|
|
|
CompatUtils.syncCssClasses($dropdown, this.$element, dropdownCssAdapter);
|
|
|
|
$dropdown.css(dropdownCss);
|
|
$dropdown.addClass(dropdownCssClass);
|
|
|
|
return $dropdown;
|
|
};
|
|
|
|
return DropdownCSS;
|
|
});
|
|
|
|
S2.define('select2/compat/initSelection',[
|
|
'jquery'
|
|
], function ($) {
|
|
function InitSelection (decorated, $element, options) {
|
|
if (options.get('debug') && window.console && console.warn) {
|
|
console.warn(
|
|
'Select2: The `initSelection` option has been deprecated in favor' +
|
|
' of a custom data adapter that overrides the `current` method. ' +
|
|
'This method is now called multiple times instead of a single ' +
|
|
'time when the instance is initialized. Support will be removed ' +
|
|
'for the `initSelection` option in future versions of Select2'
|
|
);
|
|
}
|
|
|
|
this.initSelection = options.get('initSelection');
|
|
this._isInitialized = false;
|
|
|
|
decorated.call(this, $element, options);
|
|
}
|
|
|
|
InitSelection.prototype.current = function (decorated, callback) {
|
|
var self = this;
|
|
|
|
if (this._isInitialized) {
|
|
decorated.call(this, callback);
|
|
|
|
return;
|
|
}
|
|
|
|
this.initSelection.call(null, this.$element, function (data) {
|
|
self._isInitialized = true;
|
|
|
|
if (!$.isArray(data)) {
|
|
data = [data];
|
|
}
|
|
|
|
callback(data);
|
|
});
|
|
};
|
|
|
|
return InitSelection;
|
|
});
|
|
|
|
S2.define('select2/compat/inputData',[
|
|
'jquery',
|
|
'../utils'
|
|
], function ($, Utils) {
|
|
function InputData (decorated, $element, options) {
|
|
this._currentData = [];
|
|
this._valueSeparator = options.get('valueSeparator') || ',';
|
|
|
|
if ($element.prop('type') === 'hidden') {
|
|
if (options.get('debug') && console && console.warn) {
|
|
console.warn(
|
|
'Select2: Using a hidden input with Select2 is no longer ' +
|
|
'supported and may stop working in the future. It is recommended ' +
|
|
'to use a `<select>` element instead.'
|
|
);
|
|
}
|
|
}
|
|
|
|
decorated.call(this, $element, options);
|
|
}
|
|
|
|
InputData.prototype.current = function (_, callback) {
|
|
function getSelected (data, selectedIds) {
|
|
var selected = [];
|
|
|
|
if (data.selected || $.inArray(data.id, selectedIds) !== -1) {
|
|
data.selected = true;
|
|
selected.push(data);
|
|
} else {
|
|
data.selected = false;
|
|
}
|
|
|
|
if (data.children) {
|
|
selected.push.apply(selected, getSelected(data.children, selectedIds));
|
|
}
|
|
|
|
return selected;
|
|
}
|
|
|
|
var selected = [];
|
|
|
|
for (var d = 0; d < this._currentData.length; d++) {
|
|
var data = this._currentData[d];
|
|
|
|
selected.push.apply(
|
|
selected,
|
|
getSelected(
|
|
data,
|
|
this.$element.val().split(
|
|
this._valueSeparator
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
callback(selected);
|
|
};
|
|
|
|
InputData.prototype.select = function (_, data) {
|
|
if (!this.options.get('multiple')) {
|
|
this.current(function (allData) {
|
|
$.map(allData, function (data) {
|
|
data.selected = false;
|
|
});
|
|
});
|
|
|
|
this.$element.val(data.id);
|
|
this.$element.trigger('input').trigger('change');
|
|
} else {
|
|
var value = this.$element.val();
|
|
value += this._valueSeparator + data.id;
|
|
|
|
this.$element.val(value);
|
|
this.$element.trigger('input').trigger('change');
|
|
}
|
|
};
|
|
|
|
InputData.prototype.unselect = function (_, data) {
|
|
var self = this;
|
|
|
|
data.selected = false;
|
|
|
|
this.current(function (allData) {
|
|
var values = [];
|
|
|
|
for (var d = 0; d < allData.length; d++) {
|
|
var item = allData[d];
|
|
|
|
if (data.id == item.id) {
|
|
continue;
|
|
}
|
|
|
|
values.push(item.id);
|
|
}
|
|
|
|
self.$element.val(values.join(self._valueSeparator));
|
|
self.$element.trigger('input').trigger('change');
|
|
});
|
|
};
|
|
|
|
InputData.prototype.query = function (_, params, callback) {
|
|
var results = [];
|
|
|
|
for (var d = 0; d < this._currentData.length; d++) {
|
|
var data = this._currentData[d];
|
|
|
|
var matches = this.matches(params, data);
|
|
|
|
if (matches !== null) {
|
|
results.push(matches);
|
|
}
|
|
}
|
|
|
|
callback({
|
|
results: results
|
|
});
|
|
};
|
|
|
|
InputData.prototype.addOptions = function (_, $options) {
|
|
var options = $.map($options, function ($option) {
|
|
return Utils.GetData($option[0], 'data');
|
|
});
|
|
|
|
this._currentData.push.apply(this._currentData, options);
|
|
};
|
|
|
|
return InputData;
|
|
});
|
|
|
|
S2.define('select2/compat/matcher',[
|
|
'jquery'
|
|
], function ($) {
|
|
function oldMatcher (matcher) {
|
|
function wrappedMatcher (params, data) {
|
|
var match = $.extend(true, {}, data);
|
|
|
|
if (params.term == null || $.trim(params.term) === '') {
|
|
return match;
|
|
}
|
|
|
|
if (data.children) {
|
|
for (var c = data.children.length - 1; c >= 0; c--) {
|
|
var child = data.children[c];
|
|
|
|
// Check if the child object matches
|
|
// The old matcher returned a boolean true or false
|
|
var doesMatch = matcher(params.term, child.text, child);
|
|
|
|
// If the child didn't match, pop it off
|
|
if (!doesMatch) {
|
|
match.children.splice(c, 1);
|
|
}
|
|
}
|
|
|
|
if (match.children.length > 0) {
|
|
return match;
|
|
}
|
|
}
|
|
|
|
if (matcher(params.term, data.text, data)) {
|
|
return match;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
return wrappedMatcher;
|
|
}
|
|
|
|
return oldMatcher;
|
|
});
|
|
|
|
S2.define('select2/compat/query',[
|
|
|
|
], function () {
|
|
function Query (decorated, $element, options) {
|
|
if (options.get('debug') && window.console && console.warn) {
|
|
console.warn(
|
|
'Select2: The `query` option has been deprecated in favor of a ' +
|
|
'custom data adapter that overrides the `query` method. Support ' +
|
|
'will be removed for the `query` option in future versions of ' +
|
|
'Select2.'
|
|
);
|
|
}
|
|
|
|
decorated.call(this, $element, options);
|
|
}
|
|
|
|
Query.prototype.query = function (_, params, callback) {
|
|
params.callback = callback;
|
|
|
|
var query = this.options.get('query');
|
|
|
|
query.call(null, params);
|
|
};
|
|
|
|
return Query;
|
|
});
|
|
|
|
S2.define('select2/dropdown/attachContainer',[
|
|
|
|
], function () {
|
|
function AttachContainer (decorated, $element, options) {
|
|
decorated.call(this, $element, options);
|
|
}
|
|
|
|
AttachContainer.prototype.position =
|
|
function (decorated, $dropdown, $container) {
|
|
var $dropdownContainer = $container.find('.dropdown-wrapper');
|
|
$dropdownContainer.append($dropdown);
|
|
|
|
$dropdown.addClass('select2-dropdown--below');
|
|
$container.addClass('select2-container--below');
|
|
};
|
|
|
|
return AttachContainer;
|
|
});
|
|
|
|
S2.define('select2/dropdown/stopPropagation',[
|
|
|
|
], function () {
|
|
function StopPropagation () { }
|
|
|
|
StopPropagation.prototype.bind = function (decorated, container, $container) {
|
|
decorated.call(this, container, $container);
|
|
|
|
var stoppedEvents = [
|
|
'blur',
|
|
'change',
|
|
'click',
|
|
'dblclick',
|
|
'focus',
|
|
'focusin',
|
|
'focusout',
|
|
'input',
|
|
'keydown',
|
|
'keyup',
|
|
'keypress',
|
|
'mousedown',
|
|
'mouseenter',
|
|
'mouseleave',
|
|
'mousemove',
|
|
'mouseover',
|
|
'mouseup',
|
|
'search',
|
|
'touchend',
|
|
'touchstart'
|
|
];
|
|
|
|
this.$dropdown.on(stoppedEvents.join(' '), function (evt) {
|
|
evt.stopPropagation();
|
|
});
|
|
};
|
|
|
|
return StopPropagation;
|
|
});
|
|
|
|
S2.define('select2/selection/stopPropagation',[
|
|
|
|
], function () {
|
|
function StopPropagation () { }
|
|
|
|
StopPropagation.prototype.bind = function (decorated, container, $container) {
|
|
decorated.call(this, container, $container);
|
|
|
|
var stoppedEvents = [
|
|
'blur',
|
|
'change',
|
|
'click',
|
|
'dblclick',
|
|
'focus',
|
|
'focusin',
|
|
'focusout',
|
|
'input',
|
|
'keydown',
|
|
'keyup',
|
|
'keypress',
|
|
'mousedown',
|
|
'mouseenter',
|
|
'mouseleave',
|
|
'mousemove',
|
|
'mouseover',
|
|
'mouseup',
|
|
'search',
|
|
'touchend',
|
|
'touchstart'
|
|
];
|
|
|
|
this.$selection.on(stoppedEvents.join(' '), function (evt) {
|
|
evt.stopPropagation();
|
|
});
|
|
};
|
|
|
|
return StopPropagation;
|
|
});
|
|
|
|
/*!
|
|
* jQuery Mousewheel 3.1.13
|
|
*
|
|
* Copyright jQuery Foundation and other contributors
|
|
* Released under the MIT license
|
|
* http://jquery.org/license
|
|
*/
|
|
|
|
(function (factory) {
|
|
if ( typeof S2.define === 'function' && S2.define.amd ) {
|
|
// AMD. Register as an anonymous module.
|
|
S2.define('jquery-mousewheel',['jquery'], factory);
|
|
} else if (true) {
|
|
// Node/CommonJS style for Browserify
|
|
module.exports = factory;
|
|
} else {}
|
|
}(function ($) {
|
|
|
|
var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
|
|
toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
|
|
['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
|
|
slice = Array.prototype.slice,
|
|
nullLowestDeltaTimeout, lowestDelta;
|
|
|
|
if ( $.event.fixHooks ) {
|
|
for ( var i = toFix.length; i; ) {
|
|
$.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
|
|
}
|
|
}
|
|
|
|
var special = $.event.special.mousewheel = {
|
|
version: '3.1.12',
|
|
|
|
setup: function() {
|
|
if ( this.addEventListener ) {
|
|
for ( var i = toBind.length; i; ) {
|
|
this.addEventListener( toBind[--i], handler, false );
|
|
}
|
|
} else {
|
|
this.onmousewheel = handler;
|
|
}
|
|
// Store the line height and page height for this particular element
|
|
$.data(this, 'mousewheel-line-height', special.getLineHeight(this));
|
|
$.data(this, 'mousewheel-page-height', special.getPageHeight(this));
|
|
},
|
|
|
|
teardown: function() {
|
|
if ( this.removeEventListener ) {
|
|
for ( var i = toBind.length; i; ) {
|
|
this.removeEventListener( toBind[--i], handler, false );
|
|
}
|
|
} else {
|
|
this.onmousewheel = null;
|
|
}
|
|
// Clean up the data we added to the element
|
|
$.removeData(this, 'mousewheel-line-height');
|
|
$.removeData(this, 'mousewheel-page-height');
|
|
},
|
|
|
|
getLineHeight: function(elem) {
|
|
var $elem = $(elem),
|
|
$parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
|
|
if (!$parent.length) {
|
|
$parent = $('body');
|
|
}
|
|
return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
|
|
},
|
|
|
|
getPageHeight: function(elem) {
|
|
return $(elem).height();
|
|
},
|
|
|
|
settings: {
|
|
adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
|
|
normalizeOffset: true // calls getBoundingClientRect for each event
|
|
}
|
|
};
|
|
|
|
$.fn.extend({
|
|
mousewheel: function(fn) {
|
|
return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
|
|
},
|
|
|
|
unmousewheel: function(fn) {
|
|
return this.unbind('mousewheel', fn);
|
|
}
|
|
});
|
|
|
|
|
|
function handler(event) {
|
|
var orgEvent = event || window.event,
|
|
args = slice.call(arguments, 1),
|
|
delta = 0,
|
|
deltaX = 0,
|
|
deltaY = 0,
|
|
absDelta = 0,
|
|
offsetX = 0,
|
|
offsetY = 0;
|
|
event = $.event.fix(orgEvent);
|
|
event.type = 'mousewheel';
|
|
|
|
// Old school scrollwheel delta
|
|
if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
|
|
if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
|
|
if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
|
|
if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
|
|
|
|
// Firefox < 17 horizontal scrolling related to DOMMouseScroll event
|
|
if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
|
|
deltaX = deltaY * -1;
|
|
deltaY = 0;
|
|
}
|
|
|
|
// Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
|
|
delta = deltaY === 0 ? deltaX : deltaY;
|
|
|
|
// New school wheel delta (wheel event)
|
|
if ( 'deltaY' in orgEvent ) {
|
|
deltaY = orgEvent.deltaY * -1;
|
|
delta = deltaY;
|
|
}
|
|
if ( 'deltaX' in orgEvent ) {
|
|
deltaX = orgEvent.deltaX;
|
|
if ( deltaY === 0 ) { delta = deltaX * -1; }
|
|
}
|
|
|
|
// No change actually happened, no reason to go any further
|
|
if ( deltaY === 0 && deltaX === 0 ) { return; }
|
|
|
|
// Need to convert lines and pages to pixels if we aren't already in pixels
|
|
// There are three delta modes:
|
|
// * deltaMode 0 is by pixels, nothing to do
|
|
// * deltaMode 1 is by lines
|
|
// * deltaMode 2 is by pages
|
|
if ( orgEvent.deltaMode === 1 ) {
|
|
var lineHeight = $.data(this, 'mousewheel-line-height');
|
|
delta *= lineHeight;
|
|
deltaY *= lineHeight;
|
|
deltaX *= lineHeight;
|
|
} else if ( orgEvent.deltaMode === 2 ) {
|
|
var pageHeight = $.data(this, 'mousewheel-page-height');
|
|
delta *= pageHeight;
|
|
deltaY *= pageHeight;
|
|
deltaX *= pageHeight;
|
|
}
|
|
|
|
// Store lowest absolute delta to normalize the delta values
|
|
absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
|
|
|
|
if ( !lowestDelta || absDelta < lowestDelta ) {
|
|
lowestDelta = absDelta;
|
|
|
|
// Adjust older deltas if necessary
|
|
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
|
|
lowestDelta /= 40;
|
|
}
|
|
}
|
|
|
|
// Adjust older deltas if necessary
|
|
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
|
|
// Divide all the things by 40!
|
|
delta /= 40;
|
|
deltaX /= 40;
|
|
deltaY /= 40;
|
|
}
|
|
|
|
// Get a whole, normalized value for the deltas
|
|
delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
|
|
deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
|
|
deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
|
|
|
|
// Normalise offsetX and offsetY properties
|
|
if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
|
|
var boundingRect = this.getBoundingClientRect();
|
|
offsetX = event.clientX - boundingRect.left;
|
|
offsetY = event.clientY - boundingRect.top;
|
|
}
|
|
|
|
// Add information to the event object
|
|
event.deltaX = deltaX;
|
|
event.deltaY = deltaY;
|
|
event.deltaFactor = lowestDelta;
|
|
event.offsetX = offsetX;
|
|
event.offsetY = offsetY;
|
|
// Go ahead and set deltaMode to 0 since we converted to pixels
|
|
// Although this is a little odd since we overwrite the deltaX/Y
|
|
// properties with normalized deltas.
|
|
event.deltaMode = 0;
|
|
|
|
// Add event and delta to the front of the arguments
|
|
args.unshift(event, delta, deltaX, deltaY);
|
|
|
|
// Clearout lowestDelta after sometime to better
|
|
// handle multiple device types that give different
|
|
// a different lowestDelta
|
|
// Ex: trackpad = 3 and mouse wheel = 120
|
|
if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
|
|
nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
|
|
|
|
return ($.event.dispatch || $.event.handle).apply(this, args);
|
|
}
|
|
|
|
function nullLowestDelta() {
|
|
lowestDelta = null;
|
|
}
|
|
|
|
function shouldAdjustOldDeltas(orgEvent, absDelta) {
|
|
// If this is an older event and the delta is divisable by 120,
|
|
// then we are assuming that the browser is treating this as an
|
|
// older mouse wheel event and that we should divide the deltas
|
|
// by 40 to try and get a more usable deltaFactor.
|
|
// Side note, this actually impacts the reported scroll distance
|
|
// in older browsers and can cause scrolling to be slower than native.
|
|
// Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
|
|
return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
|
|
}
|
|
|
|
}));
|
|
|
|
S2.define('jquery.select2',[
|
|
'jquery',
|
|
'jquery-mousewheel',
|
|
|
|
'./select2/core',
|
|
'./select2/defaults',
|
|
'./select2/utils'
|
|
], function ($, _, Select2, Defaults, Utils) {
|
|
if ($.fn.select2 == null) {
|
|
// All methods that should return the element
|
|
var thisMethods = ['open', 'close', 'destroy'];
|
|
|
|
$.fn.select2 = function (options) {
|
|
options = options || {};
|
|
|
|
if (typeof options === 'object') {
|
|
this.each(function () {
|
|
var instanceOptions = $.extend(true, {}, options);
|
|
|
|
var instance = new Select2($(this), instanceOptions);
|
|
});
|
|
|
|
return this;
|
|
} else if (typeof options === 'string') {
|
|
var ret;
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
|
|
this.each(function () {
|
|
var instance = Utils.GetData(this, 'select2');
|
|
|
|
if (instance == null && window.console && console.error) {
|
|
console.error(
|
|
'The select2(\'' + options + '\') method was called on an ' +
|
|
'element that is not using Select2.'
|
|
);
|
|
}
|
|
|
|
ret = instance[options].apply(instance, args);
|
|
});
|
|
|
|
// Check if we should be returning `this`
|
|
if ($.inArray(options, thisMethods) > -1) {
|
|
return this;
|
|
}
|
|
|
|
return ret;
|
|
} else {
|
|
throw new Error('Invalid arguments for Select2: ' + options);
|
|
}
|
|
};
|
|
}
|
|
|
|
if ($.fn.select2.defaults == null) {
|
|
$.fn.select2.defaults = Defaults;
|
|
}
|
|
|
|
return Select2;
|
|
});
|
|
|
|
// Return the AMD loader configuration so it can be used outside of this file
|
|
return {
|
|
define: S2.define,
|
|
require: S2.require
|
|
};
|
|
}());
|
|
|
|
// Autoload the jQuery bindings
|
|
// We know that all of the modules exist above this, so we're safe
|
|
var select2 = S2.require('jquery.select2');
|
|
|
|
// Hold the AMD module references on the jQuery function that was just loaded
|
|
// This allows Select2 to use the internal loader outside of this file, such
|
|
// as in the language files.
|
|
jQuery.fn.select2.amd = S2;
|
|
|
|
// Return the Select2 instance for anyone who is importing it.
|
|
return select2;
|
|
}));
|
|
|
|
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))
|
|
|
|
/***/ }),
|
|
/* 75 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
// extracted by mini-css-extract-plugin
|
|
|
|
/***/ }),
|
|
/* 76 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* WEBPACK VAR INJECTION */(function(global, module) {var __WEBPACK_AMD_DEFINE_RESULT__;/**
|
|
* @license
|
|
* Lodash <https://lodash.com/>
|
|
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
|
* Released under MIT license <https://lodash.com/license>
|
|
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
|
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
|
*/
|
|
;(function() {
|
|
|
|
/** Used as a safe reference for `undefined` in pre-ES5 environments. */
|
|
var undefined;
|
|
|
|
/** Used as the semantic version number. */
|
|
var VERSION = '4.17.19';
|
|
|
|
/** Used as the size to enable large array optimizations. */
|
|
var LARGE_ARRAY_SIZE = 200;
|
|
|
|
/** Error message constants. */
|
|
var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
|
|
FUNC_ERROR_TEXT = 'Expected a function';
|
|
|
|
/** Used to stand-in for `undefined` hash values. */
|
|
var HASH_UNDEFINED = '__lodash_hash_undefined__';
|
|
|
|
/** Used as the maximum memoize cache size. */
|
|
var MAX_MEMOIZE_SIZE = 500;
|
|
|
|
/** Used as the internal argument placeholder. */
|
|
var PLACEHOLDER = '__lodash_placeholder__';
|
|
|
|
/** Used to compose bitmasks for cloning. */
|
|
var CLONE_DEEP_FLAG = 1,
|
|
CLONE_FLAT_FLAG = 2,
|
|
CLONE_SYMBOLS_FLAG = 4;
|
|
|
|
/** Used to compose bitmasks for value comparisons. */
|
|
var COMPARE_PARTIAL_FLAG = 1,
|
|
COMPARE_UNORDERED_FLAG = 2;
|
|
|
|
/** Used to compose bitmasks for function metadata. */
|
|
var WRAP_BIND_FLAG = 1,
|
|
WRAP_BIND_KEY_FLAG = 2,
|
|
WRAP_CURRY_BOUND_FLAG = 4,
|
|
WRAP_CURRY_FLAG = 8,
|
|
WRAP_CURRY_RIGHT_FLAG = 16,
|
|
WRAP_PARTIAL_FLAG = 32,
|
|
WRAP_PARTIAL_RIGHT_FLAG = 64,
|
|
WRAP_ARY_FLAG = 128,
|
|
WRAP_REARG_FLAG = 256,
|
|
WRAP_FLIP_FLAG = 512;
|
|
|
|
/** Used as default options for `_.truncate`. */
|
|
var DEFAULT_TRUNC_LENGTH = 30,
|
|
DEFAULT_TRUNC_OMISSION = '...';
|
|
|
|
/** Used to detect hot functions by number of calls within a span of milliseconds. */
|
|
var HOT_COUNT = 800,
|
|
HOT_SPAN = 16;
|
|
|
|
/** Used to indicate the type of lazy iteratees. */
|
|
var LAZY_FILTER_FLAG = 1,
|
|
LAZY_MAP_FLAG = 2,
|
|
LAZY_WHILE_FLAG = 3;
|
|
|
|
/** Used as references for various `Number` constants. */
|
|
var INFINITY = 1 / 0,
|
|
MAX_SAFE_INTEGER = 9007199254740991,
|
|
MAX_INTEGER = 1.7976931348623157e+308,
|
|
NAN = 0 / 0;
|
|
|
|
/** Used as references for the maximum length and index of an array. */
|
|
var MAX_ARRAY_LENGTH = 4294967295,
|
|
MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
|
|
HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
|
|
|
|
/** Used to associate wrap methods with their bit flags. */
|
|
var wrapFlags = [
|
|
['ary', WRAP_ARY_FLAG],
|
|
['bind', WRAP_BIND_FLAG],
|
|
['bindKey', WRAP_BIND_KEY_FLAG],
|
|
['curry', WRAP_CURRY_FLAG],
|
|
['curryRight', WRAP_CURRY_RIGHT_FLAG],
|
|
['flip', WRAP_FLIP_FLAG],
|
|
['partial', WRAP_PARTIAL_FLAG],
|
|
['partialRight', WRAP_PARTIAL_RIGHT_FLAG],
|
|
['rearg', WRAP_REARG_FLAG]
|
|
];
|
|
|
|
/** `Object#toString` result references. */
|
|
var argsTag = '[object Arguments]',
|
|
arrayTag = '[object Array]',
|
|
asyncTag = '[object AsyncFunction]',
|
|
boolTag = '[object Boolean]',
|
|
dateTag = '[object Date]',
|
|
domExcTag = '[object DOMException]',
|
|
errorTag = '[object Error]',
|
|
funcTag = '[object Function]',
|
|
genTag = '[object GeneratorFunction]',
|
|
mapTag = '[object Map]',
|
|
numberTag = '[object Number]',
|
|
nullTag = '[object Null]',
|
|
objectTag = '[object Object]',
|
|
promiseTag = '[object Promise]',
|
|
proxyTag = '[object Proxy]',
|
|
regexpTag = '[object RegExp]',
|
|
setTag = '[object Set]',
|
|
stringTag = '[object String]',
|
|
symbolTag = '[object Symbol]',
|
|
undefinedTag = '[object Undefined]',
|
|
weakMapTag = '[object WeakMap]',
|
|
weakSetTag = '[object WeakSet]';
|
|
|
|
var arrayBufferTag = '[object ArrayBuffer]',
|
|
dataViewTag = '[object DataView]',
|
|
float32Tag = '[object Float32Array]',
|
|
float64Tag = '[object Float64Array]',
|
|
int8Tag = '[object Int8Array]',
|
|
int16Tag = '[object Int16Array]',
|
|
int32Tag = '[object Int32Array]',
|
|
uint8Tag = '[object Uint8Array]',
|
|
uint8ClampedTag = '[object Uint8ClampedArray]',
|
|
uint16Tag = '[object Uint16Array]',
|
|
uint32Tag = '[object Uint32Array]';
|
|
|
|
/** Used to match empty string literals in compiled template source. */
|
|
var reEmptyStringLeading = /\b__p \+= '';/g,
|
|
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
|
|
reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
|
|
|
|
/** Used to match HTML entities and HTML characters. */
|
|
var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
|
|
reUnescapedHtml = /[&<>"']/g,
|
|
reHasEscapedHtml = RegExp(reEscapedHtml.source),
|
|
reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
|
|
|
|
/** Used to match template delimiters. */
|
|
var reEscape = /<%-([\s\S]+?)%>/g,
|
|
reEvaluate = /<%([\s\S]+?)%>/g,
|
|
reInterpolate = /<%=([\s\S]+?)%>/g;
|
|
|
|
/** Used to match property names within property paths. */
|
|
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
|
|
reIsPlainProp = /^\w*$/,
|
|
rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
|
|
|
|
/**
|
|
* Used to match `RegExp`
|
|
* [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
|
|
*/
|
|
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
|
|
reHasRegExpChar = RegExp(reRegExpChar.source);
|
|
|
|
/** Used to match leading and trailing whitespace. */
|
|
var reTrim = /^\s+|\s+$/g,
|
|
reTrimStart = /^\s+/,
|
|
reTrimEnd = /\s+$/;
|
|
|
|
/** Used to match wrap detail comments. */
|
|
var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
|
|
reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
|
|
reSplitDetails = /,? & /;
|
|
|
|
/** Used to match words composed of alphanumeric characters. */
|
|
var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
|
|
|
|
/** Used to match backslashes in property paths. */
|
|
var reEscapeChar = /\\(\\)?/g;
|
|
|
|
/**
|
|
* Used to match
|
|
* [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
|
|
*/
|
|
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
|
|
|
|
/** Used to match `RegExp` flags from their coerced string values. */
|
|
var reFlags = /\w*$/;
|
|
|
|
/** Used to detect bad signed hexadecimal string values. */
|
|
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
|
|
|
|
/** Used to detect binary string values. */
|
|
var reIsBinary = /^0b[01]+$/i;
|
|
|
|
/** Used to detect host constructors (Safari). */
|
|
var reIsHostCtor = /^\[object .+?Constructor\]$/;
|
|
|
|
/** Used to detect octal string values. */
|
|
var reIsOctal = /^0o[0-7]+$/i;
|
|
|
|
/** Used to detect unsigned integer values. */
|
|
var reIsUint = /^(?:0|[1-9]\d*)$/;
|
|
|
|
/** Used to match Latin Unicode letters (excluding mathematical operators). */
|
|
var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
|
|
|
|
/** Used to ensure capturing order of template delimiters. */
|
|
var reNoMatch = /($^)/;
|
|
|
|
/** Used to match unescaped characters in compiled string literals. */
|
|
var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
|
|
|
|
/** Used to compose unicode character classes. */
|
|
var rsAstralRange = '\\ud800-\\udfff',
|
|
rsComboMarksRange = '\\u0300-\\u036f',
|
|
reComboHalfMarksRange = '\\ufe20-\\ufe2f',
|
|
rsComboSymbolsRange = '\\u20d0-\\u20ff',
|
|
rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
|
|
rsDingbatRange = '\\u2700-\\u27bf',
|
|
rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
|
|
rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
|
|
rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
|
|
rsPunctuationRange = '\\u2000-\\u206f',
|
|
rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
|
|
rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
|
|
rsVarRange = '\\ufe0e\\ufe0f',
|
|
rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
|
|
|
|
/** Used to compose unicode capture groups. */
|
|
var rsApos = "['\u2019]",
|
|
rsAstral = '[' + rsAstralRange + ']',
|
|
rsBreak = '[' + rsBreakRange + ']',
|
|
rsCombo = '[' + rsComboRange + ']',
|
|
rsDigits = '\\d+',
|
|
rsDingbat = '[' + rsDingbatRange + ']',
|
|
rsLower = '[' + rsLowerRange + ']',
|
|
rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
|
|
rsFitz = '\\ud83c[\\udffb-\\udfff]',
|
|
rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
|
|
rsNonAstral = '[^' + rsAstralRange + ']',
|
|
rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
|
|
rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
|
|
rsUpper = '[' + rsUpperRange + ']',
|
|
rsZWJ = '\\u200d';
|
|
|
|
/** Used to compose unicode regexes. */
|
|
var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
|
|
rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
|
|
rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
|
|
rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
|
|
reOptMod = rsModifier + '?',
|
|
rsOptVar = '[' + rsVarRange + ']?',
|
|
rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
|
|
rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])',
|
|
rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])',
|
|
rsSeq = rsOptVar + reOptMod + rsOptJoin,
|
|
rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
|
|
rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
|
|
|
|
/** Used to match apostrophes. */
|
|
var reApos = RegExp(rsApos, 'g');
|
|
|
|
/**
|
|
* Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
|
|
* [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
|
|
*/
|
|
var reComboMark = RegExp(rsCombo, 'g');
|
|
|
|
/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
|
|
var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
|
|
|
|
/** Used to match complex or compound words. */
|
|
var reUnicodeWord = RegExp([
|
|
rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
|
|
rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',
|
|
rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,
|
|
rsUpper + '+' + rsOptContrUpper,
|
|
rsOrdUpper,
|
|
rsOrdLower,
|
|
rsDigits,
|
|
rsEmoji
|
|
].join('|'), 'g');
|
|
|
|
/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
|
|
var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
|
|
|
|
/** Used to detect strings that need a more robust regexp to match words. */
|
|
var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
|
|
|
|
/** Used to assign default `context` object properties. */
|
|
var contextProps = [
|
|
'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',
|
|
'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
|
|
'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
|
|
'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
|
|
'_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
|
|
];
|
|
|
|
/** Used to make template sourceURLs easier to identify. */
|
|
var templateCounter = -1;
|
|
|
|
/** Used to identify `toStringTag` values of typed arrays. */
|
|
var typedArrayTags = {};
|
|
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
|
|
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
|
|
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
|
|
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
|
|
typedArrayTags[uint32Tag] = true;
|
|
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
|
|
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
|
|
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
|
|
typedArrayTags[errorTag] = typedArrayTags[funcTag] =
|
|
typedArrayTags[mapTag] = typedArrayTags[numberTag] =
|
|
typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
|
|
typedArrayTags[setTag] = typedArrayTags[stringTag] =
|
|
typedArrayTags[weakMapTag] = false;
|
|
|
|
/** Used to identify `toStringTag` values supported by `_.clone`. */
|
|
var cloneableTags = {};
|
|
cloneableTags[argsTag] = cloneableTags[arrayTag] =
|
|
cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
|
|
cloneableTags[boolTag] = cloneableTags[dateTag] =
|
|
cloneableTags[float32Tag] = cloneableTags[float64Tag] =
|
|
cloneableTags[int8Tag] = cloneableTags[int16Tag] =
|
|
cloneableTags[int32Tag] = cloneableTags[mapTag] =
|
|
cloneableTags[numberTag] = cloneableTags[objectTag] =
|
|
cloneableTags[regexpTag] = cloneableTags[setTag] =
|
|
cloneableTags[stringTag] = cloneableTags[symbolTag] =
|
|
cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
|
|
cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
|
|
cloneableTags[errorTag] = cloneableTags[funcTag] =
|
|
cloneableTags[weakMapTag] = false;
|
|
|
|
/** Used to map Latin Unicode letters to basic Latin letters. */
|
|
var deburredLetters = {
|
|
// Latin-1 Supplement block.
|
|
'\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
|
|
'\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
|
|
'\xc7': 'C', '\xe7': 'c',
|
|
'\xd0': 'D', '\xf0': 'd',
|
|
'\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
|
|
'\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
|
|
'\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
|
|
'\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
|
|
'\xd1': 'N', '\xf1': 'n',
|
|
'\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
|
|
'\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
|
|
'\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
|
|
'\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
|
|
'\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
|
|
'\xc6': 'Ae', '\xe6': 'ae',
|
|
'\xde': 'Th', '\xfe': 'th',
|
|
'\xdf': 'ss',
|
|
// Latin Extended-A block.
|
|
'\u0100': 'A', '\u0102': 'A', '\u0104': 'A',
|
|
'\u0101': 'a', '\u0103': 'a', '\u0105': 'a',
|
|
'\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
|
|
'\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
|
|
'\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
|
|
'\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
|
|
'\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
|
|
'\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
|
|
'\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
|
|
'\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
|
|
'\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
|
|
'\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
|
|
'\u0134': 'J', '\u0135': 'j',
|
|
'\u0136': 'K', '\u0137': 'k', '\u0138': 'k',
|
|
'\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
|
|
'\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
|
|
'\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
|
|
'\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
|
|
'\u014c': 'O', '\u014e': 'O', '\u0150': 'O',
|
|
'\u014d': 'o', '\u014f': 'o', '\u0151': 'o',
|
|
'\u0154': 'R', '\u0156': 'R', '\u0158': 'R',
|
|
'\u0155': 'r', '\u0157': 'r', '\u0159': 'r',
|
|
'\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
|
|
'\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's',
|
|
'\u0162': 'T', '\u0164': 'T', '\u0166': 'T',
|
|
'\u0163': 't', '\u0165': 't', '\u0167': 't',
|
|
'\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
|
|
'\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
|
|
'\u0174': 'W', '\u0175': 'w',
|
|
'\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y',
|
|
'\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z',
|
|
'\u017a': 'z', '\u017c': 'z', '\u017e': 'z',
|
|
'\u0132': 'IJ', '\u0133': 'ij',
|
|
'\u0152': 'Oe', '\u0153': 'oe',
|
|
'\u0149': "'n", '\u017f': 's'
|
|
};
|
|
|
|
/** Used to map characters to HTML entities. */
|
|
var htmlEscapes = {
|
|
'&': '&',
|
|
'<': '<',
|
|
'>': '>',
|
|
'"': '"',
|
|
"'": '''
|
|
};
|
|
|
|
/** Used to map HTML entities to characters. */
|
|
var htmlUnescapes = {
|
|
'&': '&',
|
|
'<': '<',
|
|
'>': '>',
|
|
'"': '"',
|
|
''': "'"
|
|
};
|
|
|
|
/** Used to escape characters for inclusion in compiled string literals. */
|
|
var stringEscapes = {
|
|
'\\': '\\',
|
|
"'": "'",
|
|
'\n': 'n',
|
|
'\r': 'r',
|
|
'\u2028': 'u2028',
|
|
'\u2029': 'u2029'
|
|
};
|
|
|
|
/** Built-in method references without a dependency on `root`. */
|
|
var freeParseFloat = parseFloat,
|
|
freeParseInt = parseInt;
|
|
|
|
/** Detect free variable `global` from Node.js. */
|
|
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
|
|
|
|
/** Detect free variable `self`. */
|
|
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
|
|
|
|
/** Used as a reference to the global object. */
|
|
var root = freeGlobal || freeSelf || Function('return this')();
|
|
|
|
/** Detect free variable `exports`. */
|
|
var freeExports = true && exports && !exports.nodeType && exports;
|
|
|
|
/** Detect free variable `module`. */
|
|
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
|
|
|
|
/** Detect the popular CommonJS extension `module.exports`. */
|
|
var moduleExports = freeModule && freeModule.exports === freeExports;
|
|
|
|
/** Detect free variable `process` from Node.js. */
|
|
var freeProcess = moduleExports && freeGlobal.process;
|
|
|
|
/** Used to access faster Node.js helpers. */
|
|
var nodeUtil = (function() {
|
|
try {
|
|
// Use `util.types` for Node.js 10+.
|
|
var types = freeModule && freeModule.require && freeModule.require('util').types;
|
|
|
|
if (types) {
|
|
return types;
|
|
}
|
|
|
|
// Legacy `process.binding('util')` for Node.js < 10.
|
|
return freeProcess && freeProcess.binding && freeProcess.binding('util');
|
|
} catch (e) {}
|
|
}());
|
|
|
|
/* Node.js helper references. */
|
|
var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
|
|
nodeIsDate = nodeUtil && nodeUtil.isDate,
|
|
nodeIsMap = nodeUtil && nodeUtil.isMap,
|
|
nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
|
|
nodeIsSet = nodeUtil && nodeUtil.isSet,
|
|
nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* A faster alternative to `Function#apply`, this function invokes `func`
|
|
* with the `this` binding of `thisArg` and the arguments of `args`.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to invoke.
|
|
* @param {*} thisArg The `this` binding of `func`.
|
|
* @param {Array} args The arguments to invoke `func` with.
|
|
* @returns {*} Returns the result of `func`.
|
|
*/
|
|
function apply(func, thisArg, args) {
|
|
switch (args.length) {
|
|
case 0: return func.call(thisArg);
|
|
case 1: return func.call(thisArg, args[0]);
|
|
case 2: return func.call(thisArg, args[0], args[1]);
|
|
case 3: return func.call(thisArg, args[0], args[1], args[2]);
|
|
}
|
|
return func.apply(thisArg, args);
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseAggregator` for arrays.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} setter The function to set `accumulator` values.
|
|
* @param {Function} iteratee The iteratee to transform keys.
|
|
* @param {Object} accumulator The initial aggregated object.
|
|
* @returns {Function} Returns `accumulator`.
|
|
*/
|
|
function arrayAggregator(array, setter, iteratee, accumulator) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length;
|
|
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
setter(accumulator, value, iteratee(value), array);
|
|
}
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.forEach` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function arrayEach(array, iteratee) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length;
|
|
|
|
while (++index < length) {
|
|
if (iteratee(array[index], index, array) === false) {
|
|
break;
|
|
}
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.forEachRight` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function arrayEachRight(array, iteratee) {
|
|
var length = array == null ? 0 : array.length;
|
|
|
|
while (length--) {
|
|
if (iteratee(array[length], length, array) === false) {
|
|
break;
|
|
}
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.every` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @returns {boolean} Returns `true` if all elements pass the predicate check,
|
|
* else `false`.
|
|
*/
|
|
function arrayEvery(array, predicate) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length;
|
|
|
|
while (++index < length) {
|
|
if (!predicate(array[index], index, array)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.filter` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @returns {Array} Returns the new filtered array.
|
|
*/
|
|
function arrayFilter(array, predicate) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length,
|
|
resIndex = 0,
|
|
result = [];
|
|
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
if (predicate(value, index, array)) {
|
|
result[resIndex++] = value;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.includes` for arrays without support for
|
|
* specifying an index to search from.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to inspect.
|
|
* @param {*} target The value to search for.
|
|
* @returns {boolean} Returns `true` if `target` is found, else `false`.
|
|
*/
|
|
function arrayIncludes(array, value) {
|
|
var length = array == null ? 0 : array.length;
|
|
return !!length && baseIndexOf(array, value, 0) > -1;
|
|
}
|
|
|
|
/**
|
|
* This function is like `arrayIncludes` except that it accepts a comparator.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to inspect.
|
|
* @param {*} target The value to search for.
|
|
* @param {Function} comparator The comparator invoked per element.
|
|
* @returns {boolean} Returns `true` if `target` is found, else `false`.
|
|
*/
|
|
function arrayIncludesWith(array, value, comparator) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length;
|
|
|
|
while (++index < length) {
|
|
if (comparator(value, array[index])) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.map` for arrays without support for iteratee
|
|
* shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Array} Returns the new mapped array.
|
|
*/
|
|
function arrayMap(array, iteratee) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length,
|
|
result = Array(length);
|
|
|
|
while (++index < length) {
|
|
result[index] = iteratee(array[index], index, array);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Appends the elements of `values` to `array`.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to modify.
|
|
* @param {Array} values The values to append.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function arrayPush(array, values) {
|
|
var index = -1,
|
|
length = values.length,
|
|
offset = array.length;
|
|
|
|
while (++index < length) {
|
|
array[offset + index] = values[index];
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.reduce` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @param {*} [accumulator] The initial value.
|
|
* @param {boolean} [initAccum] Specify using the first element of `array` as
|
|
* the initial value.
|
|
* @returns {*} Returns the accumulated value.
|
|
*/
|
|
function arrayReduce(array, iteratee, accumulator, initAccum) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length;
|
|
|
|
if (initAccum && length) {
|
|
accumulator = array[++index];
|
|
}
|
|
while (++index < length) {
|
|
accumulator = iteratee(accumulator, array[index], index, array);
|
|
}
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.reduceRight` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @param {*} [accumulator] The initial value.
|
|
* @param {boolean} [initAccum] Specify using the last element of `array` as
|
|
* the initial value.
|
|
* @returns {*} Returns the accumulated value.
|
|
*/
|
|
function arrayReduceRight(array, iteratee, accumulator, initAccum) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (initAccum && length) {
|
|
accumulator = array[--length];
|
|
}
|
|
while (length--) {
|
|
accumulator = iteratee(accumulator, array[length], length, array);
|
|
}
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.some` for arrays without support for iteratee
|
|
* shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @returns {boolean} Returns `true` if any element passes the predicate check,
|
|
* else `false`.
|
|
*/
|
|
function arraySome(array, predicate) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length;
|
|
|
|
while (++index < length) {
|
|
if (predicate(array[index], index, array)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Gets the size of an ASCII `string`.
|
|
*
|
|
* @private
|
|
* @param {string} string The string inspect.
|
|
* @returns {number} Returns the string size.
|
|
*/
|
|
var asciiSize = baseProperty('length');
|
|
|
|
/**
|
|
* Converts an ASCII `string` to an array.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to convert.
|
|
* @returns {Array} Returns the converted array.
|
|
*/
|
|
function asciiToArray(string) {
|
|
return string.split('');
|
|
}
|
|
|
|
/**
|
|
* Splits an ASCII `string` into an array of its words.
|
|
*
|
|
* @private
|
|
* @param {string} The string to inspect.
|
|
* @returns {Array} Returns the words of `string`.
|
|
*/
|
|
function asciiWords(string) {
|
|
return string.match(reAsciiWord) || [];
|
|
}
|
|
|
|
/**
|
|
* The base implementation of methods like `_.findKey` and `_.findLastKey`,
|
|
* without support for iteratee shorthands, which iterates over `collection`
|
|
* using `eachFunc`.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to inspect.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @param {Function} eachFunc The function to iterate over `collection`.
|
|
* @returns {*} Returns the found element or its key, else `undefined`.
|
|
*/
|
|
function baseFindKey(collection, predicate, eachFunc) {
|
|
var result;
|
|
eachFunc(collection, function(value, key, collection) {
|
|
if (predicate(value, key, collection)) {
|
|
result = key;
|
|
return false;
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.findIndex` and `_.findLastIndex` without
|
|
* support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @param {number} fromIndex The index to search from.
|
|
* @param {boolean} [fromRight] Specify iterating from right to left.
|
|
* @returns {number} Returns the index of the matched value, else `-1`.
|
|
*/
|
|
function baseFindIndex(array, predicate, fromIndex, fromRight) {
|
|
var length = array.length,
|
|
index = fromIndex + (fromRight ? 1 : -1);
|
|
|
|
while ((fromRight ? index-- : ++index < length)) {
|
|
if (predicate(array[index], index, array)) {
|
|
return index;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.indexOf` without `fromIndex` bounds checks.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @param {*} value The value to search for.
|
|
* @param {number} fromIndex The index to search from.
|
|
* @returns {number} Returns the index of the matched value, else `-1`.
|
|
*/
|
|
function baseIndexOf(array, value, fromIndex) {
|
|
return value === value
|
|
? strictIndexOf(array, value, fromIndex)
|
|
: baseFindIndex(array, baseIsNaN, fromIndex);
|
|
}
|
|
|
|
/**
|
|
* This function is like `baseIndexOf` except that it accepts a comparator.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @param {*} value The value to search for.
|
|
* @param {number} fromIndex The index to search from.
|
|
* @param {Function} comparator The comparator invoked per element.
|
|
* @returns {number} Returns the index of the matched value, else `-1`.
|
|
*/
|
|
function baseIndexOfWith(array, value, fromIndex, comparator) {
|
|
var index = fromIndex - 1,
|
|
length = array.length;
|
|
|
|
while (++index < length) {
|
|
if (comparator(array[index], value)) {
|
|
return index;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isNaN` without support for number objects.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
|
|
*/
|
|
function baseIsNaN(value) {
|
|
return value !== value;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.mean` and `_.meanBy` without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {number} Returns the mean.
|
|
*/
|
|
function baseMean(array, iteratee) {
|
|
var length = array == null ? 0 : array.length;
|
|
return length ? (baseSum(array, iteratee) / length) : NAN;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.property` without support for deep paths.
|
|
*
|
|
* @private
|
|
* @param {string} key The key of the property to get.
|
|
* @returns {Function} Returns the new accessor function.
|
|
*/
|
|
function baseProperty(key) {
|
|
return function(object) {
|
|
return object == null ? undefined : object[key];
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.propertyOf` without support for deep paths.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Function} Returns the new accessor function.
|
|
*/
|
|
function basePropertyOf(object) {
|
|
return function(key) {
|
|
return object == null ? undefined : object[key];
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.reduce` and `_.reduceRight`, without support
|
|
* for iteratee shorthands, which iterates over `collection` using `eachFunc`.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @param {*} accumulator The initial value.
|
|
* @param {boolean} initAccum Specify using the first or last element of
|
|
* `collection` as the initial value.
|
|
* @param {Function} eachFunc The function to iterate over `collection`.
|
|
* @returns {*} Returns the accumulated value.
|
|
*/
|
|
function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
|
|
eachFunc(collection, function(value, index, collection) {
|
|
accumulator = initAccum
|
|
? (initAccum = false, value)
|
|
: iteratee(accumulator, value, index, collection);
|
|
});
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.sortBy` which uses `comparer` to define the
|
|
* sort order of `array` and replaces criteria objects with their corresponding
|
|
* values.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to sort.
|
|
* @param {Function} comparer The function to define sort order.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function baseSortBy(array, comparer) {
|
|
var length = array.length;
|
|
|
|
array.sort(comparer);
|
|
while (length--) {
|
|
array[length] = array[length].value;
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.sum` and `_.sumBy` without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {number} Returns the sum.
|
|
*/
|
|
function baseSum(array, iteratee) {
|
|
var result,
|
|
index = -1,
|
|
length = array.length;
|
|
|
|
while (++index < length) {
|
|
var current = iteratee(array[index]);
|
|
if (current !== undefined) {
|
|
result = result === undefined ? current : (result + current);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.times` without support for iteratee shorthands
|
|
* or max array length checks.
|
|
*
|
|
* @private
|
|
* @param {number} n The number of times to invoke `iteratee`.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Array} Returns the array of results.
|
|
*/
|
|
function baseTimes(n, iteratee) {
|
|
var index = -1,
|
|
result = Array(n);
|
|
|
|
while (++index < n) {
|
|
result[index] = iteratee(index);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
|
|
* of key-value pairs for `object` corresponding to the property names of `props`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @param {Array} props The property names to get values for.
|
|
* @returns {Object} Returns the key-value pairs.
|
|
*/
|
|
function baseToPairs(object, props) {
|
|
return arrayMap(props, function(key) {
|
|
return [key, object[key]];
|
|
});
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.unary` without support for storing metadata.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to cap arguments for.
|
|
* @returns {Function} Returns the new capped function.
|
|
*/
|
|
function baseUnary(func) {
|
|
return function(value) {
|
|
return func(value);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.values` and `_.valuesIn` which creates an
|
|
* array of `object` property values corresponding to the property names
|
|
* of `props`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @param {Array} props The property names to get values for.
|
|
* @returns {Object} Returns the array of property values.
|
|
*/
|
|
function baseValues(object, props) {
|
|
return arrayMap(props, function(key) {
|
|
return object[key];
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Checks if a `cache` value for `key` exists.
|
|
*
|
|
* @private
|
|
* @param {Object} cache The cache to query.
|
|
* @param {string} key The key of the entry to check.
|
|
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
|
|
*/
|
|
function cacheHas(cache, key) {
|
|
return cache.has(key);
|
|
}
|
|
|
|
/**
|
|
* Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
|
|
* that is not found in the character symbols.
|
|
*
|
|
* @private
|
|
* @param {Array} strSymbols The string symbols to inspect.
|
|
* @param {Array} chrSymbols The character symbols to find.
|
|
* @returns {number} Returns the index of the first unmatched string symbol.
|
|
*/
|
|
function charsStartIndex(strSymbols, chrSymbols) {
|
|
var index = -1,
|
|
length = strSymbols.length;
|
|
|
|
while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
|
|
return index;
|
|
}
|
|
|
|
/**
|
|
* Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
|
|
* that is not found in the character symbols.
|
|
*
|
|
* @private
|
|
* @param {Array} strSymbols The string symbols to inspect.
|
|
* @param {Array} chrSymbols The character symbols to find.
|
|
* @returns {number} Returns the index of the last unmatched string symbol.
|
|
*/
|
|
function charsEndIndex(strSymbols, chrSymbols) {
|
|
var index = strSymbols.length;
|
|
|
|
while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
|
|
return index;
|
|
}
|
|
|
|
/**
|
|
* Gets the number of `placeholder` occurrences in `array`.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @param {*} placeholder The placeholder to search for.
|
|
* @returns {number} Returns the placeholder count.
|
|
*/
|
|
function countHolders(array, placeholder) {
|
|
var length = array.length,
|
|
result = 0;
|
|
|
|
while (length--) {
|
|
if (array[length] === placeholder) {
|
|
++result;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
|
|
* letters to basic Latin letters.
|
|
*
|
|
* @private
|
|
* @param {string} letter The matched letter to deburr.
|
|
* @returns {string} Returns the deburred letter.
|
|
*/
|
|
var deburrLetter = basePropertyOf(deburredLetters);
|
|
|
|
/**
|
|
* Used by `_.escape` to convert characters to HTML entities.
|
|
*
|
|
* @private
|
|
* @param {string} chr The matched character to escape.
|
|
* @returns {string} Returns the escaped character.
|
|
*/
|
|
var escapeHtmlChar = basePropertyOf(htmlEscapes);
|
|
|
|
/**
|
|
* Used by `_.template` to escape characters for inclusion in compiled string literals.
|
|
*
|
|
* @private
|
|
* @param {string} chr The matched character to escape.
|
|
* @returns {string} Returns the escaped character.
|
|
*/
|
|
function escapeStringChar(chr) {
|
|
return '\\' + stringEscapes[chr];
|
|
}
|
|
|
|
/**
|
|
* Gets the value at `key` of `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} [object] The object to query.
|
|
* @param {string} key The key of the property to get.
|
|
* @returns {*} Returns the property value.
|
|
*/
|
|
function getValue(object, key) {
|
|
return object == null ? undefined : object[key];
|
|
}
|
|
|
|
/**
|
|
* Checks if `string` contains Unicode symbols.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to inspect.
|
|
* @returns {boolean} Returns `true` if a symbol is found, else `false`.
|
|
*/
|
|
function hasUnicode(string) {
|
|
return reHasUnicode.test(string);
|
|
}
|
|
|
|
/**
|
|
* Checks if `string` contains a word composed of Unicode symbols.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to inspect.
|
|
* @returns {boolean} Returns `true` if a word is found, else `false`.
|
|
*/
|
|
function hasUnicodeWord(string) {
|
|
return reHasUnicodeWord.test(string);
|
|
}
|
|
|
|
/**
|
|
* Converts `iterator` to an array.
|
|
*
|
|
* @private
|
|
* @param {Object} iterator The iterator to convert.
|
|
* @returns {Array} Returns the converted array.
|
|
*/
|
|
function iteratorToArray(iterator) {
|
|
var data,
|
|
result = [];
|
|
|
|
while (!(data = iterator.next()).done) {
|
|
result.push(data.value);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts `map` to its key-value pairs.
|
|
*
|
|
* @private
|
|
* @param {Object} map The map to convert.
|
|
* @returns {Array} Returns the key-value pairs.
|
|
*/
|
|
function mapToArray(map) {
|
|
var index = -1,
|
|
result = Array(map.size);
|
|
|
|
map.forEach(function(value, key) {
|
|
result[++index] = [key, value];
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates a unary function that invokes `func` with its argument transformed.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to wrap.
|
|
* @param {Function} transform The argument transform.
|
|
* @returns {Function} Returns the new function.
|
|
*/
|
|
function overArg(func, transform) {
|
|
return function(arg) {
|
|
return func(transform(arg));
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Replaces all `placeholder` elements in `array` with an internal placeholder
|
|
* and returns an array of their indexes.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to modify.
|
|
* @param {*} placeholder The placeholder to replace.
|
|
* @returns {Array} Returns the new array of placeholder indexes.
|
|
*/
|
|
function replaceHolders(array, placeholder) {
|
|
var index = -1,
|
|
length = array.length,
|
|
resIndex = 0,
|
|
result = [];
|
|
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
if (value === placeholder || value === PLACEHOLDER) {
|
|
array[index] = PLACEHOLDER;
|
|
result[resIndex++] = index;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts `set` to an array of its values.
|
|
*
|
|
* @private
|
|
* @param {Object} set The set to convert.
|
|
* @returns {Array} Returns the values.
|
|
*/
|
|
function setToArray(set) {
|
|
var index = -1,
|
|
result = Array(set.size);
|
|
|
|
set.forEach(function(value) {
|
|
result[++index] = value;
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts `set` to its value-value pairs.
|
|
*
|
|
* @private
|
|
* @param {Object} set The set to convert.
|
|
* @returns {Array} Returns the value-value pairs.
|
|
*/
|
|
function setToPairs(set) {
|
|
var index = -1,
|
|
result = Array(set.size);
|
|
|
|
set.forEach(function(value) {
|
|
result[++index] = [value, value];
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.indexOf` which performs strict equality
|
|
* comparisons of values, i.e. `===`.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @param {*} value The value to search for.
|
|
* @param {number} fromIndex The index to search from.
|
|
* @returns {number} Returns the index of the matched value, else `-1`.
|
|
*/
|
|
function strictIndexOf(array, value, fromIndex) {
|
|
var index = fromIndex - 1,
|
|
length = array.length;
|
|
|
|
while (++index < length) {
|
|
if (array[index] === value) {
|
|
return index;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.lastIndexOf` which performs strict equality
|
|
* comparisons of values, i.e. `===`.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @param {*} value The value to search for.
|
|
* @param {number} fromIndex The index to search from.
|
|
* @returns {number} Returns the index of the matched value, else `-1`.
|
|
*/
|
|
function strictLastIndexOf(array, value, fromIndex) {
|
|
var index = fromIndex + 1;
|
|
while (index--) {
|
|
if (array[index] === value) {
|
|
return index;
|
|
}
|
|
}
|
|
return index;
|
|
}
|
|
|
|
/**
|
|
* Gets the number of symbols in `string`.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to inspect.
|
|
* @returns {number} Returns the string size.
|
|
*/
|
|
function stringSize(string) {
|
|
return hasUnicode(string)
|
|
? unicodeSize(string)
|
|
: asciiSize(string);
|
|
}
|
|
|
|
/**
|
|
* Converts `string` to an array.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to convert.
|
|
* @returns {Array} Returns the converted array.
|
|
*/
|
|
function stringToArray(string) {
|
|
return hasUnicode(string)
|
|
? unicodeToArray(string)
|
|
: asciiToArray(string);
|
|
}
|
|
|
|
/**
|
|
* Used by `_.unescape` to convert HTML entities to characters.
|
|
*
|
|
* @private
|
|
* @param {string} chr The matched character to unescape.
|
|
* @returns {string} Returns the unescaped character.
|
|
*/
|
|
var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
|
|
|
|
/**
|
|
* Gets the size of a Unicode `string`.
|
|
*
|
|
* @private
|
|
* @param {string} string The string inspect.
|
|
* @returns {number} Returns the string size.
|
|
*/
|
|
function unicodeSize(string) {
|
|
var result = reUnicode.lastIndex = 0;
|
|
while (reUnicode.test(string)) {
|
|
++result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts a Unicode `string` to an array.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to convert.
|
|
* @returns {Array} Returns the converted array.
|
|
*/
|
|
function unicodeToArray(string) {
|
|
return string.match(reUnicode) || [];
|
|
}
|
|
|
|
/**
|
|
* Splits a Unicode `string` into an array of its words.
|
|
*
|
|
* @private
|
|
* @param {string} The string to inspect.
|
|
* @returns {Array} Returns the words of `string`.
|
|
*/
|
|
function unicodeWords(string) {
|
|
return string.match(reUnicodeWord) || [];
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Create a new pristine `lodash` function using the `context` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 1.1.0
|
|
* @category Util
|
|
* @param {Object} [context=root] The context object.
|
|
* @returns {Function} Returns a new `lodash` function.
|
|
* @example
|
|
*
|
|
* _.mixin({ 'foo': _.constant('foo') });
|
|
*
|
|
* var lodash = _.runInContext();
|
|
* lodash.mixin({ 'bar': lodash.constant('bar') });
|
|
*
|
|
* _.isFunction(_.foo);
|
|
* // => true
|
|
* _.isFunction(_.bar);
|
|
* // => false
|
|
*
|
|
* lodash.isFunction(lodash.foo);
|
|
* // => false
|
|
* lodash.isFunction(lodash.bar);
|
|
* // => true
|
|
*
|
|
* // Create a suped-up `defer` in Node.js.
|
|
* var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
|
|
*/
|
|
var runInContext = (function runInContext(context) {
|
|
context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
|
|
|
|
/** Built-in constructor references. */
|
|
var Array = context.Array,
|
|
Date = context.Date,
|
|
Error = context.Error,
|
|
Function = context.Function,
|
|
Math = context.Math,
|
|
Object = context.Object,
|
|
RegExp = context.RegExp,
|
|
String = context.String,
|
|
TypeError = context.TypeError;
|
|
|
|
/** Used for built-in method references. */
|
|
var arrayProto = Array.prototype,
|
|
funcProto = Function.prototype,
|
|
objectProto = Object.prototype;
|
|
|
|
/** Used to detect overreaching core-js shims. */
|
|
var coreJsData = context['__core-js_shared__'];
|
|
|
|
/** Used to resolve the decompiled source of functions. */
|
|
var funcToString = funcProto.toString;
|
|
|
|
/** Used to check objects for own properties. */
|
|
var hasOwnProperty = objectProto.hasOwnProperty;
|
|
|
|
/** Used to generate unique IDs. */
|
|
var idCounter = 0;
|
|
|
|
/** Used to detect methods masquerading as native. */
|
|
var maskSrcKey = (function() {
|
|
var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
|
|
return uid ? ('Symbol(src)_1.' + uid) : '';
|
|
}());
|
|
|
|
/**
|
|
* Used to resolve the
|
|
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
|
* of values.
|
|
*/
|
|
var nativeObjectToString = objectProto.toString;
|
|
|
|
/** Used to infer the `Object` constructor. */
|
|
var objectCtorString = funcToString.call(Object);
|
|
|
|
/** Used to restore the original `_` reference in `_.noConflict`. */
|
|
var oldDash = root._;
|
|
|
|
/** Used to detect if a method is native. */
|
|
var reIsNative = RegExp('^' +
|
|
funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
|
|
.replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
|
|
);
|
|
|
|
/** Built-in value references. */
|
|
var Buffer = moduleExports ? context.Buffer : undefined,
|
|
Symbol = context.Symbol,
|
|
Uint8Array = context.Uint8Array,
|
|
allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined,
|
|
getPrototype = overArg(Object.getPrototypeOf, Object),
|
|
objectCreate = Object.create,
|
|
propertyIsEnumerable = objectProto.propertyIsEnumerable,
|
|
splice = arrayProto.splice,
|
|
spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined,
|
|
symIterator = Symbol ? Symbol.iterator : undefined,
|
|
symToStringTag = Symbol ? Symbol.toStringTag : undefined;
|
|
|
|
var defineProperty = (function() {
|
|
try {
|
|
var func = getNative(Object, 'defineProperty');
|
|
func({}, '', {});
|
|
return func;
|
|
} catch (e) {}
|
|
}());
|
|
|
|
/** Mocked built-ins. */
|
|
var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
|
|
ctxNow = Date && Date.now !== root.Date.now && Date.now,
|
|
ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
|
|
|
|
/* Built-in method references for those with the same name as other `lodash` methods. */
|
|
var nativeCeil = Math.ceil,
|
|
nativeFloor = Math.floor,
|
|
nativeGetSymbols = Object.getOwnPropertySymbols,
|
|
nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
|
|
nativeIsFinite = context.isFinite,
|
|
nativeJoin = arrayProto.join,
|
|
nativeKeys = overArg(Object.keys, Object),
|
|
nativeMax = Math.max,
|
|
nativeMin = Math.min,
|
|
nativeNow = Date.now,
|
|
nativeParseInt = context.parseInt,
|
|
nativeRandom = Math.random,
|
|
nativeReverse = arrayProto.reverse;
|
|
|
|
/* Built-in method references that are verified to be native. */
|
|
var DataView = getNative(context, 'DataView'),
|
|
Map = getNative(context, 'Map'),
|
|
Promise = getNative(context, 'Promise'),
|
|
Set = getNative(context, 'Set'),
|
|
WeakMap = getNative(context, 'WeakMap'),
|
|
nativeCreate = getNative(Object, 'create');
|
|
|
|
/** Used to store function metadata. */
|
|
var metaMap = WeakMap && new WeakMap;
|
|
|
|
/** Used to lookup unminified function names. */
|
|
var realNames = {};
|
|
|
|
/** Used to detect maps, sets, and weakmaps. */
|
|
var dataViewCtorString = toSource(DataView),
|
|
mapCtorString = toSource(Map),
|
|
promiseCtorString = toSource(Promise),
|
|
setCtorString = toSource(Set),
|
|
weakMapCtorString = toSource(WeakMap);
|
|
|
|
/** Used to convert symbols to primitives and strings. */
|
|
var symbolProto = Symbol ? Symbol.prototype : undefined,
|
|
symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
|
|
symbolToString = symbolProto ? symbolProto.toString : undefined;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates a `lodash` object which wraps `value` to enable implicit method
|
|
* chain sequences. Methods that operate on and return arrays, collections,
|
|
* and functions can be chained together. Methods that retrieve a single value
|
|
* or may return a primitive value will automatically end the chain sequence
|
|
* and return the unwrapped value. Otherwise, the value must be unwrapped
|
|
* with `_#value`.
|
|
*
|
|
* Explicit chain sequences, which must be unwrapped with `_#value`, may be
|
|
* enabled using `_.chain`.
|
|
*
|
|
* The execution of chained methods is lazy, that is, it's deferred until
|
|
* `_#value` is implicitly or explicitly called.
|
|
*
|
|
* Lazy evaluation allows several methods to support shortcut fusion.
|
|
* Shortcut fusion is an optimization to merge iteratee calls; this avoids
|
|
* the creation of intermediate arrays and can greatly reduce the number of
|
|
* iteratee executions. Sections of a chain sequence qualify for shortcut
|
|
* fusion if the section is applied to an array and iteratees accept only
|
|
* one argument. The heuristic for whether a section qualifies for shortcut
|
|
* fusion is subject to change.
|
|
*
|
|
* Chaining is supported in custom builds as long as the `_#value` method is
|
|
* directly or indirectly included in the build.
|
|
*
|
|
* In addition to lodash methods, wrappers have `Array` and `String` methods.
|
|
*
|
|
* The wrapper `Array` methods are:
|
|
* `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
|
|
*
|
|
* The wrapper `String` methods are:
|
|
* `replace` and `split`
|
|
*
|
|
* The wrapper methods that support shortcut fusion are:
|
|
* `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
|
|
* `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
|
|
* `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
|
|
*
|
|
* The chainable wrapper methods are:
|
|
* `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
|
|
* `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
|
|
* `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
|
|
* `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
|
|
* `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
|
|
* `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
|
|
* `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
|
|
* `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
|
|
* `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
|
|
* `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
|
|
* `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
|
|
* `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
|
|
* `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
|
|
* `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
|
|
* `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
|
|
* `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
|
|
* `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
|
|
* `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
|
|
* `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
|
|
* `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
|
|
* `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
|
|
* `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
|
|
* `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
|
|
* `zipObject`, `zipObjectDeep`, and `zipWith`
|
|
*
|
|
* The wrapper methods that are **not** chainable by default are:
|
|
* `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
|
|
* `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
|
|
* `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
|
|
* `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
|
|
* `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
|
|
* `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
|
|
* `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
|
|
* `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
|
|
* `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
|
|
* `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
|
|
* `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
|
|
* `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
|
|
* `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
|
|
* `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
|
|
* `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
|
|
* `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
|
|
* `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
|
|
* `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
|
|
* `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
|
|
* `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
|
|
* `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
|
|
* `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
|
|
* `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
|
|
* `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
|
|
* `upperFirst`, `value`, and `words`
|
|
*
|
|
* @name _
|
|
* @constructor
|
|
* @category Seq
|
|
* @param {*} value The value to wrap in a `lodash` instance.
|
|
* @returns {Object} Returns the new `lodash` wrapper instance.
|
|
* @example
|
|
*
|
|
* function square(n) {
|
|
* return n * n;
|
|
* }
|
|
*
|
|
* var wrapped = _([1, 2, 3]);
|
|
*
|
|
* // Returns an unwrapped value.
|
|
* wrapped.reduce(_.add);
|
|
* // => 6
|
|
*
|
|
* // Returns a wrapped value.
|
|
* var squares = wrapped.map(square);
|
|
*
|
|
* _.isArray(squares);
|
|
* // => false
|
|
*
|
|
* _.isArray(squares.value());
|
|
* // => true
|
|
*/
|
|
function lodash(value) {
|
|
if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
|
|
if (value instanceof LodashWrapper) {
|
|
return value;
|
|
}
|
|
if (hasOwnProperty.call(value, '__wrapped__')) {
|
|
return wrapperClone(value);
|
|
}
|
|
}
|
|
return new LodashWrapper(value);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.create` without support for assigning
|
|
* properties to the created object.
|
|
*
|
|
* @private
|
|
* @param {Object} proto The object to inherit from.
|
|
* @returns {Object} Returns the new object.
|
|
*/
|
|
var baseCreate = (function() {
|
|
function object() {}
|
|
return function(proto) {
|
|
if (!isObject(proto)) {
|
|
return {};
|
|
}
|
|
if (objectCreate) {
|
|
return objectCreate(proto);
|
|
}
|
|
object.prototype = proto;
|
|
var result = new object;
|
|
object.prototype = undefined;
|
|
return result;
|
|
};
|
|
}());
|
|
|
|
/**
|
|
* The function whose prototype chain sequence wrappers inherit from.
|
|
*
|
|
* @private
|
|
*/
|
|
function baseLodash() {
|
|
// No operation performed.
|
|
}
|
|
|
|
/**
|
|
* The base constructor for creating `lodash` wrapper objects.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to wrap.
|
|
* @param {boolean} [chainAll] Enable explicit method chain sequences.
|
|
*/
|
|
function LodashWrapper(value, chainAll) {
|
|
this.__wrapped__ = value;
|
|
this.__actions__ = [];
|
|
this.__chain__ = !!chainAll;
|
|
this.__index__ = 0;
|
|
this.__values__ = undefined;
|
|
}
|
|
|
|
/**
|
|
* By default, the template delimiters used by lodash are like those in
|
|
* embedded Ruby (ERB) as well as ES2015 template strings. Change the
|
|
* following template settings to use alternative delimiters.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @type {Object}
|
|
*/
|
|
lodash.templateSettings = {
|
|
|
|
/**
|
|
* Used to detect `data` property values to be HTML-escaped.
|
|
*
|
|
* @memberOf _.templateSettings
|
|
* @type {RegExp}
|
|
*/
|
|
'escape': reEscape,
|
|
|
|
/**
|
|
* Used to detect code to be evaluated.
|
|
*
|
|
* @memberOf _.templateSettings
|
|
* @type {RegExp}
|
|
*/
|
|
'evaluate': reEvaluate,
|
|
|
|
/**
|
|
* Used to detect `data` property values to inject.
|
|
*
|
|
* @memberOf _.templateSettings
|
|
* @type {RegExp}
|
|
*/
|
|
'interpolate': reInterpolate,
|
|
|
|
/**
|
|
* Used to reference the data object in the template text.
|
|
*
|
|
* @memberOf _.templateSettings
|
|
* @type {string}
|
|
*/
|
|
'variable': '',
|
|
|
|
/**
|
|
* Used to import variables into the compiled template.
|
|
*
|
|
* @memberOf _.templateSettings
|
|
* @type {Object}
|
|
*/
|
|
'imports': {
|
|
|
|
/**
|
|
* A reference to the `lodash` function.
|
|
*
|
|
* @memberOf _.templateSettings.imports
|
|
* @type {Function}
|
|
*/
|
|
'_': lodash
|
|
}
|
|
};
|
|
|
|
// Ensure wrappers are instances of `baseLodash`.
|
|
lodash.prototype = baseLodash.prototype;
|
|
lodash.prototype.constructor = lodash;
|
|
|
|
LodashWrapper.prototype = baseCreate(baseLodash.prototype);
|
|
LodashWrapper.prototype.constructor = LodashWrapper;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
|
|
*
|
|
* @private
|
|
* @constructor
|
|
* @param {*} value The value to wrap.
|
|
*/
|
|
function LazyWrapper(value) {
|
|
this.__wrapped__ = value;
|
|
this.__actions__ = [];
|
|
this.__dir__ = 1;
|
|
this.__filtered__ = false;
|
|
this.__iteratees__ = [];
|
|
this.__takeCount__ = MAX_ARRAY_LENGTH;
|
|
this.__views__ = [];
|
|
}
|
|
|
|
/**
|
|
* Creates a clone of the lazy wrapper object.
|
|
*
|
|
* @private
|
|
* @name clone
|
|
* @memberOf LazyWrapper
|
|
* @returns {Object} Returns the cloned `LazyWrapper` object.
|
|
*/
|
|
function lazyClone() {
|
|
var result = new LazyWrapper(this.__wrapped__);
|
|
result.__actions__ = copyArray(this.__actions__);
|
|
result.__dir__ = this.__dir__;
|
|
result.__filtered__ = this.__filtered__;
|
|
result.__iteratees__ = copyArray(this.__iteratees__);
|
|
result.__takeCount__ = this.__takeCount__;
|
|
result.__views__ = copyArray(this.__views__);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Reverses the direction of lazy iteration.
|
|
*
|
|
* @private
|
|
* @name reverse
|
|
* @memberOf LazyWrapper
|
|
* @returns {Object} Returns the new reversed `LazyWrapper` object.
|
|
*/
|
|
function lazyReverse() {
|
|
if (this.__filtered__) {
|
|
var result = new LazyWrapper(this);
|
|
result.__dir__ = -1;
|
|
result.__filtered__ = true;
|
|
} else {
|
|
result = this.clone();
|
|
result.__dir__ *= -1;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extracts the unwrapped value from its lazy wrapper.
|
|
*
|
|
* @private
|
|
* @name value
|
|
* @memberOf LazyWrapper
|
|
* @returns {*} Returns the unwrapped value.
|
|
*/
|
|
function lazyValue() {
|
|
var array = this.__wrapped__.value(),
|
|
dir = this.__dir__,
|
|
isArr = isArray(array),
|
|
isRight = dir < 0,
|
|
arrLength = isArr ? array.length : 0,
|
|
view = getView(0, arrLength, this.__views__),
|
|
start = view.start,
|
|
end = view.end,
|
|
length = end - start,
|
|
index = isRight ? end : (start - 1),
|
|
iteratees = this.__iteratees__,
|
|
iterLength = iteratees.length,
|
|
resIndex = 0,
|
|
takeCount = nativeMin(length, this.__takeCount__);
|
|
|
|
if (!isArr || (!isRight && arrLength == length && takeCount == length)) {
|
|
return baseWrapperValue(array, this.__actions__);
|
|
}
|
|
var result = [];
|
|
|
|
outer:
|
|
while (length-- && resIndex < takeCount) {
|
|
index += dir;
|
|
|
|
var iterIndex = -1,
|
|
value = array[index];
|
|
|
|
while (++iterIndex < iterLength) {
|
|
var data = iteratees[iterIndex],
|
|
iteratee = data.iteratee,
|
|
type = data.type,
|
|
computed = iteratee(value);
|
|
|
|
if (type == LAZY_MAP_FLAG) {
|
|
value = computed;
|
|
} else if (!computed) {
|
|
if (type == LAZY_FILTER_FLAG) {
|
|
continue outer;
|
|
} else {
|
|
break outer;
|
|
}
|
|
}
|
|
}
|
|
result[resIndex++] = value;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// Ensure `LazyWrapper` is an instance of `baseLodash`.
|
|
LazyWrapper.prototype = baseCreate(baseLodash.prototype);
|
|
LazyWrapper.prototype.constructor = LazyWrapper;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates a hash object.
|
|
*
|
|
* @private
|
|
* @constructor
|
|
* @param {Array} [entries] The key-value pairs to cache.
|
|
*/
|
|
function Hash(entries) {
|
|
var index = -1,
|
|
length = entries == null ? 0 : entries.length;
|
|
|
|
this.clear();
|
|
while (++index < length) {
|
|
var entry = entries[index];
|
|
this.set(entry[0], entry[1]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes all key-value entries from the hash.
|
|
*
|
|
* @private
|
|
* @name clear
|
|
* @memberOf Hash
|
|
*/
|
|
function hashClear() {
|
|
this.__data__ = nativeCreate ? nativeCreate(null) : {};
|
|
this.size = 0;
|
|
}
|
|
|
|
/**
|
|
* Removes `key` and its value from the hash.
|
|
*
|
|
* @private
|
|
* @name delete
|
|
* @memberOf Hash
|
|
* @param {Object} hash The hash to modify.
|
|
* @param {string} key The key of the value to remove.
|
|
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
|
|
*/
|
|
function hashDelete(key) {
|
|
var result = this.has(key) && delete this.__data__[key];
|
|
this.size -= result ? 1 : 0;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the hash value for `key`.
|
|
*
|
|
* @private
|
|
* @name get
|
|
* @memberOf Hash
|
|
* @param {string} key The key of the value to get.
|
|
* @returns {*} Returns the entry value.
|
|
*/
|
|
function hashGet(key) {
|
|
var data = this.__data__;
|
|
if (nativeCreate) {
|
|
var result = data[key];
|
|
return result === HASH_UNDEFINED ? undefined : result;
|
|
}
|
|
return hasOwnProperty.call(data, key) ? data[key] : undefined;
|
|
}
|
|
|
|
/**
|
|
* Checks if a hash value for `key` exists.
|
|
*
|
|
* @private
|
|
* @name has
|
|
* @memberOf Hash
|
|
* @param {string} key The key of the entry to check.
|
|
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
|
|
*/
|
|
function hashHas(key) {
|
|
var data = this.__data__;
|
|
return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
|
|
}
|
|
|
|
/**
|
|
* Sets the hash `key` to `value`.
|
|
*
|
|
* @private
|
|
* @name set
|
|
* @memberOf Hash
|
|
* @param {string} key The key of the value to set.
|
|
* @param {*} value The value to set.
|
|
* @returns {Object} Returns the hash instance.
|
|
*/
|
|
function hashSet(key, value) {
|
|
var data = this.__data__;
|
|
this.size += this.has(key) ? 0 : 1;
|
|
data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
|
|
return this;
|
|
}
|
|
|
|
// Add methods to `Hash`.
|
|
Hash.prototype.clear = hashClear;
|
|
Hash.prototype['delete'] = hashDelete;
|
|
Hash.prototype.get = hashGet;
|
|
Hash.prototype.has = hashHas;
|
|
Hash.prototype.set = hashSet;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates an list cache object.
|
|
*
|
|
* @private
|
|
* @constructor
|
|
* @param {Array} [entries] The key-value pairs to cache.
|
|
*/
|
|
function ListCache(entries) {
|
|
var index = -1,
|
|
length = entries == null ? 0 : entries.length;
|
|
|
|
this.clear();
|
|
while (++index < length) {
|
|
var entry = entries[index];
|
|
this.set(entry[0], entry[1]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes all key-value entries from the list cache.
|
|
*
|
|
* @private
|
|
* @name clear
|
|
* @memberOf ListCache
|
|
*/
|
|
function listCacheClear() {
|
|
this.__data__ = [];
|
|
this.size = 0;
|
|
}
|
|
|
|
/**
|
|
* Removes `key` and its value from the list cache.
|
|
*
|
|
* @private
|
|
* @name delete
|
|
* @memberOf ListCache
|
|
* @param {string} key The key of the value to remove.
|
|
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
|
|
*/
|
|
function listCacheDelete(key) {
|
|
var data = this.__data__,
|
|
index = assocIndexOf(data, key);
|
|
|
|
if (index < 0) {
|
|
return false;
|
|
}
|
|
var lastIndex = data.length - 1;
|
|
if (index == lastIndex) {
|
|
data.pop();
|
|
} else {
|
|
splice.call(data, index, 1);
|
|
}
|
|
--this.size;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Gets the list cache value for `key`.
|
|
*
|
|
* @private
|
|
* @name get
|
|
* @memberOf ListCache
|
|
* @param {string} key The key of the value to get.
|
|
* @returns {*} Returns the entry value.
|
|
*/
|
|
function listCacheGet(key) {
|
|
var data = this.__data__,
|
|
index = assocIndexOf(data, key);
|
|
|
|
return index < 0 ? undefined : data[index][1];
|
|
}
|
|
|
|
/**
|
|
* Checks if a list cache value for `key` exists.
|
|
*
|
|
* @private
|
|
* @name has
|
|
* @memberOf ListCache
|
|
* @param {string} key The key of the entry to check.
|
|
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
|
|
*/
|
|
function listCacheHas(key) {
|
|
return assocIndexOf(this.__data__, key) > -1;
|
|
}
|
|
|
|
/**
|
|
* Sets the list cache `key` to `value`.
|
|
*
|
|
* @private
|
|
* @name set
|
|
* @memberOf ListCache
|
|
* @param {string} key The key of the value to set.
|
|
* @param {*} value The value to set.
|
|
* @returns {Object} Returns the list cache instance.
|
|
*/
|
|
function listCacheSet(key, value) {
|
|
var data = this.__data__,
|
|
index = assocIndexOf(data, key);
|
|
|
|
if (index < 0) {
|
|
++this.size;
|
|
data.push([key, value]);
|
|
} else {
|
|
data[index][1] = value;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
// Add methods to `ListCache`.
|
|
ListCache.prototype.clear = listCacheClear;
|
|
ListCache.prototype['delete'] = listCacheDelete;
|
|
ListCache.prototype.get = listCacheGet;
|
|
ListCache.prototype.has = listCacheHas;
|
|
ListCache.prototype.set = listCacheSet;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates a map cache object to store key-value pairs.
|
|
*
|
|
* @private
|
|
* @constructor
|
|
* @param {Array} [entries] The key-value pairs to cache.
|
|
*/
|
|
function MapCache(entries) {
|
|
var index = -1,
|
|
length = entries == null ? 0 : entries.length;
|
|
|
|
this.clear();
|
|
while (++index < length) {
|
|
var entry = entries[index];
|
|
this.set(entry[0], entry[1]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes all key-value entries from the map.
|
|
*
|
|
* @private
|
|
* @name clear
|
|
* @memberOf MapCache
|
|
*/
|
|
function mapCacheClear() {
|
|
this.size = 0;
|
|
this.__data__ = {
|
|
'hash': new Hash,
|
|
'map': new (Map || ListCache),
|
|
'string': new Hash
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Removes `key` and its value from the map.
|
|
*
|
|
* @private
|
|
* @name delete
|
|
* @memberOf MapCache
|
|
* @param {string} key The key of the value to remove.
|
|
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
|
|
*/
|
|
function mapCacheDelete(key) {
|
|
var result = getMapData(this, key)['delete'](key);
|
|
this.size -= result ? 1 : 0;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the map value for `key`.
|
|
*
|
|
* @private
|
|
* @name get
|
|
* @memberOf MapCache
|
|
* @param {string} key The key of the value to get.
|
|
* @returns {*} Returns the entry value.
|
|
*/
|
|
function mapCacheGet(key) {
|
|
return getMapData(this, key).get(key);
|
|
}
|
|
|
|
/**
|
|
* Checks if a map value for `key` exists.
|
|
*
|
|
* @private
|
|
* @name has
|
|
* @memberOf MapCache
|
|
* @param {string} key The key of the entry to check.
|
|
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
|
|
*/
|
|
function mapCacheHas(key) {
|
|
return getMapData(this, key).has(key);
|
|
}
|
|
|
|
/**
|
|
* Sets the map `key` to `value`.
|
|
*
|
|
* @private
|
|
* @name set
|
|
* @memberOf MapCache
|
|
* @param {string} key The key of the value to set.
|
|
* @param {*} value The value to set.
|
|
* @returns {Object} Returns the map cache instance.
|
|
*/
|
|
function mapCacheSet(key, value) {
|
|
var data = getMapData(this, key),
|
|
size = data.size;
|
|
|
|
data.set(key, value);
|
|
this.size += data.size == size ? 0 : 1;
|
|
return this;
|
|
}
|
|
|
|
// Add methods to `MapCache`.
|
|
MapCache.prototype.clear = mapCacheClear;
|
|
MapCache.prototype['delete'] = mapCacheDelete;
|
|
MapCache.prototype.get = mapCacheGet;
|
|
MapCache.prototype.has = mapCacheHas;
|
|
MapCache.prototype.set = mapCacheSet;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
*
|
|
* Creates an array cache object to store unique values.
|
|
*
|
|
* @private
|
|
* @constructor
|
|
* @param {Array} [values] The values to cache.
|
|
*/
|
|
function SetCache(values) {
|
|
var index = -1,
|
|
length = values == null ? 0 : values.length;
|
|
|
|
this.__data__ = new MapCache;
|
|
while (++index < length) {
|
|
this.add(values[index]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds `value` to the array cache.
|
|
*
|
|
* @private
|
|
* @name add
|
|
* @memberOf SetCache
|
|
* @alias push
|
|
* @param {*} value The value to cache.
|
|
* @returns {Object} Returns the cache instance.
|
|
*/
|
|
function setCacheAdd(value) {
|
|
this.__data__.set(value, HASH_UNDEFINED);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is in the array cache.
|
|
*
|
|
* @private
|
|
* @name has
|
|
* @memberOf SetCache
|
|
* @param {*} value The value to search for.
|
|
* @returns {number} Returns `true` if `value` is found, else `false`.
|
|
*/
|
|
function setCacheHas(value) {
|
|
return this.__data__.has(value);
|
|
}
|
|
|
|
// Add methods to `SetCache`.
|
|
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
|
|
SetCache.prototype.has = setCacheHas;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates a stack cache object to store key-value pairs.
|
|
*
|
|
* @private
|
|
* @constructor
|
|
* @param {Array} [entries] The key-value pairs to cache.
|
|
*/
|
|
function Stack(entries) {
|
|
var data = this.__data__ = new ListCache(entries);
|
|
this.size = data.size;
|
|
}
|
|
|
|
/**
|
|
* Removes all key-value entries from the stack.
|
|
*
|
|
* @private
|
|
* @name clear
|
|
* @memberOf Stack
|
|
*/
|
|
function stackClear() {
|
|
this.__data__ = new ListCache;
|
|
this.size = 0;
|
|
}
|
|
|
|
/**
|
|
* Removes `key` and its value from the stack.
|
|
*
|
|
* @private
|
|
* @name delete
|
|
* @memberOf Stack
|
|
* @param {string} key The key of the value to remove.
|
|
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
|
|
*/
|
|
function stackDelete(key) {
|
|
var data = this.__data__,
|
|
result = data['delete'](key);
|
|
|
|
this.size = data.size;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the stack value for `key`.
|
|
*
|
|
* @private
|
|
* @name get
|
|
* @memberOf Stack
|
|
* @param {string} key The key of the value to get.
|
|
* @returns {*} Returns the entry value.
|
|
*/
|
|
function stackGet(key) {
|
|
return this.__data__.get(key);
|
|
}
|
|
|
|
/**
|
|
* Checks if a stack value for `key` exists.
|
|
*
|
|
* @private
|
|
* @name has
|
|
* @memberOf Stack
|
|
* @param {string} key The key of the entry to check.
|
|
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
|
|
*/
|
|
function stackHas(key) {
|
|
return this.__data__.has(key);
|
|
}
|
|
|
|
/**
|
|
* Sets the stack `key` to `value`.
|
|
*
|
|
* @private
|
|
* @name set
|
|
* @memberOf Stack
|
|
* @param {string} key The key of the value to set.
|
|
* @param {*} value The value to set.
|
|
* @returns {Object} Returns the stack cache instance.
|
|
*/
|
|
function stackSet(key, value) {
|
|
var data = this.__data__;
|
|
if (data instanceof ListCache) {
|
|
var pairs = data.__data__;
|
|
if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
|
|
pairs.push([key, value]);
|
|
this.size = ++data.size;
|
|
return this;
|
|
}
|
|
data = this.__data__ = new MapCache(pairs);
|
|
}
|
|
data.set(key, value);
|
|
this.size = data.size;
|
|
return this;
|
|
}
|
|
|
|
// Add methods to `Stack`.
|
|
Stack.prototype.clear = stackClear;
|
|
Stack.prototype['delete'] = stackDelete;
|
|
Stack.prototype.get = stackGet;
|
|
Stack.prototype.has = stackHas;
|
|
Stack.prototype.set = stackSet;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates an array of the enumerable property names of the array-like `value`.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to query.
|
|
* @param {boolean} inherited Specify returning inherited property names.
|
|
* @returns {Array} Returns the array of property names.
|
|
*/
|
|
function arrayLikeKeys(value, inherited) {
|
|
var isArr = isArray(value),
|
|
isArg = !isArr && isArguments(value),
|
|
isBuff = !isArr && !isArg && isBuffer(value),
|
|
isType = !isArr && !isArg && !isBuff && isTypedArray(value),
|
|
skipIndexes = isArr || isArg || isBuff || isType,
|
|
result = skipIndexes ? baseTimes(value.length, String) : [],
|
|
length = result.length;
|
|
|
|
for (var key in value) {
|
|
if ((inherited || hasOwnProperty.call(value, key)) &&
|
|
!(skipIndexes && (
|
|
// Safari 9 has enumerable `arguments.length` in strict mode.
|
|
key == 'length' ||
|
|
// Node.js 0.10 has enumerable non-index properties on buffers.
|
|
(isBuff && (key == 'offset' || key == 'parent')) ||
|
|
// PhantomJS 2 has enumerable non-index properties on typed arrays.
|
|
(isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
|
|
// Skip index properties.
|
|
isIndex(key, length)
|
|
))) {
|
|
result.push(key);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.sample` for arrays.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to sample.
|
|
* @returns {*} Returns the random element.
|
|
*/
|
|
function arraySample(array) {
|
|
var length = array.length;
|
|
return length ? array[baseRandom(0, length - 1)] : undefined;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.sampleSize` for arrays.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to sample.
|
|
* @param {number} n The number of elements to sample.
|
|
* @returns {Array} Returns the random elements.
|
|
*/
|
|
function arraySampleSize(array, n) {
|
|
return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.shuffle` for arrays.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to shuffle.
|
|
* @returns {Array} Returns the new shuffled array.
|
|
*/
|
|
function arrayShuffle(array) {
|
|
return shuffleSelf(copyArray(array));
|
|
}
|
|
|
|
/**
|
|
* This function is like `assignValue` except that it doesn't assign
|
|
* `undefined` values.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to modify.
|
|
* @param {string} key The key of the property to assign.
|
|
* @param {*} value The value to assign.
|
|
*/
|
|
function assignMergeValue(object, key, value) {
|
|
if ((value !== undefined && !eq(object[key], value)) ||
|
|
(value === undefined && !(key in object))) {
|
|
baseAssignValue(object, key, value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Assigns `value` to `key` of `object` if the existing value is not equivalent
|
|
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
* for equality comparisons.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to modify.
|
|
* @param {string} key The key of the property to assign.
|
|
* @param {*} value The value to assign.
|
|
*/
|
|
function assignValue(object, key, value) {
|
|
var objValue = object[key];
|
|
if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
|
|
(value === undefined && !(key in object))) {
|
|
baseAssignValue(object, key, value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the index at which the `key` is found in `array` of key-value pairs.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @param {*} key The key to search for.
|
|
* @returns {number} Returns the index of the matched value, else `-1`.
|
|
*/
|
|
function assocIndexOf(array, key) {
|
|
var length = array.length;
|
|
while (length--) {
|
|
if (eq(array[length][0], key)) {
|
|
return length;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Aggregates elements of `collection` on `accumulator` with keys transformed
|
|
* by `iteratee` and values set by `setter`.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} setter The function to set `accumulator` values.
|
|
* @param {Function} iteratee The iteratee to transform keys.
|
|
* @param {Object} accumulator The initial aggregated object.
|
|
* @returns {Function} Returns `accumulator`.
|
|
*/
|
|
function baseAggregator(collection, setter, iteratee, accumulator) {
|
|
baseEach(collection, function(value, key, collection) {
|
|
setter(accumulator, value, iteratee(value), collection);
|
|
});
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.assign` without support for multiple sources
|
|
* or `customizer` functions.
|
|
*
|
|
* @private
|
|
* @param {Object} object The destination object.
|
|
* @param {Object} source The source object.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
function baseAssign(object, source) {
|
|
return object && copyObject(source, keys(source), object);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.assignIn` without support for multiple sources
|
|
* or `customizer` functions.
|
|
*
|
|
* @private
|
|
* @param {Object} object The destination object.
|
|
* @param {Object} source The source object.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
function baseAssignIn(object, source) {
|
|
return object && copyObject(source, keysIn(source), object);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `assignValue` and `assignMergeValue` without
|
|
* value checks.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to modify.
|
|
* @param {string} key The key of the property to assign.
|
|
* @param {*} value The value to assign.
|
|
*/
|
|
function baseAssignValue(object, key, value) {
|
|
if (key == '__proto__' && defineProperty) {
|
|
defineProperty(object, key, {
|
|
'configurable': true,
|
|
'enumerable': true,
|
|
'value': value,
|
|
'writable': true
|
|
});
|
|
} else {
|
|
object[key] = value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.at` without support for individual paths.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {string[]} paths The property paths to pick.
|
|
* @returns {Array} Returns the picked elements.
|
|
*/
|
|
function baseAt(object, paths) {
|
|
var index = -1,
|
|
length = paths.length,
|
|
result = Array(length),
|
|
skip = object == null;
|
|
|
|
while (++index < length) {
|
|
result[index] = skip ? undefined : get(object, paths[index]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.clamp` which doesn't coerce arguments.
|
|
*
|
|
* @private
|
|
* @param {number} number The number to clamp.
|
|
* @param {number} [lower] The lower bound.
|
|
* @param {number} upper The upper bound.
|
|
* @returns {number} Returns the clamped number.
|
|
*/
|
|
function baseClamp(number, lower, upper) {
|
|
if (number === number) {
|
|
if (upper !== undefined) {
|
|
number = number <= upper ? number : upper;
|
|
}
|
|
if (lower !== undefined) {
|
|
number = number >= lower ? number : lower;
|
|
}
|
|
}
|
|
return number;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.clone` and `_.cloneDeep` which tracks
|
|
* traversed objects.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to clone.
|
|
* @param {boolean} bitmask The bitmask flags.
|
|
* 1 - Deep clone
|
|
* 2 - Flatten inherited properties
|
|
* 4 - Clone symbols
|
|
* @param {Function} [customizer] The function to customize cloning.
|
|
* @param {string} [key] The key of `value`.
|
|
* @param {Object} [object] The parent object of `value`.
|
|
* @param {Object} [stack] Tracks traversed objects and their clone counterparts.
|
|
* @returns {*} Returns the cloned value.
|
|
*/
|
|
function baseClone(value, bitmask, customizer, key, object, stack) {
|
|
var result,
|
|
isDeep = bitmask & CLONE_DEEP_FLAG,
|
|
isFlat = bitmask & CLONE_FLAT_FLAG,
|
|
isFull = bitmask & CLONE_SYMBOLS_FLAG;
|
|
|
|
if (customizer) {
|
|
result = object ? customizer(value, key, object, stack) : customizer(value);
|
|
}
|
|
if (result !== undefined) {
|
|
return result;
|
|
}
|
|
if (!isObject(value)) {
|
|
return value;
|
|
}
|
|
var isArr = isArray(value);
|
|
if (isArr) {
|
|
result = initCloneArray(value);
|
|
if (!isDeep) {
|
|
return copyArray(value, result);
|
|
}
|
|
} else {
|
|
var tag = getTag(value),
|
|
isFunc = tag == funcTag || tag == genTag;
|
|
|
|
if (isBuffer(value)) {
|
|
return cloneBuffer(value, isDeep);
|
|
}
|
|
if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
|
|
result = (isFlat || isFunc) ? {} : initCloneObject(value);
|
|
if (!isDeep) {
|
|
return isFlat
|
|
? copySymbolsIn(value, baseAssignIn(result, value))
|
|
: copySymbols(value, baseAssign(result, value));
|
|
}
|
|
} else {
|
|
if (!cloneableTags[tag]) {
|
|
return object ? value : {};
|
|
}
|
|
result = initCloneByTag(value, tag, isDeep);
|
|
}
|
|
}
|
|
// Check for circular references and return its corresponding clone.
|
|
stack || (stack = new Stack);
|
|
var stacked = stack.get(value);
|
|
if (stacked) {
|
|
return stacked;
|
|
}
|
|
stack.set(value, result);
|
|
|
|
if (isSet(value)) {
|
|
value.forEach(function(subValue) {
|
|
result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
|
|
});
|
|
} else if (isMap(value)) {
|
|
value.forEach(function(subValue, key) {
|
|
result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
|
|
});
|
|
}
|
|
|
|
var keysFunc = isFull
|
|
? (isFlat ? getAllKeysIn : getAllKeys)
|
|
: (isFlat ? keysIn : keys);
|
|
|
|
var props = isArr ? undefined : keysFunc(value);
|
|
arrayEach(props || value, function(subValue, key) {
|
|
if (props) {
|
|
key = subValue;
|
|
subValue = value[key];
|
|
}
|
|
// Recursively populate clone (susceptible to call stack limits).
|
|
assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.conforms` which doesn't clone `source`.
|
|
*
|
|
* @private
|
|
* @param {Object} source The object of property predicates to conform to.
|
|
* @returns {Function} Returns the new spec function.
|
|
*/
|
|
function baseConforms(source) {
|
|
var props = keys(source);
|
|
return function(object) {
|
|
return baseConformsTo(object, source, props);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.conformsTo` which accepts `props` to check.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to inspect.
|
|
* @param {Object} source The object of property predicates to conform to.
|
|
* @returns {boolean} Returns `true` if `object` conforms, else `false`.
|
|
*/
|
|
function baseConformsTo(object, source, props) {
|
|
var length = props.length;
|
|
if (object == null) {
|
|
return !length;
|
|
}
|
|
object = Object(object);
|
|
while (length--) {
|
|
var key = props[length],
|
|
predicate = source[key],
|
|
value = object[key];
|
|
|
|
if ((value === undefined && !(key in object)) || !predicate(value)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.delay` and `_.defer` which accepts `args`
|
|
* to provide to `func`.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to delay.
|
|
* @param {number} wait The number of milliseconds to delay invocation.
|
|
* @param {Array} args The arguments to provide to `func`.
|
|
* @returns {number|Object} Returns the timer id or timeout object.
|
|
*/
|
|
function baseDelay(func, wait, args) {
|
|
if (typeof func != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
return setTimeout(function() { func.apply(undefined, args); }, wait);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of methods like `_.difference` without support
|
|
* for excluding multiple arrays or iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @param {Array} values The values to exclude.
|
|
* @param {Function} [iteratee] The iteratee invoked per element.
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
* @returns {Array} Returns the new array of filtered values.
|
|
*/
|
|
function baseDifference(array, values, iteratee, comparator) {
|
|
var index = -1,
|
|
includes = arrayIncludes,
|
|
isCommon = true,
|
|
length = array.length,
|
|
result = [],
|
|
valuesLength = values.length;
|
|
|
|
if (!length) {
|
|
return result;
|
|
}
|
|
if (iteratee) {
|
|
values = arrayMap(values, baseUnary(iteratee));
|
|
}
|
|
if (comparator) {
|
|
includes = arrayIncludesWith;
|
|
isCommon = false;
|
|
}
|
|
else if (values.length >= LARGE_ARRAY_SIZE) {
|
|
includes = cacheHas;
|
|
isCommon = false;
|
|
values = new SetCache(values);
|
|
}
|
|
outer:
|
|
while (++index < length) {
|
|
var value = array[index],
|
|
computed = iteratee == null ? value : iteratee(value);
|
|
|
|
value = (comparator || value !== 0) ? value : 0;
|
|
if (isCommon && computed === computed) {
|
|
var valuesIndex = valuesLength;
|
|
while (valuesIndex--) {
|
|
if (values[valuesIndex] === computed) {
|
|
continue outer;
|
|
}
|
|
}
|
|
result.push(value);
|
|
}
|
|
else if (!includes(values, computed, comparator)) {
|
|
result.push(value);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.forEach` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Array|Object} Returns `collection`.
|
|
*/
|
|
var baseEach = createBaseEach(baseForOwn);
|
|
|
|
/**
|
|
* The base implementation of `_.forEachRight` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Array|Object} Returns `collection`.
|
|
*/
|
|
var baseEachRight = createBaseEach(baseForOwnRight, true);
|
|
|
|
/**
|
|
* The base implementation of `_.every` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @returns {boolean} Returns `true` if all elements pass the predicate check,
|
|
* else `false`
|
|
*/
|
|
function baseEvery(collection, predicate) {
|
|
var result = true;
|
|
baseEach(collection, function(value, index, collection) {
|
|
result = !!predicate(value, index, collection);
|
|
return result;
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of methods like `_.max` and `_.min` which accepts a
|
|
* `comparator` to determine the extremum value.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} iteratee The iteratee invoked per iteration.
|
|
* @param {Function} comparator The comparator used to compare values.
|
|
* @returns {*} Returns the extremum value.
|
|
*/
|
|
function baseExtremum(array, iteratee, comparator) {
|
|
var index = -1,
|
|
length = array.length;
|
|
|
|
while (++index < length) {
|
|
var value = array[index],
|
|
current = iteratee(value);
|
|
|
|
if (current != null && (computed === undefined
|
|
? (current === current && !isSymbol(current))
|
|
: comparator(current, computed)
|
|
)) {
|
|
var computed = current,
|
|
result = value;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.fill` without an iteratee call guard.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to fill.
|
|
* @param {*} value The value to fill `array` with.
|
|
* @param {number} [start=0] The start position.
|
|
* @param {number} [end=array.length] The end position.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function baseFill(array, value, start, end) {
|
|
var length = array.length;
|
|
|
|
start = toInteger(start);
|
|
if (start < 0) {
|
|
start = -start > length ? 0 : (length + start);
|
|
}
|
|
end = (end === undefined || end > length) ? length : toInteger(end);
|
|
if (end < 0) {
|
|
end += length;
|
|
}
|
|
end = start > end ? 0 : toLength(end);
|
|
while (start < end) {
|
|
array[start++] = value;
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.filter` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @returns {Array} Returns the new filtered array.
|
|
*/
|
|
function baseFilter(collection, predicate) {
|
|
var result = [];
|
|
baseEach(collection, function(value, index, collection) {
|
|
if (predicate(value, index, collection)) {
|
|
result.push(value);
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.flatten` with support for restricting flattening.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to flatten.
|
|
* @param {number} depth The maximum recursion depth.
|
|
* @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
|
|
* @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
|
|
* @param {Array} [result=[]] The initial result value.
|
|
* @returns {Array} Returns the new flattened array.
|
|
*/
|
|
function baseFlatten(array, depth, predicate, isStrict, result) {
|
|
var index = -1,
|
|
length = array.length;
|
|
|
|
predicate || (predicate = isFlattenable);
|
|
result || (result = []);
|
|
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
if (depth > 0 && predicate(value)) {
|
|
if (depth > 1) {
|
|
// Recursively flatten arrays (susceptible to call stack limits).
|
|
baseFlatten(value, depth - 1, predicate, isStrict, result);
|
|
} else {
|
|
arrayPush(result, value);
|
|
}
|
|
} else if (!isStrict) {
|
|
result[result.length] = value;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `baseForOwn` which iterates over `object`
|
|
* properties returned by `keysFunc` and invokes `iteratee` for each property.
|
|
* Iteratee functions may exit iteration early by explicitly returning `false`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @param {Function} keysFunc The function to get the keys of `object`.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
var baseFor = createBaseFor();
|
|
|
|
/**
|
|
* This function is like `baseFor` except that it iterates over properties
|
|
* in the opposite order.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @param {Function} keysFunc The function to get the keys of `object`.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
var baseForRight = createBaseFor(true);
|
|
|
|
/**
|
|
* The base implementation of `_.forOwn` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
function baseForOwn(object, iteratee) {
|
|
return object && baseFor(object, iteratee, keys);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.forOwnRight` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
function baseForOwnRight(object, iteratee) {
|
|
return object && baseForRight(object, iteratee, keys);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.functions` which creates an array of
|
|
* `object` function property names filtered from `props`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to inspect.
|
|
* @param {Array} props The property names to filter.
|
|
* @returns {Array} Returns the function names.
|
|
*/
|
|
function baseFunctions(object, props) {
|
|
return arrayFilter(props, function(key) {
|
|
return isFunction(object[key]);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.get` without support for default values.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @param {Array|string} path The path of the property to get.
|
|
* @returns {*} Returns the resolved value.
|
|
*/
|
|
function baseGet(object, path) {
|
|
path = castPath(path, object);
|
|
|
|
var index = 0,
|
|
length = path.length;
|
|
|
|
while (object != null && index < length) {
|
|
object = object[toKey(path[index++])];
|
|
}
|
|
return (index && index == length) ? object : undefined;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `getAllKeys` and `getAllKeysIn` which uses
|
|
* `keysFunc` and `symbolsFunc` to get the enumerable property names and
|
|
* symbols of `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @param {Function} keysFunc The function to get the keys of `object`.
|
|
* @param {Function} symbolsFunc The function to get the symbols of `object`.
|
|
* @returns {Array} Returns the array of property names and symbols.
|
|
*/
|
|
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
|
|
var result = keysFunc(object);
|
|
return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `getTag` without fallbacks for buggy environments.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to query.
|
|
* @returns {string} Returns the `toStringTag`.
|
|
*/
|
|
function baseGetTag(value) {
|
|
if (value == null) {
|
|
return value === undefined ? undefinedTag : nullTag;
|
|
}
|
|
return (symToStringTag && symToStringTag in Object(value))
|
|
? getRawTag(value)
|
|
: objectToString(value);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.gt` which doesn't coerce arguments.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @returns {boolean} Returns `true` if `value` is greater than `other`,
|
|
* else `false`.
|
|
*/
|
|
function baseGt(value, other) {
|
|
return value > other;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.has` without support for deep paths.
|
|
*
|
|
* @private
|
|
* @param {Object} [object] The object to query.
|
|
* @param {Array|string} key The key to check.
|
|
* @returns {boolean} Returns `true` if `key` exists, else `false`.
|
|
*/
|
|
function baseHas(object, key) {
|
|
return object != null && hasOwnProperty.call(object, key);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.hasIn` without support for deep paths.
|
|
*
|
|
* @private
|
|
* @param {Object} [object] The object to query.
|
|
* @param {Array|string} key The key to check.
|
|
* @returns {boolean} Returns `true` if `key` exists, else `false`.
|
|
*/
|
|
function baseHasIn(object, key) {
|
|
return object != null && key in Object(object);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.inRange` which doesn't coerce arguments.
|
|
*
|
|
* @private
|
|
* @param {number} number The number to check.
|
|
* @param {number} start The start of the range.
|
|
* @param {number} end The end of the range.
|
|
* @returns {boolean} Returns `true` if `number` is in the range, else `false`.
|
|
*/
|
|
function baseInRange(number, start, end) {
|
|
return number >= nativeMin(start, end) && number < nativeMax(start, end);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of methods like `_.intersection`, without support
|
|
* for iteratee shorthands, that accepts an array of arrays to inspect.
|
|
*
|
|
* @private
|
|
* @param {Array} arrays The arrays to inspect.
|
|
* @param {Function} [iteratee] The iteratee invoked per element.
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
* @returns {Array} Returns the new array of shared values.
|
|
*/
|
|
function baseIntersection(arrays, iteratee, comparator) {
|
|
var includes = comparator ? arrayIncludesWith : arrayIncludes,
|
|
length = arrays[0].length,
|
|
othLength = arrays.length,
|
|
othIndex = othLength,
|
|
caches = Array(othLength),
|
|
maxLength = Infinity,
|
|
result = [];
|
|
|
|
while (othIndex--) {
|
|
var array = arrays[othIndex];
|
|
if (othIndex && iteratee) {
|
|
array = arrayMap(array, baseUnary(iteratee));
|
|
}
|
|
maxLength = nativeMin(array.length, maxLength);
|
|
caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
|
|
? new SetCache(othIndex && array)
|
|
: undefined;
|
|
}
|
|
array = arrays[0];
|
|
|
|
var index = -1,
|
|
seen = caches[0];
|
|
|
|
outer:
|
|
while (++index < length && result.length < maxLength) {
|
|
var value = array[index],
|
|
computed = iteratee ? iteratee(value) : value;
|
|
|
|
value = (comparator || value !== 0) ? value : 0;
|
|
if (!(seen
|
|
? cacheHas(seen, computed)
|
|
: includes(result, computed, comparator)
|
|
)) {
|
|
othIndex = othLength;
|
|
while (--othIndex) {
|
|
var cache = caches[othIndex];
|
|
if (!(cache
|
|
? cacheHas(cache, computed)
|
|
: includes(arrays[othIndex], computed, comparator))
|
|
) {
|
|
continue outer;
|
|
}
|
|
}
|
|
if (seen) {
|
|
seen.push(computed);
|
|
}
|
|
result.push(value);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.invert` and `_.invertBy` which inverts
|
|
* `object` with values transformed by `iteratee` and set by `setter`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} setter The function to set `accumulator` values.
|
|
* @param {Function} iteratee The iteratee to transform values.
|
|
* @param {Object} accumulator The initial inverted object.
|
|
* @returns {Function} Returns `accumulator`.
|
|
*/
|
|
function baseInverter(object, setter, iteratee, accumulator) {
|
|
baseForOwn(object, function(value, key, object) {
|
|
setter(accumulator, iteratee(value), key, object);
|
|
});
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.invoke` without support for individual
|
|
* method arguments.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @param {Array|string} path The path of the method to invoke.
|
|
* @param {Array} args The arguments to invoke the method with.
|
|
* @returns {*} Returns the result of the invoked method.
|
|
*/
|
|
function baseInvoke(object, path, args) {
|
|
path = castPath(path, object);
|
|
object = parent(object, path);
|
|
var func = object == null ? object : object[toKey(last(path))];
|
|
return func == null ? undefined : apply(func, object, args);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isArguments`.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is an `arguments` object,
|
|
*/
|
|
function baseIsArguments(value) {
|
|
return isObjectLike(value) && baseGetTag(value) == argsTag;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isArrayBuffer` without Node.js optimizations.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
|
|
*/
|
|
function baseIsArrayBuffer(value) {
|
|
return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isDate` without Node.js optimizations.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a date object, else `false`.
|
|
*/
|
|
function baseIsDate(value) {
|
|
return isObjectLike(value) && baseGetTag(value) == dateTag;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isEqual` which supports partial comparisons
|
|
* and tracks traversed objects.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @param {boolean} bitmask The bitmask flags.
|
|
* 1 - Unordered comparison
|
|
* 2 - Partial comparison
|
|
* @param {Function} [customizer] The function to customize comparisons.
|
|
* @param {Object} [stack] Tracks traversed `value` and `other` objects.
|
|
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
|
|
*/
|
|
function baseIsEqual(value, other, bitmask, customizer, stack) {
|
|
if (value === other) {
|
|
return true;
|
|
}
|
|
if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
|
|
return value !== value && other !== other;
|
|
}
|
|
return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseIsEqual` for arrays and objects which performs
|
|
* deep comparisons and tracks traversed objects enabling objects with circular
|
|
* references to be compared.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to compare.
|
|
* @param {Object} other The other object to compare.
|
|
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
|
|
* @param {Function} customizer The function to customize comparisons.
|
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
|
* @param {Object} [stack] Tracks traversed `object` and `other` objects.
|
|
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
|
*/
|
|
function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
|
|
var objIsArr = isArray(object),
|
|
othIsArr = isArray(other),
|
|
objTag = objIsArr ? arrayTag : getTag(object),
|
|
othTag = othIsArr ? arrayTag : getTag(other);
|
|
|
|
objTag = objTag == argsTag ? objectTag : objTag;
|
|
othTag = othTag == argsTag ? objectTag : othTag;
|
|
|
|
var objIsObj = objTag == objectTag,
|
|
othIsObj = othTag == objectTag,
|
|
isSameTag = objTag == othTag;
|
|
|
|
if (isSameTag && isBuffer(object)) {
|
|
if (!isBuffer(other)) {
|
|
return false;
|
|
}
|
|
objIsArr = true;
|
|
objIsObj = false;
|
|
}
|
|
if (isSameTag && !objIsObj) {
|
|
stack || (stack = new Stack);
|
|
return (objIsArr || isTypedArray(object))
|
|
? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
|
|
: equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
|
|
}
|
|
if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
|
|
var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
|
|
othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
|
|
|
|
if (objIsWrapped || othIsWrapped) {
|
|
var objUnwrapped = objIsWrapped ? object.value() : object,
|
|
othUnwrapped = othIsWrapped ? other.value() : other;
|
|
|
|
stack || (stack = new Stack);
|
|
return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
|
|
}
|
|
}
|
|
if (!isSameTag) {
|
|
return false;
|
|
}
|
|
stack || (stack = new Stack);
|
|
return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isMap` without Node.js optimizations.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a map, else `false`.
|
|
*/
|
|
function baseIsMap(value) {
|
|
return isObjectLike(value) && getTag(value) == mapTag;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isMatch` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to inspect.
|
|
* @param {Object} source The object of property values to match.
|
|
* @param {Array} matchData The property names, values, and compare flags to match.
|
|
* @param {Function} [customizer] The function to customize comparisons.
|
|
* @returns {boolean} Returns `true` if `object` is a match, else `false`.
|
|
*/
|
|
function baseIsMatch(object, source, matchData, customizer) {
|
|
var index = matchData.length,
|
|
length = index,
|
|
noCustomizer = !customizer;
|
|
|
|
if (object == null) {
|
|
return !length;
|
|
}
|
|
object = Object(object);
|
|
while (index--) {
|
|
var data = matchData[index];
|
|
if ((noCustomizer && data[2])
|
|
? data[1] !== object[data[0]]
|
|
: !(data[0] in object)
|
|
) {
|
|
return false;
|
|
}
|
|
}
|
|
while (++index < length) {
|
|
data = matchData[index];
|
|
var key = data[0],
|
|
objValue = object[key],
|
|
srcValue = data[1];
|
|
|
|
if (noCustomizer && data[2]) {
|
|
if (objValue === undefined && !(key in object)) {
|
|
return false;
|
|
}
|
|
} else {
|
|
var stack = new Stack;
|
|
if (customizer) {
|
|
var result = customizer(objValue, srcValue, key, object, source, stack);
|
|
}
|
|
if (!(result === undefined
|
|
? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
|
|
: result
|
|
)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isNative` without bad shim checks.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a native function,
|
|
* else `false`.
|
|
*/
|
|
function baseIsNative(value) {
|
|
if (!isObject(value) || isMasked(value)) {
|
|
return false;
|
|
}
|
|
var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
|
|
return pattern.test(toSource(value));
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isRegExp` without Node.js optimizations.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
|
|
*/
|
|
function baseIsRegExp(value) {
|
|
return isObjectLike(value) && baseGetTag(value) == regexpTag;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isSet` without Node.js optimizations.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a set, else `false`.
|
|
*/
|
|
function baseIsSet(value) {
|
|
return isObjectLike(value) && getTag(value) == setTag;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isTypedArray` without Node.js optimizations.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
|
|
*/
|
|
function baseIsTypedArray(value) {
|
|
return isObjectLike(value) &&
|
|
isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.iteratee`.
|
|
*
|
|
* @private
|
|
* @param {*} [value=_.identity] The value to convert to an iteratee.
|
|
* @returns {Function} Returns the iteratee.
|
|
*/
|
|
function baseIteratee(value) {
|
|
// Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
|
|
// See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
|
|
if (typeof value == 'function') {
|
|
return value;
|
|
}
|
|
if (value == null) {
|
|
return identity;
|
|
}
|
|
if (typeof value == 'object') {
|
|
return isArray(value)
|
|
? baseMatchesProperty(value[0], value[1])
|
|
: baseMatches(value);
|
|
}
|
|
return property(value);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property names.
|
|
*/
|
|
function baseKeys(object) {
|
|
if (!isPrototype(object)) {
|
|
return nativeKeys(object);
|
|
}
|
|
var result = [];
|
|
for (var key in Object(object)) {
|
|
if (hasOwnProperty.call(object, key) && key != 'constructor') {
|
|
result.push(key);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property names.
|
|
*/
|
|
function baseKeysIn(object) {
|
|
if (!isObject(object)) {
|
|
return nativeKeysIn(object);
|
|
}
|
|
var isProto = isPrototype(object),
|
|
result = [];
|
|
|
|
for (var key in object) {
|
|
if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
|
|
result.push(key);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.lt` which doesn't coerce arguments.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @returns {boolean} Returns `true` if `value` is less than `other`,
|
|
* else `false`.
|
|
*/
|
|
function baseLt(value, other) {
|
|
return value < other;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.map` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Array} Returns the new mapped array.
|
|
*/
|
|
function baseMap(collection, iteratee) {
|
|
var index = -1,
|
|
result = isArrayLike(collection) ? Array(collection.length) : [];
|
|
|
|
baseEach(collection, function(value, key, collection) {
|
|
result[++index] = iteratee(value, key, collection);
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.matches` which doesn't clone `source`.
|
|
*
|
|
* @private
|
|
* @param {Object} source The object of property values to match.
|
|
* @returns {Function} Returns the new spec function.
|
|
*/
|
|
function baseMatches(source) {
|
|
var matchData = getMatchData(source);
|
|
if (matchData.length == 1 && matchData[0][2]) {
|
|
return matchesStrictComparable(matchData[0][0], matchData[0][1]);
|
|
}
|
|
return function(object) {
|
|
return object === source || baseIsMatch(object, source, matchData);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
|
|
*
|
|
* @private
|
|
* @param {string} path The path of the property to get.
|
|
* @param {*} srcValue The value to match.
|
|
* @returns {Function} Returns the new spec function.
|
|
*/
|
|
function baseMatchesProperty(path, srcValue) {
|
|
if (isKey(path) && isStrictComparable(srcValue)) {
|
|
return matchesStrictComparable(toKey(path), srcValue);
|
|
}
|
|
return function(object) {
|
|
var objValue = get(object, path);
|
|
return (objValue === undefined && objValue === srcValue)
|
|
? hasIn(object, path)
|
|
: baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.merge` without support for multiple sources.
|
|
*
|
|
* @private
|
|
* @param {Object} object The destination object.
|
|
* @param {Object} source The source object.
|
|
* @param {number} srcIndex The index of `source`.
|
|
* @param {Function} [customizer] The function to customize merged values.
|
|
* @param {Object} [stack] Tracks traversed source values and their merged
|
|
* counterparts.
|
|
*/
|
|
function baseMerge(object, source, srcIndex, customizer, stack) {
|
|
if (object === source) {
|
|
return;
|
|
}
|
|
baseFor(source, function(srcValue, key) {
|
|
stack || (stack = new Stack);
|
|
if (isObject(srcValue)) {
|
|
baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
|
|
}
|
|
else {
|
|
var newValue = customizer
|
|
? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)
|
|
: undefined;
|
|
|
|
if (newValue === undefined) {
|
|
newValue = srcValue;
|
|
}
|
|
assignMergeValue(object, key, newValue);
|
|
}
|
|
}, keysIn);
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseMerge` for arrays and objects which performs
|
|
* deep merges and tracks traversed objects enabling objects with circular
|
|
* references to be merged.
|
|
*
|
|
* @private
|
|
* @param {Object} object The destination object.
|
|
* @param {Object} source The source object.
|
|
* @param {string} key The key of the value to merge.
|
|
* @param {number} srcIndex The index of `source`.
|
|
* @param {Function} mergeFunc The function to merge values.
|
|
* @param {Function} [customizer] The function to customize assigned values.
|
|
* @param {Object} [stack] Tracks traversed source values and their merged
|
|
* counterparts.
|
|
*/
|
|
function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
|
|
var objValue = safeGet(object, key),
|
|
srcValue = safeGet(source, key),
|
|
stacked = stack.get(srcValue);
|
|
|
|
if (stacked) {
|
|
assignMergeValue(object, key, stacked);
|
|
return;
|
|
}
|
|
var newValue = customizer
|
|
? customizer(objValue, srcValue, (key + ''), object, source, stack)
|
|
: undefined;
|
|
|
|
var isCommon = newValue === undefined;
|
|
|
|
if (isCommon) {
|
|
var isArr = isArray(srcValue),
|
|
isBuff = !isArr && isBuffer(srcValue),
|
|
isTyped = !isArr && !isBuff && isTypedArray(srcValue);
|
|
|
|
newValue = srcValue;
|
|
if (isArr || isBuff || isTyped) {
|
|
if (isArray(objValue)) {
|
|
newValue = objValue;
|
|
}
|
|
else if (isArrayLikeObject(objValue)) {
|
|
newValue = copyArray(objValue);
|
|
}
|
|
else if (isBuff) {
|
|
isCommon = false;
|
|
newValue = cloneBuffer(srcValue, true);
|
|
}
|
|
else if (isTyped) {
|
|
isCommon = false;
|
|
newValue = cloneTypedArray(srcValue, true);
|
|
}
|
|
else {
|
|
newValue = [];
|
|
}
|
|
}
|
|
else if (isPlainObject(srcValue) || isArguments(srcValue)) {
|
|
newValue = objValue;
|
|
if (isArguments(objValue)) {
|
|
newValue = toPlainObject(objValue);
|
|
}
|
|
else if (!isObject(objValue) || isFunction(objValue)) {
|
|
newValue = initCloneObject(srcValue);
|
|
}
|
|
}
|
|
else {
|
|
isCommon = false;
|
|
}
|
|
}
|
|
if (isCommon) {
|
|
// Recursively merge objects and arrays (susceptible to call stack limits).
|
|
stack.set(srcValue, newValue);
|
|
mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
|
|
stack['delete'](srcValue);
|
|
}
|
|
assignMergeValue(object, key, newValue);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.nth` which doesn't coerce arguments.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to query.
|
|
* @param {number} n The index of the element to return.
|
|
* @returns {*} Returns the nth element of `array`.
|
|
*/
|
|
function baseNth(array, n) {
|
|
var length = array.length;
|
|
if (!length) {
|
|
return;
|
|
}
|
|
n += n < 0 ? length : 0;
|
|
return isIndex(n, length) ? array[n] : undefined;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.orderBy` without param guards.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
|
|
* @param {string[]} orders The sort orders of `iteratees`.
|
|
* @returns {Array} Returns the new sorted array.
|
|
*/
|
|
function baseOrderBy(collection, iteratees, orders) {
|
|
if (iteratees.length) {
|
|
iteratees = arrayMap(iteratees, function(iteratee) {
|
|
if (isArray(iteratee)) {
|
|
return function(value) {
|
|
return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
|
|
}
|
|
}
|
|
return iteratee;
|
|
});
|
|
} else {
|
|
iteratees = [identity];
|
|
}
|
|
|
|
var index = -1;
|
|
iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
|
|
|
|
var result = baseMap(collection, function(value, key, collection) {
|
|
var criteria = arrayMap(iteratees, function(iteratee) {
|
|
return iteratee(value);
|
|
});
|
|
return { 'criteria': criteria, 'index': ++index, 'value': value };
|
|
});
|
|
|
|
return baseSortBy(result, function(object, other) {
|
|
return compareMultiple(object, other, orders);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.pick` without support for individual
|
|
* property identifiers.
|
|
*
|
|
* @private
|
|
* @param {Object} object The source object.
|
|
* @param {string[]} paths The property paths to pick.
|
|
* @returns {Object} Returns the new object.
|
|
*/
|
|
function basePick(object, paths) {
|
|
return basePickBy(object, paths, function(value, path) {
|
|
return hasIn(object, path);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.pickBy` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Object} object The source object.
|
|
* @param {string[]} paths The property paths to pick.
|
|
* @param {Function} predicate The function invoked per property.
|
|
* @returns {Object} Returns the new object.
|
|
*/
|
|
function basePickBy(object, paths, predicate) {
|
|
var index = -1,
|
|
length = paths.length,
|
|
result = {};
|
|
|
|
while (++index < length) {
|
|
var path = paths[index],
|
|
value = baseGet(object, path);
|
|
|
|
if (predicate(value, path)) {
|
|
baseSet(result, castPath(path, object), value);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseProperty` which supports deep paths.
|
|
*
|
|
* @private
|
|
* @param {Array|string} path The path of the property to get.
|
|
* @returns {Function} Returns the new accessor function.
|
|
*/
|
|
function basePropertyDeep(path) {
|
|
return function(object) {
|
|
return baseGet(object, path);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.pullAllBy` without support for iteratee
|
|
* shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to modify.
|
|
* @param {Array} values The values to remove.
|
|
* @param {Function} [iteratee] The iteratee invoked per element.
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function basePullAll(array, values, iteratee, comparator) {
|
|
var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
|
|
index = -1,
|
|
length = values.length,
|
|
seen = array;
|
|
|
|
if (array === values) {
|
|
values = copyArray(values);
|
|
}
|
|
if (iteratee) {
|
|
seen = arrayMap(array, baseUnary(iteratee));
|
|
}
|
|
while (++index < length) {
|
|
var fromIndex = 0,
|
|
value = values[index],
|
|
computed = iteratee ? iteratee(value) : value;
|
|
|
|
while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
|
|
if (seen !== array) {
|
|
splice.call(seen, fromIndex, 1);
|
|
}
|
|
splice.call(array, fromIndex, 1);
|
|
}
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.pullAt` without support for individual
|
|
* indexes or capturing the removed elements.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to modify.
|
|
* @param {number[]} indexes The indexes of elements to remove.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function basePullAt(array, indexes) {
|
|
var length = array ? indexes.length : 0,
|
|
lastIndex = length - 1;
|
|
|
|
while (length--) {
|
|
var index = indexes[length];
|
|
if (length == lastIndex || index !== previous) {
|
|
var previous = index;
|
|
if (isIndex(index)) {
|
|
splice.call(array, index, 1);
|
|
} else {
|
|
baseUnset(array, index);
|
|
}
|
|
}
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.random` without support for returning
|
|
* floating-point numbers.
|
|
*
|
|
* @private
|
|
* @param {number} lower The lower bound.
|
|
* @param {number} upper The upper bound.
|
|
* @returns {number} Returns the random number.
|
|
*/
|
|
function baseRandom(lower, upper) {
|
|
return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.range` and `_.rangeRight` which doesn't
|
|
* coerce arguments.
|
|
*
|
|
* @private
|
|
* @param {number} start The start of the range.
|
|
* @param {number} end The end of the range.
|
|
* @param {number} step The value to increment or decrement by.
|
|
* @param {boolean} [fromRight] Specify iterating from right to left.
|
|
* @returns {Array} Returns the range of numbers.
|
|
*/
|
|
function baseRange(start, end, step, fromRight) {
|
|
var index = -1,
|
|
length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
|
|
result = Array(length);
|
|
|
|
while (length--) {
|
|
result[fromRight ? length : ++index] = start;
|
|
start += step;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.repeat` which doesn't coerce arguments.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to repeat.
|
|
* @param {number} n The number of times to repeat the string.
|
|
* @returns {string} Returns the repeated string.
|
|
*/
|
|
function baseRepeat(string, n) {
|
|
var result = '';
|
|
if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
|
|
return result;
|
|
}
|
|
// Leverage the exponentiation by squaring algorithm for a faster repeat.
|
|
// See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
|
|
do {
|
|
if (n % 2) {
|
|
result += string;
|
|
}
|
|
n = nativeFloor(n / 2);
|
|
if (n) {
|
|
string += string;
|
|
}
|
|
} while (n);
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.rest` which doesn't validate or coerce arguments.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to apply a rest parameter to.
|
|
* @param {number} [start=func.length-1] The start position of the rest parameter.
|
|
* @returns {Function} Returns the new function.
|
|
*/
|
|
function baseRest(func, start) {
|
|
return setToString(overRest(func, start, identity), func + '');
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.sample`.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to sample.
|
|
* @returns {*} Returns the random element.
|
|
*/
|
|
function baseSample(collection) {
|
|
return arraySample(values(collection));
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.sampleSize` without param guards.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to sample.
|
|
* @param {number} n The number of elements to sample.
|
|
* @returns {Array} Returns the random elements.
|
|
*/
|
|
function baseSampleSize(collection, n) {
|
|
var array = values(collection);
|
|
return shuffleSelf(array, baseClamp(n, 0, array.length));
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.set`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to modify.
|
|
* @param {Array|string} path The path of the property to set.
|
|
* @param {*} value The value to set.
|
|
* @param {Function} [customizer] The function to customize path creation.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
function baseSet(object, path, value, customizer) {
|
|
if (!isObject(object)) {
|
|
return object;
|
|
}
|
|
path = castPath(path, object);
|
|
|
|
var index = -1,
|
|
length = path.length,
|
|
lastIndex = length - 1,
|
|
nested = object;
|
|
|
|
while (nested != null && ++index < length) {
|
|
var key = toKey(path[index]),
|
|
newValue = value;
|
|
|
|
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
|
|
return object;
|
|
}
|
|
|
|
if (index != lastIndex) {
|
|
var objValue = nested[key];
|
|
newValue = customizer ? customizer(objValue, key, nested) : undefined;
|
|
if (newValue === undefined) {
|
|
newValue = isObject(objValue)
|
|
? objValue
|
|
: (isIndex(path[index + 1]) ? [] : {});
|
|
}
|
|
}
|
|
assignValue(nested, key, newValue);
|
|
nested = nested[key];
|
|
}
|
|
return object;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `setData` without support for hot loop shorting.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to associate metadata with.
|
|
* @param {*} data The metadata.
|
|
* @returns {Function} Returns `func`.
|
|
*/
|
|
var baseSetData = !metaMap ? identity : function(func, data) {
|
|
metaMap.set(func, data);
|
|
return func;
|
|
};
|
|
|
|
/**
|
|
* The base implementation of `setToString` without support for hot loop shorting.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to modify.
|
|
* @param {Function} string The `toString` result.
|
|
* @returns {Function} Returns `func`.
|
|
*/
|
|
var baseSetToString = !defineProperty ? identity : function(func, string) {
|
|
return defineProperty(func, 'toString', {
|
|
'configurable': true,
|
|
'enumerable': false,
|
|
'value': constant(string),
|
|
'writable': true
|
|
});
|
|
};
|
|
|
|
/**
|
|
* The base implementation of `_.shuffle`.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to shuffle.
|
|
* @returns {Array} Returns the new shuffled array.
|
|
*/
|
|
function baseShuffle(collection) {
|
|
return shuffleSelf(values(collection));
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.slice` without an iteratee call guard.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to slice.
|
|
* @param {number} [start=0] The start position.
|
|
* @param {number} [end=array.length] The end position.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
*/
|
|
function baseSlice(array, start, end) {
|
|
var index = -1,
|
|
length = array.length;
|
|
|
|
if (start < 0) {
|
|
start = -start > length ? 0 : (length + start);
|
|
}
|
|
end = end > length ? length : end;
|
|
if (end < 0) {
|
|
end += length;
|
|
}
|
|
length = start > end ? 0 : ((end - start) >>> 0);
|
|
start >>>= 0;
|
|
|
|
var result = Array(length);
|
|
while (++index < length) {
|
|
result[index] = array[index + start];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.some` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @returns {boolean} Returns `true` if any element passes the predicate check,
|
|
* else `false`.
|
|
*/
|
|
function baseSome(collection, predicate) {
|
|
var result;
|
|
|
|
baseEach(collection, function(value, index, collection) {
|
|
result = predicate(value, index, collection);
|
|
return !result;
|
|
});
|
|
return !!result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
|
|
* performs a binary search of `array` to determine the index at which `value`
|
|
* should be inserted into `array` in order to maintain its sort order.
|
|
*
|
|
* @private
|
|
* @param {Array} array The sorted array to inspect.
|
|
* @param {*} value The value to evaluate.
|
|
* @param {boolean} [retHighest] Specify returning the highest qualified index.
|
|
* @returns {number} Returns the index at which `value` should be inserted
|
|
* into `array`.
|
|
*/
|
|
function baseSortedIndex(array, value, retHighest) {
|
|
var low = 0,
|
|
high = array == null ? low : array.length;
|
|
|
|
if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
|
|
while (low < high) {
|
|
var mid = (low + high) >>> 1,
|
|
computed = array[mid];
|
|
|
|
if (computed !== null && !isSymbol(computed) &&
|
|
(retHighest ? (computed <= value) : (computed < value))) {
|
|
low = mid + 1;
|
|
} else {
|
|
high = mid;
|
|
}
|
|
}
|
|
return high;
|
|
}
|
|
return baseSortedIndexBy(array, value, identity, retHighest);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
|
|
* which invokes `iteratee` for `value` and each element of `array` to compute
|
|
* their sort ranking. The iteratee is invoked with one argument; (value).
|
|
*
|
|
* @private
|
|
* @param {Array} array The sorted array to inspect.
|
|
* @param {*} value The value to evaluate.
|
|
* @param {Function} iteratee The iteratee invoked per element.
|
|
* @param {boolean} [retHighest] Specify returning the highest qualified index.
|
|
* @returns {number} Returns the index at which `value` should be inserted
|
|
* into `array`.
|
|
*/
|
|
function baseSortedIndexBy(array, value, iteratee, retHighest) {
|
|
var low = 0,
|
|
high = array == null ? 0 : array.length;
|
|
if (high === 0) {
|
|
return 0;
|
|
}
|
|
|
|
value = iteratee(value);
|
|
var valIsNaN = value !== value,
|
|
valIsNull = value === null,
|
|
valIsSymbol = isSymbol(value),
|
|
valIsUndefined = value === undefined;
|
|
|
|
while (low < high) {
|
|
var mid = nativeFloor((low + high) / 2),
|
|
computed = iteratee(array[mid]),
|
|
othIsDefined = computed !== undefined,
|
|
othIsNull = computed === null,
|
|
othIsReflexive = computed === computed,
|
|
othIsSymbol = isSymbol(computed);
|
|
|
|
if (valIsNaN) {
|
|
var setLow = retHighest || othIsReflexive;
|
|
} else if (valIsUndefined) {
|
|
setLow = othIsReflexive && (retHighest || othIsDefined);
|
|
} else if (valIsNull) {
|
|
setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
|
|
} else if (valIsSymbol) {
|
|
setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
|
|
} else if (othIsNull || othIsSymbol) {
|
|
setLow = false;
|
|
} else {
|
|
setLow = retHighest ? (computed <= value) : (computed < value);
|
|
}
|
|
if (setLow) {
|
|
low = mid + 1;
|
|
} else {
|
|
high = mid;
|
|
}
|
|
}
|
|
return nativeMin(high, MAX_ARRAY_INDEX);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
|
|
* support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @param {Function} [iteratee] The iteratee invoked per element.
|
|
* @returns {Array} Returns the new duplicate free array.
|
|
*/
|
|
function baseSortedUniq(array, iteratee) {
|
|
var index = -1,
|
|
length = array.length,
|
|
resIndex = 0,
|
|
result = [];
|
|
|
|
while (++index < length) {
|
|
var value = array[index],
|
|
computed = iteratee ? iteratee(value) : value;
|
|
|
|
if (!index || !eq(computed, seen)) {
|
|
var seen = computed;
|
|
result[resIndex++] = value === 0 ? 0 : value;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.toNumber` which doesn't ensure correct
|
|
* conversions of binary, hexadecimal, or octal string values.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to process.
|
|
* @returns {number} Returns the number.
|
|
*/
|
|
function baseToNumber(value) {
|
|
if (typeof value == 'number') {
|
|
return value;
|
|
}
|
|
if (isSymbol(value)) {
|
|
return NAN;
|
|
}
|
|
return +value;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.toString` which doesn't convert nullish
|
|
* values to empty strings.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to process.
|
|
* @returns {string} Returns the string.
|
|
*/
|
|
function baseToString(value) {
|
|
// Exit early for strings to avoid a performance hit in some environments.
|
|
if (typeof value == 'string') {
|
|
return value;
|
|
}
|
|
if (isArray(value)) {
|
|
// Recursively convert values (susceptible to call stack limits).
|
|
return arrayMap(value, baseToString) + '';
|
|
}
|
|
if (isSymbol(value)) {
|
|
return symbolToString ? symbolToString.call(value) : '';
|
|
}
|
|
var result = (value + '');
|
|
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.uniqBy` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @param {Function} [iteratee] The iteratee invoked per element.
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
* @returns {Array} Returns the new duplicate free array.
|
|
*/
|
|
function baseUniq(array, iteratee, comparator) {
|
|
var index = -1,
|
|
includes = arrayIncludes,
|
|
length = array.length,
|
|
isCommon = true,
|
|
result = [],
|
|
seen = result;
|
|
|
|
if (comparator) {
|
|
isCommon = false;
|
|
includes = arrayIncludesWith;
|
|
}
|
|
else if (length >= LARGE_ARRAY_SIZE) {
|
|
var set = iteratee ? null : createSet(array);
|
|
if (set) {
|
|
return setToArray(set);
|
|
}
|
|
isCommon = false;
|
|
includes = cacheHas;
|
|
seen = new SetCache;
|
|
}
|
|
else {
|
|
seen = iteratee ? [] : result;
|
|
}
|
|
outer:
|
|
while (++index < length) {
|
|
var value = array[index],
|
|
computed = iteratee ? iteratee(value) : value;
|
|
|
|
value = (comparator || value !== 0) ? value : 0;
|
|
if (isCommon && computed === computed) {
|
|
var seenIndex = seen.length;
|
|
while (seenIndex--) {
|
|
if (seen[seenIndex] === computed) {
|
|
continue outer;
|
|
}
|
|
}
|
|
if (iteratee) {
|
|
seen.push(computed);
|
|
}
|
|
result.push(value);
|
|
}
|
|
else if (!includes(seen, computed, comparator)) {
|
|
if (seen !== result) {
|
|
seen.push(computed);
|
|
}
|
|
result.push(value);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.unset`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to modify.
|
|
* @param {Array|string} path The property path to unset.
|
|
* @returns {boolean} Returns `true` if the property is deleted, else `false`.
|
|
*/
|
|
function baseUnset(object, path) {
|
|
path = castPath(path, object);
|
|
object = parent(object, path);
|
|
return object == null || delete object[toKey(last(path))];
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.update`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to modify.
|
|
* @param {Array|string} path The path of the property to update.
|
|
* @param {Function} updater The function to produce the updated value.
|
|
* @param {Function} [customizer] The function to customize path creation.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
function baseUpdate(object, path, updater, customizer) {
|
|
return baseSet(object, path, updater(baseGet(object, path)), customizer);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of methods like `_.dropWhile` and `_.takeWhile`
|
|
* without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to query.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @param {boolean} [isDrop] Specify dropping elements instead of taking them.
|
|
* @param {boolean} [fromRight] Specify iterating from right to left.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
*/
|
|
function baseWhile(array, predicate, isDrop, fromRight) {
|
|
var length = array.length,
|
|
index = fromRight ? length : -1;
|
|
|
|
while ((fromRight ? index-- : ++index < length) &&
|
|
predicate(array[index], index, array)) {}
|
|
|
|
return isDrop
|
|
? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
|
|
: baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `wrapperValue` which returns the result of
|
|
* performing a sequence of actions on the unwrapped `value`, where each
|
|
* successive action is supplied the return value of the previous.
|
|
*
|
|
* @private
|
|
* @param {*} value The unwrapped value.
|
|
* @param {Array} actions Actions to perform to resolve the unwrapped value.
|
|
* @returns {*} Returns the resolved value.
|
|
*/
|
|
function baseWrapperValue(value, actions) {
|
|
var result = value;
|
|
if (result instanceof LazyWrapper) {
|
|
result = result.value();
|
|
}
|
|
return arrayReduce(actions, function(result, action) {
|
|
return action.func.apply(action.thisArg, arrayPush([result], action.args));
|
|
}, result);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of methods like `_.xor`, without support for
|
|
* iteratee shorthands, that accepts an array of arrays to inspect.
|
|
*
|
|
* @private
|
|
* @param {Array} arrays The arrays to inspect.
|
|
* @param {Function} [iteratee] The iteratee invoked per element.
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
* @returns {Array} Returns the new array of values.
|
|
*/
|
|
function baseXor(arrays, iteratee, comparator) {
|
|
var length = arrays.length;
|
|
if (length < 2) {
|
|
return length ? baseUniq(arrays[0]) : [];
|
|
}
|
|
var index = -1,
|
|
result = Array(length);
|
|
|
|
while (++index < length) {
|
|
var array = arrays[index],
|
|
othIndex = -1;
|
|
|
|
while (++othIndex < length) {
|
|
if (othIndex != index) {
|
|
result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
|
|
}
|
|
}
|
|
}
|
|
return baseUniq(baseFlatten(result, 1), iteratee, comparator);
|
|
}
|
|
|
|
/**
|
|
* This base implementation of `_.zipObject` which assigns values using `assignFunc`.
|
|
*
|
|
* @private
|
|
* @param {Array} props The property identifiers.
|
|
* @param {Array} values The property values.
|
|
* @param {Function} assignFunc The function to assign values.
|
|
* @returns {Object} Returns the new object.
|
|
*/
|
|
function baseZipObject(props, values, assignFunc) {
|
|
var index = -1,
|
|
length = props.length,
|
|
valsLength = values.length,
|
|
result = {};
|
|
|
|
while (++index < length) {
|
|
var value = index < valsLength ? values[index] : undefined;
|
|
assignFunc(result, props[index], value);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Casts `value` to an empty array if it's not an array like object.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to inspect.
|
|
* @returns {Array|Object} Returns the cast array-like object.
|
|
*/
|
|
function castArrayLikeObject(value) {
|
|
return isArrayLikeObject(value) ? value : [];
|
|
}
|
|
|
|
/**
|
|
* Casts `value` to `identity` if it's not a function.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to inspect.
|
|
* @returns {Function} Returns cast function.
|
|
*/
|
|
function castFunction(value) {
|
|
return typeof value == 'function' ? value : identity;
|
|
}
|
|
|
|
/**
|
|
* Casts `value` to a path array if it's not one.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to inspect.
|
|
* @param {Object} [object] The object to query keys on.
|
|
* @returns {Array} Returns the cast property path array.
|
|
*/
|
|
function castPath(value, object) {
|
|
if (isArray(value)) {
|
|
return value;
|
|
}
|
|
return isKey(value, object) ? [value] : stringToPath(toString(value));
|
|
}
|
|
|
|
/**
|
|
* A `baseRest` alias which can be replaced with `identity` by module
|
|
* replacement plugins.
|
|
*
|
|
* @private
|
|
* @type {Function}
|
|
* @param {Function} func The function to apply a rest parameter to.
|
|
* @returns {Function} Returns the new function.
|
|
*/
|
|
var castRest = baseRest;
|
|
|
|
/**
|
|
* Casts `array` to a slice if it's needed.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @param {number} start The start position.
|
|
* @param {number} [end=array.length] The end position.
|
|
* @returns {Array} Returns the cast slice.
|
|
*/
|
|
function castSlice(array, start, end) {
|
|
var length = array.length;
|
|
end = end === undefined ? length : end;
|
|
return (!start && end >= length) ? array : baseSlice(array, start, end);
|
|
}
|
|
|
|
/**
|
|
* A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
|
|
*
|
|
* @private
|
|
* @param {number|Object} id The timer id or timeout object of the timer to clear.
|
|
*/
|
|
var clearTimeout = ctxClearTimeout || function(id) {
|
|
return root.clearTimeout(id);
|
|
};
|
|
|
|
/**
|
|
* Creates a clone of `buffer`.
|
|
*
|
|
* @private
|
|
* @param {Buffer} buffer The buffer to clone.
|
|
* @param {boolean} [isDeep] Specify a deep clone.
|
|
* @returns {Buffer} Returns the cloned buffer.
|
|
*/
|
|
function cloneBuffer(buffer, isDeep) {
|
|
if (isDeep) {
|
|
return buffer.slice();
|
|
}
|
|
var length = buffer.length,
|
|
result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
|
|
|
|
buffer.copy(result);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates a clone of `arrayBuffer`.
|
|
*
|
|
* @private
|
|
* @param {ArrayBuffer} arrayBuffer The array buffer to clone.
|
|
* @returns {ArrayBuffer} Returns the cloned array buffer.
|
|
*/
|
|
function cloneArrayBuffer(arrayBuffer) {
|
|
var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
|
|
new Uint8Array(result).set(new Uint8Array(arrayBuffer));
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates a clone of `dataView`.
|
|
*
|
|
* @private
|
|
* @param {Object} dataView The data view to clone.
|
|
* @param {boolean} [isDeep] Specify a deep clone.
|
|
* @returns {Object} Returns the cloned data view.
|
|
*/
|
|
function cloneDataView(dataView, isDeep) {
|
|
var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
|
|
return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
|
|
}
|
|
|
|
/**
|
|
* Creates a clone of `regexp`.
|
|
*
|
|
* @private
|
|
* @param {Object} regexp The regexp to clone.
|
|
* @returns {Object} Returns the cloned regexp.
|
|
*/
|
|
function cloneRegExp(regexp) {
|
|
var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
|
|
result.lastIndex = regexp.lastIndex;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates a clone of the `symbol` object.
|
|
*
|
|
* @private
|
|
* @param {Object} symbol The symbol object to clone.
|
|
* @returns {Object} Returns the cloned symbol object.
|
|
*/
|
|
function cloneSymbol(symbol) {
|
|
return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
|
|
}
|
|
|
|
/**
|
|
* Creates a clone of `typedArray`.
|
|
*
|
|
* @private
|
|
* @param {Object} typedArray The typed array to clone.
|
|
* @param {boolean} [isDeep] Specify a deep clone.
|
|
* @returns {Object} Returns the cloned typed array.
|
|
*/
|
|
function cloneTypedArray(typedArray, isDeep) {
|
|
var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
|
|
return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
|
|
}
|
|
|
|
/**
|
|
* Compares values to sort them in ascending order.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @returns {number} Returns the sort order indicator for `value`.
|
|
*/
|
|
function compareAscending(value, other) {
|
|
if (value !== other) {
|
|
var valIsDefined = value !== undefined,
|
|
valIsNull = value === null,
|
|
valIsReflexive = value === value,
|
|
valIsSymbol = isSymbol(value);
|
|
|
|
var othIsDefined = other !== undefined,
|
|
othIsNull = other === null,
|
|
othIsReflexive = other === other,
|
|
othIsSymbol = isSymbol(other);
|
|
|
|
if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
|
|
(valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
|
|
(valIsNull && othIsDefined && othIsReflexive) ||
|
|
(!valIsDefined && othIsReflexive) ||
|
|
!valIsReflexive) {
|
|
return 1;
|
|
}
|
|
if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
|
|
(othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
|
|
(othIsNull && valIsDefined && valIsReflexive) ||
|
|
(!othIsDefined && valIsReflexive) ||
|
|
!othIsReflexive) {
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Used by `_.orderBy` to compare multiple properties of a value to another
|
|
* and stable sort them.
|
|
*
|
|
* If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
|
|
* specify an order of "desc" for descending or "asc" for ascending sort order
|
|
* of corresponding values.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to compare.
|
|
* @param {Object} other The other object to compare.
|
|
* @param {boolean[]|string[]} orders The order to sort by for each property.
|
|
* @returns {number} Returns the sort order indicator for `object`.
|
|
*/
|
|
function compareMultiple(object, other, orders) {
|
|
var index = -1,
|
|
objCriteria = object.criteria,
|
|
othCriteria = other.criteria,
|
|
length = objCriteria.length,
|
|
ordersLength = orders.length;
|
|
|
|
while (++index < length) {
|
|
var result = compareAscending(objCriteria[index], othCriteria[index]);
|
|
if (result) {
|
|
if (index >= ordersLength) {
|
|
return result;
|
|
}
|
|
var order = orders[index];
|
|
return result * (order == 'desc' ? -1 : 1);
|
|
}
|
|
}
|
|
// Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
|
|
// that causes it, under certain circumstances, to provide the same value for
|
|
// `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
|
|
// for more details.
|
|
//
|
|
// This also ensures a stable sort in V8 and other engines.
|
|
// See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
|
|
return object.index - other.index;
|
|
}
|
|
|
|
/**
|
|
* Creates an array that is the composition of partially applied arguments,
|
|
* placeholders, and provided arguments into a single array of arguments.
|
|
*
|
|
* @private
|
|
* @param {Array} args The provided arguments.
|
|
* @param {Array} partials The arguments to prepend to those provided.
|
|
* @param {Array} holders The `partials` placeholder indexes.
|
|
* @params {boolean} [isCurried] Specify composing for a curried function.
|
|
* @returns {Array} Returns the new array of composed arguments.
|
|
*/
|
|
function composeArgs(args, partials, holders, isCurried) {
|
|
var argsIndex = -1,
|
|
argsLength = args.length,
|
|
holdersLength = holders.length,
|
|
leftIndex = -1,
|
|
leftLength = partials.length,
|
|
rangeLength = nativeMax(argsLength - holdersLength, 0),
|
|
result = Array(leftLength + rangeLength),
|
|
isUncurried = !isCurried;
|
|
|
|
while (++leftIndex < leftLength) {
|
|
result[leftIndex] = partials[leftIndex];
|
|
}
|
|
while (++argsIndex < holdersLength) {
|
|
if (isUncurried || argsIndex < argsLength) {
|
|
result[holders[argsIndex]] = args[argsIndex];
|
|
}
|
|
}
|
|
while (rangeLength--) {
|
|
result[leftIndex++] = args[argsIndex++];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* This function is like `composeArgs` except that the arguments composition
|
|
* is tailored for `_.partialRight`.
|
|
*
|
|
* @private
|
|
* @param {Array} args The provided arguments.
|
|
* @param {Array} partials The arguments to append to those provided.
|
|
* @param {Array} holders The `partials` placeholder indexes.
|
|
* @params {boolean} [isCurried] Specify composing for a curried function.
|
|
* @returns {Array} Returns the new array of composed arguments.
|
|
*/
|
|
function composeArgsRight(args, partials, holders, isCurried) {
|
|
var argsIndex = -1,
|
|
argsLength = args.length,
|
|
holdersIndex = -1,
|
|
holdersLength = holders.length,
|
|
rightIndex = -1,
|
|
rightLength = partials.length,
|
|
rangeLength = nativeMax(argsLength - holdersLength, 0),
|
|
result = Array(rangeLength + rightLength),
|
|
isUncurried = !isCurried;
|
|
|
|
while (++argsIndex < rangeLength) {
|
|
result[argsIndex] = args[argsIndex];
|
|
}
|
|
var offset = argsIndex;
|
|
while (++rightIndex < rightLength) {
|
|
result[offset + rightIndex] = partials[rightIndex];
|
|
}
|
|
while (++holdersIndex < holdersLength) {
|
|
if (isUncurried || argsIndex < argsLength) {
|
|
result[offset + holders[holdersIndex]] = args[argsIndex++];
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Copies the values of `source` to `array`.
|
|
*
|
|
* @private
|
|
* @param {Array} source The array to copy values from.
|
|
* @param {Array} [array=[]] The array to copy values to.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function copyArray(source, array) {
|
|
var index = -1,
|
|
length = source.length;
|
|
|
|
array || (array = Array(length));
|
|
while (++index < length) {
|
|
array[index] = source[index];
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* Copies properties of `source` to `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} source The object to copy properties from.
|
|
* @param {Array} props The property identifiers to copy.
|
|
* @param {Object} [object={}] The object to copy properties to.
|
|
* @param {Function} [customizer] The function to customize copied values.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
function copyObject(source, props, object, customizer) {
|
|
var isNew = !object;
|
|
object || (object = {});
|
|
|
|
var index = -1,
|
|
length = props.length;
|
|
|
|
while (++index < length) {
|
|
var key = props[index];
|
|
|
|
var newValue = customizer
|
|
? customizer(object[key], source[key], key, object, source)
|
|
: undefined;
|
|
|
|
if (newValue === undefined) {
|
|
newValue = source[key];
|
|
}
|
|
if (isNew) {
|
|
baseAssignValue(object, key, newValue);
|
|
} else {
|
|
assignValue(object, key, newValue);
|
|
}
|
|
}
|
|
return object;
|
|
}
|
|
|
|
/**
|
|
* Copies own symbols of `source` to `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} source The object to copy symbols from.
|
|
* @param {Object} [object={}] The object to copy symbols to.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
function copySymbols(source, object) {
|
|
return copyObject(source, getSymbols(source), object);
|
|
}
|
|
|
|
/**
|
|
* Copies own and inherited symbols of `source` to `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} source The object to copy symbols from.
|
|
* @param {Object} [object={}] The object to copy symbols to.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
function copySymbolsIn(source, object) {
|
|
return copyObject(source, getSymbolsIn(source), object);
|
|
}
|
|
|
|
/**
|
|
* Creates a function like `_.groupBy`.
|
|
*
|
|
* @private
|
|
* @param {Function} setter The function to set accumulator values.
|
|
* @param {Function} [initializer] The accumulator object initializer.
|
|
* @returns {Function} Returns the new aggregator function.
|
|
*/
|
|
function createAggregator(setter, initializer) {
|
|
return function(collection, iteratee) {
|
|
var func = isArray(collection) ? arrayAggregator : baseAggregator,
|
|
accumulator = initializer ? initializer() : {};
|
|
|
|
return func(collection, setter, getIteratee(iteratee, 2), accumulator);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function like `_.assign`.
|
|
*
|
|
* @private
|
|
* @param {Function} assigner The function to assign values.
|
|
* @returns {Function} Returns the new assigner function.
|
|
*/
|
|
function createAssigner(assigner) {
|
|
return baseRest(function(object, sources) {
|
|
var index = -1,
|
|
length = sources.length,
|
|
customizer = length > 1 ? sources[length - 1] : undefined,
|
|
guard = length > 2 ? sources[2] : undefined;
|
|
|
|
customizer = (assigner.length > 3 && typeof customizer == 'function')
|
|
? (length--, customizer)
|
|
: undefined;
|
|
|
|
if (guard && isIterateeCall(sources[0], sources[1], guard)) {
|
|
customizer = length < 3 ? undefined : customizer;
|
|
length = 1;
|
|
}
|
|
object = Object(object);
|
|
while (++index < length) {
|
|
var source = sources[index];
|
|
if (source) {
|
|
assigner(object, source, index, customizer);
|
|
}
|
|
}
|
|
return object;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates a `baseEach` or `baseEachRight` function.
|
|
*
|
|
* @private
|
|
* @param {Function} eachFunc The function to iterate over a collection.
|
|
* @param {boolean} [fromRight] Specify iterating from right to left.
|
|
* @returns {Function} Returns the new base function.
|
|
*/
|
|
function createBaseEach(eachFunc, fromRight) {
|
|
return function(collection, iteratee) {
|
|
if (collection == null) {
|
|
return collection;
|
|
}
|
|
if (!isArrayLike(collection)) {
|
|
return eachFunc(collection, iteratee);
|
|
}
|
|
var length = collection.length,
|
|
index = fromRight ? length : -1,
|
|
iterable = Object(collection);
|
|
|
|
while ((fromRight ? index-- : ++index < length)) {
|
|
if (iteratee(iterable[index], index, iterable) === false) {
|
|
break;
|
|
}
|
|
}
|
|
return collection;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a base function for methods like `_.forIn` and `_.forOwn`.
|
|
*
|
|
* @private
|
|
* @param {boolean} [fromRight] Specify iterating from right to left.
|
|
* @returns {Function} Returns the new base function.
|
|
*/
|
|
function createBaseFor(fromRight) {
|
|
return function(object, iteratee, keysFunc) {
|
|
var index = -1,
|
|
iterable = Object(object),
|
|
props = keysFunc(object),
|
|
length = props.length;
|
|
|
|
while (length--) {
|
|
var key = props[fromRight ? length : ++index];
|
|
if (iteratee(iterable[key], key, iterable) === false) {
|
|
break;
|
|
}
|
|
}
|
|
return object;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that wraps `func` to invoke it with the optional `this`
|
|
* binding of `thisArg`.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to wrap.
|
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
|
|
* @param {*} [thisArg] The `this` binding of `func`.
|
|
* @returns {Function} Returns the new wrapped function.
|
|
*/
|
|
function createBind(func, bitmask, thisArg) {
|
|
var isBind = bitmask & WRAP_BIND_FLAG,
|
|
Ctor = createCtor(func);
|
|
|
|
function wrapper() {
|
|
var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
|
|
return fn.apply(isBind ? thisArg : this, arguments);
|
|
}
|
|
return wrapper;
|
|
}
|
|
|
|
/**
|
|
* Creates a function like `_.lowerFirst`.
|
|
*
|
|
* @private
|
|
* @param {string} methodName The name of the `String` case method to use.
|
|
* @returns {Function} Returns the new case function.
|
|
*/
|
|
function createCaseFirst(methodName) {
|
|
return function(string) {
|
|
string = toString(string);
|
|
|
|
var strSymbols = hasUnicode(string)
|
|
? stringToArray(string)
|
|
: undefined;
|
|
|
|
var chr = strSymbols
|
|
? strSymbols[0]
|
|
: string.charAt(0);
|
|
|
|
var trailing = strSymbols
|
|
? castSlice(strSymbols, 1).join('')
|
|
: string.slice(1);
|
|
|
|
return chr[methodName]() + trailing;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function like `_.camelCase`.
|
|
*
|
|
* @private
|
|
* @param {Function} callback The function to combine each word.
|
|
* @returns {Function} Returns the new compounder function.
|
|
*/
|
|
function createCompounder(callback) {
|
|
return function(string) {
|
|
return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that produces an instance of `Ctor` regardless of
|
|
* whether it was invoked as part of a `new` expression or by `call` or `apply`.
|
|
*
|
|
* @private
|
|
* @param {Function} Ctor The constructor to wrap.
|
|
* @returns {Function} Returns the new wrapped function.
|
|
*/
|
|
function createCtor(Ctor) {
|
|
return function() {
|
|
// Use a `switch` statement to work with class constructors. See
|
|
// http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
|
|
// for more details.
|
|
var args = arguments;
|
|
switch (args.length) {
|
|
case 0: return new Ctor;
|
|
case 1: return new Ctor(args[0]);
|
|
case 2: return new Ctor(args[0], args[1]);
|
|
case 3: return new Ctor(args[0], args[1], args[2]);
|
|
case 4: return new Ctor(args[0], args[1], args[2], args[3]);
|
|
case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
|
|
case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
|
|
case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
|
|
}
|
|
var thisBinding = baseCreate(Ctor.prototype),
|
|
result = Ctor.apply(thisBinding, args);
|
|
|
|
// Mimic the constructor's `return` behavior.
|
|
// See https://es5.github.io/#x13.2.2 for more details.
|
|
return isObject(result) ? result : thisBinding;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that wraps `func` to enable currying.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to wrap.
|
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
|
|
* @param {number} arity The arity of `func`.
|
|
* @returns {Function} Returns the new wrapped function.
|
|
*/
|
|
function createCurry(func, bitmask, arity) {
|
|
var Ctor = createCtor(func);
|
|
|
|
function wrapper() {
|
|
var length = arguments.length,
|
|
args = Array(length),
|
|
index = length,
|
|
placeholder = getHolder(wrapper);
|
|
|
|
while (index--) {
|
|
args[index] = arguments[index];
|
|
}
|
|
var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
|
|
? []
|
|
: replaceHolders(args, placeholder);
|
|
|
|
length -= holders.length;
|
|
if (length < arity) {
|
|
return createRecurry(
|
|
func, bitmask, createHybrid, wrapper.placeholder, undefined,
|
|
args, holders, undefined, undefined, arity - length);
|
|
}
|
|
var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
|
|
return apply(fn, this, args);
|
|
}
|
|
return wrapper;
|
|
}
|
|
|
|
/**
|
|
* Creates a `_.find` or `_.findLast` function.
|
|
*
|
|
* @private
|
|
* @param {Function} findIndexFunc The function to find the collection index.
|
|
* @returns {Function} Returns the new find function.
|
|
*/
|
|
function createFind(findIndexFunc) {
|
|
return function(collection, predicate, fromIndex) {
|
|
var iterable = Object(collection);
|
|
if (!isArrayLike(collection)) {
|
|
var iteratee = getIteratee(predicate, 3);
|
|
collection = keys(collection);
|
|
predicate = function(key) { return iteratee(iterable[key], key, iterable); };
|
|
}
|
|
var index = findIndexFunc(collection, predicate, fromIndex);
|
|
return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a `_.flow` or `_.flowRight` function.
|
|
*
|
|
* @private
|
|
* @param {boolean} [fromRight] Specify iterating from right to left.
|
|
* @returns {Function} Returns the new flow function.
|
|
*/
|
|
function createFlow(fromRight) {
|
|
return flatRest(function(funcs) {
|
|
var length = funcs.length,
|
|
index = length,
|
|
prereq = LodashWrapper.prototype.thru;
|
|
|
|
if (fromRight) {
|
|
funcs.reverse();
|
|
}
|
|
while (index--) {
|
|
var func = funcs[index];
|
|
if (typeof func != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
|
|
var wrapper = new LodashWrapper([], true);
|
|
}
|
|
}
|
|
index = wrapper ? index : length;
|
|
while (++index < length) {
|
|
func = funcs[index];
|
|
|
|
var funcName = getFuncName(func),
|
|
data = funcName == 'wrapper' ? getData(func) : undefined;
|
|
|
|
if (data && isLaziable(data[0]) &&
|
|
data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
|
|
!data[4].length && data[9] == 1
|
|
) {
|
|
wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
|
|
} else {
|
|
wrapper = (func.length == 1 && isLaziable(func))
|
|
? wrapper[funcName]()
|
|
: wrapper.thru(func);
|
|
}
|
|
}
|
|
return function() {
|
|
var args = arguments,
|
|
value = args[0];
|
|
|
|
if (wrapper && args.length == 1 && isArray(value)) {
|
|
return wrapper.plant(value).value();
|
|
}
|
|
var index = 0,
|
|
result = length ? funcs[index].apply(this, args) : value;
|
|
|
|
while (++index < length) {
|
|
result = funcs[index].call(this, result);
|
|
}
|
|
return result;
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates a function that wraps `func` to invoke it with optional `this`
|
|
* binding of `thisArg`, partial application, and currying.
|
|
*
|
|
* @private
|
|
* @param {Function|string} func The function or method name to wrap.
|
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
|
|
* @param {*} [thisArg] The `this` binding of `func`.
|
|
* @param {Array} [partials] The arguments to prepend to those provided to
|
|
* the new function.
|
|
* @param {Array} [holders] The `partials` placeholder indexes.
|
|
* @param {Array} [partialsRight] The arguments to append to those provided
|
|
* to the new function.
|
|
* @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
|
|
* @param {Array} [argPos] The argument positions of the new function.
|
|
* @param {number} [ary] The arity cap of `func`.
|
|
* @param {number} [arity] The arity of `func`.
|
|
* @returns {Function} Returns the new wrapped function.
|
|
*/
|
|
function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
|
|
var isAry = bitmask & WRAP_ARY_FLAG,
|
|
isBind = bitmask & WRAP_BIND_FLAG,
|
|
isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
|
|
isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
|
|
isFlip = bitmask & WRAP_FLIP_FLAG,
|
|
Ctor = isBindKey ? undefined : createCtor(func);
|
|
|
|
function wrapper() {
|
|
var length = arguments.length,
|
|
args = Array(length),
|
|
index = length;
|
|
|
|
while (index--) {
|
|
args[index] = arguments[index];
|
|
}
|
|
if (isCurried) {
|
|
var placeholder = getHolder(wrapper),
|
|
holdersCount = countHolders(args, placeholder);
|
|
}
|
|
if (partials) {
|
|
args = composeArgs(args, partials, holders, isCurried);
|
|
}
|
|
if (partialsRight) {
|
|
args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
|
|
}
|
|
length -= holdersCount;
|
|
if (isCurried && length < arity) {
|
|
var newHolders = replaceHolders(args, placeholder);
|
|
return createRecurry(
|
|
func, bitmask, createHybrid, wrapper.placeholder, thisArg,
|
|
args, newHolders, argPos, ary, arity - length
|
|
);
|
|
}
|
|
var thisBinding = isBind ? thisArg : this,
|
|
fn = isBindKey ? thisBinding[func] : func;
|
|
|
|
length = args.length;
|
|
if (argPos) {
|
|
args = reorder(args, argPos);
|
|
} else if (isFlip && length > 1) {
|
|
args.reverse();
|
|
}
|
|
if (isAry && ary < length) {
|
|
args.length = ary;
|
|
}
|
|
if (this && this !== root && this instanceof wrapper) {
|
|
fn = Ctor || createCtor(fn);
|
|
}
|
|
return fn.apply(thisBinding, args);
|
|
}
|
|
return wrapper;
|
|
}
|
|
|
|
/**
|
|
* Creates a function like `_.invertBy`.
|
|
*
|
|
* @private
|
|
* @param {Function} setter The function to set accumulator values.
|
|
* @param {Function} toIteratee The function to resolve iteratees.
|
|
* @returns {Function} Returns the new inverter function.
|
|
*/
|
|
function createInverter(setter, toIteratee) {
|
|
return function(object, iteratee) {
|
|
return baseInverter(object, setter, toIteratee(iteratee), {});
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that performs a mathematical operation on two values.
|
|
*
|
|
* @private
|
|
* @param {Function} operator The function to perform the operation.
|
|
* @param {number} [defaultValue] The value used for `undefined` arguments.
|
|
* @returns {Function} Returns the new mathematical operation function.
|
|
*/
|
|
function createMathOperation(operator, defaultValue) {
|
|
return function(value, other) {
|
|
var result;
|
|
if (value === undefined && other === undefined) {
|
|
return defaultValue;
|
|
}
|
|
if (value !== undefined) {
|
|
result = value;
|
|
}
|
|
if (other !== undefined) {
|
|
if (result === undefined) {
|
|
return other;
|
|
}
|
|
if (typeof value == 'string' || typeof other == 'string') {
|
|
value = baseToString(value);
|
|
other = baseToString(other);
|
|
} else {
|
|
value = baseToNumber(value);
|
|
other = baseToNumber(other);
|
|
}
|
|
result = operator(value, other);
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function like `_.over`.
|
|
*
|
|
* @private
|
|
* @param {Function} arrayFunc The function to iterate over iteratees.
|
|
* @returns {Function} Returns the new over function.
|
|
*/
|
|
function createOver(arrayFunc) {
|
|
return flatRest(function(iteratees) {
|
|
iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
|
|
return baseRest(function(args) {
|
|
var thisArg = this;
|
|
return arrayFunc(iteratees, function(iteratee) {
|
|
return apply(iteratee, thisArg, args);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates the padding for `string` based on `length`. The `chars` string
|
|
* is truncated if the number of characters exceeds `length`.
|
|
*
|
|
* @private
|
|
* @param {number} length The padding length.
|
|
* @param {string} [chars=' '] The string used as padding.
|
|
* @returns {string} Returns the padding for `string`.
|
|
*/
|
|
function createPadding(length, chars) {
|
|
chars = chars === undefined ? ' ' : baseToString(chars);
|
|
|
|
var charsLength = chars.length;
|
|
if (charsLength < 2) {
|
|
return charsLength ? baseRepeat(chars, length) : chars;
|
|
}
|
|
var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
|
|
return hasUnicode(chars)
|
|
? castSlice(stringToArray(result), 0, length).join('')
|
|
: result.slice(0, length);
|
|
}
|
|
|
|
/**
|
|
* Creates a function that wraps `func` to invoke it with the `this` binding
|
|
* of `thisArg` and `partials` prepended to the arguments it receives.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to wrap.
|
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
|
|
* @param {*} thisArg The `this` binding of `func`.
|
|
* @param {Array} partials The arguments to prepend to those provided to
|
|
* the new function.
|
|
* @returns {Function} Returns the new wrapped function.
|
|
*/
|
|
function createPartial(func, bitmask, thisArg, partials) {
|
|
var isBind = bitmask & WRAP_BIND_FLAG,
|
|
Ctor = createCtor(func);
|
|
|
|
function wrapper() {
|
|
var argsIndex = -1,
|
|
argsLength = arguments.length,
|
|
leftIndex = -1,
|
|
leftLength = partials.length,
|
|
args = Array(leftLength + argsLength),
|
|
fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
|
|
|
|
while (++leftIndex < leftLength) {
|
|
args[leftIndex] = partials[leftIndex];
|
|
}
|
|
while (argsLength--) {
|
|
args[leftIndex++] = arguments[++argsIndex];
|
|
}
|
|
return apply(fn, isBind ? thisArg : this, args);
|
|
}
|
|
return wrapper;
|
|
}
|
|
|
|
/**
|
|
* Creates a `_.range` or `_.rangeRight` function.
|
|
*
|
|
* @private
|
|
* @param {boolean} [fromRight] Specify iterating from right to left.
|
|
* @returns {Function} Returns the new range function.
|
|
*/
|
|
function createRange(fromRight) {
|
|
return function(start, end, step) {
|
|
if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
|
|
end = step = undefined;
|
|
}
|
|
// Ensure the sign of `-0` is preserved.
|
|
start = toFinite(start);
|
|
if (end === undefined) {
|
|
end = start;
|
|
start = 0;
|
|
} else {
|
|
end = toFinite(end);
|
|
}
|
|
step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
|
|
return baseRange(start, end, step, fromRight);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that performs a relational operation on two values.
|
|
*
|
|
* @private
|
|
* @param {Function} operator The function to perform the operation.
|
|
* @returns {Function} Returns the new relational operation function.
|
|
*/
|
|
function createRelationalOperation(operator) {
|
|
return function(value, other) {
|
|
if (!(typeof value == 'string' && typeof other == 'string')) {
|
|
value = toNumber(value);
|
|
other = toNumber(other);
|
|
}
|
|
return operator(value, other);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that wraps `func` to continue currying.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to wrap.
|
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
|
|
* @param {Function} wrapFunc The function to create the `func` wrapper.
|
|
* @param {*} placeholder The placeholder value.
|
|
* @param {*} [thisArg] The `this` binding of `func`.
|
|
* @param {Array} [partials] The arguments to prepend to those provided to
|
|
* the new function.
|
|
* @param {Array} [holders] The `partials` placeholder indexes.
|
|
* @param {Array} [argPos] The argument positions of the new function.
|
|
* @param {number} [ary] The arity cap of `func`.
|
|
* @param {number} [arity] The arity of `func`.
|
|
* @returns {Function} Returns the new wrapped function.
|
|
*/
|
|
function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
|
|
var isCurry = bitmask & WRAP_CURRY_FLAG,
|
|
newHolders = isCurry ? holders : undefined,
|
|
newHoldersRight = isCurry ? undefined : holders,
|
|
newPartials = isCurry ? partials : undefined,
|
|
newPartialsRight = isCurry ? undefined : partials;
|
|
|
|
bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
|
|
bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
|
|
|
|
if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
|
|
bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
|
|
}
|
|
var newData = [
|
|
func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
|
|
newHoldersRight, argPos, ary, arity
|
|
];
|
|
|
|
var result = wrapFunc.apply(undefined, newData);
|
|
if (isLaziable(func)) {
|
|
setData(result, newData);
|
|
}
|
|
result.placeholder = placeholder;
|
|
return setWrapToString(result, func, bitmask);
|
|
}
|
|
|
|
/**
|
|
* Creates a function like `_.round`.
|
|
*
|
|
* @private
|
|
* @param {string} methodName The name of the `Math` method to use when rounding.
|
|
* @returns {Function} Returns the new round function.
|
|
*/
|
|
function createRound(methodName) {
|
|
var func = Math[methodName];
|
|
return function(number, precision) {
|
|
number = toNumber(number);
|
|
precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
|
|
if (precision && nativeIsFinite(number)) {
|
|
// Shift with exponential notation to avoid floating-point issues.
|
|
// See [MDN](https://mdn.io/round#Examples) for more details.
|
|
var pair = (toString(number) + 'e').split('e'),
|
|
value = func(pair[0] + 'e' + (+pair[1] + precision));
|
|
|
|
pair = (toString(value) + 'e').split('e');
|
|
return +(pair[0] + 'e' + (+pair[1] - precision));
|
|
}
|
|
return func(number);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a set object of `values`.
|
|
*
|
|
* @private
|
|
* @param {Array} values The values to add to the set.
|
|
* @returns {Object} Returns the new set.
|
|
*/
|
|
var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
|
|
return new Set(values);
|
|
};
|
|
|
|
/**
|
|
* Creates a `_.toPairs` or `_.toPairsIn` function.
|
|
*
|
|
* @private
|
|
* @param {Function} keysFunc The function to get the keys of a given object.
|
|
* @returns {Function} Returns the new pairs function.
|
|
*/
|
|
function createToPairs(keysFunc) {
|
|
return function(object) {
|
|
var tag = getTag(object);
|
|
if (tag == mapTag) {
|
|
return mapToArray(object);
|
|
}
|
|
if (tag == setTag) {
|
|
return setToPairs(object);
|
|
}
|
|
return baseToPairs(object, keysFunc(object));
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that either curries or invokes `func` with optional
|
|
* `this` binding and partially applied arguments.
|
|
*
|
|
* @private
|
|
* @param {Function|string} func The function or method name to wrap.
|
|
* @param {number} bitmask The bitmask flags.
|
|
* 1 - `_.bind`
|
|
* 2 - `_.bindKey`
|
|
* 4 - `_.curry` or `_.curryRight` of a bound function
|
|
* 8 - `_.curry`
|
|
* 16 - `_.curryRight`
|
|
* 32 - `_.partial`
|
|
* 64 - `_.partialRight`
|
|
* 128 - `_.rearg`
|
|
* 256 - `_.ary`
|
|
* 512 - `_.flip`
|
|
* @param {*} [thisArg] The `this` binding of `func`.
|
|
* @param {Array} [partials] The arguments to be partially applied.
|
|
* @param {Array} [holders] The `partials` placeholder indexes.
|
|
* @param {Array} [argPos] The argument positions of the new function.
|
|
* @param {number} [ary] The arity cap of `func`.
|
|
* @param {number} [arity] The arity of `func`.
|
|
* @returns {Function} Returns the new wrapped function.
|
|
*/
|
|
function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
|
|
var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
|
|
if (!isBindKey && typeof func != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
var length = partials ? partials.length : 0;
|
|
if (!length) {
|
|
bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
|
|
partials = holders = undefined;
|
|
}
|
|
ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
|
|
arity = arity === undefined ? arity : toInteger(arity);
|
|
length -= holders ? holders.length : 0;
|
|
|
|
if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
|
|
var partialsRight = partials,
|
|
holdersRight = holders;
|
|
|
|
partials = holders = undefined;
|
|
}
|
|
var data = isBindKey ? undefined : getData(func);
|
|
|
|
var newData = [
|
|
func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
|
|
argPos, ary, arity
|
|
];
|
|
|
|
if (data) {
|
|
mergeData(newData, data);
|
|
}
|
|
func = newData[0];
|
|
bitmask = newData[1];
|
|
thisArg = newData[2];
|
|
partials = newData[3];
|
|
holders = newData[4];
|
|
arity = newData[9] = newData[9] === undefined
|
|
? (isBindKey ? 0 : func.length)
|
|
: nativeMax(newData[9] - length, 0);
|
|
|
|
if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
|
|
bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
|
|
}
|
|
if (!bitmask || bitmask == WRAP_BIND_FLAG) {
|
|
var result = createBind(func, bitmask, thisArg);
|
|
} else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
|
|
result = createCurry(func, bitmask, arity);
|
|
} else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
|
|
result = createPartial(func, bitmask, thisArg, partials);
|
|
} else {
|
|
result = createHybrid.apply(undefined, newData);
|
|
}
|
|
var setter = data ? baseSetData : setData;
|
|
return setWrapToString(setter(result, newData), func, bitmask);
|
|
}
|
|
|
|
/**
|
|
* Used by `_.defaults` to customize its `_.assignIn` use to assign properties
|
|
* of source objects to the destination object for all destination properties
|
|
* that resolve to `undefined`.
|
|
*
|
|
* @private
|
|
* @param {*} objValue The destination value.
|
|
* @param {*} srcValue The source value.
|
|
* @param {string} key The key of the property to assign.
|
|
* @param {Object} object The parent object of `objValue`.
|
|
* @returns {*} Returns the value to assign.
|
|
*/
|
|
function customDefaultsAssignIn(objValue, srcValue, key, object) {
|
|
if (objValue === undefined ||
|
|
(eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
|
|
return srcValue;
|
|
}
|
|
return objValue;
|
|
}
|
|
|
|
/**
|
|
* Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
|
|
* objects into destination objects that are passed thru.
|
|
*
|
|
* @private
|
|
* @param {*} objValue The destination value.
|
|
* @param {*} srcValue The source value.
|
|
* @param {string} key The key of the property to merge.
|
|
* @param {Object} object The parent object of `objValue`.
|
|
* @param {Object} source The parent object of `srcValue`.
|
|
* @param {Object} [stack] Tracks traversed source values and their merged
|
|
* counterparts.
|
|
* @returns {*} Returns the value to assign.
|
|
*/
|
|
function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
|
|
if (isObject(objValue) && isObject(srcValue)) {
|
|
// Recursively merge objects and arrays (susceptible to call stack limits).
|
|
stack.set(srcValue, objValue);
|
|
baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);
|
|
stack['delete'](srcValue);
|
|
}
|
|
return objValue;
|
|
}
|
|
|
|
/**
|
|
* Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
|
|
* objects.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to inspect.
|
|
* @param {string} key The key of the property to inspect.
|
|
* @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
|
|
*/
|
|
function customOmitClone(value) {
|
|
return isPlainObject(value) ? undefined : value;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseIsEqualDeep` for arrays with support for
|
|
* partial deep comparisons.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to compare.
|
|
* @param {Array} other The other array to compare.
|
|
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
|
|
* @param {Function} customizer The function to customize comparisons.
|
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
|
* @param {Object} stack Tracks traversed `array` and `other` objects.
|
|
* @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
|
|
*/
|
|
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
|
|
var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
|
|
arrLength = array.length,
|
|
othLength = other.length;
|
|
|
|
if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
|
|
return false;
|
|
}
|
|
// Check that cyclic values are equal.
|
|
var arrStacked = stack.get(array);
|
|
var othStacked = stack.get(other);
|
|
if (arrStacked && othStacked) {
|
|
return arrStacked == other && othStacked == array;
|
|
}
|
|
var index = -1,
|
|
result = true,
|
|
seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
|
|
|
|
stack.set(array, other);
|
|
stack.set(other, array);
|
|
|
|
// Ignore non-index properties.
|
|
while (++index < arrLength) {
|
|
var arrValue = array[index],
|
|
othValue = other[index];
|
|
|
|
if (customizer) {
|
|
var compared = isPartial
|
|
? customizer(othValue, arrValue, index, other, array, stack)
|
|
: customizer(arrValue, othValue, index, array, other, stack);
|
|
}
|
|
if (compared !== undefined) {
|
|
if (compared) {
|
|
continue;
|
|
}
|
|
result = false;
|
|
break;
|
|
}
|
|
// Recursively compare arrays (susceptible to call stack limits).
|
|
if (seen) {
|
|
if (!arraySome(other, function(othValue, othIndex) {
|
|
if (!cacheHas(seen, othIndex) &&
|
|
(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
|
|
return seen.push(othIndex);
|
|
}
|
|
})) {
|
|
result = false;
|
|
break;
|
|
}
|
|
} else if (!(
|
|
arrValue === othValue ||
|
|
equalFunc(arrValue, othValue, bitmask, customizer, stack)
|
|
)) {
|
|
result = false;
|
|
break;
|
|
}
|
|
}
|
|
stack['delete'](array);
|
|
stack['delete'](other);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseIsEqualDeep` for comparing objects of
|
|
* the same `toStringTag`.
|
|
*
|
|
* **Note:** This function only supports comparing values with tags of
|
|
* `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to compare.
|
|
* @param {Object} other The other object to compare.
|
|
* @param {string} tag The `toStringTag` of the objects to compare.
|
|
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
|
|
* @param {Function} customizer The function to customize comparisons.
|
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
|
* @param {Object} stack Tracks traversed `object` and `other` objects.
|
|
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
|
*/
|
|
function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
|
|
switch (tag) {
|
|
case dataViewTag:
|
|
if ((object.byteLength != other.byteLength) ||
|
|
(object.byteOffset != other.byteOffset)) {
|
|
return false;
|
|
}
|
|
object = object.buffer;
|
|
other = other.buffer;
|
|
|
|
case arrayBufferTag:
|
|
if ((object.byteLength != other.byteLength) ||
|
|
!equalFunc(new Uint8Array(object), new Uint8Array(other))) {
|
|
return false;
|
|
}
|
|
return true;
|
|
|
|
case boolTag:
|
|
case dateTag:
|
|
case numberTag:
|
|
// Coerce booleans to `1` or `0` and dates to milliseconds.
|
|
// Invalid dates are coerced to `NaN`.
|
|
return eq(+object, +other);
|
|
|
|
case errorTag:
|
|
return object.name == other.name && object.message == other.message;
|
|
|
|
case regexpTag:
|
|
case stringTag:
|
|
// Coerce regexes to strings and treat strings, primitives and objects,
|
|
// as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
|
|
// for more details.
|
|
return object == (other + '');
|
|
|
|
case mapTag:
|
|
var convert = mapToArray;
|
|
|
|
case setTag:
|
|
var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
|
|
convert || (convert = setToArray);
|
|
|
|
if (object.size != other.size && !isPartial) {
|
|
return false;
|
|
}
|
|
// Assume cyclic values are equal.
|
|
var stacked = stack.get(object);
|
|
if (stacked) {
|
|
return stacked == other;
|
|
}
|
|
bitmask |= COMPARE_UNORDERED_FLAG;
|
|
|
|
// Recursively compare objects (susceptible to call stack limits).
|
|
stack.set(object, other);
|
|
var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
|
|
stack['delete'](object);
|
|
return result;
|
|
|
|
case symbolTag:
|
|
if (symbolValueOf) {
|
|
return symbolValueOf.call(object) == symbolValueOf.call(other);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseIsEqualDeep` for objects with support for
|
|
* partial deep comparisons.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to compare.
|
|
* @param {Object} other The other object to compare.
|
|
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
|
|
* @param {Function} customizer The function to customize comparisons.
|
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
|
* @param {Object} stack Tracks traversed `object` and `other` objects.
|
|
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
|
*/
|
|
function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
|
|
var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
|
|
objProps = getAllKeys(object),
|
|
objLength = objProps.length,
|
|
othProps = getAllKeys(other),
|
|
othLength = othProps.length;
|
|
|
|
if (objLength != othLength && !isPartial) {
|
|
return false;
|
|
}
|
|
var index = objLength;
|
|
while (index--) {
|
|
var key = objProps[index];
|
|
if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
|
|
return false;
|
|
}
|
|
}
|
|
// Check that cyclic values are equal.
|
|
var objStacked = stack.get(object);
|
|
var othStacked = stack.get(other);
|
|
if (objStacked && othStacked) {
|
|
return objStacked == other && othStacked == object;
|
|
}
|
|
var result = true;
|
|
stack.set(object, other);
|
|
stack.set(other, object);
|
|
|
|
var skipCtor = isPartial;
|
|
while (++index < objLength) {
|
|
key = objProps[index];
|
|
var objValue = object[key],
|
|
othValue = other[key];
|
|
|
|
if (customizer) {
|
|
var compared = isPartial
|
|
? customizer(othValue, objValue, key, other, object, stack)
|
|
: customizer(objValue, othValue, key, object, other, stack);
|
|
}
|
|
// Recursively compare objects (susceptible to call stack limits).
|
|
if (!(compared === undefined
|
|
? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
|
|
: compared
|
|
)) {
|
|
result = false;
|
|
break;
|
|
}
|
|
skipCtor || (skipCtor = key == 'constructor');
|
|
}
|
|
if (result && !skipCtor) {
|
|
var objCtor = object.constructor,
|
|
othCtor = other.constructor;
|
|
|
|
// Non `Object` object instances with different constructors are not equal.
|
|
if (objCtor != othCtor &&
|
|
('constructor' in object && 'constructor' in other) &&
|
|
!(typeof objCtor == 'function' && objCtor instanceof objCtor &&
|
|
typeof othCtor == 'function' && othCtor instanceof othCtor)) {
|
|
result = false;
|
|
}
|
|
}
|
|
stack['delete'](object);
|
|
stack['delete'](other);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseRest` which flattens the rest array.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to apply a rest parameter to.
|
|
* @returns {Function} Returns the new function.
|
|
*/
|
|
function flatRest(func) {
|
|
return setToString(overRest(func, undefined, flatten), func + '');
|
|
}
|
|
|
|
/**
|
|
* Creates an array of own enumerable property names and symbols of `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property names and symbols.
|
|
*/
|
|
function getAllKeys(object) {
|
|
return baseGetAllKeys(object, keys, getSymbols);
|
|
}
|
|
|
|
/**
|
|
* Creates an array of own and inherited enumerable property names and
|
|
* symbols of `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property names and symbols.
|
|
*/
|
|
function getAllKeysIn(object) {
|
|
return baseGetAllKeys(object, keysIn, getSymbolsIn);
|
|
}
|
|
|
|
/**
|
|
* Gets metadata for `func`.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to query.
|
|
* @returns {*} Returns the metadata for `func`.
|
|
*/
|
|
var getData = !metaMap ? noop : function(func) {
|
|
return metaMap.get(func);
|
|
};
|
|
|
|
/**
|
|
* Gets the name of `func`.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to query.
|
|
* @returns {string} Returns the function name.
|
|
*/
|
|
function getFuncName(func) {
|
|
var result = (func.name + ''),
|
|
array = realNames[result],
|
|
length = hasOwnProperty.call(realNames, result) ? array.length : 0;
|
|
|
|
while (length--) {
|
|
var data = array[length],
|
|
otherFunc = data.func;
|
|
if (otherFunc == null || otherFunc == func) {
|
|
return data.name;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the argument placeholder value for `func`.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to inspect.
|
|
* @returns {*} Returns the placeholder value.
|
|
*/
|
|
function getHolder(func) {
|
|
var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
|
|
return object.placeholder;
|
|
}
|
|
|
|
/**
|
|
* Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
|
|
* this function returns the custom method, otherwise it returns `baseIteratee`.
|
|
* If arguments are provided, the chosen function is invoked with them and
|
|
* its result is returned.
|
|
*
|
|
* @private
|
|
* @param {*} [value] The value to convert to an iteratee.
|
|
* @param {number} [arity] The arity of the created iteratee.
|
|
* @returns {Function} Returns the chosen function or its result.
|
|
*/
|
|
function getIteratee() {
|
|
var result = lodash.iteratee || iteratee;
|
|
result = result === iteratee ? baseIteratee : result;
|
|
return arguments.length ? result(arguments[0], arguments[1]) : result;
|
|
}
|
|
|
|
/**
|
|
* Gets the data for `map`.
|
|
*
|
|
* @private
|
|
* @param {Object} map The map to query.
|
|
* @param {string} key The reference key.
|
|
* @returns {*} Returns the map data.
|
|
*/
|
|
function getMapData(map, key) {
|
|
var data = map.__data__;
|
|
return isKeyable(key)
|
|
? data[typeof key == 'string' ? 'string' : 'hash']
|
|
: data.map;
|
|
}
|
|
|
|
/**
|
|
* Gets the property names, values, and compare flags of `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the match data of `object`.
|
|
*/
|
|
function getMatchData(object) {
|
|
var result = keys(object),
|
|
length = result.length;
|
|
|
|
while (length--) {
|
|
var key = result[length],
|
|
value = object[key];
|
|
|
|
result[length] = [key, value, isStrictComparable(value)];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the native function at `key` of `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @param {string} key The key of the method to get.
|
|
* @returns {*} Returns the function if it's native, else `undefined`.
|
|
*/
|
|
function getNative(object, key) {
|
|
var value = getValue(object, key);
|
|
return baseIsNative(value) ? value : undefined;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to query.
|
|
* @returns {string} Returns the raw `toStringTag`.
|
|
*/
|
|
function getRawTag(value) {
|
|
var isOwn = hasOwnProperty.call(value, symToStringTag),
|
|
tag = value[symToStringTag];
|
|
|
|
try {
|
|
value[symToStringTag] = undefined;
|
|
var unmasked = true;
|
|
} catch (e) {}
|
|
|
|
var result = nativeObjectToString.call(value);
|
|
if (unmasked) {
|
|
if (isOwn) {
|
|
value[symToStringTag] = tag;
|
|
} else {
|
|
delete value[symToStringTag];
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates an array of the own enumerable symbols of `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of symbols.
|
|
*/
|
|
var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
|
|
if (object == null) {
|
|
return [];
|
|
}
|
|
object = Object(object);
|
|
return arrayFilter(nativeGetSymbols(object), function(symbol) {
|
|
return propertyIsEnumerable.call(object, symbol);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Creates an array of the own and inherited enumerable symbols of `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of symbols.
|
|
*/
|
|
var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
|
|
var result = [];
|
|
while (object) {
|
|
arrayPush(result, getSymbols(object));
|
|
object = getPrototype(object);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Gets the `toStringTag` of `value`.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to query.
|
|
* @returns {string} Returns the `toStringTag`.
|
|
*/
|
|
var getTag = baseGetTag;
|
|
|
|
// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
|
|
if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
|
|
(Map && getTag(new Map) != mapTag) ||
|
|
(Promise && getTag(Promise.resolve()) != promiseTag) ||
|
|
(Set && getTag(new Set) != setTag) ||
|
|
(WeakMap && getTag(new WeakMap) != weakMapTag)) {
|
|
getTag = function(value) {
|
|
var result = baseGetTag(value),
|
|
Ctor = result == objectTag ? value.constructor : undefined,
|
|
ctorString = Ctor ? toSource(Ctor) : '';
|
|
|
|
if (ctorString) {
|
|
switch (ctorString) {
|
|
case dataViewCtorString: return dataViewTag;
|
|
case mapCtorString: return mapTag;
|
|
case promiseCtorString: return promiseTag;
|
|
case setCtorString: return setTag;
|
|
case weakMapCtorString: return weakMapTag;
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Gets the view, applying any `transforms` to the `start` and `end` positions.
|
|
*
|
|
* @private
|
|
* @param {number} start The start of the view.
|
|
* @param {number} end The end of the view.
|
|
* @param {Array} transforms The transformations to apply to the view.
|
|
* @returns {Object} Returns an object containing the `start` and `end`
|
|
* positions of the view.
|
|
*/
|
|
function getView(start, end, transforms) {
|
|
var index = -1,
|
|
length = transforms.length;
|
|
|
|
while (++index < length) {
|
|
var data = transforms[index],
|
|
size = data.size;
|
|
|
|
switch (data.type) {
|
|
case 'drop': start += size; break;
|
|
case 'dropRight': end -= size; break;
|
|
case 'take': end = nativeMin(end, start + size); break;
|
|
case 'takeRight': start = nativeMax(start, end - size); break;
|
|
}
|
|
}
|
|
return { 'start': start, 'end': end };
|
|
}
|
|
|
|
/**
|
|
* Extracts wrapper details from the `source` body comment.
|
|
*
|
|
* @private
|
|
* @param {string} source The source to inspect.
|
|
* @returns {Array} Returns the wrapper details.
|
|
*/
|
|
function getWrapDetails(source) {
|
|
var match = source.match(reWrapDetails);
|
|
return match ? match[1].split(reSplitDetails) : [];
|
|
}
|
|
|
|
/**
|
|
* Checks if `path` exists on `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @param {Array|string} path The path to check.
|
|
* @param {Function} hasFunc The function to check properties.
|
|
* @returns {boolean} Returns `true` if `path` exists, else `false`.
|
|
*/
|
|
function hasPath(object, path, hasFunc) {
|
|
path = castPath(path, object);
|
|
|
|
var index = -1,
|
|
length = path.length,
|
|
result = false;
|
|
|
|
while (++index < length) {
|
|
var key = toKey(path[index]);
|
|
if (!(result = object != null && hasFunc(object, key))) {
|
|
break;
|
|
}
|
|
object = object[key];
|
|
}
|
|
if (result || ++index != length) {
|
|
return result;
|
|
}
|
|
length = object == null ? 0 : object.length;
|
|
return !!length && isLength(length) && isIndex(key, length) &&
|
|
(isArray(object) || isArguments(object));
|
|
}
|
|
|
|
/**
|
|
* Initializes an array clone.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to clone.
|
|
* @returns {Array} Returns the initialized clone.
|
|
*/
|
|
function initCloneArray(array) {
|
|
var length = array.length,
|
|
result = new array.constructor(length);
|
|
|
|
// Add properties assigned by `RegExp#exec`.
|
|
if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
|
|
result.index = array.index;
|
|
result.input = array.input;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Initializes an object clone.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to clone.
|
|
* @returns {Object} Returns the initialized clone.
|
|
*/
|
|
function initCloneObject(object) {
|
|
return (typeof object.constructor == 'function' && !isPrototype(object))
|
|
? baseCreate(getPrototype(object))
|
|
: {};
|
|
}
|
|
|
|
/**
|
|
* Initializes an object clone based on its `toStringTag`.
|
|
*
|
|
* **Note:** This function only supports cloning values with tags of
|
|
* `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to clone.
|
|
* @param {string} tag The `toStringTag` of the object to clone.
|
|
* @param {boolean} [isDeep] Specify a deep clone.
|
|
* @returns {Object} Returns the initialized clone.
|
|
*/
|
|
function initCloneByTag(object, tag, isDeep) {
|
|
var Ctor = object.constructor;
|
|
switch (tag) {
|
|
case arrayBufferTag:
|
|
return cloneArrayBuffer(object);
|
|
|
|
case boolTag:
|
|
case dateTag:
|
|
return new Ctor(+object);
|
|
|
|
case dataViewTag:
|
|
return cloneDataView(object, isDeep);
|
|
|
|
case float32Tag: case float64Tag:
|
|
case int8Tag: case int16Tag: case int32Tag:
|
|
case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
|
|
return cloneTypedArray(object, isDeep);
|
|
|
|
case mapTag:
|
|
return new Ctor;
|
|
|
|
case numberTag:
|
|
case stringTag:
|
|
return new Ctor(object);
|
|
|
|
case regexpTag:
|
|
return cloneRegExp(object);
|
|
|
|
case setTag:
|
|
return new Ctor;
|
|
|
|
case symbolTag:
|
|
return cloneSymbol(object);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inserts wrapper `details` in a comment at the top of the `source` body.
|
|
*
|
|
* @private
|
|
* @param {string} source The source to modify.
|
|
* @returns {Array} details The details to insert.
|
|
* @returns {string} Returns the modified source.
|
|
*/
|
|
function insertWrapDetails(source, details) {
|
|
var length = details.length;
|
|
if (!length) {
|
|
return source;
|
|
}
|
|
var lastIndex = length - 1;
|
|
details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
|
|
details = details.join(length > 2 ? ', ' : ' ');
|
|
return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a flattenable `arguments` object or array.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
|
|
*/
|
|
function isFlattenable(value) {
|
|
return isArray(value) || isArguments(value) ||
|
|
!!(spreadableSymbol && value && value[spreadableSymbol]);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a valid array-like index.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
|
|
* @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
|
|
*/
|
|
function isIndex(value, length) {
|
|
var type = typeof value;
|
|
length = length == null ? MAX_SAFE_INTEGER : length;
|
|
|
|
return !!length &&
|
|
(type == 'number' ||
|
|
(type != 'symbol' && reIsUint.test(value))) &&
|
|
(value > -1 && value % 1 == 0 && value < length);
|
|
}
|
|
|
|
/**
|
|
* Checks if the given arguments are from an iteratee call.
|
|
*
|
|
* @private
|
|
* @param {*} value The potential iteratee value argument.
|
|
* @param {*} index The potential iteratee index or key argument.
|
|
* @param {*} object The potential iteratee object argument.
|
|
* @returns {boolean} Returns `true` if the arguments are from an iteratee call,
|
|
* else `false`.
|
|
*/
|
|
function isIterateeCall(value, index, object) {
|
|
if (!isObject(object)) {
|
|
return false;
|
|
}
|
|
var type = typeof index;
|
|
if (type == 'number'
|
|
? (isArrayLike(object) && isIndex(index, object.length))
|
|
: (type == 'string' && index in object)
|
|
) {
|
|
return eq(object[index], value);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a property name and not a property path.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @param {Object} [object] The object to query keys on.
|
|
* @returns {boolean} Returns `true` if `value` is a property name, else `false`.
|
|
*/
|
|
function isKey(value, object) {
|
|
if (isArray(value)) {
|
|
return false;
|
|
}
|
|
var type = typeof value;
|
|
if (type == 'number' || type == 'symbol' || type == 'boolean' ||
|
|
value == null || isSymbol(value)) {
|
|
return true;
|
|
}
|
|
return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
|
|
(object != null && value in Object(object));
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is suitable for use as unique object key.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is suitable, else `false`.
|
|
*/
|
|
function isKeyable(value) {
|
|
var type = typeof value;
|
|
return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
|
|
? (value !== '__proto__')
|
|
: (value === null);
|
|
}
|
|
|
|
/**
|
|
* Checks if `func` has a lazy counterpart.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to check.
|
|
* @returns {boolean} Returns `true` if `func` has a lazy counterpart,
|
|
* else `false`.
|
|
*/
|
|
function isLaziable(func) {
|
|
var funcName = getFuncName(func),
|
|
other = lodash[funcName];
|
|
|
|
if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
|
|
return false;
|
|
}
|
|
if (func === other) {
|
|
return true;
|
|
}
|
|
var data = getData(other);
|
|
return !!data && func === data[0];
|
|
}
|
|
|
|
/**
|
|
* Checks if `func` has its source masked.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to check.
|
|
* @returns {boolean} Returns `true` if `func` is masked, else `false`.
|
|
*/
|
|
function isMasked(func) {
|
|
return !!maskSrcKey && (maskSrcKey in func);
|
|
}
|
|
|
|
/**
|
|
* Checks if `func` is capable of being masked.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `func` is maskable, else `false`.
|
|
*/
|
|
var isMaskable = coreJsData ? isFunction : stubFalse;
|
|
|
|
/**
|
|
* Checks if `value` is likely a prototype object.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
|
|
*/
|
|
function isPrototype(value) {
|
|
var Ctor = value && value.constructor,
|
|
proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
|
|
|
|
return value === proto;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` if suitable for strict
|
|
* equality comparisons, else `false`.
|
|
*/
|
|
function isStrictComparable(value) {
|
|
return value === value && !isObject(value);
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `matchesProperty` for source values suitable
|
|
* for strict equality comparisons, i.e. `===`.
|
|
*
|
|
* @private
|
|
* @param {string} key The key of the property to get.
|
|
* @param {*} srcValue The value to match.
|
|
* @returns {Function} Returns the new spec function.
|
|
*/
|
|
function matchesStrictComparable(key, srcValue) {
|
|
return function(object) {
|
|
if (object == null) {
|
|
return false;
|
|
}
|
|
return object[key] === srcValue &&
|
|
(srcValue !== undefined || (key in Object(object)));
|
|
};
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.memoize` which clears the memoized function's
|
|
* cache when it exceeds `MAX_MEMOIZE_SIZE`.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to have its output memoized.
|
|
* @returns {Function} Returns the new memoized function.
|
|
*/
|
|
function memoizeCapped(func) {
|
|
var result = memoize(func, function(key) {
|
|
if (cache.size === MAX_MEMOIZE_SIZE) {
|
|
cache.clear();
|
|
}
|
|
return key;
|
|
});
|
|
|
|
var cache = result.cache;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Merges the function metadata of `source` into `data`.
|
|
*
|
|
* Merging metadata reduces the number of wrappers used to invoke a function.
|
|
* This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
|
|
* may be applied regardless of execution order. Methods like `_.ary` and
|
|
* `_.rearg` modify function arguments, making the order in which they are
|
|
* executed important, preventing the merging of metadata. However, we make
|
|
* an exception for a safe combined case where curried functions have `_.ary`
|
|
* and or `_.rearg` applied.
|
|
*
|
|
* @private
|
|
* @param {Array} data The destination metadata.
|
|
* @param {Array} source The source metadata.
|
|
* @returns {Array} Returns `data`.
|
|
*/
|
|
function mergeData(data, source) {
|
|
var bitmask = data[1],
|
|
srcBitmask = source[1],
|
|
newBitmask = bitmask | srcBitmask,
|
|
isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
|
|
|
|
var isCombo =
|
|
((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
|
|
((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
|
|
((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
|
|
|
|
// Exit early if metadata can't be merged.
|
|
if (!(isCommon || isCombo)) {
|
|
return data;
|
|
}
|
|
// Use source `thisArg` if available.
|
|
if (srcBitmask & WRAP_BIND_FLAG) {
|
|
data[2] = source[2];
|
|
// Set when currying a bound function.
|
|
newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
|
|
}
|
|
// Compose partial arguments.
|
|
var value = source[3];
|
|
if (value) {
|
|
var partials = data[3];
|
|
data[3] = partials ? composeArgs(partials, value, source[4]) : value;
|
|
data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
|
|
}
|
|
// Compose partial right arguments.
|
|
value = source[5];
|
|
if (value) {
|
|
partials = data[5];
|
|
data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
|
|
data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
|
|
}
|
|
// Use source `argPos` if available.
|
|
value = source[7];
|
|
if (value) {
|
|
data[7] = value;
|
|
}
|
|
// Use source `ary` if it's smaller.
|
|
if (srcBitmask & WRAP_ARY_FLAG) {
|
|
data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
|
|
}
|
|
// Use source `arity` if one is not provided.
|
|
if (data[9] == null) {
|
|
data[9] = source[9];
|
|
}
|
|
// Use source `func` and merge bitmasks.
|
|
data[0] = source[0];
|
|
data[1] = newBitmask;
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* This function is like
|
|
* [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
|
|
* except that it includes inherited enumerable properties.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property names.
|
|
*/
|
|
function nativeKeysIn(object) {
|
|
var result = [];
|
|
if (object != null) {
|
|
for (var key in Object(object)) {
|
|
result.push(key);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts `value` to a string using `Object.prototype.toString`.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to convert.
|
|
* @returns {string} Returns the converted string.
|
|
*/
|
|
function objectToString(value) {
|
|
return nativeObjectToString.call(value);
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseRest` which transforms the rest array.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to apply a rest parameter to.
|
|
* @param {number} [start=func.length-1] The start position of the rest parameter.
|
|
* @param {Function} transform The rest array transform.
|
|
* @returns {Function} Returns the new function.
|
|
*/
|
|
function overRest(func, start, transform) {
|
|
start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
|
|
return function() {
|
|
var args = arguments,
|
|
index = -1,
|
|
length = nativeMax(args.length - start, 0),
|
|
array = Array(length);
|
|
|
|
while (++index < length) {
|
|
array[index] = args[start + index];
|
|
}
|
|
index = -1;
|
|
var otherArgs = Array(start + 1);
|
|
while (++index < start) {
|
|
otherArgs[index] = args[index];
|
|
}
|
|
otherArgs[start] = transform(array);
|
|
return apply(func, this, otherArgs);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Gets the parent value at `path` of `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @param {Array} path The path to get the parent value of.
|
|
* @returns {*} Returns the parent value.
|
|
*/
|
|
function parent(object, path) {
|
|
return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
|
|
}
|
|
|
|
/**
|
|
* Reorder `array` according to the specified indexes where the element at
|
|
* the first index is assigned as the first element, the element at
|
|
* the second index is assigned as the second element, and so on.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to reorder.
|
|
* @param {Array} indexes The arranged array indexes.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function reorder(array, indexes) {
|
|
var arrLength = array.length,
|
|
length = nativeMin(indexes.length, arrLength),
|
|
oldArray = copyArray(array);
|
|
|
|
while (length--) {
|
|
var index = indexes[length];
|
|
array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* Gets the value at `key`, unless `key` is "__proto__" or "constructor".
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @param {string} key The key of the property to get.
|
|
* @returns {*} Returns the property value.
|
|
*/
|
|
function safeGet(object, key) {
|
|
if (key === 'constructor' && typeof object[key] === 'function') {
|
|
return;
|
|
}
|
|
|
|
if (key == '__proto__') {
|
|
return;
|
|
}
|
|
|
|
return object[key];
|
|
}
|
|
|
|
/**
|
|
* Sets metadata for `func`.
|
|
*
|
|
* **Note:** If this function becomes hot, i.e. is invoked a lot in a short
|
|
* period of time, it will trip its breaker and transition to an identity
|
|
* function to avoid garbage collection pauses in V8. See
|
|
* [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
|
|
* for more details.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to associate metadata with.
|
|
* @param {*} data The metadata.
|
|
* @returns {Function} Returns `func`.
|
|
*/
|
|
var setData = shortOut(baseSetData);
|
|
|
|
/**
|
|
* A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to delay.
|
|
* @param {number} wait The number of milliseconds to delay invocation.
|
|
* @returns {number|Object} Returns the timer id or timeout object.
|
|
*/
|
|
var setTimeout = ctxSetTimeout || function(func, wait) {
|
|
return root.setTimeout(func, wait);
|
|
};
|
|
|
|
/**
|
|
* Sets the `toString` method of `func` to return `string`.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to modify.
|
|
* @param {Function} string The `toString` result.
|
|
* @returns {Function} Returns `func`.
|
|
*/
|
|
var setToString = shortOut(baseSetToString);
|
|
|
|
/**
|
|
* Sets the `toString` method of `wrapper` to mimic the source of `reference`
|
|
* with wrapper details in a comment at the top of the source body.
|
|
*
|
|
* @private
|
|
* @param {Function} wrapper The function to modify.
|
|
* @param {Function} reference The reference function.
|
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
|
|
* @returns {Function} Returns `wrapper`.
|
|
*/
|
|
function setWrapToString(wrapper, reference, bitmask) {
|
|
var source = (reference + '');
|
|
return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
|
|
}
|
|
|
|
/**
|
|
* Creates a function that'll short out and invoke `identity` instead
|
|
* of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
|
|
* milliseconds.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to restrict.
|
|
* @returns {Function} Returns the new shortable function.
|
|
*/
|
|
function shortOut(func) {
|
|
var count = 0,
|
|
lastCalled = 0;
|
|
|
|
return function() {
|
|
var stamp = nativeNow(),
|
|
remaining = HOT_SPAN - (stamp - lastCalled);
|
|
|
|
lastCalled = stamp;
|
|
if (remaining > 0) {
|
|
if (++count >= HOT_COUNT) {
|
|
return arguments[0];
|
|
}
|
|
} else {
|
|
count = 0;
|
|
}
|
|
return func.apply(undefined, arguments);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.shuffle` which mutates and sets the size of `array`.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to shuffle.
|
|
* @param {number} [size=array.length] The size of `array`.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function shuffleSelf(array, size) {
|
|
var index = -1,
|
|
length = array.length,
|
|
lastIndex = length - 1;
|
|
|
|
size = size === undefined ? length : size;
|
|
while (++index < size) {
|
|
var rand = baseRandom(index, lastIndex),
|
|
value = array[rand];
|
|
|
|
array[rand] = array[index];
|
|
array[index] = value;
|
|
}
|
|
array.length = size;
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* Converts `string` to a property path array.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to convert.
|
|
* @returns {Array} Returns the property path array.
|
|
*/
|
|
var stringToPath = memoizeCapped(function(string) {
|
|
var result = [];
|
|
if (string.charCodeAt(0) === 46 /* . */) {
|
|
result.push('');
|
|
}
|
|
string.replace(rePropName, function(match, number, quote, subString) {
|
|
result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));
|
|
});
|
|
return result;
|
|
});
|
|
|
|
/**
|
|
* Converts `value` to a string key if it's not a string or symbol.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to inspect.
|
|
* @returns {string|symbol} Returns the key.
|
|
*/
|
|
function toKey(value) {
|
|
if (typeof value == 'string' || isSymbol(value)) {
|
|
return value;
|
|
}
|
|
var result = (value + '');
|
|
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
|
|
}
|
|
|
|
/**
|
|
* Converts `func` to its source code.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to convert.
|
|
* @returns {string} Returns the source code.
|
|
*/
|
|
function toSource(func) {
|
|
if (func != null) {
|
|
try {
|
|
return funcToString.call(func);
|
|
} catch (e) {}
|
|
try {
|
|
return (func + '');
|
|
} catch (e) {}
|
|
}
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Updates wrapper `details` based on `bitmask` flags.
|
|
*
|
|
* @private
|
|
* @returns {Array} details The details to modify.
|
|
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
|
|
* @returns {Array} Returns `details`.
|
|
*/
|
|
function updateWrapDetails(details, bitmask) {
|
|
arrayEach(wrapFlags, function(pair) {
|
|
var value = '_.' + pair[0];
|
|
if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
|
|
details.push(value);
|
|
}
|
|
});
|
|
return details.sort();
|
|
}
|
|
|
|
/**
|
|
* Creates a clone of `wrapper`.
|
|
*
|
|
* @private
|
|
* @param {Object} wrapper The wrapper to clone.
|
|
* @returns {Object} Returns the cloned wrapper.
|
|
*/
|
|
function wrapperClone(wrapper) {
|
|
if (wrapper instanceof LazyWrapper) {
|
|
return wrapper.clone();
|
|
}
|
|
var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
|
|
result.__actions__ = copyArray(wrapper.__actions__);
|
|
result.__index__ = wrapper.__index__;
|
|
result.__values__ = wrapper.__values__;
|
|
return result;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates an array of elements split into groups the length of `size`.
|
|
* If `array` can't be split evenly, the final chunk will be the remaining
|
|
* elements.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to process.
|
|
* @param {number} [size=1] The length of each chunk
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Array} Returns the new array of chunks.
|
|
* @example
|
|
*
|
|
* _.chunk(['a', 'b', 'c', 'd'], 2);
|
|
* // => [['a', 'b'], ['c', 'd']]
|
|
*
|
|
* _.chunk(['a', 'b', 'c', 'd'], 3);
|
|
* // => [['a', 'b', 'c'], ['d']]
|
|
*/
|
|
function chunk(array, size, guard) {
|
|
if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
|
|
size = 1;
|
|
} else {
|
|
size = nativeMax(toInteger(size), 0);
|
|
}
|
|
var length = array == null ? 0 : array.length;
|
|
if (!length || size < 1) {
|
|
return [];
|
|
}
|
|
var index = 0,
|
|
resIndex = 0,
|
|
result = Array(nativeCeil(length / size));
|
|
|
|
while (index < length) {
|
|
result[resIndex++] = baseSlice(array, index, (index += size));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates an array with all falsey values removed. The values `false`, `null`,
|
|
* `0`, `""`, `undefined`, and `NaN` are falsey.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {Array} array The array to compact.
|
|
* @returns {Array} Returns the new array of filtered values.
|
|
* @example
|
|
*
|
|
* _.compact([0, 1, false, 2, '', 3]);
|
|
* // => [1, 2, 3]
|
|
*/
|
|
function compact(array) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length,
|
|
resIndex = 0,
|
|
result = [];
|
|
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
if (value) {
|
|
result[resIndex++] = value;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates a new array concatenating `array` with any additional arrays
|
|
* and/or values.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to concatenate.
|
|
* @param {...*} [values] The values to concatenate.
|
|
* @returns {Array} Returns the new concatenated array.
|
|
* @example
|
|
*
|
|
* var array = [1];
|
|
* var other = _.concat(array, 2, [3], [[4]]);
|
|
*
|
|
* console.log(other);
|
|
* // => [1, 2, 3, [4]]
|
|
*
|
|
* console.log(array);
|
|
* // => [1]
|
|
*/
|
|
function concat() {
|
|
var length = arguments.length;
|
|
if (!length) {
|
|
return [];
|
|
}
|
|
var args = Array(length - 1),
|
|
array = arguments[0],
|
|
index = length;
|
|
|
|
while (index--) {
|
|
args[index - 1] = arguments[index];
|
|
}
|
|
return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
|
|
}
|
|
|
|
/**
|
|
* Creates an array of `array` values not included in the other given arrays
|
|
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
* for equality comparisons. The order and references of result values are
|
|
* determined by the first array.
|
|
*
|
|
* **Note:** Unlike `_.pullAll`, this method returns a new array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {...Array} [values] The values to exclude.
|
|
* @returns {Array} Returns the new array of filtered values.
|
|
* @see _.without, _.xor
|
|
* @example
|
|
*
|
|
* _.difference([2, 1], [2, 3]);
|
|
* // => [1]
|
|
*/
|
|
var difference = baseRest(function(array, values) {
|
|
return isArrayLikeObject(array)
|
|
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
|
|
: [];
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.difference` except that it accepts `iteratee` which
|
|
* is invoked for each element of `array` and `values` to generate the criterion
|
|
* by which they're compared. The order and references of result values are
|
|
* determined by the first array. The iteratee is invoked with one argument:
|
|
* (value).
|
|
*
|
|
* **Note:** Unlike `_.pullAllBy`, this method returns a new array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {...Array} [values] The values to exclude.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {Array} Returns the new array of filtered values.
|
|
* @example
|
|
*
|
|
* _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
|
|
* // => [1.2]
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
|
|
* // => [{ 'x': 2 }]
|
|
*/
|
|
var differenceBy = baseRest(function(array, values) {
|
|
var iteratee = last(values);
|
|
if (isArrayLikeObject(iteratee)) {
|
|
iteratee = undefined;
|
|
}
|
|
return isArrayLikeObject(array)
|
|
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
|
|
: [];
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.difference` except that it accepts `comparator`
|
|
* which is invoked to compare elements of `array` to `values`. The order and
|
|
* references of result values are determined by the first array. The comparator
|
|
* is invoked with two arguments: (arrVal, othVal).
|
|
*
|
|
* **Note:** Unlike `_.pullAllWith`, this method returns a new array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {...Array} [values] The values to exclude.
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
* @returns {Array} Returns the new array of filtered values.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
|
|
*
|
|
* _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
|
|
* // => [{ 'x': 2, 'y': 1 }]
|
|
*/
|
|
var differenceWith = baseRest(function(array, values) {
|
|
var comparator = last(values);
|
|
if (isArrayLikeObject(comparator)) {
|
|
comparator = undefined;
|
|
}
|
|
return isArrayLikeObject(array)
|
|
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
|
|
: [];
|
|
});
|
|
|
|
/**
|
|
* Creates a slice of `array` with `n` elements dropped from the beginning.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.5.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @param {number} [n=1] The number of elements to drop.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
* @example
|
|
*
|
|
* _.drop([1, 2, 3]);
|
|
* // => [2, 3]
|
|
*
|
|
* _.drop([1, 2, 3], 2);
|
|
* // => [3]
|
|
*
|
|
* _.drop([1, 2, 3], 5);
|
|
* // => []
|
|
*
|
|
* _.drop([1, 2, 3], 0);
|
|
* // => [1, 2, 3]
|
|
*/
|
|
function drop(array, n, guard) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (!length) {
|
|
return [];
|
|
}
|
|
n = (guard || n === undefined) ? 1 : toInteger(n);
|
|
return baseSlice(array, n < 0 ? 0 : n, length);
|
|
}
|
|
|
|
/**
|
|
* Creates a slice of `array` with `n` elements dropped from the end.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @param {number} [n=1] The number of elements to drop.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
* @example
|
|
*
|
|
* _.dropRight([1, 2, 3]);
|
|
* // => [1, 2]
|
|
*
|
|
* _.dropRight([1, 2, 3], 2);
|
|
* // => [1]
|
|
*
|
|
* _.dropRight([1, 2, 3], 5);
|
|
* // => []
|
|
*
|
|
* _.dropRight([1, 2, 3], 0);
|
|
* // => [1, 2, 3]
|
|
*/
|
|
function dropRight(array, n, guard) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (!length) {
|
|
return [];
|
|
}
|
|
n = (guard || n === undefined) ? 1 : toInteger(n);
|
|
n = length - n;
|
|
return baseSlice(array, 0, n < 0 ? 0 : n);
|
|
}
|
|
|
|
/**
|
|
* Creates a slice of `array` excluding elements dropped from the end.
|
|
* Elements are dropped until `predicate` returns falsey. The predicate is
|
|
* invoked with three arguments: (value, index, array).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'active': true },
|
|
* { 'user': 'fred', 'active': false },
|
|
* { 'user': 'pebbles', 'active': false }
|
|
* ];
|
|
*
|
|
* _.dropRightWhile(users, function(o) { return !o.active; });
|
|
* // => objects for ['barney']
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
|
|
* // => objects for ['barney', 'fred']
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.dropRightWhile(users, ['active', false]);
|
|
* // => objects for ['barney']
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.dropRightWhile(users, 'active');
|
|
* // => objects for ['barney', 'fred', 'pebbles']
|
|
*/
|
|
function dropRightWhile(array, predicate) {
|
|
return (array && array.length)
|
|
? baseWhile(array, getIteratee(predicate, 3), true, true)
|
|
: [];
|
|
}
|
|
|
|
/**
|
|
* Creates a slice of `array` excluding elements dropped from the beginning.
|
|
* Elements are dropped until `predicate` returns falsey. The predicate is
|
|
* invoked with three arguments: (value, index, array).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'active': false },
|
|
* { 'user': 'fred', 'active': false },
|
|
* { 'user': 'pebbles', 'active': true }
|
|
* ];
|
|
*
|
|
* _.dropWhile(users, function(o) { return !o.active; });
|
|
* // => objects for ['pebbles']
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.dropWhile(users, { 'user': 'barney', 'active': false });
|
|
* // => objects for ['fred', 'pebbles']
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.dropWhile(users, ['active', false]);
|
|
* // => objects for ['pebbles']
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.dropWhile(users, 'active');
|
|
* // => objects for ['barney', 'fred', 'pebbles']
|
|
*/
|
|
function dropWhile(array, predicate) {
|
|
return (array && array.length)
|
|
? baseWhile(array, getIteratee(predicate, 3), true)
|
|
: [];
|
|
}
|
|
|
|
/**
|
|
* Fills elements of `array` with `value` from `start` up to, but not
|
|
* including, `end`.
|
|
*
|
|
* **Note:** This method mutates `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.2.0
|
|
* @category Array
|
|
* @param {Array} array The array to fill.
|
|
* @param {*} value The value to fill `array` with.
|
|
* @param {number} [start=0] The start position.
|
|
* @param {number} [end=array.length] The end position.
|
|
* @returns {Array} Returns `array`.
|
|
* @example
|
|
*
|
|
* var array = [1, 2, 3];
|
|
*
|
|
* _.fill(array, 'a');
|
|
* console.log(array);
|
|
* // => ['a', 'a', 'a']
|
|
*
|
|
* _.fill(Array(3), 2);
|
|
* // => [2, 2, 2]
|
|
*
|
|
* _.fill([4, 6, 8, 10], '*', 1, 3);
|
|
* // => [4, '*', '*', 10]
|
|
*/
|
|
function fill(array, value, start, end) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (!length) {
|
|
return [];
|
|
}
|
|
if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
|
|
start = 0;
|
|
end = length;
|
|
}
|
|
return baseFill(array, value, start, end);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.find` except that it returns the index of the first
|
|
* element `predicate` returns truthy for instead of the element itself.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 1.1.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @param {number} [fromIndex=0] The index to search from.
|
|
* @returns {number} Returns the index of the found element, else `-1`.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'active': false },
|
|
* { 'user': 'fred', 'active': false },
|
|
* { 'user': 'pebbles', 'active': true }
|
|
* ];
|
|
*
|
|
* _.findIndex(users, function(o) { return o.user == 'barney'; });
|
|
* // => 0
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.findIndex(users, { 'user': 'fred', 'active': false });
|
|
* // => 1
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.findIndex(users, ['active', false]);
|
|
* // => 0
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.findIndex(users, 'active');
|
|
* // => 2
|
|
*/
|
|
function findIndex(array, predicate, fromIndex) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (!length) {
|
|
return -1;
|
|
}
|
|
var index = fromIndex == null ? 0 : toInteger(fromIndex);
|
|
if (index < 0) {
|
|
index = nativeMax(length + index, 0);
|
|
}
|
|
return baseFindIndex(array, getIteratee(predicate, 3), index);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.findIndex` except that it iterates over elements
|
|
* of `collection` from right to left.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @param {number} [fromIndex=array.length-1] The index to search from.
|
|
* @returns {number} Returns the index of the found element, else `-1`.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'active': true },
|
|
* { 'user': 'fred', 'active': false },
|
|
* { 'user': 'pebbles', 'active': false }
|
|
* ];
|
|
*
|
|
* _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
|
|
* // => 2
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.findLastIndex(users, { 'user': 'barney', 'active': true });
|
|
* // => 0
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.findLastIndex(users, ['active', false]);
|
|
* // => 2
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.findLastIndex(users, 'active');
|
|
* // => 0
|
|
*/
|
|
function findLastIndex(array, predicate, fromIndex) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (!length) {
|
|
return -1;
|
|
}
|
|
var index = length - 1;
|
|
if (fromIndex !== undefined) {
|
|
index = toInteger(fromIndex);
|
|
index = fromIndex < 0
|
|
? nativeMax(length + index, 0)
|
|
: nativeMin(index, length - 1);
|
|
}
|
|
return baseFindIndex(array, getIteratee(predicate, 3), index, true);
|
|
}
|
|
|
|
/**
|
|
* Flattens `array` a single level deep.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {Array} array The array to flatten.
|
|
* @returns {Array} Returns the new flattened array.
|
|
* @example
|
|
*
|
|
* _.flatten([1, [2, [3, [4]], 5]]);
|
|
* // => [1, 2, [3, [4]], 5]
|
|
*/
|
|
function flatten(array) {
|
|
var length = array == null ? 0 : array.length;
|
|
return length ? baseFlatten(array, 1) : [];
|
|
}
|
|
|
|
/**
|
|
* Recursively flattens `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to flatten.
|
|
* @returns {Array} Returns the new flattened array.
|
|
* @example
|
|
*
|
|
* _.flattenDeep([1, [2, [3, [4]], 5]]);
|
|
* // => [1, 2, 3, 4, 5]
|
|
*/
|
|
function flattenDeep(array) {
|
|
var length = array == null ? 0 : array.length;
|
|
return length ? baseFlatten(array, INFINITY) : [];
|
|
}
|
|
|
|
/**
|
|
* Recursively flatten `array` up to `depth` times.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.4.0
|
|
* @category Array
|
|
* @param {Array} array The array to flatten.
|
|
* @param {number} [depth=1] The maximum recursion depth.
|
|
* @returns {Array} Returns the new flattened array.
|
|
* @example
|
|
*
|
|
* var array = [1, [2, [3, [4]], 5]];
|
|
*
|
|
* _.flattenDepth(array, 1);
|
|
* // => [1, 2, [3, [4]], 5]
|
|
*
|
|
* _.flattenDepth(array, 2);
|
|
* // => [1, 2, 3, [4], 5]
|
|
*/
|
|
function flattenDepth(array, depth) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (!length) {
|
|
return [];
|
|
}
|
|
depth = depth === undefined ? 1 : toInteger(depth);
|
|
return baseFlatten(array, depth);
|
|
}
|
|
|
|
/**
|
|
* The inverse of `_.toPairs`; this method returns an object composed
|
|
* from key-value `pairs`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} pairs The key-value pairs.
|
|
* @returns {Object} Returns the new object.
|
|
* @example
|
|
*
|
|
* _.fromPairs([['a', 1], ['b', 2]]);
|
|
* // => { 'a': 1, 'b': 2 }
|
|
*/
|
|
function fromPairs(pairs) {
|
|
var index = -1,
|
|
length = pairs == null ? 0 : pairs.length,
|
|
result = {};
|
|
|
|
while (++index < length) {
|
|
var pair = pairs[index];
|
|
result[pair[0]] = pair[1];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the first element of `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @alias first
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @returns {*} Returns the first element of `array`.
|
|
* @example
|
|
*
|
|
* _.head([1, 2, 3]);
|
|
* // => 1
|
|
*
|
|
* _.head([]);
|
|
* // => undefined
|
|
*/
|
|
function head(array) {
|
|
return (array && array.length) ? array[0] : undefined;
|
|
}
|
|
|
|
/**
|
|
* Gets the index at which the first occurrence of `value` is found in `array`
|
|
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
* for equality comparisons. If `fromIndex` is negative, it's used as the
|
|
* offset from the end of `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {*} value The value to search for.
|
|
* @param {number} [fromIndex=0] The index to search from.
|
|
* @returns {number} Returns the index of the matched value, else `-1`.
|
|
* @example
|
|
*
|
|
* _.indexOf([1, 2, 1, 2], 2);
|
|
* // => 1
|
|
*
|
|
* // Search from the `fromIndex`.
|
|
* _.indexOf([1, 2, 1, 2], 2, 2);
|
|
* // => 3
|
|
*/
|
|
function indexOf(array, value, fromIndex) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (!length) {
|
|
return -1;
|
|
}
|
|
var index = fromIndex == null ? 0 : toInteger(fromIndex);
|
|
if (index < 0) {
|
|
index = nativeMax(length + index, 0);
|
|
}
|
|
return baseIndexOf(array, value, index);
|
|
}
|
|
|
|
/**
|
|
* Gets all but the last element of `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
* @example
|
|
*
|
|
* _.initial([1, 2, 3]);
|
|
* // => [1, 2]
|
|
*/
|
|
function initial(array) {
|
|
var length = array == null ? 0 : array.length;
|
|
return length ? baseSlice(array, 0, -1) : [];
|
|
}
|
|
|
|
/**
|
|
* Creates an array of unique values that are included in all given arrays
|
|
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
* for equality comparisons. The order and references of result values are
|
|
* determined by the first array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {...Array} [arrays] The arrays to inspect.
|
|
* @returns {Array} Returns the new array of intersecting values.
|
|
* @example
|
|
*
|
|
* _.intersection([2, 1], [2, 3]);
|
|
* // => [2]
|
|
*/
|
|
var intersection = baseRest(function(arrays) {
|
|
var mapped = arrayMap(arrays, castArrayLikeObject);
|
|
return (mapped.length && mapped[0] === arrays[0])
|
|
? baseIntersection(mapped)
|
|
: [];
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.intersection` except that it accepts `iteratee`
|
|
* which is invoked for each element of each `arrays` to generate the criterion
|
|
* by which they're compared. The order and references of result values are
|
|
* determined by the first array. The iteratee is invoked with one argument:
|
|
* (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {...Array} [arrays] The arrays to inspect.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {Array} Returns the new array of intersecting values.
|
|
* @example
|
|
*
|
|
* _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
|
|
* // => [2.1]
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
|
|
* // => [{ 'x': 1 }]
|
|
*/
|
|
var intersectionBy = baseRest(function(arrays) {
|
|
var iteratee = last(arrays),
|
|
mapped = arrayMap(arrays, castArrayLikeObject);
|
|
|
|
if (iteratee === last(mapped)) {
|
|
iteratee = undefined;
|
|
} else {
|
|
mapped.pop();
|
|
}
|
|
return (mapped.length && mapped[0] === arrays[0])
|
|
? baseIntersection(mapped, getIteratee(iteratee, 2))
|
|
: [];
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.intersection` except that it accepts `comparator`
|
|
* which is invoked to compare elements of `arrays`. The order and references
|
|
* of result values are determined by the first array. The comparator is
|
|
* invoked with two arguments: (arrVal, othVal).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {...Array} [arrays] The arrays to inspect.
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
* @returns {Array} Returns the new array of intersecting values.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
|
|
* var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
|
|
*
|
|
* _.intersectionWith(objects, others, _.isEqual);
|
|
* // => [{ 'x': 1, 'y': 2 }]
|
|
*/
|
|
var intersectionWith = baseRest(function(arrays) {
|
|
var comparator = last(arrays),
|
|
mapped = arrayMap(arrays, castArrayLikeObject);
|
|
|
|
comparator = typeof comparator == 'function' ? comparator : undefined;
|
|
if (comparator) {
|
|
mapped.pop();
|
|
}
|
|
return (mapped.length && mapped[0] === arrays[0])
|
|
? baseIntersection(mapped, undefined, comparator)
|
|
: [];
|
|
});
|
|
|
|
/**
|
|
* Converts all elements in `array` into a string separated by `separator`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to convert.
|
|
* @param {string} [separator=','] The element separator.
|
|
* @returns {string} Returns the joined string.
|
|
* @example
|
|
*
|
|
* _.join(['a', 'b', 'c'], '~');
|
|
* // => 'a~b~c'
|
|
*/
|
|
function join(array, separator) {
|
|
return array == null ? '' : nativeJoin.call(array, separator);
|
|
}
|
|
|
|
/**
|
|
* Gets the last element of `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @returns {*} Returns the last element of `array`.
|
|
* @example
|
|
*
|
|
* _.last([1, 2, 3]);
|
|
* // => 3
|
|
*/
|
|
function last(array) {
|
|
var length = array == null ? 0 : array.length;
|
|
return length ? array[length - 1] : undefined;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.indexOf` except that it iterates over elements of
|
|
* `array` from right to left.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {*} value The value to search for.
|
|
* @param {number} [fromIndex=array.length-1] The index to search from.
|
|
* @returns {number} Returns the index of the matched value, else `-1`.
|
|
* @example
|
|
*
|
|
* _.lastIndexOf([1, 2, 1, 2], 2);
|
|
* // => 3
|
|
*
|
|
* // Search from the `fromIndex`.
|
|
* _.lastIndexOf([1, 2, 1, 2], 2, 2);
|
|
* // => 1
|
|
*/
|
|
function lastIndexOf(array, value, fromIndex) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (!length) {
|
|
return -1;
|
|
}
|
|
var index = length;
|
|
if (fromIndex !== undefined) {
|
|
index = toInteger(fromIndex);
|
|
index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
|
|
}
|
|
return value === value
|
|
? strictLastIndexOf(array, value, index)
|
|
: baseFindIndex(array, baseIsNaN, index, true);
|
|
}
|
|
|
|
/**
|
|
* Gets the element at index `n` of `array`. If `n` is negative, the nth
|
|
* element from the end is returned.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.11.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @param {number} [n=0] The index of the element to return.
|
|
* @returns {*} Returns the nth element of `array`.
|
|
* @example
|
|
*
|
|
* var array = ['a', 'b', 'c', 'd'];
|
|
*
|
|
* _.nth(array, 1);
|
|
* // => 'b'
|
|
*
|
|
* _.nth(array, -2);
|
|
* // => 'c';
|
|
*/
|
|
function nth(array, n) {
|
|
return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;
|
|
}
|
|
|
|
/**
|
|
* Removes all given values from `array` using
|
|
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
* for equality comparisons.
|
|
*
|
|
* **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
|
|
* to remove elements from an array by predicate.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to modify.
|
|
* @param {...*} [values] The values to remove.
|
|
* @returns {Array} Returns `array`.
|
|
* @example
|
|
*
|
|
* var array = ['a', 'b', 'c', 'a', 'b', 'c'];
|
|
*
|
|
* _.pull(array, 'a', 'c');
|
|
* console.log(array);
|
|
* // => ['b', 'b']
|
|
*/
|
|
var pull = baseRest(pullAll);
|
|
|
|
/**
|
|
* This method is like `_.pull` except that it accepts an array of values to remove.
|
|
*
|
|
* **Note:** Unlike `_.difference`, this method mutates `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to modify.
|
|
* @param {Array} values The values to remove.
|
|
* @returns {Array} Returns `array`.
|
|
* @example
|
|
*
|
|
* var array = ['a', 'b', 'c', 'a', 'b', 'c'];
|
|
*
|
|
* _.pullAll(array, ['a', 'c']);
|
|
* console.log(array);
|
|
* // => ['b', 'b']
|
|
*/
|
|
function pullAll(array, values) {
|
|
return (array && array.length && values && values.length)
|
|
? basePullAll(array, values)
|
|
: array;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.pullAll` except that it accepts `iteratee` which is
|
|
* invoked for each element of `array` and `values` to generate the criterion
|
|
* by which they're compared. The iteratee is invoked with one argument: (value).
|
|
*
|
|
* **Note:** Unlike `_.differenceBy`, this method mutates `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to modify.
|
|
* @param {Array} values The values to remove.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {Array} Returns `array`.
|
|
* @example
|
|
*
|
|
* var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
|
|
*
|
|
* _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
|
|
* console.log(array);
|
|
* // => [{ 'x': 2 }]
|
|
*/
|
|
function pullAllBy(array, values, iteratee) {
|
|
return (array && array.length && values && values.length)
|
|
? basePullAll(array, values, getIteratee(iteratee, 2))
|
|
: array;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.pullAll` except that it accepts `comparator` which
|
|
* is invoked to compare elements of `array` to `values`. The comparator is
|
|
* invoked with two arguments: (arrVal, othVal).
|
|
*
|
|
* **Note:** Unlike `_.differenceWith`, this method mutates `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.6.0
|
|
* @category Array
|
|
* @param {Array} array The array to modify.
|
|
* @param {Array} values The values to remove.
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
* @returns {Array} Returns `array`.
|
|
* @example
|
|
*
|
|
* var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
|
|
*
|
|
* _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
|
|
* console.log(array);
|
|
* // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
|
|
*/
|
|
function pullAllWith(array, values, comparator) {
|
|
return (array && array.length && values && values.length)
|
|
? basePullAll(array, values, undefined, comparator)
|
|
: array;
|
|
}
|
|
|
|
/**
|
|
* Removes elements from `array` corresponding to `indexes` and returns an
|
|
* array of removed elements.
|
|
*
|
|
* **Note:** Unlike `_.at`, this method mutates `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to modify.
|
|
* @param {...(number|number[])} [indexes] The indexes of elements to remove.
|
|
* @returns {Array} Returns the new array of removed elements.
|
|
* @example
|
|
*
|
|
* var array = ['a', 'b', 'c', 'd'];
|
|
* var pulled = _.pullAt(array, [1, 3]);
|
|
*
|
|
* console.log(array);
|
|
* // => ['a', 'c']
|
|
*
|
|
* console.log(pulled);
|
|
* // => ['b', 'd']
|
|
*/
|
|
var pullAt = flatRest(function(array, indexes) {
|
|
var length = array == null ? 0 : array.length,
|
|
result = baseAt(array, indexes);
|
|
|
|
basePullAt(array, arrayMap(indexes, function(index) {
|
|
return isIndex(index, length) ? +index : index;
|
|
}).sort(compareAscending));
|
|
|
|
return result;
|
|
});
|
|
|
|
/**
|
|
* Removes all elements from `array` that `predicate` returns truthy for
|
|
* and returns an array of the removed elements. The predicate is invoked
|
|
* with three arguments: (value, index, array).
|
|
*
|
|
* **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
|
|
* to pull elements from an array by value.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to modify.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the new array of removed elements.
|
|
* @example
|
|
*
|
|
* var array = [1, 2, 3, 4];
|
|
* var evens = _.remove(array, function(n) {
|
|
* return n % 2 == 0;
|
|
* });
|
|
*
|
|
* console.log(array);
|
|
* // => [1, 3]
|
|
*
|
|
* console.log(evens);
|
|
* // => [2, 4]
|
|
*/
|
|
function remove(array, predicate) {
|
|
var result = [];
|
|
if (!(array && array.length)) {
|
|
return result;
|
|
}
|
|
var index = -1,
|
|
indexes = [],
|
|
length = array.length;
|
|
|
|
predicate = getIteratee(predicate, 3);
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
if (predicate(value, index, array)) {
|
|
result.push(value);
|
|
indexes.push(index);
|
|
}
|
|
}
|
|
basePullAt(array, indexes);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Reverses `array` so that the first element becomes the last, the second
|
|
* element becomes the second to last, and so on.
|
|
*
|
|
* **Note:** This method mutates `array` and is based on
|
|
* [`Array#reverse`](https://mdn.io/Array/reverse).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to modify.
|
|
* @returns {Array} Returns `array`.
|
|
* @example
|
|
*
|
|
* var array = [1, 2, 3];
|
|
*
|
|
* _.reverse(array);
|
|
* // => [3, 2, 1]
|
|
*
|
|
* console.log(array);
|
|
* // => [3, 2, 1]
|
|
*/
|
|
function reverse(array) {
|
|
return array == null ? array : nativeReverse.call(array);
|
|
}
|
|
|
|
/**
|
|
* Creates a slice of `array` from `start` up to, but not including, `end`.
|
|
*
|
|
* **Note:** This method is used instead of
|
|
* [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
|
|
* returned.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to slice.
|
|
* @param {number} [start=0] The start position.
|
|
* @param {number} [end=array.length] The end position.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
*/
|
|
function slice(array, start, end) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (!length) {
|
|
return [];
|
|
}
|
|
if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
|
|
start = 0;
|
|
end = length;
|
|
}
|
|
else {
|
|
start = start == null ? 0 : toInteger(start);
|
|
end = end === undefined ? length : toInteger(end);
|
|
}
|
|
return baseSlice(array, start, end);
|
|
}
|
|
|
|
/**
|
|
* Uses a binary search to determine the lowest index at which `value`
|
|
* should be inserted into `array` in order to maintain its sort order.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {Array} array The sorted array to inspect.
|
|
* @param {*} value The value to evaluate.
|
|
* @returns {number} Returns the index at which `value` should be inserted
|
|
* into `array`.
|
|
* @example
|
|
*
|
|
* _.sortedIndex([30, 50], 40);
|
|
* // => 1
|
|
*/
|
|
function sortedIndex(array, value) {
|
|
return baseSortedIndex(array, value);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.sortedIndex` except that it accepts `iteratee`
|
|
* which is invoked for `value` and each element of `array` to compute their
|
|
* sort ranking. The iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The sorted array to inspect.
|
|
* @param {*} value The value to evaluate.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {number} Returns the index at which `value` should be inserted
|
|
* into `array`.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'x': 4 }, { 'x': 5 }];
|
|
*
|
|
* _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
|
|
* // => 0
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.sortedIndexBy(objects, { 'x': 4 }, 'x');
|
|
* // => 0
|
|
*/
|
|
function sortedIndexBy(array, value, iteratee) {
|
|
return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.indexOf` except that it performs a binary
|
|
* search on a sorted `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {*} value The value to search for.
|
|
* @returns {number} Returns the index of the matched value, else `-1`.
|
|
* @example
|
|
*
|
|
* _.sortedIndexOf([4, 5, 5, 5, 6], 5);
|
|
* // => 1
|
|
*/
|
|
function sortedIndexOf(array, value) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (length) {
|
|
var index = baseSortedIndex(array, value);
|
|
if (index < length && eq(array[index], value)) {
|
|
return index;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.sortedIndex` except that it returns the highest
|
|
* index at which `value` should be inserted into `array` in order to
|
|
* maintain its sort order.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Array
|
|
* @param {Array} array The sorted array to inspect.
|
|
* @param {*} value The value to evaluate.
|
|
* @returns {number} Returns the index at which `value` should be inserted
|
|
* into `array`.
|
|
* @example
|
|
*
|
|
* _.sortedLastIndex([4, 5, 5, 5, 6], 5);
|
|
* // => 4
|
|
*/
|
|
function sortedLastIndex(array, value) {
|
|
return baseSortedIndex(array, value, true);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.sortedLastIndex` except that it accepts `iteratee`
|
|
* which is invoked for `value` and each element of `array` to compute their
|
|
* sort ranking. The iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The sorted array to inspect.
|
|
* @param {*} value The value to evaluate.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {number} Returns the index at which `value` should be inserted
|
|
* into `array`.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'x': 4 }, { 'x': 5 }];
|
|
*
|
|
* _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
|
|
* // => 1
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
|
|
* // => 1
|
|
*/
|
|
function sortedLastIndexBy(array, value, iteratee) {
|
|
return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.lastIndexOf` except that it performs a binary
|
|
* search on a sorted `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {*} value The value to search for.
|
|
* @returns {number} Returns the index of the matched value, else `-1`.
|
|
* @example
|
|
*
|
|
* _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
|
|
* // => 3
|
|
*/
|
|
function sortedLastIndexOf(array, value) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (length) {
|
|
var index = baseSortedIndex(array, value, true) - 1;
|
|
if (eq(array[index], value)) {
|
|
return index;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.uniq` except that it's designed and optimized
|
|
* for sorted arrays.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @returns {Array} Returns the new duplicate free array.
|
|
* @example
|
|
*
|
|
* _.sortedUniq([1, 1, 2]);
|
|
* // => [1, 2]
|
|
*/
|
|
function sortedUniq(array) {
|
|
return (array && array.length)
|
|
? baseSortedUniq(array)
|
|
: [];
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.uniqBy` except that it's designed and optimized
|
|
* for sorted arrays.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {Function} [iteratee] The iteratee invoked per element.
|
|
* @returns {Array} Returns the new duplicate free array.
|
|
* @example
|
|
*
|
|
* _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
|
|
* // => [1.1, 2.3]
|
|
*/
|
|
function sortedUniqBy(array, iteratee) {
|
|
return (array && array.length)
|
|
? baseSortedUniq(array, getIteratee(iteratee, 2))
|
|
: [];
|
|
}
|
|
|
|
/**
|
|
* Gets all but the first element of `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
* @example
|
|
*
|
|
* _.tail([1, 2, 3]);
|
|
* // => [2, 3]
|
|
*/
|
|
function tail(array) {
|
|
var length = array == null ? 0 : array.length;
|
|
return length ? baseSlice(array, 1, length) : [];
|
|
}
|
|
|
|
/**
|
|
* Creates a slice of `array` with `n` elements taken from the beginning.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @param {number} [n=1] The number of elements to take.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
* @example
|
|
*
|
|
* _.take([1, 2, 3]);
|
|
* // => [1]
|
|
*
|
|
* _.take([1, 2, 3], 2);
|
|
* // => [1, 2]
|
|
*
|
|
* _.take([1, 2, 3], 5);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* _.take([1, 2, 3], 0);
|
|
* // => []
|
|
*/
|
|
function take(array, n, guard) {
|
|
if (!(array && array.length)) {
|
|
return [];
|
|
}
|
|
n = (guard || n === undefined) ? 1 : toInteger(n);
|
|
return baseSlice(array, 0, n < 0 ? 0 : n);
|
|
}
|
|
|
|
/**
|
|
* Creates a slice of `array` with `n` elements taken from the end.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @param {number} [n=1] The number of elements to take.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
* @example
|
|
*
|
|
* _.takeRight([1, 2, 3]);
|
|
* // => [3]
|
|
*
|
|
* _.takeRight([1, 2, 3], 2);
|
|
* // => [2, 3]
|
|
*
|
|
* _.takeRight([1, 2, 3], 5);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* _.takeRight([1, 2, 3], 0);
|
|
* // => []
|
|
*/
|
|
function takeRight(array, n, guard) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (!length) {
|
|
return [];
|
|
}
|
|
n = (guard || n === undefined) ? 1 : toInteger(n);
|
|
n = length - n;
|
|
return baseSlice(array, n < 0 ? 0 : n, length);
|
|
}
|
|
|
|
/**
|
|
* Creates a slice of `array` with elements taken from the end. Elements are
|
|
* taken until `predicate` returns falsey. The predicate is invoked with
|
|
* three arguments: (value, index, array).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'active': true },
|
|
* { 'user': 'fred', 'active': false },
|
|
* { 'user': 'pebbles', 'active': false }
|
|
* ];
|
|
*
|
|
* _.takeRightWhile(users, function(o) { return !o.active; });
|
|
* // => objects for ['fred', 'pebbles']
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
|
|
* // => objects for ['pebbles']
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.takeRightWhile(users, ['active', false]);
|
|
* // => objects for ['fred', 'pebbles']
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.takeRightWhile(users, 'active');
|
|
* // => []
|
|
*/
|
|
function takeRightWhile(array, predicate) {
|
|
return (array && array.length)
|
|
? baseWhile(array, getIteratee(predicate, 3), false, true)
|
|
: [];
|
|
}
|
|
|
|
/**
|
|
* Creates a slice of `array` with elements taken from the beginning. Elements
|
|
* are taken until `predicate` returns falsey. The predicate is invoked with
|
|
* three arguments: (value, index, array).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to query.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the slice of `array`.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'active': false },
|
|
* { 'user': 'fred', 'active': false },
|
|
* { 'user': 'pebbles', 'active': true }
|
|
* ];
|
|
*
|
|
* _.takeWhile(users, function(o) { return !o.active; });
|
|
* // => objects for ['barney', 'fred']
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.takeWhile(users, { 'user': 'barney', 'active': false });
|
|
* // => objects for ['barney']
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.takeWhile(users, ['active', false]);
|
|
* // => objects for ['barney', 'fred']
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.takeWhile(users, 'active');
|
|
* // => []
|
|
*/
|
|
function takeWhile(array, predicate) {
|
|
return (array && array.length)
|
|
? baseWhile(array, getIteratee(predicate, 3))
|
|
: [];
|
|
}
|
|
|
|
/**
|
|
* Creates an array of unique values, in order, from all given arrays using
|
|
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
* for equality comparisons.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {...Array} [arrays] The arrays to inspect.
|
|
* @returns {Array} Returns the new array of combined values.
|
|
* @example
|
|
*
|
|
* _.union([2], [1, 2]);
|
|
* // => [2, 1]
|
|
*/
|
|
var union = baseRest(function(arrays) {
|
|
return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.union` except that it accepts `iteratee` which is
|
|
* invoked for each element of each `arrays` to generate the criterion by
|
|
* which uniqueness is computed. Result values are chosen from the first
|
|
* array in which the value occurs. The iteratee is invoked with one argument:
|
|
* (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {...Array} [arrays] The arrays to inspect.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {Array} Returns the new array of combined values.
|
|
* @example
|
|
*
|
|
* _.unionBy([2.1], [1.2, 2.3], Math.floor);
|
|
* // => [2.1, 1.2]
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
|
|
* // => [{ 'x': 1 }, { 'x': 2 }]
|
|
*/
|
|
var unionBy = baseRest(function(arrays) {
|
|
var iteratee = last(arrays);
|
|
if (isArrayLikeObject(iteratee)) {
|
|
iteratee = undefined;
|
|
}
|
|
return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.union` except that it accepts `comparator` which
|
|
* is invoked to compare elements of `arrays`. Result values are chosen from
|
|
* the first array in which the value occurs. The comparator is invoked
|
|
* with two arguments: (arrVal, othVal).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {...Array} [arrays] The arrays to inspect.
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
* @returns {Array} Returns the new array of combined values.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
|
|
* var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
|
|
*
|
|
* _.unionWith(objects, others, _.isEqual);
|
|
* // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
|
|
*/
|
|
var unionWith = baseRest(function(arrays) {
|
|
var comparator = last(arrays);
|
|
comparator = typeof comparator == 'function' ? comparator : undefined;
|
|
return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
|
|
});
|
|
|
|
/**
|
|
* Creates a duplicate-free version of an array, using
|
|
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
* for equality comparisons, in which only the first occurrence of each element
|
|
* is kept. The order of result values is determined by the order they occur
|
|
* in the array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @returns {Array} Returns the new duplicate free array.
|
|
* @example
|
|
*
|
|
* _.uniq([2, 1, 2]);
|
|
* // => [2, 1]
|
|
*/
|
|
function uniq(array) {
|
|
return (array && array.length) ? baseUniq(array) : [];
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.uniq` except that it accepts `iteratee` which is
|
|
* invoked for each element in `array` to generate the criterion by which
|
|
* uniqueness is computed. The order of result values is determined by the
|
|
* order they occur in the array. The iteratee is invoked with one argument:
|
|
* (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {Array} Returns the new duplicate free array.
|
|
* @example
|
|
*
|
|
* _.uniqBy([2.1, 1.2, 2.3], Math.floor);
|
|
* // => [2.1, 1.2]
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
|
|
* // => [{ 'x': 1 }, { 'x': 2 }]
|
|
*/
|
|
function uniqBy(array, iteratee) {
|
|
return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.uniq` except that it accepts `comparator` which
|
|
* is invoked to compare elements of `array`. The order of result values is
|
|
* determined by the order they occur in the array.The comparator is invoked
|
|
* with two arguments: (arrVal, othVal).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
* @returns {Array} Returns the new duplicate free array.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
|
|
*
|
|
* _.uniqWith(objects, _.isEqual);
|
|
* // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
|
|
*/
|
|
function uniqWith(array, comparator) {
|
|
comparator = typeof comparator == 'function' ? comparator : undefined;
|
|
return (array && array.length) ? baseUniq(array, undefined, comparator) : [];
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.zip` except that it accepts an array of grouped
|
|
* elements and creates an array regrouping the elements to their pre-zip
|
|
* configuration.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 1.2.0
|
|
* @category Array
|
|
* @param {Array} array The array of grouped elements to process.
|
|
* @returns {Array} Returns the new array of regrouped elements.
|
|
* @example
|
|
*
|
|
* var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
|
|
* // => [['a', 1, true], ['b', 2, false]]
|
|
*
|
|
* _.unzip(zipped);
|
|
* // => [['a', 'b'], [1, 2], [true, false]]
|
|
*/
|
|
function unzip(array) {
|
|
if (!(array && array.length)) {
|
|
return [];
|
|
}
|
|
var length = 0;
|
|
array = arrayFilter(array, function(group) {
|
|
if (isArrayLikeObject(group)) {
|
|
length = nativeMax(group.length, length);
|
|
return true;
|
|
}
|
|
});
|
|
return baseTimes(length, function(index) {
|
|
return arrayMap(array, baseProperty(index));
|
|
});
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.unzip` except that it accepts `iteratee` to specify
|
|
* how regrouped values should be combined. The iteratee is invoked with the
|
|
* elements of each group: (...group).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.8.0
|
|
* @category Array
|
|
* @param {Array} array The array of grouped elements to process.
|
|
* @param {Function} [iteratee=_.identity] The function to combine
|
|
* regrouped values.
|
|
* @returns {Array} Returns the new array of regrouped elements.
|
|
* @example
|
|
*
|
|
* var zipped = _.zip([1, 2], [10, 20], [100, 200]);
|
|
* // => [[1, 10, 100], [2, 20, 200]]
|
|
*
|
|
* _.unzipWith(zipped, _.add);
|
|
* // => [3, 30, 300]
|
|
*/
|
|
function unzipWith(array, iteratee) {
|
|
if (!(array && array.length)) {
|
|
return [];
|
|
}
|
|
var result = unzip(array);
|
|
if (iteratee == null) {
|
|
return result;
|
|
}
|
|
return arrayMap(result, function(group) {
|
|
return apply(iteratee, undefined, group);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates an array excluding all given values using
|
|
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
* for equality comparisons.
|
|
*
|
|
* **Note:** Unlike `_.pull`, this method returns a new array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {...*} [values] The values to exclude.
|
|
* @returns {Array} Returns the new array of filtered values.
|
|
* @see _.difference, _.xor
|
|
* @example
|
|
*
|
|
* _.without([2, 1, 2, 3], 1, 2);
|
|
* // => [3]
|
|
*/
|
|
var without = baseRest(function(array, values) {
|
|
return isArrayLikeObject(array)
|
|
? baseDifference(array, values)
|
|
: [];
|
|
});
|
|
|
|
/**
|
|
* Creates an array of unique values that is the
|
|
* [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
|
|
* of the given arrays. The order of result values is determined by the order
|
|
* they occur in the arrays.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.4.0
|
|
* @category Array
|
|
* @param {...Array} [arrays] The arrays to inspect.
|
|
* @returns {Array} Returns the new array of filtered values.
|
|
* @see _.difference, _.without
|
|
* @example
|
|
*
|
|
* _.xor([2, 1], [2, 3]);
|
|
* // => [1, 3]
|
|
*/
|
|
var xor = baseRest(function(arrays) {
|
|
return baseXor(arrayFilter(arrays, isArrayLikeObject));
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.xor` except that it accepts `iteratee` which is
|
|
* invoked for each element of each `arrays` to generate the criterion by
|
|
* which by which they're compared. The order of result values is determined
|
|
* by the order they occur in the arrays. The iteratee is invoked with one
|
|
* argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {...Array} [arrays] The arrays to inspect.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {Array} Returns the new array of filtered values.
|
|
* @example
|
|
*
|
|
* _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
|
|
* // => [1.2, 3.4]
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
|
|
* // => [{ 'x': 2 }]
|
|
*/
|
|
var xorBy = baseRest(function(arrays) {
|
|
var iteratee = last(arrays);
|
|
if (isArrayLikeObject(iteratee)) {
|
|
iteratee = undefined;
|
|
}
|
|
return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.xor` except that it accepts `comparator` which is
|
|
* invoked to compare elements of `arrays`. The order of result values is
|
|
* determined by the order they occur in the arrays. The comparator is invoked
|
|
* with two arguments: (arrVal, othVal).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {...Array} [arrays] The arrays to inspect.
|
|
* @param {Function} [comparator] The comparator invoked per element.
|
|
* @returns {Array} Returns the new array of filtered values.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
|
|
* var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
|
|
*
|
|
* _.xorWith(objects, others, _.isEqual);
|
|
* // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
|
|
*/
|
|
var xorWith = baseRest(function(arrays) {
|
|
var comparator = last(arrays);
|
|
comparator = typeof comparator == 'function' ? comparator : undefined;
|
|
return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
|
|
});
|
|
|
|
/**
|
|
* Creates an array of grouped elements, the first of which contains the
|
|
* first elements of the given arrays, the second of which contains the
|
|
* second elements of the given arrays, and so on.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Array
|
|
* @param {...Array} [arrays] The arrays to process.
|
|
* @returns {Array} Returns the new array of grouped elements.
|
|
* @example
|
|
*
|
|
* _.zip(['a', 'b'], [1, 2], [true, false]);
|
|
* // => [['a', 1, true], ['b', 2, false]]
|
|
*/
|
|
var zip = baseRest(unzip);
|
|
|
|
/**
|
|
* This method is like `_.fromPairs` except that it accepts two arrays,
|
|
* one of property identifiers and one of corresponding values.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.4.0
|
|
* @category Array
|
|
* @param {Array} [props=[]] The property identifiers.
|
|
* @param {Array} [values=[]] The property values.
|
|
* @returns {Object} Returns the new object.
|
|
* @example
|
|
*
|
|
* _.zipObject(['a', 'b'], [1, 2]);
|
|
* // => { 'a': 1, 'b': 2 }
|
|
*/
|
|
function zipObject(props, values) {
|
|
return baseZipObject(props || [], values || [], assignValue);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.zipObject` except that it supports property paths.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.1.0
|
|
* @category Array
|
|
* @param {Array} [props=[]] The property identifiers.
|
|
* @param {Array} [values=[]] The property values.
|
|
* @returns {Object} Returns the new object.
|
|
* @example
|
|
*
|
|
* _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
|
|
* // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
|
|
*/
|
|
function zipObjectDeep(props, values) {
|
|
return baseZipObject(props || [], values || [], baseSet);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.zip` except that it accepts `iteratee` to specify
|
|
* how grouped values should be combined. The iteratee is invoked with the
|
|
* elements of each group: (...group).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.8.0
|
|
* @category Array
|
|
* @param {...Array} [arrays] The arrays to process.
|
|
* @param {Function} [iteratee=_.identity] The function to combine
|
|
* grouped values.
|
|
* @returns {Array} Returns the new array of grouped elements.
|
|
* @example
|
|
*
|
|
* _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
|
|
* return a + b + c;
|
|
* });
|
|
* // => [111, 222]
|
|
*/
|
|
var zipWith = baseRest(function(arrays) {
|
|
var length = arrays.length,
|
|
iteratee = length > 1 ? arrays[length - 1] : undefined;
|
|
|
|
iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
|
|
return unzipWith(arrays, iteratee);
|
|
});
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates a `lodash` wrapper instance that wraps `value` with explicit method
|
|
* chain sequences enabled. The result of such sequences must be unwrapped
|
|
* with `_#value`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 1.3.0
|
|
* @category Seq
|
|
* @param {*} value The value to wrap.
|
|
* @returns {Object} Returns the new `lodash` wrapper instance.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'age': 36 },
|
|
* { 'user': 'fred', 'age': 40 },
|
|
* { 'user': 'pebbles', 'age': 1 }
|
|
* ];
|
|
*
|
|
* var youngest = _
|
|
* .chain(users)
|
|
* .sortBy('age')
|
|
* .map(function(o) {
|
|
* return o.user + ' is ' + o.age;
|
|
* })
|
|
* .head()
|
|
* .value();
|
|
* // => 'pebbles is 1'
|
|
*/
|
|
function chain(value) {
|
|
var result = lodash(value);
|
|
result.__chain__ = true;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* This method invokes `interceptor` and returns `value`. The interceptor
|
|
* is invoked with one argument; (value). The purpose of this method is to
|
|
* "tap into" a method chain sequence in order to modify intermediate results.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Seq
|
|
* @param {*} value The value to provide to `interceptor`.
|
|
* @param {Function} interceptor The function to invoke.
|
|
* @returns {*} Returns `value`.
|
|
* @example
|
|
*
|
|
* _([1, 2, 3])
|
|
* .tap(function(array) {
|
|
* // Mutate input array.
|
|
* array.pop();
|
|
* })
|
|
* .reverse()
|
|
* .value();
|
|
* // => [2, 1]
|
|
*/
|
|
function tap(value, interceptor) {
|
|
interceptor(value);
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.tap` except that it returns the result of `interceptor`.
|
|
* The purpose of this method is to "pass thru" values replacing intermediate
|
|
* results in a method chain sequence.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Seq
|
|
* @param {*} value The value to provide to `interceptor`.
|
|
* @param {Function} interceptor The function to invoke.
|
|
* @returns {*} Returns the result of `interceptor`.
|
|
* @example
|
|
*
|
|
* _(' abc ')
|
|
* .chain()
|
|
* .trim()
|
|
* .thru(function(value) {
|
|
* return [value];
|
|
* })
|
|
* .value();
|
|
* // => ['abc']
|
|
*/
|
|
function thru(value, interceptor) {
|
|
return interceptor(value);
|
|
}
|
|
|
|
/**
|
|
* This method is the wrapper version of `_.at`.
|
|
*
|
|
* @name at
|
|
* @memberOf _
|
|
* @since 1.0.0
|
|
* @category Seq
|
|
* @param {...(string|string[])} [paths] The property paths to pick.
|
|
* @returns {Object} Returns the new `lodash` wrapper instance.
|
|
* @example
|
|
*
|
|
* var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
|
|
*
|
|
* _(object).at(['a[0].b.c', 'a[1]']).value();
|
|
* // => [3, 4]
|
|
*/
|
|
var wrapperAt = flatRest(function(paths) {
|
|
var length = paths.length,
|
|
start = length ? paths[0] : 0,
|
|
value = this.__wrapped__,
|
|
interceptor = function(object) { return baseAt(object, paths); };
|
|
|
|
if (length > 1 || this.__actions__.length ||
|
|
!(value instanceof LazyWrapper) || !isIndex(start)) {
|
|
return this.thru(interceptor);
|
|
}
|
|
value = value.slice(start, +start + (length ? 1 : 0));
|
|
value.__actions__.push({
|
|
'func': thru,
|
|
'args': [interceptor],
|
|
'thisArg': undefined
|
|
});
|
|
return new LodashWrapper(value, this.__chain__).thru(function(array) {
|
|
if (length && !array.length) {
|
|
array.push(undefined);
|
|
}
|
|
return array;
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
|
|
*
|
|
* @name chain
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Seq
|
|
* @returns {Object} Returns the new `lodash` wrapper instance.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'age': 36 },
|
|
* { 'user': 'fred', 'age': 40 }
|
|
* ];
|
|
*
|
|
* // A sequence without explicit chaining.
|
|
* _(users).head();
|
|
* // => { 'user': 'barney', 'age': 36 }
|
|
*
|
|
* // A sequence with explicit chaining.
|
|
* _(users)
|
|
* .chain()
|
|
* .head()
|
|
* .pick('user')
|
|
* .value();
|
|
* // => { 'user': 'barney' }
|
|
*/
|
|
function wrapperChain() {
|
|
return chain(this);
|
|
}
|
|
|
|
/**
|
|
* Executes the chain sequence and returns the wrapped result.
|
|
*
|
|
* @name commit
|
|
* @memberOf _
|
|
* @since 3.2.0
|
|
* @category Seq
|
|
* @returns {Object} Returns the new `lodash` wrapper instance.
|
|
* @example
|
|
*
|
|
* var array = [1, 2];
|
|
* var wrapped = _(array).push(3);
|
|
*
|
|
* console.log(array);
|
|
* // => [1, 2]
|
|
*
|
|
* wrapped = wrapped.commit();
|
|
* console.log(array);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* wrapped.last();
|
|
* // => 3
|
|
*
|
|
* console.log(array);
|
|
* // => [1, 2, 3]
|
|
*/
|
|
function wrapperCommit() {
|
|
return new LodashWrapper(this.value(), this.__chain__);
|
|
}
|
|
|
|
/**
|
|
* Gets the next value on a wrapped object following the
|
|
* [iterator protocol](https://mdn.io/iteration_protocols#iterator).
|
|
*
|
|
* @name next
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Seq
|
|
* @returns {Object} Returns the next iterator value.
|
|
* @example
|
|
*
|
|
* var wrapped = _([1, 2]);
|
|
*
|
|
* wrapped.next();
|
|
* // => { 'done': false, 'value': 1 }
|
|
*
|
|
* wrapped.next();
|
|
* // => { 'done': false, 'value': 2 }
|
|
*
|
|
* wrapped.next();
|
|
* // => { 'done': true, 'value': undefined }
|
|
*/
|
|
function wrapperNext() {
|
|
if (this.__values__ === undefined) {
|
|
this.__values__ = toArray(this.value());
|
|
}
|
|
var done = this.__index__ >= this.__values__.length,
|
|
value = done ? undefined : this.__values__[this.__index__++];
|
|
|
|
return { 'done': done, 'value': value };
|
|
}
|
|
|
|
/**
|
|
* Enables the wrapper to be iterable.
|
|
*
|
|
* @name Symbol.iterator
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Seq
|
|
* @returns {Object} Returns the wrapper object.
|
|
* @example
|
|
*
|
|
* var wrapped = _([1, 2]);
|
|
*
|
|
* wrapped[Symbol.iterator]() === wrapped;
|
|
* // => true
|
|
*
|
|
* Array.from(wrapped);
|
|
* // => [1, 2]
|
|
*/
|
|
function wrapperToIterator() {
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Creates a clone of the chain sequence planting `value` as the wrapped value.
|
|
*
|
|
* @name plant
|
|
* @memberOf _
|
|
* @since 3.2.0
|
|
* @category Seq
|
|
* @param {*} value The value to plant.
|
|
* @returns {Object} Returns the new `lodash` wrapper instance.
|
|
* @example
|
|
*
|
|
* function square(n) {
|
|
* return n * n;
|
|
* }
|
|
*
|
|
* var wrapped = _([1, 2]).map(square);
|
|
* var other = wrapped.plant([3, 4]);
|
|
*
|
|
* other.value();
|
|
* // => [9, 16]
|
|
*
|
|
* wrapped.value();
|
|
* // => [1, 4]
|
|
*/
|
|
function wrapperPlant(value) {
|
|
var result,
|
|
parent = this;
|
|
|
|
while (parent instanceof baseLodash) {
|
|
var clone = wrapperClone(parent);
|
|
clone.__index__ = 0;
|
|
clone.__values__ = undefined;
|
|
if (result) {
|
|
previous.__wrapped__ = clone;
|
|
} else {
|
|
result = clone;
|
|
}
|
|
var previous = clone;
|
|
parent = parent.__wrapped__;
|
|
}
|
|
previous.__wrapped__ = value;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* This method is the wrapper version of `_.reverse`.
|
|
*
|
|
* **Note:** This method mutates the wrapped array.
|
|
*
|
|
* @name reverse
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Seq
|
|
* @returns {Object} Returns the new `lodash` wrapper instance.
|
|
* @example
|
|
*
|
|
* var array = [1, 2, 3];
|
|
*
|
|
* _(array).reverse().value()
|
|
* // => [3, 2, 1]
|
|
*
|
|
* console.log(array);
|
|
* // => [3, 2, 1]
|
|
*/
|
|
function wrapperReverse() {
|
|
var value = this.__wrapped__;
|
|
if (value instanceof LazyWrapper) {
|
|
var wrapped = value;
|
|
if (this.__actions__.length) {
|
|
wrapped = new LazyWrapper(this);
|
|
}
|
|
wrapped = wrapped.reverse();
|
|
wrapped.__actions__.push({
|
|
'func': thru,
|
|
'args': [reverse],
|
|
'thisArg': undefined
|
|
});
|
|
return new LodashWrapper(wrapped, this.__chain__);
|
|
}
|
|
return this.thru(reverse);
|
|
}
|
|
|
|
/**
|
|
* Executes the chain sequence to resolve the unwrapped value.
|
|
*
|
|
* @name value
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @alias toJSON, valueOf
|
|
* @category Seq
|
|
* @returns {*} Returns the resolved unwrapped value.
|
|
* @example
|
|
*
|
|
* _([1, 2, 3]).value();
|
|
* // => [1, 2, 3]
|
|
*/
|
|
function wrapperValue() {
|
|
return baseWrapperValue(this.__wrapped__, this.__actions__);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates an object composed of keys generated from the results of running
|
|
* each element of `collection` thru `iteratee`. The corresponding value of
|
|
* each key is the number of times the key was returned by `iteratee`. The
|
|
* iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.5.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The iteratee to transform keys.
|
|
* @returns {Object} Returns the composed aggregate object.
|
|
* @example
|
|
*
|
|
* _.countBy([6.1, 4.2, 6.3], Math.floor);
|
|
* // => { '4': 1, '6': 2 }
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.countBy(['one', 'two', 'three'], 'length');
|
|
* // => { '3': 2, '5': 1 }
|
|
*/
|
|
var countBy = createAggregator(function(result, value, key) {
|
|
if (hasOwnProperty.call(result, key)) {
|
|
++result[key];
|
|
} else {
|
|
baseAssignValue(result, key, 1);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Checks if `predicate` returns truthy for **all** elements of `collection`.
|
|
* Iteration is stopped once `predicate` returns falsey. The predicate is
|
|
* invoked with three arguments: (value, index|key, collection).
|
|
*
|
|
* **Note:** This method returns `true` for
|
|
* [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
|
|
* [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
|
|
* elements of empty collections.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {boolean} Returns `true` if all elements pass the predicate check,
|
|
* else `false`.
|
|
* @example
|
|
*
|
|
* _.every([true, 1, null, 'yes'], Boolean);
|
|
* // => false
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'age': 36, 'active': false },
|
|
* { 'user': 'fred', 'age': 40, 'active': false }
|
|
* ];
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.every(users, { 'user': 'barney', 'active': false });
|
|
* // => false
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.every(users, ['active', false]);
|
|
* // => true
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.every(users, 'active');
|
|
* // => false
|
|
*/
|
|
function every(collection, predicate, guard) {
|
|
var func = isArray(collection) ? arrayEvery : baseEvery;
|
|
if (guard && isIterateeCall(collection, predicate, guard)) {
|
|
predicate = undefined;
|
|
}
|
|
return func(collection, getIteratee(predicate, 3));
|
|
}
|
|
|
|
/**
|
|
* Iterates over elements of `collection`, returning an array of all elements
|
|
* `predicate` returns truthy for. The predicate is invoked with three
|
|
* arguments: (value, index|key, collection).
|
|
*
|
|
* **Note:** Unlike `_.remove`, this method returns a new array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the new filtered array.
|
|
* @see _.reject
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'age': 36, 'active': true },
|
|
* { 'user': 'fred', 'age': 40, 'active': false }
|
|
* ];
|
|
*
|
|
* _.filter(users, function(o) { return !o.active; });
|
|
* // => objects for ['fred']
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.filter(users, { 'age': 36, 'active': true });
|
|
* // => objects for ['barney']
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.filter(users, ['active', false]);
|
|
* // => objects for ['fred']
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.filter(users, 'active');
|
|
* // => objects for ['barney']
|
|
*
|
|
* // Combining several predicates using `_.overEvery` or `_.overSome`.
|
|
* _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]]));
|
|
* // => objects for ['fred', 'barney']
|
|
*/
|
|
function filter(collection, predicate) {
|
|
var func = isArray(collection) ? arrayFilter : baseFilter;
|
|
return func(collection, getIteratee(predicate, 3));
|
|
}
|
|
|
|
/**
|
|
* Iterates over elements of `collection`, returning the first element
|
|
* `predicate` returns truthy for. The predicate is invoked with three
|
|
* arguments: (value, index|key, collection).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to inspect.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @param {number} [fromIndex=0] The index to search from.
|
|
* @returns {*} Returns the matched element, else `undefined`.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'age': 36, 'active': true },
|
|
* { 'user': 'fred', 'age': 40, 'active': false },
|
|
* { 'user': 'pebbles', 'age': 1, 'active': true }
|
|
* ];
|
|
*
|
|
* _.find(users, function(o) { return o.age < 40; });
|
|
* // => object for 'barney'
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.find(users, { 'age': 1, 'active': true });
|
|
* // => object for 'pebbles'
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.find(users, ['active', false]);
|
|
* // => object for 'fred'
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.find(users, 'active');
|
|
* // => object for 'barney'
|
|
*/
|
|
var find = createFind(findIndex);
|
|
|
|
/**
|
|
* This method is like `_.find` except that it iterates over elements of
|
|
* `collection` from right to left.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.0.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to inspect.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @param {number} [fromIndex=collection.length-1] The index to search from.
|
|
* @returns {*} Returns the matched element, else `undefined`.
|
|
* @example
|
|
*
|
|
* _.findLast([1, 2, 3, 4], function(n) {
|
|
* return n % 2 == 1;
|
|
* });
|
|
* // => 3
|
|
*/
|
|
var findLast = createFind(findLastIndex);
|
|
|
|
/**
|
|
* Creates a flattened array of values by running each element in `collection`
|
|
* thru `iteratee` and flattening the mapped results. The iteratee is invoked
|
|
* with three arguments: (value, index|key, collection).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the new flattened array.
|
|
* @example
|
|
*
|
|
* function duplicate(n) {
|
|
* return [n, n];
|
|
* }
|
|
*
|
|
* _.flatMap([1, 2], duplicate);
|
|
* // => [1, 1, 2, 2]
|
|
*/
|
|
function flatMap(collection, iteratee) {
|
|
return baseFlatten(map(collection, iteratee), 1);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.flatMap` except that it recursively flattens the
|
|
* mapped results.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.7.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the new flattened array.
|
|
* @example
|
|
*
|
|
* function duplicate(n) {
|
|
* return [[[n, n]]];
|
|
* }
|
|
*
|
|
* _.flatMapDeep([1, 2], duplicate);
|
|
* // => [1, 1, 2, 2]
|
|
*/
|
|
function flatMapDeep(collection, iteratee) {
|
|
return baseFlatten(map(collection, iteratee), INFINITY);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.flatMap` except that it recursively flattens the
|
|
* mapped results up to `depth` times.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.7.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @param {number} [depth=1] The maximum recursion depth.
|
|
* @returns {Array} Returns the new flattened array.
|
|
* @example
|
|
*
|
|
* function duplicate(n) {
|
|
* return [[[n, n]]];
|
|
* }
|
|
*
|
|
* _.flatMapDepth([1, 2], duplicate, 2);
|
|
* // => [[1, 1], [2, 2]]
|
|
*/
|
|
function flatMapDepth(collection, iteratee, depth) {
|
|
depth = depth === undefined ? 1 : toInteger(depth);
|
|
return baseFlatten(map(collection, iteratee), depth);
|
|
}
|
|
|
|
/**
|
|
* Iterates over elements of `collection` and invokes `iteratee` for each element.
|
|
* The iteratee is invoked with three arguments: (value, index|key, collection).
|
|
* Iteratee functions may exit iteration early by explicitly returning `false`.
|
|
*
|
|
* **Note:** As with other "Collections" methods, objects with a "length"
|
|
* property are iterated like arrays. To avoid this behavior use `_.forIn`
|
|
* or `_.forOwn` for object iteration.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @alias each
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Array|Object} Returns `collection`.
|
|
* @see _.forEachRight
|
|
* @example
|
|
*
|
|
* _.forEach([1, 2], function(value) {
|
|
* console.log(value);
|
|
* });
|
|
* // => Logs `1` then `2`.
|
|
*
|
|
* _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
|
|
* console.log(key);
|
|
* });
|
|
* // => Logs 'a' then 'b' (iteration order is not guaranteed).
|
|
*/
|
|
function forEach(collection, iteratee) {
|
|
var func = isArray(collection) ? arrayEach : baseEach;
|
|
return func(collection, getIteratee(iteratee, 3));
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.forEach` except that it iterates over elements of
|
|
* `collection` from right to left.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.0.0
|
|
* @alias eachRight
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Array|Object} Returns `collection`.
|
|
* @see _.forEach
|
|
* @example
|
|
*
|
|
* _.forEachRight([1, 2], function(value) {
|
|
* console.log(value);
|
|
* });
|
|
* // => Logs `2` then `1`.
|
|
*/
|
|
function forEachRight(collection, iteratee) {
|
|
var func = isArray(collection) ? arrayEachRight : baseEachRight;
|
|
return func(collection, getIteratee(iteratee, 3));
|
|
}
|
|
|
|
/**
|
|
* Creates an object composed of keys generated from the results of running
|
|
* each element of `collection` thru `iteratee`. The order of grouped values
|
|
* is determined by the order they occur in `collection`. The corresponding
|
|
* value of each key is an array of elements responsible for generating the
|
|
* key. The iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The iteratee to transform keys.
|
|
* @returns {Object} Returns the composed aggregate object.
|
|
* @example
|
|
*
|
|
* _.groupBy([6.1, 4.2, 6.3], Math.floor);
|
|
* // => { '4': [4.2], '6': [6.1, 6.3] }
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.groupBy(['one', 'two', 'three'], 'length');
|
|
* // => { '3': ['one', 'two'], '5': ['three'] }
|
|
*/
|
|
var groupBy = createAggregator(function(result, value, key) {
|
|
if (hasOwnProperty.call(result, key)) {
|
|
result[key].push(value);
|
|
} else {
|
|
baseAssignValue(result, key, [value]);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Checks if `value` is in `collection`. If `collection` is a string, it's
|
|
* checked for a substring of `value`, otherwise
|
|
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
* is used for equality comparisons. If `fromIndex` is negative, it's used as
|
|
* the offset from the end of `collection`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object|string} collection The collection to inspect.
|
|
* @param {*} value The value to search for.
|
|
* @param {number} [fromIndex=0] The index to search from.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
|
|
* @returns {boolean} Returns `true` if `value` is found, else `false`.
|
|
* @example
|
|
*
|
|
* _.includes([1, 2, 3], 1);
|
|
* // => true
|
|
*
|
|
* _.includes([1, 2, 3], 1, 2);
|
|
* // => false
|
|
*
|
|
* _.includes({ 'a': 1, 'b': 2 }, 1);
|
|
* // => true
|
|
*
|
|
* _.includes('abcd', 'bc');
|
|
* // => true
|
|
*/
|
|
function includes(collection, value, fromIndex, guard) {
|
|
collection = isArrayLike(collection) ? collection : values(collection);
|
|
fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
|
|
|
|
var length = collection.length;
|
|
if (fromIndex < 0) {
|
|
fromIndex = nativeMax(length + fromIndex, 0);
|
|
}
|
|
return isString(collection)
|
|
? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
|
|
: (!!length && baseIndexOf(collection, value, fromIndex) > -1);
|
|
}
|
|
|
|
/**
|
|
* Invokes the method at `path` of each element in `collection`, returning
|
|
* an array of the results of each invoked method. Any additional arguments
|
|
* are provided to each invoked method. If `path` is a function, it's invoked
|
|
* for, and `this` bound to, each element in `collection`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Array|Function|string} path The path of the method to invoke or
|
|
* the function invoked per iteration.
|
|
* @param {...*} [args] The arguments to invoke each method with.
|
|
* @returns {Array} Returns the array of results.
|
|
* @example
|
|
*
|
|
* _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
|
|
* // => [[1, 5, 7], [1, 2, 3]]
|
|
*
|
|
* _.invokeMap([123, 456], String.prototype.split, '');
|
|
* // => [['1', '2', '3'], ['4', '5', '6']]
|
|
*/
|
|
var invokeMap = baseRest(function(collection, path, args) {
|
|
var index = -1,
|
|
isFunc = typeof path == 'function',
|
|
result = isArrayLike(collection) ? Array(collection.length) : [];
|
|
|
|
baseEach(collection, function(value) {
|
|
result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
|
|
});
|
|
return result;
|
|
});
|
|
|
|
/**
|
|
* Creates an object composed of keys generated from the results of running
|
|
* each element of `collection` thru `iteratee`. The corresponding value of
|
|
* each key is the last element responsible for generating the key. The
|
|
* iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The iteratee to transform keys.
|
|
* @returns {Object} Returns the composed aggregate object.
|
|
* @example
|
|
*
|
|
* var array = [
|
|
* { 'dir': 'left', 'code': 97 },
|
|
* { 'dir': 'right', 'code': 100 }
|
|
* ];
|
|
*
|
|
* _.keyBy(array, function(o) {
|
|
* return String.fromCharCode(o.code);
|
|
* });
|
|
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
|
|
*
|
|
* _.keyBy(array, 'dir');
|
|
* // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
|
|
*/
|
|
var keyBy = createAggregator(function(result, value, key) {
|
|
baseAssignValue(result, key, value);
|
|
});
|
|
|
|
/**
|
|
* Creates an array of values by running each element in `collection` thru
|
|
* `iteratee`. The iteratee is invoked with three arguments:
|
|
* (value, index|key, collection).
|
|
*
|
|
* Many lodash methods are guarded to work as iteratees for methods like
|
|
* `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
|
|
*
|
|
* The guarded methods are:
|
|
* `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
|
|
* `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
|
|
* `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
|
|
* `template`, `trim`, `trimEnd`, `trimStart`, and `words`
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the new mapped array.
|
|
* @example
|
|
*
|
|
* function square(n) {
|
|
* return n * n;
|
|
* }
|
|
*
|
|
* _.map([4, 8], square);
|
|
* // => [16, 64]
|
|
*
|
|
* _.map({ 'a': 4, 'b': 8 }, square);
|
|
* // => [16, 64] (iteration order is not guaranteed)
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney' },
|
|
* { 'user': 'fred' }
|
|
* ];
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.map(users, 'user');
|
|
* // => ['barney', 'fred']
|
|
*/
|
|
function map(collection, iteratee) {
|
|
var func = isArray(collection) ? arrayMap : baseMap;
|
|
return func(collection, getIteratee(iteratee, 3));
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.sortBy` except that it allows specifying the sort
|
|
* orders of the iteratees to sort by. If `orders` is unspecified, all values
|
|
* are sorted in ascending order. Otherwise, specify an order of "desc" for
|
|
* descending or "asc" for ascending sort order of corresponding values.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
|
|
* The iteratees to sort by.
|
|
* @param {string[]} [orders] The sort orders of `iteratees`.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
|
|
* @returns {Array} Returns the new sorted array.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'fred', 'age': 48 },
|
|
* { 'user': 'barney', 'age': 34 },
|
|
* { 'user': 'fred', 'age': 40 },
|
|
* { 'user': 'barney', 'age': 36 }
|
|
* ];
|
|
*
|
|
* // Sort by `user` in ascending order and by `age` in descending order.
|
|
* _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
|
|
* // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
|
|
*/
|
|
function orderBy(collection, iteratees, orders, guard) {
|
|
if (collection == null) {
|
|
return [];
|
|
}
|
|
if (!isArray(iteratees)) {
|
|
iteratees = iteratees == null ? [] : [iteratees];
|
|
}
|
|
orders = guard ? undefined : orders;
|
|
if (!isArray(orders)) {
|
|
orders = orders == null ? [] : [orders];
|
|
}
|
|
return baseOrderBy(collection, iteratees, orders);
|
|
}
|
|
|
|
/**
|
|
* Creates an array of elements split into two groups, the first of which
|
|
* contains elements `predicate` returns truthy for, the second of which
|
|
* contains elements `predicate` returns falsey for. The predicate is
|
|
* invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the array of grouped elements.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'age': 36, 'active': false },
|
|
* { 'user': 'fred', 'age': 40, 'active': true },
|
|
* { 'user': 'pebbles', 'age': 1, 'active': false }
|
|
* ];
|
|
*
|
|
* _.partition(users, function(o) { return o.active; });
|
|
* // => objects for [['fred'], ['barney', 'pebbles']]
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.partition(users, { 'age': 1, 'active': false });
|
|
* // => objects for [['pebbles'], ['barney', 'fred']]
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.partition(users, ['active', false]);
|
|
* // => objects for [['barney', 'pebbles'], ['fred']]
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.partition(users, 'active');
|
|
* // => objects for [['fred'], ['barney', 'pebbles']]
|
|
*/
|
|
var partition = createAggregator(function(result, value, key) {
|
|
result[key ? 0 : 1].push(value);
|
|
}, function() { return [[], []]; });
|
|
|
|
/**
|
|
* Reduces `collection` to a value which is the accumulated result of running
|
|
* each element in `collection` thru `iteratee`, where each successive
|
|
* invocation is supplied the return value of the previous. If `accumulator`
|
|
* is not given, the first element of `collection` is used as the initial
|
|
* value. The iteratee is invoked with four arguments:
|
|
* (accumulator, value, index|key, collection).
|
|
*
|
|
* Many lodash methods are guarded to work as iteratees for methods like
|
|
* `_.reduce`, `_.reduceRight`, and `_.transform`.
|
|
*
|
|
* The guarded methods are:
|
|
* `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
|
|
* and `sortBy`
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @param {*} [accumulator] The initial value.
|
|
* @returns {*} Returns the accumulated value.
|
|
* @see _.reduceRight
|
|
* @example
|
|
*
|
|
* _.reduce([1, 2], function(sum, n) {
|
|
* return sum + n;
|
|
* }, 0);
|
|
* // => 3
|
|
*
|
|
* _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
|
|
* (result[value] || (result[value] = [])).push(key);
|
|
* return result;
|
|
* }, {});
|
|
* // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
|
|
*/
|
|
function reduce(collection, iteratee, accumulator) {
|
|
var func = isArray(collection) ? arrayReduce : baseReduce,
|
|
initAccum = arguments.length < 3;
|
|
|
|
return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.reduce` except that it iterates over elements of
|
|
* `collection` from right to left.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @param {*} [accumulator] The initial value.
|
|
* @returns {*} Returns the accumulated value.
|
|
* @see _.reduce
|
|
* @example
|
|
*
|
|
* var array = [[0, 1], [2, 3], [4, 5]];
|
|
*
|
|
* _.reduceRight(array, function(flattened, other) {
|
|
* return flattened.concat(other);
|
|
* }, []);
|
|
* // => [4, 5, 2, 3, 0, 1]
|
|
*/
|
|
function reduceRight(collection, iteratee, accumulator) {
|
|
var func = isArray(collection) ? arrayReduceRight : baseReduce,
|
|
initAccum = arguments.length < 3;
|
|
|
|
return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
|
|
}
|
|
|
|
/**
|
|
* The opposite of `_.filter`; this method returns the elements of `collection`
|
|
* that `predicate` does **not** return truthy for.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the new filtered array.
|
|
* @see _.filter
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'age': 36, 'active': false },
|
|
* { 'user': 'fred', 'age': 40, 'active': true }
|
|
* ];
|
|
*
|
|
* _.reject(users, function(o) { return !o.active; });
|
|
* // => objects for ['fred']
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.reject(users, { 'age': 40, 'active': true });
|
|
* // => objects for ['barney']
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.reject(users, ['active', false]);
|
|
* // => objects for ['fred']
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.reject(users, 'active');
|
|
* // => objects for ['barney']
|
|
*/
|
|
function reject(collection, predicate) {
|
|
var func = isArray(collection) ? arrayFilter : baseFilter;
|
|
return func(collection, negate(getIteratee(predicate, 3)));
|
|
}
|
|
|
|
/**
|
|
* Gets a random element from `collection`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.0.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to sample.
|
|
* @returns {*} Returns the random element.
|
|
* @example
|
|
*
|
|
* _.sample([1, 2, 3, 4]);
|
|
* // => 2
|
|
*/
|
|
function sample(collection) {
|
|
var func = isArray(collection) ? arraySample : baseSample;
|
|
return func(collection);
|
|
}
|
|
|
|
/**
|
|
* Gets `n` random elements at unique keys from `collection` up to the
|
|
* size of `collection`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to sample.
|
|
* @param {number} [n=1] The number of elements to sample.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Array} Returns the random elements.
|
|
* @example
|
|
*
|
|
* _.sampleSize([1, 2, 3], 2);
|
|
* // => [3, 1]
|
|
*
|
|
* _.sampleSize([1, 2, 3], 4);
|
|
* // => [2, 3, 1]
|
|
*/
|
|
function sampleSize(collection, n, guard) {
|
|
if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
|
|
n = 1;
|
|
} else {
|
|
n = toInteger(n);
|
|
}
|
|
var func = isArray(collection) ? arraySampleSize : baseSampleSize;
|
|
return func(collection, n);
|
|
}
|
|
|
|
/**
|
|
* Creates an array of shuffled values, using a version of the
|
|
* [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to shuffle.
|
|
* @returns {Array} Returns the new shuffled array.
|
|
* @example
|
|
*
|
|
* _.shuffle([1, 2, 3, 4]);
|
|
* // => [4, 1, 3, 2]
|
|
*/
|
|
function shuffle(collection) {
|
|
var func = isArray(collection) ? arrayShuffle : baseShuffle;
|
|
return func(collection);
|
|
}
|
|
|
|
/**
|
|
* Gets the size of `collection` by returning its length for array-like
|
|
* values or the number of own enumerable string keyed properties for objects.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object|string} collection The collection to inspect.
|
|
* @returns {number} Returns the collection size.
|
|
* @example
|
|
*
|
|
* _.size([1, 2, 3]);
|
|
* // => 3
|
|
*
|
|
* _.size({ 'a': 1, 'b': 2 });
|
|
* // => 2
|
|
*
|
|
* _.size('pebbles');
|
|
* // => 7
|
|
*/
|
|
function size(collection) {
|
|
if (collection == null) {
|
|
return 0;
|
|
}
|
|
if (isArrayLike(collection)) {
|
|
return isString(collection) ? stringSize(collection) : collection.length;
|
|
}
|
|
var tag = getTag(collection);
|
|
if (tag == mapTag || tag == setTag) {
|
|
return collection.size;
|
|
}
|
|
return baseKeys(collection).length;
|
|
}
|
|
|
|
/**
|
|
* Checks if `predicate` returns truthy for **any** element of `collection`.
|
|
* Iteration is stopped once `predicate` returns truthy. The predicate is
|
|
* invoked with three arguments: (value, index|key, collection).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {boolean} Returns `true` if any element passes the predicate check,
|
|
* else `false`.
|
|
* @example
|
|
*
|
|
* _.some([null, 0, 'yes', false], Boolean);
|
|
* // => true
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'active': true },
|
|
* { 'user': 'fred', 'active': false }
|
|
* ];
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.some(users, { 'user': 'barney', 'active': false });
|
|
* // => false
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.some(users, ['active', false]);
|
|
* // => true
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.some(users, 'active');
|
|
* // => true
|
|
*/
|
|
function some(collection, predicate, guard) {
|
|
var func = isArray(collection) ? arraySome : baseSome;
|
|
if (guard && isIterateeCall(collection, predicate, guard)) {
|
|
predicate = undefined;
|
|
}
|
|
return func(collection, getIteratee(predicate, 3));
|
|
}
|
|
|
|
/**
|
|
* Creates an array of elements, sorted in ascending order by the results of
|
|
* running each element in a collection thru each iteratee. This method
|
|
* performs a stable sort, that is, it preserves the original sort order of
|
|
* equal elements. The iteratees are invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Collection
|
|
* @param {Array|Object} collection The collection to iterate over.
|
|
* @param {...(Function|Function[])} [iteratees=[_.identity]]
|
|
* The iteratees to sort by.
|
|
* @returns {Array} Returns the new sorted array.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'fred', 'age': 48 },
|
|
* { 'user': 'barney', 'age': 36 },
|
|
* { 'user': 'fred', 'age': 30 },
|
|
* { 'user': 'barney', 'age': 34 }
|
|
* ];
|
|
*
|
|
* _.sortBy(users, [function(o) { return o.user; }]);
|
|
* // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]
|
|
*
|
|
* _.sortBy(users, ['user', 'age']);
|
|
* // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]
|
|
*/
|
|
var sortBy = baseRest(function(collection, iteratees) {
|
|
if (collection == null) {
|
|
return [];
|
|
}
|
|
var length = iteratees.length;
|
|
if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
|
|
iteratees = [];
|
|
} else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
|
|
iteratees = [iteratees[0]];
|
|
}
|
|
return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
|
|
});
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Gets the timestamp of the number of milliseconds that have elapsed since
|
|
* the Unix epoch (1 January 1970 00:00:00 UTC).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.4.0
|
|
* @category Date
|
|
* @returns {number} Returns the timestamp.
|
|
* @example
|
|
*
|
|
* _.defer(function(stamp) {
|
|
* console.log(_.now() - stamp);
|
|
* }, _.now());
|
|
* // => Logs the number of milliseconds it took for the deferred invocation.
|
|
*/
|
|
var now = ctxNow || function() {
|
|
return root.Date.now();
|
|
};
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* The opposite of `_.before`; this method creates a function that invokes
|
|
* `func` once it's called `n` or more times.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Function
|
|
* @param {number} n The number of calls before `func` is invoked.
|
|
* @param {Function} func The function to restrict.
|
|
* @returns {Function} Returns the new restricted function.
|
|
* @example
|
|
*
|
|
* var saves = ['profile', 'settings'];
|
|
*
|
|
* var done = _.after(saves.length, function() {
|
|
* console.log('done saving!');
|
|
* });
|
|
*
|
|
* _.forEach(saves, function(type) {
|
|
* asyncSave({ 'type': type, 'complete': done });
|
|
* });
|
|
* // => Logs 'done saving!' after the two async saves have completed.
|
|
*/
|
|
function after(n, func) {
|
|
if (typeof func != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
n = toInteger(n);
|
|
return function() {
|
|
if (--n < 1) {
|
|
return func.apply(this, arguments);
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes `func`, with up to `n` arguments,
|
|
* ignoring any additional arguments.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Function
|
|
* @param {Function} func The function to cap arguments for.
|
|
* @param {number} [n=func.length] The arity cap.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Function} Returns the new capped function.
|
|
* @example
|
|
*
|
|
* _.map(['6', '8', '10'], _.ary(parseInt, 1));
|
|
* // => [6, 8, 10]
|
|
*/
|
|
function ary(func, n, guard) {
|
|
n = guard ? undefined : n;
|
|
n = (func && n == null) ? func.length : n;
|
|
return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes `func`, with the `this` binding and arguments
|
|
* of the created function, while it's called less than `n` times. Subsequent
|
|
* calls to the created function return the result of the last `func` invocation.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Function
|
|
* @param {number} n The number of calls at which `func` is no longer invoked.
|
|
* @param {Function} func The function to restrict.
|
|
* @returns {Function} Returns the new restricted function.
|
|
* @example
|
|
*
|
|
* jQuery(element).on('click', _.before(5, addContactToList));
|
|
* // => Allows adding up to 4 contacts to the list.
|
|
*/
|
|
function before(n, func) {
|
|
var result;
|
|
if (typeof func != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
n = toInteger(n);
|
|
return function() {
|
|
if (--n > 0) {
|
|
result = func.apply(this, arguments);
|
|
}
|
|
if (n <= 1) {
|
|
func = undefined;
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes `func` with the `this` binding of `thisArg`
|
|
* and `partials` prepended to the arguments it receives.
|
|
*
|
|
* The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
|
|
* may be used as a placeholder for partially applied arguments.
|
|
*
|
|
* **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
|
|
* property of bound functions.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Function
|
|
* @param {Function} func The function to bind.
|
|
* @param {*} thisArg The `this` binding of `func`.
|
|
* @param {...*} [partials] The arguments to be partially applied.
|
|
* @returns {Function} Returns the new bound function.
|
|
* @example
|
|
*
|
|
* function greet(greeting, punctuation) {
|
|
* return greeting + ' ' + this.user + punctuation;
|
|
* }
|
|
*
|
|
* var object = { 'user': 'fred' };
|
|
*
|
|
* var bound = _.bind(greet, object, 'hi');
|
|
* bound('!');
|
|
* // => 'hi fred!'
|
|
*
|
|
* // Bound with placeholders.
|
|
* var bound = _.bind(greet, object, _, '!');
|
|
* bound('hi');
|
|
* // => 'hi fred!'
|
|
*/
|
|
var bind = baseRest(function(func, thisArg, partials) {
|
|
var bitmask = WRAP_BIND_FLAG;
|
|
if (partials.length) {
|
|
var holders = replaceHolders(partials, getHolder(bind));
|
|
bitmask |= WRAP_PARTIAL_FLAG;
|
|
}
|
|
return createWrap(func, bitmask, thisArg, partials, holders);
|
|
});
|
|
|
|
/**
|
|
* Creates a function that invokes the method at `object[key]` with `partials`
|
|
* prepended to the arguments it receives.
|
|
*
|
|
* This method differs from `_.bind` by allowing bound functions to reference
|
|
* methods that may be redefined or don't yet exist. See
|
|
* [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
|
|
* for more details.
|
|
*
|
|
* The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
|
|
* builds, may be used as a placeholder for partially applied arguments.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.10.0
|
|
* @category Function
|
|
* @param {Object} object The object to invoke the method on.
|
|
* @param {string} key The key of the method.
|
|
* @param {...*} [partials] The arguments to be partially applied.
|
|
* @returns {Function} Returns the new bound function.
|
|
* @example
|
|
*
|
|
* var object = {
|
|
* 'user': 'fred',
|
|
* 'greet': function(greeting, punctuation) {
|
|
* return greeting + ' ' + this.user + punctuation;
|
|
* }
|
|
* };
|
|
*
|
|
* var bound = _.bindKey(object, 'greet', 'hi');
|
|
* bound('!');
|
|
* // => 'hi fred!'
|
|
*
|
|
* object.greet = function(greeting, punctuation) {
|
|
* return greeting + 'ya ' + this.user + punctuation;
|
|
* };
|
|
*
|
|
* bound('!');
|
|
* // => 'hiya fred!'
|
|
*
|
|
* // Bound with placeholders.
|
|
* var bound = _.bindKey(object, 'greet', _, '!');
|
|
* bound('hi');
|
|
* // => 'hiya fred!'
|
|
*/
|
|
var bindKey = baseRest(function(object, key, partials) {
|
|
var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
|
|
if (partials.length) {
|
|
var holders = replaceHolders(partials, getHolder(bindKey));
|
|
bitmask |= WRAP_PARTIAL_FLAG;
|
|
}
|
|
return createWrap(key, bitmask, object, partials, holders);
|
|
});
|
|
|
|
/**
|
|
* Creates a function that accepts arguments of `func` and either invokes
|
|
* `func` returning its result, if at least `arity` number of arguments have
|
|
* been provided, or returns a function that accepts the remaining `func`
|
|
* arguments, and so on. The arity of `func` may be specified if `func.length`
|
|
* is not sufficient.
|
|
*
|
|
* The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
|
|
* may be used as a placeholder for provided arguments.
|
|
*
|
|
* **Note:** This method doesn't set the "length" property of curried functions.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.0.0
|
|
* @category Function
|
|
* @param {Function} func The function to curry.
|
|
* @param {number} [arity=func.length] The arity of `func`.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Function} Returns the new curried function.
|
|
* @example
|
|
*
|
|
* var abc = function(a, b, c) {
|
|
* return [a, b, c];
|
|
* };
|
|
*
|
|
* var curried = _.curry(abc);
|
|
*
|
|
* curried(1)(2)(3);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* curried(1, 2)(3);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* curried(1, 2, 3);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* // Curried with placeholders.
|
|
* curried(1)(_, 3)(2);
|
|
* // => [1, 2, 3]
|
|
*/
|
|
function curry(func, arity, guard) {
|
|
arity = guard ? undefined : arity;
|
|
var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
|
|
result.placeholder = curry.placeholder;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.curry` except that arguments are applied to `func`
|
|
* in the manner of `_.partialRight` instead of `_.partial`.
|
|
*
|
|
* The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
|
|
* builds, may be used as a placeholder for provided arguments.
|
|
*
|
|
* **Note:** This method doesn't set the "length" property of curried functions.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Function
|
|
* @param {Function} func The function to curry.
|
|
* @param {number} [arity=func.length] The arity of `func`.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Function} Returns the new curried function.
|
|
* @example
|
|
*
|
|
* var abc = function(a, b, c) {
|
|
* return [a, b, c];
|
|
* };
|
|
*
|
|
* var curried = _.curryRight(abc);
|
|
*
|
|
* curried(3)(2)(1);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* curried(2, 3)(1);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* curried(1, 2, 3);
|
|
* // => [1, 2, 3]
|
|
*
|
|
* // Curried with placeholders.
|
|
* curried(3)(1, _)(2);
|
|
* // => [1, 2, 3]
|
|
*/
|
|
function curryRight(func, arity, guard) {
|
|
arity = guard ? undefined : arity;
|
|
var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
|
|
result.placeholder = curryRight.placeholder;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates a debounced function that delays invoking `func` until after `wait`
|
|
* milliseconds have elapsed since the last time the debounced function was
|
|
* invoked. The debounced function comes with a `cancel` method to cancel
|
|
* delayed `func` invocations and a `flush` method to immediately invoke them.
|
|
* Provide `options` to indicate whether `func` should be invoked on the
|
|
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked
|
|
* with the last arguments provided to the debounced function. Subsequent
|
|
* calls to the debounced function return the result of the last `func`
|
|
* invocation.
|
|
*
|
|
* **Note:** If `leading` and `trailing` options are `true`, `func` is
|
|
* invoked on the trailing edge of the timeout only if the debounced function
|
|
* is invoked more than once during the `wait` timeout.
|
|
*
|
|
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
|
|
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
|
|
*
|
|
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
|
|
* for details over the differences between `_.debounce` and `_.throttle`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Function
|
|
* @param {Function} func The function to debounce.
|
|
* @param {number} [wait=0] The number of milliseconds to delay.
|
|
* @param {Object} [options={}] The options object.
|
|
* @param {boolean} [options.leading=false]
|
|
* Specify invoking on the leading edge of the timeout.
|
|
* @param {number} [options.maxWait]
|
|
* The maximum time `func` is allowed to be delayed before it's invoked.
|
|
* @param {boolean} [options.trailing=true]
|
|
* Specify invoking on the trailing edge of the timeout.
|
|
* @returns {Function} Returns the new debounced function.
|
|
* @example
|
|
*
|
|
* // Avoid costly calculations while the window size is in flux.
|
|
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
|
|
*
|
|
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
|
|
* jQuery(element).on('click', _.debounce(sendMail, 300, {
|
|
* 'leading': true,
|
|
* 'trailing': false
|
|
* }));
|
|
*
|
|
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
|
|
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
|
|
* var source = new EventSource('/stream');
|
|
* jQuery(source).on('message', debounced);
|
|
*
|
|
* // Cancel the trailing debounced invocation.
|
|
* jQuery(window).on('popstate', debounced.cancel);
|
|
*/
|
|
function debounce(func, wait, options) {
|
|
var lastArgs,
|
|
lastThis,
|
|
maxWait,
|
|
result,
|
|
timerId,
|
|
lastCallTime,
|
|
lastInvokeTime = 0,
|
|
leading = false,
|
|
maxing = false,
|
|
trailing = true;
|
|
|
|
if (typeof func != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
wait = toNumber(wait) || 0;
|
|
if (isObject(options)) {
|
|
leading = !!options.leading;
|
|
maxing = 'maxWait' in options;
|
|
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
|
|
trailing = 'trailing' in options ? !!options.trailing : trailing;
|
|
}
|
|
|
|
function invokeFunc(time) {
|
|
var args = lastArgs,
|
|
thisArg = lastThis;
|
|
|
|
lastArgs = lastThis = undefined;
|
|
lastInvokeTime = time;
|
|
result = func.apply(thisArg, args);
|
|
return result;
|
|
}
|
|
|
|
function leadingEdge(time) {
|
|
// Reset any `maxWait` timer.
|
|
lastInvokeTime = time;
|
|
// Start the timer for the trailing edge.
|
|
timerId = setTimeout(timerExpired, wait);
|
|
// Invoke the leading edge.
|
|
return leading ? invokeFunc(time) : result;
|
|
}
|
|
|
|
function remainingWait(time) {
|
|
var timeSinceLastCall = time - lastCallTime,
|
|
timeSinceLastInvoke = time - lastInvokeTime,
|
|
timeWaiting = wait - timeSinceLastCall;
|
|
|
|
return maxing
|
|
? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
|
|
: timeWaiting;
|
|
}
|
|
|
|
function shouldInvoke(time) {
|
|
var timeSinceLastCall = time - lastCallTime,
|
|
timeSinceLastInvoke = time - lastInvokeTime;
|
|
|
|
// Either this is the first call, activity has stopped and we're at the
|
|
// trailing edge, the system time has gone backwards and we're treating
|
|
// it as the trailing edge, or we've hit the `maxWait` limit.
|
|
return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
|
|
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
|
|
}
|
|
|
|
function timerExpired() {
|
|
var time = now();
|
|
if (shouldInvoke(time)) {
|
|
return trailingEdge(time);
|
|
}
|
|
// Restart the timer.
|
|
timerId = setTimeout(timerExpired, remainingWait(time));
|
|
}
|
|
|
|
function trailingEdge(time) {
|
|
timerId = undefined;
|
|
|
|
// Only invoke if we have `lastArgs` which means `func` has been
|
|
// debounced at least once.
|
|
if (trailing && lastArgs) {
|
|
return invokeFunc(time);
|
|
}
|
|
lastArgs = lastThis = undefined;
|
|
return result;
|
|
}
|
|
|
|
function cancel() {
|
|
if (timerId !== undefined) {
|
|
clearTimeout(timerId);
|
|
}
|
|
lastInvokeTime = 0;
|
|
lastArgs = lastCallTime = lastThis = timerId = undefined;
|
|
}
|
|
|
|
function flush() {
|
|
return timerId === undefined ? result : trailingEdge(now());
|
|
}
|
|
|
|
function debounced() {
|
|
var time = now(),
|
|
isInvoking = shouldInvoke(time);
|
|
|
|
lastArgs = arguments;
|
|
lastThis = this;
|
|
lastCallTime = time;
|
|
|
|
if (isInvoking) {
|
|
if (timerId === undefined) {
|
|
return leadingEdge(lastCallTime);
|
|
}
|
|
if (maxing) {
|
|
// Handle invocations in a tight loop.
|
|
clearTimeout(timerId);
|
|
timerId = setTimeout(timerExpired, wait);
|
|
return invokeFunc(lastCallTime);
|
|
}
|
|
}
|
|
if (timerId === undefined) {
|
|
timerId = setTimeout(timerExpired, wait);
|
|
}
|
|
return result;
|
|
}
|
|
debounced.cancel = cancel;
|
|
debounced.flush = flush;
|
|
return debounced;
|
|
}
|
|
|
|
/**
|
|
* Defers invoking the `func` until the current call stack has cleared. Any
|
|
* additional arguments are provided to `func` when it's invoked.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Function
|
|
* @param {Function} func The function to defer.
|
|
* @param {...*} [args] The arguments to invoke `func` with.
|
|
* @returns {number} Returns the timer id.
|
|
* @example
|
|
*
|
|
* _.defer(function(text) {
|
|
* console.log(text);
|
|
* }, 'deferred');
|
|
* // => Logs 'deferred' after one millisecond.
|
|
*/
|
|
var defer = baseRest(function(func, args) {
|
|
return baseDelay(func, 1, args);
|
|
});
|
|
|
|
/**
|
|
* Invokes `func` after `wait` milliseconds. Any additional arguments are
|
|
* provided to `func` when it's invoked.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Function
|
|
* @param {Function} func The function to delay.
|
|
* @param {number} wait The number of milliseconds to delay invocation.
|
|
* @param {...*} [args] The arguments to invoke `func` with.
|
|
* @returns {number} Returns the timer id.
|
|
* @example
|
|
*
|
|
* _.delay(function(text) {
|
|
* console.log(text);
|
|
* }, 1000, 'later');
|
|
* // => Logs 'later' after one second.
|
|
*/
|
|
var delay = baseRest(function(func, wait, args) {
|
|
return baseDelay(func, toNumber(wait) || 0, args);
|
|
});
|
|
|
|
/**
|
|
* Creates a function that invokes `func` with arguments reversed.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Function
|
|
* @param {Function} func The function to flip arguments for.
|
|
* @returns {Function} Returns the new flipped function.
|
|
* @example
|
|
*
|
|
* var flipped = _.flip(function() {
|
|
* return _.toArray(arguments);
|
|
* });
|
|
*
|
|
* flipped('a', 'b', 'c', 'd');
|
|
* // => ['d', 'c', 'b', 'a']
|
|
*/
|
|
function flip(func) {
|
|
return createWrap(func, WRAP_FLIP_FLAG);
|
|
}
|
|
|
|
/**
|
|
* Creates a function that memoizes the result of `func`. If `resolver` is
|
|
* provided, it determines the cache key for storing the result based on the
|
|
* arguments provided to the memoized function. By default, the first argument
|
|
* provided to the memoized function is used as the map cache key. The `func`
|
|
* is invoked with the `this` binding of the memoized function.
|
|
*
|
|
* **Note:** The cache is exposed as the `cache` property on the memoized
|
|
* function. Its creation may be customized by replacing the `_.memoize.Cache`
|
|
* constructor with one whose instances implement the
|
|
* [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
|
|
* method interface of `clear`, `delete`, `get`, `has`, and `set`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Function
|
|
* @param {Function} func The function to have its output memoized.
|
|
* @param {Function} [resolver] The function to resolve the cache key.
|
|
* @returns {Function} Returns the new memoized function.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1, 'b': 2 };
|
|
* var other = { 'c': 3, 'd': 4 };
|
|
*
|
|
* var values = _.memoize(_.values);
|
|
* values(object);
|
|
* // => [1, 2]
|
|
*
|
|
* values(other);
|
|
* // => [3, 4]
|
|
*
|
|
* object.a = 2;
|
|
* values(object);
|
|
* // => [1, 2]
|
|
*
|
|
* // Modify the result cache.
|
|
* values.cache.set(object, ['a', 'b']);
|
|
* values(object);
|
|
* // => ['a', 'b']
|
|
*
|
|
* // Replace `_.memoize.Cache`.
|
|
* _.memoize.Cache = WeakMap;
|
|
*/
|
|
function memoize(func, resolver) {
|
|
if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
var memoized = function() {
|
|
var args = arguments,
|
|
key = resolver ? resolver.apply(this, args) : args[0],
|
|
cache = memoized.cache;
|
|
|
|
if (cache.has(key)) {
|
|
return cache.get(key);
|
|
}
|
|
var result = func.apply(this, args);
|
|
memoized.cache = cache.set(key, result) || cache;
|
|
return result;
|
|
};
|
|
memoized.cache = new (memoize.Cache || MapCache);
|
|
return memoized;
|
|
}
|
|
|
|
// Expose `MapCache`.
|
|
memoize.Cache = MapCache;
|
|
|
|
/**
|
|
* Creates a function that negates the result of the predicate `func`. The
|
|
* `func` predicate is invoked with the `this` binding and arguments of the
|
|
* created function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Function
|
|
* @param {Function} predicate The predicate to negate.
|
|
* @returns {Function} Returns the new negated function.
|
|
* @example
|
|
*
|
|
* function isEven(n) {
|
|
* return n % 2 == 0;
|
|
* }
|
|
*
|
|
* _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
|
|
* // => [1, 3, 5]
|
|
*/
|
|
function negate(predicate) {
|
|
if (typeof predicate != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
return function() {
|
|
var args = arguments;
|
|
switch (args.length) {
|
|
case 0: return !predicate.call(this);
|
|
case 1: return !predicate.call(this, args[0]);
|
|
case 2: return !predicate.call(this, args[0], args[1]);
|
|
case 3: return !predicate.call(this, args[0], args[1], args[2]);
|
|
}
|
|
return !predicate.apply(this, args);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a function that is restricted to invoking `func` once. Repeat calls
|
|
* to the function return the value of the first invocation. The `func` is
|
|
* invoked with the `this` binding and arguments of the created function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Function
|
|
* @param {Function} func The function to restrict.
|
|
* @returns {Function} Returns the new restricted function.
|
|
* @example
|
|
*
|
|
* var initialize = _.once(createApplication);
|
|
* initialize();
|
|
* initialize();
|
|
* // => `createApplication` is invoked once
|
|
*/
|
|
function once(func) {
|
|
return before(2, func);
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes `func` with its arguments transformed.
|
|
*
|
|
* @static
|
|
* @since 4.0.0
|
|
* @memberOf _
|
|
* @category Function
|
|
* @param {Function} func The function to wrap.
|
|
* @param {...(Function|Function[])} [transforms=[_.identity]]
|
|
* The argument transforms.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* function doubled(n) {
|
|
* return n * 2;
|
|
* }
|
|
*
|
|
* function square(n) {
|
|
* return n * n;
|
|
* }
|
|
*
|
|
* var func = _.overArgs(function(x, y) {
|
|
* return [x, y];
|
|
* }, [square, doubled]);
|
|
*
|
|
* func(9, 3);
|
|
* // => [81, 6]
|
|
*
|
|
* func(10, 5);
|
|
* // => [100, 10]
|
|
*/
|
|
var overArgs = castRest(function(func, transforms) {
|
|
transforms = (transforms.length == 1 && isArray(transforms[0]))
|
|
? arrayMap(transforms[0], baseUnary(getIteratee()))
|
|
: arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
|
|
|
|
var funcsLength = transforms.length;
|
|
return baseRest(function(args) {
|
|
var index = -1,
|
|
length = nativeMin(args.length, funcsLength);
|
|
|
|
while (++index < length) {
|
|
args[index] = transforms[index].call(this, args[index]);
|
|
}
|
|
return apply(func, this, args);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Creates a function that invokes `func` with `partials` prepended to the
|
|
* arguments it receives. This method is like `_.bind` except it does **not**
|
|
* alter the `this` binding.
|
|
*
|
|
* The `_.partial.placeholder` value, which defaults to `_` in monolithic
|
|
* builds, may be used as a placeholder for partially applied arguments.
|
|
*
|
|
* **Note:** This method doesn't set the "length" property of partially
|
|
* applied functions.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.2.0
|
|
* @category Function
|
|
* @param {Function} func The function to partially apply arguments to.
|
|
* @param {...*} [partials] The arguments to be partially applied.
|
|
* @returns {Function} Returns the new partially applied function.
|
|
* @example
|
|
*
|
|
* function greet(greeting, name) {
|
|
* return greeting + ' ' + name;
|
|
* }
|
|
*
|
|
* var sayHelloTo = _.partial(greet, 'hello');
|
|
* sayHelloTo('fred');
|
|
* // => 'hello fred'
|
|
*
|
|
* // Partially applied with placeholders.
|
|
* var greetFred = _.partial(greet, _, 'fred');
|
|
* greetFred('hi');
|
|
* // => 'hi fred'
|
|
*/
|
|
var partial = baseRest(function(func, partials) {
|
|
var holders = replaceHolders(partials, getHolder(partial));
|
|
return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.partial` except that partially applied arguments
|
|
* are appended to the arguments it receives.
|
|
*
|
|
* The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
|
|
* builds, may be used as a placeholder for partially applied arguments.
|
|
*
|
|
* **Note:** This method doesn't set the "length" property of partially
|
|
* applied functions.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 1.0.0
|
|
* @category Function
|
|
* @param {Function} func The function to partially apply arguments to.
|
|
* @param {...*} [partials] The arguments to be partially applied.
|
|
* @returns {Function} Returns the new partially applied function.
|
|
* @example
|
|
*
|
|
* function greet(greeting, name) {
|
|
* return greeting + ' ' + name;
|
|
* }
|
|
*
|
|
* var greetFred = _.partialRight(greet, 'fred');
|
|
* greetFred('hi');
|
|
* // => 'hi fred'
|
|
*
|
|
* // Partially applied with placeholders.
|
|
* var sayHelloTo = _.partialRight(greet, 'hello', _);
|
|
* sayHelloTo('fred');
|
|
* // => 'hello fred'
|
|
*/
|
|
var partialRight = baseRest(function(func, partials) {
|
|
var holders = replaceHolders(partials, getHolder(partialRight));
|
|
return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
|
|
});
|
|
|
|
/**
|
|
* Creates a function that invokes `func` with arguments arranged according
|
|
* to the specified `indexes` where the argument value at the first index is
|
|
* provided as the first argument, the argument value at the second index is
|
|
* provided as the second argument, and so on.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Function
|
|
* @param {Function} func The function to rearrange arguments for.
|
|
* @param {...(number|number[])} indexes The arranged argument indexes.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* var rearged = _.rearg(function(a, b, c) {
|
|
* return [a, b, c];
|
|
* }, [2, 0, 1]);
|
|
*
|
|
* rearged('b', 'c', 'a')
|
|
* // => ['a', 'b', 'c']
|
|
*/
|
|
var rearg = flatRest(function(func, indexes) {
|
|
return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
|
|
});
|
|
|
|
/**
|
|
* Creates a function that invokes `func` with the `this` binding of the
|
|
* created function and arguments from `start` and beyond provided as
|
|
* an array.
|
|
*
|
|
* **Note:** This method is based on the
|
|
* [rest parameter](https://mdn.io/rest_parameters).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Function
|
|
* @param {Function} func The function to apply a rest parameter to.
|
|
* @param {number} [start=func.length-1] The start position of the rest parameter.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* var say = _.rest(function(what, names) {
|
|
* return what + ' ' + _.initial(names).join(', ') +
|
|
* (_.size(names) > 1 ? ', & ' : '') + _.last(names);
|
|
* });
|
|
*
|
|
* say('hello', 'fred', 'barney', 'pebbles');
|
|
* // => 'hello fred, barney, & pebbles'
|
|
*/
|
|
function rest(func, start) {
|
|
if (typeof func != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
start = start === undefined ? start : toInteger(start);
|
|
return baseRest(func, start);
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes `func` with the `this` binding of the
|
|
* create function and an array of arguments much like
|
|
* [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
|
|
*
|
|
* **Note:** This method is based on the
|
|
* [spread operator](https://mdn.io/spread_operator).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.2.0
|
|
* @category Function
|
|
* @param {Function} func The function to spread arguments over.
|
|
* @param {number} [start=0] The start position of the spread.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* var say = _.spread(function(who, what) {
|
|
* return who + ' says ' + what;
|
|
* });
|
|
*
|
|
* say(['fred', 'hello']);
|
|
* // => 'fred says hello'
|
|
*
|
|
* var numbers = Promise.all([
|
|
* Promise.resolve(40),
|
|
* Promise.resolve(36)
|
|
* ]);
|
|
*
|
|
* numbers.then(_.spread(function(x, y) {
|
|
* return x + y;
|
|
* }));
|
|
* // => a Promise of 76
|
|
*/
|
|
function spread(func, start) {
|
|
if (typeof func != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
start = start == null ? 0 : nativeMax(toInteger(start), 0);
|
|
return baseRest(function(args) {
|
|
var array = args[start],
|
|
otherArgs = castSlice(args, 0, start);
|
|
|
|
if (array) {
|
|
arrayPush(otherArgs, array);
|
|
}
|
|
return apply(func, this, otherArgs);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates a throttled function that only invokes `func` at most once per
|
|
* every `wait` milliseconds. The throttled function comes with a `cancel`
|
|
* method to cancel delayed `func` invocations and a `flush` method to
|
|
* immediately invoke them. Provide `options` to indicate whether `func`
|
|
* should be invoked on the leading and/or trailing edge of the `wait`
|
|
* timeout. The `func` is invoked with the last arguments provided to the
|
|
* throttled function. Subsequent calls to the throttled function return the
|
|
* result of the last `func` invocation.
|
|
*
|
|
* **Note:** If `leading` and `trailing` options are `true`, `func` is
|
|
* invoked on the trailing edge of the timeout only if the throttled function
|
|
* is invoked more than once during the `wait` timeout.
|
|
*
|
|
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
|
|
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
|
|
*
|
|
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
|
|
* for details over the differences between `_.throttle` and `_.debounce`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Function
|
|
* @param {Function} func The function to throttle.
|
|
* @param {number} [wait=0] The number of milliseconds to throttle invocations to.
|
|
* @param {Object} [options={}] The options object.
|
|
* @param {boolean} [options.leading=true]
|
|
* Specify invoking on the leading edge of the timeout.
|
|
* @param {boolean} [options.trailing=true]
|
|
* Specify invoking on the trailing edge of the timeout.
|
|
* @returns {Function} Returns the new throttled function.
|
|
* @example
|
|
*
|
|
* // Avoid excessively updating the position while scrolling.
|
|
* jQuery(window).on('scroll', _.throttle(updatePosition, 100));
|
|
*
|
|
* // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
|
|
* var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
|
|
* jQuery(element).on('click', throttled);
|
|
*
|
|
* // Cancel the trailing throttled invocation.
|
|
* jQuery(window).on('popstate', throttled.cancel);
|
|
*/
|
|
function throttle(func, wait, options) {
|
|
var leading = true,
|
|
trailing = true;
|
|
|
|
if (typeof func != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
if (isObject(options)) {
|
|
leading = 'leading' in options ? !!options.leading : leading;
|
|
trailing = 'trailing' in options ? !!options.trailing : trailing;
|
|
}
|
|
return debounce(func, wait, {
|
|
'leading': leading,
|
|
'maxWait': wait,
|
|
'trailing': trailing
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates a function that accepts up to one argument, ignoring any
|
|
* additional arguments.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Function
|
|
* @param {Function} func The function to cap arguments for.
|
|
* @returns {Function} Returns the new capped function.
|
|
* @example
|
|
*
|
|
* _.map(['6', '8', '10'], _.unary(parseInt));
|
|
* // => [6, 8, 10]
|
|
*/
|
|
function unary(func) {
|
|
return ary(func, 1);
|
|
}
|
|
|
|
/**
|
|
* Creates a function that provides `value` to `wrapper` as its first
|
|
* argument. Any additional arguments provided to the function are appended
|
|
* to those provided to the `wrapper`. The wrapper is invoked with the `this`
|
|
* binding of the created function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Function
|
|
* @param {*} value The value to wrap.
|
|
* @param {Function} [wrapper=identity] The wrapper function.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* var p = _.wrap(_.escape, function(func, text) {
|
|
* return '<p>' + func(text) + '</p>';
|
|
* });
|
|
*
|
|
* p('fred, barney, & pebbles');
|
|
* // => '<p>fred, barney, & pebbles</p>'
|
|
*/
|
|
function wrap(value, wrapper) {
|
|
return partial(castFunction(wrapper), value);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Casts `value` as an array if it's not one.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.4.0
|
|
* @category Lang
|
|
* @param {*} value The value to inspect.
|
|
* @returns {Array} Returns the cast array.
|
|
* @example
|
|
*
|
|
* _.castArray(1);
|
|
* // => [1]
|
|
*
|
|
* _.castArray({ 'a': 1 });
|
|
* // => [{ 'a': 1 }]
|
|
*
|
|
* _.castArray('abc');
|
|
* // => ['abc']
|
|
*
|
|
* _.castArray(null);
|
|
* // => [null]
|
|
*
|
|
* _.castArray(undefined);
|
|
* // => [undefined]
|
|
*
|
|
* _.castArray();
|
|
* // => []
|
|
*
|
|
* var array = [1, 2, 3];
|
|
* console.log(_.castArray(array) === array);
|
|
* // => true
|
|
*/
|
|
function castArray() {
|
|
if (!arguments.length) {
|
|
return [];
|
|
}
|
|
var value = arguments[0];
|
|
return isArray(value) ? value : [value];
|
|
}
|
|
|
|
/**
|
|
* Creates a shallow clone of `value`.
|
|
*
|
|
* **Note:** This method is loosely based on the
|
|
* [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
|
|
* and supports cloning arrays, array buffers, booleans, date objects, maps,
|
|
* numbers, `Object` objects, regexes, sets, strings, symbols, and typed
|
|
* arrays. The own enumerable properties of `arguments` objects are cloned
|
|
* as plain objects. An empty object is returned for uncloneable values such
|
|
* as error objects, functions, DOM nodes, and WeakMaps.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to clone.
|
|
* @returns {*} Returns the cloned value.
|
|
* @see _.cloneDeep
|
|
* @example
|
|
*
|
|
* var objects = [{ 'a': 1 }, { 'b': 2 }];
|
|
*
|
|
* var shallow = _.clone(objects);
|
|
* console.log(shallow[0] === objects[0]);
|
|
* // => true
|
|
*/
|
|
function clone(value) {
|
|
return baseClone(value, CLONE_SYMBOLS_FLAG);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.clone` except that it accepts `customizer` which
|
|
* is invoked to produce the cloned value. If `customizer` returns `undefined`,
|
|
* cloning is handled by the method instead. The `customizer` is invoked with
|
|
* up to four arguments; (value [, index|key, object, stack]).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to clone.
|
|
* @param {Function} [customizer] The function to customize cloning.
|
|
* @returns {*} Returns the cloned value.
|
|
* @see _.cloneDeepWith
|
|
* @example
|
|
*
|
|
* function customizer(value) {
|
|
* if (_.isElement(value)) {
|
|
* return value.cloneNode(false);
|
|
* }
|
|
* }
|
|
*
|
|
* var el = _.cloneWith(document.body, customizer);
|
|
*
|
|
* console.log(el === document.body);
|
|
* // => false
|
|
* console.log(el.nodeName);
|
|
* // => 'BODY'
|
|
* console.log(el.childNodes.length);
|
|
* // => 0
|
|
*/
|
|
function cloneWith(value, customizer) {
|
|
customizer = typeof customizer == 'function' ? customizer : undefined;
|
|
return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.clone` except that it recursively clones `value`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 1.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to recursively clone.
|
|
* @returns {*} Returns the deep cloned value.
|
|
* @see _.clone
|
|
* @example
|
|
*
|
|
* var objects = [{ 'a': 1 }, { 'b': 2 }];
|
|
*
|
|
* var deep = _.cloneDeep(objects);
|
|
* console.log(deep[0] === objects[0]);
|
|
* // => false
|
|
*/
|
|
function cloneDeep(value) {
|
|
return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.cloneWith` except that it recursively clones `value`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to recursively clone.
|
|
* @param {Function} [customizer] The function to customize cloning.
|
|
* @returns {*} Returns the deep cloned value.
|
|
* @see _.cloneWith
|
|
* @example
|
|
*
|
|
* function customizer(value) {
|
|
* if (_.isElement(value)) {
|
|
* return value.cloneNode(true);
|
|
* }
|
|
* }
|
|
*
|
|
* var el = _.cloneDeepWith(document.body, customizer);
|
|
*
|
|
* console.log(el === document.body);
|
|
* // => false
|
|
* console.log(el.nodeName);
|
|
* // => 'BODY'
|
|
* console.log(el.childNodes.length);
|
|
* // => 20
|
|
*/
|
|
function cloneDeepWith(value, customizer) {
|
|
customizer = typeof customizer == 'function' ? customizer : undefined;
|
|
return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
|
|
}
|
|
|
|
/**
|
|
* Checks if `object` conforms to `source` by invoking the predicate
|
|
* properties of `source` with the corresponding property values of `object`.
|
|
*
|
|
* **Note:** This method is equivalent to `_.conforms` when `source` is
|
|
* partially applied.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.14.0
|
|
* @category Lang
|
|
* @param {Object} object The object to inspect.
|
|
* @param {Object} source The object of property predicates to conform to.
|
|
* @returns {boolean} Returns `true` if `object` conforms, else `false`.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1, 'b': 2 };
|
|
*
|
|
* _.conformsTo(object, { 'b': function(n) { return n > 1; } });
|
|
* // => true
|
|
*
|
|
* _.conformsTo(object, { 'b': function(n) { return n > 2; } });
|
|
* // => false
|
|
*/
|
|
function conformsTo(object, source) {
|
|
return source == null || baseConformsTo(object, source, keys(source));
|
|
}
|
|
|
|
/**
|
|
* Performs a
|
|
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
* comparison between two values to determine if they are equivalent.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1 };
|
|
* var other = { 'a': 1 };
|
|
*
|
|
* _.eq(object, object);
|
|
* // => true
|
|
*
|
|
* _.eq(object, other);
|
|
* // => false
|
|
*
|
|
* _.eq('a', 'a');
|
|
* // => true
|
|
*
|
|
* _.eq('a', Object('a'));
|
|
* // => false
|
|
*
|
|
* _.eq(NaN, NaN);
|
|
* // => true
|
|
*/
|
|
function eq(value, other) {
|
|
return value === other || (value !== value && other !== other);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is greater than `other`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.9.0
|
|
* @category Lang
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @returns {boolean} Returns `true` if `value` is greater than `other`,
|
|
* else `false`.
|
|
* @see _.lt
|
|
* @example
|
|
*
|
|
* _.gt(3, 1);
|
|
* // => true
|
|
*
|
|
* _.gt(3, 3);
|
|
* // => false
|
|
*
|
|
* _.gt(1, 3);
|
|
* // => false
|
|
*/
|
|
var gt = createRelationalOperation(baseGt);
|
|
|
|
/**
|
|
* Checks if `value` is greater than or equal to `other`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.9.0
|
|
* @category Lang
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @returns {boolean} Returns `true` if `value` is greater than or equal to
|
|
* `other`, else `false`.
|
|
* @see _.lte
|
|
* @example
|
|
*
|
|
* _.gte(3, 1);
|
|
* // => true
|
|
*
|
|
* _.gte(3, 3);
|
|
* // => true
|
|
*
|
|
* _.gte(1, 3);
|
|
* // => false
|
|
*/
|
|
var gte = createRelationalOperation(function(value, other) {
|
|
return value >= other;
|
|
});
|
|
|
|
/**
|
|
* Checks if `value` is likely an `arguments` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is an `arguments` object,
|
|
* else `false`.
|
|
* @example
|
|
*
|
|
* _.isArguments(function() { return arguments; }());
|
|
* // => true
|
|
*
|
|
* _.isArguments([1, 2, 3]);
|
|
* // => false
|
|
*/
|
|
var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
|
|
return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
|
|
!propertyIsEnumerable.call(value, 'callee');
|
|
};
|
|
|
|
/**
|
|
* Checks if `value` is classified as an `Array` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is an array, else `false`.
|
|
* @example
|
|
*
|
|
* _.isArray([1, 2, 3]);
|
|
* // => true
|
|
*
|
|
* _.isArray(document.body.children);
|
|
* // => false
|
|
*
|
|
* _.isArray('abc');
|
|
* // => false
|
|
*
|
|
* _.isArray(_.noop);
|
|
* // => false
|
|
*/
|
|
var isArray = Array.isArray;
|
|
|
|
/**
|
|
* Checks if `value` is classified as an `ArrayBuffer` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.3.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
|
|
* @example
|
|
*
|
|
* _.isArrayBuffer(new ArrayBuffer(2));
|
|
* // => true
|
|
*
|
|
* _.isArrayBuffer(new Array(2));
|
|
* // => false
|
|
*/
|
|
var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
|
|
|
|
/**
|
|
* Checks if `value` is array-like. A value is considered array-like if it's
|
|
* not a function and has a `value.length` that's an integer greater than or
|
|
* equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is array-like, else `false`.
|
|
* @example
|
|
*
|
|
* _.isArrayLike([1, 2, 3]);
|
|
* // => true
|
|
*
|
|
* _.isArrayLike(document.body.children);
|
|
* // => true
|
|
*
|
|
* _.isArrayLike('abc');
|
|
* // => true
|
|
*
|
|
* _.isArrayLike(_.noop);
|
|
* // => false
|
|
*/
|
|
function isArrayLike(value) {
|
|
return value != null && isLength(value.length) && !isFunction(value);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.isArrayLike` except that it also checks if `value`
|
|
* is an object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is an array-like object,
|
|
* else `false`.
|
|
* @example
|
|
*
|
|
* _.isArrayLikeObject([1, 2, 3]);
|
|
* // => true
|
|
*
|
|
* _.isArrayLikeObject(document.body.children);
|
|
* // => true
|
|
*
|
|
* _.isArrayLikeObject('abc');
|
|
* // => false
|
|
*
|
|
* _.isArrayLikeObject(_.noop);
|
|
* // => false
|
|
*/
|
|
function isArrayLikeObject(value) {
|
|
return isObjectLike(value) && isArrayLike(value);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is classified as a boolean primitive or object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
|
|
* @example
|
|
*
|
|
* _.isBoolean(false);
|
|
* // => true
|
|
*
|
|
* _.isBoolean(null);
|
|
* // => false
|
|
*/
|
|
function isBoolean(value) {
|
|
return value === true || value === false ||
|
|
(isObjectLike(value) && baseGetTag(value) == boolTag);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a buffer.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.3.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
|
|
* @example
|
|
*
|
|
* _.isBuffer(new Buffer(2));
|
|
* // => true
|
|
*
|
|
* _.isBuffer(new Uint8Array(2));
|
|
* // => false
|
|
*/
|
|
var isBuffer = nativeIsBuffer || stubFalse;
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `Date` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a date object, else `false`.
|
|
* @example
|
|
*
|
|
* _.isDate(new Date);
|
|
* // => true
|
|
*
|
|
* _.isDate('Mon April 23 2012');
|
|
* // => false
|
|
*/
|
|
var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
|
|
|
|
/**
|
|
* Checks if `value` is likely a DOM element.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
|
|
* @example
|
|
*
|
|
* _.isElement(document.body);
|
|
* // => true
|
|
*
|
|
* _.isElement('<body>');
|
|
* // => false
|
|
*/
|
|
function isElement(value) {
|
|
return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is an empty object, collection, map, or set.
|
|
*
|
|
* Objects are considered empty if they have no own enumerable string keyed
|
|
* properties.
|
|
*
|
|
* Array-like values such as `arguments` objects, arrays, buffers, strings, or
|
|
* jQuery-like collections are considered empty if they have a `length` of `0`.
|
|
* Similarly, maps and sets are considered empty if they have a `size` of `0`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is empty, else `false`.
|
|
* @example
|
|
*
|
|
* _.isEmpty(null);
|
|
* // => true
|
|
*
|
|
* _.isEmpty(true);
|
|
* // => true
|
|
*
|
|
* _.isEmpty(1);
|
|
* // => true
|
|
*
|
|
* _.isEmpty([1, 2, 3]);
|
|
* // => false
|
|
*
|
|
* _.isEmpty({ 'a': 1 });
|
|
* // => false
|
|
*/
|
|
function isEmpty(value) {
|
|
if (value == null) {
|
|
return true;
|
|
}
|
|
if (isArrayLike(value) &&
|
|
(isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
|
|
isBuffer(value) || isTypedArray(value) || isArguments(value))) {
|
|
return !value.length;
|
|
}
|
|
var tag = getTag(value);
|
|
if (tag == mapTag || tag == setTag) {
|
|
return !value.size;
|
|
}
|
|
if (isPrototype(value)) {
|
|
return !baseKeys(value).length;
|
|
}
|
|
for (var key in value) {
|
|
if (hasOwnProperty.call(value, key)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Performs a deep comparison between two values to determine if they are
|
|
* equivalent.
|
|
*
|
|
* **Note:** This method supports comparing arrays, array buffers, booleans,
|
|
* date objects, error objects, maps, numbers, `Object` objects, regexes,
|
|
* sets, strings, symbols, and typed arrays. `Object` objects are compared
|
|
* by their own, not inherited, enumerable properties. Functions and DOM
|
|
* nodes are compared by strict equality, i.e. `===`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1 };
|
|
* var other = { 'a': 1 };
|
|
*
|
|
* _.isEqual(object, other);
|
|
* // => true
|
|
*
|
|
* object === other;
|
|
* // => false
|
|
*/
|
|
function isEqual(value, other) {
|
|
return baseIsEqual(value, other);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.isEqual` except that it accepts `customizer` which
|
|
* is invoked to compare values. If `customizer` returns `undefined`, comparisons
|
|
* are handled by the method instead. The `customizer` is invoked with up to
|
|
* six arguments: (objValue, othValue [, index|key, object, other, stack]).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @param {Function} [customizer] The function to customize comparisons.
|
|
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
|
|
* @example
|
|
*
|
|
* function isGreeting(value) {
|
|
* return /^h(?:i|ello)$/.test(value);
|
|
* }
|
|
*
|
|
* function customizer(objValue, othValue) {
|
|
* if (isGreeting(objValue) && isGreeting(othValue)) {
|
|
* return true;
|
|
* }
|
|
* }
|
|
*
|
|
* var array = ['hello', 'goodbye'];
|
|
* var other = ['hi', 'goodbye'];
|
|
*
|
|
* _.isEqualWith(array, other, customizer);
|
|
* // => true
|
|
*/
|
|
function isEqualWith(value, other, customizer) {
|
|
customizer = typeof customizer == 'function' ? customizer : undefined;
|
|
var result = customizer ? customizer(value, other) : undefined;
|
|
return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
|
|
* `SyntaxError`, `TypeError`, or `URIError` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is an error object, else `false`.
|
|
* @example
|
|
*
|
|
* _.isError(new Error);
|
|
* // => true
|
|
*
|
|
* _.isError(Error);
|
|
* // => false
|
|
*/
|
|
function isError(value) {
|
|
if (!isObjectLike(value)) {
|
|
return false;
|
|
}
|
|
var tag = baseGetTag(value);
|
|
return tag == errorTag || tag == domExcTag ||
|
|
(typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a finite primitive number.
|
|
*
|
|
* **Note:** This method is based on
|
|
* [`Number.isFinite`](https://mdn.io/Number/isFinite).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
|
|
* @example
|
|
*
|
|
* _.isFinite(3);
|
|
* // => true
|
|
*
|
|
* _.isFinite(Number.MIN_VALUE);
|
|
* // => true
|
|
*
|
|
* _.isFinite(Infinity);
|
|
* // => false
|
|
*
|
|
* _.isFinite('3');
|
|
* // => false
|
|
*/
|
|
function isFinite(value) {
|
|
return typeof value == 'number' && nativeIsFinite(value);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `Function` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a function, else `false`.
|
|
* @example
|
|
*
|
|
* _.isFunction(_);
|
|
* // => true
|
|
*
|
|
* _.isFunction(/abc/);
|
|
* // => false
|
|
*/
|
|
function isFunction(value) {
|
|
if (!isObject(value)) {
|
|
return false;
|
|
}
|
|
// The use of `Object#toString` avoids issues with the `typeof` operator
|
|
// in Safari 9 which returns 'object' for typed arrays and other constructors.
|
|
var tag = baseGetTag(value);
|
|
return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is an integer.
|
|
*
|
|
* **Note:** This method is based on
|
|
* [`Number.isInteger`](https://mdn.io/Number/isInteger).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is an integer, else `false`.
|
|
* @example
|
|
*
|
|
* _.isInteger(3);
|
|
* // => true
|
|
*
|
|
* _.isInteger(Number.MIN_VALUE);
|
|
* // => false
|
|
*
|
|
* _.isInteger(Infinity);
|
|
* // => false
|
|
*
|
|
* _.isInteger('3');
|
|
* // => false
|
|
*/
|
|
function isInteger(value) {
|
|
return typeof value == 'number' && value == toInteger(value);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a valid array-like length.
|
|
*
|
|
* **Note:** This method is loosely based on
|
|
* [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
|
|
* @example
|
|
*
|
|
* _.isLength(3);
|
|
* // => true
|
|
*
|
|
* _.isLength(Number.MIN_VALUE);
|
|
* // => false
|
|
*
|
|
* _.isLength(Infinity);
|
|
* // => false
|
|
*
|
|
* _.isLength('3');
|
|
* // => false
|
|
*/
|
|
function isLength(value) {
|
|
return typeof value == 'number' &&
|
|
value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is the
|
|
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
|
|
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
|
|
* @example
|
|
*
|
|
* _.isObject({});
|
|
* // => true
|
|
*
|
|
* _.isObject([1, 2, 3]);
|
|
* // => true
|
|
*
|
|
* _.isObject(_.noop);
|
|
* // => true
|
|
*
|
|
* _.isObject(null);
|
|
* // => false
|
|
*/
|
|
function isObject(value) {
|
|
var type = typeof value;
|
|
return value != null && (type == 'object' || type == 'function');
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is object-like. A value is object-like if it's not `null`
|
|
* and has a `typeof` result of "object".
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
|
|
* @example
|
|
*
|
|
* _.isObjectLike({});
|
|
* // => true
|
|
*
|
|
* _.isObjectLike([1, 2, 3]);
|
|
* // => true
|
|
*
|
|
* _.isObjectLike(_.noop);
|
|
* // => false
|
|
*
|
|
* _.isObjectLike(null);
|
|
* // => false
|
|
*/
|
|
function isObjectLike(value) {
|
|
return value != null && typeof value == 'object';
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `Map` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.3.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a map, else `false`.
|
|
* @example
|
|
*
|
|
* _.isMap(new Map);
|
|
* // => true
|
|
*
|
|
* _.isMap(new WeakMap);
|
|
* // => false
|
|
*/
|
|
var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
|
|
|
|
/**
|
|
* Performs a partial deep comparison between `object` and `source` to
|
|
* determine if `object` contains equivalent property values.
|
|
*
|
|
* **Note:** This method is equivalent to `_.matches` when `source` is
|
|
* partially applied.
|
|
*
|
|
* Partial comparisons will match empty array and empty object `source`
|
|
* values against any array or object value, respectively. See `_.isEqual`
|
|
* for a list of supported value comparisons.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Lang
|
|
* @param {Object} object The object to inspect.
|
|
* @param {Object} source The object of property values to match.
|
|
* @returns {boolean} Returns `true` if `object` is a match, else `false`.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1, 'b': 2 };
|
|
*
|
|
* _.isMatch(object, { 'b': 2 });
|
|
* // => true
|
|
*
|
|
* _.isMatch(object, { 'b': 1 });
|
|
* // => false
|
|
*/
|
|
function isMatch(object, source) {
|
|
return object === source || baseIsMatch(object, source, getMatchData(source));
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.isMatch` except that it accepts `customizer` which
|
|
* is invoked to compare values. If `customizer` returns `undefined`, comparisons
|
|
* are handled by the method instead. The `customizer` is invoked with five
|
|
* arguments: (objValue, srcValue, index|key, object, source).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {Object} object The object to inspect.
|
|
* @param {Object} source The object of property values to match.
|
|
* @param {Function} [customizer] The function to customize comparisons.
|
|
* @returns {boolean} Returns `true` if `object` is a match, else `false`.
|
|
* @example
|
|
*
|
|
* function isGreeting(value) {
|
|
* return /^h(?:i|ello)$/.test(value);
|
|
* }
|
|
*
|
|
* function customizer(objValue, srcValue) {
|
|
* if (isGreeting(objValue) && isGreeting(srcValue)) {
|
|
* return true;
|
|
* }
|
|
* }
|
|
*
|
|
* var object = { 'greeting': 'hello' };
|
|
* var source = { 'greeting': 'hi' };
|
|
*
|
|
* _.isMatchWith(object, source, customizer);
|
|
* // => true
|
|
*/
|
|
function isMatchWith(object, source, customizer) {
|
|
customizer = typeof customizer == 'function' ? customizer : undefined;
|
|
return baseIsMatch(object, source, getMatchData(source), customizer);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is `NaN`.
|
|
*
|
|
* **Note:** This method is based on
|
|
* [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
|
|
* global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
|
|
* `undefined` and other non-number values.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
|
|
* @example
|
|
*
|
|
* _.isNaN(NaN);
|
|
* // => true
|
|
*
|
|
* _.isNaN(new Number(NaN));
|
|
* // => true
|
|
*
|
|
* isNaN(undefined);
|
|
* // => true
|
|
*
|
|
* _.isNaN(undefined);
|
|
* // => false
|
|
*/
|
|
function isNaN(value) {
|
|
// An `NaN` primitive is the only value that is not equal to itself.
|
|
// Perform the `toStringTag` check first to avoid errors with some
|
|
// ActiveX objects in IE.
|
|
return isNumber(value) && value != +value;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a pristine native function.
|
|
*
|
|
* **Note:** This method can't reliably detect native functions in the presence
|
|
* of the core-js package because core-js circumvents this kind of detection.
|
|
* Despite multiple requests, the core-js maintainer has made it clear: any
|
|
* attempt to fix the detection will be obstructed. As a result, we're left
|
|
* with little choice but to throw an error. Unfortunately, this also affects
|
|
* packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
|
|
* which rely on core-js.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a native function,
|
|
* else `false`.
|
|
* @example
|
|
*
|
|
* _.isNative(Array.prototype.push);
|
|
* // => true
|
|
*
|
|
* _.isNative(_);
|
|
* // => false
|
|
*/
|
|
function isNative(value) {
|
|
if (isMaskable(value)) {
|
|
throw new Error(CORE_ERROR_TEXT);
|
|
}
|
|
return baseIsNative(value);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is `null`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is `null`, else `false`.
|
|
* @example
|
|
*
|
|
* _.isNull(null);
|
|
* // => true
|
|
*
|
|
* _.isNull(void 0);
|
|
* // => false
|
|
*/
|
|
function isNull(value) {
|
|
return value === null;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is `null` or `undefined`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is nullish, else `false`.
|
|
* @example
|
|
*
|
|
* _.isNil(null);
|
|
* // => true
|
|
*
|
|
* _.isNil(void 0);
|
|
* // => true
|
|
*
|
|
* _.isNil(NaN);
|
|
* // => false
|
|
*/
|
|
function isNil(value) {
|
|
return value == null;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `Number` primitive or object.
|
|
*
|
|
* **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
|
|
* classified as numbers, use the `_.isFinite` method.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a number, else `false`.
|
|
* @example
|
|
*
|
|
* _.isNumber(3);
|
|
* // => true
|
|
*
|
|
* _.isNumber(Number.MIN_VALUE);
|
|
* // => true
|
|
*
|
|
* _.isNumber(Infinity);
|
|
* // => true
|
|
*
|
|
* _.isNumber('3');
|
|
* // => false
|
|
*/
|
|
function isNumber(value) {
|
|
return typeof value == 'number' ||
|
|
(isObjectLike(value) && baseGetTag(value) == numberTag);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a plain object, that is, an object created by the
|
|
* `Object` constructor or one with a `[[Prototype]]` of `null`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.8.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* }
|
|
*
|
|
* _.isPlainObject(new Foo);
|
|
* // => false
|
|
*
|
|
* _.isPlainObject([1, 2, 3]);
|
|
* // => false
|
|
*
|
|
* _.isPlainObject({ 'x': 0, 'y': 0 });
|
|
* // => true
|
|
*
|
|
* _.isPlainObject(Object.create(null));
|
|
* // => true
|
|
*/
|
|
function isPlainObject(value) {
|
|
if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
|
|
return false;
|
|
}
|
|
var proto = getPrototype(value);
|
|
if (proto === null) {
|
|
return true;
|
|
}
|
|
var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
|
|
return typeof Ctor == 'function' && Ctor instanceof Ctor &&
|
|
funcToString.call(Ctor) == objectCtorString;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `RegExp` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
|
|
* @example
|
|
*
|
|
* _.isRegExp(/abc/);
|
|
* // => true
|
|
*
|
|
* _.isRegExp('/abc/');
|
|
* // => false
|
|
*/
|
|
var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
|
|
|
|
/**
|
|
* Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
|
|
* double precision number which isn't the result of a rounded unsafe integer.
|
|
*
|
|
* **Note:** This method is based on
|
|
* [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
|
|
* @example
|
|
*
|
|
* _.isSafeInteger(3);
|
|
* // => true
|
|
*
|
|
* _.isSafeInteger(Number.MIN_VALUE);
|
|
* // => false
|
|
*
|
|
* _.isSafeInteger(Infinity);
|
|
* // => false
|
|
*
|
|
* _.isSafeInteger('3');
|
|
* // => false
|
|
*/
|
|
function isSafeInteger(value) {
|
|
return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `Set` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.3.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a set, else `false`.
|
|
* @example
|
|
*
|
|
* _.isSet(new Set);
|
|
* // => true
|
|
*
|
|
* _.isSet(new WeakSet);
|
|
* // => false
|
|
*/
|
|
var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `String` primitive or object.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a string, else `false`.
|
|
* @example
|
|
*
|
|
* _.isString('abc');
|
|
* // => true
|
|
*
|
|
* _.isString(1);
|
|
* // => false
|
|
*/
|
|
function isString(value) {
|
|
return typeof value == 'string' ||
|
|
(!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `Symbol` primitive or object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
|
|
* @example
|
|
*
|
|
* _.isSymbol(Symbol.iterator);
|
|
* // => true
|
|
*
|
|
* _.isSymbol('abc');
|
|
* // => false
|
|
*/
|
|
function isSymbol(value) {
|
|
return typeof value == 'symbol' ||
|
|
(isObjectLike(value) && baseGetTag(value) == symbolTag);
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is classified as a typed array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
|
|
* @example
|
|
*
|
|
* _.isTypedArray(new Uint8Array);
|
|
* // => true
|
|
*
|
|
* _.isTypedArray([]);
|
|
* // => false
|
|
*/
|
|
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
|
|
|
|
/**
|
|
* Checks if `value` is `undefined`.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
|
|
* @example
|
|
*
|
|
* _.isUndefined(void 0);
|
|
* // => true
|
|
*
|
|
* _.isUndefined(null);
|
|
* // => false
|
|
*/
|
|
function isUndefined(value) {
|
|
return value === undefined;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `WeakMap` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.3.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
|
|
* @example
|
|
*
|
|
* _.isWeakMap(new WeakMap);
|
|
* // => true
|
|
*
|
|
* _.isWeakMap(new Map);
|
|
* // => false
|
|
*/
|
|
function isWeakMap(value) {
|
|
return isObjectLike(value) && getTag(value) == weakMapTag;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `WeakSet` object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.3.0
|
|
* @category Lang
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
|
|
* @example
|
|
*
|
|
* _.isWeakSet(new WeakSet);
|
|
* // => true
|
|
*
|
|
* _.isWeakSet(new Set);
|
|
* // => false
|
|
*/
|
|
function isWeakSet(value) {
|
|
return isObjectLike(value) && baseGetTag(value) == weakSetTag;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is less than `other`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.9.0
|
|
* @category Lang
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @returns {boolean} Returns `true` if `value` is less than `other`,
|
|
* else `false`.
|
|
* @see _.gt
|
|
* @example
|
|
*
|
|
* _.lt(1, 3);
|
|
* // => true
|
|
*
|
|
* _.lt(3, 3);
|
|
* // => false
|
|
*
|
|
* _.lt(3, 1);
|
|
* // => false
|
|
*/
|
|
var lt = createRelationalOperation(baseLt);
|
|
|
|
/**
|
|
* Checks if `value` is less than or equal to `other`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.9.0
|
|
* @category Lang
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @returns {boolean} Returns `true` if `value` is less than or equal to
|
|
* `other`, else `false`.
|
|
* @see _.gte
|
|
* @example
|
|
*
|
|
* _.lte(1, 3);
|
|
* // => true
|
|
*
|
|
* _.lte(3, 3);
|
|
* // => true
|
|
*
|
|
* _.lte(3, 1);
|
|
* // => false
|
|
*/
|
|
var lte = createRelationalOperation(function(value, other) {
|
|
return value <= other;
|
|
});
|
|
|
|
/**
|
|
* Converts `value` to an array.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Lang
|
|
* @param {*} value The value to convert.
|
|
* @returns {Array} Returns the converted array.
|
|
* @example
|
|
*
|
|
* _.toArray({ 'a': 1, 'b': 2 });
|
|
* // => [1, 2]
|
|
*
|
|
* _.toArray('abc');
|
|
* // => ['a', 'b', 'c']
|
|
*
|
|
* _.toArray(1);
|
|
* // => []
|
|
*
|
|
* _.toArray(null);
|
|
* // => []
|
|
*/
|
|
function toArray(value) {
|
|
if (!value) {
|
|
return [];
|
|
}
|
|
if (isArrayLike(value)) {
|
|
return isString(value) ? stringToArray(value) : copyArray(value);
|
|
}
|
|
if (symIterator && value[symIterator]) {
|
|
return iteratorToArray(value[symIterator]());
|
|
}
|
|
var tag = getTag(value),
|
|
func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
|
|
|
|
return func(value);
|
|
}
|
|
|
|
/**
|
|
* Converts `value` to a finite number.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.12.0
|
|
* @category Lang
|
|
* @param {*} value The value to convert.
|
|
* @returns {number} Returns the converted number.
|
|
* @example
|
|
*
|
|
* _.toFinite(3.2);
|
|
* // => 3.2
|
|
*
|
|
* _.toFinite(Number.MIN_VALUE);
|
|
* // => 5e-324
|
|
*
|
|
* _.toFinite(Infinity);
|
|
* // => 1.7976931348623157e+308
|
|
*
|
|
* _.toFinite('3.2');
|
|
* // => 3.2
|
|
*/
|
|
function toFinite(value) {
|
|
if (!value) {
|
|
return value === 0 ? value : 0;
|
|
}
|
|
value = toNumber(value);
|
|
if (value === INFINITY || value === -INFINITY) {
|
|
var sign = (value < 0 ? -1 : 1);
|
|
return sign * MAX_INTEGER;
|
|
}
|
|
return value === value ? value : 0;
|
|
}
|
|
|
|
/**
|
|
* Converts `value` to an integer.
|
|
*
|
|
* **Note:** This method is loosely based on
|
|
* [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to convert.
|
|
* @returns {number} Returns the converted integer.
|
|
* @example
|
|
*
|
|
* _.toInteger(3.2);
|
|
* // => 3
|
|
*
|
|
* _.toInteger(Number.MIN_VALUE);
|
|
* // => 0
|
|
*
|
|
* _.toInteger(Infinity);
|
|
* // => 1.7976931348623157e+308
|
|
*
|
|
* _.toInteger('3.2');
|
|
* // => 3
|
|
*/
|
|
function toInteger(value) {
|
|
var result = toFinite(value),
|
|
remainder = result % 1;
|
|
|
|
return result === result ? (remainder ? result - remainder : result) : 0;
|
|
}
|
|
|
|
/**
|
|
* Converts `value` to an integer suitable for use as the length of an
|
|
* array-like object.
|
|
*
|
|
* **Note:** This method is based on
|
|
* [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to convert.
|
|
* @returns {number} Returns the converted integer.
|
|
* @example
|
|
*
|
|
* _.toLength(3.2);
|
|
* // => 3
|
|
*
|
|
* _.toLength(Number.MIN_VALUE);
|
|
* // => 0
|
|
*
|
|
* _.toLength(Infinity);
|
|
* // => 4294967295
|
|
*
|
|
* _.toLength('3.2');
|
|
* // => 3
|
|
*/
|
|
function toLength(value) {
|
|
return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
|
|
}
|
|
|
|
/**
|
|
* Converts `value` to a number.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to process.
|
|
* @returns {number} Returns the number.
|
|
* @example
|
|
*
|
|
* _.toNumber(3.2);
|
|
* // => 3.2
|
|
*
|
|
* _.toNumber(Number.MIN_VALUE);
|
|
* // => 5e-324
|
|
*
|
|
* _.toNumber(Infinity);
|
|
* // => Infinity
|
|
*
|
|
* _.toNumber('3.2');
|
|
* // => 3.2
|
|
*/
|
|
function toNumber(value) {
|
|
if (typeof value == 'number') {
|
|
return value;
|
|
}
|
|
if (isSymbol(value)) {
|
|
return NAN;
|
|
}
|
|
if (isObject(value)) {
|
|
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
|
|
value = isObject(other) ? (other + '') : other;
|
|
}
|
|
if (typeof value != 'string') {
|
|
return value === 0 ? value : +value;
|
|
}
|
|
value = value.replace(reTrim, '');
|
|
var isBinary = reIsBinary.test(value);
|
|
return (isBinary || reIsOctal.test(value))
|
|
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
|
|
: (reIsBadHex.test(value) ? NAN : +value);
|
|
}
|
|
|
|
/**
|
|
* Converts `value` to a plain object flattening inherited enumerable string
|
|
* keyed properties of `value` to own properties of the plain object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to convert.
|
|
* @returns {Object} Returns the converted plain object.
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.b = 2;
|
|
* }
|
|
*
|
|
* Foo.prototype.c = 3;
|
|
*
|
|
* _.assign({ 'a': 1 }, new Foo);
|
|
* // => { 'a': 1, 'b': 2 }
|
|
*
|
|
* _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
|
|
* // => { 'a': 1, 'b': 2, 'c': 3 }
|
|
*/
|
|
function toPlainObject(value) {
|
|
return copyObject(value, keysIn(value));
|
|
}
|
|
|
|
/**
|
|
* Converts `value` to a safe integer. A safe integer can be compared and
|
|
* represented correctly.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to convert.
|
|
* @returns {number} Returns the converted integer.
|
|
* @example
|
|
*
|
|
* _.toSafeInteger(3.2);
|
|
* // => 3
|
|
*
|
|
* _.toSafeInteger(Number.MIN_VALUE);
|
|
* // => 0
|
|
*
|
|
* _.toSafeInteger(Infinity);
|
|
* // => 9007199254740991
|
|
*
|
|
* _.toSafeInteger('3.2');
|
|
* // => 3
|
|
*/
|
|
function toSafeInteger(value) {
|
|
return value
|
|
? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)
|
|
: (value === 0 ? value : 0);
|
|
}
|
|
|
|
/**
|
|
* Converts `value` to a string. An empty string is returned for `null`
|
|
* and `undefined` values. The sign of `-0` is preserved.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Lang
|
|
* @param {*} value The value to convert.
|
|
* @returns {string} Returns the converted string.
|
|
* @example
|
|
*
|
|
* _.toString(null);
|
|
* // => ''
|
|
*
|
|
* _.toString(-0);
|
|
* // => '-0'
|
|
*
|
|
* _.toString([1, 2, 3]);
|
|
* // => '1,2,3'
|
|
*/
|
|
function toString(value) {
|
|
return value == null ? '' : baseToString(value);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Assigns own enumerable string keyed properties of source objects to the
|
|
* destination object. Source objects are applied from left to right.
|
|
* Subsequent sources overwrite property assignments of previous sources.
|
|
*
|
|
* **Note:** This method mutates `object` and is loosely based on
|
|
* [`Object.assign`](https://mdn.io/Object/assign).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.10.0
|
|
* @category Object
|
|
* @param {Object} object The destination object.
|
|
* @param {...Object} [sources] The source objects.
|
|
* @returns {Object} Returns `object`.
|
|
* @see _.assignIn
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* }
|
|
*
|
|
* function Bar() {
|
|
* this.c = 3;
|
|
* }
|
|
*
|
|
* Foo.prototype.b = 2;
|
|
* Bar.prototype.d = 4;
|
|
*
|
|
* _.assign({ 'a': 0 }, new Foo, new Bar);
|
|
* // => { 'a': 1, 'c': 3 }
|
|
*/
|
|
var assign = createAssigner(function(object, source) {
|
|
if (isPrototype(source) || isArrayLike(source)) {
|
|
copyObject(source, keys(source), object);
|
|
return;
|
|
}
|
|
for (var key in source) {
|
|
if (hasOwnProperty.call(source, key)) {
|
|
assignValue(object, key, source[key]);
|
|
}
|
|
}
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.assign` except that it iterates over own and
|
|
* inherited source properties.
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @alias extend
|
|
* @category Object
|
|
* @param {Object} object The destination object.
|
|
* @param {...Object} [sources] The source objects.
|
|
* @returns {Object} Returns `object`.
|
|
* @see _.assign
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* }
|
|
*
|
|
* function Bar() {
|
|
* this.c = 3;
|
|
* }
|
|
*
|
|
* Foo.prototype.b = 2;
|
|
* Bar.prototype.d = 4;
|
|
*
|
|
* _.assignIn({ 'a': 0 }, new Foo, new Bar);
|
|
* // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
|
|
*/
|
|
var assignIn = createAssigner(function(object, source) {
|
|
copyObject(source, keysIn(source), object);
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.assignIn` except that it accepts `customizer`
|
|
* which is invoked to produce the assigned values. If `customizer` returns
|
|
* `undefined`, assignment is handled by the method instead. The `customizer`
|
|
* is invoked with five arguments: (objValue, srcValue, key, object, source).
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @alias extendWith
|
|
* @category Object
|
|
* @param {Object} object The destination object.
|
|
* @param {...Object} sources The source objects.
|
|
* @param {Function} [customizer] The function to customize assigned values.
|
|
* @returns {Object} Returns `object`.
|
|
* @see _.assignWith
|
|
* @example
|
|
*
|
|
* function customizer(objValue, srcValue) {
|
|
* return _.isUndefined(objValue) ? srcValue : objValue;
|
|
* }
|
|
*
|
|
* var defaults = _.partialRight(_.assignInWith, customizer);
|
|
*
|
|
* defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
|
|
* // => { 'a': 1, 'b': 2 }
|
|
*/
|
|
var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
|
|
copyObject(source, keysIn(source), object, customizer);
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.assign` except that it accepts `customizer`
|
|
* which is invoked to produce the assigned values. If `customizer` returns
|
|
* `undefined`, assignment is handled by the method instead. The `customizer`
|
|
* is invoked with five arguments: (objValue, srcValue, key, object, source).
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Object
|
|
* @param {Object} object The destination object.
|
|
* @param {...Object} sources The source objects.
|
|
* @param {Function} [customizer] The function to customize assigned values.
|
|
* @returns {Object} Returns `object`.
|
|
* @see _.assignInWith
|
|
* @example
|
|
*
|
|
* function customizer(objValue, srcValue) {
|
|
* return _.isUndefined(objValue) ? srcValue : objValue;
|
|
* }
|
|
*
|
|
* var defaults = _.partialRight(_.assignWith, customizer);
|
|
*
|
|
* defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
|
|
* // => { 'a': 1, 'b': 2 }
|
|
*/
|
|
var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
|
|
copyObject(source, keys(source), object, customizer);
|
|
});
|
|
|
|
/**
|
|
* Creates an array of values corresponding to `paths` of `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 1.0.0
|
|
* @category Object
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {...(string|string[])} [paths] The property paths to pick.
|
|
* @returns {Array} Returns the picked values.
|
|
* @example
|
|
*
|
|
* var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
|
|
*
|
|
* _.at(object, ['a[0].b.c', 'a[1]']);
|
|
* // => [3, 4]
|
|
*/
|
|
var at = flatRest(baseAt);
|
|
|
|
/**
|
|
* Creates an object that inherits from the `prototype` object. If a
|
|
* `properties` object is given, its own enumerable string keyed properties
|
|
* are assigned to the created object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.3.0
|
|
* @category Object
|
|
* @param {Object} prototype The object to inherit from.
|
|
* @param {Object} [properties] The properties to assign to the object.
|
|
* @returns {Object} Returns the new object.
|
|
* @example
|
|
*
|
|
* function Shape() {
|
|
* this.x = 0;
|
|
* this.y = 0;
|
|
* }
|
|
*
|
|
* function Circle() {
|
|
* Shape.call(this);
|
|
* }
|
|
*
|
|
* Circle.prototype = _.create(Shape.prototype, {
|
|
* 'constructor': Circle
|
|
* });
|
|
*
|
|
* var circle = new Circle;
|
|
* circle instanceof Circle;
|
|
* // => true
|
|
*
|
|
* circle instanceof Shape;
|
|
* // => true
|
|
*/
|
|
function create(prototype, properties) {
|
|
var result = baseCreate(prototype);
|
|
return properties == null ? result : baseAssign(result, properties);
|
|
}
|
|
|
|
/**
|
|
* Assigns own and inherited enumerable string keyed properties of source
|
|
* objects to the destination object for all destination properties that
|
|
* resolve to `undefined`. Source objects are applied from left to right.
|
|
* Once a property is set, additional values of the same property are ignored.
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Object
|
|
* @param {Object} object The destination object.
|
|
* @param {...Object} [sources] The source objects.
|
|
* @returns {Object} Returns `object`.
|
|
* @see _.defaultsDeep
|
|
* @example
|
|
*
|
|
* _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
|
|
* // => { 'a': 1, 'b': 2 }
|
|
*/
|
|
var defaults = baseRest(function(object, sources) {
|
|
object = Object(object);
|
|
|
|
var index = -1;
|
|
var length = sources.length;
|
|
var guard = length > 2 ? sources[2] : undefined;
|
|
|
|
if (guard && isIterateeCall(sources[0], sources[1], guard)) {
|
|
length = 1;
|
|
}
|
|
|
|
while (++index < length) {
|
|
var source = sources[index];
|
|
var props = keysIn(source);
|
|
var propsIndex = -1;
|
|
var propsLength = props.length;
|
|
|
|
while (++propsIndex < propsLength) {
|
|
var key = props[propsIndex];
|
|
var value = object[key];
|
|
|
|
if (value === undefined ||
|
|
(eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {
|
|
object[key] = source[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
return object;
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.defaults` except that it recursively assigns
|
|
* default properties.
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.10.0
|
|
* @category Object
|
|
* @param {Object} object The destination object.
|
|
* @param {...Object} [sources] The source objects.
|
|
* @returns {Object} Returns `object`.
|
|
* @see _.defaults
|
|
* @example
|
|
*
|
|
* _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
|
|
* // => { 'a': { 'b': 2, 'c': 3 } }
|
|
*/
|
|
var defaultsDeep = baseRest(function(args) {
|
|
args.push(undefined, customDefaultsMerge);
|
|
return apply(mergeWith, undefined, args);
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.find` except that it returns the key of the first
|
|
* element `predicate` returns truthy for instead of the element itself.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 1.1.0
|
|
* @category Object
|
|
* @param {Object} object The object to inspect.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @returns {string|undefined} Returns the key of the matched element,
|
|
* else `undefined`.
|
|
* @example
|
|
*
|
|
* var users = {
|
|
* 'barney': { 'age': 36, 'active': true },
|
|
* 'fred': { 'age': 40, 'active': false },
|
|
* 'pebbles': { 'age': 1, 'active': true }
|
|
* };
|
|
*
|
|
* _.findKey(users, function(o) { return o.age < 40; });
|
|
* // => 'barney' (iteration order is not guaranteed)
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.findKey(users, { 'age': 1, 'active': true });
|
|
* // => 'pebbles'
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.findKey(users, ['active', false]);
|
|
* // => 'fred'
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.findKey(users, 'active');
|
|
* // => 'barney'
|
|
*/
|
|
function findKey(object, predicate) {
|
|
return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.findKey` except that it iterates over elements of
|
|
* a collection in the opposite order.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.0.0
|
|
* @category Object
|
|
* @param {Object} object The object to inspect.
|
|
* @param {Function} [predicate=_.identity] The function invoked per iteration.
|
|
* @returns {string|undefined} Returns the key of the matched element,
|
|
* else `undefined`.
|
|
* @example
|
|
*
|
|
* var users = {
|
|
* 'barney': { 'age': 36, 'active': true },
|
|
* 'fred': { 'age': 40, 'active': false },
|
|
* 'pebbles': { 'age': 1, 'active': true }
|
|
* };
|
|
*
|
|
* _.findLastKey(users, function(o) { return o.age < 40; });
|
|
* // => returns 'pebbles' assuming `_.findKey` returns 'barney'
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.findLastKey(users, { 'age': 36, 'active': true });
|
|
* // => 'barney'
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.findLastKey(users, ['active', false]);
|
|
* // => 'fred'
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.findLastKey(users, 'active');
|
|
* // => 'pebbles'
|
|
*/
|
|
function findLastKey(object, predicate) {
|
|
return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
|
|
}
|
|
|
|
/**
|
|
* Iterates over own and inherited enumerable string keyed properties of an
|
|
* object and invokes `iteratee` for each property. The iteratee is invoked
|
|
* with three arguments: (value, key, object). Iteratee functions may exit
|
|
* iteration early by explicitly returning `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.3.0
|
|
* @category Object
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Object} Returns `object`.
|
|
* @see _.forInRight
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* this.b = 2;
|
|
* }
|
|
*
|
|
* Foo.prototype.c = 3;
|
|
*
|
|
* _.forIn(new Foo, function(value, key) {
|
|
* console.log(key);
|
|
* });
|
|
* // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
|
|
*/
|
|
function forIn(object, iteratee) {
|
|
return object == null
|
|
? object
|
|
: baseFor(object, getIteratee(iteratee, 3), keysIn);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.forIn` except that it iterates over properties of
|
|
* `object` in the opposite order.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.0.0
|
|
* @category Object
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Object} Returns `object`.
|
|
* @see _.forIn
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* this.b = 2;
|
|
* }
|
|
*
|
|
* Foo.prototype.c = 3;
|
|
*
|
|
* _.forInRight(new Foo, function(value, key) {
|
|
* console.log(key);
|
|
* });
|
|
* // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
|
|
*/
|
|
function forInRight(object, iteratee) {
|
|
return object == null
|
|
? object
|
|
: baseForRight(object, getIteratee(iteratee, 3), keysIn);
|
|
}
|
|
|
|
/**
|
|
* Iterates over own enumerable string keyed properties of an object and
|
|
* invokes `iteratee` for each property. The iteratee is invoked with three
|
|
* arguments: (value, key, object). Iteratee functions may exit iteration
|
|
* early by explicitly returning `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.3.0
|
|
* @category Object
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Object} Returns `object`.
|
|
* @see _.forOwnRight
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* this.b = 2;
|
|
* }
|
|
*
|
|
* Foo.prototype.c = 3;
|
|
*
|
|
* _.forOwn(new Foo, function(value, key) {
|
|
* console.log(key);
|
|
* });
|
|
* // => Logs 'a' then 'b' (iteration order is not guaranteed).
|
|
*/
|
|
function forOwn(object, iteratee) {
|
|
return object && baseForOwn(object, getIteratee(iteratee, 3));
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.forOwn` except that it iterates over properties of
|
|
* `object` in the opposite order.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.0.0
|
|
* @category Object
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Object} Returns `object`.
|
|
* @see _.forOwn
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* this.b = 2;
|
|
* }
|
|
*
|
|
* Foo.prototype.c = 3;
|
|
*
|
|
* _.forOwnRight(new Foo, function(value, key) {
|
|
* console.log(key);
|
|
* });
|
|
* // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
|
|
*/
|
|
function forOwnRight(object, iteratee) {
|
|
return object && baseForOwnRight(object, getIteratee(iteratee, 3));
|
|
}
|
|
|
|
/**
|
|
* Creates an array of function property names from own enumerable properties
|
|
* of `object`.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Object
|
|
* @param {Object} object The object to inspect.
|
|
* @returns {Array} Returns the function names.
|
|
* @see _.functionsIn
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = _.constant('a');
|
|
* this.b = _.constant('b');
|
|
* }
|
|
*
|
|
* Foo.prototype.c = _.constant('c');
|
|
*
|
|
* _.functions(new Foo);
|
|
* // => ['a', 'b']
|
|
*/
|
|
function functions(object) {
|
|
return object == null ? [] : baseFunctions(object, keys(object));
|
|
}
|
|
|
|
/**
|
|
* Creates an array of function property names from own and inherited
|
|
* enumerable properties of `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Object
|
|
* @param {Object} object The object to inspect.
|
|
* @returns {Array} Returns the function names.
|
|
* @see _.functions
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = _.constant('a');
|
|
* this.b = _.constant('b');
|
|
* }
|
|
*
|
|
* Foo.prototype.c = _.constant('c');
|
|
*
|
|
* _.functionsIn(new Foo);
|
|
* // => ['a', 'b', 'c']
|
|
*/
|
|
function functionsIn(object) {
|
|
return object == null ? [] : baseFunctions(object, keysIn(object));
|
|
}
|
|
|
|
/**
|
|
* Gets the value at `path` of `object`. If the resolved value is
|
|
* `undefined`, the `defaultValue` is returned in its place.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.7.0
|
|
* @category Object
|
|
* @param {Object} object The object to query.
|
|
* @param {Array|string} path The path of the property to get.
|
|
* @param {*} [defaultValue] The value returned for `undefined` resolved values.
|
|
* @returns {*} Returns the resolved value.
|
|
* @example
|
|
*
|
|
* var object = { 'a': [{ 'b': { 'c': 3 } }] };
|
|
*
|
|
* _.get(object, 'a[0].b.c');
|
|
* // => 3
|
|
*
|
|
* _.get(object, ['a', '0', 'b', 'c']);
|
|
* // => 3
|
|
*
|
|
* _.get(object, 'a.b.c', 'default');
|
|
* // => 'default'
|
|
*/
|
|
function get(object, path, defaultValue) {
|
|
var result = object == null ? undefined : baseGet(object, path);
|
|
return result === undefined ? defaultValue : result;
|
|
}
|
|
|
|
/**
|
|
* Checks if `path` is a direct property of `object`.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Object
|
|
* @param {Object} object The object to query.
|
|
* @param {Array|string} path The path to check.
|
|
* @returns {boolean} Returns `true` if `path` exists, else `false`.
|
|
* @example
|
|
*
|
|
* var object = { 'a': { 'b': 2 } };
|
|
* var other = _.create({ 'a': _.create({ 'b': 2 }) });
|
|
*
|
|
* _.has(object, 'a');
|
|
* // => true
|
|
*
|
|
* _.has(object, 'a.b');
|
|
* // => true
|
|
*
|
|
* _.has(object, ['a', 'b']);
|
|
* // => true
|
|
*
|
|
* _.has(other, 'a');
|
|
* // => false
|
|
*/
|
|
function has(object, path) {
|
|
return object != null && hasPath(object, path, baseHas);
|
|
}
|
|
|
|
/**
|
|
* Checks if `path` is a direct or inherited property of `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Object
|
|
* @param {Object} object The object to query.
|
|
* @param {Array|string} path The path to check.
|
|
* @returns {boolean} Returns `true` if `path` exists, else `false`.
|
|
* @example
|
|
*
|
|
* var object = _.create({ 'a': _.create({ 'b': 2 }) });
|
|
*
|
|
* _.hasIn(object, 'a');
|
|
* // => true
|
|
*
|
|
* _.hasIn(object, 'a.b');
|
|
* // => true
|
|
*
|
|
* _.hasIn(object, ['a', 'b']);
|
|
* // => true
|
|
*
|
|
* _.hasIn(object, 'b');
|
|
* // => false
|
|
*/
|
|
function hasIn(object, path) {
|
|
return object != null && hasPath(object, path, baseHasIn);
|
|
}
|
|
|
|
/**
|
|
* Creates an object composed of the inverted keys and values of `object`.
|
|
* If `object` contains duplicate values, subsequent values overwrite
|
|
* property assignments of previous values.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.7.0
|
|
* @category Object
|
|
* @param {Object} object The object to invert.
|
|
* @returns {Object} Returns the new inverted object.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1, 'b': 2, 'c': 1 };
|
|
*
|
|
* _.invert(object);
|
|
* // => { '1': 'c', '2': 'b' }
|
|
*/
|
|
var invert = createInverter(function(result, value, key) {
|
|
if (value != null &&
|
|
typeof value.toString != 'function') {
|
|
value = nativeObjectToString.call(value);
|
|
}
|
|
|
|
result[value] = key;
|
|
}, constant(identity));
|
|
|
|
/**
|
|
* This method is like `_.invert` except that the inverted object is generated
|
|
* from the results of running each element of `object` thru `iteratee`. The
|
|
* corresponding inverted value of each inverted key is an array of keys
|
|
* responsible for generating the inverted value. The iteratee is invoked
|
|
* with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.1.0
|
|
* @category Object
|
|
* @param {Object} object The object to invert.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {Object} Returns the new inverted object.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1, 'b': 2, 'c': 1 };
|
|
*
|
|
* _.invertBy(object);
|
|
* // => { '1': ['a', 'c'], '2': ['b'] }
|
|
*
|
|
* _.invertBy(object, function(value) {
|
|
* return 'group' + value;
|
|
* });
|
|
* // => { 'group1': ['a', 'c'], 'group2': ['b'] }
|
|
*/
|
|
var invertBy = createInverter(function(result, value, key) {
|
|
if (value != null &&
|
|
typeof value.toString != 'function') {
|
|
value = nativeObjectToString.call(value);
|
|
}
|
|
|
|
if (hasOwnProperty.call(result, value)) {
|
|
result[value].push(key);
|
|
} else {
|
|
result[value] = [key];
|
|
}
|
|
}, getIteratee);
|
|
|
|
/**
|
|
* Invokes the method at `path` of `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Object
|
|
* @param {Object} object The object to query.
|
|
* @param {Array|string} path The path of the method to invoke.
|
|
* @param {...*} [args] The arguments to invoke the method with.
|
|
* @returns {*} Returns the result of the invoked method.
|
|
* @example
|
|
*
|
|
* var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
|
|
*
|
|
* _.invoke(object, 'a[0].b.c.slice', 1, 3);
|
|
* // => [2, 3]
|
|
*/
|
|
var invoke = baseRest(baseInvoke);
|
|
|
|
/**
|
|
* Creates an array of the own enumerable property names of `object`.
|
|
*
|
|
* **Note:** Non-object values are coerced to objects. See the
|
|
* [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
|
|
* for more details.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Object
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property names.
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* this.b = 2;
|
|
* }
|
|
*
|
|
* Foo.prototype.c = 3;
|
|
*
|
|
* _.keys(new Foo);
|
|
* // => ['a', 'b'] (iteration order is not guaranteed)
|
|
*
|
|
* _.keys('hi');
|
|
* // => ['0', '1']
|
|
*/
|
|
function keys(object) {
|
|
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
|
|
}
|
|
|
|
/**
|
|
* Creates an array of the own and inherited enumerable property names of `object`.
|
|
*
|
|
* **Note:** Non-object values are coerced to objects.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Object
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property names.
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* this.b = 2;
|
|
* }
|
|
*
|
|
* Foo.prototype.c = 3;
|
|
*
|
|
* _.keysIn(new Foo);
|
|
* // => ['a', 'b', 'c'] (iteration order is not guaranteed)
|
|
*/
|
|
function keysIn(object) {
|
|
return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
|
|
}
|
|
|
|
/**
|
|
* The opposite of `_.mapValues`; this method creates an object with the
|
|
* same values as `object` and keys generated by running each own enumerable
|
|
* string keyed property of `object` thru `iteratee`. The iteratee is invoked
|
|
* with three arguments: (value, key, object).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.8.0
|
|
* @category Object
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Object} Returns the new mapped object.
|
|
* @see _.mapValues
|
|
* @example
|
|
*
|
|
* _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
|
|
* return key + value;
|
|
* });
|
|
* // => { 'a1': 1, 'b2': 2 }
|
|
*/
|
|
function mapKeys(object, iteratee) {
|
|
var result = {};
|
|
iteratee = getIteratee(iteratee, 3);
|
|
|
|
baseForOwn(object, function(value, key, object) {
|
|
baseAssignValue(result, iteratee(value, key, object), value);
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates an object with the same keys as `object` and values generated
|
|
* by running each own enumerable string keyed property of `object` thru
|
|
* `iteratee`. The iteratee is invoked with three arguments:
|
|
* (value, key, object).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.4.0
|
|
* @category Object
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Object} Returns the new mapped object.
|
|
* @see _.mapKeys
|
|
* @example
|
|
*
|
|
* var users = {
|
|
* 'fred': { 'user': 'fred', 'age': 40 },
|
|
* 'pebbles': { 'user': 'pebbles', 'age': 1 }
|
|
* };
|
|
*
|
|
* _.mapValues(users, function(o) { return o.age; });
|
|
* // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.mapValues(users, 'age');
|
|
* // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
|
|
*/
|
|
function mapValues(object, iteratee) {
|
|
var result = {};
|
|
iteratee = getIteratee(iteratee, 3);
|
|
|
|
baseForOwn(object, function(value, key, object) {
|
|
baseAssignValue(result, key, iteratee(value, key, object));
|
|
});
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.assign` except that it recursively merges own and
|
|
* inherited enumerable string keyed properties of source objects into the
|
|
* destination object. Source properties that resolve to `undefined` are
|
|
* skipped if a destination value exists. Array and plain object properties
|
|
* are merged recursively. Other objects and value types are overridden by
|
|
* assignment. Source objects are applied from left to right. Subsequent
|
|
* sources overwrite property assignments of previous sources.
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.5.0
|
|
* @category Object
|
|
* @param {Object} object The destination object.
|
|
* @param {...Object} [sources] The source objects.
|
|
* @returns {Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* var object = {
|
|
* 'a': [{ 'b': 2 }, { 'd': 4 }]
|
|
* };
|
|
*
|
|
* var other = {
|
|
* 'a': [{ 'c': 3 }, { 'e': 5 }]
|
|
* };
|
|
*
|
|
* _.merge(object, other);
|
|
* // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
|
|
*/
|
|
var merge = createAssigner(function(object, source, srcIndex) {
|
|
baseMerge(object, source, srcIndex);
|
|
});
|
|
|
|
/**
|
|
* This method is like `_.merge` except that it accepts `customizer` which
|
|
* is invoked to produce the merged values of the destination and source
|
|
* properties. If `customizer` returns `undefined`, merging is handled by the
|
|
* method instead. The `customizer` is invoked with six arguments:
|
|
* (objValue, srcValue, key, object, source, stack).
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Object
|
|
* @param {Object} object The destination object.
|
|
* @param {...Object} sources The source objects.
|
|
* @param {Function} customizer The function to customize assigned values.
|
|
* @returns {Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* function customizer(objValue, srcValue) {
|
|
* if (_.isArray(objValue)) {
|
|
* return objValue.concat(srcValue);
|
|
* }
|
|
* }
|
|
*
|
|
* var object = { 'a': [1], 'b': [2] };
|
|
* var other = { 'a': [3], 'b': [4] };
|
|
*
|
|
* _.mergeWith(object, other, customizer);
|
|
* // => { 'a': [1, 3], 'b': [2, 4] }
|
|
*/
|
|
var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
|
|
baseMerge(object, source, srcIndex, customizer);
|
|
});
|
|
|
|
/**
|
|
* The opposite of `_.pick`; this method creates an object composed of the
|
|
* own and inherited enumerable property paths of `object` that are not omitted.
|
|
*
|
|
* **Note:** This method is considerably slower than `_.pick`.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Object
|
|
* @param {Object} object The source object.
|
|
* @param {...(string|string[])} [paths] The property paths to omit.
|
|
* @returns {Object} Returns the new object.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1, 'b': '2', 'c': 3 };
|
|
*
|
|
* _.omit(object, ['a', 'c']);
|
|
* // => { 'b': '2' }
|
|
*/
|
|
var omit = flatRest(function(object, paths) {
|
|
var result = {};
|
|
if (object == null) {
|
|
return result;
|
|
}
|
|
var isDeep = false;
|
|
paths = arrayMap(paths, function(path) {
|
|
path = castPath(path, object);
|
|
isDeep || (isDeep = path.length > 1);
|
|
return path;
|
|
});
|
|
copyObject(object, getAllKeysIn(object), result);
|
|
if (isDeep) {
|
|
result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
|
|
}
|
|
var length = paths.length;
|
|
while (length--) {
|
|
baseUnset(result, paths[length]);
|
|
}
|
|
return result;
|
|
});
|
|
|
|
/**
|
|
* The opposite of `_.pickBy`; this method creates an object composed of
|
|
* the own and inherited enumerable string keyed properties of `object` that
|
|
* `predicate` doesn't return truthy for. The predicate is invoked with two
|
|
* arguments: (value, key).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Object
|
|
* @param {Object} object The source object.
|
|
* @param {Function} [predicate=_.identity] The function invoked per property.
|
|
* @returns {Object} Returns the new object.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1, 'b': '2', 'c': 3 };
|
|
*
|
|
* _.omitBy(object, _.isNumber);
|
|
* // => { 'b': '2' }
|
|
*/
|
|
function omitBy(object, predicate) {
|
|
return pickBy(object, negate(getIteratee(predicate)));
|
|
}
|
|
|
|
/**
|
|
* Creates an object composed of the picked `object` properties.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Object
|
|
* @param {Object} object The source object.
|
|
* @param {...(string|string[])} [paths] The property paths to pick.
|
|
* @returns {Object} Returns the new object.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1, 'b': '2', 'c': 3 };
|
|
*
|
|
* _.pick(object, ['a', 'c']);
|
|
* // => { 'a': 1, 'c': 3 }
|
|
*/
|
|
var pick = flatRest(function(object, paths) {
|
|
return object == null ? {} : basePick(object, paths);
|
|
});
|
|
|
|
/**
|
|
* Creates an object composed of the `object` properties `predicate` returns
|
|
* truthy for. The predicate is invoked with two arguments: (value, key).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Object
|
|
* @param {Object} object The source object.
|
|
* @param {Function} [predicate=_.identity] The function invoked per property.
|
|
* @returns {Object} Returns the new object.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1, 'b': '2', 'c': 3 };
|
|
*
|
|
* _.pickBy(object, _.isNumber);
|
|
* // => { 'a': 1, 'c': 3 }
|
|
*/
|
|
function pickBy(object, predicate) {
|
|
if (object == null) {
|
|
return {};
|
|
}
|
|
var props = arrayMap(getAllKeysIn(object), function(prop) {
|
|
return [prop];
|
|
});
|
|
predicate = getIteratee(predicate);
|
|
return basePickBy(object, props, function(value, path) {
|
|
return predicate(value, path[0]);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.get` except that if the resolved value is a
|
|
* function it's invoked with the `this` binding of its parent object and
|
|
* its result is returned.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Object
|
|
* @param {Object} object The object to query.
|
|
* @param {Array|string} path The path of the property to resolve.
|
|
* @param {*} [defaultValue] The value returned for `undefined` resolved values.
|
|
* @returns {*} Returns the resolved value.
|
|
* @example
|
|
*
|
|
* var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
|
|
*
|
|
* _.result(object, 'a[0].b.c1');
|
|
* // => 3
|
|
*
|
|
* _.result(object, 'a[0].b.c2');
|
|
* // => 4
|
|
*
|
|
* _.result(object, 'a[0].b.c3', 'default');
|
|
* // => 'default'
|
|
*
|
|
* _.result(object, 'a[0].b.c3', _.constant('default'));
|
|
* // => 'default'
|
|
*/
|
|
function result(object, path, defaultValue) {
|
|
path = castPath(path, object);
|
|
|
|
var index = -1,
|
|
length = path.length;
|
|
|
|
// Ensure the loop is entered when path is empty.
|
|
if (!length) {
|
|
length = 1;
|
|
object = undefined;
|
|
}
|
|
while (++index < length) {
|
|
var value = object == null ? undefined : object[toKey(path[index])];
|
|
if (value === undefined) {
|
|
index = length;
|
|
value = defaultValue;
|
|
}
|
|
object = isFunction(value) ? value.call(object) : value;
|
|
}
|
|
return object;
|
|
}
|
|
|
|
/**
|
|
* Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
|
|
* it's created. Arrays are created for missing index properties while objects
|
|
* are created for all other missing properties. Use `_.setWith` to customize
|
|
* `path` creation.
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.7.0
|
|
* @category Object
|
|
* @param {Object} object The object to modify.
|
|
* @param {Array|string} path The path of the property to set.
|
|
* @param {*} value The value to set.
|
|
* @returns {Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* var object = { 'a': [{ 'b': { 'c': 3 } }] };
|
|
*
|
|
* _.set(object, 'a[0].b.c', 4);
|
|
* console.log(object.a[0].b.c);
|
|
* // => 4
|
|
*
|
|
* _.set(object, ['x', '0', 'y', 'z'], 5);
|
|
* console.log(object.x[0].y.z);
|
|
* // => 5
|
|
*/
|
|
function set(object, path, value) {
|
|
return object == null ? object : baseSet(object, path, value);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.set` except that it accepts `customizer` which is
|
|
* invoked to produce the objects of `path`. If `customizer` returns `undefined`
|
|
* path creation is handled by the method instead. The `customizer` is invoked
|
|
* with three arguments: (nsValue, key, nsObject).
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Object
|
|
* @param {Object} object The object to modify.
|
|
* @param {Array|string} path The path of the property to set.
|
|
* @param {*} value The value to set.
|
|
* @param {Function} [customizer] The function to customize assigned values.
|
|
* @returns {Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* var object = {};
|
|
*
|
|
* _.setWith(object, '[0][1]', 'a', Object);
|
|
* // => { '0': { '1': 'a' } }
|
|
*/
|
|
function setWith(object, path, value, customizer) {
|
|
customizer = typeof customizer == 'function' ? customizer : undefined;
|
|
return object == null ? object : baseSet(object, path, value, customizer);
|
|
}
|
|
|
|
/**
|
|
* Creates an array of own enumerable string keyed-value pairs for `object`
|
|
* which can be consumed by `_.fromPairs`. If `object` is a map or set, its
|
|
* entries are returned.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @alias entries
|
|
* @category Object
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the key-value pairs.
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* this.b = 2;
|
|
* }
|
|
*
|
|
* Foo.prototype.c = 3;
|
|
*
|
|
* _.toPairs(new Foo);
|
|
* // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
|
|
*/
|
|
var toPairs = createToPairs(keys);
|
|
|
|
/**
|
|
* Creates an array of own and inherited enumerable string keyed-value pairs
|
|
* for `object` which can be consumed by `_.fromPairs`. If `object` is a map
|
|
* or set, its entries are returned.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @alias entriesIn
|
|
* @category Object
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the key-value pairs.
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* this.b = 2;
|
|
* }
|
|
*
|
|
* Foo.prototype.c = 3;
|
|
*
|
|
* _.toPairsIn(new Foo);
|
|
* // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
|
|
*/
|
|
var toPairsIn = createToPairs(keysIn);
|
|
|
|
/**
|
|
* An alternative to `_.reduce`; this method transforms `object` to a new
|
|
* `accumulator` object which is the result of running each of its own
|
|
* enumerable string keyed properties thru `iteratee`, with each invocation
|
|
* potentially mutating the `accumulator` object. If `accumulator` is not
|
|
* provided, a new object with the same `[[Prototype]]` will be used. The
|
|
* iteratee is invoked with four arguments: (accumulator, value, key, object).
|
|
* Iteratee functions may exit iteration early by explicitly returning `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 1.3.0
|
|
* @category Object
|
|
* @param {Object} object The object to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @param {*} [accumulator] The custom accumulator value.
|
|
* @returns {*} Returns the accumulated value.
|
|
* @example
|
|
*
|
|
* _.transform([2, 3, 4], function(result, n) {
|
|
* result.push(n *= n);
|
|
* return n % 2 == 0;
|
|
* }, []);
|
|
* // => [4, 9]
|
|
*
|
|
* _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
|
|
* (result[value] || (result[value] = [])).push(key);
|
|
* }, {});
|
|
* // => { '1': ['a', 'c'], '2': ['b'] }
|
|
*/
|
|
function transform(object, iteratee, accumulator) {
|
|
var isArr = isArray(object),
|
|
isArrLike = isArr || isBuffer(object) || isTypedArray(object);
|
|
|
|
iteratee = getIteratee(iteratee, 4);
|
|
if (accumulator == null) {
|
|
var Ctor = object && object.constructor;
|
|
if (isArrLike) {
|
|
accumulator = isArr ? new Ctor : [];
|
|
}
|
|
else if (isObject(object)) {
|
|
accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
|
|
}
|
|
else {
|
|
accumulator = {};
|
|
}
|
|
}
|
|
(isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
|
|
return iteratee(accumulator, value, index, object);
|
|
});
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* Removes the property at `path` of `object`.
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Object
|
|
* @param {Object} object The object to modify.
|
|
* @param {Array|string} path The path of the property to unset.
|
|
* @returns {boolean} Returns `true` if the property is deleted, else `false`.
|
|
* @example
|
|
*
|
|
* var object = { 'a': [{ 'b': { 'c': 7 } }] };
|
|
* _.unset(object, 'a[0].b.c');
|
|
* // => true
|
|
*
|
|
* console.log(object);
|
|
* // => { 'a': [{ 'b': {} }] };
|
|
*
|
|
* _.unset(object, ['a', '0', 'b', 'c']);
|
|
* // => true
|
|
*
|
|
* console.log(object);
|
|
* // => { 'a': [{ 'b': {} }] };
|
|
*/
|
|
function unset(object, path) {
|
|
return object == null ? true : baseUnset(object, path);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.set` except that accepts `updater` to produce the
|
|
* value to set. Use `_.updateWith` to customize `path` creation. The `updater`
|
|
* is invoked with one argument: (value).
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.6.0
|
|
* @category Object
|
|
* @param {Object} object The object to modify.
|
|
* @param {Array|string} path The path of the property to set.
|
|
* @param {Function} updater The function to produce the updated value.
|
|
* @returns {Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* var object = { 'a': [{ 'b': { 'c': 3 } }] };
|
|
*
|
|
* _.update(object, 'a[0].b.c', function(n) { return n * n; });
|
|
* console.log(object.a[0].b.c);
|
|
* // => 9
|
|
*
|
|
* _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
|
|
* console.log(object.x[0].y.z);
|
|
* // => 0
|
|
*/
|
|
function update(object, path, updater) {
|
|
return object == null ? object : baseUpdate(object, path, castFunction(updater));
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.update` except that it accepts `customizer` which is
|
|
* invoked to produce the objects of `path`. If `customizer` returns `undefined`
|
|
* path creation is handled by the method instead. The `customizer` is invoked
|
|
* with three arguments: (nsValue, key, nsObject).
|
|
*
|
|
* **Note:** This method mutates `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.6.0
|
|
* @category Object
|
|
* @param {Object} object The object to modify.
|
|
* @param {Array|string} path The path of the property to set.
|
|
* @param {Function} updater The function to produce the updated value.
|
|
* @param {Function} [customizer] The function to customize assigned values.
|
|
* @returns {Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* var object = {};
|
|
*
|
|
* _.updateWith(object, '[0][1]', _.constant('a'), Object);
|
|
* // => { '0': { '1': 'a' } }
|
|
*/
|
|
function updateWith(object, path, updater, customizer) {
|
|
customizer = typeof customizer == 'function' ? customizer : undefined;
|
|
return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
|
|
}
|
|
|
|
/**
|
|
* Creates an array of the own enumerable string keyed property values of `object`.
|
|
*
|
|
* **Note:** Non-object values are coerced to objects.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Object
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property values.
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* this.b = 2;
|
|
* }
|
|
*
|
|
* Foo.prototype.c = 3;
|
|
*
|
|
* _.values(new Foo);
|
|
* // => [1, 2] (iteration order is not guaranteed)
|
|
*
|
|
* _.values('hi');
|
|
* // => ['h', 'i']
|
|
*/
|
|
function values(object) {
|
|
return object == null ? [] : baseValues(object, keys(object));
|
|
}
|
|
|
|
/**
|
|
* Creates an array of the own and inherited enumerable string keyed property
|
|
* values of `object`.
|
|
*
|
|
* **Note:** Non-object values are coerced to objects.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Object
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property values.
|
|
* @example
|
|
*
|
|
* function Foo() {
|
|
* this.a = 1;
|
|
* this.b = 2;
|
|
* }
|
|
*
|
|
* Foo.prototype.c = 3;
|
|
*
|
|
* _.valuesIn(new Foo);
|
|
* // => [1, 2, 3] (iteration order is not guaranteed)
|
|
*/
|
|
function valuesIn(object) {
|
|
return object == null ? [] : baseValues(object, keysIn(object));
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Clamps `number` within the inclusive `lower` and `upper` bounds.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Number
|
|
* @param {number} number The number to clamp.
|
|
* @param {number} [lower] The lower bound.
|
|
* @param {number} upper The upper bound.
|
|
* @returns {number} Returns the clamped number.
|
|
* @example
|
|
*
|
|
* _.clamp(-10, -5, 5);
|
|
* // => -5
|
|
*
|
|
* _.clamp(10, -5, 5);
|
|
* // => 5
|
|
*/
|
|
function clamp(number, lower, upper) {
|
|
if (upper === undefined) {
|
|
upper = lower;
|
|
lower = undefined;
|
|
}
|
|
if (upper !== undefined) {
|
|
upper = toNumber(upper);
|
|
upper = upper === upper ? upper : 0;
|
|
}
|
|
if (lower !== undefined) {
|
|
lower = toNumber(lower);
|
|
lower = lower === lower ? lower : 0;
|
|
}
|
|
return baseClamp(toNumber(number), lower, upper);
|
|
}
|
|
|
|
/**
|
|
* Checks if `n` is between `start` and up to, but not including, `end`. If
|
|
* `end` is not specified, it's set to `start` with `start` then set to `0`.
|
|
* If `start` is greater than `end` the params are swapped to support
|
|
* negative ranges.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.3.0
|
|
* @category Number
|
|
* @param {number} number The number to check.
|
|
* @param {number} [start=0] The start of the range.
|
|
* @param {number} end The end of the range.
|
|
* @returns {boolean} Returns `true` if `number` is in the range, else `false`.
|
|
* @see _.range, _.rangeRight
|
|
* @example
|
|
*
|
|
* _.inRange(3, 2, 4);
|
|
* // => true
|
|
*
|
|
* _.inRange(4, 8);
|
|
* // => true
|
|
*
|
|
* _.inRange(4, 2);
|
|
* // => false
|
|
*
|
|
* _.inRange(2, 2);
|
|
* // => false
|
|
*
|
|
* _.inRange(1.2, 2);
|
|
* // => true
|
|
*
|
|
* _.inRange(5.2, 4);
|
|
* // => false
|
|
*
|
|
* _.inRange(-3, -2, -6);
|
|
* // => true
|
|
*/
|
|
function inRange(number, start, end) {
|
|
start = toFinite(start);
|
|
if (end === undefined) {
|
|
end = start;
|
|
start = 0;
|
|
} else {
|
|
end = toFinite(end);
|
|
}
|
|
number = toNumber(number);
|
|
return baseInRange(number, start, end);
|
|
}
|
|
|
|
/**
|
|
* Produces a random number between the inclusive `lower` and `upper` bounds.
|
|
* If only one argument is provided a number between `0` and the given number
|
|
* is returned. If `floating` is `true`, or either `lower` or `upper` are
|
|
* floats, a floating-point number is returned instead of an integer.
|
|
*
|
|
* **Note:** JavaScript follows the IEEE-754 standard for resolving
|
|
* floating-point values which can produce unexpected results.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.7.0
|
|
* @category Number
|
|
* @param {number} [lower=0] The lower bound.
|
|
* @param {number} [upper=1] The upper bound.
|
|
* @param {boolean} [floating] Specify returning a floating-point number.
|
|
* @returns {number} Returns the random number.
|
|
* @example
|
|
*
|
|
* _.random(0, 5);
|
|
* // => an integer between 0 and 5
|
|
*
|
|
* _.random(5);
|
|
* // => also an integer between 0 and 5
|
|
*
|
|
* _.random(5, true);
|
|
* // => a floating-point number between 0 and 5
|
|
*
|
|
* _.random(1.2, 5.2);
|
|
* // => a floating-point number between 1.2 and 5.2
|
|
*/
|
|
function random(lower, upper, floating) {
|
|
if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
|
|
upper = floating = undefined;
|
|
}
|
|
if (floating === undefined) {
|
|
if (typeof upper == 'boolean') {
|
|
floating = upper;
|
|
upper = undefined;
|
|
}
|
|
else if (typeof lower == 'boolean') {
|
|
floating = lower;
|
|
lower = undefined;
|
|
}
|
|
}
|
|
if (lower === undefined && upper === undefined) {
|
|
lower = 0;
|
|
upper = 1;
|
|
}
|
|
else {
|
|
lower = toFinite(lower);
|
|
if (upper === undefined) {
|
|
upper = lower;
|
|
lower = 0;
|
|
} else {
|
|
upper = toFinite(upper);
|
|
}
|
|
}
|
|
if (lower > upper) {
|
|
var temp = lower;
|
|
lower = upper;
|
|
upper = temp;
|
|
}
|
|
if (floating || lower % 1 || upper % 1) {
|
|
var rand = nativeRandom();
|
|
return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
|
|
}
|
|
return baseRandom(lower, upper);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the camel cased string.
|
|
* @example
|
|
*
|
|
* _.camelCase('Foo Bar');
|
|
* // => 'fooBar'
|
|
*
|
|
* _.camelCase('--foo-bar--');
|
|
* // => 'fooBar'
|
|
*
|
|
* _.camelCase('__FOO_BAR__');
|
|
* // => 'fooBar'
|
|
*/
|
|
var camelCase = createCompounder(function(result, word, index) {
|
|
word = word.toLowerCase();
|
|
return result + (index ? capitalize(word) : word);
|
|
});
|
|
|
|
/**
|
|
* Converts the first character of `string` to upper case and the remaining
|
|
* to lower case.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to capitalize.
|
|
* @returns {string} Returns the capitalized string.
|
|
* @example
|
|
*
|
|
* _.capitalize('FRED');
|
|
* // => 'Fred'
|
|
*/
|
|
function capitalize(string) {
|
|
return upperFirst(toString(string).toLowerCase());
|
|
}
|
|
|
|
/**
|
|
* Deburrs `string` by converting
|
|
* [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
|
|
* and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
|
|
* letters to basic Latin letters and removing
|
|
* [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to deburr.
|
|
* @returns {string} Returns the deburred string.
|
|
* @example
|
|
*
|
|
* _.deburr('déjà vu');
|
|
* // => 'deja vu'
|
|
*/
|
|
function deburr(string) {
|
|
string = toString(string);
|
|
return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
|
|
}
|
|
|
|
/**
|
|
* Checks if `string` ends with the given target string.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to inspect.
|
|
* @param {string} [target] The string to search for.
|
|
* @param {number} [position=string.length] The position to search up to.
|
|
* @returns {boolean} Returns `true` if `string` ends with `target`,
|
|
* else `false`.
|
|
* @example
|
|
*
|
|
* _.endsWith('abc', 'c');
|
|
* // => true
|
|
*
|
|
* _.endsWith('abc', 'b');
|
|
* // => false
|
|
*
|
|
* _.endsWith('abc', 'b', 2);
|
|
* // => true
|
|
*/
|
|
function endsWith(string, target, position) {
|
|
string = toString(string);
|
|
target = baseToString(target);
|
|
|
|
var length = string.length;
|
|
position = position === undefined
|
|
? length
|
|
: baseClamp(toInteger(position), 0, length);
|
|
|
|
var end = position;
|
|
position -= target.length;
|
|
return position >= 0 && string.slice(position, end) == target;
|
|
}
|
|
|
|
/**
|
|
* Converts the characters "&", "<", ">", '"', and "'" in `string` to their
|
|
* corresponding HTML entities.
|
|
*
|
|
* **Note:** No other characters are escaped. To escape additional
|
|
* characters use a third-party library like [_he_](https://mths.be/he).
|
|
*
|
|
* Though the ">" character is escaped for symmetry, characters like
|
|
* ">" and "/" don't need escaping in HTML and have no special meaning
|
|
* unless they're part of a tag or unquoted attribute value. See
|
|
* [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
|
|
* (under "semi-related fun fact") for more details.
|
|
*
|
|
* When working with HTML you should always
|
|
* [quote attribute values](http://wonko.com/post/html-escaping) to reduce
|
|
* XSS vectors.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category String
|
|
* @param {string} [string=''] The string to escape.
|
|
* @returns {string} Returns the escaped string.
|
|
* @example
|
|
*
|
|
* _.escape('fred, barney, & pebbles');
|
|
* // => 'fred, barney, & pebbles'
|
|
*/
|
|
function escape(string) {
|
|
string = toString(string);
|
|
return (string && reHasUnescapedHtml.test(string))
|
|
? string.replace(reUnescapedHtml, escapeHtmlChar)
|
|
: string;
|
|
}
|
|
|
|
/**
|
|
* Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
|
|
* "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to escape.
|
|
* @returns {string} Returns the escaped string.
|
|
* @example
|
|
*
|
|
* _.escapeRegExp('[lodash](https://lodash.com/)');
|
|
* // => '\[lodash\]\(https://lodash\.com/\)'
|
|
*/
|
|
function escapeRegExp(string) {
|
|
string = toString(string);
|
|
return (string && reHasRegExpChar.test(string))
|
|
? string.replace(reRegExpChar, '\\$&')
|
|
: string;
|
|
}
|
|
|
|
/**
|
|
* Converts `string` to
|
|
* [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the kebab cased string.
|
|
* @example
|
|
*
|
|
* _.kebabCase('Foo Bar');
|
|
* // => 'foo-bar'
|
|
*
|
|
* _.kebabCase('fooBar');
|
|
* // => 'foo-bar'
|
|
*
|
|
* _.kebabCase('__FOO_BAR__');
|
|
* // => 'foo-bar'
|
|
*/
|
|
var kebabCase = createCompounder(function(result, word, index) {
|
|
return result + (index ? '-' : '') + word.toLowerCase();
|
|
});
|
|
|
|
/**
|
|
* Converts `string`, as space separated words, to lower case.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the lower cased string.
|
|
* @example
|
|
*
|
|
* _.lowerCase('--Foo-Bar--');
|
|
* // => 'foo bar'
|
|
*
|
|
* _.lowerCase('fooBar');
|
|
* // => 'foo bar'
|
|
*
|
|
* _.lowerCase('__FOO_BAR__');
|
|
* // => 'foo bar'
|
|
*/
|
|
var lowerCase = createCompounder(function(result, word, index) {
|
|
return result + (index ? ' ' : '') + word.toLowerCase();
|
|
});
|
|
|
|
/**
|
|
* Converts the first character of `string` to lower case.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the converted string.
|
|
* @example
|
|
*
|
|
* _.lowerFirst('Fred');
|
|
* // => 'fred'
|
|
*
|
|
* _.lowerFirst('FRED');
|
|
* // => 'fRED'
|
|
*/
|
|
var lowerFirst = createCaseFirst('toLowerCase');
|
|
|
|
/**
|
|
* Pads `string` on the left and right sides if it's shorter than `length`.
|
|
* Padding characters are truncated if they can't be evenly divided by `length`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to pad.
|
|
* @param {number} [length=0] The padding length.
|
|
* @param {string} [chars=' '] The string used as padding.
|
|
* @returns {string} Returns the padded string.
|
|
* @example
|
|
*
|
|
* _.pad('abc', 8);
|
|
* // => ' abc '
|
|
*
|
|
* _.pad('abc', 8, '_-');
|
|
* // => '_-abc_-_'
|
|
*
|
|
* _.pad('abc', 3);
|
|
* // => 'abc'
|
|
*/
|
|
function pad(string, length, chars) {
|
|
string = toString(string);
|
|
length = toInteger(length);
|
|
|
|
var strLength = length ? stringSize(string) : 0;
|
|
if (!length || strLength >= length) {
|
|
return string;
|
|
}
|
|
var mid = (length - strLength) / 2;
|
|
return (
|
|
createPadding(nativeFloor(mid), chars) +
|
|
string +
|
|
createPadding(nativeCeil(mid), chars)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Pads `string` on the right side if it's shorter than `length`. Padding
|
|
* characters are truncated if they exceed `length`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to pad.
|
|
* @param {number} [length=0] The padding length.
|
|
* @param {string} [chars=' '] The string used as padding.
|
|
* @returns {string} Returns the padded string.
|
|
* @example
|
|
*
|
|
* _.padEnd('abc', 6);
|
|
* // => 'abc '
|
|
*
|
|
* _.padEnd('abc', 6, '_-');
|
|
* // => 'abc_-_'
|
|
*
|
|
* _.padEnd('abc', 3);
|
|
* // => 'abc'
|
|
*/
|
|
function padEnd(string, length, chars) {
|
|
string = toString(string);
|
|
length = toInteger(length);
|
|
|
|
var strLength = length ? stringSize(string) : 0;
|
|
return (length && strLength < length)
|
|
? (string + createPadding(length - strLength, chars))
|
|
: string;
|
|
}
|
|
|
|
/**
|
|
* Pads `string` on the left side if it's shorter than `length`. Padding
|
|
* characters are truncated if they exceed `length`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to pad.
|
|
* @param {number} [length=0] The padding length.
|
|
* @param {string} [chars=' '] The string used as padding.
|
|
* @returns {string} Returns the padded string.
|
|
* @example
|
|
*
|
|
* _.padStart('abc', 6);
|
|
* // => ' abc'
|
|
*
|
|
* _.padStart('abc', 6, '_-');
|
|
* // => '_-_abc'
|
|
*
|
|
* _.padStart('abc', 3);
|
|
* // => 'abc'
|
|
*/
|
|
function padStart(string, length, chars) {
|
|
string = toString(string);
|
|
length = toInteger(length);
|
|
|
|
var strLength = length ? stringSize(string) : 0;
|
|
return (length && strLength < length)
|
|
? (createPadding(length - strLength, chars) + string)
|
|
: string;
|
|
}
|
|
|
|
/**
|
|
* Converts `string` to an integer of the specified radix. If `radix` is
|
|
* `undefined` or `0`, a `radix` of `10` is used unless `value` is a
|
|
* hexadecimal, in which case a `radix` of `16` is used.
|
|
*
|
|
* **Note:** This method aligns with the
|
|
* [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 1.1.0
|
|
* @category String
|
|
* @param {string} string The string to convert.
|
|
* @param {number} [radix=10] The radix to interpret `value` by.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {number} Returns the converted integer.
|
|
* @example
|
|
*
|
|
* _.parseInt('08');
|
|
* // => 8
|
|
*
|
|
* _.map(['6', '08', '10'], _.parseInt);
|
|
* // => [6, 8, 10]
|
|
*/
|
|
function parseInt(string, radix, guard) {
|
|
if (guard || radix == null) {
|
|
radix = 0;
|
|
} else if (radix) {
|
|
radix = +radix;
|
|
}
|
|
return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
|
|
}
|
|
|
|
/**
|
|
* Repeats the given string `n` times.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to repeat.
|
|
* @param {number} [n=1] The number of times to repeat the string.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {string} Returns the repeated string.
|
|
* @example
|
|
*
|
|
* _.repeat('*', 3);
|
|
* // => '***'
|
|
*
|
|
* _.repeat('abc', 2);
|
|
* // => 'abcabc'
|
|
*
|
|
* _.repeat('abc', 0);
|
|
* // => ''
|
|
*/
|
|
function repeat(string, n, guard) {
|
|
if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {
|
|
n = 1;
|
|
} else {
|
|
n = toInteger(n);
|
|
}
|
|
return baseRepeat(toString(string), n);
|
|
}
|
|
|
|
/**
|
|
* Replaces matches for `pattern` in `string` with `replacement`.
|
|
*
|
|
* **Note:** This method is based on
|
|
* [`String#replace`](https://mdn.io/String/replace).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to modify.
|
|
* @param {RegExp|string} pattern The pattern to replace.
|
|
* @param {Function|string} replacement The match replacement.
|
|
* @returns {string} Returns the modified string.
|
|
* @example
|
|
*
|
|
* _.replace('Hi Fred', 'Fred', 'Barney');
|
|
* // => 'Hi Barney'
|
|
*/
|
|
function replace() {
|
|
var args = arguments,
|
|
string = toString(args[0]);
|
|
|
|
return args.length < 3 ? string : string.replace(args[1], args[2]);
|
|
}
|
|
|
|
/**
|
|
* Converts `string` to
|
|
* [snake case](https://en.wikipedia.org/wiki/Snake_case).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the snake cased string.
|
|
* @example
|
|
*
|
|
* _.snakeCase('Foo Bar');
|
|
* // => 'foo_bar'
|
|
*
|
|
* _.snakeCase('fooBar');
|
|
* // => 'foo_bar'
|
|
*
|
|
* _.snakeCase('--FOO-BAR--');
|
|
* // => 'foo_bar'
|
|
*/
|
|
var snakeCase = createCompounder(function(result, word, index) {
|
|
return result + (index ? '_' : '') + word.toLowerCase();
|
|
});
|
|
|
|
/**
|
|
* Splits `string` by `separator`.
|
|
*
|
|
* **Note:** This method is based on
|
|
* [`String#split`](https://mdn.io/String/split).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to split.
|
|
* @param {RegExp|string} separator The separator pattern to split by.
|
|
* @param {number} [limit] The length to truncate results to.
|
|
* @returns {Array} Returns the string segments.
|
|
* @example
|
|
*
|
|
* _.split('a-b-c', '-', 2);
|
|
* // => ['a', 'b']
|
|
*/
|
|
function split(string, separator, limit) {
|
|
if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
|
|
separator = limit = undefined;
|
|
}
|
|
limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
|
|
if (!limit) {
|
|
return [];
|
|
}
|
|
string = toString(string);
|
|
if (string && (
|
|
typeof separator == 'string' ||
|
|
(separator != null && !isRegExp(separator))
|
|
)) {
|
|
separator = baseToString(separator);
|
|
if (!separator && hasUnicode(string)) {
|
|
return castSlice(stringToArray(string), 0, limit);
|
|
}
|
|
}
|
|
return string.split(separator, limit);
|
|
}
|
|
|
|
/**
|
|
* Converts `string` to
|
|
* [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.1.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the start cased string.
|
|
* @example
|
|
*
|
|
* _.startCase('--foo-bar--');
|
|
* // => 'Foo Bar'
|
|
*
|
|
* _.startCase('fooBar');
|
|
* // => 'Foo Bar'
|
|
*
|
|
* _.startCase('__FOO_BAR__');
|
|
* // => 'FOO BAR'
|
|
*/
|
|
var startCase = createCompounder(function(result, word, index) {
|
|
return result + (index ? ' ' : '') + upperFirst(word);
|
|
});
|
|
|
|
/**
|
|
* Checks if `string` starts with the given target string.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to inspect.
|
|
* @param {string} [target] The string to search for.
|
|
* @param {number} [position=0] The position to search from.
|
|
* @returns {boolean} Returns `true` if `string` starts with `target`,
|
|
* else `false`.
|
|
* @example
|
|
*
|
|
* _.startsWith('abc', 'a');
|
|
* // => true
|
|
*
|
|
* _.startsWith('abc', 'b');
|
|
* // => false
|
|
*
|
|
* _.startsWith('abc', 'b', 1);
|
|
* // => true
|
|
*/
|
|
function startsWith(string, target, position) {
|
|
string = toString(string);
|
|
position = position == null
|
|
? 0
|
|
: baseClamp(toInteger(position), 0, string.length);
|
|
|
|
target = baseToString(target);
|
|
return string.slice(position, position + target.length) == target;
|
|
}
|
|
|
|
/**
|
|
* Creates a compiled template function that can interpolate data properties
|
|
* in "interpolate" delimiters, HTML-escape interpolated data properties in
|
|
* "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
|
|
* properties may be accessed as free variables in the template. If a setting
|
|
* object is given, it takes precedence over `_.templateSettings` values.
|
|
*
|
|
* **Note:** In the development build `_.template` utilizes
|
|
* [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
|
|
* for easier debugging.
|
|
*
|
|
* For more information on precompiling templates see
|
|
* [lodash's custom builds documentation](https://lodash.com/custom-builds).
|
|
*
|
|
* For more information on Chrome extension sandboxes see
|
|
* [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category String
|
|
* @param {string} [string=''] The template string.
|
|
* @param {Object} [options={}] The options object.
|
|
* @param {RegExp} [options.escape=_.templateSettings.escape]
|
|
* The HTML "escape" delimiter.
|
|
* @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
|
|
* The "evaluate" delimiter.
|
|
* @param {Object} [options.imports=_.templateSettings.imports]
|
|
* An object to import into the template as free variables.
|
|
* @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
|
|
* The "interpolate" delimiter.
|
|
* @param {string} [options.sourceURL='lodash.templateSources[n]']
|
|
* The sourceURL of the compiled template.
|
|
* @param {string} [options.variable='obj']
|
|
* The data object variable name.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Function} Returns the compiled template function.
|
|
* @example
|
|
*
|
|
* // Use the "interpolate" delimiter to create a compiled template.
|
|
* var compiled = _.template('hello <%= user %>!');
|
|
* compiled({ 'user': 'fred' });
|
|
* // => 'hello fred!'
|
|
*
|
|
* // Use the HTML "escape" delimiter to escape data property values.
|
|
* var compiled = _.template('<b><%- value %></b>');
|
|
* compiled({ 'value': '<script>' });
|
|
* // => '<b><script></b>'
|
|
*
|
|
* // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
|
|
* var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
|
|
* compiled({ 'users': ['fred', 'barney'] });
|
|
* // => '<li>fred</li><li>barney</li>'
|
|
*
|
|
* // Use the internal `print` function in "evaluate" delimiters.
|
|
* var compiled = _.template('<% print("hello " + user); %>!');
|
|
* compiled({ 'user': 'barney' });
|
|
* // => 'hello barney!'
|
|
*
|
|
* // Use the ES template literal delimiter as an "interpolate" delimiter.
|
|
* // Disable support by replacing the "interpolate" delimiter.
|
|
* var compiled = _.template('hello ${ user }!');
|
|
* compiled({ 'user': 'pebbles' });
|
|
* // => 'hello pebbles!'
|
|
*
|
|
* // Use backslashes to treat delimiters as plain text.
|
|
* var compiled = _.template('<%= "\\<%- value %\\>" %>');
|
|
* compiled({ 'value': 'ignored' });
|
|
* // => '<%- value %>'
|
|
*
|
|
* // Use the `imports` option to import `jQuery` as `jq`.
|
|
* var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
|
|
* var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
|
|
* compiled({ 'users': ['fred', 'barney'] });
|
|
* // => '<li>fred</li><li>barney</li>'
|
|
*
|
|
* // Use the `sourceURL` option to specify a custom sourceURL for the template.
|
|
* var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
|
|
* compiled(data);
|
|
* // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
|
|
*
|
|
* // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
|
|
* var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
|
|
* compiled.source;
|
|
* // => function(data) {
|
|
* // var __t, __p = '';
|
|
* // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
|
|
* // return __p;
|
|
* // }
|
|
*
|
|
* // Use custom template delimiters.
|
|
* _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
|
|
* var compiled = _.template('hello {{ user }}!');
|
|
* compiled({ 'user': 'mustache' });
|
|
* // => 'hello mustache!'
|
|
*
|
|
* // Use the `source` property to inline compiled templates for meaningful
|
|
* // line numbers in error messages and stack traces.
|
|
* fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
|
|
* var JST = {\
|
|
* "main": ' + _.template(mainText).source + '\
|
|
* };\
|
|
* ');
|
|
*/
|
|
function template(string, options, guard) {
|
|
// Based on John Resig's `tmpl` implementation
|
|
// (http://ejohn.org/blog/javascript-micro-templating/)
|
|
// and Laura Doktorova's doT.js (https://github.com/olado/doT).
|
|
var settings = lodash.templateSettings;
|
|
|
|
if (guard && isIterateeCall(string, options, guard)) {
|
|
options = undefined;
|
|
}
|
|
string = toString(string);
|
|
options = assignInWith({}, options, settings, customDefaultsAssignIn);
|
|
|
|
var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
|
|
importsKeys = keys(imports),
|
|
importsValues = baseValues(imports, importsKeys);
|
|
|
|
var isEscaping,
|
|
isEvaluating,
|
|
index = 0,
|
|
interpolate = options.interpolate || reNoMatch,
|
|
source = "__p += '";
|
|
|
|
// Compile the regexp to match each delimiter.
|
|
var reDelimiters = RegExp(
|
|
(options.escape || reNoMatch).source + '|' +
|
|
interpolate.source + '|' +
|
|
(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
|
|
(options.evaluate || reNoMatch).source + '|$'
|
|
, 'g');
|
|
|
|
// Use a sourceURL for easier debugging.
|
|
// The sourceURL gets injected into the source that's eval-ed, so be careful
|
|
// to normalize all kinds of whitespace, so e.g. newlines (and unicode versions of it) can't sneak in
|
|
// and escape the comment, thus injecting code that gets evaled.
|
|
var sourceURL = '//# sourceURL=' +
|
|
(hasOwnProperty.call(options, 'sourceURL')
|
|
? (options.sourceURL + '').replace(/\s/g, ' ')
|
|
: ('lodash.templateSources[' + (++templateCounter) + ']')
|
|
) + '\n';
|
|
|
|
string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
|
|
interpolateValue || (interpolateValue = esTemplateValue);
|
|
|
|
// Escape characters that can't be included in string literals.
|
|
source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
|
|
|
|
// Replace delimiters with snippets.
|
|
if (escapeValue) {
|
|
isEscaping = true;
|
|
source += "' +\n__e(" + escapeValue + ") +\n'";
|
|
}
|
|
if (evaluateValue) {
|
|
isEvaluating = true;
|
|
source += "';\n" + evaluateValue + ";\n__p += '";
|
|
}
|
|
if (interpolateValue) {
|
|
source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
|
|
}
|
|
index = offset + match.length;
|
|
|
|
// The JS engine embedded in Adobe products needs `match` returned in
|
|
// order to produce the correct `offset` value.
|
|
return match;
|
|
});
|
|
|
|
source += "';\n";
|
|
|
|
// If `variable` is not specified wrap a with-statement around the generated
|
|
// code to add the data object to the top of the scope chain.
|
|
var variable = hasOwnProperty.call(options, 'variable') && options.variable;
|
|
if (!variable) {
|
|
source = 'with (obj) {\n' + source + '\n}\n';
|
|
}
|
|
// Cleanup code by stripping empty strings.
|
|
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
|
|
.replace(reEmptyStringMiddle, '$1')
|
|
.replace(reEmptyStringTrailing, '$1;');
|
|
|
|
// Frame code as the function body.
|
|
source = 'function(' + (variable || 'obj') + ') {\n' +
|
|
(variable
|
|
? ''
|
|
: 'obj || (obj = {});\n'
|
|
) +
|
|
"var __t, __p = ''" +
|
|
(isEscaping
|
|
? ', __e = _.escape'
|
|
: ''
|
|
) +
|
|
(isEvaluating
|
|
? ', __j = Array.prototype.join;\n' +
|
|
"function print() { __p += __j.call(arguments, '') }\n"
|
|
: ';\n'
|
|
) +
|
|
source +
|
|
'return __p\n}';
|
|
|
|
var result = attempt(function() {
|
|
return Function(importsKeys, sourceURL + 'return ' + source)
|
|
.apply(undefined, importsValues);
|
|
});
|
|
|
|
// Provide the compiled function's source by its `toString` method or
|
|
// the `source` property as a convenience for inlining compiled templates.
|
|
result.source = source;
|
|
if (isError(result)) {
|
|
throw result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts `string`, as a whole, to lower case just like
|
|
* [String#toLowerCase](https://mdn.io/toLowerCase).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the lower cased string.
|
|
* @example
|
|
*
|
|
* _.toLower('--Foo-Bar--');
|
|
* // => '--foo-bar--'
|
|
*
|
|
* _.toLower('fooBar');
|
|
* // => 'foobar'
|
|
*
|
|
* _.toLower('__FOO_BAR__');
|
|
* // => '__foo_bar__'
|
|
*/
|
|
function toLower(value) {
|
|
return toString(value).toLowerCase();
|
|
}
|
|
|
|
/**
|
|
* Converts `string`, as a whole, to upper case just like
|
|
* [String#toUpperCase](https://mdn.io/toUpperCase).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the upper cased string.
|
|
* @example
|
|
*
|
|
* _.toUpper('--foo-bar--');
|
|
* // => '--FOO-BAR--'
|
|
*
|
|
* _.toUpper('fooBar');
|
|
* // => 'FOOBAR'
|
|
*
|
|
* _.toUpper('__foo_bar__');
|
|
* // => '__FOO_BAR__'
|
|
*/
|
|
function toUpper(value) {
|
|
return toString(value).toUpperCase();
|
|
}
|
|
|
|
/**
|
|
* Removes leading and trailing whitespace or specified characters from `string`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to trim.
|
|
* @param {string} [chars=whitespace] The characters to trim.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {string} Returns the trimmed string.
|
|
* @example
|
|
*
|
|
* _.trim(' abc ');
|
|
* // => 'abc'
|
|
*
|
|
* _.trim('-_-abc-_-', '_-');
|
|
* // => 'abc'
|
|
*
|
|
* _.map([' foo ', ' bar '], _.trim);
|
|
* // => ['foo', 'bar']
|
|
*/
|
|
function trim(string, chars, guard) {
|
|
string = toString(string);
|
|
if (string && (guard || chars === undefined)) {
|
|
return string.replace(reTrim, '');
|
|
}
|
|
if (!string || !(chars = baseToString(chars))) {
|
|
return string;
|
|
}
|
|
var strSymbols = stringToArray(string),
|
|
chrSymbols = stringToArray(chars),
|
|
start = charsStartIndex(strSymbols, chrSymbols),
|
|
end = charsEndIndex(strSymbols, chrSymbols) + 1;
|
|
|
|
return castSlice(strSymbols, start, end).join('');
|
|
}
|
|
|
|
/**
|
|
* Removes trailing whitespace or specified characters from `string`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to trim.
|
|
* @param {string} [chars=whitespace] The characters to trim.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {string} Returns the trimmed string.
|
|
* @example
|
|
*
|
|
* _.trimEnd(' abc ');
|
|
* // => ' abc'
|
|
*
|
|
* _.trimEnd('-_-abc-_-', '_-');
|
|
* // => '-_-abc'
|
|
*/
|
|
function trimEnd(string, chars, guard) {
|
|
string = toString(string);
|
|
if (string && (guard || chars === undefined)) {
|
|
return string.replace(reTrimEnd, '');
|
|
}
|
|
if (!string || !(chars = baseToString(chars))) {
|
|
return string;
|
|
}
|
|
var strSymbols = stringToArray(string),
|
|
end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
|
|
|
|
return castSlice(strSymbols, 0, end).join('');
|
|
}
|
|
|
|
/**
|
|
* Removes leading whitespace or specified characters from `string`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to trim.
|
|
* @param {string} [chars=whitespace] The characters to trim.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {string} Returns the trimmed string.
|
|
* @example
|
|
*
|
|
* _.trimStart(' abc ');
|
|
* // => 'abc '
|
|
*
|
|
* _.trimStart('-_-abc-_-', '_-');
|
|
* // => 'abc-_-'
|
|
*/
|
|
function trimStart(string, chars, guard) {
|
|
string = toString(string);
|
|
if (string && (guard || chars === undefined)) {
|
|
return string.replace(reTrimStart, '');
|
|
}
|
|
if (!string || !(chars = baseToString(chars))) {
|
|
return string;
|
|
}
|
|
var strSymbols = stringToArray(string),
|
|
start = charsStartIndex(strSymbols, stringToArray(chars));
|
|
|
|
return castSlice(strSymbols, start).join('');
|
|
}
|
|
|
|
/**
|
|
* Truncates `string` if it's longer than the given maximum string length.
|
|
* The last characters of the truncated string are replaced with the omission
|
|
* string which defaults to "...".
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to truncate.
|
|
* @param {Object} [options={}] The options object.
|
|
* @param {number} [options.length=30] The maximum string length.
|
|
* @param {string} [options.omission='...'] The string to indicate text is omitted.
|
|
* @param {RegExp|string} [options.separator] The separator pattern to truncate to.
|
|
* @returns {string} Returns the truncated string.
|
|
* @example
|
|
*
|
|
* _.truncate('hi-diddly-ho there, neighborino');
|
|
* // => 'hi-diddly-ho there, neighbo...'
|
|
*
|
|
* _.truncate('hi-diddly-ho there, neighborino', {
|
|
* 'length': 24,
|
|
* 'separator': ' '
|
|
* });
|
|
* // => 'hi-diddly-ho there,...'
|
|
*
|
|
* _.truncate('hi-diddly-ho there, neighborino', {
|
|
* 'length': 24,
|
|
* 'separator': /,? +/
|
|
* });
|
|
* // => 'hi-diddly-ho there...'
|
|
*
|
|
* _.truncate('hi-diddly-ho there, neighborino', {
|
|
* 'omission': ' [...]'
|
|
* });
|
|
* // => 'hi-diddly-ho there, neig [...]'
|
|
*/
|
|
function truncate(string, options) {
|
|
var length = DEFAULT_TRUNC_LENGTH,
|
|
omission = DEFAULT_TRUNC_OMISSION;
|
|
|
|
if (isObject(options)) {
|
|
var separator = 'separator' in options ? options.separator : separator;
|
|
length = 'length' in options ? toInteger(options.length) : length;
|
|
omission = 'omission' in options ? baseToString(options.omission) : omission;
|
|
}
|
|
string = toString(string);
|
|
|
|
var strLength = string.length;
|
|
if (hasUnicode(string)) {
|
|
var strSymbols = stringToArray(string);
|
|
strLength = strSymbols.length;
|
|
}
|
|
if (length >= strLength) {
|
|
return string;
|
|
}
|
|
var end = length - stringSize(omission);
|
|
if (end < 1) {
|
|
return omission;
|
|
}
|
|
var result = strSymbols
|
|
? castSlice(strSymbols, 0, end).join('')
|
|
: string.slice(0, end);
|
|
|
|
if (separator === undefined) {
|
|
return result + omission;
|
|
}
|
|
if (strSymbols) {
|
|
end += (result.length - end);
|
|
}
|
|
if (isRegExp(separator)) {
|
|
if (string.slice(end).search(separator)) {
|
|
var match,
|
|
substring = result;
|
|
|
|
if (!separator.global) {
|
|
separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
|
|
}
|
|
separator.lastIndex = 0;
|
|
while ((match = separator.exec(substring))) {
|
|
var newEnd = match.index;
|
|
}
|
|
result = result.slice(0, newEnd === undefined ? end : newEnd);
|
|
}
|
|
} else if (string.indexOf(baseToString(separator), end) != end) {
|
|
var index = result.lastIndexOf(separator);
|
|
if (index > -1) {
|
|
result = result.slice(0, index);
|
|
}
|
|
}
|
|
return result + omission;
|
|
}
|
|
|
|
/**
|
|
* The inverse of `_.escape`; this method converts the HTML entities
|
|
* `&`, `<`, `>`, `"`, and `'` in `string` to
|
|
* their corresponding characters.
|
|
*
|
|
* **Note:** No other HTML entities are unescaped. To unescape additional
|
|
* HTML entities use a third-party library like [_he_](https://mths.be/he).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.6.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to unescape.
|
|
* @returns {string} Returns the unescaped string.
|
|
* @example
|
|
*
|
|
* _.unescape('fred, barney, & pebbles');
|
|
* // => 'fred, barney, & pebbles'
|
|
*/
|
|
function unescape(string) {
|
|
string = toString(string);
|
|
return (string && reHasEscapedHtml.test(string))
|
|
? string.replace(reEscapedHtml, unescapeHtmlChar)
|
|
: string;
|
|
}
|
|
|
|
/**
|
|
* Converts `string`, as space separated words, to upper case.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the upper cased string.
|
|
* @example
|
|
*
|
|
* _.upperCase('--foo-bar');
|
|
* // => 'FOO BAR'
|
|
*
|
|
* _.upperCase('fooBar');
|
|
* // => 'FOO BAR'
|
|
*
|
|
* _.upperCase('__foo_bar__');
|
|
* // => 'FOO BAR'
|
|
*/
|
|
var upperCase = createCompounder(function(result, word, index) {
|
|
return result + (index ? ' ' : '') + word.toUpperCase();
|
|
});
|
|
|
|
/**
|
|
* Converts the first character of `string` to upper case.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to convert.
|
|
* @returns {string} Returns the converted string.
|
|
* @example
|
|
*
|
|
* _.upperFirst('fred');
|
|
* // => 'Fred'
|
|
*
|
|
* _.upperFirst('FRED');
|
|
* // => 'FRED'
|
|
*/
|
|
var upperFirst = createCaseFirst('toUpperCase');
|
|
|
|
/**
|
|
* Splits `string` into an array of its words.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category String
|
|
* @param {string} [string=''] The string to inspect.
|
|
* @param {RegExp|string} [pattern] The pattern to match words.
|
|
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
|
* @returns {Array} Returns the words of `string`.
|
|
* @example
|
|
*
|
|
* _.words('fred, barney, & pebbles');
|
|
* // => ['fred', 'barney', 'pebbles']
|
|
*
|
|
* _.words('fred, barney, & pebbles', /[^, ]+/g);
|
|
* // => ['fred', 'barney', '&', 'pebbles']
|
|
*/
|
|
function words(string, pattern, guard) {
|
|
string = toString(string);
|
|
pattern = guard ? undefined : pattern;
|
|
|
|
if (pattern === undefined) {
|
|
return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
|
|
}
|
|
return string.match(pattern) || [];
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Attempts to invoke `func`, returning either the result or the caught error
|
|
* object. Any additional arguments are provided to `func` when it's invoked.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Util
|
|
* @param {Function} func The function to attempt.
|
|
* @param {...*} [args] The arguments to invoke `func` with.
|
|
* @returns {*} Returns the `func` result or error object.
|
|
* @example
|
|
*
|
|
* // Avoid throwing errors for invalid selectors.
|
|
* var elements = _.attempt(function(selector) {
|
|
* return document.querySelectorAll(selector);
|
|
* }, '>_>');
|
|
*
|
|
* if (_.isError(elements)) {
|
|
* elements = [];
|
|
* }
|
|
*/
|
|
var attempt = baseRest(function(func, args) {
|
|
try {
|
|
return apply(func, undefined, args);
|
|
} catch (e) {
|
|
return isError(e) ? e : new Error(e);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Binds methods of an object to the object itself, overwriting the existing
|
|
* method.
|
|
*
|
|
* **Note:** This method doesn't set the "length" property of bound functions.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {Object} object The object to bind and assign the bound methods to.
|
|
* @param {...(string|string[])} methodNames The object method names to bind.
|
|
* @returns {Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* var view = {
|
|
* 'label': 'docs',
|
|
* 'click': function() {
|
|
* console.log('clicked ' + this.label);
|
|
* }
|
|
* };
|
|
*
|
|
* _.bindAll(view, ['click']);
|
|
* jQuery(element).on('click', view.click);
|
|
* // => Logs 'clicked docs' when clicked.
|
|
*/
|
|
var bindAll = flatRest(function(object, methodNames) {
|
|
arrayEach(methodNames, function(key) {
|
|
key = toKey(key);
|
|
baseAssignValue(object, key, bind(object[key], object));
|
|
});
|
|
return object;
|
|
});
|
|
|
|
/**
|
|
* Creates a function that iterates over `pairs` and invokes the corresponding
|
|
* function of the first predicate to return truthy. The predicate-function
|
|
* pairs are invoked with the `this` binding and arguments of the created
|
|
* function.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {Array} pairs The predicate-function pairs.
|
|
* @returns {Function} Returns the new composite function.
|
|
* @example
|
|
*
|
|
* var func = _.cond([
|
|
* [_.matches({ 'a': 1 }), _.constant('matches A')],
|
|
* [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
|
|
* [_.stubTrue, _.constant('no match')]
|
|
* ]);
|
|
*
|
|
* func({ 'a': 1, 'b': 2 });
|
|
* // => 'matches A'
|
|
*
|
|
* func({ 'a': 0, 'b': 1 });
|
|
* // => 'matches B'
|
|
*
|
|
* func({ 'a': '1', 'b': '2' });
|
|
* // => 'no match'
|
|
*/
|
|
function cond(pairs) {
|
|
var length = pairs == null ? 0 : pairs.length,
|
|
toIteratee = getIteratee();
|
|
|
|
pairs = !length ? [] : arrayMap(pairs, function(pair) {
|
|
if (typeof pair[1] != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
return [toIteratee(pair[0]), pair[1]];
|
|
});
|
|
|
|
return baseRest(function(args) {
|
|
var index = -1;
|
|
while (++index < length) {
|
|
var pair = pairs[index];
|
|
if (apply(pair[0], this, args)) {
|
|
return apply(pair[1], this, args);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes the predicate properties of `source` with
|
|
* the corresponding property values of a given object, returning `true` if
|
|
* all predicates return truthy, else `false`.
|
|
*
|
|
* **Note:** The created function is equivalent to `_.conformsTo` with
|
|
* `source` partially applied.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {Object} source The object of property predicates to conform to.
|
|
* @returns {Function} Returns the new spec function.
|
|
* @example
|
|
*
|
|
* var objects = [
|
|
* { 'a': 2, 'b': 1 },
|
|
* { 'a': 1, 'b': 2 }
|
|
* ];
|
|
*
|
|
* _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
|
|
* // => [{ 'a': 1, 'b': 2 }]
|
|
*/
|
|
function conforms(source) {
|
|
return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* Creates a function that returns `value`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.4.0
|
|
* @category Util
|
|
* @param {*} value The value to return from the new function.
|
|
* @returns {Function} Returns the new constant function.
|
|
* @example
|
|
*
|
|
* var objects = _.times(2, _.constant({ 'a': 1 }));
|
|
*
|
|
* console.log(objects);
|
|
* // => [{ 'a': 1 }, { 'a': 1 }]
|
|
*
|
|
* console.log(objects[0] === objects[1]);
|
|
* // => true
|
|
*/
|
|
function constant(value) {
|
|
return function() {
|
|
return value;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Checks `value` to determine whether a default value should be returned in
|
|
* its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
|
|
* or `undefined`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.14.0
|
|
* @category Util
|
|
* @param {*} value The value to check.
|
|
* @param {*} defaultValue The default value.
|
|
* @returns {*} Returns the resolved value.
|
|
* @example
|
|
*
|
|
* _.defaultTo(1, 10);
|
|
* // => 1
|
|
*
|
|
* _.defaultTo(undefined, 10);
|
|
* // => 10
|
|
*/
|
|
function defaultTo(value, defaultValue) {
|
|
return (value == null || value !== value) ? defaultValue : value;
|
|
}
|
|
|
|
/**
|
|
* Creates a function that returns the result of invoking the given functions
|
|
* with the `this` binding of the created function, where each successive
|
|
* invocation is supplied the return value of the previous.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Util
|
|
* @param {...(Function|Function[])} [funcs] The functions to invoke.
|
|
* @returns {Function} Returns the new composite function.
|
|
* @see _.flowRight
|
|
* @example
|
|
*
|
|
* function square(n) {
|
|
* return n * n;
|
|
* }
|
|
*
|
|
* var addSquare = _.flow([_.add, square]);
|
|
* addSquare(1, 2);
|
|
* // => 9
|
|
*/
|
|
var flow = createFlow();
|
|
|
|
/**
|
|
* This method is like `_.flow` except that it creates a function that
|
|
* invokes the given functions from right to left.
|
|
*
|
|
* @static
|
|
* @since 3.0.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {...(Function|Function[])} [funcs] The functions to invoke.
|
|
* @returns {Function} Returns the new composite function.
|
|
* @see _.flow
|
|
* @example
|
|
*
|
|
* function square(n) {
|
|
* return n * n;
|
|
* }
|
|
*
|
|
* var addSquare = _.flowRight([square, _.add]);
|
|
* addSquare(1, 2);
|
|
* // => 9
|
|
*/
|
|
var flowRight = createFlow(true);
|
|
|
|
/**
|
|
* This method returns the first argument it receives.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {*} value Any value.
|
|
* @returns {*} Returns `value`.
|
|
* @example
|
|
*
|
|
* var object = { 'a': 1 };
|
|
*
|
|
* console.log(_.identity(object) === object);
|
|
* // => true
|
|
*/
|
|
function identity(value) {
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes `func` with the arguments of the created
|
|
* function. If `func` is a property name, the created function returns the
|
|
* property value for a given element. If `func` is an array or object, the
|
|
* created function returns `true` for elements that contain the equivalent
|
|
* source properties, otherwise it returns `false`.
|
|
*
|
|
* @static
|
|
* @since 4.0.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {*} [func=_.identity] The value to convert to a callback.
|
|
* @returns {Function} Returns the callback.
|
|
* @example
|
|
*
|
|
* var users = [
|
|
* { 'user': 'barney', 'age': 36, 'active': true },
|
|
* { 'user': 'fred', 'age': 40, 'active': false }
|
|
* ];
|
|
*
|
|
* // The `_.matches` iteratee shorthand.
|
|
* _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
|
|
* // => [{ 'user': 'barney', 'age': 36, 'active': true }]
|
|
*
|
|
* // The `_.matchesProperty` iteratee shorthand.
|
|
* _.filter(users, _.iteratee(['user', 'fred']));
|
|
* // => [{ 'user': 'fred', 'age': 40 }]
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.map(users, _.iteratee('user'));
|
|
* // => ['barney', 'fred']
|
|
*
|
|
* // Create custom iteratee shorthands.
|
|
* _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
|
|
* return !_.isRegExp(func) ? iteratee(func) : function(string) {
|
|
* return func.test(string);
|
|
* };
|
|
* });
|
|
*
|
|
* _.filter(['abc', 'def'], /ef/);
|
|
* // => ['def']
|
|
*/
|
|
function iteratee(func) {
|
|
return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* Creates a function that performs a partial deep comparison between a given
|
|
* object and `source`, returning `true` if the given object has equivalent
|
|
* property values, else `false`.
|
|
*
|
|
* **Note:** The created function is equivalent to `_.isMatch` with `source`
|
|
* partially applied.
|
|
*
|
|
* Partial comparisons will match empty array and empty object `source`
|
|
* values against any array or object value, respectively. See `_.isEqual`
|
|
* for a list of supported value comparisons.
|
|
*
|
|
* **Note:** Multiple values can be checked by combining several matchers
|
|
* using `_.overSome`
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Util
|
|
* @param {Object} source The object of property values to match.
|
|
* @returns {Function} Returns the new spec function.
|
|
* @example
|
|
*
|
|
* var objects = [
|
|
* { 'a': 1, 'b': 2, 'c': 3 },
|
|
* { 'a': 4, 'b': 5, 'c': 6 }
|
|
* ];
|
|
*
|
|
* _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
|
|
* // => [{ 'a': 4, 'b': 5, 'c': 6 }]
|
|
*
|
|
* // Checking for several possible values
|
|
* _.filter(users, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })]));
|
|
* // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
|
|
*/
|
|
function matches(source) {
|
|
return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* Creates a function that performs a partial deep comparison between the
|
|
* value at `path` of a given object to `srcValue`, returning `true` if the
|
|
* object value is equivalent, else `false`.
|
|
*
|
|
* **Note:** Partial comparisons will match empty array and empty object
|
|
* `srcValue` values against any array or object value, respectively. See
|
|
* `_.isEqual` for a list of supported value comparisons.
|
|
*
|
|
* **Note:** Multiple values can be checked by combining several matchers
|
|
* using `_.overSome`
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.2.0
|
|
* @category Util
|
|
* @param {Array|string} path The path of the property to get.
|
|
* @param {*} srcValue The value to match.
|
|
* @returns {Function} Returns the new spec function.
|
|
* @example
|
|
*
|
|
* var objects = [
|
|
* { 'a': 1, 'b': 2, 'c': 3 },
|
|
* { 'a': 4, 'b': 5, 'c': 6 }
|
|
* ];
|
|
*
|
|
* _.find(objects, _.matchesProperty('a', 4));
|
|
* // => { 'a': 4, 'b': 5, 'c': 6 }
|
|
*
|
|
* // Checking for several possible values
|
|
* _.filter(users, _.overSome([_.matchesProperty('a', 1), _.matchesProperty('a', 4)]));
|
|
* // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
|
|
*/
|
|
function matchesProperty(path, srcValue) {
|
|
return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes the method at `path` of a given object.
|
|
* Any additional arguments are provided to the invoked method.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.7.0
|
|
* @category Util
|
|
* @param {Array|string} path The path of the method to invoke.
|
|
* @param {...*} [args] The arguments to invoke the method with.
|
|
* @returns {Function} Returns the new invoker function.
|
|
* @example
|
|
*
|
|
* var objects = [
|
|
* { 'a': { 'b': _.constant(2) } },
|
|
* { 'a': { 'b': _.constant(1) } }
|
|
* ];
|
|
*
|
|
* _.map(objects, _.method('a.b'));
|
|
* // => [2, 1]
|
|
*
|
|
* _.map(objects, _.method(['a', 'b']));
|
|
* // => [2, 1]
|
|
*/
|
|
var method = baseRest(function(path, args) {
|
|
return function(object) {
|
|
return baseInvoke(object, path, args);
|
|
};
|
|
});
|
|
|
|
/**
|
|
* The opposite of `_.method`; this method creates a function that invokes
|
|
* the method at a given path of `object`. Any additional arguments are
|
|
* provided to the invoked method.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.7.0
|
|
* @category Util
|
|
* @param {Object} object The object to query.
|
|
* @param {...*} [args] The arguments to invoke the method with.
|
|
* @returns {Function} Returns the new invoker function.
|
|
* @example
|
|
*
|
|
* var array = _.times(3, _.constant),
|
|
* object = { 'a': array, 'b': array, 'c': array };
|
|
*
|
|
* _.map(['a[2]', 'c[0]'], _.methodOf(object));
|
|
* // => [2, 0]
|
|
*
|
|
* _.map([['a', '2'], ['c', '0']], _.methodOf(object));
|
|
* // => [2, 0]
|
|
*/
|
|
var methodOf = baseRest(function(object, args) {
|
|
return function(path) {
|
|
return baseInvoke(object, path, args);
|
|
};
|
|
});
|
|
|
|
/**
|
|
* Adds all own enumerable string keyed function properties of a source
|
|
* object to the destination object. If `object` is a function, then methods
|
|
* are added to its prototype as well.
|
|
*
|
|
* **Note:** Use `_.runInContext` to create a pristine `lodash` function to
|
|
* avoid conflicts caused by modifying the original.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {Function|Object} [object=lodash] The destination object.
|
|
* @param {Object} source The object of functions to add.
|
|
* @param {Object} [options={}] The options object.
|
|
* @param {boolean} [options.chain=true] Specify whether mixins are chainable.
|
|
* @returns {Function|Object} Returns `object`.
|
|
* @example
|
|
*
|
|
* function vowels(string) {
|
|
* return _.filter(string, function(v) {
|
|
* return /[aeiou]/i.test(v);
|
|
* });
|
|
* }
|
|
*
|
|
* _.mixin({ 'vowels': vowels });
|
|
* _.vowels('fred');
|
|
* // => ['e']
|
|
*
|
|
* _('fred').vowels().value();
|
|
* // => ['e']
|
|
*
|
|
* _.mixin({ 'vowels': vowels }, { 'chain': false });
|
|
* _('fred').vowels();
|
|
* // => ['e']
|
|
*/
|
|
function mixin(object, source, options) {
|
|
var props = keys(source),
|
|
methodNames = baseFunctions(source, props);
|
|
|
|
if (options == null &&
|
|
!(isObject(source) && (methodNames.length || !props.length))) {
|
|
options = source;
|
|
source = object;
|
|
object = this;
|
|
methodNames = baseFunctions(source, keys(source));
|
|
}
|
|
var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
|
|
isFunc = isFunction(object);
|
|
|
|
arrayEach(methodNames, function(methodName) {
|
|
var func = source[methodName];
|
|
object[methodName] = func;
|
|
if (isFunc) {
|
|
object.prototype[methodName] = function() {
|
|
var chainAll = this.__chain__;
|
|
if (chain || chainAll) {
|
|
var result = object(this.__wrapped__),
|
|
actions = result.__actions__ = copyArray(this.__actions__);
|
|
|
|
actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
|
|
result.__chain__ = chainAll;
|
|
return result;
|
|
}
|
|
return func.apply(object, arrayPush([this.value()], arguments));
|
|
};
|
|
}
|
|
});
|
|
|
|
return object;
|
|
}
|
|
|
|
/**
|
|
* Reverts the `_` variable to its previous value and returns a reference to
|
|
* the `lodash` function.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @returns {Function} Returns the `lodash` function.
|
|
* @example
|
|
*
|
|
* var lodash = _.noConflict();
|
|
*/
|
|
function noConflict() {
|
|
if (root._ === this) {
|
|
root._ = oldDash;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* This method returns `undefined`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.3.0
|
|
* @category Util
|
|
* @example
|
|
*
|
|
* _.times(2, _.noop);
|
|
* // => [undefined, undefined]
|
|
*/
|
|
function noop() {
|
|
// No operation performed.
|
|
}
|
|
|
|
/**
|
|
* Creates a function that gets the argument at index `n`. If `n` is negative,
|
|
* the nth argument from the end is returned.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {number} [n=0] The index of the argument to return.
|
|
* @returns {Function} Returns the new pass-thru function.
|
|
* @example
|
|
*
|
|
* var func = _.nthArg(1);
|
|
* func('a', 'b', 'c', 'd');
|
|
* // => 'b'
|
|
*
|
|
* var func = _.nthArg(-2);
|
|
* func('a', 'b', 'c', 'd');
|
|
* // => 'c'
|
|
*/
|
|
function nthArg(n) {
|
|
n = toInteger(n);
|
|
return baseRest(function(args) {
|
|
return baseNth(args, n);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates a function that invokes `iteratees` with the arguments it receives
|
|
* and returns their results.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {...(Function|Function[])} [iteratees=[_.identity]]
|
|
* The iteratees to invoke.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* var func = _.over([Math.max, Math.min]);
|
|
*
|
|
* func(1, 2, 3, 4);
|
|
* // => [4, 1]
|
|
*/
|
|
var over = createOver(arrayMap);
|
|
|
|
/**
|
|
* Creates a function that checks if **all** of the `predicates` return
|
|
* truthy when invoked with the arguments it receives.
|
|
*
|
|
* Following shorthands are possible for providing predicates.
|
|
* Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
|
|
* Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {...(Function|Function[])} [predicates=[_.identity]]
|
|
* The predicates to check.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* var func = _.overEvery([Boolean, isFinite]);
|
|
*
|
|
* func('1');
|
|
* // => true
|
|
*
|
|
* func(null);
|
|
* // => false
|
|
*
|
|
* func(NaN);
|
|
* // => false
|
|
*/
|
|
var overEvery = createOver(arrayEvery);
|
|
|
|
/**
|
|
* Creates a function that checks if **any** of the `predicates` return
|
|
* truthy when invoked with the arguments it receives.
|
|
*
|
|
* Following shorthands are possible for providing predicates.
|
|
* Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
|
|
* Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {...(Function|Function[])} [predicates=[_.identity]]
|
|
* The predicates to check.
|
|
* @returns {Function} Returns the new function.
|
|
* @example
|
|
*
|
|
* var func = _.overSome([Boolean, isFinite]);
|
|
*
|
|
* func('1');
|
|
* // => true
|
|
*
|
|
* func(null);
|
|
* // => true
|
|
*
|
|
* func(NaN);
|
|
* // => false
|
|
*
|
|
* var matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }])
|
|
* var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]])
|
|
*/
|
|
var overSome = createOver(arraySome);
|
|
|
|
/**
|
|
* Creates a function that returns the value at `path` of a given object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 2.4.0
|
|
* @category Util
|
|
* @param {Array|string} path The path of the property to get.
|
|
* @returns {Function} Returns the new accessor function.
|
|
* @example
|
|
*
|
|
* var objects = [
|
|
* { 'a': { 'b': 2 } },
|
|
* { 'a': { 'b': 1 } }
|
|
* ];
|
|
*
|
|
* _.map(objects, _.property('a.b'));
|
|
* // => [2, 1]
|
|
*
|
|
* _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
|
|
* // => [1, 2]
|
|
*/
|
|
function property(path) {
|
|
return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
|
|
}
|
|
|
|
/**
|
|
* The opposite of `_.property`; this method creates a function that returns
|
|
* the value at a given path of `object`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.0.0
|
|
* @category Util
|
|
* @param {Object} object The object to query.
|
|
* @returns {Function} Returns the new accessor function.
|
|
* @example
|
|
*
|
|
* var array = [0, 1, 2],
|
|
* object = { 'a': array, 'b': array, 'c': array };
|
|
*
|
|
* _.map(['a[2]', 'c[0]'], _.propertyOf(object));
|
|
* // => [2, 0]
|
|
*
|
|
* _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
|
|
* // => [2, 0]
|
|
*/
|
|
function propertyOf(object) {
|
|
return function(path) {
|
|
return object == null ? undefined : baseGet(object, path);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates an array of numbers (positive and/or negative) progressing from
|
|
* `start` up to, but not including, `end`. A step of `-1` is used if a negative
|
|
* `start` is specified without an `end` or `step`. If `end` is not specified,
|
|
* it's set to `start` with `start` then set to `0`.
|
|
*
|
|
* **Note:** JavaScript follows the IEEE-754 standard for resolving
|
|
* floating-point values which can produce unexpected results.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {number} [start=0] The start of the range.
|
|
* @param {number} end The end of the range.
|
|
* @param {number} [step=1] The value to increment or decrement by.
|
|
* @returns {Array} Returns the range of numbers.
|
|
* @see _.inRange, _.rangeRight
|
|
* @example
|
|
*
|
|
* _.range(4);
|
|
* // => [0, 1, 2, 3]
|
|
*
|
|
* _.range(-4);
|
|
* // => [0, -1, -2, -3]
|
|
*
|
|
* _.range(1, 5);
|
|
* // => [1, 2, 3, 4]
|
|
*
|
|
* _.range(0, 20, 5);
|
|
* // => [0, 5, 10, 15]
|
|
*
|
|
* _.range(0, -4, -1);
|
|
* // => [0, -1, -2, -3]
|
|
*
|
|
* _.range(1, 4, 0);
|
|
* // => [1, 1, 1]
|
|
*
|
|
* _.range(0);
|
|
* // => []
|
|
*/
|
|
var range = createRange();
|
|
|
|
/**
|
|
* This method is like `_.range` except that it populates values in
|
|
* descending order.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {number} [start=0] The start of the range.
|
|
* @param {number} end The end of the range.
|
|
* @param {number} [step=1] The value to increment or decrement by.
|
|
* @returns {Array} Returns the range of numbers.
|
|
* @see _.inRange, _.range
|
|
* @example
|
|
*
|
|
* _.rangeRight(4);
|
|
* // => [3, 2, 1, 0]
|
|
*
|
|
* _.rangeRight(-4);
|
|
* // => [-3, -2, -1, 0]
|
|
*
|
|
* _.rangeRight(1, 5);
|
|
* // => [4, 3, 2, 1]
|
|
*
|
|
* _.rangeRight(0, 20, 5);
|
|
* // => [15, 10, 5, 0]
|
|
*
|
|
* _.rangeRight(0, -4, -1);
|
|
* // => [-3, -2, -1, 0]
|
|
*
|
|
* _.rangeRight(1, 4, 0);
|
|
* // => [1, 1, 1]
|
|
*
|
|
* _.rangeRight(0);
|
|
* // => []
|
|
*/
|
|
var rangeRight = createRange(true);
|
|
|
|
/**
|
|
* This method returns a new empty array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.13.0
|
|
* @category Util
|
|
* @returns {Array} Returns the new empty array.
|
|
* @example
|
|
*
|
|
* var arrays = _.times(2, _.stubArray);
|
|
*
|
|
* console.log(arrays);
|
|
* // => [[], []]
|
|
*
|
|
* console.log(arrays[0] === arrays[1]);
|
|
* // => false
|
|
*/
|
|
function stubArray() {
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* This method returns `false`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.13.0
|
|
* @category Util
|
|
* @returns {boolean} Returns `false`.
|
|
* @example
|
|
*
|
|
* _.times(2, _.stubFalse);
|
|
* // => [false, false]
|
|
*/
|
|
function stubFalse() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method returns a new empty object.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.13.0
|
|
* @category Util
|
|
* @returns {Object} Returns the new empty object.
|
|
* @example
|
|
*
|
|
* var objects = _.times(2, _.stubObject);
|
|
*
|
|
* console.log(objects);
|
|
* // => [{}, {}]
|
|
*
|
|
* console.log(objects[0] === objects[1]);
|
|
* // => false
|
|
*/
|
|
function stubObject() {
|
|
return {};
|
|
}
|
|
|
|
/**
|
|
* This method returns an empty string.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.13.0
|
|
* @category Util
|
|
* @returns {string} Returns the empty string.
|
|
* @example
|
|
*
|
|
* _.times(2, _.stubString);
|
|
* // => ['', '']
|
|
*/
|
|
function stubString() {
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* This method returns `true`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.13.0
|
|
* @category Util
|
|
* @returns {boolean} Returns `true`.
|
|
* @example
|
|
*
|
|
* _.times(2, _.stubTrue);
|
|
* // => [true, true]
|
|
*/
|
|
function stubTrue() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Invokes the iteratee `n` times, returning an array of the results of
|
|
* each invocation. The iteratee is invoked with one argument; (index).
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {number} n The number of times to invoke `iteratee`.
|
|
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
|
* @returns {Array} Returns the array of results.
|
|
* @example
|
|
*
|
|
* _.times(3, String);
|
|
* // => ['0', '1', '2']
|
|
*
|
|
* _.times(4, _.constant(0));
|
|
* // => [0, 0, 0, 0]
|
|
*/
|
|
function times(n, iteratee) {
|
|
n = toInteger(n);
|
|
if (n < 1 || n > MAX_SAFE_INTEGER) {
|
|
return [];
|
|
}
|
|
var index = MAX_ARRAY_LENGTH,
|
|
length = nativeMin(n, MAX_ARRAY_LENGTH);
|
|
|
|
iteratee = getIteratee(iteratee);
|
|
n -= MAX_ARRAY_LENGTH;
|
|
|
|
var result = baseTimes(length, iteratee);
|
|
while (++index < n) {
|
|
iteratee(index);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts `value` to a property path array.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Util
|
|
* @param {*} value The value to convert.
|
|
* @returns {Array} Returns the new property path array.
|
|
* @example
|
|
*
|
|
* _.toPath('a.b.c');
|
|
* // => ['a', 'b', 'c']
|
|
*
|
|
* _.toPath('a[0].b.c');
|
|
* // => ['a', '0', 'b', 'c']
|
|
*/
|
|
function toPath(value) {
|
|
if (isArray(value)) {
|
|
return arrayMap(value, toKey);
|
|
}
|
|
return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
|
|
}
|
|
|
|
/**
|
|
* Generates a unique ID. If `prefix` is given, the ID is appended to it.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Util
|
|
* @param {string} [prefix=''] The value to prefix the ID with.
|
|
* @returns {string} Returns the unique ID.
|
|
* @example
|
|
*
|
|
* _.uniqueId('contact_');
|
|
* // => 'contact_104'
|
|
*
|
|
* _.uniqueId();
|
|
* // => '105'
|
|
*/
|
|
function uniqueId(prefix) {
|
|
var id = ++idCounter;
|
|
return toString(prefix) + id;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Adds two numbers.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.4.0
|
|
* @category Math
|
|
* @param {number} augend The first number in an addition.
|
|
* @param {number} addend The second number in an addition.
|
|
* @returns {number} Returns the total.
|
|
* @example
|
|
*
|
|
* _.add(6, 4);
|
|
* // => 10
|
|
*/
|
|
var add = createMathOperation(function(augend, addend) {
|
|
return augend + addend;
|
|
}, 0);
|
|
|
|
/**
|
|
* Computes `number` rounded up to `precision`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.10.0
|
|
* @category Math
|
|
* @param {number} number The number to round up.
|
|
* @param {number} [precision=0] The precision to round up to.
|
|
* @returns {number} Returns the rounded up number.
|
|
* @example
|
|
*
|
|
* _.ceil(4.006);
|
|
* // => 5
|
|
*
|
|
* _.ceil(6.004, 2);
|
|
* // => 6.01
|
|
*
|
|
* _.ceil(6040, -2);
|
|
* // => 6100
|
|
*/
|
|
var ceil = createRound('ceil');
|
|
|
|
/**
|
|
* Divide two numbers.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.7.0
|
|
* @category Math
|
|
* @param {number} dividend The first number in a division.
|
|
* @param {number} divisor The second number in a division.
|
|
* @returns {number} Returns the quotient.
|
|
* @example
|
|
*
|
|
* _.divide(6, 4);
|
|
* // => 1.5
|
|
*/
|
|
var divide = createMathOperation(function(dividend, divisor) {
|
|
return dividend / divisor;
|
|
}, 1);
|
|
|
|
/**
|
|
* Computes `number` rounded down to `precision`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.10.0
|
|
* @category Math
|
|
* @param {number} number The number to round down.
|
|
* @param {number} [precision=0] The precision to round down to.
|
|
* @returns {number} Returns the rounded down number.
|
|
* @example
|
|
*
|
|
* _.floor(4.006);
|
|
* // => 4
|
|
*
|
|
* _.floor(0.046, 2);
|
|
* // => 0.04
|
|
*
|
|
* _.floor(4060, -2);
|
|
* // => 4000
|
|
*/
|
|
var floor = createRound('floor');
|
|
|
|
/**
|
|
* Computes the maximum value of `array`. If `array` is empty or falsey,
|
|
* `undefined` is returned.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @returns {*} Returns the maximum value.
|
|
* @example
|
|
*
|
|
* _.max([4, 2, 8, 6]);
|
|
* // => 8
|
|
*
|
|
* _.max([]);
|
|
* // => undefined
|
|
*/
|
|
function max(array) {
|
|
return (array && array.length)
|
|
? baseExtremum(array, identity, baseGt)
|
|
: undefined;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.max` except that it accepts `iteratee` which is
|
|
* invoked for each element in `array` to generate the criterion by which
|
|
* the value is ranked. The iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {*} Returns the maximum value.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'n': 1 }, { 'n': 2 }];
|
|
*
|
|
* _.maxBy(objects, function(o) { return o.n; });
|
|
* // => { 'n': 2 }
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.maxBy(objects, 'n');
|
|
* // => { 'n': 2 }
|
|
*/
|
|
function maxBy(array, iteratee) {
|
|
return (array && array.length)
|
|
? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
|
|
: undefined;
|
|
}
|
|
|
|
/**
|
|
* Computes the mean of the values in `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @returns {number} Returns the mean.
|
|
* @example
|
|
*
|
|
* _.mean([4, 2, 8, 6]);
|
|
* // => 5
|
|
*/
|
|
function mean(array) {
|
|
return baseMean(array, identity);
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.mean` except that it accepts `iteratee` which is
|
|
* invoked for each element in `array` to generate the value to be averaged.
|
|
* The iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.7.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {number} Returns the mean.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
|
|
*
|
|
* _.meanBy(objects, function(o) { return o.n; });
|
|
* // => 5
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.meanBy(objects, 'n');
|
|
* // => 5
|
|
*/
|
|
function meanBy(array, iteratee) {
|
|
return baseMean(array, getIteratee(iteratee, 2));
|
|
}
|
|
|
|
/**
|
|
* Computes the minimum value of `array`. If `array` is empty or falsey,
|
|
* `undefined` is returned.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @returns {*} Returns the minimum value.
|
|
* @example
|
|
*
|
|
* _.min([4, 2, 8, 6]);
|
|
* // => 2
|
|
*
|
|
* _.min([]);
|
|
* // => undefined
|
|
*/
|
|
function min(array) {
|
|
return (array && array.length)
|
|
? baseExtremum(array, identity, baseLt)
|
|
: undefined;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.min` except that it accepts `iteratee` which is
|
|
* invoked for each element in `array` to generate the criterion by which
|
|
* the value is ranked. The iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {*} Returns the minimum value.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'n': 1 }, { 'n': 2 }];
|
|
*
|
|
* _.minBy(objects, function(o) { return o.n; });
|
|
* // => { 'n': 1 }
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.minBy(objects, 'n');
|
|
* // => { 'n': 1 }
|
|
*/
|
|
function minBy(array, iteratee) {
|
|
return (array && array.length)
|
|
? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
|
|
: undefined;
|
|
}
|
|
|
|
/**
|
|
* Multiply two numbers.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.7.0
|
|
* @category Math
|
|
* @param {number} multiplier The first number in a multiplication.
|
|
* @param {number} multiplicand The second number in a multiplication.
|
|
* @returns {number} Returns the product.
|
|
* @example
|
|
*
|
|
* _.multiply(6, 4);
|
|
* // => 24
|
|
*/
|
|
var multiply = createMathOperation(function(multiplier, multiplicand) {
|
|
return multiplier * multiplicand;
|
|
}, 1);
|
|
|
|
/**
|
|
* Computes `number` rounded to `precision`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.10.0
|
|
* @category Math
|
|
* @param {number} number The number to round.
|
|
* @param {number} [precision=0] The precision to round to.
|
|
* @returns {number} Returns the rounded number.
|
|
* @example
|
|
*
|
|
* _.round(4.006);
|
|
* // => 4
|
|
*
|
|
* _.round(4.006, 2);
|
|
* // => 4.01
|
|
*
|
|
* _.round(4060, -2);
|
|
* // => 4100
|
|
*/
|
|
var round = createRound('round');
|
|
|
|
/**
|
|
* Subtract two numbers.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Math
|
|
* @param {number} minuend The first number in a subtraction.
|
|
* @param {number} subtrahend The second number in a subtraction.
|
|
* @returns {number} Returns the difference.
|
|
* @example
|
|
*
|
|
* _.subtract(6, 4);
|
|
* // => 2
|
|
*/
|
|
var subtract = createMathOperation(function(minuend, subtrahend) {
|
|
return minuend - subtrahend;
|
|
}, 0);
|
|
|
|
/**
|
|
* Computes the sum of the values in `array`.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 3.4.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @returns {number} Returns the sum.
|
|
* @example
|
|
*
|
|
* _.sum([4, 2, 8, 6]);
|
|
* // => 20
|
|
*/
|
|
function sum(array) {
|
|
return (array && array.length)
|
|
? baseSum(array, identity)
|
|
: 0;
|
|
}
|
|
|
|
/**
|
|
* This method is like `_.sum` except that it accepts `iteratee` which is
|
|
* invoked for each element in `array` to generate the value to be summed.
|
|
* The iteratee is invoked with one argument: (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Math
|
|
* @param {Array} array The array to iterate over.
|
|
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
|
* @returns {number} Returns the sum.
|
|
* @example
|
|
*
|
|
* var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
|
|
*
|
|
* _.sumBy(objects, function(o) { return o.n; });
|
|
* // => 20
|
|
*
|
|
* // The `_.property` iteratee shorthand.
|
|
* _.sumBy(objects, 'n');
|
|
* // => 20
|
|
*/
|
|
function sumBy(array, iteratee) {
|
|
return (array && array.length)
|
|
? baseSum(array, getIteratee(iteratee, 2))
|
|
: 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
// Add methods that return wrapped values in chain sequences.
|
|
lodash.after = after;
|
|
lodash.ary = ary;
|
|
lodash.assign = assign;
|
|
lodash.assignIn = assignIn;
|
|
lodash.assignInWith = assignInWith;
|
|
lodash.assignWith = assignWith;
|
|
lodash.at = at;
|
|
lodash.before = before;
|
|
lodash.bind = bind;
|
|
lodash.bindAll = bindAll;
|
|
lodash.bindKey = bindKey;
|
|
lodash.castArray = castArray;
|
|
lodash.chain = chain;
|
|
lodash.chunk = chunk;
|
|
lodash.compact = compact;
|
|
lodash.concat = concat;
|
|
lodash.cond = cond;
|
|
lodash.conforms = conforms;
|
|
lodash.constant = constant;
|
|
lodash.countBy = countBy;
|
|
lodash.create = create;
|
|
lodash.curry = curry;
|
|
lodash.curryRight = curryRight;
|
|
lodash.debounce = debounce;
|
|
lodash.defaults = defaults;
|
|
lodash.defaultsDeep = defaultsDeep;
|
|
lodash.defer = defer;
|
|
lodash.delay = delay;
|
|
lodash.difference = difference;
|
|
lodash.differenceBy = differenceBy;
|
|
lodash.differenceWith = differenceWith;
|
|
lodash.drop = drop;
|
|
lodash.dropRight = dropRight;
|
|
lodash.dropRightWhile = dropRightWhile;
|
|
lodash.dropWhile = dropWhile;
|
|
lodash.fill = fill;
|
|
lodash.filter = filter;
|
|
lodash.flatMap = flatMap;
|
|
lodash.flatMapDeep = flatMapDeep;
|
|
lodash.flatMapDepth = flatMapDepth;
|
|
lodash.flatten = flatten;
|
|
lodash.flattenDeep = flattenDeep;
|
|
lodash.flattenDepth = flattenDepth;
|
|
lodash.flip = flip;
|
|
lodash.flow = flow;
|
|
lodash.flowRight = flowRight;
|
|
lodash.fromPairs = fromPairs;
|
|
lodash.functions = functions;
|
|
lodash.functionsIn = functionsIn;
|
|
lodash.groupBy = groupBy;
|
|
lodash.initial = initial;
|
|
lodash.intersection = intersection;
|
|
lodash.intersectionBy = intersectionBy;
|
|
lodash.intersectionWith = intersectionWith;
|
|
lodash.invert = invert;
|
|
lodash.invertBy = invertBy;
|
|
lodash.invokeMap = invokeMap;
|
|
lodash.iteratee = iteratee;
|
|
lodash.keyBy = keyBy;
|
|
lodash.keys = keys;
|
|
lodash.keysIn = keysIn;
|
|
lodash.map = map;
|
|
lodash.mapKeys = mapKeys;
|
|
lodash.mapValues = mapValues;
|
|
lodash.matches = matches;
|
|
lodash.matchesProperty = matchesProperty;
|
|
lodash.memoize = memoize;
|
|
lodash.merge = merge;
|
|
lodash.mergeWith = mergeWith;
|
|
lodash.method = method;
|
|
lodash.methodOf = methodOf;
|
|
lodash.mixin = mixin;
|
|
lodash.negate = negate;
|
|
lodash.nthArg = nthArg;
|
|
lodash.omit = omit;
|
|
lodash.omitBy = omitBy;
|
|
lodash.once = once;
|
|
lodash.orderBy = orderBy;
|
|
lodash.over = over;
|
|
lodash.overArgs = overArgs;
|
|
lodash.overEvery = overEvery;
|
|
lodash.overSome = overSome;
|
|
lodash.partial = partial;
|
|
lodash.partialRight = partialRight;
|
|
lodash.partition = partition;
|
|
lodash.pick = pick;
|
|
lodash.pickBy = pickBy;
|
|
lodash.property = property;
|
|
lodash.propertyOf = propertyOf;
|
|
lodash.pull = pull;
|
|
lodash.pullAll = pullAll;
|
|
lodash.pullAllBy = pullAllBy;
|
|
lodash.pullAllWith = pullAllWith;
|
|
lodash.pullAt = pullAt;
|
|
lodash.range = range;
|
|
lodash.rangeRight = rangeRight;
|
|
lodash.rearg = rearg;
|
|
lodash.reject = reject;
|
|
lodash.remove = remove;
|
|
lodash.rest = rest;
|
|
lodash.reverse = reverse;
|
|
lodash.sampleSize = sampleSize;
|
|
lodash.set = set;
|
|
lodash.setWith = setWith;
|
|
lodash.shuffle = shuffle;
|
|
lodash.slice = slice;
|
|
lodash.sortBy = sortBy;
|
|
lodash.sortedUniq = sortedUniq;
|
|
lodash.sortedUniqBy = sortedUniqBy;
|
|
lodash.split = split;
|
|
lodash.spread = spread;
|
|
lodash.tail = tail;
|
|
lodash.take = take;
|
|
lodash.takeRight = takeRight;
|
|
lodash.takeRightWhile = takeRightWhile;
|
|
lodash.takeWhile = takeWhile;
|
|
lodash.tap = tap;
|
|
lodash.throttle = throttle;
|
|
lodash.thru = thru;
|
|
lodash.toArray = toArray;
|
|
lodash.toPairs = toPairs;
|
|
lodash.toPairsIn = toPairsIn;
|
|
lodash.toPath = toPath;
|
|
lodash.toPlainObject = toPlainObject;
|
|
lodash.transform = transform;
|
|
lodash.unary = unary;
|
|
lodash.union = union;
|
|
lodash.unionBy = unionBy;
|
|
lodash.unionWith = unionWith;
|
|
lodash.uniq = uniq;
|
|
lodash.uniqBy = uniqBy;
|
|
lodash.uniqWith = uniqWith;
|
|
lodash.unset = unset;
|
|
lodash.unzip = unzip;
|
|
lodash.unzipWith = unzipWith;
|
|
lodash.update = update;
|
|
lodash.updateWith = updateWith;
|
|
lodash.values = values;
|
|
lodash.valuesIn = valuesIn;
|
|
lodash.without = without;
|
|
lodash.words = words;
|
|
lodash.wrap = wrap;
|
|
lodash.xor = xor;
|
|
lodash.xorBy = xorBy;
|
|
lodash.xorWith = xorWith;
|
|
lodash.zip = zip;
|
|
lodash.zipObject = zipObject;
|
|
lodash.zipObjectDeep = zipObjectDeep;
|
|
lodash.zipWith = zipWith;
|
|
|
|
// Add aliases.
|
|
lodash.entries = toPairs;
|
|
lodash.entriesIn = toPairsIn;
|
|
lodash.extend = assignIn;
|
|
lodash.extendWith = assignInWith;
|
|
|
|
// Add methods to `lodash.prototype`.
|
|
mixin(lodash, lodash);
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
// Add methods that return unwrapped values in chain sequences.
|
|
lodash.add = add;
|
|
lodash.attempt = attempt;
|
|
lodash.camelCase = camelCase;
|
|
lodash.capitalize = capitalize;
|
|
lodash.ceil = ceil;
|
|
lodash.clamp = clamp;
|
|
lodash.clone = clone;
|
|
lodash.cloneDeep = cloneDeep;
|
|
lodash.cloneDeepWith = cloneDeepWith;
|
|
lodash.cloneWith = cloneWith;
|
|
lodash.conformsTo = conformsTo;
|
|
lodash.deburr = deburr;
|
|
lodash.defaultTo = defaultTo;
|
|
lodash.divide = divide;
|
|
lodash.endsWith = endsWith;
|
|
lodash.eq = eq;
|
|
lodash.escape = escape;
|
|
lodash.escapeRegExp = escapeRegExp;
|
|
lodash.every = every;
|
|
lodash.find = find;
|
|
lodash.findIndex = findIndex;
|
|
lodash.findKey = findKey;
|
|
lodash.findLast = findLast;
|
|
lodash.findLastIndex = findLastIndex;
|
|
lodash.findLastKey = findLastKey;
|
|
lodash.floor = floor;
|
|
lodash.forEach = forEach;
|
|
lodash.forEachRight = forEachRight;
|
|
lodash.forIn = forIn;
|
|
lodash.forInRight = forInRight;
|
|
lodash.forOwn = forOwn;
|
|
lodash.forOwnRight = forOwnRight;
|
|
lodash.get = get;
|
|
lodash.gt = gt;
|
|
lodash.gte = gte;
|
|
lodash.has = has;
|
|
lodash.hasIn = hasIn;
|
|
lodash.head = head;
|
|
lodash.identity = identity;
|
|
lodash.includes = includes;
|
|
lodash.indexOf = indexOf;
|
|
lodash.inRange = inRange;
|
|
lodash.invoke = invoke;
|
|
lodash.isArguments = isArguments;
|
|
lodash.isArray = isArray;
|
|
lodash.isArrayBuffer = isArrayBuffer;
|
|
lodash.isArrayLike = isArrayLike;
|
|
lodash.isArrayLikeObject = isArrayLikeObject;
|
|
lodash.isBoolean = isBoolean;
|
|
lodash.isBuffer = isBuffer;
|
|
lodash.isDate = isDate;
|
|
lodash.isElement = isElement;
|
|
lodash.isEmpty = isEmpty;
|
|
lodash.isEqual = isEqual;
|
|
lodash.isEqualWith = isEqualWith;
|
|
lodash.isError = isError;
|
|
lodash.isFinite = isFinite;
|
|
lodash.isFunction = isFunction;
|
|
lodash.isInteger = isInteger;
|
|
lodash.isLength = isLength;
|
|
lodash.isMap = isMap;
|
|
lodash.isMatch = isMatch;
|
|
lodash.isMatchWith = isMatchWith;
|
|
lodash.isNaN = isNaN;
|
|
lodash.isNative = isNative;
|
|
lodash.isNil = isNil;
|
|
lodash.isNull = isNull;
|
|
lodash.isNumber = isNumber;
|
|
lodash.isObject = isObject;
|
|
lodash.isObjectLike = isObjectLike;
|
|
lodash.isPlainObject = isPlainObject;
|
|
lodash.isRegExp = isRegExp;
|
|
lodash.isSafeInteger = isSafeInteger;
|
|
lodash.isSet = isSet;
|
|
lodash.isString = isString;
|
|
lodash.isSymbol = isSymbol;
|
|
lodash.isTypedArray = isTypedArray;
|
|
lodash.isUndefined = isUndefined;
|
|
lodash.isWeakMap = isWeakMap;
|
|
lodash.isWeakSet = isWeakSet;
|
|
lodash.join = join;
|
|
lodash.kebabCase = kebabCase;
|
|
lodash.last = last;
|
|
lodash.lastIndexOf = lastIndexOf;
|
|
lodash.lowerCase = lowerCase;
|
|
lodash.lowerFirst = lowerFirst;
|
|
lodash.lt = lt;
|
|
lodash.lte = lte;
|
|
lodash.max = max;
|
|
lodash.maxBy = maxBy;
|
|
lodash.mean = mean;
|
|
lodash.meanBy = meanBy;
|
|
lodash.min = min;
|
|
lodash.minBy = minBy;
|
|
lodash.stubArray = stubArray;
|
|
lodash.stubFalse = stubFalse;
|
|
lodash.stubObject = stubObject;
|
|
lodash.stubString = stubString;
|
|
lodash.stubTrue = stubTrue;
|
|
lodash.multiply = multiply;
|
|
lodash.nth = nth;
|
|
lodash.noConflict = noConflict;
|
|
lodash.noop = noop;
|
|
lodash.now = now;
|
|
lodash.pad = pad;
|
|
lodash.padEnd = padEnd;
|
|
lodash.padStart = padStart;
|
|
lodash.parseInt = parseInt;
|
|
lodash.random = random;
|
|
lodash.reduce = reduce;
|
|
lodash.reduceRight = reduceRight;
|
|
lodash.repeat = repeat;
|
|
lodash.replace = replace;
|
|
lodash.result = result;
|
|
lodash.round = round;
|
|
lodash.runInContext = runInContext;
|
|
lodash.sample = sample;
|
|
lodash.size = size;
|
|
lodash.snakeCase = snakeCase;
|
|
lodash.some = some;
|
|
lodash.sortedIndex = sortedIndex;
|
|
lodash.sortedIndexBy = sortedIndexBy;
|
|
lodash.sortedIndexOf = sortedIndexOf;
|
|
lodash.sortedLastIndex = sortedLastIndex;
|
|
lodash.sortedLastIndexBy = sortedLastIndexBy;
|
|
lodash.sortedLastIndexOf = sortedLastIndexOf;
|
|
lodash.startCase = startCase;
|
|
lodash.startsWith = startsWith;
|
|
lodash.subtract = subtract;
|
|
lodash.sum = sum;
|
|
lodash.sumBy = sumBy;
|
|
lodash.template = template;
|
|
lodash.times = times;
|
|
lodash.toFinite = toFinite;
|
|
lodash.toInteger = toInteger;
|
|
lodash.toLength = toLength;
|
|
lodash.toLower = toLower;
|
|
lodash.toNumber = toNumber;
|
|
lodash.toSafeInteger = toSafeInteger;
|
|
lodash.toString = toString;
|
|
lodash.toUpper = toUpper;
|
|
lodash.trim = trim;
|
|
lodash.trimEnd = trimEnd;
|
|
lodash.trimStart = trimStart;
|
|
lodash.truncate = truncate;
|
|
lodash.unescape = unescape;
|
|
lodash.uniqueId = uniqueId;
|
|
lodash.upperCase = upperCase;
|
|
lodash.upperFirst = upperFirst;
|
|
|
|
// Add aliases.
|
|
lodash.each = forEach;
|
|
lodash.eachRight = forEachRight;
|
|
lodash.first = head;
|
|
|
|
mixin(lodash, (function() {
|
|
var source = {};
|
|
baseForOwn(lodash, function(func, methodName) {
|
|
if (!hasOwnProperty.call(lodash.prototype, methodName)) {
|
|
source[methodName] = func;
|
|
}
|
|
});
|
|
return source;
|
|
}()), { 'chain': false });
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* The semantic version number.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @type {string}
|
|
*/
|
|
lodash.VERSION = VERSION;
|
|
|
|
// Assign default placeholders.
|
|
arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
|
|
lodash[methodName].placeholder = lodash;
|
|
});
|
|
|
|
// Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
|
|
arrayEach(['drop', 'take'], function(methodName, index) {
|
|
LazyWrapper.prototype[methodName] = function(n) {
|
|
n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
|
|
|
|
var result = (this.__filtered__ && !index)
|
|
? new LazyWrapper(this)
|
|
: this.clone();
|
|
|
|
if (result.__filtered__) {
|
|
result.__takeCount__ = nativeMin(n, result.__takeCount__);
|
|
} else {
|
|
result.__views__.push({
|
|
'size': nativeMin(n, MAX_ARRAY_LENGTH),
|
|
'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
|
|
});
|
|
}
|
|
return result;
|
|
};
|
|
|
|
LazyWrapper.prototype[methodName + 'Right'] = function(n) {
|
|
return this.reverse()[methodName](n).reverse();
|
|
};
|
|
});
|
|
|
|
// Add `LazyWrapper` methods that accept an `iteratee` value.
|
|
arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
|
|
var type = index + 1,
|
|
isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
|
|
|
|
LazyWrapper.prototype[methodName] = function(iteratee) {
|
|
var result = this.clone();
|
|
result.__iteratees__.push({
|
|
'iteratee': getIteratee(iteratee, 3),
|
|
'type': type
|
|
});
|
|
result.__filtered__ = result.__filtered__ || isFilter;
|
|
return result;
|
|
};
|
|
});
|
|
|
|
// Add `LazyWrapper` methods for `_.head` and `_.last`.
|
|
arrayEach(['head', 'last'], function(methodName, index) {
|
|
var takeName = 'take' + (index ? 'Right' : '');
|
|
|
|
LazyWrapper.prototype[methodName] = function() {
|
|
return this[takeName](1).value()[0];
|
|
};
|
|
});
|
|
|
|
// Add `LazyWrapper` methods for `_.initial` and `_.tail`.
|
|
arrayEach(['initial', 'tail'], function(methodName, index) {
|
|
var dropName = 'drop' + (index ? '' : 'Right');
|
|
|
|
LazyWrapper.prototype[methodName] = function() {
|
|
return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
|
|
};
|
|
});
|
|
|
|
LazyWrapper.prototype.compact = function() {
|
|
return this.filter(identity);
|
|
};
|
|
|
|
LazyWrapper.prototype.find = function(predicate) {
|
|
return this.filter(predicate).head();
|
|
};
|
|
|
|
LazyWrapper.prototype.findLast = function(predicate) {
|
|
return this.reverse().find(predicate);
|
|
};
|
|
|
|
LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
|
|
if (typeof path == 'function') {
|
|
return new LazyWrapper(this);
|
|
}
|
|
return this.map(function(value) {
|
|
return baseInvoke(value, path, args);
|
|
});
|
|
});
|
|
|
|
LazyWrapper.prototype.reject = function(predicate) {
|
|
return this.filter(negate(getIteratee(predicate)));
|
|
};
|
|
|
|
LazyWrapper.prototype.slice = function(start, end) {
|
|
start = toInteger(start);
|
|
|
|
var result = this;
|
|
if (result.__filtered__ && (start > 0 || end < 0)) {
|
|
return new LazyWrapper(result);
|
|
}
|
|
if (start < 0) {
|
|
result = result.takeRight(-start);
|
|
} else if (start) {
|
|
result = result.drop(start);
|
|
}
|
|
if (end !== undefined) {
|
|
end = toInteger(end);
|
|
result = end < 0 ? result.dropRight(-end) : result.take(end - start);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
LazyWrapper.prototype.takeRightWhile = function(predicate) {
|
|
return this.reverse().takeWhile(predicate).reverse();
|
|
};
|
|
|
|
LazyWrapper.prototype.toArray = function() {
|
|
return this.take(MAX_ARRAY_LENGTH);
|
|
};
|
|
|
|
// Add `LazyWrapper` methods to `lodash.prototype`.
|
|
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
|
var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
|
|
isTaker = /^(?:head|last)$/.test(methodName),
|
|
lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
|
|
retUnwrapped = isTaker || /^find/.test(methodName);
|
|
|
|
if (!lodashFunc) {
|
|
return;
|
|
}
|
|
lodash.prototype[methodName] = function() {
|
|
var value = this.__wrapped__,
|
|
args = isTaker ? [1] : arguments,
|
|
isLazy = value instanceof LazyWrapper,
|
|
iteratee = args[0],
|
|
useLazy = isLazy || isArray(value);
|
|
|
|
var interceptor = function(value) {
|
|
var result = lodashFunc.apply(lodash, arrayPush([value], args));
|
|
return (isTaker && chainAll) ? result[0] : result;
|
|
};
|
|
|
|
if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
|
|
// Avoid lazy use if the iteratee has a "length" value other than `1`.
|
|
isLazy = useLazy = false;
|
|
}
|
|
var chainAll = this.__chain__,
|
|
isHybrid = !!this.__actions__.length,
|
|
isUnwrapped = retUnwrapped && !chainAll,
|
|
onlyLazy = isLazy && !isHybrid;
|
|
|
|
if (!retUnwrapped && useLazy) {
|
|
value = onlyLazy ? value : new LazyWrapper(this);
|
|
var result = func.apply(value, args);
|
|
result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
|
|
return new LodashWrapper(result, chainAll);
|
|
}
|
|
if (isUnwrapped && onlyLazy) {
|
|
return func.apply(this, args);
|
|
}
|
|
result = this.thru(interceptor);
|
|
return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
|
|
};
|
|
});
|
|
|
|
// Add `Array` methods to `lodash.prototype`.
|
|
arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
|
|
var func = arrayProto[methodName],
|
|
chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
|
|
retUnwrapped = /^(?:pop|shift)$/.test(methodName);
|
|
|
|
lodash.prototype[methodName] = function() {
|
|
var args = arguments;
|
|
if (retUnwrapped && !this.__chain__) {
|
|
var value = this.value();
|
|
return func.apply(isArray(value) ? value : [], args);
|
|
}
|
|
return this[chainName](function(value) {
|
|
return func.apply(isArray(value) ? value : [], args);
|
|
});
|
|
};
|
|
});
|
|
|
|
// Map minified method names to their real names.
|
|
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
|
var lodashFunc = lodash[methodName];
|
|
if (lodashFunc) {
|
|
var key = lodashFunc.name + '';
|
|
if (!hasOwnProperty.call(realNames, key)) {
|
|
realNames[key] = [];
|
|
}
|
|
realNames[key].push({ 'name': methodName, 'func': lodashFunc });
|
|
}
|
|
});
|
|
|
|
realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{
|
|
'name': 'wrapper',
|
|
'func': undefined
|
|
}];
|
|
|
|
// Add methods to `LazyWrapper`.
|
|
LazyWrapper.prototype.clone = lazyClone;
|
|
LazyWrapper.prototype.reverse = lazyReverse;
|
|
LazyWrapper.prototype.value = lazyValue;
|
|
|
|
// Add chain sequence methods to the `lodash` wrapper.
|
|
lodash.prototype.at = wrapperAt;
|
|
lodash.prototype.chain = wrapperChain;
|
|
lodash.prototype.commit = wrapperCommit;
|
|
lodash.prototype.next = wrapperNext;
|
|
lodash.prototype.plant = wrapperPlant;
|
|
lodash.prototype.reverse = wrapperReverse;
|
|
lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
|
|
|
|
// Add lazy aliases.
|
|
lodash.prototype.first = lodash.prototype.head;
|
|
|
|
if (symIterator) {
|
|
lodash.prototype[symIterator] = wrapperToIterator;
|
|
}
|
|
return lodash;
|
|
});
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
// Export lodash.
|
|
var _ = runInContext();
|
|
|
|
// Some AMD build optimizers, like r.js, check for condition patterns like:
|
|
if (true) {
|
|
// Expose Lodash on the global object to prevent errors when Lodash is
|
|
// loaded by a script tag in the presence of an AMD loader.
|
|
// See http://requirejs.org/docs/errors.html#mismatch for more details.
|
|
// Use `_.noConflict` to remove Lodash from the global object.
|
|
root._ = _;
|
|
|
|
// Define as an anonymous module so, through path mapping, it can be
|
|
// referenced as the "underscore" module.
|
|
!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
|
|
return _;
|
|
}).call(exports, __webpack_require__, exports, module),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
|
}
|
|
// Check for `exports` after `define` in case a build optimizer adds it.
|
|
else {}
|
|
}.call(this));
|
|
|
|
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(6), __webpack_require__(77)(module)))
|
|
|
|
/***/ }),
|
|
/* 77 */
|
|
/***/ (function(module, exports) {
|
|
|
|
module.exports = function(module) {
|
|
if (!module.webpackPolyfill) {
|
|
module.deprecate = function() {};
|
|
module.paths = [];
|
|
// module.parent = undefined by default
|
|
if (!module.children) module.children = [];
|
|
Object.defineProperty(module, "loaded", {
|
|
enumerable: true,
|
|
get: function() {
|
|
return module.l;
|
|
}
|
|
});
|
|
Object.defineProperty(module, "id", {
|
|
enumerable: true,
|
|
get: function() {
|
|
return module.i;
|
|
}
|
|
});
|
|
module.webpackPolyfill = 1;
|
|
}
|
|
return module;
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 78 */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/*! gettext.js - Guillaume Potier - MIT Licensed */
|
|
var i18n = function (options) {
|
|
options = options || {};
|
|
this.__version = '1.0.0';
|
|
|
|
// default values that could be overriden in i18n() construct
|
|
var defaults = {
|
|
domain: 'messages',
|
|
locale: (typeof document !== 'undefined' ? document.documentElement.getAttribute('lang') : false) || 'en',
|
|
plural_func: function (n) { return { nplurals: 2, plural: (n!=1) ? 1 : 0 }; },
|
|
ctxt_delimiter: String.fromCharCode(4) // \u0004
|
|
};
|
|
|
|
// handy mixins taken from underscode.js
|
|
var _ = {
|
|
isObject: function (obj) {
|
|
var type = typeof obj;
|
|
return type === 'function' || type === 'object' && !!obj;
|
|
},
|
|
isArray: function (obj) {
|
|
return toString.call(obj) === '[object Array]';
|
|
}
|
|
};
|
|
|
|
var
|
|
_plural_funcs = {},
|
|
_locale = options.locale || defaults.locale,
|
|
_domain = options.domain || defaults.domain,
|
|
_dictionary = {},
|
|
_plural_forms = {},
|
|
_ctxt_delimiter = options.ctxt_delimiter || defaults.ctxt_delimiter;
|
|
|
|
if (options.messages) {
|
|
_dictionary[_domain] = {};
|
|
_dictionary[_domain][_locale] = options.messages;
|
|
}
|
|
|
|
if (options.plural_forms) {
|
|
_plural_forms[_locale] = options.plural_forms;
|
|
}
|
|
|
|
// sprintf equivalent, takes a string and some arguments to make a computed string
|
|
// eg: strfmt("%1 dogs are in %2", 7, "the kitchen"); => "7 dogs are in the kitchen"
|
|
// eg: strfmt("I like %1, bananas and %1", "apples"); => "I like apples, bananas and apples"
|
|
// NB: removes msg context if there is one present
|
|
var strfmt = function (fmt) {
|
|
var args = arguments;
|
|
|
|
return fmt
|
|
// put space after double % to prevent placeholder replacement of such matches
|
|
.replace(/%%/g, '%% ')
|
|
// replace placeholders
|
|
.replace(/%(\d+)/g, function (str, p1) {
|
|
return args[p1];
|
|
})
|
|
// replace double % and space with single %
|
|
.replace(/%% /g, '%')
|
|
};
|
|
|
|
var removeContext = function(str) {
|
|
// if there is context, remove it
|
|
if (str.indexOf(_ctxt_delimiter) !== -1) {
|
|
var parts = str.split(_ctxt_delimiter);
|
|
return parts[1];
|
|
}
|
|
|
|
return str;
|
|
};
|
|
|
|
var expand_locale = function(locale) {
|
|
var locales = [locale],
|
|
i = locale.lastIndexOf('-');
|
|
while (i > 0) {
|
|
locale = locale.slice(0, i);
|
|
locales.push(locale);
|
|
i = locale.lastIndexOf('-');
|
|
}
|
|
return locales;
|
|
};
|
|
|
|
var getPluralFunc = function (plural_form) {
|
|
// Plural form string regexp
|
|
// taken from https://github.com/Orange-OpenSource/gettext.js/blob/master/lib.gettext.js
|
|
// plural forms list available here http://localization-guide.readthedocs.org/en/latest/l10n/pluralforms.html
|
|
var pf_re = new RegExp('^\\s*nplurals\\s*=\\s*[0-9]+\\s*;\\s*plural\\s*=\\s*(?:\\s|[-\\?\\|&=!<>+*/%:;n0-9_\(\)])+');
|
|
|
|
if (!pf_re.test(plural_form))
|
|
throw new Error(strfmt('The plural form "%1" is not valid', plural_form));
|
|
|
|
// Careful here, this is a hidden eval() equivalent..
|
|
// Risk should be reasonable though since we test the plural_form through regex before
|
|
// taken from https://github.com/Orange-OpenSource/gettext.js/blob/master/lib.gettext.js
|
|
// TODO: should test if https://github.com/soney/jsep present and use it if so
|
|
return new Function("n", 'var plural, nplurals; '+ plural_form +' return { nplurals: nplurals, plural: (plural === true ? 1 : (plural ? plural : 0)) };');
|
|
};
|
|
|
|
// Proper translation function that handle plurals and directives
|
|
// Contains juicy parts of https://github.com/Orange-OpenSource/gettext.js/blob/master/lib.gettext.js
|
|
var t = function (messages, n, options /* ,extra */) {
|
|
// Singular is very easy, just pass dictionnary message through strfmt
|
|
if (!options.plural_form)
|
|
return strfmt.apply(this, [removeContext(messages[0])].concat(Array.prototype.slice.call(arguments, 3)));
|
|
|
|
var plural;
|
|
|
|
// if a plural func is given, use that one
|
|
if (options.plural_func) {
|
|
plural = options.plural_func(n);
|
|
|
|
// if plural form never interpreted before, do it now and store it
|
|
} else if (!_plural_funcs[_locale]) {
|
|
_plural_funcs[_locale] = getPluralFunc(_plural_forms[_locale]);
|
|
plural = _plural_funcs[_locale](n);
|
|
|
|
// we have the plural function, compute the plural result
|
|
} else {
|
|
plural = _plural_funcs[_locale](n);
|
|
}
|
|
|
|
// If there is a problem with plurals, fallback to singular one
|
|
if ('undefined' === typeof plural.plural || plural.plural > plural.nplurals || messages.length <= plural.plural)
|
|
plural.plural = 0;
|
|
|
|
return strfmt.apply(this, [removeContext(messages[plural.plural]), n].concat(Array.prototype.slice.call(arguments, 3)));
|
|
};
|
|
|
|
return {
|
|
strfmt: strfmt, // expose strfmt util
|
|
expand_locale: expand_locale, // expose expand_locale util
|
|
|
|
// Declare shortcuts
|
|
__: function () { return this.gettext.apply(this, arguments); },
|
|
_n: function () { return this.ngettext.apply(this, arguments); },
|
|
_p: function () { return this.pgettext.apply(this, arguments); },
|
|
|
|
setMessages: function (domain, locale, messages, plural_forms) {
|
|
if (!domain || !locale || !messages)
|
|
throw new Error('You must provide a domain, a locale and messages');
|
|
|
|
if ('string' !== typeof domain || 'string' !== typeof locale || !_.isObject(messages))
|
|
throw new Error('Invalid arguments');
|
|
|
|
if (plural_forms)
|
|
_plural_forms[locale] = plural_forms;
|
|
|
|
if (!_dictionary[domain])
|
|
_dictionary[domain] = {};
|
|
|
|
_dictionary[domain][locale] = messages;
|
|
|
|
return this;
|
|
},
|
|
loadJSON: function (jsonData, domain) {
|
|
if (!_.isObject(jsonData))
|
|
jsonData = JSON.parse(jsonData);
|
|
|
|
if (!jsonData[''] || !jsonData['']['language'] || !jsonData['']['plural-forms'])
|
|
throw new Error('Wrong JSON, it must have an empty key ("") with "language" and "plural-forms" information');
|
|
|
|
var headers = jsonData[''];
|
|
delete jsonData[''];
|
|
|
|
return this.setMessages(domain || defaults.domain, headers['language'], jsonData, headers['plural-forms']);
|
|
},
|
|
setLocale: function (locale) {
|
|
_locale = locale;
|
|
return this;
|
|
},
|
|
getLocale: function () {
|
|
return _locale;
|
|
},
|
|
// getter/setter for domain
|
|
textdomain: function (domain) {
|
|
if (!domain)
|
|
return _domain;
|
|
_domain = domain;
|
|
return this;
|
|
},
|
|
gettext: function (msgid /* , extra */) {
|
|
return this.dcnpgettext.apply(this, [undefined, undefined, msgid, undefined, undefined].concat(Array.prototype.slice.call(arguments, 1)));
|
|
},
|
|
ngettext: function (msgid, msgid_plural, n /* , extra */) {
|
|
return this.dcnpgettext.apply(this, [undefined, undefined, msgid, msgid_plural, n].concat(Array.prototype.slice.call(arguments, 3)));
|
|
},
|
|
pgettext: function (msgctxt, msgid /* , extra */) {
|
|
return this.dcnpgettext.apply(this, [undefined, msgctxt, msgid, undefined, undefined].concat(Array.prototype.slice.call(arguments, 2)));
|
|
},
|
|
dcnpgettext: function (domain, msgctxt, msgid, msgid_plural, n /* , extra */) {
|
|
domain = domain || _domain;
|
|
|
|
if ('string' !== typeof msgid)
|
|
throw new Error(this.strfmt('Msgid "%1" is not a valid translatable string', msgid));
|
|
|
|
var
|
|
translation,
|
|
options = { plural_form: false },
|
|
key = msgctxt ? msgctxt + _ctxt_delimiter + msgid : msgid,
|
|
exist,
|
|
locale,
|
|
locales = expand_locale(_locale);
|
|
|
|
for (var i in locales) {
|
|
locale = locales[i];
|
|
exist = _dictionary[domain] && _dictionary[domain][locale] && _dictionary[domain][locale][key];
|
|
|
|
// because it's not possible to define both a singular and a plural form of the same msgid,
|
|
// we need to check that the stored form is the same as the expected one.
|
|
// if not, we'll just ignore the translation and consider it as not translated.
|
|
if (msgid_plural) {
|
|
exist = exist && "string" !== typeof _dictionary[domain][locale][key];
|
|
} else {
|
|
exist = exist && "string" === typeof _dictionary[domain][locale][key];
|
|
}
|
|
if (exist) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!exist) {
|
|
translation = msgid;
|
|
options.plural_func = defaults.plural_func;
|
|
} else {
|
|
translation = _dictionary[domain][locale][key];
|
|
}
|
|
|
|
// Singular form
|
|
if (!msgid_plural)
|
|
return t.apply(this, [[translation], n, options].concat(Array.prototype.slice.call(arguments, 5)));
|
|
|
|
// Plural one
|
|
options.plural_form = true;
|
|
return t.apply(this, [exist ? translation : [msgid, msgid_plural], n, options].concat(Array.prototype.slice.call(arguments, 5)));
|
|
}
|
|
};
|
|
};
|
|
|
|
/* harmony default export */ __webpack_exports__["default"] = (i18n);
|
|
|
|
|
|
/***/ })
|
|
/******/ ]);
|
|
//# sourceMappingURL=base.js.map |