19958 lines
613 KiB
JavaScript
19958 lines
613 KiB
JavaScript
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["/js/vendor"],{
|
|
|
|
/***/ "./node_modules/@glidejs/glide/dist/glide.modular.esm.js":
|
|
/*!***************************************************************!*\
|
|
!*** ./node_modules/@glidejs/glide/dist/glide.modular.esm.js ***!
|
|
\***************************************************************/
|
|
/*! exports provided: default, Swipe, Images, Anchors, Controls, Keyboard, Autoplay, Breakpoints */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Swipe", function() { return swipe; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Images", function() { return images; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Anchors", function() { return anchors; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Controls", function() { return controls; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Keyboard", function() { return keyboard; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Autoplay", function() { return autoplay; });
|
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Breakpoints", function() { return breakpoints; });
|
|
function _typeof2(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof2 = function _typeof2(obj) { return typeof obj; }; } else { _typeof2 = function _typeof2(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof2(obj); }
|
|
|
|
/*!
|
|
* Glide.js v3.4.1
|
|
* (c) 2013-2019 Jędrzej Chałubek <jedrzej.chalubek@gmail.com> (http://jedrzejchalubek.com/)
|
|
* Released under the MIT License.
|
|
*/
|
|
var defaults = {
|
|
/**
|
|
* Type of the movement.
|
|
*
|
|
* Available types:
|
|
* `slider` - Rewinds slider to the start/end when it reaches the first or last slide.
|
|
* `carousel` - Changes slides without starting over when it reaches the first or last slide.
|
|
*
|
|
* @type {String}
|
|
*/
|
|
type: 'slider',
|
|
|
|
/**
|
|
* Start at specific slide number defined with zero-based index.
|
|
*
|
|
* @type {Number}
|
|
*/
|
|
startAt: 0,
|
|
|
|
/**
|
|
* A number of slides visible on the single viewport.
|
|
*
|
|
* @type {Number}
|
|
*/
|
|
perView: 1,
|
|
|
|
/**
|
|
* Focus currently active slide at a specified position in the track.
|
|
*
|
|
* Available inputs:
|
|
* `center` - Current slide will be always focused at the center of a track.
|
|
* `0,1,2,3...` - Current slide will be focused on the specified zero-based index.
|
|
*
|
|
* @type {String|Number}
|
|
*/
|
|
focusAt: 0,
|
|
|
|
/**
|
|
* A size of the gap added between slides.
|
|
*
|
|
* @type {Number}
|
|
*/
|
|
gap: 10,
|
|
|
|
/**
|
|
* Change slides after a specified interval. Use `false` for turning off autoplay.
|
|
*
|
|
* @type {Number|Boolean}
|
|
*/
|
|
autoplay: false,
|
|
|
|
/**
|
|
* Stop autoplay on mouseover event.
|
|
*
|
|
* @type {Boolean}
|
|
*/
|
|
hoverpause: true,
|
|
|
|
/**
|
|
* Allow for changing slides with left and right keyboard arrows.
|
|
*
|
|
* @type {Boolean}
|
|
*/
|
|
keyboard: true,
|
|
|
|
/**
|
|
* Stop running `perView` number of slides from the end. Use this
|
|
* option if you don't want to have an empty space after
|
|
* a slider. Works only with `slider` type and a
|
|
* non-centered `focusAt` setting.
|
|
*
|
|
* @type {Boolean}
|
|
*/
|
|
bound: false,
|
|
|
|
/**
|
|
* Minimal swipe distance needed to change the slide. Use `false` for turning off a swiping.
|
|
*
|
|
* @type {Number|Boolean}
|
|
*/
|
|
swipeThreshold: 80,
|
|
|
|
/**
|
|
* Minimal mouse drag distance needed to change the slide. Use `false` for turning off a dragging.
|
|
*
|
|
* @type {Number|Boolean}
|
|
*/
|
|
dragThreshold: 120,
|
|
|
|
/**
|
|
* A maximum number of slides to which movement will be made on swiping or dragging. Use `false` for unlimited.
|
|
*
|
|
* @type {Number|Boolean}
|
|
*/
|
|
perTouch: false,
|
|
|
|
/**
|
|
* Moving distance ratio of the slides on a swiping and dragging.
|
|
*
|
|
* @type {Number}
|
|
*/
|
|
touchRatio: 0.5,
|
|
|
|
/**
|
|
* Angle required to activate slides moving on swiping or dragging.
|
|
*
|
|
* @type {Number}
|
|
*/
|
|
touchAngle: 45,
|
|
|
|
/**
|
|
* Duration of the animation in milliseconds.
|
|
*
|
|
* @type {Number}
|
|
*/
|
|
animationDuration: 400,
|
|
|
|
/**
|
|
* Allows looping the `slider` type. Slider will rewind to the first/last slide when it's at the start/end.
|
|
*
|
|
* @type {Boolean}
|
|
*/
|
|
rewind: true,
|
|
|
|
/**
|
|
* Duration of the rewinding animation of the `slider` type in milliseconds.
|
|
*
|
|
* @type {Number}
|
|
*/
|
|
rewindDuration: 800,
|
|
|
|
/**
|
|
* Easing function for the animation.
|
|
*
|
|
* @type {String}
|
|
*/
|
|
animationTimingFunc: 'cubic-bezier(.165, .840, .440, 1)',
|
|
|
|
/**
|
|
* Throttle costly events at most once per every wait milliseconds.
|
|
*
|
|
* @type {Number}
|
|
*/
|
|
throttle: 10,
|
|
|
|
/**
|
|
* Moving direction mode.
|
|
*
|
|
* Available inputs:
|
|
* - 'ltr' - left to right movement,
|
|
* - 'rtl' - right to left movement.
|
|
*
|
|
* @type {String}
|
|
*/
|
|
direction: 'ltr',
|
|
|
|
/**
|
|
* The distance value of the next and previous viewports which
|
|
* have to peek in the current view. Accepts number and
|
|
* pixels as a string. Left and right peeking can be
|
|
* set up separately with a directions object.
|
|
*
|
|
* For example:
|
|
* `100` - Peek 100px on the both sides.
|
|
* { before: 100, after: 50 }` - Peek 100px on the left side and 50px on the right side.
|
|
*
|
|
* @type {Number|String|Object}
|
|
*/
|
|
peek: 0,
|
|
|
|
/**
|
|
* Collection of options applied at specified media breakpoints.
|
|
* For example: display two slides per view under 800px.
|
|
* `{
|
|
* '800px': {
|
|
* perView: 2
|
|
* }
|
|
* }`
|
|
*/
|
|
breakpoints: {},
|
|
|
|
/**
|
|
* Collection of internally used HTML classes.
|
|
*
|
|
* @todo Refactor `slider` and `carousel` properties to single `type: { slider: '', carousel: '' }` object
|
|
* @type {Object}
|
|
*/
|
|
classes: {
|
|
direction: {
|
|
ltr: 'glide--ltr',
|
|
rtl: 'glide--rtl'
|
|
},
|
|
slider: 'glide--slider',
|
|
carousel: 'glide--carousel',
|
|
swipeable: 'glide--swipeable',
|
|
dragging: 'glide--dragging',
|
|
cloneSlide: 'glide__slide--clone',
|
|
activeNav: 'glide__bullet--active',
|
|
activeSlide: 'glide__slide--active',
|
|
disabledArrow: 'glide__arrow--disabled'
|
|
}
|
|
};
|
|
/**
|
|
* Outputs warning message to the bowser console.
|
|
*
|
|
* @param {String} msg
|
|
* @return {Void}
|
|
*/
|
|
|
|
function warn(msg) {
|
|
console.error("[Glide warn]: " + msg);
|
|
}
|
|
|
|
var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
|
|
return _typeof2(obj);
|
|
} : function (obj) {
|
|
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof2(obj);
|
|
};
|
|
|
|
var classCallCheck = function classCallCheck(instance, Constructor) {
|
|
if (!(instance instanceof Constructor)) {
|
|
throw new TypeError("Cannot call a class as a function");
|
|
}
|
|
};
|
|
|
|
var createClass = function () {
|
|
function defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
if ("value" in descriptor) descriptor.writable = true;
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
|
|
return function (Constructor, protoProps, staticProps) {
|
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
if (staticProps) defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
};
|
|
}();
|
|
|
|
var _extends = Object.assign || function (target) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
var source = arguments[i];
|
|
|
|
for (var key in source) {
|
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
target[key] = source[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
return target;
|
|
};
|
|
|
|
var get = function get(object, property, receiver) {
|
|
if (object === null) object = Function.prototype;
|
|
var desc = Object.getOwnPropertyDescriptor(object, property);
|
|
|
|
if (desc === undefined) {
|
|
var parent = Object.getPrototypeOf(object);
|
|
|
|
if (parent === null) {
|
|
return undefined;
|
|
} else {
|
|
return get(parent, property, receiver);
|
|
}
|
|
} else if ("value" in desc) {
|
|
return desc.value;
|
|
} else {
|
|
var getter = desc.get;
|
|
|
|
if (getter === undefined) {
|
|
return undefined;
|
|
}
|
|
|
|
return getter.call(receiver);
|
|
}
|
|
};
|
|
|
|
var inherits = function inherits(subClass, superClass) {
|
|
if (typeof superClass !== "function" && superClass !== null) {
|
|
throw new TypeError("Super expression must either be null or a function, not " + _typeof2(superClass));
|
|
}
|
|
|
|
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
constructor: {
|
|
value: subClass,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
|
|
};
|
|
|
|
var possibleConstructorReturn = function possibleConstructorReturn(self, call) {
|
|
if (!self) {
|
|
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
}
|
|
|
|
return call && (_typeof2(call) === "object" || typeof call === "function") ? call : self;
|
|
};
|
|
/**
|
|
* Converts value entered as number
|
|
* or string to integer value.
|
|
*
|
|
* @param {String} value
|
|
* @returns {Number}
|
|
*/
|
|
|
|
|
|
function toInt(value) {
|
|
return parseInt(value);
|
|
}
|
|
/**
|
|
* Converts value entered as number
|
|
* or string to flat value.
|
|
*
|
|
* @param {String} value
|
|
* @returns {Number}
|
|
*/
|
|
|
|
|
|
function toFloat(value) {
|
|
return parseFloat(value);
|
|
}
|
|
/**
|
|
* Indicates whether the specified value is a string.
|
|
*
|
|
* @param {*} value
|
|
* @return {Boolean}
|
|
*/
|
|
|
|
|
|
function isString(value) {
|
|
return typeof value === 'string';
|
|
}
|
|
/**
|
|
* Indicates whether the specified value is an object.
|
|
*
|
|
* @param {*} value
|
|
* @return {Boolean}
|
|
*
|
|
* @see https://github.com/jashkenas/underscore
|
|
*/
|
|
|
|
|
|
function isObject(value) {
|
|
var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
|
|
return type === 'function' || type === 'object' && !!value; // eslint-disable-line no-mixed-operators
|
|
}
|
|
/**
|
|
* Indicates whether the specified value is a number.
|
|
*
|
|
* @param {*} value
|
|
* @return {Boolean}
|
|
*/
|
|
|
|
|
|
function isNumber(value) {
|
|
return typeof value === 'number';
|
|
}
|
|
/**
|
|
* Indicates whether the specified value is a function.
|
|
*
|
|
* @param {*} value
|
|
* @return {Boolean}
|
|
*/
|
|
|
|
|
|
function isFunction(value) {
|
|
return typeof value === 'function';
|
|
}
|
|
/**
|
|
* Indicates whether the specified value is undefined.
|
|
*
|
|
* @param {*} value
|
|
* @return {Boolean}
|
|
*/
|
|
|
|
|
|
function isUndefined(value) {
|
|
return typeof value === 'undefined';
|
|
}
|
|
/**
|
|
* Indicates whether the specified value is an array.
|
|
*
|
|
* @param {*} value
|
|
* @return {Boolean}
|
|
*/
|
|
|
|
|
|
function isArray(value) {
|
|
return value.constructor === Array;
|
|
}
|
|
/**
|
|
* Creates and initializes specified collection of extensions.
|
|
* Each extension receives access to instance of glide and rest of components.
|
|
*
|
|
* @param {Object} glide
|
|
* @param {Object} extensions
|
|
*
|
|
* @returns {Object}
|
|
*/
|
|
|
|
|
|
function mount(glide, extensions, events) {
|
|
var components = {};
|
|
|
|
for (var name in extensions) {
|
|
if (isFunction(extensions[name])) {
|
|
components[name] = extensions[name](glide, components, events);
|
|
} else {
|
|
warn('Extension must be a function');
|
|
}
|
|
}
|
|
|
|
for (var _name in components) {
|
|
if (isFunction(components[_name].mount)) {
|
|
components[_name].mount();
|
|
}
|
|
}
|
|
|
|
return components;
|
|
}
|
|
/**
|
|
* Defines getter and setter property on the specified object.
|
|
*
|
|
* @param {Object} obj Object where property has to be defined.
|
|
* @param {String} prop Name of the defined property.
|
|
* @param {Object} definition Get and set definitions for the property.
|
|
* @return {Void}
|
|
*/
|
|
|
|
|
|
function define(obj, prop, definition) {
|
|
Object.defineProperty(obj, prop, definition);
|
|
}
|
|
/**
|
|
* Sorts aphabetically object keys.
|
|
*
|
|
* @param {Object} obj
|
|
* @return {Object}
|
|
*/
|
|
|
|
|
|
function sortKeys(obj) {
|
|
return Object.keys(obj).sort().reduce(function (r, k) {
|
|
r[k] = obj[k];
|
|
return r[k], r;
|
|
}, {});
|
|
}
|
|
/**
|
|
* Merges passed settings object with default options.
|
|
*
|
|
* @param {Object} defaults
|
|
* @param {Object} settings
|
|
* @return {Object}
|
|
*/
|
|
|
|
|
|
function mergeOptions(defaults, settings) {
|
|
var options = _extends({}, defaults, settings); // `Object.assign` do not deeply merge objects, so we
|
|
// have to do it manually for every nested object
|
|
// in options. Although it does not look smart,
|
|
// it's smaller and faster than some fancy
|
|
// merging deep-merge algorithm script.
|
|
|
|
|
|
if (settings.hasOwnProperty('classes')) {
|
|
options.classes = _extends({}, defaults.classes, settings.classes);
|
|
|
|
if (settings.classes.hasOwnProperty('direction')) {
|
|
options.classes.direction = _extends({}, defaults.classes.direction, settings.classes.direction);
|
|
}
|
|
}
|
|
|
|
if (settings.hasOwnProperty('breakpoints')) {
|
|
options.breakpoints = _extends({}, defaults.breakpoints, settings.breakpoints);
|
|
}
|
|
|
|
return options;
|
|
}
|
|
|
|
var EventsBus = function () {
|
|
/**
|
|
* Construct a EventBus instance.
|
|
*
|
|
* @param {Object} events
|
|
*/
|
|
function EventsBus() {
|
|
var events = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
classCallCheck(this, EventsBus);
|
|
this.events = events;
|
|
this.hop = events.hasOwnProperty;
|
|
}
|
|
/**
|
|
* Adds listener to the specifed event.
|
|
*
|
|
* @param {String|Array} event
|
|
* @param {Function} handler
|
|
*/
|
|
|
|
|
|
createClass(EventsBus, [{
|
|
key: 'on',
|
|
value: function on(event, handler) {
|
|
if (isArray(event)) {
|
|
for (var i = 0; i < event.length; i++) {
|
|
this.on(event[i], handler);
|
|
}
|
|
} // Create the event's object if not yet created
|
|
|
|
|
|
if (!this.hop.call(this.events, event)) {
|
|
this.events[event] = [];
|
|
} // Add the handler to queue
|
|
|
|
|
|
var index = this.events[event].push(handler) - 1; // Provide handle back for removal of event
|
|
|
|
return {
|
|
remove: function remove() {
|
|
delete this.events[event][index];
|
|
}
|
|
};
|
|
}
|
|
/**
|
|
* Runs registered handlers for specified event.
|
|
*
|
|
* @param {String|Array} event
|
|
* @param {Object=} context
|
|
*/
|
|
|
|
}, {
|
|
key: 'emit',
|
|
value: function emit(event, context) {
|
|
if (isArray(event)) {
|
|
for (var i = 0; i < event.length; i++) {
|
|
this.emit(event[i], context);
|
|
}
|
|
} // If the event doesn't exist, or there's no handlers in queue, just leave
|
|
|
|
|
|
if (!this.hop.call(this.events, event)) {
|
|
return;
|
|
} // Cycle through events queue, fire!
|
|
|
|
|
|
this.events[event].forEach(function (item) {
|
|
item(context || {});
|
|
});
|
|
}
|
|
}]);
|
|
return EventsBus;
|
|
}();
|
|
|
|
var Glide = function () {
|
|
/**
|
|
* Construct glide.
|
|
*
|
|
* @param {String} selector
|
|
* @param {Object} options
|
|
*/
|
|
function Glide(selector) {
|
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
classCallCheck(this, Glide);
|
|
this._c = {};
|
|
this._t = [];
|
|
this._e = new EventsBus();
|
|
this.disabled = false;
|
|
this.selector = selector;
|
|
this.settings = mergeOptions(defaults, options);
|
|
this.index = this.settings.startAt;
|
|
}
|
|
/**
|
|
* Initializes glide.
|
|
*
|
|
* @param {Object} extensions Collection of extensions to initialize.
|
|
* @return {Glide}
|
|
*/
|
|
|
|
|
|
createClass(Glide, [{
|
|
key: 'mount',
|
|
value: function mount$$1() {
|
|
var extensions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
|
|
this._e.emit('mount.before');
|
|
|
|
if (isObject(extensions)) {
|
|
this._c = mount(this, extensions, this._e);
|
|
} else {
|
|
warn('You need to provide a object on `mount()`');
|
|
}
|
|
|
|
this._e.emit('mount.after');
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* Collects an instance `translate` transformers.
|
|
*
|
|
* @param {Array} transformers Collection of transformers.
|
|
* @return {Void}
|
|
*/
|
|
|
|
}, {
|
|
key: 'mutate',
|
|
value: function mutate() {
|
|
var transformers = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
|
|
if (isArray(transformers)) {
|
|
this._t = transformers;
|
|
} else {
|
|
warn('You need to provide a array on `mutate()`');
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* Updates glide with specified settings.
|
|
*
|
|
* @param {Object} settings
|
|
* @return {Glide}
|
|
*/
|
|
|
|
}, {
|
|
key: 'update',
|
|
value: function update() {
|
|
var settings = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
this.settings = mergeOptions(this.settings, settings);
|
|
|
|
if (settings.hasOwnProperty('startAt')) {
|
|
this.index = settings.startAt;
|
|
}
|
|
|
|
this._e.emit('update');
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* Change slide with specified pattern. A pattern must be in the special format:
|
|
* `>` - Move one forward
|
|
* `<` - Move one backward
|
|
* `={i}` - Go to {i} zero-based slide (eq. '=1', will go to second slide)
|
|
* `>>` - Rewinds to end (last slide)
|
|
* `<<` - Rewinds to start (first slide)
|
|
*
|
|
* @param {String} pattern
|
|
* @return {Glide}
|
|
*/
|
|
|
|
}, {
|
|
key: 'go',
|
|
value: function go(pattern) {
|
|
this._c.Run.make(pattern);
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* Move track by specified distance.
|
|
*
|
|
* @param {String} distance
|
|
* @return {Glide}
|
|
*/
|
|
|
|
}, {
|
|
key: 'move',
|
|
value: function move(distance) {
|
|
this._c.Transition.disable();
|
|
|
|
this._c.Move.make(distance);
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* Destroy instance and revert all changes done by this._c.
|
|
*
|
|
* @return {Glide}
|
|
*/
|
|
|
|
}, {
|
|
key: 'destroy',
|
|
value: function destroy() {
|
|
this._e.emit('destroy');
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* Start instance autoplaying.
|
|
*
|
|
* @param {Boolean|Number} interval Run autoplaying with passed interval regardless of `autoplay` settings
|
|
* @return {Glide}
|
|
*/
|
|
|
|
}, {
|
|
key: 'play',
|
|
value: function play() {
|
|
var interval = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
|
|
if (interval) {
|
|
this.settings.autoplay = interval;
|
|
}
|
|
|
|
this._e.emit('play');
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* Stop instance autoplaying.
|
|
*
|
|
* @return {Glide}
|
|
*/
|
|
|
|
}, {
|
|
key: 'pause',
|
|
value: function pause() {
|
|
this._e.emit('pause');
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* Sets glide into a idle status.
|
|
*
|
|
* @return {Glide}
|
|
*/
|
|
|
|
}, {
|
|
key: 'disable',
|
|
value: function disable() {
|
|
this.disabled = true;
|
|
return this;
|
|
}
|
|
/**
|
|
* Sets glide into a active status.
|
|
*
|
|
* @return {Glide}
|
|
*/
|
|
|
|
}, {
|
|
key: 'enable',
|
|
value: function enable() {
|
|
this.disabled = false;
|
|
return this;
|
|
}
|
|
/**
|
|
* Adds cuutom event listener with handler.
|
|
*
|
|
* @param {String|Array} event
|
|
* @param {Function} handler
|
|
* @return {Glide}
|
|
*/
|
|
|
|
}, {
|
|
key: 'on',
|
|
value: function on(event, handler) {
|
|
this._e.on(event, handler);
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* Checks if glide is a precised type.
|
|
*
|
|
* @param {String} name
|
|
* @return {Boolean}
|
|
*/
|
|
|
|
}, {
|
|
key: 'isType',
|
|
value: function isType(name) {
|
|
return this.settings.type === name;
|
|
}
|
|
/**
|
|
* Gets value of the core options.
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
|
|
}, {
|
|
key: 'settings',
|
|
get: function get$$1() {
|
|
return this._o;
|
|
}
|
|
/**
|
|
* Sets value of the core options.
|
|
*
|
|
* @param {Object} o
|
|
* @return {Void}
|
|
*/
|
|
,
|
|
set: function set$$1(o) {
|
|
if (isObject(o)) {
|
|
this._o = o;
|
|
} else {
|
|
warn('Options must be an `object` instance.');
|
|
}
|
|
}
|
|
/**
|
|
* Gets current index of the slider.
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
|
|
}, {
|
|
key: 'index',
|
|
get: function get$$1() {
|
|
return this._i;
|
|
}
|
|
/**
|
|
* Sets current index a slider.
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
,
|
|
set: function set$$1(i) {
|
|
this._i = toInt(i);
|
|
}
|
|
/**
|
|
* Gets type name of the slider.
|
|
*
|
|
* @return {String}
|
|
*/
|
|
|
|
}, {
|
|
key: 'type',
|
|
get: function get$$1() {
|
|
return this.settings.type;
|
|
}
|
|
/**
|
|
* Gets value of the idle status.
|
|
*
|
|
* @return {Boolean}
|
|
*/
|
|
|
|
}, {
|
|
key: 'disabled',
|
|
get: function get$$1() {
|
|
return this._d;
|
|
}
|
|
/**
|
|
* Sets value of the idle status.
|
|
*
|
|
* @return {Boolean}
|
|
*/
|
|
,
|
|
set: function set$$1(status) {
|
|
this._d = !!status;
|
|
}
|
|
}]);
|
|
return Glide;
|
|
}();
|
|
|
|
function Run(Glide, Components, Events) {
|
|
var Run = {
|
|
/**
|
|
* Initializes autorunning of the glide.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
mount: function mount() {
|
|
this._o = false;
|
|
},
|
|
|
|
/**
|
|
* Makes glides running based on the passed moving schema.
|
|
*
|
|
* @param {String} move
|
|
*/
|
|
make: function make(move) {
|
|
var _this = this;
|
|
|
|
if (!Glide.disabled) {
|
|
Glide.disable();
|
|
this.move = move;
|
|
Events.emit('run.before', this.move);
|
|
this.calculate();
|
|
Events.emit('run', this.move);
|
|
Components.Transition.after(function () {
|
|
if (_this.isStart()) {
|
|
Events.emit('run.start', _this.move);
|
|
}
|
|
|
|
if (_this.isEnd()) {
|
|
Events.emit('run.end', _this.move);
|
|
}
|
|
|
|
if (_this.isOffset('<') || _this.isOffset('>')) {
|
|
_this._o = false;
|
|
Events.emit('run.offset', _this.move);
|
|
}
|
|
|
|
Events.emit('run.after', _this.move);
|
|
Glide.enable();
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Calculates current index based on defined move.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
calculate: function calculate() {
|
|
var move = this.move,
|
|
length = this.length;
|
|
var steps = move.steps,
|
|
direction = move.direction;
|
|
var countableSteps = isNumber(toInt(steps)) && toInt(steps) !== 0;
|
|
|
|
switch (direction) {
|
|
case '>':
|
|
if (steps === '>') {
|
|
Glide.index = length;
|
|
} else if (this.isEnd()) {
|
|
if (!(Glide.isType('slider') && !Glide.settings.rewind)) {
|
|
this._o = true;
|
|
Glide.index = 0;
|
|
}
|
|
} else if (countableSteps) {
|
|
Glide.index += Math.min(length - Glide.index, -toInt(steps));
|
|
} else {
|
|
Glide.index++;
|
|
}
|
|
|
|
break;
|
|
|
|
case '<':
|
|
if (steps === '<') {
|
|
Glide.index = 0;
|
|
} else if (this.isStart()) {
|
|
if (!(Glide.isType('slider') && !Glide.settings.rewind)) {
|
|
this._o = true;
|
|
Glide.index = length;
|
|
}
|
|
} else if (countableSteps) {
|
|
Glide.index -= Math.min(Glide.index, toInt(steps));
|
|
} else {
|
|
Glide.index--;
|
|
}
|
|
|
|
break;
|
|
|
|
case '=':
|
|
Glide.index = steps;
|
|
break;
|
|
|
|
default:
|
|
warn('Invalid direction pattern [' + direction + steps + '] has been used');
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Checks if we are on the first slide.
|
|
*
|
|
* @return {Boolean}
|
|
*/
|
|
isStart: function isStart() {
|
|
return Glide.index === 0;
|
|
},
|
|
|
|
/**
|
|
* Checks if we are on the last slide.
|
|
*
|
|
* @return {Boolean}
|
|
*/
|
|
isEnd: function isEnd() {
|
|
return Glide.index === this.length;
|
|
},
|
|
|
|
/**
|
|
* Checks if we are making a offset run.
|
|
*
|
|
* @param {String} direction
|
|
* @return {Boolean}
|
|
*/
|
|
isOffset: function isOffset(direction) {
|
|
return this._o && this.move.direction === direction;
|
|
}
|
|
};
|
|
define(Run, 'move', {
|
|
/**
|
|
* Gets value of the move schema.
|
|
*
|
|
* @returns {Object}
|
|
*/
|
|
get: function get() {
|
|
return this._m;
|
|
},
|
|
|
|
/**
|
|
* Sets value of the move schema.
|
|
*
|
|
* @returns {Object}
|
|
*/
|
|
set: function set(value) {
|
|
var step = value.substr(1);
|
|
this._m = {
|
|
direction: value.substr(0, 1),
|
|
steps: step ? toInt(step) ? toInt(step) : step : 0
|
|
};
|
|
}
|
|
});
|
|
define(Run, 'length', {
|
|
/**
|
|
* Gets value of the running distance based
|
|
* on zero-indexing number of slides.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
get: function get() {
|
|
var settings = Glide.settings;
|
|
var length = Components.Html.slides.length; // If the `bound` option is acitve, a maximum running distance should be
|
|
// reduced by `perView` and `focusAt` settings. Running distance
|
|
// should end before creating an empty space after instance.
|
|
|
|
if (Glide.isType('slider') && settings.focusAt !== 'center' && settings.bound) {
|
|
return length - 1 - (toInt(settings.perView) - 1) + toInt(settings.focusAt);
|
|
}
|
|
|
|
return length - 1;
|
|
}
|
|
});
|
|
define(Run, 'offset', {
|
|
/**
|
|
* Gets status of the offsetting flag.
|
|
*
|
|
* @return {Boolean}
|
|
*/
|
|
get: function get() {
|
|
return this._o;
|
|
}
|
|
});
|
|
return Run;
|
|
}
|
|
/**
|
|
* Returns a current time.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
|
|
|
|
function now() {
|
|
return new Date().getTime();
|
|
}
|
|
/**
|
|
* Returns a function, that, when invoked, will only be triggered
|
|
* at most once during a given window of time.
|
|
*
|
|
* @param {Function} func
|
|
* @param {Number} wait
|
|
* @param {Object=} options
|
|
* @return {Function}
|
|
*
|
|
* @see https://github.com/jashkenas/underscore
|
|
*/
|
|
|
|
|
|
function throttle(func, wait, options) {
|
|
var timeout = void 0,
|
|
context = void 0,
|
|
args = void 0,
|
|
result = void 0;
|
|
var previous = 0;
|
|
if (!options) options = {};
|
|
|
|
var later = function later() {
|
|
previous = options.leading === false ? 0 : now();
|
|
timeout = null;
|
|
result = func.apply(context, args);
|
|
if (!timeout) context = args = null;
|
|
};
|
|
|
|
var throttled = function throttled() {
|
|
var at = now();
|
|
if (!previous && options.leading === false) previous = at;
|
|
var remaining = wait - (at - previous);
|
|
context = this;
|
|
args = arguments;
|
|
|
|
if (remaining <= 0 || remaining > wait) {
|
|
if (timeout) {
|
|
clearTimeout(timeout);
|
|
timeout = null;
|
|
}
|
|
|
|
previous = at;
|
|
result = func.apply(context, args);
|
|
if (!timeout) context = args = null;
|
|
} else if (!timeout && options.trailing !== false) {
|
|
timeout = setTimeout(later, remaining);
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
throttled.cancel = function () {
|
|
clearTimeout(timeout);
|
|
previous = 0;
|
|
timeout = context = args = null;
|
|
};
|
|
|
|
return throttled;
|
|
}
|
|
|
|
var MARGIN_TYPE = {
|
|
ltr: ['marginLeft', 'marginRight'],
|
|
rtl: ['marginRight', 'marginLeft']
|
|
};
|
|
|
|
function Gaps(Glide, Components, Events) {
|
|
var Gaps = {
|
|
/**
|
|
* Applies gaps between slides. First and last
|
|
* slides do not receive it's edge margins.
|
|
*
|
|
* @param {HTMLCollection} slides
|
|
* @return {Void}
|
|
*/
|
|
apply: function apply(slides) {
|
|
for (var i = 0, len = slides.length; i < len; i++) {
|
|
var style = slides[i].style;
|
|
var direction = Components.Direction.value;
|
|
|
|
if (i !== 0) {
|
|
style[MARGIN_TYPE[direction][0]] = this.value / 2 + 'px';
|
|
} else {
|
|
style[MARGIN_TYPE[direction][0]] = '';
|
|
}
|
|
|
|
if (i !== slides.length - 1) {
|
|
style[MARGIN_TYPE[direction][1]] = this.value / 2 + 'px';
|
|
} else {
|
|
style[MARGIN_TYPE[direction][1]] = '';
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Removes gaps from the slides.
|
|
*
|
|
* @param {HTMLCollection} slides
|
|
* @returns {Void}
|
|
*/
|
|
remove: function remove(slides) {
|
|
for (var i = 0, len = slides.length; i < len; i++) {
|
|
var style = slides[i].style;
|
|
style.marginLeft = '';
|
|
style.marginRight = '';
|
|
}
|
|
}
|
|
};
|
|
define(Gaps, 'value', {
|
|
/**
|
|
* Gets value of the gap.
|
|
*
|
|
* @returns {Number}
|
|
*/
|
|
get: function get() {
|
|
return toInt(Glide.settings.gap);
|
|
}
|
|
});
|
|
define(Gaps, 'grow', {
|
|
/**
|
|
* Gets additional dimentions value caused by gaps.
|
|
* Used to increase width of the slides wrapper.
|
|
*
|
|
* @returns {Number}
|
|
*/
|
|
get: function get() {
|
|
return Gaps.value * (Components.Sizes.length - 1);
|
|
}
|
|
});
|
|
define(Gaps, 'reductor', {
|
|
/**
|
|
* Gets reduction value caused by gaps.
|
|
* Used to subtract width of the slides.
|
|
*
|
|
* @returns {Number}
|
|
*/
|
|
get: function get() {
|
|
var perView = Glide.settings.perView;
|
|
return Gaps.value * (perView - 1) / perView;
|
|
}
|
|
});
|
|
/**
|
|
* Apply calculated gaps:
|
|
* - after building, so slides (including clones) will receive proper margins
|
|
* - on updating via API, to recalculate gaps with new options
|
|
*/
|
|
|
|
Events.on(['build.after', 'update'], throttle(function () {
|
|
Gaps.apply(Components.Html.wrapper.children);
|
|
}, 30));
|
|
/**
|
|
* Remove gaps:
|
|
* - on destroying to bring markup to its inital state
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Gaps.remove(Components.Html.wrapper.children);
|
|
});
|
|
return Gaps;
|
|
}
|
|
/**
|
|
* Finds siblings nodes of the passed node.
|
|
*
|
|
* @param {Element} node
|
|
* @return {Array}
|
|
*/
|
|
|
|
|
|
function siblings(node) {
|
|
if (node && node.parentNode) {
|
|
var n = node.parentNode.firstChild;
|
|
var matched = [];
|
|
|
|
for (; n; n = n.nextSibling) {
|
|
if (n.nodeType === 1 && n !== node) {
|
|
matched.push(n);
|
|
}
|
|
}
|
|
|
|
return matched;
|
|
}
|
|
|
|
return [];
|
|
}
|
|
/**
|
|
* Checks if passed node exist and is a valid element.
|
|
*
|
|
* @param {Element} node
|
|
* @return {Boolean}
|
|
*/
|
|
|
|
|
|
function exist(node) {
|
|
if (node && node instanceof window.HTMLElement) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
var TRACK_SELECTOR = '[data-glide-el="track"]';
|
|
|
|
function Html(Glide, Components) {
|
|
var Html = {
|
|
/**
|
|
* Setup slider HTML nodes.
|
|
*
|
|
* @param {Glide} glide
|
|
*/
|
|
mount: function mount() {
|
|
this.root = Glide.selector;
|
|
this.track = this.root.querySelector(TRACK_SELECTOR);
|
|
this.slides = Array.prototype.slice.call(this.wrapper.children).filter(function (slide) {
|
|
return !slide.classList.contains(Glide.settings.classes.cloneSlide);
|
|
});
|
|
}
|
|
};
|
|
define(Html, 'root', {
|
|
/**
|
|
* Gets node of the glide main element.
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
get: function get() {
|
|
return Html._r;
|
|
},
|
|
|
|
/**
|
|
* Sets node of the glide main element.
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
set: function set(r) {
|
|
if (isString(r)) {
|
|
r = document.querySelector(r);
|
|
}
|
|
|
|
if (exist(r)) {
|
|
Html._r = r;
|
|
} else {
|
|
warn('Root element must be a existing Html node');
|
|
}
|
|
}
|
|
});
|
|
define(Html, 'track', {
|
|
/**
|
|
* Gets node of the glide track with slides.
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
get: function get() {
|
|
return Html._t;
|
|
},
|
|
|
|
/**
|
|
* Sets node of the glide track with slides.
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
set: function set(t) {
|
|
if (exist(t)) {
|
|
Html._t = t;
|
|
} else {
|
|
warn('Could not find track element. Please use ' + TRACK_SELECTOR + ' attribute.');
|
|
}
|
|
}
|
|
});
|
|
define(Html, 'wrapper', {
|
|
/**
|
|
* Gets node of the slides wrapper.
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
get: function get() {
|
|
return Html.track.children[0];
|
|
}
|
|
});
|
|
return Html;
|
|
}
|
|
|
|
function Peek(Glide, Components, Events) {
|
|
var Peek = {
|
|
/**
|
|
* Setups how much to peek based on settings.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
mount: function mount() {
|
|
this.value = Glide.settings.peek;
|
|
}
|
|
};
|
|
define(Peek, 'value', {
|
|
/**
|
|
* Gets value of the peek.
|
|
*
|
|
* @returns {Number|Object}
|
|
*/
|
|
get: function get() {
|
|
return Peek._v;
|
|
},
|
|
|
|
/**
|
|
* Sets value of the peek.
|
|
*
|
|
* @param {Number|Object} value
|
|
* @return {Void}
|
|
*/
|
|
set: function set(value) {
|
|
if (isObject(value)) {
|
|
value.before = toInt(value.before);
|
|
value.after = toInt(value.after);
|
|
} else {
|
|
value = toInt(value);
|
|
}
|
|
|
|
Peek._v = value;
|
|
}
|
|
});
|
|
define(Peek, 'reductor', {
|
|
/**
|
|
* Gets reduction value caused by peek.
|
|
*
|
|
* @returns {Number}
|
|
*/
|
|
get: function get() {
|
|
var value = Peek.value;
|
|
var perView = Glide.settings.perView;
|
|
|
|
if (isObject(value)) {
|
|
return value.before / perView + value.after / perView;
|
|
}
|
|
|
|
return value * 2 / perView;
|
|
}
|
|
});
|
|
/**
|
|
* Recalculate peeking sizes on:
|
|
* - when resizing window to update to proper percents
|
|
*/
|
|
|
|
Events.on(['resize', 'update'], function () {
|
|
Peek.mount();
|
|
});
|
|
return Peek;
|
|
}
|
|
|
|
function Move(Glide, Components, Events) {
|
|
var Move = {
|
|
/**
|
|
* Constructs move component.
|
|
*
|
|
* @returns {Void}
|
|
*/
|
|
mount: function mount() {
|
|
this._o = 0;
|
|
},
|
|
|
|
/**
|
|
* Calculates a movement value based on passed offset and currently active index.
|
|
*
|
|
* @param {Number} offset
|
|
* @return {Void}
|
|
*/
|
|
make: function make() {
|
|
var _this = this;
|
|
|
|
var offset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
this.offset = offset;
|
|
Events.emit('move', {
|
|
movement: this.value
|
|
});
|
|
Components.Transition.after(function () {
|
|
Events.emit('move.after', {
|
|
movement: _this.value
|
|
});
|
|
});
|
|
}
|
|
};
|
|
define(Move, 'offset', {
|
|
/**
|
|
* Gets an offset value used to modify current translate.
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
get: function get() {
|
|
return Move._o;
|
|
},
|
|
|
|
/**
|
|
* Sets an offset value used to modify current translate.
|
|
*
|
|
* @return {Object}
|
|
*/
|
|
set: function set(value) {
|
|
Move._o = !isUndefined(value) ? toInt(value) : 0;
|
|
}
|
|
});
|
|
define(Move, 'translate', {
|
|
/**
|
|
* Gets a raw movement value.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
get: function get() {
|
|
return Components.Sizes.slideWidth * Glide.index;
|
|
}
|
|
});
|
|
define(Move, 'value', {
|
|
/**
|
|
* Gets an actual movement value corrected by offset.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
get: function get() {
|
|
var offset = this.offset;
|
|
var translate = this.translate;
|
|
|
|
if (Components.Direction.is('rtl')) {
|
|
return translate + offset;
|
|
}
|
|
|
|
return translate - offset;
|
|
}
|
|
});
|
|
/**
|
|
* Make movement to proper slide on:
|
|
* - before build, so glide will start at `startAt` index
|
|
* - on each standard run to move to newly calculated index
|
|
*/
|
|
|
|
Events.on(['build.before', 'run'], function () {
|
|
Move.make();
|
|
});
|
|
return Move;
|
|
}
|
|
|
|
function Sizes(Glide, Components, Events) {
|
|
var Sizes = {
|
|
/**
|
|
* Setups dimentions of slides.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
setupSlides: function setupSlides() {
|
|
var width = this.slideWidth + 'px';
|
|
var slides = Components.Html.slides;
|
|
|
|
for (var i = 0; i < slides.length; i++) {
|
|
slides[i].style.width = width;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Setups dimentions of slides wrapper.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
setupWrapper: function setupWrapper(dimention) {
|
|
Components.Html.wrapper.style.width = this.wrapperSize + 'px';
|
|
},
|
|
|
|
/**
|
|
* Removes applied styles from HTML elements.
|
|
*
|
|
* @returns {Void}
|
|
*/
|
|
remove: function remove() {
|
|
var slides = Components.Html.slides;
|
|
|
|
for (var i = 0; i < slides.length; i++) {
|
|
slides[i].style.width = '';
|
|
}
|
|
|
|
Components.Html.wrapper.style.width = '';
|
|
}
|
|
};
|
|
define(Sizes, 'length', {
|
|
/**
|
|
* Gets count number of the slides.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
get: function get() {
|
|
return Components.Html.slides.length;
|
|
}
|
|
});
|
|
define(Sizes, 'width', {
|
|
/**
|
|
* Gets width value of the glide.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
get: function get() {
|
|
return Components.Html.root.offsetWidth;
|
|
}
|
|
});
|
|
define(Sizes, 'wrapperSize', {
|
|
/**
|
|
* Gets size of the slides wrapper.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
get: function get() {
|
|
return Sizes.slideWidth * Sizes.length + Components.Gaps.grow + Components.Clones.grow;
|
|
}
|
|
});
|
|
define(Sizes, 'slideWidth', {
|
|
/**
|
|
* Gets width value of the single slide.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
get: function get() {
|
|
return Sizes.width / Glide.settings.perView - Components.Peek.reductor - Components.Gaps.reductor;
|
|
}
|
|
});
|
|
/**
|
|
* Apply calculated glide's dimensions:
|
|
* - before building, so other dimentions (e.g. translate) will be calculated propertly
|
|
* - when resizing window to recalculate sildes dimensions
|
|
* - on updating via API, to calculate dimensions based on new options
|
|
*/
|
|
|
|
Events.on(['build.before', 'resize', 'update'], function () {
|
|
Sizes.setupSlides();
|
|
Sizes.setupWrapper();
|
|
});
|
|
/**
|
|
* Remove calculated glide's dimensions:
|
|
* - on destoting to bring markup to its inital state
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Sizes.remove();
|
|
});
|
|
return Sizes;
|
|
}
|
|
|
|
function Build(Glide, Components, Events) {
|
|
var Build = {
|
|
/**
|
|
* Init glide building. Adds classes, sets
|
|
* dimensions and setups initial state.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
mount: function mount() {
|
|
Events.emit('build.before');
|
|
this.typeClass();
|
|
this.activeClass();
|
|
Events.emit('build.after');
|
|
},
|
|
|
|
/**
|
|
* Adds `type` class to the glide element.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
typeClass: function typeClass() {
|
|
Components.Html.root.classList.add(Glide.settings.classes[Glide.settings.type]);
|
|
},
|
|
|
|
/**
|
|
* Sets active class to current slide.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
activeClass: function activeClass() {
|
|
var classes = Glide.settings.classes;
|
|
var slide = Components.Html.slides[Glide.index];
|
|
|
|
if (slide) {
|
|
slide.classList.add(classes.activeSlide);
|
|
siblings(slide).forEach(function (sibling) {
|
|
sibling.classList.remove(classes.activeSlide);
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Removes HTML classes applied at building.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
removeClasses: function removeClasses() {
|
|
var classes = Glide.settings.classes;
|
|
Components.Html.root.classList.remove(classes[Glide.settings.type]);
|
|
Components.Html.slides.forEach(function (sibling) {
|
|
sibling.classList.remove(classes.activeSlide);
|
|
});
|
|
}
|
|
};
|
|
/**
|
|
* Clear building classes:
|
|
* - on destroying to bring HTML to its initial state
|
|
* - on updating to remove classes before remounting component
|
|
*/
|
|
|
|
Events.on(['destroy', 'update'], function () {
|
|
Build.removeClasses();
|
|
});
|
|
/**
|
|
* Remount component:
|
|
* - on resizing of the window to calculate new dimentions
|
|
* - on updating settings via API
|
|
*/
|
|
|
|
Events.on(['resize', 'update'], function () {
|
|
Build.mount();
|
|
});
|
|
/**
|
|
* Swap active class of current slide:
|
|
* - after each move to the new index
|
|
*/
|
|
|
|
Events.on('move.after', function () {
|
|
Build.activeClass();
|
|
});
|
|
return Build;
|
|
}
|
|
|
|
function Clones(Glide, Components, Events) {
|
|
var Clones = {
|
|
/**
|
|
* Create pattern map and collect slides to be cloned.
|
|
*/
|
|
mount: function mount() {
|
|
this.items = [];
|
|
|
|
if (Glide.isType('carousel')) {
|
|
this.items = this.collect();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Collect clones with pattern.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
collect: function collect() {
|
|
var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
var slides = Components.Html.slides;
|
|
var _Glide$settings = Glide.settings,
|
|
perView = _Glide$settings.perView,
|
|
classes = _Glide$settings.classes;
|
|
var peekIncrementer = +!!Glide.settings.peek;
|
|
var part = perView + peekIncrementer;
|
|
var start = slides.slice(0, part);
|
|
var end = slides.slice(-part);
|
|
|
|
for (var r = 0; r < Math.max(1, Math.floor(perView / slides.length)); r++) {
|
|
for (var i = 0; i < start.length; i++) {
|
|
var clone = start[i].cloneNode(true);
|
|
clone.classList.add(classes.cloneSlide);
|
|
items.push(clone);
|
|
}
|
|
|
|
for (var _i = 0; _i < end.length; _i++) {
|
|
var _clone = end[_i].cloneNode(true);
|
|
|
|
_clone.classList.add(classes.cloneSlide);
|
|
|
|
items.unshift(_clone);
|
|
}
|
|
}
|
|
|
|
return items;
|
|
},
|
|
|
|
/**
|
|
* Append cloned slides with generated pattern.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
append: function append() {
|
|
var items = this.items;
|
|
var _Components$Html = Components.Html,
|
|
wrapper = _Components$Html.wrapper,
|
|
slides = _Components$Html.slides;
|
|
var half = Math.floor(items.length / 2);
|
|
var prepend = items.slice(0, half).reverse();
|
|
var append = items.slice(half, items.length);
|
|
var width = Components.Sizes.slideWidth + 'px';
|
|
|
|
for (var i = 0; i < append.length; i++) {
|
|
wrapper.appendChild(append[i]);
|
|
}
|
|
|
|
for (var _i2 = 0; _i2 < prepend.length; _i2++) {
|
|
wrapper.insertBefore(prepend[_i2], slides[0]);
|
|
}
|
|
|
|
for (var _i3 = 0; _i3 < items.length; _i3++) {
|
|
items[_i3].style.width = width;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Remove all cloned slides.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
remove: function remove() {
|
|
var items = this.items;
|
|
|
|
for (var i = 0; i < items.length; i++) {
|
|
Components.Html.wrapper.removeChild(items[i]);
|
|
}
|
|
}
|
|
};
|
|
define(Clones, 'grow', {
|
|
/**
|
|
* Gets additional dimentions value caused by clones.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
get: function get() {
|
|
return (Components.Sizes.slideWidth + Components.Gaps.value) * Clones.items.length;
|
|
}
|
|
});
|
|
/**
|
|
* Append additional slide's clones:
|
|
* - while glide's type is `carousel`
|
|
*/
|
|
|
|
Events.on('update', function () {
|
|
Clones.remove();
|
|
Clones.mount();
|
|
Clones.append();
|
|
});
|
|
/**
|
|
* Append additional slide's clones:
|
|
* - while glide's type is `carousel`
|
|
*/
|
|
|
|
Events.on('build.before', function () {
|
|
if (Glide.isType('carousel')) {
|
|
Clones.append();
|
|
}
|
|
});
|
|
/**
|
|
* Remove clones HTMLElements:
|
|
* - on destroying, to bring HTML to its initial state
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Clones.remove();
|
|
});
|
|
return Clones;
|
|
}
|
|
|
|
var EventsBinder = function () {
|
|
/**
|
|
* Construct a EventsBinder instance.
|
|
*/
|
|
function EventsBinder() {
|
|
var listeners = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
classCallCheck(this, EventsBinder);
|
|
this.listeners = listeners;
|
|
}
|
|
/**
|
|
* Adds events listeners to arrows HTML elements.
|
|
*
|
|
* @param {String|Array} events
|
|
* @param {Element|Window|Document} el
|
|
* @param {Function} closure
|
|
* @param {Boolean|Object} capture
|
|
* @return {Void}
|
|
*/
|
|
|
|
|
|
createClass(EventsBinder, [{
|
|
key: 'on',
|
|
value: function on(events, el, closure) {
|
|
var capture = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
|
|
if (isString(events)) {
|
|
events = [events];
|
|
}
|
|
|
|
for (var i = 0; i < events.length; i++) {
|
|
this.listeners[events[i]] = closure;
|
|
el.addEventListener(events[i], this.listeners[events[i]], capture);
|
|
}
|
|
}
|
|
/**
|
|
* Removes event listeners from arrows HTML elements.
|
|
*
|
|
* @param {String|Array} events
|
|
* @param {Element|Window|Document} el
|
|
* @param {Boolean|Object} capture
|
|
* @return {Void}
|
|
*/
|
|
|
|
}, {
|
|
key: 'off',
|
|
value: function off(events, el) {
|
|
var capture = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
|
|
if (isString(events)) {
|
|
events = [events];
|
|
}
|
|
|
|
for (var i = 0; i < events.length; i++) {
|
|
el.removeEventListener(events[i], this.listeners[events[i]], capture);
|
|
}
|
|
}
|
|
/**
|
|
* Destroy collected listeners.
|
|
*
|
|
* @returns {Void}
|
|
*/
|
|
|
|
}, {
|
|
key: 'destroy',
|
|
value: function destroy() {
|
|
delete this.listeners;
|
|
}
|
|
}]);
|
|
return EventsBinder;
|
|
}();
|
|
|
|
function Resize(Glide, Components, Events) {
|
|
/**
|
|
* Instance of the binder for DOM Events.
|
|
*
|
|
* @type {EventsBinder}
|
|
*/
|
|
var Binder = new EventsBinder();
|
|
var Resize = {
|
|
/**
|
|
* Initializes window bindings.
|
|
*/
|
|
mount: function mount() {
|
|
this.bind();
|
|
},
|
|
|
|
/**
|
|
* Binds `rezsize` listener to the window.
|
|
* It's a costly event, so we are debouncing it.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
bind: function bind() {
|
|
Binder.on('resize', window, throttle(function () {
|
|
Events.emit('resize');
|
|
}, Glide.settings.throttle));
|
|
},
|
|
|
|
/**
|
|
* Unbinds listeners from the window.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
unbind: function unbind() {
|
|
Binder.off('resize', window);
|
|
}
|
|
};
|
|
/**
|
|
* Remove bindings from window:
|
|
* - on destroying, to remove added EventListener
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Resize.unbind();
|
|
Binder.destroy();
|
|
});
|
|
return Resize;
|
|
}
|
|
|
|
var VALID_DIRECTIONS = ['ltr', 'rtl'];
|
|
var FLIPED_MOVEMENTS = {
|
|
'>': '<',
|
|
'<': '>',
|
|
'=': '='
|
|
};
|
|
|
|
function Direction(Glide, Components, Events) {
|
|
var Direction = {
|
|
/**
|
|
* Setups gap value based on settings.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
mount: function mount() {
|
|
this.value = Glide.settings.direction;
|
|
},
|
|
|
|
/**
|
|
* Resolves pattern based on direction value
|
|
*
|
|
* @param {String} pattern
|
|
* @returns {String}
|
|
*/
|
|
resolve: function resolve(pattern) {
|
|
var token = pattern.slice(0, 1);
|
|
|
|
if (this.is('rtl')) {
|
|
return pattern.split(token).join(FLIPED_MOVEMENTS[token]);
|
|
}
|
|
|
|
return pattern;
|
|
},
|
|
|
|
/**
|
|
* Checks value of direction mode.
|
|
*
|
|
* @param {String} direction
|
|
* @returns {Boolean}
|
|
*/
|
|
is: function is(direction) {
|
|
return this.value === direction;
|
|
},
|
|
|
|
/**
|
|
* Applies direction class to the root HTML element.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
addClass: function addClass() {
|
|
Components.Html.root.classList.add(Glide.settings.classes.direction[this.value]);
|
|
},
|
|
|
|
/**
|
|
* Removes direction class from the root HTML element.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
removeClass: function removeClass() {
|
|
Components.Html.root.classList.remove(Glide.settings.classes.direction[this.value]);
|
|
}
|
|
};
|
|
define(Direction, 'value', {
|
|
/**
|
|
* Gets value of the direction.
|
|
*
|
|
* @returns {Number}
|
|
*/
|
|
get: function get() {
|
|
return Direction._v;
|
|
},
|
|
|
|
/**
|
|
* Sets value of the direction.
|
|
*
|
|
* @param {String} value
|
|
* @return {Void}
|
|
*/
|
|
set: function set(value) {
|
|
if (VALID_DIRECTIONS.indexOf(value) > -1) {
|
|
Direction._v = value;
|
|
} else {
|
|
warn('Direction value must be `ltr` or `rtl`');
|
|
}
|
|
}
|
|
});
|
|
/**
|
|
* Clear direction class:
|
|
* - on destroy to bring HTML to its initial state
|
|
* - on update to remove class before reappling bellow
|
|
*/
|
|
|
|
Events.on(['destroy', 'update'], function () {
|
|
Direction.removeClass();
|
|
});
|
|
/**
|
|
* Remount component:
|
|
* - on update to reflect changes in direction value
|
|
*/
|
|
|
|
Events.on('update', function () {
|
|
Direction.mount();
|
|
});
|
|
/**
|
|
* Apply direction class:
|
|
* - before building to apply class for the first time
|
|
* - on updating to reapply direction class that may changed
|
|
*/
|
|
|
|
Events.on(['build.before', 'update'], function () {
|
|
Direction.addClass();
|
|
});
|
|
return Direction;
|
|
}
|
|
/**
|
|
* Reflects value of glide movement.
|
|
*
|
|
* @param {Object} Glide
|
|
* @param {Object} Components
|
|
* @return {Object}
|
|
*/
|
|
|
|
|
|
function Rtl(Glide, Components) {
|
|
return {
|
|
/**
|
|
* Negates the passed translate if glide is in RTL option.
|
|
*
|
|
* @param {Number} translate
|
|
* @return {Number}
|
|
*/
|
|
modify: function modify(translate) {
|
|
if (Components.Direction.is('rtl')) {
|
|
return -translate;
|
|
}
|
|
|
|
return translate;
|
|
}
|
|
};
|
|
}
|
|
/**
|
|
* Updates glide movement with a `gap` settings.
|
|
*
|
|
* @param {Object} Glide
|
|
* @param {Object} Components
|
|
* @return {Object}
|
|
*/
|
|
|
|
|
|
function Gap(Glide, Components) {
|
|
return {
|
|
/**
|
|
* Modifies passed translate value with number in the `gap` settings.
|
|
*
|
|
* @param {Number} translate
|
|
* @return {Number}
|
|
*/
|
|
modify: function modify(translate) {
|
|
return translate + Components.Gaps.value * Glide.index;
|
|
}
|
|
};
|
|
}
|
|
/**
|
|
* Updates glide movement with width of additional clones width.
|
|
*
|
|
* @param {Object} Glide
|
|
* @param {Object} Components
|
|
* @return {Object}
|
|
*/
|
|
|
|
|
|
function Grow(Glide, Components) {
|
|
return {
|
|
/**
|
|
* Adds to the passed translate width of the half of clones.
|
|
*
|
|
* @param {Number} translate
|
|
* @return {Number}
|
|
*/
|
|
modify: function modify(translate) {
|
|
return translate + Components.Clones.grow / 2;
|
|
}
|
|
};
|
|
}
|
|
/**
|
|
* Updates glide movement with a `peek` settings.
|
|
*
|
|
* @param {Object} Glide
|
|
* @param {Object} Components
|
|
* @return {Object}
|
|
*/
|
|
|
|
|
|
function Peeking(Glide, Components) {
|
|
return {
|
|
/**
|
|
* Modifies passed translate value with a `peek` setting.
|
|
*
|
|
* @param {Number} translate
|
|
* @return {Number}
|
|
*/
|
|
modify: function modify(translate) {
|
|
if (Glide.settings.focusAt >= 0) {
|
|
var peek = Components.Peek.value;
|
|
|
|
if (isObject(peek)) {
|
|
return translate - peek.before;
|
|
}
|
|
|
|
return translate - peek;
|
|
}
|
|
|
|
return translate;
|
|
}
|
|
};
|
|
}
|
|
/**
|
|
* Updates glide movement with a `focusAt` settings.
|
|
*
|
|
* @param {Object} Glide
|
|
* @param {Object} Components
|
|
* @return {Object}
|
|
*/
|
|
|
|
|
|
function Focusing(Glide, Components) {
|
|
return {
|
|
/**
|
|
* Modifies passed translate value with index in the `focusAt` setting.
|
|
*
|
|
* @param {Number} translate
|
|
* @return {Number}
|
|
*/
|
|
modify: function modify(translate) {
|
|
var gap = Components.Gaps.value;
|
|
var width = Components.Sizes.width;
|
|
var focusAt = Glide.settings.focusAt;
|
|
var slideWidth = Components.Sizes.slideWidth;
|
|
|
|
if (focusAt === 'center') {
|
|
return translate - (width / 2 - slideWidth / 2);
|
|
}
|
|
|
|
return translate - slideWidth * focusAt - gap * focusAt;
|
|
}
|
|
};
|
|
}
|
|
/**
|
|
* Applies diffrent transformers on translate value.
|
|
*
|
|
* @param {Object} Glide
|
|
* @param {Object} Components
|
|
* @return {Object}
|
|
*/
|
|
|
|
|
|
function mutator(Glide, Components, Events) {
|
|
/**
|
|
* Merge instance transformers with collection of default transformers.
|
|
* It's important that the Rtl component be last on the list,
|
|
* so it reflects all previous transformations.
|
|
*
|
|
* @type {Array}
|
|
*/
|
|
var TRANSFORMERS = [Gap, Grow, Peeking, Focusing].concat(Glide._t, [Rtl]);
|
|
return {
|
|
/**
|
|
* Piplines translate value with registered transformers.
|
|
*
|
|
* @param {Number} translate
|
|
* @return {Number}
|
|
*/
|
|
mutate: function mutate(translate) {
|
|
for (var i = 0; i < TRANSFORMERS.length; i++) {
|
|
var transformer = TRANSFORMERS[i];
|
|
|
|
if (isFunction(transformer) && isFunction(transformer().modify)) {
|
|
translate = transformer(Glide, Components, Events).modify(translate);
|
|
} else {
|
|
warn('Transformer should be a function that returns an object with `modify()` method');
|
|
}
|
|
}
|
|
|
|
return translate;
|
|
}
|
|
};
|
|
}
|
|
|
|
function Translate(Glide, Components, Events) {
|
|
var Translate = {
|
|
/**
|
|
* Sets value of translate on HTML element.
|
|
*
|
|
* @param {Number} value
|
|
* @return {Void}
|
|
*/
|
|
set: function set(value) {
|
|
var transform = mutator(Glide, Components).mutate(value);
|
|
Components.Html.wrapper.style.transform = 'translate3d(' + -1 * transform + 'px, 0px, 0px)';
|
|
},
|
|
|
|
/**
|
|
* Removes value of translate from HTML element.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
remove: function remove() {
|
|
Components.Html.wrapper.style.transform = '';
|
|
}
|
|
};
|
|
/**
|
|
* Set new translate value:
|
|
* - on move to reflect index change
|
|
* - on updating via API to reflect possible changes in options
|
|
*/
|
|
|
|
Events.on('move', function (context) {
|
|
var gap = Components.Gaps.value;
|
|
var length = Components.Sizes.length;
|
|
var width = Components.Sizes.slideWidth;
|
|
|
|
if (Glide.isType('carousel') && Components.Run.isOffset('<')) {
|
|
Components.Transition.after(function () {
|
|
Events.emit('translate.jump');
|
|
Translate.set(width * (length - 1));
|
|
});
|
|
return Translate.set(-width - gap * length);
|
|
}
|
|
|
|
if (Glide.isType('carousel') && Components.Run.isOffset('>')) {
|
|
Components.Transition.after(function () {
|
|
Events.emit('translate.jump');
|
|
Translate.set(0);
|
|
});
|
|
return Translate.set(width * length + gap * length);
|
|
}
|
|
|
|
return Translate.set(context.movement);
|
|
});
|
|
/**
|
|
* Remove translate:
|
|
* - on destroying to bring markup to its inital state
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Translate.remove();
|
|
});
|
|
return Translate;
|
|
}
|
|
|
|
function Transition(Glide, Components, Events) {
|
|
/**
|
|
* Holds inactivity status of transition.
|
|
* When true transition is not applied.
|
|
*
|
|
* @type {Boolean}
|
|
*/
|
|
var disabled = false;
|
|
var Transition = {
|
|
/**
|
|
* Composes string of the CSS transition.
|
|
*
|
|
* @param {String} property
|
|
* @return {String}
|
|
*/
|
|
compose: function compose(property) {
|
|
var settings = Glide.settings;
|
|
|
|
if (!disabled) {
|
|
return property + ' ' + this.duration + 'ms ' + settings.animationTimingFunc;
|
|
}
|
|
|
|
return property + ' 0ms ' + settings.animationTimingFunc;
|
|
},
|
|
|
|
/**
|
|
* Sets value of transition on HTML element.
|
|
*
|
|
* @param {String=} property
|
|
* @return {Void}
|
|
*/
|
|
set: function set() {
|
|
var property = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'transform';
|
|
Components.Html.wrapper.style.transition = this.compose(property);
|
|
},
|
|
|
|
/**
|
|
* Removes value of transition from HTML element.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
remove: function remove() {
|
|
Components.Html.wrapper.style.transition = '';
|
|
},
|
|
|
|
/**
|
|
* Runs callback after animation.
|
|
*
|
|
* @param {Function} callback
|
|
* @return {Void}
|
|
*/
|
|
after: function after(callback) {
|
|
setTimeout(function () {
|
|
callback();
|
|
}, this.duration);
|
|
},
|
|
|
|
/**
|
|
* Enable transition.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
enable: function enable() {
|
|
disabled = false;
|
|
this.set();
|
|
},
|
|
|
|
/**
|
|
* Disable transition.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
disable: function disable() {
|
|
disabled = true;
|
|
this.set();
|
|
}
|
|
};
|
|
define(Transition, 'duration', {
|
|
/**
|
|
* Gets duration of the transition based
|
|
* on currently running animation type.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
get: function get() {
|
|
var settings = Glide.settings;
|
|
|
|
if (Glide.isType('slider') && Components.Run.offset) {
|
|
return settings.rewindDuration;
|
|
}
|
|
|
|
return settings.animationDuration;
|
|
}
|
|
});
|
|
/**
|
|
* Set transition `style` value:
|
|
* - on each moving, because it may be cleared by offset move
|
|
*/
|
|
|
|
Events.on('move', function () {
|
|
Transition.set();
|
|
});
|
|
/**
|
|
* Disable transition:
|
|
* - before initial build to avoid transitioning from `0` to `startAt` index
|
|
* - while resizing window and recalculating dimentions
|
|
* - on jumping from offset transition at start and end edges in `carousel` type
|
|
*/
|
|
|
|
Events.on(['build.before', 'resize', 'translate.jump'], function () {
|
|
Transition.disable();
|
|
});
|
|
/**
|
|
* Enable transition:
|
|
* - on each running, because it may be disabled by offset move
|
|
*/
|
|
|
|
Events.on('run', function () {
|
|
Transition.enable();
|
|
});
|
|
/**
|
|
* Remove transition:
|
|
* - on destroying to bring markup to its inital state
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Transition.remove();
|
|
});
|
|
return Transition;
|
|
}
|
|
/**
|
|
* Test via a getter in the options object to see
|
|
* if the passive property is accessed.
|
|
*
|
|
* @see https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection
|
|
*/
|
|
|
|
|
|
var supportsPassive = false;
|
|
|
|
try {
|
|
var opts = Object.defineProperty({}, 'passive', {
|
|
get: function get() {
|
|
supportsPassive = true;
|
|
}
|
|
});
|
|
window.addEventListener('testPassive', null, opts);
|
|
window.removeEventListener('testPassive', null, opts);
|
|
} catch (e) {}
|
|
|
|
var supportsPassive$1 = supportsPassive;
|
|
var START_EVENTS = ['touchstart', 'mousedown'];
|
|
var MOVE_EVENTS = ['touchmove', 'mousemove'];
|
|
var END_EVENTS = ['touchend', 'touchcancel', 'mouseup', 'mouseleave'];
|
|
var MOUSE_EVENTS = ['mousedown', 'mousemove', 'mouseup', 'mouseleave'];
|
|
|
|
function swipe(Glide, Components, Events) {
|
|
/**
|
|
* Instance of the binder for DOM Events.
|
|
*
|
|
* @type {EventsBinder}
|
|
*/
|
|
var Binder = new EventsBinder();
|
|
var swipeSin = 0;
|
|
var swipeStartX = 0;
|
|
var swipeStartY = 0;
|
|
var disabled = false;
|
|
var capture = supportsPassive$1 ? {
|
|
passive: true
|
|
} : false;
|
|
var Swipe = {
|
|
/**
|
|
* Initializes swipe bindings.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
mount: function mount() {
|
|
this.bindSwipeStart();
|
|
},
|
|
|
|
/**
|
|
* Handler for `swipestart` event. Calculates entry points of the user's tap.
|
|
*
|
|
* @param {Object} event
|
|
* @return {Void}
|
|
*/
|
|
start: function start(event) {
|
|
if (!disabled && !Glide.disabled) {
|
|
this.disable();
|
|
var swipe = this.touches(event);
|
|
swipeSin = null;
|
|
swipeStartX = toInt(swipe.pageX);
|
|
swipeStartY = toInt(swipe.pageY);
|
|
this.bindSwipeMove();
|
|
this.bindSwipeEnd();
|
|
Events.emit('swipe.start');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handler for `swipemove` event. Calculates user's tap angle and distance.
|
|
*
|
|
* @param {Object} event
|
|
*/
|
|
move: function move(event) {
|
|
if (!Glide.disabled) {
|
|
var _Glide$settings = Glide.settings,
|
|
touchAngle = _Glide$settings.touchAngle,
|
|
touchRatio = _Glide$settings.touchRatio,
|
|
classes = _Glide$settings.classes;
|
|
var swipe = this.touches(event);
|
|
var subExSx = toInt(swipe.pageX) - swipeStartX;
|
|
var subEySy = toInt(swipe.pageY) - swipeStartY;
|
|
var powEX = Math.abs(subExSx << 2);
|
|
var powEY = Math.abs(subEySy << 2);
|
|
var swipeHypotenuse = Math.sqrt(powEX + powEY);
|
|
var swipeCathetus = Math.sqrt(powEY);
|
|
swipeSin = Math.asin(swipeCathetus / swipeHypotenuse);
|
|
|
|
if (swipeSin * 180 / Math.PI < touchAngle) {
|
|
event.stopPropagation();
|
|
Components.Move.make(subExSx * toFloat(touchRatio));
|
|
Components.Html.root.classList.add(classes.dragging);
|
|
Events.emit('swipe.move');
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handler for `swipeend` event. Finitializes user's tap and decides about glide move.
|
|
*
|
|
* @param {Object} event
|
|
* @return {Void}
|
|
*/
|
|
end: function end(event) {
|
|
if (!Glide.disabled) {
|
|
var settings = Glide.settings;
|
|
var swipe = this.touches(event);
|
|
var threshold = this.threshold(event);
|
|
var swipeDistance = swipe.pageX - swipeStartX;
|
|
var swipeDeg = swipeSin * 180 / Math.PI;
|
|
var steps = Math.round(swipeDistance / Components.Sizes.slideWidth);
|
|
this.enable();
|
|
|
|
if (swipeDistance > threshold && swipeDeg < settings.touchAngle) {
|
|
// While swipe is positive and greater than threshold move backward.
|
|
if (settings.perTouch) {
|
|
steps = Math.min(steps, toInt(settings.perTouch));
|
|
}
|
|
|
|
if (Components.Direction.is('rtl')) {
|
|
steps = -steps;
|
|
}
|
|
|
|
Components.Run.make(Components.Direction.resolve('<' + steps));
|
|
} else if (swipeDistance < -threshold && swipeDeg < settings.touchAngle) {
|
|
// While swipe is negative and lower than negative threshold move forward.
|
|
if (settings.perTouch) {
|
|
steps = Math.max(steps, -toInt(settings.perTouch));
|
|
}
|
|
|
|
if (Components.Direction.is('rtl')) {
|
|
steps = -steps;
|
|
}
|
|
|
|
Components.Run.make(Components.Direction.resolve('>' + steps));
|
|
} else {
|
|
// While swipe don't reach distance apply previous transform.
|
|
Components.Move.make();
|
|
}
|
|
|
|
Components.Html.root.classList.remove(settings.classes.dragging);
|
|
this.unbindSwipeMove();
|
|
this.unbindSwipeEnd();
|
|
Events.emit('swipe.end');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Binds swipe's starting event.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
bindSwipeStart: function bindSwipeStart() {
|
|
var _this = this;
|
|
|
|
var settings = Glide.settings;
|
|
|
|
if (settings.swipeThreshold) {
|
|
Binder.on(START_EVENTS[0], Components.Html.wrapper, function (event) {
|
|
_this.start(event);
|
|
}, capture);
|
|
}
|
|
|
|
if (settings.dragThreshold) {
|
|
Binder.on(START_EVENTS[1], Components.Html.wrapper, function (event) {
|
|
_this.start(event);
|
|
}, capture);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Unbinds swipe's starting event.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
unbindSwipeStart: function unbindSwipeStart() {
|
|
Binder.off(START_EVENTS[0], Components.Html.wrapper, capture);
|
|
Binder.off(START_EVENTS[1], Components.Html.wrapper, capture);
|
|
},
|
|
|
|
/**
|
|
* Binds swipe's moving event.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
bindSwipeMove: function bindSwipeMove() {
|
|
var _this2 = this;
|
|
|
|
Binder.on(MOVE_EVENTS, Components.Html.wrapper, throttle(function (event) {
|
|
_this2.move(event);
|
|
}, Glide.settings.throttle), capture);
|
|
},
|
|
|
|
/**
|
|
* Unbinds swipe's moving event.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
unbindSwipeMove: function unbindSwipeMove() {
|
|
Binder.off(MOVE_EVENTS, Components.Html.wrapper, capture);
|
|
},
|
|
|
|
/**
|
|
* Binds swipe's ending event.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
bindSwipeEnd: function bindSwipeEnd() {
|
|
var _this3 = this;
|
|
|
|
Binder.on(END_EVENTS, Components.Html.wrapper, function (event) {
|
|
_this3.end(event);
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Unbinds swipe's ending event.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
unbindSwipeEnd: function unbindSwipeEnd() {
|
|
Binder.off(END_EVENTS, Components.Html.wrapper);
|
|
},
|
|
|
|
/**
|
|
* Normalizes event touches points accorting to different types.
|
|
*
|
|
* @param {Object} event
|
|
*/
|
|
touches: function touches(event) {
|
|
if (MOUSE_EVENTS.indexOf(event.type) > -1) {
|
|
return event;
|
|
}
|
|
|
|
return event.touches[0] || event.changedTouches[0];
|
|
},
|
|
|
|
/**
|
|
* Gets value of minimum swipe distance settings based on event type.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
threshold: function threshold(event) {
|
|
var settings = Glide.settings;
|
|
|
|
if (MOUSE_EVENTS.indexOf(event.type) > -1) {
|
|
return settings.dragThreshold;
|
|
}
|
|
|
|
return settings.swipeThreshold;
|
|
},
|
|
|
|
/**
|
|
* Enables swipe event.
|
|
*
|
|
* @return {self}
|
|
*/
|
|
enable: function enable() {
|
|
disabled = false;
|
|
Components.Transition.enable();
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Disables swipe event.
|
|
*
|
|
* @return {self}
|
|
*/
|
|
disable: function disable() {
|
|
disabled = true;
|
|
Components.Transition.disable();
|
|
return this;
|
|
}
|
|
};
|
|
/**
|
|
* Add component class:
|
|
* - after initial building
|
|
*/
|
|
|
|
Events.on('build.after', function () {
|
|
Components.Html.root.classList.add(Glide.settings.classes.swipeable);
|
|
});
|
|
/**
|
|
* Remove swiping bindings:
|
|
* - on destroying, to remove added EventListeners
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Swipe.unbindSwipeStart();
|
|
Swipe.unbindSwipeMove();
|
|
Swipe.unbindSwipeEnd();
|
|
Binder.destroy();
|
|
});
|
|
return Swipe;
|
|
}
|
|
|
|
function images(Glide, Components, Events) {
|
|
/**
|
|
* Instance of the binder for DOM Events.
|
|
*
|
|
* @type {EventsBinder}
|
|
*/
|
|
var Binder = new EventsBinder();
|
|
var Images = {
|
|
/**
|
|
* Binds listener to glide wrapper.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
mount: function mount() {
|
|
this.bind();
|
|
},
|
|
|
|
/**
|
|
* Binds `dragstart` event on wrapper to prevent dragging images.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
bind: function bind() {
|
|
Binder.on('dragstart', Components.Html.wrapper, this.dragstart);
|
|
},
|
|
|
|
/**
|
|
* Unbinds `dragstart` event on wrapper.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
unbind: function unbind() {
|
|
Binder.off('dragstart', Components.Html.wrapper);
|
|
},
|
|
|
|
/**
|
|
* Event handler. Prevents dragging.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
dragstart: function dragstart(event) {
|
|
event.preventDefault();
|
|
}
|
|
};
|
|
/**
|
|
* Remove bindings from images:
|
|
* - on destroying, to remove added EventListeners
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Images.unbind();
|
|
Binder.destroy();
|
|
});
|
|
return Images;
|
|
}
|
|
|
|
function anchors(Glide, Components, Events) {
|
|
/**
|
|
* Instance of the binder for DOM Events.
|
|
*
|
|
* @type {EventsBinder}
|
|
*/
|
|
var Binder = new EventsBinder();
|
|
/**
|
|
* Holds detaching status of anchors.
|
|
* Prevents detaching of already detached anchors.
|
|
*
|
|
* @private
|
|
* @type {Boolean}
|
|
*/
|
|
|
|
var detached = false;
|
|
/**
|
|
* Holds preventing status of anchors.
|
|
* If `true` redirection after click will be disabled.
|
|
*
|
|
* @private
|
|
* @type {Boolean}
|
|
*/
|
|
|
|
var prevented = false;
|
|
var Anchors = {
|
|
/**
|
|
* Setups a initial state of anchors component.
|
|
*
|
|
* @returns {Void}
|
|
*/
|
|
mount: function mount() {
|
|
/**
|
|
* Holds collection of anchors elements.
|
|
*
|
|
* @private
|
|
* @type {HTMLCollection}
|
|
*/
|
|
this._a = Components.Html.wrapper.querySelectorAll('a');
|
|
this.bind();
|
|
},
|
|
|
|
/**
|
|
* Binds events to anchors inside a track.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
bind: function bind() {
|
|
Binder.on('click', Components.Html.wrapper, this.click);
|
|
},
|
|
|
|
/**
|
|
* Unbinds events attached to anchors inside a track.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
unbind: function unbind() {
|
|
Binder.off('click', Components.Html.wrapper);
|
|
},
|
|
|
|
/**
|
|
* Handler for click event. Prevents clicks when glide is in `prevent` status.
|
|
*
|
|
* @param {Object} event
|
|
* @return {Void}
|
|
*/
|
|
click: function click(event) {
|
|
if (prevented) {
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Detaches anchors click event inside glide.
|
|
*
|
|
* @return {self}
|
|
*/
|
|
detach: function detach() {
|
|
prevented = true;
|
|
|
|
if (!detached) {
|
|
for (var i = 0; i < this.items.length; i++) {
|
|
this.items[i].draggable = false;
|
|
this.items[i].setAttribute('data-href', this.items[i].getAttribute('href'));
|
|
this.items[i].removeAttribute('href');
|
|
}
|
|
|
|
detached = true;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Attaches anchors click events inside glide.
|
|
*
|
|
* @return {self}
|
|
*/
|
|
attach: function attach() {
|
|
prevented = false;
|
|
|
|
if (detached) {
|
|
for (var i = 0; i < this.items.length; i++) {
|
|
this.items[i].draggable = true;
|
|
this.items[i].setAttribute('href', this.items[i].getAttribute('data-href'));
|
|
}
|
|
|
|
detached = false;
|
|
}
|
|
|
|
return this;
|
|
}
|
|
};
|
|
define(Anchors, 'items', {
|
|
/**
|
|
* Gets collection of the arrows HTML elements.
|
|
*
|
|
* @return {HTMLElement[]}
|
|
*/
|
|
get: function get() {
|
|
return Anchors._a;
|
|
}
|
|
});
|
|
/**
|
|
* Detach anchors inside slides:
|
|
* - on swiping, so they won't redirect to its `href` attributes
|
|
*/
|
|
|
|
Events.on('swipe.move', function () {
|
|
Anchors.detach();
|
|
});
|
|
/**
|
|
* Attach anchors inside slides:
|
|
* - after swiping and transitions ends, so they can redirect after click again
|
|
*/
|
|
|
|
Events.on('swipe.end', function () {
|
|
Components.Transition.after(function () {
|
|
Anchors.attach();
|
|
});
|
|
});
|
|
/**
|
|
* Unbind anchors inside slides:
|
|
* - on destroying, to bring anchors to its initial state
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Anchors.attach();
|
|
Anchors.unbind();
|
|
Binder.destroy();
|
|
});
|
|
return Anchors;
|
|
}
|
|
|
|
var NAV_SELECTOR = '[data-glide-el="controls[nav]"]';
|
|
var CONTROLS_SELECTOR = '[data-glide-el^="controls"]';
|
|
|
|
function controls(Glide, Components, Events) {
|
|
/**
|
|
* Instance of the binder for DOM Events.
|
|
*
|
|
* @type {EventsBinder}
|
|
*/
|
|
var Binder = new EventsBinder();
|
|
var capture = supportsPassive$1 ? {
|
|
passive: true
|
|
} : false;
|
|
var Controls = {
|
|
/**
|
|
* Inits arrows. Binds events listeners
|
|
* to the arrows HTML elements.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
mount: function mount() {
|
|
/**
|
|
* Collection of navigation HTML elements.
|
|
*
|
|
* @private
|
|
* @type {HTMLCollection}
|
|
*/
|
|
this._n = Components.Html.root.querySelectorAll(NAV_SELECTOR);
|
|
/**
|
|
* Collection of controls HTML elements.
|
|
*
|
|
* @private
|
|
* @type {HTMLCollection}
|
|
*/
|
|
|
|
this._c = Components.Html.root.querySelectorAll(CONTROLS_SELECTOR);
|
|
this.addBindings();
|
|
},
|
|
|
|
/**
|
|
* Sets active class to current slide.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
setActive: function setActive() {
|
|
for (var i = 0; i < this._n.length; i++) {
|
|
this.addClass(this._n[i].children);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Removes active class to current slide.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
removeActive: function removeActive() {
|
|
for (var i = 0; i < this._n.length; i++) {
|
|
this.removeClass(this._n[i].children);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Toggles active class on items inside navigation.
|
|
*
|
|
* @param {HTMLElement} controls
|
|
* @return {Void}
|
|
*/
|
|
addClass: function addClass(controls) {
|
|
var settings = Glide.settings;
|
|
var item = controls[Glide.index];
|
|
|
|
if (item) {
|
|
item.classList.add(settings.classes.activeNav);
|
|
siblings(item).forEach(function (sibling) {
|
|
sibling.classList.remove(settings.classes.activeNav);
|
|
});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Removes active class from active control.
|
|
*
|
|
* @param {HTMLElement} controls
|
|
* @return {Void}
|
|
*/
|
|
removeClass: function removeClass(controls) {
|
|
var item = controls[Glide.index];
|
|
|
|
if (item) {
|
|
item.classList.remove(Glide.settings.classes.activeNav);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Adds handles to the each group of controls.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
addBindings: function addBindings() {
|
|
for (var i = 0; i < this._c.length; i++) {
|
|
this.bind(this._c[i].children);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Removes handles from the each group of controls.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
removeBindings: function removeBindings() {
|
|
for (var i = 0; i < this._c.length; i++) {
|
|
this.unbind(this._c[i].children);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Binds events to arrows HTML elements.
|
|
*
|
|
* @param {HTMLCollection} elements
|
|
* @return {Void}
|
|
*/
|
|
bind: function bind(elements) {
|
|
for (var i = 0; i < elements.length; i++) {
|
|
Binder.on('click', elements[i], this.click);
|
|
Binder.on('touchstart', elements[i], this.click, capture);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Unbinds events binded to the arrows HTML elements.
|
|
*
|
|
* @param {HTMLCollection} elements
|
|
* @return {Void}
|
|
*/
|
|
unbind: function unbind(elements) {
|
|
for (var i = 0; i < elements.length; i++) {
|
|
Binder.off(['click', 'touchstart'], elements[i]);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handles `click` event on the arrows HTML elements.
|
|
* Moves slider in driection precised in
|
|
* `data-glide-dir` attribute.
|
|
*
|
|
* @param {Object} event
|
|
* @return {Void}
|
|
*/
|
|
click: function click(event) {
|
|
event.preventDefault();
|
|
Components.Run.make(Components.Direction.resolve(event.currentTarget.getAttribute('data-glide-dir')));
|
|
}
|
|
};
|
|
define(Controls, 'items', {
|
|
/**
|
|
* Gets collection of the controls HTML elements.
|
|
*
|
|
* @return {HTMLElement[]}
|
|
*/
|
|
get: function get() {
|
|
return Controls._c;
|
|
}
|
|
});
|
|
/**
|
|
* Swap active class of current navigation item:
|
|
* - after mounting to set it to initial index
|
|
* - after each move to the new index
|
|
*/
|
|
|
|
Events.on(['mount.after', 'move.after'], function () {
|
|
Controls.setActive();
|
|
});
|
|
/**
|
|
* Remove bindings and HTML Classes:
|
|
* - on destroying, to bring markup to its initial state
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Controls.removeBindings();
|
|
Controls.removeActive();
|
|
Binder.destroy();
|
|
});
|
|
return Controls;
|
|
}
|
|
|
|
function keyboard(Glide, Components, Events) {
|
|
/**
|
|
* Instance of the binder for DOM Events.
|
|
*
|
|
* @type {EventsBinder}
|
|
*/
|
|
var Binder = new EventsBinder();
|
|
var Keyboard = {
|
|
/**
|
|
* Binds keyboard events on component mount.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
mount: function mount() {
|
|
if (Glide.settings.keyboard) {
|
|
this.bind();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Adds keyboard press events.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
bind: function bind() {
|
|
Binder.on('keyup', document, this.press);
|
|
},
|
|
|
|
/**
|
|
* Removes keyboard press events.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
unbind: function unbind() {
|
|
Binder.off('keyup', document);
|
|
},
|
|
|
|
/**
|
|
* Handles keyboard's arrows press and moving glide foward and backward.
|
|
*
|
|
* @param {Object} event
|
|
* @return {Void}
|
|
*/
|
|
press: function press(event) {
|
|
if (event.keyCode === 39) {
|
|
Components.Run.make(Components.Direction.resolve('>'));
|
|
}
|
|
|
|
if (event.keyCode === 37) {
|
|
Components.Run.make(Components.Direction.resolve('<'));
|
|
}
|
|
}
|
|
};
|
|
/**
|
|
* Remove bindings from keyboard:
|
|
* - on destroying to remove added events
|
|
* - on updating to remove events before remounting
|
|
*/
|
|
|
|
Events.on(['destroy', 'update'], function () {
|
|
Keyboard.unbind();
|
|
});
|
|
/**
|
|
* Remount component
|
|
* - on updating to reflect potential changes in settings
|
|
*/
|
|
|
|
Events.on('update', function () {
|
|
Keyboard.mount();
|
|
});
|
|
/**
|
|
* Destroy binder:
|
|
* - on destroying to remove listeners
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Binder.destroy();
|
|
});
|
|
return Keyboard;
|
|
}
|
|
|
|
function autoplay(Glide, Components, Events) {
|
|
/**
|
|
* Instance of the binder for DOM Events.
|
|
*
|
|
* @type {EventsBinder}
|
|
*/
|
|
var Binder = new EventsBinder();
|
|
var Autoplay = {
|
|
/**
|
|
* Initializes autoplaying and events.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
mount: function mount() {
|
|
this.start();
|
|
|
|
if (Glide.settings.hoverpause) {
|
|
this.bind();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Starts autoplaying in configured interval.
|
|
*
|
|
* @param {Boolean|Number} force Run autoplaying with passed interval regardless of `autoplay` settings
|
|
* @return {Void}
|
|
*/
|
|
start: function start() {
|
|
var _this = this;
|
|
|
|
if (Glide.settings.autoplay) {
|
|
if (isUndefined(this._i)) {
|
|
this._i = setInterval(function () {
|
|
_this.stop();
|
|
|
|
Components.Run.make('>');
|
|
|
|
_this.start();
|
|
}, this.time);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Stops autorunning of the glide.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
stop: function stop() {
|
|
this._i = clearInterval(this._i);
|
|
},
|
|
|
|
/**
|
|
* Stops autoplaying while mouse is over glide's area.
|
|
*
|
|
* @return {Void}
|
|
*/
|
|
bind: function bind() {
|
|
var _this2 = this;
|
|
|
|
Binder.on('mouseover', Components.Html.root, function () {
|
|
_this2.stop();
|
|
});
|
|
Binder.on('mouseout', Components.Html.root, function () {
|
|
_this2.start();
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Unbind mouseover events.
|
|
*
|
|
* @returns {Void}
|
|
*/
|
|
unbind: function unbind() {
|
|
Binder.off(['mouseover', 'mouseout'], Components.Html.root);
|
|
}
|
|
};
|
|
define(Autoplay, 'time', {
|
|
/**
|
|
* Gets time period value for the autoplay interval. Prioritizes
|
|
* times in `data-glide-autoplay` attrubutes over options.
|
|
*
|
|
* @return {Number}
|
|
*/
|
|
get: function get() {
|
|
var autoplay = Components.Html.slides[Glide.index].getAttribute('data-glide-autoplay');
|
|
|
|
if (autoplay) {
|
|
return toInt(autoplay);
|
|
}
|
|
|
|
return toInt(Glide.settings.autoplay);
|
|
}
|
|
});
|
|
/**
|
|
* Stop autoplaying and unbind events:
|
|
* - on destroying, to clear defined interval
|
|
* - on updating via API to reset interval that may changed
|
|
*/
|
|
|
|
Events.on(['destroy', 'update'], function () {
|
|
Autoplay.unbind();
|
|
});
|
|
/**
|
|
* Stop autoplaying:
|
|
* - before each run, to restart autoplaying
|
|
* - on pausing via API
|
|
* - on destroying, to clear defined interval
|
|
* - while starting a swipe
|
|
* - on updating via API to reset interval that may changed
|
|
*/
|
|
|
|
Events.on(['run.before', 'pause', 'destroy', 'swipe.start', 'update'], function () {
|
|
Autoplay.stop();
|
|
});
|
|
/**
|
|
* Start autoplaying:
|
|
* - after each run, to restart autoplaying
|
|
* - on playing via API
|
|
* - while ending a swipe
|
|
*/
|
|
|
|
Events.on(['run.after', 'play', 'swipe.end'], function () {
|
|
Autoplay.start();
|
|
});
|
|
/**
|
|
* Remount autoplaying:
|
|
* - on updating via API to reset interval that may changed
|
|
*/
|
|
|
|
Events.on('update', function () {
|
|
Autoplay.mount();
|
|
});
|
|
/**
|
|
* Destroy a binder:
|
|
* - on destroying glide instance to clearup listeners
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Binder.destroy();
|
|
});
|
|
return Autoplay;
|
|
}
|
|
/**
|
|
* Sorts keys of breakpoint object so they will be ordered from lower to bigger.
|
|
*
|
|
* @param {Object} points
|
|
* @returns {Object}
|
|
*/
|
|
|
|
|
|
function sortBreakpoints(points) {
|
|
if (isObject(points)) {
|
|
return sortKeys(points);
|
|
} else {
|
|
warn('Breakpoints option must be an object');
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
function breakpoints(Glide, Components, Events) {
|
|
/**
|
|
* Instance of the binder for DOM Events.
|
|
*
|
|
* @type {EventsBinder}
|
|
*/
|
|
var Binder = new EventsBinder();
|
|
/**
|
|
* Holds reference to settings.
|
|
*
|
|
* @type {Object}
|
|
*/
|
|
|
|
var settings = Glide.settings;
|
|
/**
|
|
* Holds reference to breakpoints object in settings. Sorts breakpoints
|
|
* from smaller to larger. It is required in order to proper
|
|
* matching currently active breakpoint settings.
|
|
*
|
|
* @type {Object}
|
|
*/
|
|
|
|
var points = sortBreakpoints(settings.breakpoints);
|
|
/**
|
|
* Cache initial settings before overwritting.
|
|
*
|
|
* @type {Object}
|
|
*/
|
|
|
|
var defaults = _extends({}, settings);
|
|
|
|
var Breakpoints = {
|
|
/**
|
|
* Matches settings for currectly matching media breakpoint.
|
|
*
|
|
* @param {Object} points
|
|
* @returns {Object}
|
|
*/
|
|
match: function match(points) {
|
|
if (typeof window.matchMedia !== 'undefined') {
|
|
for (var point in points) {
|
|
if (points.hasOwnProperty(point)) {
|
|
if (window.matchMedia('(max-width: ' + point + 'px)').matches) {
|
|
return points[point];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return defaults;
|
|
}
|
|
};
|
|
/**
|
|
* Overwrite instance settings with currently matching breakpoint settings.
|
|
* This happens right after component initialization.
|
|
*/
|
|
|
|
_extends(settings, Breakpoints.match(points));
|
|
/**
|
|
* Update glide with settings of matched brekpoint:
|
|
* - window resize to update slider
|
|
*/
|
|
|
|
|
|
Binder.on('resize', window, throttle(function () {
|
|
Glide.settings = mergeOptions(settings, Breakpoints.match(points));
|
|
}, Glide.settings.throttle));
|
|
/**
|
|
* Resort and update default settings:
|
|
* - on reinit via API, so breakpoint matching will be performed with options
|
|
*/
|
|
|
|
Events.on('update', function () {
|
|
points = sortBreakpoints(points);
|
|
defaults = _extends({}, settings);
|
|
});
|
|
/**
|
|
* Unbind resize listener:
|
|
* - on destroying, to bring markup to its initial state
|
|
*/
|
|
|
|
Events.on('destroy', function () {
|
|
Binder.off('resize', window);
|
|
});
|
|
return Breakpoints;
|
|
}
|
|
|
|
var COMPONENTS = {
|
|
Html: Html,
|
|
Translate: Translate,
|
|
Transition: Transition,
|
|
Direction: Direction,
|
|
Peek: Peek,
|
|
Sizes: Sizes,
|
|
Gaps: Gaps,
|
|
Move: Move,
|
|
Clones: Clones,
|
|
Resize: Resize,
|
|
Build: Build,
|
|
Run: Run
|
|
};
|
|
|
|
var Glide$1 = function (_Core) {
|
|
inherits(Glide$$1, _Core);
|
|
|
|
function Glide$$1() {
|
|
classCallCheck(this, Glide$$1);
|
|
return possibleConstructorReturn(this, (Glide$$1.__proto__ || Object.getPrototypeOf(Glide$$1)).apply(this, arguments));
|
|
}
|
|
|
|
createClass(Glide$$1, [{
|
|
key: 'mount',
|
|
value: function mount() {
|
|
var extensions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
return get(Glide$$1.prototype.__proto__ || Object.getPrototypeOf(Glide$$1.prototype), 'mount', this).call(this, _extends({}, COMPONENTS, extensions));
|
|
}
|
|
}]);
|
|
return Glide$$1;
|
|
}(Glide);
|
|
|
|
/* harmony default export */ __webpack_exports__["default"] = (Glide$1);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/aos/dist/aos.js":
|
|
/*!**************************************!*\
|
|
!*** ./node_modules/aos/dist/aos.js ***!
|
|
\**************************************/
|
|
/*! no static exports found */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* WEBPACK VAR INJECTION */(function(module) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
|
|
|
!function (e, t) {
|
|
"object" == ( false ? undefined : _typeof(exports)) && "object" == ( false ? undefined : _typeof(module)) ? module.exports = t() : true ? !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (t),
|
|
__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__)) : undefined;
|
|
}(this, function () {
|
|
return function (e) {
|
|
function t(o) {
|
|
if (n[o]) return n[o].exports;
|
|
var i = n[o] = {
|
|
exports: {},
|
|
id: o,
|
|
loaded: !1
|
|
};
|
|
return e[o].call(i.exports, i, i.exports, t), i.loaded = !0, i.exports;
|
|
}
|
|
|
|
var n = {};
|
|
return t.m = e, t.c = n, t.p = "dist/", t(0);
|
|
}([function (e, t, n) {
|
|
"use strict";
|
|
|
|
function o(e) {
|
|
return e && e.__esModule ? e : {
|
|
"default": e
|
|
};
|
|
}
|
|
|
|
var i = Object.assign || function (e) {
|
|
for (var t = 1; t < arguments.length; t++) {
|
|
var n = arguments[t];
|
|
|
|
for (var o in n) {
|
|
Object.prototype.hasOwnProperty.call(n, o) && (e[o] = n[o]);
|
|
}
|
|
}
|
|
|
|
return e;
|
|
},
|
|
r = n(1),
|
|
a = (o(r), n(6)),
|
|
u = o(a),
|
|
c = n(7),
|
|
s = o(c),
|
|
f = n(8),
|
|
d = o(f),
|
|
l = n(9),
|
|
p = o(l),
|
|
m = n(10),
|
|
b = o(m),
|
|
v = n(11),
|
|
y = o(v),
|
|
g = n(14),
|
|
h = o(g),
|
|
w = [],
|
|
k = !1,
|
|
x = {
|
|
offset: 120,
|
|
delay: 0,
|
|
easing: "ease",
|
|
duration: 400,
|
|
disable: !1,
|
|
once: !1,
|
|
startEvent: "DOMContentLoaded",
|
|
throttleDelay: 99,
|
|
debounceDelay: 50,
|
|
disableMutationObserver: !1
|
|
},
|
|
j = function j() {
|
|
var e = arguments.length > 0 && void 0 !== arguments[0] && arguments[0];
|
|
if (e && (k = !0), k) return w = (0, y["default"])(w, x), (0, b["default"])(w, x.once), w;
|
|
},
|
|
O = function O() {
|
|
w = (0, h["default"])(), j();
|
|
},
|
|
M = function M() {
|
|
w.forEach(function (e, t) {
|
|
e.node.removeAttribute("data-aos"), e.node.removeAttribute("data-aos-easing"), e.node.removeAttribute("data-aos-duration"), e.node.removeAttribute("data-aos-delay");
|
|
});
|
|
},
|
|
S = function S(e) {
|
|
return e === !0 || "mobile" === e && p["default"].mobile() || "phone" === e && p["default"].phone() || "tablet" === e && p["default"].tablet() || "function" == typeof e && e() === !0;
|
|
},
|
|
_ = function _(e) {
|
|
x = i(x, e), w = (0, h["default"])();
|
|
var t = document.all && !window.atob;
|
|
return S(x.disable) || t ? M() : (x.disableMutationObserver || d["default"].isSupported() || (console.info('\n aos: MutationObserver is not supported on this browser,\n code mutations observing has been disabled.\n You may have to call "refreshHard()" by yourself.\n '), x.disableMutationObserver = !0), document.querySelector("body").setAttribute("data-aos-easing", x.easing), document.querySelector("body").setAttribute("data-aos-duration", x.duration), document.querySelector("body").setAttribute("data-aos-delay", x.delay), "DOMContentLoaded" === x.startEvent && ["complete", "interactive"].indexOf(document.readyState) > -1 ? j(!0) : "load" === x.startEvent ? window.addEventListener(x.startEvent, function () {
|
|
j(!0);
|
|
}) : document.addEventListener(x.startEvent, function () {
|
|
j(!0);
|
|
}), window.addEventListener("resize", (0, s["default"])(j, x.debounceDelay, !0)), window.addEventListener("orientationchange", (0, s["default"])(j, x.debounceDelay, !0)), window.addEventListener("scroll", (0, u["default"])(function () {
|
|
(0, b["default"])(w, x.once);
|
|
}, x.throttleDelay), {
|
|
passive: !0
|
|
}), x.disableMutationObserver || d["default"].ready("[data-aos]", O), w);
|
|
};
|
|
|
|
e.exports = {
|
|
init: _,
|
|
refresh: j,
|
|
refreshHard: O
|
|
};
|
|
}, function (e, t) {},,,,, function (e, t) {
|
|
(function (t) {
|
|
"use strict";
|
|
|
|
function n(e, t, n) {
|
|
function o(t) {
|
|
var n = b,
|
|
o = v;
|
|
return b = v = void 0, k = t, g = e.apply(o, n);
|
|
}
|
|
|
|
function r(e) {
|
|
return k = e, h = setTimeout(f, t), M ? o(e) : g;
|
|
}
|
|
|
|
function a(e) {
|
|
var n = e - w,
|
|
o = e - k,
|
|
i = t - n;
|
|
return S ? j(i, y - o) : i;
|
|
}
|
|
|
|
function c(e) {
|
|
var n = e - w,
|
|
o = e - k;
|
|
return void 0 === w || n >= t || n < 0 || S && o >= y;
|
|
}
|
|
|
|
function f() {
|
|
var e = O();
|
|
return c(e) ? d(e) : void (h = setTimeout(f, a(e)));
|
|
}
|
|
|
|
function d(e) {
|
|
return h = void 0, _ && b ? o(e) : (b = v = void 0, g);
|
|
}
|
|
|
|
function l() {
|
|
void 0 !== h && clearTimeout(h), k = 0, b = w = v = h = void 0;
|
|
}
|
|
|
|
function p() {
|
|
return void 0 === h ? g : d(O());
|
|
}
|
|
|
|
function m() {
|
|
var e = O(),
|
|
n = c(e);
|
|
|
|
if (b = arguments, v = this, w = e, n) {
|
|
if (void 0 === h) return r(w);
|
|
if (S) return h = setTimeout(f, t), o(w);
|
|
}
|
|
|
|
return void 0 === h && (h = setTimeout(f, t)), g;
|
|
}
|
|
|
|
var b,
|
|
v,
|
|
y,
|
|
g,
|
|
h,
|
|
w,
|
|
k = 0,
|
|
M = !1,
|
|
S = !1,
|
|
_ = !0;
|
|
|
|
if ("function" != typeof e) throw new TypeError(s);
|
|
return t = u(t) || 0, i(n) && (M = !!n.leading, S = "maxWait" in n, y = S ? x(u(n.maxWait) || 0, t) : y, _ = "trailing" in n ? !!n.trailing : _), m.cancel = l, m.flush = p, m;
|
|
}
|
|
|
|
function o(e, t, o) {
|
|
var r = !0,
|
|
a = !0;
|
|
if ("function" != typeof e) throw new TypeError(s);
|
|
return i(o) && (r = "leading" in o ? !!o.leading : r, a = "trailing" in o ? !!o.trailing : a), n(e, t, {
|
|
leading: r,
|
|
maxWait: t,
|
|
trailing: a
|
|
});
|
|
}
|
|
|
|
function i(e) {
|
|
var t = "undefined" == typeof e ? "undefined" : c(e);
|
|
return !!e && ("object" == t || "function" == t);
|
|
}
|
|
|
|
function r(e) {
|
|
return !!e && "object" == ("undefined" == typeof e ? "undefined" : c(e));
|
|
}
|
|
|
|
function a(e) {
|
|
return "symbol" == ("undefined" == typeof e ? "undefined" : c(e)) || r(e) && k.call(e) == d;
|
|
}
|
|
|
|
function u(e) {
|
|
if ("number" == typeof e) return e;
|
|
if (a(e)) return f;
|
|
|
|
if (i(e)) {
|
|
var t = "function" == typeof e.valueOf ? e.valueOf() : e;
|
|
e = i(t) ? t + "" : t;
|
|
}
|
|
|
|
if ("string" != typeof e) return 0 === e ? e : +e;
|
|
e = e.replace(l, "");
|
|
var n = m.test(e);
|
|
return n || b.test(e) ? v(e.slice(2), n ? 2 : 8) : p.test(e) ? f : +e;
|
|
}
|
|
|
|
var c = "function" == typeof Symbol && "symbol" == _typeof(Symbol.iterator) ? function (e) {
|
|
return _typeof(e);
|
|
} : function (e) {
|
|
return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : _typeof(e);
|
|
},
|
|
s = "Expected a function",
|
|
f = NaN,
|
|
d = "[object Symbol]",
|
|
l = /^\s+|\s+$/g,
|
|
p = /^[-+]0x[0-9a-f]+$/i,
|
|
m = /^0b[01]+$/i,
|
|
b = /^0o[0-7]+$/i,
|
|
v = parseInt,
|
|
y = "object" == ("undefined" == typeof t ? "undefined" : c(t)) && t && t.Object === Object && t,
|
|
g = "object" == ("undefined" == typeof self ? "undefined" : c(self)) && self && self.Object === Object && self,
|
|
h = y || g || Function("return this")(),
|
|
w = Object.prototype,
|
|
k = w.toString,
|
|
x = Math.max,
|
|
j = Math.min,
|
|
O = function O() {
|
|
return h.Date.now();
|
|
};
|
|
|
|
e.exports = o;
|
|
}).call(t, function () {
|
|
return this;
|
|
}());
|
|
}, function (e, t) {
|
|
(function (t) {
|
|
"use strict";
|
|
|
|
function n(e, t, n) {
|
|
function i(t) {
|
|
var n = b,
|
|
o = v;
|
|
return b = v = void 0, O = t, g = e.apply(o, n);
|
|
}
|
|
|
|
function r(e) {
|
|
return O = e, h = setTimeout(f, t), M ? i(e) : g;
|
|
}
|
|
|
|
function u(e) {
|
|
var n = e - w,
|
|
o = e - O,
|
|
i = t - n;
|
|
return S ? x(i, y - o) : i;
|
|
}
|
|
|
|
function s(e) {
|
|
var n = e - w,
|
|
o = e - O;
|
|
return void 0 === w || n >= t || n < 0 || S && o >= y;
|
|
}
|
|
|
|
function f() {
|
|
var e = j();
|
|
return s(e) ? d(e) : void (h = setTimeout(f, u(e)));
|
|
}
|
|
|
|
function d(e) {
|
|
return h = void 0, _ && b ? i(e) : (b = v = void 0, g);
|
|
}
|
|
|
|
function l() {
|
|
void 0 !== h && clearTimeout(h), O = 0, b = w = v = h = void 0;
|
|
}
|
|
|
|
function p() {
|
|
return void 0 === h ? g : d(j());
|
|
}
|
|
|
|
function m() {
|
|
var e = j(),
|
|
n = s(e);
|
|
|
|
if (b = arguments, v = this, w = e, n) {
|
|
if (void 0 === h) return r(w);
|
|
if (S) return h = setTimeout(f, t), i(w);
|
|
}
|
|
|
|
return void 0 === h && (h = setTimeout(f, t)), g;
|
|
}
|
|
|
|
var b,
|
|
v,
|
|
y,
|
|
g,
|
|
h,
|
|
w,
|
|
O = 0,
|
|
M = !1,
|
|
S = !1,
|
|
_ = !0;
|
|
|
|
if ("function" != typeof e) throw new TypeError(c);
|
|
return t = a(t) || 0, o(n) && (M = !!n.leading, S = "maxWait" in n, y = S ? k(a(n.maxWait) || 0, t) : y, _ = "trailing" in n ? !!n.trailing : _), m.cancel = l, m.flush = p, m;
|
|
}
|
|
|
|
function o(e) {
|
|
var t = "undefined" == typeof e ? "undefined" : u(e);
|
|
return !!e && ("object" == t || "function" == t);
|
|
}
|
|
|
|
function i(e) {
|
|
return !!e && "object" == ("undefined" == typeof e ? "undefined" : u(e));
|
|
}
|
|
|
|
function r(e) {
|
|
return "symbol" == ("undefined" == typeof e ? "undefined" : u(e)) || i(e) && w.call(e) == f;
|
|
}
|
|
|
|
function a(e) {
|
|
if ("number" == typeof e) return e;
|
|
if (r(e)) return s;
|
|
|
|
if (o(e)) {
|
|
var t = "function" == typeof e.valueOf ? e.valueOf() : e;
|
|
e = o(t) ? t + "" : t;
|
|
}
|
|
|
|
if ("string" != typeof e) return 0 === e ? e : +e;
|
|
e = e.replace(d, "");
|
|
var n = p.test(e);
|
|
return n || m.test(e) ? b(e.slice(2), n ? 2 : 8) : l.test(e) ? s : +e;
|
|
}
|
|
|
|
var u = "function" == typeof Symbol && "symbol" == _typeof(Symbol.iterator) ? function (e) {
|
|
return _typeof(e);
|
|
} : function (e) {
|
|
return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : _typeof(e);
|
|
},
|
|
c = "Expected a function",
|
|
s = NaN,
|
|
f = "[object Symbol]",
|
|
d = /^\s+|\s+$/g,
|
|
l = /^[-+]0x[0-9a-f]+$/i,
|
|
p = /^0b[01]+$/i,
|
|
m = /^0o[0-7]+$/i,
|
|
b = parseInt,
|
|
v = "object" == ("undefined" == typeof t ? "undefined" : u(t)) && t && t.Object === Object && t,
|
|
y = "object" == ("undefined" == typeof self ? "undefined" : u(self)) && self && self.Object === Object && self,
|
|
g = v || y || Function("return this")(),
|
|
h = Object.prototype,
|
|
w = h.toString,
|
|
k = Math.max,
|
|
x = Math.min,
|
|
j = function j() {
|
|
return g.Date.now();
|
|
};
|
|
|
|
e.exports = n;
|
|
}).call(t, function () {
|
|
return this;
|
|
}());
|
|
}, function (e, t) {
|
|
"use strict";
|
|
|
|
function n(e) {
|
|
var t = void 0,
|
|
o = void 0,
|
|
i = void 0;
|
|
|
|
for (t = 0; t < e.length; t += 1) {
|
|
if (o = e[t], o.dataset && o.dataset.aos) return !0;
|
|
if (i = o.children && n(o.children)) return !0;
|
|
}
|
|
|
|
return !1;
|
|
}
|
|
|
|
function o() {
|
|
return window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
|
|
}
|
|
|
|
function i() {
|
|
return !!o();
|
|
}
|
|
|
|
function r(e, t) {
|
|
var n = window.document,
|
|
i = o(),
|
|
r = new i(a);
|
|
u = t, r.observe(n.documentElement, {
|
|
childList: !0,
|
|
subtree: !0,
|
|
removedNodes: !0
|
|
});
|
|
}
|
|
|
|
function a(e) {
|
|
e && e.forEach(function (e) {
|
|
var t = Array.prototype.slice.call(e.addedNodes),
|
|
o = Array.prototype.slice.call(e.removedNodes),
|
|
i = t.concat(o);
|
|
if (n(i)) return u();
|
|
});
|
|
}
|
|
|
|
Object.defineProperty(t, "__esModule", {
|
|
value: !0
|
|
});
|
|
|
|
var u = function u() {};
|
|
|
|
t["default"] = {
|
|
isSupported: i,
|
|
ready: r
|
|
};
|
|
}, function (e, t) {
|
|
"use strict";
|
|
|
|
function n(e, t) {
|
|
if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function");
|
|
}
|
|
|
|
function o() {
|
|
return navigator.userAgent || navigator.vendor || window.opera || "";
|
|
}
|
|
|
|
Object.defineProperty(t, "__esModule", {
|
|
value: !0
|
|
});
|
|
|
|
var i = function () {
|
|
function e(e, t) {
|
|
for (var n = 0; n < t.length; n++) {
|
|
var o = t[n];
|
|
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, o.key, o);
|
|
}
|
|
}
|
|
|
|
return function (t, n, o) {
|
|
return n && e(t.prototype, n), o && e(t, o), t;
|
|
};
|
|
}(),
|
|
r = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i,
|
|
a = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i,
|
|
u = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i,
|
|
c = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i,
|
|
s = function () {
|
|
function e() {
|
|
n(this, e);
|
|
}
|
|
|
|
return i(e, [{
|
|
key: "phone",
|
|
value: function value() {
|
|
var e = o();
|
|
return !(!r.test(e) && !a.test(e.substr(0, 4)));
|
|
}
|
|
}, {
|
|
key: "mobile",
|
|
value: function value() {
|
|
var e = o();
|
|
return !(!u.test(e) && !c.test(e.substr(0, 4)));
|
|
}
|
|
}, {
|
|
key: "tablet",
|
|
value: function value() {
|
|
return this.mobile() && !this.phone();
|
|
}
|
|
}]), e;
|
|
}();
|
|
|
|
t["default"] = new s();
|
|
}, function (e, t) {
|
|
"use strict";
|
|
|
|
Object.defineProperty(t, "__esModule", {
|
|
value: !0
|
|
});
|
|
|
|
var n = function n(e, t, _n) {
|
|
var o = e.node.getAttribute("data-aos-once");
|
|
t > e.position ? e.node.classList.add("aos-animate") : "undefined" != typeof o && ("false" === o || !_n && "true" !== o) && e.node.classList.remove("aos-animate");
|
|
},
|
|
o = function o(e, t) {
|
|
var o = window.pageYOffset,
|
|
i = window.innerHeight;
|
|
e.forEach(function (e, r) {
|
|
n(e, i + o, t);
|
|
});
|
|
};
|
|
|
|
t["default"] = o;
|
|
}, function (e, t, n) {
|
|
"use strict";
|
|
|
|
function o(e) {
|
|
return e && e.__esModule ? e : {
|
|
"default": e
|
|
};
|
|
}
|
|
|
|
Object.defineProperty(t, "__esModule", {
|
|
value: !0
|
|
});
|
|
|
|
var i = n(12),
|
|
r = o(i),
|
|
a = function a(e, t) {
|
|
return e.forEach(function (e, n) {
|
|
e.node.classList.add("aos-init"), e.position = (0, r["default"])(e.node, t.offset);
|
|
}), e;
|
|
};
|
|
|
|
t["default"] = a;
|
|
}, function (e, t, n) {
|
|
"use strict";
|
|
|
|
function o(e) {
|
|
return e && e.__esModule ? e : {
|
|
"default": e
|
|
};
|
|
}
|
|
|
|
Object.defineProperty(t, "__esModule", {
|
|
value: !0
|
|
});
|
|
|
|
var i = n(13),
|
|
r = o(i),
|
|
a = function a(e, t) {
|
|
var n = 0,
|
|
o = 0,
|
|
i = window.innerHeight,
|
|
a = {
|
|
offset: e.getAttribute("data-aos-offset"),
|
|
anchor: e.getAttribute("data-aos-anchor"),
|
|
anchorPlacement: e.getAttribute("data-aos-anchor-placement")
|
|
};
|
|
|
|
switch (a.offset && !isNaN(a.offset) && (o = parseInt(a.offset)), a.anchor && document.querySelectorAll(a.anchor) && (e = document.querySelectorAll(a.anchor)[0]), n = (0, r["default"])(e).top, a.anchorPlacement) {
|
|
case "top-bottom":
|
|
break;
|
|
|
|
case "center-bottom":
|
|
n += e.offsetHeight / 2;
|
|
break;
|
|
|
|
case "bottom-bottom":
|
|
n += e.offsetHeight;
|
|
break;
|
|
|
|
case "top-center":
|
|
n += i / 2;
|
|
break;
|
|
|
|
case "bottom-center":
|
|
n += i / 2 + e.offsetHeight;
|
|
break;
|
|
|
|
case "center-center":
|
|
n += i / 2 + e.offsetHeight / 2;
|
|
break;
|
|
|
|
case "top-top":
|
|
n += i;
|
|
break;
|
|
|
|
case "bottom-top":
|
|
n += e.offsetHeight + i;
|
|
break;
|
|
|
|
case "center-top":
|
|
n += e.offsetHeight / 2 + i;
|
|
}
|
|
|
|
return a.anchorPlacement || a.offset || isNaN(t) || (o = t), n + o;
|
|
};
|
|
|
|
t["default"] = a;
|
|
}, function (e, t) {
|
|
"use strict";
|
|
|
|
Object.defineProperty(t, "__esModule", {
|
|
value: !0
|
|
});
|
|
|
|
var n = function n(e) {
|
|
for (var t = 0, n = 0; e && !isNaN(e.offsetLeft) && !isNaN(e.offsetTop);) {
|
|
t += e.offsetLeft - ("BODY" != e.tagName ? e.scrollLeft : 0), n += e.offsetTop - ("BODY" != e.tagName ? e.scrollTop : 0), e = e.offsetParent;
|
|
}
|
|
|
|
return {
|
|
top: n,
|
|
left: t
|
|
};
|
|
};
|
|
|
|
t["default"] = n;
|
|
}, function (e, t) {
|
|
"use strict";
|
|
|
|
Object.defineProperty(t, "__esModule", {
|
|
value: !0
|
|
});
|
|
|
|
var n = function n(e) {
|
|
return e = e || document.querySelectorAll("[data-aos]"), Array.prototype.map.call(e, function (e) {
|
|
return {
|
|
node: e
|
|
};
|
|
});
|
|
};
|
|
|
|
t["default"] = n;
|
|
}]);
|
|
});
|
|
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../webpack/buildin/module.js */ "./node_modules/webpack/buildin/module.js")(module)))
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/fitvids/index.js":
|
|
/*!***************************************!*\
|
|
!*** ./node_modules/fitvids/index.js ***!
|
|
\***************************************/
|
|
/*! no static exports found */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var selectors = ['iframe[src*="player.vimeo.com"]', 'iframe[src*="youtube.com"]', 'iframe[src*="youtube-nocookie.com"]', 'iframe[src*="kickstarter.com"][src*="video.html"]', 'object'];
|
|
var css = '.fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}';
|
|
|
|
module.exports = function (parentSelector, opts) {
|
|
parentSelector = parentSelector || 'body';
|
|
opts = opts || {};
|
|
|
|
if (isObject(parentSelector)) {
|
|
opts = parentSelector;
|
|
parentSelector = 'body';
|
|
}
|
|
|
|
opts.ignore = opts.ignore || '';
|
|
opts.players = opts.players || '';
|
|
var containers = queryAll(parentSelector);
|
|
if (!hasLength(containers)) return;
|
|
|
|
if (!document.getElementById('fit-vids-style')) {
|
|
var head = document.head || document.getElementsByTagName('head')[0];
|
|
head.appendChild(styles());
|
|
}
|
|
|
|
var custom = toSelectorArray(opts.players) || [];
|
|
var ignored = toSelectorArray(opts.ignore) || [];
|
|
var selector = selectors.filter(notIgnored(ignored)).concat(custom).join();
|
|
if (!hasLength(selector)) return;
|
|
containers.forEach(function (container) {
|
|
var videos = queryAll(container, selector);
|
|
videos.forEach(function (video) {
|
|
wrap(video);
|
|
});
|
|
});
|
|
};
|
|
|
|
function queryAll(el, selector) {
|
|
if (typeof el === 'string') {
|
|
selector = el;
|
|
el = document;
|
|
}
|
|
|
|
return Array.prototype.slice.call(el.querySelectorAll(selector));
|
|
}
|
|
|
|
function toSelectorArray(input) {
|
|
if (typeof input === 'string') {
|
|
return input.split(',').map(trim).filter(hasLength);
|
|
} else if (isArray(input)) {
|
|
return flatten(input.map(toSelectorArray).filter(hasLength));
|
|
}
|
|
|
|
return input || [];
|
|
}
|
|
|
|
function wrap(el) {
|
|
if (/fluid-width-video-wrapper/.test(el.parentNode.className)) return;
|
|
var widthAttr = parseInt(el.getAttribute('width'), 10);
|
|
var heightAttr = parseInt(el.getAttribute('height'), 10);
|
|
var width = !isNaN(widthAttr) ? widthAttr : el.clientWidth;
|
|
var height = !isNaN(heightAttr) ? heightAttr : el.clientHeight;
|
|
var aspect = height / width;
|
|
el.removeAttribute('width');
|
|
el.removeAttribute('height');
|
|
var wrapper = document.createElement('div');
|
|
el.parentNode.insertBefore(wrapper, el);
|
|
wrapper.className = 'fluid-width-video-wrapper';
|
|
wrapper.style.paddingTop = aspect * 100 + '%';
|
|
wrapper.appendChild(el);
|
|
}
|
|
|
|
function styles() {
|
|
var div = document.createElement('div');
|
|
div.innerHTML = '<p>x</p><style id="fit-vids-style">' + css + '</style>';
|
|
return div.childNodes[1];
|
|
}
|
|
|
|
function notIgnored(ignored) {
|
|
if (ignored.length < 1) {
|
|
return function () {
|
|
return true;
|
|
};
|
|
}
|
|
|
|
return function (selector) {
|
|
return ignored.indexOf(selector) === -1;
|
|
};
|
|
}
|
|
|
|
function hasLength(input) {
|
|
return input.length > 0;
|
|
}
|
|
|
|
function trim(str) {
|
|
return str.replace(/^\s+|\s+$/g, '');
|
|
}
|
|
|
|
function flatten(input) {
|
|
return [].concat.apply([], input);
|
|
}
|
|
|
|
function isObject(input) {
|
|
return Object.prototype.toString.call(input) === '[object Object]';
|
|
}
|
|
|
|
function isArray(input) {
|
|
return Object.prototype.toString.call(input) === '[object Array]';
|
|
}
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/fuse.js/dist/fuse.basic.esm.min.js":
|
|
/*!*********************************************************!*\
|
|
!*** ./node_modules/fuse.js/dist/fuse.basic.esm.min.js ***!
|
|
\*********************************************************/
|
|
/*! exports provided: default */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
|
|
|
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
|
|
|
|
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
|
|
|
|
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
|
|
|
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
|
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
|
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
|
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
|
|
/**
|
|
* Fuse.js v6.3.1 - Lightweight fuzzy-search (http://fusejs.io)
|
|
*
|
|
* Copyright (c) 2020 Kiro Risk (http://kiro.me)
|
|
* All Rights Reserved. Apache Software License 2.0
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*/
|
|
function t(t) {
|
|
return Array.isArray ? Array.isArray(t) : "[object Array]" === Object.prototype.toString.call(t);
|
|
}
|
|
|
|
function e(t) {
|
|
return "string" == typeof t;
|
|
}
|
|
|
|
function n(t) {
|
|
return "number" == typeof t;
|
|
}
|
|
|
|
function s(t) {
|
|
return null != t;
|
|
}
|
|
|
|
function i(t) {
|
|
return !t.trim().length;
|
|
}
|
|
|
|
var r = Object.prototype.hasOwnProperty;
|
|
|
|
var o =
|
|
/*#__PURE__*/
|
|
function () {
|
|
function o(t) {
|
|
var _this = this;
|
|
|
|
_classCallCheck(this, o);
|
|
|
|
this._keys = [], this._keyMap = {};
|
|
var e = 0;
|
|
t.forEach(function (t) {
|
|
var n = c(t);
|
|
e += n.weight, _this._keys.push(n), _this._keyMap[n.id] = n, e += n.weight;
|
|
}), this._keys.forEach(function (t) {
|
|
t.weight /= e;
|
|
});
|
|
}
|
|
|
|
_createClass(o, [{
|
|
key: "get",
|
|
value: function get(t) {
|
|
return this._keyMap[t];
|
|
}
|
|
}, {
|
|
key: "keys",
|
|
value: function keys() {
|
|
return this._keys;
|
|
}
|
|
}, {
|
|
key: "toJSON",
|
|
value: function toJSON() {
|
|
return JSON.stringify(this._keys);
|
|
}
|
|
}]);
|
|
|
|
return o;
|
|
}();
|
|
|
|
function c(n) {
|
|
var s = null,
|
|
i = null,
|
|
o = null,
|
|
c = 1;
|
|
if (e(n) || t(n)) o = n, s = h(n), i = a(n);else {
|
|
if (!r.call(n, "name")) throw new Error(function (t) {
|
|
return "Missing ".concat(t, " property in key");
|
|
}("name"));
|
|
var _t = n.name;
|
|
if (o = _t, r.call(n, "weight") && (c = n.weight, c <= 0)) throw new Error(function (t) {
|
|
return "Property 'weight' in key '".concat(t, "' must be a positive integer");
|
|
}(_t));
|
|
s = h(_t), i = a(_t);
|
|
}
|
|
return {
|
|
path: s,
|
|
id: i,
|
|
weight: c,
|
|
src: o
|
|
};
|
|
}
|
|
|
|
function h(e) {
|
|
return t(e) ? e : e.split(".");
|
|
}
|
|
|
|
function a(e) {
|
|
return t(e) ? e.join(".") : e;
|
|
}
|
|
|
|
var l = _objectSpread({
|
|
isCaseSensitive: !1,
|
|
includeScore: !1,
|
|
keys: [],
|
|
shouldSort: !0,
|
|
sortFn: function sortFn(t, e) {
|
|
return t.score === e.score ? t.idx < e.idx ? -1 : 1 : t.score < e.score ? -1 : 1;
|
|
},
|
|
includeMatches: !1,
|
|
findAllMatches: !1,
|
|
minMatchCharLength: 1,
|
|
location: 0,
|
|
threshold: .6,
|
|
distance: 100
|
|
}, {
|
|
useExtendedSearch: !1,
|
|
getFn: function getFn(i, r) {
|
|
var o = [],
|
|
c = !1;
|
|
|
|
var h = function h(i, r, a) {
|
|
if (r[a]) {
|
|
var _l = i[r[a]];
|
|
if (!s(_l)) return;
|
|
if (a === r.length - 1 && (e(_l) || n(_l))) o.push(function (t) {
|
|
return null == t ? "" : function (t) {
|
|
if ("string" == typeof t) return t;
|
|
var e = t + "";
|
|
return "0" == e && 1 / t == -1 / 0 ? "-0" : e;
|
|
}(t);
|
|
}(_l));else if (t(_l)) {
|
|
c = !0;
|
|
|
|
for (var _t2 = 0, _e = _l.length; _t2 < _e; _t2 += 1) {
|
|
h(_l[_t2], r, a + 1);
|
|
}
|
|
} else r.length && h(_l, r, a + 1);
|
|
} else o.push(i);
|
|
};
|
|
|
|
return h(i, e(r) ? r.split(".") : r, 0), c ? o : o[0];
|
|
},
|
|
ignoreLocation: !1,
|
|
ignoreFieldNorm: !1
|
|
});
|
|
|
|
var d = /[^ ]+/g;
|
|
|
|
var u =
|
|
/*#__PURE__*/
|
|
function () {
|
|
function u() {
|
|
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
|
_ref$getFn = _ref.getFn,
|
|
t = _ref$getFn === void 0 ? l.getFn : _ref$getFn;
|
|
|
|
_classCallCheck(this, u);
|
|
|
|
this.norm = function () {
|
|
var t = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 3;
|
|
var e = new Map();
|
|
return {
|
|
get: function get(n) {
|
|
var s = n.match(d).length;
|
|
if (e.has(s)) return e.get(s);
|
|
var i = parseFloat((1 / Math.sqrt(s)).toFixed(t));
|
|
return e.set(s, i), i;
|
|
},
|
|
clear: function clear() {
|
|
e.clear();
|
|
}
|
|
};
|
|
}(3), this.getFn = t, this.isCreated = !1, this.setIndexRecords();
|
|
}
|
|
|
|
_createClass(u, [{
|
|
key: "setSources",
|
|
value: function setSources() {
|
|
var t = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
this.docs = t;
|
|
}
|
|
}, {
|
|
key: "setIndexRecords",
|
|
value: function setIndexRecords() {
|
|
var t = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
this.records = t;
|
|
}
|
|
}, {
|
|
key: "setKeys",
|
|
value: function setKeys() {
|
|
var _this2 = this;
|
|
|
|
var t = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
this.keys = t, this._keysMap = {}, t.forEach(function (t, e) {
|
|
_this2._keysMap[t.id] = e;
|
|
});
|
|
}
|
|
}, {
|
|
key: "create",
|
|
value: function create() {
|
|
var _this3 = this;
|
|
|
|
!this.isCreated && this.docs.length && (this.isCreated = !0, e(this.docs[0]) ? this.docs.forEach(function (t, e) {
|
|
_this3._addString(t, e);
|
|
}) : this.docs.forEach(function (t, e) {
|
|
_this3._addObject(t, e);
|
|
}), this.norm.clear());
|
|
}
|
|
}, {
|
|
key: "add",
|
|
value: function add(t) {
|
|
var n = this.size();
|
|
e(t) ? this._addString(t, n) : this._addObject(t, n);
|
|
}
|
|
}, {
|
|
key: "removeAt",
|
|
value: function removeAt(t) {
|
|
this.records.splice(t, 1);
|
|
|
|
for (var _e2 = t, _n = this.size(); _e2 < _n; _e2 += 1) {
|
|
this.records[_e2].i -= 1;
|
|
}
|
|
}
|
|
}, {
|
|
key: "getValueForItemAtKeyId",
|
|
value: function getValueForItemAtKeyId(t, e) {
|
|
return t[this._keysMap[e]];
|
|
}
|
|
}, {
|
|
key: "size",
|
|
value: function size() {
|
|
return this.records.length;
|
|
}
|
|
}, {
|
|
key: "_addString",
|
|
value: function _addString(t, e) {
|
|
if (!s(t) || i(t)) return;
|
|
var n = {
|
|
v: t,
|
|
i: e,
|
|
n: this.norm.get(t)
|
|
};
|
|
this.records.push(n);
|
|
}
|
|
}, {
|
|
key: "_addObject",
|
|
value: function _addObject(n, r) {
|
|
var _this4 = this;
|
|
|
|
var o = {
|
|
i: r,
|
|
$: {}
|
|
};
|
|
this.keys.forEach(function (r, c) {
|
|
var h = _this4.getFn(n, r.path);
|
|
|
|
if (s(h)) if (t(h)) {
|
|
(function () {
|
|
var n = [];
|
|
var r = [{
|
|
nestedArrIndex: -1,
|
|
value: h
|
|
}];
|
|
|
|
for (; r.length;) {
|
|
var _r$pop = r.pop(),
|
|
_o = _r$pop.nestedArrIndex,
|
|
_c = _r$pop.value;
|
|
|
|
if (s(_c)) if (e(_c) && !i(_c)) {
|
|
var _t3 = {
|
|
v: _c,
|
|
i: _o,
|
|
n: _this4.norm.get(_c)
|
|
};
|
|
n.push(_t3);
|
|
} else t(_c) && _c.forEach(function (t, e) {
|
|
r.push({
|
|
nestedArrIndex: e,
|
|
value: t
|
|
});
|
|
});
|
|
}
|
|
|
|
o.$[c] = n;
|
|
})();
|
|
} else if (!i(h)) {
|
|
var _t4 = {
|
|
v: h,
|
|
n: _this4.norm.get(h)
|
|
};
|
|
o.$[c] = _t4;
|
|
}
|
|
}), this.records.push(o);
|
|
}
|
|
}, {
|
|
key: "toJSON",
|
|
value: function toJSON() {
|
|
return {
|
|
keys: this.keys,
|
|
records: this.records
|
|
};
|
|
}
|
|
}]);
|
|
|
|
return u;
|
|
}();
|
|
|
|
function f(t, e) {
|
|
var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
|
|
_ref2$getFn = _ref2.getFn,
|
|
n = _ref2$getFn === void 0 ? l.getFn : _ref2$getFn;
|
|
|
|
var s = new u({
|
|
getFn: n
|
|
});
|
|
return s.setKeys(t.map(c)), s.setSources(e), s.create(), s;
|
|
}
|
|
|
|
function g(t, e) {
|
|
var n = t.matches;
|
|
e.matches = [], s(n) && n.forEach(function (t) {
|
|
if (!s(t.indices) || !t.indices.length) return;
|
|
var n = t.indices,
|
|
i = t.value;
|
|
var r = {
|
|
indices: n,
|
|
value: i
|
|
};
|
|
t.key && (r.key = t.key.src), t.idx > -1 && (r.refIndex = t.idx), e.matches.push(r);
|
|
});
|
|
}
|
|
|
|
function p(t, e) {
|
|
e.score = t.score;
|
|
}
|
|
|
|
function m(t) {
|
|
var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
_ref3$errors = _ref3.errors,
|
|
e = _ref3$errors === void 0 ? 0 : _ref3$errors,
|
|
_ref3$currentLocation = _ref3.currentLocation,
|
|
n = _ref3$currentLocation === void 0 ? 0 : _ref3$currentLocation,
|
|
_ref3$expectedLocatio = _ref3.expectedLocation,
|
|
s = _ref3$expectedLocatio === void 0 ? 0 : _ref3$expectedLocatio,
|
|
_ref3$distance = _ref3.distance,
|
|
i = _ref3$distance === void 0 ? l.distance : _ref3$distance,
|
|
_ref3$ignoreLocation = _ref3.ignoreLocation,
|
|
r = _ref3$ignoreLocation === void 0 ? l.ignoreLocation : _ref3$ignoreLocation;
|
|
|
|
var o = e / t.length;
|
|
if (r) return o;
|
|
var c = Math.abs(s - n);
|
|
return i ? o + c / i : c ? 1 : o;
|
|
}
|
|
|
|
function y(t, e, n) {
|
|
var _ref4 = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
|
|
_ref4$location = _ref4.location,
|
|
s = _ref4$location === void 0 ? l.location : _ref4$location,
|
|
_ref4$distance = _ref4.distance,
|
|
i = _ref4$distance === void 0 ? l.distance : _ref4$distance,
|
|
_ref4$threshold = _ref4.threshold,
|
|
r = _ref4$threshold === void 0 ? l.threshold : _ref4$threshold,
|
|
_ref4$findAllMatches = _ref4.findAllMatches,
|
|
o = _ref4$findAllMatches === void 0 ? l.findAllMatches : _ref4$findAllMatches,
|
|
_ref4$minMatchCharLen = _ref4.minMatchCharLength,
|
|
c = _ref4$minMatchCharLen === void 0 ? l.minMatchCharLength : _ref4$minMatchCharLen,
|
|
_ref4$includeMatches = _ref4.includeMatches,
|
|
h = _ref4$includeMatches === void 0 ? l.includeMatches : _ref4$includeMatches,
|
|
_ref4$ignoreLocation = _ref4.ignoreLocation,
|
|
a = _ref4$ignoreLocation === void 0 ? l.ignoreLocation : _ref4$ignoreLocation;
|
|
|
|
if (e.length > 32) throw new Error("Pattern length exceeds max of ".concat(32, "."));
|
|
var d = e.length,
|
|
u = t.length,
|
|
f = Math.max(0, Math.min(s, u));
|
|
var g = r,
|
|
p = f;
|
|
var y = c > 1 || h,
|
|
M = y ? Array(u) : [];
|
|
var x;
|
|
|
|
for (; (x = t.indexOf(e, p)) > -1;) {
|
|
var _t5 = m(e, {
|
|
currentLocation: x,
|
|
expectedLocation: f,
|
|
distance: i,
|
|
ignoreLocation: a
|
|
});
|
|
|
|
if (g = Math.min(_t5, g), p = x + d, y) {
|
|
var _t6 = 0;
|
|
|
|
for (; _t6 < d;) {
|
|
M[x + _t6] = 1, _t6 += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
p = -1;
|
|
var L = [],
|
|
_ = 1,
|
|
k = d + u;
|
|
var v = 1 << d - 1;
|
|
|
|
for (var _s = 0; _s < d; _s += 1) {
|
|
var _r = 0,
|
|
_c2 = k;
|
|
|
|
for (; _r < _c2;) {
|
|
m(e, {
|
|
errors: _s,
|
|
currentLocation: f + _c2,
|
|
expectedLocation: f,
|
|
distance: i,
|
|
ignoreLocation: a
|
|
}) <= g ? _r = _c2 : k = _c2, _c2 = Math.floor((k - _r) / 2 + _r);
|
|
}
|
|
|
|
k = _c2;
|
|
|
|
var _h = Math.max(1, f - _c2 + 1),
|
|
_l2 = o ? u : Math.min(f + _c2, u) + d,
|
|
_x = Array(_l2 + 2);
|
|
|
|
_x[_l2 + 1] = (1 << _s) - 1;
|
|
|
|
for (var _r2 = _l2; _r2 >= _h; _r2 -= 1) {
|
|
var _o2 = _r2 - 1,
|
|
_c3 = n[t.charAt(_o2)];
|
|
|
|
if (y && (M[_o2] = +!!_c3), _x[_r2] = (_x[_r2 + 1] << 1 | 1) & _c3, _s && (_x[_r2] |= (L[_r2 + 1] | L[_r2]) << 1 | 1 | L[_r2 + 1]), _x[_r2] & v && (_ = m(e, {
|
|
errors: _s,
|
|
currentLocation: _o2,
|
|
expectedLocation: f,
|
|
distance: i,
|
|
ignoreLocation: a
|
|
}), _ <= g)) {
|
|
if (g = _, p = _o2, p <= f) break;
|
|
_h = Math.max(1, 2 * f - p);
|
|
}
|
|
}
|
|
|
|
if (m(e, {
|
|
errors: _s + 1,
|
|
currentLocation: f,
|
|
expectedLocation: f,
|
|
distance: i,
|
|
ignoreLocation: a
|
|
}) > g) break;
|
|
L = _x;
|
|
}
|
|
|
|
var w = {
|
|
isMatch: p >= 0,
|
|
score: Math.max(.001, _)
|
|
};
|
|
|
|
if (y) {
|
|
var _t7 = function () {
|
|
var t = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
var e = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : l.minMatchCharLength;
|
|
var n = [],
|
|
s = -1,
|
|
i = -1,
|
|
r = 0;
|
|
|
|
for (var _o3 = t.length; r < _o3; r += 1) {
|
|
var _o4 = t[r];
|
|
_o4 && -1 === s ? s = r : _o4 || -1 === s || (i = r - 1, i - s + 1 >= e && n.push([s, i]), s = -1);
|
|
}
|
|
|
|
return t[r - 1] && r - s >= e && n.push([s, r - 1]), n;
|
|
}(M, c);
|
|
|
|
_t7.length ? h && (w.indices = _t7) : w.isMatch = !1;
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
function M(t) {
|
|
var e = {};
|
|
|
|
for (var _n2 = 0, _s2 = t.length; _n2 < _s2; _n2 += 1) {
|
|
var _i = t.charAt(_n2);
|
|
|
|
e[_i] = (e[_i] || 0) | 1 << _s2 - _n2 - 1;
|
|
}
|
|
|
|
return e;
|
|
}
|
|
|
|
var x =
|
|
/*#__PURE__*/
|
|
function () {
|
|
function x(t) {
|
|
var _this5 = this;
|
|
|
|
var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
_ref5$location = _ref5.location,
|
|
e = _ref5$location === void 0 ? l.location : _ref5$location,
|
|
_ref5$threshold = _ref5.threshold,
|
|
n = _ref5$threshold === void 0 ? l.threshold : _ref5$threshold,
|
|
_ref5$distance = _ref5.distance,
|
|
s = _ref5$distance === void 0 ? l.distance : _ref5$distance,
|
|
_ref5$includeMatches = _ref5.includeMatches,
|
|
i = _ref5$includeMatches === void 0 ? l.includeMatches : _ref5$includeMatches,
|
|
_ref5$findAllMatches = _ref5.findAllMatches,
|
|
r = _ref5$findAllMatches === void 0 ? l.findAllMatches : _ref5$findAllMatches,
|
|
_ref5$minMatchCharLen = _ref5.minMatchCharLength,
|
|
o = _ref5$minMatchCharLen === void 0 ? l.minMatchCharLength : _ref5$minMatchCharLen,
|
|
_ref5$isCaseSensitive = _ref5.isCaseSensitive,
|
|
c = _ref5$isCaseSensitive === void 0 ? l.isCaseSensitive : _ref5$isCaseSensitive,
|
|
_ref5$ignoreLocation = _ref5.ignoreLocation,
|
|
h = _ref5$ignoreLocation === void 0 ? l.ignoreLocation : _ref5$ignoreLocation;
|
|
|
|
_classCallCheck(this, x);
|
|
|
|
if (this.options = {
|
|
location: e,
|
|
threshold: n,
|
|
distance: s,
|
|
includeMatches: i,
|
|
findAllMatches: r,
|
|
minMatchCharLength: o,
|
|
isCaseSensitive: c,
|
|
ignoreLocation: h
|
|
}, this.pattern = c ? t : t.toLowerCase(), this.chunks = [], !this.pattern.length) return;
|
|
|
|
var a = function a(t, e) {
|
|
_this5.chunks.push({
|
|
pattern: t,
|
|
alphabet: M(t),
|
|
startIndex: e
|
|
});
|
|
},
|
|
d = this.pattern.length;
|
|
|
|
if (d > 32) {
|
|
var _t8 = 0;
|
|
|
|
var _e3 = d % 32,
|
|
_n3 = d - _e3;
|
|
|
|
for (; _t8 < _n3;) {
|
|
a(this.pattern.substr(_t8, 32), _t8), _t8 += 32;
|
|
}
|
|
|
|
if (_e3) {
|
|
var _t9 = d - 32;
|
|
|
|
a(this.pattern.substr(_t9), _t9);
|
|
}
|
|
} else a(this.pattern, 0);
|
|
}
|
|
|
|
_createClass(x, [{
|
|
key: "searchIn",
|
|
value: function searchIn(t) {
|
|
var _this$options = this.options,
|
|
e = _this$options.isCaseSensitive,
|
|
n = _this$options.includeMatches;
|
|
|
|
if (e || (t = t.toLowerCase()), this.pattern === t) {
|
|
var _e4 = {
|
|
isMatch: !0,
|
|
score: 0
|
|
};
|
|
return n && (_e4.indices = [[0, t.length - 1]]), _e4;
|
|
}
|
|
|
|
var _this$options2 = this.options,
|
|
s = _this$options2.location,
|
|
i = _this$options2.distance,
|
|
r = _this$options2.threshold,
|
|
o = _this$options2.findAllMatches,
|
|
c = _this$options2.minMatchCharLength,
|
|
h = _this$options2.ignoreLocation;
|
|
var a = [],
|
|
l = 0,
|
|
d = !1;
|
|
this.chunks.forEach(function (_ref6) {
|
|
var e = _ref6.pattern,
|
|
u = _ref6.alphabet,
|
|
f = _ref6.startIndex;
|
|
|
|
var _y = y(t, e, u, {
|
|
location: s + f,
|
|
distance: i,
|
|
threshold: r,
|
|
findAllMatches: o,
|
|
minMatchCharLength: c,
|
|
includeMatches: n,
|
|
ignoreLocation: h
|
|
}),
|
|
g = _y.isMatch,
|
|
p = _y.score,
|
|
m = _y.indices;
|
|
|
|
g && (d = !0), l += p, g && m && (a = [].concat(_toConsumableArray(a), _toConsumableArray(m)));
|
|
});
|
|
var u = {
|
|
isMatch: d,
|
|
score: d ? l / this.chunks.length : 1
|
|
};
|
|
return d && n && (u.indices = a), u;
|
|
}
|
|
}]);
|
|
|
|
return x;
|
|
}();
|
|
|
|
var L = [];
|
|
|
|
function _(t, e) {
|
|
for (var _n4 = 0, _s3 = L.length; _n4 < _s3; _n4 += 1) {
|
|
var _s4 = L[_n4];
|
|
if (_s4.condition(t, e)) return new _s4(t, e);
|
|
}
|
|
|
|
return new x(t, e);
|
|
}
|
|
|
|
var k =
|
|
/*#__PURE__*/
|
|
function () {
|
|
function k(t) {
|
|
var e = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
var n = arguments.length > 2 ? arguments[2] : undefined;
|
|
|
|
_classCallCheck(this, k);
|
|
|
|
if (this.options = _objectSpread({}, l, {}, e), this.options.useExtendedSearch) throw new Error("Extended search is not available");
|
|
this._keyStore = new o(this.options.keys), this.setCollection(t, n);
|
|
}
|
|
|
|
_createClass(k, [{
|
|
key: "setCollection",
|
|
value: function setCollection(t, e) {
|
|
if (this._docs = t, e && !(e instanceof u)) throw new Error("Incorrect 'index' type");
|
|
this._myIndex = e || f(this.options.keys, this._docs, {
|
|
getFn: this.options.getFn
|
|
});
|
|
}
|
|
}, {
|
|
key: "add",
|
|
value: function add(t) {
|
|
s(t) && (this._docs.push(t), this._myIndex.add(t));
|
|
}
|
|
}, {
|
|
key: "remove",
|
|
value: function remove() {
|
|
var t = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {
|
|
return !1;
|
|
};
|
|
var e = [];
|
|
|
|
for (var _n5 = 0, _s5 = this._docs.length; _n5 < _s5; _n5 += 1) {
|
|
var _s6 = this._docs[_n5];
|
|
t(_s6, _n5) && (this.removeAt(_n5), _n5 -= 1, e.push(_s6));
|
|
}
|
|
|
|
return e;
|
|
}
|
|
}, {
|
|
key: "removeAt",
|
|
value: function removeAt(t) {
|
|
this._docs.splice(t, 1), this._myIndex.removeAt(t);
|
|
}
|
|
}, {
|
|
key: "getIndex",
|
|
value: function getIndex() {
|
|
return this._myIndex;
|
|
}
|
|
}, {
|
|
key: "search",
|
|
value: function search(t) {
|
|
var _ref7 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
_ref7$limit = _ref7.limit,
|
|
s = _ref7$limit === void 0 ? -1 : _ref7$limit;
|
|
|
|
var _this$options3 = this.options,
|
|
i = _this$options3.includeMatches,
|
|
r = _this$options3.includeScore,
|
|
o = _this$options3.shouldSort,
|
|
c = _this$options3.sortFn,
|
|
h = _this$options3.ignoreFieldNorm;
|
|
var a = e(t) ? e(this._docs[0]) ? this._searchStringList(t) : this._searchObjectList(t) : this._searchLogical(t);
|
|
return function (t, e, _ref8) {
|
|
var _ref8$ignoreFieldNorm = _ref8.ignoreFieldNorm,
|
|
n = _ref8$ignoreFieldNorm === void 0 ? l.ignoreFieldNorm : _ref8$ignoreFieldNorm;
|
|
t.forEach(function (t) {
|
|
var e = 1;
|
|
t.matches.forEach(function (_ref9) {
|
|
var t = _ref9.key,
|
|
s = _ref9.norm,
|
|
i = _ref9.score;
|
|
var r = t ? t.weight : null;
|
|
e *= Math.pow(0 === i && r ? Number.EPSILON : i, (r || 1) * (n ? 1 : s));
|
|
}), t.score = e;
|
|
});
|
|
}(a, this._keyStore, {
|
|
ignoreFieldNorm: h
|
|
}), o && a.sort(c), n(s) && s > -1 && (a = a.slice(0, s)), function (t, e) {
|
|
var _ref10 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
|
|
_ref10$includeMatches = _ref10.includeMatches,
|
|
n = _ref10$includeMatches === void 0 ? l.includeMatches : _ref10$includeMatches,
|
|
_ref10$includeScore = _ref10.includeScore,
|
|
s = _ref10$includeScore === void 0 ? l.includeScore : _ref10$includeScore;
|
|
|
|
var i = [];
|
|
n && i.push(g);
|
|
s && i.push(p);
|
|
return t.map(function (t) {
|
|
var n = t.idx,
|
|
s = {
|
|
item: e[n],
|
|
refIndex: n
|
|
};
|
|
return i.length && i.forEach(function (e) {
|
|
e(t, s);
|
|
}), s;
|
|
});
|
|
}(a, this._docs, {
|
|
includeMatches: i,
|
|
includeScore: r
|
|
});
|
|
}
|
|
}, {
|
|
key: "_searchStringList",
|
|
value: function _searchStringList(t) {
|
|
var e = _(t, this.options),
|
|
n = this._myIndex.records,
|
|
i = [];
|
|
|
|
return n.forEach(function (_ref11) {
|
|
var t = _ref11.v,
|
|
n = _ref11.i,
|
|
r = _ref11.n;
|
|
if (!s(t)) return;
|
|
|
|
var _e$searchIn = e.searchIn(t),
|
|
o = _e$searchIn.isMatch,
|
|
c = _e$searchIn.score,
|
|
h = _e$searchIn.indices;
|
|
|
|
o && i.push({
|
|
item: t,
|
|
idx: n,
|
|
matches: [{
|
|
score: c,
|
|
value: t,
|
|
norm: r,
|
|
indices: h
|
|
}]
|
|
});
|
|
}), i;
|
|
}
|
|
}, {
|
|
key: "_searchLogical",
|
|
value: function _searchLogical(t) {
|
|
throw new Error("Logical search is not available");
|
|
}
|
|
}, {
|
|
key: "_searchObjectList",
|
|
value: function _searchObjectList(t) {
|
|
var _this6 = this;
|
|
|
|
var e = _(t, this.options),
|
|
_this$_myIndex = this._myIndex,
|
|
n = _this$_myIndex.keys,
|
|
i = _this$_myIndex.records,
|
|
r = [];
|
|
|
|
return i.forEach(function (_ref12) {
|
|
var t = _ref12.$,
|
|
i = _ref12.i;
|
|
if (!s(t)) return;
|
|
var o = [];
|
|
n.forEach(function (n, s) {
|
|
o.push.apply(o, _toConsumableArray(_this6._findMatches({
|
|
key: n,
|
|
value: t[s],
|
|
searcher: e
|
|
})));
|
|
}), o.length && r.push({
|
|
idx: i,
|
|
item: t,
|
|
matches: o
|
|
});
|
|
}), r;
|
|
}
|
|
}, {
|
|
key: "_findMatches",
|
|
value: function _findMatches(_ref13) {
|
|
var e = _ref13.key,
|
|
n = _ref13.value,
|
|
i = _ref13.searcher;
|
|
if (!s(n)) return [];
|
|
var r = [];
|
|
if (t(n)) n.forEach(function (_ref14) {
|
|
var t = _ref14.v,
|
|
n = _ref14.i,
|
|
o = _ref14.n;
|
|
if (!s(t)) return;
|
|
|
|
var _i$searchIn = i.searchIn(t),
|
|
c = _i$searchIn.isMatch,
|
|
h = _i$searchIn.score,
|
|
a = _i$searchIn.indices;
|
|
|
|
c && r.push({
|
|
score: h,
|
|
key: e,
|
|
value: t,
|
|
idx: n,
|
|
norm: o,
|
|
indices: a
|
|
});
|
|
});else {
|
|
var _t10 = n.v,
|
|
_s7 = n.n,
|
|
_i$searchIn2 = i.searchIn(_t10),
|
|
_o5 = _i$searchIn2.isMatch,
|
|
_c4 = _i$searchIn2.score,
|
|
_h2 = _i$searchIn2.indices;
|
|
|
|
_o5 && r.push({
|
|
score: _c4,
|
|
key: e,
|
|
value: _t10,
|
|
norm: _s7,
|
|
indices: _h2
|
|
});
|
|
}
|
|
return r;
|
|
}
|
|
}]);
|
|
|
|
return k;
|
|
}();
|
|
|
|
k.version = "6.3.1", k.createIndex = f, k.parseIndex = function (t) {
|
|
var _ref15 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
_ref15$getFn = _ref15.getFn,
|
|
e = _ref15$getFn === void 0 ? l.getFn : _ref15$getFn;
|
|
|
|
var n = t.keys,
|
|
s = t.records,
|
|
i = new u({
|
|
getFn: e
|
|
});
|
|
return i.setKeys(n), i.setIndexRecords(s), i;
|
|
}, k.config = l;
|
|
/* harmony default export */ __webpack_exports__["default"] = (k);
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/headroom.js/dist/headroom.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/headroom.js/dist/headroom.js ***!
|
|
\***************************************************/
|
|
/*! no static exports found */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
|
|
|
/*!
|
|
* headroom.js v0.10.3 - Give your page some headroom. Hide your header until you need it
|
|
* Copyright (c) 2019 Nick Williams - http://wicky.nillia.ms/headroom.js
|
|
* License: MIT
|
|
*/
|
|
(function (global, factory) {
|
|
( false ? undefined : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory() : true ? !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
|
(__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) :
|
|
__WEBPACK_AMD_DEFINE_FACTORY__),
|
|
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) : (undefined);
|
|
})(this, function () {
|
|
'use strict';
|
|
|
|
function isBrowser() {
|
|
return typeof window !== "undefined";
|
|
}
|
|
/**
|
|
* Used to detect browser support for adding an event listener with options
|
|
* Credit: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
|
|
*/
|
|
|
|
|
|
function passiveEventsSupported() {
|
|
var supported = false;
|
|
|
|
try {
|
|
var options = {
|
|
// eslint-disable-next-line getter-return
|
|
get passive() {
|
|
supported = true;
|
|
}
|
|
|
|
};
|
|
window.addEventListener("test", options, options);
|
|
window.removeEventListener("test", options, options);
|
|
} catch (err) {
|
|
supported = false;
|
|
}
|
|
|
|
return supported;
|
|
}
|
|
|
|
function isSupported() {
|
|
return !!(isBrowser() && function () {}.bind && "classList" in document.documentElement && Object.assign && Object.keys && requestAnimationFrame);
|
|
}
|
|
|
|
function isDocument(obj) {
|
|
return obj.nodeType === 9; // Node.DOCUMENT_NODE === 9
|
|
}
|
|
|
|
function isWindow(obj) {
|
|
// `obj === window` or `obj instanceof Window` is not sufficient,
|
|
// as the obj may be the window of an iframe.
|
|
return obj && obj.document && isDocument(obj.document);
|
|
}
|
|
|
|
function windowScroller(win) {
|
|
var doc = win.document;
|
|
var body = doc.body;
|
|
var html = doc.documentElement;
|
|
return {
|
|
/**
|
|
* @see http://james.padolsey.com/javascript/get-document-height-cross-browser/
|
|
* @return {Number} the scroll height of the document in pixels
|
|
*/
|
|
scrollHeight: function scrollHeight() {
|
|
return Math.max(body.scrollHeight, html.scrollHeight, body.offsetHeight, html.offsetHeight, body.clientHeight, html.clientHeight);
|
|
},
|
|
|
|
/**
|
|
* @see http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript
|
|
* @return {Number} the height of the viewport in pixels
|
|
*/
|
|
height: function height() {
|
|
return win.innerHeight || html.clientHeight || body.clientHeight;
|
|
},
|
|
|
|
/**
|
|
* Gets the Y scroll position
|
|
* @return {Number} pixels the page has scrolled along the Y-axis
|
|
*/
|
|
scrollY: function scrollY() {
|
|
if (win.pageYOffset !== undefined) {
|
|
return win.pageYOffset;
|
|
}
|
|
|
|
return (html || body.parentNode || body).scrollTop;
|
|
}
|
|
};
|
|
}
|
|
|
|
function elementScroller(element) {
|
|
return {
|
|
/**
|
|
* @return {Number} the scroll height of the element in pixels
|
|
*/
|
|
scrollHeight: function scrollHeight() {
|
|
return Math.max(element.scrollHeight, element.offsetHeight, element.clientHeight);
|
|
},
|
|
|
|
/**
|
|
* @return {Number} the height of the element in pixels
|
|
*/
|
|
height: function height() {
|
|
return Math.max(element.offsetHeight, element.clientHeight);
|
|
},
|
|
|
|
/**
|
|
* Gets the Y scroll position
|
|
* @return {Number} pixels the element has scrolled along the Y-axis
|
|
*/
|
|
scrollY: function scrollY() {
|
|
return element.scrollTop;
|
|
}
|
|
};
|
|
}
|
|
|
|
function createScroller(element) {
|
|
return isWindow(element) ? windowScroller(element) : elementScroller(element);
|
|
}
|
|
/**
|
|
* @param element EventTarget
|
|
*/
|
|
|
|
|
|
function trackScroll(element, options, callback) {
|
|
var isPassiveSupported = passiveEventsSupported();
|
|
var rafId;
|
|
var scrolled = false;
|
|
var scroller = createScroller(element);
|
|
var lastScrollY = scroller.scrollY();
|
|
var details = {};
|
|
|
|
function update() {
|
|
var scrollY = Math.round(scroller.scrollY());
|
|
var height = scroller.height();
|
|
var scrollHeight = scroller.scrollHeight(); // reuse object for less memory churn
|
|
|
|
details.scrollY = scrollY;
|
|
details.lastScrollY = lastScrollY;
|
|
details.direction = scrollY > lastScrollY ? "down" : "up";
|
|
details.distance = Math.abs(scrollY - lastScrollY);
|
|
details.isOutOfBounds = scrollY < 0 || scrollY + height > scrollHeight;
|
|
details.top = scrollY <= options.offset;
|
|
details.bottom = scrollY + height >= scrollHeight;
|
|
details.toleranceExceeded = details.distance > options.tolerance[details.direction];
|
|
callback(details);
|
|
lastScrollY = scrollY;
|
|
scrolled = false;
|
|
}
|
|
|
|
function handleScroll() {
|
|
if (!scrolled) {
|
|
scrolled = true;
|
|
rafId = requestAnimationFrame(update);
|
|
}
|
|
}
|
|
|
|
var eventOptions = isPassiveSupported ? {
|
|
passive: true,
|
|
capture: false
|
|
} : false;
|
|
element.addEventListener("scroll", handleScroll, eventOptions);
|
|
return {
|
|
destroy: function destroy() {
|
|
cancelAnimationFrame(rafId);
|
|
element.removeEventListener("scroll", handleScroll, eventOptions);
|
|
}
|
|
};
|
|
}
|
|
|
|
function normalizeTolerance(t) {
|
|
return t === Object(t) ? t : {
|
|
down: t,
|
|
up: t
|
|
};
|
|
}
|
|
/**
|
|
* UI enhancement for fixed headers.
|
|
* Hides header when scrolling down
|
|
* Shows header when scrolling up
|
|
* @constructor
|
|
* @param {DOMElement} elem the header element
|
|
* @param {Object} options options for the widget
|
|
*/
|
|
|
|
|
|
function Headroom(elem, options) {
|
|
options = options || {};
|
|
Object.assign(this, Headroom.options, options);
|
|
this.classes = Object.assign({}, Headroom.options.classes, options.classes);
|
|
this.elem = elem;
|
|
this.tolerance = normalizeTolerance(this.tolerance);
|
|
this.initialised = false;
|
|
this.frozen = false;
|
|
}
|
|
|
|
Headroom.prototype = {
|
|
constructor: Headroom,
|
|
|
|
/**
|
|
* Start listening to scrolling
|
|
* @public
|
|
*/
|
|
init: function init() {
|
|
if (Headroom.cutsTheMustard && !this.initialised) {
|
|
this.addClass("initial");
|
|
this.initialised = true; // defer event registration to handle browser
|
|
// potentially restoring previous scroll position
|
|
|
|
setTimeout(function (self) {
|
|
self.scrollTracker = trackScroll(self.scroller, {
|
|
offset: self.offset,
|
|
tolerance: self.tolerance
|
|
}, self.update.bind(self));
|
|
}, 100, this);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Destroy the widget, clearing up after itself
|
|
* @public
|
|
*/
|
|
destroy: function destroy() {
|
|
this.initialised = false;
|
|
Object.keys(this.classes).forEach(this.removeClass, this);
|
|
this.scrollTracker.destroy();
|
|
},
|
|
|
|
/**
|
|
* Unpin the element
|
|
* @public
|
|
*/
|
|
unpin: function unpin() {
|
|
if (this.hasClass("pinned") || !this.hasClass("unpinned")) {
|
|
this.addClass("unpinned");
|
|
this.removeClass("pinned");
|
|
|
|
if (this.onUnpin) {
|
|
this.onUnpin.call(this);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Pin the element
|
|
* @public
|
|
*/
|
|
pin: function pin() {
|
|
if (this.hasClass("unpinned")) {
|
|
this.addClass("pinned");
|
|
this.removeClass("unpinned");
|
|
|
|
if (this.onPin) {
|
|
this.onPin.call(this);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Freezes the current state of the widget
|
|
* @public
|
|
*/
|
|
freeze: function freeze() {
|
|
this.frozen = true;
|
|
this.addClass("frozen");
|
|
},
|
|
|
|
/**
|
|
* Re-enables the default behaviour of the widget
|
|
* @public
|
|
*/
|
|
unfreeze: function unfreeze() {
|
|
this.frozen = false;
|
|
this.removeClass("frozen");
|
|
},
|
|
top: function top() {
|
|
if (!this.hasClass("top")) {
|
|
this.addClass("top");
|
|
this.removeClass("notTop");
|
|
|
|
if (this.onTop) {
|
|
this.onTop.call(this);
|
|
}
|
|
}
|
|
},
|
|
notTop: function notTop() {
|
|
if (!this.hasClass("notTop")) {
|
|
this.addClass("notTop");
|
|
this.removeClass("top");
|
|
|
|
if (this.onNotTop) {
|
|
this.onNotTop.call(this);
|
|
}
|
|
}
|
|
},
|
|
bottom: function bottom() {
|
|
if (!this.hasClass("bottom")) {
|
|
this.addClass("bottom");
|
|
this.removeClass("notBottom");
|
|
|
|
if (this.onBottom) {
|
|
this.onBottom.call(this);
|
|
}
|
|
}
|
|
},
|
|
notBottom: function notBottom() {
|
|
if (!this.hasClass("notBottom")) {
|
|
this.addClass("notBottom");
|
|
this.removeClass("bottom");
|
|
|
|
if (this.onNotBottom) {
|
|
this.onNotBottom.call(this);
|
|
}
|
|
}
|
|
},
|
|
shouldUnpin: function shouldUnpin(details) {
|
|
var scrollingDown = details.direction === "down";
|
|
return scrollingDown && !details.top && details.toleranceExceeded;
|
|
},
|
|
shouldPin: function shouldPin(details) {
|
|
var scrollingUp = details.direction === "up";
|
|
return scrollingUp && details.toleranceExceeded || details.top;
|
|
},
|
|
addClass: function addClass(className) {
|
|
this.elem.classList.add(this.classes[className]);
|
|
},
|
|
removeClass: function removeClass(className) {
|
|
this.elem.classList.remove(this.classes[className]);
|
|
},
|
|
hasClass: function hasClass(className) {
|
|
return this.elem.classList.contains(this.classes[className]);
|
|
},
|
|
update: function update(details) {
|
|
if (details.isOutOfBounds) {
|
|
// Ignore bouncy scrolling in OSX
|
|
return;
|
|
}
|
|
|
|
if (this.frozen === true) {
|
|
return;
|
|
}
|
|
|
|
if (details.top) {
|
|
this.top();
|
|
} else {
|
|
this.notTop();
|
|
}
|
|
|
|
if (details.bottom) {
|
|
this.bottom();
|
|
} else {
|
|
this.notBottom();
|
|
}
|
|
|
|
if (this.shouldUnpin(details)) {
|
|
this.unpin();
|
|
} else if (this.shouldPin(details)) {
|
|
this.pin();
|
|
}
|
|
}
|
|
};
|
|
/**
|
|
* Default options
|
|
* @type {Object}
|
|
*/
|
|
|
|
Headroom.options = {
|
|
tolerance: {
|
|
up: 0,
|
|
down: 0
|
|
},
|
|
offset: 0,
|
|
scroller: isBrowser() ? window : null,
|
|
classes: {
|
|
frozen: "headroom--frozen",
|
|
pinned: "headroom--pinned",
|
|
unpinned: "headroom--unpinned",
|
|
top: "headroom--top",
|
|
notTop: "headroom--not-top",
|
|
bottom: "headroom--bottom",
|
|
notBottom: "headroom--not-bottom",
|
|
initial: "headroom"
|
|
}
|
|
};
|
|
Headroom.cutsTheMustard = isSupported();
|
|
return Headroom;
|
|
});
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/jquery/dist/jquery.js":
|
|
/*!********************************************!*\
|
|
!*** ./node_modules/jquery/dist/jquery.js ***!
|
|
\********************************************/
|
|
/*! no static exports found */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* WEBPACK VAR INJECTION */(function(module) {var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
|
|
|
/*!
|
|
* jQuery JavaScript Library v3.4.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: 2019-05-01T21:04Z
|
|
*/
|
|
(function (global, factory) {
|
|
"use strict";
|
|
|
|
if (( false ? undefined : _typeof(module)) === "object" && _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 document = window.document;
|
|
var getProto = Object.getPrototypeOf;
|
|
var _slice = arr.slice;
|
|
var concat = arr.concat;
|
|
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 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.4.1",
|
|
// Define a local copy of jQuery
|
|
jQuery = function jQuery(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);
|
|
},
|
|
// Support: Android <=4.0 only
|
|
// Make sure we trim BOM and NBSP
|
|
rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
|
|
|
|
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 toArray() {
|
|
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 get(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 pushStack(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 each(callback) {
|
|
return jQuery.each(this, callback);
|
|
},
|
|
map: function map(callback) {
|
|
return this.pushStack(jQuery.map(this, function (elem, i) {
|
|
return callback.call(elem, i, elem);
|
|
}));
|
|
},
|
|
slice: function slice() {
|
|
return this.pushStack(_slice.apply(this, arguments));
|
|
},
|
|
first: function first() {
|
|
return this.eq(0);
|
|
},
|
|
last: function last() {
|
|
return this.eq(-1);
|
|
},
|
|
eq: function eq(i) {
|
|
var len = this.length,
|
|
j = +i + (i < 0 ? len : 0);
|
|
return this.pushStack(j >= 0 && j < len ? [this[j]] : []);
|
|
},
|
|
end: function end() {
|
|
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 error(msg) {
|
|
throw new Error(msg);
|
|
},
|
|
noop: function noop() {},
|
|
isPlainObject: function isPlainObject(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 isEmptyObject(obj) {
|
|
var name;
|
|
|
|
for (name in obj) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
},
|
|
// Evaluates a script in a global context
|
|
globalEval: function globalEval(code, options) {
|
|
DOMEval(code, {
|
|
nonce: options && options.nonce
|
|
});
|
|
},
|
|
each: function each(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;
|
|
},
|
|
// Support: Android <=4.0 only
|
|
trim: function trim(text) {
|
|
return text == null ? "" : (text + "").replace(rtrim, "");
|
|
},
|
|
// results is for internal usage only
|
|
makeArray: function makeArray(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 inArray(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 merge(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 grep(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 map(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 concat.apply([], 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.4
|
|
* https://sizzlejs.com/
|
|
*
|
|
* Copyright JS Foundation and other contributors
|
|
* Released under the MIT license
|
|
* https://js.foundation/
|
|
*
|
|
* Date: 2019-04-08
|
|
*/
|
|
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 sortOrder(a, b) {
|
|
if (a === b) {
|
|
hasDuplicate = true;
|
|
}
|
|
|
|
return 0;
|
|
},
|
|
// Instance methods
|
|
hasOwn = {}.hasOwnProperty,
|
|
arr = [],
|
|
pop = arr.pop,
|
|
push_native = 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 indexOf(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]",
|
|
// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
|
|
identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
|
|
// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
|
|
attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + // Operator (capture 2)
|
|
"*([*^$|!~]?=)" + whitespace + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
|
|
"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]",
|
|
pseudos = ":(" + identifier + ")(?:\\((" + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
|
|
// 1. quoted (capture 3; capture 4 or capture 5)
|
|
"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + // 2. simple (capture 6)
|
|
"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + // 3. anything else (capture 2)
|
|
".*" + ")\\)|)",
|
|
// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
|
|
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-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig"),
|
|
funescape = function funescape(_, escaped, escapedWhitespace) {
|
|
var high = "0x" + escaped - 0x10000; // NaN means non-codepoint
|
|
// Support: Firefox<24
|
|
// Workaround erroneous numeric interpretation of +"0x"
|
|
|
|
return high !== high || escapedWhitespace ? escaped : high < 0 ? // BMP codepoint
|
|
String.fromCharCode(high + 0x10000) : // Supplemental Plane codepoint (surrogate pair)
|
|
String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00);
|
|
},
|
|
// 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 fcssescape(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 unloadHandler() {
|
|
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
|
|
|
|
arr[preferredDoc.childNodes.length].nodeType;
|
|
} catch (e) {
|
|
push = {
|
|
apply: arr.length ? // Leverage slice if possible
|
|
function (target, els) {
|
|
push_native.apply(target, slice.call(els));
|
|
} : // Support: IE<9
|
|
// Otherwise append directly
|
|
function (target, els) {
|
|
var j = target.length,
|
|
i = 0; // Can't trust NodeList.length
|
|
|
|
while (target[j++] = els[i++]) {}
|
|
|
|
target.length = j - 1;
|
|
}
|
|
};
|
|
}
|
|
|
|
function Sizzle(selector, context, results, seed) {
|
|
var 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) {
|
|
if ((context ? context.ownerDocument || context : preferredDoc) !== document) {
|
|
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.
|
|
// Thanks to Andrew Dupont for this technique.
|
|
|
|
if (nodeType === 1 && rdescend.test(selector)) {
|
|
// 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 + " " + toSelector(groups[i]);
|
|
}
|
|
|
|
newSelector = groups.join(","); // Expand context for sibling selectors
|
|
|
|
newContext = rsibling.test(selector) && testContext(context.parentNode) || context;
|
|
}
|
|
|
|
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
|
|
|
|
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
|
|
// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
|
|
|
|
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);
|
|
}
|
|
}
|
|
/* 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) {
|
|
// 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("~=");
|
|
} // 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(".#.+[+~]");
|
|
}
|
|
});
|
|
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");
|
|
} // 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
|
|
|
|
|
|
compare = (a.ownerDocument || a) === (b.ownerDocument || b) ? a.compareDocumentPosition(b) : // Otherwise we know they are disconnected
|
|
1; // Disconnected nodes
|
|
|
|
if (compare & 1 || !support.sortDetached && b.compareDocumentPosition(a) === compare) {
|
|
// Choose the first element that is related to our preferred document
|
|
if (a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a)) {
|
|
return -1;
|
|
}
|
|
|
|
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) {
|
|
return a === document ? -1 : b === document ? 1 : 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
|
|
ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0;
|
|
};
|
|
return document;
|
|
};
|
|
|
|
Sizzle.matches = function (expr, elements) {
|
|
return Sizzle(expr, null, null, elements);
|
|
};
|
|
|
|
Sizzle.matchesSelector = function (elem, expr) {
|
|
// Set document vars if needed
|
|
if ((elem.ownerDocument || elem) !== document) {
|
|
setDocument(elem);
|
|
}
|
|
|
|
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
|
|
if ((context.ownerDocument || context) !== document) {
|
|
setDocument(context);
|
|
}
|
|
|
|
return contains(context, elem);
|
|
};
|
|
|
|
Sizzle.attr = function (elem, name) {
|
|
// Set document vars if needed
|
|
if ((elem.ownerDocument || elem) !== document) {
|
|
setDocument(elem);
|
|
}
|
|
|
|
var fn = Expr.attrHandle[name.toLowerCase()],
|
|
// Don't get fooled by Object.prototype properties (jQuery #13807)
|
|
val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? fn(elem, name, !documentIsHTML) : undefined;
|
|
return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute(name) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null;
|
|
};
|
|
|
|
Sizzle.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 ATTR(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 CHILD(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 PSEUDO(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 TAG(nodeNameSelector) {
|
|
var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase();
|
|
return nodeNameSelector === "*" ? function () {
|
|
return true;
|
|
} : function (elem) {
|
|
return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
|
|
};
|
|
},
|
|
"CLASS": function CLASS(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 ATTR(name, operator, check) {
|
|
return function (elem) {
|
|
var result = Sizzle.attr(elem, name);
|
|
|
|
if (result == null) {
|
|
return operator === "!=";
|
|
}
|
|
|
|
if (!operator) {
|
|
return true;
|
|
}
|
|
|
|
result += "";
|
|
return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf(check) === 0 : operator === "*=" ? check && result.indexOf(check) > -1 : operator === "$=" ? check && result.slice(-check.length) === check : operator === "~=" ? (" " + result.replace(rwhitespace, " ") + " ").indexOf(check) > -1 : operator === "|=" ? result === check || result.slice(0, check.length + 1) === check + "-" : false;
|
|
};
|
|
},
|
|
"CHILD": function CHILD(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(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 target(elem) {
|
|
var hash = window.location && window.location.hash;
|
|
return hash && hash.slice(1) === elem.id;
|
|
},
|
|
"root": function root(elem) {
|
|
return elem === docElem;
|
|
},
|
|
"focus": function focus(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 checked(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 selected(elem) {
|
|
// Accessing this property makes selected-by-default
|
|
// options in Safari work properly
|
|
if (elem.parentNode) {
|
|
elem.parentNode.selectedIndex;
|
|
}
|
|
|
|
return elem.selected === true;
|
|
},
|
|
// Contents
|
|
"empty": function empty(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 parent(elem) {
|
|
return !Expr.pseudos["empty"](elem);
|
|
},
|
|
// Element/input types
|
|
"header": function header(elem) {
|
|
return rheader.test(elem.nodeName);
|
|
},
|
|
"input": function input(elem) {
|
|
return rinputs.test(elem.nodeName);
|
|
},
|
|
"button": function button(elem) {
|
|
var name = elem.nodeName.toLowerCase();
|
|
return name === "input" && elem.type === "button" || name === "button";
|
|
},
|
|
"text": function text(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 superMatcher(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) {
|
|
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;
|
|
|
|
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 dir(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 siblings(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 find(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 filter(selector) {
|
|
return this.pushStack(winnow(this, selector || [], false));
|
|
},
|
|
not: function not(selector) {
|
|
return this.pushStack(winnow(this, selector || [], true));
|
|
},
|
|
is: function is(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 has(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 closest(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 index(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 add(selector, context) {
|
|
return this.pushStack(jQuery.uniqueSort(jQuery.merge(this.get(), jQuery(selector, context))));
|
|
},
|
|
addBack: function addBack(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 parent(elem) {
|
|
var parent = elem.parentNode;
|
|
return parent && parent.nodeType !== 11 ? parent : null;
|
|
},
|
|
parents: function parents(elem) {
|
|
return dir(elem, "parentNode");
|
|
},
|
|
parentsUntil: function parentsUntil(elem, i, until) {
|
|
return dir(elem, "parentNode", until);
|
|
},
|
|
next: function next(elem) {
|
|
return sibling(elem, "nextSibling");
|
|
},
|
|
prev: function prev(elem) {
|
|
return sibling(elem, "previousSibling");
|
|
},
|
|
nextAll: function nextAll(elem) {
|
|
return dir(elem, "nextSibling");
|
|
},
|
|
prevAll: function prevAll(elem) {
|
|
return dir(elem, "previousSibling");
|
|
},
|
|
nextUntil: function nextUntil(elem, i, until) {
|
|
return dir(elem, "nextSibling", until);
|
|
},
|
|
prevUntil: function prevUntil(elem, i, until) {
|
|
return dir(elem, "previousSibling", until);
|
|
},
|
|
siblings: function siblings(elem) {
|
|
return _siblings((elem.parentNode || {}).firstChild, elem);
|
|
},
|
|
children: function children(elem) {
|
|
return _siblings(elem.firstChild);
|
|
},
|
|
contents: function contents(elem) {
|
|
if (typeof elem.contentDocument !== "undefined") {
|
|
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 fire() {
|
|
// 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 add() {
|
|
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 remove() {
|
|
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 has(fn) {
|
|
return fn ? jQuery.inArray(fn, list) > -1 : list.length > 0;
|
|
},
|
|
// Remove all callbacks from the list
|
|
empty: function empty() {
|
|
if (list) {
|
|
list = [];
|
|
}
|
|
|
|
return this;
|
|
},
|
|
// Disable .fire and .add
|
|
// Abort any current/pending executions
|
|
// Clear all callbacks and values
|
|
disable: function disable() {
|
|
_locked = queue = [];
|
|
list = memory = "";
|
|
return this;
|
|
},
|
|
disabled: function disabled() {
|
|
return !list;
|
|
},
|
|
// Disable .fire
|
|
// Also disable .add unless we have memory (since it would have no effect)
|
|
// Abort any pending executions
|
|
lock: function lock() {
|
|
_locked = queue = [];
|
|
|
|
if (!memory && !firing) {
|
|
list = memory = "";
|
|
}
|
|
|
|
return this;
|
|
},
|
|
locked: function locked() {
|
|
return !!_locked;
|
|
},
|
|
// Call all callbacks with the given context and arguments
|
|
fireWith: function fireWith(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 fire() {
|
|
self.fireWith(this, arguments);
|
|
return this;
|
|
},
|
|
// To know if the callbacks have already been called at least once
|
|
fired: function fired() {
|
|
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 Deferred(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 state() {
|
|
return _state;
|
|
},
|
|
always: function always() {
|
|
deferred.done(arguments).fail(arguments);
|
|
return this;
|
|
},
|
|
"catch": function _catch(fn) {
|
|
return _promise.then(null, fn);
|
|
},
|
|
// Keep pipe for back-compat
|
|
pipe: function pipe()
|
|
/* 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 then(onFulfilled, onRejected, onProgress) {
|
|
var maxDepth = 0;
|
|
|
|
function resolve(depth, deferred, handler, special) {
|
|
return function () {
|
|
var that = this,
|
|
args = arguments,
|
|
mightThrow = function mightThrow() {
|
|
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 promise(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 when(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 updateFunc(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 ready(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 access(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 fn(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 acceptData(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 cache(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 set(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 get(owner, key) {
|
|
return key === undefined ? this.cache(owner) : // Always use camelCase key (gh-2257)
|
|
owner[this.expando] && owner[this.expando][camelCase(key)];
|
|
},
|
|
access: function access(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 remove(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 hasData(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 hasData(elem) {
|
|
return dataUser.hasData(elem) || dataPriv.hasData(elem);
|
|
},
|
|
data: function data(elem, name, _data) {
|
|
return dataUser.access(elem, name, _data);
|
|
},
|
|
removeData: function removeData(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 _data(elem, name, data) {
|
|
return dataPriv.access(elem, name, data);
|
|
},
|
|
_removeData: function _removeData(elem, name) {
|
|
dataPriv.remove(elem, name);
|
|
}
|
|
});
|
|
jQuery.fn.extend({
|
|
data: function data(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 removeData(key) {
|
|
return this.each(function () {
|
|
dataUser.remove(this, key);
|
|
});
|
|
}
|
|
});
|
|
jQuery.extend({
|
|
queue: function queue(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 dequeue(elem, type) {
|
|
type = type || "fx";
|
|
|
|
var queue = jQuery.queue(elem, type),
|
|
startLength = queue.length,
|
|
fn = queue.shift(),
|
|
hooks = jQuery._queueHooks(elem, type),
|
|
next = function next() {
|
|
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 _queueHooks(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 queue(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 dequeue(type) {
|
|
return this.each(function () {
|
|
jQuery.dequeue(this, type);
|
|
});
|
|
},
|
|
clearQueue: function clearQueue(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 promise(type, obj) {
|
|
var tmp,
|
|
count = 1,
|
|
defer = jQuery.Deferred(),
|
|
elements = this,
|
|
i = this.length,
|
|
resolve = function resolve() {
|
|
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 isAttached(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 isAttached(elem) {
|
|
return jQuery.contains(elem.ownerDocument, elem) || elem.getRootNode(composed) === elem.ownerDocument;
|
|
};
|
|
}
|
|
|
|
var isHiddenWithinTree = function isHiddenWithinTree(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";
|
|
};
|
|
|
|
var swap = function swap(elem, options, callback, args) {
|
|
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.apply(elem, args || []); // Revert the old values
|
|
|
|
for (name in options) {
|
|
elem.style[name] = old[name];
|
|
}
|
|
|
|
return ret;
|
|
};
|
|
|
|
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 show() {
|
|
return showHide(this, true);
|
|
},
|
|
hide: function hide() {
|
|
return showHide(this);
|
|
},
|
|
toggle: function toggle(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; // We have to close these tags to support XHTML (#13200)
|
|
|
|
var wrapMap = {
|
|
// Support: IE <=9 only
|
|
option: [1, "<select multiple='multiple'>", "</select>"],
|
|
// 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, "", ""]
|
|
}; // Support: IE <=9 only
|
|
|
|
wrapMap.optgroup = wrapMap.option;
|
|
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
|
|
wrapMap.th = wrapMap.td;
|
|
|
|
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;
|
|
}
|
|
|
|
(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;
|
|
})();
|
|
|
|
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 fn(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 add(elem, types, handler, data, selector) {
|
|
var handleObjIn,
|
|
eventHandle,
|
|
tmp,
|
|
events,
|
|
t,
|
|
handleObj,
|
|
special,
|
|
handlers,
|
|
type,
|
|
namespaces,
|
|
origType,
|
|
elemData = dataPriv.get(elem); // Don't attach events to noData or text/comment nodes (but allow plain objects)
|
|
|
|
if (!elemData) {
|
|
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 = {};
|
|
}
|
|
|
|
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 remove(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 dispatch(nativeEvent) {
|
|
// Make a writable jQuery.Event from the native event object
|
|
var event = jQuery.event.fix(nativeEvent);
|
|
var i,
|
|
j,
|
|
ret,
|
|
matched,
|
|
handleObj,
|
|
handlerQueue,
|
|
args = new Array(arguments.length),
|
|
handlers = (dataPriv.get(this, "events") || {})[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 handlers(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 addProp(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 set(value) {
|
|
Object.defineProperty(this, name, {
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true,
|
|
value: value
|
|
});
|
|
}
|
|
});
|
|
},
|
|
fix: function fix(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 setup(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 trigger(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 _default(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 postDispatch(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 handler(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 preventDefault() {
|
|
var e = this.originalEvent;
|
|
this.isDefaultPrevented = returnTrue;
|
|
|
|
if (e && !this.isSimulated) {
|
|
e.preventDefault();
|
|
}
|
|
},
|
|
stopPropagation: function stopPropagation() {
|
|
var e = this.originalEvent;
|
|
this.isPropagationStopped = returnTrue;
|
|
|
|
if (e && !this.isSimulated) {
|
|
e.stopPropagation();
|
|
}
|
|
},
|
|
stopImmediatePropagation: function stopImmediatePropagation() {
|
|
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 which(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 setup() {
|
|
// 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 trigger() {
|
|
// 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 handle(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 on(types, selector, data, fn) {
|
|
return _on(this, types, selector, data, fn);
|
|
},
|
|
one: function one(types, selector, data, fn) {
|
|
return _on(this, types, selector, data, fn, 1);
|
|
},
|
|
off: function off(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
|
|
/* eslint-disable max-len */
|
|
// See https://github.com/eslint/eslint/issues/3229
|
|
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
|
|
|
|
/* eslint-enable */
|
|
// 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, pdataCur, udataOld, udataCur, events;
|
|
|
|
if (dest.nodeType !== 1) {
|
|
return;
|
|
} // 1. Copy private data: events, handlers, etc.
|
|
|
|
|
|
if (dataPriv.hasData(src)) {
|
|
pdataOld = dataPriv.access(src);
|
|
pdataCur = dataPriv.set(dest, pdataOld);
|
|
events = pdataOld.events;
|
|
|
|
if (events) {
|
|
delete pdataCur.handle;
|
|
pdataCur.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 = concat.apply([], 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")
|
|
});
|
|
}
|
|
} 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 htmlPrefilter(html) {
|
|
return html.replace(rxhtmlTag, "<$1></$2>");
|
|
},
|
|
clone: function clone(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 cleanData(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 detach(selector) {
|
|
return _remove(this, selector, true);
|
|
},
|
|
remove: function remove(selector) {
|
|
return _remove(this, selector);
|
|
},
|
|
text: function text(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 append() {
|
|
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 prepend() {
|
|
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 before() {
|
|
return domManip(this, arguments, function (elem) {
|
|
if (this.parentNode) {
|
|
this.parentNode.insertBefore(elem, this);
|
|
}
|
|
});
|
|
},
|
|
after: function after() {
|
|
return domManip(this, arguments, function (elem) {
|
|
if (this.parentNode) {
|
|
this.parentNode.insertBefore(elem, this.nextSibling);
|
|
}
|
|
});
|
|
},
|
|
empty: function empty() {
|
|
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 clone(dataAndEvents, deepDataAndEvents) {
|
|
dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
|
|
deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
|
|
return this.map(function () {
|
|
return jQuery.clone(this, dataAndEvents, deepDataAndEvents);
|
|
});
|
|
},
|
|
html: function html(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 replaceWith() {
|
|
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 getStyles(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 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,
|
|
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 boxSizingReliable() {
|
|
computeStyleTests();
|
|
return boxSizingReliableVal;
|
|
},
|
|
pixelBoxStyles: function pixelBoxStyles() {
|
|
computeStyleTests();
|
|
return pixelBoxStylesVal;
|
|
},
|
|
pixelPosition: function pixelPosition() {
|
|
computeStyleTests();
|
|
return pixelPositionVal;
|
|
},
|
|
reliableMarginLeft: function reliableMarginLeft() {
|
|
computeStyleTests();
|
|
return reliableMarginLeftVal;
|
|
},
|
|
scrollboxSize: function scrollboxSize() {
|
|
computeStyleTests();
|
|
return scrollboxSizeVal;
|
|
}
|
|
});
|
|
})();
|
|
|
|
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 get() {
|
|
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";
|
|
} // Fall back to offsetWidth/offsetHeight when value is "auto"
|
|
// This happens for inline elements with no explicit setting (gh-3571)
|
|
// Support: Android <=4.1 - 4.3 only
|
|
// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)
|
|
// Support: IE 9-11 only
|
|
// Also use offsetWidth/offsetHeight for when box sizing is unreliable
|
|
// We use getClientRects() to check for hidden/disconnected.
|
|
// In those cases, the computed value can be trusted to be border-box
|
|
|
|
|
|
if ((!support.boxSizingReliable() && isBorderBox || val === "auto" || !parseFloat(val) && jQuery.css(elem, "display", false, styles) === "inline") && 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 get(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 style(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 css(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 get(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 set(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 expand(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 css(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 init(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 cur() {
|
|
var hooks = Tween.propHooks[this.prop];
|
|
return hooks && hooks.get ? hooks.get(this) : Tween.propHooks._default.get(this);
|
|
},
|
|
run: function run(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 get(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 set(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 set(tween) {
|
|
if (tween.elem.nodeType && tween.elem.parentNode) {
|
|
tween.elem[tween.prop] = tween.now;
|
|
}
|
|
}
|
|
};
|
|
jQuery.easing = {
|
|
linear: function linear(p) {
|
|
return p;
|
|
},
|
|
swing: function swing(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 tick() {
|
|
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 createTween(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 stop(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 tweener(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 prefilter(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 fadeTo(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 animate(prop, speed, easing, callback) {
|
|
var empty = jQuery.isEmptyObject(prop),
|
|
optall = jQuery.speed(speed, easing, callback),
|
|
doAnimation = function doAnimation() {
|
|
// 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 stop(type, clearQueue, gotoEnd) {
|
|
var stopQueue = function stopQueue(hooks) {
|
|
var stop = hooks.stop;
|
|
delete hooks.stop;
|
|
stop(gotoEnd);
|
|
};
|
|
|
|
if (typeof type !== "string") {
|
|
gotoEnd = clearQueue;
|
|
clearQueue = type;
|
|
type = undefined;
|
|
}
|
|
|
|
if (clearQueue && type !== false) {
|
|
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 finish(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 attr(name, value) {
|
|
return access(this, jQuery.attr, name, value, arguments.length > 1);
|
|
},
|
|
removeAttr: function removeAttr(name) {
|
|
return this.each(function () {
|
|
jQuery.removeAttr(this, name);
|
|
});
|
|
}
|
|
});
|
|
jQuery.extend({
|
|
attr: function attr(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 set(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 removeAttr(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 set(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 prop(name, value) {
|
|
return access(this, jQuery.prop, name, value, arguments.length > 1);
|
|
},
|
|
removeProp: function removeProp(name) {
|
|
return this.each(function () {
|
|
delete this[jQuery.propFix[name] || name];
|
|
});
|
|
}
|
|
});
|
|
jQuery.extend({
|
|
prop: function prop(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 get(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 get(elem) {
|
|
/* eslint no-unused-expressions: "off" */
|
|
var parent = elem.parentNode;
|
|
|
|
if (parent && parent.parentNode) {
|
|
parent.parentNode.selectedIndex;
|
|
}
|
|
|
|
return null;
|
|
},
|
|
set: function set(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 addClass(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 removeClass(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 toggleClass(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 hasClass(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 val(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 get(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 get(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 set(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 set(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 stopPropagationCallback(e) {
|
|
e.stopPropagation();
|
|
};
|
|
|
|
jQuery.extend(jQuery.event, {
|
|
trigger: function trigger(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") || {})[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 simulate(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 trigger(type, data) {
|
|
return this.each(function () {
|
|
jQuery.event.trigger(type, data, this);
|
|
});
|
|
},
|
|
triggerHandler: function triggerHandler(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 handler(event) {
|
|
jQuery.event.simulate(fix, event.target, jQuery.event.fix(event));
|
|
};
|
|
|
|
jQuery.event.special[fix] = {
|
|
setup: function setup() {
|
|
var doc = this.ownerDocument || this,
|
|
attaches = dataPriv.access(doc, fix);
|
|
|
|
if (!attaches) {
|
|
doc.addEventListener(orig, handler, true);
|
|
}
|
|
|
|
dataPriv.access(doc, fix, (attaches || 0) + 1);
|
|
},
|
|
teardown: function teardown() {
|
|
var doc = this.ownerDocument || 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 = 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 add(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 serialize() {
|
|
return jQuery.param(this.serializeArray());
|
|
},
|
|
serializeArray: function serializeArray() {
|
|
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 ajaxSetup(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 ajax(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 getResponseHeader(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 getAllResponseHeaders() {
|
|
return completed ? responseHeadersString : null;
|
|
},
|
|
// Caches the header
|
|
setRequestHeader: function setRequestHeader(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 overrideMimeType(type) {
|
|
if (completed == null) {
|
|
s.mimeType = type;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
// Status-dependent callbacks
|
|
statusCode: function statusCode(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 abort(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++ + 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);
|
|
} // 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 getJSON(url, data, callback) {
|
|
return jQuery.get(url, data, callback, "json");
|
|
},
|
|
getScript: function getScript(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._evalUrl = function (url, options) {
|
|
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 textScript() {}
|
|
},
|
|
dataFilter: function dataFilter(response) {
|
|
jQuery.globalEval(response, options);
|
|
}
|
|
});
|
|
};
|
|
|
|
jQuery.fn.extend({
|
|
wrapAll: function wrapAll(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 wrapInner(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 wrap(html) {
|
|
var htmlIsFunction = isFunction(html);
|
|
return this.each(function (i) {
|
|
jQuery(this).wrapAll(htmlIsFunction ? html.call(this, i) : html);
|
|
});
|
|
},
|
|
unwrap: function unwrap(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 send(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 callback(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 abort() {
|
|
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 textScript(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, _callback2;
|
|
|
|
return {
|
|
send: function send(_, complete) {
|
|
script = jQuery("<script>").attr(s.scriptAttrs || {}).prop({
|
|
charset: s.scriptCharset,
|
|
src: s.url
|
|
}).on("load error", _callback2 = function callback(evt) {
|
|
script.remove();
|
|
_callback2 = 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 abort() {
|
|
if (_callback2) {
|
|
_callback2();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
});
|
|
var oldCallbacks = [],
|
|
rjsonp = /(=)\?(?=&|$)|\?\?/; // Default jsonp settings
|
|
|
|
jQuery.ajaxSetup({
|
|
jsonp: "callback",
|
|
jsonpCallback: function jsonpCallback() {
|
|
var callback = oldCallbacks.pop() || jQuery.expando + "_" + nonce++;
|
|
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;
|
|
}; // Attach a bunch of functions for handling common AJAX events
|
|
|
|
|
|
jQuery.each(["ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend"], function (i, type) {
|
|
jQuery.fn[type] = function (fn) {
|
|
return this.on(type, fn);
|
|
};
|
|
});
|
|
|
|
jQuery.expr.pseudos.animated = function (elem) {
|
|
return jQuery.grep(jQuery.timers, function (fn) {
|
|
return elem === fn.elem;
|
|
}).length;
|
|
};
|
|
|
|
jQuery.offset = {
|
|
setOffset: function setOffset(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 {
|
|
curElem.css(props);
|
|
}
|
|
}
|
|
};
|
|
jQuery.fn.extend({
|
|
// offset() relates an element's border box to the document origin
|
|
offset: function offset(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 position() {
|
|
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 offsetParent() {
|
|
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(("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);
|
|
};
|
|
});
|
|
jQuery.fn.extend({
|
|
hover: function hover(fnOver, fnOut) {
|
|
return this.mouseenter(fnOver).mouseleave(fnOut || fnOver);
|
|
}
|
|
});
|
|
jQuery.fn.extend({
|
|
bind: function bind(types, data, fn) {
|
|
return this.on(types, null, data, fn);
|
|
},
|
|
unbind: function unbind(types, fn) {
|
|
return this.off(types, null, fn);
|
|
},
|
|
delegate: function delegate(selector, types, data, fn) {
|
|
return this.on(types, selector, data, fn);
|
|
},
|
|
undelegate: function undelegate(selector, types, fn) {
|
|
// ( namespace ) or ( selector, types [, fn] )
|
|
return arguments.length === 1 ? this.off(selector, "**") : this.off(types, selector || "**", fn);
|
|
}
|
|
}); // 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 proxy() {
|
|
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));
|
|
}; // 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 (!noGlobal) {
|
|
window.jQuery = window.$ = jQuery;
|
|
}
|
|
|
|
return jQuery;
|
|
});
|
|
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../webpack/buildin/module.js */ "./node_modules/webpack/buildin/module.js")(module)))
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/medium-zoom/dist/medium-zoom.esm.js":
|
|
/*!**********************************************************!*\
|
|
!*** ./node_modules/medium-zoom/dist/medium-zoom.esm.js ***!
|
|
\**********************************************************/
|
|
/*! exports provided: default */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/*! medium-zoom 1.0.4 | MIT License | https://github.com/francoischalifour/medium-zoom */
|
|
var _extends = Object.assign || function (a) {
|
|
for (var b, c = 1; c < arguments.length; c++) {
|
|
for (var d in b = arguments[c], b) {
|
|
Object.prototype.hasOwnProperty.call(b, d) && (a[d] = b[d]);
|
|
}
|
|
}
|
|
|
|
return a;
|
|
},
|
|
isSupported = function isSupported(a) {
|
|
return 'IMG' === a.tagName;
|
|
},
|
|
isNodeList = function isNodeList(a) {
|
|
return NodeList.prototype.isPrototypeOf(a);
|
|
},
|
|
isNode = function isNode(a) {
|
|
return a && 1 === a.nodeType;
|
|
},
|
|
isSvg = function isSvg(a) {
|
|
var b = a.currentSrc || a.src;
|
|
return '.svg' === b.substr(-4).toLowerCase();
|
|
},
|
|
getImagesFromSelector = function getImagesFromSelector(a) {
|
|
try {
|
|
return Array.isArray(a) ? a.filter(isSupported) : isNodeList(a) ? [].slice.call(a).filter(isSupported) : isNode(a) ? [a].filter(isSupported) : 'string' == typeof a ? [].slice.call(document.querySelectorAll(a)).filter(isSupported) : [];
|
|
} catch (a) {
|
|
throw new TypeError('The provided selector is invalid.\nExpects a CSS selector, a Node element, a NodeList or an array.\nSee: https://github.com/francoischalifour/medium-zoom');
|
|
}
|
|
},
|
|
createOverlay = function createOverlay(a) {
|
|
var b = document.createElement('div');
|
|
return b.classList.add('medium-zoom-overlay'), b.style.background = a, b;
|
|
},
|
|
cloneTarget = function cloneTarget(a) {
|
|
var b = a.getBoundingClientRect(),
|
|
c = b.top,
|
|
d = b.left,
|
|
e = b.width,
|
|
f = b.height,
|
|
g = a.cloneNode(),
|
|
h = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0,
|
|
i = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
|
|
return g.removeAttribute('id'), g.style.position = 'absolute', g.style.top = c + h + 'px', g.style.left = d + i + 'px', g.style.width = e + 'px', g.style.height = f + 'px', g.style.transform = '', g;
|
|
},
|
|
createCustomEvent = function createCustomEvent(a, b) {
|
|
var c = _extends({
|
|
bubbles: !1,
|
|
cancelable: !1,
|
|
detail: void 0
|
|
}, b);
|
|
|
|
if ('function' == typeof window.CustomEvent) return new CustomEvent(a, c);
|
|
var d = document.createEvent('CustomEvent');
|
|
return d.initCustomEvent(a, c.bubbles, c.cancelable, c.detail), d;
|
|
},
|
|
mediumZoom = function a(b) {
|
|
var c = 1 < arguments.length && arguments[1] !== void 0 ? arguments[1] : {},
|
|
d = window.Promise || function (a) {
|
|
function b() {}
|
|
|
|
a(b, b);
|
|
},
|
|
e = function e(a) {
|
|
var b = a.target;
|
|
return b === x ? void n() : void (-1 === r.indexOf(b) || o({
|
|
target: b
|
|
}));
|
|
},
|
|
f = function f() {
|
|
if (!t && w.original) {
|
|
var a = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
|
|
Math.abs(u - a) > v.scrollOffset && setTimeout(n, 150);
|
|
}
|
|
},
|
|
g = function g() {
|
|
var a = 0 < arguments.length && void 0 !== arguments[0] ? arguments[0] : {},
|
|
b = a;
|
|
|
|
if (a.background && (x.style.background = a.background), a.container && a.container instanceof Object && (b.container = _extends({}, v.container, a.container)), a.template) {
|
|
var c = isNode(a.template) ? a.template : document.querySelector(a.template);
|
|
b.template = c;
|
|
}
|
|
|
|
return v = _extends({}, v, b), r.forEach(function (a) {
|
|
a.dispatchEvent(createCustomEvent('medium-zoom:update', {
|
|
detail: {
|
|
zoom: y
|
|
}
|
|
}));
|
|
}), y;
|
|
},
|
|
h = function h() {
|
|
var b = 0 < arguments.length && arguments[0] !== void 0 ? arguments[0] : {};
|
|
return a(_extends({}, v, b));
|
|
},
|
|
i = function i() {
|
|
for (var a = arguments.length, b = Array(a), c = 0; c < a; c++) {
|
|
b[c] = arguments[c];
|
|
}
|
|
|
|
var d = b.reduce(function (a, b) {
|
|
return [].concat(a, getImagesFromSelector(b));
|
|
}, []);
|
|
return d.filter(function (a) {
|
|
return -1 === r.indexOf(a);
|
|
}).forEach(function (a) {
|
|
r.push(a), a.classList.add('medium-zoom-image');
|
|
}), s.forEach(function (a) {
|
|
var b = a.type,
|
|
c = a.listener,
|
|
e = a.options;
|
|
d.forEach(function (a) {
|
|
a.addEventListener(b, c, e);
|
|
});
|
|
}), y;
|
|
},
|
|
j = function j() {
|
|
for (var a = arguments.length, b = Array(a), c = 0; c < a; c++) {
|
|
b[c] = arguments[c];
|
|
}
|
|
|
|
w.zoomed && n();
|
|
var d = 0 < b.length ? b.reduce(function (a, b) {
|
|
return [].concat(a, getImagesFromSelector(b));
|
|
}, []) : r;
|
|
return d.forEach(function (a) {
|
|
a.classList.remove('medium-zoom-image'), a.dispatchEvent(createCustomEvent('medium-zoom:detach', {
|
|
detail: {
|
|
zoom: y
|
|
}
|
|
}));
|
|
}), r = r.filter(function (a) {
|
|
return -1 === d.indexOf(a);
|
|
}), y;
|
|
},
|
|
k = function k(a, b) {
|
|
var c = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : {};
|
|
return r.forEach(function (d) {
|
|
d.addEventListener('medium-zoom:' + a, b, c);
|
|
}), s.push({
|
|
type: 'medium-zoom:' + a,
|
|
listener: b,
|
|
options: c
|
|
}), y;
|
|
},
|
|
l = function l(a, b) {
|
|
var c = 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : {};
|
|
return r.forEach(function (d) {
|
|
d.removeEventListener('medium-zoom:' + a, b, c);
|
|
}), s = s.filter(function (c) {
|
|
return c.type !== 'medium-zoom:' + a || c.listener.toString() !== b.toString();
|
|
}), y;
|
|
},
|
|
m = function m() {
|
|
var a = 0 < arguments.length && arguments[0] !== void 0 ? arguments[0] : {},
|
|
b = a.target,
|
|
c = function c() {
|
|
var a = Math.min,
|
|
b = {
|
|
width: document.documentElement.clientWidth,
|
|
height: document.documentElement.clientHeight,
|
|
left: 0,
|
|
top: 0,
|
|
right: 0,
|
|
bottom: 0
|
|
},
|
|
c = void 0,
|
|
d = void 0;
|
|
if (v.container) if (v.container instanceof Object) b = _extends({}, b, v.container), c = b.width - b.left - b.right - 2 * v.margin, d = b.height - b.top - b.bottom - 2 * v.margin;else {
|
|
var e = isNode(v.container) ? v.container : document.querySelector(v.container),
|
|
f = e.getBoundingClientRect(),
|
|
g = f.width,
|
|
h = f.height,
|
|
i = f.left,
|
|
j = f.top;
|
|
b = _extends({}, b, {
|
|
width: g,
|
|
height: h,
|
|
left: i,
|
|
top: j
|
|
});
|
|
}
|
|
c = c || b.width - 2 * v.margin, d = d || b.height - 2 * v.margin;
|
|
var k = w.zoomedHd || w.original,
|
|
l = isSvg(k) ? c : k.naturalWidth || c,
|
|
m = isSvg(k) ? d : k.naturalHeight || d,
|
|
n = k.getBoundingClientRect(),
|
|
o = n.top,
|
|
p = n.left,
|
|
q = n.width,
|
|
r = n.height,
|
|
s = a(l, c) / q,
|
|
t = a(m, d) / r,
|
|
u = a(s, t),
|
|
x = (-p + (c - q) / 2 + v.margin + b.left) / u,
|
|
y = (-o + (d - r) / 2 + v.margin + b.top) / u,
|
|
z = 'scale(' + u + ') translate3d(' + x + 'px, ' + y + 'px, 0)';
|
|
w.zoomed.style.transform = z, w.zoomedHd && (w.zoomedHd.style.transform = z);
|
|
};
|
|
|
|
return new d(function (a) {
|
|
if (b && -1 === r.indexOf(b)) return void a(y);
|
|
if (w.zoomed) return void a(y);
|
|
if (b) w.original = b;else if (0 < r.length) {
|
|
var d = r;
|
|
w.original = d[0];
|
|
} else return void a(y);
|
|
|
|
if (w.original.dispatchEvent(createCustomEvent('medium-zoom:open', {
|
|
detail: {
|
|
zoom: y
|
|
}
|
|
})), u = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0, t = !0, w.zoomed = cloneTarget(w.original), document.body.appendChild(x), v.template) {
|
|
var e = isNode(v.template) ? v.template : document.querySelector(v.template);
|
|
w.template = document.createElement('div'), w.template.appendChild(e.content.cloneNode(!0)), document.body.appendChild(w.template);
|
|
}
|
|
|
|
if (document.body.appendChild(w.zoomed), window.requestAnimationFrame(function () {
|
|
document.body.classList.add('medium-zoom--opened');
|
|
}), w.original.classList.add('medium-zoom-image--hidden'), w.zoomed.classList.add('medium-zoom-image--opened'), w.zoomed.addEventListener('click', n), w.zoomed.addEventListener('transitionend', function b() {
|
|
t = !1, w.zoomed.removeEventListener('transitionend', b), w.original.dispatchEvent(createCustomEvent('medium-zoom:opened', {
|
|
detail: {
|
|
zoom: y
|
|
}
|
|
})), a(y);
|
|
}), w.original.getAttribute('data-zoom-src')) {
|
|
w.zoomedHd = w.zoomed.cloneNode(), w.zoomedHd.removeAttribute('srcset'), w.zoomedHd.removeAttribute('sizes'), w.zoomedHd.src = w.zoomed.getAttribute('data-zoom-src'), w.zoomedHd.onerror = function () {
|
|
clearInterval(f), console.warn('Unable to reach the zoom image target ' + w.zoomedHd.src), w.zoomedHd = null, c();
|
|
};
|
|
var f = setInterval(function () {
|
|
w.zoomedHd.complete && (clearInterval(f), w.zoomedHd.classList.add('medium-zoom-image--opened'), w.zoomedHd.addEventListener('click', n), document.body.appendChild(w.zoomedHd), c());
|
|
}, 10);
|
|
} else if (w.original.hasAttribute('srcset')) {
|
|
w.zoomedHd = w.zoomed.cloneNode(), w.zoomedHd.removeAttribute('sizes');
|
|
var g = w.zoomedHd.addEventListener('load', function () {
|
|
w.zoomedHd.removeEventListener('load', g), w.zoomedHd.classList.add('medium-zoom-image--opened'), w.zoomedHd.addEventListener('click', n), document.body.appendChild(w.zoomedHd), c();
|
|
});
|
|
} else c();
|
|
});
|
|
},
|
|
n = function n() {
|
|
return new d(function (a) {
|
|
if (t || !w.original) return void a(y);
|
|
t = !0, document.body.classList.remove('medium-zoom--opened'), w.zoomed.style.transform = '', w.zoomedHd && (w.zoomedHd.style.transform = ''), w.template && (w.template.style.transition = 'opacity 150ms', w.template.style.opacity = 0), w.original.dispatchEvent(createCustomEvent('medium-zoom:close', {
|
|
detail: {
|
|
zoom: y
|
|
}
|
|
})), w.zoomed.addEventListener('transitionend', function b() {
|
|
w.original.classList.remove('medium-zoom-image--hidden'), document.body.removeChild(w.zoomed), w.zoomedHd && document.body.removeChild(w.zoomedHd), document.body.removeChild(x), w.zoomed.classList.remove('medium-zoom-image--opened'), w.template && document.body.removeChild(w.template), t = !1, w.zoomed.removeEventListener('transitionend', b), w.original.dispatchEvent(createCustomEvent('medium-zoom:closed', {
|
|
detail: {
|
|
zoom: y
|
|
}
|
|
})), w.original = null, w.zoomed = null, w.zoomedHd = null, w.template = null, a(y);
|
|
});
|
|
});
|
|
},
|
|
o = function o() {
|
|
var a = 0 < arguments.length && arguments[0] !== void 0 ? arguments[0] : {},
|
|
b = a.target;
|
|
return w.original ? n() : m({
|
|
target: b
|
|
});
|
|
},
|
|
p = function p() {
|
|
return v;
|
|
},
|
|
q = function q() {
|
|
return r;
|
|
},
|
|
r = [],
|
|
s = [],
|
|
t = !1,
|
|
u = 0,
|
|
v = c,
|
|
w = {
|
|
original: null,
|
|
zoomed: null,
|
|
zoomedHd: null,
|
|
template: null
|
|
};
|
|
|
|
'[object Object]' === Object.prototype.toString.call(b) ? v = b : (b || 'string' == typeof b) && i(b), v = _extends({
|
|
margin: 0,
|
|
background: '#fff',
|
|
scrollOffset: 40,
|
|
container: null,
|
|
template: null
|
|
}, v);
|
|
var x = createOverlay(v.background);
|
|
document.addEventListener('click', e), document.addEventListener('keyup', function (a) {
|
|
27 === (a.keyCode || a.which) && n();
|
|
}), document.addEventListener('scroll', f), window.addEventListener('resize', n);
|
|
var y = {
|
|
open: m,
|
|
close: n,
|
|
toggle: o,
|
|
update: g,
|
|
clone: h,
|
|
attach: i,
|
|
detach: j,
|
|
on: k,
|
|
off: l,
|
|
getOptions: p,
|
|
getImages: q,
|
|
getZoomedImage: function getZoomedImage() {
|
|
return w.original;
|
|
}
|
|
};
|
|
return y;
|
|
};
|
|
|
|
function styleInject(a, b) {
|
|
void 0 === b && (b = {});
|
|
var c = b.insertAt;
|
|
|
|
if (a && 'undefined' != typeof document) {
|
|
var d = document.head || document.getElementsByTagName('head')[0],
|
|
e = document.createElement('style');
|
|
e.type = 'text/css', 'top' === c ? d.firstChild ? d.insertBefore(e, d.firstChild) : d.appendChild(e) : d.appendChild(e), e.styleSheet ? e.styleSheet.cssText = a : e.appendChild(document.createTextNode(a));
|
|
}
|
|
}
|
|
|
|
var css = '.medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}';
|
|
styleInject('.medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}');
|
|
/* harmony default export */ __webpack_exports__["default"] = (mediumZoom);
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/popper.js/dist/esm/popper.js":
|
|
/*!***************************************************!*\
|
|
!*** ./node_modules/popper.js/dist/esm/popper.js ***!
|
|
\***************************************************/
|
|
/*! exports provided: default */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* WEBPACK VAR INJECTION */(function(global) {/**!
|
|
* @fileOverview Kickass library to create and place poppers near their reference elements.
|
|
* @version 1.15.0
|
|
* @license
|
|
* Copyright (c) 2016 Federico Zivolo and 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 isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
|
|
var timeoutDuration = 0;
|
|
|
|
for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
|
|
if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
|
|
timeoutDuration = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
function microtaskDebounce(fn) {
|
|
var called = false;
|
|
return function () {
|
|
if (called) {
|
|
return;
|
|
}
|
|
|
|
called = true;
|
|
window.Promise.resolve().then(function () {
|
|
called = false;
|
|
fn();
|
|
});
|
|
};
|
|
}
|
|
|
|
function taskDebounce(fn) {
|
|
var scheduled = false;
|
|
return function () {
|
|
if (!scheduled) {
|
|
scheduled = true;
|
|
setTimeout(function () {
|
|
scheduled = false;
|
|
fn();
|
|
}, timeoutDuration);
|
|
}
|
|
};
|
|
}
|
|
|
|
var supportsMicroTasks = isBrowser && window.Promise;
|
|
/**
|
|
* Create a debounced version of a method, that's asynchronously deferred
|
|
* but called in the minimum time possible.
|
|
*
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Function} fn
|
|
* @returns {Function}
|
|
*/
|
|
|
|
var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
|
|
/**
|
|
* Check if the given variable is a function
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Any} functionToCheck - variable to check
|
|
* @returns {Boolean} answer to: is a function?
|
|
*/
|
|
|
|
function isFunction(functionToCheck) {
|
|
var getType = {};
|
|
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
|
|
}
|
|
/**
|
|
* Get CSS computed property of the given element
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Eement} element
|
|
* @argument {String} property
|
|
*/
|
|
|
|
|
|
function getStyleComputedProperty(element, property) {
|
|
if (element.nodeType !== 1) {
|
|
return [];
|
|
} // NOTE: 1 DOM access here
|
|
|
|
|
|
var window = element.ownerDocument.defaultView;
|
|
var css = window.getComputedStyle(element, null);
|
|
return property ? css[property] : css;
|
|
}
|
|
/**
|
|
* Returns the parentNode or the host of the element
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Element} element
|
|
* @returns {Element} parent
|
|
*/
|
|
|
|
|
|
function getParentNode(element) {
|
|
if (element.nodeName === 'HTML') {
|
|
return element;
|
|
}
|
|
|
|
return element.parentNode || element.host;
|
|
}
|
|
/**
|
|
* Returns the scrolling parent of the given element
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Element} element
|
|
* @returns {Element} scroll parent
|
|
*/
|
|
|
|
|
|
function getScrollParent(element) {
|
|
// Return body, `getScroll` will take care to get the correct `scrollTop` from it
|
|
if (!element) {
|
|
return document.body;
|
|
}
|
|
|
|
switch (element.nodeName) {
|
|
case 'HTML':
|
|
case 'BODY':
|
|
return element.ownerDocument.body;
|
|
|
|
case '#document':
|
|
return element.body;
|
|
} // Firefox want us to check `-x` and `-y` variations as well
|
|
|
|
|
|
var _getStyleComputedProp = getStyleComputedProperty(element),
|
|
overflow = _getStyleComputedProp.overflow,
|
|
overflowX = _getStyleComputedProp.overflowX,
|
|
overflowY = _getStyleComputedProp.overflowY;
|
|
|
|
if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {
|
|
return element;
|
|
}
|
|
|
|
return getScrollParent(getParentNode(element));
|
|
}
|
|
|
|
var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);
|
|
var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);
|
|
/**
|
|
* Determines if the browser is Internet Explorer
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @param {Number} version to check
|
|
* @returns {Boolean} isIE
|
|
*/
|
|
|
|
function isIE(version) {
|
|
if (version === 11) {
|
|
return isIE11;
|
|
}
|
|
|
|
if (version === 10) {
|
|
return isIE10;
|
|
}
|
|
|
|
return isIE11 || isIE10;
|
|
}
|
|
/**
|
|
* Returns the offset parent of the given element
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Element} element
|
|
* @returns {Element} offset parent
|
|
*/
|
|
|
|
|
|
function getOffsetParent(element) {
|
|
if (!element) {
|
|
return document.documentElement;
|
|
}
|
|
|
|
var noOffsetParent = isIE(10) ? document.body : null; // NOTE: 1 DOM access here
|
|
|
|
var offsetParent = element.offsetParent || null; // Skip hidden elements which don't have an offsetParent
|
|
|
|
while (offsetParent === noOffsetParent && element.nextElementSibling) {
|
|
offsetParent = (element = element.nextElementSibling).offsetParent;
|
|
}
|
|
|
|
var nodeName = offsetParent && offsetParent.nodeName;
|
|
|
|
if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
|
|
return element ? element.ownerDocument.documentElement : document.documentElement;
|
|
} // .offsetParent will return the closest TH, TD or TABLE in case
|
|
// no offsetParent is present, I hate this job...
|
|
|
|
|
|
if (['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
|
|
return getOffsetParent(offsetParent);
|
|
}
|
|
|
|
return offsetParent;
|
|
}
|
|
|
|
function isOffsetContainer(element) {
|
|
var nodeName = element.nodeName;
|
|
|
|
if (nodeName === 'BODY') {
|
|
return false;
|
|
}
|
|
|
|
return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
|
|
}
|
|
/**
|
|
* Finds the root node (document, shadowDOM root) of the given element
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Element} node
|
|
* @returns {Element} root node
|
|
*/
|
|
|
|
|
|
function getRoot(node) {
|
|
if (node.parentNode !== null) {
|
|
return getRoot(node.parentNode);
|
|
}
|
|
|
|
return node;
|
|
}
|
|
/**
|
|
* Finds the offset parent common to the two provided nodes
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Element} element1
|
|
* @argument {Element} element2
|
|
* @returns {Element} common offset parent
|
|
*/
|
|
|
|
|
|
function findCommonOffsetParent(element1, element2) {
|
|
// This check is needed to avoid errors in case one of the elements isn't defined for any reason
|
|
if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
|
|
return document.documentElement;
|
|
} // Here we make sure to give as "start" the element that comes first in the DOM
|
|
|
|
|
|
var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
|
|
var start = order ? element1 : element2;
|
|
var end = order ? element2 : element1; // Get common ancestor container
|
|
|
|
var range = document.createRange();
|
|
range.setStart(start, 0);
|
|
range.setEnd(end, 0);
|
|
var commonAncestorContainer = range.commonAncestorContainer; // Both nodes are inside #document
|
|
|
|
if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
|
|
if (isOffsetContainer(commonAncestorContainer)) {
|
|
return commonAncestorContainer;
|
|
}
|
|
|
|
return getOffsetParent(commonAncestorContainer);
|
|
} // one of the nodes is inside shadowDOM, find which one
|
|
|
|
|
|
var element1root = getRoot(element1);
|
|
|
|
if (element1root.host) {
|
|
return findCommonOffsetParent(element1root.host, element2);
|
|
} else {
|
|
return findCommonOffsetParent(element1, getRoot(element2).host);
|
|
}
|
|
}
|
|
/**
|
|
* Gets the scroll value of the given element in the given side (top and left)
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Element} element
|
|
* @argument {String} side `top` or `left`
|
|
* @returns {number} amount of scrolled pixels
|
|
*/
|
|
|
|
|
|
function getScroll(element) {
|
|
var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
|
|
var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
|
|
var nodeName = element.nodeName;
|
|
|
|
if (nodeName === 'BODY' || nodeName === 'HTML') {
|
|
var html = element.ownerDocument.documentElement;
|
|
var scrollingElement = element.ownerDocument.scrollingElement || html;
|
|
return scrollingElement[upperSide];
|
|
}
|
|
|
|
return element[upperSide];
|
|
}
|
|
/*
|
|
* Sum or subtract the element scroll values (left and top) from a given rect object
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @param {Object} rect - Rect object you want to change
|
|
* @param {HTMLElement} element - The element from the function reads the scroll values
|
|
* @param {Boolean} subtract - set to true if you want to subtract the scroll values
|
|
* @return {Object} rect - The modifier rect object
|
|
*/
|
|
|
|
|
|
function includeScroll(rect, element) {
|
|
var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
var scrollTop = getScroll(element, 'top');
|
|
var scrollLeft = getScroll(element, 'left');
|
|
var modifier = subtract ? -1 : 1;
|
|
rect.top += scrollTop * modifier;
|
|
rect.bottom += scrollTop * modifier;
|
|
rect.left += scrollLeft * modifier;
|
|
rect.right += scrollLeft * modifier;
|
|
return rect;
|
|
}
|
|
/*
|
|
* Helper to detect borders of a given element
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @param {CSSStyleDeclaration} styles
|
|
* Result of `getStyleComputedProperty` on the given element
|
|
* @param {String} axis - `x` or `y`
|
|
* @return {number} borders - The borders size of the given axis
|
|
*/
|
|
|
|
|
|
function getBordersSize(styles, axis) {
|
|
var sideA = axis === 'x' ? 'Left' : 'Top';
|
|
var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
|
|
return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
|
|
}
|
|
|
|
function getSize(axis, body, html, computedStyle) {
|
|
return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? parseInt(html['offset' + axis]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')]) + parseInt(computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')]) : 0);
|
|
}
|
|
|
|
function getWindowSizes(document) {
|
|
var body = document.body;
|
|
var html = document.documentElement;
|
|
var computedStyle = isIE(10) && getComputedStyle(html);
|
|
return {
|
|
height: getSize('Height', body, html, computedStyle),
|
|
width: getSize('Width', body, html, computedStyle)
|
|
};
|
|
}
|
|
|
|
var classCallCheck = function classCallCheck(instance, Constructor) {
|
|
if (!(instance instanceof Constructor)) {
|
|
throw new TypeError("Cannot call a class as a function");
|
|
}
|
|
};
|
|
|
|
var createClass = function () {
|
|
function defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
if ("value" in descriptor) descriptor.writable = true;
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
|
|
return function (Constructor, protoProps, staticProps) {
|
|
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
|
if (staticProps) defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
};
|
|
}();
|
|
|
|
var defineProperty = function defineProperty(obj, key, value) {
|
|
if (key in obj) {
|
|
Object.defineProperty(obj, key, {
|
|
value: value,
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true
|
|
});
|
|
} else {
|
|
obj[key] = value;
|
|
}
|
|
|
|
return obj;
|
|
};
|
|
|
|
var _extends = Object.assign || function (target) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
var source = arguments[i];
|
|
|
|
for (var key in source) {
|
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
target[key] = source[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
return target;
|
|
};
|
|
/**
|
|
* Given element offsets, generate an output similar to getBoundingClientRect
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Object} offsets
|
|
* @returns {Object} ClientRect like output
|
|
*/
|
|
|
|
|
|
function getClientRect(offsets) {
|
|
return _extends({}, offsets, {
|
|
right: offsets.left + offsets.width,
|
|
bottom: offsets.top + offsets.height
|
|
});
|
|
}
|
|
/**
|
|
* Get bounding client rect of given element
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @param {HTMLElement} element
|
|
* @return {Object} client rect
|
|
*/
|
|
|
|
|
|
function getBoundingClientRect(element) {
|
|
var rect = {}; // IE10 10 FIX: Please, don't ask, the element isn't
|
|
// considered in DOM in some circumstances...
|
|
// This isn't reproducible in IE10 compatibility mode of IE11
|
|
|
|
try {
|
|
if (isIE(10)) {
|
|
rect = element.getBoundingClientRect();
|
|
var scrollTop = getScroll(element, 'top');
|
|
var scrollLeft = getScroll(element, 'left');
|
|
rect.top += scrollTop;
|
|
rect.left += scrollLeft;
|
|
rect.bottom += scrollTop;
|
|
rect.right += scrollLeft;
|
|
} else {
|
|
rect = element.getBoundingClientRect();
|
|
}
|
|
} catch (e) {}
|
|
|
|
var result = {
|
|
left: rect.left,
|
|
top: rect.top,
|
|
width: rect.right - rect.left,
|
|
height: rect.bottom - rect.top
|
|
}; // subtract scrollbar size from sizes
|
|
|
|
var sizes = element.nodeName === 'HTML' ? getWindowSizes(element.ownerDocument) : {};
|
|
var width = sizes.width || element.clientWidth || result.right - result.left;
|
|
var height = sizes.height || element.clientHeight || result.bottom - result.top;
|
|
var horizScrollbar = element.offsetWidth - width;
|
|
var vertScrollbar = element.offsetHeight - height; // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
|
|
// we make this check conditional for performance reasons
|
|
|
|
if (horizScrollbar || vertScrollbar) {
|
|
var styles = getStyleComputedProperty(element);
|
|
horizScrollbar -= getBordersSize(styles, 'x');
|
|
vertScrollbar -= getBordersSize(styles, 'y');
|
|
result.width -= horizScrollbar;
|
|
result.height -= vertScrollbar;
|
|
}
|
|
|
|
return getClientRect(result);
|
|
}
|
|
|
|
function getOffsetRectRelativeToArbitraryNode(children, parent) {
|
|
var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
var isIE10 = isIE(10);
|
|
var isHTML = parent.nodeName === 'HTML';
|
|
var childrenRect = getBoundingClientRect(children);
|
|
var parentRect = getBoundingClientRect(parent);
|
|
var scrollParent = getScrollParent(children);
|
|
var styles = getStyleComputedProperty(parent);
|
|
var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
|
|
var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10); // In cases where the parent is fixed, we must ignore negative scroll in offset calc
|
|
|
|
if (fixedPosition && isHTML) {
|
|
parentRect.top = Math.max(parentRect.top, 0);
|
|
parentRect.left = Math.max(parentRect.left, 0);
|
|
}
|
|
|
|
var offsets = getClientRect({
|
|
top: childrenRect.top - parentRect.top - borderTopWidth,
|
|
left: childrenRect.left - parentRect.left - borderLeftWidth,
|
|
width: childrenRect.width,
|
|
height: childrenRect.height
|
|
});
|
|
offsets.marginTop = 0;
|
|
offsets.marginLeft = 0; // Subtract margins of documentElement in case it's being used as parent
|
|
// we do this only on HTML because it's the only element that behaves
|
|
// differently when margins are applied to it. The margins are included in
|
|
// the box of the documentElement, in the other cases not.
|
|
|
|
if (!isIE10 && isHTML) {
|
|
var marginTop = parseFloat(styles.marginTop, 10);
|
|
var marginLeft = parseFloat(styles.marginLeft, 10);
|
|
offsets.top -= borderTopWidth - marginTop;
|
|
offsets.bottom -= borderTopWidth - marginTop;
|
|
offsets.left -= borderLeftWidth - marginLeft;
|
|
offsets.right -= borderLeftWidth - marginLeft; // Attach marginTop and marginLeft because in some circumstances we may need them
|
|
|
|
offsets.marginTop = marginTop;
|
|
offsets.marginLeft = marginLeft;
|
|
}
|
|
|
|
if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
|
|
offsets = includeScroll(offsets, parent);
|
|
}
|
|
|
|
return offsets;
|
|
}
|
|
|
|
function getViewportOffsetRectRelativeToArtbitraryNode(element) {
|
|
var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
var html = element.ownerDocument.documentElement;
|
|
var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
|
|
var width = Math.max(html.clientWidth, window.innerWidth || 0);
|
|
var height = Math.max(html.clientHeight, window.innerHeight || 0);
|
|
var scrollTop = !excludeScroll ? getScroll(html) : 0;
|
|
var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;
|
|
var offset = {
|
|
top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
|
|
left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
|
|
width: width,
|
|
height: height
|
|
};
|
|
return getClientRect(offset);
|
|
}
|
|
/**
|
|
* Check if the given element is fixed or is inside a fixed parent
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Element} element
|
|
* @argument {Element} customContainer
|
|
* @returns {Boolean} answer to "isFixed?"
|
|
*/
|
|
|
|
|
|
function isFixed(element) {
|
|
var nodeName = element.nodeName;
|
|
|
|
if (nodeName === 'BODY' || nodeName === 'HTML') {
|
|
return false;
|
|
}
|
|
|
|
if (getStyleComputedProperty(element, 'position') === 'fixed') {
|
|
return true;
|
|
}
|
|
|
|
var parentNode = getParentNode(element);
|
|
|
|
if (!parentNode) {
|
|
return false;
|
|
}
|
|
|
|
return isFixed(parentNode);
|
|
}
|
|
/**
|
|
* Finds the first parent of an element that has a transformed property defined
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Element} element
|
|
* @returns {Element} first transformed parent or documentElement
|
|
*/
|
|
|
|
|
|
function getFixedPositionOffsetParent(element) {
|
|
// This check is needed to avoid errors in case one of the elements isn't defined for any reason
|
|
if (!element || !element.parentElement || isIE()) {
|
|
return document.documentElement;
|
|
}
|
|
|
|
var el = element.parentElement;
|
|
|
|
while (el && getStyleComputedProperty(el, 'transform') === 'none') {
|
|
el = el.parentElement;
|
|
}
|
|
|
|
return el || document.documentElement;
|
|
}
|
|
/**
|
|
* Computed the boundaries limits and return them
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @param {HTMLElement} popper
|
|
* @param {HTMLElement} reference
|
|
* @param {number} padding
|
|
* @param {HTMLElement} boundariesElement - Element used to define the boundaries
|
|
* @param {Boolean} fixedPosition - Is in fixed position mode
|
|
* @returns {Object} Coordinates of the boundaries
|
|
*/
|
|
|
|
|
|
function getBoundaries(popper, reference, padding, boundariesElement) {
|
|
var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; // NOTE: 1 DOM access here
|
|
|
|
var boundaries = {
|
|
top: 0,
|
|
left: 0
|
|
};
|
|
var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference); // Handle viewport case
|
|
|
|
if (boundariesElement === 'viewport') {
|
|
boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);
|
|
} else {
|
|
// Handle other cases based on DOM element used as boundaries
|
|
var boundariesNode = void 0;
|
|
|
|
if (boundariesElement === 'scrollParent') {
|
|
boundariesNode = getScrollParent(getParentNode(reference));
|
|
|
|
if (boundariesNode.nodeName === 'BODY') {
|
|
boundariesNode = popper.ownerDocument.documentElement;
|
|
}
|
|
} else if (boundariesElement === 'window') {
|
|
boundariesNode = popper.ownerDocument.documentElement;
|
|
} else {
|
|
boundariesNode = boundariesElement;
|
|
}
|
|
|
|
var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition); // In case of HTML, we need a different computation
|
|
|
|
if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
|
|
var _getWindowSizes = getWindowSizes(popper.ownerDocument),
|
|
height = _getWindowSizes.height,
|
|
width = _getWindowSizes.width;
|
|
|
|
boundaries.top += offsets.top - offsets.marginTop;
|
|
boundaries.bottom = height + offsets.top;
|
|
boundaries.left += offsets.left - offsets.marginLeft;
|
|
boundaries.right = width + offsets.left;
|
|
} else {
|
|
// for all the other DOM elements, this one is good
|
|
boundaries = offsets;
|
|
}
|
|
} // Add paddings
|
|
|
|
|
|
padding = padding || 0;
|
|
var isPaddingNumber = typeof padding === 'number';
|
|
boundaries.left += isPaddingNumber ? padding : padding.left || 0;
|
|
boundaries.top += isPaddingNumber ? padding : padding.top || 0;
|
|
boundaries.right -= isPaddingNumber ? padding : padding.right || 0;
|
|
boundaries.bottom -= isPaddingNumber ? padding : padding.bottom || 0;
|
|
return boundaries;
|
|
}
|
|
|
|
function getArea(_ref) {
|
|
var width = _ref.width,
|
|
height = _ref.height;
|
|
return width * height;
|
|
}
|
|
/**
|
|
* Utility used to transform the `auto` placement to the placement with more
|
|
* available space.
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Object} data - The data object generated by update method
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @returns {Object} The data object, properly modified
|
|
*/
|
|
|
|
|
|
function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
|
|
var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
|
|
|
|
if (placement.indexOf('auto') === -1) {
|
|
return placement;
|
|
}
|
|
|
|
var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
|
|
var rects = {
|
|
top: {
|
|
width: boundaries.width,
|
|
height: refRect.top - boundaries.top
|
|
},
|
|
right: {
|
|
width: boundaries.right - refRect.right,
|
|
height: boundaries.height
|
|
},
|
|
bottom: {
|
|
width: boundaries.width,
|
|
height: boundaries.bottom - refRect.bottom
|
|
},
|
|
left: {
|
|
width: refRect.left - boundaries.left,
|
|
height: boundaries.height
|
|
}
|
|
};
|
|
var sortedAreas = Object.keys(rects).map(function (key) {
|
|
return _extends({
|
|
key: key
|
|
}, rects[key], {
|
|
area: getArea(rects[key])
|
|
});
|
|
}).sort(function (a, b) {
|
|
return b.area - a.area;
|
|
});
|
|
var filteredAreas = sortedAreas.filter(function (_ref2) {
|
|
var width = _ref2.width,
|
|
height = _ref2.height;
|
|
return width >= popper.clientWidth && height >= popper.clientHeight;
|
|
});
|
|
var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
|
|
var variation = placement.split('-')[1];
|
|
return computedPlacement + (variation ? '-' + variation : '');
|
|
}
|
|
/**
|
|
* Get offsets to the reference element
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @param {Object} state
|
|
* @param {Element} popper - the popper element
|
|
* @param {Element} reference - the reference element (the popper will be relative to this)
|
|
* @param {Element} fixedPosition - is in fixed position mode
|
|
* @returns {Object} An object containing the offsets which will be applied to the popper
|
|
*/
|
|
|
|
|
|
function getReferenceOffsets(state, popper, reference) {
|
|
var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
|
|
var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);
|
|
return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);
|
|
}
|
|
/**
|
|
* Get the outer sizes of the given element (offset size + margins)
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Element} element
|
|
* @returns {Object} object containing width and height properties
|
|
*/
|
|
|
|
|
|
function getOuterSizes(element) {
|
|
var window = element.ownerDocument.defaultView;
|
|
var styles = window.getComputedStyle(element);
|
|
var x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0);
|
|
var y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0);
|
|
var result = {
|
|
width: element.offsetWidth + y,
|
|
height: element.offsetHeight + x
|
|
};
|
|
return result;
|
|
}
|
|
/**
|
|
* Get the opposite placement of the given one
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {String} placement
|
|
* @returns {String} flipped placement
|
|
*/
|
|
|
|
|
|
function getOppositePlacement(placement) {
|
|
var hash = {
|
|
left: 'right',
|
|
right: 'left',
|
|
bottom: 'top',
|
|
top: 'bottom'
|
|
};
|
|
return placement.replace(/left|right|bottom|top/g, function (matched) {
|
|
return hash[matched];
|
|
});
|
|
}
|
|
/**
|
|
* Get offsets to the popper
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @param {Object} position - CSS position the Popper will get applied
|
|
* @param {HTMLElement} popper - the popper element
|
|
* @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
|
|
* @param {String} placement - one of the valid placement options
|
|
* @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
|
|
*/
|
|
|
|
|
|
function getPopperOffsets(popper, referenceOffsets, placement) {
|
|
placement = placement.split('-')[0]; // Get popper node sizes
|
|
|
|
var popperRect = getOuterSizes(popper); // Add position, width and height to our offsets object
|
|
|
|
var popperOffsets = {
|
|
width: popperRect.width,
|
|
height: popperRect.height
|
|
}; // depending by the popper placement we have to compute its offsets slightly differently
|
|
|
|
var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
|
|
var mainSide = isHoriz ? 'top' : 'left';
|
|
var secondarySide = isHoriz ? 'left' : 'top';
|
|
var measurement = isHoriz ? 'height' : 'width';
|
|
var secondaryMeasurement = !isHoriz ? 'height' : 'width';
|
|
popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
|
|
|
|
if (placement === secondarySide) {
|
|
popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
|
|
} else {
|
|
popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
|
|
}
|
|
|
|
return popperOffsets;
|
|
}
|
|
/**
|
|
* Mimics the `find` method of Array
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Array} arr
|
|
* @argument prop
|
|
* @argument value
|
|
* @returns index or -1
|
|
*/
|
|
|
|
|
|
function find(arr, check) {
|
|
// use native find if supported
|
|
if (Array.prototype.find) {
|
|
return arr.find(check);
|
|
} // use `filter` to obtain the same behavior of `find`
|
|
|
|
|
|
return arr.filter(check)[0];
|
|
}
|
|
/**
|
|
* Return the index of the matching object
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Array} arr
|
|
* @argument prop
|
|
* @argument value
|
|
* @returns index or -1
|
|
*/
|
|
|
|
|
|
function findIndex(arr, prop, value) {
|
|
// use native findIndex if supported
|
|
if (Array.prototype.findIndex) {
|
|
return arr.findIndex(function (cur) {
|
|
return cur[prop] === value;
|
|
});
|
|
} // use `find` + `indexOf` if `findIndex` isn't supported
|
|
|
|
|
|
var match = find(arr, function (obj) {
|
|
return obj[prop] === value;
|
|
});
|
|
return arr.indexOf(match);
|
|
}
|
|
/**
|
|
* Loop trough the list of modifiers and run them in order,
|
|
* each of them will then edit the data object.
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @param {dataObject} data
|
|
* @param {Array} modifiers
|
|
* @param {String} ends - Optional modifier name used as stopper
|
|
* @returns {dataObject}
|
|
*/
|
|
|
|
|
|
function runModifiers(modifiers, data, ends) {
|
|
var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
|
|
modifiersToRun.forEach(function (modifier) {
|
|
if (modifier['function']) {
|
|
// eslint-disable-line dot-notation
|
|
console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
|
|
}
|
|
|
|
var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
|
|
|
|
if (modifier.enabled && isFunction(fn)) {
|
|
// Add properties to offsets to make them a complete clientRect object
|
|
// we do this before each modifier to make sure the previous one doesn't
|
|
// mess with these values
|
|
data.offsets.popper = getClientRect(data.offsets.popper);
|
|
data.offsets.reference = getClientRect(data.offsets.reference);
|
|
data = fn(data, modifier);
|
|
}
|
|
});
|
|
return data;
|
|
}
|
|
/**
|
|
* Updates the position of the popper, computing the new offsets and applying
|
|
* the new style.<br />
|
|
* Prefer `scheduleUpdate` over `update` because of performance reasons.
|
|
* @method
|
|
* @memberof Popper
|
|
*/
|
|
|
|
|
|
function update() {
|
|
// if popper is destroyed, don't perform any further update
|
|
if (this.state.isDestroyed) {
|
|
return;
|
|
}
|
|
|
|
var data = {
|
|
instance: this,
|
|
styles: {},
|
|
arrowStyles: {},
|
|
attributes: {},
|
|
flipped: false,
|
|
offsets: {}
|
|
}; // compute reference element offsets
|
|
|
|
data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed); // compute auto placement, store placement inside the data object,
|
|
// modifiers will be able to edit `placement` if needed
|
|
// and refer to originalPlacement to know the original value
|
|
|
|
data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding); // store the computed placement inside `originalPlacement`
|
|
|
|
data.originalPlacement = data.placement;
|
|
data.positionFixed = this.options.positionFixed; // compute the popper offsets
|
|
|
|
data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
|
|
data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute'; // run the modifiers
|
|
|
|
data = runModifiers(this.modifiers, data); // the first `update` will call `onCreate` callback
|
|
// the other ones will call `onUpdate` callback
|
|
|
|
if (!this.state.isCreated) {
|
|
this.state.isCreated = true;
|
|
this.options.onCreate(data);
|
|
} else {
|
|
this.options.onUpdate(data);
|
|
}
|
|
}
|
|
/**
|
|
* Helper used to know if the given modifier is enabled.
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @returns {Boolean}
|
|
*/
|
|
|
|
|
|
function isModifierEnabled(modifiers, modifierName) {
|
|
return modifiers.some(function (_ref) {
|
|
var name = _ref.name,
|
|
enabled = _ref.enabled;
|
|
return enabled && name === modifierName;
|
|
});
|
|
}
|
|
/**
|
|
* Get the prefixed supported property name
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {String} property (camelCase)
|
|
* @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
|
|
*/
|
|
|
|
|
|
function getSupportedPropertyName(property) {
|
|
var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
|
|
var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
|
|
|
|
for (var i = 0; i < prefixes.length; i++) {
|
|
var prefix = prefixes[i];
|
|
var toCheck = prefix ? '' + prefix + upperProp : property;
|
|
|
|
if (typeof document.body.style[toCheck] !== 'undefined') {
|
|
return toCheck;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
/**
|
|
* Destroys the popper.
|
|
* @method
|
|
* @memberof Popper
|
|
*/
|
|
|
|
|
|
function destroy() {
|
|
this.state.isDestroyed = true; // touch DOM only if `applyStyle` modifier is enabled
|
|
|
|
if (isModifierEnabled(this.modifiers, 'applyStyle')) {
|
|
this.popper.removeAttribute('x-placement');
|
|
this.popper.style.position = '';
|
|
this.popper.style.top = '';
|
|
this.popper.style.left = '';
|
|
this.popper.style.right = '';
|
|
this.popper.style.bottom = '';
|
|
this.popper.style.willChange = '';
|
|
this.popper.style[getSupportedPropertyName('transform')] = '';
|
|
}
|
|
|
|
this.disableEventListeners(); // remove the popper if user explicity asked for the deletion on destroy
|
|
// do not use `remove` because IE11 doesn't support it
|
|
|
|
if (this.options.removeOnDestroy) {
|
|
this.popper.parentNode.removeChild(this.popper);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
/**
|
|
* Get the window associated with the element
|
|
* @argument {Element} element
|
|
* @returns {Window}
|
|
*/
|
|
|
|
|
|
function getWindow(element) {
|
|
var ownerDocument = element.ownerDocument;
|
|
return ownerDocument ? ownerDocument.defaultView : window;
|
|
}
|
|
|
|
function attachToScrollParents(scrollParent, event, callback, scrollParents) {
|
|
var isBody = scrollParent.nodeName === 'BODY';
|
|
var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
|
|
target.addEventListener(event, callback, {
|
|
passive: true
|
|
});
|
|
|
|
if (!isBody) {
|
|
attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
|
|
}
|
|
|
|
scrollParents.push(target);
|
|
}
|
|
/**
|
|
* Setup needed event listeners used to update the popper position
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @private
|
|
*/
|
|
|
|
|
|
function setupEventListeners(reference, options, state, updateBound) {
|
|
// Resize event listener on window
|
|
state.updateBound = updateBound;
|
|
getWindow(reference).addEventListener('resize', state.updateBound, {
|
|
passive: true
|
|
}); // Scroll event listener on scroll parents
|
|
|
|
var scrollElement = getScrollParent(reference);
|
|
attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
|
|
state.scrollElement = scrollElement;
|
|
state.eventsEnabled = true;
|
|
return state;
|
|
}
|
|
/**
|
|
* It will add resize/scroll events and start recalculating
|
|
* position of the popper element when they are triggered.
|
|
* @method
|
|
* @memberof Popper
|
|
*/
|
|
|
|
|
|
function enableEventListeners() {
|
|
if (!this.state.eventsEnabled) {
|
|
this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
|
|
}
|
|
}
|
|
/**
|
|
* Remove event listeners used to update the popper position
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @private
|
|
*/
|
|
|
|
|
|
function removeEventListeners(reference, state) {
|
|
// Remove resize event listener on window
|
|
getWindow(reference).removeEventListener('resize', state.updateBound); // Remove scroll event listener on scroll parents
|
|
|
|
state.scrollParents.forEach(function (target) {
|
|
target.removeEventListener('scroll', state.updateBound);
|
|
}); // Reset state
|
|
|
|
state.updateBound = null;
|
|
state.scrollParents = [];
|
|
state.scrollElement = null;
|
|
state.eventsEnabled = false;
|
|
return state;
|
|
}
|
|
/**
|
|
* It will remove resize/scroll events and won't recalculate popper position
|
|
* when they are triggered. It also won't trigger `onUpdate` callback anymore,
|
|
* unless you call `update` method manually.
|
|
* @method
|
|
* @memberof Popper
|
|
*/
|
|
|
|
|
|
function disableEventListeners() {
|
|
if (this.state.eventsEnabled) {
|
|
cancelAnimationFrame(this.scheduleUpdate);
|
|
this.state = removeEventListeners(this.reference, this.state);
|
|
}
|
|
}
|
|
/**
|
|
* Tells if a given input is a number
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @param {*} input to check
|
|
* @return {Boolean}
|
|
*/
|
|
|
|
|
|
function isNumeric(n) {
|
|
return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
|
|
}
|
|
/**
|
|
* Set the style to the given popper
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Element} element - Element to apply the style to
|
|
* @argument {Object} styles
|
|
* Object with a list of properties and values which will be applied to the element
|
|
*/
|
|
|
|
|
|
function setStyles(element, styles) {
|
|
Object.keys(styles).forEach(function (prop) {
|
|
var unit = ''; // add unit if the value is numeric and is one of the following
|
|
|
|
if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
|
|
unit = 'px';
|
|
}
|
|
|
|
element.style[prop] = styles[prop] + unit;
|
|
});
|
|
}
|
|
/**
|
|
* Set the attributes to the given popper
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {Element} element - Element to apply the attributes to
|
|
* @argument {Object} styles
|
|
* Object with a list of properties and values which will be applied to the element
|
|
*/
|
|
|
|
|
|
function setAttributes(element, attributes) {
|
|
Object.keys(attributes).forEach(function (prop) {
|
|
var value = attributes[prop];
|
|
|
|
if (value !== false) {
|
|
element.setAttribute(prop, attributes[prop]);
|
|
} else {
|
|
element.removeAttribute(prop);
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* @function
|
|
* @memberof Modifiers
|
|
* @argument {Object} data - The data object generated by `update` method
|
|
* @argument {Object} data.styles - List of style properties - values to apply to popper element
|
|
* @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @returns {Object} The same data object
|
|
*/
|
|
|
|
|
|
function applyStyle(data) {
|
|
// any property present in `data.styles` will be applied to the popper,
|
|
// in this way we can make the 3rd party modifiers add custom styles to it
|
|
// Be aware, modifiers could override the properties defined in the previous
|
|
// lines of this modifier!
|
|
setStyles(data.instance.popper, data.styles); // any property present in `data.attributes` will be applied to the popper,
|
|
// they will be set as HTML attributes of the element
|
|
|
|
setAttributes(data.instance.popper, data.attributes); // if arrowElement is defined and arrowStyles has some properties
|
|
|
|
if (data.arrowElement && Object.keys(data.arrowStyles).length) {
|
|
setStyles(data.arrowElement, data.arrowStyles);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
/**
|
|
* Set the x-placement attribute before everything else because it could be used
|
|
* to add margins to the popper margins needs to be calculated to get the
|
|
* correct popper offsets.
|
|
* @method
|
|
* @memberof Popper.modifiers
|
|
* @param {HTMLElement} reference - The reference element used to position the popper
|
|
* @param {HTMLElement} popper - The HTML element used as popper
|
|
* @param {Object} options - Popper.js options
|
|
*/
|
|
|
|
|
|
function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
|
|
// compute reference element offsets
|
|
var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed); // compute auto placement, store placement inside the data object,
|
|
// modifiers will be able to edit `placement` if needed
|
|
// and refer to originalPlacement to know the original value
|
|
|
|
var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
|
|
popper.setAttribute('x-placement', placement); // Apply `position` to popper before anything else because
|
|
// without the position applied we can't guarantee correct computations
|
|
|
|
setStyles(popper, {
|
|
position: options.positionFixed ? 'fixed' : 'absolute'
|
|
});
|
|
return options;
|
|
}
|
|
/**
|
|
* @function
|
|
* @memberof Popper.Utils
|
|
* @argument {Object} data - The data object generated by `update` method
|
|
* @argument {Boolean} shouldRound - If the offsets should be rounded at all
|
|
* @returns {Object} The popper's position offsets rounded
|
|
*
|
|
* The tale of pixel-perfect positioning. It's still not 100% perfect, but as
|
|
* good as it can be within reason.
|
|
* Discussion here: https://github.com/FezVrasta/popper.js/pull/715
|
|
*
|
|
* Low DPI screens cause a popper to be blurry if not using full pixels (Safari
|
|
* as well on High DPI screens).
|
|
*
|
|
* Firefox prefers no rounding for positioning and does not have blurriness on
|
|
* high DPI screens.
|
|
*
|
|
* Only horizontal placement and left/right values need to be considered.
|
|
*/
|
|
|
|
|
|
function getRoundedOffsets(data, shouldRound) {
|
|
var _data$offsets = data.offsets,
|
|
popper = _data$offsets.popper,
|
|
reference = _data$offsets.reference;
|
|
var round = Math.round,
|
|
floor = Math.floor;
|
|
|
|
var noRound = function noRound(v) {
|
|
return v;
|
|
};
|
|
|
|
var referenceWidth = round(reference.width);
|
|
var popperWidth = round(popper.width);
|
|
var isVertical = ['left', 'right'].indexOf(data.placement) !== -1;
|
|
var isVariation = data.placement.indexOf('-') !== -1;
|
|
var sameWidthParity = referenceWidth % 2 === popperWidth % 2;
|
|
var bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1;
|
|
var horizontalToInteger = !shouldRound ? noRound : isVertical || isVariation || sameWidthParity ? round : floor;
|
|
var verticalToInteger = !shouldRound ? noRound : round;
|
|
return {
|
|
left: horizontalToInteger(bothOddWidth && !isVariation && shouldRound ? popper.left - 1 : popper.left),
|
|
top: verticalToInteger(popper.top),
|
|
bottom: verticalToInteger(popper.bottom),
|
|
right: horizontalToInteger(popper.right)
|
|
};
|
|
}
|
|
|
|
var isFirefox = isBrowser && /Firefox/i.test(navigator.userAgent);
|
|
/**
|
|
* @function
|
|
* @memberof Modifiers
|
|
* @argument {Object} data - The data object generated by `update` method
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @returns {Object} The data object, properly modified
|
|
*/
|
|
|
|
function computeStyle(data, options) {
|
|
var x = options.x,
|
|
y = options.y;
|
|
var popper = data.offsets.popper; // Remove this legacy support in Popper.js v2
|
|
|
|
var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
|
|
return modifier.name === 'applyStyle';
|
|
}).gpuAcceleration;
|
|
|
|
if (legacyGpuAccelerationOption !== undefined) {
|
|
console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
|
|
}
|
|
|
|
var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
|
|
var offsetParent = getOffsetParent(data.instance.popper);
|
|
var offsetParentRect = getBoundingClientRect(offsetParent); // Styles
|
|
|
|
var styles = {
|
|
position: popper.position
|
|
};
|
|
var offsets = getRoundedOffsets(data, window.devicePixelRatio < 2 || !isFirefox);
|
|
var sideA = x === 'bottom' ? 'top' : 'bottom';
|
|
var sideB = y === 'right' ? 'left' : 'right'; // if gpuAcceleration is set to `true` and transform is supported,
|
|
// we use `translate3d` to apply the position to the popper we
|
|
// automatically use the supported prefixed version if needed
|
|
|
|
var prefixedProperty = getSupportedPropertyName('transform'); // now, let's make a step back and look at this code closely (wtf?)
|
|
// If the content of the popper grows once it's been positioned, it
|
|
// may happen that the popper gets misplaced because of the new content
|
|
// overflowing its reference element
|
|
// To avoid this problem, we provide two options (x and y), which allow
|
|
// the consumer to define the offset origin.
|
|
// If we position a popper on top of a reference element, we can set
|
|
// `x` to `top` to make the popper grow towards its top instead of
|
|
// its bottom.
|
|
|
|
var left = void 0,
|
|
top = void 0;
|
|
|
|
if (sideA === 'bottom') {
|
|
// when offsetParent is <html> the positioning is relative to the bottom of the screen (excluding the scrollbar)
|
|
// and not the bottom of the html element
|
|
if (offsetParent.nodeName === 'HTML') {
|
|
top = -offsetParent.clientHeight + offsets.bottom;
|
|
} else {
|
|
top = -offsetParentRect.height + offsets.bottom;
|
|
}
|
|
} else {
|
|
top = offsets.top;
|
|
}
|
|
|
|
if (sideB === 'right') {
|
|
if (offsetParent.nodeName === 'HTML') {
|
|
left = -offsetParent.clientWidth + offsets.right;
|
|
} else {
|
|
left = -offsetParentRect.width + offsets.right;
|
|
}
|
|
} else {
|
|
left = offsets.left;
|
|
}
|
|
|
|
if (gpuAcceleration && prefixedProperty) {
|
|
styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
|
|
styles[sideA] = 0;
|
|
styles[sideB] = 0;
|
|
styles.willChange = 'transform';
|
|
} else {
|
|
// othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
|
|
var invertTop = sideA === 'bottom' ? -1 : 1;
|
|
var invertLeft = sideB === 'right' ? -1 : 1;
|
|
styles[sideA] = top * invertTop;
|
|
styles[sideB] = left * invertLeft;
|
|
styles.willChange = sideA + ', ' + sideB;
|
|
} // Attributes
|
|
|
|
|
|
var attributes = {
|
|
'x-placement': data.placement
|
|
}; // Update `data` attributes, styles and arrowStyles
|
|
|
|
data.attributes = _extends({}, attributes, data.attributes);
|
|
data.styles = _extends({}, styles, data.styles);
|
|
data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
|
|
return data;
|
|
}
|
|
/**
|
|
* Helper used to know if the given modifier depends from another one.<br />
|
|
* It checks if the needed modifier is listed and enabled.
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @param {Array} modifiers - list of modifiers
|
|
* @param {String} requestingName - name of requesting modifier
|
|
* @param {String} requestedName - name of requested modifier
|
|
* @returns {Boolean}
|
|
*/
|
|
|
|
|
|
function isModifierRequired(modifiers, requestingName, requestedName) {
|
|
var requesting = find(modifiers, function (_ref) {
|
|
var name = _ref.name;
|
|
return name === requestingName;
|
|
});
|
|
var isRequired = !!requesting && modifiers.some(function (modifier) {
|
|
return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
|
|
});
|
|
|
|
if (!isRequired) {
|
|
var _requesting = '`' + requestingName + '`';
|
|
|
|
var requested = '`' + requestedName + '`';
|
|
console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
|
|
}
|
|
|
|
return isRequired;
|
|
}
|
|
/**
|
|
* @function
|
|
* @memberof Modifiers
|
|
* @argument {Object} data - The data object generated by update method
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @returns {Object} The data object, properly modified
|
|
*/
|
|
|
|
|
|
function arrow(data, options) {
|
|
var _data$offsets$arrow; // arrow depends on keepTogether in order to work
|
|
|
|
|
|
if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
|
|
return data;
|
|
}
|
|
|
|
var arrowElement = options.element; // if arrowElement is a string, suppose it's a CSS selector
|
|
|
|
if (typeof arrowElement === 'string') {
|
|
arrowElement = data.instance.popper.querySelector(arrowElement); // if arrowElement is not found, don't run the modifier
|
|
|
|
if (!arrowElement) {
|
|
return data;
|
|
}
|
|
} else {
|
|
// if the arrowElement isn't a query selector we must check that the
|
|
// provided DOM node is child of its popper node
|
|
if (!data.instance.popper.contains(arrowElement)) {
|
|
console.warn('WARNING: `arrow.element` must be child of its popper element!');
|
|
return data;
|
|
}
|
|
}
|
|
|
|
var placement = data.placement.split('-')[0];
|
|
var _data$offsets = data.offsets,
|
|
popper = _data$offsets.popper,
|
|
reference = _data$offsets.reference;
|
|
var isVertical = ['left', 'right'].indexOf(placement) !== -1;
|
|
var len = isVertical ? 'height' : 'width';
|
|
var sideCapitalized = isVertical ? 'Top' : 'Left';
|
|
var side = sideCapitalized.toLowerCase();
|
|
var altSide = isVertical ? 'left' : 'top';
|
|
var opSide = isVertical ? 'bottom' : 'right';
|
|
var arrowElementSize = getOuterSizes(arrowElement)[len]; //
|
|
// extends keepTogether behavior making sure the popper and its
|
|
// reference have enough pixels in conjunction
|
|
//
|
|
// top/left side
|
|
|
|
if (reference[opSide] - arrowElementSize < popper[side]) {
|
|
data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
|
|
} // bottom/right side
|
|
|
|
|
|
if (reference[side] + arrowElementSize > popper[opSide]) {
|
|
data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
|
|
}
|
|
|
|
data.offsets.popper = getClientRect(data.offsets.popper); // compute center of the popper
|
|
|
|
var center = reference[side] + reference[len] / 2 - arrowElementSize / 2; // Compute the sideValue using the updated popper offsets
|
|
// take popper margin in account because we don't have this info available
|
|
|
|
var css = getStyleComputedProperty(data.instance.popper);
|
|
var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);
|
|
var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);
|
|
var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide; // prevent arrowElement from being placed not contiguously to its popper
|
|
|
|
sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
|
|
data.arrowElement = arrowElement;
|
|
data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
|
|
return data;
|
|
}
|
|
/**
|
|
* Get the opposite placement variation of the given one
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {String} placement variation
|
|
* @returns {String} flipped placement variation
|
|
*/
|
|
|
|
|
|
function getOppositeVariation(variation) {
|
|
if (variation === 'end') {
|
|
return 'start';
|
|
} else if (variation === 'start') {
|
|
return 'end';
|
|
}
|
|
|
|
return variation;
|
|
}
|
|
/**
|
|
* List of accepted placements to use as values of the `placement` option.<br />
|
|
* Valid placements are:
|
|
* - `auto`
|
|
* - `top`
|
|
* - `right`
|
|
* - `bottom`
|
|
* - `left`
|
|
*
|
|
* Each placement can have a variation from this list:
|
|
* - `-start`
|
|
* - `-end`
|
|
*
|
|
* Variations are interpreted easily if you think of them as the left to right
|
|
* written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
|
|
* is right.<br />
|
|
* Vertically (`left` and `right`), `start` is top and `end` is bottom.
|
|
*
|
|
* Some valid examples are:
|
|
* - `top-end` (on top of reference, right aligned)
|
|
* - `right-start` (on right of reference, top aligned)
|
|
* - `bottom` (on bottom, centered)
|
|
* - `auto-end` (on the side with more space available, alignment depends by placement)
|
|
*
|
|
* @static
|
|
* @type {Array}
|
|
* @enum {String}
|
|
* @readonly
|
|
* @method placements
|
|
* @memberof Popper
|
|
*/
|
|
|
|
|
|
var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']; // Get rid of `auto` `auto-start` and `auto-end`
|
|
|
|
var validPlacements = placements.slice(3);
|
|
/**
|
|
* Given an initial placement, returns all the subsequent placements
|
|
* clockwise (or counter-clockwise).
|
|
*
|
|
* @method
|
|
* @memberof Popper.Utils
|
|
* @argument {String} placement - A valid placement (it accepts variations)
|
|
* @argument {Boolean} counter - Set to true to walk the placements counterclockwise
|
|
* @returns {Array} placements including their variations
|
|
*/
|
|
|
|
function clockwise(placement) {
|
|
var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
var index = validPlacements.indexOf(placement);
|
|
var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
|
|
return counter ? arr.reverse() : arr;
|
|
}
|
|
|
|
var BEHAVIORS = {
|
|
FLIP: 'flip',
|
|
CLOCKWISE: 'clockwise',
|
|
COUNTERCLOCKWISE: 'counterclockwise'
|
|
};
|
|
/**
|
|
* @function
|
|
* @memberof Modifiers
|
|
* @argument {Object} data - The data object generated by update method
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @returns {Object} The data object, properly modified
|
|
*/
|
|
|
|
function flip(data, options) {
|
|
// if `inner` modifier is enabled, we can't use the `flip` modifier
|
|
if (isModifierEnabled(data.instance.modifiers, 'inner')) {
|
|
return data;
|
|
}
|
|
|
|
if (data.flipped && data.placement === data.originalPlacement) {
|
|
// seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
|
|
return data;
|
|
}
|
|
|
|
var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);
|
|
var placement = data.placement.split('-')[0];
|
|
var placementOpposite = getOppositePlacement(placement);
|
|
var variation = data.placement.split('-')[1] || '';
|
|
var flipOrder = [];
|
|
|
|
switch (options.behavior) {
|
|
case BEHAVIORS.FLIP:
|
|
flipOrder = [placement, placementOpposite];
|
|
break;
|
|
|
|
case BEHAVIORS.CLOCKWISE:
|
|
flipOrder = clockwise(placement);
|
|
break;
|
|
|
|
case BEHAVIORS.COUNTERCLOCKWISE:
|
|
flipOrder = clockwise(placement, true);
|
|
break;
|
|
|
|
default:
|
|
flipOrder = options.behavior;
|
|
}
|
|
|
|
flipOrder.forEach(function (step, index) {
|
|
if (placement !== step || flipOrder.length === index + 1) {
|
|
return data;
|
|
}
|
|
|
|
placement = data.placement.split('-')[0];
|
|
placementOpposite = getOppositePlacement(placement);
|
|
var popperOffsets = data.offsets.popper;
|
|
var refOffsets = data.offsets.reference; // using floor because the reference offsets may contain decimals we are not going to consider here
|
|
|
|
var floor = Math.floor;
|
|
var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);
|
|
var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
|
|
var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
|
|
var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
|
|
var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
|
|
var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom; // flip the variation if required
|
|
|
|
var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; // flips variation if reference element overflows boundaries
|
|
|
|
var flippedVariationByRef = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom); // flips variation if popper content overflows boundaries
|
|
|
|
var flippedVariationByContent = !!options.flipVariationsByContent && (isVertical && variation === 'start' && overflowsRight || isVertical && variation === 'end' && overflowsLeft || !isVertical && variation === 'start' && overflowsBottom || !isVertical && variation === 'end' && overflowsTop);
|
|
var flippedVariation = flippedVariationByRef || flippedVariationByContent;
|
|
|
|
if (overlapsRef || overflowsBoundaries || flippedVariation) {
|
|
// this boolean to detect any flip loop
|
|
data.flipped = true;
|
|
|
|
if (overlapsRef || overflowsBoundaries) {
|
|
placement = flipOrder[index + 1];
|
|
}
|
|
|
|
if (flippedVariation) {
|
|
variation = getOppositeVariation(variation);
|
|
}
|
|
|
|
data.placement = placement + (variation ? '-' + variation : ''); // this object contains `position`, we want to preserve it along with
|
|
// any additional property we may add in the future
|
|
|
|
data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
|
|
data = runModifiers(data.instance.modifiers, data, 'flip');
|
|
}
|
|
});
|
|
return data;
|
|
}
|
|
/**
|
|
* @function
|
|
* @memberof Modifiers
|
|
* @argument {Object} data - The data object generated by update method
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @returns {Object} The data object, properly modified
|
|
*/
|
|
|
|
|
|
function keepTogether(data) {
|
|
var _data$offsets = data.offsets,
|
|
popper = _data$offsets.popper,
|
|
reference = _data$offsets.reference;
|
|
var placement = data.placement.split('-')[0];
|
|
var floor = Math.floor;
|
|
var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
|
|
var side = isVertical ? 'right' : 'bottom';
|
|
var opSide = isVertical ? 'left' : 'top';
|
|
var measurement = isVertical ? 'width' : 'height';
|
|
|
|
if (popper[side] < floor(reference[opSide])) {
|
|
data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
|
|
}
|
|
|
|
if (popper[opSide] > floor(reference[side])) {
|
|
data.offsets.popper[opSide] = floor(reference[side]);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
/**
|
|
* Converts a string containing value + unit into a px value number
|
|
* @function
|
|
* @memberof {modifiers~offset}
|
|
* @private
|
|
* @argument {String} str - Value + unit string
|
|
* @argument {String} measurement - `height` or `width`
|
|
* @argument {Object} popperOffsets
|
|
* @argument {Object} referenceOffsets
|
|
* @returns {Number|String}
|
|
* Value in pixels, or original string if no values were extracted
|
|
*/
|
|
|
|
|
|
function toValue(str, measurement, popperOffsets, referenceOffsets) {
|
|
// separate value from unit
|
|
var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
|
|
var value = +split[1];
|
|
var unit = split[2]; // If it's not a number it's an operator, I guess
|
|
|
|
if (!value) {
|
|
return str;
|
|
}
|
|
|
|
if (unit.indexOf('%') === 0) {
|
|
var element = void 0;
|
|
|
|
switch (unit) {
|
|
case '%p':
|
|
element = popperOffsets;
|
|
break;
|
|
|
|
case '%':
|
|
case '%r':
|
|
default:
|
|
element = referenceOffsets;
|
|
}
|
|
|
|
var rect = getClientRect(element);
|
|
return rect[measurement] / 100 * value;
|
|
} else if (unit === 'vh' || unit === 'vw') {
|
|
// if is a vh or vw, we calculate the size based on the viewport
|
|
var size = void 0;
|
|
|
|
if (unit === 'vh') {
|
|
size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
|
|
} else {
|
|
size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
|
|
}
|
|
|
|
return size / 100 * value;
|
|
} else {
|
|
// if is an explicit pixel unit, we get rid of the unit and keep the value
|
|
// if is an implicit unit, it's px, and we return just the value
|
|
return value;
|
|
}
|
|
}
|
|
/**
|
|
* Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
|
|
* @function
|
|
* @memberof {modifiers~offset}
|
|
* @private
|
|
* @argument {String} offset
|
|
* @argument {Object} popperOffsets
|
|
* @argument {Object} referenceOffsets
|
|
* @argument {String} basePlacement
|
|
* @returns {Array} a two cells array with x and y offsets in numbers
|
|
*/
|
|
|
|
|
|
function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
|
|
var offsets = [0, 0]; // Use height if placement is left or right and index is 0 otherwise use width
|
|
// in this way the first offset will use an axis and the second one
|
|
// will use the other one
|
|
|
|
var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1; // Split the offset string to obtain a list of values and operands
|
|
// The regex addresses values with the plus or minus sign in front (+10, -20, etc)
|
|
|
|
var fragments = offset.split(/(\+|\-)/).map(function (frag) {
|
|
return frag.trim();
|
|
}); // Detect if the offset string contains a pair of values or a single one
|
|
// they could be separated by comma or space
|
|
|
|
var divider = fragments.indexOf(find(fragments, function (frag) {
|
|
return frag.search(/,|\s/) !== -1;
|
|
}));
|
|
|
|
if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
|
|
console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
|
|
} // If divider is found, we divide the list of values and operands to divide
|
|
// them by ofset X and Y.
|
|
|
|
|
|
var splitRegex = /\s*,\s*|\s+/;
|
|
var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments]; // Convert the values with units to absolute pixels to allow our computations
|
|
|
|
ops = ops.map(function (op, index) {
|
|
// Most of the units rely on the orientation of the popper
|
|
var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
|
|
var mergeWithPrevious = false;
|
|
return op // This aggregates any `+` or `-` sign that aren't considered operators
|
|
// e.g.: 10 + +5 => [10, +, +5]
|
|
.reduce(function (a, b) {
|
|
if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
|
|
a[a.length - 1] = b;
|
|
mergeWithPrevious = true;
|
|
return a;
|
|
} else if (mergeWithPrevious) {
|
|
a[a.length - 1] += b;
|
|
mergeWithPrevious = false;
|
|
return a;
|
|
} else {
|
|
return a.concat(b);
|
|
}
|
|
}, []) // Here we convert the string values into number values (in px)
|
|
.map(function (str) {
|
|
return toValue(str, measurement, popperOffsets, referenceOffsets);
|
|
});
|
|
}); // Loop trough the offsets arrays and execute the operations
|
|
|
|
ops.forEach(function (op, index) {
|
|
op.forEach(function (frag, index2) {
|
|
if (isNumeric(frag)) {
|
|
offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
|
|
}
|
|
});
|
|
});
|
|
return offsets;
|
|
}
|
|
/**
|
|
* @function
|
|
* @memberof Modifiers
|
|
* @argument {Object} data - The data object generated by update method
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @argument {Number|String} options.offset=0
|
|
* The offset value as described in the modifier description
|
|
* @returns {Object} The data object, properly modified
|
|
*/
|
|
|
|
|
|
function offset(data, _ref) {
|
|
var offset = _ref.offset;
|
|
var placement = data.placement,
|
|
_data$offsets = data.offsets,
|
|
popper = _data$offsets.popper,
|
|
reference = _data$offsets.reference;
|
|
var basePlacement = placement.split('-')[0];
|
|
var offsets = void 0;
|
|
|
|
if (isNumeric(+offset)) {
|
|
offsets = [+offset, 0];
|
|
} else {
|
|
offsets = parseOffset(offset, popper, reference, basePlacement);
|
|
}
|
|
|
|
if (basePlacement === 'left') {
|
|
popper.top += offsets[0];
|
|
popper.left -= offsets[1];
|
|
} else if (basePlacement === 'right') {
|
|
popper.top += offsets[0];
|
|
popper.left += offsets[1];
|
|
} else if (basePlacement === 'top') {
|
|
popper.left += offsets[0];
|
|
popper.top -= offsets[1];
|
|
} else if (basePlacement === 'bottom') {
|
|
popper.left += offsets[0];
|
|
popper.top += offsets[1];
|
|
}
|
|
|
|
data.popper = popper;
|
|
return data;
|
|
}
|
|
/**
|
|
* @function
|
|
* @memberof Modifiers
|
|
* @argument {Object} data - The data object generated by `update` method
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @returns {Object} The data object, properly modified
|
|
*/
|
|
|
|
|
|
function preventOverflow(data, options) {
|
|
var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper); // If offsetParent is the reference element, we really want to
|
|
// go one step up and use the next offsetParent as reference to
|
|
// avoid to make this modifier completely useless and look like broken
|
|
|
|
if (data.instance.reference === boundariesElement) {
|
|
boundariesElement = getOffsetParent(boundariesElement);
|
|
} // NOTE: DOM access here
|
|
// resets the popper's position so that the document size can be calculated excluding
|
|
// the size of the popper element itself
|
|
|
|
|
|
var transformProp = getSupportedPropertyName('transform');
|
|
var popperStyles = data.instance.popper.style; // assignment to help minification
|
|
|
|
var top = popperStyles.top,
|
|
left = popperStyles.left,
|
|
transform = popperStyles[transformProp];
|
|
popperStyles.top = '';
|
|
popperStyles.left = '';
|
|
popperStyles[transformProp] = '';
|
|
var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed); // NOTE: DOM access here
|
|
// restores the original style properties after the offsets have been computed
|
|
|
|
popperStyles.top = top;
|
|
popperStyles.left = left;
|
|
popperStyles[transformProp] = transform;
|
|
options.boundaries = boundaries;
|
|
var order = options.priority;
|
|
var popper = data.offsets.popper;
|
|
var check = {
|
|
primary: function primary(placement) {
|
|
var value = popper[placement];
|
|
|
|
if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
|
|
value = Math.max(popper[placement], boundaries[placement]);
|
|
}
|
|
|
|
return defineProperty({}, placement, value);
|
|
},
|
|
secondary: function secondary(placement) {
|
|
var mainSide = placement === 'right' ? 'left' : 'top';
|
|
var value = popper[mainSide];
|
|
|
|
if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
|
|
value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
|
|
}
|
|
|
|
return defineProperty({}, mainSide, value);
|
|
}
|
|
};
|
|
order.forEach(function (placement) {
|
|
var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
|
|
popper = _extends({}, popper, check[side](placement));
|
|
});
|
|
data.offsets.popper = popper;
|
|
return data;
|
|
}
|
|
/**
|
|
* @function
|
|
* @memberof Modifiers
|
|
* @argument {Object} data - The data object generated by `update` method
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @returns {Object} The data object, properly modified
|
|
*/
|
|
|
|
|
|
function shift(data) {
|
|
var placement = data.placement;
|
|
var basePlacement = placement.split('-')[0];
|
|
var shiftvariation = placement.split('-')[1]; // if shift shiftvariation is specified, run the modifier
|
|
|
|
if (shiftvariation) {
|
|
var _data$offsets = data.offsets,
|
|
reference = _data$offsets.reference,
|
|
popper = _data$offsets.popper;
|
|
var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
|
|
var side = isVertical ? 'left' : 'top';
|
|
var measurement = isVertical ? 'width' : 'height';
|
|
var shiftOffsets = {
|
|
start: defineProperty({}, side, reference[side]),
|
|
end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
|
|
};
|
|
data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
/**
|
|
* @function
|
|
* @memberof Modifiers
|
|
* @argument {Object} data - The data object generated by update method
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @returns {Object} The data object, properly modified
|
|
*/
|
|
|
|
|
|
function hide(data) {
|
|
if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
|
|
return data;
|
|
}
|
|
|
|
var refRect = data.offsets.reference;
|
|
var bound = find(data.instance.modifiers, function (modifier) {
|
|
return modifier.name === 'preventOverflow';
|
|
}).boundaries;
|
|
|
|
if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
|
|
// Avoid unnecessary DOM access if visibility hasn't changed
|
|
if (data.hide === true) {
|
|
return data;
|
|
}
|
|
|
|
data.hide = true;
|
|
data.attributes['x-out-of-boundaries'] = '';
|
|
} else {
|
|
// Avoid unnecessary DOM access if visibility hasn't changed
|
|
if (data.hide === false) {
|
|
return data;
|
|
}
|
|
|
|
data.hide = false;
|
|
data.attributes['x-out-of-boundaries'] = false;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
/**
|
|
* @function
|
|
* @memberof Modifiers
|
|
* @argument {Object} data - The data object generated by `update` method
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @returns {Object} The data object, properly modified
|
|
*/
|
|
|
|
|
|
function inner(data) {
|
|
var placement = data.placement;
|
|
var basePlacement = placement.split('-')[0];
|
|
var _data$offsets = data.offsets,
|
|
popper = _data$offsets.popper,
|
|
reference = _data$offsets.reference;
|
|
var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
|
|
var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
|
|
popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
|
|
data.placement = getOppositePlacement(placement);
|
|
data.offsets.popper = getClientRect(popper);
|
|
return data;
|
|
}
|
|
/**
|
|
* Modifier function, each modifier can have a function of this type assigned
|
|
* to its `fn` property.<br />
|
|
* These functions will be called on each update, this means that you must
|
|
* make sure they are performant enough to avoid performance bottlenecks.
|
|
*
|
|
* @function ModifierFn
|
|
* @argument {dataObject} data - The data object generated by `update` method
|
|
* @argument {Object} options - Modifiers configuration and options
|
|
* @returns {dataObject} The data object, properly modified
|
|
*/
|
|
|
|
/**
|
|
* Modifiers are plugins used to alter the behavior of your poppers.<br />
|
|
* Popper.js uses a set of 9 modifiers to provide all the basic functionalities
|
|
* needed by the library.
|
|
*
|
|
* Usually you don't want to override the `order`, `fn` and `onLoad` props.
|
|
* All the other properties are configurations that could be tweaked.
|
|
* @namespace modifiers
|
|
*/
|
|
|
|
|
|
var modifiers = {
|
|
/**
|
|
* Modifier used to shift the popper on the start or end of its reference
|
|
* element.<br />
|
|
* It will read the variation of the `placement` property.<br />
|
|
* It can be one either `-end` or `-start`.
|
|
* @memberof modifiers
|
|
* @inner
|
|
*/
|
|
shift: {
|
|
/** @prop {number} order=100 - Index used to define the order of execution */
|
|
order: 100,
|
|
|
|
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
|
|
enabled: true,
|
|
|
|
/** @prop {ModifierFn} */
|
|
fn: shift
|
|
},
|
|
|
|
/**
|
|
* The `offset` modifier can shift your popper on both its axis.
|
|
*
|
|
* It accepts the following units:
|
|
* - `px` or unit-less, interpreted as pixels
|
|
* - `%` or `%r`, percentage relative to the length of the reference element
|
|
* - `%p`, percentage relative to the length of the popper element
|
|
* - `vw`, CSS viewport width unit
|
|
* - `vh`, CSS viewport height unit
|
|
*
|
|
* For length is intended the main axis relative to the placement of the popper.<br />
|
|
* This means that if the placement is `top` or `bottom`, the length will be the
|
|
* `width`. In case of `left` or `right`, it will be the `height`.
|
|
*
|
|
* You can provide a single value (as `Number` or `String`), or a pair of values
|
|
* as `String` divided by a comma or one (or more) white spaces.<br />
|
|
* The latter is a deprecated method because it leads to confusion and will be
|
|
* removed in v2.<br />
|
|
* Additionally, it accepts additions and subtractions between different units.
|
|
* Note that multiplications and divisions aren't supported.
|
|
*
|
|
* Valid examples are:
|
|
* ```
|
|
* 10
|
|
* '10%'
|
|
* '10, 10'
|
|
* '10%, 10'
|
|
* '10 + 10%'
|
|
* '10 - 5vh + 3%'
|
|
* '-10px + 5vh, 5px - 6%'
|
|
* ```
|
|
* > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
|
|
* > with their reference element, unfortunately, you will have to disable the `flip` modifier.
|
|
* > You can read more on this at this [issue](https://github.com/FezVrasta/popper.js/issues/373).
|
|
*
|
|
* @memberof modifiers
|
|
* @inner
|
|
*/
|
|
offset: {
|
|
/** @prop {number} order=200 - Index used to define the order of execution */
|
|
order: 200,
|
|
|
|
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
|
|
enabled: true,
|
|
|
|
/** @prop {ModifierFn} */
|
|
fn: offset,
|
|
|
|
/** @prop {Number|String} offset=0
|
|
* The offset value as described in the modifier description
|
|
*/
|
|
offset: 0
|
|
},
|
|
|
|
/**
|
|
* Modifier used to prevent the popper from being positioned outside the boundary.
|
|
*
|
|
* A scenario exists where the reference itself is not within the boundaries.<br />
|
|
* We can say it has "escaped the boundaries" — or just "escaped".<br />
|
|
* In this case we need to decide whether the popper should either:
|
|
*
|
|
* - detach from the reference and remain "trapped" in the boundaries, or
|
|
* - if it should ignore the boundary and "escape with its reference"
|
|
*
|
|
* When `escapeWithReference` is set to`true` and reference is completely
|
|
* outside its boundaries, the popper will overflow (or completely leave)
|
|
* the boundaries in order to remain attached to the edge of the reference.
|
|
*
|
|
* @memberof modifiers
|
|
* @inner
|
|
*/
|
|
preventOverflow: {
|
|
/** @prop {number} order=300 - Index used to define the order of execution */
|
|
order: 300,
|
|
|
|
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
|
|
enabled: true,
|
|
|
|
/** @prop {ModifierFn} */
|
|
fn: preventOverflow,
|
|
|
|
/**
|
|
* @prop {Array} [priority=['left','right','top','bottom']]
|
|
* Popper will try to prevent overflow following these priorities by default,
|
|
* then, it could overflow on the left and on top of the `boundariesElement`
|
|
*/
|
|
priority: ['left', 'right', 'top', 'bottom'],
|
|
|
|
/**
|
|
* @prop {number} padding=5
|
|
* Amount of pixel used to define a minimum distance between the boundaries
|
|
* and the popper. This makes sure the popper always has a little padding
|
|
* between the edges of its container
|
|
*/
|
|
padding: 5,
|
|
|
|
/**
|
|
* @prop {String|HTMLElement} boundariesElement='scrollParent'
|
|
* Boundaries used by the modifier. Can be `scrollParent`, `window`,
|
|
* `viewport` or any DOM element.
|
|
*/
|
|
boundariesElement: 'scrollParent'
|
|
},
|
|
|
|
/**
|
|
* Modifier used to make sure the reference and its popper stay near each other
|
|
* without leaving any gap between the two. Especially useful when the arrow is
|
|
* enabled and you want to ensure that it points to its reference element.
|
|
* It cares only about the first axis. You can still have poppers with margin
|
|
* between the popper and its reference element.
|
|
* @memberof modifiers
|
|
* @inner
|
|
*/
|
|
keepTogether: {
|
|
/** @prop {number} order=400 - Index used to define the order of execution */
|
|
order: 400,
|
|
|
|
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
|
|
enabled: true,
|
|
|
|
/** @prop {ModifierFn} */
|
|
fn: keepTogether
|
|
},
|
|
|
|
/**
|
|
* This modifier is used to move the `arrowElement` of the popper to make
|
|
* sure it is positioned between the reference element and its popper element.
|
|
* It will read the outer size of the `arrowElement` node to detect how many
|
|
* pixels of conjunction are needed.
|
|
*
|
|
* It has no effect if no `arrowElement` is provided.
|
|
* @memberof modifiers
|
|
* @inner
|
|
*/
|
|
arrow: {
|
|
/** @prop {number} order=500 - Index used to define the order of execution */
|
|
order: 500,
|
|
|
|
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
|
|
enabled: true,
|
|
|
|
/** @prop {ModifierFn} */
|
|
fn: arrow,
|
|
|
|
/** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
|
|
element: '[x-arrow]'
|
|
},
|
|
|
|
/**
|
|
* Modifier used to flip the popper's placement when it starts to overlap its
|
|
* reference element.
|
|
*
|
|
* Requires the `preventOverflow` modifier before it in order to work.
|
|
*
|
|
* **NOTE:** this modifier will interrupt the current update cycle and will
|
|
* restart it if it detects the need to flip the placement.
|
|
* @memberof modifiers
|
|
* @inner
|
|
*/
|
|
flip: {
|
|
/** @prop {number} order=600 - Index used to define the order of execution */
|
|
order: 600,
|
|
|
|
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
|
|
enabled: true,
|
|
|
|
/** @prop {ModifierFn} */
|
|
fn: flip,
|
|
|
|
/**
|
|
* @prop {String|Array} behavior='flip'
|
|
* The behavior used to change the popper's placement. It can be one of
|
|
* `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
|
|
* placements (with optional variations)
|
|
*/
|
|
behavior: 'flip',
|
|
|
|
/**
|
|
* @prop {number} padding=5
|
|
* The popper will flip if it hits the edges of the `boundariesElement`
|
|
*/
|
|
padding: 5,
|
|
|
|
/**
|
|
* @prop {String|HTMLElement} boundariesElement='viewport'
|
|
* The element which will define the boundaries of the popper position.
|
|
* The popper will never be placed outside of the defined boundaries
|
|
* (except if `keepTogether` is enabled)
|
|
*/
|
|
boundariesElement: 'viewport',
|
|
|
|
/**
|
|
* @prop {Boolean} flipVariations=false
|
|
* The popper will switch placement variation between `-start` and `-end` when
|
|
* the reference element overlaps its boundaries.
|
|
*
|
|
* The original placement should have a set variation.
|
|
*/
|
|
flipVariations: false,
|
|
|
|
/**
|
|
* @prop {Boolean} flipVariationsByContent=false
|
|
* The popper will switch placement variation between `-start` and `-end` when
|
|
* the popper element overlaps its reference boundaries.
|
|
*
|
|
* The original placement should have a set variation.
|
|
*/
|
|
flipVariationsByContent: false
|
|
},
|
|
|
|
/**
|
|
* Modifier used to make the popper flow toward the inner of the reference element.
|
|
* By default, when this modifier is disabled, the popper will be placed outside
|
|
* the reference element.
|
|
* @memberof modifiers
|
|
* @inner
|
|
*/
|
|
inner: {
|
|
/** @prop {number} order=700 - Index used to define the order of execution */
|
|
order: 700,
|
|
|
|
/** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
|
|
enabled: false,
|
|
|
|
/** @prop {ModifierFn} */
|
|
fn: inner
|
|
},
|
|
|
|
/**
|
|
* Modifier used to hide the popper when its reference element is outside of the
|
|
* popper boundaries. It will set a `x-out-of-boundaries` attribute which can
|
|
* be used to hide with a CSS selector the popper when its reference is
|
|
* out of boundaries.
|
|
*
|
|
* Requires the `preventOverflow` modifier before it in order to work.
|
|
* @memberof modifiers
|
|
* @inner
|
|
*/
|
|
hide: {
|
|
/** @prop {number} order=800 - Index used to define the order of execution */
|
|
order: 800,
|
|
|
|
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
|
|
enabled: true,
|
|
|
|
/** @prop {ModifierFn} */
|
|
fn: hide
|
|
},
|
|
|
|
/**
|
|
* Computes the style that will be applied to the popper element to gets
|
|
* properly positioned.
|
|
*
|
|
* Note that this modifier will not touch the DOM, it just prepares the styles
|
|
* so that `applyStyle` modifier can apply it. This separation is useful
|
|
* in case you need to replace `applyStyle` with a custom implementation.
|
|
*
|
|
* This modifier has `850` as `order` value to maintain backward compatibility
|
|
* with previous versions of Popper.js. Expect the modifiers ordering method
|
|
* to change in future major versions of the library.
|
|
*
|
|
* @memberof modifiers
|
|
* @inner
|
|
*/
|
|
computeStyle: {
|
|
/** @prop {number} order=850 - Index used to define the order of execution */
|
|
order: 850,
|
|
|
|
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
|
|
enabled: true,
|
|
|
|
/** @prop {ModifierFn} */
|
|
fn: computeStyle,
|
|
|
|
/**
|
|
* @prop {Boolean} gpuAcceleration=true
|
|
* If true, it uses the CSS 3D transformation to position the popper.
|
|
* Otherwise, it will use the `top` and `left` properties
|
|
*/
|
|
gpuAcceleration: true,
|
|
|
|
/**
|
|
* @prop {string} [x='bottom']
|
|
* Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
|
|
* Change this if your popper should grow in a direction different from `bottom`
|
|
*/
|
|
x: 'bottom',
|
|
|
|
/**
|
|
* @prop {string} [x='left']
|
|
* Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
|
|
* Change this if your popper should grow in a direction different from `right`
|
|
*/
|
|
y: 'right'
|
|
},
|
|
|
|
/**
|
|
* Applies the computed styles to the popper element.
|
|
*
|
|
* All the DOM manipulations are limited to this modifier. This is useful in case
|
|
* you want to integrate Popper.js inside a framework or view library and you
|
|
* want to delegate all the DOM manipulations to it.
|
|
*
|
|
* Note that if you disable this modifier, you must make sure the popper element
|
|
* has its position set to `absolute` before Popper.js can do its work!
|
|
*
|
|
* Just disable this modifier and define your own to achieve the desired effect.
|
|
*
|
|
* @memberof modifiers
|
|
* @inner
|
|
*/
|
|
applyStyle: {
|
|
/** @prop {number} order=900 - Index used to define the order of execution */
|
|
order: 900,
|
|
|
|
/** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
|
|
enabled: true,
|
|
|
|
/** @prop {ModifierFn} */
|
|
fn: applyStyle,
|
|
|
|
/** @prop {Function} */
|
|
onLoad: applyStyleOnLoad,
|
|
|
|
/**
|
|
* @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
|
|
* @prop {Boolean} gpuAcceleration=true
|
|
* If true, it uses the CSS 3D transformation to position the popper.
|
|
* Otherwise, it will use the `top` and `left` properties
|
|
*/
|
|
gpuAcceleration: undefined
|
|
}
|
|
};
|
|
/**
|
|
* The `dataObject` is an object containing all the information used by Popper.js.
|
|
* This object is passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
|
|
* @name dataObject
|
|
* @property {Object} data.instance The Popper.js instance
|
|
* @property {String} data.placement Placement applied to popper
|
|
* @property {String} data.originalPlacement Placement originally defined on init
|
|
* @property {Boolean} data.flipped True if popper has been flipped by flip modifier
|
|
* @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper
|
|
* @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
|
|
* @property {Object} data.styles Any CSS property defined here will be applied to the popper. It expects the JavaScript nomenclature (eg. `marginBottom`)
|
|
* @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow. It expects the JavaScript nomenclature (eg. `marginBottom`)
|
|
* @property {Object} data.boundaries Offsets of the popper boundaries
|
|
* @property {Object} data.offsets The measurements of popper, reference and arrow elements
|
|
* @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
|
|
* @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
|
|
* @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
|
|
*/
|
|
|
|
/**
|
|
* Default options provided to Popper.js constructor.<br />
|
|
* These can be overridden using the `options` argument of Popper.js.<br />
|
|
* To override an option, simply pass an object with the same
|
|
* structure of the `options` object, as the 3rd argument. For example:
|
|
* ```
|
|
* new Popper(ref, pop, {
|
|
* modifiers: {
|
|
* preventOverflow: { enabled: false }
|
|
* }
|
|
* })
|
|
* ```
|
|
* @type {Object}
|
|
* @static
|
|
* @memberof Popper
|
|
*/
|
|
|
|
var Defaults = {
|
|
/**
|
|
* Popper's placement.
|
|
* @prop {Popper.placements} placement='bottom'
|
|
*/
|
|
placement: 'bottom',
|
|
|
|
/**
|
|
* Set this to true if you want popper to position it self in 'fixed' mode
|
|
* @prop {Boolean} positionFixed=false
|
|
*/
|
|
positionFixed: false,
|
|
|
|
/**
|
|
* Whether events (resize, scroll) are initially enabled.
|
|
* @prop {Boolean} eventsEnabled=true
|
|
*/
|
|
eventsEnabled: true,
|
|
|
|
/**
|
|
* Set to true if you want to automatically remove the popper when
|
|
* you call the `destroy` method.
|
|
* @prop {Boolean} removeOnDestroy=false
|
|
*/
|
|
removeOnDestroy: false,
|
|
|
|
/**
|
|
* Callback called when the popper is created.<br />
|
|
* By default, it is set to no-op.<br />
|
|
* Access Popper.js instance with `data.instance`.
|
|
* @prop {onCreate}
|
|
*/
|
|
onCreate: function onCreate() {},
|
|
|
|
/**
|
|
* Callback called when the popper is updated. This callback is not called
|
|
* on the initialization/creation of the popper, but only on subsequent
|
|
* updates.<br />
|
|
* By default, it is set to no-op.<br />
|
|
* Access Popper.js instance with `data.instance`.
|
|
* @prop {onUpdate}
|
|
*/
|
|
onUpdate: function onUpdate() {},
|
|
|
|
/**
|
|
* List of modifiers used to modify the offsets before they are applied to the popper.
|
|
* They provide most of the functionalities of Popper.js.
|
|
* @prop {modifiers}
|
|
*/
|
|
modifiers: modifiers
|
|
};
|
|
/**
|
|
* @callback onCreate
|
|
* @param {dataObject} data
|
|
*/
|
|
|
|
/**
|
|
* @callback onUpdate
|
|
* @param {dataObject} data
|
|
*/
|
|
// Utils
|
|
// Methods
|
|
|
|
var Popper = function () {
|
|
/**
|
|
* Creates a new Popper.js instance.
|
|
* @class Popper
|
|
* @param {Element|referenceObject} reference - The reference element used to position the popper
|
|
* @param {Element} popper - The HTML / XML element used as the popper
|
|
* @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
|
|
* @return {Object} instance - The generated Popper.js instance
|
|
*/
|
|
function Popper(reference, popper) {
|
|
var _this = this;
|
|
|
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
classCallCheck(this, Popper);
|
|
|
|
this.scheduleUpdate = function () {
|
|
return requestAnimationFrame(_this.update);
|
|
}; // make update() debounced, so that it only runs at most once-per-tick
|
|
|
|
|
|
this.update = debounce(this.update.bind(this)); // with {} we create a new object with the options inside it
|
|
|
|
this.options = _extends({}, Popper.Defaults, options); // init state
|
|
|
|
this.state = {
|
|
isDestroyed: false,
|
|
isCreated: false,
|
|
scrollParents: []
|
|
}; // get reference and popper elements (allow jQuery wrappers)
|
|
|
|
this.reference = reference && reference.jquery ? reference[0] : reference;
|
|
this.popper = popper && popper.jquery ? popper[0] : popper; // Deep merge modifiers options
|
|
|
|
this.options.modifiers = {};
|
|
Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
|
|
_this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
|
|
}); // Refactoring modifiers' list (Object => Array)
|
|
|
|
this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
|
|
return _extends({
|
|
name: name
|
|
}, _this.options.modifiers[name]);
|
|
}) // sort the modifiers by order
|
|
.sort(function (a, b) {
|
|
return a.order - b.order;
|
|
}); // modifiers have the ability to execute arbitrary code when Popper.js get inited
|
|
// such code is executed in the same order of its modifier
|
|
// they could add new properties to their options configuration
|
|
// BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
|
|
|
|
this.modifiers.forEach(function (modifierOptions) {
|
|
if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
|
|
modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
|
|
}
|
|
}); // fire the first update to position the popper in the right place
|
|
|
|
this.update();
|
|
var eventsEnabled = this.options.eventsEnabled;
|
|
|
|
if (eventsEnabled) {
|
|
// setup event listeners, they will take care of update the position in specific situations
|
|
this.enableEventListeners();
|
|
}
|
|
|
|
this.state.eventsEnabled = eventsEnabled;
|
|
} // We can't use class properties because they don't get listed in the
|
|
// class prototype and break stuff like Sinon stubs
|
|
|
|
|
|
createClass(Popper, [{
|
|
key: 'update',
|
|
value: function update$$1() {
|
|
return update.call(this);
|
|
}
|
|
}, {
|
|
key: 'destroy',
|
|
value: function destroy$$1() {
|
|
return destroy.call(this);
|
|
}
|
|
}, {
|
|
key: 'enableEventListeners',
|
|
value: function enableEventListeners$$1() {
|
|
return enableEventListeners.call(this);
|
|
}
|
|
}, {
|
|
key: 'disableEventListeners',
|
|
value: function disableEventListeners$$1() {
|
|
return disableEventListeners.call(this);
|
|
}
|
|
/**
|
|
* Schedules an update. It will run on the next UI update available.
|
|
* @method scheduleUpdate
|
|
* @memberof Popper
|
|
*/
|
|
|
|
/**
|
|
* Collection of utilities useful when writing custom modifiers.
|
|
* Starting from version 1.7, this method is available only if you
|
|
* include `popper-utils.js` before `popper.js`.
|
|
*
|
|
* **DEPRECATION**: This way to access PopperUtils is deprecated
|
|
* and will be removed in v2! Use the PopperUtils module directly instead.
|
|
* Due to the high instability of the methods contained in Utils, we can't
|
|
* guarantee them to follow semver. Use them at your own risk!
|
|
* @static
|
|
* @private
|
|
* @type {Object}
|
|
* @deprecated since version 1.8
|
|
* @member Utils
|
|
* @memberof Popper
|
|
*/
|
|
|
|
}]);
|
|
return Popper;
|
|
}();
|
|
/**
|
|
* The `referenceObject` is an object that provides an interface compatible with Popper.js
|
|
* and lets you use it as replacement of a real DOM node.<br />
|
|
* You can use this method to position a popper relatively to a set of coordinates
|
|
* in case you don't have a DOM node to use as reference.
|
|
*
|
|
* ```
|
|
* new Popper(referenceObject, popperNode);
|
|
* ```
|
|
*
|
|
* NB: This feature isn't supported in Internet Explorer 10.
|
|
* @name referenceObject
|
|
* @property {Function} data.getBoundingClientRect
|
|
* A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
|
|
* @property {number} data.clientWidth
|
|
* An ES6 getter that will return the width of the virtual reference element.
|
|
* @property {number} data.clientHeight
|
|
* An ES6 getter that will return the height of the virtual reference element.
|
|
*/
|
|
|
|
|
|
Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
|
|
Popper.placements = placements;
|
|
Popper.Defaults = Defaults;
|
|
/* harmony default export */ __webpack_exports__["default"] = (Popper);
|
|
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../../webpack/buildin/global.js */ "./node_modules/webpack/buildin/global.js")))
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/shave/dist/shave.es.js":
|
|
/*!*********************************************!*\
|
|
!*** ./node_modules/shave/dist/shave.es.js ***!
|
|
\*********************************************/
|
|
/*! exports provided: default */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/**
|
|
shave - Shave is a javascript plugin that truncates multi-line text within a html element based on set max height
|
|
@version v2.5.6
|
|
@link https://github.com/dollarshaveclub/shave#readme
|
|
@author Jeff Wainwright <yowainwright@gmail.com> (jeffry.in)
|
|
@license MIT
|
|
**/
|
|
function shave(target, maxHeight) {
|
|
var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
if (typeof maxHeight === 'undefined' || isNaN(maxHeight)) throw Error('maxHeight is required');
|
|
var els = typeof target === 'string' ? document.querySelectorAll(target) : target;
|
|
if (!els) return;
|
|
var character = opts.character || '…';
|
|
var classname = opts.classname || 'js-shave';
|
|
var spaces = typeof opts.spaces === 'boolean' ? opts.spaces : true;
|
|
var charHtml = "<span class=\"js-shave-char\">".concat(character, "</span>");
|
|
if (!('length' in els)) els = [els];
|
|
|
|
for (var i = 0; i < els.length; i += 1) {
|
|
var el = els[i];
|
|
var styles = el.style;
|
|
var span = el.querySelector(".".concat(classname));
|
|
var textProp = el.textContent === undefined ? 'innerText' : 'textContent'; // If element text has already been shaved
|
|
|
|
if (span) {
|
|
// Remove the ellipsis to recapture the original text
|
|
el.removeChild(el.querySelector('.js-shave-char'));
|
|
el[textProp] = el[textProp]; // eslint-disable-line
|
|
// nuke span, recombine text
|
|
}
|
|
|
|
var fullText = el[textProp];
|
|
var words = spaces ? fullText.split(' ') : fullText; // If 0 or 1 words, we're done
|
|
|
|
if (words.length < 2) continue; // Temporarily remove any CSS height for text height calculation
|
|
|
|
var heightStyle = styles.height;
|
|
styles.height = 'auto';
|
|
var maxHeightStyle = styles.maxHeight;
|
|
styles.maxHeight = 'none'; // If already short enough, we're done
|
|
|
|
if (el.offsetHeight <= maxHeight) {
|
|
styles.height = heightStyle;
|
|
styles.maxHeight = maxHeightStyle;
|
|
continue;
|
|
} // Binary search for number of words which can fit in allotted height
|
|
|
|
|
|
var max = words.length - 1;
|
|
var min = 0;
|
|
var pivot = void 0;
|
|
|
|
while (min < max) {
|
|
pivot = min + max + 1 >> 1; // eslint-disable-line no-bitwise
|
|
|
|
el[textProp] = spaces ? words.slice(0, pivot).join(' ') : words.slice(0, pivot);
|
|
el.insertAdjacentHTML('beforeend', charHtml);
|
|
if (el.offsetHeight > maxHeight) max = pivot - 1;else min = pivot;
|
|
}
|
|
|
|
el[textProp] = spaces ? words.slice(0, max).join(' ') : words.slice(0, max);
|
|
el.insertAdjacentHTML('beforeend', charHtml);
|
|
var diff = spaces ? " ".concat(words.slice(max).join(' ')) : words.slice(max);
|
|
var shavedText = document.createTextNode(diff);
|
|
var elWithShavedText = document.createElement('span');
|
|
elWithShavedText.classList.add(classname);
|
|
elWithShavedText.style.display = 'none';
|
|
elWithShavedText.appendChild(shavedText);
|
|
el.insertAdjacentElement('beforeend', elWithShavedText);
|
|
styles.height = heightStyle;
|
|
styles.maxHeight = maxHeightStyle;
|
|
}
|
|
}
|
|
|
|
/* harmony default export */ __webpack_exports__["default"] = (shave);
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/tippy.js/esm/index.all.js":
|
|
/*!************************************************!*\
|
|
!*** ./node_modules/tippy.js/esm/index.all.js ***!
|
|
\************************************************/
|
|
/*! exports provided: default */
|
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
|
|
"use strict";
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony import */ var popper_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! popper.js */ "./node_modules/popper.js/dist/esm/popper.js");
|
|
/**!
|
|
* tippy.js v4.3.5
|
|
* (c) 2017-2019 atomiks
|
|
* MIT License
|
|
*/
|
|
|
|
var css = ".tippy-iOS{cursor:pointer!important;-webkit-tap-highlight-color:transparent}.tippy-popper{transition-timing-function:cubic-bezier(.165,.84,.44,1);max-width:calc(100% - 8px);pointer-events:none;outline:0}.tippy-popper[x-placement^=top] .tippy-backdrop{border-radius:40% 40% 0 0}.tippy-popper[x-placement^=top] .tippy-roundarrow{bottom:-7px;bottom:-6.5px;-webkit-transform-origin:50% 0;transform-origin:50% 0;margin:0 3px}.tippy-popper[x-placement^=top] .tippy-roundarrow svg{position:absolute;left:0;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.tippy-popper[x-placement^=top] .tippy-arrow{border-top:8px solid #333;border-right:8px solid transparent;border-left:8px solid transparent;bottom:-7px;margin:0 3px;-webkit-transform-origin:50% 0;transform-origin:50% 0}.tippy-popper[x-placement^=top] .tippy-backdrop{-webkit-transform-origin:0 25%;transform-origin:0 25%}.tippy-popper[x-placement^=top] .tippy-backdrop[data-state=visible]{-webkit-transform:scale(1) translate(-50%,-55%);transform:scale(1) translate(-50%,-55%)}.tippy-popper[x-placement^=top] .tippy-backdrop[data-state=hidden]{-webkit-transform:scale(.2) translate(-50%,-45%);transform:scale(.2) translate(-50%,-45%);opacity:0}.tippy-popper[x-placement^=top] [data-animation=shift-toward][data-state=visible]{-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=shift-toward][data-state=hidden]{opacity:0;-webkit-transform:translateY(-20px);transform:translateY(-20px)}.tippy-popper[x-placement^=top] [data-animation=perspective]{-webkit-transform-origin:bottom;transform-origin:bottom}.tippy-popper[x-placement^=top] [data-animation=perspective][data-state=visible]{-webkit-transform:perspective(700px) translateY(-10px);transform:perspective(700px) translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=perspective][data-state=hidden]{opacity:0;-webkit-transform:perspective(700px) rotateX(60deg);transform:perspective(700px) rotateX(60deg)}.tippy-popper[x-placement^=top] [data-animation=fade][data-state=visible]{-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=fade][data-state=hidden]{opacity:0;-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=shift-away][data-state=visible]{-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=shift-away][data-state=hidden]{opacity:0}.tippy-popper[x-placement^=top] [data-animation=scale]{-webkit-transform-origin:bottom;transform-origin:bottom}.tippy-popper[x-placement^=top] [data-animation=scale][data-state=visible]{-webkit-transform:translateY(-10px);transform:translateY(-10px)}.tippy-popper[x-placement^=top] [data-animation=scale][data-state=hidden]{opacity:0;-webkit-transform:translateY(-10px) scale(.5);transform:translateY(-10px) scale(.5)}.tippy-popper[x-placement^=bottom] .tippy-backdrop{border-radius:0 0 30% 30%}.tippy-popper[x-placement^=bottom] .tippy-roundarrow{top:-7px;-webkit-transform-origin:50% 100%;transform-origin:50% 100%;margin:0 3px}.tippy-popper[x-placement^=bottom] .tippy-roundarrow svg{position:absolute;left:0}.tippy-popper[x-placement^=bottom] .tippy-arrow{border-bottom:8px solid #333;border-right:8px solid transparent;border-left:8px solid transparent;top:-7px;margin:0 3px;-webkit-transform-origin:50% 100%;transform-origin:50% 100%}.tippy-popper[x-placement^=bottom] .tippy-backdrop{-webkit-transform-origin:0 -50%;transform-origin:0 -50%}.tippy-popper[x-placement^=bottom] .tippy-backdrop[data-state=visible]{-webkit-transform:scale(1) translate(-50%,-45%);transform:scale(1) translate(-50%,-45%)}.tippy-popper[x-placement^=bottom] .tippy-backdrop[data-state=hidden]{-webkit-transform:scale(.2) translate(-50%);transform:scale(.2) translate(-50%);opacity:0}.tippy-popper[x-placement^=bottom] [data-animation=shift-toward][data-state=visible]{-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=shift-toward][data-state=hidden]{opacity:0;-webkit-transform:translateY(20px);transform:translateY(20px)}.tippy-popper[x-placement^=bottom] [data-animation=perspective]{-webkit-transform-origin:top;transform-origin:top}.tippy-popper[x-placement^=bottom] [data-animation=perspective][data-state=visible]{-webkit-transform:perspective(700px) translateY(10px);transform:perspective(700px) translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=perspective][data-state=hidden]{opacity:0;-webkit-transform:perspective(700px) rotateX(-60deg);transform:perspective(700px) rotateX(-60deg)}.tippy-popper[x-placement^=bottom] [data-animation=fade][data-state=visible]{-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=fade][data-state=hidden]{opacity:0;-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=shift-away][data-state=visible]{-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=shift-away][data-state=hidden]{opacity:0}.tippy-popper[x-placement^=bottom] [data-animation=scale]{-webkit-transform-origin:top;transform-origin:top}.tippy-popper[x-placement^=bottom] [data-animation=scale][data-state=visible]{-webkit-transform:translateY(10px);transform:translateY(10px)}.tippy-popper[x-placement^=bottom] [data-animation=scale][data-state=hidden]{opacity:0;-webkit-transform:translateY(10px) scale(.5);transform:translateY(10px) scale(.5)}.tippy-popper[x-placement^=left] .tippy-backdrop{border-radius:50% 0 0 50%}.tippy-popper[x-placement^=left] .tippy-roundarrow{right:-12px;-webkit-transform-origin:33.33333333% 50%;transform-origin:33.33333333% 50%;margin:3px 0}.tippy-popper[x-placement^=left] .tippy-roundarrow svg{position:absolute;left:0;-webkit-transform:rotate(90deg);transform:rotate(90deg)}.tippy-popper[x-placement^=left] .tippy-arrow{border-left:8px solid #333;border-top:8px solid transparent;border-bottom:8px solid transparent;right:-7px;margin:3px 0;-webkit-transform-origin:0 50%;transform-origin:0 50%}.tippy-popper[x-placement^=left] .tippy-backdrop{-webkit-transform-origin:50% 0;transform-origin:50% 0}.tippy-popper[x-placement^=left] .tippy-backdrop[data-state=visible]{-webkit-transform:scale(1) translate(-50%,-50%);transform:scale(1) translate(-50%,-50%)}.tippy-popper[x-placement^=left] .tippy-backdrop[data-state=hidden]{-webkit-transform:scale(.2) translate(-75%,-50%);transform:scale(.2) translate(-75%,-50%);opacity:0}.tippy-popper[x-placement^=left] [data-animation=shift-toward][data-state=visible]{-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=shift-toward][data-state=hidden]{opacity:0;-webkit-transform:translateX(-20px);transform:translateX(-20px)}.tippy-popper[x-placement^=left] [data-animation=perspective]{-webkit-transform-origin:right;transform-origin:right}.tippy-popper[x-placement^=left] [data-animation=perspective][data-state=visible]{-webkit-transform:perspective(700px) translateX(-10px);transform:perspective(700px) translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=perspective][data-state=hidden]{opacity:0;-webkit-transform:perspective(700px) rotateY(-60deg);transform:perspective(700px) rotateY(-60deg)}.tippy-popper[x-placement^=left] [data-animation=fade][data-state=visible]{-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=fade][data-state=hidden]{opacity:0;-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=shift-away][data-state=visible]{-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=shift-away][data-state=hidden]{opacity:0}.tippy-popper[x-placement^=left] [data-animation=scale]{-webkit-transform-origin:right;transform-origin:right}.tippy-popper[x-placement^=left] [data-animation=scale][data-state=visible]{-webkit-transform:translateX(-10px);transform:translateX(-10px)}.tippy-popper[x-placement^=left] [data-animation=scale][data-state=hidden]{opacity:0;-webkit-transform:translateX(-10px) scale(.5);transform:translateX(-10px) scale(.5)}.tippy-popper[x-placement^=right] .tippy-backdrop{border-radius:0 50% 50% 0}.tippy-popper[x-placement^=right] .tippy-roundarrow{left:-12px;-webkit-transform-origin:66.66666666% 50%;transform-origin:66.66666666% 50%;margin:3px 0}.tippy-popper[x-placement^=right] .tippy-roundarrow svg{position:absolute;left:0;-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.tippy-popper[x-placement^=right] .tippy-arrow{border-right:8px solid #333;border-top:8px solid transparent;border-bottom:8px solid transparent;left:-7px;margin:3px 0;-webkit-transform-origin:100% 50%;transform-origin:100% 50%}.tippy-popper[x-placement^=right] .tippy-backdrop{-webkit-transform-origin:-50% 0;transform-origin:-50% 0}.tippy-popper[x-placement^=right] .tippy-backdrop[data-state=visible]{-webkit-transform:scale(1) translate(-50%,-50%);transform:scale(1) translate(-50%,-50%)}.tippy-popper[x-placement^=right] .tippy-backdrop[data-state=hidden]{-webkit-transform:scale(.2) translate(-25%,-50%);transform:scale(.2) translate(-25%,-50%);opacity:0}.tippy-popper[x-placement^=right] [data-animation=shift-toward][data-state=visible]{-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=shift-toward][data-state=hidden]{opacity:0;-webkit-transform:translateX(20px);transform:translateX(20px)}.tippy-popper[x-placement^=right] [data-animation=perspective]{-webkit-transform-origin:left;transform-origin:left}.tippy-popper[x-placement^=right] [data-animation=perspective][data-state=visible]{-webkit-transform:perspective(700px) translateX(10px);transform:perspective(700px) translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=perspective][data-state=hidden]{opacity:0;-webkit-transform:perspective(700px) rotateY(60deg);transform:perspective(700px) rotateY(60deg)}.tippy-popper[x-placement^=right] [data-animation=fade][data-state=visible]{-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=fade][data-state=hidden]{opacity:0;-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=shift-away][data-state=visible]{-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=shift-away][data-state=hidden]{opacity:0}.tippy-popper[x-placement^=right] [data-animation=scale]{-webkit-transform-origin:left;transform-origin:left}.tippy-popper[x-placement^=right] [data-animation=scale][data-state=visible]{-webkit-transform:translateX(10px);transform:translateX(10px)}.tippy-popper[x-placement^=right] [data-animation=scale][data-state=hidden]{opacity:0;-webkit-transform:translateX(10px) scale(.5);transform:translateX(10px) scale(.5)}.tippy-tooltip{position:relative;color:#fff;border-radius:.25rem;font-size:.875rem;padding:.3125rem .5625rem;line-height:1.4;text-align:center;background-color:#333}.tippy-tooltip[data-size=small]{padding:.1875rem .375rem;font-size:.75rem}.tippy-tooltip[data-size=large]{padding:.375rem .75rem;font-size:1rem}.tippy-tooltip[data-animatefill]{overflow:hidden;background-color:initial}.tippy-tooltip[data-interactive],.tippy-tooltip[data-interactive] .tippy-roundarrow path{pointer-events:auto}.tippy-tooltip[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-tooltip[data-inertia][data-state=hidden]{transition-timing-function:ease}.tippy-arrow,.tippy-roundarrow{position:absolute;width:0;height:0}.tippy-roundarrow{width:18px;height:7px;fill:#333;pointer-events:none}.tippy-backdrop{position:absolute;background-color:#333;border-radius:50%;width:calc(110% + 2rem);left:50%;top:50%;z-index:-1;transition:all cubic-bezier(.46,.1,.52,.98);-webkit-backface-visibility:hidden;backface-visibility:hidden}.tippy-backdrop:after{content:\"\";float:left;padding-top:100%}.tippy-backdrop+.tippy-content{transition-property:opacity;will-change:opacity}.tippy-backdrop+.tippy-content[data-state=hidden]{opacity:0}";
|
|
|
|
function _extends() {
|
|
_extends = Object.assign || function (target) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
var source = arguments[i];
|
|
|
|
for (var key in source) {
|
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
target[key] = source[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
return target;
|
|
};
|
|
|
|
return _extends.apply(this, arguments);
|
|
}
|
|
|
|
var version = "4.3.5";
|
|
var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
var ua = isBrowser ? navigator.userAgent : '';
|
|
var isIE = /MSIE |Trident\//.test(ua);
|
|
var isUCBrowser = /UCBrowser\//.test(ua);
|
|
var isIOS = isBrowser && /iPhone|iPad|iPod/.test(navigator.platform) && !window.MSStream;
|
|
var defaultProps = {
|
|
a11y: true,
|
|
allowHTML: true,
|
|
animateFill: true,
|
|
animation: 'shift-away',
|
|
appendTo: function appendTo() {
|
|
return document.body;
|
|
},
|
|
aria: 'describedby',
|
|
arrow: false,
|
|
arrowType: 'sharp',
|
|
boundary: 'scrollParent',
|
|
content: '',
|
|
delay: 0,
|
|
distance: 10,
|
|
duration: [325, 275],
|
|
flip: true,
|
|
flipBehavior: 'flip',
|
|
flipOnUpdate: false,
|
|
followCursor: false,
|
|
hideOnClick: true,
|
|
ignoreAttributes: false,
|
|
inertia: false,
|
|
interactive: false,
|
|
interactiveBorder: 2,
|
|
interactiveDebounce: 0,
|
|
lazy: true,
|
|
maxWidth: 350,
|
|
multiple: false,
|
|
offset: 0,
|
|
onHidden: function onHidden() {},
|
|
onHide: function onHide() {},
|
|
onMount: function onMount() {},
|
|
onShow: function onShow() {},
|
|
onShown: function onShown() {},
|
|
onTrigger: function onTrigger() {},
|
|
placement: 'top',
|
|
popperOptions: {},
|
|
role: 'tooltip',
|
|
showOnInit: false,
|
|
size: 'regular',
|
|
sticky: false,
|
|
target: '',
|
|
theme: 'dark',
|
|
touch: true,
|
|
touchHold: false,
|
|
trigger: 'mouseenter focus',
|
|
triggerTarget: null,
|
|
updateDuration: 0,
|
|
wait: null,
|
|
zIndex: 9999
|
|
/**
|
|
* If the set() method encounters one of these, the popperInstance must be
|
|
* recreated
|
|
*/
|
|
|
|
};
|
|
var POPPER_INSTANCE_DEPENDENCIES = ['arrow', 'arrowType', 'boundary', 'distance', 'flip', 'flipBehavior', 'flipOnUpdate', 'offset', 'placement', 'popperOptions'];
|
|
var elementProto = isBrowser ? Element.prototype : {};
|
|
var matches = elementProto.matches || elementProto.matchesSelector || elementProto.webkitMatchesSelector || elementProto.mozMatchesSelector || elementProto.msMatchesSelector;
|
|
/**
|
|
* Ponyfill for Array.from - converts iterable values to an array
|
|
*/
|
|
|
|
function arrayFrom(value) {
|
|
return [].slice.call(value);
|
|
}
|
|
/**
|
|
* Ponyfill for Element.prototype.closest
|
|
*/
|
|
|
|
|
|
function closest(element, selector) {
|
|
return closestCallback(element, function (el) {
|
|
return matches.call(el, selector);
|
|
});
|
|
}
|
|
/**
|
|
* Works like Element.prototype.closest, but uses a callback instead
|
|
*/
|
|
|
|
|
|
function closestCallback(element, callback) {
|
|
while (element) {
|
|
if (callback(element)) {
|
|
return element;
|
|
}
|
|
|
|
element = element.parentElement;
|
|
}
|
|
|
|
return null;
|
|
} // Passive event listener config
|
|
|
|
|
|
var PASSIVE = {
|
|
passive: true // Popper `preventOverflow` padding
|
|
|
|
};
|
|
var PADDING = 4; // Popper attributes
|
|
// In Popper v2 these will be `data-*` instead of `x-*` to adhere to HTML5 spec
|
|
|
|
var PLACEMENT_ATTRIBUTE = 'x-placement';
|
|
var OUT_OF_BOUNDARIES_ATTRIBUTE = 'x-out-of-boundaries'; // Classes
|
|
|
|
var IOS_CLASS = "tippy-iOS";
|
|
var ACTIVE_CLASS = "tippy-active";
|
|
var POPPER_CLASS = "tippy-popper";
|
|
var TOOLTIP_CLASS = "tippy-tooltip";
|
|
var CONTENT_CLASS = "tippy-content";
|
|
var BACKDROP_CLASS = "tippy-backdrop";
|
|
var ARROW_CLASS = "tippy-arrow";
|
|
var ROUND_ARROW_CLASS = "tippy-roundarrow"; // Selectors
|
|
|
|
var POPPER_SELECTOR = ".".concat(POPPER_CLASS);
|
|
var TOOLTIP_SELECTOR = ".".concat(TOOLTIP_CLASS);
|
|
var CONTENT_SELECTOR = ".".concat(CONTENT_CLASS);
|
|
var BACKDROP_SELECTOR = ".".concat(BACKDROP_CLASS);
|
|
var ARROW_SELECTOR = ".".concat(ARROW_CLASS);
|
|
var ROUND_ARROW_SELECTOR = ".".concat(ROUND_ARROW_CLASS);
|
|
var isUsingTouch = false;
|
|
|
|
function onDocumentTouch() {
|
|
if (isUsingTouch) {
|
|
return;
|
|
}
|
|
|
|
isUsingTouch = true;
|
|
|
|
if (isIOS) {
|
|
document.body.classList.add(IOS_CLASS);
|
|
}
|
|
|
|
if (window.performance) {
|
|
document.addEventListener('mousemove', onDocumentMouseMove);
|
|
}
|
|
}
|
|
|
|
var lastMouseMoveTime = 0;
|
|
|
|
function onDocumentMouseMove() {
|
|
var now = performance.now(); // Chrome 60+ is 1 mousemove per animation frame, use 20ms time difference
|
|
|
|
if (now - lastMouseMoveTime < 20) {
|
|
isUsingTouch = false;
|
|
document.removeEventListener('mousemove', onDocumentMouseMove);
|
|
|
|
if (!isIOS) {
|
|
document.body.classList.remove(IOS_CLASS);
|
|
}
|
|
}
|
|
|
|
lastMouseMoveTime = now;
|
|
}
|
|
|
|
function onWindowBlur() {
|
|
var _document = document,
|
|
activeElement = _document.activeElement;
|
|
|
|
if (activeElement && activeElement.blur && activeElement._tippy) {
|
|
activeElement.blur();
|
|
}
|
|
}
|
|
/**
|
|
* Adds the needed global event listeners
|
|
*/
|
|
|
|
|
|
function bindGlobalEventListeners() {
|
|
document.addEventListener('touchstart', onDocumentTouch, PASSIVE);
|
|
window.addEventListener('blur', onWindowBlur);
|
|
}
|
|
|
|
var keys = Object.keys(defaultProps);
|
|
/**
|
|
* Returns an object of optional props from data-tippy-* attributes
|
|
*/
|
|
|
|
function getDataAttributeOptions(reference) {
|
|
return keys.reduce(function (acc, key) {
|
|
var valueAsString = (reference.getAttribute("data-tippy-".concat(key)) || '').trim();
|
|
|
|
if (!valueAsString) {
|
|
return acc;
|
|
}
|
|
|
|
if (key === 'content') {
|
|
acc[key] = valueAsString;
|
|
} else {
|
|
try {
|
|
acc[key] = JSON.parse(valueAsString);
|
|
} catch (e) {
|
|
acc[key] = valueAsString;
|
|
}
|
|
}
|
|
|
|
return acc;
|
|
}, {});
|
|
}
|
|
/**
|
|
* Polyfills the virtual reference (plain object) with Element.prototype props
|
|
* Mutating because DOM elements are mutated, adds `_tippy` property
|
|
*/
|
|
|
|
|
|
function polyfillElementPrototypeProperties(virtualReference) {
|
|
var polyfills = {
|
|
isVirtual: true,
|
|
attributes: virtualReference.attributes || {},
|
|
contains: function contains() {},
|
|
setAttribute: function setAttribute(key, value) {
|
|
virtualReference.attributes[key] = value;
|
|
},
|
|
getAttribute: function getAttribute(key) {
|
|
return virtualReference.attributes[key];
|
|
},
|
|
removeAttribute: function removeAttribute(key) {
|
|
delete virtualReference.attributes[key];
|
|
},
|
|
hasAttribute: function hasAttribute(key) {
|
|
return key in virtualReference.attributes;
|
|
},
|
|
addEventListener: function addEventListener() {},
|
|
removeEventListener: function removeEventListener() {},
|
|
classList: {
|
|
classNames: {},
|
|
add: function add(key) {
|
|
virtualReference.classList.classNames[key] = true;
|
|
},
|
|
remove: function remove(key) {
|
|
delete virtualReference.classList.classNames[key];
|
|
},
|
|
contains: function contains(key) {
|
|
return key in virtualReference.classList.classNames;
|
|
}
|
|
}
|
|
};
|
|
|
|
for (var key in polyfills) {
|
|
virtualReference[key] = polyfills[key];
|
|
}
|
|
}
|
|
/**
|
|
* Determines if a value is a "bare" virtual element (before mutations done
|
|
* by `polyfillElementPrototypeProperties()`). JSDOM elements show up as
|
|
* [object Object], we can check if the value is "element-like" if it has
|
|
* `addEventListener`
|
|
*/
|
|
|
|
|
|
function isBareVirtualElement(value) {
|
|
return {}.toString.call(value) === '[object Object]' && !value.addEventListener;
|
|
}
|
|
/**
|
|
* Determines if the value is a reference element
|
|
*/
|
|
|
|
|
|
function isReferenceElement(value) {
|
|
return !!value._tippy && !matches.call(value, POPPER_SELECTOR);
|
|
}
|
|
/**
|
|
* Safe .hasOwnProperty check, for prototype-less objects
|
|
*/
|
|
|
|
|
|
function hasOwnProperty(obj, key) {
|
|
return {}.hasOwnProperty.call(obj, key);
|
|
}
|
|
/**
|
|
* Returns an array of elements based on the value
|
|
*/
|
|
|
|
|
|
function getArrayOfElements(value) {
|
|
if (isSingular(value)) {
|
|
// TODO: VirtualReference is not compatible to type Element
|
|
return [value];
|
|
}
|
|
|
|
if (value instanceof NodeList) {
|
|
return arrayFrom(value);
|
|
}
|
|
|
|
if (Array.isArray(value)) {
|
|
return value;
|
|
}
|
|
|
|
try {
|
|
return arrayFrom(document.querySelectorAll(value));
|
|
} catch (e) {
|
|
return [];
|
|
}
|
|
}
|
|
/**
|
|
* Returns a value at a given index depending on if it's an array or number
|
|
*/
|
|
|
|
|
|
function getValue(value, index, defaultValue) {
|
|
if (Array.isArray(value)) {
|
|
var v = value[index];
|
|
return v == null ? defaultValue : v;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
/**
|
|
* Debounce utility. To avoid bloating bundle size, we're only passing 1
|
|
* argument here, a more generic function would pass all arguments. Only
|
|
* `onMouseMove` uses this which takes the event object for now.
|
|
*/
|
|
|
|
|
|
function debounce(fn, ms) {
|
|
// Avoid wrapping in `setTimeout` if ms is 0 anyway
|
|
if (ms === 0) {
|
|
return fn;
|
|
}
|
|
|
|
var timeout;
|
|
return function (arg) {
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(function () {
|
|
fn(arg);
|
|
}, ms);
|
|
};
|
|
}
|
|
/**
|
|
* Prevents errors from being thrown while accessing nested modifier objects
|
|
* in `popperOptions`
|
|
*/
|
|
|
|
|
|
function getModifier(obj, key) {
|
|
return obj && obj.modifiers && obj.modifiers[key];
|
|
}
|
|
/**
|
|
* Determines if an array or string includes a value
|
|
*/
|
|
|
|
|
|
function includes(a, b) {
|
|
return a.indexOf(b) > -1;
|
|
}
|
|
/**
|
|
* Determines if the value is a real element
|
|
*/
|
|
|
|
|
|
function isRealElement(value) {
|
|
return value instanceof Element;
|
|
}
|
|
/**
|
|
* Determines if the value is singular-like
|
|
*/
|
|
|
|
|
|
function isSingular(value) {
|
|
return !!(value && hasOwnProperty(value, 'isVirtual')) || isRealElement(value);
|
|
}
|
|
/**
|
|
* Firefox extensions don't allow setting .innerHTML directly, this will trick it
|
|
*/
|
|
|
|
|
|
function innerHTML() {
|
|
return 'innerHTML';
|
|
}
|
|
/**
|
|
* Evaluates a function if one, or returns the value
|
|
*/
|
|
|
|
|
|
function invokeWithArgsOrReturn(value, args) {
|
|
return typeof value === 'function' ? value.apply(null, args) : value;
|
|
}
|
|
/**
|
|
* Sets a popperInstance `flip` modifier's enabled state
|
|
*/
|
|
|
|
|
|
function setFlipModifierEnabled(modifiers, value) {
|
|
modifiers.filter(function (m) {
|
|
return m.name === 'flip';
|
|
})[0].enabled = value;
|
|
}
|
|
/**
|
|
* Determines if an element can receive focus
|
|
* Always returns true for virtual objects
|
|
*/
|
|
|
|
|
|
function canReceiveFocus(element) {
|
|
return isRealElement(element) ? matches.call(element, 'a[href],area[href],button,details,input,textarea,select,iframe,[tabindex]') && !element.hasAttribute('disabled') : true;
|
|
}
|
|
/**
|
|
* Returns a new `div` element
|
|
*/
|
|
|
|
|
|
function div() {
|
|
return document.createElement('div');
|
|
}
|
|
/**
|
|
* Applies a transition duration to a list of elements
|
|
*/
|
|
|
|
|
|
function setTransitionDuration(els, value) {
|
|
els.forEach(function (el) {
|
|
if (el) {
|
|
el.style.transitionDuration = "".concat(value, "ms");
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Sets the visibility state to elements so they can begin to transition
|
|
*/
|
|
|
|
|
|
function setVisibilityState(els, state) {
|
|
els.forEach(function (el) {
|
|
if (el) {
|
|
el.setAttribute('data-state', state);
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Evaluates the props object by merging data attributes and
|
|
* disabling conflicting options where necessary
|
|
*/
|
|
|
|
|
|
function evaluateProps(reference, props) {
|
|
var out = _extends({}, props, {
|
|
content: invokeWithArgsOrReturn(props.content, [reference])
|
|
}, props.ignoreAttributes ? {} : getDataAttributeOptions(reference));
|
|
|
|
if (out.arrow || isUCBrowser) {
|
|
out.animateFill = false;
|
|
}
|
|
|
|
return out;
|
|
}
|
|
/**
|
|
* Validates an object of options with the valid default props object
|
|
*/
|
|
|
|
|
|
function validateOptions(options, defaultProps) {
|
|
Object.keys(options).forEach(function (option) {
|
|
if (!hasOwnProperty(defaultProps, option)) {
|
|
throw new Error("[tippy]: `".concat(option, "` is not a valid option"));
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Sets the innerHTML of an element
|
|
*/
|
|
|
|
|
|
function setInnerHTML(element, html) {
|
|
element[innerHTML()] = isRealElement(html) ? html[innerHTML()] : html;
|
|
}
|
|
/**
|
|
* Sets the content of a tooltip
|
|
*/
|
|
|
|
|
|
function setContent(contentEl, props) {
|
|
if (isRealElement(props.content)) {
|
|
setInnerHTML(contentEl, '');
|
|
contentEl.appendChild(props.content);
|
|
} else if (typeof props.content !== 'function') {
|
|
var key = props.allowHTML ? 'innerHTML' : 'textContent';
|
|
contentEl[key] = props.content;
|
|
}
|
|
}
|
|
/**
|
|
* Returns the child elements of a popper element
|
|
*/
|
|
|
|
|
|
function getChildren(popper) {
|
|
return {
|
|
tooltip: popper.querySelector(TOOLTIP_SELECTOR),
|
|
backdrop: popper.querySelector(BACKDROP_SELECTOR),
|
|
content: popper.querySelector(CONTENT_SELECTOR),
|
|
arrow: popper.querySelector(ARROW_SELECTOR) || popper.querySelector(ROUND_ARROW_SELECTOR)
|
|
};
|
|
}
|
|
/**
|
|
* Adds `data-inertia` attribute
|
|
*/
|
|
|
|
|
|
function addInertia(tooltip) {
|
|
tooltip.setAttribute('data-inertia', '');
|
|
}
|
|
/**
|
|
* Removes `data-inertia` attribute
|
|
*/
|
|
|
|
|
|
function removeInertia(tooltip) {
|
|
tooltip.removeAttribute('data-inertia');
|
|
}
|
|
/**
|
|
* Creates an arrow element and returns it
|
|
*/
|
|
|
|
|
|
function createArrowElement(arrowType) {
|
|
var arrow = div();
|
|
|
|
if (arrowType === 'round') {
|
|
arrow.className = ROUND_ARROW_CLASS;
|
|
setInnerHTML(arrow, '<svg viewBox="0 0 18 7" xmlns="http://www.w3.org/2000/svg"><path d="M0 7s2.021-.015 5.253-4.218C6.584 1.051 7.797.007 9 0c1.203-.007 2.416 1.035 3.761 2.782C16.012 7.005 18 7 18 7H0z"/></svg>');
|
|
} else {
|
|
arrow.className = ARROW_CLASS;
|
|
}
|
|
|
|
return arrow;
|
|
}
|
|
/**
|
|
* Creates a backdrop element and returns it
|
|
*/
|
|
|
|
|
|
function createBackdropElement() {
|
|
var backdrop = div();
|
|
backdrop.className = BACKDROP_CLASS;
|
|
backdrop.setAttribute('data-state', 'hidden');
|
|
return backdrop;
|
|
}
|
|
/**
|
|
* Adds interactive-related attributes
|
|
*/
|
|
|
|
|
|
function addInteractive(popper, tooltip) {
|
|
popper.setAttribute('tabindex', '-1');
|
|
tooltip.setAttribute('data-interactive', '');
|
|
}
|
|
/**
|
|
* Removes interactive-related attributes
|
|
*/
|
|
|
|
|
|
function removeInteractive(popper, tooltip) {
|
|
popper.removeAttribute('tabindex');
|
|
tooltip.removeAttribute('data-interactive');
|
|
}
|
|
/**
|
|
* Add/remove transitionend listener from tooltip
|
|
*/
|
|
|
|
|
|
function updateTransitionEndListener(tooltip, action, listener) {
|
|
// UC Browser hasn't adopted the `transitionend` event despite supporting
|
|
// unprefixed transitions...
|
|
var eventName = isUCBrowser && document.body.style.webkitTransition !== undefined ? 'webkitTransitionEnd' : 'transitionend';
|
|
tooltip[action + 'EventListener'](eventName, listener);
|
|
}
|
|
/**
|
|
* Returns the popper's placement, ignoring shifting (top-start, etc)
|
|
*/
|
|
|
|
|
|
function getBasicPlacement(popper) {
|
|
var fullPlacement = popper.getAttribute(PLACEMENT_ATTRIBUTE);
|
|
return fullPlacement ? fullPlacement.split('-')[0] : '';
|
|
}
|
|
/**
|
|
* Triggers reflow
|
|
*/
|
|
|
|
|
|
function reflow(popper) {
|
|
void popper.offsetHeight;
|
|
}
|
|
/**
|
|
* Adds/removes theme from tooltip's classList
|
|
*/
|
|
|
|
|
|
function updateTheme(tooltip, action, theme) {
|
|
theme.split(' ').forEach(function (themeName) {
|
|
tooltip.classList[action](themeName + '-theme');
|
|
});
|
|
}
|
|
/**
|
|
* Constructs the popper element and returns it
|
|
*/
|
|
|
|
|
|
function createPopperElement(id, props) {
|
|
var popper = div();
|
|
popper.className = POPPER_CLASS;
|
|
popper.id = "tippy-".concat(id);
|
|
popper.style.zIndex = '' + props.zIndex;
|
|
popper.style.position = 'absolute';
|
|
popper.style.top = '0';
|
|
popper.style.left = '0';
|
|
|
|
if (props.role) {
|
|
popper.setAttribute('role', props.role);
|
|
}
|
|
|
|
var tooltip = div();
|
|
tooltip.className = TOOLTIP_CLASS;
|
|
tooltip.style.maxWidth = props.maxWidth + (typeof props.maxWidth === 'number' ? 'px' : '');
|
|
tooltip.setAttribute('data-size', props.size);
|
|
tooltip.setAttribute('data-animation', props.animation);
|
|
tooltip.setAttribute('data-state', 'hidden');
|
|
updateTheme(tooltip, 'add', props.theme);
|
|
var content = div();
|
|
content.className = CONTENT_CLASS;
|
|
content.setAttribute('data-state', 'hidden');
|
|
|
|
if (props.interactive) {
|
|
addInteractive(popper, tooltip);
|
|
}
|
|
|
|
if (props.arrow) {
|
|
tooltip.appendChild(createArrowElement(props.arrowType));
|
|
}
|
|
|
|
if (props.animateFill) {
|
|
tooltip.appendChild(createBackdropElement());
|
|
tooltip.setAttribute('data-animatefill', '');
|
|
}
|
|
|
|
if (props.inertia) {
|
|
addInertia(tooltip);
|
|
}
|
|
|
|
setContent(content, props);
|
|
tooltip.appendChild(content);
|
|
popper.appendChild(tooltip);
|
|
return popper;
|
|
}
|
|
/**
|
|
* Updates the popper element based on the new props
|
|
*/
|
|
|
|
|
|
function updatePopperElement(popper, prevProps, nextProps) {
|
|
var _getChildren = getChildren(popper),
|
|
tooltip = _getChildren.tooltip,
|
|
content = _getChildren.content,
|
|
backdrop = _getChildren.backdrop,
|
|
arrow = _getChildren.arrow;
|
|
|
|
popper.style.zIndex = '' + nextProps.zIndex;
|
|
tooltip.setAttribute('data-size', nextProps.size);
|
|
tooltip.setAttribute('data-animation', nextProps.animation);
|
|
tooltip.style.maxWidth = nextProps.maxWidth + (typeof nextProps.maxWidth === 'number' ? 'px' : '');
|
|
|
|
if (nextProps.role) {
|
|
popper.setAttribute('role', nextProps.role);
|
|
} else {
|
|
popper.removeAttribute('role');
|
|
}
|
|
|
|
if (prevProps.content !== nextProps.content) {
|
|
setContent(content, nextProps);
|
|
} // animateFill
|
|
|
|
|
|
if (!prevProps.animateFill && nextProps.animateFill) {
|
|
tooltip.appendChild(createBackdropElement());
|
|
tooltip.setAttribute('data-animatefill', '');
|
|
} else if (prevProps.animateFill && !nextProps.animateFill) {
|
|
tooltip.removeChild(backdrop);
|
|
tooltip.removeAttribute('data-animatefill');
|
|
} // arrow
|
|
|
|
|
|
if (!prevProps.arrow && nextProps.arrow) {
|
|
tooltip.appendChild(createArrowElement(nextProps.arrowType));
|
|
} else if (prevProps.arrow && !nextProps.arrow) {
|
|
tooltip.removeChild(arrow);
|
|
} // arrowType
|
|
|
|
|
|
if (prevProps.arrow && nextProps.arrow && prevProps.arrowType !== nextProps.arrowType) {
|
|
tooltip.replaceChild(createArrowElement(nextProps.arrowType), arrow);
|
|
} // interactive
|
|
|
|
|
|
if (!prevProps.interactive && nextProps.interactive) {
|
|
addInteractive(popper, tooltip);
|
|
} else if (prevProps.interactive && !nextProps.interactive) {
|
|
removeInteractive(popper, tooltip);
|
|
} // inertia
|
|
|
|
|
|
if (!prevProps.inertia && nextProps.inertia) {
|
|
addInertia(tooltip);
|
|
} else if (prevProps.inertia && !nextProps.inertia) {
|
|
removeInertia(tooltip);
|
|
} // theme
|
|
|
|
|
|
if (prevProps.theme !== nextProps.theme) {
|
|
updateTheme(tooltip, 'remove', prevProps.theme);
|
|
updateTheme(tooltip, 'add', nextProps.theme);
|
|
}
|
|
}
|
|
/**
|
|
* Hides all visible poppers on the document
|
|
*/
|
|
|
|
|
|
function hideAll() {
|
|
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
|
excludedReferenceOrInstance = _ref.exclude,
|
|
duration = _ref.duration;
|
|
|
|
arrayFrom(document.querySelectorAll(POPPER_SELECTOR)).forEach(function (popper) {
|
|
var instance = popper._tippy;
|
|
|
|
if (instance) {
|
|
var isExcluded = false;
|
|
|
|
if (excludedReferenceOrInstance) {
|
|
isExcluded = isReferenceElement(excludedReferenceOrInstance) ? instance.reference === excludedReferenceOrInstance : popper === excludedReferenceOrInstance.popper;
|
|
}
|
|
|
|
if (!isExcluded) {
|
|
instance.hide(duration);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Determines if the mouse cursor is outside of the popper's interactive border
|
|
* region
|
|
*/
|
|
|
|
|
|
function isCursorOutsideInteractiveBorder(popperPlacement, popperRect, event, props) {
|
|
if (!popperPlacement) {
|
|
return true;
|
|
}
|
|
|
|
var x = event.clientX,
|
|
y = event.clientY;
|
|
var interactiveBorder = props.interactiveBorder,
|
|
distance = props.distance;
|
|
var exceedsTop = popperRect.top - y > (popperPlacement === 'top' ? interactiveBorder + distance : interactiveBorder);
|
|
var exceedsBottom = y - popperRect.bottom > (popperPlacement === 'bottom' ? interactiveBorder + distance : interactiveBorder);
|
|
var exceedsLeft = popperRect.left - x > (popperPlacement === 'left' ? interactiveBorder + distance : interactiveBorder);
|
|
var exceedsRight = x - popperRect.right > (popperPlacement === 'right' ? interactiveBorder + distance : interactiveBorder);
|
|
return exceedsTop || exceedsBottom || exceedsLeft || exceedsRight;
|
|
}
|
|
/**
|
|
* Returns the distance offset, taking into account the default offset due to
|
|
* the transform: translate() rule (10px) in CSS
|
|
*/
|
|
|
|
|
|
function getOffsetDistanceInPx(distance) {
|
|
return -(distance - 10) + 'px';
|
|
}
|
|
|
|
var idCounter = 1; // Workaround for IE11's lack of new MouseEvent constructor
|
|
|
|
var mouseMoveListeners = [];
|
|
/**
|
|
* Creates and returns a Tippy object. We're using a closure pattern instead of
|
|
* a class so that the exposed object API is clean without private members
|
|
* prefixed with `_`.
|
|
*/
|
|
|
|
function createTippy(reference, collectionProps) {
|
|
var props = evaluateProps(reference, collectionProps); // If the reference shouldn't have multiple tippys, return null early
|
|
|
|
if (!props.multiple && reference._tippy) {
|
|
return null;
|
|
}
|
|
/* ======================= 🔒 Private members 🔒 ======================= */
|
|
|
|
|
|
var lastTriggerEventType;
|
|
var lastMouseMoveEvent;
|
|
var showTimeoutId;
|
|
var hideTimeoutId;
|
|
var scheduleHideAnimationFrameId;
|
|
var isScheduledToShow = false;
|
|
var isBeingDestroyed = false;
|
|
var previousPlacement;
|
|
var wasVisibleDuringPreviousUpdate = false;
|
|
var hasMountCallbackRun = false;
|
|
var currentMountCallback;
|
|
var currentTransitionEndListener;
|
|
var listeners = [];
|
|
var currentComputedPadding;
|
|
var debouncedOnMouseMove = debounce(onMouseMove, props.interactiveDebounce);
|
|
/* ======================= 🔑 Public members 🔑 ======================= */
|
|
|
|
var id = idCounter++;
|
|
var popper = createPopperElement(id, props);
|
|
var popperChildren = getChildren(popper);
|
|
var popperInstance = null;
|
|
var state = {
|
|
// Is the instance currently enabled?
|
|
isEnabled: true,
|
|
// Is the tippy currently showing and not transitioning out?
|
|
isVisible: false,
|
|
// Has the instance been destroyed?
|
|
isDestroyed: false,
|
|
// Is the tippy currently mounted to the DOM?
|
|
isMounted: false,
|
|
// Has the tippy finished transitioning in?
|
|
isShown: false
|
|
};
|
|
var instance = {
|
|
// properties
|
|
id: id,
|
|
reference: reference,
|
|
popper: popper,
|
|
popperChildren: popperChildren,
|
|
popperInstance: popperInstance,
|
|
props: props,
|
|
state: state,
|
|
// methods
|
|
clearDelayTimeouts: clearDelayTimeouts,
|
|
set: set,
|
|
setContent: setContent,
|
|
show: show,
|
|
hide: hide,
|
|
enable: enable,
|
|
disable: disable,
|
|
destroy: destroy
|
|
/* ==================== Initial instance mutations =================== */
|
|
|
|
};
|
|
reference._tippy = instance;
|
|
popper._tippy = instance;
|
|
addTriggersToReference();
|
|
|
|
if (!props.lazy) {
|
|
createPopperInstance();
|
|
}
|
|
|
|
if (props.showOnInit) {
|
|
scheduleShow();
|
|
} // Ensure the event listeners target can receive focus
|
|
|
|
|
|
if (props.a11y && !props.target && !canReceiveFocus(getEventListenersTarget())) {
|
|
getEventListenersTarget().setAttribute('tabindex', '0');
|
|
} // Prevent a tippy with a delay from hiding if the cursor left then returned
|
|
// before it started hiding
|
|
|
|
|
|
popper.addEventListener('mouseenter', function (event) {
|
|
if (instance.props.interactive && instance.state.isVisible && lastTriggerEventType === 'mouseenter') {
|
|
// We don't want props.onTrigger() to be called here, since the `event`
|
|
// object is not related to the reference element
|
|
scheduleShow(event, true);
|
|
}
|
|
});
|
|
popper.addEventListener('mouseleave', function () {
|
|
if (instance.props.interactive && lastTriggerEventType === 'mouseenter') {
|
|
document.addEventListener('mousemove', debouncedOnMouseMove);
|
|
}
|
|
});
|
|
return instance;
|
|
/* ======================= 🔒 Private methods 🔒 ======================= */
|
|
|
|
/**
|
|
* Removes the follow cursor listener
|
|
*/
|
|
|
|
function removeFollowCursorListener() {
|
|
document.removeEventListener('mousemove', positionVirtualReferenceNearCursor);
|
|
}
|
|
/**
|
|
* Cleans up interactive mouse listeners
|
|
*/
|
|
|
|
|
|
function cleanupInteractiveMouseListeners() {
|
|
document.body.removeEventListener('mouseleave', scheduleHide);
|
|
document.removeEventListener('mousemove', debouncedOnMouseMove);
|
|
mouseMoveListeners = mouseMoveListeners.filter(function (listener) {
|
|
return listener !== debouncedOnMouseMove;
|
|
});
|
|
}
|
|
/**
|
|
* Returns correct target used for event listeners
|
|
*/
|
|
|
|
|
|
function getEventListenersTarget() {
|
|
return instance.props.triggerTarget || reference;
|
|
}
|
|
/**
|
|
* Adds the document click event listener for the instance
|
|
*/
|
|
|
|
|
|
function addDocumentClickListener() {
|
|
document.addEventListener('click', onDocumentClick, true);
|
|
}
|
|
/**
|
|
* Removes the document click event listener for the instance
|
|
*/
|
|
|
|
|
|
function removeDocumentClickListener() {
|
|
document.removeEventListener('click', onDocumentClick, true);
|
|
}
|
|
/**
|
|
* Returns transitionable inner elements used in show/hide methods
|
|
*/
|
|
|
|
|
|
function getTransitionableElements() {
|
|
return [instance.popperChildren.tooltip, instance.popperChildren.backdrop, instance.popperChildren.content];
|
|
}
|
|
/**
|
|
* Determines if the instance is in `followCursor` mode.
|
|
* NOTE: in v5, touch devices will use `initial` behavior no matter the value.
|
|
*/
|
|
|
|
|
|
function getIsInLooseFollowCursorMode() {
|
|
var followCursor = instance.props.followCursor;
|
|
return followCursor && lastTriggerEventType !== 'focus' || isUsingTouch && followCursor === 'initial';
|
|
}
|
|
/**
|
|
* Updates the tooltip's position on each animation frame
|
|
*/
|
|
|
|
|
|
function makeSticky() {
|
|
setTransitionDuration([popper], isIE ? 0 : instance.props.updateDuration);
|
|
var prevRefRect = reference.getBoundingClientRect();
|
|
|
|
function updatePosition() {
|
|
var currentRefRect = reference.getBoundingClientRect(); // Only schedule an update if the reference rect has changed
|
|
|
|
if (prevRefRect.top !== currentRefRect.top || prevRefRect.right !== currentRefRect.right || prevRefRect.bottom !== currentRefRect.bottom || prevRefRect.left !== currentRefRect.left) {
|
|
instance.popperInstance.scheduleUpdate();
|
|
}
|
|
|
|
prevRefRect = currentRefRect;
|
|
|
|
if (instance.state.isMounted) {
|
|
requestAnimationFrame(updatePosition);
|
|
}
|
|
}
|
|
|
|
updatePosition();
|
|
}
|
|
/**
|
|
* Invokes a callback once the tooltip has fully transitioned out
|
|
*/
|
|
|
|
|
|
function onTransitionedOut(duration, callback) {
|
|
onTransitionEnd(duration, function () {
|
|
if (!instance.state.isVisible && popper.parentNode && popper.parentNode.contains(popper)) {
|
|
callback();
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Invokes a callback once the tooltip has fully transitioned in
|
|
*/
|
|
|
|
|
|
function onTransitionedIn(duration, callback) {
|
|
onTransitionEnd(duration, callback);
|
|
}
|
|
/**
|
|
* Invokes a callback once the tooltip's CSS transition ends
|
|
*/
|
|
|
|
|
|
function onTransitionEnd(duration, callback) {
|
|
var tooltip = instance.popperChildren.tooltip;
|
|
/**
|
|
* Listener added as the `transitionend` handler
|
|
*/
|
|
|
|
function listener(event) {
|
|
if (event.target === tooltip) {
|
|
updateTransitionEndListener(tooltip, 'remove', listener);
|
|
callback();
|
|
}
|
|
} // Make callback synchronous if duration is 0
|
|
// `transitionend` won't fire otherwise
|
|
|
|
|
|
if (duration === 0) {
|
|
return callback();
|
|
}
|
|
|
|
updateTransitionEndListener(tooltip, 'remove', currentTransitionEndListener);
|
|
updateTransitionEndListener(tooltip, 'add', listener);
|
|
currentTransitionEndListener = listener;
|
|
}
|
|
/**
|
|
* Adds an event listener to the reference and stores it in `listeners`
|
|
*/
|
|
|
|
|
|
function on(eventType, handler) {
|
|
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
getEventListenersTarget().addEventListener(eventType, handler, options);
|
|
listeners.push({
|
|
eventType: eventType,
|
|
handler: handler,
|
|
options: options
|
|
});
|
|
}
|
|
/**
|
|
* Adds event listeners to the reference based on the `trigger` prop
|
|
*/
|
|
|
|
|
|
function addTriggersToReference() {
|
|
if (instance.props.touchHold && !instance.props.target) {
|
|
on('touchstart', onTrigger, PASSIVE);
|
|
on('touchend', onMouseLeave, PASSIVE);
|
|
}
|
|
|
|
instance.props.trigger.trim().split(' ').forEach(function (eventType) {
|
|
if (eventType === 'manual') {
|
|
return;
|
|
} // Non-delegates
|
|
|
|
|
|
if (!instance.props.target) {
|
|
on(eventType, onTrigger);
|
|
|
|
switch (eventType) {
|
|
case 'mouseenter':
|
|
on('mouseleave', onMouseLeave);
|
|
break;
|
|
|
|
case 'focus':
|
|
on(isIE ? 'focusout' : 'blur', onBlur);
|
|
break;
|
|
}
|
|
} else {
|
|
// Delegates
|
|
switch (eventType) {
|
|
case 'mouseenter':
|
|
on('mouseover', onDelegateShow);
|
|
on('mouseout', onDelegateHide);
|
|
break;
|
|
|
|
case 'focus':
|
|
on('focusin', onDelegateShow);
|
|
on('focusout', onDelegateHide);
|
|
break;
|
|
|
|
case 'click':
|
|
on(eventType, onDelegateShow);
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
/**
|
|
* Removes event listeners from the reference
|
|
*/
|
|
|
|
|
|
function removeTriggersFromReference() {
|
|
listeners.forEach(function (_ref) {
|
|
var eventType = _ref.eventType,
|
|
handler = _ref.handler,
|
|
options = _ref.options;
|
|
getEventListenersTarget().removeEventListener(eventType, handler, options);
|
|
});
|
|
listeners = [];
|
|
}
|
|
/**
|
|
* Positions the virtual reference near the cursor
|
|
*/
|
|
|
|
|
|
function positionVirtualReferenceNearCursor(event) {
|
|
var _lastMouseMoveEvent = lastMouseMoveEvent = event,
|
|
x = _lastMouseMoveEvent.clientX,
|
|
y = _lastMouseMoveEvent.clientY; // Gets set once popperInstance `onCreate` has been called
|
|
|
|
|
|
if (!currentComputedPadding) {
|
|
return;
|
|
} // If the instance is interactive, avoid updating the position unless it's
|
|
// over the reference element
|
|
|
|
|
|
var isCursorOverReference = closestCallback(event.target, function (el) {
|
|
return el === reference;
|
|
});
|
|
var rect = reference.getBoundingClientRect();
|
|
var followCursor = instance.props.followCursor;
|
|
var isHorizontal = followCursor === 'horizontal';
|
|
var isVertical = followCursor === 'vertical'; // The virtual reference needs some size to prevent itself from overflowing
|
|
|
|
var isVerticalPlacement = includes(['top', 'bottom'], getBasicPlacement(popper));
|
|
var fullPlacement = popper.getAttribute(PLACEMENT_ATTRIBUTE);
|
|
var isVariation = fullPlacement ? !!fullPlacement.split('-')[1] : false;
|
|
var size = isVerticalPlacement ? popper.offsetWidth : popper.offsetHeight;
|
|
var halfSize = size / 2;
|
|
var verticalIncrease = isVerticalPlacement ? 0 : isVariation ? size : halfSize;
|
|
var horizontalIncrease = isVerticalPlacement ? isVariation ? size : halfSize : 0;
|
|
|
|
if (isCursorOverReference || !instance.props.interactive) {
|
|
instance.popperInstance.reference = _extends({}, instance.popperInstance.reference, {
|
|
// This will exist in next Popper.js feature release to fix #532
|
|
// @ts-ignore
|
|
referenceNode: reference,
|
|
// These `client` values don't get used by Popper.js if they are 0
|
|
clientWidth: 0,
|
|
clientHeight: 0,
|
|
getBoundingClientRect: function getBoundingClientRect() {
|
|
return {
|
|
width: isVerticalPlacement ? size : 0,
|
|
height: isVerticalPlacement ? 0 : size,
|
|
top: (isHorizontal ? rect.top : y) - verticalIncrease,
|
|
bottom: (isHorizontal ? rect.bottom : y) + verticalIncrease,
|
|
left: (isVertical ? rect.left : x) - horizontalIncrease,
|
|
right: (isVertical ? rect.right : x) + horizontalIncrease
|
|
};
|
|
}
|
|
});
|
|
instance.popperInstance.update();
|
|
}
|
|
|
|
if (followCursor === 'initial' && instance.state.isVisible) {
|
|
removeFollowCursorListener();
|
|
}
|
|
}
|
|
/**
|
|
* Creates the tippy instance for a delegate when it's been triggered
|
|
*/
|
|
|
|
|
|
function createDelegateChildTippy(event) {
|
|
if (event) {
|
|
var targetEl = closest(event.target, instance.props.target);
|
|
|
|
if (targetEl && !targetEl._tippy) {
|
|
createTippy(targetEl, _extends({}, instance.props, {
|
|
content: invokeWithArgsOrReturn(collectionProps.content, [targetEl]),
|
|
appendTo: collectionProps.appendTo,
|
|
target: '',
|
|
showOnInit: true
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Event listener invoked upon trigger
|
|
*/
|
|
|
|
|
|
function onTrigger(event) {
|
|
if (!instance.state.isEnabled || isEventListenerStopped(event)) {
|
|
return;
|
|
}
|
|
|
|
if (!instance.state.isVisible) {
|
|
lastTriggerEventType = event.type;
|
|
|
|
if (event instanceof MouseEvent) {
|
|
lastMouseMoveEvent = event; // If scrolling, `mouseenter` events can be fired if the cursor lands
|
|
// over a new target, but `mousemove` events don't get fired. This
|
|
// causes interactive tooltips to get stuck open until the cursor is
|
|
// moved
|
|
|
|
mouseMoveListeners.forEach(function (listener) {
|
|
return listener(event);
|
|
});
|
|
}
|
|
} // Toggle show/hide when clicking click-triggered tooltips
|
|
|
|
|
|
if (event.type === 'click' && instance.props.hideOnClick !== false && instance.state.isVisible) {
|
|
scheduleHide();
|
|
} else {
|
|
scheduleShow(event);
|
|
}
|
|
}
|
|
/**
|
|
* Event listener used for interactive tooltips to detect when they should
|
|
* hide
|
|
*/
|
|
|
|
|
|
function onMouseMove(event) {
|
|
var isCursorOverPopper = closest(event.target, POPPER_SELECTOR) === popper;
|
|
var isCursorOverReference = closestCallback(event.target, function (el) {
|
|
return el === reference;
|
|
});
|
|
|
|
if (isCursorOverPopper || isCursorOverReference) {
|
|
return;
|
|
}
|
|
|
|
if (isCursorOutsideInteractiveBorder(getBasicPlacement(popper), popper.getBoundingClientRect(), event, instance.props)) {
|
|
cleanupInteractiveMouseListeners();
|
|
scheduleHide();
|
|
}
|
|
}
|
|
/**
|
|
* Event listener invoked upon mouseleave
|
|
*/
|
|
|
|
|
|
function onMouseLeave(event) {
|
|
if (isEventListenerStopped(event)) {
|
|
return;
|
|
}
|
|
|
|
if (instance.props.interactive) {
|
|
document.body.addEventListener('mouseleave', scheduleHide);
|
|
document.addEventListener('mousemove', debouncedOnMouseMove);
|
|
mouseMoveListeners.push(debouncedOnMouseMove);
|
|
return;
|
|
}
|
|
|
|
scheduleHide();
|
|
}
|
|
/**
|
|
* Event listener invoked upon blur
|
|
*/
|
|
|
|
|
|
function onBlur(event) {
|
|
if (event.target !== getEventListenersTarget()) {
|
|
return;
|
|
}
|
|
|
|
if (instance.props.interactive && event.relatedTarget && popper.contains(event.relatedTarget)) {
|
|
return;
|
|
}
|
|
|
|
scheduleHide();
|
|
}
|
|
/**
|
|
* Event listener invoked when a child target is triggered
|
|
*/
|
|
|
|
|
|
function onDelegateShow(event) {
|
|
if (closest(event.target, instance.props.target)) {
|
|
scheduleShow(event);
|
|
}
|
|
}
|
|
/**
|
|
* Event listener invoked when a child target should hide
|
|
*/
|
|
|
|
|
|
function onDelegateHide(event) {
|
|
if (closest(event.target, instance.props.target)) {
|
|
scheduleHide();
|
|
}
|
|
}
|
|
/**
|
|
* Determines if an event listener should stop further execution due to the
|
|
* `touchHold` option
|
|
*/
|
|
|
|
|
|
function isEventListenerStopped(event) {
|
|
var supportsTouch = 'ontouchstart' in window;
|
|
var isTouchEvent = includes(event.type, 'touch');
|
|
var touchHold = instance.props.touchHold;
|
|
return supportsTouch && isUsingTouch && touchHold && !isTouchEvent || isUsingTouch && !touchHold && isTouchEvent;
|
|
}
|
|
/**
|
|
* Runs the mount callback
|
|
*/
|
|
|
|
|
|
function runMountCallback() {
|
|
if (!hasMountCallbackRun && currentMountCallback) {
|
|
hasMountCallbackRun = true;
|
|
reflow(popper);
|
|
currentMountCallback();
|
|
}
|
|
}
|
|
/**
|
|
* Creates the popper instance for the instance
|
|
*/
|
|
|
|
|
|
function createPopperInstance() {
|
|
var popperOptions = instance.props.popperOptions;
|
|
var _instance$popperChild = instance.popperChildren,
|
|
tooltip = _instance$popperChild.tooltip,
|
|
arrow = _instance$popperChild.arrow;
|
|
var preventOverflowModifier = getModifier(popperOptions, 'preventOverflow');
|
|
|
|
function applyMutations(data) {
|
|
if (instance.props.flip && !instance.props.flipOnUpdate) {
|
|
if (data.flipped) {
|
|
instance.popperInstance.options.placement = data.placement;
|
|
}
|
|
|
|
setFlipModifierEnabled(instance.popperInstance.modifiers, false);
|
|
} // Apply all of the popper's attributes to the tootip node as well.
|
|
// Allows users to avoid using the .tippy-popper selector for themes.
|
|
|
|
|
|
tooltip.setAttribute(PLACEMENT_ATTRIBUTE, data.placement);
|
|
|
|
if (data.attributes[OUT_OF_BOUNDARIES_ATTRIBUTE] !== false) {
|
|
tooltip.setAttribute(OUT_OF_BOUNDARIES_ATTRIBUTE, '');
|
|
} else {
|
|
tooltip.removeAttribute(OUT_OF_BOUNDARIES_ATTRIBUTE);
|
|
} // Prevents a transition when changing placements (while tippy is visible)
|
|
// for scroll/resize updates
|
|
|
|
|
|
if (previousPlacement && previousPlacement !== data.placement && wasVisibleDuringPreviousUpdate) {
|
|
tooltip.style.transition = 'none';
|
|
requestAnimationFrame(function () {
|
|
tooltip.style.transition = '';
|
|
});
|
|
}
|
|
|
|
previousPlacement = data.placement;
|
|
wasVisibleDuringPreviousUpdate = instance.state.isVisible;
|
|
var basicPlacement = getBasicPlacement(popper);
|
|
var styles = tooltip.style; // Account for the `distance` offset
|
|
|
|
styles.top = styles.bottom = styles.left = styles.right = '';
|
|
styles[basicPlacement] = getOffsetDistanceInPx(instance.props.distance);
|
|
var padding = preventOverflowModifier && preventOverflowModifier.padding !== undefined ? preventOverflowModifier.padding : PADDING;
|
|
var isPaddingNumber = typeof padding === 'number';
|
|
|
|
var computedPadding = _extends({
|
|
top: isPaddingNumber ? padding : padding.top,
|
|
bottom: isPaddingNumber ? padding : padding.bottom,
|
|
left: isPaddingNumber ? padding : padding.left,
|
|
right: isPaddingNumber ? padding : padding.right
|
|
}, !isPaddingNumber && padding);
|
|
|
|
computedPadding[basicPlacement] = isPaddingNumber ? padding + instance.props.distance : (padding[basicPlacement] || 0) + instance.props.distance;
|
|
instance.popperInstance.modifiers.filter(function (m) {
|
|
return m.name === 'preventOverflow';
|
|
})[0].padding = computedPadding;
|
|
currentComputedPadding = computedPadding;
|
|
}
|
|
|
|
var config = _extends({
|
|
eventsEnabled: false,
|
|
placement: instance.props.placement
|
|
}, popperOptions, {
|
|
modifiers: _extends({}, popperOptions ? popperOptions.modifiers : {}, {
|
|
preventOverflow: _extends({
|
|
boundariesElement: instance.props.boundary,
|
|
padding: PADDING
|
|
}, preventOverflowModifier),
|
|
arrow: _extends({
|
|
element: arrow,
|
|
enabled: !!arrow
|
|
}, getModifier(popperOptions, 'arrow')),
|
|
flip: _extends({
|
|
enabled: instance.props.flip,
|
|
// The tooltip is offset by 10px from the popper in CSS,
|
|
// we need to account for its distance
|
|
padding: instance.props.distance + PADDING,
|
|
behavior: instance.props.flipBehavior
|
|
}, getModifier(popperOptions, 'flip')),
|
|
offset: _extends({
|
|
offset: instance.props.offset
|
|
}, getModifier(popperOptions, 'offset'))
|
|
}),
|
|
onCreate: function onCreate(data) {
|
|
applyMutations(data);
|
|
runMountCallback();
|
|
|
|
if (popperOptions && popperOptions.onCreate) {
|
|
popperOptions.onCreate(data);
|
|
}
|
|
},
|
|
onUpdate: function onUpdate(data) {
|
|
applyMutations(data);
|
|
runMountCallback();
|
|
|
|
if (popperOptions && popperOptions.onUpdate) {
|
|
popperOptions.onUpdate(data);
|
|
}
|
|
}
|
|
});
|
|
|
|
instance.popperInstance = new popper_js__WEBPACK_IMPORTED_MODULE_0__["default"](reference, popper, config);
|
|
}
|
|
/**
|
|
* Mounts the tooltip to the DOM
|
|
*/
|
|
|
|
|
|
function mount() {
|
|
hasMountCallbackRun = false;
|
|
var isInLooseFollowCursorMode = getIsInLooseFollowCursorMode();
|
|
|
|
if (instance.popperInstance) {
|
|
setFlipModifierEnabled(instance.popperInstance.modifiers, instance.props.flip);
|
|
|
|
if (!isInLooseFollowCursorMode) {
|
|
instance.popperInstance.reference = reference;
|
|
instance.popperInstance.enableEventListeners();
|
|
}
|
|
|
|
instance.popperInstance.scheduleUpdate();
|
|
} else {
|
|
createPopperInstance();
|
|
|
|
if (!isInLooseFollowCursorMode) {
|
|
instance.popperInstance.enableEventListeners();
|
|
}
|
|
}
|
|
|
|
var appendTo = instance.props.appendTo;
|
|
var parentNode = appendTo === 'parent' ? reference.parentNode : invokeWithArgsOrReturn(appendTo, [reference]);
|
|
|
|
if (!parentNode.contains(popper)) {
|
|
parentNode.appendChild(popper);
|
|
instance.props.onMount(instance);
|
|
instance.state.isMounted = true;
|
|
}
|
|
}
|
|
/**
|
|
* Setup before show() is invoked (delays, etc.)
|
|
*/
|
|
|
|
|
|
function scheduleShow(event, shouldAvoidCallingOnTrigger) {
|
|
clearDelayTimeouts();
|
|
|
|
if (instance.state.isVisible) {
|
|
return;
|
|
} // Is a delegate, create an instance for the child target
|
|
|
|
|
|
if (instance.props.target) {
|
|
return createDelegateChildTippy(event);
|
|
}
|
|
|
|
isScheduledToShow = true;
|
|
|
|
if (event && !shouldAvoidCallingOnTrigger) {
|
|
instance.props.onTrigger(instance, event);
|
|
}
|
|
|
|
if (instance.props.wait) {
|
|
return instance.props.wait(instance, event);
|
|
} // If the tooltip has a delay, we need to be listening to the mousemove as
|
|
// soon as the trigger event is fired, so that it's in the correct position
|
|
// upon mount.
|
|
// Edge case: if the tooltip is still mounted, but then scheduleShow() is
|
|
// called, it causes a jump.
|
|
|
|
|
|
if (getIsInLooseFollowCursorMode() && !instance.state.isMounted) {
|
|
if (!instance.popperInstance) {
|
|
createPopperInstance();
|
|
}
|
|
|
|
document.addEventListener('mousemove', positionVirtualReferenceNearCursor);
|
|
}
|
|
|
|
addDocumentClickListener();
|
|
var delay = getValue(instance.props.delay, 0, defaultProps.delay);
|
|
|
|
if (delay) {
|
|
showTimeoutId = setTimeout(function () {
|
|
show();
|
|
}, delay);
|
|
} else {
|
|
show();
|
|
}
|
|
}
|
|
/**
|
|
* Setup before hide() is invoked (delays, etc.)
|
|
*/
|
|
|
|
|
|
function scheduleHide() {
|
|
clearDelayTimeouts();
|
|
|
|
if (!instance.state.isVisible) {
|
|
removeFollowCursorListener();
|
|
removeDocumentClickListener();
|
|
return;
|
|
}
|
|
|
|
isScheduledToShow = false;
|
|
var delay = getValue(instance.props.delay, 1, defaultProps.delay);
|
|
|
|
if (delay) {
|
|
hideTimeoutId = setTimeout(function () {
|
|
if (instance.state.isVisible) {
|
|
hide();
|
|
}
|
|
}, delay);
|
|
} else {
|
|
// Fixes a `transitionend` problem when it fires 1 frame too
|
|
// late sometimes, we don't want hide() to be called.
|
|
scheduleHideAnimationFrameId = requestAnimationFrame(function () {
|
|
hide();
|
|
});
|
|
}
|
|
}
|
|
/**
|
|
* Listener to handle clicks on the document to determine if the
|
|
* instance should hide
|
|
*/
|
|
|
|
|
|
function onDocumentClick(event) {
|
|
// Clicked on interactive popper
|
|
if (instance.props.interactive && popper.contains(event.target)) {
|
|
return;
|
|
} // Clicked on the event listeners target
|
|
|
|
|
|
if (getEventListenersTarget().contains(event.target)) {
|
|
if (isUsingTouch) {
|
|
return;
|
|
}
|
|
|
|
if (instance.state.isVisible && includes(instance.props.trigger, 'click')) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (instance.props.hideOnClick === true) {
|
|
clearDelayTimeouts();
|
|
hide();
|
|
}
|
|
}
|
|
/* ======================= 🔑 Public methods 🔑 ======================= */
|
|
|
|
/**
|
|
* Enables the instance to allow it to show or hide
|
|
*/
|
|
|
|
|
|
function enable() {
|
|
instance.state.isEnabled = true;
|
|
}
|
|
/**
|
|
* Disables the instance to disallow it to show or hide
|
|
*/
|
|
|
|
|
|
function disable() {
|
|
instance.state.isEnabled = false;
|
|
}
|
|
/**
|
|
* Clears pending timeouts related to the `delay` prop if any
|
|
*/
|
|
|
|
|
|
function clearDelayTimeouts() {
|
|
clearTimeout(showTimeoutId);
|
|
clearTimeout(hideTimeoutId);
|
|
cancelAnimationFrame(scheduleHideAnimationFrameId);
|
|
}
|
|
/**
|
|
* Sets new props for the instance and redraws the tooltip
|
|
*/
|
|
|
|
|
|
function set(options) {
|
|
// Backwards-compatible after TypeScript change
|
|
options = options || {};
|
|
validateOptions(options, defaultProps);
|
|
removeTriggersFromReference();
|
|
var prevProps = instance.props;
|
|
var nextProps = evaluateProps(reference, _extends({}, instance.props, {}, options, {
|
|
ignoreAttributes: true
|
|
}));
|
|
nextProps.ignoreAttributes = hasOwnProperty(options, 'ignoreAttributes') ? options.ignoreAttributes || false : prevProps.ignoreAttributes;
|
|
instance.props = nextProps;
|
|
addTriggersToReference();
|
|
cleanupInteractiveMouseListeners();
|
|
debouncedOnMouseMove = debounce(onMouseMove, nextProps.interactiveDebounce);
|
|
updatePopperElement(popper, prevProps, nextProps);
|
|
instance.popperChildren = getChildren(popper);
|
|
|
|
if (instance.popperInstance) {
|
|
if (POPPER_INSTANCE_DEPENDENCIES.some(function (prop) {
|
|
return hasOwnProperty(options, prop) && options[prop] !== prevProps[prop];
|
|
})) {
|
|
instance.popperInstance.destroy();
|
|
createPopperInstance();
|
|
|
|
if (instance.state.isVisible) {
|
|
instance.popperInstance.enableEventListeners();
|
|
}
|
|
|
|
if (instance.props.followCursor && lastMouseMoveEvent) {
|
|
positionVirtualReferenceNearCursor(lastMouseMoveEvent);
|
|
}
|
|
} else {
|
|
instance.popperInstance.update();
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Shortcut for .set({ content: newContent })
|
|
*/
|
|
|
|
|
|
function setContent(content) {
|
|
set({
|
|
content: content
|
|
});
|
|
}
|
|
/**
|
|
* Shows the tooltip
|
|
*/
|
|
|
|
|
|
function show() {
|
|
var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getValue(instance.props.duration, 0, defaultProps.duration[1]);
|
|
|
|
if (instance.state.isDestroyed || !instance.state.isEnabled || isUsingTouch && !instance.props.touch) {
|
|
return;
|
|
} // Standardize `disabled` behavior across browsers.
|
|
// Firefox allows events on disabled elements, but Chrome doesn't.
|
|
// Using a wrapper element (i.e. <span>) is recommended.
|
|
|
|
|
|
if (getEventListenersTarget().hasAttribute('disabled')) {
|
|
return;
|
|
}
|
|
|
|
if (instance.props.onShow(instance) === false) {
|
|
return;
|
|
}
|
|
|
|
addDocumentClickListener();
|
|
popper.style.visibility = 'visible';
|
|
instance.state.isVisible = true;
|
|
|
|
if (instance.props.interactive) {
|
|
getEventListenersTarget().classList.add(ACTIVE_CLASS);
|
|
} // Prevent a transition if the popper is at the opposite placement
|
|
|
|
|
|
var transitionableElements = getTransitionableElements();
|
|
setTransitionDuration(transitionableElements.concat(popper), 0);
|
|
|
|
currentMountCallback = function currentMountCallback() {
|
|
if (!instance.state.isVisible) {
|
|
return;
|
|
}
|
|
|
|
var isInLooseFollowCursorMode = getIsInLooseFollowCursorMode();
|
|
|
|
if (isInLooseFollowCursorMode && lastMouseMoveEvent) {
|
|
positionVirtualReferenceNearCursor(lastMouseMoveEvent);
|
|
} else if (!isInLooseFollowCursorMode) {
|
|
// Double update will apply correct mutations
|
|
instance.popperInstance.update();
|
|
}
|
|
|
|
if (instance.popperChildren.backdrop) {
|
|
instance.popperChildren.content.style.transitionDelay = Math.round(duration / 12) + 'ms';
|
|
}
|
|
|
|
if (instance.props.sticky) {
|
|
makeSticky();
|
|
}
|
|
|
|
setTransitionDuration([popper], instance.props.updateDuration);
|
|
setTransitionDuration(transitionableElements, duration);
|
|
setVisibilityState(transitionableElements, 'visible');
|
|
onTransitionedIn(duration, function () {
|
|
if (instance.props.aria) {
|
|
getEventListenersTarget().setAttribute("aria-".concat(instance.props.aria), popper.id);
|
|
}
|
|
|
|
instance.props.onShown(instance);
|
|
instance.state.isShown = true;
|
|
});
|
|
};
|
|
|
|
mount();
|
|
}
|
|
/**
|
|
* Hides the tooltip
|
|
*/
|
|
|
|
|
|
function hide() {
|
|
var duration = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getValue(instance.props.duration, 1, defaultProps.duration[1]);
|
|
|
|
if (instance.state.isDestroyed || !instance.state.isEnabled && !isBeingDestroyed) {
|
|
return;
|
|
}
|
|
|
|
if (instance.props.onHide(instance) === false && !isBeingDestroyed) {
|
|
return;
|
|
}
|
|
|
|
removeDocumentClickListener();
|
|
popper.style.visibility = 'hidden';
|
|
instance.state.isVisible = false;
|
|
instance.state.isShown = false;
|
|
wasVisibleDuringPreviousUpdate = false;
|
|
|
|
if (instance.props.interactive) {
|
|
getEventListenersTarget().classList.remove(ACTIVE_CLASS);
|
|
}
|
|
|
|
var transitionableElements = getTransitionableElements();
|
|
setTransitionDuration(transitionableElements, duration);
|
|
setVisibilityState(transitionableElements, 'hidden');
|
|
onTransitionedOut(duration, function () {
|
|
if (!isScheduledToShow) {
|
|
removeFollowCursorListener();
|
|
}
|
|
|
|
if (instance.props.aria) {
|
|
getEventListenersTarget().removeAttribute("aria-".concat(instance.props.aria));
|
|
}
|
|
|
|
instance.popperInstance.disableEventListeners();
|
|
instance.popperInstance.options.placement = instance.props.placement;
|
|
popper.parentNode.removeChild(popper);
|
|
instance.props.onHidden(instance);
|
|
instance.state.isMounted = false;
|
|
});
|
|
}
|
|
/**
|
|
* Destroys the tooltip
|
|
*/
|
|
|
|
|
|
function destroy(destroyTargetInstances) {
|
|
if (instance.state.isDestroyed) {
|
|
return;
|
|
}
|
|
|
|
isBeingDestroyed = true; // If the popper is currently mounted to the DOM, we want to ensure it gets
|
|
// hidden and unmounted instantly upon destruction
|
|
|
|
if (instance.state.isMounted) {
|
|
hide(0);
|
|
}
|
|
|
|
removeTriggersFromReference();
|
|
delete reference._tippy;
|
|
var target = instance.props.target;
|
|
|
|
if (target && destroyTargetInstances && isRealElement(reference)) {
|
|
arrayFrom(reference.querySelectorAll(target)).forEach(function (child) {
|
|
if (child._tippy) {
|
|
child._tippy.destroy();
|
|
}
|
|
});
|
|
}
|
|
|
|
if (instance.popperInstance) {
|
|
instance.popperInstance.destroy();
|
|
}
|
|
|
|
isBeingDestroyed = false;
|
|
instance.state.isDestroyed = true;
|
|
}
|
|
}
|
|
/**
|
|
* Groups an array of instances by taking control of their props during
|
|
* certain lifecycles.
|
|
*/
|
|
|
|
|
|
function group(instances) {
|
|
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
|
|
_ref$delay = _ref.delay,
|
|
delay = _ref$delay === void 0 ? instances[0].props.delay : _ref$delay,
|
|
_ref$duration = _ref.duration,
|
|
duration = _ref$duration === void 0 ? 0 : _ref$duration;
|
|
|
|
var isAnyTippyOpen = false;
|
|
instances.forEach(function (instance) {
|
|
if (instance._originalProps) {
|
|
instance.set(instance._originalProps);
|
|
} else {
|
|
instance._originalProps = _extends({}, instance.props);
|
|
}
|
|
});
|
|
|
|
function setIsAnyTippyOpen(value) {
|
|
isAnyTippyOpen = value;
|
|
updateInstances();
|
|
}
|
|
|
|
function onShow(instance) {
|
|
instance._originalProps.onShow(instance);
|
|
|
|
instances.forEach(function (instance) {
|
|
instance.set({
|
|
duration: duration
|
|
});
|
|
|
|
if (instance.state.isVisible) {
|
|
instance.hide();
|
|
}
|
|
});
|
|
setIsAnyTippyOpen(true);
|
|
}
|
|
|
|
function onHide(instance) {
|
|
instance._originalProps.onHide(instance);
|
|
|
|
setIsAnyTippyOpen(false);
|
|
}
|
|
|
|
function onShown(instance) {
|
|
instance._originalProps.onShown(instance);
|
|
|
|
instance.set({
|
|
duration: instance._originalProps.duration
|
|
});
|
|
}
|
|
|
|
function updateInstances() {
|
|
instances.forEach(function (instance) {
|
|
instance.set({
|
|
onShow: onShow,
|
|
onShown: onShown,
|
|
onHide: onHide,
|
|
delay: isAnyTippyOpen ? [0, Array.isArray(delay) ? delay[1] : delay] : delay,
|
|
duration: isAnyTippyOpen ? duration : instance._originalProps.duration
|
|
});
|
|
});
|
|
}
|
|
|
|
updateInstances();
|
|
}
|
|
|
|
var globalEventListenersBound = false;
|
|
/**
|
|
* Exported module
|
|
*/
|
|
|
|
function tippy(targets, options) {
|
|
validateOptions(options || {}, defaultProps);
|
|
|
|
if (!globalEventListenersBound) {
|
|
bindGlobalEventListeners();
|
|
globalEventListenersBound = true;
|
|
}
|
|
|
|
var props = _extends({}, defaultProps, {}, options); // If they are specifying a virtual positioning reference, we need to polyfill
|
|
// some native DOM props
|
|
|
|
|
|
if (isBareVirtualElement(targets)) {
|
|
polyfillElementPrototypeProperties(targets);
|
|
}
|
|
|
|
var instances = getArrayOfElements(targets).reduce(function (acc, reference) {
|
|
var instance = reference && createTippy(reference, props);
|
|
|
|
if (instance) {
|
|
acc.push(instance);
|
|
}
|
|
|
|
return acc;
|
|
}, []);
|
|
return isSingular(targets) ? instances[0] : instances;
|
|
}
|
|
/**
|
|
* Static props
|
|
*/
|
|
|
|
|
|
tippy.version = version;
|
|
tippy.defaults = defaultProps;
|
|
/**
|
|
* Static methods
|
|
*/
|
|
|
|
tippy.setDefaults = function (partialDefaults) {
|
|
Object.keys(partialDefaults).forEach(function (key) {
|
|
// @ts-ignore
|
|
defaultProps[key] = partialDefaults[key];
|
|
});
|
|
};
|
|
|
|
tippy.hideAll = hideAll;
|
|
tippy.group = group;
|
|
/**
|
|
* Auto-init tooltips for elements with a `data-tippy="..."` attribute
|
|
*/
|
|
|
|
function autoInit() {
|
|
arrayFrom(document.querySelectorAll('[data-tippy]')).forEach(function (el) {
|
|
var content = el.getAttribute('data-tippy');
|
|
|
|
if (content) {
|
|
tippy(el, {
|
|
content: content
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
if (isBrowser) {
|
|
setTimeout(autoInit);
|
|
}
|
|
/**
|
|
* Injects a string of CSS styles to a style node in <head>
|
|
*/
|
|
|
|
|
|
function injectCSS(css) {
|
|
if (isBrowser) {
|
|
var style = document.createElement('style');
|
|
style.type = 'text/css';
|
|
style.textContent = css;
|
|
style.setAttribute('data-tippy-stylesheet', '');
|
|
var head = document.head;
|
|
var firstStyleOrLinkTag = head.querySelector('style,link');
|
|
|
|
if (firstStyleOrLinkTag) {
|
|
head.insertBefore(style, firstStyleOrLinkTag);
|
|
} else {
|
|
head.appendChild(style);
|
|
}
|
|
}
|
|
}
|
|
|
|
injectCSS(css);
|
|
/* harmony default export */ __webpack_exports__["default"] = (tippy);
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webpack/buildin/global.js":
|
|
/*!***********************************!*\
|
|
!*** (webpack)/buildin/global.js ***!
|
|
\***********************************/
|
|
/*! no static exports found */
|
|
/***/ (function(module, exports) {
|
|
|
|
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
|
|
|
|
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 === "undefined" ? "undefined" : _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;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/webpack/buildin/module.js":
|
|
/*!***********************************!*\
|
|
!*** (webpack)/buildin/module.js ***!
|
|
\***********************************/
|
|
/*! no static exports found */
|
|
/***/ (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 get() {
|
|
return module.l;
|
|
}
|
|
});
|
|
Object.defineProperty(module, "id", {
|
|
enumerable: true,
|
|
get: function get() {
|
|
return module.i;
|
|
}
|
|
});
|
|
module.webpackPolyfill = 1;
|
|
}
|
|
|
|
return module;
|
|
};
|
|
|
|
/***/ })
|
|
|
|
}]); |