PageSourceSearch

https://www.8xmille.it/wp-content/themes/8xmille-theme/assets/dist…/ottoxmille.imported-scripts.js?ver=2.0.88

js 8xmille.it collected 2026-09-24 21:36:54 UTC 307,212 bytes, 11,486 lines download raw bytes

1/*!
2 * Select2 4.1.0-rc
vendor: 17,404 bytes, lines 2-501
2.0
3 * https://select2.github.io
4 *
5 * Released under the MIT license
6 * https://github.com/select2/select2/blob/master/LICENSE.md
7 */
8;(function (factory) {
9  if (typeof define === 'function' && define.amd) {
10    // AMD. Register as an anonymous module.
11    define(['jquery'], factory);
12  } else if (typeof module === 'object' && module.exports) {
13    // Node/CommonJS
14    module.exports = function (root, jQuery) {
15      if (jQuery === undefined) {
16        // require('jQuery') returns a factory that requires window to
17        // build a jQuery instance, we normalize how we use modules
18        // that require this pattern but the window provided is a noop
19        // if it's defined (how jquery works)
20        if (typeof window !== 'undefined') {
21          jQuery = require('jquery');
22        }
23        else {
24          jQuery = require('jquery')(root);
25        }
26      }
27      factory(jQuery);
28      return jQuery;
29    };
30  } else {
31    // Browser globals
32    factory(jQuery);
33  }
34} (function (jQuery) {
35  // This is needed so we can catch the AMD loader configuration and use it
36  // The inner file should be wrapped (by `banner.start.js`) in a function that
37  // returns the AMD loader references.
38  var S2 =(function () {
39  // Restore the Select2 AMD loader so it can be used
40  // Needed mostly in the language files, where the loader is not inserted
41  if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
42    var S2 = jQuery.fn.select2.amd;
43  }
44var S2;(function () { if (!S2 || !S2.requirejs) {
45if (!S2) { S2 = {}; } else { require = S2; }
46/**
47 * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
48 * Released under MIT license, http://github.com/requirejs/almond/LICENSE
49 */
50//Going sloppy to avoid 'use strict' string cost, but strict practices should
51//be followed.
52/*global setTimeout: false */
53
54var requirejs, require, define;
55(function (undef) {
56    var main, req, makeMap, handlers,
57        defined = {},
58        waiting = {},
59        config = {},
60        defining = {},
61        hasOwn = Object.prototype.hasOwnProperty,
62        aps = [].slice,
63        jsSuffixRegExp = /\.js$/;
64
65    function hasProp(obj, prop) {
66        return hasOwn.call(obj, prop);
67    }
68
69    /**
70     * Given a relative module name, like ./something, normalize it to
71     * a real name that can be mapped to a path.
72     * @param {String} name the relative name
73     * @param {String} baseName a real name that the name arg is relative
74     * to.
75     * @returns {String} normalized name
76     */
77    function normalize(name, baseName) {
78        var nameParts, nameSegment, mapValue, foundMap, lastIndex,
79            foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
80            baseParts = baseName && baseName.split("/"),
81            map = config.map,
82            starMap = (map && map['*']) || {};
83
84        //Adjust any relative paths.
85        if (name) {
86            name = name.split('/');
87            lastIndex = name.length - 1;
88
89            // If wanting node ID compatibility, strip .js from end
90            // of IDs. Have to do this here, and not in nameToUrl
91            // because node allows either .js or non .js to map
92            // to same file.
93            if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
94                name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
95            }
96
97            // Starts with a '.' so need the baseName
98            if (name[0].charAt(0) === '.' && baseParts) {
99                //Convert baseName to array, and lop off the last part,
100                //so that . matches that 'directory' and not name of the baseName's
101                //module. For instance, baseName of 'one/two/three', maps to
102                //'one/two/three.js', but we want the directory, 'one/two' for
103                //this normalization.
104                normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
105                name = normalizedBaseParts.concat(name);
106            }
107
108            //start trimDots
109            for (i = 0; i < name.length; i++) {
110                part = name[i];
111                if (part === '.') {
112                    name.splice(i, 1);
113                    i -= 1;
114                } else if (part === '..') {
115                    // If at the start, or previous value is still ..,
116                    // keep them so that when converted to a path it may
117                    // still work when converted to a path, even though
118                    // as an ID it is less than ideal. In larger point
119                    // releases, may be better to just kick out an error.
120                    if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
121                        continue;
122                    } else if (i > 0) {
123                        name.splice(i - 1, 2);
124                        i -= 2;
125                    }
126                }
127            }
128            //end trimDots
129
130            name = name.join('/');
131        }
132
133        //Apply map config if available.
134        if ((baseParts || starMap) && map) {
135            nameParts = name.split('/');
136
137            for (i = nameParts.length; i > 0; i -= 1) {
138                nameSegment = nameParts.slice(0, i).join("/");
139
140                if (baseParts) {
141                    //Find the longest baseName segment match in the config.
142                    //So, do joins on the biggest to smallest lengths of baseParts.
143                    for (j = baseParts.length; j > 0; j -= 1) {
144                        mapValue = map[baseParts.slice(0, j).join('/')];
145
146                        //baseName segment has  config, find if it has one for
147                        //this name.
148                        if (mapValue) {
149                            mapValue = mapValue[nameSegment];
150                            if (mapValue) {
151                                //Match, update name to the new value.
152                                foundMap = mapValue;
153                                foundI = i;
154                                break;
155                            }
156                        }
157                    }
158                }
159
160                if (foundMap) {
161                    break;
162                }
163
164                //Check for a star map match, but just hold on to it,
165                //if there is a shorter segment match later in a matching
166                //config, then favor over this star map.
167                if (!foundStarMap && starMap && starMap[nameSegment]) {
168                    foundStarMap = starMap[nameSegment];
169                    starI = i;
170                }
171            }
172
173            if (!foundMap && foundStarMap) {
174                foundMap = foundStarMap;
175                foundI = starI;
176            }
177
178            if (foundMap) {
179                nameParts.splice(0, foundI, foundMap);
180                name = nameParts.join('/');
181            }
182        }
183
184        return name;
185    }
186
187    function makeRequire(relName, forceSync) {
188        return function () {
189            //A version of a require function that passes a moduleName
190            //value for items that may need to
191            //look up paths relative to the moduleName
192            var args = aps.call(arguments, 0);
193
194            //If first arg is not require('string'), and there is only
195            //one arg, it is the array form without a callback. Insert
196            //a null so that the following concat is correct.
197            if (typeof args[0] !== 'string' && args.length === 1) {
198                args.push(null);
199            }
200            return req.apply(undef, args.concat([relName, forceSync]));
201        };
202    }
203
204    function makeNormalize(relName) {
205        return function (name) {
206            return normalize(name, relName);
207        };
208    }
209
210    function makeLoad(depName) {
211        return function (value) {
212            defined[depName] = value;
213        };
214    }
215
216    function callDep(name) {
217        if (hasProp(waiting, name)) {
218            var args = waiting[name];
219            delete waiting[name];
220            defining[name] = true;
221            main.apply(undef, args);
222        }
223
224        if (!hasProp(defined, name) && !hasProp(defining, name)) {
225            throw new Error('No ' + name);
226        }
227        return defined[name];
228    }
229
230    //Turns a plugin!resource to [plugin, resource]
231    //with the plugin being undefined if the name
232    //did not have a plugin prefix.
233    function splitPrefix(name) {
234        var prefix,
235            index = name ? name.indexOf('!') : -1;
236        if (index > -1) {
237            prefix = name.substring(0, index);
238            name = name.substring(index + 1, name.length);
239        }
240        return [prefix, name];
241    }
242
243    //Creates a parts array for a relName where first part is plugin ID,
244    //second part is resource ID. Assumes relName has already been normalized.
245    function makeRelParts(relName) {
246        return relName ? splitPrefix(relName) : [];
247    }
248
249    /**
250     * Makes a name map, normalizing the name, and using a plugin
251     * for normalization if necessary. Grabs a ref to plugin
252     * too, as an optimization.
253     */
254    makeMap = function (name, relParts) {
255        var plugin,
256            parts = splitPrefix(name),
257            prefix = parts[0],
258            relResourceName = relParts[1];
259
260        name = parts[1];
261
262        if (prefix) {
263            prefix = normalize(prefix, relResourceName);
264            plugin = callDep(prefix);
265        }
266
267        //Normalize according
268        if (prefix) {
269            if (plugin && plugin.normalize) {
270                name = plugin.normalize(name, makeNormalize(relResourceName));
271            } else {
272                name = normalize(name, relResourceName);
273            }
274        } else {
275            name = normalize(name, relResourceName);
276            parts = splitPrefix(name);
277            prefix = parts[0];
278            name = parts[1];
279            if (prefix) {
280                plugin = callDep(prefix);
281            }
282        }
283
284        //Using ridiculous property names for space reasons
285        return {
286            f: prefix ? prefix + '!' + name : name, //fullName
287            n: name,
288            pr: prefix,
289            p: plugin
290        };
291    };
292
293    function makeConfig(name) {
294        return function () {
295            return (config && config.config && config.config[name]) || {};
296        };
297    }
298
299    handlers = {
300        require: function (name) {
301            return makeRequire(name);
302        },
303        exports: function (name) {
304            var e = defined[name];
305            if (typeof e !== 'undefined') {
306                return e;
307            } else {
308                return (defined[name] = {});
309            }
310        },
311        module: function (name) {
312            return {
313                id: name,
314                uri: '',
315                exports: defined[name],
316                config: makeConfig(name)
317            };
318        }
319    };
320
321    main = function (name, deps, callback, relName) {
322        var cjsModule, depName, ret, map, i, relParts,
323            args = [],
324            callbackType = typeof callback,
325            usingExports;
326
327        //Use name if no relName
328        relName = relName || name;
329        relParts = makeRelParts(relName);
330
331        //Call the callback to define the module, if necessary.
332        if (callbackType === 'undefined' || callbackType === 'function') {
333            //Pull out the defined dependencies and pass the ordered
334            //values to the callback.
335            //Default to [require, exports, module] if no deps
336            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
337            for (i = 0; i < deps.length; i += 1) {
338                map = makeMap(deps[i], relParts);
339                depName = map.f;
340
341                //Fast path CommonJS standard dependencies.
342                if (depName === "require") {
343                    args[i] = handlers.require(name);
344                } else if (depName === "exports") {
345                    //CommonJS module spec 1.1
346                    args[i] = handlers.exports(name);
347                    usingExports = true;
348                } else if (depName === "module") {
349                    //CommonJS module spec 1.1
350                    cjsModule = args[i] = handlers.module(name);
351                } else if (hasProp(defined, depName) ||
352                           hasProp(waiting, depName) ||
353                           hasProp(defining, depName)) {
354                    args[i] = callDep(depName);
355                } else if (map.p) {
356                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
357                    args[i] = defined[depName];
358                } else {
359                    throw new Error(name + ' missing ' + depName);
360                }
361            }
362
363            ret = callback ? callback.apply(defined[name], args) : undefined;
364
365            if (name) {
366                //If setting exports via "module" is in play,
367                //favor that over return value and exports. After that,
368                //favor a non-undefined return value over exports use.
369                if (cjsModule && cjsModule.exports !== undef &&
370                        cjsModule.exports !== defined[name]) {
371                    defined[name] = cjsModule.exports;
372                } else if (ret !== undef || !usingExports) {
373                    //Use the return value from the function.
374                    defined[name] = ret;
375                }
376            }
377        } else if (name) {
378            //May just be an object definition for the module. Only
379            //worry about defining if have a module name.
380            defined[name] = callback;
381        }
382    };
383
384    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
385        if (typeof deps === "string") {
386            if (handlers[deps]) {
387                //callback in this case is really relName
388                return handlers[deps](callback);
389            }
390            //Just return the module wanted. In this scenario, the
391            //deps arg is the module name, and second arg (if passed)
392            //is just the relName.
393            //Normalize module name, if it contains . or ..
394            return callDep(makeMap(deps, makeRelParts(callback)).f);
395        } else if (!deps.splice) {
396            //deps is a config object, not an array.
397            config = deps;
398            if (config.deps) {
399                req(config.deps, config.callback);
400            }
401            if (!callback) {
402                return;
403            }
404
405            if (callback.splice) {
406                //callback is an array, which means it is a dependency list.
407                //Adjust args if there are dependencies
408                deps = callback;
409                callback = relName;
410                relName = null;
411            } else {
412                deps = undef;
413            }
414        }
415
416        //Support require(['a'])
417        callback = callback || function () {};
418
419        //If relName is a function, it is an errback handler,
420        //so remove it.
421        if (typeof relName === 'function') {
422            relName = forceSync;
423            forceSync = alt;
424        }
425
426        //Simulate async callback;
427        if (forceSync) {
428            main(undef, deps, callback, relName);
429        } else {
430            //Using a non-zero value because of concern for what old browsers
431            //do, and latest browsers "upgrade" to 4 if lower value is used:
432            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
433            //If want a value immediately, use require('id') instead -- something
434            //that works in almond on the global level, but not guaranteed and
435            //unlikely to work in other AMD implementations.
436            setTimeout(function () {
437                main(undef, deps, callback, relName);
438            }, 4);
439        }
440
441        return req;
442    };
443
444    /**
445     * Just drops the config on the floor, but returns req in case
446     * the config return value is used.
447     */
448    req.config = function (cfg) {
449        return req(cfg);
450    };
451
452    /**
453     * Expose module registry for debugging and tooling
454     */
455    requirejs._defined = defined;
456
457    define = function (name, deps, callback) {
458        if (typeof name !== 'string') {
459            throw new Error('See almond README: incorrect module build, no module name');
460        }
461
462        //This module may not have dependencies
463        if (!deps.splice) {
464            //deps is not an array, so probably means
465            //an object literal or factory function for
466            //the value. Adjust args.
467            callback = deps;
468            deps = [];
469        }
470
471        if (!hasProp(defined, name) && !hasProp(waiting, name)) {
472            waiting[name] = [name, deps, callback];
473        }
474    };
475
476    define.amd = {
477        jQuery: true
478    };
479}());
480
481S2.requirejs = requirejs;S2.require = require;S2.define = define;
482}
483}());
484S2.define("almond", function(){});
485
486/* global jQuery:false, $:false */
487S2.define('jquery',[],function () {
488  var _$ = jQuery || $;
489
490  if (_$ == null && console && console.error) {
491    console.error(
492      'Select2: An instance of jQuery or a jQuery-compatible library was not ' +
493      'found. Make sure that you are including jQuery before Select2 on your ' +
494      'web page.'
495    );
496  }
497
498  return _$;
499});
500
501S2.define('select2/utils',[
vendor: 105,775 bytes, lines 502-4914
502  'jquery'
503], function ($) {
504  var Utils = {};
505
506  Utils.Extend = function (ChildClass, SuperClass) {
507    var __hasProp = {}.hasOwnProperty;
508
509    function BaseConstructor () {
510      this.constructor = ChildClass;
511    }
512
513    for (var key in SuperClass) {
514      if (__hasProp.call(SuperClass, key)) {
515        ChildClass[key] = SuperClass[key];
516      }
517    }
518
519    BaseConstructor.prototype = SuperClass.prototype;
520    ChildClass.prototype = new BaseConstructor();
521    ChildClass.__super__ = SuperClass.prototype;
522
523    return ChildClass;
524  };
525
526  function getMethods (theClass) {
527    var proto = theClass.prototype;
528
529    var methods = [];
530
531    for (var methodName in proto) {
532      var m = proto[methodName];
533
534      if (typeof m !== 'function') {
535        continue;
536      }
537
538      if (methodName === 'constructor') {
539        continue;
540      }
541
542      methods.push(methodName);
543    }
544
545    return methods;
546  }
547
548  Utils.Decorate = function (SuperClass, DecoratorClass) {
549    var decoratedMethods = getMethods(DecoratorClass);
550    var superMethods = getMethods(SuperClass);
551
552    function DecoratedClass () {
553      var unshift = Array.prototype.unshift;
554
555      var argCount = DecoratorClass.prototype.constructor.length;
556
557      var calledConstructor = SuperClass.prototype.constructor;
558
559      if (argCount > 0) {
560        unshift.call(arguments, SuperClass.prototype.constructor);
561
562        calledConstructor = DecoratorClass.prototype.constructor;
563      }
564
565      calledConstructor.apply(this, arguments);
566    }
567
568    DecoratorClass.displayName = SuperClass.displayName;
569
570    function ctr () {
571      this.constructor = DecoratedClass;
572    }
573
574    DecoratedClass.prototype = new ctr();
575
576    for (var m = 0; m < superMethods.length; m++) {
577      var superMethod = superMethods[m];
578
579      DecoratedClass.prototype[superMethod] =
580        SuperClass.prototype[superMethod];
581    }
582
583    var calledMethod = function (methodName) {
584      // Stub out the original method if it's not decorating an actual method
585      var originalMethod = function () {};
586
587      if (methodName in DecoratedClass.prototype) {
588        originalMethod = DecoratedClass.prototype[methodName];
589      }
590
591      var decoratedMethod = DecoratorClass.prototype[methodName];
592
593      return function () {
594        var unshift = Array.prototype.unshift;
595
596        unshift.call(arguments, originalMethod);
597
598        return decoratedMethod.apply(this, arguments);
599      };
600    };
601
602    for (var d = 0; d < decoratedMethods.length; d++) {
603      var decoratedMethod = decoratedMethods[d];
604
605      DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);
606    }
607
608    return DecoratedClass;
609  };
610
611  var Observable = function () {
612    this.listeners = {};
613  };
614
615  Observable.prototype.on = function (event, callback) {
616    this.listeners = this.listeners || {};
617
618    if (event in this.listeners) {
619      this.listeners[event].push(callback);
620    } else {
621      this.listeners[event] = [callback];
622    }
623  };
624
625  Observable.prototype.trigger = function (event) {
626    var slice = Array.prototype.slice;
627    var params = slice.call(arguments, 1);
628
629    this.listeners = this.listeners || {};
630
631    // Params should always come in as an array
632    if (params == null) {
633      params = [];
634    }
635
636    // If there are no arguments to the event, use a temporary object
637    if (params.length === 0) {
638      params.push({});
639    }
640
641    // Set the `_type` of the first object to the event
642    params[0]._type = event;
643
644    if (event in this.listeners) {
645      this.invoke(this.listeners[event], slice.call(arguments, 1));
646    }
647
648    if ('*' in this.listeners) {
649      this.invoke(this.listeners['*'], arguments);
650    }
651  };
652
653  Observable.prototype.invoke = function (listeners, params) {
654    for (var i = 0, len = listeners.length; i < len; i++) {
655      listeners[i].apply(this, params);
656    }
657  };
658
659  Utils.Observable = Observable;
660
661  Utils.generateChars = function (length) {
662    var chars = '';
663
664    for (var i = 0; i < length; i++) {
665      var randomChar = Math.floor(Math.random() * 36);
666      chars += randomChar.toString(36);
667    }
668
669    return chars;
670  };
671
672  Utils.bind = function (func, context) {
673    return function () {
674      func.apply(context, arguments);
675    };
676  };
677
678  Utils._convertData = function (data) {
679    for (var originalKey in data) {
680      var keys = originalKey.split('-');
681
682      var dataLevel = data;
683
684      if (keys.length === 1) {
685        continue;
686      }
687
688      for (var k = 0; k < keys.length; k++) {
689        var key = keys[k];
690
691        // Lowercase the first letter
692        // By default, dash-separated becomes camelCase
693        key = key.substring(0, 1).toLowerCase() + key.substring(1);
694
695        if (!(key in dataLevel)) {
696          dataLevel[key] = {};
697        }
698
699        if (k == keys.length - 1) {
700          dataLevel[key] = data[originalKey];
701        }
702
703        dataLevel = dataLevel[key];
704      }
705
706      delete data[originalKey];
707    }
708
709    return data;
710  };
711
712  Utils.hasScroll = function (index, el) {
713    // Adapted from the function created by @ShadowScripter
714    // and adapted by @BillBarry on the Stack Exchange Code Review website.
715    // The original code can be found at
716    // http://codereview.stackexchange.com/q/13338
717    // and was designed to be used with the Sizzle selector engine.
718
719    var $el = $(el);
720    var overflowX = el.style.overflowX;
721    var overflowY = el.style.overflowY;
722
723    //Check both x and y declarations
724    if (overflowX === overflowY &&
725        (overflowY === 'hidden' || overflowY === 'visible')) {
726      return false;
727    }
728
729    if (overflowX === 'scroll' || overflowY === 'scroll') {
730      return true;
731    }
732
733    return ($el.innerHeight() < el.scrollHeight ||
734      $el.innerWidth() < el.scrollWidth);
735  };
736
737  Utils.escapeMarkup = function (markup) {
738    var replaceMap = {
739      '\\': '&#92;',
740      '&': '&amp;',
741      '<': '&lt;',
742      '>': '&gt;',
743      '"': '&quot;',
744      '\'': '&#39;',
745      '/': '&#47;'
746    };
747
748    // Do not try to escape the markup if it's not a string
749    if (typeof markup !== 'string') {
750      return markup;
751    }
752
753    return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
754      return replaceMap[match];
755    });
756  };
757
758  // Cache objects in Utils.__cache instead of $.data (see #4346)
759  Utils.__cache = {};
760
761  var id = 0;
762  Utils.GetUniqueElementId = function (element) {
763    // Get a unique element Id. If element has no id,
764    // creates a new unique number, stores it in the id
765    // attribute and returns the new id with a prefix.
766    // If an id already exists, it simply returns it with a prefix.
767
768    var select2Id = element.getAttribute('data-select2-id');
769
770    if (select2Id != null) {
771      return select2Id;
772    }
773
774    // If element has id, use it.
775    if (element.id) {
776      select2Id = 'select2-data-' + element.id;
777    } else {
778      select2Id = 'select2-data-' + (++id).toString() +
779        '-' + Utils.generateChars(4);
780    }
781
782    element.setAttribute('data-select2-id', select2Id);
783
784    return select2Id;
785  };
786
787  Utils.StoreData = function (element, name, value) {
788    // Stores an item in the cache for a specified element.
789    // name is the cache key.
790    var id = Utils.GetUniqueElementId(element);
791    if (!Utils.__cache[id]) {
792      Utils.__cache[id] = {};
793    }
794
795    Utils.__cache[id][name] = value;
796  };
797
798  Utils.GetData = function (element, name) {
799    // Retrieves a value from the cache by its key (name)
800    // name is optional. If no name specified, return
801    // all cache items for the specified element.
802    // and for a specified element.
803    var id = Utils.GetUniqueElementId(element);
804    if (name) {
805      if (Utils.__cache[id]) {
806        if (Utils.__cache[id][name] != null) {
807          return Utils.__cache[id][name];
808        }
809        return $(element).data(name); // Fallback to HTML5 data attribs.
810      }
811      return $(element).data(name); // Fallback to HTML5 data attribs.
812    } else {
813      return Utils.__cache[id];
814    }
815  };
816
817  Utils.RemoveData = function (element) {
818    // Removes all cached items for a specified element.
819    var id = Utils.GetUniqueElementId(element);
820    if (Utils.__cache[id] != null) {
821      delete Utils.__cache[id];
822    }
823
824    element.removeAttribute('data-select2-id');
825  };
826
827  Utils.copyNonInternalCssClasses = function (dest, src) {
828    var classes;
829
830    var destinationClasses = dest.getAttribute('class').trim().split(/\s+/);
831
832    destinationClasses = destinationClasses.filter(function (clazz) {
833      // Save all Select2 classes
834      return clazz.indexOf('select2-') === 0;
835    });
836
837    var sourceClasses = src.getAttribute('class').trim().split(/\s+/);
838
839    sourceClasses = sourceClasses.filter(function (clazz) {
840      // Only copy non-Select2 classes
841      return clazz.indexOf('select2-') !== 0;
842    });
843
844    var replacements = destinationClasses.concat(sourceClasses);
845
846    dest.setAttribute('class', replacements.join(' '));
847  };
848
849  return Utils;
850});
851
852S2.define('select2/results',[
853  'jquery',
854  './utils'
855], function ($, Utils) {
856  function Results ($element, options, dataAdapter) {
857    this.$element = $element;
858    this.data = dataAdapter;
859    this.options = options;
860
861    Results.__super__.constructor.call(this);
862  }
863
864  Utils.Extend(Results, Utils.Observable);
865
866  Results.prototype.render = function () {
867    var $results = $(
868      '<ul class="select2-results__options" role="listbox"></ul>'
869    );
870
871    if (this.options.get('multiple')) {
872      $results.attr('aria-multiselectable', 'true');
873    }
874
875    this.$results = $results;
876
877    return $results;
878  };
879
880  Results.prototype.clear = function () {
881    this.$results.empty();
882  };
883
884  Results.prototype.displayMessage = function (params) {
885    var escapeMarkup = this.options.get('escapeMarkup');
886
887    this.clear();
888    this.hideLoading();
889
890    var $message = $(
891      '<li role="alert" aria-live="assertive"' +
892      ' class="select2-results__option"></li>'
893    );
894
895    var message = this.options.get('translations').get(params.message);
896
897    $message.append(
898      escapeMarkup(
899        message(params.args)
900      )
901    );
902
903    $message[0].className += ' select2-results__message';
904
905    this.$results.append($message);
906  };
907
908  Results.prototype.hideMessages = function () {
909    this.$results.find('.select2-results__message').remove();
910  };
911
912  Results.prototype.append = function (data) {
913    this.hideLoading();
914
915    var $options = [];
916
917    if (data.results == null || data.results.length === 0) {
918      if (this.$results.children().length === 0) {
919        this.trigger('results:message', {
920          message: 'noResults'
921        });
922      }
923
924      return;
925    }
926
927    data.results = this.sort(data.results);
928
929    for (var d = 0; d < data.results.length; d++) {
930      var item = data.results[d];
931
932      var $option = this.option(item);
933
934      $options.push($option);
935    }
936
937    this.$results.append($options);
938  };
939
940  Results.prototype.position = function ($results, $dropdown) {
941    var $resultsContainer = $dropdown.find('.select2-results');
942    $resultsContainer.append($results);
943  };
944
945  Results.prototype.sort = function (data) {
946    var sorter = this.options.get('sorter');
947
948    return sorter(data);
949  };
950
951  Results.prototype.highlightFirstItem = function () {
952    var $options = this.$results
953      .find('.select2-results__option--selectable');
954
955    var $selected = $options.filter('.select2-results__option--selected');
956
957    // Check if there are any selected options
958    if ($selected.length > 0) {
959      // If there are selected options, highlight the first
960      $selected.first().trigger('mouseenter');
961    } else {
962      // If there are no selected options, highlight the first option
963      // in the dropdown
964      $options.first().trigger('mouseenter');
965    }
966
967    this.ensureHighlightVisible();
968  };
969
970  Results.prototype.setClasses = function () {
971    var self = this;
972
973    this.data.current(function (selected) {
974      var selectedIds = selected.map(function (s) {
975        return s.id.toString();
976      });
977
978      var $options = self.$results
979        .find('.select2-results__option--selectable');
980
981      $options.each(function () {
982        var $option = $(this);
983
984        var item = Utils.GetData(this, 'data');
985
986        // id needs to be converted to a string when comparing
987        var id = '' + item.id;
988
989        if ((item.element != null && item.element.selected) ||
990            (item.element == null && selectedIds.indexOf(id) > -1)) {
991          this.classList.add('select2-results__option--selected');
992          $option.attr('aria-selected', 'true');
993        } else {
994          this.classList.remove('select2-results__option--selected');
995          $option.attr('aria-selected', 'false');
996        }
997      });
998
999    });
1000  };
1001
1002  Results.prototype.showLoading = function (params) {
1003    this.hideLoading();
1004
1005    var loadingMore = this.options.get('translations').get('searching');
1006
1007    var loading = {
1008      disabled: true,
1009      loading: true,
1010      text: loadingMore(params)
1011    };
1012    var $loading = this.option(loading);
1013    $loading.className += ' loading-results';
1014
1015    this.$results.prepend($loading);
1016  };
1017
1018  Results.prototype.hideLoading = function () {
1019    this.$results.find('.loading-results').remove();
1020  };
1021
1022  Results.prototype.option = function (data) {
1023    var option = document.createElement('li');
1024    option.classList.add('select2-results__option');
1025    option.classList.add('select2-results__option--selectable');
1026
1027    var attrs = {
1028      'role': 'option'
1029    };
1030
1031    var matches = window.Element.prototype.matches ||
1032      window.Element.prototype.msMatchesSelector ||
1033      window.Element.prototype.webkitMatchesSelector;
1034
1035    if ((data.element != null && matches.call(data.element, ':disabled')) ||
1036        (data.element == null && data.disabled)) {
1037      attrs['aria-disabled'] = 'true';
1038
1039      option.classList.remove('select2-results__option--selectable');
1040      option.classList.add('select2-results__option--disabled');
1041    }
1042
1043    if (data.id == null) {
1044      option.classList.remove('select2-results__option--selectable');
1045    }
1046
1047    if (data._resultId != null) {
1048      option.id = data._resultId;
1049    }
1050
1051    if (data.title) {
1052      option.title = data.title;
1053    }
1054
1055    if (data.children) {
1056      attrs.role = 'group';
1057      attrs['aria-label'] = data.text;
1058
1059      option.classList.remove('select2-results__option--selectable');
1060      option.classList.add('select2-results__option--group');
1061    }
1062
1063    for (var attr in attrs) {
1064      var val = attrs[attr];
1065
1066      option.setAttribute(attr, val);
1067    }
1068
1069    if (data.children) {
1070      var $option = $(option);
1071
1072      var label = document.createElement('strong');
1073      label.className = 'select2-results__group';
1074
1075      this.template(data, label);
1076
1077      var $children = [];
1078
1079      for (var c = 0; c < data.children.length; c++) {
1080        var child = data.children[c];
1081
1082        var $child = this.option(child);
1083
1084        $children.push($child);
1085      }
1086
1087      var $childrenContainer = $('<ul></ul>', {
1088        'class': 'select2-results__options select2-results__options--nested',
1089        'role': 'none'
1090      });
1091
1092      $childrenContainer.append($children);
1093
1094      $option.append(label);
1095      $option.append($childrenContainer);
1096    } else {
1097      this.template(data, option);
1098    }
1099
1100    Utils.StoreData(option, 'data', data);
1101
1102    return option;
1103  };
1104
1105  Results.prototype.bind = function (container, $container) {
1106    var self = this;
1107
1108    var id = container.id + '-results';
1109
1110    this.$results.attr('id', id);
1111
1112    container.on('results:all', function (params) {
1113      self.clear();
1114      self.append(params.data);
1115
1116      if (container.isOpen()) {
1117        self.setClasses();
1118        self.highlightFirstItem();
1119      }
1120    });
1121
1122    container.on('results:append', function (params) {
1123      self.append(params.data);
1124
1125      if (container.isOpen()) {
1126        self.setClasses();
1127      }
1128    });
1129
1130    container.on('query', function (params) {
1131      self.hideMessages();
1132      self.showLoading(params);
1133    });
1134
1135    container.on('select', function () {
1136      if (!container.isOpen()) {
1137        return;
1138      }
1139
1140      self.setClasses();
1141
1142      if (self.options.get('scrollAfterSelect')) {
1143        self.highlightFirstItem();
1144      }
1145    });
1146
1147    container.on('unselect', function () {
1148      if (!container.isOpen()) {
1149        return;
1150      }
1151
1152      self.setClasses();
1153
1154      if (self.options.get('scrollAfterSelect')) {
1155        self.highlightFirstItem();
1156      }
1157    });
1158
1159    container.on('open', function () {
1160      // When the dropdown is open, aria-expended="true"
1161      self.$results.attr('aria-expanded', 'true');
1162      self.$results.attr('aria-hidden', 'false');
1163
1164      self.setClasses();
1165      self.ensureHighlightVisible();
1166    });
1167
1168    container.on('close', function () {
1169      // When the dropdown is closed, aria-expended="false"
1170      self.$results.attr('aria-expanded', 'false');
1171      self.$results.attr('aria-hidden', 'true');
1172      self.$results.removeAttr('aria-activedescendant');
1173    });
1174
1175    container.on('results:toggle', function () {
1176      var $highlighted = self.getHighlightedResults();
1177
1178      if ($highlighted.length === 0) {
1179        return;
1180      }
1181
1182      $highlighted.trigger('mouseup');
1183    });
1184
1185    container.on('results:select', function () {
1186      var $highlighted = self.getHighlightedResults();
1187
1188      if ($highlighted.length === 0) {
1189        return;
1190      }
1191
1192      var data = Utils.GetData($highlighted[0], 'data');
1193
1194      if ($highlighted.hasClass('select2-results__option--selected')) {
1195        self.trigger('close', {});
1196      } else {
1197        self.trigger('select', {
1198          data: data
1199        });
1200      }
1201    });
1202
1203    container.on('results:previous', function () {
1204      var $highlighted = self.getHighlightedResults();
1205
1206      var $options = self.$results.find('.select2-results__option--selectable');
1207
1208      var currentIndex = $options.index($highlighted);
1209
1210      // If we are already at the top, don't move further
1211      // If no options, currentIndex will be -1
1212      if (currentIndex <= 0) {
1213        return;
1214      }
1215
1216      var nextIndex = currentIndex - 1;
1217
1218      // If none are highlighted, highlight the first
1219      if ($highlighted.length === 0) {
1220        nextIndex = 0;
1221      }
1222
1223      var $next = $options.eq(nextIndex);
1224
1225      $next.trigger('mouseenter');
1226
1227      var currentOffset = self.$results.offset().top;
1228      var nextTop = $next.offset().top;
1229      var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);
1230
1231      if (nextIndex === 0) {
1232        self.$results.scrollTop(0);
1233      } else if (nextTop - currentOffset < 0) {
1234        self.$results.scrollTop(nextOffset);
1235      }
1236    });
1237
1238    container.on('results:next', function () {
1239      var $highlighted = self.getHighlightedResults();
1240
1241      var $options = self.$results.find('.select2-results__option--selectable');
1242
1243      var currentIndex = $options.index($highlighted);
1244
1245      var nextIndex = currentIndex + 1;
1246
1247      // If we are at the last option, stay there
1248      if (nextIndex >= $options.length) {
1249        return;
1250      }
1251
1252      var $next = $options.eq(nextIndex);
1253
1254      $next.trigger('mouseenter');
1255
1256      var currentOffset = self.$results.offset().top +
1257        self.$results.outerHeight(false);
1258      var nextBottom = $next.offset().top + $next.outerHeight(false);
1259      var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;
1260
1261      if (nextIndex === 0) {
1262        self.$results.scrollTop(0);
1263      } else if (nextBottom > currentOffset) {
1264        self.$results.scrollTop(nextOffset);
1265      }
1266    });
1267
1268    container.on('results:focus', function (params) {
1269      params.element[0].classList.add('select2-results__option--highlighted');
1270      params.element[0].setAttribute('aria-selected', 'true');
1271    });
1272
1273    container.on('results:message', function (params) {
1274      self.displayMessage(params);
1275    });
1276
1277    if ($.fn.mousewheel) {
1278      this.$results.on('mousewheel', function (e) {
1279        var top = self.$results.scrollTop();
1280
1281        var bottom = self.$results.get(0).scrollHeight - top + e.deltaY;
1282
1283        var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;
1284        var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();
1285
1286        if (isAtTop) {
1287          self.$results.scrollTop(0);
1288
1289          e.preventDefault();
1290          e.stopPropagation();
1291        } else if (isAtBottom) {
1292          self.$results.scrollTop(
1293            self.$results.get(0).scrollHeight - self.$results.height()
1294          );
1295
1296          e.preventDefault();
1297          e.stopPropagation();
1298        }
1299      });
1300    }
1301
1302    this.$results.on('mouseup', '.select2-results__option--selectable',
1303      function (evt) {
1304      var $this = $(this);
1305
1306      var data = Utils.GetData(this, 'data');
1307
1308      if ($this.hasClass('select2-results__option--selected')) {
1309        if (self.options.get('multiple')) {
1310          self.trigger('unselect', {
1311            originalEvent: evt,
1312            data: data
1313          });
1314        } else {
1315          self.trigger('close', {});
1316        }
1317
1318        return;
1319      }
1320
1321      self.trigger('select', {
1322        originalEvent: evt,
1323        data: data
1324      });
1325    });
1326
1327    this.$results.on('mouseenter', '.select2-results__option--selectable',
1328      function (evt) {
1329      var data = Utils.GetData(this, 'data');
1330
1331      self.getHighlightedResults()
1332          .removeClass('select2-results__option--highlighted')
1333          .attr('aria-selected', 'false');
1334
1335      self.trigger('results:focus', {
1336        data: data,
1337        element: $(this)
1338      });
1339    });
1340  };
1341
1342  Results.prototype.getHighlightedResults = function () {
1343    var $highlighted = this.$results
1344    .find('.select2-results__option--highlighted');
1345
1346    return $highlighted;
1347  };
1348
1349  Results.prototype.destroy = function () {
1350    this.$results.remove();
1351  };
1352
1353  Results.prototype.ensureHighlightVisible = function () {
1354    var $highlighted = this.getHighlightedResults();
1355
1356    if ($highlighted.length === 0) {
1357      return;
1358    }
1359
1360    var $options = this.$results.find('.select2-results__option--selectable');
1361
1362    var currentIndex = $options.index($highlighted);
1363
1364    var currentOffset = this.$results.offset().top;
1365    var nextTop = $highlighted.offset().top;
1366    var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);
1367
1368    var offsetDelta = nextTop - currentOffset;
1369    nextOffset -= $highlighted.outerHeight(false) * 2;
1370
1371    if (currentIndex <= 2) {
1372      this.$results.scrollTop(0);
1373    } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {
1374      this.$results.scrollTop(nextOffset);
1375    }
1376  };
1377
1378  Results.prototype.template = function (result, container) {
1379    var template = this.options.get('templateResult');
1380    var escapeMarkup = this.options.get('escapeMarkup');
1381
1382    var content = template(result, container);
1383
1384    if (content == null) {
1385      container.style.display = 'none';
1386    } else if (typeof content === 'string') {
1387      container.innerHTML = escapeMarkup(content);
1388    } else {
1389      $(container).append(content);
1390    }
1391  };
1392
1393  return Results;
1394});
1395
1396S2.define('select2/keys',[
1397
1398], function () {
1399  var KEYS = {
1400    BACKSPACE: 8,
1401    TAB: 9,
1402    ENTER: 13,
1403    SHIFT: 16,
1404    CTRL: 17,
1405    ALT: 18,
1406    ESC: 27,
1407    SPACE: 32,
1408    PAGE_UP: 33,
1409    PAGE_DOWN: 34,
1410    END: 35,
1411    HOME: 36,
1412    LEFT: 37,
1413    UP: 38,
1414    RIGHT: 39,
1415    DOWN: 40,
1416    DELETE: 46
1417  };
1418
1419  return KEYS;
1420});
1421
1422S2.define('select2/selection/base',[
1423  'jquery',
1424  '../utils',
1425  '../keys'
1426], function ($, Utils, KEYS) {
1427  function BaseSelection ($element, options) {
1428    this.$element = $element;
1429    this.options = options;
1430
1431    BaseSelection.__super__.constructor.call(this);
1432  }
1433
1434  Utils.Extend(BaseSelection, Utils.Observable);
1435
1436  BaseSelection.prototype.render = function () {
1437    var $selection = $(
1438      '<span class="select2-selection" role="combobox" ' +
1439      ' aria-haspopup="true" aria-expanded="false">' +
1440      '</span>'
1441    );
1442
1443    this._tabindex = 0;
1444
1445    if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
1446      this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
1447    } else if (this.$element.attr('tabindex') != null) {
1448      this._tabindex = this.$element.attr('tabindex');
1449    }
1450
1451    $selection.attr('title', this.$element.attr('title'));
1452    $selection.attr('tabindex', this._tabindex);
1453    $selection.attr('aria-disabled', 'false');
1454
1455    this.$selection = $selection;
1456
1457    return $selection;
1458  };
1459
1460  BaseSelection.prototype.bind = function (container, $container) {
1461    var self = this;
1462
1463    var resultsId = container.id + '-results';
1464
1465    this.container = container;
1466
1467    this.$selection.on('focus', function (evt) {
1468      self.trigger('focus', evt);
1469    });
1470
1471    this.$selection.on('blur', function (evt) {
1472      self._handleBlur(evt);
1473    });
1474
1475    this.$selection.on('keydown', function (evt) {
1476      self.trigger('keypress', evt);
1477
1478      if (evt.which === KEYS.SPACE) {
1479        evt.preventDefault();
1480      }
1481    });
1482
1483    container.on('results:focus', function (params) {
1484      self.$selection.attr('aria-activedescendant', params.data._resultId);
1485    });
1486
1487    container.on('selection:update', function (params) {
1488      self.update(params.data);
1489    });
1490
1491    container.on('open', function () {
1492      // When the dropdown is open, aria-expanded="true"
1493      self.$selection.attr('aria-expanded', 'true');
1494      self.$selection.attr('aria-owns', resultsId);
1495
1496      self._attachCloseHandler(container);
1497    });
1498
1499    container.on('close', function () {
1500      // When the dropdown is closed, aria-expanded="false"
1501      self.$selection.attr('aria-expanded', 'false');
1502      self.$selection.removeAttr('aria-activedescendant');
1503      self.$selection.removeAttr('aria-owns');
1504
1505      self.$selection.trigger('focus');
1506
1507      self._detachCloseHandler(container);
1508    });
1509
1510    container.on('enable', function () {
1511      self.$selection.attr('tabindex', self._tabindex);
1512      self.$selection.attr('aria-disabled', 'false');
1513    });
1514
1515    container.on('disable', function () {
1516      self.$selection.attr('tabindex', '-1');
1517      self.$selection.attr('aria-disabled', 'true');
1518    });
1519  };
1520
1521  BaseSelection.prototype._handleBlur = function (evt) {
1522    var self = this;
1523
1524    // This needs to be delayed as the active element is the body when the tab
1525    // key is pressed, possibly along with others.
1526    window.setTimeout(function () {
1527      // Don't trigger `blur` if the focus is still in the selection
1528      if (
1529        (document.activeElement == self.$selection[0]) ||
1530        ($.contains(self.$selection[0], document.activeElement))
1531      ) {
1532        return;
1533      }
1534
1535      self.trigger('blur', evt);
1536    }, 1);
1537  };
1538
1539  BaseSelection.prototype._attachCloseHandler = function (container) {
1540
1541    $(document.body).on('mousedown.select2.' + container.id, function (e) {
1542      var $target = $(e.target);
1543
1544      var $select = $target.closest('.select2');
1545
1546      var $all = $('.select2.select2-container--open');
1547
1548      $all.each(function () {
1549        if (this == $select[0]) {
1550          return;
1551        }
1552
1553        var $element = Utils.GetData(this, 'element');
1554
1555        $element.select2('close');
1556      });
1557    });
1558  };
1559
1560  BaseSelection.prototype._detachCloseHandler = function (container) {
1561    $(document.body).off('mousedown.select2.' + container.id);
1562  };
1563
1564  BaseSelection.prototype.position = function ($selection, $container) {
1565    var $selectionContainer = $container.find('.selection');
1566    $selectionContainer.append($selection);
1567  };
1568
1569  BaseSelection.prototype.destroy = function () {
1570    this._detachCloseHandler(this.container);
1571  };
1572
1573  BaseSelection.prototype.update = function (data) {
1574    throw new Error('The `update` method must be defined in child classes.');
1575  };
1576
1577  /**
1578   * Helper method to abstract the "enabled" (not "disabled") state of this
1579   * object.
1580   *
1581   * @return {true} if the instance is not disabled.
1582   * @return {false} if the instance is disabled.
1583   */
1584  BaseSelection.prototype.isEnabled = function () {
1585    return !this.isDisabled();
1586  };
1587
1588  /**
1589   * Helper method to abstract the "disabled" state of this object.
1590   *
1591   * @return {true} if the disabled option is true.
1592   * @return {false} if the disabled option is false.
1593   */
1594  BaseSelection.prototype.isDisabled = function () {
1595    return this.options.get('disabled');
1596  };
1597
1598  return BaseSelection;
1599});
1600
1601S2.define('select2/selection/single',[
1602  'jquery',
1603  './base',
1604  '../utils',
1605  '../keys'
1606], function ($, BaseSelection, Utils, KEYS) {
1607  function SingleSelection () {
1608    SingleSelection.__super__.constructor.apply(this, arguments);
1609  }
1610
1611  Utils.Extend(SingleSelection, BaseSelection);
1612
1613  SingleSelection.prototype.render = function () {
1614    var $selection = SingleSelection.__super__.render.call(this);
1615
1616    $selection[0].classList.add('select2-selection--single');
1617
1618    $selection.html(
1619      '<span class="select2-selection__rendered"></span>' +
1620      '<span class="select2-selection__arrow" role="presentation">' +
1621        '<b role="presentation"></b>' +
1622      '</span>'
1623    );
1624
1625    return $selection;
1626  };
1627
1628  SingleSelection.prototype.bind = function (container, $container) {
1629    var self = this;
1630
1631    SingleSelection.__super__.bind.apply(this, arguments);
1632
1633    var id = container.id + '-container';
1634
1635    this.$selection.find('.select2-selection__rendered')
1636      .attr('id', id)
1637      .attr('role', 'textbox')
1638      .attr('aria-readonly', 'true');
1639    this.$selection.attr('aria-labelledby', id);
1640    this.$selection.attr('aria-controls', id);
1641
1642    this.$selection.on('mousedown', function (evt) {
1643      // Only respond to left clicks
1644      if (evt.which !== 1) {
1645        return;
1646      }
1647
1648      self.trigger('toggle', {
1649        originalEvent: evt
1650      });
1651    });
1652
1653    this.$selection.on('focus', function (evt) {
1654      // User focuses on the container
1655    });
1656
1657    this.$selection.on('blur', function (evt) {
1658      // User exits the container
1659    });
1660
1661    container.on('focus', function (evt) {
1662      if (!container.isOpen()) {
1663        self.$selection.trigger('focus');
1664      }
1665    });
1666  };
1667
1668  SingleSelection.prototype.clear = function () {
1669    var $rendered = this.$selection.find('.select2-selection__rendered');
1670    $rendered.empty();
1671    $rendered.removeAttr('title'); // clear tooltip on empty
1672  };
1673
1674  SingleSelection.prototype.display = function (data, container) {
1675    var template = this.options.get('templateSelection');
1676    var escapeMarkup = this.options.get('escapeMarkup');
1677
1678    return escapeMarkup(template(data, container));
1679  };
1680
1681  SingleSelection.prototype.selectionContainer = function () {
1682    return $('<span></span>');
1683  };
1684
1685  SingleSelection.prototype.update = function (data) {
1686    if (data.length === 0) {
1687      this.clear();
1688      return;
1689    }
1690
1691    var selection = data[0];
1692
1693    var $rendered = this.$selection.find('.select2-selection__rendered');
1694    var formatted = this.display(selection, $rendered);
1695
1696    $rendered.empty().append(formatted);
1697
1698    var title = selection.title || selection.text;
1699
1700    if (title) {
1701      $rendered.attr('title', title);
1702    } else {
1703      $rendered.removeAttr('title');
1704    }
1705  };
1706
1707  return SingleSelection;
1708});
1709
1710S2.define('select2/selection/multiple',[
1711  'jquery',
1712  './base',
1713  '../utils'
1714], function ($, BaseSelection, Utils) {
1715  function MultipleSelection ($element, options) {
1716    MultipleSelection.__super__.constructor.apply(this, arguments);
1717  }
1718
1719  Utils.Extend(MultipleSelection, BaseSelection);
1720
1721  MultipleSelection.prototype.render = function () {
1722    var $selection = MultipleSelection.__super__.render.call(this);
1723
1724    $selection[0].classList.add('select2-selection--multiple');
1725
1726    $selection.html(
1727      '<ul class="select2-selection__rendered"></ul>'
1728    );
1729
1730    return $selection;
1731  };
1732
1733  MultipleSelection.prototype.bind = function (container, $container) {
1734    var self = this;
1735
1736    MultipleSelection.__super__.bind.apply(this, arguments);
1737
1738    var id = container.id + '-container';
1739    this.$selection.find('.select2-selection__rendered').attr('id', id);
1740
1741    this.$selection.on('click', function (evt) {
1742      self.trigger('toggle', {
1743        originalEvent: evt
1744      });
1745    });
1746
1747    this.$selection.on(
1748      'click',
1749      '.select2-selection__choice__remove',
1750      function (evt) {
1751        // Ignore the event if it is disabled
1752        if (self.isDisabled()) {
1753          return;
1754        }
1755
1756        var $remove = $(this);
1757        var $selection = $remove.parent();
1758
1759        var data = Utils.GetData($selection[0], 'data');
1760
1761        self.trigger('unselect', {
1762          originalEvent: evt,
1763          data: data
1764        });
1765      }
1766    );
1767
1768    this.$selection.on(
1769      'keydown',
1770      '.select2-selection__choice__remove',
1771      function (evt) {
1772        // Ignore the event if it is disabled
1773        if (self.isDisabled()) {
1774          return;
1775        }
1776
1777        evt.stopPropagation();
1778      }
1779    );
1780  };
1781
1782  MultipleSelection.prototype.clear = function () {
1783    var $rendered = this.$selection.find('.select2-selection__rendered');
1784    $rendered.empty();
1785    $rendered.removeAttr('title');
1786  };
1787
1788  MultipleSelection.prototype.display = function (data, container) {
1789    var template = this.options.get('templateSelection');
1790    var escapeMarkup = this.options.get('escapeMarkup');
1791
1792    return escapeMarkup(template(data, container));
1793  };
1794
1795  MultipleSelection.prototype.selectionContainer = function () {
1796    var $container = $(
1797      '<li class="select2-selection__choice">' +
1798        '<button type="button" class="select2-selection__choice__remove" ' +
1799        'tabindex="-1">' +
1800          '<span aria-hidden="true">&times;</span>' +
1801        '</button>' +
1802        '<span class="select2-selection__choice__display"></span>' +
1803      '</li>'
1804    );
1805
1806    return $container;
1807  };
1808
1809  MultipleSelection.prototype.update = function (data) {
1810    this.clear();
1811
1812    if (data.length === 0) {
1813      return;
1814    }
1815
1816    var $selections = [];
1817
1818    var selectionIdPrefix = this.$selection.find('.select2-selection__rendered')
1819      .attr('id') + '-choice-';
1820
1821    for (var d = 0; d < data.length; d++) {
1822      var selection = data[d];
1823
1824      var $selection = this.selectionContainer();
1825      var formatted = this.display(selection, $selection);
1826
1827      var selectionId = selectionIdPrefix + Utils.generateChars(4) + '-';
1828
1829      if (selection.id) {
1830        selectionId += selection.id;
1831      } else {
1832        selectionId += Utils.generateChars(4);
1833      }
1834
1835      $selection.find('.select2-selection__choice__display')
1836        .append(formatted)
1837        .attr('id', selectionId);
1838
1839      var title = selection.title || selection.text;
1840
1841      if (title) {
1842        $selection.attr('title', title);
1843      }
1844
1845      var removeItem = this.options.get('translations').get('removeItem');
1846
1847      var $remove = $selection.find('.select2-selection__choice__remove');
1848
1849      $remove.attr('title', removeItem());
1850      $remove.attr('aria-label', removeItem());
1851      $remove.attr('aria-describedby', selectionId);
1852
1853      Utils.StoreData($selection[0], 'data', selection);
1854
1855      $selections.push($selection);
1856    }
1857
1858    var $rendered = this.$selection.find('.select2-selection__rendered');
1859
1860    $rendered.append($selections);
1861  };
1862
1863  return MultipleSelection;
1864});
1865
1866S2.define('select2/selection/placeholder',[
1867
1868], function () {
1869  function Placeholder (decorated, $element, options) {
1870    this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
1871
1872    decorated.call(this, $element, options);
1873  }
1874
1875  Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {
1876    if (typeof placeholder === 'string') {
1877      placeholder = {
1878        id: '',
1879        text: placeholder
1880      };
1881    }
1882
1883    return placeholder;
1884  };
1885
1886  Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
1887    var $placeholder = this.selectionContainer();
1888
1889    $placeholder.html(this.display(placeholder));
1890    $placeholder[0].classList.add('select2-selection__placeholder');
1891    $placeholder[0].classList.remove('select2-selection__choice');
1892
1893    var placeholderTitle = placeholder.title ||
1894      placeholder.text ||
1895      $placeholder.text();
1896
1897    this.$selection.find('.select2-selection__rendered').attr(
1898      'title',
1899      placeholderTitle
1900    );
1901
1902    return $placeholder;
1903  };
1904
1905  Placeholder.prototype.update = function (decorated, data) {
1906    var singlePlaceholder = (
1907      data.length == 1 && data[0].id != this.placeholder.id
1908    );
1909    var multipleSelections = data.length > 1;
1910
1911    if (multipleSelections || singlePlaceholder) {
1912      return decorated.call(this, data);
1913    }
1914
1915    this.clear();
1916
1917    var $placeholder = this.createPlaceholder(this.placeholder);
1918
1919    this.$selection.find('.select2-selection__rendered').append($placeholder);
1920  };
1921
1922  return Placeholder;
1923});
1924
1925S2.define('select2/selection/allowClear',[
1926  'jquery',
1927  '../keys',
1928  '../utils'
1929], function ($, KEYS, Utils) {
1930  function AllowClear () { }
1931
1932  AllowClear.prototype.bind = function (decorated, container, $container) {
1933    var self = this;
1934
1935    decorated.call(this, container, $container);
1936
1937    if (this.placeholder == null) {
1938      if (this.options.get('debug') && window.console && console.error) {
1939        console.error(
1940          'Select2: The `allowClear` option should be used in combination ' +
1941          'with the `placeholder` option.'
1942        );
1943      }
1944    }
1945
1946    this.$selection.on('mousedown', '.select2-selection__clear',
1947      function (evt) {
1948        self._handleClear(evt);
1949    });
1950
1951    container.on('keypress', function (evt) {
1952      self._handleKeyboardClear(evt, container);
1953    });
1954  };
1955
1956  AllowClear.prototype._handleClear = function (_, evt) {
1957    // Ignore the event if it is disabled
1958    if (this.isDisabled()) {
1959      return;
1960    }
1961
1962    var $clear = this.$selection.find('.select2-selection__clear');
1963
1964    // Ignore the event if nothing has been selected
1965    if ($clear.length === 0) {
1966      return;
1967    }
1968
1969    evt.stopPropagation();
1970
1971    var data = Utils.GetData($clear[0], 'data');
1972
1973    var previousVal = this.$element.val();
1974    this.$element.val(this.placeholder.id);
1975
1976    var unselectData = {
1977      data: data
1978    };
1979    this.trigger('clear', unselectData);
1980    if (unselectData.prevented) {
1981      this.$element.val(previousVal);
1982      return;
1983    }
1984
1985    for (var d = 0; d < data.length; d++) {
1986      unselectData = {
1987        data: data[d]
1988      };
1989
1990      // Trigger the `unselect` event, so people can prevent it from being
1991      // cleared.
1992      this.trigger('unselect', unselectData);
1993
1994      // If the event was prevented, don't clear it out.
1995      if (unselectData.prevented) {
1996        this.$element.val(previousVal);
1997        return;
1998      }
1999    }
2000
2001    this.$element.trigger('input').trigger('change');
2002
2003    this.trigger('toggle', {});
2004  };
2005
2006  AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
2007    if (container.isOpen()) {
2008      return;
2009    }
2010
2011    if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
2012      this._handleClear(evt);
2013    }
2014  };
2015
2016  AllowClear.prototype.update = function (decorated, data) {
2017    decorated.call(this, data);
2018
2019    this.$selection.find('.select2-selection__clear').remove();
2020    this.$selection[0].classList.remove('select2-selection--clearable');
2021
2022    if (this.$selection.find('.select2-selection__placeholder').length > 0 ||
2023        data.length === 0) {
2024      return;
2025    }
2026
2027    var selectionId = this.$selection.find('.select2-selection__rendered')
2028      .attr('id');
2029
2030    var removeAll = this.options.get('translations').get('removeAllItems');
2031
2032    var $remove = $(
2033      '<button type="button" class="select2-selection__clear" tabindex="-1">' +
2034        '<span aria-hidden="true">&times;</span>' +
2035      '</button>'
2036    );
2037    $remove.attr('title', removeAll());
2038    $remove.attr('aria-label', removeAll());
2039    $remove.attr('aria-describedby', selectionId);
2040    Utils.StoreData($remove[0], 'data', data);
2041
2042    this.$selection.prepend($remove);
2043    this.$selection[0].classList.add('select2-selection--clearable');
2044  };
2045
2046  return AllowClear;
2047});
2048
2049S2.define('select2/selection/search',[
2050  'jquery',
2051  '../utils',
2052  '../keys'
2053], function ($, Utils, KEYS) {
2054  function Search (decorated, $element, options) {
2055    decorated.call(this, $element, options);
2056  }
2057
2058  Search.prototype.render = function (decorated) {
2059    var searchLabel = this.options.get('translations').get('search');
2060    var $search = $(
2061      '<span class="select2-search select2-search--inline">' +
2062        '<textarea class="select2-search__field"'+
2063        ' type="search" tabindex="-1"' +
2064        ' autocorrect="off" autocapitalize="none"' +
2065        ' spellcheck="false" role="searchbox" aria-autocomplete="list" >' +
2066        '</textarea>' +
2067      '</span>'
2068    );
2069
2070    this.$searchContainer = $search;
2071    this.$search = $search.find('textarea');
2072
2073    this.$search.prop('autocomplete', this.options.get('autocomplete'));
2074    this.$search.attr('aria-label', searchLabel());
2075
2076    var $rendered = decorated.call(this);
2077
2078    this._transferTabIndex();
2079    $rendered.append(this.$searchContainer);
2080
2081    return $rendered;
2082  };
2083
2084  Search.prototype.bind = function (decorated, container, $container) {
2085    var self = this;
2086
2087    var resultsId = container.id + '-results';
2088    var selectionId = container.id + '-container';
2089
2090    decorated.call(this, container, $container);
2091
2092    self.$search.attr('aria-describedby', selectionId);
2093
2094    container.on('open', function () {
2095      self.$search.attr('aria-controls', resultsId);
2096      self.$search.trigger('focus');
2097    });
2098
2099    container.on('close', function () {
2100      self.$search.val('');
2101      self.resizeSearch();
2102      self.$search.removeAttr('aria-controls');
2103      self.$search.removeAttr('aria-activedescendant');
2104      self.$search.trigger('focus');
2105    });
2106
2107    container.on('enable', function () {
2108      self.$search.prop('disabled', false);
2109
2110      self._transferTabIndex();
2111    });
2112
2113    container.on('disable', function () {
2114      self.$search.prop('disabled', true);
2115    });
2116
2117    container.on('focus', function (evt) {
2118      self.$search.trigger('focus');
2119    });
2120
2121    container.on('results:focus', function (params) {
2122      if (params.data._resultId) {
2123        self.$search.attr('aria-activedescendant', params.data._resultId);
2124      } else {
2125        self.$search.removeAttr('aria-activedescendant');
2126      }
2127    });
2128
2129    this.$selection.on('focusin', '.select2-search--inline', function (evt) {
2130      self.trigger('focus', evt);
2131    });
2132
2133    this.$selection.on('focusout', '.select2-search--inline', function (evt) {
2134      self._handleBlur(evt);
2135    });
2136
2137    this.$selection.on('keydown', '.select2-search--inline', function (evt) {
2138      evt.stopPropagation();
2139
2140      self.trigger('keypress', evt);
2141
2142      self._keyUpPrevented = evt.isDefaultPrevented();
2143
2144      var key = evt.which;
2145
2146      if (key === KEYS.BACKSPACE && self.$search.val() === '') {
2147        var $previousChoice = self.$selection
2148          .find('.select2-selection__choice').last();
2149
2150        if ($previousChoice.length > 0) {
2151          var item = Utils.GetData($previousChoice[0], 'data');
2152
2153          self.searchRemoveChoice(item);
2154
2155          evt.preventDefault();
2156        }
2157      }
2158    });
2159
2160    this.$selection.on('click', '.select2-search--inline', function (evt) {
2161      if (self.$search.val()) {
2162        evt.stopPropagation();
2163      }
2164    });
2165
2166    // Try to detect the IE version should the `documentMode` property that
2167    // is stored on the document. This is only implemented in IE and is
2168    // slightly cleaner than doing a user agent check.
2169    // This property is not available in Edge, but Edge also doesn't have
2170    // this bug.
2171    var msie = document.documentMode;
2172    var disableInputEvents = msie && msie <= 11;
2173
2174    // Workaround for browsers which do not support the `input` event
2175    // This will prevent double-triggering of events for browsers which support
2176    // both the `keyup` and `input` events.
2177    this.$selection.on(
2178      'input.searchcheck',
2179      '.select2-search--inline',
2180      function (evt) {
2181        // IE will trigger the `input` event when a placeholder is used on a
2182        // search box. To get around this issue, we are forced to ignore all
2183        // `input` events in IE and keep using `keyup`.
2184        if (disableInputEvents) {
2185          self.$selection.off('input.search input.searchcheck');
2186          return;
2187        }
2188
2189        // Unbind the duplicated `keyup` event
2190        self.$selection.off('keyup.search');
2191      }
2192    );
2193
2194    this.$selection.on(
2195      'keyup.search input.search',
2196      '.select2-search--inline',
2197      function (evt) {
2198        // IE will trigger the `input` event when a placeholder is used on a
2199        // search box. To get around this issue, we are forced to ignore all
2200        // `input` events in IE and keep using `keyup`.
2201        if (disableInputEvents && evt.type === 'input') {
2202          self.$selection.off('input.search input.searchcheck');
2203          return;
2204        }
2205
2206        var key = evt.which;
2207
2208        // We can freely ignore events from modifier keys
2209        if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
2210          return;
2211        }
2212
2213        // Tabbing will be handled during the `keydown` phase
2214        if (key == KEYS.TAB) {
2215          return;
2216        }
2217
2218        self.handleSearch(evt);
2219      }
2220    );
2221  };
2222
2223  /**
2224   * This method will transfer the tabindex attribute from the rendered
2225   * selection to the search box. This allows for the search box to be used as
2226   * the primary focus instead of the selection container.
2227   *
2228   * @private
2229   */
2230  Search.prototype._transferTabIndex = function (decorated) {
2231    this.$search.attr('tabindex', this.$selection.attr('tabindex'));
2232    this.$selection.attr('tabindex', '-1');
2233  };
2234
2235  Search.prototype.createPlaceholder = function (decorated, placeholder) {
2236    this.$search.attr('placeholder', placeholder.text);
2237  };
2238
2239  Search.prototype.update = function (decorated, data) {
2240    var searchHadFocus = this.$search[0] == document.activeElement;
2241
2242    this.$search.attr('placeholder', '');
2243
2244    decorated.call(this, data);
2245
2246    this.resizeSearch();
2247    if (searchHadFocus) {
2248      this.$search.trigger('focus');
2249    }
2250  };
2251
2252  Search.prototype.handleSearch = function () {
2253    this.resizeSearch();
2254
2255    if (!this._keyUpPrevented) {
2256      var input = this.$search.val();
2257
2258      this.trigger('query', {
2259        term: input
2260      });
2261    }
2262
2263    this._keyUpPrevented = false;
2264  };
2265
2266  Search.prototype.searchRemoveChoice = function (decorated, item) {
2267    this.trigger('unselect', {
2268      data: item
2269    });
2270
2271    this.$search.val(item.text);
2272    this.handleSearch();
2273  };
2274
2275  Search.prototype.resizeSearch = function () {
2276    this.$search.css('width', '25px');
2277
2278    var width = '100%';
2279
2280    if (this.$search.attr('placeholder') === '') {
2281      var minimumWidth = this.$search.val().length + 1;
2282
2283      width = (minimumWidth * 0.75) + 'em';
2284    }
2285
2286    this.$search.css('width', width);
2287  };
2288
2289  return Search;
2290});
2291
2292S2.define('select2/selection/selectionCss',[
2293  '../utils'
2294], function (Utils) {
2295  function SelectionCSS () { }
2296
2297  SelectionCSS.prototype.render = function (decorated) {
2298    var $selection = decorated.call(this);
2299
2300    var selectionCssClass = this.options.get('selectionCssClass') || '';
2301
2302    if (selectionCssClass.indexOf(':all:') !== -1) {
2303      selectionCssClass = selectionCssClass.replace(':all:', '');
2304
2305      Utils.copyNonInternalCssClasses($selection[0], this.$element[0]);
2306    }
2307
2308    $selection.addClass(selectionCssClass);
2309
2310    return $selection;
2311  };
2312
2313  return SelectionCSS;
2314});
2315
2316S2.define('select2/selection/eventRelay',[
2317  'jquery'
2318], function ($) {
2319  function EventRelay () { }
2320
2321  EventRelay.prototype.bind = function (decorated, container, $container) {
2322    var self = this;
2323    var relayEvents = [
2324      'open', 'opening',
2325      'close', 'closing',
2326      'select', 'selecting',
2327      'unselect', 'unselecting',
2328      'clear', 'clearing'
2329    ];
2330
2331    var preventableEvents = [
2332      'opening', 'closing', 'selecting', 'unselecting', 'clearing'
2333    ];
2334
2335    decorated.call(this, container, $container);
2336
2337    container.on('*', function (name, params) {
2338      // Ignore events that should not be relayed
2339      if (relayEvents.indexOf(name) === -1) {
2340        return;
2341      }
2342
2343      // The parameters should always be an object
2344      params = params || {};
2345
2346      // Generate the jQuery event for the Select2 event
2347      var evt = $.Event('select2:' + name, {
2348        params: params
2349      });
2350
2351      self.$element.trigger(evt);
2352
2353      // Only handle preventable events if it was one
2354      if (preventableEvents.indexOf(name) === -1) {
2355        return;
2356      }
2357
2358      params.prevented = evt.isDefaultPrevented();
2359    });
2360  };
2361
2362  return EventRelay;
2363});
2364
2365S2.define('select2/translation',[
2366  'jquery',
2367  'require'
2368], function ($, require) {
2369  function Translation (dict) {
2370    this.dict = dict || {};
2371  }
2372
2373  Translation.prototype.all = function () {
2374    return this.dict;
2375  };
2376
2377  Translation.prototype.get = function (key) {
2378    return this.dict[key];
2379  };
2380
2381  Translation.prototype.extend = function (translation) {
2382    this.dict = $.extend({}, translation.all(), this.dict);
2383  };
2384
2385  // Static functions
2386
2387  Translation._cache = {};
2388
2389  Translation.loadPath = function (path) {
2390    if (!(path in Translation._cache)) {
2391      var translations = require(path);
2392
2393      Translation._cache[path] = translations;
2394    }
2395
2396    return new Translation(Translation._cache[path]);
2397  };
2398
2399  return Translation;
2400});
2401
2402S2.define('select2/diacritics',[
2403
2404], function () {
2405  var diacritics = {
2406    '\u24B6': 'A',
2407    '\uFF21': 'A',
2408    '\u00C0': 'A',
2409    '\u00C1': 'A',
2410    '\u00C2': 'A',
2411    '\u1EA6': 'A',
2412    '\u1EA4': 'A',
2413    '\u1EAA': 'A',
2414    '\u1EA8': 'A',
2415    '\u00C3': 'A',
2416    '\u0100': 'A',
2417    '\u0102': 'A',
2418    '\u1EB0': 'A',
2419    '\u1EAE': 'A',
2420    '\u1EB4': 'A',
2421    '\u1EB2': 'A',
2422    '\u0226': 'A',
2423    '\u01E0': 'A',
2424    '\u00C4': 'A',
2425    '\u01DE': 'A',
2426    '\u1EA2': 'A',
2427    '\u00C5': 'A',
2428    '\u01FA': 'A',
2429    '\u01CD': 'A',
2430    '\u0200': 'A',
2431    '\u0202': 'A',
2432    '\u1EA0': 'A',
2433    '\u1EAC': 'A',
2434    '\u1EB6': 'A',
2435    '\u1E00': 'A',
2436    '\u0104': 'A',
2437    '\u023A': 'A',
2438    '\u2C6F': 'A',
2439    '\uA732': 'AA',
2440    '\u00C6': 'AE',
2441    '\u01FC': 'AE',
2442    '\u01E2': 'AE',
2443    '\uA734': 'AO',
2444    '\uA736': 'AU',
2445    '\uA738': 'AV',
2446    '\uA73A': 'AV',
2447    '\uA73C': 'AY',
2448    '\u24B7': 'B',
2449    '\uFF22': 'B',
2450    '\u1E02': 'B',
2451    '\u1E04': 'B',
2452    '\u1E06': 'B',
2453    '\u0243': 'B',
2454    '\u0182': 'B',
2455    '\u0181': 'B',
2456    '\u24B8': 'C',
2457    '\uFF23': 'C',
2458    '\u0106': 'C',
2459    '\u0108': 'C',
2460    '\u010A': 'C',
2461    '\u010C': 'C',
2462    '\u00C7': 'C',
2463    '\u1E08': 'C',
2464    '\u0187': 'C',
2465    '\u023B': 'C',
2466    '\uA73E': 'C',
2467    '\u24B9': 'D',
2468    '\uFF24': 'D',
2469    '\u1E0A': 'D',
2470    '\u010E': 'D',
2471    '\u1E0C': 'D',
2472    '\u1E10': 'D',
2473    '\u1E12': 'D',
2474    '\u1E0E': 'D',
2475    '\u0110': 'D',
2476    '\u018B': 'D',
2477    '\u018A': 'D',
2478    '\u0189': 'D',
2479    '\uA779': 'D',
2480    '\u01F1': 'DZ',
2481    '\u01C4': 'DZ',
2482    '\u01F2': 'Dz',
2483    '\u01C5': 'Dz',
2484    '\u24BA': 'E',
2485    '\uFF25': 'E',
2486    '\u00C8': 'E',
2487    '\u00C9': 'E',
2488    '\u00CA': 'E',
2489    '\u1EC0': 'E',
2490    '\u1EBE': 'E',
2491    '\u1EC4': 'E',
2492    '\u1EC2': 'E',
2493    '\u1EBC': 'E',
2494    '\u0112': 'E',
2495    '\u1E14': 'E',
2496    '\u1E16': 'E',
2497    '\u0114': 'E',
2498    '\u0116': 'E',
2499    '\u00CB': 'E',
2500    '\u1EBA': 'E',
2501    '\u011A': 'E',
2502    '\u0204': 'E',
2503    '\u0206': 'E',
2504    '\u1EB8': 'E',
2505    '\u1EC6': 'E',
2506    '\u0228': 'E',
2507    '\u1E1C': 'E',
2508    '\u0118': 'E',
2509    '\u1E18': 'E',
2510    '\u1E1A': 'E',
2511    '\u0190': 'E',
2512    '\u018E': 'E',
2513    '\u24BB': 'F',
2514    '\uFF26': 'F',
2515    '\u1E1E': 'F',
2516    '\u0191': 'F',
2517    '\uA77B': 'F',
2518    '\u24BC': 'G',
2519    '\uFF27': 'G',
2520    '\u01F4': 'G',
2521    '\u011C': 'G',
2522    '\u1E20': 'G',
2523    '\u011E': 'G',
2524    '\u0120': 'G',
2525    '\u01E6': 'G',
2526    '\u0122': 'G',
2527    '\u01E4': 'G',
2528    '\u0193': 'G',
2529    '\uA7A0': 'G',
2530    '\uA77D': 'G',
2531    '\uA77E': 'G',
2532    '\u24BD': 'H',
2533    '\uFF28': 'H',
2534    '\u0124': 'H',
2535    '\u1E22': 'H',
2536    '\u1E26': 'H',
2537    '\u021E': 'H',
2538    '\u1E24': 'H',
2539    '\u1E28': 'H',
2540    '\u1E2A': 'H',
2541    '\u0126': 'H',
2542    '\u2C67': 'H',
2543    '\u2C75': 'H',
2544    '\uA78D': 'H',
2545    '\u24BE': 'I',
2546    '\uFF29': 'I',
2547    '\u00CC': 'I',
2548    '\u00CD': 'I',
2549    '\u00CE': 'I',
2550    '\u0128': 'I',
2551    '\u012A': 'I',
2552    '\u012C': 'I',
2553    '\u0130': 'I',
2554    '\u00CF': 'I',
2555    '\u1E2E': 'I',
2556    '\u1EC8': 'I',
2557    '\u01CF': 'I',
2558    '\u0208': 'I',
2559    '\u020A': 'I',
2560    '\u1ECA': 'I',
2561    '\u012E': 'I',
2562    '\u1E2C': 'I',
2563    '\u0197': 'I',
2564    '\u24BF': 'J',
2565    '\uFF2A': 'J',
2566    '\u0134': 'J',
2567    '\u0248': 'J',
2568    '\u24C0': 'K',
2569    '\uFF2B': 'K',
2570    '\u1E30': 'K',
2571    '\u01E8': 'K',
2572    '\u1E32': 'K',
2573    '\u0136': 'K',
2574    '\u1E34': 'K',
2575    '\u0198': 'K',
2576    '\u2C69': 'K',
2577    '\uA740': 'K',
2578    '\uA742': 'K',
2579    '\uA744': 'K',
2580    '\uA7A2': 'K',
2581    '\u24C1': 'L',
2582    '\uFF2C': 'L',
2583    '\u013F': 'L',
2584    '\u0139': 'L',
2585    '\u013D': 'L',
2586    '\u1E36': 'L',
2587    '\u1E38': 'L',
2588    '\u013B': 'L',
2589    '\u1E3C': 'L',
2590    '\u1E3A': 'L',
2591    '\u0141': 'L',
2592    '\u023D': 'L',
2593    '\u2C62': 'L',
2594    '\u2C60': 'L',
2595    '\uA748': 'L',
2596    '\uA746': 'L',
2597    '\uA780': 'L',
2598    '\u01C7': 'LJ',
2599    '\u01C8': 'Lj',
2600    '\u24C2': 'M',
2601    '\uFF2D': 'M',
2602    '\u1E3E': 'M',
2603    '\u1E40': 'M',
2604    '\u1E42': 'M',
2605    '\u2C6E': 'M',
2606    '\u019C': 'M',
2607    '\u24C3': 'N',
2608    '\uFF2E': 'N',
2609    '\u01F8': 'N',
2610    '\u0143': 'N',
2611    '\u00D1': 'N',
2612    '\u1E44': 'N',
2613    '\u0147': 'N',
2614    '\u1E46': 'N',
2615    '\u0145': 'N',
2616    '\u1E4A': 'N',
2617    '\u1E48': 'N',
2618    '\u0220': 'N',
2619    '\u019D': 'N',
2620    '\uA790': 'N',
2621    '\uA7A4': 'N',
2622    '\u01CA': 'NJ',
2623    '\u01CB': 'Nj',
2624    '\u24C4': 'O',
2625    '\uFF2F': 'O',
2626    '\u00D2': 'O',
2627    '\u00D3': 'O',
2628    '\u00D4': 'O',
2629    '\u1ED2': 'O',
2630    '\u1ED0': 'O',
2631    '\u1ED6': 'O',
2632    '\u1ED4': 'O',
2633    '\u00D5': 'O',
2634    '\u1E4C': 'O',
2635    '\u022C': 'O',
2636    '\u1E4E': 'O',
2637    '\u014C': 'O',
2638    '\u1E50': 'O',
2639    '\u1E52': 'O',
2640    '\u014E': 'O',
2641    '\u022E': 'O',
2642    '\u0230': 'O',
2643    '\u00D6': 'O',
2644    '\u022A': 'O',
2645    '\u1ECE': 'O',
2646    '\u0150': 'O',
2647    '\u01D1': 'O',
2648    '\u020C': 'O',
2649    '\u020E': 'O',
2650    '\u01A0': 'O',
2651    '\u1EDC': 'O',
2652    '\u1EDA': 'O',
2653    '\u1EE0': 'O',
2654    '\u1EDE': 'O',
2655    '\u1EE2': 'O',
2656    '\u1ECC': 'O',
2657    '\u1ED8': 'O',
2658    '\u01EA': 'O',
2659    '\u01EC': 'O',
2660    '\u00D8': 'O',
2661    '\u01FE': 'O',
2662    '\u0186': 'O',
2663    '\u019F': 'O',
2664    '\uA74A': 'O',
2665    '\uA74C': 'O',
2666    '\u0152': 'OE',
2667    '\u01A2': 'OI',
2668    '\uA74E': 'OO',
2669    '\u0222': 'OU',
2670    '\u24C5': 'P',
2671    '\uFF30': 'P',
2672    '\u1E54': 'P',
2673    '\u1E56': 'P',
2674    '\u01A4': 'P',
2675    '\u2C63': 'P',
2676    '\uA750': 'P',
2677    '\uA752': 'P',
2678    '\uA754': 'P',
2679    '\u24C6': 'Q',
2680    '\uFF31': 'Q',
2681    '\uA756': 'Q',
2682    '\uA758': 'Q',
2683    '\u024A': 'Q',
2684    '\u24C7': 'R',
2685    '\uFF32': 'R',
2686    '\u0154': 'R',
2687    '\u1E58': 'R',
2688    '\u0158': 'R',
2689    '\u0210': 'R',
2690    '\u0212': 'R',
2691    '\u1E5A': 'R',
2692    '\u1E5C': 'R',
2693    '\u0156': 'R',
2694    '\u1E5E': 'R',
2695    '\u024C': 'R',
2696    '\u2C64': 'R',
2697    '\uA75A': 'R',
2698    '\uA7A6': 'R',
2699    '\uA782': 'R',
2700    '\u24C8': 'S',
2701    '\uFF33': 'S',
2702    '\u1E9E': 'S',
2703    '\u015A': 'S',
2704    '\u1E64': 'S',
2705    '\u015C': 'S',
2706    '\u1E60': 'S',
2707    '\u0160': 'S',
2708    '\u1E66': 'S',
2709    '\u1E62': 'S',
2710    '\u1E68': 'S',
2711    '\u0218': 'S',
2712    '\u015E': 'S',
2713    '\u2C7E': 'S',
2714    '\uA7A8': 'S',
2715    '\uA784': 'S',
2716    '\u24C9': 'T',
2717    '\uFF34': 'T',
2718    '\u1E6A': 'T',
2719    '\u0164': 'T',
2720    '\u1E6C': 'T',
2721    '\u021A': 'T',
2722    '\u0162': 'T',
2723    '\u1E70': 'T',
2724    '\u1E6E': 'T',
2725    '\u0166': 'T',
2726    '\u01AC': 'T',
2727    '\u01AE': 'T',
2728    '\u023E': 'T',
2729    '\uA786': 'T',
2730    '\uA728': 'TZ',
2731    '\u24CA': 'U',
2732    '\uFF35': 'U',
2733    '\u00D9': 'U',
2734    '\u00DA': 'U',
2735    '\u00DB': 'U',
2736    '\u0168': 'U',
2737    '\u1E78': 'U',
2738    '\u016A': 'U',
2739    '\u1E7A': 'U',
2740    '\u016C': 'U',
2741    '\u00DC': 'U',
2742    '\u01DB': 'U',
2743    '\u01D7': 'U',
2744    '\u01D5': 'U',
2745    '\u01D9': 'U',
2746    '\u1EE6': 'U',
2747    '\u016E': 'U',
2748    '\u0170': 'U',
2749    '\u01D3': 'U',
2750    '\u0214': 'U',
2751    '\u0216': 'U',
2752    '\u01AF': 'U',
2753    '\u1EEA': 'U',
2754    '\u1EE8': 'U',
2755    '\u1EEE': 'U',
2756    '\u1EEC': 'U',
2757    '\u1EF0': 'U',
2758    '\u1EE4': 'U',
2759    '\u1E72': 'U',
2760    '\u0172': 'U',
2761    '\u1E76': 'U',
2762    '\u1E74': 'U',
2763    '\u0244': 'U',
2764    '\u24CB': 'V',
2765    '\uFF36': 'V',
2766    '\u1E7C': 'V',
2767    '\u1E7E': 'V',
2768    '\u01B2': 'V',
2769    '\uA75E': 'V',
2770    '\u0245': 'V',
2771    '\uA760': 'VY',
2772    '\u24CC': 'W',
2773    '\uFF37': 'W',
2774    '\u1E80': 'W',
2775    '\u1E82': 'W',
2776    '\u0174': 'W',
2777    '\u1E86': 'W',
2778    '\u1E84': 'W',
2779    '\u1E88': 'W',
2780    '\u2C72': 'W',
2781    '\u24CD': 'X',
2782    '\uFF38': 'X',
2783    '\u1E8A': 'X',
2784    '\u1E8C': 'X',
2785    '\u24CE': 'Y',
2786    '\uFF39': 'Y',
2787    '\u1EF2': 'Y',
2788    '\u00DD': 'Y',
2789    '\u0176': 'Y',
2790    '\u1EF8': 'Y',
2791    '\u0232': 'Y',
2792    '\u1E8E': 'Y',
2793    '\u0178': 'Y',
2794    '\u1EF6': 'Y',
2795    '\u1EF4': 'Y',
2796    '\u01B3': 'Y',
2797    '\u024E': 'Y',
2798    '\u1EFE': 'Y',
2799    '\u24CF': 'Z',
2800    '\uFF3A': 'Z',
2801    '\u0179': 'Z',
2802    '\u1E90': 'Z',
2803    '\u017B': 'Z',
2804    '\u017D': 'Z',
2805    '\u1E92': 'Z',
2806    '\u1E94': 'Z',
2807    '\u01B5': 'Z',
2808    '\u0224': 'Z',
2809    '\u2C7F': 'Z',
2810    '\u2C6B': 'Z',
2811    '\uA762': 'Z',
2812    '\u24D0': 'a',
2813    '\uFF41': 'a',
2814    '\u1E9A': 'a',
2815    '\u00E0': 'a',
2816    '\u00E1': 'a',
2817    '\u00E2': 'a',
2818    '\u1EA7': 'a',
2819    '\u1EA5': 'a',
2820    '\u1EAB': 'a',
2821    '\u1EA9': 'a',
2822    '\u00E3': 'a',
2823    '\u0101': 'a',
2824    '\u0103': 'a',
2825    '\u1EB1': 'a',
2826    '\u1EAF': 'a',
2827    '\u1EB5': 'a',
2828    '\u1EB3': 'a',
2829    '\u0227': 'a',
2830    '\u01E1': 'a',
2831    '\u00E4': 'a',
2832    '\u01DF': 'a',
2833    '\u1EA3': 'a',
2834    '\u00E5': 'a',
2835    '\u01FB': 'a',
2836    '\u01CE': 'a',
2837    '\u0201': 'a',
2838    '\u0203': 'a',
2839    '\u1EA1': 'a',
2840    '\u1EAD': 'a',
2841    '\u1EB7': 'a',
2842    '\u1E01': 'a',
2843    '\u0105': 'a',
2844    '\u2C65': 'a',
2845    '\u0250': 'a',
2846    '\uA733': 'aa',
2847    '\u00E6': 'ae',
2848    '\u01FD': 'ae',
2849    '\u01E3': 'ae',
2850    '\uA735': 'ao',
2851    '\uA737': 'au',
2852    '\uA739': 'av',
2853    '\uA73B': 'av',
2854    '\uA73D': 'ay',
2855    '\u24D1': 'b',
2856    '\uFF42': 'b',
2857    '\u1E03': 'b',
2858    '\u1E05': 'b',
2859    '\u1E07': 'b',
2860    '\u0180': 'b',
2861    '\u0183': 'b',
2862    '\u0253': 'b',
2863    '\u24D2': 'c',
2864    '\uFF43': 'c',
2865    '\u0107': 'c',
2866    '\u0109': 'c',
2867    '\u010B': 'c',
2868    '\u010D': 'c',
2869    '\u00E7': 'c',
2870    '\u1E09': 'c',
2871    '\u0188': 'c',
2872    '\u023C': 'c',
2873    '\uA73F': 'c',
2874    '\u2184': 'c',
2875    '\u24D3': 'd',
2876    '\uFF44': 'd',
2877    '\u1E0B': 'd',
2878    '\u010F': 'd',
2879    '\u1E0D': 'd',
2880    '\u1E11': 'd',
2881    '\u1E13': 'd',
2882    '\u1E0F': 'd',
2883    '\u0111': 'd',
2884    '\u018C': 'd',
2885    '\u0256': 'd',
2886    '\u0257': 'd',
2887    '\uA77A': 'd',
2888    '\u01F3': 'dz',
2889    '\u01C6': 'dz',
2890    '\u24D4': 'e',
2891    '\uFF45': 'e',
2892    '\u00E8': 'e',
2893    '\u00E9': 'e',
2894    '\u00EA': 'e',
2895    '\u1EC1': 'e',
2896    '\u1EBF': 'e',
2897    '\u1EC5': 'e',
2898    '\u1EC3': 'e',
2899    '\u1EBD': 'e',
2900    '\u0113': 'e',
2901    '\u1E15': 'e',
2902    '\u1E17': 'e',
2903    '\u0115': 'e',
2904    '\u0117': 'e',
2905    '\u00EB': 'e',
2906    '\u1EBB': 'e',
2907    '\u011B': 'e',
2908    '\u0205': 'e',
2909    '\u0207': 'e',
2910    '\u1EB9': 'e',
2911    '\u1EC7': 'e',
2912    '\u0229': 'e',
2913    '\u1E1D': 'e',
2914    '\u0119': 'e',
2915    '\u1E19': 'e',
2916    '\u1E1B': 'e',
2917    '\u0247': 'e',
2918    '\u025B': 'e',
2919    '\u01DD': 'e',
2920    '\u24D5': 'f',
2921    '\uFF46': 'f',
2922    '\u1E1F': 'f',
2923    '\u0192': 'f',
2924    '\uA77C': 'f',
2925    '\u24D6': 'g',
2926    '\uFF47': 'g',
2927    '\u01F5': 'g',
2928    '\u011D': 'g',
2929    '\u1E21': 'g',
2930    '\u011F': 'g',
2931    '\u0121': 'g',
2932    '\u01E7': 'g',
2933    '\u0123': 'g',
2934    '\u01E5': 'g',
2935    '\u0260': 'g',
2936    '\uA7A1': 'g',
2937    '\u1D79': 'g',
2938    '\uA77F': 'g',
2939    '\u24D7': 'h',
2940    '\uFF48': 'h',
2941    '\u0125': 'h',
2942    '\u1E23': 'h',
2943    '\u1E27': 'h',
2944    '\u021F': 'h',
2945    '\u1E25': 'h',
2946    '\u1E29': 'h',
2947    '\u1E2B': 'h',
2948    '\u1E96': 'h',
2949    '\u0127': 'h',
2950    '\u2C68': 'h',
2951    '\u2C76': 'h',
2952    '\u0265': 'h',
2953    '\u0195': 'hv',
2954    '\u24D8': 'i',
2955    '\uFF49': 'i',
2956    '\u00EC': 'i',
2957    '\u00ED': 'i',
2958    '\u00EE': 'i',
2959    '\u0129': 'i',
2960    '\u012B': 'i',
2961    '\u012D': 'i',
2962    '\u00EF': 'i',
2963    '\u1E2F': 'i',
2964    '\u1EC9': 'i',
2965    '\u01D0': 'i',
2966    '\u0209': 'i',
2967    '\u020B': 'i',
2968    '\u1ECB': 'i',
2969    '\u012F': 'i',
2970    '\u1E2D': 'i',
2971    '\u0268': 'i',
2972    '\u0131': 'i',
2973    '\u24D9': 'j',
2974    '\uFF4A': 'j',
2975    '\u0135': 'j',
2976    '\u01F0': 'j',
2977    '\u0249': 'j',
2978    '\u24DA': 'k',
2979    '\uFF4B': 'k',
2980    '\u1E31': 'k',
2981    '\u01E9': 'k',
2982    '\u1E33': 'k',
2983    '\u0137': 'k',
2984    '\u1E35': 'k',
2985    '\u0199': 'k',
2986    '\u2C6A': 'k',
2987    '\uA741': 'k',
2988    '\uA743': 'k',
2989    '\uA745': 'k',
2990    '\uA7A3': 'k',
2991    '\u24DB': 'l',
2992    '\uFF4C': 'l',
2993    '\u0140': 'l',
2994    '\u013A': 'l',
2995    '\u013E': 'l',
2996    '\u1E37': 'l',
2997    '\u1E39': 'l',
2998    '\u013C': 'l',
2999    '\u1E3D': 'l',
3000    '\u1E3B': 'l',
3001    '\u017F': 'l',
3002    '\u0142': 'l',
3003    '\u019A': 'l',
3004    '\u026B': 'l',
3005    '\u2C61': 'l',
3006    '\uA749': 'l',
3007    '\uA781': 'l',
3008    '\uA747': 'l',
3009    '\u01C9': 'lj',
3010    '\u24DC': 'm',
3011    '\uFF4D': 'm',
3012    '\u1E3F': 'm',
3013    '\u1E41': 'm',
3014    '\u1E43': 'm',
3015    '\u0271': 'm',
3016    '\u026F': 'm',
3017    '\u24DD': 'n',
3018    '\uFF4E': 'n',
3019    '\u01F9': 'n',
3020    '\u0144': 'n',
3021    '\u00F1': 'n',
3022    '\u1E45': 'n',
3023    '\u0148': 'n',
3024    '\u1E47': 'n',
3025    '\u0146': 'n',
3026    '\u1E4B': 'n',
3027    '\u1E49': 'n',
3028    '\u019E': 'n',
3029    '\u0272': 'n',
3030    '\u0149': 'n',
3031    '\uA791': 'n',
3032    '\uA7A5': 'n',
3033    '\u01CC': 'nj',
3034    '\u24DE': 'o',
3035    '\uFF4F': 'o',
3036    '\u00F2': 'o',
3037    '\u00F3': 'o',
3038    '\u00F4': 'o',
3039    '\u1ED3': 'o',
3040    '\u1ED1': 'o',
3041    '\u1ED7': 'o',
3042    '\u1ED5': 'o',
3043    '\u00F5': 'o',
3044    '\u1E4D': 'o',
3045    '\u022D': 'o',
3046    '\u1E4F': 'o',
3047    '\u014D': 'o',
3048    '\u1E51': 'o',
3049    '\u1E53': 'o',
3050    '\u014F': 'o',
3051    '\u022F': 'o',
3052    '\u0231': 'o',
3053    '\u00F6': 'o',
3054    '\u022B': 'o',
3055    '\u1ECF': 'o',
3056    '\u0151': 'o',
3057    '\u01D2': 'o',
3058    '\u020D': 'o',
3059    '\u020F': 'o',
3060    '\u01A1': 'o',
3061    '\u1EDD': 'o',
3062    '\u1EDB': 'o',
3063    '\u1EE1': 'o',
3064    '\u1EDF': 'o',
3065    '\u1EE3': 'o',
3066    '\u1ECD': 'o',
3067    '\u1ED9': 'o',
3068    '\u01EB': 'o',
3069    '\u01ED': 'o',
3070    '\u00F8': 'o',
3071    '\u01FF': 'o',
3072    '\u0254': 'o',
3073    '\uA74B': 'o',
3074    '\uA74D': 'o',
3075    '\u0275': 'o',
3076    '\u0153': 'oe',
3077    '\u01A3': 'oi',
3078    '\u0223': 'ou',
3079    '\uA74F': 'oo',
3080    '\u24DF': 'p',
3081    '\uFF50': 'p',
3082    '\u1E55': 'p',
3083    '\u1E57': 'p',
3084    '\u01A5': 'p',
3085    '\u1D7D': 'p',
3086    '\uA751': 'p',
3087    '\uA753': 'p',
3088    '\uA755': 'p',
3089    '\u24E0': 'q',
3090    '\uFF51': 'q',
3091    '\u024B': 'q',
3092    '\uA757': 'q',
3093    '\uA759': 'q',
3094    '\u24E1': 'r',
3095    '\uFF52': 'r',
3096    '\u0155': 'r',
3097    '\u1E59': 'r',
3098    '\u0159': 'r',
3099    '\u0211': 'r',
3100    '\u0213': 'r',
3101    '\u1E5B': 'r',
3102    '\u1E5D': 'r',
3103    '\u0157': 'r',
3104    '\u1E5F': 'r',
3105    '\u024D': 'r',
3106    '\u027D': 'r',
3107    '\uA75B': 'r',
3108    '\uA7A7': 'r',
3109    '\uA783': 'r',
3110    '\u24E2': 's',
3111    '\uFF53': 's',
3112    '\u00DF': 's',
3113    '\u015B': 's',
3114    '\u1E65': 's',
3115    '\u015D': 's',
3116    '\u1E61': 's',
3117    '\u0161': 's',
3118    '\u1E67': 's',
3119    '\u1E63': 's',
3120    '\u1E69': 's',
3121    '\u0219': 's',
3122    '\u015F': 's',
3123    '\u023F': 's',
3124    '\uA7A9': 's',
3125    '\uA785': 's',
3126    '\u1E9B': 's',
3127    '\u24E3': 't',
3128    '\uFF54': 't',
3129    '\u1E6B': 't',
3130    '\u1E97': 't',
3131    '\u0165': 't',
3132    '\u1E6D': 't',
3133    '\u021B': 't',
3134    '\u0163': 't',
3135    '\u1E71': 't',
3136    '\u1E6F': 't',
3137    '\u0167': 't',
3138    '\u01AD': 't',
3139    '\u0288': 't',
3140    '\u2C66': 't',
3141    '\uA787': 't',
3142    '\uA729': 'tz',
3143    '\u24E4': 'u',
3144    '\uFF55': 'u',
3145    '\u00F9': 'u',
3146    '\u00FA': 'u',
3147    '\u00FB': 'u',
3148    '\u0169': 'u',
3149    '\u1E79': 'u',
3150    '\u016B': 'u',
3151    '\u1E7B': 'u',
3152    '\u016D': 'u',
3153    '\u00FC': 'u',
3154    '\u01DC': 'u',
3155    '\u01D8': 'u',
3156    '\u01D6': 'u',
3157    '\u01DA': 'u',
3158    '\u1EE7': 'u',
3159    '\u016F': 'u',
3160    '\u0171': 'u',
3161    '\u01D4': 'u',
3162    '\u0215': 'u',
3163    '\u0217': 'u',
3164    '\u01B0': 'u',
3165    '\u1EEB': 'u',
3166    '\u1EE9': 'u',
3167    '\u1EEF': 'u',
3168    '\u1EED': 'u',
3169    '\u1EF1': 'u',
3170    '\u1EE5': 'u',
3171    '\u1E73': 'u',
3172    '\u0173': 'u',
3173    '\u1E77': 'u',
3174    '\u1E75': 'u',
3175    '\u0289': 'u',
3176    '\u24E5': 'v',
3177    '\uFF56': 'v',
3178    '\u1E7D': 'v',
3179    '\u1E7F': 'v',
3180    '\u028B': 'v',
3181    '\uA75F': 'v',
3182    '\u028C': 'v',
3183    '\uA761': 'vy',
3184    '\u24E6': 'w',
3185    '\uFF57': 'w',
3186    '\u1E81': 'w',
3187    '\u1E83': 'w',
3188    '\u0175': 'w',
3189    '\u1E87': 'w',
3190    '\u1E85': 'w',
3191    '\u1E98': 'w',
3192    '\u1E89': 'w',
3193    '\u2C73': 'w',
3194    '\u24E7': 'x',
3195    '\uFF58': 'x',
3196    '\u1E8B': 'x',
3197    '\u1E8D': 'x',
3198    '\u24E8': 'y',
3199    '\uFF59': 'y',
3200    '\u1EF3': 'y',
3201    '\u00FD': 'y',
3202    '\u0177': 'y',
3203    '\u1EF9': 'y',
3204    '\u0233': 'y',
3205    '\u1E8F': 'y',
3206    '\u00FF': 'y',
3207    '\u1EF7': 'y',
3208    '\u1E99': 'y',
3209    '\u1EF5': 'y',
3210    '\u01B4': 'y',
3211    '\u024F': 'y',
3212    '\u1EFF': 'y',
3213    '\u24E9': 'z',
3214    '\uFF5A': 'z',
3215    '\u017A': 'z',
3216    '\u1E91': 'z',
3217    '\u017C': 'z',
3218    '\u017E': 'z',
3219    '\u1E93': 'z',
3220    '\u1E95': 'z',
3221    '\u01B6': 'z',
3222    '\u0225': 'z',
3223    '\u0240': 'z',
3224    '\u2C6C': 'z',
3225    '\uA763': 'z',
3226    '\u0386': '\u0391',
3227    '\u0388': '\u0395',
3228    '\u0389': '\u0397',
3229    '\u038A': '\u0399',
3230    '\u03AA': '\u0399',
3231    '\u038C': '\u039F',
3232    '\u038E': '\u03A5',
3233    '\u03AB': '\u03A5',
3234    '\u038F': '\u03A9',
3235    '\u03AC': '\u03B1',
3236    '\u03AD': '\u03B5',
3237    '\u03AE': '\u03B7',
3238    '\u03AF': '\u03B9',
3239    '\u03CA': '\u03B9',
3240    '\u0390': '\u03B9',
3241    '\u03CC': '\u03BF',
3242    '\u03CD': '\u03C5',
3243    '\u03CB': '\u03C5',
3244    '\u03B0': '\u03C5',
3245    '\u03CE': '\u03C9',
3246    '\u03C2': '\u03C3',
3247    '\u2019': '\''
3248  };
3249
3250  return diacritics;
3251});
3252
3253S2.define('select2/data/base',[
3254  '../utils'
3255], function (Utils) {
3256  function BaseAdapter ($element, options) {
3257    BaseAdapter.__super__.constructor.call(this);
3258  }
3259
3260  Utils.Extend(BaseAdapter, Utils.Observable);
3261
3262  BaseAdapter.prototype.current = function (callback) {
3263    throw new Error('The `current` method must be defined in child classes.');
3264  };
3265
3266  BaseAdapter.prototype.query = function (params, callback) {
3267    throw new Error('The `query` method must be defined in child classes.');
3268  };
3269
3270  BaseAdapter.prototype.bind = function (container, $container) {
3271    // Can be implemented in subclasses
3272  };
3273
3274  BaseAdapter.prototype.destroy = function () {
3275    // Can be implemented in subclasses
3276  };
3277
3278  BaseAdapter.prototype.generateResultId = function (container, data) {
3279    var id = container.id + '-result-';
3280
3281    id += Utils.generateChars(4);
3282
3283    if (data.id != null) {
3284      id += '-' + data.id.toString();
3285    } else {
3286      id += '-' + Utils.generateChars(4);
3287    }
3288    return id;
3289  };
3290
3291  return BaseAdapter;
3292});
3293
3294S2.define('select2/data/select',[
3295  './base',
3296  '../utils',
3297  'jquery'
3298], function (BaseAdapter, Utils, $) {
3299  function SelectAdapter ($element, options) {
3300    this.$element = $element;
3301    this.options = options;
3302
3303    SelectAdapter.__super__.constructor.call(this);
3304  }
3305
3306  Utils.Extend(SelectAdapter, BaseAdapter);
3307
3308  SelectAdapter.prototype.current = function (callback) {
3309    var self = this;
3310
3311    var data = Array.prototype.map.call(
3312      this.$element[0].querySelectorAll(':checked'),
3313      function (selectedElement) {
3314        return self.item($(selectedElement));
3315      }
3316    );
3317
3318    callback(data);
3319  };
3320
3321  SelectAdapter.prototype.select = function (data) {
3322    var self = this;
3323
3324    data.selected = true;
3325
3326    // If data.element is a DOM node, use it instead
3327    if (
3328      data.element != null && data.element.tagName.toLowerCase() === 'option'
3329    ) {
3330      data.element.selected = true;
3331
3332      this.$element.trigger('input').trigger('change');
3333
3334      return;
3335    }
3336
3337    if (this.$element.prop('multiple')) {
3338      this.current(function (currentData) {
3339        var val = [];
3340
3341        data = [data];
3342        data.push.apply(data, currentData);
3343
3344        for (var d = 0; d < data.length; d++) {
3345          var id = data[d].id;
3346
3347          if (val.indexOf(id) === -1) {
3348            val.push(id);
3349          }
3350        }
3351
3352        self.$element.val(val);
3353        self.$element.trigger('input').trigger('change');
3354      });
3355    } else {
3356      var val = data.id;
3357
3358      this.$element.val(val);
3359      this.$element.trigger('input').trigger('change');
3360    }
3361  };
3362
3363  SelectAdapter.prototype.unselect = function (data) {
3364    var self = this;
3365
3366    if (!this.$element.prop('multiple')) {
3367      return;
3368    }
3369
3370    data.selected = false;
3371
3372    if (
3373      data.element != null &&
3374      data.element.tagName.toLowerCase() === 'option'
3375    ) {
3376      data.element.selected = false;
3377
3378      this.$element.trigger('input').trigger('change');
3379
3380      return;
3381    }
3382
3383    this.current(function (currentData) {
3384      var val = [];
3385
3386      for (var d = 0; d < currentData.length; d++) {
3387        var id = currentData[d].id;
3388
3389        if (id !== data.id && val.indexOf(id) === -1) {
3390          val.push(id);
3391        }
3392      }
3393
3394      self.$element.val(val);
3395
3396      self.$element.trigger('input').trigger('change');
3397    });
3398  };
3399
3400  SelectAdapter.prototype.bind = function (container, $container) {
3401    var self = this;
3402
3403    this.container = container;
3404
3405    container.on('select', function (params) {
3406      self.select(params.data);
3407    });
3408
3409    container.on('unselect', function (params) {
3410      self.unselect(params.data);
3411    });
3412  };
3413
3414  SelectAdapter.prototype.destroy = function () {
3415    // Remove anything added to child elements
3416    this.$element.find('*').each(function () {
3417      // Remove any custom data set by Select2
3418      Utils.RemoveData(this);
3419    });
3420  };
3421
3422  SelectAdapter.prototype.query = function (params, callback) {
3423    var data = [];
3424    var self = this;
3425
3426    var $options = this.$element.children();
3427
3428    $options.each(function () {
3429      if (
3430        this.tagName.toLowerCase() !== 'option' &&
3431        this.tagName.toLowerCase() !== 'optgroup'
3432      ) {
3433        return;
3434      }
3435
3436      var $option = $(this);
3437
3438      var option = self.item($option);
3439
3440      var matches = self.matches(params, option);
3441
3442      if (matches !== null) {
3443        data.push(matches);
3444      }
3445    });
3446
3447    callback({
3448      results: data
3449    });
3450  };
3451
3452  SelectAdapter.prototype.addOptions = function ($options) {
3453    this.$element.append($options);
3454  };
3455
3456  SelectAdapter.prototype.option = function (data) {
3457    var option;
3458
3459    if (data.children) {
3460      option = document.createElement('optgroup');
3461      option.label = data.text;
3462    } else {
3463      option = document.createElement('option');
3464
3465      if (option.textContent !== undefined) {
3466        option.textContent = data.text;
3467      } else {
3468        option.innerText = data.text;
3469      }
3470    }
3471
3472    if (data.id !== undefined) {
3473      option.value = data.id;
3474    }
3475
3476    if (data.disabled) {
3477      option.disabled = true;
3478    }
3479
3480    if (data.selected) {
3481      option.selected = true;
3482    }
3483
3484    if (data.title) {
3485      option.title = data.title;
3486    }
3487
3488    var normalizedData = this._normalizeItem(data);
3489    normalizedData.element = option;
3490
3491    // Override the option's data with the combined data
3492    Utils.StoreData(option, 'data', normalizedData);
3493
3494    return $(option);
3495  };
3496
3497  SelectAdapter.prototype.item = function ($option) {
3498    var data = {};
3499
3500    data = Utils.GetData($option[0], 'data');
3501
3502    if (data != null) {
3503      return data;
3504    }
3505
3506    var option = $option[0];
3507
3508    if (option.tagName.toLowerCase() === 'option') {
3509      data = {
3510        id: $option.val(),
3511        text: $option.text(),
3512        disabled: $option.prop('disabled'),
3513        selected: $option.prop('selected'),
3514        title: $option.prop('title')
3515      };
3516    } else if (option.tagName.toLowerCase() === 'optgroup') {
3517      data = {
3518        text: $option.prop('label'),
3519        children: [],
3520        title: $option.prop('title')
3521      };
3522
3523      var $children = $option.children('option');
3524      var children = [];
3525
3526      for (var c = 0; c < $children.length; c++) {
3527        var $child = $($children[c]);
3528
3529        var child = this.item($child);
3530
3531        children.push(child);
3532      }
3533
3534      data.children = children;
3535    }
3536
3537    data = this._normalizeItem(data);
3538    data.element = $option[0];
3539
3540    Utils.StoreData($option[0], 'data', data);
3541
3542    return data;
3543  };
3544
3545  SelectAdapter.prototype._normalizeItem = function (item) {
3546    if (item !== Object(item)) {
3547      item = {
3548        id: item,
3549        text: item
3550      };
3551    }
3552
3553    item = $.extend({}, {
3554      text: ''
3555    }, item);
3556
3557    var defaults = {
3558      selected: false,
3559      disabled: false
3560    };
3561
3562    if (item.id != null) {
3563      item.id = item.id.toString();
3564    }
3565
3566    if (item.text != null) {
3567      item.text = item.text.toString();
3568    }
3569
3570    if (item._resultId == null && item.id && this.container != null) {
3571      item._resultId = this.generateResultId(this.container, item);
3572    }
3573
3574    return $.extend({}, defaults, item);
3575  };
3576
3577  SelectAdapter.prototype.matches = function (params, data) {
3578    var matcher = this.options.get('matcher');
3579
3580    return matcher(params, data);
3581  };
3582
3583  return SelectAdapter;
3584});
3585
3586S2.define('select2/data/array',[
3587  './select',
3588  '../utils',
3589  'jquery'
3590], function (SelectAdapter, Utils, $) {
3591  function ArrayAdapter ($element, options) {
3592    this._dataToConvert = options.get('data') || [];
3593
3594    ArrayAdapter.__super__.constructor.call(this, $element, options);
3595  }
3596
3597  Utils.Extend(ArrayAdapter, SelectAdapter);
3598
3599  ArrayAdapter.prototype.bind = function (container, $container) {
3600    ArrayAdapter.__super__.bind.call(this, container, $container);
3601
3602    this.addOptions(this.convertToOptions(this._dataToConvert));
3603  };
3604
3605  ArrayAdapter.prototype.select = function (data) {
3606    var $option = this.$element.find('option').filter(function (i, elm) {
3607      return elm.value == data.id.toString();
3608    });
3609
3610    if ($option.length === 0) {
3611      $option = this.option(data);
3612
3613      this.addOptions($option);
3614    }
3615
3616    ArrayAdapter.__super__.select.call(this, data);
3617  };
3618
3619  ArrayAdapter.prototype.convertToOptions = function (data) {
3620    var self = this;
3621
3622    var $existing = this.$element.find('option');
3623    var existingIds = $existing.map(function () {
3624      return self.item($(this)).id;
3625    }).get();
3626
3627    var $options = [];
3628
3629    // Filter out all items except for the one passed in the argument
3630    function onlyItem (item) {
3631      return function () {
3632        return $(this).val() == item.id;
3633      };
3634    }
3635
3636    for (var d = 0; d < data.length; d++) {
3637      var item = this._normalizeItem(data[d]);
3638
3639      // Skip items which were pre-loaded, only merge the data
3640      if (existingIds.indexOf(item.id) >= 0) {
3641        var $existingOption = $existing.filter(onlyItem(item));
3642
3643        var existingData = this.item($existingOption);
3644        var newData = $.extend(true, {}, item, existingData);
3645
3646        var $newOption = this.option(newData);
3647
3648        $existingOption.replaceWith($newOption);
3649
3650        continue;
3651      }
3652
3653      var $option = this.option(item);
3654
3655      if (item.children) {
3656        var $children = this.convertToOptions(item.children);
3657
3658        $option.append($children);
3659      }
3660
3661      $options.push($option);
3662    }
3663
3664    return $options;
3665  };
3666
3667  return ArrayAdapter;
3668});
3669
3670S2.define('select2/data/ajax',[
3671  './array',
3672  '../utils',
3673  'jquery'
3674], function (ArrayAdapter, Utils, $) {
3675  function AjaxAdapter ($element, options) {
3676    this.ajaxOptions = this._applyDefaults(options.get('ajax'));
3677
3678    if (this.ajaxOptions.processResults != null) {
3679      this.processResults = this.ajaxOptions.processResults;
3680    }
3681
3682    AjaxAdapter.__super__.constructor.call(this, $element, options);
3683  }
3684
3685  Utils.Extend(AjaxAdapter, ArrayAdapter);
3686
3687  AjaxAdapter.prototype._applyDefaults = function (options) {
3688    var defaults = {
3689      data: function (params) {
3690        return $.extend({}, params, {
3691          q: params.term
3692        });
3693      },
3694      transport: function (params, success, failure) {
3695        var $request = $.ajax(params);
3696
3697        $request.then(success);
3698        $request.fail(failure);
3699
3700        return $request;
3701      }
3702    };
3703
3704    return $.extend({}, defaults, options, true);
3705  };
3706
3707  AjaxAdapter.prototype.processResults = function (results) {
3708    return results;
3709  };
3710
3711  AjaxAdapter.prototype.query = function (params, callback) {
3712    var matches = [];
3713    var self = this;
3714
3715    if (this._request != null) {
3716      // JSONP requests cannot always be aborted
3717      if (typeof this._request.abort === 'function') {
3718        this._request.abort();
3719      }
3720
3721      this._request = null;
3722    }
3723
3724    var options = $.extend({
3725      type: 'GET'
3726    }, this.ajaxOptions);
3727
3728    if (typeof options.url === 'function') {
3729      options.url = options.url.call(this.$element, params);
3730    }
3731
3732    if (typeof options.data === 'function') {
3733      options.data = options.data.call(this.$element, params);
3734    }
3735
3736    function request () {
3737      var $request = options.transport(options, function (data) {
3738        var results = self.processResults(data, params);
3739
3740        if (self.options.get('debug') && window.console && console.error) {
3741          // Check to make sure that the response included a `results` key.
3742          if (!results || !results.results || !Array.isArray(results.results)) {
3743            console.error(
3744              'Select2: The AJAX results did not return an array in the ' +
3745              '`results` key of the response.'
3746            );
3747          }
3748        }
3749
3750        callback(results);
3751      }, function () {
3752        // Attempt to detect if a request was aborted
3753        // Only works if the transport exposes a status property
3754        if ('status' in $request &&
3755            ($request.status === 0 || $request.status === '0')) {
3756          return;
3757        }
3758
3759        self.trigger('results:message', {
3760          message: 'errorLoading'
3761        });
3762      });
3763
3764      self._request = $request;
3765    }
3766
3767    if (this.ajaxOptions.delay && params.term != null) {
3768      if (this._queryTimeout) {
3769        window.clearTimeout(this._queryTimeout);
3770      }
3771
3772      this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);
3773    } else {
3774      request();
3775    }
3776  };
3777
3778  return AjaxAdapter;
3779});
3780
3781S2.define('select2/data/tags',[
3782  'jquery'
3783], function ($) {
3784  function Tags (decorated, $element, options) {
3785    var tags = options.get('tags');
3786
3787    var createTag = options.get('createTag');
3788
3789    if (createTag !== undefined) {
3790      this.createTag = createTag;
3791    }
3792
3793    var insertTag = options.get('insertTag');
3794
3795    if (insertTag !== undefined) {
3796        this.insertTag = insertTag;
3797    }
3798
3799    decorated.call(this, $element, options);
3800
3801    if (Array.isArray(tags)) {
3802      for (var t = 0; t < tags.length; t++) {
3803        var tag = tags[t];
3804        var item = this._normalizeItem(tag);
3805
3806        var $option = this.option(item);
3807
3808        this.$element.append($option);
3809      }
3810    }
3811  }
3812
3813  Tags.prototype.query = function (decorated, params, callback) {
3814    var self = this;
3815
3816    this._removeOldTags();
3817
3818    if (params.term == null || params.page != null) {
3819      decorated.call(this, params, callback);
3820      return;
3821    }
3822
3823    function wrapper (obj, child) {
3824      var data = obj.results;
3825
3826      for (var i = 0; i < data.length; i++) {
3827        var option = data[i];
3828
3829        var checkChildren = (
3830          option.children != null &&
3831          !wrapper({
3832            results: option.children
3833          }, true)
3834        );
3835
3836        var optionText = (option.text || '').toUpperCase();
3837        var paramsTerm = (params.term || '').toUpperCase();
3838
3839        var checkText = optionText === paramsTerm;
3840
3841        if (checkText || checkChildren) {
3842          if (child) {
3843            return false;
3844          }
3845
3846          obj.data = data;
3847          callback(obj);
3848
3849          return;
3850        }
3851      }
3852
3853      if (child) {
3854        return true;
3855      }
3856
3857      var tag = self.createTag(params);
3858
3859      if (tag != null) {
3860        var $option = self.option(tag);
3861        $option.attr('data-select2-tag', 'true');
3862
3863        self.addOptions([$option]);
3864
3865        self.insertTag(data, tag);
3866      }
3867
3868      obj.results = data;
3869
3870      callback(obj);
3871    }
3872
3873    decorated.call(this, params, wrapper);
3874  };
3875
3876  Tags.prototype.createTag = function (decorated, params) {
3877    if (params.term == null) {
3878      return null;
3879    }
3880
3881    var term = params.term.trim();
3882
3883    if (term === '') {
3884      return null;
3885    }
3886
3887    return {
3888      id: term,
3889      text: term
3890    };
3891  };
3892
3893  Tags.prototype.insertTag = function (_, data, tag) {
3894    data.unshift(tag);
3895  };
3896
3897  Tags.prototype._removeOldTags = function (_) {
3898    var $options = this.$element.find('option[data-select2-tag]');
3899
3900    $options.each(function () {
3901      if (this.selected) {
3902        return;
3903      }
3904
3905      $(this).remove();
3906    });
3907  };
3908
3909  return Tags;
3910});
3911
3912S2.define('select2/data/tokenizer',[
3913  'jquery'
3914], function ($) {
3915  function Tokenizer (decorated, $element, options) {
3916    var tokenizer = options.get('tokenizer');
3917
3918    if (tokenizer !== undefined) {
3919      this.tokenizer = tokenizer;
3920    }
3921
3922    decorated.call(this, $element, options);
3923  }
3924
3925  Tokenizer.prototype.bind = function (decorated, container, $container) {
3926    decorated.call(this, container, $container);
3927
3928    this.$search =  container.dropdown.$search || container.selection.$search ||
3929      $container.find('.select2-search__field');
3930  };
3931
3932  Tokenizer.prototype.query = function (decorated, params, callback) {
3933    var self = this;
3934
3935    function createAndSelect (data) {
3936      // Normalize the data object so we can use it for checks
3937      var item = self._normalizeItem(data);
3938
3939      // Check if the data object already exists as a tag
3940      // Select it if it doesn't
3941      var $existingOptions = self.$element.find('option').filter(function () {
3942        return $(this).val() === item.id;
3943      });
3944
3945      // If an existing option wasn't found for it, create the option
3946      if (!$existingOptions.length) {
3947        var $option = self.option(item);
3948        $option.attr('data-select2-tag', true);
3949
3950        self._removeOldTags();
3951        self.addOptions([$option]);
3952      }
3953
3954      // Select the item, now that we know there is an option for it
3955      select(item);
3956    }
3957
3958    function select (data) {
3959      self.trigger('select', {
3960        data: data
3961      });
3962    }
3963
3964    params.term = params.term || '';
3965
3966    var tokenData = this.tokenizer(params, this.options, createAndSelect);
3967
3968    if (tokenData.term !== params.term) {
3969      // Replace the search term if we have the search box
3970      if (this.$search.length) {
3971        this.$search.val(tokenData.term);
3972        this.$search.trigger('focus');
3973      }
3974
3975      params.term = tokenData.term;
3976    }
3977
3978    decorated.call(this, params, callback);
3979  };
3980
3981  Tokenizer.prototype.tokenizer = function (_, params, options, callback) {
3982    var separators = options.get('tokenSeparators') || [];
3983    var term = params.term;
3984    var i = 0;
3985
3986    var createTag = this.createTag || function (params) {
3987      return {
3988        id: params.term,
3989        text: params.term
3990      };
3991    };
3992
3993    while (i < term.length) {
3994      var termChar = term[i];
3995
3996      if (separators.indexOf(termChar) === -1) {
3997        i++;
3998
3999        continue;
4000      }
4001
4002      var part = term.substr(0, i);
4003      var partParams = $.extend({}, params, {
4004        term: part
4005      });
4006
4007      var data = createTag(partParams);
4008
4009      if (data == null) {
4010        i++;
4011        continue;
4012      }
4013
4014      callback(data);
4015
4016      // Reset the term to not include the tokenized portion
4017      term = term.substr(i + 1) || '';
4018      i = 0;
4019    }
4020
4021    return {
4022      term: term
4023    };
4024  };
4025
4026  return Tokenizer;
4027});
4028
4029S2.define('select2/data/minimumInputLength',[
4030
4031], function () {
4032  function MinimumInputLength (decorated, $e, options) {
4033    this.minimumInputLength = options.get('minimumInputLength');
4034
4035    decorated.call(this, $e, options);
4036  }
4037
4038  MinimumInputLength.prototype.query = function (decorated, params, callback) {
4039    params.term = params.term || '';
4040
4041    if (params.term.length < this.minimumInputLength) {
4042      this.trigger('results:message', {
4043        message: 'inputTooShort',
4044        args: {
4045          minimum: this.minimumInputLength,
4046          input: params.term,
4047          params: params
4048        }
4049      });
4050
4051      return;
4052    }
4053
4054    decorated.call(this, params, callback);
4055  };
4056
4057  return MinimumInputLength;
4058});
4059
4060S2.define('select2/data/maximumInputLength',[
4061
4062], function () {
4063  function MaximumInputLength (decorated, $e, options) {
4064    this.maximumInputLength = options.get('maximumInputLength');
4065
4066    decorated.call(this, $e, options);
4067  }
4068
4069  MaximumInputLength.prototype.query = function (decorated, params, callback) {
4070    params.term = params.term || '';
4071
4072    if (this.maximumInputLength > 0 &&
4073        params.term.length > this.maximumInputLength) {
4074      this.trigger('results:message', {
4075        message: 'inputTooLong',
4076        args: {
4077          maximum: this.maximumInputLength,
4078          input: params.term,
4079          params: params
4080        }
4081      });
4082
4083      return;
4084    }
4085
4086    decorated.call(this, params, callback);
4087  };
4088
4089  return MaximumInputLength;
4090});
4091
4092S2.define('select2/data/maximumSelectionLength',[
4093
4094], function (){
4095  function MaximumSelectionLength (decorated, $e, options) {
4096    this.maximumSelectionLength = options.get('maximumSelectionLength');
4097
4098    decorated.call(this, $e, options);
4099  }
4100
4101  MaximumSelectionLength.prototype.bind =
4102    function (decorated, container, $container) {
4103      var self = this;
4104
4105      decorated.call(this, container, $container);
4106
4107      container.on('select', function () {
4108        self._checkIfMaximumSelected();
4109      });
4110  };
4111
4112  MaximumSelectionLength.prototype.query =
4113    function (decorated, params, callback) {
4114      var self = this;
4115
4116      this._checkIfMaximumSelected(function () {
4117        decorated.call(self, params, callback);
4118      });
4119  };
4120
4121  MaximumSelectionLength.prototype._checkIfMaximumSelected =
4122    function (_, successCallback) {
4123      var self = this;
4124
4125      this.current(function (currentData) {
4126        var count = currentData != null ? currentData.length : 0;
4127        if (self.maximumSelectionLength > 0 &&
4128          count >= self.maximumSelectionLength) {
4129          self.trigger('results:message', {
4130            message: 'maximumSelected',
4131            args: {
4132              maximum: self.maximumSelectionLength
4133            }
4134          });
4135          return;
4136        }
4137
4138        if (successCallback) {
4139          successCallback();
4140        }
4141      });
4142  };
4143
4144  return MaximumSelectionLength;
4145});
4146
4147S2.define('select2/dropdown',[
4148  'jquery',
4149  './utils'
4150], function ($, Utils) {
4151  function Dropdown ($element, options) {
4152    this.$element = $element;
4153    this.options = options;
4154
4155    Dropdown.__super__.constructor.call(this);
4156  }
4157
4158  Utils.Extend(Dropdown, Utils.Observable);
4159
4160  Dropdown.prototype.render = function () {
4161    var $dropdown = $(
4162      '<span class="select2-dropdown">' +
4163        '<span class="select2-results"></span>' +
4164      '</span>'
4165    );
4166
4167    $dropdown.attr('dir', this.options.get('dir'));
4168
4169    this.$dropdown = $dropdown;
4170
4171    return $dropdown;
4172  };
4173
4174  Dropdown.prototype.bind = function () {
4175    // Should be implemented in subclasses
4176  };
4177
4178  Dropdown.prototype.position = function ($dropdown, $container) {
4179    // Should be implemented in subclasses
4180  };
4181
4182  Dropdown.prototype.destroy = function () {
4183    // Remove the dropdown from the DOM
4184    this.$dropdown.remove();
4185  };
4186
4187  return Dropdown;
4188});
4189
4190S2.define('select2/dropdown/search',[
4191  'jquery'
4192], function ($) {
4193  function Search () { }
4194
4195  Search.prototype.render = function (decorated) {
4196    var $rendered = decorated.call(this);
4197    var searchLabel = this.options.get('translations').get('search');
4198
4199    var $search = $(
4200      '<span class="select2-search select2-search--dropdown">' +
4201        '<input class="select2-search__field" type="search" tabindex="-1"' +
4202        ' autocorrect="off" autocapitalize="none"' +
4203        ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
4204      '</span>'
4205    );
4206
4207    this.$searchContainer = $search;
4208    this.$search = $search.find('input');
4209
4210    this.$search.prop('autocomplete', this.options.get('autocomplete'));
4211    this.$search.attr('aria-label', searchLabel());
4212
4213    $rendered.prepend($search);
4214
4215    return $rendered;
4216  };
4217
4218  Search.prototype.bind = function (decorated, container, $container) {
4219    var self = this;
4220
4221    var resultsId = container.id + '-results';
4222
4223    decorated.call(this, container, $container);
4224
4225    this.$search.on('keydown', function (evt) {
4226      self.trigger('keypress', evt);
4227
4228      self._keyUpPrevented = evt.isDefaultPrevented();
4229    });
4230
4231    // Workaround for browsers which do not support the `input` event
4232    // This will prevent double-triggering of events for browsers which support
4233    // both the `keyup` and `input` events.
4234    this.$search.on('input', function (evt) {
4235      // Unbind the duplicated `keyup` event
4236      $(this).off('keyup');
4237    });
4238
4239    this.$search.on('keyup input', function (evt) {
4240      self.handleSearch(evt);
4241    });
4242
4243    container.on('open', function () {
4244      self.$search.attr('tabindex', 0);
4245      self.$search.attr('aria-controls', resultsId);
4246
4247      self.$search.trigger('focus');
4248
4249      window.setTimeout(function () {
4250        self.$search.trigger('focus');
4251      }, 0);
4252    });
4253
4254    container.on('close', function () {
4255      self.$search.attr('tabindex', -1);
4256      self.$search.removeAttr('aria-controls');
4257      self.$search.removeAttr('aria-activedescendant');
4258
4259      self.$search.val('');
4260      self.$search.trigger('blur');
4261    });
4262
4263    container.on('focus', function () {
4264      if (!container.isOpen()) {
4265        self.$search.trigger('focus');
4266      }
4267    });
4268
4269    container.on('results:all', function (params) {
4270      if (params.query.term == null || params.query.term === '') {
4271        var showSearch = self.showSearch(params);
4272
4273        if (showSearch) {
4274          self.$searchContainer[0].classList.remove('select2-search--hide');
4275        } else {
4276          self.$searchContainer[0].classList.add('select2-search--hide');
4277        }
4278      }
4279    });
4280
4281    container.on('results:focus', function (params) {
4282      if (params.data._resultId) {
4283        self.$search.attr('aria-activedescendant', params.data._resultId);
4284      } else {
4285        self.$search.removeAttr('aria-activedescendant');
4286      }
4287    });
4288  };
4289
4290  Search.prototype.handleSearch = function (evt) {
4291    if (!this._keyUpPrevented) {
4292      var input = this.$search.val();
4293
4294      this.trigger('query', {
4295        term: input
4296      });
4297    }
4298
4299    this._keyUpPrevented = false;
4300  };
4301
4302  Search.prototype.showSearch = function (_, params) {
4303    return true;
4304  };
4305
4306  return Search;
4307});
4308
4309S2.define('select2/dropdown/hidePlaceholder',[
4310
4311], function () {
4312  function HidePlaceholder (decorated, $element, options, dataAdapter) {
4313    this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
4314
4315    decorated.call(this, $element, options, dataAdapter);
4316  }
4317
4318  HidePlaceholder.prototype.append = function (decorated, data) {
4319    data.results = this.removePlaceholder(data.results);
4320
4321    decorated.call(this, data);
4322  };
4323
4324  HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {
4325    if (typeof placeholder === 'string') {
4326      placeholder = {
4327        id: '',
4328        text: placeholder
4329      };
4330    }
4331
4332    return placeholder;
4333  };
4334
4335  HidePlaceholder.prototype.removePlaceholder = function (_, data) {
4336    var modifiedData = data.slice(0);
4337
4338    for (var d = data.length - 1; d >= 0; d--) {
4339      var item = data[d];
4340
4341      if (this.placeholder.id === item.id) {
4342        modifiedData.splice(d, 1);
4343      }
4344    }
4345
4346    return modifiedData;
4347  };
4348
4349  return HidePlaceholder;
4350});
4351
4352S2.define('select2/dropdown/infiniteScroll',[
4353  'jquery'
4354], function ($) {
4355  function InfiniteScroll (decorated, $element, options, dataAdapter) {
4356    this.lastParams = {};
4357
4358    decorated.call(this, $element, options, dataAdapter);
4359
4360    this.$loadingMore = this.createLoadingMore();
4361    this.loading = false;
4362  }
4363
4364  InfiniteScroll.prototype.append = function (decorated, data) {
4365    this.$loadingMore.remove();
4366    this.loading = false;
4367
4368    decorated.call(this, data);
4369
4370    if (this.showLoadingMore(data)) {
4371      this.$results.append(this.$loadingMore);
4372      this.loadMoreIfNeeded();
4373    }
4374  };
4375
4376  InfiniteScroll.prototype.bind = function (decorated, container, $container) {
4377    var self = this;
4378
4379    decorated.call(this, container, $container);
4380
4381    container.on('query', function (params) {
4382      self.lastParams = params;
4383      self.loading = true;
4384    });
4385
4386    container.on('query:append', function (params) {
4387      self.lastParams = params;
4388      self.loading = true;
4389    });
4390
4391    this.$results.on('scroll', this.loadMoreIfNeeded.bind(this));
4392  };
4393
4394  InfiniteScroll.prototype.loadMoreIfNeeded = function () {
4395    var isLoadMoreVisible = $.contains(
4396      document.documentElement,
4397      this.$loadingMore[0]
4398    );
4399
4400    if (this.loading || !isLoadMoreVisible) {
4401      return;
4402    }
4403
4404    var currentOffset = this.$results.offset().top +
4405      this.$results.outerHeight(false);
4406    var loadingMoreOffset = this.$loadingMore.offset().top +
4407      this.$loadingMore.outerHeight(false);
4408
4409    if (currentOffset + 50 >= loadingMoreOffset) {
4410      this.loadMore();
4411    }
4412  };
4413
4414  InfiniteScroll.prototype.loadMore = function () {
4415    this.loading = true;
4416
4417    var params = $.extend({}, {page: 1}, this.lastParams);
4418
4419    params.page++;
4420
4421    this.trigger('query:append', params);
4422  };
4423
4424  InfiniteScroll.prototype.showLoadingMore = function (_, data) {
4425    return data.pagination && data.pagination.more;
4426  };
4427
4428  InfiniteScroll.prototype.createLoadingMore = function () {
4429    var $option = $(
4430      '<li ' +
4431      'class="select2-results__option select2-results__option--load-more"' +
4432      'role="option" aria-disabled="true"></li>'
4433    );
4434
4435    var message = this.options.get('translations').get('loadingMore');
4436
4437    $option.html(message(this.lastParams));
4438
4439    return $option;
4440  };
4441
4442  return InfiniteScroll;
4443});
4444
4445S2.define('select2/dropdown/attachBody',[
4446  'jquery',
4447  '../utils'
4448], function ($, Utils) {
4449  function AttachBody (decorated, $element, options) {
4450    this.$dropdownParent = $(options.get('dropdownParent') || document.body);
4451
4452    decorated.call(this, $element, options);
4453  }
4454
4455  AttachBody.prototype.bind = function (decorated, container, $container) {
4456    var self = this;
4457
4458    decorated.call(this, container, $container);
4459
4460    container.on('open', function () {
4461      self._showDropdown();
4462      self._attachPositioningHandler(container);
4463
4464      // Must bind after the results handlers to ensure correct sizing
4465      self._bindContainerResultHandlers(container);
4466    });
4467
4468    container.on('close', function () {
4469      self._hideDropdown();
4470      self._detachPositioningHandler(container);
4471    });
4472
4473    this.$dropdownContainer.on('mousedown', function (evt) {
4474      evt.stopPropagation();
4475    });
4476  };
4477
4478  AttachBody.prototype.destroy = function (decorated) {
4479    decorated.call(this);
4480
4481    this.$dropdownContainer.remove();
4482  };
4483
4484  AttachBody.prototype.position = function (decorated, $dropdown, $container) {
4485    // Clone all of the container classes
4486    $dropdown.attr('class', $container.attr('class'));
4487
4488    $dropdown[0].classList.remove('select2');
4489    $dropdown[0].classList.add('select2-container--open');
4490
4491    $dropdown.css({
4492      position: 'absolute',
4493      top: -999999
4494    });
4495
4496    this.$container = $container;
4497  };
4498
4499  AttachBody.prototype.render = function (decorated) {
4500    var $container = $('<span></span>');
4501
4502    var $dropdown = decorated.call(this);
4503    $container.append($dropdown);
4504
4505    this.$dropdownContainer = $container;
4506
4507    return $container;
4508  };
4509
4510  AttachBody.prototype._hideDropdown = function (decorated) {
4511    this.$dropdownContainer.detach();
4512  };
4513
4514  AttachBody.prototype._bindContainerResultHandlers =
4515      function (decorated, container) {
4516
4517    // These should only be bound once
4518    if (this._containerResultsHandlersBound) {
4519      return;
4520    }
4521
4522    var self = this;
4523
4524    container.on('results:all', function () {
4525      self._positionDropdown();
4526      self._resizeDropdown();
4527    });
4528
4529    container.on('results:append', function () {
4530      self._positionDropdown();
4531      self._resizeDropdown();
4532    });
4533
4534    container.on('results:message', function () {
4535      self._positionDropdown();
4536      self._resizeDropdown();
4537    });
4538
4539    container.on('select', function () {
4540      self._positionDropdown();
4541      self._resizeDropdown();
4542    });
4543
4544    container.on('unselect', function () {
4545      self._positionDropdown();
4546      self._resizeDropdown();
4547    });
4548
4549    this._containerResultsHandlersBound = true;
4550  };
4551
4552  AttachBody.prototype._attachPositioningHandler =
4553      function (decorated, container) {
4554    var self = this;
4555
4556    var scrollEvent = 'scroll.select2.' + container.id;
4557    var resizeEvent = 'resize.select2.' + container.id;
4558    var orientationEvent = 'orientationchange.select2.' + container.id;
4559
4560    var $watchers = this.$container.parents().filter(Utils.hasScroll);
4561    $watchers.each(function () {
4562      Utils.StoreData(this, 'select2-scroll-position', {
4563        x: $(this).scrollLeft(),
4564        y: $(this).scrollTop()
4565      });
4566    });
4567
4568    $watchers.on(scrollEvent, function (ev) {
4569      var position = Utils.GetData(this, 'select2-scroll-position');
4570      $(this).scrollTop(position.y);
4571    });
4572
4573    $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,
4574      function (e) {
4575      self._positionDropdown();
4576      self._resizeDropdown();
4577    });
4578  };
4579
4580  AttachBody.prototype._detachPositioningHandler =
4581      function (decorated, container) {
4582    var scrollEvent = 'scroll.select2.' + container.id;
4583    var resizeEvent = 'resize.select2.' + container.id;
4584    var orientationEvent = 'orientationchange.select2.' + container.id;
4585
4586    var $watchers = this.$container.parents().filter(Utils.hasScroll);
4587    $watchers.off(scrollEvent);
4588
4589    $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);
4590  };
4591
4592  AttachBody.prototype._positionDropdown = function () {
4593    var $window = $(window);
4594
4595    var isCurrentlyAbove = this.$dropdown[0].classList
4596      .contains('select2-dropdown--above');
4597    var isCurrentlyBelow = this.$dropdown[0].classList
4598      .contains('select2-dropdown--below');
4599
4600    var newDirection = null;
4601
4602    var offset = this.$container.offset();
4603
4604    offset.bottom = offset.top + this.$container.outerHeight(false);
4605
4606    var container = {
4607      height: this.$container.outerHeight(false)
4608    };
4609
4610    container.top = offset.top;
4611    container.bottom = offset.top + container.height;
4612
4613    var dropdown = {
4614      height: this.$dropdown.outerHeight(false)
4615    };
4616
4617    var viewport = {
4618      top: $window.scrollTop(),
4619      bottom: $window.scrollTop() + $window.height()
4620    };
4621
4622    var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
4623    var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
4624
4625    var css = {
4626      left: offset.left,
4627      top: container.bottom
4628    };
4629
4630    // Determine what the parent element is to use for calculating the offset
4631    var $offsetParent = this.$dropdownParent;
4632
4633    // For statically positioned elements, we need to get the element
4634    // that is determining the offset
4635    if ($offsetParent.css('position') === 'static') {
4636      $offsetParent = $offsetParent.offsetParent();
4637    }
4638
4639    var parentOffset = {
4640      top: 0,
4641      left: 0
4642    };
4643
4644    if (
4645      $.contains(document.body, $offsetParent[0]) ||
4646      $offsetParent[0].isConnected
4647      ) {
4648      parentOffset = $offsetParent.offset();
4649    }
4650
4651    css.top -= parentOffset.top;
4652    css.left -= parentOffset.left;
4653
4654    if (!isCurrentlyAbove && !isCurrentlyBelow) {
4655      newDirection = 'below';
4656    }
4657
4658    if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
4659      newDirection = 'above';
4660    } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
4661      newDirection = 'below';
4662    }
4663
4664    if (newDirection == 'above' ||
4665      (isCurrentlyAbove && newDirection !== 'below')) {
4666      css.top = container.top - parentOffset.top - dropdown.height;
4667    }
4668
4669    if (newDirection != null) {
4670      this.$dropdown[0].classList.remove('select2-dropdown--below');
4671      this.$dropdown[0].classList.remove('select2-dropdown--above');
4672      this.$dropdown[0].classList.add('select2-dropdown--' + newDirection);
4673
4674      this.$container[0].classList.remove('select2-container--below');
4675      this.$container[0].classList.remove('select2-container--above');
4676      this.$container[0].classList.add('select2-container--' + newDirection);
4677    }
4678
4679    this.$dropdownContainer.css(css);
4680  };
4681
4682  AttachBody.prototype._resizeDropdown = function () {
4683    var css = {
4684      width: this.$container.outerWidth(false) + 'px'
4685    };
4686
4687    if (this.options.get('dropdownAutoWidth')) {
4688      css.minWidth = css.width;
4689      css.position = 'relative';
4690      css.width = 'auto';
4691    }
4692
4693    this.$dropdown.css(css);
4694  };
4695
4696  AttachBody.prototype._showDropdown = function (decorated) {
4697    this.$dropdownContainer.appendTo(this.$dropdownParent);
4698
4699    this._positionDropdown();
4700    this._resizeDropdown();
4701  };
4702
4703  return AttachBody;
4704});
4705
4706S2.define('select2/dropdown/minimumResultsForSearch',[
4707
4708], function () {
4709  function countResults (data) {
4710    var count = 0;
4711
4712    for (var d = 0; d < data.length; d++) {
4713      var item = data[d];
4714
4715      if (item.children) {
4716        count += countResults(item.children);
4717      } else {
4718        count++;
4719      }
4720    }
4721
4722    return count;
4723  }
4724
4725  function MinimumResultsForSearch (decorated, $element, options, dataAdapter) {
4726    this.minimumResultsForSearch = options.get('minimumResultsForSearch');
4727
4728    if (this.minimumResultsForSearch < 0) {
4729      this.minimumResultsForSearch = Infinity;
4730    }
4731
4732    decorated.call(this, $element, options, dataAdapter);
4733  }
4734
4735  MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {
4736    if (countResults(params.data.results) < this.minimumResultsForSearch) {
4737      return false;
4738    }
4739
4740    return decorated.call(this, params);
4741  };
4742
4743  return MinimumResultsForSearch;
4744});
4745
4746S2.define('select2/dropdown/selectOnClose',[
4747  '../utils'
4748], function (Utils) {
4749  function SelectOnClose () { }
4750
4751  SelectOnClose.prototype.bind = function (decorated, container, $container) {
4752    var self = this;
4753
4754    decorated.call(this, container, $container);
4755
4756    container.on('close', function (params) {
4757      self._handleSelectOnClose(params);
4758    });
4759  };
4760
4761  SelectOnClose.prototype._handleSelectOnClose = function (_, params) {
4762    if (params && params.originalSelect2Event != null) {
4763      var event = params.originalSelect2Event;
4764
4765      // Don't select an item if the close event was triggered from a select or
4766      // unselect event
4767      if (event._type === 'select' || event._type === 'unselect') {
4768        return;
4769      }
4770    }
4771
4772    var $highlightedResults = this.getHighlightedResults();
4773
4774    // Only select highlighted results
4775    if ($highlightedResults.length < 1) {
4776      return;
4777    }
4778
4779    var data = Utils.GetData($highlightedResults[0], 'data');
4780
4781    // Don't re-select already selected resulte
4782    if (
4783      (data.element != null && data.element.selected) ||
4784      (data.element == null && data.selected)
4785    ) {
4786      return;
4787    }
4788
4789    this.trigger('select', {
4790        data: data
4791    });
4792  };
4793
4794  return SelectOnClose;
4795});
4796
4797S2.define('select2/dropdown/closeOnSelect',[
4798
4799], function () {
4800  function CloseOnSelect () { }
4801
4802  CloseOnSelect.prototype.bind = function (decorated, container, $container) {
4803    var self = this;
4804
4805    decorated.call(this, container, $container);
4806
4807    container.on('select', function (evt) {
4808      self._selectTriggered(evt);
4809    });
4810
4811    container.on('unselect', function (evt) {
4812      self._selectTriggered(evt);
4813    });
4814  };
4815
4816  CloseOnSelect.prototype._selectTriggered = function (_, evt) {
4817    var originalEvent = evt.originalEvent;
4818
4819    // Don't close if the control key is being held
4820    if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) {
4821      return;
4822    }
4823
4824    this.trigger('close', {
4825      originalEvent: originalEvent,
4826      originalSelect2Event: evt
4827    });
4828  };
4829
4830  return CloseOnSelect;
4831});
4832
4833S2.define('select2/dropdown/dropdownCss',[
4834  '../utils'
4835], function (Utils) {
4836  function DropdownCSS () { }
4837
4838  DropdownCSS.prototype.render = function (decorated) {
4839    var $dropdown = decorated.call(this);
4840
4841    var dropdownCssClass = this.options.get('dropdownCssClass') || '';
4842
4843    if (dropdownCssClass.indexOf(':all:') !== -1) {
4844      dropdownCssClass = dropdownCssClass.replace(':all:', '');
4845
4846      Utils.copyNonInternalCssClasses($dropdown[0], this.$element[0]);
4847    }
4848
4849    $dropdown.addClass(dropdownCssClass);
4850
4851    return $dropdown;
4852  };
4853
4854  return DropdownCSS;
4855});
4856
4857S2.define('select2/dropdown/tagsSearchHighlight',[
4858  '../utils'
4859], function (Utils) {
4860  function TagsSearchHighlight () { }
4861
4862  TagsSearchHighlight.prototype.highlightFirstItem = function (decorated) {
4863    var $options = this.$results
4864    .find(
4865      '.select2-results__option--selectable' +
4866      ':not(.select2-results__option--selected)'
4867    );
4868
4869    if ($options.length > 0) {
4870      var $firstOption = $options.first();
4871      var data = Utils.GetData($firstOption[0], 'data');
4872      var firstElement = data.element;
4873
4874      if (firstElement && firstElement.getAttribute) {
4875        if (firstElement.getAttribute('data-select2-tag') === 'true') {
4876          $firstOption.trigger('mouseenter');
4877
4878          return;
4879        }
4880      }
4881    }
4882
4883    decorated.call(this);
4884  };
4885
4886  return TagsSearchHighlight;
4887});
4888
4889S2.define('select2/i18n/en',[],function () {
4890  // English
4891  return {
4892    errorLoading: function () {
4893      return 'The results could not be loaded.';
4894    },
4895    inputTooLong: function (args) {
4896      var overChars = args.input.length - args.maximum;
4897
4898      var message = 'Please delete ' + overChars + ' character';
4899
4900      if (overChars != 1) {
4901        message += 's';
4902      }
4903
4904      return message;
4905    },
4906    inputTooShort: function (args) {
4907      var remainingChars = args.minimum - args.input.length;
4908
4909      var message = 'Please enter ' + remainingChars + ' or more characters';
4910
4911      return message;
4912    },
4913    loadingMore: function () {
4914      return 'Loading more results…';
4915    },
4916    maximumSelected: function (args) {
4917      var message = 'You can only select ' + args.maximum + ' item';
4918
4919      if (args.maximum != 1) {
4920        message += 's';
4921      }
4922
4923      return message;
4924    },
4925    noResults: function () {
4926      return 'No results found';
4927    },
4928    searching: function () {
4929      return 'Searchingâ€Â
vendor: 8,933 bytes, lines 4929-5271
4929¦';
4930    },
4931    removeAllItems: function () {
4932      return 'Remove all items';
4933    },
4934    removeItem: function () {
4935      return 'Remove item';
4936    },
4937    search: function() {
4938      return 'Search';
4939    }
4940  };
4941});
4942
4943S2.define('select2/defaults',[
4944  'jquery',
4945
4946  './results',
4947
4948  './selection/single',
4949  './selection/multiple',
4950  './selection/placeholder',
4951  './selection/allowClear',
4952  './selection/search',
4953  './selection/selectionCss',
4954  './selection/eventRelay',
4955
4956  './utils',
4957  './translation',
4958  './diacritics',
4959
4960  './data/select',
4961  './data/array',
4962  './data/ajax',
4963  './data/tags',
4964  './data/tokenizer',
4965  './data/minimumInputLength',
4966  './data/maximumInputLength',
4967  './data/maximumSelectionLength',
4968
4969  './dropdown',
4970  './dropdown/search',
4971  './dropdown/hidePlaceholder',
4972  './dropdown/infiniteScroll',
4973  './dropdown/attachBody',
4974  './dropdown/minimumResultsForSearch',
4975  './dropdown/selectOnClose',
4976  './dropdown/closeOnSelect',
4977  './dropdown/dropdownCss',
4978  './dropdown/tagsSearchHighlight',
4979
4980  './i18n/en'
4981], function ($,
4982
4983             ResultsList,
4984
4985             SingleSelection, MultipleSelection, Placeholder, AllowClear,
4986             SelectionSearch, SelectionCSS, EventRelay,
4987
4988             Utils, Translation, DIACRITICS,
4989
4990             SelectData, ArrayData, AjaxData, Tags, Tokenizer,
4991             MinimumInputLength, MaximumInputLength, MaximumSelectionLength,
4992
4993             Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
4994             AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,
4995             DropdownCSS, TagsSearchHighlight,
4996
4997             EnglishTranslation) {
4998  function Defaults () {
4999    this.reset();
5000  }
5001
5002  Defaults.prototype.apply = function (options) {
5003    options = $.extend(true, {}, this.defaults, options);
5004
5005    if (options.dataAdapter == null) {
5006      if (options.ajax != null) {
5007        options.dataAdapter = AjaxData;
5008      } else if (options.data != null) {
5009        options.dataAdapter = ArrayData;
5010      } else {
5011        options.dataAdapter = SelectData;
5012      }
5013
5014      if (options.minimumInputLength > 0) {
5015        options.dataAdapter = Utils.Decorate(
5016          options.dataAdapter,
5017          MinimumInputLength
5018        );
5019      }
5020
5021      if (options.maximumInputLength > 0) {
5022        options.dataAdapter = Utils.Decorate(
5023          options.dataAdapter,
5024          MaximumInputLength
5025        );
5026      }
5027
5028      if (options.maximumSelectionLength > 0) {
5029        options.dataAdapter = Utils.Decorate(
5030          options.dataAdapter,
5031          MaximumSelectionLength
5032        );
5033      }
5034
5035      if (options.tags) {
5036        options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);
5037      }
5038
5039      if (options.tokenSeparators != null || options.tokenizer != null) {
5040        options.dataAdapter = Utils.Decorate(
5041          options.dataAdapter,
5042          Tokenizer
5043        );
5044      }
5045    }
5046
5047    if (options.resultsAdapter == null) {
5048      options.resultsAdapter = ResultsList;
5049
5050      if (options.ajax != null) {
5051        options.resultsAdapter = Utils.Decorate(
5052          options.resultsAdapter,
5053          InfiniteScroll
5054        );
5055      }
5056
5057      if (options.placeholder != null) {
5058        options.resultsAdapter = Utils.Decorate(
5059          options.resultsAdapter,
5060          HidePlaceholder
5061        );
5062      }
5063
5064      if (options.selectOnClose) {
5065        options.resultsAdapter = Utils.Decorate(
5066          options.resultsAdapter,
5067          SelectOnClose
5068        );
5069      }
5070
5071      if (options.tags) {
5072        options.resultsAdapter = Utils.Decorate(
5073          options.resultsAdapter,
5074          TagsSearchHighlight
5075        );
5076      }
5077    }
5078
5079    if (options.dropdownAdapter == null) {
5080      if (options.multiple) {
5081        options.dropdownAdapter = Dropdown;
5082      } else {
5083        var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);
5084
5085        options.dropdownAdapter = SearchableDropdown;
5086      }
5087
5088      if (options.minimumResultsForSearch !== 0) {
5089        options.dropdownAdapter = Utils.Decorate(
5090          options.dropdownAdapter,
5091          MinimumResultsForSearch
5092        );
5093      }
5094
5095      if (options.closeOnSelect) {
5096        options.dropdownAdapter = Utils.Decorate(
5097          options.dropdownAdapter,
5098          CloseOnSelect
5099        );
5100      }
5101
5102      if (options.dropdownCssClass != null) {
5103        options.dropdownAdapter = Utils.Decorate(
5104          options.dropdownAdapter,
5105          DropdownCSS
5106        );
5107      }
5108
5109      options.dropdownAdapter = Utils.Decorate(
5110        options.dropdownAdapter,
5111        AttachBody
5112      );
5113    }
5114
5115    if (options.selectionAdapter == null) {
5116      if (options.multiple) {
5117        options.selectionAdapter = MultipleSelection;
5118      } else {
5119        options.selectionAdapter = SingleSelection;
5120      }
5121
5122      // Add the placeholder mixin if a placeholder was specified
5123      if (options.placeholder != null) {
5124        options.selectionAdapter = Utils.Decorate(
5125          options.selectionAdapter,
5126          Placeholder
5127        );
5128      }
5129
5130      if (options.allowClear) {
5131        options.selectionAdapter = Utils.Decorate(
5132          options.selectionAdapter,
5133          AllowClear
5134        );
5135      }
5136
5137      if (options.multiple) {
5138        options.selectionAdapter = Utils.Decorate(
5139          options.selectionAdapter,
5140          SelectionSearch
5141        );
5142      }
5143
5144      if (options.selectionCssClass != null) {
5145        options.selectionAdapter = Utils.Decorate(
5146          options.selectionAdapter,
5147          SelectionCSS
5148        );
5149      }
5150
5151      options.selectionAdapter = Utils.Decorate(
5152        options.selectionAdapter,
5153        EventRelay
5154      );
5155    }
5156
5157    // If the defaults were not previously applied from an element, it is
5158    // possible for the language option to have not been resolved
5159    options.language = this._resolveLanguage(options.language);
5160
5161    // Always fall back to English since it will always be complete
5162    options.language.push('en');
5163
5164    var uniqueLanguages = [];
5165
5166    for (var l = 0; l < options.language.length; l++) {
5167      var language = options.language[l];
5168
5169      if (uniqueLanguages.indexOf(language) === -1) {
5170        uniqueLanguages.push(language);
5171      }
5172    }
5173
5174    options.language = uniqueLanguages;
5175
5176    options.translations = this._processTranslations(
5177      options.language,
5178      options.debug
5179    );
5180
5181    return options;
5182  };
5183
5184  Defaults.prototype.reset = function () {
5185    function stripDiacritics (text) {
5186      // Used 'uni range + named function' from http://jsperf.com/diacritics/18
5187      function match(a) {
5188        return DIACRITICS[a] || a;
5189      }
5190
5191      return text.replace(/[^\u0000-\u007E]/g, match);
5192    }
5193
5194    function matcher (params, data) {
5195      // Always return the object if there is nothing to compare
5196      if (params.term == null || params.term.trim() === '') {
5197        return data;
5198      }
5199
5200      // Do a recursive check for options with children
5201      if (data.children && data.children.length > 0) {
5202        // Clone the data object if there are children
5203        // This is required as we modify the object to remove any non-matches
5204        var match = $.extend(true, {}, data);
5205
5206        // Check each child of the option
5207        for (var c = data.children.length - 1; c >= 0; c--) {
5208          var child = data.children[c];
5209
5210          var matches = matcher(params, child);
5211
5212          // If there wasn't a match, remove the object in the array
5213          if (matches == null) {
5214            match.children.splice(c, 1);
5215          }
5216        }
5217
5218        // If any children matched, return the new object
5219        if (match.children.length > 0) {
5220          return match;
5221        }
5222
5223        // If there were no matching children, check just the plain object
5224        return matcher(params, match);
5225      }
5226
5227      var original = stripDiacritics(data.text).toUpperCase();
5228      var term = stripDiacritics(params.term).toUpperCase();
5229
5230      // Check if the text contains the term
5231      if (original.indexOf(term) > -1) {
5232        return data;
5233      }
5234
5235      // If it doesn't contain the term, don't return anything
5236      return null;
5237    }
5238
5239    this.defaults = {
5240      amdLanguageBase: './i18n/',
5241      autocomplete: 'off',
5242      closeOnSelect: true,
5243      debug: false,
5244      dropdownAutoWidth: false,
5245      escapeMarkup: Utils.escapeMarkup,
5246      language: {},
5247      matcher: matcher,
5248      minimumInputLength: 0,
5249      maximumInputLength: 0,
5250      maximumSelectionLength: 0,
5251      minimumResultsForSearch: 0,
5252      selectOnClose: false,
5253      scrollAfterSelect: false,
5254      sorter: function (data) {
5255        return data;
5256      },
5257      templateResult: function (result) {
5258        return result.text;
5259      },
5260      templateSelection: function (selection) {
5261        return selection.text;
5262      },
5263      theme: 'default',
5264      width: 'resolve'
5265    };
5266  };
5267
5268  Defaults.prototype.applyFromElement = function (options, $element) {
5269    var optionLanguage = options.language;
5270    var defaultLanguage = this.defaults.language;
5271    var elementLanguage = $element
vendor: 19,057 bytes, lines 5271-6002
5271.prop('lang');
5272    var parentLanguage = $element.closest('[lang]').prop('lang');
5273
5274    var languages = Array.prototype.concat.call(
5275      this._resolveLanguage(elementLanguage),
5276      this._resolveLanguage(optionLanguage),
5277      this._resolveLanguage(defaultLanguage),
5278      this._resolveLanguage(parentLanguage)
5279    );
5280
5281    options.language = languages;
5282
5283    return options;
5284  };
5285
5286  Defaults.prototype._resolveLanguage = function (language) {
5287    if (!language) {
5288      return [];
5289    }
5290
5291    if ($.isEmptyObject(language)) {
5292      return [];
5293    }
5294
5295    if ($.isPlainObject(language)) {
5296      return [language];
5297    }
5298
5299    var languages;
5300
5301    if (!Array.isArray(language)) {
5302      languages = [language];
5303    } else {
5304      languages = language;
5305    }
5306
5307    var resolvedLanguages = [];
5308
5309    for (var l = 0; l < languages.length; l++) {
5310      resolvedLanguages.push(languages[l]);
5311
5312      if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
5313        // Extract the region information if it is included
5314        var languageParts = languages[l].split('-');
5315        var baseLanguage = languageParts[0];
5316
5317        resolvedLanguages.push(baseLanguage);
5318      }
5319    }
5320
5321    return resolvedLanguages;
5322  };
5323
5324  Defaults.prototype._processTranslations = function (languages, debug) {
5325    var translations = new Translation();
5326
5327    for (var l = 0; l < languages.length; l++) {
5328      var languageData = new Translation();
5329
5330      var language = languages[l];
5331
5332      if (typeof language === 'string') {
5333        try {
5334          // Try to load it with the original name
5335          languageData = Translation.loadPath(language);
5336        } catch (e) {
5337          try {
5338            // If we couldn't load it, check if it wasn't the full path
5339            language = this.defaults.amdLanguageBase + language;
5340            languageData = Translation.loadPath(language);
5341          } catch (ex) {
5342            // The translation could not be loaded at all. Sometimes this is
5343            // because of a configuration problem, other times this can be
5344            // because of how Select2 helps load all possible translation files
5345            if (debug && window.console && console.warn) {
5346              console.warn(
5347                'Select2: The language file for "' + language + '" could ' +
5348                'not be automatically loaded. A fallback will be used instead.'
5349              );
5350            }
5351          }
5352        }
5353      } else if ($.isPlainObject(language)) {
5354        languageData = new Translation(language);
5355      } else {
5356        languageData = language;
5357      }
5358
5359      translations.extend(languageData);
5360    }
5361
5362    return translations;
5363  };
5364
5365  Defaults.prototype.set = function (key, value) {
5366    var camelKey = $.camelCase(key);
5367
5368    var data = {};
5369    data[camelKey] = value;
5370
5371    var convertedData = Utils._convertData(data);
5372
5373    $.extend(true, this.defaults, convertedData);
5374  };
5375
5376  var defaults = new Defaults();
5377
5378  return defaults;
5379});
5380
5381S2.define('select2/options',[
5382  'jquery',
5383  './defaults',
5384  './utils'
5385], function ($, Defaults, Utils) {
5386  function Options (options, $element) {
5387    this.options = options;
5388
5389    if ($element != null) {
5390      this.fromElement($element);
5391    }
5392
5393    if ($element != null) {
5394      this.options = Defaults.applyFromElement(this.options, $element);
5395    }
5396
5397    this.options = Defaults.apply(this.options);
5398  }
5399
5400  Options.prototype.fromElement = function ($e) {
5401    var excludedData = ['select2'];
5402
5403    if (this.options.multiple == null) {
5404      this.options.multiple = $e.prop('multiple');
5405    }
5406
5407    if (this.options.disabled == null) {
5408      this.options.disabled = $e.prop('disabled');
5409    }
5410
5411    if (this.options.autocomplete == null && $e.prop('autocomplete')) {
5412      this.options.autocomplete = $e.prop('autocomplete');
5413    }
5414
5415    if (this.options.dir == null) {
5416      if ($e.prop('dir')) {
5417        this.options.dir = $e.prop('dir');
5418      } else if ($e.closest('[dir]').prop('dir')) {
5419        this.options.dir = $e.closest('[dir]').prop('dir');
5420      } else {
5421        this.options.dir = 'ltr';
5422      }
5423    }
5424
5425    $e.prop('disabled', this.options.disabled);
5426    $e.prop('multiple', this.options.multiple);
5427
5428    if (Utils.GetData($e[0], 'select2Tags')) {
5429      if (this.options.debug && window.console && console.warn) {
5430        console.warn(
5431          'Select2: The `data-select2-tags` attribute has been changed to ' +
5432          'use the `data-data` and `data-tags="true"` attributes and will be ' +
5433          'removed in future versions of Select2.'
5434        );
5435      }
5436
5437      Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
5438      Utils.StoreData($e[0], 'tags', true);
5439    }
5440
5441    if (Utils.GetData($e[0], 'ajaxUrl')) {
5442      if (this.options.debug && window.console && console.warn) {
5443        console.warn(
5444          'Select2: The `data-ajax-url` attribute has been changed to ' +
5445          '`data-ajax--url` and support for the old attribute will be removed' +
5446          ' in future versions of Select2.'
5447        );
5448      }
5449
5450      $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
5451      Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
5452    }
5453
5454    var dataset = {};
5455
5456    function upperCaseLetter(_, letter) {
5457      return letter.toUpperCase();
5458    }
5459
5460    // Pre-load all of the attributes which are prefixed with `data-`
5461    for (var attr = 0; attr < $e[0].attributes.length; attr++) {
5462      var attributeName = $e[0].attributes[attr].name;
5463      var prefix = 'data-';
5464
5465      if (attributeName.substr(0, prefix.length) == prefix) {
5466        // Get the contents of the attribute after `data-`
5467        var dataName = attributeName.substring(prefix.length);
5468
5469        // Get the data contents from the consistent source
5470        // This is more than likely the jQuery data helper
5471        var dataValue = Utils.GetData($e[0], dataName);
5472
5473        // camelCase the attribute name to match the spec
5474        var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter);
5475
5476        // Store the data attribute contents into the dataset since
5477        dataset[camelDataName] = dataValue;
5478      }
5479    }
5480
5481    // Prefer the element's `dataset` attribute if it exists
5482    // jQuery 1.x does not correctly handle data attributes with multiple dashes
5483    if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
5484      dataset = $.extend(true, {}, $e[0].dataset, dataset);
5485    }
5486
5487    // Prefer our internal data cache if it exists
5488    var data = $.extend(true, {}, Utils.GetData($e[0]), dataset);
5489
5490    data = Utils._convertData(data);
5491
5492    for (var key in data) {
5493      if (excludedData.indexOf(key) > -1) {
5494        continue;
5495      }
5496
5497      if ($.isPlainObject(this.options[key])) {
5498        $.extend(this.options[key], data[key]);
5499      } else {
5500        this.options[key] = data[key];
5501      }
5502    }
5503
5504    return this;
5505  };
5506
5507  Options.prototype.get = function (key) {
5508    return this.options[key];
5509  };
5510
5511  Options.prototype.set = function (key, val) {
5512    this.options[key] = val;
5513  };
5514
5515  return Options;
5516});
5517
5518S2.define('select2/core',[
5519  'jquery',
5520  './options',
5521  './utils',
5522  './keys'
5523], function ($, Options, Utils, KEYS) {
5524  var Select2 = function ($element, options) {
5525    if (Utils.GetData($element[0], 'select2') != null) {
5526      Utils.GetData($element[0], 'select2').destroy();
5527    }
5528
5529    this.$element = $element;
5530
5531    this.id = this._generateId($element);
5532
5533    options = options || {};
5534
5535    this.options = new Options(options, $element);
5536
5537    Select2.__super__.constructor.call(this);
5538
5539    // Set up the tabindex
5540
5541    var tabindex = $element.attr('tabindex') || 0;
5542    Utils.StoreData($element[0], 'old-tabindex', tabindex);
5543    $element.attr('tabindex', '-1');
5544
5545    // Set up containers and adapters
5546
5547    var DataAdapter = this.options.get('dataAdapter');
5548    this.dataAdapter = new DataAdapter($element, this.options);
5549
5550    var $container = this.render();
5551
5552    this._placeContainer($container);
5553
5554    var SelectionAdapter = this.options.get('selectionAdapter');
5555    this.selection = new SelectionAdapter($element, this.options);
5556    this.$selection = this.selection.render();
5557
5558    this.selection.position(this.$selection, $container);
5559
5560    var DropdownAdapter = this.options.get('dropdownAdapter');
5561    this.dropdown = new DropdownAdapter($element, this.options);
5562    this.$dropdown = this.dropdown.render();
5563
5564    this.dropdown.position(this.$dropdown, $container);
5565
5566    var ResultsAdapter = this.options.get('resultsAdapter');
5567    this.results = new ResultsAdapter($element, this.options, this.dataAdapter);
5568    this.$results = this.results.render();
5569
5570    this.results.position(this.$results, this.$dropdown);
5571
5572    // Bind events
5573
5574    var self = this;
5575
5576    // Bind the container to all of the adapters
5577    this._bindAdapters();
5578
5579    // Register any DOM event handlers
5580    this._registerDomEvents();
5581
5582    // Register any internal event handlers
5583    this._registerDataEvents();
5584    this._registerSelectionEvents();
5585    this._registerDropdownEvents();
5586    this._registerResultsEvents();
5587    this._registerEvents();
5588
5589    // Set the initial state
5590    this.dataAdapter.current(function (initialData) {
5591      self.trigger('selection:update', {
5592        data: initialData
5593      });
5594    });
5595
5596    // Hide the original select
5597    $element[0].classList.add('select2-hidden-accessible');
5598    $element.attr('aria-hidden', 'true');
5599
5600    // Synchronize any monitored attributes
5601    this._syncAttributes();
5602
5603    Utils.StoreData($element[0], 'select2', this);
5604
5605    // Ensure backwards compatibility with $element.data('select2').
5606    $element.data('select2', this);
5607  };
5608
5609  Utils.Extend(Select2, Utils.Observable);
5610
5611  Select2.prototype._generateId = function ($element) {
5612    var id = '';
5613
5614    if ($element.attr('id') != null) {
5615      id = $element.attr('id');
5616    } else if ($element.attr('name') != null) {
5617      id = $element.attr('name') + '-' + Utils.generateChars(2);
5618    } else {
5619      id = Utils.generateChars(4);
5620    }
5621
5622    id = id.replace(/(:|\.|\[|\]|,)/g, '');
5623    id = 'select2-' + id;
5624
5625    return id;
5626  };
5627
5628  Select2.prototype._placeContainer = function ($container) {
5629    $container.insertAfter(this.$element);
5630
5631    var width = this._resolveWidth(this.$element, this.options.get('width'));
5632
5633    if (width != null) {
5634      $container.css('width', width);
5635    }
5636  };
5637
5638  Select2.prototype._resolveWidth = function ($element, method) {
5639    var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;
5640
5641    if (method == 'resolve') {
5642      var styleWidth = this._resolveWidth($element, 'style');
5643
5644      if (styleWidth != null) {
5645        return styleWidth;
5646      }
5647
5648      return this._resolveWidth($element, 'element');
5649    }
5650
5651    if (method == 'element') {
5652      var elementWidth = $element.outerWidth(false);
5653
5654      if (elementWidth <= 0) {
5655        return 'auto';
5656      }
5657
5658      return elementWidth + 'px';
5659    }
5660
5661    if (method == 'style') {
5662      var style = $element.attr('style');
5663
5664      if (typeof(style) !== 'string') {
5665        return null;
5666      }
5667
5668      var attrs = style.split(';');
5669
5670      for (var i = 0, l = attrs.length; i < l; i = i + 1) {
5671        var attr = attrs[i].replace(/\s/g, '');
5672        var matches = attr.match(WIDTH);
5673
5674        if (matches !== null && matches.length >= 1) {
5675          return matches[1];
5676        }
5677      }
5678
5679      return null;
5680    }
5681
5682    if (method == 'computedstyle') {
5683      var computedStyle = window.getComputedStyle($element[0]);
5684
5685      return computedStyle.width;
5686    }
5687
5688    return method;
5689  };
5690
5691  Select2.prototype._bindAdapters = function () {
5692    this.dataAdapter.bind(this, this.$container);
5693    this.selection.bind(this, this.$container);
5694
5695    this.dropdown.bind(this, this.$container);
5696    this.results.bind(this, this.$container);
5697  };
5698
5699  Select2.prototype._registerDomEvents = function () {
5700    var self = this;
5701
5702    this.$element.on('change.select2', function () {
5703      self.dataAdapter.current(function (data) {
5704        self.trigger('selection:update', {
5705          data: data
5706        });
5707      });
5708    });
5709
5710    this.$element.on('focus.select2', function (evt) {
5711      self.trigger('focus', evt);
5712    });
5713
5714    this._syncA = Utils.bind(this._syncAttributes, this);
5715    this._syncS = Utils.bind(this._syncSubtree, this);
5716
5717    this._observer = new window.MutationObserver(function (mutations) {
5718      self._syncA();
5719      self._syncS(mutations);
5720    });
5721    this._observer.observe(this.$element[0], {
5722      attributes: true,
5723      childList: true,
5724      subtree: false
5725    });
5726  };
5727
5728  Select2.prototype._registerDataEvents = function () {
5729    var self = this;
5730
5731    this.dataAdapter.on('*', function (name, params) {
5732      self.trigger(name, params);
5733    });
5734  };
5735
5736  Select2.prototype._registerSelectionEvents = function () {
5737    var self = this;
5738    var nonRelayEvents = ['toggle', 'focus'];
5739
5740    this.selection.on('toggle', function () {
5741      self.toggleDropdown();
5742    });
5743
5744    this.selection.on('focus', function (params) {
5745      self.focus(params);
5746    });
5747
5748    this.selection.on('*', function (name, params) {
5749      if (nonRelayEvents.indexOf(name) !== -1) {
5750        return;
5751      }
5752
5753      self.trigger(name, params);
5754    });
5755  };
5756
5757  Select2.prototype._registerDropdownEvents = function () {
5758    var self = this;
5759
5760    this.dropdown.on('*', function (name, params) {
5761      self.trigger(name, params);
5762    });
5763  };
5764
5765  Select2.prototype._registerResultsEvents = function () {
5766    var self = this;
5767
5768    this.results.on('*', function (name, params) {
5769      self.trigger(name, params);
5770    });
5771  };
5772
5773  Select2.prototype._registerEvents = function () {
5774    var self = this;
5775
5776    this.on('open', function () {
5777      self.$container[0].classList.add('select2-container--open');
5778    });
5779
5780    this.on('close', function () {
5781      self.$container[0].classList.remove('select2-container--open');
5782    });
5783
5784    this.on('enable', function () {
5785      self.$container[0].classList.remove('select2-container--disabled');
5786    });
5787
5788    this.on('disable', function () {
5789      self.$container[0].classList.add('select2-container--disabled');
5790    });
5791
5792    this.on('blur', function () {
5793      self.$container[0].classList.remove('select2-container--focus');
5794    });
5795
5796    this.on('query', function (params) {
5797      if (!self.isOpen()) {
5798        self.trigger('open', {});
5799      }
5800
5801      this.dataAdapter.query(params, function (data) {
5802        self.trigger('results:all', {
5803          data: data,
5804          query: params
5805        });
5806      });
5807    });
5808
5809    this.on('query:append', function (params) {
5810      this.dataAdapter.query(params, function (data) {
5811        self.trigger('results:append', {
5812          data: data,
5813          query: params
5814        });
5815      });
5816    });
5817
5818    this.on('keypress', function (evt) {
5819      var key = evt.which;
5820
5821      if (self.isOpen()) {
5822        if (key === KEYS.ESC || (key === KEYS.UP && evt.altKey)) {
5823          self.close(evt);
5824
5825          evt.preventDefault();
5826        } else if (key === KEYS.ENTER || key === KEYS.TAB) {
5827          self.trigger('results:select', {});
5828
5829          evt.preventDefault();
5830        } else if ((key === KEYS.SPACE && evt.ctrlKey)) {
5831          self.trigger('results:toggle', {});
5832
5833          evt.preventDefault();
5834        } else if (key === KEYS.UP) {
5835          self.trigger('results:previous', {});
5836
5837          evt.preventDefault();
5838        } else if (key === KEYS.DOWN) {
5839          self.trigger('results:next', {});
5840
5841          evt.preventDefault();
5842        }
5843      } else {
5844        if (key === KEYS.ENTER || key === KEYS.SPACE ||
5845            (key === KEYS.DOWN && evt.altKey)) {
5846          self.open();
5847
5848          evt.preventDefault();
5849        }
5850      }
5851    });
5852  };
5853
5854  Select2.prototype._syncAttributes = function () {
5855    this.options.set('disabled', this.$element.prop('disabled'));
5856
5857    if (this.isDisabled()) {
5858      if (this.isOpen()) {
5859        this.close();
5860      }
5861
5862      this.trigger('disable', {});
5863    } else {
5864      this.trigger('enable', {});
5865    }
5866  };
5867
5868  Select2.prototype._isChangeMutation = function (mutations) {
5869    var self = this;
5870
5871    if (mutations.addedNodes && mutations.addedNodes.length > 0) {
5872      for (var n = 0; n < mutations.addedNodes.length; n++) {
5873        var node = mutations.addedNodes[n];
5874
5875        if (node.selected) {
5876          return true;
5877        }
5878      }
5879    } else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
5880      return true;
5881    } else if (Array.isArray(mutations)) {
5882      return mutations.some(function (mutation) {
5883        return self._isChangeMutation(mutation);
5884      });
5885    }
5886
5887    return false;
5888  };
5889
5890  Select2.prototype._syncSubtree = function (mutations) {
5891    var changed = this._isChangeMutation(mutations);
5892    var self = this;
5893
5894    // Only re-pull the data if we think there is a change
5895    if (changed) {
5896      this.dataAdapter.current(function (currentData) {
5897        self.trigger('selection:update', {
5898          data: currentData
5899        });
5900      });
5901    }
5902  };
5903
5904  /**
5905   * Override the trigger method to automatically trigger pre-events when
5906   * there are events that can be prevented.
5907   */
5908  Select2.prototype.trigger = function (name, args) {
5909    var actualTrigger = Select2.__super__.trigger;
5910    var preTriggerMap = {
5911      'open': 'opening',
5912      'close': 'closing',
5913      'select': 'selecting',
5914      'unselect': 'unselecting',
5915      'clear': 'clearing'
5916    };
5917
5918    if (args === undefined) {
5919      args = {};
5920    }
5921
5922    if (name in preTriggerMap) {
5923      var preTriggerName = preTriggerMap[name];
5924      var preTriggerArgs = {
5925        prevented: false,
5926        name: name,
5927        args: args
5928      };
5929
5930      actualTrigger.call(this, preTriggerName, preTriggerArgs);
5931
5932      if (preTriggerArgs.prevented) {
5933        args.prevented = true;
5934
5935        return;
5936      }
5937    }
5938
5939    actualTrigger.call(this, name, args);
5940  };
5941
5942  Select2.prototype.toggleDropdown = function () {
5943    if (this.isDisabled()) {
5944      return;
5945    }
5946
5947    if (this.isOpen()) {
5948      this.close();
5949    } else {
5950      this.open();
5951    }
5952  };
5953
5954  Select2.prototype.open = function () {
5955    if (this.isOpen()) {
5956      return;
5957    }
5958
5959    if (this.isDisabled()) {
5960      return;
5961    }
5962
5963    this.trigger('query', {});
5964  };
5965
5966  Select2.prototype.close = function (evt) {
5967    if (!this.isOpen()) {
5968      return;
5969    }
5970
5971    this.trigger('close', { originalEvent : evt });
5972  };
5973
5974  /**
5975   * Helper method to abstract the "enabled" (not "disabled") state of this
5976   * object.
5977   *
5978   * @return {true} if the instance is not disabled.
5979   * @return {false} if the instance is disabled.
5980   */
5981  Select2.prototype.isEnabled = function () {
5982    return !this.isDisabled();
5983  };
5984
5985  /**
5986   * Helper method to abstract the "disabled" state of this object.
5987   *
5988   * @return {true} if the disabled option is true.
5989   * @return {false} if the disabled option is false.
5990   */
5991  Select2.prototype.isDisabled = function () {
5992    return this.options.get('disabled');
5993  };
5994
5995  Select2.prototype.isOpen = function () {
5996    return this.$container[0].classList.contains('select2-container--open');
5997  };
5998
5999  Select2.prototype.hasFocus = function () {
6000    return this.$container[0].classList.contains('select2-container--focus');
6001  };
6002
vendor: 5,477 bytes, lines 6003-6211
6003  Select2.prototype.focus = function (data) {
6004    // No need to re-trigger focus events if we are already focused
6005    if (this.hasFocus()) {
6006      return;
6007    }
6008
6009    this.$container[0].classList.add('select2-container--focus');
6010    this.trigger('focus', {});
6011  };
6012
6013  Select2.prototype.enable = function (args) {
6014    if (this.options.get('debug') && window.console && console.warn) {
6015      console.warn(
6016        'Select2: The `select2("enable")` method has been deprecated and will' +
6017        ' be removed in later Select2 versions. Use $element.prop("disabled")' +
6018        ' instead.'
6019      );
6020    }
6021
6022    if (args == null || args.length === 0) {
6023      args = [true];
6024    }
6025
6026    var disabled = !args[0];
6027
6028    this.$element.prop('disabled', disabled);
6029  };
6030
6031  Select2.prototype.data = function () {
6032    if (this.options.get('debug') &&
6033        arguments.length > 0 && window.console && console.warn) {
6034      console.warn(
6035        'Select2: Data can no longer be set using `select2("data")`. You ' +
6036        'should consider setting the value instead using `$element.val()`.'
6037      );
6038    }
6039
6040    var data = [];
6041
6042    this.dataAdapter.current(function (currentData) {
6043      data = currentData;
6044    });
6045
6046    return data;
6047  };
6048
6049  Select2.prototype.val = function (args) {
6050    if (this.options.get('debug') && window.console && console.warn) {
6051      console.warn(
6052        'Select2: The `select2("val")` method has been deprecated and will be' +
6053        ' removed in later Select2 versions. Use $element.val() instead.'
6054      );
6055    }
6056
6057    if (args == null || args.length === 0) {
6058      return this.$element.val();
6059    }
6060
6061    var newVal = args[0];
6062
6063    if (Array.isArray(newVal)) {
6064      newVal = newVal.map(function (obj) {
6065        return obj.toString();
6066      });
6067    }
6068
6069    this.$element.val(newVal).trigger('input').trigger('change');
6070  };
6071
6072  Select2.prototype.destroy = function () {
6073    Utils.RemoveData(this.$container[0]);
6074    this.$container.remove();
6075
6076    this._observer.disconnect();
6077    this._observer = null;
6078
6079    this._syncA = null;
6080    this._syncS = null;
6081
6082    this.$element.off('.select2');
6083    this.$element.attr('tabindex',
6084    Utils.GetData(this.$element[0], 'old-tabindex'));
6085
6086    this.$element[0].classList.remove('select2-hidden-accessible');
6087    this.$element.attr('aria-hidden', 'false');
6088    Utils.RemoveData(this.$element[0]);
6089    this.$element.removeData('select2');
6090
6091    this.dataAdapter.destroy();
6092    this.selection.destroy();
6093    this.dropdown.destroy();
6094    this.results.destroy();
6095
6096    this.dataAdapter = null;
6097    this.selection = null;
6098    this.dropdown = null;
6099    this.results = null;
6100  };
6101
6102  Select2.prototype.render = function () {
6103    var $container = $(
6104      '<span class="select2 select2-container">' +
6105        '<span class="selection"></span>' +
6106        '<span class="dropdown-wrapper" aria-hidden="true"></span>' +
6107      '</span>'
6108    );
6109
6110    $container.attr('dir', this.options.get('dir'));
6111
6112    this.$container = $container;
6113
6114    this.$container[0].classList
6115      .add('select2-container--' + this.options.get('theme'));
6116
6117    Utils.StoreData($container[0], 'element', this.$element);
6118
6119    return $container;
6120  };
6121
6122  return Select2;
6123});
6124
6125S2.define('jquery-mousewheel',[
6126  'jquery'
6127], function ($) {
6128  // Used to shim jQuery.mousewheel for non-full builds.
6129  return $;
6130});
6131
6132S2.define('jquery.select2',[
6133  'jquery',
6134  'jquery-mousewheel',
6135
6136  './select2/core',
6137  './select2/defaults',
6138  './select2/utils'
6139], function ($, _, Select2, Defaults, Utils) {
6140  if ($.fn.select2 == null) {
6141    // All methods that should return the element
6142    var thisMethods = ['open', 'close', 'destroy'];
6143
6144    $.fn.select2 = function (options) {
6145      options = options || {};
6146
6147      if (typeof options === 'object') {
6148        this.each(function () {
6149          var instanceOptions = $.extend(true, {}, options);
6150
6151          var instance = new Select2($(this), instanceOptions);
6152        });
6153
6154        return this;
6155      } else if (typeof options === 'string') {
6156        var ret;
6157        var args = Array.prototype.slice.call(arguments, 1);
6158
6159        this.each(function () {
6160          var instance = Utils.GetData(this, 'select2');
6161
6162          if (instance == null && window.console && console.error) {
6163            console.error(
6164              'The select2(\'' + options + '\') method was called on an ' +
6165              'element that is not using Select2.'
6166            );
6167          }
6168
6169          ret = instance[options].apply(instance, args);
6170        });
6171
6172        // Check if we should be returning `this`
6173        if (thisMethods.indexOf(options) > -1) {
6174          return this;
6175        }
6176
6177        return ret;
6178      } else {
6179        throw new Error('Invalid arguments for Select2: ' + options);
6180      }
6181    };
6182  }
6183
6184  if ($.fn.select2.defaults == null) {
6185    $.fn.select2.defaults = Defaults;
6186  }
6187
6188  return Select2;
6189});
6190
6191  // Return the AMD loader configuration so it can be used outside of this file
6192  return {
6193    define: S2.define,
6194    require: S2.require
6195  };
6196}());
6197
6198  // Autoload the jQuery bindings
6199  // We know that all of the modules exist above this, so we're safe
6200  var select2 = S2.require('jquery.select2');
6201
6202  // Hold the AMD module references on the jQuery function that was just loaded
6203  // This allows Select2 to use the internal loader outside of this file, such
6204  // as in the language files.
6205  jQuery.fn.select2.amd = S2;
6206
6207  // Return the Select2 instance for anyone who is importing it.
6208  return select2;
6209}));
6210
6211/*! Magnific Popup - v1.1.0 - 2016-02-20
vendor: 55,124 bytes, lines 6212-8079
6212* http://dimsemenov.com/plugins/magnific-popup/
6213* Copyright (c) 2016 Dmitry Semenov; */
6214;(function (factory) {
6215if (typeof define === 'function' && define.amd) {
6216 // AMD. Register as an anonymous module.
6217 define(['jquery'], factory);
6218 } else if (typeof exports === 'object') {
6219 // Node/CommonJS
6220 factory(require('jquery'));
6221 } else {
6222 // Browser globals
6223 factory(window.jQuery || window.Zepto);
6224 }
6225 }(function($) {
6226
6227/*>>core*/
6228/**
6229 *
6230 * Magnific Popup Core JS file
6231 *
6232 */
6233
6234
6235/**
6236 * Private static constants
6237 */
6238var CLOSE_EVENT = 'Close',
6239    BEFORE_CLOSE_EVENT = 'BeforeClose',
6240    AFTER_CLOSE_EVENT = 'AfterClose',
6241    BEFORE_APPEND_EVENT = 'BeforeAppend',
6242    MARKUP_PARSE_EVENT = 'MarkupParse',
6243    OPEN_EVENT = 'Open',
6244    CHANGE_EVENT = 'Change',
6245    NS = 'mfp',
6246    EVENT_NS = '.' + NS,
6247    READY_CLASS = 'mfp-ready',
6248    REMOVING_CLASS = 'mfp-removing',
6249    PREVENT_CLOSE_CLASS = 'mfp-prevent-close';
6250
6251
6252/**
6253 * Private vars
6254 */
6255/*jshint -W079 */
6256var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this'
6257    MagnificPopup = function(){},
6258    _isJQ = !!(window.jQuery),
6259    _prevStatus,
6260    _window = $(window),
6261    _document,
6262    _prevContentType,
6263    _wrapClasses,
6264    _currPopupType;
6265
6266
6267/**
6268 * Private functions
6269 */
6270var _mfpOn = function(name, f) {
6271        mfp.ev.on(NS + name + EVENT_NS, f);
6272    },
6273    _getEl = function(className, appendTo, html, raw) {
6274        var el = document.createElement('div');
6275        el.className = 'mfp-'+className;
6276        if(html) {
6277            el.innerHTML = html;
6278        }
6279        if(!raw) {
6280            el = $(el);
6281            if(appendTo) {
6282                el.appendTo(appendTo);
6283            }
6284        } else if(appendTo) {
6285            appendTo.appendChild(el);
6286        }
6287        return el;
6288    },
6289    _mfpTrigger = function(e, data) {
6290        mfp.ev.triggerHandler(NS + e, data);
6291
6292        if(mfp.st.callbacks) {
6293            // converts "mfpEventName" to "eventName" callback and triggers it if it's present
6294            e = e.charAt(0).toLowerCase() + e.slice(1);
6295            if(mfp.st.callbacks[e]) {
6296                mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]);
6297            }
6298        }
6299    },
6300    _getCloseBtn = function(type) {
6301        if(type !== _currPopupType || !mfp.currTemplate.closeBtn) {
6302            mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) );
6303            _currPopupType = type;
6304        }
6305        return mfp.currTemplate.closeBtn;
6306    },
6307    // Initialize Magnific Popup only when called at least once
6308    _checkInstance = function() {
6309        if(!$.magnificPopup.instance) {
6310            /*jshint -W020 */
6311            mfp = new MagnificPopup();
6312            mfp.init();
6313            $.magnificPopup.instance = mfp;
6314        }
6315    },
6316    // CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
6317    supportsTransitions = function() {
6318        var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist
6319            v = ['ms','O','Moz','Webkit']; // 'v' for vendor
6320
6321        if( s['transition'] !== undefined ) {
6322            return true;
6323        }
6324
6325        while( v.length ) {
6326            if( v.pop() + 'Transition' in s ) {
6327                return true;
6328            }
6329        }
6330
6331        return false;
6332    };
6333
6334
6335
6336/**
6337 * Public functions
6338 */
6339MagnificPopup.prototype = {
6340
6341    constructor: MagnificPopup,
6342
6343    /**
6344     * Initializes Magnific Popup plugin.
6345     * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed
6346     */
6347    init: function() {
6348        var appVersion = navigator.appVersion;
6349        mfp.isLowIE = mfp.isIE8 = document.all && !document.addEventListener;
6350        mfp.isAndroid = (/android/gi).test(appVersion);
6351        mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion);
6352        mfp.supportsTransition = supportsTransitions();
6353
6354        // We disable fixed positioned lightbox on devices that don't handle it nicely.
6355        // If you know a better way of detecting this - let me know.
6356        mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) );
6357        _document = $(document);
6358
6359        mfp.popupsCache = {};
6360    },
6361
6362    /**
6363     * Opens popup
6364     * @param  data [description]
6365     */
6366    open: function(data) {
6367
6368        var i;
6369
6370        if(data.isObj === false) {
6371            // convert jQuery collection to array to avoid conflicts later
6372            mfp.items = data.items.toArray();
6373
6374            mfp.index = 0;
6375            var items = data.items,
6376                item;
6377            for(i = 0; i < items.length; i++) {
6378                item = items[i];
6379                if(item.parsed) {
6380                    item = item.el[0];
6381                }
6382                if(item === data.el[0]) {
6383                    mfp.index = i;
6384                    break;
6385                }
6386            }
6387        } else {
6388            mfp.items = $.isArray(data.items) ? data.items : [data.items];
6389            mfp.index = data.index || 0;
6390        }
6391
6392        // if popup is already opened - we just update the content
6393        if(mfp.isOpen) {
6394            mfp.updateItemHTML();
6395            return;
6396        }
6397
6398        mfp.types = [];
6399        _wrapClasses = '';
6400        if(data.mainEl && data.mainEl.length) {
6401            mfp.ev = data.mainEl.eq(0);
6402        } else {
6403            mfp.ev = _document;
6404        }
6405
6406        if(data.key) {
6407            if(!mfp.popupsCache[data.key]) {
6408                mfp.popupsCache[data.key] = {};
6409            }
6410            mfp.currTemplate = mfp.popupsCache[data.key];
6411        } else {
6412            mfp.currTemplate = {};
6413        }
6414
6415
6416
6417        mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data );
6418        mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos;
6419
6420        if(mfp.st.modal) {
6421            mfp.st.closeOnContentClick = false;
6422            mfp.st.closeOnBgClick = false;
6423            mfp.st.showCloseBtn = false;
6424            mfp.st.enableEscapeKey = false;
6425        }
6426
6427
6428        // Building markup
6429        // main containers are created only once
6430        if(!mfp.bgOverlay) {
6431
6432            // Dark overlay
6433            mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() {
6434                mfp.close();
6435            });
6436
6437            mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) {
6438                if(mfp._checkIfClose(e.target)) {
6439                    mfp.close();
6440                }
6441            });
6442
6443            mfp.container = _getEl('container', mfp.wrap);
6444        }
6445
6446        mfp.contentContainer = _getEl('content');
6447        if(mfp.st.preloader) {
6448            mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading);
6449        }
6450
6451
6452        // Initializing modules
6453        var modules = $.magnificPopup.modules;
6454        for(i = 0; i < modules.length; i++) {
6455            var n = modules[i];
6456            n = n.charAt(0).toUpperCase() + n.slice(1);
6457            mfp['init'+n].call(mfp);
6458        }
6459        _mfpTrigger('BeforeOpen');
6460
6461
6462        if(mfp.st.showCloseBtn) {
6463            // Close button
6464            if(!mfp.st.closeBtnInside) {
6465                mfp.wrap.append( _getCloseBtn() );
6466            } else {
6467                _mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
6468                    values.close_replaceWith = _getCloseBtn(item.type);
6469                });
6470                _wrapClasses += ' mfp-close-btn-in';
6471            }
6472        }
6473
6474        if(mfp.st.alignTop) {
6475            _wrapClasses += ' mfp-align-top';
6476        }
6477
6478
6479
6480        if(mfp.fixedContentPos) {
6481            mfp.wrap.css({
6482                overflow: mfp.st.overflowY,
6483                overflowX: 'hidden',
6484                overflowY: mfp.st.overflowY
6485            });
6486        } else {
6487            mfp.wrap.css({
6488                top: _window.scrollTop(),
6489                position: 'absolute'
6490            });
6491        }
6492        if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) {
6493            mfp.bgOverlay.css({
6494                height: _document.height(),
6495                position: 'absolute'
6496            });
6497        }
6498
6499
6500
6501        if(mfp.st.enableEscapeKey) {
6502            // Close on ESC key
6503            _document.on('keyup' + EVENT_NS, function(e) {
6504                if(e.keyCode === 27) {
6505                    mfp.close();
6506                }
6507            });
6508        }
6509
6510        _window.on('resize' + EVENT_NS, function() {
6511            mfp.updateSize();
6512        });
6513
6514
6515        if(!mfp.st.closeOnContentClick) {
6516            _wrapClasses += ' mfp-auto-cursor';
6517        }
6518
6519        if(_wrapClasses)
6520            mfp.wrap.addClass(_wrapClasses);
6521
6522
6523        // this triggers recalculation of layout, so we get it once to not to trigger twice
6524        var windowHeight = mfp.wH = _window.height();
6525
6526
6527        var windowStyles = {};
6528
6529        if( mfp.fixedContentPos ) {
6530            if(mfp._hasScrollBar(windowHeight)){
6531                var s = mfp._getScrollbarSize();
6532                if(s) {
6533                    windowStyles.marginRight = s;
6534                }
6535            }
6536        }
6537
6538        if(mfp.fixedContentPos) {
6539            if(!mfp.isIE7) {
6540                windowStyles.overflow = 'hidden';
6541            } else {
6542                // ie7 double-scroll bug
6543                $('body, html').css('overflow', 'hidden');
6544            }
6545        }
6546
6547
6548
6549        var classesToadd = mfp.st.mainClass;
6550        if(mfp.isIE7) {
6551            classesToadd += ' mfp-ie7';
6552        }
6553        if(classesToadd) {
6554            mfp._addClassToMFP( classesToadd );
6555        }
6556
6557        // add content
6558        mfp.updateItemHTML();
6559
6560        _mfpTrigger('BuildControls');
6561
6562        // remove scrollbar, add margin e.t.c
6563        $('html').css(windowStyles);
6564
6565        // add everything to DOM
6566        mfp.bgOverlay.add(mfp.wrap).prependTo( mfp.st.prependTo || $(document.body) );
6567
6568        // Save last focused element
6569        mfp._lastFocusedEl = document.activeElement;
6570
6571        // Wait for next cycle to allow CSS transition
6572        setTimeout(function() {
6573
6574            if(mfp.content) {
6575                mfp._addClassToMFP(READY_CLASS);
6576                mfp._setFocus();
6577            } else {
6578                // if content is not defined (not loaded e.t.c) we add class only for BG
6579                mfp.bgOverlay.addClass(READY_CLASS);
6580            }
6581
6582            // Trap the focus in popup
6583            _document.on('focusin' + EVENT_NS, mfp._onFocusIn);
6584
6585        }, 16);
6586
6587        mfp.isOpen = true;
6588        mfp.updateSize(windowHeight);
6589        _mfpTrigger(OPEN_EVENT);
6590
6591        return data;
6592    },
6593
6594    /**
6595     * Closes the popup
6596     */
6597    close: function() {
6598        if(!mfp.isOpen) return;
6599        _mfpTrigger(BEFORE_CLOSE_EVENT);
6600
6601        mfp.isOpen = false;
6602        // for CSS3 animation
6603        if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition )  {
6604            mfp._addClassToMFP(REMOVING_CLASS);
6605            setTimeout(function() {
6606                mfp._close();
6607            }, mfp.st.removalDelay);
6608        } else {
6609            mfp._close();
6610        }
6611    },
6612
6613    /**
6614     * Helper for close() function
6615     */
6616    _close: function() {
6617        _mfpTrigger(CLOSE_EVENT);
6618
6619        var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' ';
6620
6621        mfp.bgOverlay.detach();
6622        mfp.wrap.detach();
6623        mfp.container.empty();
6624
6625        if(mfp.st.mainClass) {
6626            classesToRemove += mfp.st.mainClass + ' ';
6627        }
6628
6629        mfp._removeClassFromMFP(classesToRemove);
6630
6631        if(mfp.fixedContentPos) {
6632            var windowStyles = {marginRight: ''};
6633            if(mfp.isIE7) {
6634                $('body, html').css('overflow', '');
6635            } else {
6636                windowStyles.overflow = '';
6637            }
6638            $('html').css(windowStyles);
6639        }
6640
6641        _document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS);
6642        mfp.ev.off(EVENT_NS);
6643
6644        // clean up DOM elements that aren't removed
6645        mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style');
6646        mfp.bgOverlay.attr('class', 'mfp-bg');
6647        mfp.container.attr('class', 'mfp-container');
6648
6649        // remove close button from target element
6650        if(mfp.st.showCloseBtn &&
6651        (!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) {
6652            if(mfp.currTemplate.closeBtn)
6653                mfp.currTemplate.closeBtn.detach();
6654        }
6655
6656
6657        if(mfp.st.autoFocusLast && mfp._lastFocusedEl) {
6658            $(mfp._lastFocusedEl).focus(); // put tab focus back
6659        }
6660        mfp.currItem = null;
6661        mfp.content = null;
6662        mfp.currTemplate = null;
6663        mfp.prevHeight = 0;
6664
6665        _mfpTrigger(AFTER_CLOSE_EVENT);
6666    },
6667
6668    updateSize: function(winHeight) {
6669
6670        if(mfp.isIOS) {
6671            // fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2
6672            var zoomLevel = document.documentElement.clientWidth / window.innerWidth;
6673            var height = window.innerHeight * zoomLevel;
6674            mfp.wrap.css('height', height);
6675            mfp.wH = height;
6676        } else {
6677            mfp.wH = winHeight || _window.height();
6678        }
6679        // Fixes #84: popup incorrectly positioned with position:relative on body
6680        if(!mfp.fixedContentPos) {
6681            mfp.wrap.css('height', mfp.wH);
6682        }
6683
6684        _mfpTrigger('Resize');
6685
6686    },
6687
6688    /**
6689     * Set content of popup based on current index
6690     */
6691    updateItemHTML: function() {
6692        var item = mfp.items[mfp.index];
6693
6694        // Detach and perform modifications
6695        mfp.contentContainer.detach();
6696
6697        if(mfp.content)
6698            mfp.content.detach();
6699
6700        if(!item.parsed) {
6701            item = mfp.parseEl( mfp.index );
6702        }
6703
6704        var type = item.type;
6705
6706        _mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]);
6707        // BeforeChange event works like so:
6708        // _mfpOn('BeforeChange', function(e, prevType, newType) { });
6709
6710        mfp.currItem = item;
6711
6712        if(!mfp.currTemplate[type]) {
6713            var markup = mfp.st[type] ? mfp.st[type].markup : false;
6714
6715            // allows to modify markup
6716            _mfpTrigger('FirstMarkupParse', markup);
6717
6718            if(markup) {
6719                mfp.currTemplate[type] = $(markup);
6720            } else {
6721                // if there is no markup found we just define that template is parsed
6722                mfp.currTemplate[type] = true;
6723            }
6724        }
6725
6726        if(_prevContentType && _prevContentType !== item.type) {
6727            mfp.container.removeClass('mfp-'+_prevContentType+'-holder');
6728        }
6729
6730        var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]);
6731        mfp.appendContent(newContent, type);
6732
6733        item.preloaded = true;
6734
6735        _mfpTrigger(CHANGE_EVENT, item);
6736        _prevContentType = item.type;
6737
6738        // Append container back after its content changed
6739        mfp.container.prepend(mfp.contentContainer);
6740
6741        _mfpTrigger('AfterChange');
6742    },
6743
6744
6745    /**
6746     * Set HTML content of popup
6747     */
6748    appendContent: function(newContent, type) {
6749        mfp.content = newContent;
6750
6751        if(newContent) {
6752            if(mfp.st.showCloseBtn && mfp.st.closeBtnInside &&
6753                mfp.currTemplate[type] === true) {
6754                // if there is no markup, we just append close button element inside
6755                if(!mfp.content.find('.mfp-close').length) {
6756                    mfp.content.append(_getCloseBtn());
6757                }
6758            } else {
6759                mfp.content = newContent;
6760            }
6761        } else {
6762            mfp.content = '';
6763        }
6764
6765        _mfpTrigger(BEFORE_APPEND_EVENT);
6766        mfp.container.addClass('mfp-'+type+'-holder');
6767
6768        mfp.contentContainer.append(mfp.content);
6769    },
6770
6771
6772    /**
6773     * Creates Magnific Popup data object based on given data
6774     * @param  {int} index Index of item to parse
6775     */
6776    parseEl: function(index) {
6777        var item = mfp.items[index],
6778            type;
6779
6780        if(item.tagName) {
6781            item = { el: $(item) };
6782        } else {
6783            type = item.type;
6784            item = { data: item, src: item.src };
6785        }
6786
6787        if(item.el) {
6788            var types = mfp.types;
6789
6790            // check for 'mfp-TYPE' class
6791            for(var i = 0; i < types.length; i++) {
6792                if( item.el.hasClass('mfp-'+types[i]) ) {
6793                    type = types[i];
6794                    break;
6795                }
6796            }
6797
6798            item.src = item.el.attr('data-mfp-src');
6799            if(!item.src) {
6800                item.src = item.el.attr('href');
6801            }
6802        }
6803
6804        item.type = type || mfp.st.type || 'inline';
6805        item.index = index;
6806        item.parsed = true;
6807        mfp.items[index] = item;
6808        _mfpTrigger('ElementParse', item);
6809
6810        return mfp.items[index];
6811    },
6812
6813
6814    /**
6815     * Initializes single popup or a group of popups
6816     */
6817    addGroup: function(el, options) {
6818        var eHandler = function(e) {
6819            e.mfpEl = this;
6820            mfp._openClick(e, el, options);
6821        };
6822
6823        if(!options) {
6824            options = {};
6825        }
6826
6827        var eName = 'click.magnificPopup';
6828        options.mainEl = el;
6829
6830        if(options.items) {
6831            options.isObj = true;
6832            el.off(eName).on(eName, eHandler);
6833        } else {
6834            options.isObj = false;
6835            if(options.delegate) {
6836                el.off(eName).on(eName, options.delegate , eHandler);
6837            } else {
6838                options.items = el;
6839                el.off(eName).on(eName, eHandler);
6840            }
6841        }
6842    },
6843    _openClick: function(e, el, options) {
6844        var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick;
6845
6846
6847        if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey ) ) {
6848            return;
6849        }
6850
6851        var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn;
6852
6853        if(disableOn) {
6854            if($.isFunction(disableOn)) {
6855                if( !disableOn.call(mfp) ) {
6856                    return true;
6857                }
6858            } else { // else it's number
6859                if( _window.width() < disableOn ) {
6860                    return true;
6861                }
6862            }
6863        }
6864
6865        if(e.type) {
6866            e.preventDefault();
6867
6868            // This will prevent popup from closing if element is inside and popup is already opened
6869            if(mfp.isOpen) {
6870                e.stopPropagation();
6871            }
6872        }
6873
6874        options.el = $(e.mfpEl);
6875        if(options.delegate) {
6876            options.items = el.find(options.delegate);
6877        }
6878        mfp.open(options);
6879    },
6880
6881
6882    /**
6883     * Updates text on preloader
6884     */
6885    updateStatus: function(status, text) {
6886
6887        if(mfp.preloader) {
6888            if(_prevStatus !== status) {
6889                mfp.container.removeClass('mfp-s-'+_prevStatus);
6890            }
6891
6892            if(!text && status === 'loading') {
6893                text = mfp.st.tLoading;
6894            }
6895
6896            var data = {
6897                status: status,
6898                text: text
6899            };
6900            // allows to modify status
6901            _mfpTrigger('UpdateStatus', data);
6902
6903            status = data.status;
6904            text = data.text;
6905
6906            mfp.preloader.html(text);
6907
6908            mfp.preloader.find('a').on('click', function(e) {
6909                e.stopImmediatePropagation();
6910            });
6911
6912            mfp.container.addClass('mfp-s-'+status);
6913            _prevStatus = status;
6914        }
6915    },
6916
6917
6918    /*
6919        "Private" helpers that aren't private at all
6920     */
6921    // Check to close popup or not
6922    // "target" is an element that was clicked
6923    _checkIfClose: function(target) {
6924
6925        if($(target).hasClass(PREVENT_CLOSE_CLASS)) {
6926            return;
6927        }
6928
6929        var closeOnContent = mfp.st.closeOnContentClick;
6930        var closeOnBg = mfp.st.closeOnBgClick;
6931
6932        if(closeOnContent && closeOnBg) {
6933            return true;
6934        } else {
6935
6936            // We close the popup if click is on close button or on preloader. Or if there is no content.
6937            if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) {
6938                return true;
6939            }
6940
6941            // if click is outside the content
6942            if(  (target !== mfp.content[0] && !$.contains(mfp.content[0], target))  ) {
6943                if(closeOnBg) {
6944                    // last check, if the clicked element is in DOM, (in case it's removed onclick)
6945                    if( $.contains(document, target) ) {
6946                        return true;
6947                    }
6948                }
6949            } else if(closeOnContent) {
6950                return true;
6951            }
6952
6953        }
6954        return false;
6955    },
6956    _addClassToMFP: function(cName) {
6957        mfp.bgOverlay.addClass(cName);
6958        mfp.wrap.addClass(cName);
6959    },
6960    _removeClassFromMFP: function(cName) {
6961        this.bgOverlay.removeClass(cName);
6962        mfp.wrap.removeClass(cName);
6963    },
6964    _hasScrollBar: function(winHeight) {
6965        return (  (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) );
6966    },
6967    _setFocus: function() {
6968        (mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus();
6969    },
6970    _onFocusIn: function(e) {
6971        if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) {
6972            mfp._setFocus();
6973            return false;
6974        }
6975    },
6976    _parseMarkup: function(template, values, item) {
6977        var arr;
6978        if(item.data) {
6979            values = $.extend(item.data, values);
6980        }
6981        _mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] );
6982
6983        $.each(values, function(key, value) {
6984            if(value === undefined || value === false) {
6985                return true;
6986            }
6987            arr = key.split('_');
6988            if(arr.length > 1) {
6989                var el = template.find(EVENT_NS + '-'+arr[0]);
6990
6991                if(el.length > 0) {
6992                    var attr = arr[1];
6993                    if(attr === 'replaceWith') {
6994                        if(el[0] !== value[0]) {
6995                            el.replaceWith(value);
6996                        }
6997                    } else if(attr === 'img') {
6998                        if(el.is('img')) {
6999                            el.attr('src', value);
7000                        } else {
7001                            el.replaceWith( $('<img>').attr('src', value).attr('class', el.attr('class')) );
7002                        }
7003                    } else {
7004                        el.attr(arr[1], value);
7005                    }
7006                }
7007
7008            } else {
7009                template.find(EVENT_NS + '-'+key).html(value);
7010            }
7011        });
7012    },
7013
7014    _getScrollbarSize: function() {
7015        // thx David
7016        if(mfp.scrollbarSize === undefined) {
7017            var scrollDiv = document.createElement("div");
7018            scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';
7019            document.body.appendChild(scrollDiv);
7020            mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;
7021            document.body.removeChild(scrollDiv);
7022        }
7023        return mfp.scrollbarSize;
7024    }
7025
7026}; /* MagnificPopup core prototype end */
7027
7028
7029
7030
7031/**
7032 * Public static functions
7033 */
7034$.magnificPopup = {
7035    instance: null,
7036    proto: MagnificPopup.prototype,
7037    modules: [],
7038
7039    open: function(options, index) {
7040        _checkInstance();
7041
7042        if(!options) {
7043            options = {};
7044        } else {
7045            options = $.extend(true, {}, options);
7046        }
7047
7048        options.isObj = true;
7049        options.index = index || 0;
7050        return this.instance.open(options);
7051    },
7052
7053    close: function() {
7054        return $.magnificPopup.instance && $.magnificPopup.instance.close();
7055    },
7056
7057    registerModule: function(name, module) {
7058        if(module.options) {
7059            $.magnificPopup.defaults[name] = module.options;
7060        }
7061        $.extend(this.proto, module.proto);
7062        this.modules.push(name);
7063    },
7064
7065    defaults: {
7066
7067        // Info about options is in docs:
7068        // http://dimsemenov.com/plugins/magnific-popup/documentation.html#options
7069
7070        disableOn: 0,
7071
7072        key: null,
7073
7074        midClick: false,
7075
7076        mainClass: '',
7077
7078        preloader: true,
7079
7080        focus: '', // CSS selector of input to focus after popup is opened
7081
7082        closeOnContentClick: false,
7083
7084        closeOnBgClick: true,
7085
7086        closeBtnInside: true,
7087
7088        showCloseBtn: true,
7089
7090        enableEscapeKey: true,
7091
7092        modal: false,
7093
7094        alignTop: false,
7095
7096        removalDelay: 0,
7097
7098        prependTo: null,
7099
7100        fixedContentPos: 'auto',
7101
7102        fixedBgPos: 'auto',
7103
7104        overflowY: 'auto',
7105
7106        closeMarkup: '<button title="%title%" type="button" class="mfp-close">&#215;</button>',
7107
7108        tClose: 'Close (Esc)',
7109
7110        tLoading: 'Loading...',
7111
7112        autoFocusLast: true
7113
7114    }
7115};
7116
7117
7118
7119$.fn.magnificPopup = function(options) {
7120    _checkInstance();
7121
7122    var jqEl = $(this);
7123
7124    // We call some API method of first param is a string
7125    if (typeof options === "string" ) {
7126
7127        if(options === 'open') {
7128            var items,
7129                itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup,
7130                index = parseInt(arguments[1], 10) || 0;
7131
7132            if(itemOpts.items) {
7133                items = itemOpts.items[index];
7134            } else {
7135                items = jqEl;
7136                if(itemOpts.delegate) {
7137                    items = items.find(itemOpts.delegate);
7138                }
7139                items = items.eq( index );
7140            }
7141            mfp._openClick({mfpEl:items}, jqEl, itemOpts);
7142        } else {
7143            if(mfp.isOpen)
7144                mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1));
7145        }
7146
7147    } else {
7148        // clone options obj
7149        options = $.extend(true, {}, options);
7150
7151        /*
7152         * As Zepto doesn't support .data() method for objects
7153         * and it works only in normal browsers
7154         * we assign "options" object directly to the DOM element. FTW!
7155         */
7156        if(_isJQ) {
7157            jqEl.data('magnificPopup', options);
7158        } else {
7159            jqEl[0].magnificPopup = options;
7160        }
7161
7162        mfp.addGroup(jqEl, options);
7163
7164    }
7165    return jqEl;
7166};
7167
7168/*>>core*/
7169
7170/*>>inline*/
7171
7172var INLINE_NS = 'inline',
7173    _hiddenClass,
7174    _inlinePlaceholder,
7175    _lastInlineElement,
7176    _putInlineElementsBack = function() {
7177        if(_lastInlineElement) {
7178            _inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach();
7179            _lastInlineElement = null;
7180        }
7181    };
7182
7183$.magnificPopup.registerModule(INLINE_NS, {
7184    options: {
7185        hiddenClass: 'hide', // will be appended with `mfp-` prefix
7186        markup: '',
7187        tNotFound: 'Content not found'
7188    },
7189    proto: {
7190
7191        initInline: function() {
7192            mfp.types.push(INLINE_NS);
7193
7194            _mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() {
7195                _putInlineElementsBack();
7196            });
7197        },
7198
7199        getInline: function(item, template) {
7200
7201            _putInlineElementsBack();
7202
7203            if(item.src) {
7204                var inlineSt = mfp.st.inline,
7205                    el = $(item.src);
7206
7207                if(el.length) {
7208
7209                    // If target element has parent - we replace it with placeholder and put it back after popup is closed
7210                    var parent = el[0].parentNode;
7211                    if(parent && parent.tagName) {
7212                        if(!_inlinePlaceholder) {
7213                            _hiddenClass = inlineSt.hiddenClass;
7214                            _inlinePlaceholder = _getEl(_hiddenClass);
7215                            _hiddenClass = 'mfp-'+_hiddenClass;
7216                        }
7217                        // replace target inline element with placeholder
7218                        _lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass);
7219                    }
7220
7221                    mfp.updateStatus('ready');
7222                } else {
7223                    mfp.updateStatus('error', inlineSt.tNotFound);
7224                    el = $('<div>');
7225                }
7226
7227                item.inlineElement = el;
7228                return el;
7229            }
7230
7231            mfp.updateStatus('ready');
7232            mfp._parseMarkup(template, {}, item);
7233            return template;
7234        }
7235    }
7236});
7237
7238/*>>inline*/
7239
7240/*>>ajax*/
7241var AJAX_NS = 'ajax',
7242    _ajaxCur,
7243    _removeAjaxCursor = function() {
7244        if(_ajaxCur) {
7245            $(document.body).removeClass(_ajaxCur);
7246        }
7247    },
7248    _destroyAjaxRequest = function() {
7249        _removeAjaxCursor();
7250        if(mfp.req) {
7251            mfp.req.abort();
7252        }
7253    };
7254
7255$.magnificPopup.registerModule(AJAX_NS, {
7256
7257    options: {
7258        settings: null,
7259        cursor: 'mfp-ajax-cur',
7260        tError: '<a href="%url%">The content</a> could not be loaded.'
7261    },
7262
7263    proto: {
7264        initAjax: function() {
7265            mfp.types.push(AJAX_NS);
7266            _ajaxCur = mfp.st.ajax.cursor;
7267
7268            _mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest);
7269            _mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest);
7270        },
7271        getAjax: function(item) {
7272
7273            if(_ajaxCur) {
7274                $(document.body).addClass(_ajaxCur);
7275            }
7276
7277            mfp.updateStatus('loading');
7278
7279            var opts = $.extend({
7280                url: item.src,
7281                success: function(data, textStatus, jqXHR) {
7282                    var temp = {
7283                        data:data,
7284                        xhr:jqXHR
7285                    };
7286
7287                    _mfpTrigger('ParseAjax', temp);
7288
7289                    mfp.appendContent( $(temp.data), AJAX_NS );
7290
7291                    item.finished = true;
7292
7293                    _removeAjaxCursor();
7294
7295                    mfp._setFocus();
7296
7297                    setTimeout(function() {
7298                        mfp.wrap.addClass(READY_CLASS);
7299                    }, 16);
7300
7301                    mfp.updateStatus('ready');
7302
7303                    _mfpTrigger('AjaxContentAdded');
7304                },
7305                error: function() {
7306                    _removeAjaxCursor();
7307                    item.finished = item.loadError = true;
7308                    mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src));
7309                }
7310            }, mfp.st.ajax.settings);
7311
7312            mfp.req = $.ajax(opts);
7313
7314            return '';
7315        }
7316    }
7317});
7318
7319/*>>ajax*/
7320
7321/*>>image*/
7322var _imgInterval,
7323    _getTitle = function(item) {
7324        if(item.data && item.data.title !== undefined)
7325            return item.data.title;
7326
7327        var src = mfp.st.image.titleSrc;
7328
7329        if(src) {
7330            if($.isFunction(src)) {
7331                return src.call(mfp, item);
7332            } else if(item.el) {
7333                return item.el.attr(src) || '';
7334            }
7335        }
7336        return '';
7337    };
7338
7339$.magnificPopup.registerModule('image', {
7340
7341    options: {
7342        markup: '<div class="mfp-figure">'+
7343                    '<div class="mfp-close"></div>'+
7344                    '<figure>'+
7345                        '<div class="mfp-img"></div>'+
7346                        '<figcaption>'+
7347                            '<div class="mfp-bottom-bar">'+
7348                                '<div class="mfp-title"></div>'+
7349                                '<div class="mfp-counter"></div>'+
7350                            '</div>'+
7351                        '</figcaption>'+
7352                    '</figure>'+
7353                '</div>',
7354        cursor: 'mfp-zoom-out-cur',
7355        titleSrc: 'title',
7356        verticalFit: true,
7357        tError: '<a href="%url%">The image</a> could not be loaded.'
7358    },
7359
7360    proto: {
7361        initImage: function() {
7362            var imgSt = mfp.st.image,
7363                ns = '.image';
7364
7365            mfp.types.push('image');
7366
7367            _mfpOn(OPEN_EVENT+ns, function() {
7368                if(mfp.currItem.type === 'image' && imgSt.cursor) {
7369                    $(document.body).addClass(imgSt.cursor);
7370                }
7371            });
7372
7373            _mfpOn(CLOSE_EVENT+ns, function() {
7374                if(imgSt.cursor) {
7375                    $(document.body).removeClass(imgSt.cursor);
7376                }
7377                _window.off('resize' + EVENT_NS);
7378            });
7379
7380            _mfpOn('Resize'+ns, mfp.resizeImage);
7381            if(mfp.isLowIE) {
7382                _mfpOn('AfterChange', mfp.resizeImage);
7383            }
7384        },
7385        resizeImage: function() {
7386            var item = mfp.currItem;
7387            if(!item || !item.img) return;
7388
7389            if(mfp.st.image.verticalFit) {
7390                var decr = 0;
7391                // fix box-sizing in ie7/8
7392                if(mfp.isLowIE) {
7393                    decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10);
7394                }
7395                item.img.css('max-height', mfp.wH-decr);
7396            }
7397        },
7398        _onImageHasSize: function(item) {
7399            if(item.img) {
7400
7401                item.hasSize = true;
7402
7403                if(_imgInterval) {
7404                    clearInterval(_imgInterval);
7405                }
7406
7407                item.isCheckingImgSize = false;
7408
7409                _mfpTrigger('ImageHasSize', item);
7410
7411                if(item.imgHidden) {
7412                    if(mfp.content)
7413                        mfp.content.removeClass('mfp-loading');
7414
7415                    item.imgHidden = false;
7416                }
7417
7418            }
7419        },
7420
7421        /**
7422         * Function that loops until the image has size to display elements that rely on it asap
7423         */
7424        findImageSize: function(item) {
7425
7426            var counter = 0,
7427                img = item.img[0],
7428                mfpSetInterval = function(delay) {
7429
7430                    if(_imgInterval) {
7431                        clearInterval(_imgInterval);
7432                    }
7433                    // decelerating interval that checks for size of an image
7434                    _imgInterval = setInterval(function() {
7435                        if(img.naturalWidth > 0) {
7436                            mfp._onImageHasSize(item);
7437                            return;
7438                        }
7439
7440                        if(counter > 200) {
7441                            clearInterval(_imgInterval);
7442                        }
7443
7444                        counter++;
7445                        if(counter === 3) {
7446                            mfpSetInterval(10);
7447                        } else if(counter === 40) {
7448                            mfpSetInterval(50);
7449                        } else if(counter === 100) {
7450                            mfpSetInterval(500);
7451                        }
7452                    }, delay);
7453                };
7454
7455            mfpSetInterval(1);
7456        },
7457
7458        getImage: function(item, template) {
7459
7460            var guard = 0,
7461
7462                // image load complete handler
7463                onLoadComplete = function() {
7464                    if(item) {
7465                        if (item.img[0].complete) {
7466                            item.img.off('.mfploader');
7467
7468                            if(item === mfp.currItem){
7469                                mfp._onImageHasSize(item);
7470
7471                                mfp.updateStatus('ready');
7472                            }
7473
7474                            item.hasSize = true;
7475                            item.loaded = true;
7476
7477                            _mfpTrigger('ImageLoadComplete');
7478
7479                        }
7480                        else {
7481                            // if image complete check fails 200 times (20 sec), we assume that there was an error.
7482                            guard++;
7483                            if(guard < 200) {
7484                                setTimeout(onLoadComplete,100);
7485                            } else {
7486                                onLoadError();
7487                            }
7488                        }
7489                    }
7490                },
7491
7492                // image error handler
7493                onLoadError = function() {
7494                    if(item) {
7495                        item.img.off('.mfploader');
7496                        if(item === mfp.currItem){
7497                            mfp._onImageHasSize(item);
7498                            mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
7499                        }
7500
7501                        item.hasSize = true;
7502                        item.loaded = true;
7503                        item.loadError = true;
7504                    }
7505                },
7506                imgSt = mfp.st.image;
7507
7508
7509            var el = template.find('.mfp-img');
7510            if(el.length) {
7511                var img = document.createElement('img');
7512                img.className = 'mfp-img';
7513                if(item.el && item.el.find('img').length) {
7514                    img.alt = item.el.find('img').attr('alt');
7515                }
7516                item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError);
7517                img.src = item.src;
7518
7519                // without clone() "error" event is not firing when IMG is replaced by new IMG
7520                // TODO: find a way to avoid such cloning
7521                if(el.is('img')) {
7522                    item.img = item.img.clone();
7523                }
7524
7525                img = item.img[0];
7526                if(img.naturalWidth > 0) {
7527                    item.hasSize = true;
7528                } else if(!img.width) {
7529                    item.hasSize = false;
7530                }
7531            }
7532
7533            mfp._parseMarkup(template, {
7534                title: _getTitle(item),
7535                img_replaceWith: item.img
7536            }, item);
7537
7538            mfp.resizeImage();
7539
7540            if(item.hasSize) {
7541                if(_imgInterval) clearInterval(_imgInterval);
7542
7543                if(item.loadError) {
7544                    template.addClass('mfp-loading');
7545                    mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
7546                } else {
7547                    template.removeClass('mfp-loading');
7548                    mfp.updateStatus('ready');
7549                }
7550                return template;
7551            }
7552
7553            mfp.updateStatus('loading');
7554            item.loading = true;
7555
7556            if(!item.hasSize) {
7557                item.imgHidden = true;
7558                template.addClass('mfp-loading');
7559                mfp.findImageSize(item);
7560            }
7561
7562            return template;
7563        }
7564    }
7565});
7566
7567/*>>image*/
7568
7569/*>>zoom*/
7570var hasMozTransform,
7571    getHasMozTransform = function() {
7572        if(hasMozTransform === undefined) {
7573            hasMozTransform = document.createElement('p').style.MozTransform !== undefined;
7574        }
7575        return hasMozTransform;
7576    };
7577
7578$.magnificPopup.registerModule('zoom', {
7579
7580    options: {
7581        enabled: false,
7582        easing: 'ease-in-out',
7583        duration: 300,
7584        opener: function(element) {
7585            return element.is('img') ? element : element.find('img');
7586        }
7587    },
7588
7589    proto: {
7590
7591        initZoom: function() {
7592            var zoomSt = mfp.st.zoom,
7593                ns = '.zoom',
7594                image;
7595
7596            if(!zoomSt.enabled || !mfp.supportsTransition) {
7597                return;
7598            }
7599
7600            var duration = zoomSt.duration,
7601                getElToAnimate = function(image) {
7602                    var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'),
7603                        transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing,
7604                        cssObj = {
7605                            position: 'fixed',
7606                            zIndex: 9999,
7607                            left: 0,
7608                            top: 0,
7609                            '-webkit-backface-visibility': 'hidden'
7610                        },
7611                        t = 'transition';
7612
7613                    cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition;
7614
7615                    newImg.css(cssObj);
7616                    return newImg;
7617                },
7618                showMainContent = function() {
7619                    mfp.content.css('visibility', 'visible');
7620                },
7621                openTimeout,
7622                animatedImg;
7623
7624            _mfpOn('BuildControls'+ns, function() {
7625                if(mfp._allowZoom()) {
7626
7627                    clearTimeout(openTimeout);
7628                    mfp.content.css('visibility', 'hidden');
7629
7630                    // Basically, all code below does is clones existing image, puts in on top of the current one and animated it
7631
7632                    image = mfp._getItemToZoom();
7633
7634                    if(!image) {
7635                        showMainContent();
7636                        return;
7637                    }
7638
7639                    animatedImg = getElToAnimate(image);
7640
7641                    animatedImg.css( mfp._getOffset() );
7642
7643                    mfp.wrap.append(animatedImg);
7644
7645                    openTimeout = setTimeout(function() {
7646                        animatedImg.css( mfp._getOffset( true ) );
7647                        openTimeout = setTimeout(function() {
7648
7649                            showMainContent();
7650
7651                            setTimeout(function() {
7652                                animatedImg.remove();
7653                                image = animatedImg = null;
7654                                _mfpTrigger('ZoomAnimationEnded');
7655                            }, 16); // avoid blink when switching images
7656
7657                        }, duration); // this timeout equals animation duration
7658
7659                    }, 16); // by adding this timeout we avoid short glitch at the beginning of animation
7660
7661
7662                    // Lots of timeouts...
7663                }
7664            });
7665            _mfpOn(BEFORE_CLOSE_EVENT+ns, function() {
7666                if(mfp._allowZoom()) {
7667
7668                    clearTimeout(openTimeout);
7669
7670                    mfp.st.removalDelay = duration;
7671
7672                    if(!image) {
7673                        image = mfp._getItemToZoom();
7674                        if(!image) {
7675                            return;
7676                        }
7677                        animatedImg = getElToAnimate(image);
7678                    }
7679
7680                    animatedImg.css( mfp._getOffset(true) );
7681                    mfp.wrap.append(animatedImg);
7682                    mfp.content.css('visibility', 'hidden');
7683
7684                    setTimeout(function() {
7685                        animatedImg.css( mfp._getOffset() );
7686                    }, 16);
7687                }
7688
7689            });
7690
7691            _mfpOn(CLOSE_EVENT+ns, function() {
7692                if(mfp._allowZoom()) {
7693                    showMainContent();
7694                    if(animatedImg) {
7695                        animatedImg.remove();
7696                    }
7697                    image = null;
7698                }
7699            });
7700        },
7701
7702        _allowZoom: function() {
7703            return mfp.currItem.type === 'image';
7704        },
7705
7706        _getItemToZoom: function() {
7707            if(mfp.currItem.hasSize) {
7708                return mfp.currItem.img;
7709            } else {
7710                return false;
7711            }
7712        },
7713
7714        // Get element postion relative to viewport
7715        _getOffset: function(isLarge) {
7716            var el;
7717            if(isLarge) {
7718                el = mfp.currItem.img;
7719            } else {
7720                el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem);
7721            }
7722
7723            var offset = el.offset();
7724            var paddingTop = parseInt(el.css('padding-top'),10);
7725            var paddingBottom = parseInt(el.css('padding-bottom'),10);
7726            offset.top -= ( $(window).scrollTop() - paddingTop );
7727
7728
7729            /*
7730
7731            Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa.
7732
7733             */
7734            var obj = {
7735                width: el.width(),
7736                // fix Zepto height+padding issue
7737                height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop
7738            };
7739
7740            // I hate to do this, but there is no another option
7741            if( getHasMozTransform() ) {
7742                obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)';
7743            } else {
7744                obj.left = offset.left;
7745                obj.top = offset.top;
7746            }
7747            return obj;
7748        }
7749
7750    }
7751});
7752
7753
7754
7755/*>>zoom*/
7756
7757/*>>iframe*/
7758
7759var IFRAME_NS = 'iframe',
7760    _emptyPage = '//about:blank',
7761
7762    _fixIframeBugs = function(isShowing) {
7763        if(mfp.currTemplate[IFRAME_NS]) {
7764            var el = mfp.currTemplate[IFRAME_NS].find('iframe');
7765            if(el.length) {
7766                // reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug
7767                if(!isShowing) {
7768                    el[0].src = _emptyPage;
7769                }
7770
7771                // IE8 black screen bug fix
7772                if(mfp.isIE8) {
7773                    el.css('display', isShowing ? 'block' : 'none');
7774                }
7775            }
7776        }
7777    };
7778
7779$.magnificPopup.registerModule(IFRAME_NS, {
7780
7781    options: {
7782        markup: '<div class="mfp-iframe-scaler">'+
7783                    '<div class="mfp-close"></div>'+
7784                    '<iframe class="mfp-iframe ytifra" src="//about:blank" frameborder="0" allowfullscreen allow="accelerometer; autoplay; clipboard-write; encrypted-media;"></iframe>'+
7785                '</div>',
7786
7787        srcAction: 'iframe_src',
7788
7789
7790        // we don't care and support only one default type of URL by default
7791        patterns: {
7792            youtube: {
7793                index: 'youtube-nocookie.com',
7794                id: 'v=',
7795                src: '//www.youtube-nocookie.com/embed/%id%?autoplay=1&modestbranding=1&playsinline=1&rel=0&showinfo=0'
7796            },
7797
7798            vimeo: {
7799                index: 'vimeo.com/',
7800                id: '/',
7801                src: '//player.vimeo.com/video/%id%?autoplay=1'
7802            },
7803            gmaps: {
7804                index: '//maps.google.',
7805                src: '%id%&output=embed'
7806            }
7807        }
7808    },
7809
7810    proto: {
7811        initIframe: function() {
7812            mfp.types.push(IFRAME_NS);
7813          //  console.log("initiframe")
7814          //  console.log(mfp)
7815            _mfpOn('BeforeChange', function(e, prevType, newType) {
7816                if(prevType !== newType) {
7817                    if(prevType === IFRAME_NS) {
7818                        _fixIframeBugs(); // iframe if removed
7819                    } else if(newType === IFRAME_NS) {
7820                        _fixIframeBugs(true); // iframe is showing
7821                    }
7822                }// else {
7823                    // iframe source is switched, don't do anything
7824                //}
7825            });
7826
7827            _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
7828                _fixIframeBugs();
7829            });
7830        },
7831
7832        getIframe: function(item, template) {
7833            // console.log("ITEM",item);
7834          //   console.log("MFP",mfp);
7835            var embedSrc = item.src;
7836            var iframeSt = mfp.st.iframe;
7837
7838            $.each(iframeSt.patterns, function() {
7839                if(embedSrc.indexOf( this.index ) > -1) {
7840                    if(this.id) {
7841                        if(typeof this.id === 'string') {
7842                            embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
7843                        } else {
7844                            embedSrc = this.id.call( this, embedSrc );
7845                        }
7846                    }
7847                    embedSrc = this.src.replace('%id%', embedSrc );
7848                    console.log("embedSrc", embedSrc);
7849                    return false; // break;
7850                }
7851            });
7852
7853            var dataObj = {};
7854            if(iframeSt.srcAction) {
7855                dataObj[iframeSt.srcAction] = embedSrc;
7856            }
7857            mfp._parseMarkup(template, dataObj, item);
7858
7859            mfp.updateStatus('ready');
7860          //  console.log(template);
7861           // console.log(dataObj);
7862          //  console.log(item);
7863
7864            return template;
7865        }
7866    }
7867});
7868
7869
7870
7871/*>>iframe*/
7872
7873/*>>gallery*/
7874/**
7875 * Get looped index depending on number of slides
7876 */
7877var _getLoopedId = function(index) {
7878        var numSlides = mfp.items.length;
7879        if(index > numSlides - 1) {
7880            return index - numSlides;
7881        } else  if(index < 0) {
7882            return numSlides + index;
7883        }
7884        return index;
7885    },
7886    _replaceCurrTotal = function(text, curr, total) {
7887        return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total);
7888    };
7889
7890$.magnificPopup.registerModule('gallery', {
7891
7892    options: {
7893        enabled: false,
7894        arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
7895        preload: [0,2],
7896        navigateByImgClick: true,
7897        arrows: true,
7898
7899        tPrev: 'Previous (Left arrow key)',
7900        tNext: 'Next (Right arrow key)',
7901        tCounter: '%curr% of %total%'
7902    },
7903
7904    proto: {
7905        initGallery: function() {
7906
7907            var gSt = mfp.st.gallery,
7908                ns = '.mfp-gallery';
7909
7910            mfp.direction = true; // true - next, false - prev
7911
7912            if(!gSt || !gSt.enabled ) return false;
7913
7914            _wrapClasses += ' mfp-gallery';
7915
7916            _mfpOn(OPEN_EVENT+ns, function() {
7917
7918                if(gSt.navigateByImgClick) {
7919                    mfp.wrap.on('click'+ns, '.mfp-img', function() {
7920                        if(mfp.items.length > 1) {
7921                            mfp.next();
7922                            return false;
7923                        }
7924                    });
7925                }
7926
7927                _document.on('keydown'+ns, function(e) {
7928                    if (e.keyCode === 37) {
7929                        mfp.prev();
7930                    } else if (e.keyCode === 39) {
7931                        mfp.next();
7932                    }
7933                });
7934            });
7935
7936            _mfpOn('UpdateStatus'+ns, function(e, data) {
7937                if(data.text) {
7938                    data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length);
7939                }
7940            });
7941
7942            _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) {
7943                var l = mfp.items.length;
7944                values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : '';
7945            });
7946
7947            _mfpOn('BuildControls' + ns, function() {
7948                if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) {
7949                    var markup = gSt.arrowMarkup,
7950                        arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS),
7951                        arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS);
7952
7953                    arrowLeft.click(function() {
7954                        mfp.prev();
7955                    });
7956                    arrowRight.click(function() {
7957                        mfp.next();
7958                    });
7959
7960                    mfp.container.append(arrowLeft.add(arrowRight));
7961                }
7962            });
7963
7964            _mfpOn(CHANGE_EVENT+ns, function() {
7965                if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout);
7966
7967                mfp._preloadTimeout = setTimeout(function() {
7968                    mfp.preloadNearbyImages();
7969                    mfp._preloadTimeout = null;
7970                }, 16);
7971            });
7972
7973
7974            _mfpOn(CLOSE_EVENT+ns, function() {
7975                _document.off(ns);
7976                mfp.wrap.off('click'+ns);
7977                mfp.arrowRight = mfp.arrowLeft = null;
7978            });
7979
7980        },
7981        next: function() {
7982            mfp.direction = true;
7983            mfp.index = _getLoopedId(mfp.index + 1);
7984            mfp.updateItemHTML();
7985        },
7986        prev: function() {
7987            mfp.direction = false;
7988            mfp.index = _getLoopedId(mfp.index - 1);
7989            mfp.updateItemHTML();
7990        },
7991        goTo: function(newIndex) {
7992            mfp.direction = (newIndex >= mfp.index);
7993            mfp.index = newIndex;
7994            mfp.updateItemHTML();
7995        },
7996        preloadNearbyImages: function() {
7997            var p = mfp.st.gallery.preload,
7998                preloadBefore = Math.min(p[0], mfp.items.length),
7999                preloadAfter = Math.min(p[1], mfp.items.length),
8000                i;
8001
8002            for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) {
8003                mfp._preloadItem(mfp.index+i);
8004            }
8005            for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) {
8006                mfp._preloadItem(mfp.index-i);
8007            }
8008        },
8009        _preloadItem: function(index) {
8010            index = _getLoopedId(index);
8011
8012            if(mfp.items[index].preloaded) {
8013                return;
8014            }
8015
8016            var item = mfp.items[index];
8017            if(!item.parsed) {
8018                item = mfp.parseEl( index );
8019            }
8020
8021            _mfpTrigger('LazyLoad', item);
8022
8023            if(item.type === 'image') {
8024                item.img = $('<img class="mfp-img" />').on('load.mfploader', function() {
8025                    item.hasSize = true;
8026                }).on('error.mfploader', function() {
8027                    item.hasSize = true;
8028                    item.loadError = true;
8029                    _mfpTrigger('LazyLoadError', item);
8030                }).attr('src', item.src);
8031            }
8032
8033
8034            item.preloaded = true;
8035        }
8036    }
8037});
8038
8039/*>>gallery*/
8040
8041/*>>retina*/
8042
8043var RETINA_NS = 'retina';
8044
8045$.magnificPopup.registerModule(RETINA_NS, {
8046    options: {
8047        replaceSrc: function(item) {
8048            return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; });
8049        },
8050        ratio: 1 // Function or number.  Set to 1 to disable.
8051    },
8052    proto: {
8053        initRetina: function() {
8054            if(window.devicePixelRatio > 1) {
8055
8056                var st = mfp.st.retina,
8057                    ratio = st.ratio;
8058
8059                ratio = !isNaN(ratio) ? ratio : ratio();
8060
8061                if(ratio > 1) {
8062                    _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) {
8063                        item.img.css({
8064                            'max-width': item.img[0].naturalWidth / ratio,
8065                            'width': '100%'
8066                        });
8067                    });
8068                    _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) {
8069                        item.src = st.replaceSrc(item, ratio);
8070                    });
8071                }
8072            }
8073
8074        }
8075    }
8076});
8077
8078/*>>retina*/
8079 _checkInstance(); }));
vendor: 95,083 bytes, lines 8080-11486
8080/*!
8081 * Flickity PACKAGED v3.0.0
8082 * Touch, responsive, flickable carousels
8083 *
8084 * Licensed GPLv3 for open source use
8085 * or Flickity Commercial License for commercial use
8086 *
8087 * https://flickity.metafizzy.co
8088 * Copyright 2015-2022 Metafizzy
8089 */
8090
8091/**
8092 * Bridget makes jQuery widgets
8093 * v3.0.1
8094 * MIT license
8095 */
8096
8097( function( window, factory ) {
8098  // module definition
8099 if ( typeof module == 'object' && module.exports ) {
8100   // CommonJS
8101   module.exports = factory(
8102       window,
8103       require('jquery'),
8104   );
8105 } else {
8106   // browser global
8107   window.jQueryBridget = factory(
8108       window,
8109       window.jQuery,
8110   );
8111 }
8112
8113}( window, function factory( window, jQuery ) {
8114
8115// ----- utils ----- //
8116
8117// helper function for logging errors
8118// $.error breaks jQuery chaining
8119let console = window.console;
8120let logError = typeof console == 'undefined' ? function() {} :
8121  function( message ) {
8122    console.error( message );
8123  };
8124
8125// ----- jQueryBridget ----- //
8126
8127function jQueryBridget( namespace, PluginClass, $ ) {
8128  $ = $ || jQuery || window.jQuery;
8129  if ( !$ ) {
8130    return;
8131  }
8132
8133  // add option method -> $().plugin('option', {...})
8134  if ( !PluginClass.prototype.option ) {
8135    // option setter
8136    PluginClass.prototype.option = function( opts ) {
8137      if ( !opts ) return;
8138
8139      this.options = Object.assign( this.options || {}, opts );
8140    };
8141  }
8142
8143  // make jQuery plugin
8144  $.fn[ namespace ] = function( arg0, ...args ) {
8145    if ( typeof arg0 == 'string' ) {
8146      // method call $().plugin( 'methodName', { options } )
8147      return methodCall( this, arg0, args );
8148    }
8149    // just $().plugin({ options })
8150    plainCall( this, arg0 );
8151    return this;
8152  };
8153
8154  // $().plugin('methodName')
8155  function methodCall( $elems, methodName, args ) {
8156    let returnValue;
8157    let pluginMethodStr = `$().${namespace}("${methodName}")`;
8158
8159    $elems.each( function( i, elem ) {
8160      // get instance
8161      let instance = $.data( elem, namespace );
8162      if ( !instance ) {
8163        logError( `${namespace} not initialized.` +
8164          ` Cannot call method ${pluginMethodStr}` );
8165        return;
8166      }
8167
8168      let method = instance[ methodName ];
8169      if ( !method || methodName.charAt( 0 ) == '_' ) {
8170        logError(`${pluginMethodStr} is not a valid method`);
8171        return;
8172      }
8173
8174      // apply method, get return value
8175      let value = method.apply( instance, args );
8176      // set return value if value is returned, use only first value
8177      returnValue = returnValue === undefined ? value : returnValue;
8178    } );
8179
8180    return returnValue !== undefined ? returnValue : $elems;
8181  }
8182
8183  function plainCall( $elems, options ) {
8184    $elems.each( function( i, elem ) {
8185      let instance = $.data( elem, namespace );
8186      if ( instance ) {
8187        // set options & init
8188        instance.option( options );
8189        instance._init();
8190      } else {
8191        // initialize new instance
8192        instance = new PluginClass( elem, options );
8193        $.data( elem, namespace, instance );
8194      }
8195    } );
8196  }
8197
8198}
8199
8200// -----  ----- //
8201
8202return jQueryBridget;
8203
8204} ) );
8205/**
8206 * EvEmitter v2.1.1
8207 * Lil' event emitter
8208 * MIT License
8209 */
8210
8211( function( global, factory ) {
8212  // universal module definition
8213  if ( typeof module == 'object' && module.exports ) {
8214    // CommonJS - Browserify, Webpack
8215    module.exports = factory();
8216  } else {
8217    // Browser globals
8218    global.EvEmitter = factory();
8219  }
8220
8221}( typeof window != 'undefined' ? window : this, function() {
8222
8223function EvEmitter() {}
8224
8225let proto = EvEmitter.prototype;
8226
8227proto.on = function( eventName, listener ) {
8228  if ( !eventName || !listener ) return this;
8229
8230  // set events hash
8231  let events = this._events = this._events || {};
8232  // set listeners array
8233  let listeners = events[ eventName ] = events[ eventName ] || [];
8234  // only add once
8235  if ( !listeners.includes( listener ) ) {
8236    listeners.push( listener );
8237  }
8238
8239  return this;
8240};
8241
8242proto.once = function( eventName, listener ) {
8243  if ( !eventName || !listener ) return this;
8244
8245  // add event
8246  this.on( eventName, listener );
8247  // set once flag
8248  // set onceEvents hash
8249  let onceEvents = this._onceEvents = this._onceEvents || {};
8250  // set onceListeners object
8251  let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
8252  // set flag
8253  onceListeners[ listener ] = true;
8254
8255  return this;
8256};
8257
8258proto.off = function( eventName, listener ) {
8259  let listeners = this._events && this._events[ eventName ];
8260  if ( !listeners || !listeners.length ) return this;
8261
8262  let index = listeners.indexOf( listener );
8263  if ( index != -1 ) {
8264    listeners.splice( index, 1 );
8265  }
8266
8267  return this;
8268};
8269
8270proto.emitEvent = function( eventName, args ) {
8271  let listeners = this._events && this._events[ eventName ];
8272  if ( !listeners || !listeners.length ) return this;
8273
8274  // copy over to avoid interference if .off() in listener
8275  listeners = listeners.slice( 0 );
8276  args = args || [];
8277  // once stuff
8278  let onceListeners = this._onceEvents && this._onceEvents[ eventName ];
8279
8280  for ( let listener of listeners ) {
8281    let isOnce = onceListeners && onceListeners[ listener ];
8282    if ( isOnce ) {
8283      // remove listener
8284      // remove before trigger to prevent recursion
8285      this.off( eventName, listener );
8286      // unset once flag
8287      delete onceListeners[ listener ];
8288    }
8289    // trigger listener
8290    listener.apply( this, args );
8291  }
8292
8293  return this;
8294};
8295
8296proto.allOff = function() {
8297  delete this._events;
8298  delete this._onceEvents;
8299  return this;
8300};
8301
8302return EvEmitter;
8303
8304} ) );
8305/*!
8306 * Infinite Scroll v2.0.4
8307 * measure size of elements
8308 * MIT license
8309 */
8310
8311( function( window, factory ) {
8312  if ( typeof module == 'object' && module.exports ) {
8313    // CommonJS
8314    module.exports = factory();
8315  } else {
8316    // browser global
8317    window.getSize = factory();
8318  }
8319
8320} )( window, function factory() {
8321
8322// -------------------------- helpers -------------------------- //
8323
8324// get a number from a string, not a percentage
8325function getStyleSize( value ) {
8326  let num = parseFloat( value );
8327  // not a percent like '100%', and a number
8328  let isValid = value.indexOf('%') == -1 && !isNaN( num );
8329  return isValid && num;
8330}
8331
8332// -------------------------- measurements -------------------------- //
8333
8334let measurements = [
8335  'paddingLeft',
8336  'paddingRight',
8337  'paddingTop',
8338  'paddingBottom',
8339  'marginLeft',
8340  'marginRight',
8341  'marginTop',
8342  'marginBottom',
8343  'borderLeftWidth',
8344  'borderRightWidth',
8345  'borderTopWidth',
8346  'borderBottomWidth',
8347];
8348
8349let measurementsLength = measurements.length;
8350
8351function getZeroSize() {
8352  let size = {
8353    width: 0,
8354    height: 0,
8355    innerWidth: 0,
8356    innerHeight: 0,
8357    outerWidth: 0,
8358    outerHeight: 0,
8359  };
8360  measurements.forEach( ( measurement ) => {
8361    size[ measurement ] = 0;
8362  } );
8363  return size;
8364}
8365
8366// -------------------------- getSize -------------------------- //
8367
8368function getSize( elem ) {
8369  // use querySeletor if elem is string
8370  if ( typeof elem == 'string' ) elem = document.querySelector( elem );
8371
8372  // do not proceed on non-objects
8373  let isElement = elem && typeof elem == 'object' && elem.nodeType;
8374  if ( !isElement ) return;
8375
8376  let style = getComputedStyle( elem );
8377
8378  // if hidden, everything is 0
8379  if ( style.display == 'none' ) return getZeroSize();
8380
8381  let size = {};
8382  size.width = elem.offsetWidth;
8383  size.height = elem.offsetHeight;
8384
8385  let isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
8386
8387  // get all measurements
8388  measurements.forEach( ( measurement ) => {
8389    let value = style[ measurement ];
8390    let num = parseFloat( value );
8391    // any 'auto', 'medium' value will be 0
8392    size[ measurement ] = !isNaN( num ) ? num : 0;
8393  } );
8394
8395  let paddingWidth = size.paddingLeft + size.paddingRight;
8396  let paddingHeight = size.paddingTop + size.paddingBottom;
8397  let marginWidth = size.marginLeft + size.marginRight;
8398  let marginHeight = size.marginTop + size.marginBottom;
8399  let borderWidth = size.borderLeftWidth + size.borderRightWidth;
8400  let borderHeight = size.borderTopWidth + size.borderBottomWidth;
8401
8402  // overwrite width and height if we can get it from style
8403  let styleWidth = getStyleSize( style.width );
8404  if ( styleWidth !== false ) {
8405    size.width = styleWidth +
8406      // add padding and border unless it's already including it
8407      ( isBorderBox ? 0 : paddingWidth + borderWidth );
8408  }
8409
8410  let styleHeight = getStyleSize( style.height );
8411  if ( styleHeight !== false ) {
8412    size.height = styleHeight +
8413      // add padding and border unless it's already including it
8414      ( isBorderBox ? 0 : paddingHeight + borderHeight );
8415  }
8416
8417  size.innerWidth = size.width - ( paddingWidth + borderWidth );
8418  size.innerHeight = size.height - ( paddingHeight + borderHeight );
8419
8420  size.outerWidth = size.width + marginWidth;
8421  size.outerHeight = size.height + marginHeight;
8422
8423  return size;
8424}
8425
8426return getSize;
8427
8428} );
8429/**
8430 * Fizzy UI utils v3.0.0
8431 * MIT license
8432 */
8433
8434( function( global, factory ) {
8435  // universal module definition
8436  if ( typeof module == 'object' && module.exports ) {
8437    // CommonJS
8438    module.exports = factory( global );
8439  } else {
8440    // browser global
8441    global.fizzyUIUtils = factory( global );
8442  }
8443
8444}( this, function factory( global ) {
8445
8446let utils = {};
8447
8448// ----- extend ----- //
8449
8450// extends objects
8451utils.extend = function( a, b ) {
8452  return Object.assign( a, b );
8453};
8454
8455// ----- modulo ----- //
8456
8457utils.modulo = function( num, div ) {
8458  return ( ( num % div ) + div ) % div;
8459};
8460
8461// ----- makeArray ----- //
8462
8463// turn element or nodeList into an array
8464utils.makeArray = function( obj ) {
8465  // use object if already an array
8466  if ( Array.isArray( obj ) ) return obj;
8467
8468  // return empty array if undefined or null. #6
8469  if ( obj === null || obj === undefined ) return [];
8470
8471  let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
8472  // convert nodeList to array
8473  if ( isArrayLike ) return [ ...obj ];
8474
8475  // array of single index
8476  return [ obj ];
8477};
8478
8479// ----- removeFrom ----- //
8480
8481utils.removeFrom = function( ary, obj ) {
8482  let index = ary.indexOf( obj );
8483  if ( index != -1 ) {
8484    ary.splice( index, 1 );
8485  }
8486};
8487
8488// ----- getParent ----- //
8489
8490utils.getParent = function( elem, selector ) {
8491  while ( elem.parentNode && elem != document.body ) {
8492    elem = elem.parentNode;
8493    if ( elem.matches( selector ) ) return elem;
8494  }
8495};
8496
8497// ----- getQueryElement ----- //
8498
8499// use element as selector string
8500utils.getQueryElement = function( elem ) {
8501  if ( typeof elem == 'string' ) {
8502    return document.querySelector( elem );
8503  }
8504  return elem;
8505};
8506
8507// ----- handleEvent ----- //
8508
8509// enable .ontype to trigger from .addEventListener( elem, 'type' )
8510utils.handleEvent = function( event ) {
8511  let method = 'on' + event.type;
8512  if ( this[ method ] ) {
8513    this[ method ]( event );
8514  }
8515};
8516
8517// ----- filterFindElements ----- //
8518
8519utils.filterFindElements = function( elems, selector ) {
8520  // make array of elems
8521  elems = utils.makeArray( elems );
8522
8523  return elems
8524    // check that elem is an actual element
8525    .filter( ( elem ) => elem instanceof HTMLElement )
8526    .reduce( ( ffElems, elem ) => {
8527      // add elem if no selector
8528      if ( !selector ) {
8529        ffElems.push( elem );
8530        return ffElems;
8531      }
8532      // filter & find items if we have a selector
8533      // filter
8534      if ( elem.matches( selector ) ) {
8535        ffElems.push( elem );
8536      }
8537      // find children
8538      let childElems = elem.querySelectorAll( selector );
8539      // concat childElems to filterFound array
8540      ffElems = ffElems.concat( ...childElems );
8541      return ffElems;
8542    }, [] );
8543};
8544
8545// ----- debounceMethod ----- //
8546
8547utils.debounceMethod = function( _class, methodName, threshold ) {
8548  threshold = threshold || 100;
8549  // original method
8550  let method = _class.prototype[ methodName ];
8551  let timeoutName = methodName + 'Timeout';
8552
8553  _class.prototype[ methodName ] = function() {
8554    clearTimeout( this[ timeoutName ] );
8555
8556    let args = arguments;
8557    this[ timeoutName ] = setTimeout( () => {
8558      method.apply( this, args );
8559      delete this[ timeoutName ];
8560    }, threshold );
8561  };
8562};
8563
8564// ----- docReady ----- //
8565
8566utils.docReady = function( onDocReady ) {
8567  let readyState = document.readyState;
8568  if ( readyState == 'complete' || readyState == 'interactive' ) {
8569    // do async to allow for other scripts to run. metafizzy/flickity#441
8570    setTimeout( onDocReady );
8571  } else {
8572    document.addEventListener( 'DOMContentLoaded', onDocReady );
8573  }
8574};
8575
8576// ----- htmlInit ----- //
8577
8578// http://bit.ly/3oYLusc
8579utils.toDashed = function( str ) {
8580  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
8581    return $1 + '-' + $2;
8582  } ).toLowerCase();
8583};
8584
8585let console = global.console;
8586
8587// allow user to initialize classes via [data-namespace] or .js-namespace class
8588// htmlInit( Widget, 'widgetName' )
8589// options are parsed from data-namespace-options
8590utils.htmlInit = function( WidgetClass, namespace ) {
8591  utils.docReady( function() {
8592    let dashedNamespace = utils.toDashed( namespace );
8593    let dataAttr = 'data-' + dashedNamespace;
8594    let dataAttrElems = document.querySelectorAll( `[${dataAttr}]` );
8595    let jQuery = global.jQuery;
8596
8597    [ ...dataAttrElems ].forEach( ( elem ) => {
8598      let attr = elem.getAttribute( dataAttr );
8599      let options;
8600      try {
8601        options = attr && JSON.parse( attr );
8602      } catch ( error ) {
8603        // log error, do not initialize
8604        if ( console ) {
8605          console.error( `Error parsing ${dataAttr} on ${elem.className}: ${error}` );
8606        }
8607        return;
8608      }
8609      // initialize
8610      let instance = new WidgetClass( elem, options );
8611      // make available via $().data('namespace')
8612      if ( jQuery ) {
8613        jQuery.data( elem, namespace, instance );
8614      }
8615    } );
8616
8617  } );
8618};
8619
8620// -----  ----- //
8621
8622return utils;
8623
8624} ) );
8625/*!
8626 * Unidragger v3.0.0
8627 * Draggable base class
8628 * MIT license
8629 */
8630
8631( function( window, factory ) {
8632  // universal module definition
8633  if ( typeof module == 'object' && module.exports ) {
8634    // CommonJS
8635    module.exports = factory(
8636        window,
8637        require('ev-emitter'),
8638    );
8639  } else {
8640    // browser global
8641    window.Unidragger = factory(
8642        window,
8643        window.EvEmitter,
8644    );
8645  }
8646
8647}( typeof window != 'undefined' ? window : this, function factory( window, EvEmitter ) {
8648
8649function Unidragger() {}
8650
8651// inherit EvEmitter
8652let proto = Unidragger.prototype = Object.create( EvEmitter.prototype );
8653
8654// ----- bind start ----- //
8655
8656// trigger handler methods for events
8657proto.handleEvent = function( event ) {
8658  let method = 'on' + event.type;
8659  if ( this[ method ] ) {
8660    this[ method ]( event );
8661  }
8662};
8663
8664let startEvent, activeEvents;
8665if ( 'ontouchstart' in window ) {
8666  // HACK prefer Touch Events as you can preventDefault on touchstart to
8667  // disable scroll in iOS & mobile Chrome metafizzy/flickity#1177
8668  startEvent = 'touchstart';
8669  activeEvents = [ 'touchmove', 'touchend', 'touchcancel' ];
8670} else if ( window.PointerEvent ) {
8671  // Pointer Events
8672  startEvent = 'pointerdown';
8673  activeEvents = [ 'pointermove', 'pointerup', 'pointercancel' ];
8674} else {
8675  // mouse events
8676  startEvent = 'mousedown';
8677  activeEvents = [ 'mousemove', 'mouseup' ];
8678}
8679
8680// prototype so it can be overwriteable by Flickity
8681proto.touchActionValue = 'none';
8682
8683proto.bindHandles = function() {
8684  this._bindHandles( 'addEventListener', this.touchActionValue );
8685};
8686
8687proto.unbindHandles = function() {
8688  this._bindHandles( 'removeEventListener', '' );
8689};
8690
8691/**
8692 * Add or remove start event
8693 * @param {String} bindMethod - addEventListener or removeEventListener
8694 * @param {String} touchAction - value for touch-action CSS property
8695 */
8696proto._bindHandles = function( bindMethod, touchAction ) {
8697  this.handles.forEach( ( handle ) => {
8698    handle[ bindMethod ]( startEvent, this );
8699    handle[ bindMethod ]( 'click', this );
8700    // touch-action: none to override browser touch gestures. metafizzy/flickity#540
8701    if ( window.PointerEvent ) handle.style.touchAction = touchAction;
8702  } );
8703};
8704
8705proto.bindActivePointerEvents = function() {
8706  activeEvents.forEach( ( eventName ) => {
8707    window.addEventListener( eventName, this );
8708  } );
8709};
8710
8711proto.unbindActivePointerEvents = function() {
8712  activeEvents.forEach( ( eventName ) => {
8713    window.removeEventListener( eventName, this );
8714  } );
8715};
8716
8717// ----- event handler helpers ----- //
8718
8719// trigger method with matching pointer
8720proto.withPointer = function( methodName, event ) {
8721  if ( event.pointerId == this.pointerIdentifier ) {
8722    this[ methodName ]( event, event );
8723  }
8724};
8725
8726// trigger method with matching touch
8727proto.withTouch = function( methodName, event ) {
8728  let touch;
8729  for ( let changedTouch of event.changedTouches ) {
8730    if ( changedTouch.identifier == this.pointerIdentifier ) {
8731      touch = changedTouch;
8732    }
8733  }
8734  if ( touch ) this[ methodName ]( event, touch );
8735};
8736
8737// ----- start event ----- //
8738
8739proto.onmousedown = function( event ) {
8740  this.pointerDown( event, event );
8741};
8742
8743proto.ontouchstart = function( event ) {
8744  this.pointerDown( event, event.changedTouches[0] );
8745};
8746
8747proto.onpointerdown = function( event ) {
8748  this.pointerDown( event, event );
8749};
8750
8751// nodes that have text fields
8752const cursorNodes = [ 'TEXTAREA', 'INPUT', 'SELECT', 'OPTION' ];
8753// input types that do not have text fields
8754const clickTypes = [ 'radio', 'checkbox', 'button', 'submit', 'image', 'file' ];
8755
8756/**
8757 * any time you set `event, pointer` it refers to:
8758 * @param {Event} event
8759 * @param {Event | Touch} pointer
8760 */
8761proto.pointerDown = function( event, pointer ) {
8762  // dismiss multi-touch taps, right clicks, and clicks on text fields
8763  let isCursorNode = cursorNodes.includes( event.target.nodeName );
8764  let isClickType = clickTypes.includes( event.target.type );
8765  let isOkayElement = !isCursorNode || isClickType;
8766  let isOkay = !this.isPointerDown && !event.button && isOkayElement;
8767  if ( !isOkay ) return;
8768
8769  this.isPointerDown = true;
8770  // save pointer identifier to match up touch events
8771  this.pointerIdentifier = pointer.pointerId !== undefined ?
8772    // pointerId for pointer events, touch.indentifier for touch events
8773    pointer.pointerId : pointer.identifier;
8774  // track position for move
8775  this.pointerDownPointer = {
8776    pageX: pointer.pageX,
8777    pageY: pointer.pageY,
8778  };
8779
8780  this.bindActivePointerEvents();
8781  this.emitEvent( 'pointerDown', [ event, pointer ] );
8782};
8783
8784// ----- move ----- //
8785
8786proto.onmousemove = function( event ) {
8787  this.pointerMove( event, event );
8788};
8789
8790proto.onpointermove = function( event ) {
8791  this.withPointer( 'pointerMove', event );
8792};
8793
8794proto.ontouchmove = function( event ) {
8795  this.withTouch( 'pointerMove', event );
8796};
8797
8798proto.pointerMove = function( event, pointer ) {
8799  let moveVector = {
8800    x: pointer.pageX - this.pointerDownPointer.pageX,
8801    y: pointer.pageY - this.pointerDownPointer.pageY,
8802  };
8803  this.emitEvent( 'pointerMove', [ event, pointer, moveVector ] );
8804  // start drag if pointer has moved far enough to start drag
8805  let isDragStarting = !this.isDragging && this.hasDragStarted( moveVector );
8806  if ( isDragStarting ) this.dragStart( event, pointer );
8807  if ( this.isDragging ) this.dragMove( event, pointer, moveVector );
8808};
8809
8810// condition if pointer has moved far enough to start drag
8811proto.hasDragStarted = function( moveVector ) {
8812  return Math.abs( moveVector.x ) > 3 || Math.abs( moveVector.y ) > 3;
8813};
8814
8815// ----- drag ----- //
8816
8817proto.dragStart = function( event, pointer ) {
8818  this.isDragging = true;
8819  this.isPreventingClicks = true; // set flag to prevent clicks
8820  this.emitEvent( 'dragStart', [ event, pointer ] );
8821};
8822
8823proto.dragMove = function( event, pointer, moveVector ) {
8824  this.emitEvent( 'dragMove', [ event, pointer, moveVector ] );
8825};
8826
8827// ----- end ----- //
8828
8829proto.onmouseup = function( event ) {
8830  this.pointerUp( event, event );
8831};
8832
8833proto.onpointerup = function( event ) {
8834  this.withPointer( 'pointerUp', event );
8835};
8836
8837proto.ontouchend = function( event ) {
8838  this.withTouch( 'pointerUp', event );
8839};
8840
8841proto.pointerUp = function( event, pointer ) {
8842  this.pointerDone();
8843  this.emitEvent( 'pointerUp', [ event, pointer ] );
8844
8845  if ( this.isDragging ) {
8846    this.dragEnd( event, pointer );
8847  } else {
8848    // pointer didn't move enough for drag to start
8849    this.staticClick( event, pointer );
8850  }
8851};
8852
8853proto.dragEnd = function( event, pointer ) {
8854  this.isDragging = false; // reset flag
8855  // re-enable clicking async
8856  setTimeout( () => delete this.isPreventingClicks );
8857
8858  this.emitEvent( 'dragEnd', [ event, pointer ] );
8859};
8860
8861// triggered on pointer up & pointer cancel
8862proto.pointerDone = function() {
8863  this.isPointerDown = false;
8864  delete this.pointerIdentifier;
8865  this.unbindActivePointerEvents();
8866  this.emitEvent('pointerDone');
8867};
8868
8869// ----- cancel ----- //
8870
8871proto.onpointercancel = function( event ) {
8872  this.withPointer( 'pointerCancel', event );
8873};
8874
8875proto.ontouchcancel = function( event ) {
8876  this.withTouch( 'pointerCancel', event );
8877};
8878
8879proto.pointerCancel = function( event, pointer ) {
8880  this.pointerDone();
8881  this.emitEvent( 'pointerCancel', [ event, pointer ] );
8882};
8883
8884// ----- click ----- //
8885
8886// handle all clicks and prevent clicks when dragging
8887proto.onclick = function( event ) {
8888  if ( this.isPreventingClicks ) event.preventDefault();
8889};
8890
8891// triggered after pointer down & up with no/tiny movement
8892proto.staticClick = function( event, pointer ) {
8893  // ignore emulated mouse up clicks
8894  let isMouseup = event.type == 'mouseup';
8895  if ( isMouseup && this.isIgnoringMouseUp ) return;
8896
8897  this.emitEvent( 'staticClick', [ event, pointer ] );
8898
8899  // set flag for emulated clicks 300ms after touchend
8900  if ( isMouseup ) {
8901    this.isIgnoringMouseUp = true;
8902    // reset flag after 400ms
8903    setTimeout( () => {
8904      delete this.isIgnoringMouseUp;
8905    }, 400 );
8906  }
8907};
8908
8909// -----  ----- //
8910
8911return Unidragger;
8912
8913} ) );
8914/*!
8915 * imagesLoaded v5.0.0
8916 * JavaScript is all like "You images are done yet or what?"
8917 * MIT License
8918 */
8919
8920( function( window, factory ) {
8921  // universal module definition
8922  if ( typeof module == 'object' && module.exports ) {
8923    // CommonJS
8924    module.exports = factory( window, require('ev-emitter') );
8925  } else {
8926    // browser global
8927    window.imagesLoaded = factory( window, window.EvEmitter );
8928  }
8929
8930} )( typeof window !== 'undefined' ? window : this,
8931    function factory( window, EvEmitter ) {
8932
8933let $ = window.jQuery;
8934let console = window.console;
8935
8936// -------------------------- helpers -------------------------- //
8937
8938// turn element or nodeList into an array
8939function makeArray( obj ) {
8940  // use object if already an array
8941  if ( Array.isArray( obj ) ) return obj;
8942
8943  let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
8944  // convert nodeList to array
8945  if ( isArrayLike ) return [ ...obj ];
8946
8947  // array of single index
8948  return [ obj ];
8949}
8950
8951// -------------------------- imagesLoaded -------------------------- //
8952
8953/**
8954 * @param {[Array, Element, NodeList, String]} elem
8955 * @param {[Object, Function]} options - if function, use as callback
8956 * @param {Function} onAlways - callback function
8957 * @returns {ImagesLoaded}
8958 */
8959function ImagesLoaded( elem, options, onAlways ) {
8960  // coerce ImagesLoaded() without new, to be new ImagesLoaded()
8961  if ( !( this instanceof ImagesLoaded ) ) {
8962    return new ImagesLoaded( elem, options, onAlways );
8963  }
8964  // use elem as selector string
8965  let queryElem = elem;
8966  if ( typeof elem == 'string' ) {
8967    queryElem = document.querySelectorAll( elem );
8968  }
8969  // bail if bad element
8970  if ( !queryElem ) {
8971    console.error(`Bad element for imagesLoaded ${queryElem || elem}`);
8972    return;
8973  }
8974
8975  this.elements = makeArray( queryElem );
8976  this.options = {};
8977  // shift arguments if no options set
8978  if ( typeof options == 'function' ) {
8979    onAlways = options;
8980  } else {
8981    Object.assign( this.options, options );
8982  }
8983
8984  if ( onAlways ) this.on( 'always', onAlways );
8985
8986  this.getImages();
8987  // add jQuery Deferred object
8988  if ( $ ) this.jqDeferred = new $.Deferred();
8989
8990  // HACK check async to allow time to bind listeners
8991  setTimeout( this.check.bind( this ) );
8992}
8993
8994ImagesLoaded.prototype = Object.create( EvEmitter.prototype );
8995
8996ImagesLoaded.prototype.getImages = function() {
8997  this.images = [];
8998
8999  // filter & find items if we have an item selector
9000  this.elements.forEach( this.addElementImages, this );
9001};
9002
9003const elementNodeTypes = [ 1, 9, 11 ];
9004
9005/**
9006 * @param {Node} elem
9007 */
9008ImagesLoaded.prototype.addElementImages = function( elem ) {
9009  // filter siblings
9010  if ( elem.nodeName === 'IMG' ) {
9011    this.addImage( elem );
9012  }
9013  // get background image on element
9014  if ( this.options.background === true ) {
9015    this.addElementBackgroundImages( elem );
9016  }
9017
9018  // find children
9019  // no non-element nodes, #143
9020  let { nodeType } = elem;
9021  if ( !nodeType || !elementNodeTypes.includes( nodeType ) ) return;
9022
9023  let childImgs = elem.querySelectorAll('img');
9024  // concat childElems to filterFound array
9025  for ( let img of childImgs ) {
9026    this.addImage( img );
9027  }
9028
9029  // get child background images
9030  if ( typeof this.options.background == 'string' ) {
9031    let children = elem.querySelectorAll( this.options.background );
9032    for ( let child of children ) {
9033      this.addElementBackgroundImages( child );
9034    }
9035  }
9036};
9037
9038const reURL = /url\((['"])?(.*?)\1\)/gi;
9039
9040ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {
9041  let style = getComputedStyle( elem );
9042  // Firefox returns null if in a hidden iframe https://bugzil.la/548397
9043  if ( !style ) return;
9044
9045  // get url inside url("...")
9046  let matches = reURL.exec( style.backgroundImage );
9047  while ( matches !== null ) {
9048    let url = matches && matches[2];
9049    if ( url ) {
9050      this.addBackground( url, elem );
9051    }
9052    matches = reURL.exec( style.backgroundImage );
9053  }
9054};
9055
9056/**
9057 * @param {Image} img
9058 */
9059ImagesLoaded.prototype.addImage = function( img ) {
9060  let loadingImage = new LoadingImage( img );
9061  this.images.push( loadingImage );
9062};
9063
9064ImagesLoaded.prototype.addBackground = function( url, elem ) {
9065  let background = new Background( url, elem );
9066  this.images.push( background );
9067};
9068
9069ImagesLoaded.prototype.check = function() {
9070  this.progressedCount = 0;
9071  this.hasAnyBroken = false;
9072  // complete if no images
9073  if ( !this.images.length ) {
9074    this.complete();
9075    return;
9076  }
9077
9078  /* eslint-disable-next-line func-style */
9079  let onProgress = ( image, elem, message ) => {
9080    // HACK - Chrome triggers event before object properties have changed. #83
9081    setTimeout( () => {
9082      this.progress( image, elem, message );
9083    } );
9084  };
9085
9086  this.images.forEach( function( loadingImage ) {
9087    loadingImage.once( 'progress', onProgress );
9088    loadingImage.check();
9089  } );
9090};
9091
9092ImagesLoaded.prototype.progress = function( image, elem, message ) {
9093  this.progressedCount++;
9094  this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
9095  // progress event
9096  this.emitEvent( 'progress', [ this, image, elem ] );
9097  if ( this.jqDeferred && this.jqDeferred.notify ) {
9098    this.jqDeferred.notify( this, image );
9099  }
9100  // check if completed
9101  if ( this.progressedCount === this.images.length ) {
9102    this.complete();
9103  }
9104
9105  if ( this.options.debug && console ) {
9106    console.log( `progress: ${message}`, image, elem );
9107  }
9108};
9109
9110ImagesLoaded.prototype.complete = function() {
9111  let eventName = this.hasAnyBroken ? 'fail' : 'done';
9112  this.isComplete = true;
9113  this.emitEvent( eventName, [ this ] );
9114  this.emitEvent( 'always', [ this ] );
9115  if ( this.jqDeferred ) {
9116    let jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
9117    this.jqDeferred[ jqMethod ]( this );
9118  }
9119};
9120
9121// --------------------------  -------------------------- //
9122
9123function LoadingImage( img ) {
9124  this.img = img;
9125}
9126
9127LoadingImage.prototype = Object.create( EvEmitter.prototype );
9128
9129LoadingImage.prototype.check = function() {
9130  // If complete is true and browser supports natural sizes,
9131  // try to check for image status manually.
9132  let isComplete = this.getIsImageComplete();
9133  if ( isComplete ) {
9134    // report based on naturalWidth
9135    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
9136    return;
9137  }
9138
9139  // If none of the checks above matched, simulate loading on detached element.
9140  this.proxyImage = new Image();
9141  // add crossOrigin attribute. #204
9142  if ( this.img.crossOrigin ) {
9143    this.proxyImage.crossOrigin = this.img.crossOrigin;
9144  }
9145  this.proxyImage.addEventListener( 'load', this );
9146  this.proxyImage.addEventListener( 'error', this );
9147  // bind to image as well for Firefox. #191
9148  this.img.addEventListener( 'load', this );
9149  this.img.addEventListener( 'error', this );
9150  this.proxyImage.src = this.img.currentSrc || this.img.src;
9151};
9152
9153LoadingImage.prototype.getIsImageComplete = function() {
9154  // check for non-zero, non-undefined naturalWidth
9155  // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671
9156  return this.img.complete && this.img.naturalWidth;
9157};
9158
9159LoadingImage.prototype.confirm = function( isLoaded, message ) {
9160  this.isLoaded = isLoaded;
9161  let { parentNode } = this.img;
9162  // emit progress with parent <picture> or self <img>
9163  let elem = parentNode.nodeName === 'PICTURE' ? parentNode : this.img;
9164  this.emitEvent( 'progress', [ this, elem, message ] );
9165};
9166
9167// ----- events ----- //
9168
9169// trigger specified handler for event type
9170LoadingImage.prototype.handleEvent = function( event ) {
9171  let method = 'on' + event.type;
9172  if ( this[ method ] ) {
9173    this[ method ]( event );
9174  }
9175};
9176
9177LoadingImage.prototype.onload = function() {
9178  this.confirm( true, 'onload' );
9179  this.unbindEvents();
9180};
9181
9182LoadingImage.prototype.onerror = function() {
9183  this.confirm( false, 'onerror' );
9184  this.unbindEvents();
9185};
9186
9187LoadingImage.prototype.unbindEvents = function() {
9188  this.proxyImage.removeEventListener( 'load', this );
9189  this.proxyImage.removeEventListener( 'error', this );
9190  this.img.removeEventListener( 'load', this );
9191  this.img.removeEventListener( 'error', this );
9192};
9193
9194// -------------------------- Background -------------------------- //
9195
9196function Background( url, element ) {
9197  this.url = url;
9198  this.element = element;
9199  this.img = new Image();
9200}
9201
9202// inherit LoadingImage prototype
9203Background.prototype = Object.create( LoadingImage.prototype );
9204
9205Background.prototype.check = function() {
9206  this.img.addEventListener( 'load', this );
9207  this.img.addEventListener( 'error', this );
9208  this.img.src = this.url;
9209  // check if image is already complete
9210  let isComplete = this.getIsImageComplete();
9211  if ( isComplete ) {
9212    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
9213    this.unbindEvents();
9214  }
9215};
9216
9217Background.prototype.unbindEvents = function() {
9218  this.img.removeEventListener( 'load', this );
9219  this.img.removeEventListener( 'error', this );
9220};
9221
9222Background.prototype.confirm = function( isLoaded, message ) {
9223  this.isLoaded = isLoaded;
9224  this.emitEvent( 'progress', [ this, this.element, message ] );
9225};
9226
9227// -------------------------- jQuery -------------------------- //
9228
9229ImagesLoaded.makeJQueryPlugin = function( jQuery ) {
9230  jQuery = jQuery || window.jQuery;
9231  if ( !jQuery ) return;
9232
9233  // set local variable
9234  $ = jQuery;
9235  // $().imagesLoaded()
9236  $.fn.imagesLoaded = function( options, onAlways ) {
9237    let instance = new ImagesLoaded( this, options, onAlways );
9238    return instance.jqDeferred.promise( $( this ) );
9239  };
9240};
9241// try making plugin
9242ImagesLoaded.makeJQueryPlugin();
9243
9244// --------------------------  -------------------------- //
9245
9246return ImagesLoaded;
9247
9248} );
9249// Flickity.Cell
9250( function( window, factory ) {
9251  // universal module definition
9252  if ( typeof module == 'object' && module.exports ) {
9253    // CommonJS
9254    module.exports = factory( require('get-size') );
9255  } else {
9256    // browser global
9257    window.Flickity = window.Flickity || {};
9258    window.Flickity.Cell = factory( window.getSize );
9259  }
9260
9261}( typeof window != 'undefined' ? window : this, function factory( getSize ) {
9262
9263const cellClassName = 'flickity-cell';
9264
9265function Cell( elem ) {
9266  this.element = elem;
9267  this.element.classList.add( cellClassName );
9268
9269  this.x = 0;
9270  this.unselect();
9271}
9272
9273let proto = Cell.prototype;
9274
9275proto.destroy = function() {
9276  // reset style
9277  this.unselect();
9278  this.element.classList.remove( cellClassName );
9279  this.element.style.transform = '';
9280  this.element.removeAttribute('aria-hidden');
9281};
9282
9283proto.getSize = function() {
9284  this.size = getSize( this.element );
9285};
9286
9287proto.select = function() {
9288  this.element.classList.add('is-selected');
9289  this.element.removeAttribute('aria-hidden');
9290};
9291
9292proto.unselect = function() {
9293  this.element.classList.remove('is-selected');
9294  this.element.setAttribute( 'aria-hidden', 'true' );
9295};
9296
9297proto.remove = function() {
9298  this.element.remove();
9299};
9300
9301return Cell;
9302
9303} ) );
9304// slide
9305( function( window, factory ) {
9306  // universal module definition
9307  if ( typeof module == 'object' && module.exports ) {
9308    // CommonJS
9309    module.exports = factory();
9310  } else {
9311    // browser global
9312    window.Flickity = window.Flickity || {};
9313    window.Flickity.Slide = factory();
9314  }
9315
9316}( typeof window != 'undefined' ? window : this, function factory() {
9317
9318function Slide( beginMargin, endMargin, cellAlign ) {
9319  this.beginMargin = beginMargin;
9320  this.endMargin = endMargin;
9321  this.cellAlign = cellAlign;
9322  this.cells = [];
9323  this.outerWidth = 0;
9324  this.height = 0;
9325}
9326
9327let proto = Slide.prototype;
9328
9329proto.addCell = function( cell ) {
9330  this.cells.push( cell );
9331  this.outerWidth += cell.size.outerWidth;
9332  this.height = Math.max( cell.size.outerHeight, this.height );
9333  // first cell stuff
9334  if ( this.cells.length === 1 ) {
9335    this.x = cell.x; // x comes from first cell
9336    this.firstMargin = cell.size[ this.beginMargin ];
9337  }
9338};
9339
9340proto.updateTarget = function() {
9341  let lastCell = this.getLastCell();
9342  let lastMargin = lastCell ? lastCell.size[ this.endMargin ] : 0;
9343  let slideWidth = this.outerWidth - ( this.firstMargin + lastMargin );
9344  this.target = this.x + this.firstMargin + slideWidth * this.cellAlign;
9345};
9346
9347proto.getLastCell = function() {
9348  return this.cells[ this.cells.length - 1 ];
9349};
9350
9351proto.select = function() {
9352  this.cells.forEach( ( cell ) => cell.select() );
9353};
9354
9355proto.unselect = function() {
9356  this.cells.forEach( ( cell ) => cell.unselect() );
9357};
9358
9359proto.getCellElements = function() {
9360  return this.cells.map( ( cell ) => cell.element );
9361};
9362
9363return Slide;
9364
9365} ) );
9366// animate
9367( function( window, factory ) {
9368  // universal module definition
9369  if ( typeof module == 'object' && module.exports ) {
9370    // CommonJS
9371    module.exports = factory( require('fizzy-ui-utils') );
9372  } else {
9373    // browser global
9374    window.Flickity = window.Flickity || {};
9375    window.Flickity.animatePrototype = factory( window.fizzyUIUtils );
9376  }
9377
9378}( typeof window != 'undefined' ? window : this, function factory( utils ) {
9379
9380// -------------------------- animate -------------------------- //
9381
9382let proto = {};
9383
9384proto.startAnimation = function() {
9385  if ( this.isAnimating ) return;
9386
9387  this.isAnimating = true;
9388  this.restingFrames = 0;
9389  this.animate();
9390};
9391
9392proto.animate = function() {
9393  this.applyDragForce();
9394  this.applySelectedAttraction();
9395
9396  let previousX = this.x;
9397
9398  this.integratePhysics();
9399  this.positionSlider();
9400  this.settle( previousX );
9401  // animate next frame
9402  if ( this.isAnimating ) requestAnimationFrame( () => this.animate() );
9403};
9404
9405proto.positionSlider = function() {
9406  let x = this.x;
9407  // wrap position around
9408  if ( this.isWrapping ) {
9409    x = utils.modulo( x, this.slideableWidth ) - this.slideableWidth;
9410    this.shiftWrapCells( x );
9411  }
9412
9413  this.setTranslateX( x, this.isAnimating );
9414  this.dispatchScrollEvent();
9415};
9416
9417proto.setTranslateX = function( x, is3d ) {
9418  x += this.cursorPosition;
9419  // reverse if right-to-left and using transform
9420  if ( this.options.rightToLeft ) x = -x;
9421  let translateX = this.getPositionValue( x );
9422  // use 3D transforms for hardware acceleration on iOS
9423  // but use 2D when settled, for better font-rendering
9424  this.slider.style.transform = is3d ?
9425    `translate3d(${translateX},0,0)` : `translateX(${translateX})`;
9426};
9427
9428proto.dispatchScrollEvent = function() {
9429  let firstSlide = this.slides[0];
9430  if ( !firstSlide ) return;
9431
9432  let positionX = -this.x - firstSlide.target;
9433  let progress = positionX / this.slidesWidth;
9434  this.dispatchEvent( 'scroll', null, [ progress, positionX ] );
9435};
9436
9437proto.positionSliderAtSelected = function() {
9438  if ( !this.cells.length ) return;
9439
9440  this.x = -this.selectedSlide.target;
9441  this.velocity = 0; // stop wobble
9442  this.positionSlider();
9443};
9444
9445proto.getPositionValue = function( position ) {
9446  if ( this.options.percentPosition ) {
9447    // percent position, round to 2 digits, like 12.34%
9448    return ( Math.round( ( position / this.size.innerWidth ) * 10000 ) * 0.01 ) + '%';
9449  } else {
9450    // pixel positioning
9451    return Math.round( position ) + 'px';
9452  }
9453};
9454
9455proto.settle = function( previousX ) {
9456  // keep track of frames where x hasn't moved
9457  let isResting = !this.isPointerDown &&
9458      Math.round( this.x * 100 ) === Math.round( previousX * 100 );
9459  if ( isResting ) this.restingFrames++;
9460  // stop animating if resting for 3 or more frames
9461  if ( this.restingFrames > 2 ) {
9462    this.isAnimating = false;
9463    delete this.isFreeScrolling;
9464    // render position with translateX when settled
9465    this.positionSlider();
9466    this.dispatchEvent( 'settle', null, [ this.selectedIndex ] );
9467  }
9468};
9469
9470proto.shiftWrapCells = function( x ) {
9471  // shift before cells
9472  let beforeGap = this.cursorPosition + x;
9473  this._shiftCells( this.beforeShiftCells, beforeGap, -1 );
9474  // shift after cells
9475  let afterGap = this.size.innerWidth - ( x + this.slideableWidth + this.cursorPosition );
9476  this._shiftCells( this.afterShiftCells, afterGap, 1 );
9477};
9478
9479proto._shiftCells = function( cells, gap, shift ) {
9480  cells.forEach( ( cell ) => {
9481    let cellShift = gap > 0 ? shift : 0;
9482    this._wrapShiftCell( cell, cellShift );
9483    gap -= cell.size.outerWidth;
9484  } );
9485};
9486
9487proto._unshiftCells = function( cells ) {
9488  if ( !cells || !cells.length ) return;
9489
9490  cells.forEach( ( cell ) => this._wrapShiftCell( cell, 0 ) );
9491};
9492
9493// @param {Integer} shift - 0, 1, or -1
9494proto._wrapShiftCell = function( cell, shift ) {
9495  this._renderCellPosition( cell, cell.x + this.slideableWidth * shift );
9496};
9497
9498// -------------------------- physics -------------------------- //
9499
9500proto.integratePhysics = function() {
9501  this.x += this.velocity;
9502  this.velocity *= this.getFrictionFactor();
9503};
9504
9505proto.applyForce = function( force ) {
9506  this.velocity += force;
9507};
9508
9509proto.getFrictionFactor = function() {
9510  return 1 - this.options[ this.isFreeScrolling ? 'freeScrollFriction' : 'friction' ];
9511};
9512
9513proto.getRestingPosition = function() {
9514  // my thanks to Steven Wittens, who simplified this math greatly
9515  return this.x + this.velocity / ( 1 - this.getFrictionFactor() );
9516};
9517
9518proto.applyDragForce = function() {
9519  if ( !this.isDraggable || !this.isPointerDown ) return;
9520
9521  // change the position to drag position by applying force
9522  let dragVelocity = this.dragX - this.x;
9523  let dragForce = dragVelocity - this.velocity;
9524  this.applyForce( dragForce );
9525};
9526
9527proto.applySelectedAttraction = function() {
9528  // do not attract if pointer down or no slides
9529  let dragDown = this.isDraggable && this.isPointerDown;
9530  if ( dragDown || this.isFreeScrolling || !this.slides.length ) return;
9531
9532  let distance = this.selectedSlide.target * -1 - this.x;
9533  let force = distance * this.options.selectedAttraction;
9534  this.applyForce( force );
9535};
9536
9537return proto;
9538
9539} ) );
9540// Flickity main
9541/* eslint-disable max-params */
9542( function( window, factory ) {
9543  // universal module definition
9544  if ( typeof module == 'object' && module.exports ) {
9545    // CommonJS
9546    module.exports = factory(
9547        window,
9548        require('ev-emitter'),
9549        require('get-size'),
9550        require('fizzy-ui-utils'),
9551        require('./cell'),
9552        require('./slide'),
9553        require('./animate'),
9554    );
9555  } else {
9556    // browser global
9557    let _Flickity = window.Flickity;
9558
9559    window.Flickity = factory(
9560        window,
9561        window.EvEmitter,
9562        window.getSize,
9563        window.fizzyUIUtils,
9564        _Flickity.Cell,
9565        _Flickity.Slide,
9566        _Flickity.animatePrototype,
9567    );
9568  }
9569
9570}( typeof window != 'undefined' ? window : this,
9571    function factory( window, EvEmitter, getSize, utils, Cell, Slide, animatePrototype ) {
9572/* eslint-enable max-params */
9573
9574// vars
9575const { getComputedStyle, console } = window;
9576let { jQuery } = window;
9577
9578// -------------------------- Flickity -------------------------- //
9579
9580// globally unique identifiers
9581let GUID = 0;
9582// internal store of all Flickity intances
9583let instances = {};
9584
9585function Flickity( element, options ) {
9586  let queryElement = utils.getQueryElement( element );
9587  if ( !queryElement ) {
9588    if ( console ) console.error(`Bad element for Flickity: ${queryElement || element}`);
9589    return;
9590  }
9591  this.element = queryElement;
9592  // do not initialize twice on same element
9593  if ( this.element.flickityGUID ) {
9594    let instance = instances[ this.element.flickityGUID ];
9595    if ( instance ) instance.option( options );
9596    return instance;
9597  }
9598
9599  // add jQuery
9600  if ( jQuery ) {
9601    this.$element = jQuery( this.element );
9602  }
9603  // options
9604  this.options = { ...this.constructor.defaults };
9605  this.option( options );
9606
9607  // kick things off
9608  this._create();
9609}
9610
9611Flickity.defaults = {
9612  accessibility: true,
9613  // adaptiveHeight: false,
9614  cellAlign: 'center',
9615  // cellSelector: undefined,
9616  // contain: false,
9617  freeScrollFriction: 0.075, // friction when free-scrolling
9618  friction: 0.28, // friction when selecting
9619  namespaceJQueryEvents: true,
9620  // initialIndex: 0,
9621  percentPosition: true,
9622  resize: true,
9623  selectedAttraction: 0.025,
9624  setGallerySize: true,
9625  // watchCSS: false,
9626  // wrapAround: false
9627};
9628
9629// hash of methods triggered on _create()
9630Flickity.create = {};
9631
9632let proto = Flickity.prototype;
9633// inherit EventEmitter
9634Object.assign( proto, EvEmitter.prototype );
9635
9636proto._create = function() {
9637  let { resize, watchCSS, rightToLeft } = this.options;
9638  // add id for Flickity.data
9639  let id = this.guid = ++GUID;
9640  this.element.flickityGUID = id; // expando
9641  instances[ id ] = this; // associate via id
9642  // initial properties
9643  this.selectedIndex = 0;
9644  // how many frames slider has been in same position
9645  this.restingFrames = 0;
9646  // initial physics properties
9647  this.x = 0;
9648  this.velocity = 0;
9649  this.beginMargin = rightToLeft ? 'marginRight' : 'marginLeft';
9650  this.endMargin = rightToLeft ? 'marginLeft' : 'marginRight';
9651  // create viewport & slider
9652  this.viewport = document.createElement('div');
9653  this.viewport.className = 'flickity-viewport';
9654  this._createSlider();
9655  // used for keyboard navigation
9656  this.focusableElems = [ this.element ];
9657
9658  if ( resize || watchCSS ) {
9659    window.addEventListener( 'resize', this );
9660  }
9661
9662  // add listeners from on option
9663  for ( let eventName in this.options.on ) {
9664    let listener = this.options.on[ eventName ];
9665    this.on( eventName, listener );
9666  }
9667
9668  for ( let method in Flickity.create ) {
9669    Flickity.create[ method ].call( this );
9670  }
9671
9672  if ( watchCSS ) {
9673    this.watchCSS();
9674  } else {
9675    this.activate();
9676  }
9677};
9678
9679/**
9680 * set options
9681 * @param {Object} opts - options to extend
9682 */
9683proto.option = function( opts ) {
9684  Object.assign( this.options, opts );
9685};
9686
9687proto.activate = function() {
9688  if ( this.isActive ) return;
9689
9690  this.isActive = true;
9691  this.element.classList.add('flickity-enabled');
9692  if ( this.options.rightToLeft ) {
9693    this.element.classList.add('flickity-rtl');
9694  }
9695
9696  this.getSize();
9697  // move initial cell elements so they can be loaded as cells
9698  let cellElems = this._filterFindCellElements( this.element.children );
9699  this.slider.append( ...cellElems );
9700  this.viewport.append( this.slider );
9701  this.element.append( this.viewport );
9702  // get cells from children
9703  this.reloadCells();
9704
9705  if ( this.options.accessibility ) {
9706    // allow element to focusable
9707    this.element.tabIndex = 0;
9708    // listen for key presses
9709    this.element.addEventListener( 'keydown', this );
9710  }
9711
9712  this.emitEvent('activate');
9713  this.selectInitialIndex();
9714  // flag for initial activation, for using initialIndex
9715  this.isInitActivated = true;
9716  // ready event. #493
9717  this.dispatchEvent('ready');
9718};
9719
9720// slider positions the cells
9721proto._createSlider = function() {
9722  // slider element does all the positioning
9723  let slider = document.createElement('div');
9724  slider.className = 'flickity-slider';
9725  this.slider = slider;
9726};
9727
9728proto._filterFindCellElements = function( elems ) {
9729  return utils.filterFindElements( elems, this.options.cellSelector );
9730};
9731
9732// goes through all children
9733proto.reloadCells = function() {
9734  // collection of item elements
9735  this.cells = this._makeCells( this.slider.children );
9736  this.positionCells();
9737  this._updateWrapShiftCells();
9738  this.setGallerySize();
9739};
9740
9741/**
9742 * turn elements into Flickity.Cells
9743 * @param {[Array, NodeList, HTMLElement]} elems - elements to make into cells
9744 * @returns {Array} items - collection of new Flickity Cells
9745 */
9746proto._makeCells = function( elems ) {
9747  let cellElems = this._filterFindCellElements( elems );
9748
9749  // create new Cells for collection
9750  return cellElems.map( ( cellElem ) => new Cell( cellElem ) );
9751};
9752
9753proto.getLastCell = function() {
9754  return this.cells[ this.cells.length - 1 ];
9755};
9756
9757proto.getLastSlide = function() {
9758  return this.slides[ this.slides.length - 1 ];
9759};
9760
9761// positions all cells
9762proto.positionCells = function() {
9763  // size all cells
9764  this._sizeCells( this.cells );
9765  // position all cells
9766  this._positionCells( 0 );
9767};
9768
9769/**
9770 * position certain cells
9771 * @param {Integer} index - which cell to start with
9772 */
9773proto._positionCells = function( index ) {
9774  index = index || 0;
9775  // also measure maxCellHeight
9776  // start 0 if positioning all cells
9777  this.maxCellHeight = index ? this.maxCellHeight || 0 : 0;
9778  let cellX = 0;
9779  // get cellX
9780  if ( index > 0 ) {
9781    let startCell = this.cells[ index - 1 ];
9782    cellX = startCell.x + startCell.size.outerWidth;
9783  }
9784
9785  this.cells.slice( index ).forEach( ( cell ) => {
9786    cell.x = cellX;
9787    this._renderCellPosition( cell, cellX );
9788    cellX += cell.size.outerWidth;
9789    this.maxCellHeight = Math.max( cell.size.outerHeight, this.maxCellHeight );
9790  } );
9791  // keep track of cellX for wrap-around
9792  this.slideableWidth = cellX;
9793  // slides
9794  this.updateSlides();
9795  // contain slides target
9796  this._containSlides();
9797  // update slidesWidth
9798  this.slidesWidth = this.cells.length ?
9799    this.getLastSlide().target - this.slides[0].target : 0;
9800};
9801
9802proto._renderCellPosition = function( cell, x ) {
9803  // render position of cell with in slider
9804  let sideOffset = this.options.rightToLeft ? -1 : 1;
9805  let renderX = x * sideOffset;
9806  if ( this.options.percentPosition ) renderX *= this.size.innerWidth / cell.size.width;
9807  let positionValue = this.getPositionValue( renderX );
9808  cell.element.style.transform = `translateX( ${positionValue} )`;
9809};
9810
9811/**
9812 * cell.getSize() on multiple cells
9813 * @param {Array} cells - cells to size
9814 */
9815proto._sizeCells = function( cells ) {
9816  cells.forEach( ( cell ) => cell.getSize() );
9817};
9818
9819// --------------------------  -------------------------- //
9820
9821proto.updateSlides = function() {
9822  this.slides = [];
9823  if ( !this.cells.length ) return;
9824
9825  let { beginMargin, endMargin } = this;
9826  let slide = new Slide( beginMargin, endMargin, this.cellAlign );
9827  this.slides.push( slide );
9828
9829  let canCellFit = this._getCanCellFit();
9830
9831  this.cells.forEach( ( cell, i ) => {
9832    // just add cell if first cell in slide
9833    if ( !slide.cells.length ) {
9834      slide.addCell( cell );
9835      return;
9836    }
9837
9838    let slideWidth = ( slide.outerWidth - slide.firstMargin ) +
9839      ( cell.size.outerWidth - cell.size[ endMargin ] );
9840
9841    if ( canCellFit( i, slideWidth ) ) {
9842      slide.addCell( cell );
9843    } else {
9844      // doesn't fit, new slide
9845      slide.updateTarget();
9846
9847      slide = new Slide( beginMargin, endMargin, this.cellAlign );
9848      this.slides.push( slide );
9849      slide.addCell( cell );
9850    }
9851  } );
9852  // last slide
9853  slide.updateTarget();
9854  // update .selectedSlide
9855  this.updateSelectedSlide();
9856};
9857
9858proto._getCanCellFit = function() {
9859  let { groupCells } = this.options;
9860  if ( !groupCells ) return () => false;
9861
9862  if ( typeof groupCells == 'number' ) {
9863    // group by number. 3 -> [0,1,2], [3,4,5], ...
9864    let number = parseInt( groupCells, 10 );
9865    return ( i ) => ( i % number ) !== 0;
9866  }
9867  // default, group by width of slide
9868  let percent = 1;
9869  // parse '75%
9870  let percentMatch = typeof groupCells == 'string' && groupCells.match( /^(\d+)%$/ );
9871  if ( percentMatch ) percent = parseInt( percentMatch[1], 10 ) / 100;
9872  let groupWidth = ( this.size.innerWidth + 1 ) * percent;
9873  return ( i, slideWidth ) => slideWidth <= groupWidth;
9874};
9875
9876// alias _init for jQuery plugin .flickity()
9877proto._init =
9878proto.reposition = function() {
9879  this.positionCells();
9880  this.positionSliderAtSelected();
9881};
9882
9883proto.getSize = function() {
9884  this.size = getSize( this.element );
9885  this.setCellAlign();
9886  this.cursorPosition = this.size.innerWidth * this.cellAlign;
9887};
9888
9889let cellAlignShorthands = {
9890  left: 0,
9891  center: 0.5,
9892  right: 1,
9893};
9894
9895proto.setCellAlign = function() {
9896  let { cellAlign, rightToLeft } = this.options;
9897  let shorthand = cellAlignShorthands[ cellAlign ];
9898  this.cellAlign = shorthand !== undefined ? shorthand : cellAlign;
9899  if ( rightToLeft ) this.cellAlign = 1 - this.cellAlign;
9900};
9901
9902proto.setGallerySize = function() {
9903  if ( !this.options.setGallerySize ) return;
9904
9905  let height = this.options.adaptiveHeight && this.selectedSlide ?
9906    this.selectedSlide.height : this.maxCellHeight;
9907  this.viewport.style.height = `${height}px`;
9908};
9909
9910proto._updateWrapShiftCells = function() {
9911  // update isWrapping
9912  this.isWrapping = this.getIsWrapping();
9913  // only for wrap-around
9914  if ( !this.isWrapping ) return;
9915
9916  // unshift previous cells
9917  this._unshiftCells( this.beforeShiftCells );
9918  this._unshiftCells( this.afterShiftCells );
9919  // get before cells
9920  // initial gap
9921  let beforeGapX = this.cursorPosition;
9922  let lastIndex = this.cells.length - 1;
9923  this.beforeShiftCells = this._getGapCells( beforeGapX, lastIndex, -1 );
9924  // get after cells
9925  // ending gap between last cell and end of gallery viewport
9926  let afterGapX = this.size.innerWidth - this.cursorPosition;
9927  // start cloning at first cell, working forwards
9928  this.afterShiftCells = this._getGapCells( afterGapX, 0, 1 );
9929};
9930
9931proto.getIsWrapping = function() {
9932  let { wrapAround } = this.options;
9933  if ( !wrapAround || this.slides.length < 2 ) return false;
9934
9935  if ( wrapAround !== 'fill' ) return true;
9936  // check that slides can fit
9937
9938  let gapWidth = this.slideableWidth - this.size.innerWidth;
9939  if ( gapWidth > this.size.innerWidth ) return true; // gap * 2x big, all good
9940  // check that content width - shifting cell is bigger than viewport width
9941  for ( let cell of this.cells ) {
9942    if ( cell.size.outerWidth > gapWidth ) return false;
9943  }
9944  return true;
9945};
9946
9947proto._getGapCells = function( gapX, cellIndex, increment ) {
9948  // keep adding cells until the cover the initial gap
9949  let cells = [];
9950  while ( gapX > 0 ) {
9951    let cell = this.cells[ cellIndex ];
9952    if ( !cell ) break;
9953
9954    cells.push( cell );
9955    cellIndex += increment;
9956    gapX -= cell.size.outerWidth;
9957  }
9958  return cells;
9959};
9960
9961// ----- contain & wrap ----- //
9962
9963// contain cell targets so no excess sliding
9964proto._containSlides = function() {
9965  let isContaining = this.options.contain && !this.isWrapping &&
9966      this.cells.length;
9967  if ( !isContaining ) return;
9968
9969  let contentWidth = this.slideableWidth - this.getLastCell().size[ this.endMargin ];
9970  // content is less than gallery size
9971  let isContentSmaller = contentWidth < this.size.innerWidth;
9972  if ( isContentSmaller ) {
9973    // all cells fit inside gallery
9974    this.slides.forEach( ( slide ) => {
9975      slide.target = contentWidth * this.cellAlign;
9976    } );
9977  } else {
9978    // contain to bounds
9979    let beginBound = this.cursorPosition + this.cells[0].size[ this.beginMargin ];
9980    let endBound = contentWidth - this.size.innerWidth * ( 1 - this.cellAlign );
9981    this.slides.forEach( ( slide ) => {
9982      slide.target = Math.max( slide.target, beginBound );
9983      slide.target = Math.min( slide.target, endBound );
9984    } );
9985  }
9986};
9987
9988// ----- events ----- //
9989
9990/**
9991 * emits events via eventEmitter and jQuery events
9992 * @param {String} type - name of event
9993 * @param {Event} event - original event
9994 * @param {Array} args - extra arguments
9995 */
9996proto.dispatchEvent = function( type, event, args ) {
9997  let emitArgs = event ? [ event ].concat( args ) : args;
9998  this.emitEvent( type, emitArgs );
9999
10000  if ( jQuery && this.$element ) {
10001    // default trigger with type if no event
10002    type += this.options.namespaceJQueryEvents ? '.flickity' : '';
10003    let $event = type;
10004    if ( event ) {
10005      // create jQuery event
10006      let jQEvent = new jQuery.Event( event );
10007      jQEvent.type = type;
10008      $event = jQEvent;
10009    }
10010    this.$element.trigger( $event, args );
10011  }
10012};
10013
10014const unidraggerEvents = [
10015  'dragStart',
10016  'dragMove',
10017  'dragEnd',
10018  'pointerDown',
10019  'pointerMove',
10020  'pointerEnd',
10021  'staticClick',
10022];
10023
10024let _emitEvent = proto.emitEvent;
10025proto.emitEvent = function( eventName, args ) {
10026  if ( eventName === 'staticClick' ) {
10027    // add cellElem and cellIndex args to staticClick
10028    let clickedCell = this.getParentCell( args[0].target );
10029    let cellElem = clickedCell && clickedCell.element;
10030    let cellIndex = clickedCell && this.cells.indexOf( clickedCell );
10031    args = args.concat( cellElem, cellIndex );
10032  }
10033  // do regular thing
10034  _emitEvent.call( this, eventName, args );
10035  // duck-punch in jQuery events for Unidragger events
10036  let isUnidraggerEvent = unidraggerEvents.includes( eventName );
10037  if ( !isUnidraggerEvent || !jQuery || !this.$element ) return;
10038
10039  eventName += this.options.namespaceJQueryEvents ? '.flickity' : '';
10040  let event = args.shift( 0 );
10041  let jQEvent = new jQuery.Event( event );
10042  jQEvent.type = eventName;
10043  this.$element.trigger( jQEvent, args );
10044};
10045
10046// -------------------------- select -------------------------- //
10047
10048/**
10049 * @param {Integer} index - index of the slide
10050 * @param {Boolean} isWrap - will wrap-around to last/first if at the end
10051 * @param {Boolean} isInstant - will immediately set position at selected cell
10052 */
10053proto.select = function( index, isWrap, isInstant ) {
10054  if ( !this.isActive ) return;
10055
10056  index = parseInt( index, 10 );
10057  this._wrapSelect( index );
10058
10059  if ( this.isWrapping || isWrap ) {
10060    index = utils.modulo( index, this.slides.length );
10061  }
10062  // bail if invalid index
10063  if ( !this.slides[ index ] ) return;
10064
10065  let prevIndex = this.selectedIndex;
10066  this.selectedIndex = index;
10067  this.updateSelectedSlide();
10068  if ( isInstant ) {
10069    this.positionSliderAtSelected();
10070  } else {
10071    this.startAnimation();
10072  }
10073  if ( this.options.adaptiveHeight ) {
10074    this.setGallerySize();
10075  }
10076  // events
10077  this.dispatchEvent( 'select', null, [ index ] );
10078  // change event if new index
10079  if ( index !== prevIndex ) {
10080    this.dispatchEvent( 'change', null, [ index ] );
10081  }
10082};
10083
10084// wraps position for wrapAround, to move to closest slide. #113
10085proto._wrapSelect = function( index ) {
10086  if ( !this.isWrapping ) return;
10087
10088  const { selectedIndex, slideableWidth, slides: { length } } = this;
10089  // shift index for wrap, do not wrap dragSelect
10090  if ( !this.isDragSelect ) {
10091    let wrapIndex = utils.modulo( index, length );
10092    // go to shortest
10093    let delta = Math.abs( wrapIndex - selectedIndex );
10094    let backWrapDelta = Math.abs( ( wrapIndex + length ) - selectedIndex );
10095    let forewardWrapDelta = Math.abs( ( wrapIndex - length ) - selectedIndex );
10096    if ( backWrapDelta < delta ) {
10097      index += length;
10098    } else if ( forewardWrapDelta < delta ) {
10099      index -= length;
10100    }
10101  }
10102
10103  // wrap position so slider is within normal area
10104  if ( index < 0 ) {
10105    this.x -= slideableWidth;
10106  } else if ( index >= length ) {
10107    this.x += slideableWidth;
10108  }
10109};
10110
10111proto.previous = function( isWrap, isInstant ) {
10112  this.select( this.selectedIndex - 1, isWrap, isInstant );
10113};
10114
10115proto.next = function( isWrap, isInstant ) {
10116  this.select( this.selectedIndex + 1, isWrap, isInstant );
10117};
10118
10119proto.updateSelectedSlide = function() {
10120  let slide = this.slides[ this.selectedIndex ];
10121  // selectedIndex could be outside of slides, if triggered before resize()
10122  if ( !slide ) return;
10123
10124  // unselect previous selected slide
10125  this.unselectSelectedSlide();
10126  // update new selected slide
10127  this.selectedSlide = slide;
10128  slide.select();
10129  this.selectedCells = slide.cells;
10130  this.selectedElements = slide.getCellElements();
10131  // HACK: selectedCell & selectedElement is first cell in slide, backwards compatibility
10132  this.selectedCell = slide.cells[0];
10133  this.selectedElement = this.selectedElements[0];
10134};
10135
10136proto.unselectSelectedSlide = function() {
10137  if ( this.selectedSlide ) this.selectedSlide.unselect();
10138};
10139
10140proto.selectInitialIndex = function() {
10141  let initialIndex = this.options.initialIndex;
10142  // already activated, select previous selectedIndex
10143  if ( this.isInitActivated ) {
10144    this.select( this.selectedIndex, false, true );
10145    return;
10146  }
10147  // select with selector string
10148  if ( initialIndex && typeof initialIndex == 'string' ) {
10149    let cell = this.queryCell( initialIndex );
10150    if ( cell ) {
10151      this.selectCell( initialIndex, false, true );
10152      return;
10153    }
10154  }
10155
10156  let index = 0;
10157  // select with number
10158  if ( initialIndex && this.slides[ initialIndex ] ) {
10159    index = initialIndex;
10160  }
10161  // select instantly
10162  this.select( index, false, true );
10163};
10164
10165/**
10166 * select slide from number or cell element
10167 * @param {[Element, Number]} value - zero-based index or element to select
10168 * @param {Boolean} isWrap - enables wrapping around for extra index
10169 * @param {Boolean} isInstant - disables slide animation
10170 */
10171proto.selectCell = function( value, isWrap, isInstant ) {
10172  // get cell
10173  let cell = this.queryCell( value );
10174  if ( !cell ) return;
10175
10176  let index = this.getCellSlideIndex( cell );
10177  this.select( index, isWrap, isInstant );
10178};
10179
10180proto.getCellSlideIndex = function( cell ) {
10181  // get index of slide that has cell
10182  let cellSlide = this.slides.find( ( slide ) => slide.cells.includes( cell ) );
10183  return this.slides.indexOf( cellSlide );
10184};
10185
10186// -------------------------- get cells -------------------------- //
10187
10188/**
10189 * get Flickity.Cell, given an Element
10190 * @param {Element} elem - matching cell element
10191 * @returns {Flickity.Cell} cell - matching cell
10192 */
10193proto.getCell = function( elem ) {
10194  // loop through cells to get the one that matches
10195  for ( let cell of this.cells ) {
10196    if ( cell.element === elem ) return cell;
10197  }
10198};
10199
10200/**
10201 * get collection of Flickity.Cells, given Elements
10202 * @param {[Element, Array, NodeList]} elems - multiple elements
10203 * @returns {Array} cells - Flickity.Cells
10204 */
10205proto.getCells = function( elems ) {
10206  elems = utils.makeArray( elems );
10207  return elems.map( ( elem ) => this.getCell( elem ) ).filter( Boolean );
10208};
10209
10210/**
10211 * get cell elements
10212 * @returns {Array} cellElems
10213 */
10214proto.getCellElements = function() {
10215  return this.cells.map( ( cell ) => cell.element );
10216};
10217
10218/**
10219 * get parent cell from an element
10220 * @param {Element} elem - child element
10221 * @returns {Flickit.Cell} cell - parent cell
10222 */
10223proto.getParentCell = function( elem ) {
10224  // first check if elem is cell
10225  let cell = this.getCell( elem );
10226  if ( cell ) return cell;
10227
10228  // try to get parent cell elem
10229  let closest = elem.closest('.flickity-slider > *');
10230  return this.getCell( closest );
10231};
10232
10233/**
10234 * get cells adjacent to a slide
10235 * @param {Integer} adjCount - number of adjacent slides
10236 * @param {Integer} index - index of slide to start
10237 * @returns {Array} cells - array of Flickity.Cells
10238 */
10239proto.getAdjacentCellElements = function( adjCount, index ) {
10240  if ( !adjCount ) return this.selectedSlide.getCellElements();
10241
10242  index = index === undefined ? this.selectedIndex : index;
10243
10244  let len = this.slides.length;
10245  if ( 1 + ( adjCount * 2 ) >= len ) {
10246    return this.getCellElements(); // get all
10247  }
10248
10249  let cellElems = [];
10250  for ( let i = index - adjCount; i <= index + adjCount; i++ ) {
10251    let slideIndex = this.isWrapping ? utils.modulo( i, len ) : i;
10252    let slide = this.slides[ slideIndex ];
10253    if ( slide ) {
10254      cellElems = cellElems.concat( slide.getCellElements() );
10255    }
10256  }
10257  return cellElems;
10258};
10259
10260/**
10261 * select slide from number or cell element
10262 * @param {[Element, String, Number]} selector - element, selector string, or index
10263 * @returns {Flickity.Cell} - matching cell
10264 */
10265proto.queryCell = function( selector ) {
10266  if ( typeof selector == 'number' ) {
10267    // use number as index
10268    return this.cells[ selector ];
10269  }
10270  // do not select invalid selectors from hash: #123, #/. #791
10271  let isSelectorString = typeof selector == 'string' && !selector.match( /^[#.]?[\d/]/ );
10272  if ( isSelectorString ) {
10273    // use string as selector, get element
10274    selector = this.element.querySelector( selector );
10275  }
10276  // get cell from element
10277  return this.getCell( selector );
10278};
10279
10280// -------------------------- events -------------------------- //
10281
10282proto.uiChange = function() {
10283  this.emitEvent('uiChange');
10284};
10285
10286// ----- resize ----- //
10287
10288proto.onresize = function() {
10289  this.watchCSS();
10290  this.resize();
10291};
10292
10293utils.debounceMethod( Flickity, 'onresize', 150 );
10294
10295proto.resize = function() {
10296  // #1177 disable resize behavior when animating or dragging for iOS 15
10297  if ( !this.isActive || this.isAnimating || this.isDragging ) return;
10298  this.getSize();
10299  // wrap values
10300  if ( this.isWrapping ) {
10301    this.x = utils.modulo( this.x, this.slideableWidth );
10302  }
10303  this.positionCells();
10304  this._updateWrapShiftCells();
10305  this.setGallerySize();
10306  this.emitEvent('resize');
10307  // update selected index for group slides, instant
10308  // TODO: position can be lost between groups of various numbers
10309  let selectedElement = this.selectedElements && this.selectedElements[0];
10310  this.selectCell( selectedElement, false, true );
10311};
10312
10313// watches the :after property, activates/deactivates
10314proto.watchCSS = function() {
10315  if ( !this.options.watchCSS ) return;
10316
10317  let afterContent = getComputedStyle( this.element, ':after' ).content;
10318  // activate if :after { content: 'flickity' }
10319  if ( afterContent.includes('flickity') ) {
10320    this.activate();
10321  } else {
10322    this.deactivate();
10323  }
10324};
10325
10326// ----- keydown ----- //
10327
10328// go previous/next if left/right keys pressed
10329proto.onkeydown = function( event ) {
10330  let { activeElement } = document;
10331  let handler = Flickity.keyboardHandlers[ event.key ];
10332  // only work if element is in focus
10333  if ( !this.options.accessibility || !activeElement || !handler ) return;
10334
10335  let isFocused = this.focusableElems.some( ( elem ) => activeElement === elem );
10336  if ( isFocused ) handler.call( this );
10337};
10338
10339Flickity.keyboardHandlers = {
10340  ArrowLeft: function() {
10341    this.uiChange();
10342    let leftMethod = this.options.rightToLeft ? 'next' : 'previous';
10343    this[ leftMethod ]();
10344  },
10345  ArrowRight: function() {
10346    this.uiChange();
10347    let rightMethod = this.options.rightToLeft ? 'previous' : 'next';
10348    this[ rightMethod ]();
10349  },
10350};
10351
10352// ----- focus ----- //
10353
10354proto.focus = function() {
10355  this.element.focus({ preventScroll: true });
10356};
10357
10358// -------------------------- destroy -------------------------- //
10359
10360// deactivate all Flickity functionality, but keep stuff available
10361proto.deactivate = function() {
10362  if ( !this.isActive ) return;
10363
10364  this.element.classList.remove('flickity-enabled');
10365  this.element.classList.remove('flickity-rtl');
10366  this.unselectSelectedSlide();
10367  // destroy cells
10368  this.cells.forEach( ( cell ) => cell.destroy() );
10369  this.viewport.remove();
10370  // move child elements back into element
10371  this.element.append( ...this.slider.children );
10372  if ( this.options.accessibility ) {
10373    this.element.removeAttribute('tabIndex');
10374    this.element.removeEventListener( 'keydown', this );
10375  }
10376  // set flags
10377  this.isActive = false;
10378  this.emitEvent('deactivate');
10379};
10380
10381proto.destroy = function() {
10382  this.deactivate();
10383  window.removeEventListener( 'resize', this );
10384  this.allOff();
10385  this.emitEvent('destroy');
10386  if ( jQuery && this.$element ) {
10387    jQuery.removeData( this.element, 'flickity' );
10388  }
10389  delete this.element.flickityGUID;
10390  delete instances[ this.guid ];
10391};
10392
10393// -------------------------- prototype -------------------------- //
10394
10395Object.assign( proto, animatePrototype );
10396
10397// -------------------------- extras -------------------------- //
10398
10399/**
10400 * get Flickity instance from element
10401 * @param {[Element, String]} elem - element or selector string
10402 * @returns {Flickity} - Flickity instance
10403 */
10404Flickity.data = function( elem ) {
10405  elem = utils.getQueryElement( elem );
10406  if ( elem ) return instances[ elem.flickityGUID ];
10407};
10408
10409utils.htmlInit( Flickity, 'flickity' );
10410
10411let { jQueryBridget } = window;
10412if ( jQuery && jQueryBridget ) {
10413  jQueryBridget( 'flickity', Flickity, jQuery );
10414}
10415
10416// set internal jQuery, for Webpack + jQuery v3, #478
10417Flickity.setJQuery = function( jq ) {
10418  jQuery = jq;
10419};
10420
10421Flickity.Cell = Cell;
10422Flickity.Slide = Slide;
10423
10424return Flickity;
10425
10426} ) );
10427// drag
10428( function( window, factory ) {
10429  // universal module definition
10430  if ( typeof module == 'object' && module.exports ) {
10431    // CommonJS
10432    module.exports = factory(
10433        window,
10434        require('./core'),
10435        require('unidragger'),
10436        require('fizzy-ui-utils'),
10437    );
10438  } else {
10439    // browser global
10440    window.Flickity = factory(
10441        window,
10442        window.Flickity,
10443        window.Unidragger,
10444        window.fizzyUIUtils,
10445    );
10446  }
10447
10448}( typeof window != 'undefined' ? window : this,
10449    function factory( window, Flickity, Unidragger, utils ) {
10450
10451// ----- defaults ----- //
10452
10453Object.assign( Flickity.defaults, {
10454  draggable: '>1',
10455  dragThreshold: 3,
10456} );
10457
10458// -------------------------- drag prototype -------------------------- //
10459
10460let proto = Flickity.prototype;
10461Object.assign( proto, Unidragger.prototype ); // inherit Unidragger
10462proto.touchActionValue = '';
10463
10464// --------------------------  -------------------------- //
10465
10466Flickity.create.drag = function() {
10467  this.on( 'activate', this.onActivateDrag );
10468  this.on( 'uiChange', this._uiChangeDrag );
10469  this.on( 'deactivate', this.onDeactivateDrag );
10470  this.on( 'cellChange', this.updateDraggable );
10471  this.on( 'pointerDown', this.handlePointerDown );
10472  this.on( 'pointerUp', this.handlePointerUp );
10473  this.on( 'pointerDown', this.handlePointerDone );
10474  this.on( 'dragStart', this.handleDragStart );
10475  this.on( 'dragMove', this.handleDragMove );
10476  this.on( 'dragEnd', this.handleDragEnd );
10477  this.on( 'staticClick', this.handleStaticClick );
10478  // TODO updateDraggable on resize? if groupCells & slides change
10479};
10480
10481proto.onActivateDrag = function() {
10482  this.handles = [ this.viewport ];
10483  this.bindHandles();
10484  this.updateDraggable();
10485};
10486
10487proto.onDeactivateDrag = function() {
10488  this.unbindHandles();
10489  this.element.classList.remove('is-draggable');
10490};
10491
10492proto.updateDraggable = function() {
10493  // disable dragging if less than 2 slides. #278
10494  if ( this.options.draggable === '>1' ) {
10495    this.isDraggable = this.slides.length > 1;
10496  } else {
10497    this.isDraggable = this.options.draggable;
10498  }
10499  this.element.classList.toggle( 'is-draggable', this.isDraggable );
10500};
10501
10502proto._uiChangeDrag = function() {
10503  delete this.isFreeScrolling;
10504};
10505
10506// -------------------------- pointer events -------------------------- //
10507
10508proto.handlePointerDown = function( event ) {
10509  if ( !this.isDraggable ) {
10510    // proceed for staticClick
10511    this.bindActivePointerEvents( event );
10512    return;
10513  }
10514
10515  let isTouchStart = event.type === 'touchstart';
10516  let isTouchPointer = event.pointerType === 'touch';
10517  let isFocusNode = event.target.matches('input, textarea, select');
10518  if ( !isTouchStart && !isTouchPointer && !isFocusNode ) event.preventDefault();
10519  if ( !isFocusNode ) this.focus();
10520  // blur
10521  if ( document.activeElement !== this.element ) document.activeElement.blur();
10522  // stop if it was moving
10523  this.dragX = this.x;
10524  this.viewport.classList.add('is-pointer-down');
10525  // track scrolling
10526  this.pointerDownScroll = getScrollPosition();
10527  window.addEventListener( 'scroll', this );
10528  this.bindActivePointerEvents( event );
10529};
10530
10531// ----- move ----- //
10532
10533proto.hasDragStarted = function( moveVector ) {
10534  return Math.abs( moveVector.x ) > this.options.dragThreshold;
10535};
10536
10537// ----- up ----- //
10538
10539proto.handlePointerUp = function() {
10540  delete this.isTouchScrolling;
10541  this.viewport.classList.remove('is-pointer-down');
10542};
10543
10544proto.handlePointerDone = function() {
10545  window.removeEventListener( 'scroll', this );
10546  delete this.pointerDownScroll;
10547};
10548
10549// -------------------------- dragging -------------------------- //
10550
10551proto.handleDragStart = function() {
10552  if ( !this.isDraggable ) return;
10553
10554  this.dragStartPosition = this.x;
10555  this.startAnimation();
10556  window.removeEventListener( 'scroll', this );
10557};
10558
10559proto.handleDragMove = function( event, pointer, moveVector ) {
10560  if ( !this.isDraggable ) return;
10561
10562  event.preventDefault();
10563
10564  this.previousDragX = this.dragX;
10565  // reverse if right-to-left
10566  let direction = this.options.rightToLeft ? -1 : 1;
10567  // wrap around move. #589
10568  if ( this.isWrapping ) moveVector.x %= this.slideableWidth;
10569  let dragX = this.dragStartPosition + moveVector.x * direction;
10570
10571  if ( !this.isWrapping ) {
10572    // slow drag
10573    let originBound = Math.max( -this.slides[0].target, this.dragStartPosition );
10574    dragX = dragX > originBound ? ( dragX + originBound ) * 0.5 : dragX;
10575    let endBound = Math.min( -this.getLastSlide().target, this.dragStartPosition );
10576    dragX = dragX < endBound ? ( dragX + endBound ) * 0.5 : dragX;
10577  }
10578
10579  this.dragX = dragX;
10580  this.dragMoveTime = new Date();
10581};
10582
10583proto.handleDragEnd = function() {
10584  if ( !this.isDraggable ) return;
10585
10586  let { freeScroll } = this.options;
10587  if ( freeScroll ) this.isFreeScrolling = true;
10588  // set selectedIndex based on where flick will end up
10589  let index = this.dragEndRestingSelect();
10590
10591  if ( freeScroll && !this.isWrapping ) {
10592    // if free-scroll & not wrap around
10593    // do not free-scroll if going outside of bounding slides
10594    // so bounding slides can attract slider, and keep it in bounds
10595    let restingX = this.getRestingPosition();
10596    this.isFreeScrolling = -restingX > this.slides[0].target &&
10597      -restingX < this.getLastSlide().target;
10598  } else if ( !freeScroll && index === this.selectedIndex ) {
10599    // boost selection if selected index has not changed
10600    index += this.dragEndBoostSelect();
10601  }
10602  delete this.previousDragX;
10603  // apply selection
10604  // HACK, set flag so dragging stays in correct direction
10605  this.isDragSelect = this.isWrapping;
10606  this.select( index );
10607  delete this.isDragSelect;
10608};
10609
10610proto.dragEndRestingSelect = function() {
10611  let restingX = this.getRestingPosition();
10612  // how far away from selected slide
10613  let distance = Math.abs( this.getSlideDistance( -restingX, this.selectedIndex ) );
10614  // get closet resting going up and going down
10615  let positiveResting = this._getClosestResting( restingX, distance, 1 );
10616  let negativeResting = this._getClosestResting( restingX, distance, -1 );
10617  // use closer resting for wrap-around
10618  return positiveResting.distance < negativeResting.distance ?
10619    positiveResting.index : negativeResting.index;
10620};
10621
10622/**
10623 * given resting X and distance to selected cell
10624 * get the distance and index of the closest cell
10625 * @param {Number} restingX - estimated post-flick resting position
10626 * @param {Number} distance - distance to selected cell
10627 * @param {Integer} increment - +1 or -1, going up or down
10628 * @returns {Object} - { distance: {Number}, index: {Integer} }
10629 */
10630proto._getClosestResting = function( restingX, distance, increment ) {
10631  let index = this.selectedIndex;
10632  let minDistance = Infinity;
10633  let condition = this.options.contain && !this.isWrapping ?
10634    // if containing, keep going if distance is equal to minDistance
10635    ( dist, minDist ) => dist <= minDist :
10636    ( dist, minDist ) => dist < minDist;
10637
10638  while ( condition( distance, minDistance ) ) {
10639    // measure distance to next cell
10640    index += increment;
10641    minDistance = distance;
10642    distance = this.getSlideDistance( -restingX, index );
10643    if ( distance === null ) break;
10644
10645    distance = Math.abs( distance );
10646  }
10647  return {
10648    distance: minDistance,
10649    // selected was previous index
10650    index: index - increment,
10651  };
10652};
10653
10654/**
10655 * measure distance between x and a slide target
10656 * @param {Number} x - horizontal position
10657 * @param {Integer} index - slide index
10658 * @returns {Number} - slide distance
10659 */
10660proto.getSlideDistance = function( x, index ) {
10661  let len = this.slides.length;
10662  // wrap around if at least 2 slides
10663  let isWrapAround = this.options.wrapAround && len > 1;
10664  let slideIndex = isWrapAround ? utils.modulo( index, len ) : index;
10665  let slide = this.slides[ slideIndex ];
10666  if ( !slide ) return null;
10667
10668  // add distance for wrap-around slides
10669  let wrap = isWrapAround ? this.slideableWidth * Math.floor( index/len ) : 0;
10670  return x - ( slide.target + wrap );
10671};
10672
10673proto.dragEndBoostSelect = function() {
10674  // do not boost if no previousDragX or dragMoveTime
10675  if ( this.previousDragX === undefined || !this.dragMoveTime ||
10676    // or if drag was held for 100 ms
10677    new Date() - this.dragMoveTime > 100 ) {
10678    return 0;
10679  }
10680
10681  let distance = this.getSlideDistance( -this.dragX, this.selectedIndex );
10682  let delta = this.previousDragX - this.dragX;
10683  if ( distance > 0 && delta > 0 ) {
10684    // boost to next if moving towards the right, and positive velocity
10685    return 1;
10686  } else if ( distance < 0 && delta < 0 ) {
10687    // boost to previous if moving towards the left, and negative velocity
10688    return -1;
10689  }
10690  return 0;
10691};
10692
10693// ----- scroll ----- //
10694
10695proto.onscroll = function() {
10696  let scroll = getScrollPosition();
10697  let scrollMoveX = this.pointerDownScroll.x - scroll.x;
10698  let scrollMoveY = this.pointerDownScroll.y - scroll.y;
10699  // cancel click/tap if scroll is too much
10700  if ( Math.abs( scrollMoveX ) > 3 || Math.abs( scrollMoveY ) > 3 ) {
10701    this.pointerDone();
10702  }
10703};
10704
10705// ----- utils ----- //
10706
10707function getScrollPosition() {
10708  return {
10709    x: window.pageXOffset,
10710    y: window.pageYOffset,
10711  };
10712}
10713
10714// -----  ----- //
10715
10716return Flickity;
10717
10718} ) );
10719// prev/next buttons
10720( function( window, factory ) {
10721  // universal module definition
10722  if ( typeof module == 'object' && module.exports ) {
10723    // CommonJS
10724    module.exports = factory( require('./core') );
10725  } else {
10726    // browser global
10727    factory( window.Flickity );
10728  }
10729
10730}( typeof window != 'undefined' ? window : this, function factory( Flickity ) {
10731
10732const svgURI = 'http://www.w3.org/2000/svg';
10733
10734// -------------------------- PrevNextButton -------------------------- //
10735
10736function PrevNextButton( increment, direction, arrowShape ) {
10737  this.increment = increment;
10738  this.direction = direction;
10739  this.isPrevious = increment === 'previous';
10740  this.isLeft = direction === 'left';
10741  this._create( arrowShape );
10742}
10743
10744PrevNextButton.prototype._create = function( arrowShape ) {
10745  // properties
10746  let element = this.element = document.createElement('button');
10747  element.className = `flickity-button flickity-prev-next-button ${this.increment}`;
10748  let label = this.isPrevious ? 'Previous' : 'Next';
10749  // prevent button from submitting form https://stackoverflow.com/a/10836076/182183
10750  element.setAttribute( 'type', 'button' );
10751  element.setAttribute( 'aria-label', label );
10752  // init as disabled
10753  this.disable();
10754  // create arrow
10755  let svg = this.createSVG( label, arrowShape );
10756  element.append( svg );
10757};
10758
10759PrevNextButton.prototype.createSVG = function( label, arrowShape ) {
10760  let svg = document.createElementNS( svgURI, 'svg' );
10761  svg.setAttribute( 'class', 'flickity-button-icon' );
10762  svg.setAttribute( 'viewBox', '0 0 100 100' );
10763  // add title #1189
10764  let title = document.createElementNS( svgURI, 'title' );
10765  title.append( label );
10766  // add path
10767  let path = document.createElementNS( svgURI, 'path' );
10768  let pathMovements = getArrowMovements( arrowShape );
10769  path.setAttribute( 'd', pathMovements );
10770  path.setAttribute( 'class', 'arrow' );
10771  // rotate arrow
10772  if ( !this.isLeft ) {
10773    path.setAttribute( 'transform', 'translate(100, 100) rotate(180)' );
10774  }
10775  svg.append( title, path );
10776  return svg;
10777};
10778
10779// get SVG path movmement
10780function getArrowMovements( shape ) {
10781  // use shape as movement if string
10782  if ( typeof shape == 'string' ) return shape;
10783
10784  let { x0, x1, x2, x3, y1, y2 } = shape;
10785
10786  // create movement string
10787  return `M ${x0}, 50
10788    L ${x1}, ${y1 + 50}
10789    L ${x2}, ${y2 + 50}
10790    L ${x3}, 50
10791    L ${x2}, ${50 - y2}
10792    L ${x1}, ${50 - y1}
10793    Z`;
10794}
10795
10796// -----  ----- //
10797
10798PrevNextButton.prototype.enable = function() {
10799  this.element.removeAttribute('disabled');
10800};
10801
10802PrevNextButton.prototype.disable = function() {
10803  this.element.setAttribute( 'disabled', true );
10804};
10805
10806// -------------------------- Flickity prototype -------------------------- //
10807
10808Object.assign( Flickity.defaults, {
10809  prevNextButtons: true,
10810  arrowShape: {
10811    x0: 10,
10812    x1: 60, y1: 50,
10813    x2: 70, y2: 40,
10814    x3: 30,
10815  },
10816} );
10817
10818Flickity.create.prevNextButtons = function() {
10819  if ( !this.options.prevNextButtons ) return;
10820
10821  let { rightToLeft, arrowShape } = this.options;
10822  let prevDirection = rightToLeft ? 'right' : 'left';
10823  let nextDirection = rightToLeft ? 'left' : 'right';
10824  this.prevButton = new PrevNextButton( 'previous', prevDirection, arrowShape );
10825  this.nextButton = new PrevNextButton( 'next', nextDirection, arrowShape );
10826  this.focusableElems.push( this.prevButton.element );
10827  this.focusableElems.push( this.nextButton.element );
10828
10829  this.handlePrevButtonClick = () => {
10830    this.uiChange();
10831    this.previous();
10832  };
10833
10834  this.handleNextButtonClick = () => {
10835    this.uiChange();
10836    this.next();
10837  };
10838
10839  this.on( 'activate', this.activatePrevNextButtons );
10840  this.on( 'select', this.updatePrevNextButtons );
10841};
10842
10843let proto = Flickity.prototype;
10844
10845proto.updatePrevNextButtons = function() {
10846  let lastIndex = this.slides.length ? this.slides.length - 1 : 0;
10847  this.updatePrevNextButton( this.prevButton, 0 );
10848  this.updatePrevNextButton( this.nextButton, lastIndex );
10849};
10850
10851proto.updatePrevNextButton = function( button, disabledIndex ) {
10852  // enable is wrapAround and at least 2 slides
10853  if ( this.isWrapping && this.slides.length > 1 ) {
10854    button.enable();
10855    return;
10856  }
10857
10858  let isEnabled = this.selectedIndex !== disabledIndex;
10859  button[ isEnabled ? 'enable' : 'disable' ]();
10860  // if disabling button that is focused,
10861  // shift focus to element to maintain keyboard accessibility
10862  let isDisabledFocused = !isEnabled && document.activeElement === button.element;
10863  if ( isDisabledFocused ) this.focus();
10864};
10865
10866proto.activatePrevNextButtons = function() {
10867  this.prevButton.element.addEventListener( 'click', this.handlePrevButtonClick );
10868  this.nextButton.element.addEventListener( 'click', this.handleNextButtonClick );
10869  this.element.append( this.prevButton.element, this.nextButton.element );
10870  this.on( 'deactivate', this.deactivatePrevNextButtons );
10871};
10872
10873proto.deactivatePrevNextButtons = function() {
10874  this.prevButton.element.remove();
10875  this.nextButton.element.remove();
10876  this.prevButton.element.removeEventListener( 'click', this.handlePrevButtonClick );
10877  this.nextButton.element.removeEventListener( 'click', this.handleNextButtonClick );
10878  this.off( 'deactivate', this.deactivatePrevNextButtons );
10879};
10880
10881// --------------------------  -------------------------- //
10882
10883Flickity.PrevNextButton = PrevNextButton;
10884
10885return Flickity;
10886
10887} ) );
10888// page dots
10889( function( window, factory ) {
10890  // universal module definition
10891  if ( typeof module == 'object' && module.exports ) {
10892    // CommonJS
10893    module.exports = factory(
10894        require('./core'),
10895        require('fizzy-ui-utils'),
10896    );
10897  } else {
10898    // browser global
10899    factory(
10900        window.Flickity,
10901        window.fizzyUIUtils,
10902    );
10903  }
10904
10905}( typeof window != 'undefined' ? window : this, function factory( Flickity, utils ) {
10906
10907// -------------------------- PageDots -------------------------- //
10908
10909function PageDots() {
10910  // create holder element
10911  this.holder = document.createElement('div');
10912  this.holder.className = 'flickity-page-dots';
10913  // create dots, array of elements
10914  this.dots = [];
10915}
10916
10917PageDots.prototype.setDots = function( slidesLength ) {
10918  // get difference between number of slides and number of dots
10919  let delta = slidesLength - this.dots.length;
10920  if ( delta > 0 ) {
10921    this.addDots( delta );
10922  } else if ( delta < 0 ) {
10923    this.removeDots( -delta );
10924  }
10925};
10926
10927PageDots.prototype.addDots = function( count ) {
10928  let newDots = new Array( count ).fill()
10929    .map( ( item, i ) => {
10930      let dot = document.createElement('button');
10931      dot.setAttribute( 'type', 'button' );
10932      let num = i + 1 + this.dots.length;
10933      dot.className = 'flickity-page-dot';
10934      dot.textContent = `View slide ${num}`;
10935      return dot;
10936    } );
10937
10938  this.holder.append( ...newDots );
10939  this.dots = this.dots.concat( newDots );
10940};
10941
10942PageDots.prototype.removeDots = function( count ) {
10943  // remove from this.dots collection
10944  let removeDots = this.dots.splice( this.dots.length - count, count );
10945  // remove from DOM
10946  removeDots.forEach( ( dot ) => dot.remove() );
10947};
10948
10949PageDots.prototype.updateSelected = function( index ) {
10950  // remove selected class on previous
10951  if ( this.selectedDot ) {
10952    this.selectedDot.classList.remove('is-selected');
10953    this.selectedDot.removeAttribute('aria-current');
10954  }
10955  // don't proceed if no dots
10956  if ( !this.dots.length ) return;
10957
10958  this.selectedDot = this.dots[ index ];
10959  this.selectedDot.classList.add('is-selected');
10960  this.selectedDot.setAttribute( 'aria-current', 'step' );
10961};
10962
10963Flickity.PageDots = PageDots;
10964
10965// -------------------------- Flickity -------------------------- //
10966
10967Object.assign( Flickity.defaults, {
10968  pageDots: true,
10969} );
10970
10971Flickity.create.pageDots = function() {
10972  if ( !this.options.pageDots ) return;
10973
10974  this.pageDots = new PageDots();
10975  this.handlePageDotsClick = this.onPageDotsClick.bind( this );
10976  // events
10977  this.on( 'activate', this.activatePageDots );
10978  this.on( 'select', this.updateSelectedPageDots );
10979  this.on( 'cellChange', this.updatePageDots );
10980  this.on( 'resize', this.updatePageDots );
10981  this.on( 'deactivate', this.deactivatePageDots );
10982};
10983
10984let proto = Flickity.prototype;
10985
10986proto.activatePageDots = function() {
10987  this.pageDots.setDots( this.slides.length );
10988  this.focusableElems.push( ...this.pageDots.dots );
10989  this.pageDots.holder.addEventListener( 'click', this.handlePageDotsClick );
10990  this.element.append( this.pageDots.holder );
10991};
10992
10993proto.onPageDotsClick = function( event ) {
10994  let index = this.pageDots.dots.indexOf( event.target );
10995  if ( index === -1 ) return; // only dot clicks
10996
10997  this.uiChange();
10998  this.select( index );
10999};
11000
11001proto.updateSelectedPageDots = function() {
11002  this.pageDots.updateSelected( this.selectedIndex );
11003};
11004
11005proto.updatePageDots = function() {
11006  this.pageDots.dots.forEach( ( dot ) => {
11007    utils.removeFrom( this.focusableElems, dot );
11008  } );
11009  this.pageDots.setDots( this.slides.length );
11010  this.focusableElems.push( ...this.pageDots.dots );
11011};
11012
11013proto.deactivatePageDots = function() {
11014  this.pageDots.holder.remove();
11015  this.pageDots.holder.removeEventListener( 'click', this.handlePageDotsClick );
11016};
11017
11018// -----  ----- //
11019
11020Flickity.PageDots = PageDots;
11021
11022return Flickity;
11023
11024} ) );
11025// player & autoPlay
11026( function( window, factory ) {
11027  // universal module definition
11028  if ( typeof module == 'object' && module.exports ) {
11029    // CommonJS
11030    module.exports = factory( require('./core') );
11031  } else {
11032    // browser global
11033    factory( window.Flickity );
11034  }
11035
11036}( typeof window != 'undefined' ? window : this, function factory( Flickity ) {
11037
11038// -------------------------- Player -------------------------- //
11039
11040function Player( autoPlay, onTick ) {
11041  this.autoPlay = autoPlay;
11042  this.onTick = onTick;
11043  this.state = 'stopped';
11044  // visibility change event handler
11045  this.onVisibilityChange = this.visibilityChange.bind( this );
11046  this.onVisibilityPlay = this.visibilityPlay.bind( this );
11047}
11048
11049// start play
11050Player.prototype.play = function() {
11051  if ( this.state === 'playing' ) return;
11052
11053  // do not play if page is hidden, start playing when page is visible
11054  let isPageHidden = document.hidden;
11055  if ( isPageHidden ) {
11056    document.addEventListener( 'visibilitychange', this.onVisibilityPlay );
11057    return;
11058  }
11059
11060  this.state = 'playing';
11061  // listen to visibility change
11062  document.addEventListener( 'visibilitychange', this.onVisibilityChange );
11063  // start ticking
11064  this.tick();
11065};
11066
11067Player.prototype.tick = function() {
11068  // do not tick if not playing
11069  if ( this.state !== 'playing' ) return;
11070
11071  // default to 3 seconds
11072  let time = typeof this.autoPlay == 'number' ? this.autoPlay : 3000;
11073  // HACK: reset ticks if stopped and started within interval
11074  this.clear();
11075  this.timeout = setTimeout( () => {
11076    this.onTick();
11077    this.tick();
11078  }, time );
11079};
11080
11081Player.prototype.stop = function() {
11082  this.state = 'stopped';
11083  this.clear();
11084  // remove visibility change event
11085  document.removeEventListener( 'visibilitychange', this.onVisibilityChange );
11086};
11087
11088Player.prototype.clear = function() {
11089  clearTimeout( this.timeout );
11090};
11091
11092Player.prototype.pause = function() {
11093  if ( this.state === 'playing' ) {
11094    this.state = 'paused';
11095    this.clear();
11096  }
11097};
11098
11099Player.prototype.unpause = function() {
11100  // re-start play if paused
11101  if ( this.state === 'paused' ) this.play();
11102};
11103
11104// pause if page visibility is hidden, unpause if visible
11105Player.prototype.visibilityChange = function() {
11106  let isPageHidden = document.hidden;
11107  this[ isPageHidden ? 'pause' : 'unpause' ]();
11108};
11109
11110Player.prototype.visibilityPlay = function() {
11111  this.play();
11112  document.removeEventListener( 'visibilitychange', this.onVisibilityPlay );
11113};
11114
11115// -------------------------- Flickity -------------------------- //
11116
11117Object.assign( Flickity.defaults, {
11118  pauseAutoPlayOnHover: true,
11119} );
11120
11121Flickity.create.player = function() {
11122  this.player = new Player( this.options.autoPlay, () => {
11123    this.next( true );
11124  } );
11125
11126  this.on( 'activate', this.activatePlayer );
11127  this.on( 'uiChange', this.stopPlayer );
11128  this.on( 'pointerDown', this.stopPlayer );
11129  this.on( 'deactivate', this.deactivatePlayer );
11130};
11131
11132let proto = Flickity.prototype;
11133
11134proto.activatePlayer = function() {
11135  if ( !this.options.autoPlay ) return;
11136
11137  this.player.play();
11138  this.element.addEventListener( 'mouseenter', this );
11139};
11140
11141// Player API, don't hate the ... thanks I know where the door is
11142
11143proto.playPlayer = function() {
11144  this.player.play();
11145};
11146
11147proto.stopPlayer = function() {
11148  this.player.stop();
11149};
11150
11151proto.pausePlayer = function() {
11152  this.player.pause();
11153};
11154
11155proto.unpausePlayer = function() {
11156  this.player.unpause();
11157};
11158
11159proto.deactivatePlayer = function() {
11160  this.player.stop();
11161  this.element.removeEventListener( 'mouseenter', this );
11162};
11163
11164// ----- mouseenter/leave ----- //
11165
11166// pause auto-play on hover
11167proto.onmouseenter = function() {
11168  if ( !this.options.pauseAutoPlayOnHover ) return;
11169
11170  this.player.pause();
11171  this.element.addEventListener( 'mouseleave', this );
11172};
11173
11174// resume auto-play on hover off
11175proto.onmouseleave = function() {
11176  this.player.unpause();
11177  this.element.removeEventListener( 'mouseleave', this );
11178};
11179
11180// -----  ----- //
11181
11182Flickity.Player = Player;
11183
11184return Flickity;
11185
11186} ) );
11187// add, remove cell
11188( function( window, factory ) {
11189  // universal module definition
11190  if ( typeof module == 'object' && module.exports ) {
11191    // CommonJS
11192    module.exports = factory(
11193        require('./core'),
11194        require('fizzy-ui-utils'),
11195    );
11196  } else {
11197    // browser global
11198    factory(
11199        window.Flickity,
11200        window.fizzyUIUtils,
11201    );
11202  }
11203
11204}( typeof window != 'undefined' ? window : this, function factory( Flickity, utils ) {
11205
11206// append cells to a document fragment
11207function getCellsFragment( cells ) {
11208  let fragment = document.createDocumentFragment();
11209  cells.forEach( ( cell ) => fragment.appendChild( cell.element ) );
11210  return fragment;
11211}
11212
11213// -------------------------- add/remove cell prototype -------------------------- //
11214
11215let proto = Flickity.prototype;
11216
11217/**
11218 * Insert, prepend, or append cells
11219 * @param {[Element, Array, NodeList]} elems - Elements to insert
11220 * @param {Integer} index - Zero-based number to insert
11221 */
11222proto.insert = function( elems, index ) {
11223  let cells = this._makeCells( elems );
11224  if ( !cells || !cells.length ) return;
11225
11226  let len = this.cells.length;
11227  // default to append
11228  index = index === undefined ? len : index;
11229  // add cells with document fragment
11230  let fragment = getCellsFragment( cells );
11231  // append to slider
11232  let isAppend = index === len;
11233  if ( isAppend ) {
11234    this.slider.appendChild( fragment );
11235  } else {
11236    let insertCellElement = this.cells[ index ].element;
11237    this.slider.insertBefore( fragment, insertCellElement );
11238  }
11239  // add to this.cells
11240  if ( index === 0 ) {
11241    // prepend, add to start
11242    this.cells = cells.concat( this.cells );
11243  } else if ( isAppend ) {
11244    // append, add to end
11245    this.cells = this.cells.concat( cells );
11246  } else {
11247    // insert in this.cells
11248    let endCells = this.cells.splice( index, len - index );
11249    this.cells = this.cells.concat( cells ).concat( endCells );
11250  }
11251
11252  this._sizeCells( cells );
11253  this.cellChange( index );
11254  this.positionSliderAtSelected();
11255};
11256
11257proto.append = function( elems ) {
11258  this.insert( elems, this.cells.length );
11259};
11260
11261proto.prepend = function( elems ) {
11262  this.insert( elems, 0 );
11263};
11264
11265/**
11266 * Remove cells
11267 * @param {[Element, Array, NodeList]} elems - ELements to remove
11268 */
11269proto.remove = function( elems ) {
11270  let cells = this.getCells( elems );
11271  if ( !cells || !cells.length ) return;
11272
11273  let minCellIndex = this.cells.length - 1;
11274  // remove cells from collection & DOM
11275  cells.forEach( ( cell ) => {
11276    cell.remove();
11277    let index = this.cells.indexOf( cell );
11278    minCellIndex = Math.min( index, minCellIndex );
11279    utils.removeFrom( this.cells, cell );
11280  } );
11281
11282  this.cellChange( minCellIndex );
11283  this.positionSliderAtSelected();
11284};
11285
11286/**
11287 * logic to be run after a cell's size changes
11288 * @param {Element} elem - cell's element
11289 */
11290proto.cellSizeChange = function( elem ) {
11291  let cell = this.getCell( elem );
11292  if ( !cell ) return;
11293
11294  cell.getSize();
11295
11296  let index = this.cells.indexOf( cell );
11297  this.cellChange( index );
11298  // do not position slider after lazy load
11299};
11300
11301/**
11302 * logic any time a cell is changed: added, removed, or size changed
11303 * @param {Integer} changedCellIndex - index of the changed cell, optional
11304 */
11305proto.cellChange = function( changedCellIndex ) {
11306  let prevSelectedElem = this.selectedElement;
11307  this._positionCells( changedCellIndex );
11308  this._updateWrapShiftCells();
11309  this.setGallerySize();
11310  // update selectedIndex, try to maintain position & select previous selected element
11311  let cell = this.getCell( prevSelectedElem );
11312  if ( cell ) this.selectedIndex = this.getCellSlideIndex( cell );
11313  this.selectedIndex = Math.min( this.slides.length - 1, this.selectedIndex );
11314
11315  this.emitEvent( 'cellChange', [ changedCellIndex ] );
11316  // position slider
11317  this.select( this.selectedIndex );
11318};
11319
11320// -----  ----- //
11321
11322return Flickity;
11323
11324} ) );
11325// lazyload
11326( function( window, factory ) {
11327  // universal module definition
11328  if ( typeof module == 'object' && module.exports ) {
11329    // CommonJS
11330    module.exports = factory(
11331        require('./core'),
11332        require('fizzy-ui-utils'),
11333    );
11334  } else {
11335    // browser global
11336    factory(
11337        window.Flickity,
11338        window.fizzyUIUtils,
11339    );
11340  }
11341
11342}( typeof window != 'undefined' ? window : this, function factory( Flickity, utils ) {
11343
11344const lazyAttr = 'data-flickity-lazyload';
11345const lazySrcAttr = `${lazyAttr}-src`;
11346const lazySrcsetAttr = `${lazyAttr}-srcset`;
11347const imgSelector = `img[${lazyAttr}], img[${lazySrcAttr}], ` +
11348  `img[${lazySrcsetAttr}], source[${lazySrcsetAttr}]`;
11349
11350Flickity.create.lazyLoad = function() {
11351  this.on( 'select', this.lazyLoad );
11352
11353  this.handleLazyLoadComplete = this.onLazyLoadComplete.bind( this );
11354};
11355
11356let proto = Flickity.prototype;
11357
11358proto.lazyLoad = function() {
11359  let { lazyLoad } = this.options;
11360  if ( !lazyLoad ) return;
11361
11362  // get adjacent cells, use lazyLoad option for adjacent count
11363  let adjCount = typeof lazyLoad == 'number' ? lazyLoad : 0;
11364  // lazy load images
11365  this.getAdjacentCellElements( adjCount )
11366    .map( getCellLazyImages )
11367    .flat()
11368    .forEach( ( img ) => new LazyLoader( img, this.handleLazyLoadComplete ) );
11369};
11370
11371function getCellLazyImages( cellElem ) {
11372  // check if cell element is lazy image
11373  if ( cellElem.matches('img') ) {
11374    let cellAttr = cellElem.getAttribute( lazyAttr );
11375    let cellSrcAttr = cellElem.getAttribute( lazySrcAttr );
11376    let cellSrcsetAttr = cellElem.getAttribute( lazySrcsetAttr );
11377    if ( cellAttr || cellSrcAttr || cellSrcsetAttr ) {
11378      return cellElem;
11379    }
11380  }
11381  // select lazy images in cell
11382  return [ ...cellElem.querySelectorAll( imgSelector ) ];
11383}
11384
11385proto.onLazyLoadComplete = function( img, event ) {
11386  let cell = this.getParentCell( img );
11387  let cellElem = cell && cell.element;
11388  this.cellSizeChange( cellElem );
11389
11390  this.dispatchEvent( 'lazyLoad', event, cellElem );
11391};
11392
11393// -------------------------- LazyLoader -------------------------- //
11394
11395/**
11396 * class to handle loading images
11397 * @param {Image} img - Image element
11398 * @param {Function} onComplete - callback function
11399 */
11400function LazyLoader( img, onComplete ) {
11401  this.img = img;
11402  this.onComplete = onComplete;
11403  this.load();
11404}
11405
11406LazyLoader.prototype.handleEvent = utils.handleEvent;
11407
11408LazyLoader.prototype.load = function() {
11409  this.img.addEventListener( 'load', this );
11410  this.img.addEventListener( 'error', this );
11411  // get src & srcset
11412  let src = this.img.getAttribute( lazyAttr ) ||
11413    this.img.getAttribute( lazySrcAttr );
11414  let srcset = this.img.getAttribute( lazySrcsetAttr );
11415  // set src & serset
11416  this.img.src = src;
11417  if ( srcset ) this.img.setAttribute( 'srcset', srcset );
11418  // remove attr
11419  this.img.removeAttribute( lazyAttr );
11420  this.img.removeAttribute( lazySrcAttr );
11421  this.img.removeAttribute( lazySrcsetAttr );
11422};
11423
11424LazyLoader.prototype.onload = function( event ) {
11425  this.complete( event, 'flickity-lazyloaded' );
11426};
11427
11428LazyLoader.prototype.onerror = function( event ) {
11429  this.complete( event, 'flickity-lazyerror' );
11430};
11431
11432LazyLoader.prototype.complete = function( event, className ) {
11433  // unbind events
11434  this.img.removeEventListener( 'load', this );
11435  this.img.removeEventListener( 'error', this );
11436  let mediaElem = this.img.parentNode.matches('picture') ? this.img.parentNode : this.img;
11437  mediaElem.classList.add( className );
11438
11439  this.onComplete( this.img, event );
11440};
11441
11442// -----  ----- //
11443
11444Flickity.LazyLoader = LazyLoader;
11445
11446return Flickity;
11447
11448} ) );
11449// imagesloaded
11450( function( window, factory ) {
11451  // universal module definition
11452  if ( typeof module == 'object' && module.exports ) {
11453    // CommonJS
11454    module.exports = factory(
11455        require('./core'),
11456        require('imagesloaded'),
11457    );
11458  } else {
11459    // browser global
11460    factory(
11461        window.Flickity,
11462        window.imagesLoaded,
11463    );
11464  }
11465
11466}( typeof window != 'undefined' ? window : this,
11467    function factory( Flickity, imagesLoaded ) {
11468
11469Flickity.create.imagesLoaded = function() {
11470  this.on( 'activate', this.imagesLoaded );
11471};
11472
11473Flickity.prototype.imagesLoaded = function() {
11474  if ( !this.options.imagesLoaded ) return;
11475
11476  let onImagesLoadedProgress = ( instance, image ) => {
11477    let cell = this.getParentCell( image.img );
11478    this.cellSizeChange( cell && cell.element );
11479    if ( !this.options.freeScroll ) this.positionSliderAtSelected();
11480  };
11481  imagesLoaded( this.slider ).on( 'progress', onImagesLoadedProgress );
11482};
11483
11484return Flickity;
11485
11486} ) );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.