PageSourceSearch

https://howyoungtours.com.tw/page-assert/scripts/87/zh-TW?t=639233342538652452

js howyoungtours.com.tw collected 2026-10-06 22:46:03 UTC 956,732 bytes, 28,067 lines download raw bytes

1;(function($) {var _proto = String.prototype;
2
3if (typeof _proto.regxMatch !== 'function') {
4    _proto.regxMatch = function regxMatch() {
5        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
6            regxStr = (typeof this === "string" || this instanceof String) ? this : "";
7        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
8            return x.trim();
9        }).join(' ');
10    }
11}/**
12 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
13 * ======================================================================== */
14
15/**
16 * @license
17 * ========================================================================
18 * ScrollPos-Styler v0.7.1
19 * https://github.com/acch/scrollpos-styler
20 * ========================================================================
21 * Copyright 2015 Achim Christ
22 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
23 * ======================================================================== */
24
25// JSHint directives
26/* exported ScrollPosStyler */
27if (typeof window.ScrollOverSelfStyler === "undefined") {
28    var ScrollOverSelfStyler = (function (document, window, $) {
29        "use strict";
30
31        /* ====================
32         * private variables
33         * ==================== */
34        var scrollPosY = 0,
35            busy = false,
36
37            // toggle style / class when scrolling below this position (in px)
38            scrollOffsetY = 1,
39
40            // class used to apply scrollPosStyler to
41            spsClass = "soss",
42
43            // choose elements to apply style / class to
44            elements = document.getElementsByClassName(spsClass),
45
46            // style / class to apply to elements when above scroll position
47            classAbove = "soss--abv",
48
49            // style / class to apply to elements when below scroll position
50            classBelow = "soss--blw",
51
52            // tag to set custom scroll offset per element
53            offsetTag = "data-soss-offset";
54
55        
56        var BlockSel = '.block-item',
57            ShadowKey = "ScrollOverSelfStyler";
58
59        /* ====================
60         * private function to check scroll position
61         * ==================== */
62        function onScroll() {
63
64            // ensure that events don't stack
65            if (!busy) {
66
67                // find elements to update
68                var elementsToUpdate = getElementsToUpdate(false);
69                if (elementsToUpdate.length > 0) {
70
71                    // suspend accepting scroll events
72                    busy = true;
73
74                    // asynchronuously update elements
75                    window.requestAnimationFrame(function () {
76                        updateElements(elementsToUpdate);
77                    });
78                }
79            }
80        }
81
82        /* ====================
83         * copy Element Shadow
84         * ==================== */
85        function copyElementShadow(init) {
86            for (var i = 0; elements[i]; ++i) {
87                var element = elements[i];
88                if (!$(element).data(ShadowKey)) {
89                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
90                }
91            }
92        }
93
94        /* ====================
95         * private function to find elements to update
96         * ==================== */
97        function getElementsToUpdate(init) {
98            var elementsToUpdate = [];
99            copyElementShadow(init);
100
101            // get current scroll position from window
102            scrollPosY = window.pageYOffset;
103
104            // iterate over elements
105            // for (var elem of elements) {
106            for (var i = 0; elements[i]; ++i) { // chrome workaround
107                var element = elements[i],
108                    $shadow = $(element).data(ShadowKey);
109
110                // get offset from element, default to global option
111                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
112                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
113                    shScrollOffsetY = $shadow.offset().top;
114
115                // check current state of element
116                var elOnTop = element.classList.contains(classAbove);
117
118                // check current is visible
119                var elVisible = $(element).closest(BlockSel).is(':visible');
120
121                // cols regx
122                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
123
124                // if we were above, and are now below scroll position...
125                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
126                    
127                    element.style.top = offsetTop + "px";
128                    $shadow.css('height', $(element).css('height'));
129
130                    // remember element
131                    elementsToUpdate.push({
132                        element: element,
133                        addClass: classBelow + " " + regxMatchCol,
134                        removeClass: classAbove
135                    });
136
137                    // if we were below, and are now above scroll position...
138                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
139
140
141                    // remember element
142                    elementsToUpdate.push({
143                        element: element,
144                        addClass: classAbove,
145                        removeClass: classBelow + " " + regxMatchCol
146                    });
147
148                    $shadow.get(0).style.height = null;
149                    element.style.top = null;
150                }
151            }
152
153            return elementsToUpdate;
154        }
155
156        /* ====================
157         * private function to update elements
158         * ==================== */
159        function updateElements(elementsToUpdate) {
160
161            // iterate over elements
162            // for (var elem of elements) {
163            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
164                var map = elementsToUpdate[i];
165
166                // add style / class to element
167                //map.element.classList.add(map.addClass);
168                //map.element.classList.remove(map.removeClass);
169                $(map.element).addClass(map.addClass);
170                $(map.element).removeClass(map.removeClass);
171            }
172
173            // resume accepting scroll events
174            busy = false;
175        }
176
177        /* ====================
178         * public function to initially style elements based on scroll position
179         *
180         * options:
181         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
182         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
183         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
184         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
185         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
186         *
187         * ==================== */
188        var pub = {
189            init: function (options) {
190
191                // suspend accepting scroll events
192                busy = true;
193
194                // merge options object with global options
195                if (options) {
196                    if (options.spsClass) {
197                        spsClass = options.spsClass;
198                        elements = document.getElementsByClassName(spsClass);
199                    }
200                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
201                    classAbove = options.classAbove || classAbove;
202                    classBelow = options.classBelow || classBelow;
203                    offsetTag = options.offsetTag || offsetTag;
204                }
205
206                // ensure all elements have classAbove
207                var elementsToUpdate = getElementsToUpdate(true);
208                if (elementsToUpdate.length > 0) {
209
210                    // asynchronuously update elements
211                    window.requestAnimationFrame(function () {
212                        updateElements(elementsToUpdate);
213                    });
214                } else {
215
216                    // resume accepting scroll events
217                    busy = false;
218                }
219            }
220        };
221
222        // register for window scroll events
223        $(window).on("scroll", onScroll);
224
225        window.ScrollOverSelfStyler = pub;
226
227        return pub;
228    })(document, window, jQuery);
229}
230
231/* ====================
232 * main initialization
233 * ==================== */
234$(function () {
235    // defer initialization to allow browser to restore scroll position
236    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
237});if (typeof jQuery === 'undefined') {
238    throw new Error('Block\'s JavaScript requires jQuery')
239}
240
241+function ($) {
242    'use strict';
243    var version = $.fn.jquery.split(' ')[0].split('.')
244    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
245        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
246    }
247}(jQuery);
248
249
250+function ($, win) {
251    'use strict';
252
253    var DataKey = 'blktabs',
254        BlockSel = '.block-item',
255        TabSel = '> .module-container .blk-tabs > ul',
256        BtnSel = '> li',
257        ValSel = ' > a[href^="#blk"]',
258        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
259        DestroyBeforeSymbol = 'destroyBeforeSymbol',
260        Event = {
261            ReplacedBefore: 'renderview.replace.before',
262            ReplacedAfter: 'renderview.replace.after',
263            BlockDestroy: 'destroy',
264            BlockAppear: DataKey + '.block.appear',
265            BlockHidden: DataKey + '.block.hidden',
266            Click: {
267                Window: 'blk-nav-in',
268                Before: DataKey + '.tabs.click.before',
269                After: DataKey + '.tabs.click.after'
270            }
271        },
272        Options = {
273            focus: 'active'
274        };
275
276    function BlockTabs(element, opts) {
277
278        var self = this;
279        this._opts = $.extend(Options, $(element).data(), opts);
280        this._element = element;
281        this._tabs = $(TabSel, element).get(0);
282
283        // block 更新屬性值之後將會被置換
284        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
285        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
286        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
287            $(this).addClass(ReplacedBeforeSymbol);
288            event.data.blktabs.resetTabStatus();
289            $(this).removeClass(ReplacedBeforeSymbol);
290            $.removeData(this, DataKey);
291        });
292
293        // block 被刪除前復原 tab 關聯的 block
294        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
295            $(this).addClass(DestroyBeforeSymbol);
296            event.data.blktabs.resetTabStatus();
297        });
298
299        // block tabs click 事件
300        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
301            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
302            if ($(element).attr('href').startsWith('#')) {
303                event.preventDefault();
304                event.data.blktabs.tabClick(element);
305                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
306                    target: element,
307                    detail: {
308                        selector: $(element).attr('href')
309                    }
310                }));
311            }
312        });
313
314        this.tabAppear().resetMyStatus();
315
316        var bookmarkId = window.location.href.split('#').pop();
317        if (this._element.id == bookmarkId) {
318            // 錨點跳轉
319            var blk = this;
320            window.addEventListener("load", function (event) {
321
322                var arrParentAndButton = function (blkId) {
323                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
324                    var pblk = tab.closest(BlockSel);
325                    if (pblk.length > 0 && pblk.attr('id')) {
326                        // 記錄&尋找
327                        var r = arrParentAndButton(pblk.attr('id'));
328                        r.push([pblk, tab]);
329                        return r;
330                    }
331                    return [];
332                };
333                var arr = arrParentAndButton(blk._element.id);
334                for (var i in arr)
335                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
336
337                setTimeout(function () {
338                    $("html, body").animate({
339                        scrollTop: $(blk._element).offset().top
340                    }, 500, 'swing', function () { });
341                }, 0.5 * 1000);
342            });
343        }
344    }
345
346    var _proto = BlockTabs.prototype;
347
348    _proto.tabAppear = function tabAppear() {
349        if ($(BtnSel, this._tabs).length > 0)
350            $(this._tabs).removeClass('d-none hide');
351        return this;
352    }
353
354
355    // 取得 block tabs 所有關聯的 block target
356    _proto.getTabSelector = function getTabSelector() {
357        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
358            return $(o).attr('href');
359        }).get().join(',');
360    }
361
362    // 驅動所有關聯的 block target 執行 resetMyStatus
363    _proto.resetTabStatus = function resetTabStatus(event) {
364        $(this.getTabSelector()).each(function () {
365            if ($(this).data(DataKey))
366                $(this).data(DataKey).resetMyStatus();
367        });
368        return this;
369    }
370
371    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
372    _proto.resetMyStatus = function resetMyStatus() {
373        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
374            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
375            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
376            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
377            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
378            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
379
380        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
381            // 顯示 element
382            this._element.style.setProperty('display', '');
383
384            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
385            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
386            if ($tabLink.length < 1)
387                $tabLink = $(BtnSel + ValSel, this._tabs);
388            this.tabClick($tabLink.get(0));
389            $(this._element).trigger(Event.BlockAppear);
390        }
391        else {
392            // 隱藏 element
393            this._element.style.setProperty('display', 'none', 'important');
394            $(this._element).trigger(Event.BlockHidden);
395        }
396
397        return this.resetTabStatus();
398    }
399
400    // 點擊 block tabs
401    _proto.tabClick = function tabClick(currentBtn, closure) {
402
403        // 點擊執行內容
404        if ($.contains(this._element, currentBtn)) {
405
406            // tab 切換前
407            $(this._element).trigger(Event.Click.Before, [currentBtn]);
408
409            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
410            $(currentBtn).addClass(Options.focus);
411
412            this.resetTabStatus();
413
414            // tab 切換後
415            $(this._element).trigger(Event.Click.After, [currentBtn]);
416
417            if (typeof (closure) === "function")
418                closure();
419        }
420
421        return this;
422    }
423
424    if (typeof $.fn.blockTab !== 'function') {
425
426        $.fn.extend({
427            blockTab: function (options) {
428                this.filter(function (i, o) {
429                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
430                }).each(function (event) {
431                    $(this).data(DataKey, new BlockTabs(this, options));
432                });
433            }
434        });
435    }
436
437    $(function () {
438        $(BlockSel).blockTab();
439    });
440
441}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
442;(function($) {var _proto = String.prototype;
443
444if (typeof _proto.regxMatch !== 'function') {
445    _proto.regxMatch = function regxMatch() {
446        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
447            regxStr = (typeof this === "string" || this instanceof String) ? this 
447: "";
448        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
449            return x.trim();
450        }).join(' ');
451    }
452}/**
453 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
454 * ======================================================================== */
455
456/**
457 * @license
458 * ========================================================================
459 * ScrollPos-Styler v0.7.1
460 * https://github.com/acch/scrollpos-styler
461 * ========================================================================
462 * Copyright 2015 Achim Christ
463 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
464 * ======================================================================== */
465
466// JSHint directives
467/* exported ScrollPosStyler */
468if (typeof window.ScrollOverSelfStyler === "undefined") {
469    var ScrollOverSelfStyler = (function (document, window, $) {
470        "use strict";
471
472        /* ====================
473         * private variables
474         * ==================== */
475        var scrollPosY = 0,
476            busy = false,
477
478            // toggle style / class when scrolling below this position (in px)
479            scrollOffsetY = 1,
480
481            // class used to apply scrollPosStyler to
482            spsClass = "soss",
483
484            // choose elements to apply style / class to
485            elements = document.getElementsByClassName(spsClass),
486
487            // style / class to apply to elements when above scroll position
488            classAbove = "soss--abv",
489
490            // style / class to apply to elements when below scroll position
491            classBelow = "soss--blw",
492
493            // tag to set custom scroll offset per element
494            offsetTag = "data-soss-offset";
495
496        
497        var BlockSel = '.block-item',
498            ShadowKey = "ScrollOverSelfStyler";
499
500        /* ====================
501         * private function to check scroll position
502         * ==================== */
503        function onScroll() {
504
505            // ensure that events don't stack
506            if (!busy) {
507
508                // find elements to update
509                var elementsToUpdate = getElementsToUpdate(false);
510                if (elementsToUpdate.length > 0) {
511
512                    // suspend accepting scroll events
513                    busy = true;
514
515                    // asynchronuously update elements
516                    window.requestAnimationFrame(function () {
517                        updateElements(elementsToUpdate);
518                    });
519                }
520            }
521        }
522
523        /* ====================
524         * copy Element Shadow
525         * ==================== */
526        function copyElementShadow(init) {
527            for (var i = 0; elements[i]; ++i) {
528                var element = elements[i];
529                if (!$(element).data(ShadowKey)) {
530                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
531                }
532            }
533        }
534
535        /* ====================
536         * private function to find elements to update
537         * ==================== */
538        function getElementsToUpdate(init) {
539            var elementsToUpdate = [];
540            copyElementShadow(init);
541
542            // get current scroll position from window
543            scrollPosY = window.pageYOffset;
544
545            // iterate over elements
546            // for (var elem of elements) {
547            for (var i = 0; elements[i]; ++i) { // chrome workaround
548                var element = elements[i],
549                    $shadow = $(element).data(ShadowKey);
550
551                // get offset from element, default to global option
552                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
553                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
554                    shScrollOffsetY = $shadow.offset().top;
555
556                // check current state of element
557                var elOnTop = element.classList.contains(classAbove);
558
559                // check current is visible
560                var elVisible = $(element).closest(BlockSel).is(':visible');
561
562                // cols regx
563                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
564
565                // if we were above, and are now below scroll position...
566                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
567                    
568                    element.style.top = offsetTop + "px";
569                    $shadow.css('height', $(element).css('height'));
570
571                    // remember element
572                    elementsToUpdate.push({
573                        element: element,
574                        addClass: classBelow + " " + regxMatchCol,
575                        removeClass: classAbove
576                    });
577
578                    // if we were below, and are now above scroll position...
579                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
580
581
582                    // remember element
583                    elementsToUpdate.push({
584                        element: element,
585                        addClass: classAbove,
586                        removeClass: classBelow + " " + regxMatchCol
587                    });
588
589                    $shadow.get(0).style.height = null;
590                    element.style.top = null;
591                }
592            }
593
594            return elementsToUpdate;
595        }
596
597        /* ====================
598         * private function to update elements
599         * ==================== */
600        function updateElements(elementsToUpdate) {
601
602            // iterate over elements
603            // for (var elem of elements) {
604            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
605                var map = elementsToUpdate[i];
606
607                // add style / class to element
608                //map.element.classList.add(map.addClass);
609                //map.element.classList.remove(map.removeClass);
610                $(map.element).addClass(map.addClass);
611                $(map.element).removeClass(map.removeClass);
612            }
613
614            // resume accepting scroll events
615            busy = false;
616        }
617
618        /* ====================
619         * public function to initially style elements based on scroll position
620         *
621         * options:
622         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
623         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
624         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
625         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
626         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
627         *
628         * ==================== */
629        var pub = {
630            init: function (options) {
631
632                // suspend accepting scroll events
633                busy = true;
634
635                // merge options object with global options
636                if (options) {
637                    if (options.spsClass) {
638                        spsClass = options.spsClass;
639                        elements = document.getElementsByClassName(spsClass);
640                    }
641                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
642                    classAbove = options.classAbove || classAbove;
643                    classBelow = options.classBelow || classBelow;
644                    offsetTag = options.offsetTag || offsetTag;
645                }
646
647                // ensure all elements have classAbove
648                var elementsToUpdate = getElementsToUpdate(true);
649                if (elementsToUpdate.length > 0) {
650
651                    // asynchronuously update elements
652                    window.requestAnimationFrame(function () {
653                        updateElements(elementsToUpdate);
654                    });
655                } else {
656
657                    // resume accepting scroll events
658                    busy = false;
659                }
660            }
661        };
662
663        // register for window scroll events
664        $(window).on("scroll", onScroll);
665
666        window.ScrollOverSelfStyler = pub;
667
668        return pub;
669    })(document, window, jQuery);
670}
671
672/* ====================
673 * main initialization
674 * ==================== */
675$(function () {
676    // defer initialization to allow browser to restore scroll position
677    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
678});if (typeof jQuery === 'undefined') {
679    throw new Error('Block\'s JavaScript requires jQuery')
680}
681
682+function ($) {
683    'use strict';
684    var version = $.fn.jquery.split(' ')[0].split('.')
685    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
686        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
687    }
688}(jQuery);
689
690
691+function ($, win) {
692    'use strict';
693
694    var DataKey = 'blktabs',
695        BlockSel = '.block-item',
696        TabSel = '> .module-container .blk-tabs > ul',
697        BtnSel = '> li',
698        ValSel = ' > a[href^="#blk"]',
699        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
700        DestroyBeforeSymbol = 'destroyBeforeSymbol',
701        Event = {
702            ReplacedBefore: 'renderview.replace.before',
703            ReplacedAfter: 'renderview.replace.after',
704            BlockDestroy: 'destroy',
705            BlockAppear: DataKey + '.block.appear',
706            BlockHidden: DataKey + '.block.hidden',
707            Click: {
708                Window: 'blk-nav-in',
709                Before: DataKey + '.tabs.click.before',
710                After: DataKey + '.tabs.click.after'
711            }
712        },
713        Options = {
714            focus: 'active'
715        };
716
717    function BlockTabs(element, opts) {
718
719        var self = this;
720        this._opts = $.extend(Options, $(element).data(), opts);
721        this._element = element;
722        this._tabs = $(TabSel, element).get(0);
723
724        // block 更新屬性值之後將會被置換
725        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
726        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
727        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
728            $(this).addClass(ReplacedBeforeSymbol);
729            event.data.blktabs.resetTabStatus();
730            $(this).removeClass(ReplacedBeforeSymbol);
731            $.removeData(this, DataKey);
732        });
733
734        // block 被刪除前復原 tab 關聯的 block
735        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
736            $(this).addClass(DestroyBeforeSymbol);
737            event.data.blktabs.resetTabStatus();
738        });
739
740        // block tabs click 事件
741        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
742            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
743            if ($(element).attr('href').startsWith('#')) {
744                event.preventDefault();
745                event.data.blktabs.tabClick(element);
746                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
747                    target: element,
748                    detail: {
749                        selector: $(element).attr('href')
750                    }
751                }));
752            }
753        });
754
755        this.tabAppear().resetMyStatus();
756
757        var bookmarkId = window.location.href.split('#').pop();
758        if (this._element.id == bookmarkId) {
759            // 錨點跳轉
760            var blk = this;
761            window.addEventListener("load", function (event) {
762
763                var arrParentAndButton = function (blkId) {
764                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
765                    var pblk = tab.closest(BlockSel);
766                    if (pblk.length > 0 && pblk.attr('id')) {
767                        // 記錄&尋找
768                        var r = arrParentAndButton(pblk.attr('id'));
769                        r.push([pblk, tab]);
770                        return r;
771                    }
772                    return [];
773                };
774                var arr = arrParentAndButton(blk._element.id);
775                for (var i in arr)
776                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
777
778                setTimeout(function () {
779                    $("html, body").animate({
780                        scrollTop: $(blk._element).offset().top
781                    }, 500, 'swing', function () { });
782                }, 0.5 * 1000);
783            });
784        }
785    }
786
787    var _proto = BlockTabs.prototype;
788
789    _proto.tabAppear = function tabAppear() {
790        if ($(BtnSel, this._tabs).length > 0)
791            $(this._tabs).removeClass('d-none hide');
792        return this;
793    }
794
795
796    // 取得 block tabs 所有關聯的 block target
797    _proto.getTabSelector = function getTabSelector() {
798        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
799            return $(o).attr('href');
800        }).get().join(',');
801    }
802
803    // 驅動所有關聯的 block target 執行 resetMyStatus
804    _proto.resetTabStatus = function resetTabStatus(event) {
805        $(this.getTabSelector()).each(function () {
806            if ($(this).data(DataKey))
807                $(this).data(DataKey).resetMyStatus();
808        });
809        return this;
810    }
811
812    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
813    _proto.resetMyStatus = function resetMyStatus() {
814        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
815            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
816            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
817            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
818            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
819            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
820
821        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
822            // 顯示 element
823            this._element.style.setProperty('display', '');
824
825            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
826            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
827            if ($tabLink.length < 1)
828                $tabLink = $(BtnSel + ValSel, this._tabs);
829            this.tabClick($tabLink.get(0));
830            $(this._element).trigger(Event.BlockAppear);
831        }
832        else {
833            // 隱藏 element
834            this._element.style.setProperty('display', 'none', 'important');
835            $(this._element).trigger(Event.BlockHidden);
836        }
837
838        return this.resetTabStatus();
839    }
840
841    // 點擊 block tabs
842    _proto.tabClick = function tabClick(currentBtn, closure) {
843
844        // 點擊執行內容
845        if ($.contains(this._element, currentBtn)) {
846
847            // tab 切換前
848            $(this._element).trigger(Event.Click.Before, [currentBtn]);
849
850            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
851            $(currentBtn).addClass(Options.focus);
852
853            this.resetTabStatus();
854
855            // tab 切換後
856            $(this._element).trigger(Event.Click.After, [currentBtn]);
857
858            if (typeof (closure) === "function")
859                closure();
860        }
861
862        return this;
863    }
864
865    if (typeof $.fn.blockTab !== 'function') {
866
867        $.fn.extend({
868            blockTab: function (options) {
869                this.filter(function (i, o) {
870                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
871                }).each(function (event) {
872                    $(this).data(DataKey, new BlockTabs(this, options));
873                });
874            }
875        });
876    }
877
878    $(function () {
879        $(BlockSel).blockTab();
880    });
881
882}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
883;(function($) {var _proto = String.prototype;
884
885if (typeof _proto.regxMatch !== 'function') {
886    _proto.regxMatch = function regxMatch() {
887        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
888            regxStr = (typeof this === "string" || this instanceof String) ? this 
888: "";
889        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
890            return x.trim();
891        }).join(' ');
892    }
893}/**
894 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
895 * ======================================================================== */
896
897/**
898 * @license
899 * ========================================================================
900 * ScrollPos-Styler v0.7.1
901 * https://github.com/acch/scrollpos-styler
902 * ========================================================================
903 * Copyright 2015 Achim Christ
904 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
905 * ======================================================================== */
906
907// JSHint directives
908/* exported ScrollPosStyler */
909if (typeof window.ScrollOverSelfStyler === "undefined") {
910    var ScrollOverSelfStyler = (function (document, window, $) {
911        "use strict";
912
913        /* ====================
914         * private variables
915         * ==================== */
916        var scrollPosY = 0,
917            busy = false,
918
919            // toggle style / class when scrolling below this position (in px)
920            scrollOffsetY = 1,
921
922            // class used to apply scrollPosStyler to
923            spsClass = "soss",
924
925            // choose elements to apply style / class to
926            elements = document.getElementsByClassName(spsClass),
927
928            // style / class to apply to elements when above scroll position
929            classAbove = "soss--abv",
930
931            // style / class to apply to elements when below scroll position
932            classBelow = "soss--blw",
933
934            // tag to set custom scroll offset per element
935            offsetTag = "data-soss-offset";
936
937        
938        var BlockSel = '.block-item',
939            ShadowKey = "ScrollOverSelfStyler";
940
941        /* ====================
942         * private function to check scroll position
943         * ==================== */
944        function onScroll() {
945
946            // ensure that events don't stack
947            if (!busy) {
948
949                // find elements to update
950                var elementsToUpdate = getElementsToUpdate(false);
951                if (elementsToUpdate.length > 0) {
952
953                    // suspend accepting scroll events
954                    busy = true;
955
956                    // asynchronuously update elements
957                    window.requestAnimationFrame(function () {
958                        updateElements(elementsToUpdate);
959                    });
960                }
961            }
962        }
963
964        /* ====================
965         * copy Element Shadow
966         * ==================== */
967        function copyElementShadow(init) {
968            for (var i = 0; elements[i]; ++i) {
969                var element = elements[i];
970                if (!$(element).data(ShadowKey)) {
971                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
972                }
973            }
974        }
975
976        /* ====================
977         * private function to find elements to update
978         * ==================== */
979        function getElementsToUpdate(init) {
980            var elementsToUpdate = [];
981            copyElementShadow(init);
982
983            // get current scroll position from window
984            scrollPosY = window.pageYOffset;
985
986            // iterate over elements
987            // for (var elem of elements) {
988            for (var i = 0; elements[i]; ++i) { // chrome workaround
989                var element = elements[i],
990                    $shadow = $(element).data(ShadowKey);
991
992                // get offset from element, default to global option
993                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
994                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
995                    shScrollOffsetY = $shadow.offset().top;
996
997                // check current state of element
998                var elOnTop = element.classList.contains(classAbove);
999
1000                // check current is visible
1001                var elVisible = $(element).closest(BlockSel).is(':visible');
1002
1003                // cols regx
1004                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
1005
1006                // if we were above, and are now below scroll position...
1007                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
1008                    
1009                    element.style.top = offsetTop + "px";
1010                    $shadow.css('height', $(element).css('height'));
1011
1012                    // remember element
1013                    elementsToUpdate.push({
1014                        element: element,
1015                        addClass: classBelow + " " + regxMatchCol,
1016                        removeClass: classAbove
1017                    });
1018
1019                    // if we were below, and are now above scroll position...
1020                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
1021
1022
1023                    // remember element
1024                    elementsToUpdate.push({
1025                        element: element,
1026                        addClass: classAbove,
1027                        removeClass: classBelow + " " + regxMatchCol
1028                    });
1029
1030                    $shadow.get(0).style.height = null;
1031                    element.style.top = null;
1032                }
1033            }
1034
1035            return elementsToUpdate;
1036        }
1037
1038        /* ====================
1039         * private function to update elements
1040         * ==================== */
1041        function updateElements(elementsToUpdate) {
1042
1043            // iterate over elements
1044            // for (var elem of elements) {
1045            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
1046                var map = elementsToUpdate[i];
1047
1048                // add style / class to element
1049                //map.element.classList.add(map.addClass);
1050                //map.element.classList.remove(map.removeClass);
1051                $(map.element).addClass(map.addClass);
1052                $(map.element).removeClass(map.removeClass);
1053            }
1054
1055            // resume accepting scroll events
1056            busy = false;
1057        }
1058
1059        /* ====================
1060         * public function to initially style elements based on scroll position
1061         *
1062         * options:
1063         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
1064         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
1065         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
1066         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
1067         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
1068         *
1069         * ==================== */
1070        var pub = {
1071            init: function (options) {
1072
1073                // suspend accepting scroll events
1074                busy = true;
1075
1076                // merge options object with global options
1077                if (options) {
1078                    if (options.spsClass) {
1079                        spsClass = options.spsClass;
1080                        elements = document.getElementsByClassName(spsClass);
1081                    }
1082                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
1083                    classAbove = options.classAbove || classAbove;
1084                    classBelow = options.classBelow || classBelow;
1085                    offsetTag = options.offsetTag || offsetTag;
1086                }
1087
1088                // ensure all elements have classAbove
1089                var elementsToUpdate = getElementsToUpdate(true);
1090                if (elementsToUpdate.length > 0) {
1091
1092                    // asynchronuously update elements
1093                    window.requestAnimationFrame(function () {
1094                        updateElements(elementsToUpdate);
1095                    });
1096                } else {
1097
1098                    // resume accepting scroll events
1099                    busy = false;
1100                }
1101            }
1102        };
1103
1104        // register for window scroll events
1105        $(window).on("scroll", onScroll);
1106
1107        window.ScrollOverSelfStyler = pub;
1108
1109        return pub;
1110    })(document, window, jQuery);
1111}
1112
1113/* ====================
1114 * main initialization
1115 * ==================== */
1116$(function () {
1117    // defer initialization to allow browser to restore scroll position
1118    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
1119});if (typeof jQuery === 'undefined') {
1120    throw new Error('Block\'s JavaScript requires jQuery')
1121}
1122
1123+function ($) {
1124    'use strict';
1125    var version = $.fn.jquery.split(' ')[0].split('.')
1126    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
1127        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
1128    }
1129}(jQuery);
1130
1131
1132+function ($, win) {
1133    'use strict';
1134
1135    var DataKey = 'blktabs',
1136        BlockSel = '.block-item',
1137        TabSel = '> .module-container .blk-tabs > ul',
1138        BtnSel = '> li',
1139        ValSel = ' > a[href^="#blk"]',
1140        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
1141        DestroyBeforeSymbol = 'destroyBeforeSymbol',
1142        Event = {
1143            ReplacedBefore: 'renderview.replace.before',
1144            ReplacedAfter: 'renderview.replace.after',
1145            BlockDestroy: 'destroy',
1146            BlockAppear: DataKey + '.block.appear',
1147            BlockHidden: DataKey + '.block.hidden',
1148            Click: {
1149                Window: 'blk-nav-in',
1150                Before: DataKey + '.tabs.click.before',
1151                After: DataKey + '.tabs.click.after'
1152            }
1153        },
1154        Options = {
1155            focus: 'active'
1156        };
1157
1158    function BlockTabs(element, opts) {
1159
1160        var self = this;
1161        this._opts = $.extend(Options, $(element).data(), opts);
1162        this._element = element;
1163        this._tabs = $(TabSel, element).get(0);
1164
1165        // block 更新屬性值之後將會被置換
1166        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
1167        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
1168        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
1169            $(this).addClass(ReplacedBeforeSymbol);
1170            event.data.blktabs.resetTabStatus();
1171            $(this).removeClass(ReplacedBeforeSymbol);
1172            $.removeData(this, DataKey);
1173        });
1174
1175        // block 被刪除前復原 tab 關聯的 block
1176        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
1177            $(this).addClass(DestroyBeforeSymbol);
1178            event.data.blktabs.resetTabStatus();
1179        });
1180
1181        // block tabs click 事件
1182        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
1183            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
1184            if ($(element).attr('href').startsWith('#')) {
1185                event.preventDefault();
1186                event.data.blktabs.tabClick(element);
1187                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
1188                    target: element,
1189                    detail: {
1190                        selector: $(element).attr('href')
1191                    }
1192                }));
1193            }
1194        });
1195
1196        this.tabAppear().resetMyStatus();
1197
1198        var bookmarkId = window.location.href.split('#').pop();
1199        if (this._element.id == bookmarkId) {
1200            // 錨點跳轉
1201            var blk = this;
1202            window.addEventListener("load", function (event) {
1203
1204                var arrParentAndButton = function (blkId) {
1205                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
1206                    var pblk = tab.closest(BlockSel);
1207                    if (pblk.length > 0 && pblk.attr('id')) {
1208                        // 記錄&尋找
1209                        var r = arrParentAndButton(pblk.attr('id'));
1210                        r.push([pblk, tab]);
1211                        return r;
1212                    }
1213                    return [];
1214                };
1215                var arr = arrParentAndButton(blk._element.id);
1216                for (var i in arr)
1217                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
1218
1219                setTimeout(function () {
1220                    $("html, body").animate({
1221                        scrollTop: $(blk._element).offset().top
1222                    }, 500, 'swing', function () { });
1223                }, 0.5 * 1000);
1224            });
1225        }
1226    }
1227
1228    var _proto = BlockTabs.prototype;
1229
1230    _proto.tabAppear = function tabAppear() {
1231        if ($(BtnSel, this._tabs).length > 0)
1232            $(this._tabs).removeClass('d-none hide');
1233        return this;
1234    }
1235
1236
1237    // 取得 block tabs 所有關聯的 block target
1238    _proto.getTabSelector = function getTabSelector() {
1239        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
1240            return $(o).attr('href');
1241        }).get().join(',');
1242    }
1243
1244    // 驅動所有關聯的 block target 執行 resetMyStatus
1245    _proto.resetTabStatus = function resetTabStatus(event) {
1246        $(this.getTabSelector()).each(function () {
1247            if ($(this).data(DataKey))
1248                $(this).data(DataKey).resetMyStatus();
1249        });
1250        return this;
1251    }
1252
1253    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
1254    _proto.resetMyStatus = function resetMyStatus() {
1255        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
1256            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
1257            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
1258            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
1259            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
1260            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
1261
1262        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
1263            // 顯示 element
1264            this._element.style.setProperty('display', '');
1265
1266            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
1267            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
1268            if ($tabLink.length < 1)
1269                $tabLink = $(BtnSel + ValSel, this._tabs);
1270            this.tabClick($tabLink.get(0));
1271            $(this._element).trigger(Event.BlockAppear);
1272        }
1273        else {
1274            // 隱藏 element
1275            this._element.style.setProperty('display', 'none', 'important');
1276            $(this._element).trigger(Event.BlockHidden);
1277        }
1278
1279        return this.resetTabStatus();
1280    }
1281
1282    // 點擊 block tabs
1283    _proto.tabClick = function tabClick(currentBtn, closure) {
1284
1285        // 點擊執行內容
1286        if ($.contains(this._element, currentBtn)) {
1287
1288            // tab 切換前
1289            $(this._element).trigger(Event.Click.Before, [currentBtn]);
1290
1291            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
1292            $(currentBtn).addClass(Options.focus);
1293
1294            this.resetTabStatus();
1295
1296            // tab 切換後
1297            $(this._element).trigger(Event.Click.After, [currentBtn]);
1298
1299            if (typeof (closure) === "function")
1300                closure();
1301        }
1302
1303        return this;
1304    }
1305
1306    if (typeof $.fn.blockTab !== 'function') {
1307
1308        $.fn.extend({
1309            blockTab: function (options) {
1310                this.filter(function (i, o) {
1311                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
1312                }).each(function (event) {
1313                    $(this).data(DataKey, new BlockTabs(this, options));
1314                });
1315            }
1316        });
1317    }
1318
1319    $(function () {
1320        $(BlockSel).blockTab();
1321    });
1322
1323}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
1324;(function($) {var _proto = String.prototype;
1325
1326if (typeof _proto.regxMatch !== 'function') {
1327    _proto.regxMatch = function regxMatch() {
1328        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
1329            regxStr = (typeof this === "string" || this instanceof String) ? this 
1329: "";
1330        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
1331            return x.trim();
1332        }).join(' ');
1333    }
1334}/**
1335 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
1336 * ======================================================================== */
1337
1338/**
1339 * @license
1340 * ========================================================================
1341 * ScrollPos-Styler v0.7.1
1342 * https://github.com/acch/scrollpos-styler
1343 * ========================================================================
1344 * Copyright 2015 Achim Christ
1345 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
1346 * ======================================================================== */
1347
1348// JSHint directives
1349/* exported ScrollPosStyler */
1350if (typeof window.ScrollOverSelfStyler === "undefined") {
1351    var ScrollOverSelfStyler = (function (document, window, $) {
1352        "use strict";
1353
1354        /* ====================
1355         * private variables
1356         * ==================== */
1357        var scrollPosY = 0,
1358            busy = false,
1359
1360            // toggle style / class when scrolling below this position (in px)
1361            scrollOffsetY = 1,
1362
1363            // class used to apply scrollPosStyler to
1364            spsClass = "soss",
1365
1366            // choose elements to apply style / class to
1367            elements = document.getElementsByClassName(spsClass),
1368
1369            // style / class to apply to elements when above scroll position
1370            classAbove = "soss--abv",
1371
1372            // style / class to apply to elements when below scroll position
1373            classBelow = "soss--blw",
1374
1375            // tag to set custom scroll offset per element
1376            offsetTag = "data-soss-offset";
1377
1378        
1379        var BlockSel = '.block-item',
1380            ShadowKey = "ScrollOverSelfStyler";
1381
1382        /* ====================
1383         * private function to check scroll position
1384         * ==================== */
1385        function onScroll() {
1386
1387            // ensure that events don't stack
1388            if (!busy) {
1389
1390                // find elements to update
1391                var elementsToUpdate = getElementsToUpdate(false);
1392                if (elementsToUpdate.length > 0) {
1393
1394                    // suspend accepting scroll events
1395                    busy = true;
1396
1397                    // asynchronuously update elements
1398                    window.requestAnimationFrame(function () {
1399                        updateElements(elementsToUpdate);
1400                    });
1401                }
1402            }
1403        }
1404
1405        /* ====================
1406         * copy Element Shadow
1407         * ==================== */
1408        function copyElementShadow(init) {
1409            for (var i = 0; elements[i]; ++i) {
1410                var element = elements[i];
1411                if (!$(element).data(ShadowKey)) {
1412                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
1413                }
1414            }
1415        }
1416
1417        /* ====================
1418         * private function to find elements to update
1419         * ==================== */
1420        function getElementsToUpdate(init) {
1421            var elementsToUpdate = [];
1422            copyElementShadow(init);
1423
1424            // get current scroll position from window
1425            scrollPosY = window.pageYOffset;
1426
1427            // iterate over elements
1428            // for (var elem of elements) {
1429            for (var i = 0; elements[i]; ++i) { // chrome workaround
1430                var element = elements[i],
1431                    $shadow = $(element).data(ShadowKey);
1432
1433                // get offset from element, default to global option
1434                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
1435                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
1436                    shScrollOffsetY = $shadow.offset().top;
1437
1438                // check current state of element
1439                var elOnTop = element.classList.contains(classAbove);
1440
1441                // check current is visible
1442                var elVisible = $(element).closest(BlockSel).is(':visible');
1443
1444                // cols regx
1445                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
1446
1447                // if we were above, and are now below scroll position...
1448                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
1449                    
1450                    element.style.top = offsetTop + "px";
1451                    $shadow.css('height', $(element).css('height'));
1452
1453                    // remember element
1454                    elementsToUpdate.push({
1455                        element: element,
1456                        addClass: classBelow + " " + regxMatchCol,
1457                        removeClass: classAbove
1458                    });
1459
1460                    // if we were below, and are now above scroll position...
1461                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
1462
1463
1464                    // remember element
1465                    elementsToUpdate.push({
1466                        element: element,
1467                        addClass: classAbove,
1468                        removeClass: classBelow + " " + regxMatchCol
1469                    });
1470
1471                    $shadow.get(0).style.height = null;
1472                    element.style.top = null;
1473                }
1474            }
1475
1476            return elementsToUpdate;
1477        }
1478
1479        /* ====================
1480         * private function to update elements
1481         * ==================== */
1482        function updateElements(elementsToUpdate) {
1483
1484            // iterate over elements
1485            // for (var elem of elements) {
1486            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
1487                var map = elementsToUpdate[i];
1488
1489                // add style / class to element
1490                //map.element.classList.add(map.addClass);
1491                //map.element.classList.remove(map.removeClass);
1492                $(map.element).addClass(map.addClass);
1493                $(map.element).removeClass(map.removeClass);
1494            }
1495
1496            // resume accepting scroll events
1497            busy = false;
1498        }
1499
1500        /* ====================
1501         * public function to initially style elements based on scroll position
1502         *
1503         * options:
1504         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
1505         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
1506         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
1507         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
1508         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
1509         *
1510         * ==================== */
1511        var pub = {
1512            init: function (options) {
1513
1514                // suspend accepting scroll events
1515                busy = true;
1516
1517                // merge options object with global options
1518                if (options) {
1519                    if (options.spsClass) {
1520                        spsClass = options.spsClass;
1521                        elements = document.getElementsByClassName(spsClass);
1522                    }
1523                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
1524                    classAbove = options.classAbove || classAbove;
1525                    classBelow = options.classBelow || classBelow;
1526                    offsetTag = options.offsetTag || offsetTag;
1527                }
1528
1529                // ensure all elements have classAbove
1530                var elementsToUpdate = getElementsToUpdate(true);
1531                if (elementsToUpdate.length > 0) {
1532
1533                    // asynchronuously update elements
1534                    window.requestAnimationFrame(function () {
1535                        updateElements(elementsToUpdate);
1536                    });
1537                } else {
1538
1539                    // resume accepting scroll events
1540                    busy = false;
1541                }
1542            }
1543        };
1544
1545        // register for window scroll events
1546        $(window).on("scroll", onScroll);
1547
1548        window.ScrollOverSelfStyler = pub;
1549
1550        return pub;
1551    })(document, window, jQuery);
1552}
1553
1554/* ====================
1555 * main initialization
1556 * ==================== */
1557$(function () {
1558    // defer initialization to allow browser to restore scroll position
1559    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
1560});if (typeof jQuery === 'undefined') {
1561    throw new Error('Block\'s JavaScript requires jQuery')
1562}
1563
1564+function ($) {
1565    'use strict';
1566    var version = $.fn.jquery.split(' ')[0].split('.')
1567    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
1568        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
1569    }
1570}(jQuery);
1571
1572
1573+function ($, win) {
1574    'use strict';
1575
1576    var DataKey = 'blktabs',
1577        BlockSel = '.block-item',
1578        TabSel = '> .module-container .blk-tabs > ul',
1579        BtnSel = '> li',
1580        ValSel = ' > a[href^="#blk"]',
1581        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
1582        DestroyBeforeSymbol = 'destroyBeforeSymbol',
1583        Event = {
1584            ReplacedBefore: 'renderview.replace.before',
1585            ReplacedAfter: 'renderview.replace.after',
1586            BlockDestroy: 'destroy',
1587            BlockAppear: DataKey + '.block.appear',
1588            BlockHidden: DataKey + '.block.hidden',
1589            Click: {
1590                Window: 'blk-nav-in',
1591                Before: DataKey + '.tabs.click.before',
1592                After: DataKey + '.tabs.click.after'
1593            }
1594        },
1595        Options = {
1596            focus: 'active'
1597        };
1598
1599    function BlockTabs(element, opts) {
1600
1601        var self = this;
1602        this._opts = $.extend(Options, $(element).data(), opts);
1603        this._element = element;
1604        this._tabs = $(TabSel, element).get(0);
1605
1606        // block 更新屬性值之後將會被置換
1607        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
1608        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
1609        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
1610            $(this).addClass(ReplacedBeforeSymbol);
1611            event.data.blktabs.resetTabStatus();
1612            $(this).removeClass(ReplacedBeforeSymbol);
1613            $.removeData(this, DataKey);
1614        });
1615
1616        // block 被刪除前復原 tab 關聯的 block
1617        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
1618            $(this).addClass(DestroyBeforeSymbol);
1619            event.data.blktabs.resetTabStatus();
1620        });
1621
1622        // block tabs click 事件
1623        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
1624            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
1625            if ($(element).attr('href').startsWith('#')) {
1626                event.preventDefault();
1627                event.data.blktabs.tabClick(element);
1628                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
1629                    target: element,
1630                    detail: {
1631                        selector: $(element).attr('href')
1632                    }
1633                }));
1634            }
1635        });
1636
1637        this.tabAppear().resetMyStatus();
1638
1639        var bookmarkId = window.location.href.split('#').pop();
1640        if (this._element.id == bookmarkId) {
1641            // 錨點跳轉
1642            var blk = this;
1643            window.addEventListener("load", function (event) {
1644
1645                var arrParentAndButton = function (blkId) {
1646                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
1647                    var pblk = tab.closest(BlockSel);
1648                    if (pblk.length > 0 && pblk.attr('id')) {
1649                        // 記錄&尋找
1650                        var r = arrParentAndButton(pblk.attr('id'));
1651                        r.push([pblk, tab]);
1652                        return r;
1653                    }
1654                    return [];
1655                };
1656                var arr = arrParentAndButton(blk._element.id);
1657                for (var i in arr)
1658                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
1659
1660                setTimeout(function () {
1661                    $("html, body").animate({
1662                        scrollTop: $(blk._element).offset().top
1663                    }, 500, 'swing', function () { });
1664                }, 0.5 * 1000);
1665            });
1666        }
1667    }
1668
1669    var _proto = BlockTabs.prototype;
1670
1671    _proto.tabAppear = function tabAppear() {
1672        if ($(BtnSel, this._tabs).length > 0)
1673            $(this._tabs).removeClass('d-none hide');
1674        return this;
1675    }
1676
1677
1678    // 取得 block tabs 所有關聯的 block target
1679    _proto.getTabSelector = function getTabSelector() {
1680        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
1681            return $(o).attr('href');
1682        }).get().join(',');
1683    }
1684
1685    // 驅動所有關聯的 block target 執行 resetMyStatus
1686    _proto.resetTabStatus = function resetTabStatus(event) {
1687        $(this.getTabSelector()).each(function () {
1688            if ($(this).data(DataKey))
1689                $(this).data(DataKey).resetMyStatus();
1690        });
1691        return this;
1692    }
1693
1694    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
1695    _proto.resetMyStatus = function resetMyStatus() {
1696        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
1697            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
1698            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
1699            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
1700            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
1701            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
1702
1703        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
1704            // 顯示 element
1705            this._element.style.setProperty('display', '');
1706
1707            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
1708            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
1709            if ($tabLink.length < 1)
1710                $tabLink = $(BtnSel + ValSel, this._tabs);
1711            this.tabClick($tabLink.get(0));
1712            $(this._element).trigger(Event.BlockAppear);
1713        }
1714        else {
1715            // 隱藏 element
1716            this._element.style.setProperty('display', 'none', 'important');
1717            $(this._element).trigger(Event.BlockHidden);
1718        }
1719
1720        return this.resetTabStatus();
1721    }
1722
1723    // 點擊 block tabs
1724    _proto.tabClick = function tabClick(currentBtn, closure) {
1725
1726        // 點擊執行內容
1727        if ($.contains(this._element, currentBtn)) {
1728
1729            // tab 切換前
1730            $(this._element).trigger(Event.Click.Before, [currentBtn]);
1731
1732            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
1733            $(currentBtn).addClass(Options.focus);
1734
1735            this.resetTabStatus();
1736
1737            // tab 切換後
1738            $(this._element).trigger(Event.Click.After, [currentBtn]);
1739
1740            if (typeof (closure) === "function")
1741                closure();
1742        }
1743
1744        return this;
1745    }
1746
1747    if (typeof $.fn.blockTab !== 'function') {
1748
1749        $.fn.extend({
1750            blockTab: function (options) {
1751                this.filter(function (i, o) {
1752                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
1753                }).each(function (event) {
1754                    $(this).data(DataKey, new BlockTabs(this, options));
1755                });
1756            }
1757        });
1758    }
1759
1760    $(function () {
1761        $(BlockSel).blockTab();
1762    });
1763
1764}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
1765;(function($) {var _proto = String.prototype;
1766
1767if (typeof _proto.regxMatch !== 'function') {
1768    _proto.regxMatch = function regxMatch() {
1769        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
1770            regxStr = (typeof this === "string" || this instanceof String) ? this 
1770: "";
1771        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
1772            return x.trim();
1773        }).join(' ');
1774    }
1775}/**
1776 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
1777 * ======================================================================== */
1778
1779/**
1780 * @license
1781 * ========================================================================
1782 * ScrollPos-Styler v0.7.1
1783 * https://github.com/acch/scrollpos-styler
1784 * ========================================================================
1785 * Copyright 2015 Achim Christ
1786 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
1787 * ======================================================================== */
1788
1789// JSHint directives
1790/* exported ScrollPosStyler */
1791if (typeof window.ScrollOverSelfStyler === "undefined") {
1792    var ScrollOverSelfStyler = (function (document, window, $) {
1793        "use strict";
1794
1795        /* ====================
1796         * private variables
1797         * ==================== */
1798        var scrollPosY = 0,
1799            busy = false,
1800
1801            // toggle style / class when scrolling below this position (in px)
1802            scrollOffsetY = 1,
1803
1804            // class used to apply scrollPosStyler to
1805            spsClass = "soss",
1806
1807            // choose elements to apply style / class to
1808            elements = document.getElementsByClassName(spsClass),
1809
1810            // style / class to apply to elements when above scroll position
1811            classAbove = "soss--abv",
1812
1813            // style / class to apply to elements when below scroll position
1814            classBelow = "soss--blw",
1815
1816            // tag to set custom scroll offset per element
1817            offsetTag = "data-soss-offset";
1818
1819        
1820        var BlockSel = '.block-item',
1821            ShadowKey = "ScrollOverSelfStyler";
1822
1823        /* ====================
1824         * private function to check scroll position
1825         * ==================== */
1826        function onScroll() {
1827
1828            // ensure that events don't stack
1829            if (!busy) {
1830
1831                // find elements to update
1832                var elementsToUpdate = getElementsToUpdate(false);
1833                if (elementsToUpdate.length > 0) {
1834
1835                    // suspend accepting scroll events
1836                    busy = true;
1837
1838                    // asynchronuously update elements
1839                    window.requestAnimationFrame(function () {
1840                        updateElements(elementsToUpdate);
1841                    });
1842                }
1843            }
1844        }
1845
1846        /* ====================
1847         * copy Element Shadow
1848         * ==================== */
1849        function copyElementShadow(init) {
1850            for (var i = 0; elements[i]; ++i) {
1851                var element = elements[i];
1852                if (!$(element).data(ShadowKey)) {
1853                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
1854                }
1855            }
1856        }
1857
1858        /* ====================
1859         * private function to find elements to update
1860         * ==================== */
1861        function getElementsToUpdate(init) {
1862            var elementsToUpdate = [];
1863            copyElementShadow(init);
1864
1865            // get current scroll position from window
1866            scrollPosY = window.pageYOffset;
1867
1868            // iterate over elements
1869            // for (var elem of elements) {
1870            for (var i = 0; elements[i]; ++i) { // chrome workaround
1871                var element = elements[i],
1872                    $shadow = $(element).data(ShadowKey);
1873
1874                // get offset from element, default to global option
1875                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
1876                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
1877                    shScrollOffsetY = $shadow.offset().top;
1878
1879                // check current state of element
1880                var elOnTop = element.classList.contains(classAbove);
1881
1882                // check current is visible
1883                var elVisible = $(element).closest(BlockSel).is(':visible');
1884
1885                // cols regx
1886                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
1887
1888                // if we were above, and are now below scroll position...
1889                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
1890                    
1891                    element.style.top = offsetTop + "px";
1892                    $shadow.css('height', $(element).css('height'));
1893
1894                    // remember element
1895                    elementsToUpdate.push({
1896                        element: element,
1897                        addClass: classBelow + " " + regxMatchCol,
1898                        removeClass: classAbove
1899                    });
1900
1901                    // if we were below, and are now above scroll position...
1902                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
1903
1904
1905                    // remember element
1906                    elementsToUpdate.push({
1907                        element: element,
1908                        addClass: classAbove,
1909                        removeClass: classBelow + " " + regxMatchCol
1910                    });
1911
1912                    $shadow.get(0).style.height = null;
1913                    element.style.top = null;
1914                }
1915            }
1916
1917            return elementsToUpdate;
1918        }
1919
1920        /* ====================
1921         * private function to update elements
1922         * ==================== */
1923        function updateElements(elementsToUpdate) {
1924
1925            // iterate over elements
1926            // for (var elem of elements) {
1927            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
1928                var map = elementsToUpdate[i];
1929
1930                // add style / class to element
1931                //map.element.classList.add(map.addClass);
1932                //map.element.classList.remove(map.removeClass);
1933                $(map.element).addClass(map.addClass);
1934                $(map.element).removeClass(map.removeClass);
1935            }
1936
1937            // resume accepting scroll events
1938            busy = false;
1939        }
1940
1941        /* ====================
1942         * public function to initially style elements based on scroll position
1943         *
1944         * options:
1945         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
1946         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
1947         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
1948         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
1949         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
1950         *
1951         * ==================== */
1952        var pub = {
1953            init: function (options) {
1954
1955                // suspend accepting scroll events
1956                busy = true;
1957
1958                // merge options object with global options
1959                if (options) {
1960                    if (options.spsClass) {
1961                        spsClass = options.spsClass;
1962                        elements = document.getElementsByClassName(spsClass);
1963                    }
1964                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
1965                    classAbove = options.classAbove || classAbove;
1966                    classBelow = options.classBelow || classBelow;
1967                    offsetTag = options.offsetTag || offsetTag;
1968                }
1969
1970                // ensure all elements have classAbove
1971                var elementsToUpdate = getElementsToUpdate(true);
1972                if (elementsToUpdate.length > 0) {
1973
1974                    // asynchronuously update elements
1975                    window.requestAnimationFrame(function () {
1976                        updateElements(elementsToUpdate);
1977                    });
1978                } else {
1979
1980                    // resume accepting scroll events
1981                    busy = false;
1982                }
1983            }
1984        };
1985
1986        // register for window scroll events
1987        $(window).on("scroll", onScroll);
1988
1989        window.ScrollOverSelfStyler = pub;
1990
1991        return pub;
1992    })(document, window, jQuery);
1993}
1994
1995/* ====================
1996 * main initialization
1997 * ==================== */
1998$(function () {
1999    // defer initialization to allow browser to restore scroll position
2000    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
2001});if (typeof jQuery === 'undefined') {
2002    throw new Error('Block\'s JavaScript requires jQuery')
2003}
2004
2005+function ($) {
2006    'use strict';
2007    var version = $.fn.jquery.split(' ')[0].split('.')
2008    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
2009        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
2010    }
2011}(jQuery);
2012
2013
2014+function ($, win) {
2015    'use strict';
2016
2017    var DataKey = 'blktabs',
2018        BlockSel = '.block-item',
2019        TabSel = '> .module-container .blk-tabs > ul',
2020        BtnSel = '> li',
2021        ValSel = ' > a[href^="#blk"]',
2022        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
2023        DestroyBeforeSymbol = 'destroyBeforeSymbol',
2024        Event = {
2025            ReplacedBefore: 'renderview.replace.before',
2026            ReplacedAfter: 'renderview.replace.after',
2027            BlockDestroy: 'destroy',
2028            BlockAppear: DataKey + '.block.appear',
2029            BlockHidden: DataKey + '.block.hidden',
2030            Click: {
2031                Window: 'blk-nav-in',
2032                Before: DataKey + '.tabs.click.before',
2033                After: DataKey + '.tabs.click.after'
2034            }
2035        },
2036        Options = {
2037            focus: 'active'
2038        };
2039
2040    function BlockTabs(element, opts) {
2041
2042        var self = this;
2043        this._opts = $.extend(Options, $(element).data(), opts);
2044        this._element = element;
2045        this._tabs = $(TabSel, element).get(0);
2046
2047        // block 更新屬性值之後將會被置換
2048        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
2049        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
2050        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
2051            $(this).addClass(ReplacedBeforeSymbol);
2052            event.data.blktabs.resetTabStatus();
2053            $(this).removeClass(ReplacedBeforeSymbol);
2054            $.removeData(this, DataKey);
2055        });
2056
2057        // block 被刪除前復原 tab 關聯的 block
2058        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
2059            $(this).addClass(DestroyBeforeSymbol);
2060            event.data.blktabs.resetTabStatus();
2061        });
2062
2063        // block tabs click 事件
2064        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
2065            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
2066            if ($(element).attr('href').startsWith('#')) {
2067                event.preventDefault();
2068                event.data.blktabs.tabClick(element);
2069                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
2070                    target: element,
2071                    detail: {
2072                        selector: $(element).attr('href')
2073                    }
2074                }));
2075            }
2076        });
2077
2078        this.tabAppear().resetMyStatus();
2079
2080        var bookmarkId = window.location.href.split('#').pop();
2081        if (this._element.id == bookmarkId) {
2082            // 錨點跳轉
2083            var blk = this;
2084            window.addEventListener("load", function (event) {
2085
2086                var arrParentAndButton = function (blkId) {
2087                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
2088                    var pblk = tab.closest(BlockSel);
2089                    if (pblk.length > 0 && pblk.attr('id')) {
2090                        // 記錄&尋找
2091                        var r = arrParentAndButton(pblk.attr('id'));
2092                        r.push([pblk, tab]);
2093                        return r;
2094                    }
2095                    return [];
2096                };
2097                var arr = arrParentAndButton(blk._element.id);
2098                for (var i in arr)
2099                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
2100
2101                setTimeout(function () {
2102                    $("html, body").animate({
2103                        scrollTop: $(blk._element).offset().top
2104                    }, 500, 'swing', function () { });
2105                }, 0.5 * 1000);
2106            });
2107        }
2108    }
2109
2110    var _proto = BlockTabs.prototype;
2111
2112    _proto.tabAppear = function tabAppear() {
2113        if ($(BtnSel, this._tabs).length > 0)
2114            $(this._tabs).removeClass('d-none hide');
2115        return this;
2116    }
2117
2118
2119    // 取得 block tabs 所有關聯的 block target
2120    _proto.getTabSelector = function getTabSelector() {
2121        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
2122            return $(o).attr('href');
2123        }).get().join(',');
2124    }
2125
2126    // 驅動所有關聯的 block target 執行 resetMyStatus
2127    _proto.resetTabStatus = function resetTabStatus(event) {
2128        $(this.getTabSelector()).each(function () {
2129            if ($(this).data(DataKey))
2130                $(this).data(DataKey).resetMyStatus();
2131        });
2132        return this;
2133    }
2134
2135    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
2136    _proto.resetMyStatus = function resetMyStatus() {
2137        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
2138            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
2139            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
2140            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
2141            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
2142            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
2143
2144        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
2145            // 顯示 element
2146            this._element.style.setProperty('display', '');
2147
2148            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
2149            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
2150            if ($tabLink.length < 1)
2151                $tabLink = $(BtnSel + ValSel, this._tabs);
2152            this.tabClick($tabLink.get(0));
2153            $(this._element).trigger(Event.BlockAppear);
2154        }
2155        else {
2156            // 隱藏 element
2157            this._element.style.setProperty('display', 'none', 'important');
2158            $(this._element).trigger(Event.BlockHidden);
2159        }
2160
2161        return this.resetTabStatus();
2162    }
2163
2164    // 點擊 block tabs
2165    _proto.tabClick = function tabClick(currentBtn, closure) {
2166
2167        // 點擊執行內容
2168        if ($.contains(this._element, currentBtn)) {
2169
2170            // tab 切換前
2171            $(this._element).trigger(Event.Click.Before, [currentBtn]);
2172
2173            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
2174            $(currentBtn).addClass(Options.focus);
2175
2176            this.resetTabStatus();
2177
2178            // tab 切換後
2179            $(this._element).trigger(Event.Click.After, [currentBtn]);
2180
2181            if (typeof (closure) === "function")
2182                closure();
2183        }
2184
2185        return this;
2186    }
2187
2188    if (typeof $.fn.blockTab !== 'function') {
2189
2190        $.fn.extend({
2191            blockTab: function (options) {
2192                this.filter(function (i, o) {
2193                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
2194                }).each(function (event) {
2195                    $(this).data(DataKey, new BlockTabs(this, options));
2196                });
2197            }
2198        });
2199    }
2200
2201    $(function () {
2202        $(BlockSel).blockTab();
2203    });
2204
2205}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
2206;(function($) {var _proto = String.prototype;
2207
2208if (typeof _proto.regxMatch !== 'function') {
2209    _proto.regxMatch = function regxMatch() {
2210        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
2211            regxStr = (typeof this === "string" || this instanceof String) ? this 
2211: "";
2212        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
2213            return x.trim();
2214        }).join(' ');
2215    }
2216}/**
2217 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
2218 * ======================================================================== */
2219
2220/**
2221 * @license
2222 * ========================================================================
2223 * ScrollPos-Styler v0.7.1
2224 * https://github.com/acch/scrollpos-styler
2225 * ========================================================================
2226 * Copyright 2015 Achim Christ
2227 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
2228 * ======================================================================== */
2229
2230// JSHint directives
2231/* exported ScrollPosStyler */
2232if (typeof window.ScrollOverSelfStyler === "undefined") {
2233    var ScrollOverSelfStyler = (function (document, window, $) {
2234        "use strict";
2235
2236        /* ====================
2237         * private variables
2238         * ==================== */
2239        var scrollPosY = 0,
2240            busy = false,
2241
2242            // toggle style / class when scrolling below this position (in px)
2243            scrollOffsetY = 1,
2244
2245            // class used to apply scrollPosStyler to
2246            spsClass = "soss",
2247
2248            // choose elements to apply style / class to
2249            elements = document.getElementsByClassName(spsClass),
2250
2251            // style / class to apply to elements when above scroll position
2252            classAbove = "soss--abv",
2253
2254            // style / class to apply to elements when below scroll position
2255            classBelow = "soss--blw",
2256
2257            // tag to set custom scroll offset per element
2258            offsetTag = "data-soss-offset";
2259
2260        
2261        var BlockSel = '.block-item',
2262            ShadowKey = "ScrollOverSelfStyler";
2263
2264        /* ====================
2265         * private function to check scroll position
2266         * ==================== */
2267        function onScroll() {
2268
2269            // ensure that events don't stack
2270            if (!busy) {
2271
2272                // find elements to update
2273                var elementsToUpdate = getElementsToUpdate(false);
2274                if (elementsToUpdate.length > 0) {
2275
2276                    // suspend accepting scroll events
2277                    busy = true;
2278
2279                    // asynchronuously update elements
2280                    window.requestAnimationFrame(function () {
2281                        updateElements(elementsToUpdate);
2282                    });
2283                }
2284            }
2285        }
2286
2287        /* ====================
2288         * copy Element Shadow
2289         * ==================== */
2290        function copyElementShadow(init) {
2291            for (var i = 0; elements[i]; ++i) {
2292                var element = elements[i];
2293                if (!$(element).data(ShadowKey)) {
2294                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
2295                }
2296            }
2297        }
2298
2299        /* ====================
2300         * private function to find elements to update
2301         * ==================== */
2302        function getElementsToUpdate(init) {
2303            var elementsToUpdate = [];
2304            copyElementShadow(init);
2305
2306            // get current scroll position from window
2307            scrollPosY = window.pageYOffset;
2308
2309            // iterate over elements
2310            // for (var elem of elements) {
2311            for (var i = 0; elements[i]; ++i) { // chrome workaround
2312                var element = elements[i],
2313                    $shadow = $(element).data(ShadowKey);
2314
2315                // get offset from element, default to global option
2316                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
2317                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
2318                    shScrollOffsetY = $shadow.offset().top;
2319
2320                // check current state of element
2321                var elOnTop = element.classList.contains(classAbove);
2322
2323                // check current is visible
2324                var elVisible = $(element).closest(BlockSel).is(':visible');
2325
2326                // cols regx
2327                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
2328
2329                // if we were above, and are now below scroll position...
2330                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
2331                    
2332                    element.style.top = offsetTop + "px";
2333                    $shadow.css('height', $(element).css('height'));
2334
2335                    // remember element
2336                    elementsToUpdate.push({
2337                        element: element,
2338                        addClass: classBelow + " " + regxMatchCol,
2339                        removeClass: classAbove
2340                    });
2341
2342                    // if we were below, and are now above scroll position...
2343                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
2344
2345
2346                    // remember element
2347                    elementsToUpdate.push({
2348                        element: element,
2349                        addClass: classAbove,
2350                        removeClass: classBelow + " " + regxMatchCol
2351                    });
2352
2353                    $shadow.get(0).style.height = null;
2354                    element.style.top = null;
2355                }
2356            }
2357
2358            return elementsToUpdate;
2359        }
2360
2361        /* ====================
2362         * private function to update elements
2363         * ==================== */
2364        function updateElements(elementsToUpdate) {
2365
2366            // iterate over elements
2367            // for (var elem of elements) {
2368            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
2369                var map = elementsToUpdate[i];
2370
2371                // add style / class to element
2372                //map.element.classList.add(map.addClass);
2373                //map.element.classList.remove(map.removeClass);
2374                $(map.element).addClass(map.addClass);
2375                $(map.element).removeClass(map.removeClass);
2376            }
2377
2378            // resume accepting scroll events
2379            busy = false;
2380        }
2381
2382        /* ====================
2383         * public function to initially style elements based on scroll position
2384         *
2385         * options:
2386         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
2387         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
2388         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
2389         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
2390         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
2391         *
2392         * ==================== */
2393        var pub = {
2394            init: function (options) {
2395
2396                // suspend accepting scroll events
2397                busy = true;
2398
2399                // merge options object with global options
2400                if (options) {
2401                    if (options.spsClass) {
2402                        spsClass = options.spsClass;
2403                        elements = document.getElementsByClassName(spsClass);
2404                    }
2405                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
2406                    classAbove = options.classAbove || classAbove;
2407                    classBelow = options.classBelow || classBelow;
2408                    offsetTag = options.offsetTag || offsetTag;
2409                }
2410
2411                // ensure all elements have classAbove
2412                var elementsToUpdate = getElementsToUpdate(true);
2413                if (elementsToUpdate.length > 0) {
2414
2415                    // asynchronuously update elements
2416                    window.requestAnimationFrame(function () {
2417                        updateElements(elementsToUpdate);
2418                    });
2419                } else {
2420
2421                    // resume accepting scroll events
2422                    busy = false;
2423                }
2424            }
2425        };
2426
2427        // register for window scroll events
2428        $(window).on("scroll", onScroll);
2429
2430        window.ScrollOverSelfStyler = pub;
2431
2432        return pub;
2433    })(document, window, jQuery);
2434}
2435
2436/* ====================
2437 * main initialization
2438 * ==================== */
2439$(function () {
2440    // defer initialization to allow browser to restore scroll position
2441    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
2442});if (typeof jQuery === 'undefined') {
2443    throw new Error('Block\'s JavaScript requires jQuery')
2444}
2445
2446+function ($) {
2447    'use strict';
2448    var version = $.fn.jquery.split(' ')[0].split('.')
2449    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
2450        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
2451    }
2452}(jQuery);
2453
2454
2455+function ($, win) {
2456    'use strict';
2457
2458    var DataKey = 'blktabs',
2459        BlockSel = '.block-item',
2460        TabSel = '> .module-container .blk-tabs > ul',
2461        BtnSel = '> li',
2462        ValSel = ' > a[href^="#blk"]',
2463        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
2464        DestroyBeforeSymbol = 'destroyBeforeSymbol',
2465        Event = {
2466            ReplacedBefore: 'renderview.replace.before',
2467            ReplacedAfter: 'renderview.replace.after',
2468            BlockDestroy: 'destroy',
2469            BlockAppear: DataKey + '.block.appear',
2470            BlockHidden: DataKey + '.block.hidden',
2471            Click: {
2472                Window: 'blk-nav-in',
2473                Before: DataKey + '.tabs.click.before',
2474                After: DataKey + '.tabs.click.after'
2475            }
2476        },
2477        Options = {
2478            focus: 'active'
2479        };
2480
2481    function BlockTabs(element, opts) {
2482
2483        var self = this;
2484        this._opts = $.extend(Options, $(element).data(), opts);
2485        this._element = element;
2486        this._tabs = $(TabSel, element).get(0);
2487
2488        // block 更新屬性值之後將會被置換
2489        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
2490        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
2491        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
2492            $(this).addClass(ReplacedBeforeSymbol);
2493            event.data.blktabs.resetTabStatus();
2494            $(this).removeClass(ReplacedBeforeSymbol);
2495            $.removeData(this, DataKey);
2496        });
2497
2498        // block 被刪除前復原 tab 關聯的 block
2499        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
2500            $(this).addClass(DestroyBeforeSymbol);
2501            event.data.blktabs.resetTabStatus();
2502        });
2503
2504        // block tabs click 事件
2505        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
2506            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
2507            if ($(element).attr('href').startsWith('#')) {
2508                event.preventDefault();
2509                event.data.blktabs.tabClick(element);
2510                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
2511                    target: element,
2512                    detail: {
2513                        selector: $(element).attr('href')
2514                    }
2515                }));
2516            }
2517        });
2518
2519        this.tabAppear().resetMyStatus();
2520
2521        var bookmarkId = window.location.href.split('#').pop();
2522        if (this._element.id == bookmarkId) {
2523            // 錨點跳轉
2524            var blk = this;
2525            window.addEventListener("load", function (event) {
2526
2527                var arrParentAndButton = function (blkId) {
2528                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
2529                    var pblk = tab.closest(BlockSel);
2530                    if (pblk.length > 0 && pblk.attr('id')) {
2531                        // 記錄&尋找
2532                        var r = arrParentAndButton(pblk.attr('id'));
2533                        r.push([pblk, tab]);
2534                        return r;
2535                    }
2536                    return [];
2537                };
2538                var arr = arrParentAndButton(blk._element.id);
2539                for (var i in arr)
2540                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
2541
2542                setTimeout(function () {
2543                    $("html, body").animate({
2544                        scrollTop: $(blk._element).offset().top
2545                    }, 500, 'swing', function () { });
2546                }, 0.5 * 1000);
2547            });
2548        }
2549    }
2550
2551    var _proto = BlockTabs.prototype;
2552
2553    _proto.tabAppear = function tabAppear() {
2554        if ($(BtnSel, this._tabs).length > 0)
2555            $(this._tabs).removeClass('d-none hide');
2556        return this;
2557    }
2558
2559
2560    // 取得 block tabs 所有關聯的 block target
2561    _proto.getTabSelector = function getTabSelector() {
2562        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
2563            return $(o).attr('href');
2564        }).get().join(',');
2565    }
2566
2567    // 驅動所有關聯的 block target 執行 resetMyStatus
2568    _proto.resetTabStatus = function resetTabStatus(event) {
2569        $(this.getTabSelector()).each(function () {
2570            if ($(this).data(DataKey))
2571                $(this).data(DataKey).resetMyStatus();
2572        });
2573        return this;
2574    }
2575
2576    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
2577    _proto.resetMyStatus = function resetMyStatus() {
2578        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
2579            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
2580            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
2581            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
2582            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
2583            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
2584
2585        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
2586            // 顯示 element
2587            this._element.style.setProperty('display', '');
2588
2589            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
2590            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
2591            if ($tabLink.length < 1)
2592                $tabLink = $(BtnSel + ValSel, this._tabs);
2593            this.tabClick($tabLink.get(0));
2594            $(this._element).trigger(Event.BlockAppear);
2595        }
2596        else {
2597            // 隱藏 element
2598            this._element.style.setProperty('display', 'none', 'important');
2599            $(this._element).trigger(Event.BlockHidden);
2600        }
2601
2602        return this.resetTabStatus();
2603    }
2604
2605    // 點擊 block tabs
2606    _proto.tabClick = function tabClick(currentBtn, closure) {
2607
2608        // 點擊執行內容
2609        if ($.contains(this._element, currentBtn)) {
2610
2611            // tab 切換前
2612            $(this._element).trigger(Event.Click.Before, [currentBtn]);
2613
2614            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
2615            $(currentBtn).addClass(Options.focus);
2616
2617            this.resetTabStatus();
2618
2619            // tab 切換後
2620            $(this._element).trigger(Event.Click.After, [currentBtn]);
2621
2622            if (typeof (closure) === "function")
2623                closure();
2624        }
2625
2626        return this;
2627    }
2628
2629    if (typeof $.fn.blockTab !== 'function') {
2630
2631        $.fn.extend({
2632            blockTab: function (options) {
2633                this.filter(function (i, o) {
2634                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
2635                }).each(function (event) {
2636                    $(this).data(DataKey, new BlockTabs(this, options));
2637                });
2638            }
2639        });
2640    }
2641
2642    $(function () {
2643        $(BlockSel).blockTab();
2644    });
2645
2646}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
2647;(function($) {var _proto = String.prototype;
2648
2649if (typeof _proto.regxMatch !== 'function') {
2650    _proto.regxMatch = function regxMatch() {
2651        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
2652            regxStr = (typeof this === "string" || this instanceof String) ? this 
2652: "";
2653        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
2654            return x.trim();
2655        }).join(' ');
2656    }
2657}/**
2658 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
2659 * ======================================================================== */
2660
2661/**
2662 * @license
2663 * ========================================================================
2664 * ScrollPos-Styler v0.7.1
2665 * https://github.com/acch/scrollpos-styler
2666 * ========================================================================
2667 * Copyright 2015 Achim Christ
2668 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
2669 * ======================================================================== */
2670
2671// JSHint directives
2672/* exported ScrollPosStyler */
2673if (typeof window.ScrollOverSelfStyler === "undefined") {
2674    var ScrollOverSelfStyler = (function (document, window, $) {
2675        "use strict";
2676
2677        /* ====================
2678         * private variables
2679         * ==================== */
2680        var scrollPosY = 0,
2681            busy = false,
2682
2683            // toggle style / class when scrolling below this position (in px)
2684            scrollOffsetY = 1,
2685
2686            // class used to apply scrollPosStyler to
2687            spsClass = "soss",
2688
2689            // choose elements to apply style / class to
2690            elements = document.getElementsByClassName(spsClass),
2691
2692            // style / class to apply to elements when above scroll position
2693            classAbove = "soss--abv",
2694
2695            // style / class to apply to elements when below scroll position
2696            classBelow = "soss--blw",
2697
2698            // tag to set custom scroll offset per element
2699            offsetTag = "data-soss-offset";
2700
2701        
2702        var BlockSel = '.block-item',
2703            ShadowKey = "ScrollOverSelfStyler";
2704
2705        /* ====================
2706         * private function to check scroll position
2707         * ==================== */
2708        function onScroll() {
2709
2710            // ensure that events don't stack
2711            if (!busy) {
2712
2713                // find elements to update
2714                var elementsToUpdate = getElementsToUpdate(false);
2715                if (elementsToUpdate.length > 0) {
2716
2717                    // suspend accepting scroll events
2718                    busy = true;
2719
2720                    // asynchronuously update elements
2721                    window.requestAnimationFrame(function () {
2722                        updateElements(elementsToUpdate);
2723                    });
2724                }
2725            }
2726        }
2727
2728        /* ====================
2729         * copy Element Shadow
2730         * ==================== */
2731        function copyElementShadow(init) {
2732            for (var i = 0; elements[i]; ++i) {
2733                var element = elements[i];
2734                if (!$(element).data(ShadowKey)) {
2735                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
2736                }
2737            }
2738        }
2739
2740        /* ====================
2741         * private function to find elements to update
2742         * ==================== */
2743        function getElementsToUpdate(init) {
2744            var elementsToUpdate = [];
2745            copyElementShadow(init);
2746
2747            // get current scroll position from window
2748            scrollPosY = window.pageYOffset;
2749
2750            // iterate over elements
2751            // for (var elem of elements) {
2752            for (var i = 0; elements[i]; ++i) { // chrome workaround
2753                var element = elements[i],
2754                    $shadow = $(element).data(ShadowKey);
2755
2756                // get offset from element, default to global option
2757                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
2758                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
2759                    shScrollOffsetY = $shadow.offset().top;
2760
2761                // check current state of element
2762                var elOnTop = element.classList.contains(classAbove);
2763
2764                // check current is visible
2765                var elVisible = $(element).closest(BlockSel).is(':visible');
2766
2767                // cols regx
2768                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
2769
2770                // if we were above, and are now below scroll position...
2771                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
2772                    
2773                    element.style.top = offsetTop + "px";
2774                    $shadow.css('height', $(element).css('height'));
2775
2776                    // remember element
2777                    elementsToUpdate.push({
2778                        element: element,
2779                        addClass: classBelow + " " + regxMatchCol,
2780                        removeClass: classAbove
2781                    });
2782
2783                    // if we were below, and are now above scroll position...
2784                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
2785
2786
2787                    // remember element
2788                    elementsToUpdate.push({
2789                        element: element,
2790                        addClass: classAbove,
2791                        removeClass: classBelow + " " + regxMatchCol
2792                    });
2793
2794                    $shadow.get(0).style.height = null;
2795                    element.style.top = null;
2796                }
2797            }
2798
2799            return elementsToUpdate;
2800        }
2801
2802        /* ====================
2803         * private function to update elements
2804         * ==================== */
2805        function updateElements(elementsToUpdate) {
2806
2807            // iterate over elements
2808            // for (var elem of elements) {
2809            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
2810                var map = elementsToUpdate[i];
2811
2812                // add style / class to element
2813                //map.element.classList.add(map.addClass);
2814                //map.element.classList.remove(map.removeClass);
2815                $(map.element).addClass(map.addClass);
2816                $(map.element).removeClass(map.removeClass);
2817            }
2818
2819            // resume accepting scroll events
2820            busy = false;
2821        }
2822
2823        /* ====================
2824         * public function to initially style elements based on scroll position
2825         *
2826         * options:
2827         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
2828         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
2829         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
2830         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
2831         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
2832         *
2833         * ==================== */
2834        var pub = {
2835            init: function (options) {
2836
2837                // suspend accepting scroll events
2838                busy = true;
2839
2840                // merge options object with global options
2841                if (options) {
2842                    if (options.spsClass) {
2843                        spsClass = options.spsClass;
2844                        elements = document.getElementsByClassName(spsClass);
2845                    }
2846                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
2847                    classAbove = options.classAbove || classAbove;
2848                    classBelow = options.classBelow || classBelow;
2849                    offsetTag = options.offsetTag || offsetTag;
2850                }
2851
2852                // ensure all elements have classAbove
2853                var elementsToUpdate = getElementsToUpdate(true);
2854                if (elementsToUpdate.length > 0) {
2855
2856                    // asynchronuously update elements
2857                    window.requestAnimationFrame(function () {
2858                        updateElements(elementsToUpdate);
2859                    });
2860                } else {
2861
2862                    // resume accepting scroll events
2863                    busy = false;
2864                }
2865            }
2866        };
2867
2868        // register for window scroll events
2869        $(window).on("scroll", onScroll);
2870
2871        window.ScrollOverSelfStyler = pub;
2872
2873        return pub;
2874    })(document, window, jQuery);
2875}
2876
2877/* ====================
2878 * main initialization
2879 * ==================== */
2880$(function () {
2881    // defer initialization to allow browser to restore scroll position
2882    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
2883});if (typeof jQuery === 'undefined') {
2884    throw new Error('Block\'s JavaScript requires jQuery')
2885}
2886
2887+function ($) {
2888    'use strict';
2889    var version = $.fn.jquery.split(' ')[0].split('.')
2890    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
2891        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
2892    }
2893}(jQuery);
2894
2895
2896+function ($, win) {
2897    'use strict';
2898
2899    var DataKey = 'blktabs',
2900        BlockSel = '.block-item',
2901        TabSel = '> .module-container .blk-tabs > ul',
2902        BtnSel = '> li',
2903        ValSel = ' > a[href^="#blk"]',
2904        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
2905        DestroyBeforeSymbol = 'destroyBeforeSymbol',
2906        Event = {
2907            ReplacedBefore: 'renderview.replace.before',
2908            ReplacedAfter: 'renderview.replace.after',
2909            BlockDestroy: 'destroy',
2910            BlockAppear: DataKey + '.block.appear',
2911            BlockHidden: DataKey + '.block.hidden',
2912            Click: {
2913                Window: 'blk-nav-in',
2914                Before: DataKey + '.tabs.click.before',
2915                After: DataKey + '.tabs.click.after'
2916            }
2917        },
2918        Options = {
2919            focus: 'active'
2920        };
2921
2922    function BlockTabs(element, opts) {
2923
2924        var self = this;
2925        this._opts = $.extend(Options, $(element).data(), opts);
2926        this._element = element;
2927        this._tabs = $(TabSel, element).get(0);
2928
2929        // block 更新屬性值之後將會被置換
2930        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
2931        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
2932        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
2933            $(this).addClass(ReplacedBeforeSymbol);
2934            event.data.blktabs.resetTabStatus();
2935            $(this).removeClass(ReplacedBeforeSymbol);
2936            $.removeData(this, DataKey);
2937        });
2938
2939        // block 被刪除前復原 tab 關聯的 block
2940        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
2941            $(this).addClass(DestroyBeforeSymbol);
2942            event.data.blktabs.resetTabStatus();
2943        });
2944
2945        // block tabs click 事件
2946        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
2947            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
2948            if ($(element).attr('href').startsWith('#')) {
2949                event.preventDefault();
2950                event.data.blktabs.tabClick(element);
2951                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
2952                    target: element,
2953                    detail: {
2954                        selector: $(element).attr('href')
2955                    }
2956                }));
2957            }
2958        });
2959
2960        this.tabAppear().resetMyStatus();
2961
2962        var bookmarkId = window.location.href.split('#').pop();
2963        if (this._element.id == bookmarkId) {
2964            // 錨點跳轉
2965            var blk = this;
2966            window.addEventListener("load", function (event) {
2967
2968                var arrParentAndButton = function (blkId) {
2969                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
2970                    var pblk = tab.closest(BlockSel);
2971                    if (pblk.length > 0 && pblk.attr('id')) {
2972                        // 記錄&尋找
2973                        var r = arrParentAndButton(pblk.attr('id'));
2974                        r.push([pblk, tab]);
2975                        return r;
2976                    }
2977                    return [];
2978                };
2979                var arr = arrParentAndButton(blk._element.id);
2980                for (var i in arr)
2981                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
2982
2983                setTimeout(function () {
2984                    $("html, body").animate({
2985                        scrollTop: $(blk._element).offset().top
2986                    }, 500, 'swing', function () { });
2987                }, 0.5 * 1000);
2988            });
2989        }
2990    }
2991
2992    var _proto = BlockTabs.prototype;
2993
2994    _proto.tabAppear = function tabAppear() {
2995        if ($(BtnSel, this._tabs).length > 0)
2996            $(this._tabs).removeClass('d-none hide');
2997        return this;
2998    }
2999
3000
3001    // 取得 block tabs 所有關聯的 block target
3002    _proto.getTabSelector = function getTabSelector() {
3003        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
3004            return $(o).attr('href');
3005        }).get().join(',');
3006    }
3007
3008    // 驅動所有關聯的 block target 執行 resetMyStatus
3009    _proto.resetTabStatus = function resetTabStatus(event) {
3010        $(this.getTabSelector()).each(function () {
3011            if ($(this).data(DataKey))
3012                $(this).data(DataKey).resetMyStatus();
3013        });
3014        return this;
3015    }
3016
3017    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
3018    _proto.resetMyStatus = function resetMyStatus() {
3019        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
3020            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
3021            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
3022            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
3023            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
3024            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
3025
3026        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
3027            // 顯示 element
3028            this._element.style.setProperty('display', '');
3029
3030            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
3031            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
3032            if ($tabLink.length < 1)
3033                $tabLink = $(BtnSel + ValSel, this._tabs);
3034            this.tabClick($tabLink.get(0));
3035            $(this._element).trigger(Event.BlockAppear);
3036        }
3037        else {
3038            // 隱藏 element
3039            this._element.style.setProperty('display', 'none', 'important');
3040            $(this._element).trigger(Event.BlockHidden);
3041        }
3042
3043        return this.resetTabStatus();
3044    }
3045
3046    // 點擊 block tabs
3047    _proto.tabClick = function tabClick(currentBtn, closure) {
3048
3049        // 點擊執行內容
3050        if ($.contains(this._element, currentBtn)) {
3051
3052            // tab 切換前
3053            $(this._element).trigger(Event.Click.Before, [currentBtn]);
3054
3055            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
3056            $(currentBtn).addClass(Options.focus);
3057
3058            this.resetTabStatus();
3059
3060            // tab 切換後
3061            $(this._element).trigger(Event.Click.After, [currentBtn]);
3062
3063            if (typeof (closure) === "function")
3064                closure();
3065        }
3066
3067        return this;
3068    }
3069
3070    if (typeof $.fn.blockTab !== 'function') {
3071
3072        $.fn.extend({
3073            blockTab: function (options) {
3074                this.filter(function (i, o) {
3075                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
3076                }).each(function (event) {
3077                    $(this).data(DataKey, new BlockTabs(this, options));
3078                });
3079            }
3080        });
3081    }
3082
3083    $(function () {
3084        $(BlockSel).blockTab();
3085    });
3086
3087}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
3088;(function($) {var _proto = String.prototype;
3089
3090if (typeof _proto.regxMatch !== 'function') {
3091    _proto.regxMatch = function regxMatch() {
3092        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
3093            regxStr = (typeof this === "string" || this instanceof String) ? this 
3093: "";
3094        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
3095            return x.trim();
3096        }).join(' ');
3097    }
3098}/**
3099 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
3100 * ======================================================================== */
3101
3102/**
3103 * @license
3104 * ========================================================================
3105 * ScrollPos-Styler v0.7.1
3106 * https://github.com/acch/scrollpos-styler
3107 * ========================================================================
3108 * Copyright 2015 Achim Christ
3109 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
3110 * ======================================================================== */
3111
3112// JSHint directives
3113/* exported ScrollPosStyler */
3114if (typeof window.ScrollOverSelfStyler === "undefined") {
3115    var ScrollOverSelfStyler = (function (document, window, $) {
3116        "use strict";
3117
3118        /* ====================
3119         * private variables
3120         * ==================== */
3121        var scrollPosY = 0,
3122            busy = false,
3123
3124            // toggle style / class when scrolling below this position (in px)
3125            scrollOffsetY = 1,
3126
3127            // class used to apply scrollPosStyler to
3128            spsClass = "soss",
3129
3130            // choose elements to apply style / class to
3131            elements = document.getElementsByClassName(spsClass),
3132
3133            // style / class to apply to elements when above scroll position
3134            classAbove = "soss--abv",
3135
3136            // style / class to apply to elements when below scroll position
3137            classBelow = "soss--blw",
3138
3139            // tag to set custom scroll offset per element
3140            offsetTag = "data-soss-offset";
3141
3142        
3143        var BlockSel = '.block-item',
3144            ShadowKey = "ScrollOverSelfStyler";
3145
3146        /* ====================
3147         * private function to check scroll position
3148         * ==================== */
3149        function onScroll() {
3150
3151            // ensure that events don't stack
3152            if (!busy) {
3153
3154                // find elements to update
3155                var elementsToUpdate = getElementsToUpdate(false);
3156                if (elementsToUpdate.length > 0) {
3157
3158                    // suspend accepting scroll events
3159                    busy = true;
3160
3161                    // asynchronuously update elements
3162                    window.requestAnimationFrame(function () {
3163                        updateElements(elementsToUpdate);
3164                    });
3165                }
3166            }
3167        }
3168
3169        /* ====================
3170         * copy Element Shadow
3171         * ==================== */
3172        function copyElementShadow(init) {
3173            for (var i = 0; elements[i]; ++i) {
3174                var element = elements[i];
3175                if (!$(element).data(ShadowKey)) {
3176                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
3177                }
3178            }
3179        }
3180
3181        /* ====================
3182         * private function to find elements to update
3183         * ==================== */
3184        function getElementsToUpdate(init) {
3185            var elementsToUpdate = [];
3186            copyElementShadow(init);
3187
3188            // get current scroll position from window
3189            scrollPosY = window.pageYOffset;
3190
3191            // iterate over elements
3192            // for (var elem of elements) {
3193            for (var i = 0; elements[i]; ++i) { // chrome workaround
3194                var element = elements[i],
3195                    $shadow = $(element).data(ShadowKey);
3196
3197                // get offset from element, default to global option
3198                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
3199                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
3200                    shScrollOffsetY = $shadow.offset().top;
3201
3202                // check current state of element
3203                var elOnTop = element.classList.contains(classAbove);
3204
3205                // check current is visible
3206                var elVisible = $(element).closest(BlockSel).is(':visible');
3207
3208                // cols regx
3209                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
3210
3211                // if we were above, and are now below scroll position...
3212                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
3213                    
3214                    element.style.top = offsetTop + "px";
3215                    $shadow.css('height', $(element).css('height'));
3216
3217                    // remember element
3218                    elementsToUpdate.push({
3219                        element: element,
3220                        addClass: classBelow + " " + regxMatchCol,
3221                        removeClass: classAbove
3222                    });
3223
3224                    // if we were below, and are now above scroll position...
3225                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
3226
3227
3228                    // remember element
3229                    elementsToUpdate.push({
3230                        element: element,
3231                        addClass: classAbove,
3232                        removeClass: classBelow + " " + regxMatchCol
3233                    });
3234
3235                    $shadow.get(0).style.height = null;
3236                    element.style.top = null;
3237                }
3238            }
3239
3240            return elementsToUpdate;
3241        }
3242
3243        /* ====================
3244         * private function to update elements
3245         * ==================== */
3246        function updateElements(elementsToUpdate) {
3247
3248            // iterate over elements
3249            // for (var elem of elements) {
3250            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
3251                var map = elementsToUpdate[i];
3252
3253                // add style / class to element
3254                //map.element.classList.add(map.addClass);
3255                //map.element.classList.remove(map.removeClass);
3256                $(map.element).addClass(map.addClass);
3257                $(map.element).removeClass(map.removeClass);
3258            }
3259
3260            // resume accepting scroll events
3261            busy = false;
3262        }
3263
3264        /* ====================
3265         * public function to initially style elements based on scroll position
3266         *
3267         * options:
3268         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
3269         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
3270         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
3271         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
3272         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
3273         *
3274         * ==================== */
3275        var pub = {
3276            init: function (options) {
3277
3278                // suspend accepting scroll events
3279                busy = true;
3280
3281                // merge options object with global options
3282                if (options) {
3283                    if (options.spsClass) {
3284                        spsClass = options.spsClass;
3285                        elements = document.getElementsByClassName(spsClass);
3286                    }
3287                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
3288                    classAbove = options.classAbove || classAbove;
3289                    classBelow = options.classBelow || classBelow;
3290                    offsetTag = options.offsetTag || offsetTag;
3291                }
3292
3293                // ensure all elements have classAbove
3294                var elementsToUpdate = getElementsToUpdate(true);
3295                if (elementsToUpdate.length > 0) {
3296
3297                    // asynchronuously update elements
3298                    window.requestAnimationFrame(function () {
3299                        updateElements(elementsToUpdate);
3300                    });
3301                } else {
3302
3303                    // resume accepting scroll events
3304                    busy = false;
3305                }
3306            }
3307        };
3308
3309        // register for window scroll events
3310        $(window).on("scroll", onScroll);
3311
3312        window.ScrollOverSelfStyler = pub;
3313
3314        return pub;
3315    })(document, window, jQuery);
3316}
3317
3318/* ====================
3319 * main initialization
3320 * ==================== */
3321$(function () {
3322    // defer initialization to allow browser to restore scroll position
3323    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
3324});if (typeof jQuery === 'undefined') {
3325    throw new Error('Block\'s JavaScript requires jQuery')
3326}
3327
3328+function ($) {
3329    'use strict';
3330    var version = $.fn.jquery.split(' ')[0].split('.')
3331    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
3332        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
3333    }
3334}(jQuery);
3335
3336
3337+function ($, win) {
3338    'use strict';
3339
3340    var DataKey = 'blktabs',
3341        BlockSel = '.block-item',
3342        TabSel = '> .module-container .blk-tabs > ul',
3343        BtnSel = '> li',
3344        ValSel = ' > a[href^="#blk"]',
3345        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
3346        DestroyBeforeSymbol = 'destroyBeforeSymbol',
3347        Event = {
3348            ReplacedBefore: 'renderview.replace.before',
3349            ReplacedAfter: 'renderview.replace.after',
3350            BlockDestroy: 'destroy',
3351            BlockAppear: DataKey + '.block.appear',
3352            BlockHidden: DataKey + '.block.hidden',
3353            Click: {
3354                Window: 'blk-nav-in',
3355                Before: DataKey + '.tabs.click.before',
3356                After: DataKey + '.tabs.click.after'
3357            }
3358        },
3359        Options = {
3360            focus: 'active'
3361        };
3362
3363    function BlockTabs(element, opts) {
3364
3365        var self = this;
3366        this._opts = $.extend(Options, $(element).data(), opts);
3367        this._element = element;
3368        this._tabs = $(TabSel, element).get(0);
3369
3370        // block 更新屬性值之後將會被置換
3371        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
3372        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
3373        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
3374            $(this).addClass(ReplacedBeforeSymbol);
3375            event.data.blktabs.resetTabStatus();
3376            $(this).removeClass(ReplacedBeforeSymbol);
3377            $.removeData(this, DataKey);
3378        });
3379
3380        // block 被刪除前復原 tab 關聯的 block
3381        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
3382            $(this).addClass(DestroyBeforeSymbol);
3383            event.data.blktabs.resetTabStatus();
3384        });
3385
3386        // block tabs click 事件
3387        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
3388            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
3389            if ($(element).attr('href').startsWith('#')) {
3390                event.preventDefault();
3391                event.data.blktabs.tabClick(element);
3392                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
3393                    target: element,
3394                    detail: {
3395                        selector: $(element).attr('href')
3396                    }
3397                }));
3398            }
3399        });
3400
3401        this.tabAppear().resetMyStatus();
3402
3403        var bookmarkId = window.location.href.split('#').pop();
3404        if (this._element.id == bookmarkId) {
3405            // 錨點跳轉
3406            var blk = this;
3407            window.addEventListener("load", function (event) {
3408
3409                var arrParentAndButton = function (blkId) {
3410                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
3411                    var pblk = tab.closest(BlockSel);
3412                    if (pblk.length > 0 && pblk.attr('id')) {
3413                        // 記錄&尋找
3414                        var r = arrParentAndButton(pblk.attr('id'));
3415                        r.push([pblk, tab]);
3416                        return r;
3417                    }
3418                    return [];
3419                };
3420                var arr = arrParentAndButton(blk._element.id);
3421                for (var i in arr)
3422                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
3423
3424                setTimeout(function () {
3425                    $("html, body").animate({
3426                        scrollTop: $(blk._element).offset().top
3427                    }, 500, 'swing', function () { });
3428                }, 0.5 * 1000);
3429            });
3430        }
3431    }
3432
3433    var _proto = BlockTabs.prototype;
3434
3435    _proto.tabAppear = function tabAppear() {
3436        if ($(BtnSel, this._tabs).length > 0)
3437            $(this._tabs).removeClass('d-none hide');
3438        return this;
3439    }
3440
3441
3442    // 取得 block tabs 所有關聯的 block target
3443    _proto.getTabSelector = function getTabSelector() {
3444        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
3445            return $(o).attr('href');
3446        }).get().join(',');
3447    }
3448
3449    // 驅動所有關聯的 block target 執行 resetMyStatus
3450    _proto.resetTabStatus = function resetTabStatus(event) {
3451        $(this.getTabSelector()).each(function () {
3452            if ($(this).data(DataKey))
3453                $(this).data(DataKey).resetMyStatus();
3454        });
3455        return this;
3456    }
3457
3458    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
3459    _proto.resetMyStatus = function resetMyStatus() {
3460        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
3461            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
3462            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
3463            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
3464            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
3465            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
3466
3467        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
3468            // 顯示 element
3469            this._element.style.setProperty('display', '');
3470
3471            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
3472            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
3473            if ($tabLink.length < 1)
3474                $tabLink = $(BtnSel + ValSel, this._tabs);
3475            this.tabClick($tabLink.get(0));
3476            $(this._element).trigger(Event.BlockAppear);
3477        }
3478        else {
3479            // 隱藏 element
3480            this._element.style.setProperty('display', 'none', 'important');
3481            $(this._element).trigger(Event.BlockHidden);
3482        }
3483
3484        return this.resetTabStatus();
3485    }
3486
3487    // 點擊 block tabs
3488    _proto.tabClick = function tabClick(currentBtn, closure) {
3489
3490        // 點擊執行內容
3491        if ($.contains(this._element, currentBtn)) {
3492
3493            // tab 切換前
3494            $(this._element).trigger(Event.Click.Before, [currentBtn]);
3495
3496            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
3497            $(currentBtn).addClass(Options.focus);
3498
3499            this.resetTabStatus();
3500
3501            // tab 切換後
3502            $(this._element).trigger(Event.Click.After, [currentBtn]);
3503
3504            if (typeof (closure) === "function")
3505                closure();
3506        }
3507
3508        return this;
3509    }
3510
3511    if (typeof $.fn.blockTab !== 'function') {
3512
3513        $.fn.extend({
3514            blockTab: function (options) {
3515                this.filter(function (i, o) {
3516                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
3517                }).each(function (event) {
3518                    $(this).data(DataKey, new BlockTabs(this, options));
3519                });
3520            }
3521        });
3522    }
3523
3524    $(function () {
3525        $(BlockSel).blockTab();
3526    });
3527
3528}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
3529/* MODULE 4d5d14c2-5508-4ce2-907f-f7133f76da2a, Version: 1.1.1 */
3530(function(a){a(function(){a(".mdu_U1iHHvea0WqgjVoHTLQ").each(function(b){})})})(jQuery);
3531/* MODULE 2efbc2f9-9f72-4e00-97ef-13398ef7c6f5, Version: 1.1.11 */
3532;(function($) {var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
3533
3534// NB: does not validate input
3535function encode(int) {
3536    if (int === 0) {
3537        return CHARSET[0];
3538    }
3539
3540    var res = "";
3541    while (int > 0) {
3542        res = CHARSET[int % 62] + res;
3543        int = Math.floor(int / 62);
3544    }
3545    return res;
3546};
3547
3548function decode(str) {
3549    var res = 0,
3550        length = str.length,
3551        i, char;
3552    for (i = 0; i < length; i++) {
3553        char = str.charCodeAt(i);
3554        if (char < 58) { // 0-9
3555            char = char - 48;
3556        } else if (char < 91) { // A-Z
3557            char = char - 29;
3558        } else { // a-z
3559            char = char - 87;
3560        }
3561        res += char * Math.pow(62, length - i - 1);
3562    }
3563    return res;
3564};
3565
3566function base62() {
3567    var id; //base62
3568    do {
3569      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
3570    } while (id.match(/^[0-9]/i) !== null);
3571    return id;
3572}/*!
3573 * jQuery1113 JavaScript Library v1.11.3
3574 * http://jQuery1113.com/
3575 *
3576 * Includes Sizzle.js
3577 * http://sizzlejs.com/
3578 *
3579 * Copyright 2005, 2014 jQuery1113 Foundation, Inc. and other contributors
3580 * Released under the MIT license
3581 * http://jQuery1113.org/license
3582 *
3583 * Date: 2015-04-28T16:19Z
3584 */
3585
3586(function( global, factory ) {
3587
3588	if ( typeof module === "object" && typeof module.exports === "object" ) {
3589		// For CommonJS and CommonJS-like environments where a proper window is present,
3590		// execute the factory and get jQuery1113
3591		// For environments that do not inherently posses a window with a document
3592		// (such as Node.js), expose a jQuery1113-making factory as module.exports
3593		// This accentuates the need for the creation of a real window
3594		// e.g. var jQuery1113 = require("jQuery1113")(window);
3595		// See ticket #14549 for more info
3596		module.exports = global.document ?
3597			factory( global, true ) :
3598			function( w ) {
3599				if ( !w.document ) {
3600					throw new Error( "jQuery1113 requires a window with a document" );
3601				}
3602				return factory( w );
3603			};
3604	} else {
3605		factory( global );
3606	}
3607
3608// Pass this if window is not defined yet
3609}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
3610
3611// Can't do this because several apps including ASP.NET trace
3612// the stack via arguments.caller.callee and Firefox dies if
3613// you try to trace through "use strict" call chains. (#13335)
3614// Support: Firefox 18+
3615//
3616
3617var deletedIds = [];
3618
3619var slice = deletedIds.slice;
3620
3621var concat = deletedIds.concat;
3622
3623var push = deletedIds.push;
3624
3625var indexOf = deletedIds.indexOf;
3626
3627var class2type = {};
3628
3629var toString = class2type.toString;
3630
3631var hasOwn = class2type.hasOwnProperty;
3632
3633var support = {};
3634
3635
3636
3637var
3638	version = "1.11.3",
3639
3640	// Define a local copy of jQuery1113
3641	jQuery1113 = function( selector, context ) {
3642		// The jQuery1113 object is actually just the init constructor 'enhanced'
3643		// Need init if jQuery1113 is called (just allow error to be thrown if not included)
3644		return new jQuery1113.fn.init( selector, context );
3645	},
3646
3647	// Support: Android<4.1, IE<9
3648	// Make sure we trim BOM and NBSP
3649	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
3650
3651	// Matches dashed string for camelizing
3652	rmsPrefix = /^-ms-/,
3653	rdashAlpha = /-([\da-z])/gi,
3654
3655	// Used by jQuery1113.camelCase as callback to replace()
3656	fcamelCase = function( all, letter ) {
3657		return letter.toUpperCase();
3658	};
3659
3660jQuery1113.fn = jQuery1113.prototype = {
3661	// The current version of jQuery1113 being used
3662	jQuery1113: version,
3663
3664	constructor: jQuery1113,
3665
3666	// Start with an empty selector
3667	selector: "",
3668
3669	// The default length of a jQuery1113 object is 0
3670	length: 0,
3671
3672	toArray: function() {
3673		return slice.call( this );
3674	},
3675
3676	// Get the Nth element in the matched element set OR
3677	// Get the whole matched element set as a clean array
3678	get: function( num ) {
3679		return num != null ?
3680
3681			// Return just the one element from the set
3682			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
3683
3684			// Return all the elements in a clean array
3685			slice.call( this );
3686	},
3687
3688	// Take an array of elements and push it onto the stack
3689	// (returning the new matched element set)
3690	pushStack: function( elems ) {
3691
3692		// Build a new jQuery1113 matched element set
3693		var ret = jQuery1113.merge( this.constructor(), elems );
3694
3695		// Add the old object onto the stack (as a reference)
vendor: 9,364 bytes, lines 3696-4076
3696		ret.prevObject = this;
3697		ret.context = this.context;
3698
3699		// Return the newly-formed element set
3700		return ret;
3701	},
3702
3703	// Execute a callback for every element in the matched set.
3704	// (You can seed the arguments with an array of args, but this is
3705	// only used internally.)
3706	each: function( callback, args ) {
3707		return jQuery1113.each( this, callback, args );
3708	},
3709
3710	map: function( callback ) {
3711		return this.pushStack( jQuery1113.map(this, function( elem, i ) {
3712			return callback.call( elem, i, elem );
3713		}));
3714	},
3715
3716	slice: function() {
3717		return this.pushStack( slice.apply( this, arguments ) );
3718	},
3719
3720	first: function() {
3721		return this.eq( 0 );
3722	},
3723
3724	last: function() {
3725		return this.eq( -1 );
3726	},
3727
3728	eq: function( i ) {
3729		var len = this.length,
3730			j = +i + ( i < 0 ? len : 0 );
3731		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
3732	},
3733
3734	end: function() {
3735		return this.prevObject || this.constructor(null);
3736	},
3737
3738	// For internal use only.
3739	// Behaves like an Array's method, not like a jQuery1113 method.
3740	push: push,
3741	sort: deletedIds.sort,
3742	splice: deletedIds.splice
3743};
3744
3745jQuery1113.extend = jQuery1113.fn.extend = function() {
3746	var src, copyIsArray, copy, name, options, clone,
3747		target = arguments[0] || {},
3748		i = 1,
3749		length = arguments.length,
3750		deep = false;
3751
3752	// Handle a deep copy situation
3753	if ( typeof target === "boolean" ) {
3754		deep = target;
3755
3756		// skip the boolean and the target
3757		target = arguments[ i ] || {};
3758		i++;
3759	}
3760
3761	// Handle case when target is a string or something (possible in deep copy)
3762	if ( typeof target !== "object" && !jQuery1113.isFunction(target) ) {
3763		target = {};
3764	}
3765
3766	// extend jQuery1113 itself if only one argument is passed
3767	if ( i === length ) {
3768		target = this;
3769		i--;
3770	}
3771
3772	for ( ; i < length; i++ ) {
3773		// Only deal with non-null/undefined values
3774		if ( (options = arguments[ i ]) != null ) {
3775			// Extend the base object
3776			for ( name in options ) {
3777				src = target[ name ];
3778				copy = options[ name ];
3779
3780				// Prevent never-ending loop
3781				if ( target === copy ) {
3782					continue;
3783				}
3784
3785				// Recurse if we're merging plain objects or arrays
3786				if ( deep && copy && ( jQuery1113.isPlainObject(copy) || (copyIsArray = jQuery1113.isArray(copy)) ) ) {
3787					if ( copyIsArray ) {
3788						copyIsArray = false;
3789						clone = src && jQuery1113.isArray(src) ? src : [];
3790
3791					} else {
3792						clone = src && jQuery1113.isPlainObject(src) ? src : {};
3793					}
3794
3795					// Never move original objects, clone them
3796					target[ name ] = jQuery1113.extend( deep, clone, copy );
3797
3798				// Don't bring in undefined values
3799				} else if ( copy !== undefined ) {
3800					target[ name ] = copy;
3801				}
3802			}
3803		}
3804	}
3805
3806	// Return the modified object
3807	return target;
3808};
3809
3810jQuery1113.extend({
3811	// Unique for each copy of jQuery1113 on the page
3812	expando: "jQuery1113" + ( version + Math.random() ).replace( /\D/g, "" ),
3813
3814	// Assume jQuery1113 is ready without the ready module
3815	isReady: true,
3816
3817	error: function( msg ) {
3818		throw new Error( msg );
3819	},
3820
3821	noop: function() {},
3822
3823	// See test/unit/core.js for details concerning isFunction.
3824	// Since version 1.3, DOM methods and functions like alert
3825	// aren't supported. They return false on IE (#2968).
3826	isFunction: function( obj ) {
3827		return jQuery1113.type(obj) === "function";
3828	},
3829
3830	isArray: Array.isArray || function( obj ) {
3831		return jQuery1113.type(obj) === "array";
3832	},
3833
3834	isWindow: function( obj ) {
3835		/* jshint eqeqeq: false */
3836		return obj != null && obj == obj.window;
3837	},
3838
3839	isNumeric: function( obj ) {
3840		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
3841		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
3842		// subtraction forces infinities to NaN
3843		// adding 1 corrects loss of precision from parseFloat (#15100)
3844		return !jQuery1113.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
3845	},
3846
3847	isEmptyObject: function( obj ) {
3848		var name;
3849		for ( name in obj ) {
3850			return false;
3851		}
3852		return true;
3853	},
3854
3855	isPlainObject: function( obj ) {
3856		var key;
3857
3858		// Must be an Object.
3859		// Because of IE, we also have to check the presence of the constructor property.
3860		// Make sure that DOM nodes and window objects don't pass through, as well
3861		if ( !obj || jQuery1113.type(obj) !== "object" || obj.nodeType || jQuery1113.isWindow( obj ) ) {
3862			return false;
3863		}
3864
3865		try {
3866			// Not own constructor property must be Object
3867			if ( obj.constructor &&
3868				!hasOwn.call(obj, "constructor") &&
3869				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
3870				return false;
3871			}
3872		} catch ( e ) {
3873			// IE8,9 Will throw exceptions on certain host objects #9897
3874			return false;
3875		}
3876
3877		// Support: IE<9
3878		// Handle iteration over inherited properties before own properties.
3879		if ( support.ownLast ) {
3880			for ( key in obj ) {
3881				return hasOwn.call( obj, key );
3882			}
3883		}
3884
3885		// Own properties are enumerated firstly, so to speed up,
3886		// if last one is own, then all properties are own.
3887		for ( key in obj ) {}
3888
3889		return key === undefined || hasOwn.call( obj, key );
3890	},
3891
3892	type: function( obj ) {
3893		if ( obj == null ) {
3894			return obj + "";
3895		}
3896		return typeof obj === "object" || typeof obj === "function" ?
3897			class2type[ toString.call(obj) ] || "object" :
3898			typeof obj;
3899	},
3900
3901	// Evaluates a script in a global context
3902	// Workarounds based on findings by Jim Driscoll
3903	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
3904	globalEval: function( data ) {
3905		if ( data && jQuery1113.trim( data ) ) {
3906			// We use execScript on Internet Explorer
3907			// We use an anonymous function so that context is window
3908			// rather than jQuery1113 in Firefox
3909			( window.execScript || function( data ) {
3910				window[ "eval" ].call( window, data );
3911			} )( data );
3912		}
3913	},
3914
3915	// Convert dashed to camelCase; used by the css and data modules
3916	// Microsoft forgot to hump their vendor prefix (#9572)
3917	camelCase: function( string ) {
3918		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
3919	},
3920
3921	nodeName: function( elem, name ) {
3922		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
3923	},
3924
3925	// args is for internal usage only
3926	each: function( obj, callback, args ) {
3927		var value,
3928			i = 0,
3929			length = obj.length,
3930			isArray = isArraylike( obj );
3931
3932		if ( args ) {
3933			if ( isArray ) {
3934				for ( ; i < length; i++ ) {
3935					value = callback.apply( obj[ i ], args );
3936
3937					if ( value === false ) {
3938						break;
3939					}
3940				}
3941			} else {
3942				for ( i in obj ) {
3943					value = callback.apply( obj[ i ], args );
3944
3945					if ( value === false ) {
3946						break;
3947					}
3948				}
3949			}
3950
3951		// A special, fast, case for the most common use of each
3952		} else {
3953			if ( isArray ) {
3954				for ( ; i < length; i++ ) {
3955					value = callback.call( obj[ i ], i, obj[ i ] );
3956
3957					if ( value === false ) {
3958						break;
3959					}
3960				}
3961			} else {
3962				for ( i in obj ) {
3963					value = callback.call( obj[ i ], i, obj[ i ] );
3964
3965					if ( value === false ) {
3966						break;
3967					}
3968				}
3969			}
3970		}
3971
3972		return obj;
3973	},
3974
3975	// Support: Android<4.1, IE<9
3976	trim: function( text ) {
3977		return text == null ?
3978			"" :
3979			( text + "" ).replace( rtrim, "" );
3980	},
3981
3982	// results is for internal usage only
3983	makeArray: function( arr, results ) {
3984		var ret = results || [];
3985
3986		if ( arr != null ) {
3987			if ( isArraylike( Object(arr) ) ) {
3988				jQuery1113.merge( ret,
3989					typeof arr === "string" ?
3990					[ arr ] : arr
3991				);
3992			} else {
3993				push.call( ret, arr );
3994			}
3995		}
3996
3997		return ret;
3998	},
3999
4000	inArray: function( elem, arr, i ) {
4001		var len;
4002
4003		if ( arr ) {
4004			if ( indexOf ) {
4005				return indexOf.call( arr, elem, i );
4006			}
4007
4008			len = arr.length;
4009			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
4010
4011			for ( ; i < len; i++ ) {
4012				// Skip accessing in sparse arrays
4013				if ( i in arr && arr[ i ] === elem ) {
4014					return i;
4015				}
4016			}
4017		}
4018
4019		return -1;
4020	},
4021
4022	merge: function( first, second ) {
4023		var len = +second.length,
4024			j = 0,
4025			i = first.length;
4026
4027		while ( j < len ) {
4028			first[ i++ ] = second[ j++ ];
4029		}
4030
4031		// Support: IE<9
4032		// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
4033		if ( len !== len ) {
4034			while ( second[j] !== undefined ) {
4035				first[ i++ ] = second[ j++ ];
4036			}
4037		}
4038
4039		first.length = i;
4040
4041		return first;
4042	},
4043
4044	grep: function( elems, callback, invert ) {
4045		var callbackInverse,
4046			matches = [],
4047			i = 0,
4048			length = elems.length,
4049			callbackExpect = !invert;
4050
4051		// Go through the array, only saving the items
4052		// that pass the validator function
4053		for ( ; i < length; i++ ) {
4054			callbackInverse = !callback( elems[ i ], i );
4055			if ( callbackInverse !== callbackExpect ) {
4056				matches.push( elems[ i ] );
4057			}
4058		}
4059
4060		return matches;
4061	},
4062
4063	// arg is for internal usage only
4064	map: function( elems, callback, arg ) {
4065		var value,
4066			i = 0,
4067			length = elems.length,
4068			isArray = isArraylike( elems ),
4069			ret = [];
4070
4071		// Go through the array, translating each of the items to their new values
4072		if ( isArray ) {
4073			for ( ; i < length; i++ ) {
4074				value = callback( elems[ i ], i, arg );
4075
4076				if ( value != null ) {
vendor: 27,588 bytes, lines 4077-5002
4077					ret.push( value );
4078				}
4079			}
4080
4081		// Go through every key on the object,
4082		} else {
4083			for ( i in elems ) {
4084				value = callback( elems[ i ], i, arg );
4085
4086				if ( value != null ) {
4087					ret.push( value );
4088				}
4089			}
4090		}
4091
4092		// Flatten any nested arrays
4093		return concat.apply( [], ret );
4094	},
4095
4096	// A global GUID counter for objects
4097	guid: 1,
4098
4099	// Bind a function to a context, optionally partially applying any
4100	// arguments.
4101	proxy: function( fn, context ) {
4102		var args, proxy, tmp;
4103
4104		if ( typeof context === "string" ) {
4105			tmp = fn[ context ];
4106			context = fn;
4107			fn = tmp;
4108		}
4109
4110		// Quick check to determine if target is callable, in the spec
4111		// this throws a TypeError, but we will just return undefined.
4112		if ( !jQuery1113.isFunction( fn ) ) {
4113			return undefined;
4114		}
4115
4116		// Simulated bind
4117		args = slice.call( arguments, 2 );
4118		proxy = function() {
4119			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
4120		};
4121
4122		// Set the guid of unique handler to the same of original handler, so it can be removed
4123		proxy.guid = fn.guid = fn.guid || jQuery1113.guid++;
4124
4125		return proxy;
4126	},
4127
4128	now: function() {
4129		return +( new Date() );
4130	},
4131
4132	// jQuery1113.support is not used in Core but other projects attach their
4133	// properties to it so it needs to exist.
4134	support: support
4135});
4136
4137// Populate the class2type map
4138jQuery1113.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
4139	class2type[ "[object " + name + "]" ] = name.toLowerCase();
4140});
4141
4142function isArraylike( obj ) {
4143
4144	// Support: iOS 8.2 (not reproducible in simulator)
4145	// `in` check used to prevent JIT error (gh-2145)
4146	// hasOwn isn't used here due to false negatives
4147	// regarding Nodelist length in IE
4148	var length = "length" in obj && obj.length,
4149		type = jQuery1113.type( obj );
4150
4151	if ( type === "function" || jQuery1113.isWindow( obj ) ) {
4152		return false;
4153	}
4154
4155	if ( obj.nodeType === 1 && length ) {
4156		return true;
4157	}
4158
4159	return type === "array" || length === 0 ||
4160		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
4161}
4162var Sizzle =
4163/*!
4164 * Sizzle CSS Selector Engine v2.2.0-pre
4165 * http://sizzlejs.com/
4166 *
4167 * Copyright 2008, 2014 jQuery1113 Foundation, Inc. and other contributors
4168 * Released under the MIT license
4169 * http://jQuery1113.org/license
4170 *
4171 * Date: 2014-12-16
4172 */
4173(function( window ) {
4174
4175var i,
4176	support,
4177	Expr,
4178	getText,
4179	isXML,
4180	tokenize,
4181	compile,
4182	select,
4183	outermostContext,
4184	sortInput,
4185	hasDuplicate,
4186
4187	// Local document vars
4188	setDocument,
4189	document,
4190	docElem,
4191	documentIsHTML,
4192	rbuggyQSA,
4193	rbuggyMatches,
4194	matches,
4195	contains,
4196
4197	// Instance-specific data
4198	expando = "sizzle" + 1 * new Date(),
4199	preferredDoc = window.document,
4200	dirruns = 0,
4201	done = 0,
4202	classCache = createCache(),
4203	tokenCache = createCache(),
4204	compilerCache = createCache(),
4205	sortOrder = function( a, b ) {
4206		if ( a === b ) {
4207			hasDuplicate = true;
4208		}
4209		return 0;
4210	},
4211
4212	// General-purpose constants
4213	MAX_NEGATIVE = 1 << 31,
4214
4215	// Instance methods
4216	hasOwn = ({}).hasOwnProperty,
4217	arr = [],
4218	pop = arr.pop,
4219	push_native = arr.push,
4220	push = arr.push,
4221	slice = arr.slice,
4222	// Use a stripped-down indexOf as it's faster than native
4223	// http://jsperf.com/thor-indexof-vs-for/5
4224	indexOf = function( list, elem ) {
4225		var i = 0,
4226			len = list.length;
4227		for ( ; i < len; i++ ) {
4228			if ( list[i] === elem ) {
4229				return i;
4230			}
4231		}
4232		return -1;
4233	},
4234
4235	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
4236
4237	// Regular expressions
4238
4239	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
4240	whitespace = "[\\x20\\t\\r\\n\\f]",
4241	// http://www.w3.org/TR/css3-syntax/#characters
4242	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
4243
4244	// Loosely modeled on CSS identifier characters
4245	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
4246	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
4247	identifier = characterEncoding.replace( "w", "w#" ),
4248
4249	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
4250	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
4251		// Operator (capture 2)
4252		"*([*^$|!~]?=)" + whitespace +
4253		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
4254		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
4255		"*\\]",
4256
4257	pseudos = ":(" + characterEncoding + ")(?:\\((" +
4258		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
4259		// 1. quoted (capture 3; capture 4 or capture 5)
4260		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
4261		// 2. simple (capture 6)
4262		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
4263		// 3. anything else (capture 2)
4264		".*" +
4265		")\\)|)",
4266
4267	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
4268	rwhitespace = new RegExp( whitespace + "+", "g" ),
4269	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
4270
4271	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
4272	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
4273
4274	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
4275
4276	rpseudo = new RegExp( pseudos ),
4277	ridentifier = new RegExp( "^" + identifier + "$" ),
4278
4279	matchExpr = {
4280		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
4281		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
4282		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
4283		"ATTR": new RegExp( "^" + attributes ),
4284		"PSEUDO": new RegExp( "^" + pseudos ),
4285		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
4286			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
4287			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
4288		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
4289		// For use in libraries implementing .is()
4290		// We use this for POS matching in `select`
4291		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
4292			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
4293	},
4294
4295	rinputs = /^(?:input|select|textarea|button)$/i,
4296	rheader = /^h\d$/i,
4297
4298	rnative = /^[^{]+\{\s*\[native \w/,
4299
4300	// Easily-parseable/retrievable ID or TAG or CLASS selectors
4301	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
4302
4303	rsibling = /[+~]/,
4304	rescape = /'|\\/g,
4305
4306	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
4307	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
4308	funescape = function( _, escaped, escapedWhitespace ) {
4309		var high = "0x" + escaped - 0x10000;
4310		// NaN means non-codepoint
4311		// Support: Firefox<24
4312		// Workaround erroneous numeric interpretation of +"0x"
4313		return high !== high || escapedWhitespace ?
4314			escaped :
4315			high < 0 ?
4316				// BMP codepoint
4317				String.fromCharCode( high + 0x10000 ) :
4318				// Supplemental Plane codepoint (surrogate pair)
4319				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
4320	},
4321
4322	// Used for iframes
4323	// See setDocument()
4324	// Removing the function wrapper causes a "Permission Denied"
4325	// error in IE
4326	unloadHandler = function() {
4327		setDocument();
4328	};
4329
4330// Optimize for push.apply( _, NodeList )
4331try {
4332	push.apply(
4333		(arr = slice.call( preferredDoc.childNodes )),
4334		preferredDoc.childNodes
4335	);
4336	// Support: Android<4.0
4337	// Detect silently failing push.apply
4338	arr[ preferredDoc.childNodes.length ].nodeType;
4339} catch ( e ) {
4340	push = { apply: arr.length ?
4341
4342		// Leverage slice if possible
4343		function( target, els ) {
4344			push_native.apply( target, slice.call(els) );
4345		} :
4346
4347		// Support: IE<9
4348		// Otherwise append directly
4349		function( target, els ) {
4350			var j = target.length,
4351				i = 0;
4352			// Can't trust NodeList.length
4353			while ( (target[j++] = els[i++]) ) {}
4354			target.length = j - 1;
4355		}
4356	};
4357}
4358
4359function Sizzle( selector, context, results, seed ) {
4360	var match, elem, m, nodeType,
4361		// QSA vars
4362		i, groups, old, nid, newContext, newSelector;
4363
4364	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
4365		setDocument( context );
4366	}
4367
4368	context = context || document;
4369	results = results || [];
4370	nodeType = context.nodeType;
4371
4372	if ( typeof selector !== "string" || !selector ||
4373		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
4374
4375		return results;
4376	}
4377
4378	if ( !seed && documentIsHTML ) {
4379
4380		// Try to shortcut find operations when possible (e.g., not under DocumentFragment)
4381		if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
4382			// Speed-up: Sizzle("#ID")
4383			if ( (m = match[1]) ) {
4384				if ( nodeType === 9 ) {
4385					elem = context.getElementById( m );
4386					// Check parentNode to catch when Blackberry 4.6 returns
4387					// nodes that are no longer in the document (jQuery1113 #6963)
4388					if ( elem && elem.parentNode ) {
4389						// Handle the case where IE, Opera, and Webkit return items
4390						// by name instead of ID
4391						if ( elem.id === m ) {
4392							results.push( elem );
4393							return results;
4394						}
4395					} else {
4396						return results;
4397					}
4398				} else {
4399					// Context is not a document
4400					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
4401						contains( context, elem ) && elem.id === m ) {
4402						results.push( elem );
4403						return results;
4404					}
4405				}
4406
4407			// Speed-up: Sizzle("TAG")
4408			} else if ( match[2] ) {
4409				push.apply( results, context.getElementsByTagName( selector ) );
4410				return results;
4411
4412			// Speed-up: Sizzle(".CLASS")
4413			} else if ( (m = match[3]) && support.getElementsByClassName ) {
4414				push.apply( results, context.getElementsByClassName( m ) );
4415				return results;
4416			}
4417		}
4418
4419		// QSA path
4420		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
4421			nid = old = expando;
4422			newContext = context;
4423			newSelector = nodeType !== 1 && selector;
4424
4425			// qSA works strangely on Element-rooted queries
4426			// We can work around this by specifying an extra ID on the root
4427			// and working up from there (Thanks to Andrew Dupont for the technique)
4428			// IE 8 doesn't work on object elements
4429			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
4430				groups = tokenize( selector );
4431
4432				if ( (old = context.getAttribute("id")) ) {
4433					nid = old.replace( rescape, "\\$&" );
4434				} else {
4435					context.setAttribute( "id", nid );
4436				}
4437				nid = "[id='" + nid + "'] ";
4438
4439				i = groups.length;
4440				while ( i-- ) {
4441					groups[i] = nid + toSelector( groups[i] );
4442				}
4443				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
4444				newSelector = groups.join(",");
4445			}
4446
4447			if ( newSelector ) {
4448				try {
4449					push.apply( results,
4450						newContext.querySelectorAll( newSelector )
4451					);
4452					return results;
4453				} catch(qsaError) {
4454				} finally {
4455					if ( !old ) {
4456						context.removeAttribute("id");
4457					}
4458				}
4459			}
4460		}
4461	}
4462
4463	// All others
4464	return select( selector.replace( rtrim, "$1" ), context, results, seed );
4465}
4466
4467/**
4468 * Create key-value caches of limited size
4469 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
4470 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
4471 *	deleting the oldest entry
4472 */
4473function createCache() {
4474	var keys = [];
4475
4476	function cache( key, value ) {
4477		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
4478		if ( keys.push( key + " " ) > Expr.cacheLength ) {
4479			// Only keep the most recent entries
4480			delete cache[ keys.shift() ];
4481		}
4482		return (cache[ key + " " ] = value);
4483	}
4484	return cache;
4485}
4486
4487/**
4488 * Mark a function for special use by Sizzle
4489 * @param {Function} fn The function to mark
4490 */
4491function markFunction( fn ) {
4492	fn[ expando ] = true;
4493	return fn;
4494}
4495
4496/**
4497 * Support testing using an element
4498 * @param {Function} fn Passed the created div and expects a boolean result
4499 */
4500function assert( fn ) {
4501	var div = document.createElement("div");
4502
4503	try {
4504		return !!fn( div );
4505	} catch (e) {
4506		return false;
4507	} finally {
4508		// Remove from its parent by default
4509		if ( div.parentNode ) {
4510			div.parentNode.removeChild( div );
4511		}
4512		// release memory in IE
4513		div = null;
4514	}
4515}
4516
4517/**
4518 * Adds the same handler for all of the specified attrs
4519 * @param {String} attrs Pipe-separated list of attributes
4520 * @param {Function} handler The method that will be applied
4521 */
4522function addHandle( attrs, handler ) {
4523	var arr = attrs.split("|"),
4524		i = attrs.length;
4525
4526	while ( i-- ) {
4527		Expr.attrHandle[ arr[i] ] = handler;
4528	}
4529}
4530
4531/**
4532 * Checks document order of two siblings
4533 * @param {Element} a
4534 * @param {Element} b
4535 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
4536 */
4537function siblingCheck( a, b ) {
4538	var cur = b && a,
4539		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
4540			( ~b.sourceIndex || MAX_NEGATIVE ) -
4541			( ~a.sourceIndex || MAX_NEGATIVE );
4542
4543	// Use IE sourceIndex if available on both nodes
4544	if ( diff ) {
4545		return diff;
4546	}
4547
4548	// Check if b follows a
4549	if ( cur ) {
4550		while ( (cur = cur.nextSibling) ) {
4551			if ( cur === b ) {
4552				return -1;
4553			}
4554		}
4555	}
4556
4557	return a ? 1 : -1;
4558}
4559
4560/**
4561 * Returns a function to use in pseudos for input types
4562 * @param {String} type
4563 */
4564function createInputPseudo( type ) {
4565	return function( elem ) {
4566		var name = elem.nodeName.toLowerCase();
4567		return name === "input" && elem.type === type;
4568	};
4569}
4570
4571/**
4572 * Returns a function to use in pseudos for buttons
4573 * @param {String} type
4574 */
4575function createButtonPseudo( type ) {
4576	return function( elem ) {
4577		var name = elem.nodeName.toLowerCase();
4578		return (name === "input" || name === "button") && elem.type === type;
4579	};
4580}
4581
4582/**
4583 * Returns a function to use in pseudos for positionals
4584 * @param {Function} fn
4585 */
4586function createPositionalPseudo( fn ) {
4587	return markFunction(function( argument ) {
4588		argument = +argument;
4589		return markFunction(function( seed, matches ) {
4590			var j,
4591				matchIndexes = fn( [], seed.length, argument ),
4592				i = matchIndexes.length;
4593
4594			// Match elements found at the specified indexes
4595			while ( i-- ) {
4596				if ( seed[ (j = matchIndexes[i]) ] ) {
4597					seed[j] = !(matches[j] = seed[j]);
4598				}
4599			}
4600		});
4601	});
4602}
4603
4604/**
4605 * Checks a node for validity as a Sizzle context
4606 * @param {Element|Object=} context
4607 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
4608 */
4609function testContext( context ) {
4610	return context && typeof context.getElementsByTagName !== "undefined" && context;
4611}
4612
4613// Expose support vars for convenience
4614support = Sizzle.support = {};
4615
4616/**
4617 * Detects XML nodes
4618 * @param {Element|Object} elem An element or a document
4619 * @returns {Boolean} True iff elem is a non-HTML XML node
4620 */
4621isXML = Sizzle.isXML = function( elem ) {
4622	// documentElement is verified for cases where it doesn't yet exist
4623	// (such as loading iframes in IE - #4833)
4624	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
4625	return documentElement ? documentElement.nodeName !== "HTML" : false;
4626};
4627
4628/**
4629 * Sets document-related variables once based on the current document
4630 * @param {Element|Object} [doc] An element or document object to use to set the document
4631 * @returns {Object} Returns the current document
4632 */
4633setDocument = Sizzle.setDocument = function( node ) {
4634	var hasCompare, parent,
4635		doc = node ? node.ownerDocument || node : preferredDoc;
4636
4637	// If no document and documentElement is available, return
4638	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
4639		return document;
4640	}
4641
4642	// Set our document
4643	document = doc;
4644	docElem = doc.documentElement;
4645	parent = doc.defaultView;
4646
4647	// Support: IE>8
4648	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
4649	// IE will throw "permission denied" error when accessing "document" variable, see jQuery1113 #13936
4650	// IE6-8 do not support the defaultView property so parent will be undefined
4651	if ( parent && parent !== parent.top ) {
4652		// IE11 does not have attachEvent, so all must suffer
4653		if ( parent.addEventListener ) {
4654			parent.addEventListener( "unload", unloadHandler, false );
4655		} else if ( parent.attachEvent ) {
4656			parent.attachEvent( "onunload", unloadHandler );
4657		}
4658	}
4659
4660	/* Support tests
4661	---------------------------------------------------------------------- */
4662	documentIsHTML = !isXML( doc );
4663
4664	/* Attributes
4665	---------------------------------------------------------------------- */
4666
4667	// Support: IE<8
4668	// Verify that getAttribute really returns attributes and not properties
4669	// (excepting IE8 booleans)
4670	support.attributes = assert(function( div ) {
4671		div.className = "i";
4672		return !div.getAttribute("className");
4673	});
4674
4675	/* getElement(s)By*
4676	---------------------------------------------------------------------- */
4677
4678	// Check if getElementsByTagName("*") returns only elements
4679	support.getElementsByTagName = assert(function( div ) {
4680		div.appendChild( doc.createComment("") );
4681		return !div.getElementsByTagName("*").length;
4682	});
4683
4684	// Support: IE<9
4685	support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
4686
4687	// Support: IE<10
4688	// Check if getElementById returns elements by name
4689	// The broken getElementById methods don't pick up programatically-set names,
4690	// so use a roundabout getElementsByName test
4691	support.getById = assert(function( div ) {
4692		docElem.appendChild( div ).id = expando;
4693		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
4694	});
4695
4696	// ID find and filter
4697	if ( support.getById ) {
4698		Expr.find["ID"] = function( id, context ) {
4699			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
4700				var m = context.getElementById( id );
4701				// Check parentNode to catch when Blackberry 4.6 returns
4702				// nodes that are no longer in the document #6963
4703				return m && m.parentNode ? [ m ] : [];
4704			}
4705		};
4706		Expr.filter["ID"] = function( id ) {
4707			var attrId = id.replace( runescape, funescape );
4708			return function( elem ) {
4709				return elem.getAttribute("id") === attrId;
4710			};
4711		};
4712	} else {
4713		// Support: IE6/7
4714		// getElementById is not reliable as a find shortcut
4715		delete Expr.find["ID"];
4716
4717		Expr.filter["ID"] =  function( id ) {
4718			var attrId = id.replace( runescape, funescape );
4719			return function( elem ) {
4720				var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
4721				return node && node.value === attrId;
4722			};
4723		};
4724	}
4725
4726	// Tag
4727	Expr.find["TAG"] = support.getElementsByTagName ?
4728		function( tag, context ) {
4729			if ( typeof context.getElementsByTagName !== "undefined" ) {
4730				return context.getElementsByTagName( tag );
4731
4732			// DocumentFragment nodes don't have gEBTN
4733			} else if ( support.qsa ) {
4734				return context.querySelectorAll( tag );
4735			}
4736		} :
4737
4738		function( tag, context ) {
4739			var elem,
4740				tmp = [],
4741				i = 0,
4742				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
4743				results = context.getElementsByTagName( tag );
4744
4745			// Filter out possible comments
4746			if ( tag === "*" ) {
4747				while ( (elem = results[i++]) ) {
4748					if ( elem.nodeType === 1 ) {
4749						tmp.push( elem );
4750					}
4751				}
4752
4753				return tmp;
4754			}
4755			return results;
4756		};
4757
4758	// Class
4759	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
4760		if ( documentIsHTML ) {
4761			return context.getElementsByClassName( className );
4762		}
4763	};
4764
4765	/* QSA/matchesSelector
4766	---------------------------------------------------------------------- */
4767
4768	// QSA and matchesSelector support
4769
4770	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
4771	rbuggyMatches = [];
4772
4773	// qSa(:focus) reports false when true (Chrome 21)
4774	// We allow this because of a bug in IE8/9 that throws an error
4775	// whenever `document.activeElement` is accessed on an iframe
4776	// So, we allow :focus to pass through QSA all the time to avoid the IE error
4777	// See http://bugs.jQuery1113.com/ticket/13378
4778	rbuggyQSA = [];
4779
4780	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
4781		// Build QSA regex
4782		// Regex strategy adopted from Diego Perini
4783		assert(function( div ) {
4784			// Select is set to empty string on purpose
4785			// This is to test IE's treatment of not explicitly
4786			// setting a boolean content attribute,
4787			// since its presence should be enough
4788			// http://bugs.jQuery1113.com/ticket/12359
4789			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
4790				"<select id='" + expando + "-\f]' msallowcapture=''>" +
4791				"<option selected=''></option></select>";
4792
4793			// Support: IE8, Opera 11-12.16
4794			// Nothing should be selected when empty strings follow ^= or $= or *=
4795			// The test attribute must be unknown in Opera but "safe" for WinRT
4796			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
4797			if ( div.querySelectorAll("[msallowcapture^='']").length ) {
4798				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
4799			}
4800
4801			// Support: IE8
4802			// Boolean attributes and "value" are not treated correctly
4803			if ( !div.querySelectorAll("[selected]").length ) {
4804				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
4805			}
4806
4807			// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
4808			if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
4809				rbuggyQSA.push("~=");
4810			}
4811
4812			// Webkit/Opera - :checked should return selected option elements
4813			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4814			// IE8 throws error here and will not see later tests
4815			if ( !div.querySelectorAll(":checked").length ) {
4816				rbuggyQSA.push(":checked");
4817			}
4818
4819			// Support: Safari 8+, iOS 8+
4820			// https://bugs.webkit.org/show_bug.cgi?id=136851
4821			// In-page `selector#id sibing-combinator selector` fails
4822			if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
4823				rbuggyQSA.push(".#.+[+~]");
4824			}
4825		});
4826
4827		assert(function( div ) {
4828			// Support: Windows 8 Native Apps
4829			// The type and name attributes are restricted during .innerHTML assignment
4830			var input = doc.createElement("input");
4831			input.setAttribute( "type", "hidden" );
4832			div.appendChild( input ).setAttribute( "name", "D" );
4833
4834			// Support: IE8
4835			// Enforce case-sensitivity of name attribute
4836			if ( div.querySelectorAll("[name=d]").length ) {
4837				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
4838			}
4839
4840			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
4841			// IE8 throws error here and will not see later tests
4842			if ( !div.querySelectorAll(":enabled").length ) {
4843				rbuggyQSA.push( ":enabled", ":disabled" );
4844			}
4845
4846			// Opera 10-11 does not throw on post-comma invalid pseudos
4847			div.querySelectorAll("*,:x");
4848			rbuggyQSA.push(",.*:");
4849		});
4850	}
4851
4852	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
4853		docElem.webkitMatchesSelector ||
4854		docElem.mozMatchesSelector ||
4855		docElem.oMatchesSelector ||
4856		docElem.msMatchesSelector) )) ) {
4857
4858		assert(function( div ) {
4859			// Check to see if it's possible to do matchesSelector
4860			// on a disconnected node (IE 9)
4861			support.disconnectedMatch = matches.call( div, "div" );
4862
4863			// This should fail with an exception
4864			// Gecko does not error, returns false instead
4865			matches.call( div, "[s!='']:x" );
4866			rbuggyMatches.push( "!=", pseudos );
4867		});
4868	}
4869
4870	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
4871	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
4872
4873	/* Contains
4874	---------------------------------------------------------------------- */
4875	hasCompare = rnative.test( docElem.compareDocumentPosition );
4876
4877	// Element contains another
4878	// Purposefully does not implement inclusive descendent
4879	// As in, an element does not contain itself
4880	contains = hasCompare || rnative.test( docElem.contains ) ?
4881		function( a, b ) {
4882			var adown = a.nodeType === 9 ? a.documentElement : a,
4883				bup = b && b.parentNode;
4884			return a === bup || !!( bup && bup.nodeType === 1 && (
4885				adown.contains ?
4886					adown.contains( bup ) :
4887					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
4888			));
4889		} :
4890		function( a, b ) {
4891			if ( b ) {
4892				while ( (b = b.parentNode) ) {
4893					if ( b === a ) {
4894						return true;
4895					}
4896				}
4897			}
4898			return false;
4899		};
4900
4901	/* Sorting
4902	---------------------------------------------------------------------- */
4903
4904	// Document order sorting
4905	sortOrder = hasCompare ?
4906	function( a, b ) {
4907
4908		// Flag for duplicate removal
4909		if ( a === b ) {
4910			hasDuplicate = true;
4911			return 0;
4912		}
4913
4914		// Sort on method existence if only one input has compareDocumentPosition
4915		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
4916		if ( compare ) {
4917			return compare;
4918		}
4919
4920		// Calculate position if both inputs belong to the same document
4921		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
4922			a.compareDocumentPosition( b ) :
4923
4924			// Otherwise we know they are disconnected
4925			1;
4926
4927		// Disconnected nodes
4928		if ( compare & 1 ||
4929			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
4930
4931			// Choose the first element that is related to our preferred document
4932			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
4933				return -1;
4934			}
4935			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
4936				return 1;
4937			}
4938
4939			// Maintain original order
4940			return sortInput ?
4941				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
4942				0;
4943		}
4944
4945		return compare & 4 ? -1 : 1;
4946	} :
4947	function( a, b ) {
4948		// Exit early if the nodes are identical
4949		if ( a === b ) {
4950			hasDuplicate = true;
4951			return 0;
4952		}
4953
4954		var cur,
4955			i = 0,
4956			aup = a.parentNode,
4957			bup = b.parentNode,
4958			ap = [ a ],
4959			bp = [ b ];
4960
4961		// Parentless nodes are either documents or disconnected
4962		if ( !aup || !bup ) {
4963			return a === doc ? -1 :
4964				b === doc ? 1 :
4965				aup ? -1 :
4966				bup ? 1 :
4967				sortInput ?
4968				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
4969				0;
4970
4971		// If the nodes are siblings, we can do a quick check
4972		} else if ( aup === bup ) {
4973			return siblingCheck( a, b );
4974		}
4975
4976		// Otherwise we need full lists of their ancestors for comparison
4977		cur = a;
4978		while ( (cur = cur.parentNode) ) {
4979			ap.unshift( cur );
4980		}
4981		cur = b;
4982		while ( (cur = cur.parentNode) ) {
4983			bp.unshift( cur );
4984		}
4985
4986		// Walk down the tree looking for a discrepancy
4987		while ( ap[i] === bp[i] ) {
4988			i++;
4989		}
4990
4991		return i ?
4992			// Do a sibling check if the nodes have a common ancestor
4993			siblingCheck( ap[i], bp[i] ) :
4994
4995			// Otherwise nodes in our document sort first
4996			ap[i] === preferredDoc ? -1 :
4997			bp[i] === preferredDoc ? 1 :
4998			0;
4999	};
5000
5001	return doc;
5002};
vendor: 4,496 bytes, lines 5003-5175
5003
5004Sizzle.matches = function( expr, elements ) {
5005	return Sizzle( expr, null, null, elements );
5006};
5007
5008Sizzle.matchesSelector = function( elem, expr ) {
5009	// Set document vars if needed
5010	if ( ( elem.ownerDocument || elem ) !== document ) {
5011		setDocument( elem );
5012	}
5013
5014	// Make sure that attribute selectors are quoted
5015	expr = expr.replace( rattributeQuotes, "='$1']" );
5016
5017	if ( support.matchesSelector && documentIsHTML &&
5018		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
5019		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
5020
5021		try {
5022			var ret = matches.call( elem, expr );
5023
5024			// IE 9's matchesSelector returns false on disconnected nodes
5025			if ( ret || support.disconnectedMatch ||
5026					// As well, disconnected nodes are said to be in a document
5027					// fragment in IE 9
5028					elem.document && elem.document.nodeType !== 11 ) {
5029				return ret;
5030			}
5031		} catch (e) {}
5032	}
5033
5034	return Sizzle( expr, document, null, [ elem ] ).length > 0;
5035};
5036
5037Sizzle.contains = function( context, elem ) {
5038	// Set document vars if needed
5039	if ( ( context.ownerDocument || context ) !== document ) {
5040		setDocument( context );
5041	}
5042	return contains( context, elem );
5043};
5044
5045Sizzle.attr = function( elem, name ) {
5046	// Set document vars if needed
5047	if ( ( elem.ownerDocument || elem ) !== document ) {
5048		setDocument( elem );
5049	}
5050
5051	var fn = Expr.attrHandle[ name.toLowerCase() ],
5052		// Don't get fooled by Object.prototype properties (jQuery1113 #13807)
5053		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
5054			fn( elem, name, !documentIsHTML ) :
5055			undefined;
5056
5057	return val !== undefined ?
5058		val :
5059		support.attributes || !documentIsHTML ?
5060			elem.getAttribute( name ) :
5061			(val = elem.getAttributeNode(name)) && val.specified ?
5062				val.value :
5063				null;
5064};
5065
5066Sizzle.error = function( msg ) {
5067	throw new Error( "Syntax error, unrecognized expression: " + msg );
5068};
5069
5070/**
5071 * Document sorting and removing duplicates
5072 * @param {ArrayLike} results
5073 */
5074Sizzle.uniqueSort = function( results ) {
5075	var elem,
5076		duplicates = [],
5077		j = 0,
5078		i = 0;
5079
5080	// Unless we *know* we can detect duplicates, assume their presence
5081	hasDuplicate = !support.detectDuplicates;
5082	sortInput = !support.sortStable && results.slice( 0 );
5083	results.sort( sortOrder );
5084
5085	if ( hasDuplicate ) {
5086		while ( (elem = results[i++]) ) {
5087			if ( elem === results[ i ] ) {
5088				j = duplicates.push( i );
5089			}
5090		}
5091		while ( j-- ) {
5092			results.splice( duplicates[ j ], 1 );
5093		}
5094	}
5095
5096	// Clear input after sorting to release objects
5097	// See https://github.com/jQuery1113/sizzle/pull/225
5098	sortInput = null;
5099
5100	return results;
5101};
5102
5103/**
5104 * Utility function for retrieving the text value of an array of DOM nodes
5105 * @param {Array|Element} elem
5106 */
5107getText = Sizzle.getText = function( elem ) {
5108	var node,
5109		ret = "",
5110		i = 0,
5111		nodeType = elem.nodeType;
5112
5113	if ( !nodeType ) {
5114		// If no nodeType, this is expected to be an array
5115		while ( (node = elem[i++]) ) {
5116			// Do not traverse comment nodes
5117			ret += getText( node );
5118		}
5119	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
5120		// Use textContent for elements
5121		// innerText usage removed for consistency of new lines (jQuery1113 #11153)
5122		if ( typeof elem.textContent === "string" ) {
5123			return elem.textContent;
5124		} else {
5125			// Traverse its children
5126			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
5127				ret += getText( elem );
5128			}
5129		}
5130	} else if ( nodeType === 3 || nodeType === 4 ) {
5131		return elem.nodeValue;
5132	}
5133	// Do not include comment or processing instruction nodes
5134
5135	return ret;
5136};
5137
5138Expr = Sizzle.selectors = {
5139
5140	// Can be adjusted by the user
5141	cacheLength: 50,
5142
5143	createPseudo: markFunction,
5144
5145	match: matchExpr,
5146
5147	attrHandle: {},
5148
5149	find: {},
5150
5151	relative: {
5152		">": { dir: "parentNode", first: true },
5153		" ": { dir: "parentNode" },
5154		"+": { dir: "previousSibling", first: true },
5155		"~": { dir: "previousSibling" }
5156	},
5157
5158	preFilter: {
5159		"ATTR": function( match ) {
5160			match[1] = match[1].replace( runescape, funescape );
5161
5162			// Move the given value to match[3] whether quoted or unquoted
5163			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
5164
5165			if ( match[2] === "~=" ) {
5166				match[3] = " " + match[3] + " ";
5167			}
5168
5169			return match.slice( 0, 4 );
5170		},
5171
5172		"CHILD": function( match ) {
5173			/* matches from matchExpr["CHILD"]
5174				1 type (only|nth|...)
5175				2 what (child|of-type)
vendor: 10,120 bytes, lines 5176-5487
5176				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
5177				4 xn-component of xn+y argument ([+-]?\d*n|)
5178				5 sign of xn-component
5179				6 x of xn-component
5180				7 sign of y-component
5181				8 y of y-component
5182			*/
5183			match[1] = match[1].toLowerCase();
5184
5185			if ( match[1].slice( 0, 3 ) === "nth" ) {
5186				// nth-* requires argument
5187				if ( !match[3] ) {
5188					Sizzle.error( match[0] );
5189				}
5190
5191				// numeric x and y parameters for Expr.filter.CHILD
5192				// remember that false/true cast respectively to 0/1
5193				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
5194				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
5195
5196			// other types prohibit arguments
5197			} else if ( match[3] ) {
5198				Sizzle.error( match[0] );
5199			}
5200
5201			return match;
5202		},
5203
5204		"PSEUDO": function( match ) {
5205			var excess,
5206				unquoted = !match[6] && match[2];
5207
5208			if ( matchExpr["CHILD"].test( match[0] ) ) {
5209				return null;
5210			}
5211
5212			// Accept quoted arguments as-is
5213			if ( match[3] ) {
5214				match[2] = match[4] || match[5] || "";
5215
5216			// Strip excess characters from unquoted arguments
5217			} else if ( unquoted && rpseudo.test( unquoted ) &&
5218				// Get excess from tokenize (recursively)
5219				(excess = tokenize( unquoted, true )) &&
5220				// advance to the next closing parenthesis
5221				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
5222
5223				// excess is a negative index
5224				match[0] = match[0].slice( 0, excess );
5225				match[2] = unquoted.slice( 0, excess );
5226			}
5227
5228			// Return only captures needed by the pseudo filter method (type and argument)
5229			return match.slice( 0, 3 );
5230		}
5231	},
5232
5233	filter: {
5234
5235		"TAG": function( nodeNameSelector ) {
5236			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
5237			return nodeNameSelector === "*" ?
5238				function() { return true; } :
5239				function( elem ) {
5240					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
5241				};
5242		},
5243
5244		"CLASS": function( className ) {
5245			var pattern = classCache[ className + " " ];
5246
5247			return pattern ||
5248				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
5249				classCache( className, function( elem ) {
5250					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
5251				});
5252		},
5253
5254		"ATTR": function( name, operator, check ) {
5255			return function( elem ) {
5256				var result = Sizzle.attr( elem, name );
5257
5258				if ( result == null ) {
5259					return operator === "!=";
5260				}
5261				if ( !operator ) {
5262					return true;
5263				}
5264
5265				result += "";
5266
5267				return operator === "=" ? result === check :
5268					operator === "!=" ? result !== check :
5269					operator === "^=" ? check && result.indexOf( check ) === 0 :
5270					operator === "*=" ? check && result.indexOf( check ) > -1 :
5271					operator === "$=" ? check && result.slice( -check.length ) === check :
5272					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
5273					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
5274					false;
5275			};
5276		},
5277
5278		"CHILD": function( type, what, argument, first, last ) {
5279			var simple = type.slice( 0, 3 ) !== "nth",
5280				forward = type.slice( -4 ) !== "last",
5281				ofType = what === "of-type";
5282
5283			return first === 1 && last === 0 ?
5284
5285				// Shortcut for :nth-*(n)
5286				function( elem ) {
5287					return !!elem.parentNode;
5288				} :
5289
5290				function( elem, context, xml ) {
5291					var cache, outerCache, node, diff, nodeIndex, start,
5292						dir = simple !== forward ? "nextSibling" : "previousSibling",
5293						parent = elem.parentNode,
5294						name = ofType && elem.nodeName.toLowerCase(),
5295						useCache = !xml && !ofType;
5296
5297					if ( parent ) {
5298
5299						// :(first|last|only)-(child|of-type)
5300						if ( simple ) {
5301							while ( dir ) {
5302								node = elem;
5303								while ( (node = node[ dir ]) ) {
5304									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
5305										return false;
5306									}
5307								}
5308								// Reverse direction for :only-* (if we haven't yet done so)
5309								start = dir = type === "only" && !start && "nextSibling";
5310							}
5311							return true;
5312						}
5313
5314						start = [ forward ? parent.firstChild : parent.lastChild ];
5315
5316						// non-xml :nth-child(...) stores cache data on `parent`
5317						if ( forward && useCache ) {
5318							// Seek `elem` from a previously-cached index
5319							outerCache = parent[ expando ] || (parent[ expando ] = {});
5320							cache = outerCache[ type ] || [];
5321							nodeIndex = cache[0] === dirruns && cache[1];
5322							diff = cache[0] === dirruns && cache[2];
5323							node = nodeIndex && parent.childNodes[ nodeIndex ];
5324
5325							while ( (node = ++nodeIndex && node && node[ dir ] ||
5326
5327								// Fallback to seeking `elem` from the start
5328								(diff = nodeIndex = 0) || start.pop()) ) {
5329
5330								// When found, cache indexes on `parent` and break
5331								if ( node.nodeType === 1 && ++diff && node === elem ) {
5332									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
5333									break;
5334								}
5335							}
5336
5337						// Use previously-cached element index if available
5338						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
5339							diff = cache[1];
5340
5341						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
5342						} else {
5343							// Use the same loop as above to seek `elem` from the start
5344							while ( (node = ++nodeIndex && node && node[ dir ] ||
5345								(diff = nodeIndex = 0) || start.pop()) ) {
5346
5347								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
5348									// Cache the index of each encountered element
5349									if ( useCache ) {
5350										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
5351									}
5352
5353									if ( node === elem ) {
5354										break;
5355									}
5356								}
5357							}
5358						}
5359
5360						// Incorporate the offset, then check against cycle size
5361						diff -= last;
5362						return diff === first || ( diff % first === 0 && diff / first >= 0 );
5363					}
5364				};
5365		},
5366
5367		"PSEUDO": function( pseudo, argument ) {
5368			// pseudo-class names are case-insensitive
5369			// http://www.w3.org/TR/selectors/#pseudo-classes
5370			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
5371			// Remember that setFilters inherits from pseudos
5372			var args,
5373				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
5374					Sizzle.error( "unsupported pseudo: " + pseudo );
5375
5376			// The user may use createPseudo to indicate that
5377			// arguments are needed to create the filter function
5378			// just as Sizzle does
5379			if ( fn[ expando ] ) {
5380				return fn( argument );
5381			}
5382
5383			// But maintain support for old signatures
5384			if ( fn.length > 1 ) {
5385				args = [ pseudo, pseudo, "", argument ];
5386				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
5387					markFunction(function( seed, matches ) {
5388						var idx,
5389							matched = fn( seed, argument ),
5390							i = matched.length;
5391						while ( i-- ) {
5392							idx = indexOf( seed, matched[i] );
5393							seed[ idx ] = !( matches[ idx ] = matched[i] );
5394						}
5395					}) :
5396					function( elem ) {
5397						return fn( elem, 0, args );
5398					};
5399			}
5400
5401			return fn;
5402		}
5403	},
5404
5405	pseudos: {
5406		// Potentially complex pseudos
5407		"not": markFunction(function( selector ) {
5408			// Trim the selector passed to compile
5409			// to avoid treating leading and trailing
5410			// spaces as combinators
5411			var input = [],
5412				results = [],
5413				matcher = compile( selector.replace( rtrim, "$1" ) );
5414
5415			return matcher[ expando ] ?
5416				markFunction(function( seed, matches, context, xml ) {
5417					var elem,
5418						unmatched = matcher( seed, null, xml, [] ),
5419						i = seed.length;
5420
5421					// Match elements unmatched by `matcher`
5422					while ( i-- ) {
5423						if ( (elem = unmatched[i]) ) {
5424							seed[i] = !(matches[i] = elem);
5425						}
5426					}
5427				}) :
5428				function( elem, context, xml ) {
5429					input[0] = elem;
5430					matcher( input, null, xml, results );
5431					// Don't keep the element (issue #299)
5432					input[0] = null;
5433					return !results.pop();
5434				};
5435		}),
5436
5437		"has": markFunction(function( selector ) {
5438			return function( elem ) {
5439				return Sizzle( selector, elem ).length > 0;
5440			};
5441		}),
5442
5443		"contains": markFunction(function( text ) {
5444			text = text.replace( runescape, funescape );
5445			return function( elem ) {
5446				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
5447			};
5448		}),
5449
5450		// "Whether an element is represented by a :lang() selector
5451		// is based solely on the element's language value
5452		// being equal to the identifier C,
5453		// or beginning with the identifier C immediately followed by "-".
5454		// The matching of C against the element's language value is performed case-insensitively.
5455		// The identifier C does not have to be a valid language name."
5456		// http://www.w3.org/TR/selectors/#lang-pseudo
5457		"lang": markFunction( function( lang ) {
5458			// lang value must be a valid identifier
5459			if ( !ridentifier.test(lang || "") ) {
5460				Sizzle.error( "unsupported lang: " + lang );
5461			}
5462			lang = lang.replace( runescape, funescape ).toLowerCase();
5463			return function( elem ) {
5464				var elemLang;
5465				do {
5466					if ( (elemLang = documentIsHTML ?
5467						elem.lang :
5468						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
5469
5470						elemLang = elemLang.toLowerCase();
5471						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
5472					}
5473				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
5474				return false;
5475			};
5476		}),
5477
5478		// Miscellaneous
5479		"target": function( elem ) {
5480			var hash = window.location && window.location.hash;
5481			return hash && hash.slice( 1 ) === elem.id;
5482		},
5483
5484		"root": function( elem ) {
5485			return elem === docElem;
5486		},
5487
vendor: 5,418 bytes, lines 5488-5687
5488		"focus": function( elem ) {
5489			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
5490		},
5491
5492		// Boolean properties
5493		"enabled": function( elem ) {
5494			return elem.disabled === false;
5495		},
5496
5497		"disabled": function( elem ) {
5498			return elem.disabled === true;
5499		},
5500
5501		"checked": function( elem ) {
5502			// In CSS3, :checked should return both checked and selected elements
5503			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
5504			var nodeName = elem.nodeName.toLowerCase();
5505			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
5506		},
5507
5508		"selected": function( elem ) {
5509			// Accessing this property makes selected-by-default
5510			// options in Safari work properly
5511			if ( elem.parentNode ) {
5512				elem.parentNode.selectedIndex;
5513			}
5514
5515			return elem.selected === true;
5516		},
5517
5518		// Contents
5519		"empty": function( elem ) {
5520			// http://www.w3.org/TR/selectors/#empty-pseudo
5521			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
5522			//   but not by others (comment: 8; processing instruction: 7; etc.)
5523			// nodeType < 6 works because attributes (2) do not appear as children
5524			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
5525				if ( elem.nodeType < 6 ) {
5526					return false;
5527				}
5528			}
5529			return true;
5530		},
5531
5532		"parent": function( elem ) {
5533			return !Expr.pseudos["empty"]( elem );
5534		},
5535
5536		// Element/input types
5537		"header": function( elem ) {
5538			return rheader.test( elem.nodeName );
5539		},
5540
5541		"input": function( elem ) {
5542			return rinputs.test( elem.nodeName );
5543		},
5544
5545		"button": function( elem ) {
5546			var name = elem.nodeName.toLowerCase();
5547			return name === "input" && elem.type === "button" || name === "button";
5548		},
5549
5550		"text": function( elem ) {
5551			var attr;
5552			return elem.nodeName.toLowerCase() === "input" &&
5553				elem.type === "text" &&
5554
5555				// Support: IE<8
5556				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
5557				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
5558		},
5559
5560		// Position-in-collection
5561		"first": createPositionalPseudo(function() {
5562			return [ 0 ];
5563		}),
5564
5565		"last": createPositionalPseudo(function( matchIndexes, length ) {
5566			return [ length - 1 ];
5567		}),
5568
5569		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
5570			return [ argument < 0 ? argument + length : argument ];
5571		}),
5572
5573		"even": createPositionalPseudo(function( matchIndexes, length ) {
5574			var i = 0;
5575			for ( ; i < length; i += 2 ) {
5576				matchIndexes.push( i );
5577			}
5578			return matchIndexes;
5579		}),
5580
5581		"odd": createPositionalPseudo(function( matchIndexes, length ) {
5582			var i = 1;
5583			for ( ; i < length; i += 2 ) {
5584				matchIndexes.push( i );
5585			}
5586			return matchIndexes;
5587		}),
5588
5589		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5590			var i = argument < 0 ? argument + length : argument;
5591			for ( ; --i >= 0; ) {
5592				matchIndexes.push( i );
5593			}
5594			return matchIndexes;
5595		}),
5596
5597		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5598			var i = argument < 0 ? argument + length : argument;
5599			for ( ; ++i < length; ) {
5600				matchIndexes.push( i );
5601			}
5602			return matchIndexes;
5603		})
5604	}
5605};
5606
5607Expr.pseudos["nth"] = Expr.pseudos["eq"];
5608
5609// Add button/input type pseudos
5610for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
5611	Expr.pseudos[ i ] = createInputPseudo( i );
5612}
5613for ( i in { submit: true, reset: true } ) {
5614	Expr.pseudos[ i ] = createButtonPseudo( i );
5615}
5616
5617// Easy API for creating new setFilters
5618function setFilters() {}
5619setFilters.prototype = Expr.filters = Expr.pseudos;
5620Expr.setFilters = new setFilters();
5621
5622tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
5623	var matched, match, tokens, type,
5624		soFar, groups, preFilters,
5625		cached = tokenCache[ selector + " " ];
5626
5627	if ( cached ) {
5628		return parseOnly ? 0 : cached.slice( 0 );
5629	}
5630
5631	soFar = selector;
5632	groups = [];
5633	preFilters = Expr.preFilter;
5634
5635	while ( soFar ) {
5636
5637		// Comma and first run
5638		if ( !matched || (match = rcomma.exec( soFar )) ) {
5639			if ( match ) {
5640				// Don't consume trailing commas as valid
5641				soFar = soFar.slice( match[0].length ) || soFar;
5642			}
5643			groups.push( (tokens = []) );
5644		}
5645
5646		matched = false;
5647
5648		// Combinators
5649		if ( (match = rcombinators.exec( soFar )) ) {
5650			matched = match.shift();
5651			tokens.push({
5652				value: matched,
5653				// Cast descendant combinators to space
5654				type: match[0].replace( rtrim, " " )
5655			});
5656			soFar = soFar.slice( matched.length );
5657		}
5658
5659		// Filters
5660		for ( type in Expr.filter ) {
5661			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
5662				(match = preFilters[ type ]( match ))) ) {
5663				matched = match.shift();
5664				tokens.push({
5665					value: matched,
5666					type: type,
5667					matches: match
5668				});
5669				soFar = soFar.slice( matched.length );
5670			}
5671		}
5672
5673		if ( !matched ) {
5674			break;
5675		}
5676	}
5677
5678	// Return the length of the invalid excess
5679	// if we're just parsing
5680	// Otherwise, throw an error or return tokens
5681	return parseOnly ?
5682		soFar.length :
5683		soFar ?
5684			Sizzle.error( selector ) :
5685			// Cache the tokens
5686			tokenCache( selector, groups ).slice( 0 );
5687};
vendor: 11,230 bytes, lines 5688-6074
5688
5689function toSelector( tokens ) {
5690	var i = 0,
5691		len = tokens.length,
5692		selector = "";
5693	for ( ; i < len; i++ ) {
5694		selector += tokens[i].value;
5695	}
5696	return selector;
5697}
5698
5699function addCombinator( matcher, combinator, base ) {
5700	var dir = combinator.dir,
5701		checkNonElements = base && dir === "parentNode",
5702		doneName = done++;
5703
5704	return combinator.first ?
5705		// Check against closest ancestor/preceding element
5706		function( elem, context, xml ) {
5707			while ( (elem = elem[ dir ]) ) {
5708				if ( elem.nodeType === 1 || checkNonElements ) {
5709					return matcher( elem, context, xml );
5710				}
5711			}
5712		} :
5713
5714		// Check against all ancestor/preceding elements
5715		function( elem, context, xml ) {
5716			var oldCache, outerCache,
5717				newCache = [ dirruns, doneName ];
5718
5719			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
5720			if ( xml ) {
5721				while ( (elem = elem[ dir ]) ) {
5722					if ( elem.nodeType === 1 || checkNonElements ) {
5723						if ( matcher( elem, context, xml ) ) {
5724							return true;
5725						}
5726					}
5727				}
5728			} else {
5729				while ( (elem = elem[ dir ]) ) {
5730					if ( elem.nodeType === 1 || checkNonElements ) {
5731						outerCache = elem[ expando ] || (elem[ expando ] = {});
5732						if ( (oldCache = outerCache[ dir ]) &&
5733							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
5734
5735							// Assign to newCache so results back-propagate to previous elements
5736							return (newCache[ 2 ] = oldCache[ 2 ]);
5737						} else {
5738							// Reuse newcache so results back-propagate to previous elements
5739							outerCache[ dir ] = newCache;
5740
5741							// A match means we're done; a fail means we have to keep checking
5742							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
5743								return true;
5744							}
5745						}
5746					}
5747				}
5748			}
5749		};
5750}
5751
5752function elementMatcher( matchers ) {
5753	return matchers.length > 1 ?
5754		function( elem, context, xml ) {
5755			var i = matchers.length;
5756			while ( i-- ) {
5757				if ( !matchers[i]( elem, context, xml ) ) {
5758					return false;
5759				}
5760			}
5761			return true;
5762		} :
5763		matchers[0];
5764}
5765
5766function multipleContexts( selector, contexts, results ) {
5767	var i = 0,
5768		len = contexts.length;
5769	for ( ; i < len; i++ ) {
5770		Sizzle( selector, contexts[i], results );
5771	}
5772	return results;
5773}
5774
5775function condense( unmatched, map, filter, context, xml ) {
5776	var elem,
5777		newUnmatched = [],
5778		i = 0,
5779		len = unmatched.length,
5780		mapped = map != null;
5781
5782	for ( ; i < len; i++ ) {
5783		if ( (elem = unmatched[i]) ) {
5784			if ( !filter || filter( elem, context, xml ) ) {
5785				newUnmatched.push( elem );
5786				if ( mapped ) {
5787					map.push( i );
5788				}
5789			}
5790		}
5791	}
5792
5793	return newUnmatched;
5794}
5795
5796function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
5797	if ( postFilter && !postFilter[ expando ] ) {
5798		postFilter = setMatcher( postFilter );
5799	}
5800	if ( postFinder && !postFinder[ expando ] ) {
5801		postFinder = setMatcher( postFinder, postSelector );
5802	}
5803	return markFunction(function( seed, results, context, xml ) {
5804		var temp, i, elem,
5805			preMap = [],
5806			postMap = [],
5807			preexisting = results.length,
5808
5809			// Get initial elements from seed or context
5810			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
5811
5812			// Prefilter to get matcher input, preserving a map for seed-results synchronization
5813			matcherIn = preFilter && ( seed || !selector ) ?
5814				condense( elems, preMap, preFilter, context, xml ) :
5815				elems,
5816
5817			matcherOut = matcher ?
5818				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
5819				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
5820
5821					// ...intermediate processing is necessary
5822					[] :
5823
5824					// ...otherwise use results directly
5825					results :
5826				matcherIn;
5827
5828		// Find primary matches
5829		if ( matcher ) {
5830			matcher( matcherIn, matcherOut, context, xml );
5831		}
5832
5833		// Apply postFilter
5834		if ( postFilter ) {
5835			temp = condense( matcherOut, postMap );
5836			postFilter( temp, [], context, xml );
5837
5838			// Un-match failing elements by moving them back to matcherIn
5839			i = temp.length;
5840			while ( i-- ) {
5841				if ( (elem = temp[i]) ) {
5842					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
5843				}
5844			}
5845		}
5846
5847		if ( seed ) {
5848			if ( postFinder || preFilter ) {
5849				if ( postFinder ) {
5850					// Get the final matcherOut by condensing this intermediate into postFinder contexts
5851					temp = [];
5852					i = matcherOut.length;
5853					while ( i-- ) {
5854						if ( (elem = matcherOut[i]) ) {
5855							// Restore matcherIn since elem is not yet a final match
5856							temp.push( (matcherIn[i] = elem) );
5857						}
5858					}
5859					postFinder( null, (matcherOut = []), temp, xml );
5860				}
5861
5862				// Move matched elements from seed to results to keep them synchronized
5863				i = matcherOut.length;
5864				while ( i-- ) {
5865					if ( (elem = matcherOut[i]) &&
5866						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
5867
5868						seed[temp] = !(results[temp] = elem);
5869					}
5870				}
5871			}
5872
5873		// Add elements to results, through postFinder if defined
5874		} else {
5875			matcherOut = condense(
5876				matcherOut === results ?
5877					matcherOut.splice( preexisting, matcherOut.length ) :
5878					matcherOut
5879			);
5880			if ( postFinder ) {
5881				postFinder( null, results, matcherOut, xml );
5882			} else {
5883				push.apply( results, matcherOut );
5884			}
5885		}
5886	});
5887}
5888
5889function matcherFromTokens( tokens ) {
5890	var checkContext, matcher, j,
5891		len = tokens.length,
5892		leadingRelative = Expr.relative[ tokens[0].type ],
5893		implicitRelative = leadingRelative || Expr.relative[" "],
5894		i = leadingRelative ? 1 : 0,
5895
5896		// The foundational matcher ensures that elements are reachable from top-level context(s)
5897		matchContext = addCombinator( function( elem ) {
5898			return elem === checkContext;
5899		}, implicitRelative, true ),
5900		matchAnyContext = addCombinator( function( elem ) {
5901			return indexOf( checkContext, elem ) > -1;
5902		}, implicitRelative, true ),
5903		matchers = [ function( elem, context, xml ) {
5904			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
5905				(checkContext = context).nodeType ?
5906					matchContext( elem, context, xml ) :
5907					matchAnyContext( elem, context, xml ) );
5908			// Avoid hanging onto element (issue #299)
5909			checkContext = null;
5910			return ret;
5911		} ];
5912
5913	for ( ; i < len; i++ ) {
5914		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
5915			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
5916		} else {
5917			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
5918
5919			// Return special upon seeing a positional matcher
5920			if ( matcher[ expando ] ) {
5921				// Find the next relative operator (if any) for proper handling
5922				j = ++i;
5923				for ( ; j < len; j++ ) {
5924					if ( Expr.relative[ tokens[j].type ] ) {
5925						break;
5926					}
5927				}
5928				return setMatcher(
5929					i > 1 && elementMatcher( matchers ),
5930					i > 1 && toSelector(
5931						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
5932						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
5933					).replace( rtrim, "$1" ),
5934					matcher,
5935					i < j && matcherFromTokens( tokens.slice( i, j ) ),
5936					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
5937					j < len && toSelector( tokens )
5938				);
5939			}
5940			matchers.push( matcher );
5941		}
5942	}
5943
5944	return elementMatcher( matchers );
5945}
5946
5947function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
5948	var bySet = setMatchers.length > 0,
5949		byElement = elementMatchers.length > 0,
5950		superMatcher = function( seed, context, xml, results, outermost ) {
5951			var elem, j, matcher,
5952				matchedCount = 0,
5953				i = "0",
5954				unmatched = seed && [],
5955				setMatched = [],
5956				contextBackup = outermostContext,
5957				// We must always have either seed elements or outermost context
5958				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
5959				// Use integer dirruns iff this is the outermost matcher
5960				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
5961				len = elems.length;
5962
5963			if ( outermost ) {
5964				outermostContext = context !== document && context;
5965			}
5966
5967			// Add elements passing elementMatchers directly to results
5968			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
5969			// Support: IE<9, Safari
5970			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
5971			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
5972				if ( byElement && elem ) {
5973					j = 0;
5974					while ( (matcher = elementMatchers[j++]) ) {
5975						if ( matcher( elem, context, xml ) ) {
5976							results.push( elem );
5977							break;
5978						}
5979					}
5980					if ( outermost ) {
5981						dirruns = dirrunsUnique;
5982					}
5983				}
5984
5985				// Track unmatched elements for set filters
5986				if ( bySet ) {
5987					// They will have gone through all possible matchers
5988					if ( (elem = !matcher && elem) ) {
5989						matchedCount--;
5990					}
5991
5992					// Lengthen the array for every element, matched or not
5993					if ( seed ) {
5994						unmatched.push( elem );
5995					}
5996				}
5997			}
5998
5999			// Apply set filters to unmatched elements
6000			matchedCount += i;
6001			if ( bySet && i !== matchedCount ) {
6002				j = 0;
6003				while ( (matcher = setMatchers[j++]) ) {
6004					matcher( unmatched, setMatched, context, xml );
6005				}
6006
6007				if ( seed ) {
6008					// Reintegrate element matches to eliminate the need for sorting
6009					if ( matchedCount > 0 ) {
6010						while ( i-- ) {
6011							if ( !(unmatched[i] || setMatched[i]) ) {
6012								setMatched[i] = pop.call( results );
6013							}
6014						}
6015					}
6016
6017					// Discard index placeholder values to get only actual matches
6018					setMatched = condense( setMatched );
6019				}
6020
6021				// Add matches to results
6022				push.apply( results, setMatched );
6023
6024				// Seedless set matches succeeding multiple successful matchers stipulate sorting
6025				if ( outermost && !seed && setMatched.length > 0 &&
6026					( matchedCount + setMatchers.length ) > 1 ) {
6027
6028					Sizzle.uniqueSort( results );
6029				}
6030			}
6031
6032			// Override manipulation of globals by nested matchers
6033			if ( outermost ) {
6034				dirruns = dirrunsUnique;
6035				outermostContext = contextBackup;
6036			}
6037
6038			return unmatched;
6039		};
6040
6041	return bySet ?
6042		markFunction( superMatcher ) :
6043		superMatcher;
6044}
6045
6046compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
6047	var i,
6048		setMatchers = [],
6049		elementMatchers = [],
6050		cached = compilerCache[ selector + " " ];
6051
6052	if ( !cached ) {
6053		// Generate a function of recursive functions that can be used to check each element
6054		if ( !match ) {
6055			match = tokenize( selector );
6056		}
6057		i = match.length;
6058		while ( i-- ) {
6059			cached = matcherFromTokens( match[i] );
6060			if ( cached[ expando ] ) {
6061				setMatchers.push( cached );
6062			} else {
6063				elementMatchers.push( cached );
6064			}
6065		}
6066
6067		// Cache the compiled function
6068		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
6069
6070		// Save selector and tokenization
6071		cached.selector = selector;
6072	}
6073	return cached;
6074};
vendor: 185,445 bytes, lines 6075-12501
6075
6076/**
6077 * A low-level selection function that works with Sizzle's compiled
6078 *  selector functions
6079 * @param {String|Function} selector A selector or a pre-compiled
6080 *  selector function built with Sizzle.compile
6081 * @param {Element} context
6082 * @param {Array} [results]
6083 * @param {Array} [seed] A set of elements to match against
6084 */
6085select = Sizzle.select = function( selector, context, results, seed ) {
6086	var i, tokens, token, type, find,
6087		compiled = typeof selector === "function" && selector,
6088		match = !seed && tokenize( (selector = compiled.selector || selector) );
6089
6090	results = results || [];
6091
6092	// Try to minimize operations if there is no seed and only one group
6093	if ( match.length === 1 ) {
6094
6095		// Take a shortcut and set the context if the root selector is an ID
6096		tokens = match[0] = match[0].slice( 0 );
6097		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
6098				support.getById && context.nodeType === 9 && documentIsHTML &&
6099				Expr.relative[ tokens[1].type ] ) {
6100
6101			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
6102			if ( !context ) {
6103				return results;
6104
6105			// Precompiled matchers will still verify ancestry, so step up a level
6106			} else if ( compiled ) {
6107				context = context.parentNode;
6108			}
6109
6110			selector = selector.slice( tokens.shift().value.length );
6111		}
6112
6113		// Fetch a seed set for right-to-left matching
6114		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
6115		while ( i-- ) {
6116			token = tokens[i];
6117
6118			// Abort if we hit a combinator
6119			if ( Expr.relative[ (type = token.type) ] ) {
6120				break;
6121			}
6122			if ( (find = Expr.find[ type ]) ) {
6123				// Search, expanding context for leading sibling combinators
6124				if ( (seed = find(
6125					token.matches[0].replace( runescape, funescape ),
6126					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
6127				)) ) {
6128
6129					// If seed is empty or no tokens remain, we can return early
6130					tokens.splice( i, 1 );
6131					selector = seed.length && toSelector( tokens );
6132					if ( !selector ) {
6133						push.apply( results, seed );
6134						return results;
6135					}
6136
6137					break;
6138				}
6139			}
6140		}
6141	}
6142
6143	// Compile and execute a filtering function if one is not provided
6144	// Provide `match` to avoid retokenization if we modified the selector above
6145	( compiled || compile( selector, match ) )(
6146		seed,
6147		context,
6148		!documentIsHTML,
6149		results,
6150		rsibling.test( selector ) && testContext( context.parentNode ) || context
6151	);
6152	return results;
6153};
6154
6155// One-time assignments
6156
6157// Sort stability
6158support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
6159
6160// Support: Chrome 14-35+
6161// Always assume duplicates if they aren't passed to the comparison function
6162support.detectDuplicates = !!hasDuplicate;
6163
6164// Initialize against the default document
6165setDocument();
6166
6167// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
6168// Detached nodes confoundingly follow *each other*
6169support.sortDetached = assert(function( div1 ) {
6170	// Should return 1, but returns 4 (following)
6171	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
6172});
6173
6174// Support: IE<8
6175// Prevent attribute/property "interpolation"
6176// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
6177if ( !assert(function( div ) {
6178	div.innerHTML = "<a href='#'></a>";
6179	return div.firstChild.getAttribute("href") === "#" ;
6180}) ) {
6181	addHandle( "type|href|height|width", function( elem, name, isXML ) {
6182		if ( !isXML ) {
6183			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
6184		}
6185	});
6186}
6187
6188// Support: IE<9
6189// Use defaultValue in place of getAttribute("value")
6190if ( !support.attributes || !assert(function( div ) {
6191	div.innerHTML = "<input/>";
6192	div.firstChild.setAttribute( "value", "" );
6193	return div.firstChild.getAttribute( "value" ) === "";
6194}) ) {
6195	addHandle( "value", function( elem, name, isXML ) {
6196		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
6197			return elem.defaultValue;
6198		}
6199	});
6200}
6201
6202// Support: IE<9
6203// Use getAttributeNode to fetch booleans when getAttribute lies
6204if ( !assert(function( div ) {
6205	return div.getAttribute("disabled") == null;
6206}) ) {
6207	addHandle( booleans, function( elem, name, isXML ) {
6208		var val;
6209		if ( !isXML ) {
6210			return elem[ name ] === true ? name.toLowerCase() :
6211					(val = elem.getAttributeNode( name )) && val.specified ?
6212					val.value :
6213				null;
6214		}
6215	});
6216}
6217
6218return Sizzle;
6219
6220})( window );
6221
6222
6223
6224jQuery1113.find = Sizzle;
6225jQuery1113.expr = Sizzle.selectors;
6226jQuery1113.expr[":"] = jQuery1113.expr.pseudos;
6227jQuery1113.unique = Sizzle.uniqueSort;
6228jQuery1113.text = Sizzle.getText;
6229jQuery1113.isXMLDoc = Sizzle.isXML;
6230jQuery1113.contains = Sizzle.contains;
6231
6232
6233
6234var rneedsContext = jQuery1113.expr.match.needsContext;
6235
6236var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
6237
6238
6239
6240var risSimple = /^.[^:#\[\.,]*$/;
6241
6242// Implement the identical functionality for filter and not
6243function winnow( elements, qualifier, not ) {
6244	if ( jQuery1113.isFunction( qualifier ) ) {
6245		return jQuery1113.grep( elements, function( elem, i ) {
6246			/* jshint -W018 */
6247			return !!qualifier.call( elem, i, elem ) !== not;
6248		});
6249
6250	}
6251
6252	if ( qualifier.nodeType ) {
6253		return jQuery1113.grep( elements, function( elem ) {
6254			return ( elem === qualifier ) !== not;
6255		});
6256
6257	}
6258
6259	if ( typeof qualifier === "string" ) {
6260		if ( risSimple.test( qualifier ) ) {
6261			return jQuery1113.filter( qualifier, elements, not );
6262		}
6263
6264		qualifier = jQuery1113.filter( qualifier, elements );
6265	}
6266
6267	return jQuery1113.grep( elements, function( elem ) {
6268		return ( jQuery1113.inArray( elem, qualifier ) >= 0 ) !== not;
6269	});
6270}
6271
6272jQuery1113.filter = function( expr, elems, not ) {
6273	var elem = elems[ 0 ];
6274
6275	if ( not ) {
6276		expr = ":not(" + expr + ")";
6277	}
6278
6279	return elems.length === 1 && elem.nodeType === 1 ?
6280		jQuery1113.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
6281		jQuery1113.find.matches( expr, jQuery1113.grep( elems, function( elem ) {
6282			return elem.nodeType === 1;
6283		}));
6284};
6285
6286jQuery1113.fn.extend({
6287	find: function( selector ) {
6288		var i,
6289			ret = [],
6290			self = this,
6291			len = self.length;
6292
6293		if ( typeof selector !== "string" ) {
6294			return this.pushStack( jQuery1113( selector ).filter(function() {
6295				for ( i = 0; i < len; i++ ) {
6296					if ( jQuery1113.contains( self[ i ], this ) ) {
6297						return true;
6298					}
6299				}
6300			}) );
6301		}
6302
6303		for ( i = 0; i < len; i++ ) {
6304			jQuery1113.find( selector, self[ i ], ret );
6305		}
6306
6307		// Needed because $( selector, context ) becomes $( context ).find( selector )
6308		ret = this.pushStack( len > 1 ? jQuery1113.unique( ret ) : ret );
6309		ret.selector = this.selector ? this.selector + " " + selector : selector;
6310		return ret;
6311	},
6312	filter: function( selector ) {
6313		return this.pushStack( winnow(this, selector || [], false) );
6314	},
6315	not: function( selector ) {
6316		return this.pushStack( winnow(this, selector || [], true) );
6317	},
6318	is: function( selector ) {
6319		return !!winnow(
6320			this,
6321
6322			// If this is a positional/relative selector, check membership in the returned set
6323			// so $("p:first").is("p:last") won't return true for a doc with two "p".
6324			typeof selector === "string" && rneedsContext.test( selector ) ?
6325				jQuery1113( selector ) :
6326				selector || [],
6327			false
6328		).length;
6329	}
6330});
6331
6332
6333// Initialize a jQuery1113 object
6334
6335
6336// A central reference to the root jQuery1113(document)
6337var rootjQuery1113,
6338
6339	// Use the correct document accordingly with window argument (sandbox)
6340	document = window.document,
6341
6342	// A simple way to check for HTML strings
6343	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
6344	// Strict HTML recognition (#11290: must start with <)
6345	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
6346
6347	init = jQuery1113.fn.init = function( selector, context ) {
6348		var match, elem;
6349
6350		// HANDLE: $(""), $(null), $(undefined), $(false)
6351		if ( !selector ) {
6352			return this;
6353		}
6354
6355		// Handle HTML strings
6356		if ( typeof selector === "string" ) {
6357			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
6358				// Assume that strings that start and end with <> are HTML and skip the regex check
6359				match = [ null, selector, null ];
6360
6361			} else {
6362				match = rquickExpr.exec( selector );
6363			}
6364
6365			// Match html or make sure no context is specified for #id
6366			if ( match && (match[1] || !context) ) {
6367
6368				// HANDLE: $(html) -> $(array)
6369				if ( match[1] ) {
6370					context = context instanceof jQuery1113 ? context[0] : context;
6371
6372					// scripts is true for back-compat
6373					// Intentionally let the error be thrown if parseHTML is not present
6374					jQuery1113.merge( this, jQuery1113.parseHTML(
6375						match[1],
6376						context && context.nodeType ? context.ownerDocument || context : document,
6377						true
6378					) );
6379
6380					// HANDLE: $(html, props)
6381					if ( rsingleTag.test( match[1] ) && jQuery1113.isPlainObject( context ) ) {
6382						for ( match in context ) {
6383							// Properties of context are called as methods if possible
6384							if ( jQuery1113.isFunction( this[ match ] ) ) {
6385								this[ match ]( context[ match ] );
6386
6387							// ...and otherwise set as attributes
6388							} else {
6389								this.attr( match, context[ match ] );
6390							}
6391						}
6392					}
6393
6394					return this;
6395
6396				// HANDLE: $(#id)
6397				} else {
6398					elem = document.getElementById( match[2] );
6399
6400					// Check parentNode to catch when Blackberry 4.6 returns
6401					// nodes that are no longer in the document #6963
6402					if ( elem && elem.parentNode ) {
6403						// Handle the case where IE and Opera return items
6404						// by name instead of ID
6405						if ( elem.id !== match[2] ) {
6406							return rootjQuery1113.find( selector );
6407						}
6408
6409						// Otherwise, we inject the element directly into the jQuery1113 object
6410						this.length = 1;
6411						this[0] = elem;
6412					}
6413
6414					this.context = document;
6415					this.selector = selector;
6416					return this;
6417				}
6418
6419			// HANDLE: $(expr, $(...))
6420			} else if ( !context || context.jQuery1113 ) {
6421				return ( context || rootjQuery1113 ).find( selector );
6422
6423			// HANDLE: $(expr, context)
6424			// (which is just equivalent to: $(context).find(expr)
6425			} else {
6426				return this.constructor( context ).find( selector );
6427			}
6428
6429		// HANDLE: $(DOMElement)
6430		} else if ( selector.nodeType ) {
6431			this.context = this[0] = selector;
6432			this.length = 1;
6433			return this;
6434
6435		// HANDLE: $(function)
6436		// Shortcut for document ready
6437		} else if ( jQuery1113.isFunction( selector ) ) {
6438			return typeof rootjQuery1113.ready !== "undefined" ?
6439				rootjQuery1113.ready( selector ) :
6440				// Execute immediately if ready is not present
6441				selector( jQuery1113 );
6442		}
6443
6444		if ( selector.selector !== undefined ) {
6445			this.selector = selector.selector;
6446			this.context = selector.context;
6447		}
6448
6449		return jQuery1113.makeArray( selector, this );
6450	};
6451
6452// Give the init function the jQuery1113 prototype for later instantiation
6453init.prototype = jQuery1113.fn;
6454
6455// Initialize central reference
6456rootjQuery1113 = jQuery1113( document );
6457
6458
6459var rparentsprev = /^(?:parents|prev(?:Until|All))/,
6460	// methods guaranteed to produce a unique set when starting from a unique set
6461	guaranteedUnique = {
6462		children: true,
6463		contents: true,
6464		next: true,
6465		prev: true
6466	};
6467
6468jQuery1113.extend({
6469	dir: function( elem, dir, until ) {
6470		var matched = [],
6471			cur = elem[ dir ];
6472
6473		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery1113( cur ).is( until )) ) {
6474			if ( cur.nodeType === 1 ) {
6475				matched.push( cur );
6476			}
6477			cur = cur[dir];
6478		}
6479		return matched;
6480	},
6481
6482	sibling: function( n, elem ) {
6483		var r = [];
6484
6485		for ( ; n; n = n.nextSibling ) {
6486			if ( n.nodeType === 1 && n !== elem ) {
6487				r.push( n );
6488			}
6489		}
6490
6491		return r;
6492	}
6493});
6494
6495jQuery1113.fn.extend({
6496	has: function( target ) {
6497		var i,
6498			targets = jQuery1113( target, this ),
6499			len = targets.length;
6500
6501		return this.filter(function() {
6502			for ( i = 0; i < len; i++ ) {
6503				if ( jQuery1113.contains( this, targets[i] ) ) {
6504					return true;
6505				}
6506			}
6507		});
6508	},
6509
6510	closest: function( selectors, context ) {
6511		var cur,
6512			i = 0,
6513			l = this.length,
6514			matched = [],
6515			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
6516				jQuery1113( selectors, context || this.context ) :
6517				0;
6518
6519		for ( ; i < l; i++ ) {
6520			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
6521				// Always skip document fragments
6522				if ( cur.nodeType < 11 && (pos ?
6523					pos.index(cur) > -1 :
6524
6525					// Don't pass non-elements to Sizzle
6526					cur.nodeType === 1 &&
6527						jQuery1113.find.matchesSelector(cur, selectors)) ) {
6528
6529					matched.push( cur );
6530					break;
6531				}
6532			}
6533		}
6534
6535		return this.pushStack( matched.length > 1 ? jQuery1113.unique( matched ) : matched );
6536	},
6537
6538	// Determine the position of an element within
6539	// the matched set of elements
6540	index: function( elem ) {
6541
6542		// No argument, return index in parent
6543		if ( !elem ) {
6544			return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
6545		}
6546
6547		// index in selector
6548		if ( typeof elem === "string" ) {
6549			return jQuery1113.inArray( this[0], jQuery1113( elem ) );
6550		}
6551
6552		// Locate the position of the desired element
6553		return jQuery1113.inArray(
6554			// If it receives a jQuery1113 object, the first element is used
6555			elem.jQuery1113 ? elem[0] : elem, this );
6556	},
6557
6558	add: function( selector, context ) {
6559		return this.pushStack(
6560			jQuery1113.unique(
6561				jQuery1113.merge( this.get(), jQuery1113( selector, context ) )
6562			)
6563		);
6564	},
6565
6566	addBack: function( selector ) {
6567		return this.add( selector == null ?
6568			this.prevObject : this.prevObject.filter(selector)
6569		);
6570	}
6571});
6572
6573function sibling( cur, dir ) {
6574	do {
6575		cur = cur[ dir ];
6576	} while ( cur && cur.nodeType !== 1 );
6577
6578	return cur;
6579}
6580
6581jQuery1113.each({
6582	parent: function( elem ) {
6583		var parent = elem.parentNode;
6584		return parent && parent.nodeType !== 11 ? parent : null;
6585	},
6586	parents: function( elem ) {
6587		return jQuery1113.dir( elem, "parentNode" );
6588	},
6589	parentsUntil: function( elem, i, until ) {
6590		return jQuery1113.dir( elem, "parentNode", until );
6591	},
6592	next: function( elem ) {
6593		return sibling( elem, "nextSibling" );
6594	},
6595	prev: function( elem ) {
6596		return sibling( elem, "previousSibling" );
6597	},
6598	nextAll: function( elem ) {
6599		return jQuery1113.dir( elem, "nextSibling" );
6600	},
6601	prevAll: function( elem ) {
6602		return jQuery1113.dir( elem, "previousSibling" );
6603	},
6604	nextUntil: function( elem, i, until ) {
6605		return jQuery1113.dir( elem, "nextSibling", until );
6606	},
6607	prevUntil: function( elem, i, until ) {
6608		return jQuery1113.dir( elem, "previousSibling", until );
6609	},
6610	siblings: function( elem ) {
6611		return jQuery1113.sibling( ( elem.parentNode || {} ).firstChild, elem );
6612	},
6613	children: function( elem ) {
6614		return jQuery1113.sibling( elem.firstChild );
6615	},
6616	contents: function( elem ) {
6617		return jQuery1113.nodeName( elem, "iframe" ) ?
6618			elem.contentDocument || elem.contentWindow.document :
6619			jQuery1113.merge( [], elem.childNodes );
6620	}
6621}, function( name, fn ) {
6622	jQuery1113.fn[ name ] = function( until, selector ) {
6623		var ret = jQuery1113.map( this, fn, until );
6624
6625		if ( name.slice( -5 ) !== "Until" ) {
6626			selector = until;
6627		}
6628
6629		if ( selector && typeof selector === "string" ) {
6630			ret = jQuery1113.filter( selector, ret );
6631		}
6632
6633		if ( this.length > 1 ) {
6634			// Remove duplicates
6635			if ( !guaranteedUnique[ name ] ) {
6636				ret = jQuery1113.unique( ret );
6637			}
6638
6639			// Reverse order for parents* and prev-derivatives
6640			if ( rparentsprev.test( name ) ) {
6641				ret = ret.reverse();
6642			}
6643		}
6644
6645		return this.pushStack( ret );
6646	};
6647});
6648var rnotwhite = (/\S+/g);
6649
6650
6651
6652// String to Object options format cache
6653var optionsCache = {};
6654
6655// Convert String-formatted options into Object-formatted ones and store in cache
6656function createOptions( options ) {
6657	var object = optionsCache[ options ] = {};
6658	jQuery1113.each( options.match( rnotwhite ) || [], function( _, flag ) {
6659		object[ flag ] = true;
6660	});
6661	return object;
6662}
6663
6664/*
6665 * Create a callback list using the following parameters:
6666 *
6667 *	options: an optional list of space-separated options that will change how
6668 *			the callback list behaves or a more traditional option object
6669 *
6670 * By default a callback list will act like an event callback list and can be
6671 * "fired" multiple times.
6672 *
6673 * Possible options:
6674 *
6675 *	once:			will ensure the callback list can only be fired once (like a Deferred)
6676 *
6677 *	memory:			will keep track of previous values and will call any callback added
6678 *					after the list has been fired right away with the latest "memorized"
6679 *					values (like a Deferred)
6680 *
6681 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
6682 *
6683 *	stopOnFalse:	interrupt callings when a callback returns false
6684 *
6685 */
6686jQuery1113.Callbacks = function( options ) {
6687
6688	// Convert options from String-formatted to Object-formatted if needed
6689	// (we check in cache first)
6690	options = typeof options === "string" ?
6691		( optionsCache[ options ] || createOptions( options ) ) :
6692		jQuery1113.extend( {}, options );
6693
6694	var // Flag to know if list is currently firing
6695		firing,
6696		// Last fire value (for non-forgettable lists)
6697		memory,
6698		// Flag to know if list was already fired
6699		fired,
6700		// End of the loop when firing
6701		firingLength,
6702		// Index of currently firing callback (modified by remove if needed)
6703		firingIndex,
6704		// First callback to fire (used internally by add and fireWith)
6705		firingStart,
6706		// Actual callback list
6707		list = [],
6708		// Stack of fire calls for repeatable lists
6709		stack = !options.once && [],
6710		// Fire callbacks
6711		fire = function( data ) {
6712			memory = options.memory && data;
6713			fired = true;
6714			firingIndex = firingStart || 0;
6715			firingStart = 0;
6716			firingLength = list.length;
6717			firing = true;
6718			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
6719				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
6720					memory = false; // To prevent further calls using add
6721					break;
6722				}
6723			}
6724			firing = false;
6725			if ( list ) {
6726				if ( stack ) {
6727					if ( stack.length ) {
6728						fire( stack.shift() );
6729					}
6730				} else if ( memory ) {
6731					list = [];
6732				} else {
6733					self.disable();
6734				}
6735			}
6736		},
6737		// Actual Callbacks object
6738		self = {
6739			// Add a callback or a collection of callbacks to the list
6740			add: function() {
6741				if ( list ) {
6742					// First, we save the current length
6743					var start = list.length;
6744					(function add( args ) {
6745						jQuery1113.each( args, function( _, arg ) {
6746							var type = jQuery1113.type( arg );
6747							if ( type === "function" ) {
6748								if ( !options.unique || !self.has( arg ) ) {
6749									list.push( arg );
6750								}
6751							} else if ( arg && arg.length && type !== "string" ) {
6752								// Inspect recursively
6753								add( arg );
6754							}
6755						});
6756					})( arguments );
6757					// Do we need to add the callbacks to the
6758					// current firing batch?
6759					if ( firing ) {
6760						firingLength = list.length;
6761					// With memory, if we're not firing then
6762					// we should call right away
6763					} else if ( memory ) {
6764						firingStart = start;
6765						fire( memory );
6766					}
6767				}
6768				return this;
6769			},
6770			// Remove a callback from the list
6771			remove: function() {
6772				if ( list ) {
6773					jQuery1113.each( arguments, function( _, arg ) {
6774						var index;
6775						while ( ( index = jQuery1113.inArray( arg, list, index ) ) > -1 ) {
6776							list.splice( index, 1 );
6777							// Handle firing indexes
6778							if ( firing ) {
6779								if ( index <= firingLength ) {
6780									firingLength--;
6781								}
6782								if ( index <= firingIndex ) {
6783									firingIndex--;
6784								}
6785							}
6786						}
6787					});
6788				}
6789				return this;
6790			},
6791			// Check if a given callback is in the list.
6792			// If no argument is given, return whether or not list has callbacks attached.
6793			has: function( fn ) {
6794				return fn ? jQuery1113.inArray( fn, list ) > -1 : !!( list && list.length );
6795			},
6796			// Remove all callbacks from the list
6797			empty: function() {
6798				list = [];
6799				firingLength = 0;
6800				return this;
6801			},
6802			// Have the list do nothing anymore
6803			disable: function() {
6804				list = stack = memory = undefined;
6805				return this;
6806			},
6807			// Is it disabled?
6808			disabled: function() {
6809				return !list;
6810			},
6811			// Lock the list in its current state
6812			lock: function() {
6813				stack = undefined;
6814				if ( !memory ) {
6815					self.disable();
6816				}
6817				return this;
6818			},
6819			// Is it locked?
6820			locked: function() {
6821				return !stack;
6822			},
6823			// Call all callbacks with the given context and arguments
6824			fireWith: function( context, args ) {
6825				if ( list && ( !fired || stack ) ) {
6826					args = args || [];
6827					args = [ context, args.slice ? args.slice() : args ];
6828					if ( firing ) {
6829						stack.push( args );
6830					} else {
6831						fire( args );
6832					}
6833				}
6834				return this;
6835			},
6836			// Call all the callbacks with the given arguments
6837			fire: function() {
6838				self.fireWith( this, arguments );
6839				return this;
6840			},
6841			// To know if the callbacks have already been called at least once
6842			fired: function() {
6843				return !!fired;
6844			}
6845		};
6846
6847	return self;
6848};
6849
6850
6851jQuery1113.extend({
6852
6853	Deferred: function( func ) {
6854		var tuples = [
6855				// action, add listener, listener list, final state
6856				[ "resolve", "done", jQuery1113.Callbacks("once memory"), "resolved" ],
6857				[ "reject", "fail", jQuery1113.Callbacks("once memory"), "rejected" ],
6858				[ "notify", "progress", jQuery1113.Callbacks("memory") ]
6859			],
6860			state = "pending",
6861			promise = {
6862				state: function() {
6863					return state;
6864				},
6865				always: function() {
6866					deferred.done( arguments ).fail( arguments );
6867					return this;
6868				},
6869				then: function( /* fnDone, fnFail, fnProgress */ ) {
6870					var fns = arguments;
6871					return jQuery1113.Deferred(function( newDefer ) {
6872						jQuery1113.each( tuples, function( i, tuple ) {
6873							var fn = jQuery1113.isFunction( fns[ i ] ) && fns[ i ];
6874							// deferred[ done | fail | progress ] for forwarding actions to newDefer
6875							deferred[ tuple[1] ](function() {
6876								var returned = fn && fn.apply( this, arguments );
6877								if ( returned && jQuery1113.isFunction( returned.promise ) ) {
6878									returned.promise()
6879										.done( newDefer.resolve )
6880										.fail( newDefer.reject )
6881										.progress( newDefer.notify );
6882								} else {
6883									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
6884								}
6885							});
6886						});
6887						fns = null;
6888					}).promise();
6889				},
6890				// Get a promise for this deferred
6891				// If obj is provided, the promise aspect is added to the object
6892				promise: function( obj ) {
6893					return obj != null ? jQuery1113.extend( obj, promise ) : promise;
6894				}
6895			},
6896			deferred = {};
6897
6898		// Keep pipe for back-compat
6899		promise.pipe = promise.then;
6900
6901		// Add list-specific methods
6902		jQuery1113.each( tuples, function( i, tuple ) {
6903			var list = tuple[ 2 ],
6904				stateString = tuple[ 3 ];
6905
6906			// promise[ done | fail | progress ] = list.add
6907			promise[ tuple[1] ] = list.add;
6908
6909			// Handle state
6910			if ( stateString ) {
6911				list.add(function() {
6912					// state = [ resolved | rejected ]
6913					state = stateString;
6914
6915				// [ reject_list | resolve_list ].disable; progress_list.lock
6916				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
6917			}
6918
6919			// deferred[ resolve | reject | notify ]
6920			deferred[ tuple[0] ] = function() {
6921				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
6922				return this;
6923			};
6924			deferred[ tuple[0] + "With" ] = list.fireWith;
6925		});
6926
6927		// Make the deferred a promise
6928		promise.promise( deferred );
6929
6930		// Call given func if any
6931		if ( func ) {
6932			func.call( deferred, deferred );
6933		}
6934
6935		// All done!
6936		return deferred;
6937	},
6938
6939	// Deferred helper
6940	when: function( subordinate /* , ..., subordinateN */ ) {
6941		var i = 0,
6942			resolveValues = slice.call( arguments ),
6943			length = resolveValues.length,
6944
6945			// the count of uncompleted subordinates
6946			remaining = length !== 1 || ( subordinate && jQuery1113.isFunction( subordinate.promise ) ) ? length : 0,
6947
6948			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
6949			deferred = remaining === 1 ? subordinate : jQuery1113.Deferred(),
6950
6951			// Update function for both resolve and progress values
6952			updateFunc = function( i, contexts, values ) {
6953				return function( value ) {
6954					contexts[ i ] = this;
6955					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
6956					if ( values === progressValues ) {
6957						deferred.notifyWith( contexts, values );
6958
6959					} else if ( !(--remaining) ) {
6960						deferred.resolveWith( contexts, values );
6961					}
6962				};
6963			},
6964
6965			progressValues, progressContexts, resolveContexts;
6966
6967		// add listeners to Deferred subordinates; treat others as resolved
6968		if ( length > 1 ) {
6969			progressValues = new Array( length );
6970			progressContexts = new Array( length );
6971			resolveContexts = new Array( length );
6972			for ( ; i < length; i++ ) {
6973				if ( resolveValues[ i ] && jQuery1113.isFunction( resolveValues[ i ].promise ) ) {
6974					resolveValues[ i ].promise()
6975						.done( updateFunc( i, resolveContexts, resolveValues ) )
6976						.fail( deferred.reject )
6977						.progress( updateFunc( i, progressContexts, progressValues ) );
6978				} else {
6979					--remaining;
6980				}
6981			}
6982		}
6983
6984		// if we're not waiting on anything, resolve the master
6985		if ( !remaining ) {
6986			deferred.resolveWith( resolveContexts, resolveValues );
6987		}
6988
6989		return deferred.promise();
6990	}
6991});
6992
6993
6994// The deferred used on DOM ready
6995var readyList;
6996
6997jQuery1113.fn.ready = function( fn ) {
6998	// Add the callback
6999	jQuery1113.ready.promise().done( fn );
7000
7001	return this;
7002};
7003
7004jQuery1113.extend({
7005	// Is the DOM ready to be used? Set to true once it occurs.
7006	isReady: false,
7007
7008	// A counter to track how many items to wait for before
7009	// the ready event fires. See #6781
7010	readyWait: 1,
7011
7012	// Hold (or release) the ready event
7013	holdReady: function( hold ) {
7014		if ( hold ) {
7015			jQuery1113.readyWait++;
7016		} else {
7017			jQuery1113.ready( true );
7018		}
7019	},
7020
7021	// Handle when the DOM is ready
7022	ready: function( wait ) {
7023
7024		// Abort if there are pending holds or we're already ready
7025		if ( wait === true ? --jQuery1113.readyWait : jQuery1113.isReady ) {
7026			return;
7027		}
7028
7029		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
7030		if ( !document.body ) {
7031			return setTimeout( jQuery1113.ready );
7032		}
7033
7034		// Remember that the DOM is ready
7035		jQuery1113.isReady = true;
7036
7037		// If a normal DOM Ready event fired, decrement, and wait if need be
7038		if ( wait !== true && --jQuery1113.readyWait > 0 ) {
7039			return;
7040		}
7041
7042		// If there are functions bound, to execute
7043		readyList.resolveWith( document, [ jQuery1113 ] );
7044
7045		// Trigger any bound ready events
7046		if ( jQuery1113.fn.triggerHandler ) {
7047			jQuery1113( document ).triggerHandler( "ready" );
7048			jQuery1113( document ).off( "ready" );
7049		}
7050	}
7051});
7052
7053/**
7054 * Clean-up method for dom ready events
7055 */
7056function detach() {
7057	if ( document.addEventListener ) {
7058		document.removeEventListener( "DOMContentLoaded", completed, false );
7059		window.removeEventListener( "load", completed, false );
7060
7061	} else {
7062		document.detachEvent( "onreadystatechange", completed );
7063		window.detachEvent( "onload", completed );
7064	}
7065}
7066
7067/**
7068 * The ready event handler and self cleanup method
7069 */
7070function completed() {
7071	// readyState === "complete" is good enough for us to call the dom ready in oldIE
7072	if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
7073		detach();
7074		jQuery1113.ready();
7075	}
7076}
7077
7078jQuery1113.ready.promise = function( obj ) {
7079	if ( !readyList ) {
7080
7081		readyList = jQuery1113.Deferred();
7082
7083		// Catch cases where $(document).ready() is called after the browser event has already occurred.
7084		// we once tried to use readyState "interactive" here, but it caused issues like the one
7085		// discovered by ChrisS here: http://bugs.jQuery1113.com/ticket/12282#comment:15
7086		if ( document.readyState === "complete" ) {
7087			// Handle it asynchronously to allow scripts the opportunity to delay ready
7088			setTimeout( jQuery1113.ready );
7089
7090		// Standards-based browsers support DOMContentLoaded
7091		} else if ( document.addEventListener ) {
7092			// Use the handy event callback
7093			document.addEventListener( "DOMContentLoaded", completed, false );
7094
7095			// A fallback to window.onload, that will always work
7096			window.addEventListener( "load", completed, false );
7097
7098		// If IE event model is used
7099		} else {
7100			// Ensure firing before onload, maybe late but safe also for iframes
7101			document.attachEvent( "onreadystatechange", completed );
7102
7103			// A fallback to window.onload, that will always work
7104			window.attachEvent( "onload", completed );
7105
7106			// If IE and not a frame
7107			// continually check to see if the document is ready
7108			var top = false;
7109
7110			try {
7111				top = window.frameElement == null && document.documentElement;
7112			} catch(e) {}
7113
7114			if ( top && top.doScroll ) {
7115				(function doScrollCheck() {
7116					if ( !jQuery1113.isReady ) {
7117
7118						try {
7119							// Use the trick by Diego Perini
7120							// http://javascript.nwbox.com/IEContentLoaded/
7121							top.doScroll("left");
7122						} catch(e) {
7123							return setTimeout( doScrollCheck, 50 );
7124						}
7125
7126						// detach all dom ready events
7127						detach();
7128
7129						// and execute any waiting functions
7130						jQuery1113.ready();
7131					}
7132				})();
7133			}
7134		}
7135	}
7136	return readyList.promise( obj );
7137};
7138
7139
7140var strundefined = typeof undefined;
7141
7142
7143
7144// Support: IE<9
7145// Iteration over object's inherited properties before its own
7146var i;
7147for ( i in jQuery1113( support ) ) {
7148	break;
7149}
7150support.ownLast = i !== "0";
7151
7152// Note: most support tests are defined in their respective modules.
7153// false until the test is run
7154support.inlineBlockNeedsLayout = false;
7155
7156// Execute ASAP in case we need to set body.style.zoom
7157jQuery1113(function() {
7158	// Minified: var a,b,c,d
7159	var val, div, body, container;
7160
7161	body = document.getElementsByTagName( "body" )[ 0 ];
7162	if ( !body || !body.style ) {
7163		// Return for frameset docs that don't have a body
7164		return;
7165	}
7166
7167	// Setup
7168	div = document.createElement( "div" );
7169	container = document.createElement( "div" );
7170	container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
7171	body.appendChild( container ).appendChild( div );
7172
7173	if ( typeof div.style.zoom !== strundefined ) {
7174		// Support: IE<8
7175		// Check if natively block-level elements act like inline-block
7176		// elements when setting their display to 'inline' and giving
7177		// them layout
7178		div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
7179
7180		support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
7181		if ( val ) {
7182			// Prevent IE 6 from affecting layout for positioned elements #11048
7183			// Prevent IE from shrinking the body in IE 7 mode #12869
7184			// Support: IE<8
7185			body.style.zoom = 1;
7186		}
7187	}
7188
7189	body.removeChild( container );
7190});
7191
7192
7193
7194
7195(function() {
7196	var div = document.createElement( "div" );
7197
7198	// Execute the test only if not already executed in another module.
7199	if (support.deleteExpando == null) {
7200		// Support: IE<9
7201		support.deleteExpando = true;
7202		try {
7203			delete div.test;
7204		} catch( e ) {
7205			support.deleteExpando = false;
7206		}
7207	}
7208
7209	// Null elements to avoid leaks in IE.
7210	div = null;
7211})();
7212
7213
7214/**
7215 * Determines whether an object can have data
7216 */
7217jQuery1113.acceptData = function( elem ) {
7218	var noData = jQuery1113.noData[ (elem.nodeName + " ").toLowerCase() ],
7219		nodeType = +elem.nodeType || 1;
7220
7221	// Do not set data on non-element DOM nodes because it will not be cleared (#8335).
7222	return nodeType !== 1 && nodeType !== 9 ?
7223		false :
7224
7225		// Nodes accept data unless otherwise specified; rejection can be conditional
7226		!noData || noData !== true && elem.getAttribute("classid") === noData;
7227};
7228
7229
7230var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
7231	rmultiDash = /([A-Z])/g;
7232
7233function dataAttr( elem, key, data ) {
7234	// If nothing was found internally, try to fetch any
7235	// data from the HTML5 data-* attribute
7236	if ( data === undefined && elem.nodeType === 1 ) {
7237
7238		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
7239
7240		data = elem.getAttribute( name );
7241
7242		if ( typeof data === "string" ) {
7243			try {
7244				data = data === "true" ? true :
7245					data === "false" ? false :
7246					data === "null" ? null :
7247					// Only convert to a number if it doesn't change the string
7248					+data + "" === data ? +data :
7249					rbrace.test( data ) ? jQuery1113.parseJSON( data ) :
7250					data;
7251			} catch( e ) {}
7252
7253			// Make sure we set the data so it isn't changed later
7254			jQuery1113.data( elem, key, data );
7255
7256		} else {
7257			data = undefined;
7258		}
7259	}
7260
7261	return data;
7262}
7263
7264// checks a cache object for emptiness
7265function isEmptyDataObject( obj ) {
7266	var name;
7267	for ( name in obj ) {
7268
7269		// if the public data object is empty, the private is still empty
7270		if ( name === "data" && jQuery1113.isEmptyObject( obj[name] ) ) {
7271			continue;
7272		}
7273		if ( name !== "toJSON" ) {
7274			return false;
7275		}
7276	}
7277
7278	return true;
7279}
7280
7281function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
7282	if ( !jQuery1113.acceptData( elem ) ) {
7283		return;
7284	}
7285
7286	var ret, thisCache,
7287		internalKey = jQuery1113.expando,
7288
7289		// We have to handle DOM nodes and JS objects differently because IE6-7
7290		// can't GC object references properly across the DOM-JS boundary
7291		isNode = elem.nodeType,
7292
7293		// Only DOM nodes need the global jQuery1113 cache; JS object data is
7294		// attached directly to the object so GC can occur automatically
7295		cache = isNode ? jQuery1113.cache : elem,
7296
7297		// Only defining an ID for JS objects if its cache already exists allows
7298		// the code to shortcut on the same path as a DOM node with no cache
7299		id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
7300
7301	// Avoid doing any more work than we need to when trying to get data on an
7302	// object that has no data at all
7303	if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
7304		return;
7305	}
7306
7307	if ( !id ) {
7308		// Only DOM nodes need a new unique ID for each element since their data
7309		// ends up in the global cache
7310		if ( isNode ) {
7311			id = elem[ internalKey ] = deletedIds.pop() || jQuery1113.guid++;
7312		} else {
7313			id = internalKey;
7314		}
7315	}
7316
7317	if ( !cache[ id ] ) {
7318		// Avoid exposing jQuery1113 metadata on plain JS objects when the object
7319		// is serialized using JSON.stringify
7320		cache[ id ] = isNode ? {} : { toJSON: jQuery1113.noop };
7321	}
7322
7323	// An object can be passed to jQuery1113.data instead of a key/value pair; this gets
7324	// shallow copied over onto the existing cache
7325	if ( typeof name === "object" || typeof name === "function" ) {
7326		if ( pvt ) {
7327			cache[ id ] = jQuery1113.extend( cache[ id ], name );
7328		} else {
7329			cache[ id ].data = jQuery1113.extend( cache[ id ].data, name );
7330		}
7331	}
7332
7333	thisCache = cache[ id ];
7334
7335	// jQuery1113 data() is stored in a separate object inside the object's internal data
7336	// cache in order to avoid key collisions between internal data and user-defined
7337	// data.
7338	if ( !pvt ) {
7339		if ( !thisCache.data ) {
7340			thisCache.data = {};
7341		}
7342
7343		thisCache = thisCache.data;
7344	}
7345
7346	if ( data !== undefined ) {
7347		thisCache[ jQuery1113.camelCase( name ) ] = data;
7348	}
7349
7350	// Check for both converted-to-camel and non-converted data property names
7351	// If a data property was specified
7352	if ( typeof name === "string" ) {
7353
7354		// First Try to find as-is property data
7355		ret = thisCache[ name ];
7356
7357		// Test for null|undefined property data
7358		if ( ret == null ) {
7359
7360			// Try to find the camelCased property
7361			ret = thisCache[ jQuery1113.camelCase( name ) ];
7362		}
7363	} else {
7364		ret = thisCache;
7365	}
7366
7367	return ret;
7368}
7369
7370function internalRemoveData( elem, name, pvt ) {
7371	if ( !jQuery1113.acceptData( elem ) ) {
7372		return;
7373	}
7374
7375	var thisCache, i,
7376		isNode = elem.nodeType,
7377
7378		// See jQuery1113.data for more information
7379		cache = isNode ? jQuery1113.cache : elem,
7380		id = isNode ? elem[ jQuery1113.expando ] : jQuery1113.expando;
7381
7382	// If there is already no cache entry for this object, there is no
7383	// purpose in continuing
7384	if ( !cache[ id ] ) {
7385		return;
7386	}
7387
7388	if ( name ) {
7389
7390		thisCache = pvt ? cache[ id ] : cache[ id ].data;
7391
7392		if ( thisCache ) {
7393
7394			// Support array or space separated string names for data keys
7395			if ( !jQuery1113.isArray( name ) ) {
7396
7397				// try the string as a key before any manipulation
7398				if ( name in thisCache ) {
7399					name = [ name ];
7400				} else {
7401
7402					// split the camel cased version by spaces unless a key with the spaces exists
7403					name = jQuery1113.camelCase( name );
7404					if ( name in thisCache ) {
7405						name = [ name ];
7406					} else {
7407						name = name.split(" ");
7408					}
7409				}
7410			} else {
7411				// If "name" is an array of keys...
7412				// When data is initially created, via ("key", "val") signature,
7413				// keys will be converted to camelCase.
7414				// Since there is no way to tell _how_ a key was added, remove
7415				// both plain key and camelCase key. #12786
7416				// This will only penalize the array argument path.
7417				name = name.concat( jQuery1113.map( name, jQuery1113.camelCase ) );
7418			}
7419
7420			i = name.length;
7421			while ( i-- ) {
7422				delete thisCache[ name[i] ];
7423			}
7424
7425			// If there is no data left in the cache, we want to continue
7426			// and let the cache object itself get destroyed
7427			if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery1113.isEmptyObject(thisCache) ) {
7428				return;
7429			}
7430		}
7431	}
7432
7433	// See jQuery1113.data for more information
7434	if ( !pvt ) {
7435		delete cache[ id ].data;
7436
7437		// Don't destroy the parent cache unless the internal data object
7438		// had been the only thing left in it
7439		if ( !isEmptyDataObject( cache[ id ] ) ) {
7440			return;
7441		}
7442	}
7443
7444	// Destroy the cache
7445	if ( isNode ) {
7446		jQuery1113.cleanData( [ elem ], true );
7447
7448	// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
7449	/* jshint eqeqeq: false */
7450	} else if ( support.deleteExpando || cache != cache.window ) {
7451		/* jshint eqeqeq: true */
7452		delete cache[ id ];
7453
7454	// When all else fails, null
7455	} else {
7456		cache[ id ] = null;
7457	}
7458}
7459
7460jQuery1113.extend({
7461	cache: {},
7462
7463	// The following elements (space-suffixed to avoid Object.prototype collisions)
7464	// throw uncatchable exceptions if you attempt to set expando properties
7465	noData: {
7466		"applet ": true,
7467		"embed ": true,
7468		// ...but Flash objects (which have this classid) *can* handle expandos
7469		"object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
7470	},
7471
7472	hasData: function( elem ) {
7473		elem = elem.nodeType ? jQuery1113.cache[ elem[jQuery1113.expando] ] : elem[ jQuery1113.expando ];
7474		return !!elem && !isEmptyDataObject( elem );
7475	},
7476
7477	data: function( elem, name, data ) {
7478		return internalData( elem, name, data );
7479	},
7480
7481	removeData: function( elem, name ) {
7482		return internalRemoveData( elem, name );
7483	},
7484
7485	// For internal use only.
7486	_data: function( elem, name, data ) {
7487		return internalData( elem, name, data, true );
7488	},
7489
7490	_removeData: function( elem, name ) {
7491		return internalRemoveData( elem, name, true );
7492	}
7493});
7494
7495jQuery1113.fn.extend({
7496	data: function( key, value ) {
7497		var i, name, data,
7498			elem = this[0],
7499			attrs = elem && elem.attributes;
7500
7501		// Special expections of .data basically thwart jQuery1113.access,
7502		// so implement the relevant behavior ourselves
7503
7504		// Gets all values
7505		if ( key === undefined ) {
7506			if ( this.length ) {
7507				data = jQuery1113.data( elem );
7508
7509				if ( elem.nodeType === 1 && !jQuery1113._data( elem, "parsedAttrs" ) ) {
7510					i = attrs.length;
7511					while ( i-- ) {
7512
7513						// Support: IE11+
7514						// The attrs elements can be null (#14894)
7515						if ( attrs[ i ] ) {
7516							name = attrs[ i ].name;
7517							if ( name.indexOf( "data-" ) === 0 ) {
7518								name = jQuery1113.camelCase( name.slice(5) );
7519								dataAttr( elem, name, data[ name ] );
7520							}
7521						}
7522					}
7523					jQuery1113._data( elem, "parsedAttrs", true );
7524				}
7525			}
7526
7527			return data;
7528		}
7529
7530		// Sets multiple values
7531		if ( typeof key === "object" ) {
7532			return this.each(function() {
7533				jQuery1113.data( this, key );
7534			});
7535		}
7536
7537		return arguments.length > 1 ?
7538
7539			// Sets one value
7540			this.each(function() {
7541				jQuery1113.data( this, key, value );
7542			}) :
7543
7544			// Gets one value
7545			// Try to fetch any internally stored data first
7546			elem ? dataAttr( elem, key, jQuery1113.data( elem, key ) ) : undefined;
7547	},
7548
7549	removeData: function( key ) {
7550		return this.each(function() {
7551			jQuery1113.removeData( this, key );
7552		});
7553	}
7554});
7555
7556
7557jQuery1113.extend({
7558	queue: function( elem, type, data ) {
7559		var queue;
7560
7561		if ( elem ) {
7562			type = ( type || "fx" ) + "queue";
7563			queue = jQuery1113._data( elem, type );
7564
7565			// Speed up dequeue by getting out quickly if this is just a lookup
7566			if ( data ) {
7567				if ( !queue || jQuery1113.isArray(data) ) {
7568					queue = jQuery1113._data( elem, type, jQuery1113.makeArray(data) );
7569				} else {
7570					queue.push( data );
7571				}
7572			}
7573			return queue || [];
7574		}
7575	},
7576
7577	dequeue: function( elem, type ) {
7578		type = type || "fx";
7579
7580		var queue = jQuery1113.queue( elem, type ),
7581			startLength = queue.length,
7582			fn = queue.shift(),
7583			hooks = jQuery1113._queueHooks( elem, type ),
7584			next = function() {
7585				jQuery1113.dequeue( elem, type );
7586			};
7587
7588		// If the fx queue is dequeued, always remove the progress sentinel
7589		if ( fn === "inprogress" ) {
7590			fn = queue.shift();
7591			startLength--;
7592		}
7593
7594		if ( fn ) {
7595
7596			// Add a progress sentinel to prevent the fx queue from being
7597			// automatically dequeued
7598			if ( type === "fx" ) {
7599				queue.unshift( "inprogress" );
7600			}
7601
7602			// clear up the last queue stop function
7603			delete hooks.stop;
7604			fn.call( elem, next, hooks );
7605		}
7606
7607		if ( !startLength && hooks ) {
7608			hooks.empty.fire();
7609		}
7610	},
7611
7612	// not intended for public consumption - generates a queueHooks object, or returns the current one
7613	_queueHooks: function( elem, type ) {
7614		var key = type + "queueHooks";
7615		return jQuery1113._data( elem, key ) || jQuery1113._data( elem, key, {
7616			empty: jQuery1113.Callbacks("once memory").add(function() {
7617				jQuery1113._removeData( elem, type + "queue" );
7618				jQuery1113._removeData( elem, key );
7619			})
7620		});
7621	}
7622});
7623
7624jQuery1113.fn.extend({
7625	queue: function( type, data ) {
7626		var setter = 2;
7627
7628		if ( typeof type !== "string" ) {
7629			data = type;
7630			type = "fx";
7631			setter--;
7632		}
7633
7634		if ( arguments.length < setter ) {
7635			return jQuery1113.queue( this[0], type );
7636		}
7637
7638		return data === undefined ?
7639			this :
7640			this.each(function() {
7641				var queue = jQuery1113.queue( this, type, data );
7642
7643				// ensure a hooks for this queue
7644				jQuery1113._queueHooks( this, type );
7645
7646				if ( type === "fx" && queue[0] !== "inprogress" ) {
7647					jQuery1113.dequeue( this, type );
7648				}
7649			});
7650	},
7651	dequeue: function( type ) {
7652		return this.each(function() {
7653			jQuery1113.dequeue( this, type );
7654		});
7655	},
7656	clearQueue: function( type ) {
7657		return this.queue( type || "fx", [] );
7658	},
7659	// Get a promise resolved when queues of a certain type
7660	// are emptied (fx is the type by default)
7661	promise: function( type, obj ) {
7662		var tmp,
7663			count = 1,
7664			defer = jQuery1113.Deferred(),
7665			elements = this,
7666			i = this.length,
7667			resolve = function() {
7668				if ( !( --count ) ) {
7669					defer.resolveWith( elements, [ elements ] );
7670				}
7671			};
7672
7673		if ( typeof type !== "string" ) {
7674			obj = type;
7675			type = undefined;
7676		}
7677		type = type || "fx";
7678
7679		while ( i-- ) {
7680			tmp = jQuery1113._data( elements[ i ], type + "queueHooks" );
7681			if ( tmp && tmp.empty ) {
7682				count++;
7683				tmp.empty.add( resolve );
7684			}
7685		}
7686		resolve();
7687		return defer.promise( obj );
7688	}
7689});
7690var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
7691
7692var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
7693
7694var isHidden = function( elem, el ) {
7695		// isHidden might be called from jQuery1113#filter function;
7696		// in that case, element will be second argument
7697		elem = el || elem;
7698		return jQuery1113.css( elem, "display" ) === "none" || !jQuery1113.contains( elem.ownerDocument, elem );
7699	};
7700
7701
7702
7703// Multifunctional method to get and set values of a collection
7704// The value/s can optionally be executed if it's a function
7705var access = jQuery1113.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
7706	var i = 0,
7707		length = elems.length,
7708		bulk = key == null;
7709
7710	// Sets many values
7711	if ( jQuery1113.type( key ) === "object" ) {
7712		chainable = true;
7713		for ( i in key ) {
7714			jQuery1113.access( elems, fn, i, key[i], true, emptyGet, raw );
7715		}
7716
7717	// Sets one value
7718	} else if ( value !== undefined ) {
7719		chainable = true;
7720
7721		if ( !jQuery1113.isFunction( value ) ) {
7722			raw = true;
7723		}
7724
7725		if ( bulk ) {
7726			// Bulk operations run against the entire set
7727			if ( raw ) {
7728				fn.call( elems, value );
7729				fn = null;
7730
7731			// ...except when executing function values
7732			} else {
7733				bulk = fn;
7734				fn = function( elem, key, value ) {
7735					return bulk.call( jQuery1113( elem ), value );
7736				};
7737			}
7738		}
7739
7740		if ( fn ) {
7741			for ( ; i < length; i++ ) {
7742				fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
7743			}
7744		}
7745	}
7746
7747	return chainable ?
7748		elems :
7749
7750		// Gets
7751		bulk ?
7752			fn.call( elems ) :
7753			length ? fn( elems[0], key ) : emptyGet;
7754};
7755var rcheckableType = (/^(?:checkbox|radio)$/i);
7756
7757
7758
7759(function() {
7760	// Minified: var a,b,c
7761	var input = document.createElement( "input" ),
7762		div = document.createElement( "div" ),
7763		fragment = document.createDocumentFragment();
7764
7765	// Setup
7766	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
7767
7768	// IE strips leading whitespace when .innerHTML is used
7769	support.leadingWhitespace = div.firstChild.nodeType === 3;
7770
7771	// Make sure that tbody elements aren't automatically inserted
7772	// IE will insert them into empty tables
7773	support.tbody = !div.getElementsByTagName( "tbody" ).length;
7774
7775	// Make sure that link elements get serialized correctly by innerHTML
7776	// This requires a wrapper element in IE
7777	support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
7778
7779	// Makes sure cloning an html5 element does not cause problems
7780	// Where outerHTML is undefined, this still works
7781	support.html5Clone =
7782		document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
7783
7784	// Check if a disconnected checkbox will retain its checked
7785	// value of true after appended to the DOM (IE6/7)
7786	input.type = "checkbox";
7787	input.checked = true;
7788	fragment.appendChild( input );
7789	support.appendChecked = input.checked;
7790
7791	// Make sure textarea (and checkbox) defaultValue is properly cloned
7792	// Support: IE6-IE11+
7793	div.innerHTML = "<textarea>x</textarea>";
7794	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
7795
7796	// #11217 - WebKit loses check when the name is after the checked attribute
7797	fragment.appendChild( div );
7798	div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
7799
7800	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
7801	// old WebKit doesn't clone checked state correctly in fragments
7802	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
7803
7804	// Support: IE<9
7805	// Opera does not clone events (and typeof div.attachEvent === undefined).
7806	// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
7807	support.noCloneEvent = true;
7808	if ( div.attachEvent ) {
7809		div.attachEvent( "onclick", function() {
7810			support.noCloneEvent = false;
7811		});
7812
7813		div.cloneNode( true ).click();
7814	}
7815
7816	// Execute the test only if not already executed in another module.
7817	if (support.deleteExpando == null) {
7818		// Support: IE<9
7819		support.deleteExpando = true;
7820		try {
7821			delete div.test;
7822		} catch( e ) {
7823			support.deleteExpando = false;
7824		}
7825	}
7826})();
7827
7828
7829(function() {
7830	var i, eventName,
7831		div = document.createElement( "div" );
7832
7833	// Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
7834	for ( i in { submit: true, change: true, focusin: true }) {
7835		eventName = "on" + i;
7836
7837		if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
7838			// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
7839			div.setAttribute( eventName, "t" );
7840			support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
7841		}
7842	}
7843
7844	// Null elements to avoid leaks in IE.
7845	div = null;
7846})();
7847
7848
7849var rformElems = /^(?:input|select|textarea)$/i,
7850	rkeyEvent = /^key/,
7851	rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
7852	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
7853	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
7854
7855function returnTrue() {
7856	return true;
7857}
7858
7859function returnFalse() {
7860	return false;
7861}
7862
7863function safeActiveElement() {
7864	try {
7865		return document.activeElement;
7866	} catch ( err ) { }
7867}
7868
7869/*
7870 * Helper functions for managing events -- not part of the public interface.
7871 * Props to Dean Edwards' addEvent library for many of the ideas.
7872 */
7873jQuery1113.event = {
7874
7875	global: {},
7876
7877	add: function( elem, types, handler, data, selector ) {
7878		var tmp, events, t, handleObjIn,
7879			special, eventHandle, handleObj,
7880			handlers, type, namespaces, origType,
7881			elemData = jQuery1113._data( elem );
7882
7883		// Don't attach events to noData or text/comment nodes (but allow plain objects)
7884		if ( !elemData ) {
7885			return;
7886		}
7887
7888		// Caller can pass in an object of custom data in lieu of the handler
7889		if ( handler.handler ) {
7890			handleObjIn = handler;
7891			handler = handleObjIn.handler;
7892			selector = handleObjIn.selector;
7893		}
7894
7895		// Make sure that the handler has a unique ID, used to find/remove it later
7896		if ( !handler.guid ) {
7897			handler.guid = jQuery1113.guid++;
7898		}
7899
7900		// Init the element's event structure and main handler, if this is the first
7901		if ( !(events = elemData.events) ) {
7902			events = elemData.events = {};
7903		}
7904		if ( !(eventHandle = elemData.handle) ) {
7905			eventHandle = elemData.handle = function( e ) {
7906				// Discard the second event of a jQuery1113.event.trigger() and
7907				// when an event is called after a page has unloaded
7908				return typeof jQuery1113 !== strundefined && (!e || jQuery1113.event.triggered !== e.type) ?
7909					jQuery1113.event.dispatch.apply( eventHandle.elem, arguments ) :
7910					undefined;
7911			};
7912			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
7913			eventHandle.elem = elem;
7914		}
7915
7916		// Handle multiple events separated by a space
7917		types = ( types || "" ).match( rnotwhite ) || [ "" ];
7918		t = types.length;
7919		while ( t-- ) {
7920			tmp = rtypenamespace.exec( types[t] ) || [];
7921			type = origType = tmp[1];
7922			namespaces = ( tmp[2] || "" ).split( "." ).sort();
7923
7924			// There *must* be a type, no attaching namespace-only handlers
7925			if ( !type ) {
7926				continue;
7927			}
7928
7929			// If event changes its type, use the special event handlers for the changed type
7930			special = jQuery1113.event.special[ type ] || {};
7931
7932			// If selector defined, determine special event api type, otherwise given type
7933			type = ( selector ? special.delegateType : special.bindType ) || type;
7934
7935			// Update special based on newly reset type
7936			special = jQuery1113.event.special[ type ] || {};
7937
7938			// handleObj is passed to all event handlers
7939			handleObj = jQuery1113.extend({
7940				type: type,
7941				origType: origType,
7942				data: data,
7943				handler: handler,
7944				guid: handler.guid,
7945				selector: selector,
7946				needsContext: selector && jQuery1113.expr.match.needsContext.test( selector ),
7947				namespace: namespaces.join(".")
7948			}, handleObjIn );
7949
7950			// Init the event handler queue if we're the first
7951			if ( !(handlers = events[ type ]) ) {
7952				handlers = events[ type ] = [];
7953				handlers.delegateCount = 0;
7954
7955				// Only use addEventListener/attachEvent if the special events handler returns false
7956				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
7957					// Bind the global event handler to the element
7958					if ( elem.addEventListener ) {
7959						elem.addEventListener( type, eventHandle, false );
7960
7961					} else if ( elem.attachEvent ) {
7962						elem.attachEvent( "on" + type, eventHandle );
7963					}
7964				}
7965			}
7966
7967			if ( special.add ) {
7968				special.add.call( elem, handleObj );
7969
7970				if ( !handleObj.handler.guid ) {
7971					handleObj.handler.guid = handler.guid;
7972				}
7973			}
7974
7975			// Add to the element's handler list, delegates in front
7976			if ( selector ) {
7977				handlers.splice( handlers.delegateCount++, 0, handleObj );
7978			} else {
7979				handlers.push( handleObj );
7980			}
7981
7982			// Keep track of which events have ever been used, for event optimization
7983			jQuery1113.event.global[ type ] = true;
7984		}
7985
7986		// Nullify elem to prevent memory leaks in IE
7987		elem = null;
7988	},
7989
7990	// Detach an event or set of events from an element
7991	remove: function( elem, types, handler, selector, mappedTypes ) {
7992		var j, handleObj, tmp,
7993			origCount, t, events,
7994			special, handlers, type,
7995			namespaces, origType,
7996			elemData = jQuery1113.hasData( elem ) && jQuery1113._data( elem );
7997
7998		if ( !elemData || !(events = elemData.events) ) {
7999			return;
8000		}
8001
8002		// Once for each type.namespace in types; type may be omitted
8003		types = ( types || "" ).match( rnotwhite ) || [ "" ];
8004		t = types.length;
8005		while ( t-- ) {
8006			tmp = rtypenamespace.exec( types[t] ) || [];
8007			type = origType = tmp[1];
8008			namespaces = ( tmp[2] || "" ).split( "." ).sort();
8009
8010			// Unbind all events (on this namespace, if provided) for the element
8011			if ( !type ) {
8012				for ( type in events ) {
8013					jQuery1113.event.remove( elem, type + types[ t ], handler, selector, true );
8014				}
8015				continue;
8016			}
8017
8018			special = jQuery1113.event.special[ type ] || {};
8019			type = ( selector ? special.delegateType : special.bindType ) || type;
8020			handlers = events[ type ] || [];
8021			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
8022
8023			// Remove matching events
8024			origCount = j = handlers.length;
8025			while ( j-- ) {
8026				handleObj = handlers[ j ];
8027
8028				if ( ( mappedTypes || origType === handleObj.origType ) &&
8029					( !handler || handler.guid === handleObj.guid ) &&
8030					( !tmp || tmp.test( handleObj.namespace ) ) &&
8031					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
8032					handlers.splice( j, 1 );
8033
8034					if ( handleObj.selector ) {
8035						handlers.delegateCount--;
8036					}
8037					if ( special.remove ) {
8038						special.remove.call( elem, handleObj );
8039					}
8040				}
8041			}
8042
8043			// Remove generic event handler if we removed something and no more handlers exist
8044			// (avoids potential for endless recursion during removal of special event handlers)
8045			if ( origCount && !handlers.length ) {
8046				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
8047					jQuery1113.removeEvent( elem, type, elemData.handle );
8048				}
8049
8050				delete events[ type ];
8051			}
8052		}
8053
8054		// Remove the expando if it's no longer used
8055		if ( jQuery1113.isEmptyObject( events ) ) {
8056			delete elemData.handle;
8057
8058			// removeData also checks for emptiness and clears the expando if empty
8059			// so use it instead of delete
8060			jQuery1113._removeData( elem, "events" );
8061		}
8062	},
8063
8064	trigger: function( event, data, elem, onlyHandlers ) {
8065		var handle, ontype, cur,
8066			bubbleType, special, tmp, i,
8067			eventPath = [ elem || document ],
8068			type = hasOwn.call( event, "type" ) ? event.type : event,
8069			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
8070
8071		cur = tmp = elem = elem || document;
8072
8073		// Don't do events on text and comment nodes
8074		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
8075			return;
8076		}
8077
8078		// focus/blur morphs to focusin/out; ensure we're not firing them right now
8079		if ( rfocusMorph.test( type + jQuery1113.event.triggered ) ) {
8080			return;
8081		}
8082
8083		if ( type.indexOf(".") >= 0 ) {
8084			// Namespaced trigger; create a regexp to match event type in handle()
8085			namespaces = type.split(".");
8086			type = namespaces.shift();
8087			namespaces.sort();
8088		}
8089		ontype = type.indexOf(":") < 0 && "on" + type;
8090
8091		// Caller can pass in a jQuery1113.Event object, Object, or just an event type string
8092		event = event[ jQuery1113.expando ] ?
8093			event :
8094			new jQuery1113.Event( type, typeof event === "object" && event );
8095
8096		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery1113 (always true)
8097		event.isTrigger = onlyHandlers ? 2 : 3;
8098		event.namespace = namespaces.join(".");
8099		event.namespace_re = event.namespace ?
8100			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
8101			null;
8102
8103		// Clean up the event in case it is being reused
8104		event.result = undefined;
8105		if ( !event.target ) {
8106			event.target = elem;
8107		}
8108
8109		// Clone any incoming data and prepend the event, creating the handler arg list
8110		data = data == null ?
8111			[ event ] :
8112			jQuery1113.makeArray( data, [ event ] );
8113
8114		// Allow special events to draw outside the lines
8115		special = jQuery1113.event.special[ type ] || {};
8116		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
8117			return;
8118		}
8119
8120		// Determine event propagation path in advance, per W3C events spec (#9951)
8121		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
8122		if ( !onlyHandlers && !special.noBubble && !jQuery1113.isWindow( elem ) ) {
8123
8124			bubbleType = special.delegateType || type;
8125			if ( !rfocusMorph.test( bubbleType + type ) ) {
8126				cur = cur.parentNode;
8127			}
8128			for ( ; cur; cur = cur.parentNode ) {
8129				eventPath.push( cur );
8130				tmp = cur;
8131			}
8132
8133			// Only add window if we got to document (e.g., not plain obj or detached DOM)
8134			if ( tmp === (elem.ownerDocument || document) ) {
8135				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
8136			}
8137		}
8138
8139		// Fire handlers on the event path
8140		i = 0;
8141		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
8142
8143			event.type = i > 1 ?
8144				bubbleType :
8145				special.bindType || type;
8146
8147			// jQuery1113 handler
8148			handle = ( jQuery1113._data( cur, "events" ) || {} )[ event.type ] && jQuery1113._data( cur, "handle" );
8149			if ( handle ) {
8150				handle.apply( cur, data );
8151			}
8152
8153			// Native handler
8154			handle = ontype && cur[ ontype ];
8155			if ( handle && handle.apply && jQuery1113.acceptData( cur ) ) {
8156				event.result = handle.apply( cur, data );
8157				if ( event.result === false ) {
8158					event.preventDefault();
8159				}
8160			}
8161		}
8162		event.type = type;
8163
8164		// If nobody prevented the default action, do it now
8165		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
8166
8167			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
8168				jQuery1113.acceptData( elem ) ) {
8169
8170				// Call a native DOM method on the target with the same name name as the event.
8171				// Can't use an .isFunction() check here because IE6/7 fails that test.
8172				// Don't do default actions on window, that's where global variables be (#6170)
8173				if ( ontype && elem[ type ] && !jQuery1113.isWindow( elem ) ) {
8174
8175					// Don't re-trigger an onFOO event when we call its FOO() method
8176					tmp = elem[ ontype ];
8177
8178					if ( tmp ) {
8179						elem[ ontype ] = null;
8180					}
8181
8182					// Prevent re-triggering of the same event, since we already bubbled it above
8183					jQuery1113.event.triggered = type;
8184					try {
8185						elem[ type ]();
8186					} catch ( e ) {
8187						// IE<9 dies on focus/blur to hidden element (#1486,#12518)
8188						// only reproducible on winXP IE8 native, not IE9 in IE8 mode
8189					}
8190					jQuery1113.event.triggered = undefined;
8191
8192					if ( tmp ) {
8193						elem[ ontype ] = tmp;
8194					}
8195				}
8196			}
8197		}
8198
8199		return event.result;
8200	},
8201
8202	dispatch: function( event ) {
8203
8204		// Make a writable jQuery1113.Event from the native event object
8205		event = jQuery1113.event.fix( event );
8206
8207		var i, ret, handleObj, matched, j,
8208			handlerQueue = [],
8209			args = slice.call( arguments ),
8210			handlers = ( jQuery1113._data( this, "events" ) || {} )[ event.type ] || [],
8211			special = jQuery1113.event.special[ event.type ] || {};
8212
8213		// Use the fix-ed jQuery1113.Event rather than the (read-only) native event
8214		args[0] = event;
8215		event.delegateTarget = this;
8216
8217		// Call the preDispatch hook for the mapped type, and let it bail if desired
8218		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
8219			return;
8220		}
8221
8222		// Determine handlers
8223		handlerQueue = jQuery1113.event.handlers.call( this, event, handlers );
8224
8225		// Run delegates first; they may want to stop propagation beneath us
8226		i = 0;
8227		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
8228			event.currentTarget = matched.elem;
8229
8230			j = 0;
8231			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
8232
8233				// Triggered event must either 1) have no namespace, or
8234				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
8235				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
8236
8237					event.handleObj = handleObj;
8238					event.data = handleObj.data;
8239
8240					ret = ( (jQuery1113.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
8241							.apply( matched.elem, args );
8242
8243					if ( ret !== undefined ) {
8244						if ( (event.result = ret) === false ) {
8245							event.preventDefault();
8246							event.stopPropagation();
8247						}
8248					}
8249				}
8250			}
8251		}
8252
8253		// Call the postDispatch hook for the mapped type
8254		if ( special.postDispatch ) {
8255			special.postDispatch.call( this, event );
8256		}
8257
8258		return event.result;
8259	},
8260
8261	handlers: function( event, handlers ) {
8262		var sel, handleObj, matches, i,
8263			handlerQueue = [],
8264			delegateCount = handlers.delegateCount,
8265			cur = event.target;
8266
8267		// Find delegate handlers
8268		// Black-hole SVG <use> instance trees (#13180)
8269		// Avoid non-left-click bubbling in Firefox (#3861)
8270		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
8271
8272			/* jshint eqeqeq: false */
8273			for ( ; cur != this; cur = cur.parentNode || this ) {
8274				/* jshint eqeqeq: true */
8275
8276				// Don't check non-elements (#13208)
8277				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
8278				if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
8279					matches = [];
8280					for ( i = 0; i < delegateCount; i++ ) {
8281						handleObj = handlers[ i ];
8282
8283						// Don't conflict with Object.prototype properties (#13203)
8284						sel = handleObj.selector + " ";
8285
8286						if ( matches[ sel ] === undefined ) {
8287							matches[ sel ] = handleObj.needsContext ?
8288								jQuery1113( sel, this ).index( cur ) >= 0 :
8289								jQuery1113.find( sel, this, null, [ cur ] ).length;
8290						}
8291						if ( matches[ sel ] ) {
8292							matches.push( handleObj );
8293						}
8294					}
8295					if ( matches.length ) {
8296						handlerQueue.push({ elem: cur, handlers: matches });
8297					}
8298				}
8299			}
8300		}
8301
8302		// Add the remaining (directly-bound) handlers
8303		if ( delegateCount < handlers.length ) {
8304			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
8305		}
8306
8307		return handlerQueue;
8308	},
8309
8310	fix: function( event ) {
8311		if ( event[ jQuery1113.expando ] ) {
8312			return event;
8313		}
8314
8315		// Create a writable copy of the event object and normalize some properties
8316		var i, prop, copy,
8317			type = event.type,
8318			originalEvent = event,
8319			fixHook = this.fixHooks[ type ];
8320
8321		if ( !fixHook ) {
8322			this.fixHooks[ type ] = fixHook =
8323				rmouseEvent.test( type ) ? this.mouseHooks :
8324				rkeyEvent.test( type ) ? this.keyHooks :
8325				{};
8326		}
8327		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
8328
8329		event = new jQuery1113.Event( originalEvent );
8330
8331		i = copy.length;
8332		while ( i-- ) {
8333			prop = copy[ i ];
8334			event[ prop ] = originalEvent[ prop ];
8335		}
8336
8337		// Support: IE<9
8338		// Fix target property (#1925)
8339		if ( !event.target ) {
8340			event.target = originalEvent.srcElement || document;
8341		}
8342
8343		// Support: Chrome 23+, Safari?
8344		// Target should not be a text node (#504, #13143)
8345		if ( event.target.nodeType === 3 ) {
8346			event.target = event.target.parentNode;
8347		}
8348
8349		// Support: IE<9
8350		// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
8351		event.metaKey = !!event.metaKey;
8352
8353		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
8354	},
8355
8356	// Includes some event props shared by KeyEvent and MouseEvent
8357	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
8358
8359	fixHooks: {},
8360
8361	keyHooks: {
8362		props: "char charCode key keyCode".split(" "),
8363		filter: function( event, original ) {
8364
8365			// Add which for key events
8366			if ( event.which == null ) {
8367				event.which = original.charCode != null ? original.charCode : original.keyCode;
8368			}
8369
8370			return event;
8371		}
8372	},
8373
8374	mouseHooks: {
8375		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
8376		filter: function( event, original ) {
8377			var body, eventDoc, doc,
8378				button = original.button,
8379				fromElement = original.fromElement;
8380
8381			// Calculate pageX/Y if missing and clientX/Y available
8382			if ( event.pageX == null && original.clientX != null ) {
8383				eventDoc = event.target.ownerDocument || document;
8384				doc = eventDoc.documentElement;
8385				body = eventDoc.body;
8386
8387				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
8388				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
8389			}
8390
8391			// Add relatedTarget, if necessary
8392			if ( !event.relatedTarget && fromElement ) {
8393				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
8394			}
8395
8396			// Add which for click: 1 === left; 2 === middle; 3 === right
8397			// Note: button is not normalized, so don't use it
8398			if ( !event.which && button !== undefined ) {
8399				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
8400			}
8401
8402			return event;
8403		}
8404	},
8405
8406	special: {
8407		load: {
8408			// Prevent triggered image.load events from bubbling to window.load
8409			noBubble: true
8410		},
8411		focus: {
8412			// Fire native event if possible so blur/focus sequence is correct
8413			trigger: function() {
8414				if ( this !== safeActiveElement() && this.focus ) {
8415					try {
8416						this.focus();
8417						return false;
8418					} catch ( e ) {
8419						// Support: IE<9
8420						// If we error on focus to hidden element (#1486, #12518),
8421						// let .trigger() run the handlers
8422					}
8423				}
8424			},
8425			delegateType: "focusin"
8426		},
8427		blur: {
8428			trigger: function() {
8429				if ( this === safeActiveElement() && this.blur ) {
8430					this.blur();
8431					return false;
8432				}
8433			},
8434			delegateType: "focusout"
8435		},
8436		click: {
8437			// For checkbox, fire native event so checked state will be right
8438			trigger: function() {
8439				if ( jQuery1113.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
8440					this.click();
8441					return false;
8442				}
8443			},
8444
8445			// For cross-browser consistency, don't fire native .click() on links
8446			_default: function( event ) {
8447				return jQuery1113.nodeName( event.target, "a" );
8448			}
8449		},
8450
8451		beforeunload: {
8452			postDispatch: function( event ) {
8453
8454				// Support: Firefox 20+
8455				// Firefox doesn't alert if the returnValue field is not set.
8456				if ( event.result !== undefined && event.originalEvent ) {
8457					event.originalEvent.returnValue = event.result;
8458				}
8459			}
8460		}
8461	},
8462
8463	simulate: function( type, elem, event, bubble ) {
8464		// Piggyback on a donor event to simulate a different one.
8465		// Fake originalEvent to avoid donor's stopPropagation, but if the
8466		// simulated event prevents default then we do the same on the donor.
8467		var e = jQuery1113.extend(
8468			new jQuery1113.Event(),
8469			event,
8470			{
8471				type: type,
8472				isSimulated: true,
8473				originalEvent: {}
8474			}
8475		);
8476		if ( bubble ) {
8477			jQuery1113.event.trigger( e, null, elem );
8478		} else {
8479			jQuery1113.event.dispatch.call( elem, e );
8480		}
8481		if ( e.isDefaultPrevented() ) {
8482			event.preventDefault();
8483		}
8484	}
8485};
8486
8487jQuery1113.removeEvent = document.removeEventListener ?
8488	function( elem, type, handle ) {
8489		if ( elem.removeEventListener ) {
8490			elem.removeEventListener( type, handle, false );
8491		}
8492	} :
8493	function( elem, type, handle ) {
8494		var name = "on" + type;
8495
8496		if ( elem.detachEvent ) {
8497
8498			// #8545, #7054, preventing memory leaks for custom events in IE6-8
8499			// detachEvent needed property on element, by name of that event, to properly expose it to GC
8500			if ( typeof elem[ name ] === strundefined ) {
8501				elem[ name ] = null;
8502			}
8503
8504			elem.detachEvent( name, handle );
8505		}
8506	};
8507
8508jQuery1113.Event = function( src, props ) {
8509	// Allow instantiation without the 'new' keyword
8510	if ( !(this instanceof jQuery1113.Event) ) {
8511		return new jQuery1113.Event( src, props );
8512	}
8513
8514	// Event object
8515	if ( src && src.type ) {
8516		this.originalEvent = src;
8517		this.type = src.type;
8518
8519		// Events bubbling up the document may have been marked as prevented
8520		// by a handler lower down the tree; reflect the correct value.
8521		this.isDefaultPrevented = src.defaultPrevented ||
8522				src.defaultPrevented === undefined &&
8523				// Support: IE < 9, Android < 4.0
8524				src.returnValue === false ?
8525			returnTrue :
8526			returnFalse;
8527
8528	// Event type
8529	} else {
8530		this.type = src;
8531	}
8532
8533	// Put explicitly provided properties onto the event object
8534	if ( props ) {
8535		jQuery1113.extend( this, props );
8536	}
8537
8538	// Create a timestamp if incoming event doesn't have one
8539	this.timeStamp = src && src.timeStamp || jQuery1113.now();
8540
8541	// Mark it as fixed
8542	this[ jQuery1113.expando ] = true;
8543};
8544
8545// jQuery1113.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
8546// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
8547jQuery1113.Event.prototype = {
8548	isDefaultPrevented: returnFalse,
8549	isPropagationStopped: returnFalse,
8550	isImmediatePropagationStopped: returnFalse,
8551
8552	preventDefault: function() {
8553		var e = this.originalEvent;
8554
8555		this.isDefaultPrevented = returnTrue;
8556		if ( !e ) {
8557			return;
8558		}
8559
8560		// If preventDefault exists, run it on the original event
8561		if ( e.preventDefault ) {
8562			e.preventDefault();
8563
8564		// Support: IE
8565		// Otherwise set the returnValue property of the original event to false
8566		} else {
8567			e.returnValue = false;
8568		}
8569	},
8570	stopPropagation: function() {
8571		var e = this.originalEvent;
8572
8573		this.isPropagationStopped = returnTrue;
8574		if ( !e ) {
8575			return;
8576		}
8577		// If stopPropagation exists, run it on the original event
8578		if ( e.stopPropagation ) {
8579			e.stopPropagation();
8580		}
8581
8582		// Support: IE
8583		// Set the cancelBubble property of the original event to true
8584		e.cancelBubble = true;
8585	},
8586	stopImmediatePropagation: function() {
8587		var e = this.originalEvent;
8588
8589		this.isImmediatePropagationStopped = returnTrue;
8590
8591		if ( e && e.stopImmediatePropagation ) {
8592			e.stopImmediatePropagation();
8593		}
8594
8595		this.stopPropagation();
8596	}
8597};
8598
8599// Create mouseenter/leave events using mouseover/out and event-time checks
8600jQuery1113.each({
8601	mouseenter: "mouseover",
8602	mouseleave: "mouseout",
8603	pointerenter: "pointerover",
8604	pointerleave: "pointerout"
8605}, function( orig, fix ) {
8606	jQuery1113.event.special[ orig ] = {
8607		delegateType: fix,
8608		bindType: fix,
8609
8610		handle: function( event ) {
8611			var ret,
8612				target = this,
8613				related = event.relatedTarget,
8614				handleObj = event.handleObj;
8615
8616			// For mousenter/leave call the handler if related is outside the target.
8617			// NB: No relatedTarget if the mouse left/entered the browser window
8618			if ( !related || (related !== target && !jQuery1113.contains( target, related )) ) {
8619				event.type = handleObj.origType;
8620				ret = handleObj.handler.apply( this, arguments );
8621				event.type = fix;
8622			}
8623			return ret;
8624		}
8625	};
8626});
8627
8628// IE submit delegation
8629if ( !support.submitBubbles ) {
8630
8631	jQuery1113.event.special.submit = {
8632		setup: function() {
8633			// Only need this for delegated form submit events
8634			if ( jQuery1113.nodeName( this, "form" ) ) {
8635				return false;
8636			}
8637
8638			// Lazy-add a submit handler when a descendant form may potentially be submitted
8639			jQuery1113.event.add( this, "click._submit keypress._submit", function( e ) {
8640				// Node name check avoids a VML-related crash in IE (#9807)
8641				var elem = e.target,
8642					form = jQuery1113.nodeName( elem, "input" ) || jQuery1113.nodeName( elem, "button" ) ? elem.form : undefined;
8643				if ( form && !jQuery1113._data( form, "submitBubbles" ) ) {
8644					jQuery1113.event.add( form, "submit._submit", function( event ) {
8645						event._submit_bubble = true;
8646					});
8647					jQuery1113._data( form, "submitBubbles", true );
8648				}
8649			});
8650			// return undefined since we don't need an event listener
8651		},
8652
8653		postDispatch: function( event ) {
8654			// If form was submitted by the user, bubble the event up the tree
8655			if ( event._submit_bubble ) {
8656				delete event._submit_bubble;
8657				if ( this.parentNode && !event.isTrigger ) {
8658					jQuery1113.event.simulate( "submit", this.parentNode, event, true );
8659				}
8660			}
8661		},
8662
8663		teardown: function() {
8664			// Only need this for delegated form submit events
8665			if ( jQuery1113.nodeName( this, "form" ) ) {
8666				return false;
8667			}
8668
8669			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
8670			jQuery1113.event.remove( this, "._submit" );
8671		}
8672	};
8673}
8674
8675// IE change delegation and checkbox/radio fix
8676if ( !support.changeBubbles ) {
8677
8678	jQuery1113.event.special.change = {
8679
8680		setup: function() {
8681
8682			if ( rformElems.test( this.nodeName ) ) {
8683				// IE doesn't fire change on a check/radio until blur; trigger it on click
8684				// after a propertychange. Eat the blur-change in special.change.handle.
8685				// This still fires onchange a second time for check/radio after blur.
8686				if ( this.type === "checkbox" || this.type === "radio" ) {
8687					jQuery1113.event.add( this, "propertychange._change", function( event ) {
8688						if ( event.originalEvent.propertyName === "checked" ) {
8689							this._just_changed = true;
8690						}
8691					});
8692					jQuery1113.event.add( this, "click._change", function( event ) {
8693						if ( this._just_changed && !event.isTrigger ) {
8694							this._just_changed = false;
8695						}
8696						// Allow triggered, simulated change events (#11500)
8697						jQuery1113.event.simulate( "change", this, event, true );
8698					});
8699				}
8700				return false;
8701			}
8702			// Delegated event; lazy-add a change handler on descendant inputs
8703			jQuery1113.event.add( this, "beforeactivate._change", function( e ) {
8704				var elem = e.target;
8705
8706				if ( rformElems.test( elem.nodeName ) && !jQuery1113._data( elem, "changeBubbles" ) ) {
8707					jQuery1113.event.add( elem, "change._change", function( event ) {
8708						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
8709							jQuery1113.event.simulate( "change", this.parentNode, event, true );
8710						}
8711					});
8712					jQuery1113._data( elem, "changeBubbles", true );
8713				}
8714			});
8715		},
8716
8717		handle: function( event ) {
8718			var elem = event.target;
8719
8720			// Swallow native change events from checkbox/radio, we already triggered them above
8721			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
8722				return event.handleObj.handler.apply( this, arguments );
8723			}
8724		},
8725
8726		teardown: function() {
8727			jQuery1113.event.remove( this, "._change" );
8728
8729			return !rformElems.test( this.nodeName );
8730		}
8731	};
8732}
8733
8734// Create "bubbling" focus and blur events
8735if ( !support.focusinBubbles ) {
8736	jQuery1113.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
8737
8738		// Attach a single capturing handler on the document while someone wants focusin/focusout
8739		var handler = function( event ) {
8740				jQuery1113.event.simulate( fix, event.target, jQuery1113.event.fix( event ), true );
8741			};
8742
8743		jQuery1113.event.special[ fix ] = {
8744			setup: function() {
8745				var doc = this.ownerDocument || this,
8746					attaches = jQuery1113._data( doc, fix );
8747
8748				if ( !attaches ) {
8749					doc.addEventListener( orig, handler, true );
8750				}
8751				jQuery1113._data( doc, fix, ( attaches || 0 ) + 1 );
8752			},
8753			teardown: function() {
8754				var doc = this.ownerDocument || this,
8755					attaches = jQuery1113._data( doc, fix ) - 1;
8756
8757				if ( !attaches ) {
8758					doc.removeEventListener( orig, handler, true );
8759					jQuery1113._removeData( doc, fix );
8760				} else {
8761					jQuery1113._data( doc, fix, attaches );
8762				}
8763			}
8764		};
8765	});
8766}
8767
8768jQuery1113.fn.extend({
8769
8770	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
8771		var type, origFn;
8772
8773		// Types can be a map of types/handlers
8774		if ( typeof types === "object" ) {
8775			// ( types-Object, selector, data )
8776			if ( typeof selector !== "string" ) {
8777				// ( types-Object, data )
8778				data = data || selector;
8779				selector = undefined;
8780			}
8781			for ( type in types ) {
8782				this.on( type, selector, data, types[ type ], one );
8783			}
8784			return this;
8785		}
8786
8787		if ( data == null && fn == null ) {
8788			// ( types, fn )
8789			fn = selector;
8790			data = selector = undefined;
8791		} else if ( fn == null ) {
8792			if ( typeof selector === "string" ) {
8793				// ( types, selector, fn )
8794				fn = data;
8795				data = undefined;
8796			} else {
8797				// ( types, data, fn )
8798				fn = data;
8799				data = selector;
8800				selector = undefined;
8801			}
8802		}
8803		if ( fn === false ) {
8804			fn = returnFalse;
8805		} else if ( !fn ) {
8806			return this;
8807		}
8808
8809		if ( one === 1 ) {
8810			origFn = fn;
8811			fn = function( event ) {
8812				// Can use an empty set, since event contains the info
8813				jQuery1113().off( event );
8814				return origFn.apply( this, arguments );
8815			};
8816			// Use same guid so caller can remove using origFn
8817			fn.guid = origFn.guid || ( origFn.guid = jQuery1113.guid++ );
8818		}
8819		return this.each( function() {
8820			jQuery1113.event.add( this, types, fn, data, selector );
8821		});
8822	},
8823	one: function( types, selector, data, fn ) {
8824		return this.on( types, selector, data, fn, 1 );
8825	},
8826	off: function( types, selector, fn ) {
8827		var handleObj, type;
8828		if ( types && types.preventDefault && types.handleObj ) {
8829			// ( event )  dispatched jQuery1113.Event
8830			handleObj = types.handleObj;
8831			jQuery1113( types.delegateTarget ).off(
8832				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
8833				handleObj.selector,
8834				handleObj.handler
8835			);
8836			return this;
8837		}
8838		if ( typeof types === "object" ) {
8839			// ( types-object [, selector] )
8840			for ( type in types ) {
8841				this.off( type, selector, types[ type ] );
8842			}
8843			return this;
8844		}
8845		if ( selector === false || typeof selector === "function" ) {
8846			// ( types [, fn] )
8847			fn = selector;
8848			selector = undefined;
8849		}
8850		if ( fn === false ) {
8851			fn = returnFalse;
8852		}
8853		return this.each(function() {
8854			jQuery1113.event.remove( this, types, fn, selector );
8855		});
8856	},
8857
8858	trigger: function( type, data ) {
8859		return this.each(function() {
8860			jQuery1113.event.trigger( type, data, this );
8861		});
8862	},
8863	triggerHandler: function( type, data ) {
8864		var elem = this[0];
8865		if ( elem ) {
8866			return jQuery1113.event.trigger( type, data, elem, true );
8867		}
8868	}
8869});
8870
8871
8872function createSafeFragment( document ) {
8873	var list = nodeNames.split( "|" ),
8874		safeFrag = document.createDocumentFragment();
8875
8876	if ( safeFrag.createElement ) {
8877		while ( list.length ) {
8878			safeFrag.createElement(
8879				list.pop()
8880			);
8881		}
8882	}
8883	return safeFrag;
8884}
8885
8886var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
8887		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
8888	rinlinejQuery1113 = / jQuery1113\d+="(?:null|\d+)"/g,
8889	rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
8890	rleadingWhitespace = /^\s+/,
8891	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
8892	rtagName = /<([\w:]+)/,
8893	rtbody = /<tbody/i,
8894	rhtml = /<|&#?\w+;/,
8895	rnoInnerhtml = /<(?:script|style|link)/i,
8896	// checked="checked" or checked
8897	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
8898	rscriptType = /^$|\/(?:java|ecma)script/i,
8899	rscriptTypeMasked = /^true\/(.*)/,
8900	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
8901
8902	// We have to close these tags to support XHTML (#13200)
8903	wrapMap = {
8904		option: [ 1, "<select multiple='multiple'>", "</select>" ],
8905		legend: [ 1, "<fieldset>", "</fieldset>" ],
8906		area: [ 1, "<map>", "</map>" ],
8907		param: [ 1, "<object>", "</object>" ],
8908		thead: [ 1, "<table>", "</table>" ],
8909		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
8910		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
8911		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
8912
8913		// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
8914		// unless wrapped in a div with non-breaking characters in front of it.
8915		_default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>"  ]
8916	},
8917	safeFragment = createSafeFragment( document ),
8918	fragmentDiv = safeFragment.appendChild( document.createElement("div") );
8919
8920wrapMap.optgroup = wrapMap.option;
8921wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
8922wrapMap.th = wrapMap.td;
8923
8924function getAll( context, tag ) {
8925	var elems, elem,
8926		i = 0,
8927		found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
8928			typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
8929			undefined;
8930
8931	if ( !found ) {
8932		for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
8933			if ( !tag || jQuery1113.nodeName( elem, tag ) ) {
8934				found.push( elem );
8935			} else {
8936				jQuery1113.merge( found, getAll( elem, tag ) );
8937			}
8938		}
8939	}
8940
8941	return tag === undefined || tag && jQuery1113.nodeName( context, tag ) ?
8942		jQuery1113.merge( [ context ], found ) :
8943		found;
8944}
8945
8946// Used in buildFragment, fixes the defaultChecked property
8947function fixDefaultChecked( elem ) {
8948	if ( rcheckableType.test( elem.type ) ) {
8949		elem.defaultChecked = elem.checked;
8950	}
8951}
8952
8953// Support: IE<8
8954// Manipulating tables requires a tbody
8955function manipulationTarget( elem, content ) {
8956	return jQuery1113.nodeName( elem, "table" ) &&
8957		jQuery1113.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
8958
8959		elem.getElementsByTagName("tbody")[0] ||
8960			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
8961		elem;
8962}
8963
8964// Replace/restore the type attribute of script elements for safe DOM manipulation
8965function disableScript( elem ) {
8966	elem.type = (jQuery1113.find.attr( elem, "type" ) !== null) + "/" + elem.type;
8967	return elem;
8968}
8969function restoreScript( elem ) {
8970	var match = rscriptTypeMasked.exec( elem.type );
8971	if ( match ) {
8972		elem.type = match[1];
8973	} else {
8974		elem.removeAttribute("type");
8975	}
8976	return elem;
8977}
8978
8979// Mark scripts as having already been evaluated
8980function setGlobalEval( elems, refElements ) {
8981	var elem,
8982		i = 0;
8983	for ( ; (elem = elems[i]) != null; i++ ) {
8984		jQuery1113._data( elem, "globalEval", !refElements || jQuery1113._data( refElements[i], "globalEval" ) );
8985	}
8986}
8987
8988function cloneCopyEvent( src, dest ) {
8989
8990	if ( dest.nodeType !== 1 || !jQuery1113.hasData( src ) ) {
8991		return;
8992	}
8993
8994	var type, i, l,
8995		oldData = jQuery1113._data( src ),
8996		curData = jQuery1113._data( dest, oldData ),
8997		events = oldData.events;
8998
8999	if ( events ) {
9000		delete curData.handle;
9001		curData.events = {};
9002
9003		for ( type in events ) {
9004			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
9005				jQuery1113.event.add( dest, type, events[ type ][ i ] );
9006			}
9007		}
9008	}
9009
9010	// make the cloned public data object a copy from the original
9011	if ( curData.data ) {
9012		curData.data = jQuery1113.extend( {}, curData.data );
9013	}
9014}
9015
9016function fixCloneNodeIssues( src, dest ) {
9017	var nodeName, e, data;
9018
9019	// We do not need to do anything for non-Elements
9020	if ( dest.nodeType !== 1 ) {
9021		return;
9022	}
9023
9024	nodeName = dest.nodeName.toLowerCase();
9025
9026	// IE6-8 copies events bound via attachEvent when using cloneNode.
9027	if ( !support.noCloneEvent && dest[ jQuery1113.expando ] ) {
9028		data = jQuery1113._data( dest );
9029
9030		for ( e in data.events ) {
9031			jQuery1113.removeEvent( dest, e, data.handle );
9032		}
9033
9034		// Event data gets referenced instead of copied if the expando gets copied too
9035		dest.removeAttribute( jQuery1113.expando );
9036	}
9037
9038	// IE blanks contents when cloning scripts, and tries to evaluate newly-set text
9039	if ( nodeName === "script" && dest.text !== src.text ) {
9040		disableScript( dest ).text = src.text;
9041		restoreScript( dest );
9042
9043	// IE6-10 improperly clones children of object elements using classid.
9044	// IE10 throws NoModificationAllowedError if parent is null, #12132.
9045	} else if ( nodeName === "object" ) {
9046		if ( dest.parentNode ) {
9047			dest.outerHTML = src.outerHTML;
9048		}
9049
9050		// This path appears unavoidable for IE9. When cloning an object
9051		// element in IE9, the outerHTML strategy above is not sufficient.
9052		// If the src has innerHTML and the destination does not,
9053		// copy the src.innerHTML into the dest.innerHTML. #10324
9054		if ( support.html5Clone && ( src.innerHTML && !jQuery1113.trim(dest.innerHTML) ) ) {
9055			dest.innerHTML = src.innerHTML;
9056		}
9057
9058	} else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
9059		// IE6-8 fails to persist the checked state of a cloned checkbox
9060		// or radio button. Worse, IE6-7 fail to give the cloned element
9061		// a checked appearance if the defaultChecked value isn't also set
9062
9063		dest.defaultChecked = dest.checked = src.checked;
9064
9065		// IE6-7 get confused and end up setting the value of a cloned
9066		// checkbox/radio button to an empty string instead of "on"
9067		if ( dest.value !== src.value ) {
9068			dest.value = src.value;
9069		}
9070
9071	// IE6-8 fails to return the selected option to the default selected
9072	// state when cloning options
9073	} else if ( nodeName === "option" ) {
9074		dest.defaultSelected = dest.selected = src.defaultSelected;
9075
9076	// IE6-8 fails to set the defaultValue to the correct value when
9077	// cloning other types of input fields
9078	} else if ( nodeName === "input" || nodeName === "textarea" ) {
9079		dest.defaultValue = src.defaultValue;
9080	}
9081}
9082
9083jQuery1113.extend({
9084	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
9085		var destElements, node, clone, i, srcElements,
9086			inPage = jQuery1113.contains( elem.ownerDocument, elem );
9087
9088		if ( support.html5Clone || jQuery1113.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
9089			clone = elem.cloneNode( true );
9090
9091		// IE<=8 does not properly clone detached, unknown element nodes
9092		} else {
9093			fragmentDiv.innerHTML = elem.outerHTML;
9094			fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
9095		}
9096
9097		if ( (!support.noCloneEvent || !support.noCloneChecked) &&
9098				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery1113.isXMLDoc(elem) ) {
9099
9100			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
9101			destElements = getAll( clone );
9102			srcElements = getAll( elem );
9103
9104			// Fix all IE cloning issues
9105			for ( i = 0; (node = srcElements[i]) != null; ++i ) {
9106				// Ensure that the destination node is not null; Fixes #9587
9107				if ( destElements[i] ) {
9108					fixCloneNodeIssues( node, destElements[i] );
9109				}
9110			}
9111		}
9112
9113		// Copy the events from the original to the clone
9114		if ( dataAndEvents ) {
9115			if ( deepDataAndEvents ) {
9116				srcElements = srcElements || getAll( elem );
9117				destElements = destElements || getAll( clone );
9118
9119				for ( i = 0; (node = srcElements[i]) != null; i++ ) {
9120					cloneCopyEvent( node, destElements[i] );
9121				}
9122			} else {
9123				cloneCopyEvent( elem, clone );
9124			}
9125		}
9126
9127		// Preserve script evaluation history
9128		destElements = getAll( clone, "script" );
9129		if ( destElements.length > 0 ) {
9130			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
9131		}
9132
9133		destElements = srcElements = node = null;
9134
9135		// Return the cloned set
9136		return clone;
9137	},
9138
9139	buildFragment: function( elems, context, scripts, selection ) {
9140		var j, elem, contains,
9141			tmp, tag, tbody, wrap,
9142			l = elems.length,
9143
9144			// Ensure a safe fragment
9145			safe = createSafeFragment( context ),
9146
9147			nodes = [],
9148			i = 0;
9149
9150		for ( ; i < l; i++ ) {
9151			elem = elems[ i ];
9152
9153			if ( elem || elem === 0 ) {
9154
9155				// Add nodes directly
9156				if ( jQuery1113.type( elem ) === "object" ) {
9157					jQuery1113.merge( nodes, elem.nodeType ? [ elem ] : elem );
9158
9159				// Convert non-html into a text node
9160				} else if ( !rhtml.test( elem ) ) {
9161					nodes.push( context.createTextNode( elem ) );
9162
9163				// Convert html into DOM nodes
9164				} else {
9165					tmp = tmp || safe.appendChild( context.createElement("div") );
9166
9167					// Deserialize a standard representation
9168					tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
9169					wrap = wrapMap[ tag ] || wrapMap._default;
9170
9171					tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
9172
9173					// Descend through wrappers to the right content
9174					j = wrap[0];
9175					while ( j-- ) {
9176						tmp = tmp.lastChild;
9177					}
9178
9179					// Manually add leading whitespace removed by IE
9180					if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
9181						nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
9182					}
9183
9184					// Remove IE's autoinserted <tbody> from table fragments
9185					if ( !support.tbody ) {
9186
9187						// String was a <table>, *may* have spurious <tbody>
9188						elem = tag === "table" && !rtbody.test( elem ) ?
9189							tmp.firstChild :
9190
9191							// String was a bare <thead> or <tfoot>
9192							wrap[1] === "<table>" && !rtbody.test( elem ) ?
9193								tmp :
9194								0;
9195
9196						j = elem && elem.childNodes.length;
9197						while ( j-- ) {
9198							if ( jQuery1113.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
9199								elem.removeChild( tbody );
9200							}
9201						}
9202					}
9203
9204					jQuery1113.merge( nodes, tmp.childNodes );
9205
9206					// Fix #12392 for WebKit and IE > 9
9207					tmp.textContent = "";
9208
9209					// Fix #12392 for oldIE
9210					while ( tmp.firstChild ) {
9211						tmp.removeChild( tmp.firstChild );
9212					}
9213
9214					// Remember the top-level container for proper cleanup
9215					tmp = safe.lastChild;
9216				}
9217			}
9218		}
9219
9220		// Fix #11356: Clear elements from fragment
9221		if ( tmp ) {
9222			safe.removeChild( tmp );
9223		}
9224
9225		// Reset defaultChecked for any radios and checkboxes
9226		// about to be appended to the DOM in IE 6/7 (#8060)
9227		if ( !support.appendChecked ) {
9228			jQuery1113.grep( getAll( nodes, "input" ), fixDefaultChecked );
9229		}
9230
9231		i = 0;
9232		while ( (elem = nodes[ i++ ]) ) {
9233
9234			// #4087 - If origin and destination elements are the same, and this is
9235			// that element, do not do anything
9236			if ( selection && jQuery1113.inArray( elem, selection ) !== -1 ) {
9237				continue;
9238			}
9239
9240			contains = jQuery1113.contains( elem.ownerDocument, elem );
9241
9242			// Append to fragment
9243			tmp = getAll( safe.appendChild( elem ), "script" );
9244
9245			// Preserve script evaluation history
9246			if ( contains ) {
9247				setGlobalEval( tmp );
9248			}
9249
9250			// Capture executables
9251			if ( scripts ) {
9252				j = 0;
9253				while ( (elem = tmp[ j++ ]) ) {
9254					if ( rscriptType.test( elem.type || "" ) ) {
9255						scripts.push( elem );
9256					}
9257				}
9258			}
9259		}
9260
9261		tmp = null;
9262
9263		return safe;
9264	},
9265
9266	cleanData: function( elems, /* internal */ acceptData ) {
9267		var elem, type, id, data,
9268			i = 0,
9269			internalKey = jQuery1113.expando,
9270			cache = jQuery1113.cache,
9271			deleteExpando = support.deleteExpando,
9272			special = jQuery1113.event.special;
9273
9274		for ( ; (elem = elems[i]) != null; i++ ) {
9275			if ( acceptData || jQuery1113.acceptData( elem ) ) {
9276
9277				id = elem[ internalKey ];
9278				data = id && cache[ id ];
9279
9280				if ( data ) {
9281					if ( data.events ) {
9282						for ( type in data.events ) {
9283							if ( special[ type ] ) {
9284								jQuery1113.event.remove( elem, type );
9285
9286							// This is a shortcut to avoid jQuery1113.event.remove's overhead
9287							} else {
9288								jQuery1113.removeEvent( elem, type, data.handle );
9289							}
9290						}
9291					}
9292
9293					// Remove cache only if it was not already removed by jQuery1113.event.remove
9294					if ( cache[ id ] ) {
9295
9296						delete cache[ id ];
9297
9298						// IE does not allow us to delete expando properties from nodes,
9299						// nor does it have a removeAttribute function on Document nodes;
9300						// we must handle all of these cases
9301						if ( deleteExpando ) {
9302							delete elem[ internalKey ];
9303
9304						} else if ( typeof elem.removeAttribute !== strundefined ) {
9305							elem.removeAttribute( internalKey );
9306
9307						} else {
9308							elem[ internalKey ] = null;
9309						}
9310
9311						deletedIds.push( id );
9312					}
9313				}
9314			}
9315		}
9316	}
9317});
9318
9319jQuery1113.fn.extend({
9320	text: function( value ) {
9321		return access( this, function( value ) {
9322			return value === undefined ?
9323				jQuery1113.text( this ) :
9324				this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
9325		}, null, value, arguments.length );
9326	},
9327
9328	append: function() {
9329		return this.domManip( arguments, function( elem ) {
9330			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
9331				var target = manipulationTarget( this, elem );
9332				target.appendChild( elem );
9333			}
9334		});
9335	},
9336
9337	prepend: function() {
9338		return this.domManip( arguments, function( elem ) {
9339			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
9340				var target = manipulationTarget( this, elem );
9341				target.insertBefore( elem, target.firstChild );
9342			}
9343		});
9344	},
9345
9346	before: function() {
9347		return this.domManip( arguments, function( elem ) {
9348			if ( this.parentNode ) {
9349				this.parentNode.insertBefore( elem, this );
9350			}
9351		});
9352	},
9353
9354	after: function() {
9355		return this.domManip( arguments, function( elem ) {
9356			if ( this.parentNode ) {
9357				this.parentNode.insertBefore( elem, this.nextSibling );
9358			}
9359		});
9360	},
9361
9362	remove: function( selector, keepData /* Internal Use Only */ ) {
9363		var elem,
9364			elems = selector ? jQuery1113.filter( selector, this ) : this,
9365			i = 0;
9366
9367		for ( ; (elem = elems[i]) != null; i++ ) {
9368
9369			if ( !keepData && elem.nodeType === 1 ) {
9370				jQuery1113.cleanData( getAll( elem ) );
9371			}
9372
9373			if ( elem.parentNode ) {
9374				if ( keepData && jQuery1113.contains( elem.ownerDocument, elem ) ) {
9375					setGlobalEval( getAll( elem, "script" ) );
9376				}
9377				elem.parentNode.removeChild( elem );
9378			}
9379		}
9380
9381		return this;
9382	},
9383
9384	empty: function() {
9385		var elem,
9386			i = 0;
9387
9388		for ( ; (elem = this[i]) != null; i++ ) {
9389			// Remove element nodes and prevent memory leaks
9390			if ( elem.nodeType === 1 ) {
9391				jQuery1113.cleanData( getAll( elem, false ) );
9392			}
9393
9394			// Remove any remaining nodes
9395			while ( elem.firstChild ) {
9396				elem.removeChild( elem.firstChild );
9397			}
9398
9399			// If this is a select, ensure that it displays empty (#12336)
9400			// Support: IE<9
9401			if ( elem.options && jQuery1113.nodeName( elem, "select" ) ) {
9402				elem.options.length = 0;
9403			}
9404		}
9405
9406		return this;
9407	},
9408
9409	clone: function( dataAndEvents, deepDataAndEvents ) {
9410		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
9411		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
9412
9413		return this.map(function() {
9414			return jQuery1113.clone( this, dataAndEvents, deepDataAndEvents );
9415		});
9416	},
9417
9418	html: function( value ) {
9419		return access( this, function( value ) {
9420			var elem = this[ 0 ] || {},
9421				i = 0,
9422				l = this.length;
9423
9424			if ( value === undefined ) {
9425				return elem.nodeType === 1 ?
9426					elem.innerHTML.replace( rinlinejQuery1113, "" ) :
9427					undefined;
9428			}
9429
9430			// See if we can take a shortcut and just use innerHTML
9431			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
9432				( support.htmlSerialize || !rnoshimcache.test( value )  ) &&
9433				( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
9434				!wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
9435
9436				value = value.replace( rxhtmlTag, "<$1></$2>" );
9437
9438				try {
9439					for (; i < l; i++ ) {
9440						// Remove element nodes and prevent memory leaks
9441						elem = this[i] || {};
9442						if ( elem.nodeType === 1 ) {
9443							jQuery1113.cleanData( getAll( elem, false ) );
9444							elem.innerHTML = value;
9445						}
9446					}
9447
9448					elem = 0;
9449
9450				// If using innerHTML throws an exception, use the fallback method
9451				} catch(e) {}
9452			}
9453
9454			if ( elem ) {
9455				this.empty().append( value );
9456			}
9457		}, null, value, arguments.length );
9458	},
9459
9460	replaceWith: function() {
9461		var arg = arguments[ 0 ];
9462
9463		// Make the changes, replacing each context element with the new content
9464		this.domManip( arguments, function( elem ) {
9465			arg = this.parentNode;
9466
9467			jQuery1113.cleanData( getAll( this ) );
9468
9469			if ( arg ) {
9470				arg.replaceChild( elem, this );
9471			}
9472		});
9473
9474		// Force removal if there was no new content (e.g., from empty arguments)
9475		return arg && (arg.length || arg.nodeType) ? this : this.remove();
9476	},
9477
9478	detach: function( selector ) {
9479		return this.remove( selector, true );
9480	},
9481
9482	domManip: function( args, callback ) {
9483
9484		// Flatten any nested arrays
9485		args = concat.apply( [], args );
9486
9487		var first, node, hasScripts,
9488			scripts, doc, fragment,
9489			i = 0,
9490			l = this.length,
9491			set = this,
9492			iNoClone = l - 1,
9493			value = args[0],
9494			isFunction = jQuery1113.isFunction( value );
9495
9496		// We can't cloneNode fragments that contain checked, in WebKit
9497		if ( isFunction ||
9498				( l > 1 && typeof value === "string" &&
9499					!support.checkClone && rchecked.test( value ) ) ) {
9500			return this.each(function( index ) {
9501				var self = set.eq( index );
9502				if ( isFunction ) {
9503					args[0] = value.call( this, index, self.html() );
9504				}
9505				self.domManip( args, callback );
9506			});
9507		}
9508
9509		if ( l ) {
9510			fragment = jQuery1113.buildFragment( args, this[ 0 ].ownerDocument, false, this );
9511			first = fragment.firstChild;
9512
9513			if ( fragment.childNodes.length === 1 ) {
9514				fragment = first;
9515			}
9516
9517			if ( first ) {
9518				scripts = jQuery1113.map( getAll( fragment, "script" ), disableScript );
9519				hasScripts = scripts.length;
9520
9521				// Use the original fragment for the last item instead of the first because it can end up
9522				// being emptied incorrectly in certain situations (#8070).
9523				for ( ; i < l; i++ ) {
9524					node = fragment;
9525
9526					if ( i !== iNoClone ) {
9527						node = jQuery1113.clone( node, true, true );
9528
9529						// Keep references to cloned scripts for later restoration
9530						if ( hasScripts ) {
9531							jQuery1113.merge( scripts, getAll( node, "script" ) );
9532						}
9533					}
9534
9535					callback.call( this[i], node, i );
9536				}
9537
9538				if ( hasScripts ) {
9539					doc = scripts[ scripts.length - 1 ].ownerDocument;
9540
9541					// Reenable scripts
9542					jQuery1113.map( scripts, restoreScript );
9543
9544					// Evaluate executable scripts on first document insertion
9545					for ( i = 0; i < hasScripts; i++ ) {
9546						node = scripts[ i ];
9547						if ( rscriptType.test( node.type || "" ) &&
9548							!jQuery1113._data( node, "globalEval" ) && jQuery1113.contains( doc, node ) ) {
9549
9550							if ( node.src ) {
9551								// Optional AJAX dependency, but won't run scripts if not present
9552								if ( jQuery1113._evalUrl ) {
9553									jQuery1113._evalUrl( node.src );
9554								}
9555							} else {
9556								jQuery1113.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
9557							}
9558						}
9559					}
9560				}
9561
9562				// Fix #11809: Avoid leaking memory
9563				fragment = first = null;
9564			}
9565		}
9566
9567		return this;
9568	}
9569});
9570
9571jQuery1113.each({
9572	appendTo: "append",
9573	prependTo: "prepend",
9574	insertBefore: "before",
9575	insertAfter: "after",
9576	replaceAll: "replaceWith"
9577}, function( name, original ) {
9578	jQuery1113.fn[ name ] = function( selector ) {
9579		var elems,
9580			i = 0,
9581			ret = [],
9582			insert = jQuery1113( selector ),
9583			last = insert.length - 1;
9584
9585		for ( ; i <= last; i++ ) {
9586			elems = i === last ? this : this.clone(true);
9587			jQuery1113( insert[i] )[ original ]( elems );
9588
9589			// Modern browsers can apply jQuery1113 collections as arrays, but oldIE needs a .get()
9590			push.apply( ret, elems.get() );
9591		}
9592
9593		return this.pushStack( ret );
9594	};
9595});
9596
9597
9598var iframe,
9599	elemdisplay = {};
9600
9601/**
9602 * Retrieve the actual display of a element
9603 * @param {String} name nodeName of the element
9604 * @param {Object} doc Document object
9605 */
9606// Called only from within defaultDisplay
9607function actualDisplay( name, doc ) {
9608	var style,
9609		elem = jQuery1113( doc.createElement( name ) ).appendTo( doc.body ),
9610
9611		// getDefaultComputedStyle might be reliably used only on attached element
9612		display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
9613
9614			// Use of this method is a temporary fix (more like optmization) until something better comes along,
9615			// since it was removed from specification and supported only in FF
9616			style.display : jQuery1113.css( elem[ 0 ], "display" );
9617
9618	// We don't have any data stored on the element,
9619	// so use "detach" method as fast way to get rid of the element
9620	elem.detach();
9621
9622	return display;
9623}
9624
9625/**
9626 * Try to determine the default display value of an element
9627 * @param {String} nodeName
9628 */
9629function defaultDisplay( nodeName ) {
9630	var doc = document,
9631		display = elemdisplay[ nodeName ];
9632
9633	if ( !display ) {
9634		display = actualDisplay( nodeName, doc );
9635
9636		// If the simple way fails, read from inside an iframe
9637		if ( display === "none" || !display ) {
9638
9639			// Use the already-created iframe if possible
9640			iframe = (iframe || jQuery1113( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
9641
9642			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
9643			doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
9644
9645			// Support: IE
9646			doc.write();
9647			doc.close();
9648
9649			display = actualDisplay( nodeName, doc );
9650			iframe.detach();
9651		}
9652
9653		// Store the correct default display
9654		elemdisplay[ nodeName ] = display;
9655	}
9656
9657	return display;
9658}
9659
9660
9661(function() {
9662	var shrinkWrapBlocksVal;
9663
9664	support.shrinkWrapBlocks = function() {
9665		if ( shrinkWrapBlocksVal != null ) {
9666			return shrinkWrapBlocksVal;
9667		}
9668
9669		// Will be changed later if needed.
9670		shrinkWrapBlocksVal = false;
9671
9672		// Minified: var b,c,d
9673		var div, body, container;
9674
9675		body = document.getElementsByTagName( "body" )[ 0 ];
9676		if ( !body || !body.style ) {
9677			// Test fired too early or in an unsupported environment, exit.
9678			return;
9679		}
9680
9681		// Setup
9682		div = document.createElement( "div" );
9683		container = document.createElement( "div" );
9684		container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
9685		body.appendChild( container ).appendChild( div );
9686
9687		// Support: IE6
9688		// Check if elements with layout shrink-wrap their children
9689		if ( typeof div.style.zoom !== strundefined ) {
9690			// Reset CSS: box-sizing; display; margin; border
9691			div.style.cssText =
9692				// Support: Firefox<29, Android 2.3
9693				// Vendor-prefix box-sizing
9694				"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
9695				"box-sizing:content-box;display:block;margin:0;border:0;" +
9696				"padding:1px;width:1px;zoom:1";
9697			div.appendChild( document.createElement( "div" ) ).style.width = "5px";
9698			shrinkWrapBlocksVal = div.offsetWidth !== 3;
9699		}
9700
9701		body.removeChild( container );
9702
9703		return shrinkWrapBlocksVal;
9704	};
9705
9706})();
9707var rmargin = (/^margin/);
9708
9709var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
9710
9711
9712
9713var getStyles, curCSS,
9714	rposition = /^(top|right|bottom|left)$/;
9715
9716if ( window.getComputedStyle ) {
9717	getStyles = function( elem ) {
9718		// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
9719		// IE throws on elements created in popups
9720		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
9721		if ( elem.ownerDocument.defaultView.opener ) {
9722			return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
9723		}
9724
9725		return window.getComputedStyle( elem, null );
9726	};
9727
9728	curCSS = function( elem, name, computed ) {
9729		var width, minWidth, maxWidth, ret,
9730			style = elem.style;
9731
9732		computed = computed || getStyles( elem );
9733
9734		// getPropertyValue is only needed for .css('filter') in IE9, see #12537
9735		ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
9736
9737		if ( computed ) {
9738
9739			if ( ret === "" && !jQuery1113.contains( elem.ownerDocument, elem ) ) {
9740				ret = jQuery1113.style( elem, name );
9741			}
9742
9743			// A tribute to the "awesome hack by Dean Edwards"
9744			// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
9745			// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
9746			// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
9747			if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
9748
9749				// Remember the original values
9750				width = style.width;
9751				minWidth = style.minWidth;
9752				maxWidth = style.maxWidth;
9753
9754				// Put in the new values to get a computed value out
9755				style.minWidth = style.maxWidth = style.width = ret;
9756				ret = computed.width;
9757
9758				// Revert the changed values
9759				style.width = width;
9760				style.minWidth = minWidth;
9761				style.maxWidth = maxWidth;
9762			}
9763		}
9764
9765		// Support: IE
9766		// IE returns zIndex value as an integer.
9767		return ret === undefined ?
9768			ret :
9769			ret + "";
9770	};
9771} else if ( document.documentElement.currentStyle ) {
9772	getStyles = function( elem ) {
9773		return elem.currentStyle;
9774	};
9775
9776	curCSS = function( elem, name, computed ) {
9777		var left, rs, rsLeft, ret,
9778			style = elem.style;
9779
9780		computed = computed || getStyles( elem );
9781		ret = computed ? computed[ name ] : undefined;
9782
9783		// Avoid setting ret to empty string here
9784		// so we don't default to auto
9785		if ( ret == null && style && style[ name ] ) {
9786			ret = style[ name ];
9787		}
9788
9789		// From the awesome hack by Dean Edwards
9790		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
9791
9792		// If we're not dealing with a regular pixel number
9793		// but a number that has a weird ending, we need to convert it to pixels
9794		// but not position css attributes, as those are proportional to the parent element instead
9795		// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
9796		if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
9797
9798			// Remember the original values
9799			left = style.left;
9800			rs = elem.runtimeStyle;
9801			rsLeft = rs && rs.left;
9802
9803			// Put in the new values to get a computed value out
9804			if ( rsLeft ) {
9805				rs.left = elem.currentStyle.left;
9806			}
9807			style.left = name === "fontSize" ? "1em" : ret;
9808			ret = style.pixelLeft + "px";
9809
9810			// Revert the changed values
9811			style.left = left;
9812			if ( rsLeft ) {
9813				rs.left = rsLeft;
9814			}
9815		}
9816
9817		// Support: IE
9818		// IE returns zIndex value as an integer.
9819		return ret === undefined ?
9820			ret :
9821			ret + "" || "auto";
9822	};
9823}
9824
9825
9826
9827
9828function addGetHookIf( conditionFn, hookFn ) {
9829	// Define the hook, we'll check on the first run if it's really needed.
9830	return {
9831		get: function() {
9832			var condition = conditionFn();
9833
9834			if ( condition == null ) {
9835				// The test was not ready at this point; screw the hook this time
9836				// but check again when needed next time.
9837				return;
9838			}
9839
9840			if ( condition ) {
9841				// Hook not needed (or it's not possible to use it due to missing dependency),
9842				// remove it.
9843				// Since there are no other hooks for marginRight, remove the whole object.
9844				delete this.get;
9845				return;
9846			}
9847
9848			// Hook needed; redefine it so that the support test is not executed again.
9849
9850			return (this.get = hookFn).apply( this, arguments );
9851		}
9852	};
9853}
9854
9855
9856(function() {
9857	// Minified: var b,c,d,e,f,g, h,i
9858	var div, style, a, pixelPositionVal, boxSizingReliableVal,
9859		reliableHiddenOffsetsVal, reliableMarginRightVal;
9860
9861	// Setup
9862	div = document.createElement( "div" );
9863	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
9864	a = div.getElementsByTagName( "a" )[ 0 ];
9865	style = a && a.style;
9866
9867	// Finish early in limited (non-browser) environments
9868	if ( !style ) {
9869		return;
9870	}
9871
9872	style.cssText = "float:left;opacity:.5";
9873
9874	// Support: IE<9
9875	// Make sure that element opacity exists (as opposed to filter)
9876	support.opacity = style.opacity === "0.5";
9877
9878	// Verify style float existence
9879	// (IE uses styleFloat instead of cssFloat)
9880	support.cssFloat = !!style.cssFloat;
9881
9882	div.style.backgroundClip = "content-box";
9883	div.cloneNode( true ).style.backgroundClip = "";
9884	support.clearCloneStyle = div.style.backgroundClip === "content-box";
9885
9886	// Support: Firefox<29, Android 2.3
9887	// Vendor-prefix box-sizing
9888	support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
9889		style.WebkitBoxSizing === "";
9890
9891	jQuery1113.extend(support, {
9892		reliableHiddenOffsets: function() {
9893			if ( reliableHiddenOffsetsVal == null ) {
9894				computeStyleTests();
9895			}
9896			return reliableHiddenOffsetsVal;
9897		},
9898
9899		boxSizingReliable: function() {
9900			if ( boxSizingReliableVal == null ) {
9901				computeStyleTests();
9902			}
9903			return boxSizingReliableVal;
9904		},
9905
9906		pixelPosition: function() {
9907			if ( pixelPositionVal == null ) {
9908				computeStyleTests();
9909			}
9910			return pixelPositionVal;
9911		},
9912
9913		// Support: Android 2.3
9914		reliableMarginRight: function() {
9915			if ( reliableMarginRightVal == null ) {
9916				computeStyleTests();
9917			}
9918			return reliableMarginRightVal;
9919		}
9920	});
9921
9922	function computeStyleTests() {
9923		// Minified: var b,c,d,j
9924		var div, body, container, contents;
9925
9926		body = document.getElementsByTagName( "body" )[ 0 ];
9927		if ( !body || !body.style ) {
9928			// Test fired too early or in an unsupported environment, exit.
9929			return;
9930		}
9931
9932		// Setup
9933		div = document.createElement( "div" );
9934		container = document.createElement( "div" );
9935		container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
9936		body.appendChild( container ).appendChild( div );
9937
9938		div.style.cssText =
9939			// Support: Firefox<29, Android 2.3
9940			// Vendor-prefix box-sizing
9941			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
9942			"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
9943			"border:1px;padding:1px;width:4px;position:absolute";
9944
9945		// Support: IE<9
9946		// Assume reasonable values in the absence of getComputedStyle
9947		pixelPositionVal = boxSizingReliableVal = false;
9948		reliableMarginRightVal = true;
9949
9950		// Check for getComputedStyle so that this code is not run in IE<9.
9951		if ( window.getComputedStyle ) {
9952			pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
9953			boxSizingReliableVal =
9954				( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
9955
9956			// Support: Android 2.3
9957			// Div with explicit width and no margin-right incorrectly
9958			// gets computed margin-right based on width of container (#3333)
9959			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
9960			contents = div.appendChild( document.createElement( "div" ) );
9961
9962			// Reset CSS: box-sizing; display; margin; border; padding
9963			contents.style.cssText = div.style.cssText =
9964				// Support: Firefox<29, Android 2.3
9965				// Vendor-prefix box-sizing
9966				"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
9967				"box-sizing:content-box;display:block;margin:0;border:0;padding:0";
9968			contents.style.marginRight = contents.style.width = "0";
9969			div.style.width = "1px";
9970
9971			reliableMarginRightVal =
9972				!parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
9973
9974			div.removeChild( contents );
9975		}
9976
9977		// Support: IE8
9978		// Check if table cells still have offsetWidth/Height when they are set
9979		// to display:none and there are still other visible table cells in a
9980		// table row; if so, offsetWidth/Height are not reliable for use when
9981		// determining if an element has been hidden directly using
9982		// display:none (it is still safe to use offsets if a parent element is
9983		// hidden; don safety goggles and see bug #4512 for more information).
9984		div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
9985		contents = div.getElementsByTagName( "td" );
9986		contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
9987		reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
9988		if ( reliableHiddenOffsetsVal ) {
9989			contents[ 0 ].style.display = "";
9990			contents[ 1 ].style.display = "none";
9991			reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
9992		}
9993
9994		body.removeChild( container );
9995	}
9996
9997})();
9998
9999
10000// A method for quickly swapping in/out CSS properties to get correct calculations.
10001jQuery1113.swap = function( elem, options, callback, args ) {
10002	var ret, name,
10003		old = {};
10004
10005	// Remember the old values, and insert the new ones
10006	for ( name in options ) {
10007		old[ name ] = elem.style[ name ];
10008		elem.style[ name ] = options[ name ];
10009	}
10010
10011	ret = callback.apply( elem, args || [] );
10012
10013	// Revert the old values
10014	for ( name in options ) {
10015		elem.style[ name ] = old[ name ];
10016	}
10017
10018	return ret;
10019};
10020
10021
10022var
10023		ralpha = /alpha\([^)]*\)/i,
10024	ropacity = /opacity\s*=\s*([^)]*)/,
10025
10026	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
10027	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
10028	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
10029	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
10030	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
10031
10032	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
10033	cssNormalTransform = {
10034		letterSpacing: "0",
10035		fontWeight: "400"
10036	},
10037
10038	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
10039
10040
10041// return a css property mapped to a potentially vendor prefixed property
10042function vendorPropName( style, name ) {
10043
10044	// shortcut for names that are not vendor prefixed
10045	if ( name in style ) {
10046		return name;
10047	}
10048
10049	// check for vendor prefixed names
10050	var capName = name.charAt(0).toUpperCase() + name.slice(1),
10051		origName = name,
10052		i = cssPrefixes.length;
10053
10054	while ( i-- ) {
10055		name = cssPrefixes[ i ] + capName;
10056		if ( name in style ) {
10057			return name;
10058		}
10059	}
10060
10061	return origName;
10062}
10063
10064function showHide( elements, show ) {
10065	var display, elem, hidden,
10066		values = [],
10067		index = 0,
10068		length = elements.length;
10069
10070	for ( ; index < length; index++ ) {
10071		elem = elements[ index ];
10072		if ( !elem.style ) {
10073			continue;
10074		}
10075
10076		values[ index ] = jQuery1113._data( elem, "olddisplay" );
10077		display = elem.style.display;
10078		if ( show ) {
10079			// Reset the inline display of this element to learn if it is
10080			// being hidden by cascaded rules or not
10081			if ( !values[ index ] && display === "none" ) {
10082				elem.style.display = "";
10083			}
10084
10085			// Set elements which have been overridden with display: none
10086			// in a stylesheet to whatever the default browser style is
10087			// for such an element
10088			if ( elem.style.display === "" && isHidden( elem ) ) {
10089				values[ index ] = jQuery1113._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
10090			}
10091		} else {
10092			hidden = isHidden( elem );
10093
10094			if ( display && display !== "none" || !hidden ) {
10095				jQuery1113._data( elem, "olddisplay", hidden ? display : jQuery1113.css( elem, "display" ) );
10096			}
10097		}
10098	}
10099
10100	// Set the display of most of the elements in a second loop
10101	// to avoid the constant reflow
10102	for ( index = 0; index < length; index++ ) {
10103		elem = elements[ index ];
10104		if ( !elem.style ) {
10105			continue;
10106		}
10107		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
10108			elem.style.display = show ? values[ index ] || "" : "none";
10109		}
10110	}
10111
10112	return elements;
10113}
10114
10115function setPositiveNumber( elem, value, subtract ) {
10116	var matches = rnumsplit.exec( value );
10117	return matches ?
10118		// Guard against undefined "subtract", e.g., when used as in cssHooks
10119		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
10120		value;
10121}
10122
10123function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
10124	var i = extra === ( isBorderBox ? "border" : "content" ) ?
10125		// If we already have the right measurement, avoid augmentation
10126		4 :
10127		// Otherwise initialize for horizontal or vertical properties
10128		name === "width" ? 1 : 0,
10129
10130		val = 0;
10131
10132	for ( ; i < 4; i += 2 ) {
10133		// both box models exclude margin, so add it if we want it
10134		if ( extra === "margin" ) {
10135			val += jQuery1113.css( elem, extra + cssExpand[ i ], true, styles );
10136		}
10137
10138		if ( isBorderBox ) {
10139			// border-box includes padding, so remove it if we want content
10140			if ( extra === "content" ) {
10141				val -= jQuery1113.css( elem, "padding" + cssExpand[ i ], true, styles );
10142			}
10143
10144			// at this point, extra isn't border nor margin, so remove border
10145			if ( extra !== "margin" ) {
10146				val -= jQuery1113.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
10147			}
10148		} else {
10149			// at this point, extra isn't content, so add padding
10150			val += jQuery1113.css( elem, "padding" + cssExpand[ i ], true, styles );
10151
10152			// at this point, extra isn't content nor padding, so add border
10153			if ( extra !== "padding" ) {
10154				val += jQuery1113.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
10155			}
10156		}
10157	}
10158
10159	return val;
10160}
10161
10162function getWidthOrHeight( elem, name, extra ) {
10163
10164	// Start with offset property, which is equivalent to the border-box value
10165	var valueIsBorderBox = true,
10166		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
10167		styles = getStyles( elem ),
10168		isBorderBox = support.boxSizing && jQuery1113.css( elem, "boxSizing", false, styles ) === "border-box";
10169
10170	// some non-html elements return undefined for offsetWidth, so check for null/undefined
10171	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
10172	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
10173	if ( val <= 0 || val == null ) {
10174		// Fall back to computed then uncomputed css if necessary
10175		val = curCSS( elem, name, styles );
10176		if ( val < 0 || val == null ) {
10177			val = elem.style[ name ];
10178		}
10179
10180		// Computed unit is not pixels. Stop here and return.
10181		if ( rnumnonpx.test(val) ) {
10182			return val;
10183		}
10184
10185		// we need the check for style in case a browser which returns unreliable values
10186		// for getComputedStyle silently falls back to the reliable elem.style
10187		valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
10188
10189		// Normalize "", auto, and prepare for extra
10190		val = parseFloat( val ) || 0;
10191	}
10192
10193	// use the active box-sizing model to add/subtract irrelevant styles
10194	return ( val +
10195		augmentWidthOrHeight(
10196			elem,
10197			name,
10198			extra || ( isBorderBox ? "border" : "content" ),
10199			valueIsBorderBox,
10200			styles
10201		)
10202	) + "px";
10203}
10204
10205jQuery1113.extend({
10206	// Add in style property hooks for overriding the default
10207	// behavior of getting and setting a style property
10208	cssHooks: {
10209		opacity: {
10210			get: function( elem, computed ) {
10211				if ( computed ) {
10212					// We should always get a number back from opacity
10213					var ret = curCSS( elem, "opacity" );
10214					return ret === "" ? "1" : ret;
10215				}
10216			}
10217		}
10218	},
10219
10220	// Don't automatically add "px" to these possibly-unitless properties
10221	cssNumber: {
10222		"columnCount": true,
10223		"fillOpacity": true,
10224		"flexGrow": true,
10225		"flexShrink": true,
10226		"fontWeight": true,
10227		"lineHeight": true,
10228		"opacity": true,
10229		"order": true,
10230		"orphans": true,
10231		"widows": true,
10232		"zIndex": true,
10233		"zoom": true
10234	},
10235
10236	// Add in properties whose names you wish to fix before
10237	// setting or getting the value
10238	cssProps: {
10239		// normalize float css property
10240		"float": support.cssFloat ? "cssFloat" : "styleFloat"
10241	},
10242
10243	// Get and set the style property on a DOM Node
10244	style: function( elem, name, value, extra ) {
10245		// Don't set styles on text and comment nodes
10246		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
10247			return;
10248		}
10249
10250		// Make sure that we're working with the right name
10251		var ret, type, hooks,
10252			origName = jQuery1113.camelCase( name ),
10253			style = elem.style;
10254
10255		name = jQuery1113.cssProps[ origName ] || ( jQuery1113.cssProps[ origName ] = vendorPropName( style, origName ) );
10256
10257		// gets hook for the prefixed version
10258		// followed by the unprefixed version
10259		hooks = jQuery1113.cssHooks[ name ] || jQuery1113.cssHooks[ origName ];
10260
10261		// Check if we're setting a value
10262		if ( value !== undefined ) {
10263			type = typeof value;
10264
10265			// convert relative number strings (+= or -=) to relative numbers. #7345
10266			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
10267				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery1113.css( elem, name ) );
10268				// Fixes bug #9237
10269				type = "number";
10270			}
10271
10272			// Make sure that null and NaN values aren't set. See: #7116
10273			if ( value == null || value !== value ) {
10274				return;
10275			}
10276
10277			// If a number was passed in, add 'px' to the (except for certain CSS properties)
10278			if ( type === "number" && !jQuery1113.cssNumber[ origName ] ) {
10279				value += "px";
10280			}
10281
10282			// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
10283			// but it would mean to define eight (for every problematic property) identical functions
10284			if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
10285				style[ name ] = "inherit";
10286			}
10287
10288			// If a hook was provided, use that value, otherwise just set the specified value
10289			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
10290
10291				// Support: IE
10292				// Swallow errors from 'invalid' CSS values (#5509)
10293				try {
10294					style[ name ] = value;
10295				} catch(e) {}
10296			}
10297
10298		} else {
10299			// If a hook was provided get the non-computed value from there
10300			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
10301				return ret;
10302			}
10303
10304			// Otherwise just get the value from the style object
10305			return style[ name ];
10306		}
10307	},
10308
10309	css: function( elem, name, extra, styles ) {
10310		var num, val, hooks,
10311			origName = jQuery1113.camelCase( name );
10312
10313		// Make sure that we're working with the right name
10314		name = jQuery1113.cssProps[ origName ] || ( jQuery1113.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
10315
10316		// gets hook for the prefixed version
10317		// followed by the unprefixed version
10318		hooks = jQuery1113.cssHooks[ name ] || jQuery1113.cssHooks[ origName ];
10319
10320		// If a hook was provided get the computed value from there
10321		if ( hooks && "get" in hooks ) {
10322			val = hooks.get( elem, true, extra );
10323		}
10324
10325		// Otherwise, if a way to get the computed value exists, use that
10326		if ( val === undefined ) {
10327			val = curCSS( elem, name, styles );
10328		}
10329
10330		//convert "normal" to computed value
10331		if ( val === "normal" && name in cssNormalTransform ) {
10332			val = cssNormalTransform[ name ];
10333		}
10334
10335		// Return, converting to number if forced or a qualifier was provided and val looks numeric
10336		if ( extra === "" || extra ) {
10337			num = parseFloat( val );
10338			return extra === true || jQuery1113.isNumeric( num ) ? num || 0 : val;
10339		}
10340		return val;
10341	}
10342});
10343
10344jQuery1113.each([ "height", "width" ], function( i, name ) {
10345	jQuery1113.cssHooks[ name ] = {
10346		get: function( elem, computed, extra ) {
10347			if ( computed ) {
10348				// certain elements can have dimension info if we invisibly show them
10349				// however, it must have a current display style that would benefit from this
10350				return rdisplayswap.test( jQuery1113.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
10351					jQuery1113.swap( elem, cssShow, function() {
10352						return getWidthOrHeight( elem, name, extra );
10353					}) :
10354					getWidthOrHeight( elem, name, extra );
10355			}
10356		},
10357
10358		set: function( elem, value, extra ) {
10359			var styles = extra && getStyles( elem );
10360			return setPositiveNumber( elem, value, extra ?
10361				augmentWidthOrHeight(
10362					elem,
10363					name,
10364					extra,
10365					support.boxSizing && jQuery1113.css( elem, "boxSizing", false, styles ) === "border-box",
10366					styles
10367				) : 0
10368			);
10369		}
10370	};
10371});
10372
10373if ( !support.opacity ) {
10374	jQuery1113.cssHooks.opacity = {
10375		get: function( elem, computed ) {
10376			// IE uses filters for opacity
10377			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
10378				( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
10379				computed ? "1" : "";
10380		},
10381
10382		set: function( elem, value ) {
10383			var style = elem.style,
10384				currentStyle = elem.currentStyle,
10385				opacity = jQuery1113.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
10386				filter = currentStyle && currentStyle.filter || style.filter || "";
10387
10388			// IE has trouble with opacity if it does not have layout
10389			// Force it by setting the zoom level
10390			style.zoom = 1;
10391
10392			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
10393			// if value === "", then remove inline opacity #12685
10394			if ( ( value >= 1 || value === "" ) &&
10395					jQuery1113.trim( filter.replace( ralpha, "" ) ) === "" &&
10396					style.removeAttribute ) {
10397
10398				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
10399				// if "filter:" is present at all, clearType is disabled, we want to avoid this
10400				// style.removeAttribute is IE Only, but so apparently is this code path...
10401				style.removeAttribute( "filter" );
10402
10403				// if there is no filter style applied in a css rule or unset inline opacity, we are done
10404				if ( value === "" || currentStyle && !currentStyle.filter ) {
10405					return;
10406				}
10407			}
10408
10409			// otherwise, set new filter values
10410			style.filter = ralpha.test( filter ) ?
10411				filter.replace( ralpha, opacity ) :
10412				filter + " " + opacity;
10413		}
10414	};
10415}
10416
10417jQuery1113.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
10418	function( elem, computed ) {
10419		if ( computed ) {
10420			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
10421			// Work around by temporarily setting element display to inline-block
10422			return jQuery1113.swap( elem, { "display": "inline-block" },
10423				curCSS, [ elem, "marginRight" ] );
10424		}
10425	}
10426);
10427
10428// These hooks are used by animate to expand properties
10429jQuery1113.each({
10430	margin: "",
10431	padding: "",
10432	border: "Width"
10433}, function( prefix, suffix ) {
10434	jQuery1113.cssHooks[ prefix + suffix ] = {
10435		expand: function( value ) {
10436			var i = 0,
10437				expanded = {},
10438
10439				// assumes a single number if not a string
10440				parts = typeof value === "string" ? value.split(" ") : [ value ];
10441
10442			for ( ; i < 4; i++ ) {
10443				expanded[ prefix + cssExpand[ i ] + suffix ] =
10444					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
10445			}
10446
10447			return expanded;
10448		}
10449	};
10450
10451	if ( !rmargin.test( prefix ) ) {
10452		jQuery1113.cssHooks[ prefix + suffix ].set = setPositiveNumber;
10453	}
10454});
10455
10456jQuery1113.fn.extend({
10457	css: function( name, value ) {
10458		return access( this, function( elem, name, value ) {
10459			var styles, len,
10460				map = {},
10461				i = 0;
10462
10463			if ( jQuery1113.isArray( name ) ) {
10464				styles = getStyles( elem );
10465				len = name.length;
10466
10467				for ( ; i < len; i++ ) {
10468					map[ name[ i ] ] = jQuery1113.css( elem, name[ i ], false, styles );
10469				}
10470
10471				return map;
10472			}
10473
10474			return value !== undefined ?
10475				jQuery1113.style( elem, name, value ) :
10476				jQuery1113.css( elem, name );
10477		}, name, value, arguments.length > 1 );
10478	},
10479	show: function() {
10480		return showHide( this, true );
10481	},
10482	hide: function() {
10483		return showHide( this );
10484	},
10485	toggle: function( state ) {
10486		if ( typeof state === "boolean" ) {
10487			return state ? this.show() : this.hide();
10488		}
10489
10490		return this.each(function() {
10491			if ( isHidden( this ) ) {
10492				jQuery1113( this ).show();
10493			} else {
10494				jQuery1113( this ).hide();
10495			}
10496		});
10497	}
10498});
10499
10500
10501function Tween( elem, options, prop, end, easing ) {
10502	return new Tween.prototype.init( elem, options, prop, end, easing );
10503}
10504jQuery1113.Tween = Tween;
10505
10506Tween.prototype = {
10507	constructor: Tween,
10508	init: function( elem, options, prop, end, easing, unit ) {
10509		this.elem = elem;
10510		this.prop = prop;
10511		this.easing = easing || "swing";
10512		this.options = options;
10513		this.start = this.now = this.cur();
10514		this.end = end;
10515		this.unit = unit || ( jQuery1113.cssNumber[ prop ] ? "" : "px" );
10516	},
10517	cur: function() {
10518		var hooks = Tween.propHooks[ this.prop ];
10519
10520		return hooks && hooks.get ?
10521			hooks.get( this ) :
10522			Tween.propHooks._default.get( this );
10523	},
10524	run: function( percent ) {
10525		var eased,
10526			hooks = Tween.propHooks[ this.prop ];
10527
10528		if ( this.options.duration ) {
10529			this.pos = eased = jQuery1113.easing[ this.easing ](
10530				percent, this.options.duration * percent, 0, 1, this.options.duration
10531			);
10532		} else {
10533			this.pos = eased = percent;
10534		}
10535		this.now = ( this.end - this.start ) * eased + this.start;
10536
10537		if ( this.options.step ) {
10538			this.options.step.call( this.elem, this.now, this );
10539		}
10540
10541		if ( hooks && hooks.set ) {
10542			hooks.set( this );
10543		} else {
10544			Tween.propHooks._default.set( this );
10545		}
10546		return this;
10547	}
10548};
10549
10550Tween.prototype.init.prototype = Tween.prototype;
10551
10552Tween.propHooks = {
10553	_default: {
10554		get: function( tween ) {
10555			var result;
10556
10557			if ( tween.elem[ tween.prop ] != null &&
10558				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
10559				return tween.elem[ tween.prop ];
10560			}
10561
10562			// passing an empty string as a 3rd parameter to .css will automatically
10563			// attempt a parseFloat and fallback to a string if the parse fails
10564			// so, simple values such as "10px" are parsed to Float.
10565			// complex values such as "rotate(1rad)" are returned as is.
10566			result = jQuery1113.css( tween.elem, tween.prop, "" );
10567			// Empty strings, null, undefined and "auto" are converted to 0.
10568			return !result || result === "auto" ? 0 : result;
10569		},
10570		set: function( tween ) {
10571			// use step hook for back compat - use cssHook if its there - use .style if its
10572			// available and use plain properties where available
10573			if ( jQuery1113.fx.step[ tween.prop ] ) {
10574				jQuery1113.fx.step[ tween.prop ]( tween );
10575			} else if ( tween.elem.style && ( tween.elem.style[ jQuery1113.cssProps[ tween.prop ] ] != null || jQuery1113.cssHooks[ tween.prop ] ) ) {
10576				jQuery1113.style( tween.elem, tween.prop, tween.now + tween.unit );
10577			} else {
10578				tween.elem[ tween.prop ] = tween.now;
10579			}
10580		}
10581	}
10582};
10583
10584// Support: IE <=9
10585// Panic based approach to setting things on disconnected nodes
10586
10587Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
10588	set: function( tween ) {
10589		if ( tween.elem.nodeType && tween.elem.parentNode ) {
10590			tween.elem[ tween.prop ] = tween.now;
10591		}
10592	}
10593};
10594
10595jQuery1113.easing = {
10596	linear: function( p ) {
10597		return p;
10598	},
10599	swing: function( p ) {
10600		return 0.5 - Math.cos( p * Math.PI ) / 2;
10601	}
10602};
10603
10604jQuery1113.fx = Tween.prototype.init;
10605
10606// Back Compat <1.8 extension point
10607jQuery1113.fx.step = {};
10608
10609
10610
10611
10612var
10613	fxNow, timerId,
10614	rfxtypes = /^(?:toggle|show|hide)$/,
10615	rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
10616	rrun = /queueHooks$/,
10617	animationPrefilters = [ defaultPrefilter ],
10618	tweeners = {
10619		"*": [ function( prop, value ) {
10620			var tween = this.createTween( prop, value ),
10621				target = tween.cur(),
10622				parts = rfxnum.exec( value ),
10623				unit = parts && parts[ 3 ] || ( jQuery1113.cssNumber[ prop ] ? "" : "px" ),
10624
10625				// Starting value computation is required for potential unit mismatches
10626				start = ( jQuery1113.cssNumber[ prop ] || unit !== "px" && +target ) &&
10627					rfxnum.exec( jQuery1113.css( tween.elem, prop ) ),
10628				scale = 1,
10629				maxIterations = 20;
10630
10631			if ( start && start[ 3 ] !== unit ) {
10632				// Trust units reported by jQuery1113.css
10633				unit = unit || start[ 3 ];
10634
10635				// Make sure we update the tween properties later on
10636				parts = parts || [];
10637
10638				// Iteratively approximate from a nonzero starting point
10639				start = +target || 1;
10640
10641				do {
10642					// If previous iteration zeroed out, double until we get *something*
10643					// Use a string for doubling factor so we don't accidentally see scale as unchanged below
10644					scale = scale || ".5";
10645
10646					// Adjust and apply
10647					start = start / scale;
10648					jQuery1113.style( tween.elem, prop, start + unit );
10649
10650				// Update scale, tolerating zero or NaN from tween.cur()
10651				// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
10652				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
10653			}
10654
10655			// Update tween properties
10656			if ( parts ) {
10657				start = tween.start = +start || +target || 0;
10658				tween.unit = unit;
10659				// If a +=/-= token was provided, we're doing a relative animation
10660				tween.end = parts[ 1 ] ?
10661					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
10662					+parts[ 2 ];
10663			}
10664
10665			return tween;
10666		} ]
10667	};
10668
10669// Animations created synchronously will run synchronously
10670function createFxNow() {
10671	setTimeout(function() {
10672		fxNow = undefined;
10673	});
10674	return ( fxNow = jQuery1113.now() );
10675}
10676
10677// Generate parameters to create a standard animation
10678function genFx( type, includeWidth ) {
10679	var which,
10680		attrs = { height: type },
10681		i = 0;
10682
10683	// if we include width, step value is 1 to do all cssExpand values,
10684	// if we don't include width, step value is 2 to skip over Left and Right
10685	includeWidth = includeWidth ? 1 : 0;
10686	for ( ; i < 4 ; i += 2 - includeWidth ) {
10687		which = cssExpand[ i ];
10688		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
10689	}
10690
10691	if ( includeWidth ) {
10692		attrs.opacity = attrs.width = type;
10693	}
10694
10695	return attrs;
10696}
10697
10698function createTween( value, prop, animation ) {
10699	var tween,
10700		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
10701		index = 0,
10702		length = collection.length;
10703	for ( ; index < length; index++ ) {
10704		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
10705
10706			// we're done with this property
10707			return tween;
10708		}
10709	}
10710}
10711
10712function defaultPrefilter( elem, props, opts ) {
10713	/* jshint validthis: true */
10714	var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
10715		anim = this,
10716		orig = {},
10717		style = elem.style,
10718		hidden = elem.nodeType && isHidden( elem ),
10719		dataShow = jQuery1113._data( elem, "fxshow" );
10720
10721	// handle queue: false promises
10722	if ( !opts.queue ) {
10723		hooks = jQuery1113._queueHooks( elem, "fx" );
10724		if ( hooks.unqueued == null ) {
10725			hooks.unqueued = 0;
10726			oldfire = hooks.empty.fire;
10727			hooks.empty.fire = function() {
10728				if ( !hooks.unqueued ) {
10729					oldfire();
10730				}
10731			};
10732		}
10733		hooks.unqueued++;
10734
10735		anim.always(function() {
10736			// doing this makes sure that the complete handler will be called
10737			// before this completes
10738			anim.always(function() {
10739				hooks.unqueued--;
10740				if ( !jQuery1113.queue( elem, "fx" ).length ) {
10741					hooks.empty.fire();
10742				}
10743			});
10744		});
10745	}
10746
10747	// height/width overflow pass
10748	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
10749		// Make sure that nothing sneaks out
10750		// Record all 3 overflow attributes because IE does not
10751		// change the overflow attribute when overflowX and
10752		// overflowY are set to the same value
10753		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
10754
10755		// Set display property to inline-block for height/width
10756		// animations on inline elements that are having width/height animated
10757		display = jQuery1113.css( elem, "display" );
10758
10759		// Test default display if display is currently "none"
10760		checkDisplay = display === "none" ?
10761			jQuery1113._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
10762
10763		if ( checkDisplay === "inline" && jQuery1113.css( elem, "float" ) === "none" ) {
10764
10765			// inline-level elements accept inline-block;
10766			// block-level elements need to be inline with layout
10767			if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
10768				style.display = "inline-block";
10769			} else {
10770				style.zoom = 1;
10771			}
10772		}
10773	}
10774
10775	if ( opts.overflow ) {
10776		style.overflow = "hidden";
10777		if ( !support.shrinkWrapBlocks() ) {
10778			anim.always(function() {
10779				style.overflow = opts.overflow[ 0 ];
10780				style.overflowX = opts.overflow[ 1 ];
10781				style.overflowY = opts.overflow[ 2 ];
10782			});
10783		}
10784	}
10785
10786	// show/hide pass
10787	for ( prop in props ) {
10788		value = props[ prop ];
10789		if ( rfxtypes.exec( value ) ) {
10790			delete props[ prop ];
10791			toggle = toggle || value === "toggle";
10792			if ( value === ( hidden ? "hide" : "show" ) ) {
10793
10794				// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
10795				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
10796					hidden = true;
10797				} else {
10798					continue;
10799				}
10800			}
10801			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery1113.style( elem, prop );
10802
10803		// Any non-fx value stops us from restoring the original display value
10804		} else {
10805			display = undefined;
10806		}
10807	}
10808
10809	if ( !jQuery1113.isEmptyObject( orig ) ) {
10810		if ( dataShow ) {
10811			if ( "hidden" in dataShow ) {
10812				hidden = dataShow.hidden;
10813			}
10814		} else {
10815			dataShow = jQuery1113._data( elem, "fxshow", {} );
10816		}
10817
10818		// store state if its toggle - enables .stop().toggle() to "reverse"
10819		if ( toggle ) {
10820			dataShow.hidden = !hidden;
10821		}
10822		if ( hidden ) {
10823			jQuery1113( elem ).show();
10824		} else {
10825			anim.done(function() {
10826				jQuery1113( elem ).hide();
10827			});
10828		}
10829		anim.done(function() {
10830			var prop;
10831			jQuery1113._removeData( elem, "fxshow" );
10832			for ( prop in orig ) {
10833				jQuery1113.style( elem, prop, orig[ prop ] );
10834			}
10835		});
10836		for ( prop in orig ) {
10837			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
10838
10839			if ( !( prop in dataShow ) ) {
10840				dataShow[ prop ] = tween.start;
10841				if ( hidden ) {
10842					tween.end = tween.start;
10843					tween.start = prop === "width" || prop === "height" ? 1 : 0;
10844				}
10845			}
10846		}
10847
10848	// If this is a noop like .hide().hide(), restore an overwritten display value
10849	} else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
10850		style.display = display;
10851	}
10852}
10853
10854function propFilter( props, specialEasing ) {
10855	var index, name, easing, value, hooks;
10856
10857	// camelCase, specialEasing and expand cssHook pass
10858	for ( index in props ) {
10859		name = jQuery1113.camelCase( index );
10860		easing = specialEasing[ name ];
10861		value = props[ index ];
10862		if ( jQuery1113.isArray( value ) ) {
10863			easing = value[ 1 ];
10864			value = props[ index ] = value[ 0 ];
10865		}
10866
10867		if ( index !== name ) {
10868			props[ name ] = value;
10869			delete props[ index ];
10870		}
10871
10872		hooks = jQuery1113.cssHooks[ name ];
10873		if ( hooks && "expand" in hooks ) {
10874			value = hooks.expand( value );
10875			delete props[ name ];
10876
10877			// not quite $.extend, this wont overwrite keys already present.
10878			// also - reusing 'index' from above because we have the correct "name"
10879			for ( index in value ) {
10880				if ( !( index in props ) ) {
10881					props[ index ] = value[ index ];
10882					specialEasing[ index ] = easing;
10883				}
10884			}
10885		} else {
10886			specialEasing[ name ] = easing;
10887		}
10888	}
10889}
10890
10891function Animation( elem, properties, options ) {
10892	var result,
10893		stopped,
10894		index = 0,
10895		length = animationPrefilters.length,
10896		deferred = jQuery1113.Deferred().always( function() {
10897			// don't match elem in the :animated selector
10898			delete tick.elem;
10899		}),
10900		tick = function() {
10901			if ( stopped ) {
10902				return false;
10903			}
10904			var currentTime = fxNow || createFxNow(),
10905				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
10906				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
10907				temp = remaining / animation.duration || 0,
10908				percent = 1 - temp,
10909				index = 0,
10910				length = animation.tweens.length;
10911
10912			for ( ; index < length ; index++ ) {
10913				animation.tweens[ index ].run( percent );
10914			}
10915
10916			deferred.notifyWith( elem, [ animation, percent, remaining ]);
10917
10918			if ( percent < 1 && length ) {
10919				return remaining;
10920			} else {
10921				deferred.resolveWith( elem, [ animation ] );
10922				return false;
10923			}
10924		},
10925		animation = deferred.promise({
10926			elem: elem,
10927			props: jQuery1113.extend( {}, properties ),
10928			opts: jQuery1113.extend( true, { specialEasing: {} }, options ),
10929			originalProperties: properties,
10930			originalOptions: options,
10931			startTime: fxNow || createFxNow(),
10932			duration: options.duration,
10933			tweens: [],
10934			createTween: function( prop, end ) {
10935				var tween = jQuery1113.Tween( elem, animation.opts, prop, end,
10936						animation.opts.specialEasing[ prop ] || animation.opts.easing );
10937				animation.tweens.push( tween );
10938				return tween;
10939			},
10940			stop: function( gotoEnd ) {
10941				var index = 0,
10942					// if we are going to the end, we want to run all the tweens
10943					// otherwise we skip this part
10944					length = gotoEnd ? animation.tweens.length : 0;
10945				if ( stopped ) {
10946					return this;
10947				}
10948				stopped = true;
10949				for ( ; index < length ; index++ ) {
10950					animation.tweens[ index ].run( 1 );
10951				}
10952
10953				// resolve when we played the last frame
10954				// otherwise, reject
10955				if ( gotoEnd ) {
10956					deferred.resolveWith( elem, [ animation, gotoEnd ] );
10957				} else {
10958					deferred.rejectWith( elem, [ animation, gotoEnd ] );
10959				}
10960				return this;
10961			}
10962		}),
10963		props = animation.props;
10964
10965	propFilter( props, animation.opts.specialEasing );
10966
10967	for ( ; index < length ; index++ ) {
10968		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
10969		if ( result ) {
10970			return result;
10971		}
10972	}
10973
10974	jQuery1113.map( props, createTween, animation );
10975
10976	if ( jQuery1113.isFunction( animation.opts.start ) ) {
10977		animation.opts.start.call( elem, animation );
10978	}
10979
10980	jQuery1113.fx.timer(
10981		jQuery1113.extend( tick, {
10982			elem: elem,
10983			anim: animation,
10984			queue: animation.opts.queue
10985		})
10986	);
10987
10988	// attach callbacks from options
10989	return animation.progress( animation.opts.progress )
10990		.done( animation.opts.done, animation.opts.complete )
10991		.fail( animation.opts.fail )
10992		.always( animation.opts.always );
10993}
10994
10995jQuery1113.Animation = jQuery1113.extend( Animation, {
10996	tweener: function( props, callback ) {
10997		if ( jQuery1113.isFunction( props ) ) {
10998			callback = props;
10999			props = [ "*" ];
11000		} else {
11001			props = props.split(" ");
11002		}
11003
11004		var prop,
11005			index = 0,
11006			length = props.length;
11007
11008		for ( ; index < length ; index++ ) {
11009			prop = props[ index ];
11010			tweeners[ prop ] = tweeners[ prop ] || [];
11011			tweeners[ prop ].unshift( callback );
11012		}
11013	},
11014
11015	prefilter: function( callback, prepend ) {
11016		if ( prepend ) {
11017			animationPrefilters.unshift( callback );
11018		} else {
11019			animationPrefilters.push( callback );
11020		}
11021	}
11022});
11023
11024jQuery1113.speed = function( speed, easing, fn ) {
11025	var opt = speed && typeof speed === "object" ? jQuery1113.extend( {}, speed ) : {
11026		complete: fn || !fn && easing ||
11027			jQuery1113.isFunction( speed ) && speed,
11028		duration: speed,
11029		easing: fn && easing || easing && !jQuery1113.isFunction( easing ) && easing
11030	};
11031
11032	opt.duration = jQuery1113.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
11033		opt.duration in jQuery1113.fx.speeds ? jQuery1113.fx.speeds[ opt.duration ] : jQuery1113.fx.speeds._default;
11034
11035	// normalize opt.queue - true/undefined/null -> "fx"
11036	if ( opt.queue == null || opt.queue === true ) {
11037		opt.queue = "fx";
11038	}
11039
11040	// Queueing
11041	opt.old = opt.complete;
11042
11043	opt.complete = function() {
11044		if ( jQuery1113.isFunction( opt.old ) ) {
11045			opt.old.call( this );
11046		}
11047
11048		if ( opt.queue ) {
11049			jQuery1113.dequeue( this, opt.queue );
11050		}
11051	};
11052
11053	return opt;
11054};
11055
11056jQuery1113.fn.extend({
11057	fadeTo: function( speed, to, easing, callback ) {
11058
11059		// show any hidden elements after setting opacity to 0
11060		return this.filter( isHidden ).css( "opacity", 0 ).show()
11061
11062			// animate to the value specified
11063			.end().animate({ opacity: to }, speed, easing, callback );
11064	},
11065	animate: function( prop, speed, easing, callback ) {
11066		var empty = jQuery1113.isEmptyObject( prop ),
11067			optall = jQuery1113.speed( speed, easing, callback ),
11068			doAnimation = function() {
11069				// Operate on a copy of prop so per-property easing won't be lost
11070				var anim = Animation( this, jQuery1113.extend( {}, prop ), optall );
11071
11072				// Empty animations, or finishing resolves immediately
11073				if ( empty || jQuery1113._data( this, "finish" ) ) {
11074					anim.stop( true );
11075				}
11076			};
11077			doAnimation.finish = doAnimation;
11078
11079		return empty || optall.queue === false ?
11080			this.each( doAnimation ) :
11081			this.queue( optall.queue, doAnimation );
11082	},
11083	stop: function( type, clearQueue, gotoEnd ) {
11084		var stopQueue = function( hooks ) {
11085			var stop = hooks.stop;
11086			delete hooks.stop;
11087			stop( gotoEnd );
11088		};
11089
11090		if ( typeof type !== "string" ) {
11091			gotoEnd = clearQueue;
11092			clearQueue = type;
11093			type = undefined;
11094		}
11095		if ( clearQueue && type !== false ) {
11096			this.queue( type || "fx", [] );
11097		}
11098
11099		return this.each(function() {
11100			var dequeue = true,
11101				index = type != null && type + "queueHooks",
11102				timers = jQuery1113.timers,
11103				data = jQuery1113._data( this );
11104
11105			if ( index ) {
11106				if ( data[ index ] && data[ index ].stop ) {
11107					stopQueue( data[ index ] );
11108				}
11109			} else {
11110				for ( index in data ) {
11111					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
11112						stopQueue( data[ index ] );
11113					}
11114				}
11115			}
11116
11117			for ( index = timers.length; index--; ) {
11118				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
11119					timers[ index ].anim.stop( gotoEnd );
11120					dequeue = false;
11121					timers.splice( index, 1 );
11122				}
11123			}
11124
11125			// start the next in the queue if the last step wasn't forced
11126			// timers currently will call their complete callbacks, which will dequeue
11127			// but only if they were gotoEnd
11128			if ( dequeue || !gotoEnd ) {
11129				jQuery1113.dequeue( this, type );
11130			}
11131		});
11132	},
11133	finish: function( type ) {
11134		if ( type !== false ) {
11135			type = type || "fx";
11136		}
11137		return this.each(function() {
11138			var index,
11139				data = jQuery1113._data( this ),
11140				queue = data[ type + "queue" ],
11141				hooks = data[ type + "queueHooks" ],
11142				timers = jQuery1113.timers,
11143				length = queue ? queue.length : 0;
11144
11145			// enable finishing flag on private data
11146			data.finish = true;
11147
11148			// empty the queue first
11149			jQuery1113.queue( this, type, [] );
11150
11151			if ( hooks && hooks.stop ) {
11152				hooks.stop.call( this, true );
11153			}
11154
11155			// look for any active animations, and finish them
11156			for ( index = timers.length; index--; ) {
11157				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
11158					timers[ index ].anim.stop( true );
11159					timers.splice( index, 1 );
11160				}
11161			}
11162
11163			// look for any animations in the old queue and finish them
11164			for ( index = 0; index < length; index++ ) {
11165				if ( queue[ index ] && queue[ index ].finish ) {
11166					queue[ index ].finish.call( this );
11167				}
11168			}
11169
11170			// turn off finishing flag
11171			delete data.finish;
11172		});
11173	}
11174});
11175
11176jQuery1113.each([ "toggle", "show", "hide" ], function( i, name ) {
11177	var cssFn = jQuery1113.fn[ name ];
11178	jQuery1113.fn[ name ] = function( speed, easing, callback ) {
11179		return speed == null || typeof speed === "boolean" ?
11180			cssFn.apply( this, arguments ) :
11181			this.animate( genFx( name, true ), speed, easing, callback );
11182	};
11183});
11184
11185// Generate shortcuts for custom animations
11186jQuery1113.each({
11187	slideDown: genFx("show"),
11188	slideUp: genFx("hide"),
11189	slideToggle: genFx("toggle"),
11190	fadeIn: { opacity: "show" },
11191	fadeOut: { opacity: "hide" },
11192	fadeToggle: { opacity: "toggle" }
11193}, function( name, props ) {
11194	jQuery1113.fn[ name ] = function( speed, easing, callback ) {
11195		return this.animate( props, speed, easing, callback );
11196	};
11197});
11198
11199jQuery1113.timers = [];
11200jQuery1113.fx.tick = function() {
11201	var timer,
11202		timers = jQuery1113.timers,
11203		i = 0;
11204
11205	fxNow = jQuery1113.now();
11206
11207	for ( ; i < timers.length; i++ ) {
11208		timer = timers[ i ];
11209		// Checks the timer has not already been removed
11210		if ( !timer() && timers[ i ] === timer ) {
11211			timers.splice( i--, 1 );
11212		}
11213	}
11214
11215	if ( !timers.length ) {
11216		jQuery1113.fx.stop();
11217	}
11218	fxNow = undefined;
11219};
11220
11221jQuery1113.fx.timer = function( timer ) {
11222	jQuery1113.timers.push( timer );
11223	if ( timer() ) {
11224		jQuery1113.fx.start();
11225	} else {
11226		jQuery1113.timers.pop();
11227	}
11228};
11229
11230jQuery1113.fx.interval = 13;
11231
11232jQuery1113.fx.start = function() {
11233	if ( !timerId ) {
11234		timerId = setInterval( jQuery1113.fx.tick, jQuery1113.fx.interval );
11235	}
11236};
11237
11238jQuery1113.fx.stop = function() {
11239	clearInterval( timerId );
11240	timerId = null;
11241};
11242
11243jQuery1113.fx.speeds = {
11244	slow: 600,
11245	fast: 200,
11246	// Default speed
11247	_default: 400
11248};
11249
11250
11251// Based off of the plugin by Clint Helfers, with permission.
11252// http://blindsignals.com/index.php/2009/07/jQuery1113-delay/
11253jQuery1113.fn.delay = function( time, type ) {
11254	time = jQuery1113.fx ? jQuery1113.fx.speeds[ time ] || time : time;
11255	type = type || "fx";
11256
11257	return this.queue( type, function( next, hooks ) {
11258		var timeout = setTimeout( next, time );
11259		hooks.stop = function() {
11260			clearTimeout( timeout );
11261		};
11262	});
11263};
11264
11265
11266(function() {
11267	// Minified: var a,b,c,d,e
11268	var input, div, select, a, opt;
11269
11270	// Setup
11271	div = document.createElement( "div" );
11272	div.setAttribute( "className", "t" );
11273	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
11274	a = div.getElementsByTagName("a")[ 0 ];
11275
11276	// First batch of tests.
11277	select = document.createElement("select");
11278	opt = select.appendChild( document.createElement("option") );
11279	input = div.getElementsByTagName("input")[ 0 ];
11280
11281	a.style.cssText = "top:1px";
11282
11283	// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
11284	support.getSetAttribute = div.className !== "t";
11285
11286	// Get the style information from getAttribute
11287	// (IE uses .cssText instead)
11288	support.style = /top/.test( a.getAttribute("style") );
11289
11290	// Make sure that URLs aren't manipulated
11291	// (IE normalizes it by default)
11292	support.hrefNormalized = a.getAttribute("href") === "/a";
11293
11294	// Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
11295	support.checkOn = !!input.value;
11296
11297	// Make sure that a selected-by-default option has a working selected property.
11298	// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
11299	support.optSelected = opt.selected;
11300
11301	// Tests for enctype support on a form (#6743)
11302	support.enctype = !!document.createElement("form").enctype;
11303
11304	// Make sure that the options inside disabled selects aren't marked as disabled
11305	// (WebKit marks them as disabled)
11306	select.disabled = true;
11307	support.optDisabled = !opt.disabled;
11308
11309	// Support: IE8 only
11310	// Check if we can trust getAttribute("value")
11311	input = document.createElement( "input" );
11312	input.setAttribute( "value", "" );
11313	support.input = input.getAttribute( "value" ) === "";
11314
11315	// Check if an input maintains its value after becoming a radio
11316	input.value = "t";
11317	input.setAttribute( "type", "radio" );
11318	support.radioValue = input.value === "t";
11319})();
11320
11321
11322var rreturn = /\r/g;
11323
11324jQuery1113.fn.extend({
11325	val: function( value ) {
11326		var hooks, ret, isFunction,
11327			elem = this[0];
11328
11329		if ( !arguments.length ) {
11330			if ( elem ) {
11331				hooks = jQuery1113.valHooks[ elem.type ] || jQuery1113.valHooks[ elem.nodeName.toLowerCase() ];
11332
11333				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
11334					return ret;
11335				}
11336
11337				ret = elem.value;
11338
11339				return typeof ret === "string" ?
11340					// handle most common string cases
11341					ret.replace(rreturn, "") :
11342					// handle cases where value is null/undef or number
11343					ret == null ? "" : ret;
11344			}
11345
11346			return;
11347		}
11348
11349		isFunction = jQuery1113.isFunction( value );
11350
11351		return this.each(function( i ) {
11352			var val;
11353
11354			if ( this.nodeType !== 1 ) {
11355				return;
11356			}
11357
11358			if ( isFunction ) {
11359				val = value.call( this, i, jQuery1113( this ).val() );
11360			} else {
11361				val = value;
11362			}
11363
11364			// Treat null/undefined as ""; convert numbers to string
11365			if ( val == null ) {
11366				val = "";
11367			} else if ( typeof val === "number" ) {
11368				val += "";
11369			} else if ( jQuery1113.isArray( val ) ) {
11370				val = jQuery1113.map( val, function( value ) {
11371					return value == null ? "" : value + "";
11372				});
11373			}
11374
11375			hooks = jQuery1113.valHooks[ this.type ] || jQuery1113.valHooks[ this.nodeName.toLowerCase() ];
11376
11377			// If set returns undefined, fall back to normal setting
11378			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
11379				this.value = val;
11380			}
11381		});
11382	}
11383});
11384
11385jQuery1113.extend({
11386	valHooks: {
11387		option: {
11388			get: function( elem ) {
11389				var val = jQuery1113.find.attr( elem, "value" );
11390				return val != null ?
11391					val :
11392					// Support: IE10-11+
11393					// option.text throws exceptions (#14686, #14858)
11394					jQuery1113.trim( jQuery1113.text( elem ) );
11395			}
11396		},
11397		select: {
11398			get: function( elem ) {
11399				var value, option,
11400					options = elem.options,
11401					index = elem.selectedIndex,
11402					one = elem.type === "select-one" || index < 0,
11403					values = one ? null : [],
11404					max = one ? index + 1 : options.length,
11405					i = index < 0 ?
11406						max :
11407						one ? index : 0;
11408
11409				// Loop through all the selected options
11410				for ( ; i < max; i++ ) {
11411					option = options[ i ];
11412
11413					// oldIE doesn't update selected after form reset (#2551)
11414					if ( ( option.selected || i === index ) &&
11415							// Don't return options that are disabled or in a disabled optgroup
11416							( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
11417							( !option.parentNode.disabled || !jQuery1113.nodeName( option.parentNode, "optgroup" ) ) ) {
11418
11419						// Get the specific value for the option
11420						value = jQuery1113( option ).val();
11421
11422						// We don't need an array for one selects
11423						if ( one ) {
11424							return value;
11425						}
11426
11427						// Multi-Selects return an array
11428						values.push( value );
11429					}
11430				}
11431
11432				return values;
11433			},
11434
11435			set: function( elem, value ) {
11436				var optionSet, option,
11437					options = elem.options,
11438					values = jQuery1113.makeArray( value ),
11439					i = options.length;
11440
11441				while ( i-- ) {
11442					option = options[ i ];
11443
11444					if ( jQuery1113.inArray( jQuery1113.valHooks.option.get( option ), values ) >= 0 ) {
11445
11446						// Support: IE6
11447						// When new option element is added to select box we need to
11448						// force reflow of newly added node in order to workaround delay
11449						// of initialization properties
11450						try {
11451							option.selected = optionSet = true;
11452
11453						} catch ( _ ) {
11454
11455							// Will be executed only in IE6
11456							option.scrollHeight;
11457						}
11458
11459					} else {
11460						option.selected = false;
11461					}
11462				}
11463
11464				// Force browsers to behave consistently when non-matching value is set
11465				if ( !optionSet ) {
11466					elem.selectedIndex = -1;
11467				}
11468
11469				return options;
11470			}
11471		}
11472	}
11473});
11474
11475// Radios and checkboxes getter/setter
11476jQuery1113.each([ "radio", "checkbox" ], function() {
11477	jQuery1113.valHooks[ this ] = {
11478		set: function( elem, value ) {
11479			if ( jQuery1113.isArray( value ) ) {
11480				return ( elem.checked = jQuery1113.inArray( jQuery1113(elem).val(), value ) >= 0 );
11481			}
11482		}
11483	};
11484	if ( !support.checkOn ) {
11485		jQuery1113.valHooks[ this ].get = function( elem ) {
11486			// Support: Webkit
11487			// "" is returned instead of "on" if a value isn't specified
11488			return elem.getAttribute("value") === null ? "on" : elem.value;
11489		};
11490	}
11491});
11492
11493
11494
11495
11496var nodeHook, boolHook,
11497	attrHandle = jQuery1113.expr.attrHandle,
11498	ruseDefault = /^(?:checked|selected)$/i,
11499	getSetAttribute = support.getSetAttribute,
11500	getSetInput = support.input;
11501
11502jQuery1113.fn.extend({
11503	attr: function( name, value ) {
11504		return access( this, jQuery1113.attr, name, value, arguments.length > 1 );
11505	},
11506
11507	removeAttr: function( name ) {
11508		return this.each(function() {
11509			jQuery1113.removeAttr( this, name );
11510		});
11511	}
11512});
11513
11514jQuery1113.extend({
11515	attr: function( elem, name, value ) {
11516		var hooks, ret,
11517			nType = elem.nodeType;
11518
11519		// don't get/set attributes on text, comment and attribute nodes
11520		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
11521			return;
11522		}
11523
11524		// Fallback to prop when attributes are not supported
11525		if ( typeof elem.getAttribute === strundefined ) {
11526			return jQuery1113.prop( elem, name, value );
11527		}
11528
11529		// All attributes are lowercase
11530		// Grab necessary hook if one is defined
11531		if ( nType !== 1 || !jQuery1113.isXMLDoc( elem ) ) {
11532			name = name.toLowerCase();
11533			hooks = jQuery1113.attrHooks[ name ] ||
11534				( jQuery1113.expr.match.bool.test( name ) ? boolHook : nodeHook );
11535		}
11536
11537		if ( value !== undefined ) {
11538
11539			if ( value === null ) {
11540				jQuery1113.removeAttr( elem, name );
11541
11542			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
11543				return ret;
11544
11545			} else {
11546				elem.setAttribute( name, value + "" );
11547				return value;
11548			}
11549
11550		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
11551			return ret;
11552
11553		} else {
11554			ret = jQuery1113.find.attr( elem, name );
11555
11556			// Non-existent attributes return null, we normalize to undefined
11557			return ret == null ?
11558				undefined :
11559				ret;
11560		}
11561	},
11562
11563	removeAttr: function( elem, value ) {
11564		var name, propName,
11565			i = 0,
11566			attrNames = value && value.match( rnotwhite );
11567
11568		if ( attrNames && elem.nodeType === 1 ) {
11569			while ( (name = attrNames[i++]) ) {
11570				propName = jQuery1113.propFix[ name ] || name;
11571
11572				// Boolean attributes get special treatment (#10870)
11573				if ( jQuery1113.expr.match.bool.test( name ) ) {
11574					// Set corresponding property to false
11575					if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
11576						elem[ propName ] = false;
11577					// Support: IE<9
11578					// Also clear defaultChecked/defaultSelected (if appropriate)
11579					} else {
11580						elem[ jQuery1113.camelCase( "default-" + name ) ] =
11581							elem[ propName ] = false;
11582					}
11583
11584				// See #9699 for explanation of this approach (setting first, then removal)
11585				} else {
11586					jQuery1113.attr( elem, name, "" );
11587				}
11588
11589				elem.removeAttribute( getSetAttribute ? name : propName );
11590			}
11591		}
11592	},
11593
11594	attrHooks: {
11595		type: {
11596			set: function( elem, value ) {
11597				if ( !support.radioValue && value === "radio" && jQuery1113.nodeName(elem, "input") ) {
11598					// Setting the type on a radio button after the value resets the value in IE6-9
11599					// Reset value to default in case type is set after value during creation
11600					var val = elem.value;
11601					elem.setAttribute( "type", value );
11602					if ( val ) {
11603						elem.value = val;
11604					}
11605					return value;
11606				}
11607			}
11608		}
11609	}
11610});
11611
11612// Hook for boolean attributes
11613boolHook = {
11614	set: function( elem, value, name ) {
11615		if ( value === false ) {
11616			// Remove boolean attributes when set to false
11617			jQuery1113.removeAttr( elem, name );
11618		} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
11619			// IE<8 needs the *property* name
11620			elem.setAttribute( !getSetAttribute && jQuery1113.propFix[ name ] || name, name );
11621
11622		// Use defaultChecked and defaultSelected for oldIE
11623		} else {
11624			elem[ jQuery1113.camelCase( "default-" + name ) ] = elem[ name ] = true;
11625		}
11626
11627		return name;
11628	}
11629};
11630
11631// Retrieve booleans specially
11632jQuery1113.each( jQuery1113.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
11633
11634	var getter = attrHandle[ name ] || jQuery1113.find.attr;
11635
11636	attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
11637		function( elem, name, isXML ) {
11638			var ret, handle;
11639			if ( !isXML ) {
11640				// Avoid an infinite loop by temporarily removing this function from the getter
11641				handle = attrHandle[ name ];
11642				attrHandle[ name ] = ret;
11643				ret = getter( elem, name, isXML ) != null ?
11644					name.toLowerCase() :
11645					null;
11646				attrHandle[ name ] = handle;
11647			}
11648			return ret;
11649		} :
11650		function( elem, name, isXML ) {
11651			if ( !isXML ) {
11652				return elem[ jQuery1113.camelCase( "default-" + name ) ] ?
11653					name.toLowerCase() :
11654					null;
11655			}
11656		};
11657});
11658
11659// fix oldIE attroperties
11660if ( !getSetInput || !getSetAttribute ) {
11661	jQuery1113.attrHooks.value = {
11662		set: function( elem, value, name ) {
11663			if ( jQuery1113.nodeName( elem, "input" ) ) {
11664				// Does not return so that setAttribute is also used
11665				elem.defaultValue = value;
11666			} else {
11667				// Use nodeHook if defined (#1954); otherwise setAttribute is fine
11668				return nodeHook && nodeHook.set( elem, value, name );
11669			}
11670		}
11671	};
11672}
11673
11674// IE6/7 do not support getting/setting some attributes with get/setAttribute
11675if ( !getSetAttribute ) {
11676
11677	// Use this for any attribute in IE6/7
11678	// This fixes almost every IE6/7 issue
11679	nodeHook = {
11680		set: function( elem, value, name ) {
11681			// Set the existing or create a new attribute node
11682			var ret = elem.getAttributeNode( name );
11683			if ( !ret ) {
11684				elem.setAttributeNode(
11685					(ret = elem.ownerDocument.createAttribute( name ))
11686				);
11687			}
11688
11689			ret.value = value += "";
11690
11691			// Break association with cloned elements by also using setAttribute (#9646)
11692			if ( name === "value" || value === elem.getAttribute( name ) ) {
11693				return value;
11694			}
11695		}
11696	};
11697
11698	// Some attributes are constructed with empty-string values when not defined
11699	attrHandle.id = attrHandle.name = attrHandle.coords =
11700		function( elem, name, isXML ) {
11701			var ret;
11702			if ( !isXML ) {
11703				return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
11704					ret.value :
11705					null;
11706			}
11707		};
11708
11709	// Fixing value retrieval on a button requires this module
11710	jQuery1113.valHooks.button = {
11711		get: function( elem, name ) {
11712			var ret = elem.getAttributeNode( name );
11713			if ( ret && ret.specified ) {
11714				return ret.value;
11715			}
11716		},
11717		set: nodeHook.set
11718	};
11719
11720	// Set contenteditable to false on removals(#10429)
11721	// Setting to empty string throws an error as an invalid value
11722	jQuery1113.attrHooks.contenteditable = {
11723		set: function( elem, value, name ) {
11724			nodeHook.set( elem, value === "" ? false : value, name );
11725		}
11726	};
11727
11728	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
11729	// This is for removals
11730	jQuery1113.each([ "width", "height" ], function( i, name ) {
11731		jQuery1113.attrHooks[ name ] = {
11732			set: function( elem, value ) {
11733				if ( value === "" ) {
11734					elem.setAttribute( name, "auto" );
11735					return value;
11736				}
11737			}
11738		};
11739	});
11740}
11741
11742if ( !support.style ) {
11743	jQuery1113.attrHooks.style = {
11744		get: function( elem ) {
11745			// Return undefined in the case of empty string
11746			// Note: IE uppercases css property names, but if we were to .toLowerCase()
11747			// .cssText, that would destroy case senstitivity in URL's, like in "background"
11748			return elem.style.cssText || undefined;
11749		},
11750		set: function( elem, value ) {
11751			return ( elem.style.cssText = value + "" );
11752		}
11753	};
11754}
11755
11756
11757
11758
11759var rfocusable = /^(?:input|select|textarea|button|object)$/i,
11760	rclickable = /^(?:a|area)$/i;
11761
11762jQuery1113.fn.extend({
11763	prop: function( name, value ) {
11764		return access( this, jQuery1113.prop, name, value, arguments.length > 1 );
11765	},
11766
11767	removeProp: function( name ) {
11768		name = jQuery1113.propFix[ name ] || name;
11769		return this.each(function() {
11770			// try/catch handles cases where IE balks (such as removing a property on window)
11771			try {
11772				this[ name ] = undefined;
11773				delete this[ name ];
11774			} catch( e ) {}
11775		});
11776	}
11777});
11778
11779jQuery1113.extend({
11780	propFix: {
11781		"for": "htmlFor",
11782		"class": "className"
11783	},
11784
11785	prop: function( elem, name, value ) {
11786		var ret, hooks, notxml,
11787			nType = elem.nodeType;
11788
11789		// don't get/set properties on text, comment and attribute nodes
11790		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
11791			return;
11792		}
11793
11794		notxml = nType !== 1 || !jQuery1113.isXMLDoc( elem );
11795
11796		if ( notxml ) {
11797			// Fix name and attach hooks
11798			name = jQuery1113.propFix[ name ] || name;
11799			hooks = jQuery1113.propHooks[ name ];
11800		}
11801
11802		if ( value !== undefined ) {
11803			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
11804				ret :
11805				( elem[ name ] = value );
11806
11807		} else {
11808			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
11809				ret :
11810				elem[ name ];
11811		}
11812	},
11813
11814	propHooks: {
11815		tabIndex: {
11816			get: function( elem ) {
11817				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
11818				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
11819				// Use proper attribute retrieval(#12072)
11820				var tabindex = jQuery1113.find.attr( elem, "tabindex" );
11821
11822				return tabindex ?
11823					parseInt( tabindex, 10 ) :
11824					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
11825						0 :
11826						-1;
11827			}
11828		}
11829	}
11830});
11831
11832// Some attributes require a special call on IE
11833// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
11834if ( !support.hrefNormalized ) {
11835	// href/src property should get the full normalized URL (#10299/#12915)
11836	jQuery1113.each([ "href", "src" ], function( i, name ) {
11837		jQuery1113.propHooks[ name ] = {
11838			get: function( elem ) {
11839				return elem.getAttribute( name, 4 );
11840			}
11841		};
11842	});
11843}
11844
11845// Support: Safari, IE9+
11846// mis-reports the default selected property of an option
11847// Accessing the parent's selectedIndex property fixes it
11848if ( !support.optSelected ) {
11849	jQuery1113.propHooks.selected = {
11850		get: function( elem ) {
11851			var parent = elem.parentNode;
11852
11853			if ( parent ) {
11854				parent.selectedIndex;
11855
11856				// Make sure that it also works with optgroups, see #5701
11857				if ( parent.parentNode ) {
11858					parent.parentNode.selectedIndex;
11859				}
11860			}
11861			return null;
11862		}
11863	};
11864}
11865
11866jQuery1113.each([
11867	"tabIndex",
11868	"readOnly",
11869	"maxLength",
11870	"cellSpacing",
11871	"cellPadding",
11872	"rowSpan",
11873	"colSpan",
11874	"useMap",
11875	"frameBorder",
11876	"contentEditable"
11877], function() {
11878	jQuery1113.propFix[ this.toLowerCase() ] = this;
11879});
11880
11881// IE6/7 call enctype encoding
11882if ( !support.enctype ) {
11883	jQuery1113.propFix.enctype = "encoding";
11884}
11885
11886
11887
11888
11889var rclass = /[\t\r\n\f]/g;
11890
11891jQuery1113.fn.extend({
11892	addClass: function( value ) {
11893		var classes, elem, cur, clazz, j, finalValue,
11894			i = 0,
11895			len = this.length,
11896			proceed = typeof value === "string" && value;
11897
11898		if ( jQuery1113.isFunction( value ) ) {
11899			return this.each(function( j ) {
11900				jQuery1113( this ).addClass( value.call( this, j, this.className ) );
11901			});
11902		}
11903
11904		if ( proceed ) {
11905			// The disjunction here is for better compressibility (see removeClass)
11906			classes = ( value || "" ).match( rnotwhite ) || [];
11907
11908			for ( ; i < len; i++ ) {
11909				elem = this[ i ];
11910				cur = elem.nodeType === 1 && ( elem.className ?
11911					( " " + elem.className + " " ).replace( rclass, " " ) :
11912					" "
11913				);
11914
11915				if ( cur ) {
11916					j = 0;
11917					while ( (clazz = classes[j++]) ) {
11918						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
11919							cur += clazz + " ";
11920						}
11921					}
11922
11923					// only assign if different to avoid unneeded rendering.
11924					finalValue = jQuery1113.trim( cur );
11925					if ( elem.className !== finalValue ) {
11926						elem.className = finalValue;
11927					}
11928				}
11929			}
11930		}
11931
11932		return this;
11933	},
11934
11935	removeClass: function( value ) {
11936		var classes, elem, cur, clazz, j, finalValue,
11937			i = 0,
11938			len = this.length,
11939			proceed = arguments.length === 0 || typeof value === "string" && value;
11940
11941		if ( jQuery1113.isFunction( value ) ) {
11942			return this.each(function( j ) {
11943				jQuery1113( this ).removeClass( value.call( this, j, this.className ) );
11944			});
11945		}
11946		if ( proceed ) {
11947			classes = ( value || "" ).match( rnotwhite ) || [];
11948
11949			for ( ; i < len; i++ ) {
11950				elem = this[ i ];
11951				// This expression is here for better compressibility (see addClass)
11952				cur = elem.nodeType === 1 && ( elem.className ?
11953					( " " + elem.className + " " ).replace( rclass, " " ) :
11954					""
11955				);
11956
11957				if ( cur ) {
11958					j = 0;
11959					while ( (clazz = classes[j++]) ) {
11960						// Remove *all* instances
11961						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
11962							cur = cur.replace( " " + clazz + " ", " " );
11963						}
11964					}
11965
11966					// only assign if different to avoid unneeded rendering.
11967					finalValue = value ? jQuery1113.trim( cur ) : "";
11968					if ( elem.className !== finalValue ) {
11969						elem.className = finalValue;
11970					}
11971				}
11972			}
11973		}
11974
11975		return this;
11976	},
11977
11978	toggleClass: function( value, stateVal ) {
11979		var type = typeof value;
11980
11981		if ( typeof stateVal === "boolean" && type === "string" ) {
11982			return stateVal ? this.addClass( value ) : this.removeClass( value );
11983		}
11984
11985		if ( jQuery1113.isFunction( value ) ) {
11986			return this.each(function( i ) {
11987				jQuery1113( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
11988			});
11989		}
11990
11991		return this.each(function() {
11992			if ( type === "string" ) {
11993				// toggle individual class names
11994				var className,
11995					i = 0,
11996					self = jQuery1113( this ),
11997					classNames = value.match( rnotwhite ) || [];
11998
11999				while ( (className = classNames[ i++ ]) ) {
12000					// check each className given, space separated list
12001					if ( self.hasClass( className ) ) {
12002						self.removeClass( className );
12003					} else {
12004						self.addClass( className );
12005					}
12006				}
12007
12008			// Toggle whole class name
12009			} else if ( type === strundefined || type === "boolean" ) {
12010				if ( this.className ) {
12011					// store className if set
12012					jQuery1113._data( this, "__className__", this.className );
12013				}
12014
12015				// If the element has a class name or if we're passed "false",
12016				// then remove the whole classname (if there was one, the above saved it).
12017				// Otherwise bring back whatever was previously saved (if anything),
12018				// falling back to the empty string if nothing was stored.
12019				this.className = this.className || value === false ? "" : jQuery1113._data( this, "__className__" ) || "";
12020			}
12021		});
12022	},
12023
12024	hasClass: function( selector ) {
12025		var className = " " + selector + " ",
12026			i = 0,
12027			l = this.length;
12028		for ( ; i < l; i++ ) {
12029			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
12030				return true;
12031			}
12032		}
12033
12034		return false;
12035	}
12036});
12037
12038
12039
12040
12041// Return jQuery1113 for attributes-only inclusion
12042
12043
12044jQuery1113.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
12045	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
12046	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
12047
12048	// Handle event binding
12049	jQuery1113.fn[ name ] = function( data, fn ) {
12050		return arguments.length > 0 ?
12051			this.on( name, null, data, fn ) :
12052			this.trigger( name );
12053	};
12054});
12055
12056jQuery1113.fn.extend({
12057	hover: function( fnOver, fnOut ) {
12058		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
12059	},
12060
12061	bind: function( types, data, fn ) {
12062		return this.on( types, null, data, fn );
12063	},
12064	unbind: function( types, fn ) {
12065		return this.off( types, null, fn );
12066	},
12067
12068	delegate: function( selector, types, data, fn ) {
12069		return this.on( types, selector, data, fn );
12070	},
12071	undelegate: function( selector, types, fn ) {
12072		// ( namespace ) or ( selector, types [, fn] )
12073		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
12074	}
12075});
12076
12077
12078var nonce = jQuery1113.now();
12079
12080var rquery = (/\?/);
12081
12082
12083
12084var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
12085
12086jQuery1113.parseJSON = function( data ) {
12087	// Attempt to parse using the native JSON parser first
12088	if ( window.JSON && window.JSON.parse ) {
12089		// Support: Android 2.3
12090		// Workaround failure to string-cast null input
12091		return window.JSON.parse( data + "" );
12092	}
12093
12094	var requireNonComma,
12095		depth = null,
12096		str = jQuery1113.trim( data + "" );
12097
12098	// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
12099	// after removing valid tokens
12100	return str && !jQuery1113.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
12101
12102		// Force termination if we see a misplaced comma
12103		if ( requireNonComma && comma ) {
12104			depth = 0;
12105		}
12106
12107		// Perform no more replacements after returning to outermost depth
12108		if ( depth === 0 ) {
12109			return token;
12110		}
12111
12112		// Commas must not follow "[", "{", or ","
12113		requireNonComma = open || comma;
12114
12115		// Determine new depth
12116		// array/object open ("[" or "{"): depth += true - false (increment)
12117		// array/object close ("]" or "}"): depth += false - true (decrement)
12118		// other cases ("," or primitive): depth += true - true (numeric cast)
12119		depth += !close - !open;
12120
12121		// Remove this token
12122		return "";
12123	}) ) ?
12124		( Function( "return " + str ) )() :
12125		jQuery1113.error( "Invalid JSON: " + data );
12126};
12127
12128
12129// Cross-browser xml parsing
12130jQuery1113.parseXML = function( data ) {
12131	var xml, tmp;
12132	if ( !data || typeof data !== "string" ) {
12133		return null;
12134	}
12135	try {
12136		if ( window.DOMParser ) { // Standard
12137			tmp = new DOMParser();
12138			xml = tmp.parseFromString( data, "text/xml" );
12139		} else { // IE
12140			xml = new ActiveXObject( "Microsoft.XMLDOM" );
12141			xml.async = "false";
12142			xml.loadXML( data );
12143		}
12144	} catch( e ) {
12145		xml = undefined;
12146	}
12147	if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
12148		jQuery1113.error( "Invalid XML: " + data );
12149	}
12150	return xml;
12151};
12152
12153
12154var
12155	// Document location
12156	ajaxLocParts,
12157	ajaxLocation,
12158
12159	rhash = /#.*$/,
12160	rts = /([?&])_=[^&]*/,
12161	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
12162	// #7653, #8125, #8152: local protocol detection
12163	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
12164	rnoContent = /^(?:GET|HEAD)$/,
12165	rprotocol = /^\/\//,
12166	rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
12167
12168	/* Prefilters
12169	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
12170	 * 2) These are called:
12171	 *    - BEFORE asking for a transport
12172	 *    - AFTER param serialization (s.data is a string if s.processData is true)
12173	 * 3) key is the dataType
12174	 * 4) the catchall symbol "*" can be used
12175	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
12176	 */
12177	prefilters = {},
12178
12179	/* Transports bindings
12180	 * 1) key is the dataType
12181	 * 2) the catchall symbol "*" can be used
12182	 * 3) selection will start with transport dataType and THEN go to "*" if needed
12183	 */
12184	transports = {},
12185
12186	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
12187	allTypes = "*/".concat("*");
12188
12189// #8138, IE may throw an exception when accessing
12190// a field from window.location if document.domain has been set
12191try {
12192	ajaxLocation = location.href;
12193} catch( e ) {
12194	// Use the href attribute of an A element
12195	// since IE will modify it given document.location
12196	ajaxLocation = document.createElement( "a" );
12197	ajaxLocation.href = "";
12198	ajaxLocation = ajaxLocation.href;
12199}
12200
12201// Segment location into parts
12202ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
12203
12204// Base "constructor" for jQuery1113.ajaxPrefilter and jQuery1113.ajaxTransport
12205function addToPrefiltersOrTransports( structure ) {
12206
12207	// dataTypeExpression is optional and defaults to "*"
12208	return function( dataTypeExpression, func ) {
12209
12210		if ( typeof dataTypeExpression !== "string" ) {
12211			func = dataTypeExpression;
12212			dataTypeExpression = "*";
12213		}
12214
12215		var dataType,
12216			i = 0,
12217			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
12218
12219		if ( jQuery1113.isFunction( func ) ) {
12220			// For each dataType in the dataTypeExpression
12221			while ( (dataType = dataTypes[i++]) ) {
12222				// Prepend if requested
12223				if ( dataType.charAt( 0 ) === "+" ) {
12224					dataType = dataType.slice( 1 ) || "*";
12225					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
12226
12227				// Otherwise append
12228				} else {
12229					(structure[ dataType ] = structure[ dataType ] || []).push( func );
12230				}
12231			}
12232		}
12233	};
12234}
12235
12236// Base inspection function for prefilters and transports
12237function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
12238
12239	var inspected = {},
12240		seekingTransport = ( structure === transports );
12241
12242	function inspect( dataType ) {
12243		var selected;
12244		inspected[ dataType ] = true;
12245		jQuery1113.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
12246			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
12247			if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
12248				options.dataTypes.unshift( dataTypeOrTransport );
12249				inspect( dataTypeOrTransport );
12250				return false;
12251			} else if ( seekingTransport ) {
12252				return !( selected = dataTypeOrTransport );
12253			}
12254		});
12255		return selected;
12256	}
12257
12258	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
12259}
12260
12261// A special extend for ajax options
12262// that takes "flat" options (not to be deep extended)
12263// Fixes #9887
12264function ajaxExtend( target, src ) {
12265	var deep, key,
12266		flatOptions = jQuery1113.ajaxSettings.flatOptions || {};
12267
12268	for ( key in src ) {
12269		if ( src[ key ] !== undefined ) {
12270			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
12271		}
12272	}
12273	if ( deep ) {
12274		jQuery1113.extend( true, target, deep );
12275	}
12276
12277	return target;
12278}
12279
12280/* Handles responses to an ajax request:
12281 * - finds the right dataType (mediates between content-type and expected dataType)
12282 * - returns the corresponding response
12283 */
12284function ajaxHandleResponses( s, jqXHR, responses ) {
12285	var firstDataType, ct, finalDataType, type,
12286		contents = s.contents,
12287		dataTypes = s.dataTypes;
12288
12289	// Remove auto dataType and get content-type in the process
12290	while ( dataTypes[ 0 ] === "*" ) {
12291		dataTypes.shift();
12292		if ( ct === undefined ) {
12293			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
12294		}
12295	}
12296
12297	// Check if we're dealing with a known content-type
12298	if ( ct ) {
12299		for ( type in contents ) {
12300			if ( contents[ type ] && contents[ type ].test( ct ) ) {
12301				dataTypes.unshift( type );
12302				break;
12303			}
12304		}
12305	}
12306
12307	// Check to see if we have a response for the expected dataType
12308	if ( dataTypes[ 0 ] in responses ) {
12309		finalDataType = dataTypes[ 0 ];
12310	} else {
12311		// Try convertible dataTypes
12312		for ( type in responses ) {
12313			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
12314				finalDataType = type;
12315				break;
12316			}
12317			if ( !firstDataType ) {
12318				firstDataType = type;
12319			}
12320		}
12321		// Or just use first one
12322		finalDataType = finalDataType || firstDataType;
12323	}
12324
12325	// If we found a dataType
12326	// We add the dataType to the list if needed
12327	// and return the corresponding response
12328	if ( finalDataType ) {
12329		if ( finalDataType !== dataTypes[ 0 ] ) {
12330			dataTypes.unshift( finalDataType );
12331		}
12332		return responses[ finalDataType ];
12333	}
12334}
12335
12336/* Chain conversions given the request and the original response
12337 * Also sets the responseXXX fields on the jqXHR instance
12338 */
12339function ajaxConvert( s, response, jqXHR, isSuccess ) {
12340	var conv2, current, conv, tmp, prev,
12341		converters = {},
12342		// Work with a copy of dataTypes in case we need to modify it for conversion
12343		dataTypes = s.dataTypes.slice();
12344
12345	// Create converters map with lowercased keys
12346	if ( dataTypes[ 1 ] ) {
12347		for ( conv in s.converters ) {
12348			converters[ conv.toLowerCase() ] = s.converters[ conv ];
12349		}
12350	}
12351
12352	current = dataTypes.shift();
12353
12354	// Convert to each sequential dataType
12355	while ( current ) {
12356
12357		if ( s.responseFields[ current ] ) {
12358			jqXHR[ s.responseFields[ current ] ] = response;
12359		}
12360
12361		// Apply the dataFilter if provided
12362		if ( !prev && isSuccess && s.dataFilter ) {
12363			response = s.dataFilter( response, s.dataType );
12364		}
12365
12366		prev = current;
12367		current = dataTypes.shift();
12368
12369		if ( current ) {
12370
12371			// There's only work to do if current dataType is non-auto
12372			if ( current === "*" ) {
12373
12374				current = prev;
12375
12376			// Convert response if prev dataType is non-auto and differs from current
12377			} else if ( prev !== "*" && prev !== current ) {
12378
12379				// Seek a direct converter
12380				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
12381
12382				// If none found, seek a pair
12383				if ( !conv ) {
12384					for ( conv2 in converters ) {
12385
12386						// If conv2 outputs current
12387						tmp = conv2.split( " " );
12388						if ( tmp[ 1 ] === current ) {
12389
12390							// If prev can be converted to accepted input
12391							conv = converters[ prev + " " + tmp[ 0 ] ] ||
12392								converters[ "* " + tmp[ 0 ] ];
12393							if ( conv ) {
12394								// Condense equivalence converters
12395								if ( conv === true ) {
12396									conv = converters[ conv2 ];
12397
12398								// Otherwise, insert the intermediate dataType
12399								} else if ( converters[ conv2 ] !== true ) {
12400									current = tmp[ 0 ];
12401									dataTypes.unshift( tmp[ 1 ] );
12402								}
12403								break;
12404							}
12405						}
12406					}
12407				}
12408
12409				// Apply converter (if not an equivalence)
12410				if ( conv !== true ) {
12411
12412					// Unless errors are allowed to bubble, catch and return them
12413					if ( conv && s[ "throws" ] ) {
12414						response = conv( response );
12415					} else {
12416						try {
12417							response = conv( response );
12418						} catch ( e ) {
12419							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
12420						}
12421					}
12422				}
12423			}
12424		}
12425	}
12426
12427	return { state: "success", data: response };
12428}
12429
12430jQuery1113.extend({
12431
12432	// Counter for holding the number of active queries
12433	active: 0,
12434
12435	// Last-Modified header cache for next request
12436	lastModified: {},
12437	etag: {},
12438
12439	ajaxSettings: {
12440		url: ajaxLocation,
12441		type: "GET",
12442		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
12443		global: true,
12444		processData: true,
12445		async: true,
12446		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
12447		/*
12448		timeout: 0,
12449		data: null,
12450		dataType: null,
12451		username: null,
12452		password: null,
12453		cache: null,
12454		throws: false,
12455		traditional: false,
12456		headers: {},
12457		*/
12458
12459		accepts: {
12460			"*": allTypes,
12461			text: "text/plain",
12462			html: "text/html",
12463			xml: "application/xml, text/xml",
12464			json: "application/json, text/javascript"
12465		},
12466
12467		contents: {
12468			xml: /xml/,
12469			html: /html/,
12470			json: /json/
12471		},
12472
12473		responseFields: {
12474			xml: "responseXML",
12475			text: "responseText",
12476			json: "responseJSON"
12477		},
12478
12479		// Data converters
12480		// Keys separate source (or catchall "*") and destination types with a single space
12481		converters: {
12482
12483			// Convert anything to text
12484			"* text": String,
12485
12486			// Text to html (true = no transformation)
12487			"text html": true,
12488
12489			// Evaluate text as a json expression
12490			"text json": jQuery1113.parseJSON,
12491
12492			// Parse text as xml
12493			"text xml": jQuery1113.parseXML
12494		},
12495
12496		// For options that shouldn't be deep extended:
12497		// you can add your own custom options here if
12498		// and when you create one that shouldn't be
12499		// deep extended (see ajaxExtend)
12500		flatOptions: {
12501			url: true,
vendor: 6,167 bytes, lines 12502-12704
12502			context: true
12503		}
12504	},
12505
12506	// Creates a full fledged settings object into target
12507	// with both ajaxSettings and settings fields.
12508	// If target is omitted, writes into ajaxSettings.
12509	ajaxSetup: function( target, settings ) {
12510		return settings ?
12511
12512			// Building a settings object
12513			ajaxExtend( ajaxExtend( target, jQuery1113.ajaxSettings ), settings ) :
12514
12515			// Extending ajaxSettings
12516			ajaxExtend( jQuery1113.ajaxSettings, target );
12517	},
12518
12519	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
12520	ajaxTransport: addToPrefiltersOrTransports( transports ),
12521
12522	// Main method
12523	ajax: function( url, options ) {
12524
12525		// If url is an object, simulate pre-1.5 signature
12526		if ( typeof url === "object" ) {
12527			options = url;
12528			url = undefined;
12529		}
12530
12531		// Force options to be an object
12532		options = options || {};
12533
12534		var // Cross-domain detection vars
12535			parts,
12536			// Loop variable
12537			i,
12538			// URL without anti-cache param
12539			cacheURL,
12540			// Response headers as string
12541			responseHeadersString,
12542			// timeout handle
12543			timeoutTimer,
12544
12545			// To know if global events are to be dispatched
12546			fireGlobals,
12547
12548			transport,
12549			// Response headers
12550			responseHeaders,
12551			// Create the final options object
12552			s = jQuery1113.ajaxSetup( {}, options ),
12553			// Callbacks context
12554			callbackContext = s.context || s,
12555			// Context for global events is callbackContext if it is a DOM node or jQuery1113 collection
12556			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jQuery1113 ) ?
12557				jQuery1113( callbackContext ) :
12558				jQuery1113.event,
12559			// Deferreds
12560			deferred = jQuery1113.Deferred(),
12561			completeDeferred = jQuery1113.Callbacks("once memory"),
12562			// Status-dependent callbacks
12563			statusCode = s.statusCode || {},
12564			// Headers (they are sent all at once)
12565			requestHeaders = {},
12566			requestHeadersNames = {},
12567			// The jqXHR state
12568			state = 0,
12569			// Default abort message
12570			strAbort = "canceled",
12571			// Fake xhr
12572			jqXHR = {
12573				readyState: 0,
12574
12575				// Builds headers hashtable if needed
12576				getResponseHeader: function( key ) {
12577					var match;
12578					if ( state === 2 ) {
12579						if ( !responseHeaders ) {
12580							responseHeaders = {};
12581							while ( (match = rheaders.exec( responseHeadersString )) ) {
12582								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
12583							}
12584						}
12585						match = responseHeaders[ key.toLowerCase() ];
12586					}
12587					return match == null ? null : match;
12588				},
12589
12590				// Raw string
12591				getAllResponseHeaders: function() {
12592					return state === 2 ? responseHeadersString : null;
12593				},
12594
12595				// Caches the header
12596				setRequestHeader: function( name, value ) {
12597					var lname = name.toLowerCase();
12598					if ( !state ) {
12599						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
12600						requestHeaders[ name ] = value;
12601					}
12602					return this;
12603				},
12604
12605				// Overrides response content-type header
12606				overrideMimeType: function( type ) {
12607					if ( !state ) {
12608						s.mimeType = type;
12609					}
12610					return this;
12611				},
12612
12613				// Status-dependent callbacks
12614				statusCode: function( map ) {
12615					var code;
12616					if ( map ) {
12617						if ( state < 2 ) {
12618							for ( code in map ) {
12619								// Lazy-add the new callback in a way that preserves old ones
12620								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
12621							}
12622						} else {
12623							// Execute the appropriate callbacks
12624							jqXHR.always( map[ jqXHR.status ] );
12625						}
12626					}
12627					return this;
12628				},
12629
12630				// Cancel the request
12631				abort: function( statusText ) {
12632					var finalText = statusText || strAbort;
12633					if ( transport ) {
12634						transport.abort( finalText );
12635					}
12636					done( 0, finalText );
12637					return this;
12638				}
12639			};
12640
12641		// Attach deferreds
12642		deferred.promise( jqXHR ).complete = completeDeferred.add;
12643		jqXHR.success = jqXHR.done;
12644		jqXHR.error = jqXHR.fail;
12645
12646		// Remove hash character (#7531: and string promotion)
12647		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
12648		// Handle falsy url in the settings object (#10093: consistency with old signature)
12649		// We also use the url parameter if available
12650		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
12651
12652		// Alias method option to type as per ticket #12004
12653		s.type = options.method || options.type || s.method || s.type;
12654
12655		// Extract dataTypes list
12656		s.dataTypes = jQuery1113.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
12657
12658		// A cross-domain request is in order when we have a protocol:host:port mismatch
12659		if ( s.crossDomain == null ) {
12660			parts = rurl.exec( s.url.toLowerCase() );
12661			s.crossDomain = !!( parts &&
12662				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
12663					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
12664						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
12665			);
12666		}
12667
12668		// Convert data if not already a string
12669		if ( s.data && s.processData && typeof s.data !== "string" ) {
12670			s.data = jQuery1113.param( s.data, s.traditional );
12671		}
12672
12673		// Apply prefilters
12674		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
12675
12676		// If request was aborted inside a prefilter, stop there
12677		if ( state === 2 ) {
12678			return jqXHR;
12679		}
12680
12681		// We can fire global events as of now if asked to
12682		// Don't fire events if jQuery1113.event is undefined in an AMD-usage scenario (#15118)
12683		fireGlobals = jQuery1113.event && s.global;
12684
12685		// Watch for a new set of requests
12686		if ( fireGlobals && jQuery1113.active++ === 0 ) {
12687			jQuery1113.event.trigger("ajaxStart");
12688		}
12689
12690		// Uppercase the type
12691		s.type = s.type.toUpperCase();
12692
12693		// Determine if request has content
12694		s.hasContent = !rnoContent.test( s.type );
12695
12696		// Save the URL in case we're toying with the If-Modified-Since
12697		// and/or If-None-Match header later on
12698		cacheURL = s.url;
12699
12700		// More options handling for requests with no content
12701		if ( !s.hasContent ) {
12702
12703			// If data is available, append data to url
12704			if ( s.data ) {
vendor: 36,256 bytes, lines 12705-13968
12705				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
12706				// #9682: remove data so that it's not used in an eventual retry
12707				delete s.data;
12708			}
12709
12710			// Add anti-cache in url if needed
12711			if ( s.cache === false ) {
12712				s.url = rts.test( cacheURL ) ?
12713
12714					// If there is already a '_' parameter, set its value
12715					cacheURL.replace( rts, "$1_=" + nonce++ ) :
12716
12717					// Otherwise add one to the end
12718					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
12719			}
12720		}
12721
12722		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
12723		if ( s.ifModified ) {
12724			if ( jQuery1113.lastModified[ cacheURL ] ) {
12725				jqXHR.setRequestHeader( "If-Modified-Since", jQuery1113.lastModified[ cacheURL ] );
12726			}
12727			if ( jQuery1113.etag[ cacheURL ] ) {
12728				jqXHR.setRequestHeader( "If-None-Match", jQuery1113.etag[ cacheURL ] );
12729			}
12730		}
12731
12732		// Set the correct header, if data is being sent
12733		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
12734			jqXHR.setRequestHeader( "Content-Type", s.contentType );
12735		}
12736
12737		// Set the Accepts header for the server, depending on the dataType
12738		jqXHR.setRequestHeader(
12739			"Accept",
12740			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
12741				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
12742				s.accepts[ "*" ]
12743		);
12744
12745		// Check for headers option
12746		for ( i in s.headers ) {
12747			jqXHR.setRequestHeader( i, s.headers[ i ] );
12748		}
12749
12750		// Allow custom headers/mimetypes and early abort
12751		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
12752			// Abort if not done already and return
12753			return jqXHR.abort();
12754		}
12755
12756		// aborting is no longer a cancellation
12757		strAbort = "abort";
12758
12759		// Install callbacks on deferreds
12760		for ( i in { success: 1, error: 1, complete: 1 } ) {
12761			jqXHR[ i ]( s[ i ] );
12762		}
12763
12764		// Get transport
12765		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
12766
12767		// If no transport, we auto-abort
12768		if ( !transport ) {
12769			done( -1, "No Transport" );
12770		} else {
12771			jqXHR.readyState = 1;
12772
12773			// Send global event
12774			if ( fireGlobals ) {
12775				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
12776			}
12777			// Timeout
12778			if ( s.async && s.timeout > 0 ) {
12779				timeoutTimer = setTimeout(function() {
12780					jqXHR.abort("timeout");
12781				}, s.timeout );
12782			}
12783
12784			try {
12785				state = 1;
12786				transport.send( requestHeaders, done );
12787			} catch ( e ) {
12788				// Propagate exception as error if not done
12789				if ( state < 2 ) {
12790					done( -1, e );
12791				// Simply rethrow otherwise
12792				} else {
12793					throw e;
12794				}
12795			}
12796		}
12797
12798		// Callback for when everything is done
12799		function done( status, nativeStatusText, responses, headers ) {
12800			var isSuccess, success, error, response, modified,
12801				statusText = nativeStatusText;
12802
12803			// Called once
12804			if ( state === 2 ) {
12805				return;
12806			}
12807
12808			// State is "done" now
12809			state = 2;
12810
12811			// Clear timeout if it exists
12812			if ( timeoutTimer ) {
12813				clearTimeout( timeoutTimer );
12814			}
12815
12816			// Dereference transport for early garbage collection
12817			// (no matter how long the jqXHR object will be used)
12818			transport = undefined;
12819
12820			// Cache response headers
12821			responseHeadersString = headers || "";
12822
12823			// Set readyState
12824			jqXHR.readyState = status > 0 ? 4 : 0;
12825
12826			// Determine if successful
12827			isSuccess = status >= 200 && status < 300 || status === 304;
12828
12829			// Get response data
12830			if ( responses ) {
12831				response = ajaxHandleResponses( s, jqXHR, responses );
12832			}
12833
12834			// Convert no matter what (that way responseXXX fields are always set)
12835			response = ajaxConvert( s, response, jqXHR, isSuccess );
12836
12837			// If successful, handle type chaining
12838			if ( isSuccess ) {
12839
12840				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
12841				if ( s.ifModified ) {
12842					modified = jqXHR.getResponseHeader("Last-Modified");
12843					if ( modified ) {
12844						jQuery1113.lastModified[ cacheURL ] = modified;
12845					}
12846					modified = jqXHR.getResponseHeader("etag");
12847					if ( modified ) {
12848						jQuery1113.etag[ cacheURL ] = modified;
12849					}
12850				}
12851
12852				// if no content
12853				if ( status === 204 || s.type === "HEAD" ) {
12854					statusText = "nocontent";
12855
12856				// if not modified
12857				} else if ( status === 304 ) {
12858					statusText = "notmodified";
12859
12860				// If we have data, let's convert it
12861				} else {
12862					statusText = response.state;
12863					success = response.data;
12864					error = response.error;
12865					isSuccess = !error;
12866				}
12867			} else {
12868				// We extract error from statusText
12869				// then normalize statusText and status for non-aborts
12870				error = statusText;
12871				if ( status || !statusText ) {
12872					statusText = "error";
12873					if ( status < 0 ) {
12874						status = 0;
12875					}
12876				}
12877			}
12878
12879			// Set data for the fake xhr object
12880			jqXHR.status = status;
12881			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
12882
12883			// Success/Error
12884			if ( isSuccess ) {
12885				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
12886			} else {
12887				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
12888			}
12889
12890			// Status-dependent callbacks
12891			jqXHR.statusCode( statusCode );
12892			statusCode = undefined;
12893
12894			if ( fireGlobals ) {
12895				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
12896					[ jqXHR, s, isSuccess ? success : error ] );
12897			}
12898
12899			// Complete
12900			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
12901
12902			if ( fireGlobals ) {
12903				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
12904				// Handle the global AJAX counter
12905				if ( !( --jQuery1113.active ) ) {
12906					jQuery1113.event.trigger("ajaxStop");
12907				}
12908			}
12909		}
12910
12911		return jqXHR;
12912	},
12913
12914	getJSON: function( url, data, callback ) {
12915		return jQuery1113.get( url, data, callback, "json" );
12916	},
12917
12918	getScript: function( url, callback ) {
12919		return jQuery1113.get( url, undefined, callback, "script" );
12920	}
12921});
12922
12923jQuery1113.each( [ "get", "post" ], function( i, method ) {
12924	jQuery1113[ method ] = function( url, data, callback, type ) {
12925		// shift arguments if data argument was omitted
12926		if ( jQuery1113.isFunction( data ) ) {
12927			type = type || callback;
12928			callback = data;
12929			data = undefined;
12930		}
12931
12932		return jQuery1113.ajax({
12933			url: url,
12934			type: method,
12935			dataType: type,
12936			data: data,
12937			success: callback
12938		});
12939	};
12940});
12941
12942
12943jQuery1113._evalUrl = function( url ) {
12944	return jQuery1113.ajax({
12945		url: url,
12946		type: "GET",
12947		dataType: "script",
12948		async: false,
12949		global: false,
12950		"throws": true
12951	});
12952};
12953
12954
12955jQuery1113.fn.extend({
12956	wrapAll: function( html ) {
12957		if ( jQuery1113.isFunction( html ) ) {
12958			return this.each(function(i) {
12959				jQuery1113(this).wrapAll( html.call(this, i) );
12960			});
12961		}
12962
12963		if ( this[0] ) {
12964			// The elements to wrap the target around
12965			var wrap = jQuery1113( html, this[0].ownerDocument ).eq(0).clone(true);
12966
12967			if ( this[0].parentNode ) {
12968				wrap.insertBefore( this[0] );
12969			}
12970
12971			wrap.map(function() {
12972				var elem = this;
12973
12974				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
12975					elem = elem.firstChild;
12976				}
12977
12978				return elem;
12979			}).append( this );
12980		}
12981
12982		return this;
12983	},
12984
12985	wrapInner: function( html ) {
12986		if ( jQuery1113.isFunction( html ) ) {
12987			return this.each(function(i) {
12988				jQuery1113(this).wrapInner( html.call(this, i) );
12989			});
12990		}
12991
12992		return this.each(function() {
12993			var self = jQuery1113( this ),
12994				contents = self.contents();
12995
12996			if ( contents.length ) {
12997				contents.wrapAll( html );
12998
12999			} else {
13000				self.append( html );
13001			}
13002		});
13003	},
13004
13005	wrap: function( html ) {
13006		var isFunction = jQuery1113.isFunction( html );
13007
13008		return this.each(function(i) {
13009			jQuery1113( this ).wrapAll( isFunction ? html.call(this, i) : html );
13010		});
13011	},
13012
13013	unwrap: function() {
13014		return this.parent().each(function() {
13015			if ( !jQuery1113.nodeName( this, "body" ) ) {
13016				jQuery1113( this ).replaceWith( this.childNodes );
13017			}
13018		}).end();
13019	}
13020});
13021
13022
13023jQuery1113.expr.filters.hidden = function( elem ) {
13024	// Support: Opera <= 12.12
13025	// Opera reports offsetWidths and offsetHeights less than zero on some elements
13026	return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
13027		(!support.reliableHiddenOffsets() &&
13028			((elem.style && elem.style.display) || jQuery1113.css( elem, "display" )) === "none");
13029};
13030
13031jQuery1113.expr.filters.visible = function( elem ) {
13032	return !jQuery1113.expr.filters.hidden( elem );
13033};
13034
13035
13036
13037
13038var r20 = /%20/g,
13039	rbracket = /\[\]$/,
13040	rCRLF = /\r?\n/g,
13041	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
13042	rsubmittable = /^(?:input|select|textarea|keygen)/i;
13043
13044function buildParams( prefix, obj, traditional, add ) {
13045	var name;
13046
13047	if ( jQuery1113.isArray( obj ) ) {
13048		// Serialize array item.
13049		jQuery1113.each( obj, function( i, v ) {
13050			if ( traditional || rbracket.test( prefix ) ) {
13051				// Treat each array item as a scalar.
13052				add( prefix, v );
13053
13054			} else {
13055				// Item is non-scalar (array or object), encode its numeric index.
13056				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
13057			}
13058		});
13059
13060	} else if ( !traditional && jQuery1113.type( obj ) === "object" ) {
13061		// Serialize object item.
13062		for ( name in obj ) {
13063			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
13064		}
13065
13066	} else {
13067		// Serialize scalar item.
13068		add( prefix, obj );
13069	}
13070}
13071
13072// Serialize an array of form elements or a set of
13073// key/values into a query string
13074jQuery1113.param = function( a, traditional ) {
13075	var prefix,
13076		s = [],
13077		add = function( key, value ) {
13078			// If value is a function, invoke it and return its value
13079			value = jQuery1113.isFunction( value ) ? value() : ( value == null ? "" : value );
13080			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
13081		};
13082
13083	// Set traditional to true for jQuery1113 <= 1.3.2 behavior.
13084	if ( traditional === undefined ) {
13085		traditional = jQuery1113.ajaxSettings && jQuery1113.ajaxSettings.traditional;
13086	}
13087
13088	// If an array was passed in, assume that it is an array of form elements.
13089	if ( jQuery1113.isArray( a ) || ( a.jQuery1113 && !jQuery1113.isPlainObject( a ) ) ) {
13090		// Serialize the form elements
13091		jQuery1113.each( a, function() {
13092			add( this.name, this.value );
13093		});
13094
13095	} else {
13096		// If traditional, encode the "old" way (the way 1.3.2 or older
13097		// did it), otherwise encode params recursively.
13098		for ( prefix in a ) {
13099			buildParams( prefix, a[ prefix ], traditional, add );
13100		}
13101	}
13102
13103	// Return the resulting serialization
13104	return s.join( "&" ).replace( r20, "+" );
13105};
13106
13107jQuery1113.fn.extend({
13108	serialize: function() {
13109		return jQuery1113.param( this.serializeArray() );
13110	},
13111	serializeArray: function() {
13112		return this.map(function() {
13113			// Can add propHook for "elements" to filter or add form elements
13114			var elements = jQuery1113.prop( this, "elements" );
13115			return elements ? jQuery1113.makeArray( elements ) : this;
13116		})
13117		.filter(function() {
13118			var type = this.type;
13119			// Use .is(":disabled") so that fieldset[disabled] works
13120			return this.name && !jQuery1113( this ).is( ":disabled" ) &&
13121				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
13122				( this.checked || !rcheckableType.test( type ) );
13123		})
13124		.map(function( i, elem ) {
13125			var val = jQuery1113( this ).val();
13126
13127			return val == null ?
13128				null :
13129				jQuery1113.isArray( val ) ?
13130					jQuery1113.map( val, function( val ) {
13131						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
13132					}) :
13133					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
13134		}).get();
13135	}
13136});
13137
13138
13139// Create the request object
13140// (This is still attached to ajaxSettings for backward compatibility)
13141jQuery1113.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
13142	// Support: IE6+
13143	function() {
13144
13145		// XHR cannot access local files, always use ActiveX for that case
13146		return !this.isLocal &&
13147
13148			// Support: IE7-8
13149			// oldIE XHR does not support non-RFC2616 methods (#13240)
13150			// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
13151			// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
13152			// Although this check for six methods instead of eight
13153			// since IE also does not support "trace" and "connect"
13154			/^(get|post|head|put|delete|options)$/i.test( this.type ) &&
13155
13156			createStandardXHR() || createActiveXHR();
13157	} :
13158	// For all other browsers, use the standard XMLHttpRequest object
13159	createStandardXHR;
13160
13161var xhrId = 0,
13162	xhrCallbacks = {},
13163	xhrSupported = jQuery1113.ajaxSettings.xhr();
13164
13165// Support: IE<10
13166// Open requests must be manually aborted on unload (#5280)
13167// See https://support.microsoft.com/kb/2856746 for more info
13168if ( window.attachEvent ) {
13169	window.attachEvent( "onunload", function() {
13170		for ( var key in xhrCallbacks ) {
13171			xhrCallbacks[ key ]( undefined, true );
13172		}
13173	});
13174}
13175
13176// Determine support properties
13177support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
13178xhrSupported = support.ajax = !!xhrSupported;
13179
13180// Create transport if the browser can provide an xhr
13181if ( xhrSupported ) {
13182
13183	jQuery1113.ajaxTransport(function( options ) {
13184		// Cross domain only allowed if supported through XMLHttpRequest
13185		if ( !options.crossDomain || support.cors ) {
13186
13187			var callback;
13188
13189			return {
13190				send: function( headers, complete ) {
13191					var i,
13192						xhr = options.xhr(),
13193						id = ++xhrId;
13194
13195					// Open the socket
13196					xhr.open( options.type, options.url, options.async, options.username, options.password );
13197
13198					// Apply custom fields if provided
13199					if ( options.xhrFields ) {
13200						for ( i in options.xhrFields ) {
13201							xhr[ i ] = options.xhrFields[ i ];
13202						}
13203					}
13204
13205					// Override mime type if needed
13206					if ( options.mimeType && xhr.overrideMimeType ) {
13207						xhr.overrideMimeType( options.mimeType );
13208					}
13209
13210					// X-Requested-With header
13211					// For cross-domain requests, seeing as conditions for a preflight are
13212					// akin to a jigsaw puzzle, we simply never set it to be sure.
13213					// (it can always be set on a per-request basis or even using ajaxSetup)
13214					// For same-domain requests, won't change header if already provided.
13215					if ( !options.crossDomain && !headers["X-Requested-With"] ) {
13216						headers["X-Requested-With"] = "XMLHttpRequest";
13217					}
13218
13219					// Set headers
13220					for ( i in headers ) {
13221						// Support: IE<9
13222						// IE's ActiveXObject throws a 'Type Mismatch' exception when setting
13223						// request header to a null-value.
13224						//
13225						// To keep consistent with other XHR implementations, cast the value
13226						// to string and ignore `undefined`.
13227						if ( headers[ i ] !== undefined ) {
13228							xhr.setRequestHeader( i, headers[ i ] + "" );
13229						}
13230					}
13231
13232					// Do send the request
13233					// This may raise an exception which is actually
13234					// handled in jQuery1113.ajax (so no try/catch here)
13235					xhr.send( ( options.hasContent && options.data ) || null );
13236
13237					// Listener
13238					callback = function( _, isAbort ) {
13239						var status, statusText, responses;
13240
13241						// Was never called and is aborted or complete
13242						if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
13243							// Clean up
13244							delete xhrCallbacks[ id ];
13245							callback = undefined;
13246							xhr.onreadystatechange = jQuery1113.noop;
13247
13248							// Abort manually if needed
13249							if ( isAbort ) {
13250								if ( xhr.readyState !== 4 ) {
13251									xhr.abort();
13252								}
13253							} else {
13254								responses = {};
13255								status = xhr.status;
13256
13257								// Support: IE<10
13258								// Accessing binary-data responseText throws an exception
13259								// (#11426)
13260								if ( typeof xhr.responseText === "string" ) {
13261									responses.text = xhr.responseText;
13262								}
13263
13264								// Firefox throws an exception when accessing
13265								// statusText for faulty cross-domain requests
13266								try {
13267									statusText = xhr.statusText;
13268								} catch( e ) {
13269									// We normalize with Webkit giving an empty statusText
13270									statusText = "";
13271								}
13272
13273								// Filter status for non standard behaviors
13274
13275								// If the request is local and we have data: assume a success
13276								// (success with no data won't get notified, that's the best we
13277								// can do given current implementations)
13278								if ( !status && options.isLocal && !options.crossDomain ) {
13279									status = responses.text ? 200 : 404;
13280								// IE - #1450: sometimes returns 1223 when it should be 204
13281								} else if ( status === 1223 ) {
13282									status = 204;
13283								}
13284							}
13285						}
13286
13287						// Call complete if needed
13288						if ( responses ) {
13289							complete( status, statusText, responses, xhr.getAllResponseHeaders() );
13290						}
13291					};
13292
13293					if ( !options.async ) {
13294						// if we're in sync mode we fire the callback
13295						callback();
13296					} else if ( xhr.readyState === 4 ) {
13297						// (IE6 & IE7) if it's in cache and has been
13298						// retrieved directly we need to fire the callback
13299						setTimeout( callback );
13300					} else {
13301						// Add to the list of active xhr callbacks
13302						xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
13303					}
13304				},
13305
13306				abort: function() {
13307					if ( callback ) {
13308						callback( undefined, true );
13309					}
13310				}
13311			};
13312		}
13313	});
13314}
13315
13316// Functions to create xhrs
13317function createStandardXHR() {
13318	try {
13319		return new window.XMLHttpRequest();
13320	} catch( e ) {}
13321}
13322
13323function createActiveXHR() {
13324	try {
13325		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
13326	} catch( e ) {}
13327}
13328
13329
13330
13331
13332// Install script dataType
13333jQuery1113.ajaxSetup({
13334	accepts: {
13335		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
13336	},
13337	contents: {
13338		script: /(?:java|ecma)script/
13339	},
13340	converters: {
13341		"text script": function( text ) {
13342			jQuery1113.globalEval( text );
13343			return text;
13344		}
13345	}
13346});
13347
13348// Handle cache's special case and global
13349jQuery1113.ajaxPrefilter( "script", function( s ) {
13350	if ( s.cache === undefined ) {
13351		s.cache = false;
13352	}
13353	if ( s.crossDomain ) {
13354		s.type = "GET";
13355		s.global = false;
13356	}
13357});
13358
13359// Bind script tag hack transport
13360jQuery1113.ajaxTransport( "script", function(s) {
13361
13362	// This transport only deals with cross domain requests
13363	if ( s.crossDomain ) {
13364
13365		var script,
13366			head = document.head || jQuery1113("head")[0] || document.documentElement;
13367
13368		return {
13369
13370			send: function( _, callback ) {
13371
13372				script = document.createElement("script");
13373
13374				script.async = true;
13375
13376				if ( s.scriptCharset ) {
13377					script.charset = s.scriptCharset;
13378				}
13379
13380				script.src = s.url;
13381
13382				// Attach handlers for all browsers
13383				script.onload = script.onreadystatechange = function( _, isAbort ) {
13384
13385					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
13386
13387						// Handle memory leak in IE
13388						script.onload = script.onreadystatechange = null;
13389
13390						// Remove the script
13391						if ( script.parentNode ) {
13392							script.parentNode.removeChild( script );
13393						}
13394
13395						// Dereference the script
13396						script = null;
13397
13398						// Callback if not abort
13399						if ( !isAbort ) {
13400							callback( 200, "success" );
13401						}
13402					}
13403				};
13404
13405				// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
13406				// Use native DOM manipulation to avoid our domManip AJAX trickery
13407				head.insertBefore( script, head.firstChild );
13408			},
13409
13410			abort: function() {
13411				if ( script ) {
13412					script.onload( undefined, true );
13413				}
13414			}
13415		};
13416	}
13417});
13418
13419
13420
13421
13422var oldCallbacks = [],
13423	rjsonp = /(=)\?(?=&|$)|\?\?/;
13424
13425// Default jsonp settings
13426jQuery1113.ajaxSetup({
13427	jsonp: "callback",
13428	jsonpCallback: function() {
13429		var callback = oldCallbacks.pop() || ( jQuery1113.expando + "_" + ( nonce++ ) );
13430		this[ callback ] = true;
13431		return callback;
13432	}
13433});
13434
13435// Detect, normalize options and install callbacks for jsonp requests
13436jQuery1113.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
13437
13438	var callbackName, overwritten, responseContainer,
13439		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
13440			"url" :
13441			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
13442		);
13443
13444	// Handle iff the expected data type is "jsonp" or we have a parameter to set
13445	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
13446
13447		// Get callback name, remembering preexisting value associated with it
13448		callbackName = s.jsonpCallback = jQuery1113.isFunction( s.jsonpCallback ) ?
13449			s.jsonpCallback() :
13450			s.jsonpCallback;
13451
13452		// Insert callback into url or form data
13453		if ( jsonProp ) {
13454			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
13455		} else if ( s.jsonp !== false ) {
13456			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
13457		}
13458
13459		// Use data converter to retrieve json after script execution
13460		s.converters["script json"] = function() {
13461			if ( !responseContainer ) {
13462				jQuery1113.error( callbackName + " was not called" );
13463			}
13464			return responseContainer[ 0 ];
13465		};
13466
13467		// force json dataType
13468		s.dataTypes[ 0 ] = "json";
13469
13470		// Install callback
13471		overwritten = window[ callbackName ];
13472		window[ callbackName ] = function() {
13473			responseContainer = arguments;
13474		};
13475
13476		// Clean-up function (fires after converters)
13477		jqXHR.always(function() {
13478			// Restore preexisting value
13479			window[ callbackName ] = overwritten;
13480
13481			// Save back as free
13482			if ( s[ callbackName ] ) {
13483				// make sure that re-using the options doesn't screw things around
13484				s.jsonpCallback = originalSettings.jsonpCallback;
13485
13486				// save the callback name for future use
13487				oldCallbacks.push( callbackName );
13488			}
13489
13490			// Call if it was a function and we have a response
13491			if ( responseContainer && jQuery1113.isFunction( overwritten ) ) {
13492				overwritten( responseContainer[ 0 ] );
13493			}
13494
13495			responseContainer = overwritten = undefined;
13496		});
13497
13498		// Delegate to script
13499		return "script";
13500	}
13501});
13502
13503
13504
13505
13506// data: string of html
13507// context (optional): If specified, the fragment will be created in this context, defaults to document
13508// keepScripts (optional): If true, will include scripts passed in the html string
13509jQuery1113.parseHTML = function( data, context, keepScripts ) {
13510	if ( !data || typeof data !== "string" ) {
13511		return null;
13512	}
13513	if ( typeof context === "boolean" ) {
13514		keepScripts = context;
13515		context = false;
13516	}
13517	context = context || document;
13518
13519	var parsed = rsingleTag.exec( data ),
13520		scripts = !keepScripts && [];
13521
13522	// Single tag
13523	if ( parsed ) {
13524		return [ context.createElement( parsed[1] ) ];
13525	}
13526
13527	parsed = jQuery1113.buildFragment( [ data ], context, scripts );
13528
13529	if ( scripts && scripts.length ) {
13530		jQuery1113( scripts ).remove();
13531	}
13532
13533	return jQuery1113.merge( [], parsed.childNodes );
13534};
13535
13536
13537// Keep a copy of the old load method
13538var _load = jQuery1113.fn.load;
13539
13540/**
13541 * Load a url into a page
13542 */
13543jQuery1113.fn.load = function( url, params, callback ) {
13544	if ( typeof url !== "string" && _load ) {
13545		return _load.apply( this, arguments );
13546	}
13547
13548	var selector, response, type,
13549		self = this,
13550		off = url.indexOf(" ");
13551
13552	if ( off >= 0 ) {
13553		selector = jQuery1113.trim( url.slice( off, url.length ) );
13554		url = url.slice( 0, off );
13555	}
13556
13557	// If it's a function
13558	if ( jQuery1113.isFunction( params ) ) {
13559
13560		// We assume that it's the callback
13561		callback = params;
13562		params = undefined;
13563
13564	// Otherwise, build a param string
13565	} else if ( params && typeof params === "object" ) {
13566		type = "POST";
13567	}
13568
13569	// If we have elements to modify, make the request
13570	if ( self.length > 0 ) {
13571		jQuery1113.ajax({
13572			url: url,
13573
13574			// if "type" variable is undefined, then "GET" method will be used
13575			type: type,
13576			dataType: "html",
13577			data: params
13578		}).done(function( responseText ) {
13579
13580			// Save response for use in complete callback
13581			response = arguments;
13582
13583			self.html( selector ?
13584
13585				// If a selector was specified, locate the right elements in a dummy div
13586				// Exclude scripts to avoid IE 'Permission Denied' errors
13587				jQuery1113("<div>").append( jQuery1113.parseHTML( responseText ) ).find( selector ) :
13588
13589				// Otherwise use the full result
13590				responseText );
13591
13592		}).complete( callback && function( jqXHR, status ) {
13593			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
13594		});
13595	}
13596
13597	return this;
13598};
13599
13600
13601
13602
13603// Attach a bunch of functions for handling common AJAX events
13604jQuery1113.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
13605	jQuery1113.fn[ type ] = function( fn ) {
13606		return this.on( type, fn );
13607	};
13608});
13609
13610
13611
13612
13613jQuery1113.expr.filters.animated = function( elem ) {
13614	return jQuery1113.grep(jQuery1113.timers, function( fn ) {
13615		return elem === fn.elem;
13616	}).length;
13617};
13618
13619
13620
13621
13622
13623var docElem = window.document.documentElement;
13624
13625/**
13626 * Gets a window from an element
13627 */
13628function getWindow( elem ) {
13629	return jQuery1113.isWindow( elem ) ?
13630		elem :
13631		elem.nodeType === 9 ?
13632			elem.defaultView || elem.parentWindow :
13633			false;
13634}
13635
13636jQuery1113.offset = {
13637	setOffset: function( elem, options, i ) {
13638		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
13639			position = jQuery1113.css( elem, "position" ),
13640			curElem = jQuery1113( elem ),
13641			props = {};
13642
13643		// set position first, in-case top/left are set even on static elem
13644		if ( position === "static" ) {
13645			elem.style.position = "relative";
13646		}
13647
13648		curOffset = curElem.offset();
13649		curCSSTop = jQuery1113.css( elem, "top" );
13650		curCSSLeft = jQuery1113.css( elem, "left" );
13651		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
13652			jQuery1113.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
13653
13654		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
13655		if ( calculatePosition ) {
13656			curPosition = curElem.position();
13657			curTop = curPosition.top;
13658			curLeft = curPosition.left;
13659		} else {
13660			curTop = parseFloat( curCSSTop ) || 0;
13661			curLeft = parseFloat( curCSSLeft ) || 0;
13662		}
13663
13664		if ( jQuery1113.isFunction( options ) ) {
13665			options = options.call( elem, i, curOffset );
13666		}
13667
13668		if ( options.top != null ) {
13669			props.top = ( options.top - curOffset.top ) + curTop;
13670		}
13671		if ( options.left != null ) {
13672			props.left = ( options.left - curOffset.left ) + curLeft;
13673		}
13674
13675		if ( "using" in options ) {
13676			options.using.call( elem, props );
13677		} else {
13678			curElem.css( props );
13679		}
13680	}
13681};
13682
13683jQuery1113.fn.extend({
13684	offset: function( options ) {
13685		if ( arguments.length ) {
13686			return options === undefined ?
13687				this :
13688				this.each(function( i ) {
13689					jQuery1113.offset.setOffset( this, options, i );
13690				});
13691		}
13692
13693		var docElem, win,
13694			box = { top: 0, left: 0 },
13695			elem = this[ 0 ],
13696			doc = elem && elem.ownerDocument;
13697
13698		if ( !doc ) {
13699			return;
13700		}
13701
13702		docElem = doc.documentElement;
13703
13704		// Make sure it's not a disconnected DOM node
13705		if ( !jQuery1113.contains( docElem, elem ) ) {
13706			return box;
13707		}
13708
13709		// If we don't have gBCR, just use 0,0 rather than error
13710		// BlackBerry 5, iOS 3 (original iPhone)
13711		if ( typeof elem.getBoundingClientRect !== strundefined ) {
13712			box = elem.getBoundingClientRect();
13713		}
13714		win = getWindow( doc );
13715		return {
13716			top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
13717			left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
13718		};
13719	},
13720
13721	position: function() {
13722		if ( !this[ 0 ] ) {
13723			return;
13724		}
13725
13726		var offsetParent, offset,
13727			parentOffset = { top: 0, left: 0 },
13728			elem = this[ 0 ];
13729
13730		// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
13731		if ( jQuery1113.css( elem, "position" ) === "fixed" ) {
13732			// we assume that getBoundingClientRect is available when computed position is fixed
13733			offset = elem.getBoundingClientRect();
13734		} else {
13735			// Get *real* offsetParent
13736			offsetParent = this.offsetParent();
13737
13738			// Get correct offsets
13739			offset = this.offset();
13740			if ( !jQuery1113.nodeName( offsetParent[ 0 ], "html" ) ) {
13741				parentOffset = offsetParent.offset();
13742			}
13743
13744			// Add offsetParent borders
13745			parentOffset.top  += jQuery1113.css( offsetParent[ 0 ], "borderTopWidth", true );
13746			parentOffset.left += jQuery1113.css( offsetParent[ 0 ], "borderLeftWidth", true );
13747		}
13748
13749		// Subtract parent offsets and element margins
13750		// note: when an element has margin: auto the offsetLeft and marginLeft
13751		// are the same in Safari causing offset.left to incorrectly be 0
13752		return {
13753			top:  offset.top  - parentOffset.top - jQuery1113.css( elem, "marginTop", true ),
13754			left: offset.left - parentOffset.left - jQuery1113.css( elem, "marginLeft", true)
13755		};
13756	},
13757
13758	offsetParent: function() {
13759		return this.map(function() {
13760			var offsetParent = this.offsetParent || docElem;
13761
13762			while ( offsetParent && ( !jQuery1113.nodeName( offsetParent, "html" ) && jQuery1113.css( offsetParent, "position" ) === "static" ) ) {
13763				offsetParent = offsetParent.offsetParent;
13764			}
13765			return offsetParent || docElem;
13766		});
13767	}
13768});
13769
13770// Create scrollLeft and scrollTop methods
13771jQuery1113.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
13772	var top = /Y/.test( prop );
13773
13774	jQuery1113.fn[ method ] = function( val ) {
13775		return access( this, function( elem, method, val ) {
13776			var win = getWindow( elem );
13777
13778			if ( val === undefined ) {
13779				return win ? (prop in win) ? win[ prop ] :
13780					win.document.documentElement[ method ] :
13781					elem[ method ];
13782			}
13783
13784			if ( win ) {
13785				win.scrollTo(
13786					!top ? val : jQuery1113( win ).scrollLeft(),
13787					top ? val : jQuery1113( win ).scrollTop()
13788				);
13789
13790			} else {
13791				elem[ method ] = val;
13792			}
13793		}, method, val, arguments.length, null );
13794	};
13795});
13796
13797// Add the top/left cssHooks using jQuery1113.fn.position
13798// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
13799// getComputedStyle returns percent when specified for top/left/bottom/right
13800// rather than make the css module depend on the offset module, we just check for it here
13801jQuery1113.each( [ "top", "left" ], function( i, prop ) {
13802	jQuery1113.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
13803		function( elem, computed ) {
13804			if ( computed ) {
13805				computed = curCSS( elem, prop );
13806				// if curCSS returns percentage, fallback to offset
13807				return rnumnonpx.test( computed ) ?
13808					jQuery1113( elem ).position()[ prop ] + "px" :
13809					computed;
13810			}
13811		}
13812	);
13813});
13814
13815
13816// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
13817jQuery1113.each( { Height: "height", Width: "width" }, function( name, type ) {
13818	jQuery1113.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
13819		// margin is only for outerHeight, outerWidth
13820		jQuery1113.fn[ funcName ] = function( margin, value ) {
13821			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
13822				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
13823
13824			return access( this, function( elem, type, value ) {
13825				var doc;
13826
13827				if ( jQuery1113.isWindow( elem ) ) {
13828					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
13829					// isn't a whole lot we can do. See pull request at this URL for discussion:
13830					// https://github.com/jQuery1113/jQuery1113/pull/764
13831					return elem.document.documentElement[ "client" + name ];
13832				}
13833
13834				// Get document width or height
13835				if ( elem.nodeType === 9 ) {
13836					doc = elem.documentElement;
13837
13838					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
13839					// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
13840					return Math.max(
13841						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
13842						elem.body[ "offset" + name ], doc[ "offset" + name ],
13843						doc[ "client" + name ]
13844					);
13845				}
13846
13847				return value === undefined ?
13848					// Get width or height on the element, requesting but not forcing parseFloat
13849					jQuery1113.css( elem, type, extra ) :
13850
13851					// Set width or height on the element
13852					jQuery1113.style( elem, type, value, extra );
13853			}, type, chainable ? margin : undefined, chainable, null );
13854		};
13855	});
13856});
13857
13858
13859// The number of elements contained in the matched element set
13860jQuery1113.fn.size = function() {
13861	return this.length;
13862};
13863
13864jQuery1113.fn.andSelf = jQuery1113.fn.addBack;
13865
13866
13867
13868
13869// Register as a named AMD module, since jQuery1113 can be concatenated with other
13870// files that may use define, but not via a proper concatenation script that
13871// understands anonymous AMD modules. A named AMD is safest and most robust
13872// way to register. Lowercase jQuery1113 is used because AMD module names are
13873// derived from file names, and jQuery1113 is normally delivered in a lowercase
13874// file name. Do this after creating the global so that if an AMD module wants
13875// to call noConflict to hide this version of jQuery1113, it will work.
13876
13877// Note that for maximum portability, libraries that are not jQuery1113 should
13878// declare themselves as anonymous modules, and avoid setting a global if an
13879// AMD loader is present. jQuery1113 is a special case. For more information, see
13880// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
13881
13882if ( typeof define === "function" && define.amd ) {
13883	define( "jQuery1113", [], function() {
13884		return jQuery1113;
13885	});
13886}
13887
13888
13889
13890
13891var
13892	// Map over jQuery1113 in case of overwrite
13893	_jQuery1113 = window.jQuery1113,
13894
13895	// Map over the $ in case of overwrite
13896	_$ = window.$;
13897
13898jQuery1113.noConflict = function( deep ) {
13899	if ( window.$ === jQuery1113 ) {
13900		window.$ = _$;
13901	}
13902
13903	if ( deep && window.jQuery1113 === jQuery1113 ) {
13904		window.jQuery1113 = _jQuery1113;
13905	}
13906
13907	return jQuery1113;
13908};
13909
13910// Expose jQuery1113 and $ identifiers, even in
13911// AMD (#7102#comment:10, https://github.com/jQuery1113/jQuery1113/pull/557)
13912// and CommonJS for browser emulators (#13566)
13913if ( typeof noGlobal === strundefined ) {
13914	window.jQuery1113 = window.$ = jQuery1113;
13915}
13916
13917
13918
13919
13920return jQuery1113;
13921
13922}));
13923
13924
13925var j = jQuery1113.noConflict();! function(e) {
13926    var i = {
13927        logo_align: "left",
13928        links_align: "left",
13929        socialBar_align: "left",
13930        searchBar_align: "right",
13931        trigger: "hover",
13932        effect: "fade",
13933        effect_speed: 400,
13934        sibling: !0,
13935        outside_click_close: !0,
13936        top_fixed: !1,
13937        sticky_header: !1,
13938        sticky_header_height: 200,
13939        menu_position: "horizontal",
13940        full_width: !0,
13941        mobile_settings: {
13942            collapse: !1,
13943            sibling: !0,
13944            scrollBar: !0,
13945            scrollBar_height: 400,
13946            top_fixed: !1,
13947            sticky_header: !1,
13948            sticky_header_height: 200
13949        }
13950    };
13951    e.fn.megaMenu = function(o) {
13952        return o = e.extend({}, i, o || {}), this.each(function() {
13953            var i, s = e(this),
13954                t = "ul",
13955                n = "li",
13956                a = "a",
13957                r = s.find(".menu-logo"),
13958                l = r.children(n),
13959                d = s.find(".menu-links"),
13960                c = d.children(n),
13961                f = s.find(".menu-social-bar"),
13962                _ = s.find(".menu-search-bar"),
13963                p = ".menu-mobile-collapse-trigger",
13964                g = ".mobileTriggerButton",
13965                u = ".desktopTriggerButton",
13966                h = "active",
13967                m = "activeTrigger",
13968                b = "activeTriggerMobile",
13969                v = ".mg-drop-down-multilevel, .mg-drop-down, .mg-drop-down-tab-bar",
13970                C = "desktopTopFixed",
13971                w = "mobileTopFixed",
13972                k = "menuFullWidth",
13973                y = s.find(".menu-contact-form"),
13974                x = y.find(".nav_form_notification");
13975            i = {
13976                contact_form_ajax: function() {
13977                    e(y).submit(function(i) {
13978                        var o = e(this);
13979                        i.preventDefault();
13980                        var s = e(this).serialize();
13981                        o.find("button i.fa").css("display", "inline-block"), e.ajax({
13982                            type: "POST",
13983                            url: e(this).attr("action"),
13984                            data: s
13985                        }).done(function(e) {
13986                            x.text(e), o.find('input[type="text"]').val(""), o.find('input[type="email"]').val(""), o.find("textarea").val(""), o.find("button i.fa").css("display", "none")
13987                        }).fail(function(e) {
13988                            "" !== e.responseText && x.text("Error"), o.find("button i.fa").css("display", "none")
13989                        })
13990                    })
13991                },
13992                menu_full_width: function() {
13993                    o.full_width === !0 && s.addClass(k)
13994                },
13995                logo_Align: function() {
13996                    "right" === o.logo_align ? r.addClass("menu-logo-align-right") : r.removeClass("menu-logo-align-right")
13997                },
13998                links_Align: function() {
13999                    "right" === o.links_align ? d.addClass("menu-links-align-right") : d.removeClass("menu-links-align-right")
14000                },
14001                social_bar_Align: function() {
14002                    "right" === o.socialBar_align ? f.addClass("menu-social-bar-right") : f.removeClass("menu-social-bar-right")
14003                },
14004                search_bar_Align: function() {
14005                    "left" === o.searchBar_align ? _.addClass("menu-search-bar-left") : _.removeClass("menu-search-bar-left")
14006                },
14007                collapse_trigger_button: function() {
14008                    if (o.mobile_settings.collapse === !0) {
14009                        l.append('<div class="menu-mobile-collapse-trigger"><span></span></div>');
14010                        var i = d.add(f);
14011                        i.hide(0), _.addClass(h), s.find(p).on("click", function() {
14012                            return i.is(":hidden") ? (e(this).addClass(h), i.show(0)) : (e(this).removeClass(h), i.hide(0)), !1
14013                        })
14014                    }
14015                },
14016                switch_effect_remove: function() {
14017                    s.find(v).removeClass("effect-fade effect-scale effect-expand-top effect-expand-bottom effect-expand-left effect-expand-right")
14018                },
14019                switch_effects: function() {
14020                    switch (o.effect) {
14021                        case "fade":
14022                            this.switch_effect_remove(), s.find(v).addClass("effect-fade");
14023                            break;
14024                        case "scale":
14025                            this.switch_effect_remove(), s.find(v).addClass("effect-scale");
14026                            break;
14027                        case "expand-top":
14028                            this.switch_effect_remove(), s.find(v).addClass("effect-expand-top");
14029                            break;
14030                        case "expand-bottom":
14031                            this.switch_effect_remove(), s.find(v).addClass("effect-expand-bottom");
14032                            break;
14033                        case "expand-left":
14034                            this.switch_effect_remove(), s.find(v).addClass("effect-expand-left");
14035                            break;
14036                        case "expand-right":
14037                            this.switch_effect_remove(), s.find(v).addClass("effect-expand-right")
14038                    }
14039                },
14040                transition_delay: function() {
14041                    s.find(v).css({
14042                        webkitTransition: "all " + o.effect_speed + "ms ease ",
14043                        transition: "all " + o.effect_speed + "ms ease "
14044                    })
14045                },
14046                hover_trigger: function() {
14047                    "hover" === o.trigger && (i.transition_delay(), s.find(v).parents(n).addClass("hoverTrigger"), i.switch_effects())
14048                },
14049                mobile_trigger: function() {
14050                    0 === s.find(".mobileTriggerButton").length && s.find(v).prev(a).append('<div class="mobileTriggerButton"></div>'), 
14051                    s.find(g).each(function(){
14052                        $this=$(this);
14053                        $menuBox = $(this).parents('li').find('.megamenu_box');
14054                        //檢查有沒有副清單的內容
14055                        var menuBoxChildCount = 0;
14056                        $menuBox.children().each(function(){
14057                            if($(this).attr('class').toLowerCase() !== 'clearfix'){
14058                                menuBoxChildCount = menuBoxChildCount + 1;
14059                                return;
14060                            }
14061                        });
14062                        if (menuBoxChildCount === 0)
14063                            $this.parent().siblings('.mg-drop-down').removeClass('effect-fade');
14064                        $this.off("click").on("click", function() {
14065                            var i = e(this),
14066                                r = i.parents(a),
14067                                l = r.next(v);
14068                            //副清單沒有東西時,點這個div也觸發父node a
14069                            menuBoxChildCount === 0 ? r[0].click():"";
14070                            return l.is(":hidden") ? (o.mobile_settings.sibling === !0 && (i.parents(s).siblings(t + "," + n).find(v).hide(0), i.parents(s).siblings(n).removeClass(b), i.parents(s).siblings(t).find(n).removeClass(b)), r.parent(n).addClass(b), l.show(0)) : (r.parent(n).removeClass(b), l.hide(0)), !1
14071                        });
14072                    }), s.find("i.fa.fa-indicator").on("click", function() {
14073                        return !1
14074                    }),s.find(v).prev(a).on("click", function(el) {
14075                        var i = e(this),
14076                            l = i.next(v);
14077                        var iUrl = i.attr('href').trim().toLowerCase();
14078                        if (iUrl.startsWith('#') || iUrl.startsWith('javascript'))
14079                            return l.is(":hidden") ? (o.mobile_settings.sibling === !0 && (i.parents(s).siblings(t + "," + n).find(v).hide(0), i.parents(s).siblings(n).removeClass(b), i.parents(s).siblings(t).find(n).removeClass(b)), i.parent(n).addClass(b), l.show(0)) : (i.parent(n).removeClass(b), l.hide(0)), !1
14080                    })
14081                },
14082                click_trigger: function() {
14083                    "click" === o.trigger && (s.find(v).prev(a).append('<div class="desktopTriggerButton"></div>'), s.find(v).parents(n).addClass("ClickTrigger"), i.switch_effects(), i.transition_delay(), s.find(u).off("click").on("click", function(i) {
14084                        i.stopPropagation(), i.stopImmediatePropagation();
14085                        var r = e(this),
14086                            l = r.parents(a),
14087                            d = l.next(v);
14088                        d.hasClass(h) ? (l.parent(n).removeClass(m), d.removeClass(h)) : (o.sibling === !0 && (r.parents(s).siblings(t + "," + n).find(v).removeClass(h), r.parents(s).siblings(n).removeClass(m), r.parents(s).siblings(t).find(n).removeClass(m)), l.parent(n).addClass(m), d.addClass(h))
14089                    }))
14090                },
14091                outside_close: function() {
14092                    o.outside_click_close === !0 && "click" === o.trigger && s.find(v).is(":visible") ? e(document).off("
14092click").on("click", function(e) {
14093                        s.is(e.target) || 0 !== s.has(e.target).length || (s.find(v).removeClass(h), c.removeClass("activeTrigger"))
14094                    }) : e(document).off("click")
14095                },
14096                scroll_bar: function() {
14097                    o.mobile_settings.scrollBar === !0 && d.css({
14098                        maxHeight: o.mobile_settings.scrollBar_height + "px",
14099                        overflow: "auto"
14100                    })
14101                },
14102                top_Fixed: function() {
14103                    o.top_fixed === !0 ? s.addClass(C) : s.removeClass(C), o.mobile_settings.top_fixed ? s.addClass(w) : s.removeClass(w)
14104                },
14105                sticky_Header: function() {
14106                    var i = e(window),
14107                        t = !0,
14108                        n = !0;
14109                    s.find(v).is(":hidden") ? (i.off("scroll"), o.mobile_settings.sticky_header === !0 && o.top_fixed === !1 && i.on("scroll", function() {
14110                        i.scrollTop() > o.mobile_settings.sticky_header_height ? n === !0 && (s.addClass(w), n = !1) : n === !1 && (s.removeClass(w), n = !0)
14111                    })) : (i.off("scroll"), o.sticky_header === !0 && "horizontal" === o.menu_position && o.top_fixed === !1 && i.on("scroll", function() {
14112                        i.scrollTop() > o.sticky_header_height ? t === !0 && (s.fadeOut(200, function() {
14113                            e(this).addClass(C).fadeIn(200)
14114                        }), t = !1) : t === !1 && (s.fadeOut(200, function() {
14115                            e(this).removeClass(C).fadeIn(200)
14116                        }), t = !0)
14117                    }))
14118                },
14119                position: function() {
14120                    "vertical-left" === o.menu_position ? s.addClass("vertical-left") : s.removeClass("vertical-left"), "vertical-right" === o.menu_position ? s.addClass("vertical-right") : s.removeClass("vertical-right")
14121                },
14122                destroy_menu: function() {
14123                    s.find(v).parents(n).removeClass("hoverTrigger"), s.find(v).parents(n).removeClass("ClickTrigger")
14124                }
14125            }, i.destroy_menu(), i.menu_full_width(), i.logo_Align(), i.links_Align(), i.social_bar_Align(), i.search_bar_Align(), i.collapse_trigger_button(), i.hover_trigger(), i.mobile_trigger(), i.click_trigger(), i.outside_close(), i.scroll_bar(), i.top_Fixed(), i.sticky_Header(), i.position(), i.contact_form_ajax(), e(window).resize(function() {
14126                i.outside_close(), i.sticky_Header()
14127            })
14128        })
14129    }
14130}(jQuery1113);(function($) {
14131    $(function() {
14132        
14133        var $sel = $('[data-unicode="mdu_3FygDobCZE2PRdzXRuK2WQ"]');
14134        
14135        $sel.find('.menu-links > li.main-hover').hover(function () {
14136            if($(this).data('main-hover'))
14137                $(this).css('background', $(this).data('main-hover'));
14138        }, function () {
14139            if($(this).data('main-recovery'))
14140                $(this).css('background', $(this).data('main-recovery'));
14141            else
14142                $(this).css('background', '');
14143        })
14144
14145        $sel.find('.menu-links > li .list_box ul li a.sub-hover').hover(function () {
14146            if($(this).data('sub-hover'))
14147                $(this).css('color', $(this).data('sub-hover'));
14148        }, function () {
14149            if($(this).data('sub-recovery'))
14150                $(this).css('color', $(this).data('sub-recovery'));
14151            else
14152                $(this).css('color', '');
14153        });
14154
14155        //下拉選單沒有內容就不顯示
14156        $sel.find('.menu-links > li').each(function(){
14157            //ˇ箭頭的icon
14158            $icon = $(this).children('a').first().children('.fa-angle-down');
14159            $dropdown = $(this).find('.mg-drop-down');
14160            $menuBox = $(this).find('.megamenu_box');
14161            //menuBox空的話不需要顯示
14162            if($menuBox.children().length == 0)
14163            {
14164                $dropdown.addClass('d-none')
14165                $icon.addClass('d-none');
14166                return;
14167            }else {
14168                var menuBoxChildCount = 0;
14169                $menuBox.children().each(function(){
14170                    if($(this).attr('class').toLowerCase() !== 'clearfix'){
14171                        menuBoxChildCount = menuBoxChildCount + 1;
14172                        return;
14173                    }
14174                });
14175                //除了<div class='clearfix'></div>以外沒有東西的話不需要顯示。(備註:.clearfix這個目前不管怎樣都會生成20221004)
14176                if (menuBoxChildCount == 0){
14177                    $dropdown.addClass('d-none')
14178                    $icon.addClass('d-none');
14179                }
14180            }
14181        });
14182
14183        // menu initialize
14184        $sel.children('nav.mega-menu').megaMenu({
14185            // MOBILE MODE SETTINGS
14186            mobile_settings: {
14187                collapse: true,
14188                sibling: true,
14189                scrollBar: true,
14190                scrollBar_height: 400,
14191                top_fixed: false,
14192                sticky_header: false,
14193                sticky_header_height: 200
14194            }
14195        });
14196
14197    });
14198})(jQuery1113);
14199
14200; })(jQuery);/* compress error:[4]function encode(int) {*/
14201
14202/* MODULE e00fd3f0-0257-4fea-97f1-7b3d98c885e3, Version: 2.2.4 */
14203(function(a){(function(b){b(function(){})})(jQuery)})(jQuery);
14204/* MODULE 51efd658-95fe-4b29-bc4c-603c6613e893, Version: 1.0.8 */
14205(function(a){(function(b){b(function(){var e=b('[data-unicode="mdu_qpp0MeYTaUe6YixM5bqlKQ"]');var d=e.attr("data-unicode");var c=b("#"+d+"_btn");b(window).scroll(function(){if(b(window).scrollTop()>=100){c.css("z-index","99999999").fadeIn(300)}else{c.fadeOut(300)}});c.click(function(){b("html,body").animate({scrollTop:"0px"},800)})})})(jQuery)})(jQuery);
14206/* MODULE bc4f5320-b349-431d-b5c0-4b52b12fed62, Version: 2.3.6 */
14207;(function($) {var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
14208
14209// NB: does not validate input
14210function encode(int) {
14211    if (int === 0) {
14212        return CHARSET[0];
14213    }
14214
14215    var res = "";
14216    while (int > 0) {
14217        res = CHARSET[int % 62] + res;
14218        int = Math.floor(int / 62);
14219    }
14220    return res;
14221};
14222
14223function decode(str) {
14224    var res = 0,
14225        length = str.length,
14226        i, char;
14227    for (i = 0; i < length; i++) {
14228        char = str.charCodeAt(i);
14229        if (char < 58) { // 0-9
14230            char = char - 48;
14231        } else if (char < 91) { // A-Z
14232            char = char - 29;
14233        } else { // a-z
14234            char = char - 87;
14235        }
14236        res += char * Math.pow(62, length - i - 1);
14237    }
14238    return res;
14239};
14240
14241function base62() {
14242    var id; //base62
14243    do {
14244      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
14245    } while (id.match(/^[0-9]/i) !== null);
14246    return id;
14247}(function ($) {
14248    $(function () {
14249
14250        $('[data-unicode="mdu_yGP394lGEmQ7ZKCrOHryA"]').each(function () {
14251
14252            var $sel = $(this);
14253            var $color2 = $(this).data('li-after');
14254            var $color3 = $(this).data('hover-li');
14255            var $color4 = $(this).data('hover-hover');
14256            var id = base62();
14257
14258            $sel.attr('id', id);
14259
14260            $sel.on('click', '.menu-button', function (event) {
14261                $(this).next('ul').toggleClass('open');
14262            });
14263
14264            // 多層開合控制
14265            $sel.find('li.has-sub > a').on('click', function (e) {
14266                e.preventDefault();
14267                e.stopPropagation();
14268
14269                var $li = $(this).parent('li');
14270
14271                // 收起同層
14272                $li.siblings('.has-sub')
14273                    .removeClass('active')
14274                    .children('ul')
14275                    .stop(true, true)
14276                    .slideUp(200)
14277                    .removeAttr('style');
14278
14279                // 切換自己
14280                $li.toggleClass('active')
14281                    .children('ul')
14282                    .stop(true, true)
14283                    .slideToggle(200);
14284            });
14285
14286            $sel.prepend('<style type="text/css">' +
14287                '#' + id + ' .responsive-drop-down-menu > ul > li > ul > li {background:' + $color2 + ' !important;} ' +
14288                '#' + id + ' .responsive-drop-down-menu > ul > li:after {background:' + $color2 + ' !important;} ' +
14289                '#' + id + ' .responsive-drop-down-menu ul li ul li:hover:after {background:' + $color2 + ' !important;} ' +
14290                '#' + id + ' .responsive-drop-down-menu ul li ul li.active:after {background:' + $color2 + ' !important;} ' +
14291                '#' + id + ' .responsive-drop-down-menu ul li ul li:hover > ul > li {background:' + $color3 + ' !important;} ' +
14292                '#' + id + ' .responsive-drop-down-menu > ul > li:hover > ul > li:hover {background:' + $color3 + ' !important;} ' +
14293                '#' + id + ' .responsive-drop-down-menu ul li ul li:hover > ul > li:hover {background:' + $color4 + ' !important;}'
14294                + '</style>');
14295            /*
14296                        if($sel.data('li-after'))
14297                            $sel.prepend('<style type="text/css">#'+id+' .responsive-drop-down-menu > ul > li:after, #'+id+' .full-menu .responsive-drop-down-menu ul li ul li:hover:after, #'+id+ '.full-menu .responsive-drop-down-menu ul li ul li.active:after {background:'+$(this).data('li-after')+ !important;'}</style>');
14298                        if($sel.data('hover-li'))
14299                            $sel.prepend('<style type="text/css">#'+id+' .full-menu .responsive-drop-down-menu ul li ul li:hover > ul > li, #'+id+ '.full-menu .responsive-drop-down-menu > ul > li:hover > ul > li:hover {background:'+$(this).data('hover-li')+' !important;}</style>');
14300                        if($sel.data('hover-hover'))
14301                            $sel.prepend('<style type="text/css">#'+id+' .full-menu .responsive-drop-down-menu ul li ul li:hover > ul > li:hover {background:'+$(this).data('hover-hover')+' !important;}</style>');
14302            */
14303        });
14304
14305    });
14306})(jQuery);
14307; })(jQuery);/* compress error:[4]function encode(int) {*/
14308
14309/* MODULE ebe73f1b-af22-4d91-9ffe-a3edf5e4248b, Version: 2.1.12 */
14310(function(a){(function(b){b.expr[":"].regex=function(d,e,f){var g=f[3].split(","),j=/^(data|css):/,c={method:g[0].match(j)?g[0].split(":")[0]:"attr",property:g.shift().replace(j,"")},i="ig",h=new RegExp(g.join("").replace(/^\s+|\s+$/g,""),i);return h.test(jQuery(d)[c.method](c.property))};b(function(){var d=b('[data-unicode="mdu_OwNLpIh9YU2IXCsTq78NpA"]');d.find(".contact-box > p > a img:regex(src, .*.svg[/]*)").each(function(){var e=jQuery(this);var g=e.attr("id");var f=e.attr("class");var h=e.attr("src");jQuery.get(h,function(j){var i=jQuery(j).find("svg");if(typeof g!=="undefined"){i=i.attr("id",g)}if(typeof f!=="undefined"){i=i.attr("class",f+" replaced-svg")}i=i.removeAttr("xmlns:a");if(!i.attr("viewBox")&&i.attr("height")&&i.attr("width")){i.attr("viewBox","0 0 "+i.attr("height")+" "+i.attr("width"))}e.replaceWith(i)},"xml")});var c=d.data("notLgPadding");d.prepend('<style type="text/css">@media (max-width: 991px) {.footer-wrap .footer_center {padding-right:'+c+"!important; padding-left:"+c+"!important;}}</style>")})})(jQuery)})(jQuery);
14311/* MODULE 9e1d73c9-71ba-4925-a9a0-c97e617537ed, Version: 1.0.54 */
14312;(function($) {; var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
14313
14314// NB: does not validate input
14315function encode(int) {
14316    if (int === 0) {
14317        return CHARSET[0];
14318    }
14319
14320    var res = "";
14321    while (int > 0) {
14322        res = CHARSET[int % 62] + res;
14323        int = Math.floor(int / 62);
14324    }
14325    return res;
14326};
14327
14328function decode(str) {
14329    var res = 0,
14330        length = str.length,
14331        i, char;
14332    for (i = 0; i < length; i++) {
14333        char = str.charCodeAt(i);
14334        if (char < 58) { // 0-9
14335            char = char - 48;
14336        } else if (char < 91) { // A-Z
14337            char = char - 29;
14338        } else { // a-z
14339            char = char - 87;
14340        }
14341        res += char * Math.pow(62, length - i - 1);
14342    }
14343    return res;
14344};
14345
14346function base62() {
14347    var id; //base62
14348    do {
14349      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
14350    } while (id.match(/^[0-9]/i) !== null);
14351    return id;
14352}/*!
14353 * Datepicker for Bootstrap v1.9.0 (https://github.com/uxsolutions/bootstrap-datepicker)
14354 *
14355 * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
14356 */
14357
14358(function(factory){
14359    if (typeof define === 'function' && define.amd) {
14360        define(['jquery'], factory);
14361    } else if (typeof exports === 'object') {
14362        factory(require('jquery'));
14363    } else {
14364        factory(jQuery);
14365    }
14366}(function($, undefined){
14367	function UTCDate(){
14368		return new Date(Date.UTC.apply(Date, arguments));
14369	}
14370	function UTCToday(){
14371		var today = new Date();
14372		return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
14373	}
14374	function isUTCEquals(date1, date2) {
14375		return (
14376			date1.getUTCFullYear() === date2.getUTCFullYear() &&
14377			date1.getUTCMonth() === date2.getUTCMonth() &&
14378			date1.getUTCDate() === date2.getUTCDate()
14379		);
14380	}
14381	function alias(method, deprecationMsg){
14382		return function(){
14383			if (deprecationMsg !== undefined) {
14384				$.fn.datepicker.deprecated(deprecationMsg);
14385			}
14386
14387			return this[method].apply(this, arguments);
14388		};
14389	}
14390	function isValidDate(d) {
14391		return d && !isNaN(d.getTime());
14392	}
14393
14394	var DateArray = (function(){
14395		var extras = {
14396			get: function(i){
14397				return this.slice(i)[0];
14398			},
14399			contains: function(d){
14400				// Array.indexOf is not cross-browser;
14401				// $.inArray doesn't work with Dates
14402				var val = d && d.valueOf();
14403				for (var i=0, l=this.length; i < l; i++)
14404          // Use date arithmetic to allow dates with different times to match
14405          if (0 <= this[i].valueOf() - val && this[i].valueOf() - val < 1000*60*60*24)
14406						return i;
14407				return -1;
14408			},
14409			remove: function(i){
14410				this.splice(i,1);
14411			},
14412			replace: function(new_array){
14413				if (!new_array)
14414					return;
14415				if (!$.isArray(new_array))
14416					new_array = [new_array];
14417				this.clear();
14418				this.push.apply(this, new_array);
14419			},
14420			clear: function(){
14421				this.length = 0;
14422			},
14423			copy: function(){
14424				var a = new DateArray();
14425				a.replace(this);
14426				return a;
14427			}
14428		};
14429
14430		return function(){
14431			var a = [];
14432			a.push.apply(a, arguments);
14433			$.extend(a, extras);
14434			return a;
14435		};
14436	})();
14437
14438
14439	// Picker object
14440
14441	var Datepicker = function(element, options){
14442		$.data(element, 'datepicker', this);
14443
14444		this._events = [];
14445		this._secondaryEvents = [];
14446
14447		this._process_options(options);
14448
14449		this.dates = new DateArray();
14450		this.viewDate = this.o.defaultViewDate;
14451		this.focusDate = null;
14452
14453		this.element = $(element);
14454		this.isInput = this.element.is('input');
14455		this.inputField = this.isInput ? this.element : this.element.find('input');
14456		this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .input-group-append, .input-group-prepend, .btn') : false;
14457		if (this.component && this.component.length === 0)
14458			this.component = false;
14459		this.isInline = !this.component && this.element.is('div');
14460
14461		this.picker = $(DPGlobal.template);
14462
14463		// Checking templates and inserting
14464		if (this._check_template(this.o.templates.leftArrow)) {
14465			this.picker.find('.prev').html(this.o.templates.leftArrow);
14466		}
14467
14468		if (this._check_template(this.o.templates.rightArrow)) {
14469			this.picker.find('.next').html(this.o.templates.rightArrow);
14470		}
14471
14472		this._buildEvents();
14473		this._attachEvents();
14474
14475		if (this.isInline){
vendor: 56,186 bytes, lines 14476-16375
14476			this.picker.addClass('datepicker-inline').appendTo(this.element);
14477		}
14478		else {
14479			this.picker.addClass('datepicker-dropdown dropdown-menu');
14480		}
14481
14482		if (this.o.rtl){
14483			this.picker.addClass('datepicker-rtl');
14484		}
14485
14486		if (this.o.calendarWeeks) {
14487			this.picker.find('.datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear')
14488				.attr('colspan', function(i, val){
14489					return Number(val) + 1;
14490				});
14491		}
14492
14493		this._process_options({
14494			startDate: this._o.startDate,
14495			endDate: this._o.endDate,
14496			daysOfWeekDisabled: this.o.daysOfWeekDisabled,
14497			daysOfWeekHighlighted: this.o.daysOfWeekHighlighted,
14498			datesDisabled: this.o.datesDisabled
14499		});
14500
14501		this._allow_update = false;
14502		this.setViewMode(this.o.startView);
14503		this._allow_update = true;
14504
14505		this.fillDow();
14506		this.fillMonths();
14507
14508		this.update();
14509
14510		if (this.isInline){
14511			this.show();
14512		}
14513	};
14514
14515	Datepicker.prototype = {
14516		constructor: Datepicker,
14517
14518		_resolveViewName: function(view){
14519			$.each(DPGlobal.viewModes, function(i, viewMode){
14520				if (view === i || $.inArray(view, viewMode.names) !== -1){
14521					view = i;
14522					return false;
14523				}
14524			});
14525
14526			return view;
14527		},
14528
14529		_resolveDaysOfWeek: function(daysOfWeek){
14530			if (!$.isArray(daysOfWeek))
14531				daysOfWeek = daysOfWeek.split(/[,\s]*/);
14532			return $.map(daysOfWeek, Number);
14533		},
14534
14535		_check_template: function(tmp){
14536			try {
14537				// If empty
14538				if (tmp === undefined || tmp === "") {
14539					return false;
14540				}
14541				// If no html, everything ok
14542				if ((tmp.match(/[<>]/g) || []).length <= 0) {
14543					return true;
14544				}
14545				// Checking if html is fine
14546				var jDom = $(tmp);
14547				return jDom.length > 0;
14548			}
14549			catch (ex) {
14550				return false;
14551			}
14552		},
14553
14554		_process_options: function(opts){
14555			// Store raw options for reference
14556			this._o = $.extend({}, this._o, opts);
14557			// Processed options
14558			var o = this.o = $.extend({}, this._o);
14559
14560			// Check if "de-DE" style date is available, if not language should
14561			// fallback to 2 letter code eg "de"
14562			var lang = o.language;
14563			if (!dates[lang]){
14564				lang = lang.split('-')[0];
14565				if (!dates[lang])
14566					lang = defaults.language;
14567			}
14568			o.language = lang;
14569
14570			// Retrieve view index from any aliases
14571			o.startView = this._resolveViewName(o.startView);
14572			o.minViewMode = this._resolveViewName(o.minViewMode);
14573			o.maxViewMode = this._resolveViewName(o.maxViewMode);
14574
14575			// Check view is between min and max
14576			o.startView = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, o.startView));
14577
14578			// true, false, or Number > 0
14579			if (o.multidate !== true){
14580				o.multidate = Number(o.multidate) || false;
14581				if (o.multidate !== false)
14582					o.multidate = Math.max(0, o.multidate);
14583			}
14584			o.multidateSeparator = String(o.multidateSeparator);
14585
14586			o.weekStart %= 7;
14587			o.weekEnd = (o.weekStart + 6) % 7;
14588
14589			var format = DPGlobal.parseFormat(o.format);
14590			if (o.startDate !== -Infinity){
14591				if (!!o.startDate){
14592					if (o.startDate instanceof Date)
14593						o.startDate = this._local_to_utc(this._zero_time(o.startDate));
14594					else
14595						o.startDate = DPGlobal.parseDate(o.startDate, format, o.language, o.assumeNearbyYear);
14596				}
14597				else {
14598					o.startDate = -Infinity;
14599				}
14600			}
14601			if (o.endDate !== Infinity){
14602				if (!!o.endDate){
14603					if (o.endDate instanceof Date)
14604						o.endDate = this._local_to_utc(this._zero_time(o.endDate));
14605					else
14606						o.endDate = DPGlobal.parseDate(o.endDate, format, o.language, o.assumeNearbyYear);
14607				}
14608				else {
14609					o.endDate = Infinity;
14610				}
14611			}
14612
14613			o.daysOfWeekDisabled = this._resolveDaysOfWeek(o.daysOfWeekDisabled||[]);
14614			o.daysOfWeekHighlighted = this._resolveDaysOfWeek(o.daysOfWeekHighlighted||[]);
14615
14616			o.datesDisabled = o.datesDisabled||[];
14617			if (!$.isArray(o.datesDisabled)) {
14618				o.datesDisabled = o.datesDisabled.split(',');
14619			}
14620			o.datesDisabled = $.map(o.datesDisabled, function(d){
14621				return DPGlobal.parseDate(d, format, o.language, o.assumeNearbyYear);
14622			});
14623
14624			var plc = String(o.orientation).toLowerCase().split(/\s+/g),
14625				_plc = o.orientation.toLowerCase();
14626			plc = $.grep(plc, function(word){
14627				return /^auto|left|right|top|bottom$/.test(word);
14628			});
14629			o.orientation = {x: 'auto', y: 'auto'};
14630			if (!_plc || _plc === 'auto')
14631				; // no action
14632			else if (plc.length === 1){
14633				switch (plc[0]){
14634					case 'top':
14635					case 'bottom':
14636						o.orientation.y = plc[0];
14637						break;
14638					case 'left':
14639					case 'right':
14640						o.orientation.x = plc[0];
14641						break;
14642				}
14643			}
14644			else {
14645				_plc = $.grep(plc, function(word){
14646					return /^left|right$/.test(word);
14647				});
14648				o.orientation.x = _plc[0] || 'auto';
14649
14650				_plc = $.grep(plc, function(word){
14651					return /^top|bottom$/.test(word);
14652				});
14653				o.orientation.y = _plc[0] || 'auto';
14654			}
14655			if (o.defaultViewDate instanceof Date || typeof o.defaultViewDate === 'string') {
14656				o.defaultViewDate = DPGlobal.parseDate(o.defaultViewDate, format, o.language, o.assumeNearbyYear);
14657			} else if (o.defaultViewDate) {
14658				var year = o.defaultViewDate.year || new Date().getFullYear();
14659				var month = o.defaultViewDate.month || 0;
14660				var day = o.defaultViewDate.day || 1;
14661				o.defaultViewDate = UTCDate(year, month, day);
14662			} else {
14663				o.defaultViewDate = UTCToday();
14664			}
14665		},
14666		_applyEvents: function(evs){
14667			for (var i=0, el, ch, ev; i < evs.length; i++){
14668				el = evs[i][0];
14669				if (evs[i].length === 2){
14670					ch = undefined;
14671					ev = evs[i][1];
14672				} else if (evs[i].length === 3){
14673					ch = evs[i][1];
14674					ev = evs[i][2];
14675				}
14676				el.on(ev, ch);
14677			}
14678		},
14679		_unapplyEvents: function(evs){
14680			for (var i=0, el, ev, ch; i < evs.length; i++){
14681				el = evs[i][0];
14682				if (evs[i].length === 2){
14683					ch = undefined;
14684					ev = evs[i][1];
14685				} else if (evs[i].length === 3){
14686					ch = evs[i][1];
14687					ev = evs[i][2];
14688				}
14689				el.off(ev, ch);
14690			}
14691		},
14692		_buildEvents: function(){
14693            var events = {
14694                keyup: $.proxy(function(e){
14695                    if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
14696                        this.update();
14697                }, this),
14698                keydown: $.proxy(this.keydown, this),
14699                paste: $.proxy(this.paste, this)
14700            };
14701
14702            if (this.o.showOnFocus === true) {
14703                events.focus = $.proxy(this.show, this);
14704            }
14705
14706            if (this.isInput) { // single input
14707                this._events = [
14708                    [this.element, events]
14709                ];
14710            }
14711            // component: input + button
14712            else if (this.component && this.inputField.length) {
14713                this._events = [
14714                    // For components that are not readonly, allow keyboard nav
14715                    [this.inputField, events],
14716                    [this.component, {
14717                        click: $.proxy(this.show, this)
14718                    }]
14719                ];
14720            }
14721			else {
14722				this._events = [
14723					[this.element, {
14724						click: $.proxy(this.show, this),
14725						keydown: $.proxy(this.keydown, this)
14726					}]
14727				];
14728			}
14729			this._events.push(
14730				// Component: listen for blur on element descendants
14731				[this.element, '*', {
14732					blur: $.proxy(function(e){
14733						this._focused_from = e.target;
14734					}, this)
14735				}],
14736				// Input: listen for blur on element
14737				[this.element, {
14738					blur: $.proxy(function(e){
14739						this._focused_from = e.target;
14740					}, this)
14741				}]
14742			);
14743
14744			if (this.o.immediateUpdates) {
14745				// Trigger input updates immediately on changed year/month
14746				this._events.push([this.element, {
14747					'changeYear changeMonth': $.proxy(function(e){
14748						this.update(e.date);
14749					}, this)
14750				}]);
14751			}
14752
14753			this._secondaryEvents = [
14754				[this.picker, {
14755					click: $.proxy(this.click, this)
14756				}],
14757				[this.picker, '.prev, .next', {
14758					click: $.proxy(this.navArrowsClick, this)
14759				}],
14760				[this.picker, '.day:not(.disabled)', {
14761					click: $.proxy(this.dayCellClick, this)
14762				}],
14763				[$(window), {
14764					resize: $.proxy(this.place, this)
14765				}],
14766				[$(document), {
14767					'mousedown touchstart': $.proxy(function(e){
14768						// Clicked outside the datepicker, hide it
14769						if (!(
14770							this.element.is(e.target) ||
14771							this.element.find(e.target).length ||
14772							this.picker.is(e.target) ||
14773							this.picker.find(e.target).length ||
14774							this.isInline
14775						)){
14776							this.hide();
14777						}
14778					}, this)
14779				}]
14780			];
14781		},
14782		_attachEvents: function(){
14783			this._detachEvents();
14784			this._applyEvents(this._events);
14785		},
14786		_detachEvents: function(){
14787			this._unapplyEvents(this._events);
14788		},
14789		_attachSecondaryEvents: function(){
14790			this._detachSecondaryEvents();
14791			this._applyEvents(this._secondaryEvents);
14792		},
14793		_detachSecondaryEvents: function(){
14794			this._unapplyEvents(this._secondaryEvents);
14795		},
14796		_trigger: function(event, altdate){
14797			var date = altdate || this.dates.get(-1),
14798				local_date = this._utc_to_local(date);
14799
14800			this.element.trigger({
14801				type: event,
14802				date: local_date,
14803				viewMode: this.viewMode,
14804				dates: $.map(this.dates, this._utc_to_local),
14805				format: $.proxy(function(ix, format){
14806					if (arguments.length === 0){
14807						ix = this.dates.length - 1;
14808						format = this.o.format;
14809					} else if (typeof ix === 'string'){
14810						format = ix;
14811						ix = this.dates.length - 1;
14812					}
14813					format = format || this.o.format;
14814					var date = this.dates.get(ix);
14815					return DPGlobal.formatDate(date, format, this.o.language);
14816				}, this)
14817			});
14818		},
14819
14820		show: function(){
14821			if (this.inputField.is(':disabled') || (this.inputField.prop('readonly') && this.o.enableOnReadonly === false))
14822				return;
14823			if (!this.isInline)
14824				this.picker.appendTo(this.o.container);
14825			this.place();
14826			this.picker.show();
14827			this._attachSecondaryEvents();
14828			this._trigger('show');
14829			if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) {
14830				$(this.element).blur();
14831			}
14832			return this;
14833		},
14834
14835		hide: function(){
14836			if (this.isInline || !this.picker.is(':visible'))
14837				return this;
14838			this.focusDate = null;
14839			this.picker.hide().detach();
14840			this._detachSecondaryEvents();
14841			this.setViewMode(this.o.startView);
14842
14843			if (this.o.forceParse && this.inputField.val())
14844				this.setValue();
14845			this._trigger('hide');
14846			return this;
14847		},
14848
14849		destroy: function(){
14850			this.hide();
14851			this._detachEvents();
14852			this._detachSecondaryEvents();
14853			this.picker.remove();
14854			delete this.element.data().datepicker;
14855			if (!this.isInput){
14856				delete this.element.data().date;
14857			}
14858			return this;
14859		},
14860
14861		paste: function(e){
14862			var dateString;
14863			if (e.originalEvent.clipboardData && e.originalEvent.clipboardData.types
14864				&& $.inArray('text/plain', e.originalEvent.clipboardData.types) !== -1) {
14865				dateString = e.originalEvent.clipboardData.getData('text/plain');
14866			} else if (window.clipboardData) {
14867				dateString = window.clipboardData.getData('Text');
14868			} else {
14869				return;
14870			}
14871			this.setDate(dateString);
14872			this.update();
14873			e.preventDefault();
14874		},
14875
14876		_utc_to_local: function(utc){
14877			if (!utc) {
14878				return utc;
14879			}
14880
14881			var local = new Date(utc.getTime() + (utc.getTimezoneOffset() * 60000));
14882
14883			if (local.getTimezoneOffset() !== utc.getTimezoneOffset()) {
14884				local = new Date(utc.getTime() + (local.getTimezoneOffset() * 60000));
14885			}
14886
14887			return local;
14888		},
14889		_local_to_utc: function(local){
14890			return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000));
14891		},
14892		_zero_time: function(local){
14893			return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
14894		},
14895		_zero_utc_time: function(utc){
14896			return utc && UTCDate(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());
14897		},
14898
14899		getDates: function(){
14900			return $.map(this.dates, this._utc_to_local);
14901		},
14902
14903		getUTCDates: function(){
14904			return $.map(this.dates, function(d){
14905				return new Date(d);
14906			});
14907		},
14908
14909		getDate: function(){
14910			return this._utc_to_local(this.getUTCDate());
14911		},
14912
14913		getUTCDate: function(){
14914			var selected_date = this.dates.get(-1);
14915			if (selected_date !== undefined) {
14916				return new Date(selected_date);
14917			} else {
14918				return null;
14919			}
14920		},
14921
14922		clearDates: function(){
14923			this.inputField.val('');
14924			this.update();
14925			this._trigger('changeDate');
14926
14927			if (this.o.autoclose) {
14928				this.hide();
14929			}
14930		},
14931
14932		setDates: function(){
14933			var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
14934			this.update.apply(this, args);
14935			this._trigger('changeDate');
14936			this.setValue();
14937			return this;
14938		},
14939
14940		setUTCDates: function(){
14941			var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
14942			this.setDates.apply(this, $.map(args, this._utc_to_local));
14943			return this;
14944		},
14945
14946		setDate: alias('setDates'),
14947		setUTCDate: alias('setUTCDates'),
14948		remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead'),
14949
14950		setValue: function(){
14951			var formatted = this.getFormattedDate();
14952			this.inputField.val(formatted);
14953			return this;
14954		},
14955
14956		getFormattedDate: function(format){
14957			if (format === undefined)
14958				format = this.o.format;
14959
14960			var lang = this.o.language;
14961			return $.map(this.dates, function(d){
14962				return DPGlobal.formatDate(d, format, lang);
14963			}).join(this.o.multidateSeparator);
14964		},
14965
14966		getStartDate: function(){
14967			return this.o.startDate;
14968		},
14969
14970		setStartDate: function(startDate){
14971			this._process_options({startDate: startDate});
14972			this.update();
14973			this.updateNavArrows();
14974			return this;
14975		},
14976
14977		getEndDate: function(){
14978			return this.o.endDate;
14979		},
14980
14981		setEndDate: function(endDate){
14982			this._process_options({endDate: endDate});
14983			this.update();
14984			this.updateNavArrows();
14985			return this;
14986		},
14987
14988		setDaysOfWeekDisabled: function(daysOfWeekDisabled){
14989			this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
14990			this.update();
14991			return this;
14992		},
14993
14994		setDaysOfWeekHighlighted: function(daysOfWeekHighlighted){
14995			this._process_options({daysOfWeekHighlighted: daysOfWeekHighlighted});
14996			this.update();
14997			return this;
14998		},
14999
15000		setDatesDisabled: function(datesDisabled){
15001			this._process_options({datesDisabled: datesDisabled});
15002			this.update();
15003			return this;
15004		},
15005
15006		place: function(){
15007			if (this.isInline)
15008				return this;
15009			var calendarWidth = this.picker.outerWidth(),
15010				calendarHeight = this.picker.outerHeight(),
15011				visualPadding = 10,
15012				container = $(this.o.container),
15013				windowWidth = container.width(),
15014				scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(),
15015				appendOffset = container.offset();
15016
15017			var parentsZindex = [0];
15018			this.element.parents().each(function(){
15019				var itemZIndex = $(this).css('z-index');
15020				if (itemZIndex !== 'auto' && Number(itemZIndex) !== 0) parentsZindex.push(Number(itemZIndex));
15021			});
15022			var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset;
15023			var offset = this.component ? this.component.parent().offset() : this.element.offset();
15024			var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
15025			var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
15026			var left = offset.left - appendOffset.left;
15027			var top = offset.top - appendOffset.top;
15028
15029			if (this.o.container !== 'body') {
15030				top += scrollTop;
15031			}
15032
15033			this.picker.removeClass(
15034				'datepicker-orient-top datepicker-orient-bottom '+
15035				'datepicker-orient-right datepicker-orient-left'
15036			);
15037
15038			if (this.o.orientation.x !== 'auto'){
15039				this.picker.addClass('datepicker-orient-' + this.o.orientation.x);
15040				if (this.o.orientation.x === 'right')
15041					left -= calendarWidth - width;
15042			}
15043			// auto x orientation is best-placement: if it crosses a window
15044			// edge, fudge it sideways
15045			else {
15046				if (offset.left < 0) {
15047					// component is outside the window on the left side. Move it into visible range
15048					this.picker.addClass('datepicker-orient-left');
15049					left -= offset.left - visualPadding;
15050				} else if (left + calendarWidth > windowWidth) {
15051					// the calendar passes the widow right edge. Align it to component right side
15052					this.picker.addClass('datepicker-orient-right');
15053					left += width - calendarWidth;
15054				} else {
15055					if (this.o.rtl) {
15056						// Default to right
15057						this.picker.addClass('datepicker-orient-right');
15058					} else {
15059						// Default to left
15060						this.picker.addClass('datepicker-orient-left');
15061					}
15062				}
15063			}
15064
15065			// auto y orientation is best-situation: top or bottom, no fudging,
15066			// decision based on which shows more of the calendar
15067			var yorient = this.o.orientation.y,
15068				top_overflow;
15069			if (yorient === 'auto'){
15070				top_overflow = -scrollTop + top - calendarHeight;
15071				yorient = top_overflow < 0 ? 'bottom' : 'top';
15072			}
15073
15074			this.picker.addClass('datepicker-orient-' + yorient);
15075			if (yorient === 'top')
15076				top -= calendarHeight + parseInt(this.picker.css('padding-top'));
15077			else
15078				top += height;
15079
15080			if (this.o.rtl) {
15081				var right = windowWidth - (left + width);
15082				this.picker.css({
15083					top: top,
15084					right: right,
15085					zIndex: zIndex
15086				});
15087			} else {
15088				this.picker.css({
15089					top: top,
15090					left: left,
15091					zIndex: zIndex
15092				});
15093			}
15094			return this;
15095		},
15096
15097		_allow_update: true,
15098		update: function(){
15099			if (!this._allow_update)
15100				return this;
15101
15102			var oldDates = this.dates.copy(),
15103				dates = [],
15104				fromArgs = false;
15105			if (arguments.length){
15106				$.each(arguments, $.proxy(function(i, date){
15107					if (date instanceof Date)
15108						date = this._local_to_utc(date);
15109					dates.push(date);
15110				}, this));
15111				fromArgs = true;
15112			} else {
15113				dates = this.isInput
15114						? this.element.val()
15115						: this.element.data('date') || this.inputField.val();
15116				if (dates && this.o.multidate)
15117					dates = dates.split(this.o.multidateSeparator);
15118				else
15119					dates = [dates];
15120				delete this.element.data().date;
15121			}
15122
15123			dates = $.map(dates, $.proxy(function(date){
15124				return DPGlobal.parseDate(date, this.o.format, this.o.language, this.o.assumeNearbyYear);
15125			}, this));
15126			dates = $.grep(dates, $.proxy(function(date){
15127				return (
15128					!this.dateWithinRange(date) ||
15129					!date
15130				);
15131			}, this), true);
15132			this.dates.replace(dates);
15133
15134			if (this.o.updateViewDate) {
15135				if (this.dates.length)
15136					this.viewDate = new Date(this.dates.get(-1));
15137				else if (this.viewDate < this.o.startDate)
15138					this.viewDate = new Date(this.o.startDate);
15139				else if (this.viewDate > this.o.endDate)
15140					this.viewDate = new Date(this.o.endDate);
15141				else
15142					this.viewDate = this.o.defaultViewDate;
15143			}
15144
15145			if (fromArgs){
15146				// setting date by clicking
15147				this.setValue();
15148				this.element.change();
15149			}
15150			else if (this.dates.length){
15151				// setting date by typing
15152				if (String(oldDates) !== String(this.dates) && fromArgs) {
15153					this._trigger('changeDate');
15154					this.element.change();
15155				}
15156			}
15157			if (!this.dates.length && oldDates.length) {
15158				this._trigger('clearDate');
15159				this.element.change();
15160			}
15161
15162			this.fill();
15163			return this;
15164		},
15165
15166		fillDow: function(){
15167      if (this.o.showWeekDays) {
15168			var dowCnt = this.o.weekStart,
15169				html = '<tr>';
15170			if (this.o.calendarWeeks){
15171				html += '<th class="cw">&#160;</th>';
15172			}
15173			while (dowCnt < this.o.weekStart + 7){
15174				html += '<th class="dow';
15175        if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) !== -1)
15176          html += ' disabled';
15177        html += '">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
15178			}
15179			html += '</tr>';
15180			this.picker.find('.datepicker-days thead').append(html);
15181      }
15182		},
15183
15184		fillMonths: function(){
15185      var localDate = this._utc_to_local(this.viewDate);
15186			var html = '';
15187			var focused;
15188			for (var i = 0; i < 12; i++){
15189				focused = localDate && localDate.getMonth() === i ? ' focused' : '';
15190				html += '<span class="month' + focused + '">' + dates[this.o.language].monthsShort[i] + '</span>';
15191			}
15192			this.picker.find('.datepicker-months td').html(html);
15193		},
15194
15195		setRange: function(range){
15196			if (!range || !range.length)
15197				delete this.range;
15198			else
15199				this.range = $.map(range, function(d){
15200					return d.valueOf();
15201				});
15202			this.fill();
15203		},
15204
15205		getClassNames: function(date){
15206			var cls = [],
15207				year = this.viewDate.getUTCFullYear(),
15208				month = this.viewDate.getUTCMonth(),
15209				today = UTCToday();
15210			if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){
15211				cls.push('old');
15212			} else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
15213				cls.push('new');
15214			}
15215			if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
15216				cls.push('focused');
15217			// Compare internal UTC date with UTC today, not local today
15218			if (this.o.todayHighlight && isUTCEquals(date, today)) {
15219				cls.push('today');
15220			}
15221			if (this.dates.contains(date) !== -1)
15222				cls.push('active');
15223			if (!this.dateWithinRange(date)){
15224				cls.push('disabled');
15225			}
15226			if (this.dateIsDisabled(date)){
15227				cls.push('disabled', 'disabled-date');
15228			}
15229			if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1){
15230				cls.push('highlighted');
15231			}
15232
15233			if (this.range){
15234				if (date > this.range[0] && date < this.range[this.range.length-1]){
15235					cls.push('range');
15236				}
15237				if ($.inArray(date.valueOf(), this.range) !== -1){
15238					cls.push('selected');
15239				}
15240				if (date.valueOf() === this.range[0]){
15241          cls.push('range-start');
15242        }
15243        if (date.valueOf() === this.range[this.range.length-1]){
15244          cls.push('range-end');
15245        }
15246			}
15247			return cls;
15248		},
15249
15250		_fill_yearsView: function(selector, cssClass, factor, year, startYear, endYear, beforeFn){
15251			var html = '';
15252			var step = factor / 10;
15253			var view = this.picker.find(selector);
15254			var startVal = Math.floor(year / factor) * factor;
15255			var endVal = startVal + step * 9;
15256			var focusedVal = Math.floor(this.viewDate.getFullYear() / step) * step;
15257			var selected = $.map(this.dates, function(d){
15258				return Math.floor(d.getUTCFullYear() / step) * step;
15259			});
15260
15261			var classes, tooltip, before;
15262			for (var currVal = startVal - step; currVal <= endVal + step; currVal += step) {
15263				classes = [cssClass];
15264				tooltip = null;
15265
15266				if (currVal === startVal - step) {
15267					classes.push('old');
15268				} else if (currVal === endVal + step) {
15269					classes.push('new');
15270				}
15271				if ($.inArray(currVal, selected) !== -1) {
15272					classes.push('active');
15273				}
15274				if (currVal < startYear || currVal > endYear) {
15275					classes.push('disabled');
15276				}
15277				if (currVal === focusedVal) {
15278				  classes.push('focused');
15279        }
15280
15281				if (beforeFn !== $.noop) {
15282					before = beforeFn(new Date(currVal, 0, 1));
15283					if (before === undefined) {
15284						before = {};
15285					} else if (typeof before === 'boolean') {
15286						before = {enabled: before};
15287					} else if (typeof before === 'string') {
15288						before = {classes: before};
15289					}
15290					if (before.enabled === false) {
15291						classes.push('disabled');
15292					}
15293					if (before.classes) {
15294						classes = classes.concat(before.classes.split(/\s+/));
15295					}
15296					if (before.tooltip) {
15297						tooltip = before.tooltip;
15298					}
15299				}
15300
15301				html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + currVal + '</span>';
15302			}
15303
15304			view.find('.datepicker-switch').text(startVal + '-' + endVal);
15305			view.find('td').html(html);
15306		},
15307
15308		fill: function(){
15309			var d = new Date(this.viewDate),
15310				year = d.getUTCFullYear(),
15311				month = d.getUTCMonth(),
15312				startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
15313				startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
15314				endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
15315				endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
15316				todaytxt = dates[this.o.language].today || dates['en'].today || '',
15317				cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
15318        titleFormat = dates[this.o.language].titleFormat || dates['en'].titleFormat,
15319        todayDate = UTCToday(),
15320        titleBtnVisible = (this.o.todayBtn === true || this.o.todayBtn === 'linked') && todayDate >= this.o.startDate && todayDate <= this.o.endDate && !this.weekOfDateIsDisabled(todayDate),
15321				tooltip,
15322				before;
15323			if (isNaN(year) || isNaN(month))
15324				return;
15325			this.picker.find('.datepicker-days .datepicker-switch')
15326						.text(DPGlobal.formatDate(d, titleFormat, this.o.language));
15327			this.picker.find('tfoot .today')
15328						.text(todaytxt)
15329            .css('display', titleBtnVisible ? 'table-cell' : 'none');
15330			this.picker.find('tfoot .clear')
15331						.text(cleartxt)
15332						.css('display', this.o.clearBtn === true ? 'table-cell' : 'none');
15333			this.picker.find('thead .datepicker-title')
15334						.text(this.o.title)
15335						.css('display', typeof this.o.title === 'string' && this.o.title !== '' ? 'table-cell' : 'none');
15336			this.updateNavArrows();
15337			this.fillMonths();
15338			var prevMonth = UTCDate(year, month, 0),
15339				day = prevMonth.getUTCDate();
15340			prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);
15341			var nextMonth = new Date(prevMonth);
15342			if (prevMonth.getUTCFullYear() < 100){
15343        nextMonth.setUTCFullYear(prevMonth.getUTCFullYear());
15344      }
15345			nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
15346			nextMonth = nextMonth.valueOf();
15347			var html = [];
15348			var weekDay, clsName;
15349			while (prevMonth.valueOf() < nextMonth){
15350				weekDay = prevMonth.getUTCDay();
15351				if (weekDay === this.o.weekStart){
15352					html.push('<tr>');
15353					if (this.o.calendarWeeks){
15354						// ISO 8601: First week contains first thursday.
15355						// ISO also states week starts on Monday, but we can be more abstract here.
15356						var
15357							// Start of current week: based on weekstart/current date
15358							ws = new Date(+prevMonth + (this.o.weekStart - weekDay - 7) % 7 * 864e5),
15359							// Thursday of this week
15360							th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
15361							// First Thursday of year, year from thursday
15362							yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay()) % 7 * 864e5),
15363							// Calendar week: ms between thursdays, div ms per day, div 7 days
15364							calWeek = (th - yth) / 864e5 / 7 + 1;
15365						html.push('<td class="cw">'+ calWeek +'</td>');
15366					}
15367				}
15368				clsName = this.getClassNames(prevMonth);
15369				clsName.push('day');
15370
15371				var content = prevMonth.getUTCDate();
15372
15373				if (this.o.beforeShowDay !== $.noop){
15374					before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
15375					if (before === undefined)
15376						before = {};
15377					else if (typeof before === 'boolean')
15378						before = {enabled: before};
15379					else if (typeof before === 'string')
15380						before = {classes: before};
15381					if (before.enabled === false)
15382						clsName.push('disabled');
15383					if (before.classes)
15384						clsName = clsName.concat(before.classes.split(/\s+/));
15385					if (before.tooltip)
15386						tooltip = before.tooltip;
15387					if (before.content)
15388						content = before.content;
15389				}
15390
15391				//Check if uniqueSort exists (supported by jquery >=1.12 and >=2.2)
15392				//Fallback to unique function for older jquery versions
15393				if ($.isFunction($.uniqueSort)) {
15394					clsName = $.uniqueSort(clsName);
15395				} else {
15396					clsName = $.unique(clsName);
15397				}
15398
15399				html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + ' data-date="' + prevMonth.getTime().toString() + '">' + content + '</td>');
15400				tooltip = null;
15401				if (weekDay === this.o.weekEnd){
15402					html.push('</tr>');
15403				}
15404				prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
15405			}
15406			this.picker.find('.datepicker-days tbody').html(html.join(''));
15407
15408			var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months';
15409			var months = this.picker.find('.datepicker-months')
15410						.find('.datepicker-switch')
15411							.text(this.o.maxViewMode < 2 ? monthsTitle : year)
15412							.end()
15413						.find('tbody span').removeClass('active');
15414
15415			$.each(this.dates, function(i, d){
15416				if (d.getUTCFullYear() === year)
15417					months.eq(d.getUTCMonth()).addClass('active');
15418			});
15419
15420			if (year < startYear || year > endYear){
15421				months.addClass('disabled');
15422			}
15423			if (year === startYear){
15424				months.slice(0, startMonth).addClass('disabled');
15425			}
15426			if (year === endYear){
15427				months.slice(endMonth+1).addClass('disabled');
15428			}
15429
15430			if (this.o.beforeShowMonth !== $.noop){
15431				var that = this;
15432				$.each(months, function(i, month){
15433          var moDate = new Date(year, i, 1);
15434          var before = that.o.beforeShowMonth(moDate);
15435					if (before === undefined)
15436						before = {};
15437					else if (typeof before === 'boolean')
15438						before = {enabled: before};
15439					else if (typeof before === 'string')
15440						before = {classes: before};
15441					if (before.enabled === false && !$(month).hasClass('disabled'))
15442					    $(month).addClass('disabled');
15443					if (before.classes)
15444					    $(month).addClass(before.classes);
15445					if (before.tooltip)
15446					    $(month).prop('title', before.tooltip);
15447				});
15448			}
15449
15450			// Generating decade/years picker
15451			this._fill_yearsView(
15452				'.datepicker-years',
15453				'year',
15454				10,
15455				year,
15456				startYear,
15457				endYear,
15458				this.o.beforeShowYear
15459			);
15460
15461			// Generating century/decades picker
15462			this._fill_yearsView(
15463				'.datepicker-decades',
15464				'decade',
15465				100,
15466				year,
15467				startYear,
15468				endYear,
15469				this.o.beforeShowDecade
15470			);
15471
15472			// Generating millennium/centuries picker
15473			this._fill_yearsView(
15474				'.datepicker-centuries',
15475				'century',
15476				1000,
15477				year,
15478				startYear,
15479				endYear,
15480				this.o.beforeShowCentury
15481			);
15482		},
15483
15484		updateNavArrows: function(){
15485			if (!this._allow_update)
15486				return;
15487
15488			var d = new Date(this.viewDate),
15489				year = d.getUTCFullYear(),
15490				month = d.getUTCMonth(),
15491				startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
15492				startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
15493				endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
15494				endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
15495				prevIsDisabled,
15496				nextIsDisabled,
15497				factor = 1;
15498			switch (this.viewMode){
15499				case 4:
15500					factor *= 10;
15501					/* falls through */
15502				case 3:
15503					factor *= 10;
15504					/* falls through */
15505				case 2:
15506					factor *= 10;
15507					/* falls through */
15508				case 1:
15509					prevIsDisabled = Math.floor(year / factor) * factor <= startYear;
15510					nextIsDisabled = Math.floor(year / factor) * factor + factor > endYear;
15511					break;
15512				case 0:
15513					prevIsDisabled = year <= startYear && month <= startMonth;
15514					nextIsDisabled = year >= endYear && month >= endMonth;
15515					break;
15516			}
15517
15518			this.picker.find('.prev').toggleClass('disabled', prevIsDisabled);
15519			this.picker.find('.next').toggleClass('disabled', nextIsDisabled);
15520		},
15521
15522		click: function(e){
15523			e.preventDefault();
15524			e.stopPropagation();
15525
15526			var target, dir, day, year, month;
15527			target = $(e.target);
15528
15529			// Clicked on the switch
15530			if (target.hasClass('datepicker-switch') && this.viewMode !== this.o.maxViewMode){
15531				this.setViewMode(this.viewMode + 1);
15532			}
15533
15534			// Clicked on today button
15535			if (target.hasClass('today') && !target.hasClass('day')){
15536				this.setViewMode(0);
15537				this._setDate(UTCToday(), this.o.todayBtn === 'linked' ? null : 'view');
15538			}
15539
15540			// Clicked on clear button
15541			if (target.hasClass('clear')){
15542				this.clearDates();
15543			}
15544
15545			if (!target.hasClass('disabled')){
15546				// Clicked on a month, year, decade, century
15547				if (target.hasClass('month')
15548						|| target.hasClass('year')
15549						|| target.hasClass('decade')
15550						|| target.hasClass('century')) {
15551					this.viewDate.setUTCDate(1);
15552
15553					day = 1;
15554					if (this.viewMode === 1){
15555						month = target.parent().find('span').index(target);
15556						year = this.viewDate.getUTCFullYear();
15557						this.viewDate.setUTCMonth(month);
15558					} else {
15559						month = 0;
15560						year = Number(target.text());
15561						this.viewDate.setUTCFullYear(year);
15562					}
15563
15564					this._trigger(DPGlobal.viewModes[this.viewMode - 1].e, this.viewDate);
15565
15566					if (this.viewMode === this.o.minViewMode){
15567						this._setDate(UTCDate(year, month, day));
15568					} else {
15569						this.setViewMode(this.viewMode - 1);
15570						this.fill();
15571					}
15572				}
15573			}
15574
15575			if (this.picker.is(':visible') && this._focused_from){
15576				this._focused_from.focus();
15577			}
15578			delete this._focused_from;
15579		},
15580
15581		dayCellClick: function(e){
15582			var $target = $(e.currentTarget);
15583			var timestamp = $target.data('date');
15584			var date = new Date(timestamp);
15585
15586			if (this.o.updateViewDate) {
15587				if (date.getUTCFullYear() !== this.viewDate.getUTCFullYear()) {
15588					this._trigger('changeYear', this.viewDate);
15589				}
15590
15591				if (date.getUTCMonth() !== this.viewDate.getUTCMonth()) {
15592					this._trigger('changeMonth', this.viewDate);
15593				}
15594			}
15595			this._setDate(date);
15596		},
15597
15598		// Clicked on prev or next
15599		navArrowsClick: function(e){
15600			var $target = $(e.currentTarget);
15601			var dir = $target.hasClass('prev') ? -1 : 1;
15602			if (this.viewMode !== 0){
15603				dir *= DPGlobal.viewModes[this.viewMode].navStep * 12;
15604			}
15605			this.viewDate = this.moveMonth(this.viewDate, dir);
15606			this._trigger(DPGlobal.viewModes[this.viewMode].e, this.viewDate);
15607			this.fill();
15608		},
15609
15610		_toggle_multidate: function(date){
15611			var ix = this.dates.contains(date);
15612			if (!date){
15613				this.dates.clear();
15614			}
15615
15616			if (ix !== -1){
15617				if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive){
15618					this.dates.remove(ix);
15619				}
15620			} else if (this.o.multidate === false) {
15621				this.dates.clear();
15622				this.dates.push(date);
15623			}
15624			else {
15625				this.dates.push(date);
15626			}
15627
15628			if (typeof this.o.multidate === 'number')
15629				while (this.dates.length > this.o.multidate)
15630					this.dates.remove(0);
15631		},
15632
15633		_setDate: function(date, which){
15634			if (!which || which === 'date')
15635				this._toggle_multidate(date && new Date(date));
15636			if ((!which && this.o.updateViewDate) || which === 'view')
15637				this.viewDate = date && new Date(date);
15638
15639			this.fill();
15640			this.setValue();
15641			if (!which || which !== 'view') {
15642				this._trigger('changeDate');
15643			}
15644			this.inputField.trigger('change');
15645			if (this.o.autoclose && (!which || which === 'date')){
15646				this.hide();
15647			}
15648		},
15649
15650		moveDay: function(date, dir){
15651			var newDate = new Date(date);
15652			newDate.setUTCDate(date.getUTCDate() + dir);
15653
15654			return newDate;
15655		},
15656
15657		moveWeek: function(date, dir){
15658			return this.moveDay(date, dir * 7);
15659		},
15660
15661		moveMonth: function(date, dir){
15662			if (!isValidDate(date))
15663				return this.o.defaultViewDate;
15664			if (!dir)
15665				return date;
15666			var new_date = new Date(date.valueOf()),
15667				day = new_date.getUTCDate(),
15668				month = new_date.getUTCMonth(),
15669				mag = Math.abs(dir),
15670				new_month, test;
15671			dir = dir > 0 ? 1 : -1;
15672			if (mag === 1){
15673				test = dir === -1
15674					// If going back one month, make sure month is not current month
15675					// (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
15676					? function(){
15677						return new_date.getUTCMonth() === month;
15678					}
15679					// If going forward one month, make sure month is as expected
15680					// (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
15681					: function(){
15682						return new_date.getUTCMonth() !== new_month;
15683					};
15684				new_month = month + dir;
15685				new_date.setUTCMonth(new_month);
15686				// Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
15687				new_month = (new_month + 12) % 12;
15688			}
15689			else {
15690				// For magnitudes >1, move one month at a time...
15691				for (var i=0; i < mag; i++)
15692					// ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
15693					new_date = this.moveMonth(new_date, dir);
15694				// ...then reset the day, keeping it in the new month
15695				new_month = new_date.getUTCMonth();
15696				new_date.setUTCDate(day);
15697				test = function(){
15698					return new_month !== new_date.getUTCMonth();
15699				};
15700			}
15701			// Common date-resetting loop -- if date is beyond end of month, make it
15702			// end of month
15703			while (test()){
15704				new_date.setUTCDate(--day);
15705				new_date.setUTCMonth(new_month);
15706			}
15707			return new_date;
15708		},
15709
15710		moveYear: function(date, dir){
15711			return this.moveMonth(date, dir*12);
15712		},
15713
15714		moveAvailableDate: function(date, dir, fn){
15715			do {
15716				date = this[fn](date, dir);
15717
15718				if (!this.dateWithinRange(date))
15719					return false;
15720
15721				fn = 'moveDay';
15722			}
15723			while (this.dateIsDisabled(date));
15724
15725			return date;
15726		},
15727
15728		weekOfDateIsDisabled: function(date){
15729			return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1;
15730		},
15731
15732		dateIsDisabled: function(date){
15733			return (
15734				this.weekOfDateIsDisabled(date) ||
15735				$.grep(this.o.datesDisabled, function(d){
15736					return isUTCEquals(date, d);
15737				}).length > 0
15738			);
15739		},
15740
15741		dateWithinRange: function(date){
15742			return date >= this.o.startDate && date <= this.o.endDate;
15743		},
15744
15745		keydown: function(e){
15746			if (!this.picker.is(':visible')){
15747				if (e.keyCode === 40 || e.keyCode === 27) { // allow down to re-show picker
15748					this.show();
15749					e.stopPropagation();
15750        }
15751				return;
15752			}
15753			var dateChanged = false,
15754				dir, newViewDate,
15755				focusDate = this.focusDate || this.viewDate;
15756			switch (e.keyCode){
15757				case 27: // escape
15758					if (this.focusDate){
15759						this.focusDate = null;
15760						this.viewDate = this.dates.get(-1) || this.viewDate;
15761						this.fill();
15762					}
15763					else
15764						this.hide();
15765					e.preventDefault();
15766					e.stopPropagation();
15767					break;
15768				case 37: // left
15769				case 38: // up
15770				case 39: // right
15771				case 40: // down
15772					if (!this.o.keyboardNavigation || this.o.daysOfWeekDisabled.length === 7)
15773						break;
15774					dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1;
15775          if (this.viewMode === 0) {
15776  					if (e.ctrlKey){
15777  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
15778
15779  						if (newViewDate)
15780  							this._trigger('changeYear', this.viewDate);
15781  					} else if (e.shiftKey){
15782  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
15783
15784  						if (newViewDate)
15785  							this._trigger('changeMonth', this.viewDate);
15786  					} else if (e.keyCode === 37 || e.keyCode === 39){
15787  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay');
15788  					} else if (!this.weekOfDateIsDisabled(focusDate)){
15789  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek');
15790  					}
15791          } else if (this.viewMode === 1) {
15792            if (e.keyCode === 38 || e.keyCode === 40) {
15793              dir = dir * 4;
15794            }
15795            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
15796          } else if (this.viewMode === 2) {
15797            if (e.keyCode === 38 || e.keyCode === 40) {
15798              dir = dir * 4;
15799            }
15800            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
15801          }
15802					if (newViewDate){
15803						this.focusDate = this.viewDate = newViewDate;
15804						this.setValue();
15805						this.fill();
15806						e.preventDefault();
15807					}
15808					break;
15809				case 13: // enter
15810					if (!this.o.forceParse)
15811						break;
15812					focusDate = this.focusDate || this.dates.get(-1) || this.viewDate;
15813					if (this.o.keyboardNavigation) {
15814						this._toggle_multidate(focusDate);
15815						dateChanged = true;
15816					}
15817					this.focusDate = null;
15818					this.viewDate = this.dates.get(-1) || this.viewDate;
15819					this.setValue();
15820					this.fill();
15821					if (this.picker.is(':visible')){
15822						e.preventDefault();
15823						e.stopPropagation();
15824						if (this.o.autoclose)
15825							this.hide();
15826					}
15827					break;
15828				case 9: // tab
15829					this.focusDate = null;
15830					this.viewDate = this.dates.get(-1) || this.viewDate;
15831					this.fill();
15832					this.hide();
15833					break;
15834			}
15835			if (dateChanged){
15836				if (this.dates.length)
15837					this._trigger('changeDate');
15838				else
15839					this._trigger('clearDate');
15840				this.inputField.trigger('change');
15841			}
15842		},
15843
15844		setViewMode: function(viewMode){
15845			this.viewMode = viewMode;
15846			this.picker
15847				.children('div')
15848				.hide()
15849				.filter('.datepicker-' + DPGlobal.viewModes[this.viewMode].clsName)
15850					.show();
15851			this.updateNavArrows();
15852      this._trigger('changeViewMode', new Date(this.viewDate));
15853		}
15854	};
15855
15856	var DateRangePicker = function(element, options){
15857		$.data(element, 'datepicker', this);
15858		this.element = $(element);
15859		this.inputs = $.map(options.inputs, function(i){
15860			return i.jquery ? i[0] : i;
15861		});
15862		delete options.inputs;
15863
15864		this.keepEmptyValues = options.keepEmptyValues;
15865		delete options.keepEmptyValues;
15866
15867		datepickerPlugin.call($(this.inputs), options)
15868			.on('changeDate', $.proxy(this.dateUpdated, this));
15869
15870		this.pickers = $.map(this.inputs, function(i){
15871			return $.data(i, 'datepicker');
15872		});
15873		this.updateDates();
15874	};
15875	DateRangePicker.prototype = {
15876		updateDates: function(){
15877			this.dates = $.map(this.pickers, function(i){
15878				return i.getUTCDate();
15879			});
15880			this.updateRanges();
15881		},
15882		updateRanges: function(){
15883			var range = $.map(this.dates, function(d){
15884				return d.valueOf();
15885			});
15886			$.each(this.pickers, function(i, p){
15887				p.setRange(range);
15888			});
15889		},
15890		clearDates: function(){
15891			$.each(this.pickers, function(i, p){
15892				p.clearDates();
15893			});
15894		},
15895		dateUpdated: function(e){
15896			// `this.updating` is a workaround for preventing infinite recursion
15897			// between `changeDate` triggering and `setUTCDate` calling.  Until
15898			// there is a better mechanism.
15899			if (this.updating)
15900				return;
15901			this.updating = true;
15902
15903			var dp = $.data(e.target, 'datepicker');
15904
15905			if (dp === undefined) {
15906				return;
15907			}
15908
15909			var new_date = dp.getUTCDate(),
15910				keep_empty_values = this.keepEmptyValues,
15911				i = $.inArray(e.target, this.inputs),
15912				j = i - 1,
15913				k = i + 1,
15914				l = this.inputs.length;
15915			if (i === -1)
15916				return;
15917
15918			$.each(this.pickers, function(i, p){
15919				if (!p.getUTCDate() && (p === dp || !keep_empty_values))
15920					p.setUTCDate(new_date);
15921			});
15922
15923			if (new_date < this.dates[j]){
15924				// Date being moved earlier/left
15925				while (j >= 0 && new_date < this.dates[j]){
15926					this.pickers[j--].setUTCDate(new_date);
15927				}
15928			} else if (new_date > this.dates[k]){
15929				// Date being moved later/right
15930				while (k < l && new_date > this.dates[k]){
15931					this.pickers[k++].setUTCDate(new_date);
15932				}
15933			}
15934			this.updateDates();
15935
15936			delete this.updating;
15937		},
15938		destroy: function(){
15939			$.map(this.pickers, function(p){ p.destroy(); });
15940			$(this.inputs).off('changeDate', this.dateUpdated);
15941			delete this.element.data().datepicker;
15942		},
15943		remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead')
15944	};
15945
15946	function opts_from_el(el, prefix){
15947		// Derive options from element data-attrs
15948		var data = $(el).data(),
15949			out = {}, inkey,
15950			replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])');
15951		prefix = new RegExp('^' + prefix.toLowerCase());
15952		function re_lower(_,a){
15953			return a.toLowerCase();
15954		}
15955		for (var key in data)
15956			if (prefix.test(key)){
15957				inkey = key.replace(replace, re_lower);
15958				out[inkey] = data[key];
15959			}
15960		return out;
15961	}
15962
15963	function opts_from_locale(lang){
15964		// Derive options from locale plugins
15965		var out = {};
15966		// Check if "de-DE" style date is available, if not language should
15967		// fallback to 2 letter code eg "de"
15968		if (!dates[lang]){
15969			lang = lang.split('-')[0];
15970			if (!dates[lang])
15971				return;
15972		}
15973		var d = dates[lang];
15974		$.each(locale_opts, function(i,k){
15975			if (k in d)
15976				out[k] = d[k];
15977		});
15978		return out;
15979	}
15980
15981	var old = $.fn.datepicker;
15982	var datepickerPlugin = function(option){
15983		var args = Array.apply(null, arguments);
15984		args.shift();
15985		var internal_return;
15986		this.each(function(){
15987			var $this = $(this),
15988				data = $this.data('datepicker'),
15989				options = typeof option === 'object' && option;
15990			if (!data){
15991				var elopts = opts_from_el(this, 'date'),
15992					// Preliminary otions
15993					xopts = $.extend({}, defaults, elopts, options),
15994					locopts = opts_from_locale(xopts.language),
15995					// Options priority: js args, data-attrs, locales, defaults
15996					opts = $.extend({}, defaults, locopts, elopts, options);
15997				if ($this.hasClass('input-daterange') || opts.inputs){
15998					$.extend(opts, {
15999						inputs: opts.inputs || $this.find('input').toArray()
16000					});
16001					data = new DateRangePicker(this, opts);
16002				}
16003				else {
16004					data = new Datepicker(this, opts);
16005				}
16006				$this.data('datepicker', data);
16007			}
16008			if (typeof option === 'string' && typeof data[option] === 'function'){
16009				internal_return = data[option].apply(data, args);
16010			}
16011		});
16012
16013		if (
16014			internal_return === undefined ||
16015			internal_return instanceof Datepicker ||
16016			internal_return instanceof DateRangePicker
16017		)
16018			return this;
16019
16020		if (this.length > 1)
16021			throw new Error('Using only allowed for the collection of a single element (' + option + ' function)');
16022		else
16023			return internal_return;
16024	};
16025	$.fn.datepicker = datepickerPlugin;
16026
16027	var defaults = $.fn.datepicker.defaults = {
16028		assumeNearbyYear: false,
16029		autoclose: false,
16030		beforeShowDay: $.noop,
16031		beforeShowMonth: $.noop,
16032		beforeShowYear: $.noop,
16033		beforeShowDecade: $.noop,
16034		beforeShowCentury: $.noop,
16035		calendarWeeks: false,
16036		clearBtn: false,
16037		toggleActive: false,
16038		daysOfWeekDisabled: [],
16039		daysOfWeekHighlighted: [],
16040		datesDisabled: [],
16041		endDate: Infinity,
16042		forceParse: true,
16043		format: 'mm/dd/yyyy',
16044		keepEmptyValues: false,
16045		keyboardNavigation: true,
16046		language: 'en',
16047		minViewMode: 0,
16048		maxViewMode: 4,
16049		multidate: false,
16050		multidateSeparator: ',',
16051		orientation: "auto",
16052		rtl: false,
16053		startDate: -Infinity,
16054		startView: 0,
16055		todayBtn: false,
16056		todayHighlight: false,
16057		updateViewDate: true,
16058		weekStart: 0,
16059		disableTouchKeyboard: false,
16060		enableOnReadonly: true,
16061		showOnFocus: true,
16062		zIndexOffset: 10,
16063		container: 'body',
16064		immediateUpdates: false,
16065		title: '',
16066		templates: {
16067			leftArrow: '&#x00AB;',
16068			rightArrow: '&#x00BB;'
16069		},
16070    showWeekDays: true
16071	};
16072	var locale_opts = $.fn.datepicker.locale_opts = [
16073		'format',
16074		'rtl',
16075		'weekStart'
16076	];
16077	$.fn.datepicker.Constructor = Datepicker;
16078	var dates = $.fn.datepicker.dates = {
16079		en: {
16080			days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
16081			daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
16082			daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
16083			months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
16084			monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
16085			today: "Today",
16086			clear: "Clear",
16087			titleFormat: "MM yyyy"
16088		}
16089	};
16090
16091	var DPGlobal = {
16092		viewModes: [
16093			{
16094				names: ['days', 'month'],
16095				clsName: 'days',
16096				e: 'changeMonth'
16097			},
16098			{
16099				names: ['months', 'year'],
16100				clsName: 'months',
16101				e: 'changeYear',
16102				navStep: 1
16103			},
16104			{
16105				names: ['years', 'decade'],
16106				clsName: 'years',
16107				e: 'changeDecade',
16108				navStep: 10
16109			},
16110			{
16111				names: ['decades', 'century'],
16112				clsName: 'decades',
16113				e: 'changeCentury',
16114				navStep: 100
16115			},
16116			{
16117				names: ['centuries', 'millennium'],
16118				clsName: 'centuries',
16119				e: 'changeMillennium',
16120				navStep: 1000
16121			}
16122		],
16123		validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
16124		nonpunctuation: /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,
16125		parseFormat: function(format){
16126			if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function')
16127                return format;
16128            // IE treats \0 as a string end in inputs (truncating the value),
16129			// so it's a bad format delimiter, anyway
16130			var separators = format.replace(this.validParts, '\0').split('\0'),
16131				parts = format.match(this.validParts);
16132			if (!separators || !separators.length || !parts || parts.length === 0){
16133				throw new Error("Invalid date format.");
16134			}
16135			return {separators: separators, parts: parts};
16136		},
16137		parseDate: function(date, format, language, assumeNearby){
16138			if (!date)
16139				return undefined;
16140			if (date instanceof Date)
16141				return date;
16142			if (typeof format === 'string')
16143				format = DPGlobal.parseFormat(format);
16144			if (format.toValue)
16145				return format.toValue(date, format, language);
16146			var fn_map = {
16147					d: 'moveDay',
16148					m: 'moveMonth',
16149					w: 'moveWeek',
16150					y: 'moveYear'
16151				},
16152				dateAliases = {
16153					yesterday: '-1d',
16154					today: '+0d',
16155					tomorrow: '+1d'
16156				},
16157				parts, part, dir, i, fn;
16158			if (date in dateAliases){
16159				date = dateAliases[date];
16160			}
16161			if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(date)){
16162				parts = date.match(/([\-+]\d+)([dmwy])/gi);
16163				date = new Date();
16164				for (i=0; i < parts.length; i++){
16165					part = parts[i].match(/([\-+]\d+)([dmwy])/i);
16166					dir = Number(part[1]);
16167					fn = fn_map[part[2].toLowerCase()];
16168					date = Datepicker.prototype[fn](date, dir);
16169				}
16170				return Datepicker.prototype._zero_utc_time(date);
16171			}
16172
16173			parts = date && date.match(this.nonpunctuation) || [];
16174
16175			function applyNearbyYear(year, threshold){
16176				if (threshold === true)
16177					threshold = 10;
16178
16179				// if year is 2 digits or less, than the user most likely is trying to get a recent century
16180				if (year < 100){
16181					year += 2000;
16182					// if the new year is more than threshold years in advance, use last century
16183					if (year > ((new Date()).getFullYear()+threshold)){
16184						year -= 100;
16185					}
16186				}
16187
16188				return year;
16189			}
16190
16191			var parsed = {},
16192				setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
16193				setters_map = {
16194					yyyy: function(d,v){
16195						return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
16196					},
16197					m: function(d,v){
16198						if (isNaN(d))
16199							return d;
16200						v -= 1;
16201						while (v < 0) v += 12;
16202						v %= 12;
16203						d.setUTCMonth(v);
16204						while (d.getUTCMonth() !== v)
16205							d.setUTCDate(d.getUTCDate()-1);
16206						return d;
16207					},
16208					d: function(d,v){
16209						return d.setUTCDate(v);
16210					}
16211				},
16212				val, filtered;
16213			setters_map['yy'] = setters_map['yyyy'];
16214			setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
16215			setters_map['dd'] = setters_map['d'];
16216			date = UTCToday();
16217			var fparts = format.parts.slice();
16218			// Remove noop parts
16219			if (parts.length !== fparts.length){
16220				fparts = $(fparts).filter(function(i,p){
16221					return $.inArray(p, setters_order) !== -1;
16222				}).toArray();
16223			}
16224			// Process remainder
16225			function match_part(){
16226				var m = this.slice(0, parts[i].length),
16227					p = parts[i].slice(0, m.length);
16228				return m.toLowerCase() === p.toLowerCase();
16229			}
16230			if (parts.length === fparts.length){
16231				var cnt;
16232				for (i=0, cnt = fparts.length; i < cnt; i++){
16233					val = parseInt(parts[i], 10);
16234					part = fparts[i];
16235					if (isNaN(val)){
16236						switch (part){
16237							case 'MM':
16238								filtered = $(dates[language].months).filter(match_part);
16239								val = $.inArray(filtered[0], dates[language].months) + 1;
16240								break;
16241							case 'M':
16242								filtered = $(dates[language].monthsShort).filter(match_part);
16243								val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
16244								break;
16245						}
16246					}
16247					parsed[part] = val;
16248				}
16249				var _date, s;
16250				for (i=0; i < setters_order.length; i++){
16251					s = setters_order[i];
16252					if (s in parsed && !isNaN(parsed[s])){
16253						_date = new Date(date);
16254						setters_map[s](_date, parsed[s]);
16255						if (!isNaN(_date))
16256							date = _date;
16257					}
16258				}
16259			}
16260			return date;
16261		},
16262		formatDate: function(date, format, language){
16263			if (!date)
16264				return '';
16265			if (typeof format === 'string')
16266				format = DPGlobal.parseFormat(format);
16267			if (format.toDisplay)
16268                return format.toDisplay(date, format, language);
16269            var val = {
16270				d: date.getUTCDate(),
16271				D: dates[language].daysShort[date.getUTCDay()],
16272				DD: dates[language].days[date.getUTCDay()],
16273				m: date.getUTCMonth() + 1,
16274				M: dates[language].monthsShort[date.getUTCMonth()],
16275				MM: dates[language].months[date.getUTCMonth()],
16276				yy: date.getUTCFullYear().toString().substring(2),
16277				yyyy: date.getUTCFullYear()
16278			};
16279			val.dd = (val.d < 10 ? '0' : '') + val.d;
16280			val.mm = (val.m < 10 ? '0' : '') + val.m;
16281			date = [];
16282			var seps = $.extend([], format.separators);
16283			for (var i=0, cnt = format.parts.length; i <= cnt; i++){
16284				if (seps.length)
16285					date.push(seps.shift());
16286				date.push(val[format.parts[i]]);
16287			}
16288			return date.join('');
16289		},
16290		headTemplate: '<thead>'+
16291			              '<tr>'+
16292			                '<th colspan="7" class="datepicker-title"></th>'+
16293			              '</tr>'+
16294							'<tr>'+
16295								'<th class="prev">'+defaults.templates.leftArrow+'</th>'+
16296								'<th colspan="5" class="datepicker-switch"></th>'+
16297								'<th class="next">'+defaults.templates.rightArrow+'</th>'+
16298							'</tr>'+
16299						'</thead>',
16300		contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
16301		footTemplate: '<tfoot>'+
16302							'<tr>'+
16303								'<th colspan="7" class="today"></th>'+
16304							'</tr>'+
16305							'<tr>'+
16306								'<th colspan="7" class="clear"></th>'+
16307							'</tr>'+
16308						'</tfoot>'
16309	};
16310	DPGlobal.template = '<div class="datepicker">'+
16311							'<div class="datepicker-days">'+
16312								'<table class="table-condensed">'+
16313									DPGlobal.headTemplate+
16314									'<tbody></tbody>'+
16315									DPGlobal.footTemplate+
16316								'</table>'+
16317							'</div>'+
16318							'<div class="datepicker-months">'+
16319								'<table class="table-condensed">'+
16320									DPGlobal.headTemplate+
16321									DPGlobal.contTemplate+
16322									DPGlobal.footTemplate+
16323								'</table>'+
16324							'</div>'+
16325							'<div class="datepicker-years">'+
16326								'<table class="table-condensed">'+
16327									DPGlobal.headTemplate+
16328									DPGlobal.contTemplate+
16329									DPGlobal.footTemplate+
16330								'</table>'+
16331							'</div>'+
16332							'<div class="datepicker-decades">'+
16333								'<table class="table-condensed">'+
16334									DPGlobal.headTemplate+
16335									DPGlobal.contTemplate+
16336									DPGlobal.footTemplate+
16337								'</table>'+
16338							'</div>'+
16339							'<div class="datepicker-centuries">'+
16340								'<table class="table-condensed">'+
16341									DPGlobal.headTemplate+
16342									DPGlobal.contTemplate+
16343									DPGlobal.footTemplate+
16344								'</table>'+
16345							'</div>'+
16346						'</div>';
16347
16348	$.fn.datepicker.DPGlobal = DPGlobal;
16349
16350
16351	/* DATEPICKER NO CONFLICT
16352	* =================== */
16353
16354	$.fn.datepicker.noConflict = function(){
16355		$.fn.datepicker = old;
16356		return this;
16357	};
16358
16359	/* DATEPICKER VERSION
16360	 * =================== */
16361	$.fn.datepicker.version = '1.9.0';
16362
16363	$.fn.datepicker.deprecated = function(msg){
16364		var console = window.console;
16365		if (console && console.warn) {
16366			console.warn('DEPRECATED: ' + msg);
16367		}
16368	};
16369
16370
16371	/* DATEPICKER DATA-API
16372	* ================== */
16373
16374	$(document).on(
16375		'focus.datepicker.data-api click.datepicker.data-api',
16376		'[data-provide="datepicker"]',
16377		function(e){
16378			var $this = $(this);
16379			if ($this.data('datepicker'))
16380				return;
16381			e.preventDefault();
16382			// component click requires us to explicitly show it
16383			datepickerPlugin.call($this, 'show');
16384		}
16385	);
16386	$(function(){
16387		datepickerPlugin.call($('[data-provide="datepicker-inline"]'));
16388	});
16389
16390}));
16391!function(a){a.fn.datepicker.dates["zh-TW"]={days:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],daysShort:["週日","週一","週二","週三","週四","週五","週六"],daysMin:["日","一","二","三","四","五","六"],months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthsShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],today:"今天",format:"yyyy年mm月dd日",weekStart:1,clear:"清除"}}(jQuery);// Ion.RangeSlider
16392// version 2.1.7 Build: 371
16393// © Denis Ineshin, 2017
16394// https://github.com/IonDen
16395//
16396// Project page:    http://ionden.com/a/plugins/ion.rangeSlider/en.html
16397// GitHub page:     https://github.com/IonDen/ion.rangeSlider
16398//
16399// Released under MIT licence:
16400// http://ionden.com/a/plugins/licence-en.html
16401// =====================================================================================================================
16402//-------------------------------------------------- resizeInput
16403function resizeInput() {
16404    $('.resize_input').each(function(){
16405        $(this).attr('size', $(this).val().length);
16406    });
16407}
16408
16409;(function(factory) {
16410    if (typeof define === "function" && define.amd) {
16411        define(["jquery"], function (jQuery) {
16412            return factory(jQuery, document, window, navigator);
16413        });
16414    } else if (typeof exports === "object") {
16415        factory(require("jquery"), document, window, navigator);
16416    } else {
16417        factory(jQuery, document, window, navigator);
16418    }
16419} (function ($, document, window, navigator, undefined) {
16420    "use strict";
16421
16422    // =================================================================================================================
16423    // Service
16424
16425    var plugin_count = 0;
16426
16427    // IE8 fix
16428    var is_old_ie = (function () {
16429        var n = navigator.userAgent,
16430            r = /msie\s\d+/i,
16431            v;
16432        if (n.search(r) > 0) {
16433            v = r.exec(n).toString();
16434            v = v.split(" ")[1];
16435            if (v < 9) {
16436                $("html").addClass("lt-ie9");
16437                return true;
16438            }
16439        }
16440        return false;
16441    } ());
16442    if (!Function.prototype.bind) {
16443        Function.prototype.bind = function bind(that) {
16444
16445            var target = this;
16446            var slice = [].slice;
16447
16448            if (typeof target != "function") {
16449                throw new TypeError();
16450            }
16451
16452            var args = slice.call(arguments, 1),
16453                bound = function () {
16454
16455                    if (this instanceof bound) {
16456
16457                        var F = function(){};
16458                        F.prototype = target.prototype;
16459                        var self = new F();
16460
16461                        var result = target.apply(
16462                            self,
16463                            args.concat(slice.call(arguments))
16464                        );
16465                        if (Object(result) === result) {
16466                            return result;
16467                        }
16468                        return self;
16469
16470                    } else {
16471
16472                        return target.apply(
16473                            that,
16474                            args.concat(slice.call(arguments))
16475                        );
16476
16477                    }
16478
16479                };
16480
16481            return bound;
16482        };
16483    }
16484    if (!Array.prototype.indexOf) {
16485        Array.prototype.indexOf = function(searchElement, fromIndex) {
16486            var k;
16487            if (this == null) {
16488                throw new TypeError('"this" is null or not defined');
16489            }
16490            var O = Object(this);
16491            var len = O.length >>> 0;
16492            if (len === 0) {
16493                return -1;
16494            }
16495            var n = +fromIndex || 0;
16496            if (Math.abs(n) === Infinity) {
16497                n = 0;
16498            }
16499            if (n >= len) {
16500                return -1;
16501            }
16502            k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
16503            while (k < len) {
16504                if (k in O && O[k] === searchElement) {
16505                    return k;
16506                }
16507                k++;
16508            }
16509            return -1;
16510        };
16511    }
16512
16513
16514
16515    // =================================================================================================================
16516    // Template
16517
16518    var base_html =
16519        '<span class="irs">' +
16520        '<span class="irs-line" tabindex="-1"><span class="irs-line-left"></span><span class="irs-line-mid"></span><span class="irs-line-right"></span></span>' +
16521        '<span class="irs-min">0</span><span class="irs-max">1</span>' +
16522        '<span class="irs-from">0</span><span class="irs-to">0</span><span class="irs-single">0</span>' +
16523        '</span>' +
16524        '<span class="irs-grid"></span>' +
16525        '<span class="irs-bar"></span>';
16526
16527    var single_html =
16528        '<span class="irs-bar-edge"></span>' +
16529        '<span class="irs-shadow shadow-single"></span>' +
16530        '<span class="irs-slider single"></span>';
16531
16532    var double_html =
16533        '<span class="irs-shadow shadow-from"></span>' +
16534        '<span class="irs-shadow shadow-to"></span>' +
16535        '<span class="irs-slider from"></span>' +
16536        '<span class="irs-slider to"></span>';
16537
16538    var disable_html =
16539        '<span class="irs-disable-mask"></span>';
16540
16541
16542
16543    // =================================================================================================================
16544    // Core
16545
16546    /**
16547     * Main plugin constructor
16548     *
16549     * @param input {Object} link to base input element
16550     * @param options {Object} slider config
16551     * @param plugin_count {Number}
16552     * @constructor
16553     */
16554    var IonRangeSlider = function (input, options, plugin_count) {
16555        this.VERSION = "2.1.7";
16556        this.input = input;
16557        this.plugin_count = plugin_count;
16558        this.current_plugin = 0;
16559        this.calc_count = 0;
16560        this.update_tm = 0;
16561        this.old_from = 0;
16562        this.old_to = 0;
16563        this.old_min_interval = null;
16564        this.raf_id = null;
16565        this.dragging = false;
16566        this.force_redraw = false;
16567        this.no_diapason = false;
16568        this.is_key = false;
16569        this.is_update = false;
16570        this.is_start = true;
16571        this.is_finish = false;
16572        this.is_active = false;
16573        this.is_resize = false;
16574        this.is_click = false;
16575
16576        options = options || {};
16577
16578        // cache for links to all DOM elements
16579        this.$cache = {
16580            win: $(window),
16581            body: $(document.body),
16582            input: $(input),
16583            cont: null,
16584            rs: null,
16585            min: null,
16586            max: null,
16587            from: null,
16588            to: null,
16589            single: null,
16590            bar: null,
16591            line: null,
16592            s_single: null,
16593            s_from: null,
16594            s_to: null,
16595            shad_single: null,
16596            shad_from: null,
16597            shad_to: null,
16598            edge: null,
16599            grid: null,
16600            grid_labels: []
16601        };
16602
16603        // storage for measure variables
16604        this.coords = {
16605            // left
16606            x_gap: 0,
16607            x_pointer: 0,
16608
16609            // width
16610            w_rs: 0,
16611            w_rs_old: 0,
16612            w_handle: 0,
16613
16614            // percents
16615            p_gap: 0,
16616            p_gap_left: 0,
16617            p_gap_right: 0,
16618            p_step: 0,
16619            p_pointer: 0,
16620            p_handle: 0,
16621            p_single_fake: 0,
16622            p_single_real: 0,
16623            p_from_fake: 0,
16624            p_from_real: 0,
16625            p_to_fake: 0,
16626            p_to_real: 0,
16627            p_bar_x: 0,
16628            p_bar_w: 0,
16629
16630            // grid
16631            grid_gap: 0,
16632            big_num: 0,
16633            big: [],
16634            big_w: [],
16635            big_p: [],
16636            big_x: []
16637        };
16638
16639        // storage for labels measure variables
16640        this.labels = {
16641            // width
16642            w_min: 0,
16643            w_max: 0,
16644            w_from: 0,
16645            w_to: 0,
16646            w_single: 0,
16647
16648            // percents
16649            p_min: 0,
16650            p_max: 0,
16651            p_from_fake: 0,
16652            p_from_left: 0,
16653            p_to_fake: 0,
16654            p_to_left: 0,
16655            p_single_fake: 0,
16656            p_single_left: 0
16657        };
16658
16659
16660
16661        /**
16662         * get and validate config
16663         */
16664        var $inp = this.$cache.input,
16665            val = $inp.prop("value"),
16666            config, config_from_data, prop;
16667
16668        // default config
16669        config = {
16670            type: "single",
16671
16672            min: 10,
16673            max: 100,
16674            from: null,
16675            to: null,
16676            step: 1,
16677
16678            min_interval: 0,
16679            max_interval: 0,
16680            drag_interval: false,
16681
16682            values: [],
16683            p_values: [],
16684
16685            from_fixed: false,
16686            from_min: null,
16687            from_max: null,
16688            from_shadow: false,
16689
16690            to_fixed: false,
16691            to_min: null,
16692            to_max: null,
16693            to_shadow: false,
16694
16695            prettify_enabled: true,
16696            prettify_separator: " ",
16697            prettify: null,
16698
16699            force_edges: false,
16700
16701            keyboard: false,
16702            keyboard_step: 5,
16703
16704            grid: false,
16705            grid_margin: true,
16706            grid_num: 4,
16707            grid_snap: false,
16708
16709            hide_min_max: false,
16710            hide_from_to: false,
16711
16712            prefix: "",
16713            postfix: "",
16714            max_postfix: "",
16715            decorate_both: true,
16716            values_separator: " — ",
16717
16718            input_values_separator: ";",
16719
16720            disable: false,
16721
16722            onStart: null,
16723            onChange: null,
16724            onFinish: null,
16725            onUpdate: null
16726        };
16727
16728
16729        // check if base element is input
16730        if ($inp[0].nodeName !== "INPUT") {
16731            console && console.warn && console.warn("Base element should be <input>!", $inp[0]);
16732        }
16733
16734
16735        // config from data-attributes extends js config
16736        config_from_data = {
16737            type: $inp.data("type"),
16738
16739            min: $inp.data("min"),
16740            max: $inp.data("max"),
16741            from: $inp.data("from"),
16742            to: $inp.data("to"),
16743            step: $inp.data("step"),
16744
16745            min_interval: $inp.data("minInterval"),
16746            max_interval: $inp.data("maxInterval"),
16747            drag_interval: $inp.data("dragInterval"),
16748
16749            values: $inp.data("values"),
16750
16751            from_fixed: $inp.data("fromFixed"),
16752            from_min: $inp.data("fromMin"),
16753            from_max: $inp.data("fromMax"),
16754            from_shadow: $inp.data("fromShadow"),
16755
16756            to_fixed: $inp.data("toFixed"),
16757            to_min: $inp.data("toMin"),
16758            to_max: $inp.data("toMax"),
16759            to_shadow: $inp.data("toShadow"),
16760
16761            prettify_enabled: $inp.data("prettifyEnabled"),
16762            prettify_separator: $inp.data("prettifySeparator"),
16763
16764            force_edges: $inp.data("forceEdges"),
16765
16766            keyboard: $inp.data("keyboard"),
16767            keyboard_step: $inp.data("keyboardStep"),
16768
16769            grid: $inp.data("grid"),
16770            grid_margin: $inp.data("gridMargin"),
16771            grid_num: $inp.data("gridNum"),
16772            grid_snap: $inp.data("gridSnap"),
16773
16774            hide_min_max: $inp.data("hideMinMax"),
16775            hide_from_to: $inp.data("hideFromTo"),
16776
16777            prefix: $inp.data("prefix"),
16778            postfix: $inp.data("postfix"),
16779            max_postfix: $inp.data("maxPostfix"),
16780            decorate_both: $inp.data("decorateBoth"),
16781            values_separator: $inp.data("valuesSeparator"),
16782
16783            input_values_separator: $inp.data("inputValuesSeparator"),
16784
16785            disable: $inp.data("disable")
16786        };
16787        config_from_data.values = config_from_data.values && config_from_data.values.split(",");
16788
16789        for (prop in config_from_data) {
16790            if (config_from_data.hasOwnProperty(prop)) {
16791                if (config_from_data[prop] === undefined || config_from_data[prop] === "") {
16792                    delete config_from_data[prop];
16793                }
16794            }
16795        }
16796
16797
16798        // input value extends default config
16799        if (val !== undefined && val !== "") {
16800            val = val.split(config_from_data.input_values_separator || options.input_values_separator || ";");
16801
16802            if (val[0] && val[0] == +val[0]) {
16803                val[0] = +val[0];
16804            }
16805            if (val[1] && val[1] == +val[1]) {
16806                val[1] = +val[1];
16807            }
16808
16809            if (options && options.values && options.values.length) {
16810                config.from = val[0] && options.values.indexOf(val[0]);
16811                config.to = val[1] && options.values.indexOf(val[1]);
16812            } else {
16813                config.from = val[0] && +val[0];
16814                config.to = val[1] && +val[1];
16815            }
16816        }
16817
16818
16819
16820        // js config extends default config
16821        $.extend(config, options);
16822
16823
16824        // data config extends config
16825        $.extend(config, config_from_data);
16826        this.options = config;
16827
16828
16829
16830        // validate config, to be sure that all data types are correct
16831        this.update_check = {};
16832        this.validate();
16833
16834
16835
16836        // default result object, returned to callbacks
16837        this.result = {
16838            input: this.$cache.input,
16839            slider: null,
16840
16841            min: this.options.min,
16842            max: this.options.max,
16843
16844            from: this.options.from,
16845            from_percent: 0,
16846            from_value: null,
16847
16848            to: this.options.to,
16849            to_percent: 0,
16850            to_value: null
16851        };
16852
16853
16854
16855        this.init();
16856    };
16857
16858    IonRangeSlider.prototype = {
16859
16860        /**
16861         * Starts or updates the plugin instance
16862         *
16863         * @param [is_update] {boolean}
16864         */
16865        init: function (is_update) {
16866            this.no_diapason = false;
16867            this.coords.p_step = this.convertToPercent(this.options.step, true);
16868
16869            this.target = "base";
16870
16871            this.toggleInput();
16872            this.append();
16873            this.setMinMax();
16874
16875            if (is_update) {
16876                this.force_redraw = true;
16877                this.calc(true);
16878
16879                // callbacks called
16880                this.callOnUpdate();
16881            } else {
16882                this.force_redraw = true;
16883                this.calc(true);
16884
16885                // callbacks called
16886                this.callOnStart();
16887            }
16888
16889            this.updateScene();
16890        },
16891
16892        /**
16893         * Appends slider template to a DOM
16894         */
16895        append: function () {
16896            var container_html = '<span class="irs js-irs-' + this.plugin_count + '"></span>';
16897            this.$cache.input.before(container_html);
16898            this.$cache.input.prop("readonly", true);
16899            this.$cache.cont = this.$cache.input.prev();
16900            this.result.slider = this.$cache.cont;
16901
16902            this.$cache.cont.html(base_html);
16903            this.$cache.rs = this.$cache.cont.find(".irs");
16904            this.$cache.min = this.$cache.cont.find(".irs-min");
16905            this.$cache.max = this.$cache.cont.find(".irs-max");
16906            this.$cache.from = this.$cache.cont.find(".irs-from");
16907            this.$cache.to = this.$cache.cont.find(".irs-to");
16908            this.$cache.single = this.$cache.cont.find(".irs-single");
16909            this.$cache.bar = this.$cache.cont.find(".irs-bar");
16910            this.$cache.line = this.$cache.cont.find(".irs-line");
16911            this.$cache.grid = this.$cache.cont.find(".irs-grid");
16912
16913            if (this.options.type === "single") {
16914                this.$cache.cont.append(single_html);
16915                this.$cache.edge = this.$cache.cont.find(".irs-bar-edge");
16916                this.$cache.s_single = this.$cache.cont.find(".single");
16917                this.$cache.from[0].style.visibility = "hidden";
16918                this.$cache.to[0].style.visibility = "hidden";
16919                this.$cache.shad_single = this.$cache.cont.find(".shadow-single");
16920            } else {
16921                this.$cache.cont.append(double_html);
16922                this.$cache.s_from = this.$cache.cont.find(".from");
16923                this.$cache.s_to = this.$cache.cont.find(".to");
16924                this.$cache.shad_from = this.$cache.cont.find(".shadow-from");
16925                this.$cache.shad_to = this.$cache.cont.find(".shadow-to");
16926
16927                this.setTopHandler();
16928            }
16929
16930            if (this.options.hide_from_to) {
16931                this.$cache.from[0].style.display = "none";
16932                this.$cache.to[0].style.display = "none";
16933                this.$cache.single[0].style.display = "none";
16934            }
16935
16936            this.appendGrid();
16937
16938            if (this.options.disable) {
16939                this.appendDisableMask();
16940                this.$cache.input[0].disabled = true;
16941            } else {
16942                this.$cache.cont.removeClass("irs-disabled");
16943                this.$cache.input[0].disabled = false;
16944                this.bindEvents();
16945            }
16946
16947            if (this.options.drag_interval) {
16948                this.$cache.bar[0].style.cursor = "ew-resize";
16949            }
16950        },
16951
16952        /**
16953         * Determine which handler has a priority
16954         * works only for double slider type
16955         */
16956        setTopHandler: function () {
16957            var min = this.options.min,
16958                max = this.options.max,
16959                from = this.options.from,
16960                to = this.options.to;
16961
16962            if (from > min && to === max) {
16963                this.$cache.s_from.addClass("type_last");
16964            } else if (to < max) {
16965                this.$cache.s_to.addClass("type_last");
16966            }
16967        },
16968
16969        /**
16970         * Determine which handles was clicked last
16971         * and which handler should have hover effect
16972         *
16973         * @param target {String}
16974         */
16975        changeLevel: function (target) {
16976            switch (target) {
16977                case "single":
16978                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_single_fake);
16979                    break;
16980                case "from":
16981                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake);
16982                    this.$cache.s_from.addClass("state_hover");
16983                    this.$cache.s_from.addClass("type_last");
16984                    this.$cache.s_to.removeClass("type_last");
16985                    break;
16986                case "to":
16987                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_to_fake);
16988                    this.$cache.s_to.addClass("state_hover");
16989                    this.$cache.s_to.addClass("type_last");
16990                    this.$cache.s_from.removeClass("type_last");
16991                    break;
16992                case "both":
16993                    this.coords.p_gap_left = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake);
16994                    this.coords.p_gap_right = this.toFixed(this.coords.p_to_fake - this.coords.p_pointer);
16995                    this.$cache.s_to.removeClass("type_last");
16996                    this.$cache.s_from.removeClass("type_last");
16997                    break;
16998            }
16999        },
17000
17001        /**
17002         * Then slider is disabled
17003         * appends extra layer with opacity
17004         */
17005        appendDisableMask: function () {
17006            this.$cache.cont.append(disable_html);
17007            this.$cache.cont.addClass("irs-disabled");
17008        },
17009
17010        /**
17011         * Remove slider instance
17012         * and ubind all events
17013         */
17014        remove: function () {
17015            this.$cache.cont.remove();
17016            this.$cache.cont = null;
17017
17018            this.$cache.line.off("keydown.irs_" + this.plugin_count);
17019
17020            this.$cache.body.off("touchmove.irs_" + this.plugin_count);
17021            this.$cache.body.off("mousemove.irs_" + this.plugin_count);
17022
17023            this.$cache.win.off("touchend.irs_" + this.plugin_count);
17024            this.$cache.win.off("mouseup.irs_" + this.plugin_count);
17025
17026            if (is_old_ie) {
17027                this.$cache.body.off("mouseup.irs_" + this.plugin_count);
17028                this.$cache.body.off("mouseleave.irs_" + this.plugin_count);
17029            }
17030
17031            this.$cache.grid_labels = [];
17032            this.coords.big = [];
17033            this.coords.big_w = [];
17034            this.coords.big_p = [];
17035            this.coords.big_x = [];
17036
17037            cancelAnimationFrame(this.raf_id);
17038        },
17039
17040        /**
17041         * bind all slider events
17042         */
17043        bindEvents: function () {
17044            if (this.no_diapason) {
17045                return;
17046            }
17047
17048            this.$cache.body.on("touchmove.irs_" + this.plugin_count, this.pointerMove.bind(this));
17049            this.$cache.body.on("mousemove.irs_" + this.plugin_count, this.pointerMove.bind(this));
17050
17051            this.$cache.win.on("touchend.irs_" + this.plugin_count, this.pointerUp.bind(this));
17052            this.$cache.win.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
17053
17054            this.$cache.line.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
17055            this.$cache.line.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
17056
17057            if (this.options.drag_interval && this.options.type === "double") {
17058                this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
17059                this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
17060            } else {
17061                this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
17062                this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
17063            }
17064
17065            if (this.options.type === "single") {
17066                this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
17067                this.$cache.s_single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
17068                this.$cache.shad_single.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
17069
17070                this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
17071                this.$cache.s_single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
17072                this.$cache.edge.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
17073                this.$cache.shad_single.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
17074            } else {
17075                this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, null));
17076                this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, null));
17077
17078                this.$cache.from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
17079                this.$cache.s_from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
17080                this.$cache.to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
17081                this.$cache.s_to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
17082                this.$cache.shad_from.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
17083                this.$cache.shad_to.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
17084
17085                this.$cache.from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
17086                this.$cache.s_from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
17087                this.$cache.to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
17088                this.$cache.s_to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
17089                this.$cache.shad_from.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
17090                this.$cache.shad_to.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
17091            }
17092
17093            if (this.options.keyboard) {
17094                this.$cache.line.on("keydown.irs_" + this.plugin_count, this.key.bind(this, "keyboard"));
17095            }
17096
17097            if (is_old_ie) {
17098                this.$cache.body.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
17099                this.$cache.body.on("mouseleave.irs_" + this.plugin_count, this.pointerUp.bind(this));
17100            }
17101        },
17102
17103        /**
17104         * Mousemove or touchmove
17105         * only for handlers
17106         *
17107         * @param e {Object} event object
17108         */
17109        pointerMove: function (e) {
17110            if (!this.dragging) {
17111                return;
17112            }
17113
17114            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
17115            this.coords.x_pointer = x - this.coords.x_gap;
17116
17117            this.calc();
17118        },
17119
17120        /**
17121         * Mouseup or touchend
17122         * only for handlers
17123         *
17124         * @param e {Object} event object
17125         */
17126        pointerUp: function (e) {
17127            if (this.current_plugin !== this.plugin_count) {
17128                return;
17129            }
17130
17131            if (this.is_active) {
17132                this.is_active = false;
17133            } else {
17134                return;
17135            }
17136
17137            this.$cache.cont.find(".state_hover").removeClass("state_hover");
17138
17139            this.force_redraw = true;
17140
17141            if (is_old_ie) {
17142                $("*").prop("unselectable", false);
17143            }
17144
17145            this.updateScene();
17146            this.restoreOriginalMinInterval();
17147
17148            // callbacks call
17149            if ($.contains(this.$cache.cont[0], e.target) || this.dragging) {
17150                this.callOnFinish();
17151            }
17152            
17153            this.dragging = false;
17154        },
17155
17156        /**
17157         * Mousedown or touchstart
17158         * only for handlers
17159         *
17160         * @param target {String|null}
17161         * @param e {Object} event object
17162         */
17163        pointerDown: function (target, e) {
17164            e.preventDefault();
17165            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
17166            if (e.button === 2) {
17167                return;
17168            }
17169
17170            if (target === "both") {
17171                this.setTempMinInterval();
17172            }
17173
17174            if (!target) {
17175                target = this.target || "from";
17176            }
17177
17178            this.current_plugin = this.plugin_count;
17179            this.target = target;
17180
17181            this.is_active = true;
17182            this.dragging = true;
17183
17184            this.coords.x_gap = this.$cache.rs.offset().left;
17185            this.coords.x_pointer = x - this.coords.x_gap;
17186
17187            this.calcPointerPercent();
17188            this.changeLevel(target);
17189
17190            if (is_old_ie) {
17191                $("*").prop("unselectable", true);
17192            }
17193
17194            this.$cache.line.trigger("focus");
17195
17196            this.updateScene();
17197        },
17198
17199        /**
17200         * Mousedown or touchstart
17201         * for other slider elements, like diapason line
17202         *
17203         * @param target {String}
17204         * @param e {Object} event object
17205         */
17206        pointerClick: function (target, e) {
17207            e.preventDefault();
17208            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
17209            if (e.button === 2) {
17210                return;
17211            }
17212
17213            this.current_plugin = this.plugin_count;
17214            this.target = target;
17215
17216            this.is_click = true;
17217            this.coords.x_gap = this.$cache.rs.offset().left;
17218            this.coords.x_pointer = +(x - this.coords.x_gap).toFixed();
17219
17220            this.force_redraw = true;
17221            this.calc();
17222
17223            this.$cache.line.trigger("focus");
17224        },
17225
17226        /**
17227         * Keyborard controls for focused slider
17228         *
17229         * @param target {String}
17230         * @param e {Object} event object
17231         * @returns {boolean|undefined}
17232         */
17233        key: function (target, e) {
17234            if (this.current_plugin !== this.plugin_count || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
17235                return;
17236            }
17237
17238            switch (e.which) {
17239                case 83: // W
17240                case 65: // A
17241                case 40: // DOWN
17242                case 37: // LEFT
17243                    e.preventDefault();
17244                    this.moveByKey(false);
17245                    break;
17246
17247                case 87: // S
17248                case 68: // D
17249                case 38: // UP
17250                case 39: // RIGHT
17251                    e.preventDefault();
17252                    this.moveByKey(true);
17253                    break;
17254            }
17255
17256            return true;
17257        },
17258
17259        /**
17260         * Move by key. Beta
17261         * @todo refactor than have plenty of time
17262         *
17263         * @param right {boolean} direction to move
17264         */
17265        moveByKey: function (right) {
17266            var p = this.coords.p_pointer;
17267
17268            if (right) {
17269                p += this.options.keyboard_step;
17270            } else {
17271                p -= this.options.keyboard_step;
17272            }
17273
17274            this.coords.x_pointer = this.toFixed(this.coords.w_rs / 100 * p);
17275            this.is_key = true;
17276            this.calc();
17277        },
17278
17279        /**
17280         * Set visibility and content
17281         * of Min and Max labels
17282         */
17283        setMinMax: function () {
17284            if (!this.options) {
17285                return;
17286            }
17287
17288            if (this.options.hide_min_max) {
17289                this.$cache.min[0].style.display = "none";
17290                this.$cache.max[0].style.display = "none";
17291                return;
17292            }
17293
17294            if (this.options.values.length) {
17295                this.$cache.min.html(this.decorate(this.options.p_values[this.options.min]));
17296                this.$cache.max.html(this.decorate(this.options.p_values[this.options.max]));
17297            } else {
17298                this.$cache.min.html(this.decorate(this._prettify(this.options.min), this.options.min));
17299                this.$cache.max.html(this.decorate(this._prettify(this.options.max), this.options.max));
17300            }
17301
17302            this.labels.w_min = this.$cache.min.outerWidth(false);
17303            this.labels.w_max = this.$cache.max.outerWidth(false);
17304        },
17305
17306        /**
17307         * Then dragging interval, prevent interval collapsing
17308         * using min_interval option
17309         */
17310        setTempMinInterval: function () {
17311            var interval = this.result.to - this.result.from;
17312
17313            if (this.old_min_interval === null) {
17314                this.old_min_interval = this.options.min_interval;
17315            }
17316
17317            this.options.min_interval = interval;
17318        },
17319
17320        /**
17321         * Restore min_interval option to original
17322         */
17323        restoreOriginalMinInterval: function () {
17324            if (this.old_min_interval !== null) {
17325                this.options.min_interval = this.old_min_interval;
17326                this.old_min_interval = null;
17327            }
17328        },
17329
17330
17331
17332        // =============================================================================================================
17333        // Calculations
17334
17335        /**
17336         * All calculations and measures start here
17337         *
17338         * @param update {boolean=}
17339         */
17340        calc: function (update) {
17341            if (!this.options) {
17342                return;
17343            }
17344
17345            this.calc_count++;
17346
17347            if (this.calc_count === 10 || update) {
17348                this.calc_count = 0;
17349                this.coords.w_rs = this.$cache.rs.outerWidth(false);
17350
17351                this.calcHandlePercent();
17352            }
17353
17354            if (!this.coords.w_rs) {
17355                return;
17356            }
17357
17358            this.calcPointerPercent();
17359            var handle_x = this.getHandleX();
17360
17361
17362            if (this.target === "both") {
17363                this.coords.p_gap = 0;
17364                handle_x = this.getHandleX();
17365            }
17366
17367            if (this.target === "click") {
17368                this.coords.p_gap = this.coords.p_handle / 2;
17369                handle_x = this.getHandleX();
17370
17371                if (this.options.drag_interval) {
17372                    this.target = "both_one";
17373                } else {
17374                    this.target = this.chooseHandle(handle_x);
17375                }
17376            }
17377
17378            switch (this.target) {
17379                case "base":
17380                    var w = (this.options.max - this.options.min) / 100,
17381                        f = (this.result.from - this.options.min) / w,
17382                        t = (this.result.to - this.options.min) / w;
17383
17384                    this.coords.p_single_real = this.toFixed(f);
17385                    this.coords.p_from_real = this.toFixed(f);
17386                    this.coords.p_to_real = this.toFixed(t);
17387
17388                    this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
17389                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
17390                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
17391
17392                    this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real);
17393                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
17394                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
17395
17396                    this.target = null;
17397
17398                    break;
17399
17400                case "single":
17401                    if (this.options.from_fixed) {
17402                        break;
17403                    }
17404
17405                    this.coords.p_single_real = this.convertToRealPercent(handle_x);
17406                    this.coords.p_single_real = this.calcWithStep(this.coords.p_single_real);
17407                    this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
17408
17409                    this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real);
17410
17411                    break;
17412
17413                case "from":
17414                    if (this.options.from_fixed) {
17415                        break;
17416                    }
17417
17418                    this.coords.p_from_real = this.convertToRealPercent(handle_x);
17419                    this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real);
17420                    if (this.coords.p_from_real > this.coords.p_to_real) {
17421                        this.coords.p_from_real = this.coords.p_to_real;
17422                    }
17423                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
17424                    this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
17425                    this.coords.p_from_real = this.checkMaxInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
17426
17427                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
17428
17429                    break;
17430
17431                case "to":
17432                    if (this.options.to_fixed) {
17433                        break;
17434                    }
17435
17436                    this.coords.p_to_real = this.convertToRealPercent(handle_x);
17437                    this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real);
17438                    if (this.coords.p_to_real < this.coords.p_from_real) {
17439                        this.coords.p_to_real = this.coords.p_from_real;
17440                    }
17441                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
17442                    this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
17443                    this.coords.p_to_real = this.checkMaxInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
17444
17445                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
17446
17447                    break;
17448
17449                case "both":
17450                    if (this.options.from_fixed || this.options.to_fixed) {
17451                        break;
17452                    }
17453
17454                    handle_x = this.toFixed(handle_x + (this.coords.p_handle * 0.001));
17455
17456                    this.coords.p_from_real = this.convertToRealPercent(handle_x) - this.coords.p_gap_left;
17457                    this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real);
17458                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
17459                    this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
17460                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
17461
17462                    this.coords.p_to_real = this.convertToRealPercent(handle_x) + this.coords.p_gap_right;
17463                    this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real);
17464                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
17465                    this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
17466                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
17467
17468                    break;
17469
17470                case "both_one":
17471                    if (this.options.from_fixed || this.options.to_fixed) {
17472                        break;
17473                    }
17474
17475                    var real_x = this.convertToRealPercent(handle_x),
17476                        from = this.result.from_percent,
17477                        to = this.result.to_percent,
17478                        full = to - from,
17479                        half = full / 2,
17480                        new_from = real_x - half,
17481                        new_to = real_x + half;
17482
17483                    if (new_from < 0) {
17484                        new_from = 0;
17485                        new_to = new_from + full;
17486                    }
17487
17488                    if (new_to > 100) {
17489                        new_to = 100;
17490                        new_from = new_to - full;
17491                    }
17492
17493                    this.coords.p_from_real = this.calcWithStep(new_from);
17494                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
17495                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
17496
17497                    this.coords.p_to_real = this.calcWithStep(new_to);
17498                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
17499                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
17500
17501                    break;
17502            }
17503
17504            if (this.options.type === "single") {
17505                this.coords.p_bar_x = (this.coords.p_handle / 2);
17506                this.coords.p_bar_w = this.coords.p_single_fake;
17507
17508                this.result.from_percent = this.coords.p_single_real;
17509                this.result.from = this.convertToValue(this.coords.p_single_real);
17510
17511                if (this.options.values.length) {
17512                    this.result.from_value = this.options.values[this.result.from];
17513                }
17514            } else {
17515                this.coords.p_bar_x = this.toFixed(this.coords.p_from_fake + (this.coords.p_handle / 2));
17516                this.coords.p_bar_w = this.toFixed(this.coords.p_to_fake - this.coords.p_from_fake);
17517
17518                this.result.from_percent = this.coords.p_from_real;
17519                this.result.from = this.convertToValue(this.coords.p_from_real);
17520                this.result.to_percent = this.coords.p_to_real;
17521                this.result.to = this.convertToValue(this.coords.p_to_real);
17522
17523                if (this.options.values.length) {
17524                    this.result.from_value = this.options.values[this.result.from];
17525                    this.result.to_value = this.options.values[this.result.to];
17526                }
17527            }
17528
17529            this.calcMinMax();
17530            this.calcLabels();
17531        },
17532
17533
17534        /**
17535         * calculates pointer X in percent
17536         */
17537        calcPointerPercent: function () {
17538            if (!this.coords.w_rs) {
17539                this.coords.p_pointer = 0;
17540                return;
17541            }
17542
17543            if (this.coords.x_pointer < 0 || isNaN(this.coords.x_pointer)  ) {
17544                this.coords.x_pointer = 0;
17545            } else if (this.coords.x_pointer > this.coords.w_rs) {
17546                this.coords.x_pointer = this.coords.w_rs;
17547            }
17548
17549            this.coords.p_pointer = this.toFixed(this.coords.x_pointer / this.coords.w_rs * 100);
17550        },
17551
17552        convertToRealPercent: function (fake) {
17553            var full = 100 - this.coords.p_handle;
17554            return fake / full * 100;
17555        },
17556
17557        convertToFakePercent: function (real) {
17558            var full = 100 - this.coords.p_handle;
17559            return real / 100 * full;
17560        },
17561
17562        getHandleX: function () {
17563            var max = 100 - this.coords.p_handle,
17564                x = this.toFixed(this.coords.p_pointer - this.coords.p_gap);
17565
17566            if (x < 0) {
17567                x = 0;
17568            } else if (x > max) {
17569                x = max;
17570            }
17571
17572            return x;
17573        },
17574
17575        calcHandlePercent: function () {
17576            if (this.options.type === "single") {
17577                this.coords.w_handle = this.$cache.s_single.outerWidth(false);
17578            } else {
17579                this.coords.w_handle = this.$cache.s_from.outerWidth(false);
17580            }
17581
17582            this.coords.p_handle = this.toFixed(this.coords.w_handle / this.coords.w_rs * 100);
17583        },
17584
17585        /**
17586         * Find closest handle to pointer click
17587         *
17588         * @param real_x {Number}
17589         * @returns {String}
17590         */
17591        chooseHandle: function (real_x) {
17592            if (this.options.type === "single") {
17593                return "single";
17594            } else {
17595                var m_point = this.coords.p_from_real + ((this.coords.p_to_real - this.coords.p_from_real) / 2);
17596                if (real_x >= m_point) {
17597                    return this.options.to_fixed ? "from" : "to";
17598                } else {
17599                    return this.options.from_fixed ? "to" : "from";
17600                }
17601            }
17602        },
17603
17604        /**
17605         * Measure Min and Max labels width in percent
17606         */
17607        calcMinMax: function () {
17608            if (!this.coords.w_rs) {
17609                return;
17610            }
17611
17612            this.labels.p_min = this.labels.w_min / this.coords.w_rs * 100;
17613            this.labels.p_max = this.labels.w_max / this.coords.w_rs * 100;
17614        },
17615
17616        /**
17617         * Measure labels width and X in percent
17618         */
17619        calcLabels: function () {
17620            if (!this.coords.w_rs || this.options.hide_from_to) {
17621                return;
17622            }
17623
17624            if (this.options.type === "single") {
17625
17626                this.labels.w_single = this.$cache.single.outerWidth(false);
17627                this.labels.p_single_fake = this.labels.w_single / this.coords.w_rs * 100;
17628                this.labels.p_single_left = this.coords.p_single_fake + (this.coords.p_handle / 2) - (this.labels.p_single_fake / 2);
17629                this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single_fake);
17630
17631            } else {
17632
17633                this.labels.w_from = this.$cache.from.outerWidth(false);
17634                this.labels.p_from_fake = this.labels.w_from / this.coords.w_rs * 100;
17635                this.labels.p_from_left = this.coords.p_from_fake + (this.coords.p_handle / 2) - (this.labels.p_from_fake / 2);
17636                this.labels.p_from_left = this.toFixed(this.labels.p_from_left);
17637                this.labels.p_from_left = this.checkEdges(this.labels.p_from_left, this.labels.p_from_fake);
17638
17639                this.labels.w_to = this.$cache.to.outerWidth(false);
17640                this.labels.p_to_fake = this.labels.w_to / this.coords.w_rs * 100;
17641                this.labels.p_to_left = this.coords.p_to_fake + (this.coords.p_handle / 2) - (this.labels.p_to_fake / 2);
17642                this.labels.p_to_left = this.toFixed(this.labels.p_to_left);
17643                this.labels.p_to_left = this.checkEdges(this.labels.p_to_left, this.labels.p_to_fake);
17644
17645                this.labels.w_single = this.$cache.single.outerWidth(false);
17646                this.labels.p_single_fake = this.labels.w_single / this.coords.w_rs * 100;
17647                this.labels.p_single_left = ((this.labels.p_from_left + this.labels.p_to_left + this.labels.p_to_fake) / 2) - (this.labels.p_single_fake / 2);
17648                this.labels.p_single_left = this.toFixed(this.labels.p_single_left);
17649                this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single_fake);
17650
17651            }
17652        },
17653
17654
17655
17656        // =============================================================================================================
17657        // Drawings
17658
17659        /**
17660         * Main function called in request animation frame
17661         * to update everything
17662         */
17663        updateScene: function () {
17664            if (this.raf_id) {
17665                cancelAnimationFrame(this.raf_id);
17666                this.raf_id = null;
17667            }
17668
17669            clearTimeout(this.update_tm);
17670            this.update_tm = null;
17671
17672            if (!this.options) {
17673                return;
17674            }
17675
17676            this.drawHandles();
17677
17678            if (this.is_active) {
17679                this.raf_id = requestAnimationFrame(this.updateScene.bind(this));
17680            } else {
17681                this.update_tm = setTimeout(this.updateScene.bind(this), 300);
17682            }
17683        },
17684
17685        /**
17686         * Draw handles
17687         */
17688        drawHandles: function () {
17689            this.coords.w_rs = this.$cache.rs.outerWidth(false);
17690
17691            if (!this.coords.w_rs) {
17692                return;
17693            }
17694
17695            if (this.coords.w_rs !== this.coords.w_rs_old) {
17696                this.target = "base";
17697                this.is_resize = true;
17698            }
17699
17700            if (this.coords.w_rs !== this.coords.w_rs_old || this.force_redraw) {
17701                this.setMinMax();
17702                this.calc(true);
17703                this.drawLabels();
17704                if (this.options.grid) {
17705                    this.calcGridMargin();
17706                    this.calcGridLabels();
17707                }
17708                this.force_redraw = true;
17709                this.coords.w_rs_old = this.coords.w_rs;
17710                this.drawShadow();
17711            }
17712
17713            if (!this.coords.w_rs) {
17714                return;
17715            }
17716
17717            if (!this.dragging && !this.force_redraw && !this.is_key) {
17718                return;
17719            }
17720
17721            if (this.old_from !== this.result.from || this.old_to !== this.result.to || this.force_redraw || this.is_key) {
17722
17723                this.drawLabels();
17724
17725                this.$cache.bar[0].style.left = this.coords.p_bar_x + "%";
17726                this.$cache.bar[0].style.width = this.coords.p_bar_w + "%";
17727
17728                if (this.options.type === "single") {
17729                    this.$cache.s_single[0].style.left = this.coords.p_single_fake + "%";
17730
17731                    this.$cache.single[0].style.left = this.labels.p_single_left + "%";
17732                } else {
17733                    this.$cache.s_from[0].style.left = this.coords.p_from_fake + "%";
17734                    this.$cache.s_to[0].style.left = this.coords.p_to_fake + "%";
17735
17736                    if (this.old_from !== this.result.from || this.force_redraw) {
17737                        this.$cache.from[0].style.left = this.labels.p_from_left + "%";
17738                    }
17739                    if (this.old_to !== this.result.to || this.force_redraw) {
17740                        this.$cache.to[0].style.left = this.labels.p_to_left + "%";
17741                    }
17742
17743                    this.$cache.single[0].style.left = this.labels.p_single_left + "%";
17744                }
17745
17746                this.writeToInput();
17747
17748                if ((this.old_from !== this.result.from || this.old_to !== this.result.to) && !this.is_start) {
17749                    this.$cache.input.trigger("change");
17750                    this.$cache.input.trigger("input");
17751                }
17752
17753                this.old_from = this.result.from;
17754                this.old_to = this.result.to;
17755
17756                // callbacks call
17757                if (!this.is_resize && !this.is_update && !this.is_start && !this.is_finish) {
17758                    this.callOnChange();
17759                }
17760                if (this.is_key || this.is_click) {
17761                    this.is_key = false;
17762                    this.is_click = false;
17763                    this.callOnFinish();
17764                }
17765
17766                this.is_update = false;
17767                this.is_resize = false;
17768                this.is_finish = false;
17769            }
17770
17771            this.is_start = false;
17772            this.is_key = false;
17773            this.is_click = false;
17774            this.force_redraw = false;
17775        },
17776
17777        /**
17778         * Draw labels
17779         * measure labels collisions
17780         * collapse close labels
17781         */
17782        drawLabels: function () {
17783            if (!this.options) {
17784                return;
17785            }
17786
17787            var values_num = this.options.values.length,
17788                p_values = this.options.p_values,
17789                text_single,
17790                text_from,
17791                text_to;
17792
17793            if (this.options.hide_from_to) {
17794                return;
17795            }
17796
17797            if (this.options.type === "single") {
17798
17799                if (values_num) {
17800                    text_single = this.decorate(p_values[this.result.from]);
17801                    this.$cache.single.html(text_single);
17802                } else {
17803                    text_single = this.decorate(this._prettify(this.result.from), this.result.from);
17804                    this.$cache.single.html(text_single);
17805                }
17806
17807                this.calcLabels();
17808
17809                if (this.labels.p_single_left < this.labels.p_min + 1) {
17810                    this.$cache.min[0].style.visibility = "hidden";
17811                } else {
17812                    this.$cache.min[0].style.visibility = "visible";
17813                }
17814
17815                if (this.labels.p_single_left + this.labels.p_single_fake > 100 - this.labels.p_max - 1) {
17816                    this.$cache.max[0].style.visibility = "hidden";
17817                } else {
17818                    this.$cache.max[0].style.visibility = "visible";
17819                }
17820
17821            } else {
17822
17823                if (values_num) {
17824
17825                    if (this.options.decorate_both) {
17826                        text_single = this.decorate(p_values[this.result.from]);
17827                        text_single += this.options.values_separator;
17828                        text_single += this.decorate(p_values[this.result.to]);
17829                    } else {
17830                        text_single = this.decorate(p_values[this.result.from] + this.options.values_separator + p_values[this.result.to]);
17831                    }
17832                    text_from = this.decorate(p_values[this.result.from]);
17833                    text_to = this.decorate(p_values[this.result.to]);
17834
17835                    this.$cache.single.html(text_single);
17836                    this.$cache.from.html(text_from);
17837                    this.$cache.to.html(text_to);
17838
17839                } else {
17840
17841                    if (this.options.decorate_both) {
17842                        text_single = this.decorate(this._prettify(this.result.from), this.result.from);
17843                        text_single += this.options.values_separator;
17844                        text_single += this.decorate(this._prettify(this.result.to), this.result.to);
17845                    } else {
17846                        text_single = this.decorate(this._prettify(this.result.from) + this.options.values_separator + this._prettify(this.result.to), this.result.to);
17847                    }
17848                    text_from = this.decorate(this._prettify(this.result.from), this.result.from);
17849                    text_to = this.decorate(this._prettify(this.result.to), this.result.to);
17850
17851                    this.$cache.single.html(text_single);
17852                    this.$cache.from.html(text_from);
17853                    this.$cache.to.html(text_to);
17854
17855                }
17856
17857                this.calcLabels();
17858
17859                var min = Math.min(this.labels.p_single_left, this.labels.p_from_left),
17860                    single_left = this.labels.p_single_left + this.labels.p_single_fake,
17861                    to_left = this.labels.p_to_left + this.labels.p_to_fake,
17862                    max = Math.max(single_left, to_left);
17863
17864                if (this.labels.p_from_left + this.labels.p_from_fake >= this.labels.p_to_left) {
17865                    this.$cache.from[0].style.visibility = "hidden";
17866                    this.$cache.to[0].style.visibility = "hidden";
17867                    this.$cache.single[0].style.visibility = "visible";
17868
17869                    if (this.result.from === this.result.to) {
17870                        if (this.target === "from") {
17871                            this.$cache.from[0].style.visibility = "visible";
17872                        } else if (this.target === "to") {
17873                            this.$cache.to[0].style.visibility = "visible";
17874                        } else if (!this.target) {
17875                            this.$cache.from[0].style.visibility = "visible";
17876                        }
17877                        this.$cache.single[0].style.visibility = "hidden";
17878                        max = to_left;
17879                    } else {
17880                        this.$cache.from[0].style.visibility = "hidden";
17881                        this.$cache.to[0].style.visibility = "hidden";
17882                        this.$cache.single[0].style.visibility = "visible";
17883                        max = Math.max(single_left, to_left);
17884                    }
17885                } else {
17886                    this.$cache.from[0].style.visibility = "visible";
17887                    this.$cache.to[0].style.visibility = "visible";
17888                    this.$cache.single[0].style.visibility = "hidden";
17889                }
17890
17891                if (min < this.labels.p_min + 1) {
17892                    this.$cache.min[0].style.visibility = "hidden";
17893                } else {
17894                    this.$cache.min[0].style.visibility = "visible";
17895                }
17896
17897                if (max > 100 - this.labels.p_max - 1) {
17898                    this.$cache.max[0].style.visibility = "hidden";
17899                } else {
17900                    this.$cache.max[0].style.visibility = "visible";
17901                }
17902
17903            }
17904        },
17905
17906        /**
17907         * Draw shadow intervals
17908         */
17909        drawShadow: function () {
17910            var o = this.options,
17911                c = this.$cache,
17912
17913                is_from_min = typeof o.from_min === "number" && !isNaN(o.from_min),
17914                is_from_max = typeof o.from_max === "number" && !isNaN(o.from_max),
17915                is_to_min = typeof o.to_min === "number" && !isNaN(o.to_min),
17916                is_to_max = typeof o.to_max === "number" && !isNaN(o.to_max),
17917
17918                from_min,
17919                from_max,
17920                to_min,
17921                to_max;
17922
17923            if (o.type === "single") {
17924                if (o.from_shadow && (is_from_min || is_from_max)) {
17925                    from_min = this.convertToPercent(is_from_min ? o.from_min : o.min);
17926                    from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min;
17927                    from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
17928                    from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
17929                    from_min = from_min + (this.coords.p_handle / 2);
17930
17931                    c.shad_single[0].style.display = "block";
17932                    c.shad_single[0].style.left = from_min + "%";
17933                    c.shad_single[0].style.width = from_max + "%";
17934                } else {
17935                    c.shad_single[0].style.display = "none";
17936                }
17937            } else {
17938                if (o.from_shadow && (is_from_min || is_from_max)) {
17939                    from_min = this.convertToPercent(is_from_min ? o.from_min : o.min);
17940                    from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min;
17941                    from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
17942                    from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
17943                    from_min = from_min + (this.coords.p_handle / 2);
17944
17945                    c.shad_from[0].style.display = "block";
17946                    c.shad_from[0].style.left = from_min + "%";
17947                    c.shad_from[0].style.width = from_max + "%";
17948                } else {
17949                    c.shad_from[0].style.display = "none";
17950                }
17951
17952                if (o.to_shadow && (is_to_min || is_to_max)) {
17953                    to_min = this.convertToPercent(is_to_min ? o.to_min : o.min);
17954                    to_max = this.convertToPercent(is_to_max ? o.to_max : o.max) - to_min;
17955                    to_min = this.toFixed(to_min - (this.coords.p_handle / 100 * to_min));
17956                    to_max = this.toFixed(to_max - (this.coords.p_handle / 100 * to_max));
17957                    to_min = to_min + (this.coords.p_handle / 2);
17958
17959                    c.shad_to[0].style.display = "block";
17960                    c.shad_to[0].style.left = to_min + "%";
17961                    c.shad_to[0].style.width = to_max + "%";
17962                } else {
17963                    c.shad_to[0].style.display = "none";
17964                }
17965            }
17966        },
17967
17968
17969
17970        /**
17971         * Write values to input element
17972         */
17973        writeToInput: function () {
17974            if (this.options.type === "single") {
17975                if (this.options.values.length) {
17976                    this.$cache.input.prop("value", this.result.from_value);
17977                } else {
17978                    this.$cache.input.prop("value", this.result.from);
17979                }
17980                this.$cache.input.data("from", this.result.from);
17981            } else {
17982                if (this.options.values.length) {
17983                    this.$cache.input.prop("value", this.result.from_value + this.options.input_values_separator + this.result.to_value);
17984                } else {
17985                    this.$cache.input.prop("value", this.result.from + this.options.input_values_separator + this.result.to);
17986                }
17987                this.$cache.input.data("from", this.result.from);
17988                this.$cache.input.data("to", this.result.to);
17989            }
17990        },
17991
17992
17993
17994        // =============================================================================================================
17995        // Callbacks
17996
17997        callOnStart: function () {
17998            this.writeToInput();
17999
18000            if (this.options.onStart && typeof this.options.onStart === "function") {
18001                this.options.onStart(this.result);
18002            }
18003        },
18004        callOnChange: function () {
18005            this.writeToInput();
18006
18007            if (this.options.onChange && typeof this.options.onChange === "function") {
18008                this.options.onChange(this.result);
18009            }
18010        },
18011        callOnFinish: function () {
18012            this.writeToInput();
18013
18014            if (this.options.onFinish && typeof this.options.onFinish === "function") {
18015                this.options.onFinish(this.result);
18016            }
18017        },
18018        callOnUpdate: function () {
18019            this.writeToInput();
18020
18021            if (this.options.onUpdate && typeof this.options.onUpdate === "function") {
18022                this.options.onUpdate(this.result);
18023            }
18024        },
18025
18026
18027
18028
18029        // =============================================================================================================
18030        // Service methods
18031
18032        toggleInput: function () {
18033            this.$cache.input.toggleClass("irs-hidden-input");
18034        },
18035
18036        /**
18037         * Convert real value to percent
18038         *
18039         * @param value {Number} X in real
18040         * @param no_min {boolean=} don't use min value
18041         * @returns {Number} X in percent
18042         */
18043        convertToPercent: function (value, no_min) {
18044            var diapason = this.options.max - this.options.min,
18045                one_percent = diapason / 100,
18046                val, percent;
18047
18048            if (!diapason) {
18049                this.no_diapason = true;
18050                return 0;
18051            }
18052
18053            if (no_min) {
18054                val = value;
18055            } else {
18056                val = value - this.options.min;
18057            }
18058
18059            percent = val / one_percent;
18060
18061            return this.toFixed(percent);
18062        },
18063
18064        /**
18065         * Convert percent to real values
18066         *
18067         * @param percent {Number} X in percent
18068         * @returns {Number} X in real
18069         */
18070        convertToValue: function (percent) {
18071            var min = this.options.min,
18072                max = this.options.max,
18073                min_decimals = min.toString().split(".")[1],
18074                max_decimals = max.toString().split(".")[1],
18075                min_length, max_length,
18076                avg_decimals = 0,
18077                abs = 0;
18078
18079            if (percent === 0) {
18080                return this.options.min;
18081            }
18082            if (percent === 100) {
18083                return this.options.max;
18084            }
18085
18086
18087            if (min_decimals) {
18088                min_length = min_decimals.length;
18089                avg_decimals = min_length;
18090            }
18091            if (max_decimals) {
18092                max_length = max_decimals.length;
18093                avg_decimals = max_length;
18094            }
18095            if (min_length && max_length) {
18096                avg_decimals = (min_length >= max_length) ? min_length : max_length;
18097            }
18098
18099            if (min < 0) {
18100                abs = Math.abs(min);
18101                min = +(min + abs).toFixed(avg_decimals);
18102                max = +(max + abs).toFixed(avg_decimals);
18103            }
18104
18105            var number = ((max - min) / 100 * percent) + min,
18106                string = this.options.step.toString().split(".")[1],
18107                result;
18108
18109            if (string) {
18110                number = +number.toFixed(string.length);
18111            } else {
18112                number = number / this.options.step;
18113                number = number * this.options.step;
18114
18115                number = +number.toFixed(0);
18116            }
18117
18118            if (abs) {
18119                number -= abs;
18120            }
18121
18122            if (string) {
18123                result = +number.toFixed(string.length);
18124            } else {
18125                result = this.toFixed(number);
18126            }
18127
18128            if (result < this.options.min) {
18129                result = this.options.min;
18130            } else if (result > this.options.max) {
18131                result = this.options.max;
18132            }
18133
18134            return result;
18135        },
18136
18137        /**
18138         * Round percent value with step
18139         *
18140         * @param percent {Number}
18141         * @returns percent {Number} rounded
18142         */
18143        calcWithStep: function (percent) {
18144            var rounded = Math.round(percent / this.coords.p_step) * this.coords.p_step;
18145
18146            if (rounded > 100) {
18147                rounded = 100;
18148            }
18149            if (percent === 100) {
18150                rounded = 100;
18151            }
18152
18153            return this.toFixed(rounded);
18154        },
18155
18156        checkMinInterval: function (p_current, p_next, type) {
18157            var o = this.options,
18158                current,
18159                next;
18160
18161            if (!o.min_interval) {
18162                return p_current;
18163            }
18164
18165            current = this.convertToValue(p_current);
18166            next = this.convertToValue(p_next);
18167
18168            if (type === "from") {
18169
18170                if (next - current < o.min_interval) {
18171                    current = next - o.min_interval;
18172                }
18173
18174            } else {
18175
18176                if (current - next < o.min_interval) {
18177                    current = next + o.min_interval;
18178                }
18179
18180            }
18181
18182            return this.convertToPercent(current);
18183        },
18184
18185        checkMaxInterval: function (p_current, p_next, type) {
18186            var o = this.options,
18187                current,
18188                next;
18189
18190            if (!o.max_interval) {
18191                return p_current;
18192            }
18193
18194            current = this.convertToValue(p_current);
18195            next = this.convertToValue(p_next);
18196
18197            if (type === "from") {
18198
18199                if (next - current > o.max_interval) {
18200                    current = next - o.max_interval;
18201                }
18202
18203            } else {
18204
18205                if (current - next > o.max_interval) {
18206                    current = next + o.max_interval;
18207                }
18208
18209            }
18210
18211            return this.convertToPercent(current);
18212        },
18213
18214        checkDiapason: function (p_num, min, max) {
18215            var num = this.convertToValue(p_num),
18216                o = this.options;
18217
18218            if (typeof min !== "number") {
18219                min = o.min;
18220            }
18221
18222            if (typeof max !== "number") {
18223                max = o.max;
18224            }
18225
18226            if (num < min) {
18227                num = min;
18228            }
18229
18230            if (num > max) {
18231                num = max;
18232            }
18233
18234            return this.convertToPercent(num);
18235        },
18236
18237        toFixed: function (num) {
18238            num = num.toFixed(20);
18239            return +num;
18240        },
18241
18242        _prettify: function (num) {
18243            if (!this.options.prettify_enabled) {
18244                return num;
18245            }
18246
18247            if (this.options.prettify && typeof this.options.prettify === "function") {
18248                return this.options.prettify(num);
18249            } else {
18250                return this.prettify(num);
18251            }
18252        },
18253
18254        prettify: function (num) {
18255            var n = num.toString();
18256            return n.replace(/(\d{1,3}(?=(?:\d\d\d)+(?!\d)))/g, "$1" + this.options.prettify_separator);
18257        },
18258
18259        checkEdges: function (left, width) {
18260            if (!this.options.force_edges) {
18261                return this.toFixed(left);
18262            }
18263
18264            if (left < 0) {
18265                left = 0;
18266            } else if (left > 100 - width) {
18267                left = 100 - width;
18268            }
18269
18270            return this.toFixed(left);
18271        },
18272
18273        validate: function () {
18274            var o = this.options,
18275                r = this.result,
18276                v = o.values,
18277                vl = v.length,
18278                value,
18279                i;
18280
18281            if (typeof o.min === "string") o.min = +o.min;
18282            if (typeof o.max === "string") o.max = +o.max;
18283            if (typeof o.from === "string") o.from = +o.from;
18284            if (typeof o.to === "string") o.to = +o.to;
18285            if (typeof o.step === "string") o.step = +o.step;
18286
18287            if (typeof o.from_min === "string") o.from_min = +o.from_min;
18288            if (typeof o.from_max === "string") o.from_max = +o.from_max;
18289            if (typeof o.to_min === "string") o.to_min = +o.to_min;
18290            if (typeof o.to_max === "string") o.to_max = +o.to_max;
18291
18292            if (typeof o.keyboard_step === "string") o.keyboard_step = +o.keyboard_step;
18293            if (typeof o.grid_num === "string") o.grid_num = +o.grid_num;
18294
18295            if (o.max < o.min) {
18296                o.max = o.min;
18297            }
18298
18299            if (vl) {
18300                o.p_values = [];
18301                o.min = 0;
18302                o.max = vl - 1;
18303                o.step = 1;
18304                o.grid_num = o.max;
18305                o.grid_snap = true;
18306
18307                for (i = 0; i < vl; i++) {
18308                    value = +v[i];
18309
18310                    if (!isNaN(value)) {
18311                        v[i] = value;
18312                        value = this._prettify(value);
18313                    } else {
18314                        value = v[i];
18315                    }
18316
18317                    o.p_values.push(value);
18318                }
18319            }
18320
18321            if (typeof o.from !== "number" || isNaN(o.from)) {
18322                o.from = o.min;
18323            }
18324
18325            if (typeof o.to !== "number" || isNaN(o.to)) {
18326                o.to = o.max;
18327            }
18328
18329            if (o.type === "single") {
18330
18331                if (o.from < o.min) o.from = o.min;
18332                if (o.from > o.max) o.from = o.max;
18333
18334            } else {
18335
18336                if (o.from < o.min) o.from = o.min;
18337                if (o.from > o.max) o.from = o.max;
18338
18339                if (o.to < o.min) o.to = o.min;
18340                if (o.to > o.max) o.to = o.max;
18341
18342                if (this.update_check.from) {
18343
18344                    if (this.update_check.from !== o.from) {
18345                        if (o.from > o.to) o.from = o.to;
18346                    }
18347                    if (this.update_check.to !== o.to) {
18348                        if (o.to < o.from) o.to = o.from;
18349                    }
18350
18351                }
18352
18353                if (o.from > o.to) o.from = o.to;
18354                if (o.to < o.from) o.to = o.from;
18355
18356            }
18357
18358            if (typeof o.step !== "number" || isNaN(o.step) || !o.step || o.step < 0) {
18359                o.step = 1;
18360            }
18361
18362            if (typeof o.keyboard_step !== "number" || isNaN(o.keyboard_step) || !o.keyboard_step || o.keyboard_step < 0) {
18363                o.keyboard_step = 5;
18364            }
18365
18366            if (typeof o.from_min === "number" && o.from < o.from_min) {
18367                o.from = o.from_min;
18368            }
18369
18370            if (typeof o.from_max === "number" && o.from > o.from_max) {
18371                o.from = o.from_max;
18372            }
18373
18374            if (typeof o.to_min === "number" && o.to < o.to_min) {
18375                o.to = o.to_min;
18376            }
18377
18378            if (typeof o.to_max === "number" && o.from > o.to_max) {
18379                o.to = o.to_max;
18380            }
18381
18382            if (r) {
18383                if (r.min !== o.min) {
18384                    r.min = o.min;
18385                }
18386
18387                if (r.max !== o.max) {
18388                    r.max = o.max;
18389                }
18390
18391                if (r.from < r.min || r.from > r.max) {
18392                    r.from = o.from;
18393                }
18394
18395                if (r.to < r.min || r.to > r.max) {
18396                    r.to = o.to;
18397                }
18398            }
18399
18400            if (typeof o.min_interval !== "number" || isNaN(o.min_interval) || !o.min_interval || o.min_interval < 0) {
18401                o.min_interval = 0;
18402            }
18403
18404            if (typeof o.max_interval !== "number" || isNaN(o.max_interval) || !o.max_interval || o.max_interval < 0) {
18405                o.max_interval = 0;
18406            }
18407
18408            if (o.min_interval && o.min_interval > o.max - o.min) {
18409                o.min_interval = o.max - o.min;
18410            }
18411
18412            if (o.max_interval && o.max_interval > o.max - o.min) {
18413                o.max_interval = o.max - o.min;
18414            }
18415        },
18416
18417        decorate: function (num, original) {
18418            var decorated = "",
18419                o = this.options;
18420
18421            if (o.prefix) {
18422                decorated += o.prefix;
18423            }
18424
18425            decorated += num;
18426
18427            if (o.max_postfix) {
18428                if (o.values.length && num === o.p_values[o.max]) {
18429                    decorated += o.max_postfix;
18430                    if (o.postfix) {
18431                        decorated += " ";
18432                    }
18433                } else if (original === o.max) {
18434                    decorated += o.max_postfix;
18435                    if (o.postfix) {
18436                        decorated += " ";
18437                    }
18438                }
18439            }
18440
18441            if (o.postfix) {
18442                decorated += o.postfix;
18443            }
18444
18445            return decorated;
18446        },
18447
18448        updateFrom: function () {
18449            this.result.from = this.options.from;
18450            this.result.from_percent = this.convertToPercent(this.result.from);
18451            if (this.options.values) {
18452                this.result.from_value = this.options.values[this.result.from];
18453            }
18454        },
18455
18456        updateTo: function () {
18457            this.result.to = this.options.to;
18458            this.result.to_percent = this.convertToPercent(this.result.to);
18459            if (this.options.values) {
18460                this.result.to_value = this.options.values[this.result.to];
18461            }
18462        },
18463
18464        updateResult: function () {
18465            this.result.min = this.options.min;
18466            this.result.max = this.options.max;
18467            this.updateFrom();
18468            this.updateTo();
18469        },
18470
18471
18472        // =============================================================================================================
18473        // Grid
18474
18475        appendGrid: function () {
18476            if (!this.options.grid) {
18477                return;
18478            }
18479
18480            var o = this.options,
18481                i, z,
18482
18483                total = o.max - o.min,
18484                big_num = o.grid_num,
18485                big_p = 0,
18486                big_w = 0,
18487
18488                small_max = 4,
18489                local_small_max,
18490                small_p,
18491                small_w = 0,
18492
18493                result,
18494                html = '';
18495
18496
18497
18498            this.calcGridMargin();
18499
18500            if (o.grid_snap) {
18501
18502                if (total > 50) {
18503                    big_num = 50 / o.step;
18504                    big_p = this.toFixed(o.step / 0.5);
18505                } else {
18506                    big_num = total / o.step;
18507                    big_p = this.toFixed(o.step / (total / 100));
18508                }
18509
18510            } else {
18511                big_p = this.toFixed(100 / big_num);
18512            }
18513
18514            if (big_num > 4) {
18515                small_max = 3;
18516            }
18517            if (big_num > 7) {
18518                small_max = 2;
18519            }
18520            if (big_num > 14) {
18521                small_max = 1;
18522            }
18523            if (big_num > 28) {
18524                small_max = 0;
18525            }
18526
18527            for (i = 0; i < big_num + 1; i++) {
18528                local_small_max = small_max;
18529
18530                big_w = this.toFixed(big_p * i);
18531
18532                if (big_w > 100) {
18533                    big_w = 100;
18534
18535                    local_small_max -= 2;
18536                    if (local_small_max < 0) {
18537                        local_small_max = 0;
18538                    }
18539                }
18540                this.coords.big[i] = big_w;
18541
18542                small_p = (big_w - (big_p * (i - 1))) / (local_small_max + 1);
18543
18544                for (z = 1; z <= local_small_max; z++) {
18545                    if (big_w === 0) {
18546                        break;
18547                    }
18548
18549                    small_w = this.toFixed(big_w - (small_p * z));
18550
18551                    html += '<span class="irs-grid-pol small" style="left: ' + small_w + '%"></span>';
18552                }
18553
18554                html += '<span class="irs-grid-pol" style="left: ' + big_w + '%"></span>';
18555
18556                result = this.convertToValue(big_w);
18557                if (o.values.length) {
18558                    result = o.p_values[result];
18559                } else {
18560                    result = this._prettify(result);
18561                }
18562
18563                html += '<span class="irs-grid-text js-grid-text-' + i + '" style="left: ' + big_w + '%">' + result + '</span>';
18564            }
18565            this.coords.big_num = Math.ceil(big_num + 1);
18566
18567
18568
18569            this.$cache.cont.addClass("irs-with-grid");
18570            this.$cache.grid.html(html);
18571            this.cacheGridLabels();
18572        },
18573
18574        cacheGridLabels: function () {
18575            var $label, i,
18576                num = this.coords.big_num;
18577
18578            for (i = 0; i < num; i++) {
18579                $label = this.$cache.grid.find(".js-grid-text-" + i);
18580                this.$cache.grid_labels.push($label);
18581            }
18582
18583            this.calcGridLabels();
18584        },
18585
18586        calcGridLabels: function () {
18587            var i, label, start = [], finish = [],
18588                num = this.coords.big_num;
18589
18590            for (i = 0; i < num; i++) {
18591                this.coords.big_w[i] = this.$cache.grid_labels[i].outerWidth(false);
18592                this.coords.big_p[i] = this.toFixed(this.coords.big_w[i] / this.coords.w_rs * 100);
18593                this.coords.big_x[i] = this.toFixed(this.coords.big_p[i] / 2);
18594
18595                start[i] = this.toFixed(this.coords.big[i] - this.coords.big_x[i]);
18596                finish[i] = this.toFixed(start[i] + this.coords.big_p[i]);
18597            }
18598
18599            if (this.options.force_edges) {
18600                if (start[0] < -this.coords.grid_gap) {
18601                    start[0] = -this.coords.grid_gap;
18602                    finish[0] = this.toFixed(start[0] + this.coords.big_p[0]);
18603
18604                    this.coords.big_x[0] = this.coords.grid_gap;
18605                }
18606
18607                if (finish[num - 1] > 100 + this.coords.grid_gap) {
18608                    finish[num - 1] = 100 + this.coords.grid_gap;
18609                    start[num - 1] = this.toFixed(finish[num - 1] - this.coords.big_p[num - 1]);
18610
18611                    this.coords.big_x[num - 1] = this.toFixed(this.coords.big_p[num - 1] - this.coords.grid_gap);
18612                }
18613            }
18614
18615            this.calcGridCollision(2, start, finish);
18616            this.calcGridCollision(4, start, finish);
18617
18618            for (i = 0; i < num; i++) {
18619                label = this.$cache.grid_labels[i][0];
18620
18621                if (this.coords.big_x[i] !== Number.POSITIVE_INFINITY) {
18622                    label.style.marginLeft = -this.coords.big_x[i] + "%";
18623                }
18624            }
18625        },
18626
18627        // Collisions Calc Beta
18628        // TODO: Refactor then have plenty of time
18629        calcGridCollision: function (step, start, finish) {
18630            var i, next_i, label,
18631                num = this.coords.big_num;
18632
18633            for (i = 0; i < num; i += step) {
18634                next_i = i + (step / 2);
18635                if (next_i >= num) {
18636                    break;
18637                }
18638
18639                label = this.$cache.grid_labels[next_i][0];
18640
18641                if (finish[i] <= start[next_i]) {
18642                    label.style.visibility = "visible";
18643                } else {
18644                    label.style.visibility = "hidden";
18645                }
18646            }
18647        },
18648
18649        calcGridMargin: function () {
18650            if (!this.options.grid_margin) {
18651                return;
18652            }
18653
18654            this.coords.w_rs = this.$cache.rs.outerWidth(false);
18655            if (!this.coords.w_rs) {
18656                return;
18657            }
18658
18659            if (this.options.type === "single") {
18660                this.coords.w_handle = this.$cache.s_single.outerWidth(false);
18661            } else {
18662                this.coords.w_handle = this.$cache.s_from.outerWidth(false);
18663            }
18664            this.coords.p_handle = this.toFixed(this.coords.w_handle  / this.coords.w_rs * 100);
18665            this.coords.grid_gap = this.toFixed((this.coords.p_handle / 2) - 0.1);
18666
18667            this.$cache.grid[0].style.width = this.toFixed(100 - this.coords.p_handle) + "%";
18668            this.$cache.grid[0].style.left = this.coords.grid_gap + "%";
18669        },
18670
18671
18672
18673        // =============================================================================================================
18674        // Public methods
18675
18676        update: function (options) {
18677            if (!this.input) {
18678                return;
18679            }
18680
18681            this.is_update = true;
18682
18683            this.options.from = this.result.from;
18684            this.options.to = this.result.to;
18685            this.update_check.from = this.result.from;
18686            this.update_check.to = this.result.to;
18687
18688            this.options = $.extend(this.options, options);
18689            this.validate();
18690            this.updateResult(options);
18691
18692            this.toggleInput();
18693            this.remove();
18694            this.init(true);
18695        },
18696
18697        reset: function () {
18698            if (!this.input) {
18699                return;
18700            }
18701
18702            this.updateResult();
18703            this.update();
18704        },
18705
18706        destroy: function () {
18707            if (!this.input) {
18708                return;
18709            }
18710
18711            this.toggleInput();
18712            this.$cache.input.prop("readonly", false);
18713            $.data(this.input, "ionRangeSlider", null);
18714
18715            this.remove();
18716            this.input = null;
18717            this.options = null;
18718        }
18719    };
18720
18721    $.fn.ionRangeSlider = function (options) {
18722        return this.each(function() {
18723            if (!$.data(this, "ionRangeSlider")) {
18724                $.data(this, "ionRangeSlider", new IonRangeSlider(this, options, plugin_count++));
18725            }
18726        });
18727    };
18728
18729
18730
18731    // =================================================================================================================
18732    // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
18733    // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
18734
18735    // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
18736
18737    // MIT license
18738
18739    (function() {
18740        var lastTime = 0;
18741        var vendors = ['ms', 'moz', 'webkit', 'o'];
18742        for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
18743            window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
18744            window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
18745                || window[vendors[x]+'CancelRequestAnimationFrame'];
18746        }
18747
18748        if (!window.requestAnimationFrame)
18749            window.requestAnimationFrame = function(callback, element) {
18750                var currTime = new Date().getTime();
18751                var timeToCall = Math.max(0, 16 - (currTime - lastTime));
18752                var id = window.setTimeout(function() { callback(currTime + timeToCall); },
18753                    timeToCall);
18754                lastTime = currTime + timeToCall;
18755                return id;
18756            };
18757
18758        if (!window.cancelAnimationFrame)
18759            window.cancelAnimationFrame = function(id) {
18760                clearTimeout(id);
18761            };
18762    }());
18763
18764}));
18765
18766
18767
18768// Trigger
18769
18770$(function () {
18771  
18772        var $range = $(".js-range-slider"),
18773            $inputFrom = $(".js-input-from"),
18774            $inputTo = $(".js-input-to"),
18775            instance,
18776            min = 0,
18777            max = 1000000,
18778            from = 0,
18779            to = 0;
18780
18781        $range.ionRangeSlider({
18782            type: "double",
18783            min: min,
18784            max: max,
18785            from: 20000,
18786            to: 500000,
18787          prefix: '$ ',
18788            onStart: updateInputs,
18789            onChange: updateInputs,
18790            step: 50000,
18791            prettify_enabled: true,
18792            prettify_separator: ".",
18793          values_separator: " - ",
18794          force_edges: true
18795          
18796
18797        });
18798
18799        instance = $range.data("ionRangeSlider");
18800
18801        function updateInputs (data) {
18802            from = data.from;
18803            to = data.to;
18804            
18805            $inputFrom.prop("value", from).keyup(resizeInput).each(resizeInput);
18806            $inputTo.prop("value", to).keyup(resizeInput).each(resizeInput);
18807        }
18808
18809        $inputFrom.on("input", function () {
18810            var val = $(this).prop("value");
18811            
18812            // validate
18813            if (val < min) {
18814                val = min;
18815            } else if (val > to) {
18816                val = to;
18817            }
18818            
18819            instance.update({
18820                from: val
18821            });
18822        });
18823
18824        $inputTo.on("input", function () {
18825            var val = $(this).prop("value");
18826            
18827            // validate
18828            if (val < from) {
18829                val = from;
18830            } else if (val > max) {
18831                val = max;
18832            }
18833            
18834            instance.update({
18835                to: val
18836            });
18837        });
18838
18839});$(function () {
18840    let $sel = $('[data-unicode="mdu_eXGzRJK9LUiefOurmVggYA"]');
18841    $sel.each(async function () {
18842        let $id = base62();
18843        $(this).find('form').attr('id', $id);
18844
18845        // 初始化設定資料
18846        let settingData = [];
18847        await initFormSettings($id).then(data => settingData = data);
18848
18849        // -----------------------------------
18850        // 出發起迄設定
18851        let $startDate = $('#' + $id).find('.date-start');
18852        let $endDate = $('#' + $id).find('.date-end');
18853        $('#' + $id).find('.date-start , .date-end').datepicker({
18854            format: "yyyy/mm/dd",
18855            clearBtn: true,
18856            autoclose: true,
18857            toggleActive: true,
18858            language: "zh-TW",
18859            defaultDate: new Date(),
18860            startDate: new Date()
18861        });
18862
18863        //日期區間設定
18864        let startDateOffset = getSettingValue(settingData, "SEARCH_SDATE_OFFSET");
18865        console.log('startDateOffset: ' + startDateOffset);
18866        startDateOffset = Math.min(parseInt(startDateOffset), 60);
18867        console.log('startDateOffset: ' + startDateOffset);
18868        let $daterange = $('#' + $id).find('#daterange_value');
18869        let daterange = 0;
18870        if ($daterange.val() !== '' && !isNaN(parseInt($daterange.val()))) {
18871            daterange = parseInt($daterange.val());
18872        } else {
18873            daterange = getSettingValue(settingData, "SEARCH_DATE_INTERVAL");
18874            daterange = parseInt(daterange || "0");
18875        }
18876
18877        let date = new Date(new Date().getTime() + startDateOffset * 24 * 60 * 60 * 1000);
18878        let month = (date.getMonth() + 1) + daterange;
18879        let yaer = date.getFullYear();
18880        if (month > 12) {           //是否超過12月判斷
18881            yaer += Math.floor(month / 12);
18882            month = (month % 12);
18883        }
18884        date.setFullYear(yaer);
18885        date.setMonth(month - 1);
18886        $startDate.datepicker('setDate', new Date(new Date().getTime() + startDateOffset * 24 * 60 * 60 * 1000));
18887        $endDate.datepicker('setDate', date);
18888
18889        // 結束日期的選擇變化
18890        $endDate.datepicker().on('blur', function (e) {
18891            console.log($endDate.datepicker('getDate'));
18892            console.log($startDate.datepicker('getDate'));
18893            if ($endDate.datepicker('getDate') < $startDate.datepicker('getDate')) {
18894                alert("出發期間迄日不可小於出發期間起日");
18895                $endDate.datepicker('setDate', $startDate.datepicker('getDate'));  // 重置結束日期爲起始日期
18896            }
18897        });
18898        // -----------------------------------
18899
18900
18901        $('#' + $id).find('.icon-collect').on('click', function () {
18902            $(this).toggleClass('active');
18903        });
18904
18905        // 載入出發地(出境機場)
18906        let $port = $('#' + $id).find('[name="port_cd"]');
18907        $.post($port.data('url'), {}, function (data) {
18908            $port.find('option:not(.empty)').remove();
18909            for (var i = 0; i < data.length; i++) {
18910                $port.append($("<option></option>").attr("value", data[i].OptValue).text(data[i].OptText));
18911                if (data[i].Selected)
18912                    $port.val(data[i].OptValue);
18913            }
18914        }, "json");
18915
18916        // 載入航空公司
18917        /*let $flight = $('#'+$id).find('[name="carr_cd"]');
18918        $.post($flight.data('url'), { }, function (data) {
18919            $flight.find('option:not(.empty)').remove();
18920            for (var i in data) {
18921                $flight.append($("<option></option>").attr("value", data[i].OptValue).text(data[i].OptText));
18922                if (data[i].Selected)
18923                    $$flight.val(data[i].OptValue);
18924            }
18925        }, "json");*/
18926
18927        // 載入大分類
18928        let $regm = $('#' + $id).find('[name="regm_cd"]');
18929        $.post($regm.data('url'), {}, function (data) {
18930            $regm.find('option:not(.empty)').remove();
18931            for (var i = 0; i < data.length; i++) {
18932                $regm.append($("<option></option>").attr("value", data[i].Value).text(data[i].Text));
18933                if (data[i].Selected)
18934                    $regm.val(data[i].Value);
18935            }
18936        }, "json");
18937
18938        //選取大分類後 更改小分類+出發地選項
18939        $('#' + $id).find('[name="regm_cd"]').on('change', function () {
18940            var $regs = $('#' + $id).find('[name="regs_cd"]');
18941            $regs.find('option:not(.empty)').remove();
18942            if ($(this).val() === undefined || $(this).val() == null || $(this).val().length <= 0 || $(this).val() === '') {
18943                $regs.append($("<option></option>").attr("value", '').text('不限'));
18944            }
18945            else {
18946                $.post($(this).data('url') + '?c_type=S', { regm_cd: $(this).val() }, function (data) {
18947                    $regs.find('option:not(.empty)').remove();
18948                    for (var i = 0; i < data.length; i++) {
18949                        $regs.append($("<option></option>").attr("value", data[i].Value).text(data[i].Text));
18950                        if (data[i].Selected)
18951                            $regs.val(data[i].Value);
18952                    }
18953                }, "json");
18954                changePortSelect();
18955            }
18956        }).trigger('change');
18957
18958        //選取小分類後 更改出發地選項
18959        $('#' + $id).find('[name="regs_cd"]').on('change', function () {
18960            changePortSelect();
18961        });
18962
18963        //可報名CHECKBOX觸發
18964        let $signup_st = $('#' + $id).find('[name="signup_st"]');
18965        $('#' + $id).find('[name="_isJoin"]').on('change', function () {
18966            if ($(this).is(':checked')) {
18967                $signup_st.val('3')
18968            } else {
18969                $signup_st.val('')
18970            }
18971        });
18972
18973        // -----------------------------------
18974        // 保證出發字漾吃 ZC 站台設定
18975        let guaranteeText = getSettingValue(settingData, "DSP_GUARANTEE_TXT");
18976        if(
18977            guaranteeText !== null &&
18978            guaranteeText !== undefined &&
18979            guaranteeText !== '' &&
18980            guaranteeText !== 'null' &&
18981            guaranteeText !== 'undefined'
18982          ) $('#' + $id).find("#GuaranteeText").text(guaranteeText);
18983
18984        //保證出發CHECKBOX觸發
18985        let $promo = $('#' + $id).find('[name="promo"]');
18986        $('#' + $id).find('[name="_isPromote"]').on('change', function () {
18987            if ($(this).is(':checked')) {
18988                $promo.val('G')
18989            } else {
18990                $promo.val('')
18991            }
18992        });
18993        // -----------------------------------
18994
18995        // 依照當前所選的大小分類,取得正確的啟程地(機場/港口)下拉選單
18996        function changePortSelect() {
18997            var $port = $('#' + $id).find('[name="port_cd"]');
18998            var regmCd = $('#' + $id).find('[name="regm_cd"] :selected').val(); // 大分類代碼
18999            var regsCd = $('#' + $id).find('[name="regs_cd"] :selected').val(); // 小分類代碼
19000            var portCd = $('#' + $id).find('[name="port_cd"] :selected').val(); // 當前啟程地代碼(如果連動時,要刷新成"不限"的話,把這個改成空值就好)
19001
19002            $.post($port.data('url'), { regm_cd: regmCd, regs_cd: regsCd, port_cd: portCd }, function (data) {
19003                $port.find('option:not(.empty)').remove();
19004                for (var i = 0; i < data.length; i++) {
19005                    $port.append($("<option></option>").attr("value", data[i].OptValue).text(data[i].OptText));
19006                    if (data[i].IsSelected)
19007                        $port.val(data[i].OptValue);
19008
19009                }
19010            }, "json");
19011        }        
19012
19013        //手機版語音輸入
19014        function micButton() {
19015            return $("#" + $id).find(".mic_icon .fa-microphone");
19016        }
19017
19018        function filterKeyword() {
19019            return $("#" + $id).find("#filterKeyword")[0];
19020        }
19021
19022        // 檢查瀏覽器是否支援 webkitSpeechRecognition
19023        if ("webkitSpeechRecognition" in window) {
19024            //Web Speech API
19025            const recognition = new webkitSpeechRecognition();
19026
19027            function startSpeechRecognition() {
19028
19029                // 設置識別語言為中文
19030                recognition.lang = "zh-TW";
19031
19032                // 設置連續識別模式
19033                recognition.continuous = true;
19034
19035                // 設置識別結果是否包含中間結果
19036                recognition.interimResults = false;
19037
19038                // 定義搜尋計時器變量
19039                let searchTimer = null;
19040
19041                // 監聽語音識別結果
19042                recognition.onresult = function (event) {
19043                    const result = event.results[event.resultIndex][
190430].transcript;
19044                    filterKeyword().value = result;
19045
19046                    // 取消搜尋計時器
19047                    clearTimeout(searchTimer);
19048
19049                    // 啟動新的搜尋計時器
19050                    searchTimer = setTimeout(() => {
19051                        performSearch();
19052                    }, 1000);
19053                };
19054
19055                // 監聽語音識別結束事件
19056                recognition.onend = () => {
19057                    // 停止語音識別
19058                    recognitionStop();
19059                };
19060
19061                // 監聽語音識別錯誤事件
19062                recognition.onerror = (event) => {
19063                    console.error(`語音識別錯誤:${event.error}`);
19064                    // 停止語音識別
19065                    recognitionStop();
19066                };
19067                // 定義搜索
19068                function performSearch() {
19069                    $("#" + $id).find('.search-btn').click();
19070                }
19071
19072                // 監聽使用者停止說話事件
19073                recognition.onspeechend = () => {
19074                    // 停止語音識別
19075                    recognitionStop();
19076
19077                    // 取消搜尋計時器
19078                    if (searchTimer !== null) {
19079                        clearTimeout(searchTimer);
19080                    }
19081
19082                    // 啟動新的搜尋計時器
19083                    searchTimer = setTimeout(() => {
19084                        performSearch();
19085                    }, 500);
19086                };
19087
19088                // 設置語音識別超時,如果使用者沒有在6秒內說話,則停止語音識別
19089                setTimeout(() => {
19090                    recognitionStop();
19091                }, 6000);
19092
19093                // 啟動語音識別
19094                recognitionStart();
19095            }
19096
19097            //控制Icon
19098            function setIconVisibility(micIconVisible, chartIconVisible) {
19099                $('.micIcon').css('visibility', micIconVisible ? 'visible' : 'hidden');
19100                $('.chartIcon').css('visibility', chartIconVisible ? 'visible' : 'hidden');
19101            }
19102
19103            //控制語音輸入
19104            function recognitionStart() {
19105                recognition.start();
19106                setIconVisibility(false, true);
19107            }
19108
19109            function recognitionStop() {
19110                recognition.stop();
19111                setIconVisibility(true, false);
19112            }
19113            //--------------------------------------------------Web Speech API Modal
19114            micButton().on('click', function () {
19115
19116                // 設定燈箱開啟時禁止滑動
19117                $('body').css('overflow', 'hidden');
19118
19119                // 設定燈箱樣式
19120                const dialog = $('<div></div>').css({
19121                    position: 'fixed',
19122                    bottom: '-50%', // 設定起始位置
19123                    left: '0',
19124                    width: '100%',
19125                    height: '30%',
19126                    background: '#fff',
19127                    boxShadow: '0 0 10px rgba(0, 0, 0, 0.5)',
19128                    borderTopLeftRadius: '10px',
19129                    borderTopRightRadius: '10px'
19130                });
19131
19132                // 文字標題
19133                const message = $('<div>請說</div>').css({
19134                    position: 'absolute',
19135                    top: '20%',
19136                    left: '50%',
19137                    transform: 'translate(-50%, -50%)',
19138                    fontSize: '20px',
19139                    fontWeight: 'bold'
19140                });
19141                dialog.append(message);
19142
19143                // 文字內容1
19144                const grayText1 = $('<div>請說出您要搜尋的關鍵字</div>').css({
19145                    color: '#777',
19146                    fontSize: '15px',
19147                    position: 'absolute',
19148                    top: '35%',
19149                    left: '50%',
19150                    transform: 'translate(-50%, -50%)'
19151                });
19152                dialog.append(grayText1);
19153
19154                // 文字內容2
19155                const grayText2 = $('<div>例如:東京、奧地利、巴里島...</div>').css({
19156                    color: '#777',
19157                    fontSize: '15px',
19158                    position: 'absolute',
19159                    top: '55%',
19160                    left: '50%',
19161                    transform: 'translate(-50%, -50%)'
19162                });
19163                dialog.append(grayText2);
19164
19165                // 麥克風 Icon
19166                const micIcon = $('<div class="micIcon"><i class="fa fa-microphone"></i></div>').css({
19167                    position: 'absolute',
19168                    top: '75%',
19169                    left: '50%',
19170                    transform: 'translate(-50%, -50%)'
19171                });
19172                micIcon.find('i').css({
19173                    color: '#777',
19174                    fontSize: '40px'
19175                });
19176                dialog.append(micIcon);
19177                micIcon.on('click', startSpeechRecognition);
19178
19179                // 波型 Icon
19180                for (let i = 1; i <= 4; i++) {
19181                    const chartIcon = $('<div class="chartIcon"><i class="fa fa-align-center"></i></div>').css({
19182                        position: 'absolute',
19183                        top: '70%',
19184                        left: (28 + i * 7) + '%',
19185                    });
19186                    chartIcon.find('i').css({
19187                        color: '#777',
19188                        fontSize: '33px',
19189                        transform: i % 2 == 1 ? 'rotate(-90deg)' : 'rotate(90deg)'
19190                    });
19191                    dialog.append(chartIcon);
19192                }
19193
19194                // 設定半透明背景樣式
19195                const body = $('body');
19196                const bg = $('<div></div>');
19197                bg.css({
19198                    'position': 'fixed',
19199                    'top': '0',
19200                    'left': '0',
19201                    'width': '100%',
19202                    'height': '100%',
19203                    'background-color': 'rgba(0, 0, 0, 0.5)'
19204                });
19205
19206                const wrapper = $('<div></div>');
19207                wrapper.css({
19208                    'position': 'fixed',
19209                    'top': '0',
19210                    'left': '0',
19211                    'width': '100%',
19212                    'height': '100%',
19213                    'z-index': '9998'
19214                });
19215                wrapper.append(bg);
19216                wrapper.append(dialog);
19217                body.append(wrapper);
19218
19219                // 關閉按鈕
19220                const closeButton = $('<button>&times;</button>');
19221                closeButton.css({
19222                    position: 'absolute',
19223                    top: '10px',
19224                    right: '10px',
19225                    border: 'none',
19226                    background: 'none',
19227                    fontSize: '30px',
19228                    cursor: 'pointer'
19229                });
19230                dialog.append(closeButton);
19231
19232                // 燈箱動畫
19233                const dialogHeight = $(dialog).outerHeight();
19234                $(dialog).css('bottom', '-' + dialogHeight + 'px');
19235                setTimeout(function () {
19236                    $(dialog).css({
19237                        'transition': 'bottom 0.3s ease-out',
19238                        'bottom': '0'
19239                    });
19240                }, 10);
19241                const closeDialog = function () {
19242                    recognition.stop();
19243                    $(dialog).css('bottom', '-' + dialogHeight + 'px');
19244                    setTimeout(function () {
19245                        $(bg).remove();
19246                        $(dialog).remove();
19247                        $(wrapper).remove();
19248                        $('body').css('overflow', 'auto');
19249                    }, 300);
19250                }
19251                $(closeButton).on('click', closeDialog);
19252                $(bg).on('click', closeDialog);
19253                startSpeechRecognition();
19254            });
19255        } else {
19256            console.error("Your browser doesn't support webkitSpeechRecognition");
19257        }
19258
19259        //防止URL直接帶入NaN
19260        let $travelType = $('#' + $id).find('#travel_type');
19261        if ($travelType.val() === "NaN") {
19262            $travelType.val('');
19263        }
19264
19265        // 取得 WebSetting 資料
19266        async function initFormSettings($id) {
19267            let settingUrl = $('#' + $id).data('setting-url');
19268            try {
19269                let response = await postJsonAsync(settingUrl);
19270                return response.Data || [];
19271            } catch (e) {
19272                console.error("載入設定失敗:", e);
19273                return [];
19274            }
19275        }
19276
19277        // 取指定站台設定的 key - value
19278        function getSettingValue(dataArray, key) {
19279            const item = dataArray.find(x => x.Key === key);
19280            return item ? item.Value : null;
19281        }
19282
19283        function postJsonAsync(url, data = {}) {
19284            return new Promise((resolve, reject) => {
19285                $.post({
19286                    url: url,
19287                    data: JSON.stringify(data),
19288                    contentType: "application/json",
19289                    dataType: "json",
19290                    success: resolve,
19291                    error: reject
19292                });
19293            });
19294        }
19295    });
vendor: 32,878 bytes, lines 19296-20295
19296})
19297
19298
19299
19300; })(jQuery);/* compress error:[4]function encode(int) {*/
19301
19302/* MODULE 3a0d7da1-9bad-41da-bb89-64bd1e0eddc8, Version: 1.0.37 */
19303;(function($) {; var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
19304
19305// NB: does not validate input
19306function encode(int) {
19307    if (int === 0) {
19308        return CHARSET[0];
19309    }
19310
19311    var res = "";
19312    while (int > 0) {
19313        res = CHARSET[int % 62] + res;
19314        int = Math.floor(int / 62);
19315    }
19316    return res;
19317};
19318
19319function decode(str) {
19320    var res = 0,
19321        length = str.length,
19322        i, char;
19323    for (i = 0; i < length; i++) {
19324        char = str.charCodeAt(i);
19325        if (char < 58) { // 0-9
19326            char = char - 48;
19327        } else if (char < 91) { // A-Z
19328            char = char - 29;
19329        } else { // a-z
19330            char = char - 87;
19331        }
19332        res += char * Math.pow(62, length - i - 1);
19333    }
19334    return res;
19335};
19336
19337function base62() {
19338    var id; //base62
19339    do {
19340      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
19341    } while (id.match(/^[0-9]/i) !== null);
19342    return id;
19343}/**
19344 * Swiper 5.2.0
19345 * Most modern mobile touch slider and framework with hardware accelerated transitions
19346 * http://swiperjs.com
19347 *
19348 * Copyright 2014-2019 Vladimir Kharlampidi
19349 *
19350 * Released under the MIT License
19351 *
19352 * Released on: October 26, 2019
19353 */
19354
19355(function (global, factory) {
19356    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
19357    typeof define === 'function' && define.amd ? define(factory) :
19358    (global = global || self, global.Swiper = factory());
19359  }(this, function () { 'use strict';
19360  
19361    /**
19362     * SSR Window 1.0.1
19363     * Better handling for window object in SSR environment
19364     * https://github.com/nolimits4web/ssr-window
19365     *
19366     * Copyright 2018, Vladimir Kharlampidi
19367     *
19368     * Licensed under MIT
19369     *
19370     * Released on: July 18, 2018
19371     */
19372    var doc = (typeof document === 'undefined') ? {
19373      body: {},
19374      addEventListener: function addEventListener() {},
19375      removeEventListener: function removeEventListener() {},
19376      activeElement: {
19377        blur: function blur() {},
19378        nodeName: '',
19379      },
19380      querySelector: function querySelector() {
19381        return null;
19382      },
19383      querySelectorAll: function querySelectorAll() {
19384        return [];
19385      },
19386      getElementById: function getElementById() {
19387        return null;
19388      },
19389      createEvent: function createEvent() {
19390        return {
19391          initEvent: function initEvent() {},
19392        };
19393      },
19394      createElement: function createElement() {
19395        return {
19396          children: [],
19397          childNodes: [],
19398          style: {},
19399          setAttribute: function setAttribute() {},
19400          getElementsByTagName: function getElementsByTagName() {
19401            return [];
19402          },
19403        };
19404      },
19405      location: { hash: '' },
19406    } : document; // eslint-disable-line
19407  
19408    var win = (typeof window === 'undefined') ? {
19409      document: doc,
19410      navigator: {
19411        userAgent: '',
19412      },
19413      location: {},
19414      history: {},
19415      CustomEvent: function CustomEvent() {
19416        return this;
19417      },
19418      addEventListener: function addEventListener() {},
19419      removeEventListener: function removeEventListener() {},
19420      getComputedStyle: function getComputedStyle() {
19421        return {
19422          getPropertyValue: function getPropertyValue() {
19423            return '';
19424          },
19425        };
19426      },
19427      Image: function Image() {},
19428      Date: function Date() {},
19429      screen: {},
19430      setTimeout: function setTimeout() {},
19431      clearTimeout: function clearTimeout() {},
19432    } : window; // eslint-disable-line
19433  
19434    /**
19435     * Dom7 2.1.3
19436     * Minimalistic JavaScript library for DOM manipulation, with a jQuery-compatible API
19437     * http://framework7.io/docs/dom.html
19438     *
19439     * Copyright 2019, Vladimir Kharlampidi
19440     * The iDangero.us
19441     * http://www.idangero.us/
19442     *
19443     * Licensed under MIT
19444     *
19445     * Released on: February 11, 2019
19446     */
19447  
19448    var Dom7 = function Dom7(arr) {
19449      var self = this;
19450      // Create array-like object
19451      for (var i = 0; i < arr.length; i += 1) {
19452        self[i] = arr[i];
19453      }
19454      self.length = arr.length;
19455      // Return collection with methods
19456      return this;
19457    };
19458  
19459    function $(selector, context) {
19460      var arr = [];
19461      var i = 0;
19462      if (selector && !context) {
19463        if (selector instanceof Dom7) {
19464          return selector;
19465        }
19466      }
19467      if (selector) {
19468          // String
19469        if (typeof selector === 'string') {
19470          var els;
19471          var tempParent;
19472          var html = selector.trim();
19473          if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) {
19474            var toCreate = 'div';
19475            if (html.indexOf('<li') === 0) { toCreate = 'ul'; }
19476            if (html.indexOf('<tr') === 0) { toCreate = 'tbody'; }
19477            if (html.indexOf('<td') === 0 || html.indexOf('<th') === 0) { toCreate = 'tr'; }
19478            if (html.indexOf('<tbody') === 0) { toCreate = 'table'; }
19479            if (html.indexOf('<option') === 0) { toCreate = 'select'; }
19480            tempParent = doc.createElement(toCreate);
19481            tempParent.innerHTML = html;
19482            for (i = 0; i < tempParent.childNodes.length; i += 1) {
19483              arr.push(tempParent.childNodes[i]);
19484            }
19485          } else {
19486            if (!context && selector[0] === '#' && !selector.match(/[ .<>:~]/)) {
19487              // Pure ID selector
19488              els = [doc.getElementById(selector.trim().split('#')[1])];
19489            } else {
19490              // Other selectors
19491              els = (context || doc).querySelectorAll(selector.trim());
19492            }
19493            for (i = 0; i < els.length; i += 1) {
19494              if (els[i]) { arr.push(els[i]); }
19495            }
19496          }
19497        } else if (selector.nodeType || selector === win || selector === doc) {
19498          // Node/element
19499          arr.push(selector);
19500        } else if (selector.length > 0 && selector[0].nodeType) {
19501          // Array of elements or instance of Dom
19502          for (i = 0; i < selector.length; i += 1) {
19503            arr.push(selector[i]);
19504          }
19505        }
19506      }
19507      return new Dom7(arr);
19508    }
19509  
19510    $.fn = Dom7.prototype;
19511    $.Class = Dom7;
19512    $.Dom7 = Dom7;
19513  
19514    function unique(arr) {
19515      var uniqueArray = [];
19516      for (var i = 0; i < arr.length; i += 1) {
19517        if (uniqueArray.indexOf(arr[i]) === -1) { uniqueArray.push(arr[i]); }
19518      }
19519      return uniqueArray;
19520    }
19521  
19522    // Classes and attributes
19523    function addClass(className) {
19524      if (typeof className === 'undefined') {
19525        return this;
19526      }
19527      var classes = className.split(' ');
19528      for (var i = 0; i < classes.length; i += 1) {
19529        for (var j = 0; j < this.length; j += 1) {
19530          if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') { this[j].classList.add(classes[i]); }
19531        }
19532      }
19533      return this;
19534    }
19535    function removeClass(className) {
19536      var classes = className.split(' ');
19537      for (var i = 0; i < classes.length; i += 1) {
19538        for (var j = 0; j < this.length; j += 1) {
19539          if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') { this[j].classList.remove(classes[i]); }
19540        }
19541      }
19542      return this;
19543    }
19544    function hasClass(className) {
19545      if (!this[0]) { return false; }
19546      return this[0].classList.contains(className);
19547    }
19548    function toggleClass(className) {
19549      var classes = className.split(' ');
19550      for (var i = 0; i < classes.length; i += 1) {
19551        for (var j = 0; j < this.length; j += 1) {
19552          if (typeof this[j] !== 'undefined' && typeof this[j].classList !== 'undefined') { this[j].classList.toggle(classes[i]); }
19553        }
19554      }
19555      return this;
19556    }
19557    function attr(attrs, value) {
19558      var arguments$1 = arguments;
19559  
19560      if (arguments.length === 1 && typeof attrs === 'string') {
19561        // Get attr
19562        if (this[0]) { return this[0].getAttribute(attrs); }
19563        return undefined;
19564      }
19565  
19566      // Set attrs
19567      for (var i = 0; i < this.length; i += 1) {
19568        if (arguments$1.length === 2) {
19569          // String
19570          this[i].setAttribute(attrs, value);
19571        } else {
19572          // Object
19573          // eslint-disable-next-line
19574          for (var attrName in attrs) {
19575            this[i][attrName] = attrs[attrName];
19576            this[i].setAttribute(attrName, attrs[attrName]);
19577          }
19578        }
19579      }
19580      return this;
19581    }
19582    // eslint-disable-next-line
19583    function removeAttr(attr) {
19584      for (var i = 0; i < this.length; i += 1) {
19585        this[i].removeAttribute(attr);
19586      }
19587      return this;
19588    }
19589    function data(key, value) {
19590      var el;
19591      if (typeof value === 'undefined') {
19592        el = this[0];
19593        // Get value
19594        if (el) {
19595          if (el.dom7ElementDataStorage && (key in el.dom7ElementDataStorage)) {
19596            return el.dom7ElementDataStorage[key];
19597          }
19598  
19599          var dataKey = el.getAttribute(("data-" + key));
19600          if (dataKey) {
19601            return dataKey;
19602          }
19603          return undefined;
19604        }
19605        return undefined;
19606      }
19607  
19608      // Set value
19609      for (var i = 0; i < this.length; i += 1) {
19610        el = this[i];
19611        if (!el.dom7ElementDataStorage) { el.dom7ElementDataStorage = {}; }
19612        el.dom7ElementDataStorage[key] = value;
19613      }
19614      return this;
19615    }
19616    // Transforms
19617    // eslint-disable-next-line
19618    function transform(transform) {
19619      for (var i = 0; i < this.length; i += 1) {
19620        var elStyle = this[i].style;
19621        elStyle.webkitTransform = transform;
19622        elStyle.transform = transform;
19623      }
19624      return this;
19625    }
19626    function transition(duration) {
19627      if (typeof duration !== 'string') {
19628        duration = duration + "ms"; // eslint-disable-line
19629      }
19630      for (var i = 0; i < this.length; i += 1) {
19631        var elStyle = this[i].style;
19632        elStyle.webkitTransitionDuration = duration;
19633        elStyle.transitionDuration = duration;
19634      }
19635      return this;
19636    }
19637    // Events
19638    function on() {
19639      var assign;
19640  
19641      var args = [], len = arguments.length;
19642      while ( len-- ) args[ len ] = arguments[ len ];
19643      var eventType = args[0];
19644      var targetSelector = args[1];
19645      var listener = args[2];
19646      var capture = args[3];
19647      if (typeof args[1] === 'function') {
19648        (assign = args, eventType = assign[0], listener = assign[1], capture = assign[2]);
19649        targetSelector = undefined;
19650      }
19651      if (!capture) { capture = false; }
19652  
19653      function handleLiveEvent(e) {
19654        var target = e.target;
19655        if (!target) { return; }
19656        var eventData = e.target.dom7EventData || [];
19657        if (eventData.indexOf(e) < 0) {
19658          eventData.unshift(e);
19659        }
19660        if ($(target).is(targetSelector)) { listener.apply(target, eventData); }
19661        else {
19662          var parents = $(target).parents(); // eslint-disable-line
19663          for (var k = 0; k < parents.length; k += 1) {
19664            if ($(parents[k]).is(targetSelector)) { listener.apply(parents[k], eventData); }
19665          }
19666        }
19667      }
19668      function handleEvent(e) {
19669        var eventData = e && e.target ? e.target.dom7EventData || [] : [];
19670        if (eventData.indexOf(e) < 0) {
19671          eventData.unshift(e);
19672        }
19673        listener.apply(this, eventData);
19674      }
19675      var events = eventType.split(' ');
19676      var j;
19677      for (var i = 0; i < this.length; i += 1) {
19678        var el = this[i];
19679        if (!targetSelector) {
19680          for (j = 0; j < events.length; j += 1) {
19681            var event = events[j];
19682            if (!el.dom7Listeners) { el.dom7Listeners = {}; }
19683            if (!el.dom7Listeners[event]) { el.dom7Listeners[event] = []; }
19684            el.dom7Listeners[event].push({
19685              listener: listener,
19686              proxyListener: handleEvent,
19687            });
19688            el.addEventListener(event, handleEvent, capture);
19689          }
19690        } else {
19691          // Live events
19692          for (j = 0; j < events.length; j += 1) {
19693            var event$1 = events[j];
19694            if (!el.dom7LiveListeners) { el.dom7LiveListeners = {}; }
19695            if (!el.dom7LiveListeners[event$1]) { el.dom7LiveListeners[event$1] = []; }
19696            el.dom7LiveListeners[event$1].push({
19697              listener: listener,
19698              proxyListener: handleLiveEvent,
19699            });
19700            el.addEventListener(event$1, handleLiveEvent, capture);
19701          }
19702        }
19703      }
19704      return this;
19705    }
19706    function off() {
19707      var assign;
19708  
19709      var args = [], len = arguments.length;
19710      while ( len-- ) args[ len ] = arguments[ len ];
19711      var eventType = args[0];
19712      var targetSelector = args[1];
19713      var listener = args[2];
19714      var capture = args[3];
19715      if (typeof args[1] === 'function') {
19716        (assign = args, eventType = assign[0], listener = assign[1], capture = assign[2]);
19717        targetSelector = undefined;
19718      }
19719      if (!capture) { capture = false; }
19720  
19721      var events = eventType.split(' ');
19722      for (var i = 0; i < events.length; i += 1) {
19723        var event = events[i];
19724        for (var j = 0; j < this.length; j += 1) {
19725          var el = this[j];
19726          var handlers = (void 0);
19727          if (!targetSelector && el.dom7Listeners) {
19728            handlers = el.dom7Listeners[event];
19729          } else if (targetSelector && el.dom7LiveListeners) {
19730            handlers = el.dom7LiveListeners[event];
19731          }
19732          if (handlers && handlers.length) {
19733            for (var k = handlers.length - 1; k >= 0; k -= 1) {
19734              var handler = handlers[k];
19735              if (listener && handler.listener === listener) {
19736                el.removeEventListener(event, handler.proxyListener, capture);
19737                handlers.splice(k, 1);
19738              } else if (listener && handler.listener && handler.listener.dom7proxy && handler.listener.dom7proxy === listener) {
19739                el.removeEventListener(event, handler.proxyListener, capture);
19740                handlers.splice(k, 1);
19741              } else if (!listener) {
19742                el.removeEventListener(event, handler.proxyListener, capture);
19743                handlers.splice(k, 1);
19744              }
19745            }
19746          }
19747        }
19748      }
19749      return this;
19750    }
19751    function trigger() {
19752      var args = [], len = arguments.length;
19753      while ( len-- ) args[ len ] = arguments[ len ];
19754  
19755      var events = args[0].split(' ');
19756      var eventData = args[1];
19757      for (var i = 0; i < events.length; i += 1) {
19758        var event = events[i];
19759        for (var j = 0; j < this.length; j += 1) {
19760          var el = this[j];
19761          var evt = (void 0);
19762          try {
19763            evt = new win.CustomEvent(event, {
19764              detail: eventData,
19765              bubbles: true,
19766              cancelable: true,
19767            });
19768          } catch (e) {
19769            evt = doc.createEvent('Event');
19770            evt.initEvent(event, true, true);
19771            evt.detail = eventData;
19772          }
19773          // eslint-disable-next-line
19774          el.dom7EventData = args.filter(function (data, dataIndex) { return dataIndex > 0; });
19775          el.dispatchEvent(evt);
19776          el.dom7EventData = [];
19777          delete el.dom7EventData;
19778        }
19779      }
19780      return this;
19781    }
19782    function transitionEnd(callback) {
19783      var events = ['webkitTransitionEnd', 'transitionend'];
19784      var dom = this;
19785      var i;
19786      function fireCallBack(e) {
19787        /* jshint validthis:true */
19788        if (e.target !== this) { return; }
19789        callback.call(this, e);
19790        for (i = 0; i < events.length; i += 1) {
19791          dom.off(events[i], fireCallBack);
19792        }
19793      }
19794      if (callback) {
19795        for (i = 0; i < events.length; i += 1) {
19796          dom.on(events[i], fireCallBack);
19797        }
19798      }
19799      return this;
19800    }
19801    function outerWidth(includeMargins) {
19802      if (this.length > 0) {
19803        if (includeMargins) {
19804          // eslint-disable-next-line
19805          var styles = this.styles();
19806          return this[0].offsetWidth + parseFloat(styles.getPropertyValue('margin-right')) + parseFloat(styles.getPropertyValue('margin-left'));
19807        }
19808        return this[0].offsetWidth;
19809      }
19810      return null;
19811    }
19812    function outerHeight(includeMargins) {
19813      if (this.length > 0) {
19814        if (includeMargins) {
19815          // eslint-disable-next-line
19816          var styles = this.styles();
19817          return this[0].offsetHeight + parseFloat(styles.getPropertyValue('margin-top')) + parseFloat(styles.getPropertyValue('margin-bottom'));
19818        }
19819        return this[0].offsetHeight;
19820      }
19821      return null;
19822    }
19823    function offset() {
19824      if (this.length > 0) {
19825        var el = this[0];
19826        var box = el.getBoundingClientRect();
19827        var body = doc.body;
19828        var clientTop = el.clientTop || body.clientTop || 0;
19829        var clientLeft = el.clientLeft || body.clientLeft || 0;
19830        var scrollTop = el === win ? win.scrollY : el.scrollTop;
19831        var scrollLeft = el === win ? win.scrollX : el.scrollLeft;
19832        return {
19833          top: (box.top + scrollTop) - clientTop,
19834          left: (box.left + scrollLeft) - clientLeft,
19835        };
19836      }
19837  
19838      return null;
19839    }
19840    function styles() {
19841      if (this[0]) { return win.getComputedStyle(this[0], null); }
19842      return {};
19843    }
19844    function css(props, value) {
19845      var i;
19846      if (arguments.length === 1) {
19847        if (typeof props === 'string') {
19848          if (this[0]) { return win.getComputedStyle(this[0], null).getPropertyValue(props); }
19849        } else {
19850          for (i = 0; i < this.length; i += 1) {
19851            // eslint-disable-next-line
19852            for (var prop in props) {
19853              this[i].style[prop] = props[prop];
19854            }
19855          }
19856          return this;
19857        }
19858      }
19859      if (arguments.length === 2 && typeof props === 'string') {
19860        for (i = 0; i < this.length; i += 1) {
19861          this[i].style[props] = value;
19862        }
19863        return this;
19864      }
19865      return this;
19866    }
19867    // Iterate over the collection passing elements to `callback`
19868    function each(callback) {
19869      // Don't bother continuing without a callback
19870      if (!callback) { return this; }
19871      // Iterate over the current collection
19872      for (var i = 0; i < this.length; i += 1) {
19873        // If the callback returns false
19874        if (callback.call(this[i], i, this[i]) === false) {
19875          // End the loop early
19876          return this;
19877        }
19878      }
19879      // Return `this` to allow chained DOM operations
19880      return this;
19881    }
19882    function filter(callback) {
19883      var matchedItems = [];
19884      var dom = this;
19885      for (var i = 0; i < dom.length; i += 1) {
19886        if (callback.call(dom[i], i, dom[i])) { matchedItems.push(dom[i]); }
19887      }
19888      return new Dom7(matchedItems);
19889    }
19890    // eslint-disable-next-line
19891    function html(html) {
19892      if (typeof html === 'undefined') {
19893        return this[0] ? this[0].innerHTML : undefined;
19894      }
19895  
19896      for (var i = 0; i < this.length; i += 1) {
19897        this[i].innerHTML = html;
19898      }
19899      return this;
19900    }
19901    // eslint-disable-next-line
19902    function text(text) {
19903      if (typeof text === 'undefined') {
19904        if (this[0]) {
19905          return this[0].textContent.trim();
19906        }
19907        return null;
19908      }
19909  
19910      for (var i = 0; i < this.length; i += 1) {
19911        this[i].textContent = text;
19912      }
19913      return this;
19914    }
19915    function is(selector) {
19916      var el = this[0];
19917      var compareWith;
19918      var i;
19919      if (!el || typeof selector === 'undefined') { return false; }
19920      if (typeof selector === 'string') {
19921        if (el.matches) { return el.matches(selector); }
19922        else if (el.webkitMatchesSelector) { return el.webkitMatchesSelector(selector); }
19923        else if (el.msMatchesSelector) { return el.msMatchesSelector(selector); }
19924  
19925        compareWith = $(selector);
19926        for (i = 0; i < compareWith.length; i += 1) {
19927          if (compareWith[i] === el) { return true; }
19928        }
19929        return false;
19930      } else if (selector === doc) { return el === doc; }
19931      else if (selector === win) { return el === win; }
19932  
19933      if (selector.nodeType || selector instanceof Dom7) {
19934        compareWith = selector.nodeType ? [selector] : selector;
19935        for (i = 0; i < compareWith.length; i += 1) {
19936          if (compareWith[i] === el) { return true; }
19937        }
19938        return false;
19939      }
19940      return false;
19941    }
19942    function index() {
19943      var child = this[0];
19944      var i;
19945      if (child) {
19946        i = 0;
19947        // eslint-disable-next-line
19948        while ((child = child.previousSibling) !== null) {
19949          if (child.nodeType === 1) { i += 1; }
19950        }
19951        return i;
19952      }
19953      return undefined;
19954    }
19955    // eslint-disable-next-line
19956    function eq(index) {
19957      if (typeof index === 'undefined') { return this; }
19958      var length = this.length;
19959      var returnIndex;
19960      if (index > length - 1) {
19961        return new Dom7([]);
19962      }
19963      if (index < 0) {
19964        returnIndex = length + index;
19965        if (returnIndex < 0) { return new Dom7([]); }
19966        return new Dom7([this[returnIndex]]);
19967      }
19968      return new Dom7([this[index]]);
19969    }
19970    function append() {
19971      var args = [], len = arguments.length;
19972      while ( len-- ) args[ len ] = arguments[ len ];
19973  
19974      var newChild;
19975  
19976      for (var k = 0; k < args.length; k += 1) {
19977        newChild = args[k];
19978        for (var i = 0; i < this.length; i += 1) {
19979          if (typeof newChild === 'string') {
19980            var tempDiv = doc.createElement('div');
19981            tempDiv.innerHTML = newChild;
19982            while (tempDiv.firstChild) {
19983              this[i].appendChild(tempDiv.firstChild);
19984            }
19985          } else if (newChild instanceof Dom7) {
19986            for (var j = 0; j < newChild.length; j += 1) {
19987              this[i].appendChild(newChild[j]);
19988            }
19989          } else {
19990            this[i].appendChild(newChild);
19991          }
19992        }
19993      }
19994  
19995      return this;
19996    }
19997    function prepend(newChild) {
19998      var i;
19999      var j;
20000      for (i = 0; i < this.length; i += 1) {
20001        if (typeof newChild === 'string') {
20002          var tempDiv = doc.createElement('div');
20003          tempDiv.innerHTML = newChild;
20004          for (j = tempDiv.childNodes.length - 1; j >= 0; j -= 1) {
20005            this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]);
20006          }
20007        } else if (newChild instanceof Dom7) {
20008          for (j = 0; j < newChild.length; j += 1) {
20009            this[i].insertBefore(newChild[j], this[i].childNodes[0]);
20010          }
20011        } else {
20012          this[i].insertBefore(newChild, this[i].childNodes[0]);
20013        }
20014      }
20015      return this;
20016    }
20017    function next(selector) {
20018      if (this.length > 0) {
20019        if (selector) {
20020          if (this[0].nextElementSibling && $(this[0].nextElementSibling).is(selector)) {
20021            return new Dom7([this[0].nextElementSibling]);
20022          }
20023          return new Dom7([]);
20024        }
20025  
20026        if (this[0].nextElementSibling) { return new Dom7([this[0].nextElementSibling]); }
20027        return new Dom7([]);
20028      }
20029      return new Dom7([]);
20030    }
20031    function nextAll(selector) {
20032      var nextEls = [];
20033      var el = this[0];
20034      if (!el) { return new Dom7([]); }
20035      while (el.nextElementSibling) {
20036        var next = el.nextElementSibling; // eslint-disable-line
20037        if (selector) {
20038          if ($(next).is(selector)) { nextEls.push(next); }
20039        } else { nextEls.push(next); }
20040        el = next;
20041      }
20042      return new Dom7(nextEls);
20043    }
20044    function prev(selector) {
20045      if (this.length > 0) {
20046        var el = this[0];
20047        if (selector) {
20048          if (el.previousElementSibling && $(el.previousElementSibling).is(selector)) {
20049            return new Dom7([el.previousElementSibling]);
20050          }
20051          return new Dom7([]);
20052        }
20053  
20054        if (el.previousElementSibling) { return new Dom7([el.previousElementSibling]); }
20055        return new Dom7([]);
20056      }
20057      return new Dom7([]);
20058    }
20059    function prevAll(selector) {
20060      var prevEls = [];
20061      var el = this[0];
20062      if (!el) { return new Dom7([]); }
20063      while (el.previousElementSibling) {
20064        var prev = el.previousElementSibling; // eslint-disable-line
20065        if (selector) {
20066          if ($(prev).is(selector)) { prevEls.push(prev); }
20067        } else { prevEls.push(prev); }
20068        el = prev;
20069      }
20070      return new Dom7(prevEls);
20071    }
20072    function parent(selector) {
20073      var parents = []; // eslint-disable-line
20074      for (var i = 0; i < this.length; i += 1) {
20075        if (this[i].parentNode !== null) {
20076          if (selector) {
20077            if ($(this[i].parentNode).is(selector)) { parents.push(this[i].parentNode); }
20078          } else {
20079            parents.push(this[i].parentNode);
20080          }
20081        }
20082      }
20083      return $(unique(parents));
20084    }
20085    function parents(selector) {
20086      var parents = []; // eslint-disable-line
20087      for (var i = 0; i < this.length; i += 1) {
20088        var parent = this[i].parentNode; // eslint-disable-line
20089        while (parent) {
20090          if (selector) {
20091            if ($(parent).is(selector)) { parents.push(parent); }
20092          } else {
20093            parents.push(parent);
20094          }
20095          parent = parent.parentNode;
20096        }
20097      }
20098      return $(unique(parents));
20099    }
20100    function closest(selector) {
20101      var closest = this; // eslint-disable-line
20102      if (typeof selector === 'undefined') {
20103        return new Dom7([]);
20104      }
20105      if (!closest.is(selector)) {
20106        closest = closest.parents(selector).eq(0);
20107      }
20108      return closest;
20109    }
20110    function find(selector) {
20111      var foundElements = [];
20112      for (var i = 0; i < this.length; i += 1) {
20113        var found = this[i].querySelectorAll(selector);
20114        for (var j = 0; j < found.length; j += 1) {
20115          foundElements.push(found[j]);
20116        }
20117      }
20118      return new Dom7(foundElements);
20119    }
20120    function children(selector) {
20121      var children = []; // eslint-disable-line
20122      for (var i = 0; i < this.length; i += 1) {
20123        var childNodes = this[i].childNodes;
20124  
20125        for (var j = 0; j < childNodes.length; j += 1) {
20126          if (!selector) {
20127            if (childNodes[j].nodeType === 1) { children.push(childNodes[j]); }
20128          } else if (childNodes[j].nodeType === 1 && $(childNodes[j]).is(selector)) {
20129            children.push(childNodes[j]);
20130          }
20131        }
20132      }
20133      return new Dom7(unique(children));
20134    }
20135    function remove() {
20136      for (var i = 0; i < this.length; i += 1) {
20137        if (this[i].parentNode) { this[i].parentNode.removeChild(this[i]); }
20138      }
20139      return this;
20140    }
20141    function add() {
20142      var args = [], len = arguments.length;
20143      while ( len-- ) args[ len ] = arguments[ len ];
20144  
20145      var dom = this;
20146      var i;
20147      var j;
20148      for (i = 0; i < args.length; i += 1) {
20149        var toAdd = $(args[i]);
20150        for (j = 0; j < toAdd.length; j += 1) {
20151          dom[dom.length] = toAdd[j];
20152          dom.length += 1;
20153        }
20154      }
20155      return dom;
20156    }
20157  
20158    var Methods = {
20159      addClass: addClass,
20160      removeClass: removeClass,
20161      hasClass: hasClass,
20162      toggleClass: toggleClass,
20163      attr: attr,
20164      removeAttr: removeAttr,
20165      data: data,
20166      transform: transform,
20167      transition: transition,
20168      on: on,
20169      off: off,
20170      trigger: trigger,
20171      transitionEnd: transitionEnd,
20172      outerWidth: outerWidth,
20173      outerHeight: outerHeight,
20174      offset: offset,
20175      css: css,
20176      each: each,
20177      html: html,
20178      text: text,
20179      is: is,
20180      index: index,
20181      eq: eq,
20182      append: append,
20183      prepend: prepend,
20184      next: next,
20185      nextAll: nextAll,
20186      prev: prev,
20187      prevAll: prevAll,
20188      parent: parent,
20189      parents: parents,
20190      closest: closest,
20191      find: find,
20192      children: children,
20193      filter: filter,
20194      remove: remove,
20195      add: add,
20196      styles: styles,
20197    };
20198  
20199    Object.keys(Methods).forEach(function (methodName) {
20200      $.fn[methodName] = $.fn[methodName] || Methods[methodName];
20201    });
20202  
20203    var Utils = {
20204      deleteProps: function deleteProps(obj) {
20205        var object = obj;
20206        Object.keys(object).forEach(function (key) {
20207          try {
20208            object[key] = null;
20209          } catch (e) {
20210            // no getter for object
20211          }
20212          try {
20213            delete object[key];
20214          } catch (e) {
20215            // something got wrong
20216          }
20217        });
20218      },
20219      nextTick: function nextTick(callback, delay) {
20220        if ( delay === void 0 ) delay = 0;
20221  
20222        return setTimeout(callback, delay);
20223      },
20224      now: function now() {
20225        return Date.now();
20226      },
20227      getTranslate: function getTranslate(el, axis) {
20228        if ( axis === void 0 ) axis = 'x';
20229  
20230        var matrix;
20231        var curTransform;
20232        var transformMatrix;
20233  
20234        var curStyle = win.getComputedStyle(el, null);
20235  
20236        if (win.WebKitCSSMatrix) {
20237          curTransform = curStyle.transform || curStyle.webkitTransform;
20238          if (curTransform.split(',').length > 6) {
20239            curTransform = curTransform.split(', ').map(function (a) { return a.replace(',', '.'); }).join(', ');
20240          }
20241          // Some old versions of Webkit choke when 'none' is passed; pass
20242          // empty string instead in this case
20243          transformMatrix = new win.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
20244        } else {
20245          transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
20246          matrix = transformMatrix.toString().split(',');
20247        }
20248  
20249        if (axis === 'x') {
20250          // Latest Chrome and webkits Fix
20251          if (win.WebKitCSSMatrix) { curTransform = transformMatrix.m41; }
20252          // Crazy IE10 Matrix
20253          else if (matrix.length === 16) { curTransform = parseFloat(matrix[12]); }
20254          // Normal Browsers
20255          else { curTransform = parseFloat(matrix[4]); }
20256        }
20257        if (axis === 'y') {
20258          // Latest Chrome and webkits Fix
20259          if (win.WebKitCSSMatrix) { curTransform = transformMatrix.m42; }
20260          // Crazy IE10 Matrix
20261          else if (matrix.length === 16) { curTransform = parseFloat(matrix[13]); }
20262          // Normal Browsers
20263          else { curTransform = parseFloat(matrix[5]); }
20264        }
20265        return curTransform || 0;
20266      },
20267      parseUrlQuery: function parseUrlQuery(url) {
20268        var query = {};
20269        var urlToParse = url || win.location.href;
20270        var i;
20271        var params;
20272        var param;
20273        var length;
20274        if (typeof urlToParse === 'string' && urlToParse.length) {
20275          urlToParse = urlToParse.indexOf('?') > -1 ? urlToParse.replace(/\S*\?/, '') : '';
20276          params = urlToParse.split('&').filter(function (paramsPart) { return paramsPart !== ''; });
20277          length = params.length;
20278  
20279          for (i = 0; i < length; i += 1) {
20280            param = params[i].replace(/#\S+/g, '').split('=');
20281            query[decodeURIComponent(param[0])] = typeof param[1] === 'undefined' ? undefined : decodeURIComponent(param[1]) || '';
20282          }
20283        }
20284        return query;
20285      },
20286      isObject: function isObject(o) {
20287        return typeof o === 'object' && o !== null && o.constructor && o.constructor === Object;
20288      },
20289      extend: function extend() {
20290        var args = [], len$1 = arguments.length;
20291        while ( len$1-- ) args[ len$1 ] = arguments[ len$1 ];
20292  
20293        var to = Object(args[0]);
20294        for (var i = 1; i < args.length; i += 1) {
20295          var nextSource = args[i];
20296          if (nextSource !== undefined && nextSource !== null) {
20297            var keysArray = Object.keys(Object(nextSource));
20298            for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) {
20299              var nextKey = keysArray[nextIndex];
20300              var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
20301              if (desc !== undefined && desc.enumerable) {
20302                if (Utils.isObject(to[nextKey]) && Utils.isObject(nextSource[nextKey])) {
20303                  Utils.extend(to[nextKey], nextSource[nextKey]);
20304                } else if (!Utils.isObject(to[nextKey]) && Utils.isObject(nextSource[nextKey])) {
20305                  to[nextKey] = {};
20306                  Utils.extend(to[nextKey], nextSource[nextKey]);
20307                } else {
20308                  to[nextKey] = nextSource[nextKey];
20309                }
20310              }
20311            }
20312          }
20313        }
20314        return to;
20315      },
20316    };
20317  
20318    var Support = (function Support() {
20319      return {
20320        touch: (win.Modernizr && win.Modernizr.touch === true) || (function checkTouch() {
20321          return !!((win.navigator.maxTouchPoints > 0) || ('ontouchstart' in win) || (win.DocumentTouch && doc instanceof win.DocumentTouch));
20322        }()),
20323  
20324        pointerEvents: !!win.PointerEvent && ('maxTouchPoints' in win.navigator) && win.navigator.maxTouchPoints > 0,
20325  
20326        observer: (function checkObserver() {
20327          return ('MutationObserver' in win || 'WebkitMutationObserver' in win);
20328        }()),
20329  
20330        passiveListener: (function checkPassiveListener() {
20331          var supportsPassive = false;
20332          try {
20333            var opts = Object.defineProperty({}, 'passive', {
20334              // eslint-disable-next-line
20335              get: function get() {
20336                supportsPassive = true;
20337              },
20338            });
20339            win.addEventListener('testPassiveListener', null, opts);
20340          } catch (e) {
20341            // No support
20342          }
20343          return supportsPassive;
20344        }()),
20345  
20346        gestures: (function checkGestures() {
20347          return 'ongesturestart' in win;
20348        }()),
20349      };
20350    }());
20351  
20352    var SwiperClass = function SwiperClass(params) {
20353      if ( params === void 0 ) params = {};
20354  
20355      var self = this;
20356      self.params = params;
20357  
20358      // Events
20359      self.eventsListeners = {};
20360  
20361      if (self.params && self.params.on) {
vendor: 9,263 bytes, lines 20362-20623
20362        Object.keys(self.params.on).forEach(function (eventName) {
20363          self.on(eventName, self.params.on[eventName]);
20364        });
20365      }
20366    };
20367  
20368    var staticAccessors = { components: { configurable: true } };
20369  
20370    SwiperClass.prototype.on = function on (events, handler, priority) {
20371      var self = this;
20372      if (typeof handler !== 'function') { return self; }
20373      var method = priority ? 'unshift' : 'push';
20374      events.split(' ').forEach(function (event) {
20375        if (!self.eventsListeners[event]) { self.eventsListeners[event] = []; }
20376        self.eventsListeners[event][method](handler);
20377      });
20378      return self;
20379    };
20380  
20381    SwiperClass.prototype.once = function once (events, handler, priority) {
20382      var self = this;
20383      if (typeof handler !== 'function') { return self; }
20384      function onceHandler() {
20385          var args = [], len = arguments.length;
20386          while ( len-- ) args[ len ] = arguments[ len ];
20387  
20388        handler.apply(self, args);
20389        self.off(events, onceHandler);
20390        if (onceHandler.f7proxy) {
20391          delete onceHandler.f7proxy;
20392        }
20393      }
20394      onceHandler.f7proxy = handler;
20395      return self.on(events, onceHandler, priority);
20396    };
20397  
20398    SwiperClass.prototype.off = function off (events, handler) {
20399      var self = this;
20400      if (!self.eventsListeners) { return self; }
20401      events.split(' ').forEach(function (event) {
20402        if (typeof handler === 'undefined') {
20403          self.eventsListeners[event] = [];
20404        } else if (self.eventsListeners[event] && self.eventsListeners[event].length) {
20405          self.eventsListeners[event].forEach(function (eventHandler, index) {
20406            if (eventHandler === handler || (eventHandler.f7proxy && eventHandler.f7proxy === handler)) {
20407              self.eventsListeners[event].splice(index, 1);
20408            }
20409          });
20410        }
20411      });
20412      return self;
20413    };
20414  
20415    SwiperClass.prototype.emit = function emit () {
20416        var args = [], len = arguments.length;
20417        while ( len-- ) args[ len ] = arguments[ len ];
20418  
20419      var self = this;
20420      if (!self.eventsListeners) { return self; }
20421      var events;
20422      var data;
20423      var context;
20424      if (typeof args[0] === 'string' || Array.isArray(args[0])) {
20425        events = args[0];
20426        data = args.slice(1, args.length);
20427        context = self;
20428      } else {
20429        events = args[0].events;
20430        data = args[0].data;
20431        context = args[0].context || self;
20432      }
20433      var eventsArray = Array.isArray(events) ? events : events.split(' ');
20434      eventsArray.forEach(function (event) {
20435        if (self.eventsListeners && self.eventsListeners[event]) {
20436          var handlers = [];
20437          self.eventsListeners[event].forEach(function (eventHandler) {
20438            handlers.push(eventHandler);
20439          });
20440          handlers.forEach(function (eventHandler) {
20441            eventHandler.apply(context, data);
20442          });
20443        }
20444      });
20445      return self;
20446    };
20447  
20448    SwiperClass.prototype.useModulesParams = function useModulesParams (instanceParams) {
20449      var instance = this;
20450      if (!instance.modules) { return; }
20451      Object.keys(instance.modules).forEach(function (moduleName) {
20452        var module = instance.modules[moduleName];
20453        // Extend params
20454        if (module.params) {
20455          Utils.extend(instanceParams, module.params);
20456        }
20457      });
20458    };
20459  
20460    SwiperClass.prototype.useModules = function useModules (modulesParams) {
20461        if ( modulesParams === void 0 ) modulesParams = {};
20462  
20463      var instance = this;
20464      if (!instance.modules) { return; }
20465      Object.keys(instance.modules).forEach(function (moduleName) {
20466        var module = instance.modules[moduleName];
20467        var moduleParams = modulesParams[moduleName] || {};
20468        // Extend instance methods and props
20469        if (module.instance) {
20470          Object.keys(module.instance).forEach(function (modulePropName) {
20471            var moduleProp = module.instance[modulePropName];
20472            if (typeof moduleProp === 'function') {
20473              instance[modulePropName] = moduleProp.bind(instance);
20474            } else {
20475              instance[modulePropName] = moduleProp;
20476            }
20477          });
20478        }
20479        // Add event listeners
20480        if (module.on && instance.on) {
20481          Object.keys(module.on).forEach(function (moduleEventName) {
20482            instance.on(moduleEventName, module.on[moduleEventName]);
20483          });
20484        }
20485  
20486        // Module create callback
20487        if (module.create) {
20488          module.create.bind(instance)(moduleParams);
20489        }
20490      });
20491    };
20492  
20493    staticAccessors.components.set = function (components) {
20494      var Class = this;
20495      if (!Class.use) { return; }
20496      Class.use(components);
20497    };
20498  
20499    SwiperClass.installModule = function installModule (module) {
20500        var params = [], len = arguments.length - 1;
20501        while ( len-- > 0 ) params[ len ] = arguments[ len + 1 ];
20502  
20503      var Class = this;
20504      if (!Class.prototype.modules) { Class.prototype.modules = {}; }
20505      var name = module.name || (((Object.keys(Class.prototype.modules).length) + "_" + (Utils.now())));
20506      Class.prototype.modules[name] = module;
20507      // Prototype
20508      if (module.proto) {
20509        Object.keys(module.proto).forEach(function (key) {
20510          Class.prototype[key] = module.proto[key];
20511        });
20512      }
20513      // Class
20514      if (module.static) {
20515        Object.keys(module.static).forEach(function (key) {
20516          Class[key] = module.static[key];
20517        });
20518      }
20519      // Callback
20520      if (module.install) {
20521        module.install.apply(Class, params);
20522      }
20523      return Class;
20524    };
20525  
20526    SwiperClass.use = function use (module) {
20527        var params = [], len = arguments.length - 1;
20528        while ( len-- > 0 ) params[ len ] = arguments[ len + 1 ];
20529  
20530      var Class = this;
20531      if (Array.isArray(module)) {
20532        module.forEach(function (m) { return Class.installModule(m); });
20533        return Class;
20534      }
20535      return Class.installModule.apply(Class, [ module ].concat( params ));
20536    };
20537  
20538    Object.defineProperties( SwiperClass, staticAccessors );
20539  
20540    function updateSize () {
20541      var swiper = this;
20542      var width;
20543      var height;
20544      var $el = swiper.$el;
20545      if (typeof swiper.params.width !== 'undefined') {
20546        width = swiper.params.width;
20547      } else {
20548        width = $el[0].clientWidth;
20549      }
20550      if (typeof swiper.params.height !== 'undefined') {
20551        height = swiper.params.height;
20552      } else {
20553        height = $el[0].clientHeight;
20554      }
20555      if ((width === 0 && swiper.isHorizontal()) || (height === 0 && swiper.isVertical())) {
20556        return;
20557      }
20558  
20559      // Subtract paddings
20560      width = width - parseInt($el.css('padding-left'), 10) - parseInt($el.css('padding-right'), 10);
20561      height = height - parseInt($el.css('padding-top'), 10) - parseInt($el.css('padding-bottom'), 10);
20562  
20563      Utils.extend(swiper, {
20564        width: width,
20565        height: height,
20566        size: swiper.isHorizontal() ? width : height,
20567      });
20568    }
20569  
20570    function updateSlides () {
20571      var swiper = this;
20572      var params = swiper.params;
20573  
20574      var $wrapperEl = swiper.$wrapperEl;
20575      var swiperSize = swiper.size;
20576      var rtl = swiper.rtlTranslate;
20577      var wrongRTL = swiper.wrongRTL;
20578      var isVirtual = swiper.virtual && params.virtual.enabled;
20579      var previousSlidesLength = isVirtual ? swiper.virtual.slides.length : swiper.slides.length;
20580      var slides = $wrapperEl.children(("." + (swiper.params.slideClass)));
20581      var slidesLength = isVirtual ? swiper.virtual.slides.length : slides.length;
20582      var snapGrid = [];
20583      var slidesGrid = [];
20584      var slidesSizesGrid = [];
20585  
20586      function slidesForMargin(slideIndex) {
20587        if (!params.cssMode) { return true; }
20588        if (slideIndex === slides.length - 1) {
20589          return false;
20590        }
20591        return true;
20592      }
20593  
20594      var offsetBefore = params.slidesOffsetBefore;
20595      if (typeof offsetBefore === 'function') {
20596        offsetBefore = params.slidesOffsetBefore.call(swiper);
20597      }
20598  
20599      var offsetAfter = params.slidesOffsetAfter;
20600      if (typeof offsetAfter === 'function') {
20601        offsetAfter = params.slidesOffsetAfter.call(swiper);
20602      }
20603  
20604      var previousSnapGridLength = swiper.snapGrid.length;
20605      var previousSlidesGridLength = swiper.snapGrid.length;
20606  
20607      var spaceBetween = params.spaceBetween;
20608      var slidePosition = -offsetBefore;
20609      var prevSlideSize = 0;
20610      var index = 0;
20611      if (typeof swiperSize === 'undefined') {
20612        return;
20613      }
20614      if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
20615        spaceBetween = (parseFloat(spaceBetween.replace('%', '')) / 100) * swiperSize;
20616      }
20617  
20618      swiper.virtualSize = -spaceBetween;
20619  
20620      // reset margins
20621      if (rtl) { slides.css({ marginLeft: '', marginTop: '' }); }
20622      else { slides.css({ marginRight: '', marginBottom: '' }); }
20623  
20624      var slidesNumberEvenToRows;
20625      if (params.slidesPerColumn > 1) {
20626        if (Math.floor(slidesLength / params.slidesPerColumn) === slidesLength / swiper.params.slidesPerColumn) {
20627          slidesNumberEvenToRows = slidesLength;
20628        } else {
20629          slidesNumberEvenToRows = Math.ceil(slidesLength / params.slidesPerColumn) * params.slidesPerColumn;
20630        }
20631        if (params.slidesPerView !== 'auto' && params.slidesPerColumnFill === 'row') {
20632          slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, params.slidesPerView * params.slidesPerColumn);
20633        }
20634      }
20635  
20636      // Calc slides
20637      var slideSize;
20638      var slidesPerColumn = params.slidesPerColumn;
20639      var slidesPerRow = slidesNumberEvenToRows / slidesPerColumn;
20640      var numFullColumns = Math.floor(slidesLength / params.slidesPerColumn);
20641      for (var i = 0; i < slidesLength; i += 1) {
20642        slideSize = 0;
20643        var slide = slides.eq(i);
20644        if (params.slidesPerColumn > 1) {
20645          // Set slides order
20646          var newSlideOrderIndex = (void 0);
20647          var column = (void 0);
20648          var row = (void 0);
20649          if (params.slidesPerColumnFill === 'row' && params.slidesPerGroup > 1) {
20650            var groupIndex = Math.floor(i / (params.slidesPerGroup * params.slidesPerColumn));
20651            var slideIndexInGroup = i - params.slidesPerColumn * params.slidesPerGroup * groupIndex;
20652            var columnsInGroup = groupIndex === 0
20653              ? params.slidesPerGroup
20654              : Math.min(Math.ceil((slidesLength - groupIndex * slidesPerColumn * params.slidesPerGroup) / slidesPerColumn), params.slidesPerGroup);
20655            row = Math.floor(slideIndexInGroup / columnsInGroup);
20656            column = (slideIndexInGroup - row * columnsInGroup) + groupIndex * params.slidesPerGroup;
20657  
20658            newSlideOrderIndex = column + ((row * slidesNumberEvenToRows) / slidesPerColumn);
20659            slide
20660              .css({
20661                '-webkit-box-ordinal-group': newSlideOrderIndex,
20662                '-moz-box-ordinal-group': newSlideOrderIndex,
20663                '-ms-flex-order': newSlideOrderIndex,
20664                '-webkit-order': newSlideOrderIndex,
20665                order: newSlideOrderIndex,
20666              });
20667          } else if (params.slidesPerColumnFill === 'column') {
20668            column = Math.floor(i / slidesPerColumn);
20669            row = i - (column * slidesPerColumn);
20670            if (column > numFullColumns || (column === numFullColumns && row === slidesPerColumn - 1)) {
20671              row += 1;
20672              if (row >= slidesPerColumn) {
20673                row = 0;
20674                column += 1;
20675              }
20676            }
20677          } else {
20678            row = Math.floor(i / slidesPerRow);
20679            column = i - (row * slidesPerRow);
20680          }
20681          slide.css(
20682            ("margin-" + (swiper.isHorizontal() ? 'top' : 'left')),
20683            (row !== 0 && params.spaceBetween) && (((params.spaceBetween) + "px"))
20684          );
20685        }
20686        if (slide.css('display') === 'none') { continue; } // eslint-disable-line
20687  
20688        if (params.slidesPerView === 'auto') {
20689          var slideStyles = win.getComputedStyle(slide[0], null);
20690          var currentTransform = slide[0].style.transform;
20691          var currentWebKitTransform = slide[0].style.webkitTransform;
20692          if (currentTransform) {
20693            slide[0].style.transform = 'none';
20694          }
20695          if (currentWebKitTransform) {
20696            slide[0].style.webkitTransform = 'none';
20697          }
20698          if (params.roundLengths) {
20699            slideSize = swiper.isHorizontal()
20700              ? slide.outerWidth(true)
20701              : slide.outerHeight(true);
20702          } else {
20703            // eslint-disable-next-line
20704            if (swiper.isHorizontal()) {
20705              var width = parseFloat(slideStyles.getPropertyValue('width'));
20706              var paddingLeft = parseFloat(slideStyles.getPropertyValue('padding-left'));
20707              var paddingRight = parseFloat(slideStyles.getPropertyValue('padding-right'));
20708              var marginLeft = parseFloat(slideStyles.getPropertyValue('margin-left'));
20709              var marginRight = parseFloat(slideStyles.getPropertyValue('margin-right'));
20710              var boxSizing = slideStyles.getPropertyValue('box-sizing');
20711              if (boxSizing && boxSizing === 'border-box') {
20712                slideSize = width + marginLeft + marginRight;
20713              } else {
20714                slideSize = width + paddingLeft + paddingRight + marginLeft + marginRight;
20715              }
20716            } else {
20717              var height = parseFloat(slideStyles.getPropertyValue('height'));
20718              var paddingTop = parseFloat(slideStyles.getPropertyValue('padding-top'));
20719              var paddingBottom = parseFloat(slideStyles.getPropertyValue('padding-bottom'));
20720              var marginTop = parseFloat(slideStyles.getPropertyValue('margin-top'));
20721              var marginBottom = parseFloat(slideStyles.getPropertyValue('margin-bottom'));
20722              var boxSizing$1 = slideStyles.getPropertyValue('box-sizing');
20723              if (boxSizing$1 && boxSizing$1 === 'border-box') {
20724                slideSize = height + marginTop + marginBottom;
20725              } else {
20726                slideSize = height + paddingTop + paddingBottom + marginTop + marginBottom;
20727              }
20728            }
20729          }
20730          if (currentTransform) {
20731            slide[0].style.transform = currentTransform;
20732          }
20733          if (currentWebKitTransform) {
20734            slide[0].style.webkitTransform = currentWebKitTransform;
20735          }
20736          if (params.roundLengths) { slideSize = Math.floor(slideSize); }
20737        } else {
20738          slideSize = (swiperSize - ((params.slidesPerView - 1) * spaceBetween)) / params.slidesPerView;
20739          if (params.roundLengths) { slideSize = Math.floor(slideSize); }
20740  
20741          if (slides[i]) {
20742            if (swiper.isHorizontal()) {
20743              slides[i].style.width = slideSize + "px";
20744            } else {
20745              slides[i].style.height = slideSize + "px";
20746            }
20747          }
20748        }
20749        if (slides[i]) {
20750          slides[i].swiperSlideSize = slideSize;
20751        }
20752        slidesSizesGrid.push(slideSize);
20753  
20754  
20755        if (params.centeredSlides) {
20756          slidePosition = slidePosition + (slideSize / 2) + (prevSlideSize / 2) + spaceBetween;
20757          if (prevSlideSize === 0 && i !== 0) { slidePosition = slidePosition - (swiperSize / 2) - spaceBetween; }
20758          if (i === 0) { slidePosition = slidePosition - (swiperSize / 2) - spaceBetween; }
20759          if (Math.abs(slidePosition) < 1 / 1000) { slidePosition = 0; }
20760          if (params.roundLengths) { slidePosition = Math.floor(slidePosition); }
20761          if ((index) % params.slidesPerGroup === 0) { snapGrid.push(slidePosition); }
20762          slidesGrid.push(slidePosition);
20763        } else {
20764          if (params.roundLengths) { slidePosition = Math.floor(slidePosition); }
20765          if ((index) % params.slidesPerGroup === 0) { snapGrid.push(slidePosition); }
20766          slidesGrid.push(slidePosition);
20767          slidePosition = slidePosition + slideSize + spaceBetween;
20768        }
20769  
20770        swiper.virtualSize += slideSize + spaceBetween;
20771  
20772        prevSlideSize = slideSize;
20773  
20774        index += 1;
20775      }
20776      swiper.virtualSize = Math.max(swiper.virtualSize, swiperSize) + offsetAfter;
20777      var newSlidesGrid;
20778  
20779      if (
20780        rtl && wrongRTL && (params.effect === 'slide' || params.effect === 'coverflow')) {
20781        $wrapperEl.css({ width: ((swiper.virtualSize + params.spaceBetween) + "px") });
20782      }
20783      if (params.setWrapperSize) {
20784        if (swiper.isHorizontal()) { $wrapperEl.css({ width: ((swiper.virtualSize + params.spaceBetween) + "px") }); }
20785        else { $wrapperEl.css({ height: ((swiper.virtualSize + params.spaceBetween) + "px") }); }
20786      }
20787  
20788      if (params.slidesPerColumn > 1) {
20789        swiper.virtualSize = (slideSize + params.spaceBetween) * slidesNumberEvenToRows;
20790        swiper.virtualSize = Math.ceil(swiper.virtualSize / params.slidesPerColumn) - params.spaceBetween;
20791        if (swiper.isHorizontal()) { $wrapperEl.css({ width: ((swiper.virtualSize + params.spaceBetween) + "px") }); }
20792        else { $wrapperEl.css({ height: ((swiper.virtualSize + params.spaceBetween) + "px") }); }
20793        if (params.centeredSlides) {
20794          newSlidesGrid = [];
20795          for (var i$1 = 0; i$1 < snapGrid.length; i$1 += 1) {
20796            var slidesGridItem = snapGrid[i$1];
20797            if (params.roundLengths) { slidesGridItem = Math.floor(slidesGridItem); }
20798            if (snapGrid[i$1] < swiper.virtualSize + snapGrid[0]) { newSlidesGrid.push(slidesGridItem); }
20799          }
20800          snapGrid = newSlidesGrid;
20801        }
20802      }
20803  
20804      // Remove last grid elements depending on width
20805      if (!params.centeredSlides) {
20806        newSlidesGrid = [];
20807        for (var i$2 = 0; i$2 < snapGrid.length; i$2 += 1) {
20808          var slidesGridItem$1 = snapGrid[i$2];
20809          if (params.roundLengths) { slidesGridItem$1 = Math.floor(slidesGridItem$1); }
20810          if (snapGrid[i$2] <= swiper.virtualSize - swiperSize) {
20811            newSlidesGrid.push(slidesGridItem$1);
20812          }
20813        }
20814        snapGrid = newSlidesGrid;
20815        if (Math.floor(swiper.virtualSize - swiperSize) - Math.floor(snapGrid[snapGrid.length - 1]) > 1) {
20816          snapGrid.push(swiper.virtualSize - swiperSize);
20817        }
20818      }
20819      if (snapGrid.length === 0) { snapGrid = [0]; }
20820  
20821      if (params.spaceBetween !== 0) {
20822        if (swiper.isHorizontal()) {
20823          if (rtl) { slides.filter(slidesForMargin).css({ marginLeft: (spaceBetween + "px") }); }
20824          else { slides.filter(slidesForMargin).css({ marginRight: (spaceBetween + "px") }); }
20825        } else { slides.filter(slidesForMargin).css({ marginBottom: (spaceBetween + "px") }); }
20826      }
20827  
20828      if (params.centeredSlides && params.centeredSlidesBounds) {
20829        var allSlidesSize = 0;
20830        slidesSizesGrid.forEach(function (slideSizeValue) {
20831          allSlidesSize += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);
20832        });
20833        allSlidesSize -= params.spaceBetween;
20834        var maxSnap = allSlidesSize - swiperSize;
20835        snapGrid = snapGrid.map(function (snap) {
20836          if (snap < 0) { return -offsetBefore; }
20837          if (snap > maxSnap) { return maxSnap + offsetAfter; }
20838          return snap;
20839        });
20840      }
20841  
20842      if (params.centerInsufficientSlides) {
20843        var allSlidesSize$1 = 0;
20844        slidesSizesGrid.forEach(function (slideSizeValue) {
20845          allSlidesSize$1 += slideSizeValue + (params.spaceBetween ? params.spaceBetween : 0);
20846        });
20847        allSlidesSize$1 -= params.spaceBetween;
20848        if (allSlidesSize$1 < swiperSize) {
20849          var allSlidesOffset = (swiperSize - allSlidesSize$1) / 2;
20850          snapGrid.forEach(function (snap, snapIndex) {
20851            snapGrid[snapIndex] = snap - allSlidesOffset;
20852          });
20853          slidesGrid.forEach(function (snap, snapIndex) {
20854            slidesGrid[snapIndex] = snap + allSlidesOffset;
20855          });
20856        }
20857      }
20858  
20859      Utils.extend(swiper, {
20860        slides: slides,
20861        snapGrid: snapGrid,
20862        slidesGrid: slidesGrid,
20863        slidesSizesGrid: slidesSizesGrid,
20864      });
20865  
20866      if (slidesLength !== previousSlidesLength) {
20867        swiper.emit('slidesLengthChange');
20868      }
vendor: 9,741 bytes, lines 20869-21106
20869      if (snapGrid.length !== previousSnapGridLength) {
20870        if (swiper.params.watchOverflow) { swiper.checkOverflow(); }
20871        swiper.emit('snapGridLengthChange');
20872      }
20873      if (slidesGrid.length !== previousSlidesGridLength) {
20874        swiper.emit('slidesGridLengthChange');
20875      }
20876  
20877      if (params.watchSlidesProgress || params.watchSlidesVisibility) {
20878        swiper.updateSlidesOffset();
20879      }
20880    }
20881  
20882    function updateAutoHeight (speed) {
20883      var swiper = this;
20884      var activeSlides = [];
20885      var newHeight = 0;
20886      var i;
20887      if (typeof speed === 'number') {
20888        swiper.setTransition(speed);
20889      } else if (speed === true) {
20890        swiper.setTransition(swiper.params.speed);
20891      }
20892      // Find slides currently in view
20893      if (swiper.params.slidesPerView !== 'auto' && swiper.params.slidesPerView > 1) {
20894        for (i = 0; i < Math.ceil(swiper.params.slidesPerView); i += 1) {
20895          var index = swiper.activeIndex + i;
20896          if (index > swiper.slides.length) { break; }
20897          activeSlides.push(swiper.slides.eq(index)[0]);
20898        }
20899      } else {
20900        activeSlides.push(swiper.slides.eq(swiper.activeIndex)[0]);
20901      }
20902  
20903      // Find new height from highest slide in view
20904      for (i = 0; i < activeSlides.length; i += 1) {
20905        if (typeof activeSlides[i] !== 'undefined') {
20906          var height = activeSlides[i].offsetHeight;
20907          newHeight = height > newHeight ? height : newHeight;
20908        }
20909      }
20910  
20911      // Update Height
20912      if (newHeight) { swiper.$wrapperEl.css('height', (newHeight + "px")); }
20913    }
20914  
20915    function updateSlidesOffset () {
20916      var swiper = this;
20917      var slides = swiper.slides;
20918      for (var i = 0; i < slides.length; i += 1) {
20919        slides[i].swiperSlideOffset = swiper.isHorizontal() ? slides[i].offsetLeft : slides[i].offsetTop;
20920      }
20921    }
20922  
20923    function updateSlidesProgress (translate) {
20924      if ( translate === void 0 ) translate = (this && this.translate) || 0;
20925  
20926      var swiper = this;
20927      var params = swiper.params;
20928  
20929      var slides = swiper.slides;
20930      var rtl = swiper.rtlTranslate;
20931  
20932      if (slides.length === 0) { return; }
20933      if (typeof slides[0].swiperSlideOffset === 'undefined') { swiper.updateSlidesOffset(); }
20934  
20935      var offsetCenter = -translate;
20936      if (rtl) { offsetCenter = translate; }
20937  
20938      // Visible Slides
20939      slides.removeClass(params.slideVisibleClass);
20940  
20941      swiper.visibleSlidesIndexes = [];
20942      swiper.visibleSlides = [];
20943  
20944      for (var i = 0; i < slides.length; i += 1) {
20945        var slide = slides[i];
20946        var slideProgress = (
20947          (offsetCenter + (params.centeredSlides ? swiper.minTranslate() : 0)) - slide.swiperSlideOffset
20948        ) / (slide.swiperSlideSize + params.spaceBetween);
20949        if (params.watchSlidesVisibility) {
20950          var slideBefore = -(offsetCenter - slide.swiperSlideOffset);
20951          var slideAfter = slideBefore + swiper.slidesSizesGrid[i];
20952          var isVisible = (slideBefore >= 0 && slideBefore < swiper.size - 1)
20953                    || (slideAfter > 1 && slideAfter <= swiper.size)
20954                    || (slideBefore <= 0 && slideAfter >= swiper.size);
20955          if (isVisible) {
20956            swiper.visibleSlides.push(slide);
20957            swiper.visibleSlidesIndexes.push(i);
20958            slides.eq(i).addClass(params.slideVisibleClass);
20959          }
20960        }
20961        slide.progress = rtl ? -slideProgress : slideProgress;
20962      }
20963      swiper.visibleSlides = $(swiper.visibleSlides);
20964    }
20965  
20966    function updateProgress (translate) {
20967      var swiper = this;
20968      if (typeof translate === 'undefined') {
20969        var multiplier = swiper.rtlTranslate ? -1 : 1;
20970        // eslint-disable-next-line
20971        translate = (swiper && swiper.translate && (swiper.translate * multiplier)) || 0;
20972      }
20973      var params = swiper.params;
20974      var translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
20975      var progress = swiper.progress;
20976      var isBeginning = swiper.isBeginning;
20977      var isEnd = swiper.isEnd;
20978      var wasBeginning = isBeginning;
20979      var wasEnd = isEnd;
20980      if (translatesDiff === 0) {
20981        progress = 0;
20982        isBeginning = true;
20983        isEnd = true;
20984      } else {
20985        progress = (translate - swiper.minTranslate()) / (translatesDiff);
20986        isBeginning = progress <= 0;
20987        isEnd = progress >= 1;
20988      }
20989      Utils.extend(swiper, {
20990        progress: progress,
20991        isBeginning: isBeginning,
20992        isEnd: isEnd,
20993      });
20994  
20995      if (params.watchSlidesProgress || params.watchSlidesVisibility) { swiper.updateSlidesProgress(translate); }
20996  
20997      if (isBeginning && !wasBeginning) {
20998        swiper.emit('reachBeginning toEdge');
20999      }
21000      if (isEnd && !wasEnd) {
21001        swiper.emit('reachEnd toEdge');
21002      }
21003      if ((wasBeginning && !isBeginning) || (wasEnd && !isEnd)) {
21004        swiper.emit('fromEdge');
21005      }
21006  
21007      swiper.emit('progress', progress);
21008    }
21009  
21010    function updateSlidesClasses () {
21011      var swiper = this;
21012  
21013      var slides = swiper.slides;
21014      var params = swiper.params;
21015      var $wrapperEl = swiper.$wrapperEl;
21016      var activeIndex = swiper.activeIndex;
21017      var realIndex = swiper.realIndex;
21018      var isVirtual = swiper.virtual && params.virtual.enabled;
21019  
21020      slides.removeClass(((params.slideActiveClass) + " " + (params.slideNextClass) + " " + (params.slidePrevClass) + " " + (params.slideDuplicateActiveClass) + " " + (params.slideDuplicateNextClass) + " " + (params.slideDuplicatePrevClass)));
21021  
21022      var activeSlide;
21023      if (isVirtual) {
21024        activeSlide = swiper.$wrapperEl.find(("." + (params.slideClass) + "[data-swiper-slide-index=\"" + activeIndex + "\"]"));
21025      } else {
21026        activeSlide = slides.eq(activeIndex);
21027      }
21028  
21029      // Active classes
21030      activeSlide.addClass(params.slideActiveClass);
21031  
21032      if (params.loop) {
21033        // Duplicate to all looped slides
21034        if (activeSlide.hasClass(params.slideDuplicateClass)) {
21035          $wrapperEl
21036            .children(("." + (params.slideClass) + ":not(." + (params.slideDuplicateClass) + ")[data-swiper-slide-index=\"" + realIndex + "\"]"))
21037            .addClass(params.slideDuplicateActiveClass);
21038        } else {
21039          $wrapperEl
21040            .children(("." + (params.slideClass) + "." + (params.slideDuplicateClass) + "[data-swiper-slide-index=\"" + realIndex + "\"]"))
21041            .addClass(params.slideDuplicateActiveClass);
21042        }
21043      }
21044      // Next Slide
21045      var nextSlide = activeSlide.nextAll(("." + (params.slideClass))).eq(0).addClass(params.slideNextClass);
21046      if (params.loop && nextSlide.length === 0) {
21047        nextSlide = slides.eq(0);
21048        nextSlide.addClass(params.slideNextClass);
21049      }
21050      // Prev Slide
21051      var prevSlide = activeSlide.prevAll(("." + (params.slideClass))).eq(0).addClass(params.slidePrevClass);
21052      if (params.loop && prevSlide.length === 0) {
21053        prevSlide = slides.eq(-1);
21054        prevSlide.addClass(params.slidePrevClass);
21055      }
21056      if (params.loop) {
21057        // Duplicate to all looped slides
21058        if (nextSlide.hasClass(params.slideDuplicateClass)) {
21059          $wrapperEl
21060            .children(("." + (params.slideClass) + ":not(." + (params.slideDuplicateClass) + ")[data-swiper-slide-index=\"" + (nextSlide.attr('data-swiper-slide-index')) + "\"]"))
21061            .addClass(params.slideDuplicateNextClass);
21062        } else {
21063          $wrapperEl
21064            .children(("." + (params.slideClass) + "." + (params.slideDuplicateClass) + "[data-swiper-slide-index=\"" + (nextSlide.attr('data-swiper-slide-index')) + "\"]"))
21065            .addClass(params.slideDuplicateNextClass);
21066        }
21067        if (prevSlide.hasClass(params.slideDuplicateClass)) {
21068          $wrapperEl
21069            .children(("." + (params.slideClass) + ":not(." + (params.slideDuplicateClass) + ")[data-swiper-slide-index=\"" + (prevSlide.attr('data-swiper-slide-index')) + "\"]"))
21070            .addClass(params.slideDuplicatePrevClass);
21071        } else {
21072          $wrapperEl
21073            .children(("." + (params.slideClass) + "." + (params.slideDuplicateClass) + "[data-swiper-slide-index=\"" + (prevSlide.attr('data-swiper-slide-index')) + "\"]"))
21074            .addClass(params.slideDuplicatePrevClass);
21075        }
21076      }
21077    }
21078  
21079    function updateActiveIndex (newActiveIndex) {
21080      var swiper = this;
21081      var translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;
21082      var slidesGrid = swiper.slidesGrid;
21083      var snapGrid = swiper.snapGrid;
21084      var params = swiper.params;
21085      var previousIndex = swiper.activeIndex;
21086      var previousRealIndex = swiper.realIndex;
21087      var previousSnapIndex = swiper.snapIndex;
21088      var activeIndex = newActiveIndex;
21089      var snapIndex;
21090      if (typeof activeIndex === 'undefined') {
21091        for (var i = 0; i < slidesGrid.length; i += 1) {
21092          if (typeof slidesGrid[i + 1] !== 'undefined') {
21093            if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1] - ((slidesGrid[i + 1] - slidesGrid[i]) / 2)) {
21094              activeIndex = i;
21095            } else if (translate >= slidesGrid[i] && translate < slidesGrid[i + 1]) {
21096              activeIndex = i + 1;
21097            }
21098          } else if (translate >= slidesGrid[i]) {
21099            activeIndex = i;
21100          }
21101        }
21102        // Normalize slideIndex
21103        if (params.normalizeSlideIndex) {
21104          if (activeIndex < 0 || typeof activeIndex === 'undefined') { activeIndex = 0; }
21105        }
21106      }
21107      if (snapGrid.indexOf(translate) >= 0) {
21108        snapIndex = snapGrid.indexOf(translate);
21109      } else {
21110        snapIndex = Math.floor(activeIndex / params.slidesPerGroup);
21111      }
21112      if (snapIndex >= snapGrid.length) { snapIndex = snapGrid.length - 1; }
21113      if (activeIndex === previousIndex) {
21114        if (snapIndex !== previousSnapIndex) {
21115          swiper.snapIndex = snapIndex;
21116          swiper.emit('snapIndexChange');
21117        }
21118        return;
21119      }
21120  
21121      // Get real index
21122      var realIndex = parseInt(swiper.slides.eq(activeIndex).attr('data-swiper-slide-index') || activeIndex, 10);
21123  
21124      Utils.extend(swiper, {
21125        snapIndex: snapIndex,
21126        realIndex: realIndex,
21127        previousIndex: previousIndex,
21128        activeIndex: activeIndex,
21129      });
21130      swiper.emit('activeIndexChange');
21131      swiper.emit('snapIndexChange');
21132      if (previousRealIndex !== realIndex) {
21133        swiper.emit('realIndexChange');
21134      }
21135      if (swiper.initialized || swiper.runCallbacksOnInit) {
21136        swiper.emit('slideChange');
21137      }
21138    }
21139  
21140    function updateClickedSlide (e) {
21141      var swiper = this;
21142      var params = swiper.params;
21143      var slide = $(e.target).closest(("." + (params.slideClass)))[0];
21144      var slideFound = false;
21145      if (slide) {
21146        for (var i = 0; i < swiper.slides.length; i += 1) {
21147          if (swiper.slides[i] === slide) { slideFound = true; }
21148        }
21149      }
21150  
21151      if (slide && slideFound) {
21152        swiper.clickedSlide = slide;
21153        if (swiper.virtual && swiper.params.virtual.enabled) {
21154          swiper.clickedIndex = parseInt($(slide).attr('data-swiper-slide-index'), 10);
21155        } else {
21156          swiper.clickedIndex = $(slide).index();
21157        }
21158      } else {
21159        swiper.clickedSlide = undefined;
21160        swiper.clickedIndex = undefined;
21161        return;
21162      }
21163      if (params.slideToClickedSlide && swiper.clickedIndex !== undefined && swiper.clickedIndex !== swiper.activeIndex) {
21164        swiper.slideToClickedSlide();
21165      }
21166    }
21167  
21168    var update = {
21169      updateSize: updateSize,
21170      updateSlides: updateSlides,
21171      updateAutoHeight: updateAutoHeight,
21172      updateSlidesOffset: updateSlidesOffset,
21173      updateSlidesProgress: updateSlidesProgress,
21174      updateProgress: updateProgress,
21175      updateSlidesClasses: updateSlidesClasses,
21176      updateActiveIndex: updateActiveIndex,
21177      updateClickedSlide: updateClickedSlide,
21178    };
21179  
21180    function getTranslate (axis) {
21181      if ( axis === void 0 ) axis = this.isHorizontal() ? 'x' : 'y';
21182  
21183      var swiper = this;
21184  
21185      var params = swiper.params;
21186      var rtl = swiper.rtlTranslate;
21187      var translate = swiper.translate;
21188      var $wrapperEl = swiper.$wrapperEl;
21189  
21190      if (params.virtualTranslate) {
21191        return rtl ? -translate : translate;
21192      }
21193      if (params.cssMode) {
21194        return translate;
21195      }
21196  
21197      var currentTranslate = Utils.getTranslate($wrapperEl[0], axis);
21198      if (rtl) { currentTranslate = -currentTranslate; }
21199  
21200      return currentTranslate || 0;
21201    }
21202  
21203    function setTranslate (translate, byController) {
21204      var swiper = this;
21205      var rtl = swiper.rtlTranslate;
21206      var params = swiper.params;
21207      var $wrapperEl = swiper.$wrapperEl;
21208      var wrapperEl = swiper.wrapperEl;
21209      var progress = swiper.progress;
21210      var x = 0;
21211      var y = 0;
21212      var z = 0;
21213  
21214      if (swiper.isHorizontal()) {
21215        x = rtl ? -translate : translate;
21216      } else {
21217        y = translate;
21218      }
21219  
21220      if (params.roundLengths) {
21221        x = Math.floor(x);
21222        y = Math.floor(y);
21223      }
21224  
21225      if (params.cssMode) {
21226        wrapperEl[swiper.isHorizontal() ? 'scrollLeft' : 'scrollTop'] = swiper.isHorizontal() ? -x : -y;
21227      } else if (!params.virtualTranslate) {
21228        $wrapperEl.transform(("translate3d(" + x + "px, " + y + "px, " + z + "px)"));
21229      }
21230      swiper.previousTranslate = swiper.translate;
21231      swiper.translate = swiper.isHorizontal() ? x : y;
21232  
21233      // Check if we need to update progress
21234      var newProgress;
21235      var translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
21236      if (translatesDiff === 0) {
21237        newProgress = 0;
21238      } else {
21239        newProgress = (translate - swiper.minTranslate()) / (translatesDiff);
21240      }
21241      if (newProgress !== progress) {
21242        swiper.updateProgress(translate);
21243      }
21244  
21245      swiper.emit('setTranslate', swiper.translate, byController);
21246    }
21247  
21248    function minTranslate () {
21249      return (-this.snapGrid[0]);
21250    }
21251  
21252    function maxTranslate () {
21253      return (-this.snapGrid[this.snapGrid.length - 1]);
21254    }
21255  
21256    function translateTo (translate, speed, runCallbacks, translateBounds, internal) {
21257      var obj;
21258  
21259      if ( translate === void 0 ) translate = 0;
21260      if ( speed === void 0 ) speed = this.params.speed;
21261      if ( runCallbacks === void 0 ) runCallbacks = true;
21262      if ( translateBounds === void 0 ) translateBounds = true;
21263      var swiper = this;
21264  
21265      var params = swiper.params;
21266      var wrapperEl = swiper.wrapperEl;
21267  
21268      if (swiper.animating && params.preventInteractionOnTransition) {
21269        return false;
21270      }
21271  
21272      var minTranslate = swiper.minTranslate();
21273      var maxTranslate = swiper.maxTranslate();
21274      var newTranslate;
21275      if (translateBounds && translate > minTranslate) { newTranslate = minTranslate; }
21276      else if (translateBounds && translate < maxTranslate) { newTranslate = maxTranslate; }
21277      else { newTranslate = translate; }
21278  
21279      // Update progress
21280      swiper.updateProgress(newTranslate);
21281  
21282      if (params.cssMode) {
21283        var isH = swiper.isHorizontal();
21284        if (speed === 0) {
21285          wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -newTranslate;
21286        } else {
21287          // eslint-disable-next-line
21288          if (wrapperEl.scrollTo) {
21289            wrapperEl.scrollTo(( obj = {}, obj[isH ? 'left' : 'top'] = -newTranslate, obj.behavior = 'smooth', obj ));
21290          } else {
21291            wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -newTranslate;
21292          }
21293        }
21294        return true;
21295      }
21296  
21297      if (speed === 0) {
21298        swiper.setTransition(0);
21299        swiper.setTranslate(newTranslate);
21300        if (runCallbacks) {
21301          swiper.emit('beforeTransitionStart', speed, internal);
21302          swiper.emit('transitionEnd');
21303        }
21304      } else {
21305        swiper.setTransition(speed);
21306        swiper.setTranslate(newTranslate);
21307        if (runCallbacks) {
21308          swiper.emit('beforeTransitionStart', speed, internal);
21309          swiper.emit('transitionStart');
21310        }
21311        if (!swiper.animating) {
21312          swiper.animating = true;
21313          if (!swiper.onTranslateToWrapperTransitionEnd) {
21314            swiper.onTranslateToWrapperTransitionEnd = function transitionEnd(e) {
21315              if (!swiper || swiper.destroyed) { return; }
21316              if (e.target !== this) { return; }
21317              swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);
21318              swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.onTranslateToWrapperTransitionEnd);
21319              swiper.onTranslateToWrapperTransitionEnd = null;
21320              delete swiper.onTranslateToWrapperTransitionEnd;
21321              if (runCallbacks) {
21322                swiper.emit('transitionEnd');
21323              }
21324            };
21325          }
21326          swiper.$wrapperEl[0].addEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);
21327          swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.onTranslateToWrapperTransitionEnd);
21328        }
21329      }
21330  
21331      return true;
21332    }
21333  
21334    var translate = {
21335      getTranslate: getTranslate,
21336      setTranslate: setTranslate,
21337      minTranslate: minTranslate,
21338      maxTranslate: maxTranslate,
21339      translateTo: translateTo,
21340    };
21341  
21342    function setTransition (duration, byController) {
21343      var swiper = this;
21344  
21345      if (!swiper.params.cssMode) {
21346        swiper.$wrapperEl.transition(duration);
21347      }
21348  
21349      swiper.emit('setTransition', duration, byController);
21350    }
21351  
21352    function transitionStart (runCallbacks, direction) {
21353      if ( runCallbacks === void 0 ) runCallbacks = true;
21354  
21355      var swiper = this;
21356      var activeIndex = swiper.activeIndex;
21357      var params = swiper.params;
21358      var previousIndex = swiper.previousIndex;
21359      if (params.cssMode) { return; }
21360      if (params.autoHeight) {
21361        swiper.updateAutoHeight();
21362      }
21363  
21364      var dir = direction;
21365      if (!dir) {
21366        if (activeIndex > previousIndex) { dir = 'next'; }
21367        else if (activeIndex < previousIndex) { dir = 'prev'; }
21368        else { dir = 'reset'; }
21369      }
21370  
21371      swiper.emit('transitionStart');
21372  
21373      if (runCallbacks && activeIndex !== previousIndex) {
21374        if (dir === 'reset') {
21375          swiper.emit('slideResetTransitionStart');
21376          return;
21377        }
21378        swiper.emit('slideChangeTransitionStart');
21379        if (dir === 'next') {
21380          swiper.emit('slideNextTransitionStart');
21381        } else {
21382          swiper.emit('slidePrevTransitionStart');
21383        }
21384      }
21385    }
21386  
21387    function transitionEnd$1 (runCallbacks, direction) {
21388      if ( runCallbacks === void 0 ) runCallbacks = true;
21389  
21390      var swiper = this;
21391      var activeIndex = swiper.activeIndex;
21392      var previousIndex = swiper.previousIndex;
21393      var params = swiper.params;
21394      swiper.animating = false;
21395      if (params.cssMode) { return; }
21396      swiper.setTransition(0);
21397  
21398      var dir = direction;
21399      if (!dir) {
21400        if (activeIndex > previousIndex) { dir = 'next'; }
21401        else if (activeIndex < previousIndex) { dir = 'prev'; }
21402        else { dir = 'reset'; }
21403      }
21404  
21405      swiper.emit('transitionEnd');
21406  
21407      if (runCallbacks && activeIndex !== previousIndex) {
21408        if (dir === 'reset') {
21409          swiper.emit('slideResetTransitionEnd');
21410          return;
21411        }
21412        swiper.emit('slideChangeTransitionEnd');
21413        if (dir === 'next') {
21414          swiper.emit('slideNextTransitionEnd');
21415        } else {
21416          swiper.emit('slidePrevTransitionEnd');
21417        }
21418      }
21419    }
21420  
21421    var transition$1 = {
21422      setTransition: setTransition,
21423      transitionStart: transitionStart,
21424      transitionEnd: transitionEnd$1,
21425    };
21426  
21427    function slideTo (index, speed, runCallbacks, internal) {
21428      var obj;
21429  
21430      if ( index === void 0 ) index = 0;
21431      if ( speed === void 0 ) speed = this.params.speed;
21432      if ( runCallbacks === void 0 ) runCallbacks = true;
21433      var swiper = this;
21434      var slideIndex = index;
21435      if (slideIndex < 0) { slideIndex = 0; }
21436  
21437      var params = swiper.params;
21438      var snapGrid = swiper.snapGrid;
21439      var slidesGrid = swiper.slidesGrid;
21440      var previousIndex = swiper.previousIndex;
21441      var activeIndex = swiper.activeIndex;
21442      var rtl = swiper.rtlTranslate;
21443      var wrapperEl = swiper.wrapperEl;
21444      if (swiper.animating && params.preventInteractionOnTransition) {
21445        return false;
21446      }
21447  
21448      var snapIndex = Math.floor(slideIndex / params.slidesPerGroup);
21449      if (snapIndex >= snapGrid.length) { snapIndex = snapGrid.length - 1; }
21450  
21451      if ((activeIndex || params.initialSlide || 0) === (previousIndex || 0) && runCallbacks) {
21452        swiper.emit('beforeSlideChangeStart');
21453      }
21454  
21455      var translate = -snapGrid[snapIndex];
21456  
21457      // Update progress
21458      swiper.updateProgress(translate);
21459  
21460      // Normalize slideIndex
21461      if (params.normalizeSlideIndex) {
21462        for (var i = 0; i < slidesGrid.length; i += 1) {
21463          if (-Math.floor(translate * 100) >= Math.floor(slidesGrid[i] * 100)) {
21464            slideIndex = i;
21465          }
21466        }
21467      }
21468      // Directions locks
21469      if (swiper.initialized && slideIndex !== activeIndex) {
21470        if (!swiper.allowSlideNext && translate < swiper.translate && translate < swiper.minTranslate()) {
21471          return false;
21472        }
21473        if (!swiper.allowSlidePrev && translate > swiper.translate && translate > swiper.maxTranslate()) {
21474          if ((activeIndex || 0) !== slideIndex) { return false; }
21475        }
21476      }
21477  
21478      var direction;
21479      if (slideIndex > activeIndex) { direction = 'next'; }
21480      else if (slideIndex < activeIndex) { direction = 'prev'; }
21481      else { direction = 'reset'; }
21482  
21483  
21484      // Update Index
21485      if ((rtl && -translate === swiper.translate) || (!rtl && translate === swiper.translate)) {
21486        swiper.updateActiveIndex(slideIndex);
21487        // Update Height
21488        if (params.autoHeight) {
21489          swiper.updateAutoHeight();
21490        }
21491        swiper.updateSlidesClasses();
21492        if (params.effect !== 'slide') {
21493          swiper.setTranslate(translate);
21494        }
21495        if (direction !== 'reset') {
21496          swiper.transitionStart(runCallbacks, direction);
21497          swiper.transitionEnd(runCallbacks, direction);
21498        }
21499        return false;
21500      }
21501      if (params.cssMode) {
21502        var isH = swiper.isHorizontal();
21503        if (speed === 0) {
21504          wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -translate;
21505        } else {
21506          // eslint-disable-next-line
21507          if (wrapperEl.scrollTo) {
21508            wrapperEl.scrollTo(( obj = {}, obj[isH ? 'left' : 'top'] = -translate, obj.behavior = 'smooth', obj ));
21509          } else {
21510            wrapperEl[isH ? 'scrollLeft' : 'scrollTop'] = -translate;
21511          }
21512        }
21513        return true;
21514      }
21515  
21516      if (speed === 0) {
21517        swiper.setTransition(0);
21518        swiper.setTranslate(translate);
21519        swiper.updateActiveIndex(slideIndex);
21520        swiper.updateSlidesClasses();
21521        swiper.emit('beforeTransitionStart', speed, internal);
21522        swiper.transitionStart(runCallbacks, direction);
21523        swiper.transitionEnd(runCallbacks, direction);
21524      } else {
21525        swiper.setTransition(speed);
21526        swiper.setTranslate(translate);
21527        swiper.updateActiveIndex(slideIndex);
21528        swiper.updateSlidesClasses();
21529        swiper.emit('beforeTransitionStart', speed, internal);
21530        swiper.transitionStart(runCallbacks, direction);
21531        if (!swiper.animating) {
21532          swiper.animating = true;
21533          if (!swiper.onSlideToWrapperTransitionEnd) {
21534            swiper.onSlideToWrapperTransitionEnd = function transitionEnd(e) {
21535              if (!swiper || swiper.destroyed) { return; }
21536              if (e.target !== this) { return; }
21537              swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);
21538              swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);
21539              swiper.onSlideToWrapperTransitionEnd = null;
21540              delete swiper.onSlideToWrapperTransitionEnd;
21541              swiper.transitionEnd(runCallbacks, direction);
21542            };
21543          }
21544          swiper.$wrapperEl[0].addEventListener('transitionend', swiper.onSlideToWrapperTransitionEnd);
21545          swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.onSlideToWrapperTransitionEnd);
21546        }
21547      }
21548  
21549      return true;
21550    }
21551  
21552    function slideToLoop (index, speed, runCallbacks, internal) {
21553      if ( index === void 0 ) index = 0;
21554      if ( speed === void 0 ) speed = this.params.speed;
21555      if ( runCallbacks === void 0 ) runCallbacks = true;
21556  
21557      var swiper = this;
21558      var newIndex = index;
21559      if (swiper.params.loop) {
21560        newIndex += swiper.loopedSlides;
21561      }
21562  
21563      return swiper.slideTo(newIndex, speed, runCallbacks, internal);
21564    }
21565  
21566    /* eslint no-unused-vars: "off" */
21567    function slideNext (speed, runCallbacks, internal) {
21568      if ( speed === void 0 ) speed = this.params.speed;
21569      if ( runCallbacks === void 0 ) runCallbacks = true;
21570  
21571      var swiper = this;
21572      var params = swiper.params;
21573      var animating = swiper.animating;
21574      if (params.loop) {
21575        if (animating) { return false; }
21576        swiper.loopFix();
21577        // eslint-disable-next-line
21578        swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
21579        return swiper.slideTo(swiper.activeIndex + params.slidesPerGroup, speed, runCallbacks, internal);
21580      }
21581      return swiper.slideTo(swiper.activeIndex + params.slidesPerGroup, speed, runCallbacks, internal);
21582    }
21583  
21584    /* eslint no-unused-vars: "off" */
21585    function slidePrev (speed, runCallbacks, internal) {
21586      if ( speed === void 0 ) speed = this.params.speed;
21587      if ( runCallbacks === void 0 ) runCallbacks = true;
21588  
21589      var swiper = this;
21590      var params = swiper.params;
21591      var animating = swiper.animating;
21592      var snapGrid = swiper.snapGrid;
21593      var slidesGrid = swiper.slidesGrid;
21594      var rtlTranslate = swiper.rtlTranslate;
21595  
21596      if (params.loop) {
21597        if (animating) { return false; }
21598        swiper.loopFix();
21599        // eslint-disable-next-line
21600        swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
21601      }
21602      var translate = rtlTranslate ? swiper.translate : -swiper.translate;
21603      function normalize(val) {
21604        if (val < 0) { return -Math.floor(Math.abs(val)); }
21605        return Math.floor(val);
21606      }
21607      var normalizedTranslate = normalize(translate);
21608      var normalizedSnapGrid = snapGrid.map(function (val) { return normalize(val); });
21609      var normalizedSlidesGrid = slidesGrid.map(function (val) { return normalize(val); });
21610  
21611      var currentSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate)];
21612      var prevSnap = snapGrid[normalizedSnapGrid.indexOf(normalizedTranslate) - 1];
21613      if (typeof prevSnap === 'undefined' && params.cssMode) {
21614        snapGrid.forEach(function (snap) {
21615          if (!prevSnap && normalizedTranslate >= snap) { prevSnap = snap; }
21616        });
21617      }
21618      var prevIndex;
21619      if (typeof prevSnap !== 'undefined') {
21620        prevIndex = slidesGrid.indexOf(prevSnap);
21621        if (prevIndex < 0) { prevIndex = swiper.activeIndex - 1; }
21622      }
21623      return swiper.slideTo(prevIndex, speed, runCallbacks, internal);
21624    }
21625  
21626    /* eslint no-unused-vars: "off" */
21627    function slideReset (speed, runCallbacks, internal) {
21628      if ( speed === void 0 ) speed = this.params.speed;
21629      if ( runCallbacks === void 0 ) runCallbacks = true;
21630  
21631      var swiper = this;
21632      return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal);
21633    }
21634  
21635    /* eslint no-unused-vars: "off" */
21636    function slideToClosest (speed, runCallbacks, internal, threshold) {
21637      if ( speed === void 0 ) speed = this.params.speed;
21638      if ( runCallbacks === void 0 ) runCallbacks = true;
21639      if ( threshold === void 0 ) threshold = 0.5;
21640  
21641      var swiper = this;
21642      var index = swiper.activeIndex;
21643      var snapIndex = Math.floor(index / swiper.params.slidesPerGroup);
21644  
21645      var translate = swiper.rtlTranslate ? swiper.translate : -swiper.translate;
21646  
21647      if (translate >= swiper.snapGrid[snapIndex]) {
21648        // The current translate is on or after the current snap index, so the choice
21649        // is between the current index and the one after it.
21650        var currentSnap = swiper.snapGrid[snapIndex];
21651        var nextSnap = swiper.snapGrid[snapIndex + 1];
21652        if ((translate - currentSnap) > (nextSnap - currentSnap) * threshold) {
21653          index += swiper.params.slidesPerGroup;
21654        }
21655      } else {
21656        // The current translate is before the current snap index, so the choice
21657        // is between the current index and the one before it.
21658        var prevSnap = swiper.snapGrid[snapIndex - 1];
21659        var currentSnap$1 = swiper.snapGrid[snapIndex];
21660        if ((translate - prevSnap) <= (currentSnap$1 - prevSnap) * threshold) {
21661          index -= swiper.params.slidesPerGroup;
21662        }
21663      }
21664      index = Math.max(index, 0);
21665      index = Math.min(index, swiper.snapGrid.length - 1);
21666  
21667      return swiper.slideTo(index, speed, runCallbacks, internal);
21668    }
21669  
21670    function slideToClickedSlide () {
21671      var swiper = this;
21672      var params = swiper.params;
21673      var $wrapperEl = swiper.$wrapperEl;
21674  
21675      var slidesPerView = params.slidesPerView === 'auto' ? swiper.slidesPerViewDynamic() : params.slidesPerView;
21676      var slideToIndex = swiper.clickedIndex;
21677      var realIndex;
21678      if (params.loop) {
21679        if (swiper.animating) { return; }
21680        realIndex = parseInt($(swiper.clickedSlide).attr('data-swiper-slide-index'), 10);
21681        if (params.centeredSlides) {
21682          if (
21683            (slideToIndex < swiper.loopedSlides - (slidesPerView / 2))
21684            || (slideToIndex > (swiper.slides.length - swiper.loopedSlides) + (slidesPerView / 2))
21685          ) {
21686            swiper.loopFix();
21687            slideToIndex = $wrapperEl
21688              .children(("." + (params.slideClass) + "[data-swiper-slide-index=\"" + realIndex + "\"]:not(." + (params.slideDuplicateClass) + ")"))
21689              .eq(0)
21690              .index();
21691  
21692            Utils.nextTick(function () {
21693              swiper.slideTo(slideToIndex);
21694            });
21695          } else {
21696            swiper.slideTo(slideToIndex);
21697          }
21698        } else if (slideToIndex > swiper.slides.length - slidesPerView) {
21699          swiper.loopFix();
21700          slideToIndex = $wrapperEl
21701            .children(("." + (params.slideClass) + "[data-swiper-slide-index=\"" + realIndex + "\"]:not(." + (params.slideDuplicateClass) + ")"))
21702            .eq(0)
21703            .index();
21704  
21705          Utils.nextTick(function () {
21706            swiper.slideTo(slideToIndex);
21707          });
21708        } else {
21709          swiper.slideTo(slideToIndex);
21710        }
21711      } else {
21712        swiper.slideTo(slideToIndex);
21713      }
21714    }
21715  
21716    var slide = {
21717      slideTo: slideTo,
21718      slideToLoop: slideToLoop,
21719      slideNext: slideNext,
21720      slidePrev: slidePrev,
21721      slideReset: slideReset,
21722      slideToClosest: slideToClosest,
21723      slideToClickedSlide: slideToClickedSlide,
21724    };
21725  
21726    function loopCreate () {
21727      var swiper = this;
21728      var params = swiper.params;
21729      var $wrapperEl = swiper.$wrapperEl;
21730      // Remove duplicated slides
21731      $wrapperEl.children(("." + (params.slideClass) + "." + (params.slideDuplicateClass))).remove();
21732  
21733      var slides = $wrapperEl.children(("." + (params.slideClass)));
21734  
21735      if (params.loopFillGroupWithBlank) {
21736        var blankSlidesNum = params.slidesPerGroup - (slides.length % params.slidesPerGroup);
21737        if (blankSlidesNum !== params.slidesPerGroup) {
21738          for (var i = 0; i < blankSlidesNum; i += 1) {
21739            var blankNode = $(doc.createElement('div')).addClass(((params.slideClass) + " " + (params.slideBlankClass)));
21740            $wrapperEl.append(blankNode);
21741          }
21742          slides = $wrapperEl.children(("." + (params.slideClass)));
21743        }
21744      }
21745  
21746      if (params.slidesPerView === 'auto' && !params.loopedSlides) { params.loopedSlides = slides.length; }
21747  
21748      swiper.loopedSlides = Math.ceil(parseFloat(params.loopedSlides || params.slidesPerView, 10));
21749      swiper.loopedSlides += params.loopAdditionalSlides;
21750      if (swiper.loopedSlides > slides.length) {
21751        swiper.loopedSlides = slides.length;
21752      }
21753  
21754      var prependSlides = [];
21755      var appendSlides = [];
21756      slides.each(function (index, el) {
21757        var slide = $(el);
21758        if (index < swiper.loopedSlides) { appendSlides.push(el); }
21759        if (index < slides.length && index >= slides.length - swiper.loopedSlides) { prependSlides.push(el); }
21760        slide.attr('data-swiper-slide-index', index);
21761      });
21762      for (var i$1 = 0; i$1 < appendSlides.length; i$1 += 1) {
21763        $wrapperEl.append($(appendSlides[i$1].cloneNode(true)).addClass(params.slideDuplicateClass));
21764      }
21765      for (var i$2 = prependSlides.length - 1; i$2 >= 0; i$2 -= 1) {
21766        $wrapperEl.prepend($(prependSlides[i$2].cloneNode(true)).addClass(params.slideDuplicateClass));
21767      }
21768    }
21769  
21770    function loopFix () {
21771      var swiper = this;
21772      var activeIndex = swiper.activeIndex;
21773      var slides = swiper.slides;
21774      var loopedSlides = swiper.loopedSlides;
21775      var allowSlidePrev = swiper.allowSlidePrev;
21776      var allowSlideNext = swiper.allowSlideNext;
21777      var snapGrid = swiper.snapGrid;
21778      var rtl = swiper.rtlTranslate;
21779      var newIndex;
21780      swiper.allowSlidePrev = true;
21781      swiper.allowSlideNext = true;
21782  
21783      var snapTranslate = -snapGrid[activeIndex];
21784      var diff = snapTranslate - swiper.getTranslate();
21785  
21786  
21787      // Fix For Negative Oversliding
21788      if (activeIndex < loopedSlides) {
21789        newIndex = (slides.length - (loopedSlides * 3)) + activeIndex;
21790        newIndex += loopedSlides;
21791        var slideChanged = swiper.slideTo(newIndex, 0, false, true);
21792        if (slideChanged && diff !== 0) {
21793          swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);
21794        }
21795      } else if (activeIndex >= slides.length - loopedSlides) {
21796        // Fix For Positive Oversliding
21797        newIndex = -slides.length + activeIndex + loopedSlides;
21798        newIndex += loopedSlides;
21799        var slideChanged$1 = swiper.slideTo(newIndex, 0, false, true);
21800        if (slideChanged$1 && diff !== 0) {
21801          swiper.setTranslate((rtl ? -swiper.translate : swiper.translate) - diff);
21802        }
21803      }
21804      swiper.allowSlidePrev = allowSlidePrev;
21805      swiper.allowSlideNext = allowSlideNext;
21806    }
21807  
21808    function loopDestroy () {
21809      var swiper = this;
21810      var $wrapperEl = swiper.$wrapperEl;
21811      var params = swiper.params;
21812      var slides = swiper.slides;
21813      $wrapperEl.children(("." + (params.slideClass) + "." + (params.slideDuplicateClass) + ",." + (params.slideClass) + "." + (params.slideBlankClass))).remove();
21814      slides.removeAttr('data-swiper-slide-index');
21815    }
21816  
21817    var loop = {
21818      loopCreate: loopCreate,
21819      loopFix: loopFix,
21820      loopDestroy: loopDestroy,
21821    };
21822  
21823    function setGrabCursor (moving) {
21824      var swiper = this;
21825      if (Support.touch || !swiper.params.simulateTouch || (swiper.params.watchOverflow && swiper.isLocked) || swiper.params.cssMode) { return; }
21826      var el = swiper.el;
21827      el.style.cursor = 'move';
21828      el.style.cursor = moving ? '-webkit-grabbing' : '-webkit-grab';
21829      el.style.cursor = moving ? '-moz-grabbin' : '-moz-grab';
21830      el.style.cursor = moving ? 'grabbing' : 'grab';
21831    }
21832  
21833    function unsetGrabCursor () {
21834      var swiper = this;
21835      if (Support.touch || (swiper.params.watchOverflow && swiper.isLocked) || swiper.params.cssMode) { return; }
21836      swiper.el.style.cursor = '';
21837    }
21838  
21839    var grabCursor = {
21840      setGrabCursor: setGrabCursor,
21841      unsetGrabCursor: unsetGrabCursor,
21842    };
21843  
21844    function appendSlide (slides) {
21845      var swiper = this;
21846      var $wrapperEl = swiper.$wrapperEl;
21847      var params = swiper.params;
21848      if (params.loop) {
21849        swiper.loopDestroy();
21850      }
21851      if (typeof slides === 'object' && 'length' in slides) {
21852        for (var i = 0; i < slides.length; i += 1) {
21853          if (slides[i]) { $wrapperEl.append(slides[i]); }
21854        }
21855      } else {
21856        $wrapperEl.append(slides);
21857      }
21858      if (params.loop) {
21859        swiper.loopCreate();
21860      }
21861      if (!(params.observer && Support.observer)) {
vendor: 30,914 bytes, lines 21862-22706
21862        swiper.update();
21863      }
21864    }
21865  
21866    function prependSlide (slides) {
21867      var swiper = this;
21868      var params = swiper.params;
21869      var $wrapperEl = swiper.$wrapperEl;
21870      var activeIndex = swiper.activeIndex;
21871  
21872      if (params.loop) {
21873        swiper.loopDestroy();
21874      }
21875      var newActiveIndex = activeIndex + 1;
21876      if (typeof slides === 'object' && 'length' in slides) {
21877        for (var i = 0; i < slides.length; i += 1) {
21878          if (slides[i]) { $wrapperEl.prepend(slides[i]); }
21879        }
21880        newActiveIndex = activeIndex + slides.length;
21881      } else {
21882        $wrapperEl.prepend(slides);
21883      }
21884      if (params.loop) {
21885        swiper.loopCreate();
21886      }
21887      if (!(params.observer && Support.observer)) {
21888        swiper.update();
21889      }
21890      swiper.slideTo(newActiveIndex, 0, false);
21891    }
21892  
21893    function addSlide (index, slides) {
21894      var swiper = this;
21895      var $wrapperEl = swiper.$wrapperEl;
21896      var params = swiper.params;
21897      var activeIndex = swiper.activeIndex;
21898      var activeIndexBuffer = activeIndex;
21899      if (params.loop) {
21900        activeIndexBuffer -= swiper.loopedSlides;
21901        swiper.loopDestroy();
21902        swiper.slides = $wrapperEl.children(("." + (params.slideClass)));
21903      }
21904      var baseLength = swiper.slides.length;
21905      if (index <= 0) {
21906        swiper.prependSlide(slides);
21907        return;
21908      }
21909      if (index >= baseLength) {
21910        swiper.appendSlide(slides);
21911        return;
21912      }
21913      var newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + 1 : activeIndexBuffer;
21914  
21915      var slidesBuffer = [];
21916      for (var i = baseLength - 1; i >= index; i -= 1) {
21917        var currentSlide = swiper.slides.eq(i);
21918        currentSlide.remove();
21919        slidesBuffer.unshift(currentSlide);
21920      }
21921  
21922      if (typeof slides === 'object' && 'length' in slides) {
21923        for (var i$1 = 0; i$1 < slides.length; i$1 += 1) {
21924          if (slides[i$1]) { $wrapperEl.append(slides[i$1]); }
21925        }
21926        newActiveIndex = activeIndexBuffer > index ? activeIndexBuffer + slides.length : activeIndexBuffer;
21927      } else {
21928        $wrapperEl.append(slides);
21929      }
21930  
21931      for (var i$2 = 0; i$2 < slidesBuffer.length; i$2 += 1) {
21932        $wrapperEl.append(slidesBuffer[i$2]);
21933      }
21934  
21935      if (params.loop) {
21936        swiper.loopCreate();
21937      }
21938      if (!(params.observer && Support.observer)) {
21939        swiper.update();
21940      }
21941      if (params.loop) {
21942        swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
21943      } else {
21944        swiper.slideTo(newActiveIndex, 0, false);
21945      }
21946    }
21947  
21948    function removeSlide (slidesIndexes) {
21949      var swiper = this;
21950      var params = swiper.params;
21951      var $wrapperEl = swiper.$wrapperEl;
21952      var activeIndex = swiper.activeIndex;
21953  
21954      var activeIndexBuffer = activeIndex;
21955      if (params.loop) {
21956        activeIndexBuffer -= swiper.loopedSlides;
21957        swiper.loopDestroy();
21958        swiper.slides = $wrapperEl.children(("." + (params.slideClass)));
21959      }
21960      var newActiveIndex = activeIndexBuffer;
21961      var indexToRemove;
21962  
21963      if (typeof slidesIndexes === 'object' && 'length' in slidesIndexes) {
21964        for (var i = 0; i < slidesIndexes.length; i += 1) {
21965          indexToRemove = slidesIndexes[i];
21966          if (swiper.slides[indexToRemove]) { swiper.slides.eq(indexToRemove).remove(); }
21967          if (indexToRemove < newActiveIndex) { newActiveIndex -= 1; }
21968        }
21969        newActiveIndex = Math.max(newActiveIndex, 0);
21970      } else {
21971        indexToRemove = slidesIndexes;
21972        if (swiper.slides[indexToRemove]) { swiper.slides.eq(indexToRemove).remove(); }
21973        if (indexToRemove < newActiveIndex) { newActiveIndex -= 1; }
21974        newActiveIndex = Math.max(newActiveIndex, 0);
21975      }
21976  
21977      if (params.loop) {
21978        swiper.loopCreate();
21979      }
21980  
21981      if (!(params.observer && Support.observer)) {
21982        swiper.update();
21983      }
21984      if (params.loop) {
21985        swiper.slideTo(newActiveIndex + swiper.loopedSlides, 0, false);
21986      } else {
21987        swiper.slideTo(newActiveIndex, 0, false);
21988      }
21989    }
21990  
21991    function removeAllSlides () {
21992      var swiper = this;
21993  
21994      var slidesIndexes = [];
21995      for (var i = 0; i < swiper.slides.length; i += 1) {
21996        slidesIndexes.push(i);
21997      }
21998      swiper.removeSlide(slidesIndexes);
21999    }
22000  
22001    var manipulation = {
22002      appendSlide: appendSlide,
22003      prependSlide: prependSlide,
22004      addSlide: addSlide,
22005      removeSlide: removeSlide,
22006      removeAllSlides: removeAllSlides,
22007    };
22008  
22009    var Device = (function Device() {
22010      var platform = win.navigator.platform;
22011      var ua = win.navigator.userAgent;
22012  
22013      var device = {
22014        ios: false,
22015        android: false,
22016        androidChrome: false,
22017        desktop: false,
22018        iphone: false,
22019        ipod: false,
22020        ipad: false,
22021        edge: false,
22022        ie: false,
22023        firefox: false,
22024        macos: false,
22025        windows: false,
22026        cordova: !!(win.cordova || win.phonegap),
22027        phonegap: !!(win.cordova || win.phonegap),
22028        electron: false,
22029      };
22030  
22031      var screenWidth = win.screen.width;
22032      var screenHeight = win.screen.height;
22033  
22034      var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/); // eslint-disable-line
22035      var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
22036      var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
22037      var iphone = !ipad && ua.match(/(iPhone\sOS|iOS)\s([\d_]+)/);
22038      var ie = ua.indexOf('MSIE ') >= 0 || ua.indexOf('Trident/') >= 0;
22039      var edge = ua.indexOf('Edge/') >= 0;
22040      var firefox = ua.indexOf('Gecko/') >= 0 && ua.indexOf('Firefox/') >= 0;
22041      var windows = platform === 'Win32';
22042      var electron = ua.toLowerCase().indexOf('electron') >= 0;
22043      var macos = platform === 'MacIntel';
22044  
22045      // iPadOs 13 fix
22046      if (!ipad
22047        && macos
22048        && Support.touch
22049        && (
22050          (screenWidth === 1024 && screenHeight === 1366) // Pro 12.9
22051          || (screenWidth === 834 && screenHeight === 1194) // Pro 11
22052          || (screenWidth === 834 && screenHeight === 1112) // Pro 10.5
22053          || (screenWidth === 768 && screenHeight === 1024) // other
22054        )
22055      ) {
22056        ipad = ua.match(/(Version)\/([\d.]+)/);
22057        macos = false;
22058      }
22059  
22060      device.ie = ie;
22061      device.edge = edge;
22062      device.firefox = firefox;
22063  
22064      // Android
22065      if (android && !windows) {
22066        device.os = 'android';
22067        device.osVersion = android[2];
22068        device.android = true;
22069        device.androidChrome = ua.toLowerCase().indexOf('chrome') >= 0;
22070      }
22071      if (ipad || iphone || ipod) {
22072        device.os = 'ios';
22073        device.ios = true;
22074      }
22075      // iOS
22076      if (iphone && !ipod) {
22077        device.osVersion = iphone[2].replace(/_/g, '.');
22078        device.iphone = true;
22079      }
22080      if (ipad) {
22081        device.osVersion = ipad[2].replace(/_/g, '.');
22082        device.ipad = true;
22083      }
22084      if (ipod) {
22085        device.osVersion = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
22086        device.ipod = true;
22087      }
22088      // iOS 8+ changed UA
22089      if (device.ios && device.osVersion && ua.indexOf('Version/') >= 0) {
22090        if (device.osVersion.split('.')[0] === '10') {
22091          device.osVersion = ua.toLowerCase().split('version/')[1].split(' ')[0];
22092        }
22093      }
22094  
22095      // Webview
22096      device.webView = !!((iphone || ipad || ipod) && (ua.match(/.*AppleWebKit(?!.*Safari)/i) || win.navigator.standalone))
22097        || (win.matchMedia && win.matchMedia('(display-mode: standalone)').matches);
22098      device.webview = device.webView;
22099      device.standalone = device.webView;
22100  
22101      // Desktop
22102      device.desktop = !(device.ios || device.android) || electron;
22103      if (device.desktop) {
22104        device.electron = electron;
22105        device.macos = macos;
22106        device.windows = windows;
22107        if (device.macos) {
22108          device.os = 'macos';
22109        }
22110        if (device.windows) {
22111          device.os = 'windows';
22112        }
22113      }
22114  
22115      // Pixel Ratio
22116      device.pixelRatio = win.devicePixelRatio || 1;
22117  
22118      // Export object
22119      return device;
22120    }());
22121  
22122    function onTouchStart (event) {
22123      var swiper = this;
22124      var data = swiper.touchEventsData;
22125      var params = swiper.params;
22126      var touches = swiper.touches;
22127  
22128      if (swiper.animating && params.preventInteractionOnTransition) {
22129        return;
22130      }
22131      var e = event;
22132      if (e.originalEvent) { e = e.originalEvent; }
22133      var $targetEl = $(e.target);
22134  
22135      if (params.touchEventsTarget === 'wrapper') {
22136        if (!$targetEl.closest(swiper.wrapperEl).length) { return; }
22137      }
22138      data.isTouchEvent = e.type === 'touchstart';
22139      if (!data.isTouchEvent && 'which' in e && e.which === 3) { return; }
22140      if (!data.isTouchEvent && 'button' in e && e.button > 0) { return; }
22141      if (data.isTouched && data.isMoved) { return; }
22142      if (params.noSwiping && $targetEl.closest(params.noSwipingSelector ? params.noSwipingSelector : ("." + (params.noSwipingClass)))[0]) {
22143        swiper.allowClick = true;
22144        return;
22145      }
22146      if (params.swipeHandler) {
22147        if (!$targetEl.closest(params.swipeHandler)[0]) { return; }
22148      }
22149  
22150      touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
22151      touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
22152      var startX = touches.currentX;
22153      var startY = touches.currentY;
22154  
22155      // Do NOT start if iOS edge swipe is detected. Otherwise iOS app (UIWebView) cannot swipe-to-go-back anymore
22156  
22157      var edgeSwipeDetection = params.edgeSwipeDetection || params.iOSEdgeSwipeDetection;
22158      var edgeSwipeThreshold = params.edgeSwipeThreshold || params.iOSEdgeSwipeThreshold;
22159      if (
22160        edgeSwipeDetection
22161        && ((startX <= edgeSwipeThreshold)
22162        || (startX >= win.screen.width - edgeSwipeThreshold))
22163      ) {
22164        return;
22165      }
22166  
22167      Utils.extend(data, {
22168        isTouched: true,
22169        isMoved: false,
22170        allowTouchCallbacks: true,
22171        isScrolling: undefined,
22172        startMoving: undefined,
22173      });
22174  
22175      touches.startX = startX;
22176      touches.startY = startY;
22177      data.touchStartTime = Utils.now();
22178      swiper.allowClick = true;
22179      swiper.updateSize();
22180      swiper.swipeDirection = undefined;
22181      if (params.threshold > 0) { data.allowThresholdMove = false; }
22182      if (e.type !== 'touchstart') {
22183        var preventDefault = true;
22184        if ($targetEl.is(data.formElements)) { preventDefault = false; }
22185        if (
22186          doc.activeElement
22187          && $(doc.activeElement).is(data.formElements)
22188          && doc.activeElement !== $targetEl[0]
22189        ) {
22190          doc.activeElement.blur();
22191        }
22192  
22193        var shouldPreventDefault = preventDefault && swiper.allowTouchMove && params.touchStartPreventDefault;
22194        if (params.touchStartForcePreventDefault || shouldPreventDefault) {
22195          e.preventDefault();
22196        }
22197      }
22198      swiper.emit('touchStart', e);
22199    }
22200  
22201    function onTouchMove (event) {
22202      var swiper = this;
22203      var data = swiper.touchEventsData;
22204      var params = swiper.params;
22205      var touches = swiper.touches;
22206      var rtl = swiper.rtlTranslate;
22207      var e = event;
22208      if (e.originalEvent) { e = e.originalEvent; }
22209      if (!data.isTouched) {
22210        if (data.startMoving && data.isScrolling) {
22211          swiper.emit('touchMoveOpposite', e);
22212        }
22213        return;
22214      }
22215      if (data.isTouchEvent && e.type === 'mousemove') { return; }
22216      var targetTouch = e.type === 'touchmove' && e.targetTouches && (e.targetTouches[0] || e.changedTouches[0]);
22217      var pageX = e.type === 'touchmove' ? targetTouch.pageX : e.pageX;
22218      var pageY = e.type === 'touchmove' ? targetTouch.pageY : e.pageY;
22219      if (e.preventedByNestedSwiper) {
22220        touches.startX = pageX;
22221        touches.startY = pageY;
22222        return;
22223      }
22224      if (!swiper.allowTouchMove) {
22225        // isMoved = true;
22226        swiper.allowClick = false;
22227        if (data.isTouched) {
22228          Utils.extend(touches, {
22229            startX: pageX,
22230            startY: pageY,
22231            currentX: pageX,
22232            currentY: pageY,
22233          });
22234          data.touchStartTime = Utils.now();
22235        }
22236        return;
22237      }
22238      if (data.isTouchEvent && params.touchReleaseOnEdges && !params.loop) {
22239        if (swiper.isVertical()) {
22240          // Vertical
22241          if (
22242            (pageY < touches.startY && swiper.translate <= swiper.maxTranslate())
22243            || (pageY > touches.startY && swiper.translate >= swiper.minTranslate())
22244          ) {
22245            data.isTouched = false;
22246            data.isMoved = false;
22247            return;
22248          }
22249        } else if (
22250          (pageX < touches.startX && swiper.translate <= swiper.maxTranslate())
22251          || (pageX > touches.startX && swiper.translate >= swiper.minTranslate())
22252        ) {
22253          return;
22254        }
22255      }
22256      if (data.isTouchEvent && doc.activeElement) {
22257        if (e.target === doc.activeElement && $(e.target).is(data.formElements)) {
22258          data.isMoved = true;
22259          swiper.allowClick = false;
22260          return;
22261        }
22262      }
22263      if (data.allowTouchCallbacks) {
22264        swiper.emit('touchMove', e);
22265      }
22266      if (e.targetTouches && e.targetTouches.length > 1) { return; }
22267  
22268      touches.currentX = pageX;
22269      touches.currentY = pageY;
22270  
22271      var diffX = touches.currentX - touches.startX;
22272      var diffY = touches.currentY - touches.startY;
22273      if (swiper.params.threshold && Math.sqrt((Math.pow( diffX, 2 )) + (Math.pow( diffY, 2 ))) < swiper.params.threshold) { return; }
22274  
22275      if (typeof data.isScrolling === 'undefined') {
22276        var touchAngle;
22277        if ((swiper.isHorizontal() && touches.currentY === touches.startY) || (swiper.isVertical() && touches.currentX === touches.startX)) {
22278          data.isScrolling = false;
22279        } else {
22280          // eslint-disable-next-line
22281          if ((diffX * diffX) + (diffY * diffY) >= 25) {
22282            touchAngle = (Math.atan2(Math.abs(diffY), Math.abs(diffX)) * 180) / Math.PI;
22283            data.isScrolling = swiper.isHorizontal() ? touchAngle > params.touchAngle : (90 - touchAngle > params.touchAngle);
22284          }
22285        }
22286      }
22287      if (data.isScrolling) {
22288        swiper.emit('touchMoveOpposite', e);
22289      }
22290      if (typeof data.startMoving === 'undefined') {
22291        if (touches.currentX !== touches.startX || touches.currentY !== touches.startY) {
22292          data.startMoving = true;
22293        }
22294      }
22295      if (data.isScrolling) {
22296        data.isTouched = false;
22297        return;
22298      }
22299      if (!data.startMoving) {
22300        return;
22301      }
22302      swiper.allowClick = false;
22303      if (!params.cssMode) {
22304        e.preventDefault();
22305      }
22306      if (params.touchMoveStopPropagation && !params.nested) {
22307        e.stopPropagation();
22308      }
22309  
22310      if (!data.isMoved) {
22311        if (params.loop) {
22312          swiper.loopFix();
22313        }
22314        data.startTranslate = swiper.getTranslate();
22315        swiper.setTransition(0);
22316        if (swiper.animating) {
22317          swiper.$wrapperEl.trigger('webkitTransitionEnd transitionend');
22318        }
22319        data.allowMomentumBounce = false;
22320        // Grab Cursor
22321        if (params.grabCursor && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
22322          swiper.setGrabCursor(true);
22323        }
22324        swiper.emit('sliderFirstMove', e);
22325      }
22326      swiper.emit('sliderMove', e);
22327      data.isMoved = true;
22328  
22329      var diff = swiper.isHorizontal() ? diffX : diffY;
22330      touches.diff = diff;
22331  
22332      diff *= params.touchRatio;
22333      if (rtl) { diff = -diff; }
22334  
22335      swiper.swipeDirection = diff > 0 ? 'prev' : 'next';
22336      data.currentTranslate = diff + data.startTranslate;
22337  
22338      var disableParentSwiper = true;
22339      var resistanceRatio = params.resistanceRatio;
22340      if (params.touchReleaseOnEdges) {
22341        resistanceRatio = 0;
22342      }
22343      if ((diff > 0 && data.currentTranslate > swiper.minTranslate())) {
22344        disableParentSwiper = false;
22345        if (params.resistance) { data.currentTranslate = (swiper.minTranslate() - 1) + (Math.pow( (-swiper.minTranslate() + data.startTranslate + diff), resistanceRatio )); }
22346      } else if (diff < 0 && data.currentTranslate < swiper.maxTranslate()) {
22347        disableParentSwiper = false;
22348        if (params.resistance) { data.currentTranslate = (swiper.maxTranslate() + 1) - (Math.pow( (swiper.maxTranslate() - data.startTranslate - diff), resistanceRatio )); }
22349      }
22350  
22351      if (disableParentSwiper) {
22352        e.preventedByNestedSwiper = true;
22353      }
22354  
22355      // Directions locks
22356      if (!swiper.allowSlideNext && swiper.swipeDirection === 'next' && data.currentTranslate < data.startTranslate) {
22357        data.currentTranslate = data.startTranslate;
22358      }
22359      if (!swiper.allowSlidePrev && swiper.swipeDirection === 'prev' && data.currentTranslate > data.startTranslate) {
22360        data.currentTranslate = data.startTranslate;
22361      }
22362  
22363  
22364      // Threshold
22365      if (params.threshold > 0) {
22366        if (Math.abs(diff) > params.threshold || data.allowThresholdMove) {
22367          if (!data.allowThresholdMove) {
22368            data.allowThresholdMove = true;
22369            touches.startX = touches.currentX;
22370            touches.startY = touches.currentY;
22371            data.currentTranslate = data.startTranslate;
22372            touches.diff = swiper.isHorizontal() ? touches.currentX - touches.startX : touches.currentY - touches.startY;
22373            return;
22374          }
22375        } else {
22376          data.currentTranslate = data.startTranslate;
22377          return;
22378        }
22379      }
22380  
22381      if (!params.followFinger || params.cssMode) { return; }
22382  
22383      // Update active index in free mode
22384      if (params.freeMode || params.watchSlidesProgress || params.watchSlidesVisibility) {
22385        swiper.updateActiveIndex();
22386        swiper.updateSlidesClasses();
22387      }
22388      if (params.freeMode) {
22389        // Velocity
22390        if (data.velocities.length === 0) {
22391          data.velocities.push({
22392            position: touches[swiper.isHorizontal() ? 'startX' : 'startY'],
22393            time: data.touchStartTime,
22394          });
22395        }
22396        data.velocities.push({
22397          position: touches[swiper.isHorizontal() ? 'currentX' : 'currentY'],
22398          time: Utils.now(),
22399        });
22400      }
22401      // Update progress
22402      swiper.updateProgress(data.currentTranslate);
22403      // Update translate
22404      swiper.setTranslate(data.currentTranslate);
22405    }
22406  
22407    function onTouchEnd (event) {
22408      var swiper = this;
22409      var data = swiper.touchEventsData;
22410  
22411      var params = swiper.params;
22412      var touches = swiper.touches;
22413      var rtl = swiper.rtlTranslate;
22414      var $wrapperEl = swiper.$wrapperEl;
22415      var slidesGrid = swiper.slidesGrid;
22416      var snapGrid = swiper.snapGrid;
22417      var e = event;
22418      if (e.originalEvent) { e = e.originalEvent; }
22419      if (data.allowTouchCallbacks) {
22420        swiper.emit('touchEnd', e);
22421      }
22422      data.allowTouchCallbacks = false;
22423      if (!data.isTouched) {
22424        if (data.isMoved && params.grabCursor) {
22425          swiper.setGrabCursor(false);
22426        }
22427        data.isMoved = false;
22428        data.startMoving = false;
22429        return;
22430      }
22431      // Return Grab Cursor
22432      if (params.grabCursor && data.isMoved && data.isTouched && (swiper.allowSlideNext === true || swiper.allowSlidePrev === true)) {
22433        swiper.setGrabCursor(false);
22434      }
22435  
22436      // Time diff
22437      var touchEndTime = Utils.now();
22438      var timeDiff = touchEndTime - data.touchStartTime;
22439  
22440      // Tap, doubleTap, Click
22441      if (swiper.allowClick) {
22442        swiper.updateClickedSlide(e);
22443        swiper.emit('tap click', e);
22444        if (timeDiff < 300 && (touchEndTime - data.lastClickTime) < 300) {
22445          swiper.emit('doubleTap doubleClick', e);
22446        }
22447      }
22448  
22449      data.lastClickTime = Utils.now();
22450      Utils.nextTick(function () {
22451        if (!swiper.destroyed) { swiper.allowClick = true; }
22452      });
22453  
22454      if (!data.isTouched || !data.isMoved || !swiper.swipeDirection || touches.diff === 0 || data.currentTranslate === data.startTranslate) {
22455        data.isTouched = false;
22456        data.isMoved = false;
22457        data.startMoving = false;
22458        return;
22459      }
22460      data.isTouched = false;
22461      data.isMoved = false;
22462      data.startMoving = false;
22463  
22464      var currentPos;
22465      if (params.followFinger) {
22466        currentPos = rtl ? swiper.translate : -swiper.translate;
22467      } else {
22468        currentPos = -data.currentTranslate;
22469      }
22470  
22471      if (params.cssMode) {
22472        return;
22473      }
22474  
22475      if (params.freeMode) {
22476        if (currentPos < -swiper.minTranslate()) {
22477          swiper.slideTo(swiper.activeIndex);
22478          return;
22479        }
22480        if (currentPos > -swiper.maxTranslate()) {
22481          if (swiper.slides.length < snapGrid.length) {
22482            swiper.slideTo(snapGrid.length - 1);
22483          } else {
22484            swiper.slideTo(swiper.slides.length - 1);
22485          }
22486          return;
22487        }
22488  
22489        if (params.freeModeMomentum) {
22490          if (data.velocities.length > 1) {
22491            var lastMoveEvent = data.velocities.pop();
22492            var velocityEvent = data.velocities.pop();
22493  
22494            var distance = lastMoveEvent.position - velocityEvent.position;
22495            var time = lastMoveEvent.time - velocityEvent.time;
22496            swiper.velocity = distance / time;
22497            swiper.velocity /= 2;
22498            if (Math.abs(swiper.velocity) < params.freeModeMinimumVelocity) {
22499              swiper.velocity = 0;
22500            }
22501            // this implies that the user stopped moving a finger then released.
22502            // There would be no events with distance zero, so the last event is stale.
22503            if (time > 150 || (Utils.now() - lastMoveEvent.time) > 300) {
22504              swiper.velocity = 0;
22505            }
22506          } else {
22507            swiper.velocity = 0;
22508          }
22509          swiper.velocity *= params.freeModeMomentumVelocityRatio;
22510  
22511          data.velocities.length = 0;
22512          var momentumDuration = 1000 * params.freeModeMomentumRatio;
22513          var momentumDistance = swiper.velocity * momentumDuration;
22514  
22515          var newPosition = swiper.translate + momentumDistance;
22516          if (rtl) { newPosition = -newPosition; }
22517  
22518          var doBounce = false;
22519          var afterBouncePosition;
22520          var bounceAmount = Math.abs(swiper.velocity) * 20 * params.freeModeMomentumBounceRatio;
22521          var needsLoopFix;
22522          if (newPosition < swiper.maxTranslate()) {
22523            if (params.freeModeMomentumBounce) {
22524              if (newPosition + swiper.maxTranslate() < -bounceAmount) {
22525                newPosition = swiper.maxTranslate() - bounceAmount;
22526              }
22527              afterBouncePosition = swiper.maxTranslate();
22528              doBounce = true;
22529              data.allowMomentumBounce = true;
22530            } else {
22531              newPosition = swiper.maxTranslate();
22532            }
22533            if (params.loop && params.centeredSlides) { needsLoopFix = true; }
22534          } else if (newPosition > swiper.minTranslate()) {
22535            if (params.freeModeMomentumBounce) {
22536              if (newPosition - swiper.minTranslate() > bounceAmount) {
22537                newPosition = swiper.minTranslate() + bounceAmount;
22538              }
22539              afterBouncePosition = swiper.minTranslate();
22540              doBounce = true;
22541              data.allowMomentumBounce = true;
22542            } else {
22543              newPosition = swiper.minTranslate();
22544            }
22545            if (params.loop && params.centeredSlides) { needsLoopFix = true; }
22546          } else if (params.freeModeSticky) {
22547            var nextSlide;
22548            for (var j = 0; j < snapGrid.length; j += 1) {
22549              if (snapGrid[j] > -newPosition) {
22550                nextSlide = j;
22551                break;
22552              }
22553            }
22554  
22555            if (Math.abs(snapGrid[nextSlide] - newPosition) < Math.abs(snapGrid[nextSlide - 1] - newPosition) || swiper.swipeDirection === 'next') {
22556              newPosition = snapGrid[nextSlide];
22557            } else {
22558              newPosition = snapGrid[nextSlide - 1];
22559            }
22560            newPosition = -newPosition;
22561          }
22562          if (needsLoopFix) {
22563            swiper.once('transitionEnd', function () {
22564              swiper.loopFix();
22565            });
22566          }
22567          // Fix duration
22568          if (swiper.velocity !== 0) {
22569            if (rtl) {
22570              momentumDuration = Math.abs((-newPosition - swiper.translate) / swiper.velocity);
22571            } else {
22572              momentumDuration = Math.abs((newPosition - swiper.translate) / swiper.velocity);
22573            }
22574            if (params.freeModeSticky) {
22575              // If freeModeSticky is active and the user ends a swipe with a slow-velocity
22576              // event, then durations can be 20+ seconds to slide one (or zero!) slides.
22577              // It's easy to see this when simulating touch with mouse events. To fix this,
22578              // limit single-slide swipes to the default slide duration. This also has the
22579              // nice side effect of matching slide speed if the user stopped moving before
22580              // lifting finger or mouse vs. moving slowly before lifting the finger/mouse.
22581              // For faster swipes, also apply limits (albeit higher ones).
22582              var moveDistance = Math.abs((rtl ? -newPosition : newPosition) - swiper.translate);
22583              var currentSlideSize = swiper.slidesSizesGrid[swiper.activeIndex];
22584              if (moveDistance < currentSlideSize) {
22585                momentumDuration = params.speed;
22586              } else if (moveDistance < 2 * currentSlideSize) {
22587                momentumDuration = params.speed * 1.5;
22588              } else {
22589                momentumDuration = params.speed * 2.5;
22590              }
22591            }
22592          } else if (params.freeModeSticky) {
22593            swiper.slideToClosest();
22594            return;
22595          }
22596  
22597          if (params.freeModeMomentumBounce && doBounce) {
22598            swiper.updateProgress(afterBouncePosition);
22599            swiper.setTransition(momentumDuration);
22600            swiper.setTranslate(newPosition);
22601            swiper.transitionStart(true, swiper.swipeDirection);
22602            swiper.animating = true;
22603            $wrapperEl.transitionEnd(function () {
22604              if (!swiper || swiper.destroyed || !data.allowMomentumBounce) { return; }
22605              swiper.emit('momentumBounce');
22606  
22607              swiper.setTransition(params.speed);
22608              swiper.setTranslate(afterBouncePosition);
22609              $wrapperEl.transitionEnd(function () {
22610                if (!swiper || swiper.destroyed) { return; }
22611                swiper.transitionEnd();
22612              });
22613            });
22614          } else if (swiper.velocity) {
22615            swiper.updateProgress(newPosition);
22616            swiper.setTransition(momentumDuration);
22617            swiper.setTranslate(newPosition);
22618            swiper.transitionStart(true, swiper.swipeDirection);
22619            if (!swiper.animating) {
22620              swiper.animating = true;
22621              $wrapperEl.transitionEnd(function () {
22622                if (!swiper || swiper.destroyed) { return; }
22623                swiper.transitionEnd();
22624              });
22625            }
22626          } else {
22627            swiper.updateProgress(newPosition);
22628          }
22629  
22630          swiper.updateActiveIndex();
22631          swiper.updateSlidesClasses();
22632        } else if (params.freeModeSticky) {
22633          swiper.slideToClosest();
22634          return;
22635        }
22636  
22637        if (!params.freeModeMomentum || timeDiff >= params.longSwipesMs) {
22638          swiper.updateProgress();
22639          swiper.updateActiveIndex();
22640          swiper.updateSlidesClasses();
22641        }
22642        return;
22643      }
22644  
22645      // Find current slide
22646      var stopIndex = 0;
22647      var groupSize = swiper.slidesSizesGrid[0];
22648      for (var i = 0; i < slidesGrid.length; i += params.slidesPerGroup) {
22649        if (typeof slidesGrid[i + params.slidesPerGroup] !== 'undefined') {
22650          if (currentPos >= slidesGrid[i] && currentPos < slidesGrid[i + params.slidesPerGroup]) {
22651            stopIndex = i;
22652            groupSize = slidesGrid[i + params.slidesPerGroup] - slidesGrid[i];
22653          }
22654        } else if (currentPos >= slidesGrid[i]) {
22655          stopIndex = i;
22656          groupSize = slidesGrid[slidesGrid.length - 1] - slidesGrid[slidesGrid.length - 2];
22657        }
22658      }
22659  
22660      // Find current slide size
22661      var ratio = (currentPos - slidesGrid[stopIndex]) / groupSize;
22662  
22663      if (timeDiff > params.longSwipesMs) {
22664        // Long touches
22665        if (!params.longSwipes) {
22666          swiper.slideTo(swiper.activeIndex);
22667          return;
22668        }
22669        if (swiper.swipeDirection === 'next') {
22670          if (ratio >= params.longSwipesRatio) { swiper.slideTo(stopIndex + params.slidesPerGroup); }
22671          else { swiper.slideTo(stopIndex); }
22672        }
22673        if (swiper.swipeDirection === 'prev') {
22674          if (ratio > (1 - params.longSwipesRatio)) { swiper.slideTo(stopIndex + params.slidesPerGroup); }
22675          else { swiper.slideTo(stopIndex); }
22676        }
22677      } else {
22678        // Short swipes
22679        if (!params.shortSwipes) {
22680          swiper.slideTo(swiper.activeIndex);
22681          return;
22682        }
22683        var isNavButtonTarget = swiper.navigation && (e.target === swiper.navigation.nextEl || e.target === swiper.navigation.prevEl);
22684        if (!isNavButtonTarget) {
22685          if (swiper.swipeDirection === 'next') {
22686            swiper.slideTo(stopIndex + params.slidesPerGroup);
22687          }
22688          if (swiper.swipeDirection === 'prev') {
22689            swiper.slideTo(stopIndex);
22690          }
22691        } else if (e.target === swiper.navigation.nextEl) {
22692          swiper.slideTo(stopIndex + params.slidesPerGroup);
22693        } else {
22694          swiper.slideTo(stopIndex);
22695        }
22696      }
22697    }
22698  
22699    function onResize () {
22700      var swiper = this;
22701  
22702      var params = swiper.params;
22703      var el = swiper.el;
22704  
22705      if (el && el.offsetWidth === 0) { return; }
22706  
22707      // Breakpoints
22708      if (params.breakpoints) {
22709        swiper.setBreakpoint();
22710      }
22711  
22712      // Save locks
22713      var allowSlideNext = swiper.allowSlideNext;
22714      var allowSlidePrev = swiper.allowSlidePrev;
22715      var snapGrid = swiper.snapGrid;
22716  
22717      // Disable locks on resize
22718      swiper.allowSlideNext = true;
22719      swiper.allowSlidePrev = true;
22720  
22721      swiper.updateSize();
22722      swiper.updateSlides();
22723  
22724      swiper.updateSlidesClasses();
22725      if ((params.slidesPerView === 'auto' || params.slidesPerView > 1) && swiper.isEnd && !swiper.params.centeredSlides) {
22726        swiper.slideTo(swiper.slides.length - 1, 0, false, true);
22727      } else {
22728        swiper.slideTo(swiper.activeIndex, 0, false, true);
22729      }
22730  
22731      if (swiper.autoplay && swiper.autoplay.running && swiper.autoplay.paused) {
22732        swiper.autoplay.run();
22733      }
22734      // Return locks after resize
22735      swiper.allowSlidePrev = allowSlidePrev;
22736      swiper.allowSlideNext = allowSlideNext;
22737  
22738      if (swiper.params.watchOverflow && snapGrid !== swiper.snapGrid) {
22739        swiper.checkOverflow();
22740      }
22741    }
22742  
22743    function onClick (e) {
22744      var swiper = this;
22745      if (!swiper.allowClick) {
22746        if (swiper.params.preventClicks) { e.preventDefault(); }
22747        if (swiper.params.preventClicksPropagation && swiper.animating) {
22748          e.stopPropagation();
22749          e.stopImmediatePropagation();
22750        }
22751      }
22752    }
22753  
22754    function onScroll () {
22755      var swiper = this;
22756      var wrapperEl = swiper.wrapperEl;
22757      swiper.previousTranslate = swiper.translate;
22758      swiper.translate = swiper.isHorizontal() ? -wrapperEl.scrollLeft : -wrapperEl.scrollTop;
22759      // eslint-disable-next-line
22760      if (swiper.translate === -0) { swiper.translate = 0; }
22761  
22762      swiper.updateActiveIndex();
22763      swiper.updateSlidesClasses();
22764  
22765      var newProgress;
22766      var translatesDiff = swiper.maxTranslate() - swiper.minTranslate();
22767      if (translatesDiff === 0) {
22768        newProgress = 0;
22769      } else {
22770        newProgress = (swiper.translate - swiper.minTranslate()) / (translatesDiff);
22771      }
22772      if (newProgress !== swiper.progress) {
22773        swiper.updateProgress(swiper.translate);
22774      }
22775  
22776      swiper.emit('setTranslate', swiper.translate, false);
22777    }
22778  
22779    var dummyEventAttached = false;
22780    function dummyEventListener() {}
22781  
22782    function attachEvents() {
22783      var swiper = this;
22784      var params = swiper.params;
22785      var touchEvents = swiper.touchEvents;
22786      var el = swiper.el;
22787      var wrapperEl = swiper.wrapperEl;
22788  
22789      swiper.onTouchStart = onTouchStart.bind(swiper);
22790      swiper.onTouchMove = onTouchMove.bind(swiper);
22791      swiper.onTouchEnd = onTouchEnd.bind(swiper);
22792      if (params.cssMode) {
22793        swiper.onScroll = onScroll.bind(swiper);
22794      }
22795  
22796      swiper.onClick = onClick.bind(swiper);
22797  
22798      var capture = !!params.nested;
22799  
22800      // Touch Events
22801      if (!Support.touch && Support.pointerEvents) {
22802        el.addEventListener(touchEvents.start, swiper.onTouchStart, false);
22803        doc.addEventListener(touchEvents.move, swiper.onTouchMove, capture);
22804        doc.addEventListener(touchEvents.end, swiper.onTouchEnd, false);
22805      } else {
22806        if (Support.touch) {
22807          var passiveListener = touchEvents.start === 'touchstart' && Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
22808          el.addEventListener(touchEvents.start, swiper.onTouchStart, passiveListener);
22809          el.addEventListener(touchEvents.move, swiper.onTouchMove, Support.passiveListener ? { passive: false, capture: capture } : capture);
22810          el.addEventListener(touchEvents.end, swiper.onTouchEnd, passiveListener);
22811          if (touchEvents.cancel) {
22812            el.addEventListener(touchEvents.cancel, swiper.onTouchEnd, passiveListener);
22813          }
22814          if (!dummyEventAttached) {
22815            doc.addEventListener('touchstart', dummyEventListener);
22816            dummyEventAttached = true;
22817          }
22818        }
22819        if ((params.simulateTouch && !Device.ios && !Device.android) || (params.simulateTouch && !Support.touch && Device.ios)) {
22820          el.addEventListener('mousedown', swiper.onTouchStart, false);
22821          doc.addEventListener('mousemove', swiper.onTouchMove, capture);
22822          doc.addEventListener('mouseup', swiper.onTouchEnd, false);
22823        }
22824      }
22825      // Prevent Links Clicks
22826      if (params.preventClicks || params.preventClicksPropagation) {
22827        el.addEventListener('click', swiper.onClick, true);
22828      }
22829      if (params.cssMode) {
22830        wrapperEl.addEventListener('scroll', swiper.onScroll);
22831      }
22832  
22833      // Resize handler
22834      swiper.on((Device.ios || Device.android ? 'resize orientationchange observerUpdate' : 'resize observerUpdate'), onResize, true);
22835    }
22836  
22837    function detachEvents() {
22838      var swiper = this;
22839  
22840      var params = swiper.params;
22841      var touchEvents = swiper.touchEvents;
22842      var el = swiper.el;
22843      var wrapperEl = swiper.wrapperEl;
22844  
22845      var capture = !!params.nested;
22846  
22847      // Touch Events
22848      if (!Support.touch && Support.pointerEvents) {
22849        el.removeEventListener(touchEvents.start, swiper.onTouchStart, false);
22850        doc.removeEventListener(touchEvents.move, swiper.onTouchMove, capture);
22851        doc.removeEventListener(touchEvents.end, swiper.onTouchEnd, false);
22852      } else {
22853        if (Support.touch) {
22854          var passiveListener = touchEvents.start === 'onTouchStart' && Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
22855          el.removeEventListener(touchEvents.start, swiper.onTouchStart, passiveListener);
22856          el.removeEventListener(touchEvents.move, swiper.onTouchMove, capture);
22857          el.removeEventListener(touchEvents.end, swiper.onTouchEnd, passiveListener);
22858          if (touchEvents.cancel) {
22859            el.removeEventListener(touchEvents.cancel, swiper.onTouchEnd, passiveListener);
22860          }
22861        }
22862        if ((params.simulateTouch && !Device.ios && !Device.android) || (params.simulateTouch && !Support.touch && Device.ios)) {
22863          el.removeEventListener('mousedown', swiper.onTouchStart, false);
22864          doc.removeEventListener('mousemove', swiper.onTouchMove, capture);
22865          doc.removeEventListener('mouseup', swiper.onTouchEnd, false);
22866        }
22867      }
22868      // Prevent Links Clicks
22869      if (params.preventClicks || params.preventClicksPropagation) {
22870        el.removeEventListener('click', swiper.onClick, true);
22871      }
22872  
22873      if (params.cssMode) {
22874        wrapperEl.removeEventListener('scroll', swiper.onScroll);
22875      }
22876  
22877      // Resize handler
22878      swiper.off((Device.ios || Device.android ? 'resize orientationchange observerUpdate' : 'resize observerUpdate'), onResize);
22879    }
22880  
22881    var events = {
22882      attachEvents: attachEvents,
22883      detachEvents: detachEvents,
22884    };
22885  
22886    function setBreakpoint () {
22887      var swiper = this;
22888      var activeIndex = swiper.activeIndex;
22889      var initialized = swiper.initialized;
22890      var loopedSlides = swiper.loopedSlides; if ( loopedSlides === void 0 ) loopedSlides = 0;
22891      var params = swiper.params;
22892      var $el = swiper.$el;
22893      var breakpoints = params.breakpoints;
22894      if (!breakpoints || (breakpoints && Object.keys(breakpoints).length === 0)) { return; }
22895  
22896      // Get breakpoint for window width and update parameters
22897      var breakpoint = swiper.getBreakpoint(breakpoints);
22898  
22899      if (breakpoint && swiper.currentBreakpoint !== breakpoint) {
22900        var breakpointOnlyParams = breakpoint in breakpoints ? breakpoints[breakpoint] : undefined;
22901        if (breakpointOnlyParams) {
22902          ['slidesPerView', 'spaceBetween', 'slidesPerGroup', 'slidesPerColumn'].forEach(function (param) {
22903            var paramValue = breakpointOnlyParams[param];
22904            if (typeof paramValue === 'undefined') { return; }
22905            if (param === 'slidesPerView' && (paramValue === 'AUTO' || paramValue === 'auto')) {
22906              breakpointOnlyParams[param] = 'auto';
22907            } else if (param === 'slidesPerView') {
22908              breakpointOnlyParams[param] = parseFloat(paramValue);
22909            } else {
22910              breakpointOnlyParams[param] = parseInt(paramValue, 10);
22911            }
22912          });
22913        }
22914  
22915        var breakpointParams = breakpointOnlyParams || swiper.originalParams;
22916        var wasMultiRow = params.slidesPerColumn > 1;
22917        var isMultiRow = breakpointParams.slidesPerColumn > 1;
22918        if (wasMultiRow && !isMultiRow) {
22919          $el.removeClass(((params.containerModifierClass) + "multirow " + (params.containerModifierClass) + "multirow-column"));
22920        } else if (!wasMultiRow && isMultiRow) {
22921          $el.addClass(((params.containerModifierClass) + "multirow"));
22922          if (breakpointParams.slidesPerColumnFill === 'column') {
22923            $el.addClass(((params.containerModifierClass) + "multirow-column"));
22924          }
22925        }
22926  
22927        var directionChanged = breakpointParams.direction && breakpointParams.direction !== params.direction;
22928        var needsReLoop = params.loop && (breakpointParams.slidesPerView !== params.slidesPerView || directionChanged);
22929  
22930        if (directionChanged && initialized) {
22931          swiper.changeDirection();
22932        }
22933  
22934        Utils.extend(swiper.params, breakpointParams);
22935  
22936        Utils.extend(swiper, {
22937          allowTouchMove: swiper.params.allowTouchMove,
22938          allowSlideNext: swiper.params.allowSlideNext,
22939          allowSlidePrev: swiper.params.allowSlidePrev,
22940        });
22941  
22942        swiper.currentBreakpoint = breakpoint;
22943  
22944        if (needsReLoop && initialized) {
22945          swiper.loopDestroy();
22946          swiper.loopCreate();
22947          swiper.updateSlides();
22948          swiper.slideTo((activeIndex - loopedSlides) + swiper.loopedSlides, 0, false);
22949        }
22950  
22951        swiper.emit('breakpoint', breakpointParams);
22952      }
22953    }
22954  
22955    function getBreakpoint (breakpoints) {
22956      // Get breakpoint for window width
22957      if (!breakpoints) { return undefined; }
22958      var breakpoint = false;
22959      var points = [];
22960      Object.keys(breakpoints).forEach(function (point) {
22961        points.push(point);
22962      });
22963      points.sort(function (a, b) { return parseInt(a, 10) - parseInt(b, 10); });
22964      for (var i = 0; i < points.length; i += 1) {
22965        var point = points[i];
22966        if (point <= win.innerWidth) {
22967          breakpoint = point;
22968        }
22969      }
22970      return breakpoint || 'max';
22971    }
22972  
22973    var breakpoints = { setBreakpoint: setBreakpoint, getBreakpoint: getBreakpoint };
22974  
22975    function addClasses () {
22976      var swiper = this;
22977      var classNames = swiper.classNames;
22978      var params = swiper.params;
22979      var rtl = swiper.rtl;
22980      var $el = swiper.$el;
22981      var suffixes = [];
22982  
22983      suffixes.push('initialized');
22984      suffixes.push(params.direction);
22985  
22986      if (params.freeMode) {
22987        suffixes.push('free-mode');
22988      }
22989      if (params.autoHeight) {
22990        suffixes.push('autoheight');
22991      }
22992      if (rtl) {
22993        suffixes.push('rtl');
22994      }
22995      if (params.slidesPerColumn > 1) {
22996        suffixes.push('multirow');
22997        if (params.slidesPerColumnFill === 'column') {
22998          suffixes.push('multirow-column');
22999        }
23000      }
23001      if (Device.android) {
23002        suffixes.push('android');
23003      }
23004      if (Device.ios) {
23005        suffixes.push('ios');
23006      }
23007  
23008      if (params.cssMode) {
23009        suffixes.push('css-mode');
23010      }
23011  
23012      suffixes.forEach(function (suffix) {
23013        classNames.push(params.containerModifierClass + suffix);
23014      });
23015  
23016      $el.addClass(classNames.join(' '));
23017    }
23018  
23019    function removeClasses () {
23020      var swiper = this;
23021      var $el = swiper.$el;
23022      var classNames = swiper.classNames;
23023  
23024      $el.removeClass(classNames.join(' '));
23025    }
23026  
23027    var classes = { addClasses: addClasses, removeClasses: removeClasses };
23028  
23029    function loadImage (imageEl, src, srcset, sizes, checkForComplete, callback) {
23030      var image;
23031      function onReady() {
23032        if (callback) { callback(); }
23033      }
23034      if (!imageEl.complete || !checkForComplete) {
23035        if (src) {
23036          image = new win.Image();
23037          image.onload = onReady;
23038          image.onerror = onReady;
23039          if (sizes) {
23040            image.sizes = sizes;
23041          }
23042          if (srcset) {
23043            image.srcset = srcset;
23044          }
23045          if (src) {
23046            image.src = src;
23047          }
23048        } else {
23049          onReady();
23050        }
23051      } else {
23052        // image already loaded...
23053        onReady();
23054      }
23055    }
23056  
23057    function preloadImages () {
23058      var swiper = this;
23059      swiper.imagesToLoad = swiper.$el.find('img');
23060      function onReady() {
23061        if (typeof swiper === 'undefined' || swiper === null || !swiper || swiper.destroyed) { return; }
23062        if (swiper.imagesLoaded !== undefined) { swiper.imagesLoaded += 1; }
23063        if (swiper.imagesLoaded === swiper.imagesToLoad.length) {
23064          if (swiper.params.updateOnImagesReady) { swiper.update(); }
23065          swiper.emit('imagesReady');
23066        }
23067      }
23068      for (var i = 0; i < swiper.imagesToLoad.length; i += 1) {
23069        var imageEl = swiper.imagesToLoad[i];
23070        swiper.loadImage(
23071          imageEl,
23072          imageEl.currentSrc || imageEl.getAttribute('src'),
23073          imageEl.srcset || imageEl.getAttribute('srcset'),
23074          imageEl.sizes || imageEl.getAttribute('sizes'),
23075          true,
23076          onReady
23077        );
23078      }
23079    }
23080  
23081    var images = {
23082      loadImage: loadImage,
23083      preloadImages: preloadImages,
23084    };
23085  
23086    function checkOverflow() {
23087      var swiper = this;
23088      var params = swiper.params;
23089      var wasLocked = swiper.isLocked;
23090      var lastSlidePosition = swiper.slides.length > 0 && (params.slidesOffsetBefore + (params.spaceBetween * (swiper.slides.length - 1)) + ((swiper.slides[0]).offsetWidth) * swiper.slides.length);
23091  
23092      if (params.slidesOffsetBefore && params.slidesOffsetAfter && lastSlidePosition) {
23093        swiper.isLocked = lastSlidePosition <= swiper.size;
23094      } else {
23095        swiper.isLocked = swiper.snapGrid.length === 1;
23096      }
23097  
23098      swiper.allowSlideNext = !swiper.isLocked;
23099      swiper.allowSlidePrev = !swiper.isLocked;
23100  
23101      // events
23102      if (wasLocked !== swiper.isLocked) { swiper.emit(swiper.isLocked ? 'lock' : 'unlock'); }
23103  
23104      if (wasLocked && wasLocked !== swiper.isLocked) {
23105        swiper.isEnd = false;
23106        swiper.navigation.update();
23107      }
23108    }
23109  
23110    var checkOverflow$1 = { checkOverflow: checkOverflow };
23111  
23112    var defaults = {
23113      init: true,
23114      direction: 'horizontal',
23115      touchEventsTarget: 'container',
23116      initialSlide: 0,
23117      speed: 300,
23118      cssMode: false,
23119      //
23120      preventInteractionOnTransition: false,
23121  
23122      // To support iOS's swipe-to-go-back gesture (when being used in-app, with UIWebView).
23123      edgeSwipeDetection: false,
23124      edgeSwipeThreshold: 20,
23125  
23126      // Free mode
23127      freeMode: false,
23128      freeModeMomentum: true,
23129      freeModeMomentumRatio: 1,
23130      freeModeMomentumBounce: true,
23131      freeModeMomentumBounceRatio: 1,
23132      freeModeMomentumVelocityRatio: 1,
23133      freeModeSticky: false,
23134      freeModeMinimumVelocity: 0.02,
23135  
23136      // Autoheight
23137      autoHeight: false,
23138  
23139      // Set wrapper width
23140      setWrapperSize: false,
23141  
23142      // Virtual Translate
23143      virtualTranslate: false,
23144  
23145      // Effects
23146      effect: 'slide', // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'
23147  
vendor: 37,447 bytes, lines 23148-24245
23148      // Breakpoints
23149      breakpoints: undefined,
23150  
23151      // Slides grid
23152      spaceBetween: 0,
23153      slidesPerView: 1,
23154      slidesPerColumn: 1,
23155      slidesPerColumnFill: 'column',
23156      slidesPerGroup: 1,
23157      centeredSlides: false,
23158      centeredSlidesBounds: false,
23159      slidesOffsetBefore: 0, // in px
23160      slidesOffsetAfter: 0, // in px
23161      normalizeSlideIndex: true,
23162      centerInsufficientSlides: false,
23163  
23164      // Disable swiper and hide navigation when container not overflow
23165      watchOverflow: false,
23166  
23167      // Round length
23168      roundLengths: false,
23169  
23170      // Touches
23171      touchRatio: 1,
23172      touchAngle: 45,
23173      simulateTouch: true,
23174      shortSwipes: true,
23175      longSwipes: true,
23176      longSwipesRatio: 0.5,
23177      longSwipesMs: 300,
23178      followFinger: true,
23179      allowTouchMove: true,
23180      threshold: 0,
23181      touchMoveStopPropagation: false,
23182      touchStartPreventDefault: true,
23183      touchStartForcePreventDefault: false,
23184      touchReleaseOnEdges: false,
23185  
23186      // Unique Navigation Elements
23187      uniqueNavElements: true,
23188  
23189      // Resistance
23190      resistance: true,
23191      resistanceRatio: 0.85,
23192  
23193      // Progress
23194      watchSlidesProgress: false,
23195      watchSlidesVisibility: false,
23196  
23197      // Cursor
23198      grabCursor: false,
23199  
23200      // Clicks
23201      preventClicks: true,
23202      preventClicksPropagation: true,
23203      slideToClickedSlide: false,
23204  
23205      // Images
23206      preloadImages: true,
23207      updateOnImagesReady: true,
23208  
23209      // loop
23210      loop: false,
23211      loopAdditionalSlides: 0,
23212      loopedSlides: null,
23213      loopFillGroupWithBlank: false,
23214  
23215      // Swiping/no swiping
23216      allowSlidePrev: true,
23217      allowSlideNext: true,
23218      swipeHandler: null, // '.swipe-handler',
23219      noSwiping: true,
23220      noSwipingClass: 'swiper-no-swiping',
23221      noSwipingSelector: null,
23222  
23223      // Passive Listeners
23224      passiveListeners: true,
23225  
23226      // NS
23227      containerModifierClass: 'swiper-container-', // NEW
23228      slideClass: 'swiper-slide',
23229      slideBlankClass: 'swiper-slide-invisible-blank',
23230      slideActiveClass: 'swiper-slide-active',
23231      slideDuplicateActiveClass: 'swiper-slide-duplicate-active',
23232      slideVisibleClass: 'swiper-slide-visible',
23233      slideDuplicateClass: 'swiper-slide-duplicate',
23234      slideNextClass: 'swiper-slide-next',
23235      slideDuplicateNextClass: 'swiper-slide-duplicate-next',
23236      slidePrevClass: 'swiper-slide-prev',
23237      slideDuplicatePrevClass: 'swiper-slide-duplicate-prev',
23238      wrapperClass: 'swiper-wrapper',
23239  
23240      // Callbacks
23241      runCallbacksOnInit: true,
23242    };
23243  
23244    /* eslint no-param-reassign: "off" */
23245  
23246    var prototypes = {
23247      update: update,
23248      translate: translate,
23249      transition: transition$1,
23250      slide: slide,
23251      loop: loop,
23252      grabCursor: grabCursor,
23253      manipulation: manipulation,
23254      events: events,
23255      breakpoints: breakpoints,
23256      checkOverflow: checkOverflow$1,
23257      classes: classes,
23258      images: images,
23259    };
23260  
23261    var extendedDefaults = {};
23262  
23263    var Swiper = /*@__PURE__*/(function (SwiperClass) {
23264      function Swiper() {
23265        var assign;
23266  
23267        var args = [], len = arguments.length;
23268        while ( len-- ) args[ len ] = arguments[ len ];
23269        var el;
23270        var params;
23271        if (args.length === 1 && args[0].constructor && args[0].constructor === Object) {
23272          params = args[0];
23273        } else {
23274          (assign = args, el = assign[0], params = assign[1]);
23275        }
23276        if (!params) { params = {}; }
23277  
23278        params = Utils.extend({}, params);
23279        if (el && !params.el) { params.el = el; }
23280  
23281        SwiperClass.call(this, params);
23282  
23283        Object.keys(prototypes).forEach(function (prototypeGroup) {
23284          Object.keys(prototypes[prototypeGroup]).forEach(function (protoMethod) {
23285            if (!Swiper.prototype[protoMethod]) {
23286              Swiper.prototype[protoMethod] = prototypes[prototypeGroup][protoMethod];
23287            }
23288          });
23289        });
23290  
23291        // Swiper Instance
23292        var swiper = this;
23293        if (typeof swiper.modules === 'undefined') {
23294          swiper.modules = {};
23295        }
23296        Object.keys(swiper.modules).forEach(function (moduleName) {
23297          var module = swiper.modules[moduleName];
23298          if (module.params) {
23299            var moduleParamName = Object.keys(module.params)[0];
23300            var moduleParams = module.params[moduleParamName];
23301            if (typeof moduleParams !== 'object' || moduleParams === null) { return; }
23302            if (!(moduleParamName in params && 'enabled' in moduleParams)) { return; }
23303            if (params[moduleParamName] === true) {
23304              params[moduleParamName] = { enabled: true };
23305            }
23306            if (
23307              typeof params[moduleParamName] === 'object'
23308              && !('enabled' in params[moduleParamName])
23309            ) {
23310              params[moduleParamName].enabled = true;
23311            }
23312            if (!params[moduleParamName]) { params[moduleParamName] = { enabled: false }; }
23313          }
23314        });
23315  
23316        // Extend defaults with modules params
23317        var swiperParams = Utils.extend({}, defaults);
23318        swiper.useModulesParams(swiperParams);
23319  
23320        // Extend defaults with passed params
23321        swiper.params = Utils.extend({}, swiperParams, extendedDefaults, params);
23322        swiper.originalParams = Utils.extend({}, swiper.params);
23323        swiper.passedParams = Utils.extend({}, params);
23324  
23325        // Save Dom lib
23326        swiper.$ = $;
23327  
23328        // Find el
23329        var $el = $(swiper.params.el);
23330        el = $el[0];
23331  
23332        if (!el) {
23333          return undefined;
23334        }
23335  
23336        if ($el.length > 1) {
23337          var swipers = [];
23338          $el.each(function (index, containerEl) {
23339            var newParams = Utils.extend({}, params, { el: containerEl });
23340            swipers.push(new Swiper(newParams));
23341          });
23342          return swipers;
23343        }
23344  
23345        el.swiper = swiper;
23346        $el.data('swiper', swiper);
23347  
23348        // Find Wrapper
23349        var $wrapperEl;
23350        if (el && el.shadowRoot && el.shadowRoot.querySelector) {
23351          $wrapperEl = $(el.shadowRoot.querySelector(("." + (swiper.params.wrapperClass))));
23352          // Children needs to return slot items
23353          $wrapperEl.children = function (options) { return $el.children(options); };
23354        } else {
23355          $wrapperEl = $el.children(("." + (swiper.params.wrapperClass)));
23356        }
23357        // Extend Swiper
23358        Utils.extend(swiper, {
23359          $el: $el,
23360          el: el,
23361          $wrapperEl: $wrapperEl,
23362          wrapperEl: $wrapperEl[0],
23363  
23364          // Classes
23365          classNames: [],
23366  
23367          // Slides
23368          slides: $(),
23369          slidesGrid: [],
23370          snapGrid: [],
23371          slidesSizesGrid: [],
23372  
23373          // isDirection
23374          isHorizontal: function isHorizontal() {
23375            return swiper.params.direction === 'horizontal';
23376          },
23377          isVertical: function isVertical() {
23378            return swiper.params.direction === 'vertical';
23379          },
23380          // RTL
23381          rtl: (el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl'),
23382          rtlTranslate: swiper.params.direction === 'horizontal' && (el.dir.toLowerCase() === 'rtl' || $el.css('direction') === 'rtl'),
23383          wrongRTL: $wrapperEl.css('display') === '-webkit-box',
23384  
23385          // Indexes
23386          activeIndex: 0,
23387          realIndex: 0,
23388  
23389          //
23390          isBeginning: true,
23391          isEnd: false,
23392  
23393          // Props
23394          translate: 0,
23395          previousTranslate: 0,
23396          progress: 0,
23397          velocity: 0,
23398          animating: false,
23399  
23400          // Locks
23401          allowSlideNext: swiper.params.allowSlideNext,
23402          allowSlidePrev: swiper.params.allowSlidePrev,
23403  
23404          // Touch Events
23405          touchEvents: (function touchEvents() {
23406            var touch = ['touchstart', 'touchmove', 'touchend', 'touchcancel'];
23407            var desktop = ['mousedown', 'mousemove', 'mouseup'];
23408            if (Support.pointerEvents) {
23409              desktop = ['pointerdown', 'pointermove', 'pointerup'];
23410            }
23411            swiper.touchEventsTouch = {
23412              start: touch[0],
23413              move: touch[1],
23414              end: touch[2],
23415              cancel: touch[3],
23416            };
23417            swiper.touchEventsDesktop = {
23418              start: desktop[0],
23419              move: desktop[1],
23420              end: desktop[2],
23421            };
23422            return Support.touch || !swiper.params.simulateTouch ? swiper.touchEventsTouch : swiper.touchEventsDesktop;
23423          }()),
23424          touchEventsData: {
23425            isTouched: undefined,
23426            isMoved: undefined,
23427            allowTouchCallbacks: undefined,
23428            touchStartTime: undefined,
23429            isScrolling: undefined,
23430            currentTranslate: undefined,
23431            startTranslate: undefined,
23432            allowThresholdMove: undefined,
23433            // Form elements to match
23434            formElements: 'input, select, option, textarea, button, video',
23435            // Last click time
23436            lastClickTime: Utils.now(),
23437            clickTimeout: undefined,
23438            // Velocities
23439            velocities: [],
23440            allowMomentumBounce: undefined,
23441            isTouchEvent: undefined,
23442            startMoving: undefined,
23443          },
23444  
23445          // Clicks
23446          allowClick: true,
23447  
23448          // Touches
23449          allowTouchMove: swiper.params.allowTouchMove,
23450  
23451          touches: {
23452            startX: 0,
23453            startY: 0,
23454            currentX: 0,
23455            currentY: 0,
23456            diff: 0,
23457          },
23458  
23459          // Images
23460          imagesToLoad: [],
23461          imagesLoaded: 0,
23462  
23463        });
23464  
23465        // Install Modules
23466        swiper.useModules();
23467  
23468        // Init
23469        if (swiper.params.init) {
23470          swiper.init();
23471        }
23472  
23473        // Return app instance
23474        return swiper;
23475      }
23476  
23477      if ( SwiperClass ) Swiper.__proto__ = SwiperClass;
23478      Swiper.prototype = Object.create( SwiperClass && SwiperClass.prototype );
23479      Swiper.prototype.constructor = Swiper;
23480  
23481      var staticAccessors = { extendedDefaults: { configurable: true },defaults: { configurable: true },Class: { configurable: true },$: { configurable: true } };
23482  
23483      Swiper.prototype.slidesPerViewDynamic = function slidesPerViewDynamic () {
23484        var swiper = this;
23485        var params = swiper.params;
23486        var slides = swiper.slides;
23487        var slidesGrid = swiper.slidesGrid;
23488        var swiperSize = swiper.size;
23489        var activeIndex = swiper.activeIndex;
23490        var spv = 1;
23491        if (params.centeredSlides) {
23492          var slideSize = slides[activeIndex].swiperSlideSize;
23493          var breakLoop;
23494          for (var i = activeIndex + 1; i < slides.length; i += 1) {
23495            if (slides[i] && !breakLoop) {
23496              slideSize += slides[i].swiperSlideSize;
23497              spv += 1;
23498              if (slideSize > swiperSize) { breakLoop = true; }
23499            }
23500          }
23501          for (var i$1 = activeIndex - 1; i$1 >= 0; i$1 -= 1) {
23502            if (slides[i$1] && !breakLoop) {
23503              slideSize += slides[i$1].swiperSlideSize;
23504              spv += 1;
23505              if (slideSize > swiperSize) { breakLoop = true; }
23506            }
23507          }
23508        } else {
23509          for (var i$2 = activeIndex + 1; i$2 < slides.length; i$2 += 1) {
23510            if (slidesGrid[i$2] - slidesGrid[activeIndex] < swiperSize) {
23511              spv += 1;
23512            }
23513          }
23514        }
23515        return spv;
23516      };
23517  
23518      Swiper.prototype.update = function update () {
23519        var swiper = this;
23520        if (!swiper || swiper.destroyed) { return; }
23521        var snapGrid = swiper.snapGrid;
23522        var params = swiper.params;
23523        // Breakpoints
23524        if (params.breakpoints) {
23525          swiper.setBreakpoint();
23526        }
23527        swiper.updateSize();
23528        swiper.updateSlides();
23529        swiper.updateProgress();
23530        swiper.updateSlidesClasses();
23531  
23532        function setTranslate() {
23533          var translateValue = swiper.rtlTranslate ? swiper.translate * -1 : swiper.translate;
23534          var newTranslate = Math.min(Math.max(translateValue, swiper.maxTranslate()), swiper.minTranslate());
23535          swiper.setTranslate(newTranslate);
23536          swiper.updateActiveIndex();
23537          swiper.updateSlidesClasses();
23538        }
23539        var translated;
23540        if (swiper.params.freeMode) {
23541          setTranslate();
23542          if (swiper.params.autoHeight) {
23543            swiper.updateAutoHeight();
23544          }
23545        } else {
23546          if ((swiper.params.slidesPerView === 'auto' || swiper.params.slidesPerView > 1) && swiper.isEnd && !swiper.params.centeredSlides) {
23547            translated = swiper.slideTo(swiper.slides.length - 1, 0, false, true);
23548          } else {
23549            translated = swiper.slideTo(swiper.activeIndex, 0, false, true);
23550          }
23551          if (!translated) {
23552            setTranslate();
23553          }
23554        }
23555        if (params.watchOverflow && snapGrid !== swiper.snapGrid) {
23556          swiper.checkOverflow();
23557        }
23558        swiper.emit('update');
23559      };
23560  
23561      Swiper.prototype.changeDirection = function changeDirection (newDirection, needUpdate) {
23562        if ( needUpdate === void 0 ) needUpdate = true;
23563  
23564        var swiper = this;
23565        var currentDirection = swiper.params.direction;
23566        if (!newDirection) {
23567          // eslint-disable-next-line
23568          newDirection = currentDirection === 'horizontal' ? 'vertical' : 'horizontal';
23569        }
23570        if ((newDirection === currentDirection) || (newDirection !== 'horizontal' && newDirection !== 'vertical')) {
23571          return swiper;
23572        }
23573  
23574        swiper.$el
23575          .removeClass(("" + (swiper.params.containerModifierClass) + currentDirection))
23576          .addClass(("" + (swiper.params.containerModifierClass) + newDirection));
23577  
23578        swiper.params.direction = newDirection;
23579  
23580        swiper.slides.each(function (slideIndex, slideEl) {
23581          if (newDirection === 'vertical') {
23582            slideEl.style.width = '';
23583          } else {
23584            slideEl.style.height = '';
23585          }
23586        });
23587  
23588        swiper.emit('changeDirection');
23589        if (needUpdate) { swiper.update(); }
23590  
23591        return swiper;
23592      };
23593  
23594      Swiper.prototype.init = function init () {
23595        var swiper = this;
23596        if (swiper.initialized) { return; }
23597  
23598        swiper.emit('beforeInit');
23599  
23600        // Set breakpoint
23601        if (swiper.params.breakpoints) {
23602          swiper.setBreakpoint();
23603        }
23604  
23605        // Add Classes
23606        swiper.addClasses();
23607  
23608        // Create loop
23609        if (swiper.params.loop) {
23610          swiper.loopCreate();
23611        }
23612  
23613        // Update size
23614        swiper.updateSize();
23615  
23616        // Update slides
23617        swiper.updateSlides();
23618  
23619        if (swiper.params.watchOverflow) {
23620          swiper.checkOverflow();
23621        }
23622  
23623        // Set Grab Cursor
23624        if (swiper.params.grabCursor) {
23625          swiper.setGrabCursor();
23626        }
23627  
23628        if (swiper.params.preloadImages) {
23629          swiper.preloadImages();
23630        }
23631  
23632        // Slide To Initial Slide
23633        if (swiper.params.loop) {
23634          swiper.slideTo(swiper.params.initialSlide + swiper.loopedSlides, 0, swiper.params.runCallbacksOnInit);
23635        } else {
23636          swiper.slideTo(swiper.params.initialSlide, 0, swiper.params.runCallbacksOnInit);
23637        }
23638  
23639        // Attach events
23640        swiper.attachEvents();
23641  
23642        // Init Flag
23643        swiper.initialized = true;
23644  
23645        // Emit
23646        swiper.emit('init');
23647      };
23648  
23649      Swiper.prototype.destroy = function destroy (deleteInstance, cleanStyles) {
23650        if ( deleteInstance === void 0 ) deleteInstance = true;
23651        if ( cleanStyles === void 0 ) cleanStyles = true;
23652  
23653        var swiper = this;
23654        var params = swiper.params;
23655        var $el = swiper.$el;
23656        var $wrapperEl = swiper.$wrapperEl;
23657        var slides = swiper.slides;
23658  
23659        if (typeof swiper.params === 'undefined' || swiper.destroyed) {
23660          return null;
23661        }
23662  
23663        swiper.emit('beforeDestroy');
23664  
23665        // Init Flag
23666        swiper.initialized = false;
23667  
23668        // Detach events
23669        swiper.detachEvents();
23670  
23671        // Destroy loop
23672        if (params.loop) {
23673          swiper.loopDestroy();
23674        }
23675  
23676        // Cleanup styles
23677        if (cleanStyles) {
23678          swiper.removeClasses();
23679          $el.removeAttr('style');
23680          $wrapperEl.removeAttr('style');
23681          if (slides && slides.length) {
23682            slides
23683              .removeClass([
23684                params.slideVisibleClass,
23685                params.slideActiveClass,
23686                params.slideNextClass,
23687                params.slidePrevClass ].join(' '))
23688              .removeAttr('style')
23689              .removeAttr('data-swiper-slide-index');
23690          }
23691        }
23692  
23693        swiper.emit('destroy');
23694  
23695        // Detach emitter events
23696        Object.keys(swiper.eventsListeners).forEach(function (eventName) {
23697          swiper.off(eventName);
23698        });
23699  
23700        if (deleteInstance !== false) {
23701          swiper.$el[0].swiper = null;
23702          swiper.$el.data('swiper', null);
23703          Utils.deleteProps(swiper);
23704        }
23705        swiper.destroyed = true;
23706  
23707        return null;
23708      };
23709  
23710      Swiper.extendDefaults = function extendDefaults (newDefaults) {
23711        Utils.extend(extendedDefaults, newDefaults);
23712      };
23713  
23714      staticAccessors.extendedDefaults.get = function () {
23715        return extendedDefaults;
23716      };
23717  
23718      staticAccessors.defaults.get = function () {
23719        return defaults;
23720      };
23721  
23722      staticAccessors.Class.get = function () {
23723        return SwiperClass;
23724      };
23725  
23726      staticAccessors.$.get = function () {
23727        return $;
23728      };
23729  
23730      Object.defineProperties( Swiper, staticAccessors );
23731  
23732      return Swiper;
23733    }(SwiperClass));
23734  
23735    var Device$1 = {
23736      name: 'device',
23737      proto: {
23738        device: Device,
23739      },
23740      static: {
23741        device: Device,
23742      },
23743    };
23744  
23745    var Support$1 = {
23746      name: 'support',
23747      proto: {
23748        support: Support,
23749      },
23750      static: {
23751        support: Support,
23752      },
23753    };
23754  
23755    var Browser = (function Browser() {
23756      function isSafari() {
23757        var ua = win.navigator.userAgent.toLowerCase();
23758        return (ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0);
23759      }
23760      return {
23761        isEdge: !!win.navigator.userAgent.match(/Edge/g),
23762        isSafari: isSafari(),
23763        isUiWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(win.navigator.userAgent),
23764      };
23765    }());
23766  
23767    var Browser$1 = {
23768      name: 'browser',
23769      proto: {
23770        browser: Browser,
23771      },
23772      static: {
23773        browser: Browser,
23774      },
23775    };
23776  
23777    var Resize = {
23778      name: 'resize',
23779      create: function create() {
23780        var swiper = this;
23781        Utils.extend(swiper, {
23782          resize: {
23783            resizeHandler: function resizeHandler() {
23784              if (!swiper || swiper.destroyed || !swiper.initialized) { return; }
23785              swiper.emit('beforeResize');
23786              swiper.emit('resize');
23787            },
23788            orientationChangeHandler: function orientationChangeHandler() {
23789              if (!swiper || swiper.destroyed || !swiper.initialized) { return; }
23790              swiper.emit('orientationchange');
23791            },
23792          },
23793        });
23794      },
23795      on: {
23796        init: function init() {
23797          var swiper = this;
23798          // Emit resize
23799          win.addEventListener('resize', swiper.resize.resizeHandler);
23800  
23801          // Emit orientationchange
23802          win.addEventListener('orientationchange', swiper.resize.orientationChangeHandler);
23803        },
23804        destroy: function destroy() {
23805          var swiper = this;
23806          win.removeEventListener('resize', swiper.resize.resizeHandler);
23807          win.removeEventListener('orientationchange', swiper.resize.orientationChangeHandler);
23808        },
23809      },
23810    };
23811  
23812    var Observer = {
23813      func: win.MutationObserver || win.WebkitMutationObserver,
23814      attach: function attach(target, options) {
23815        if ( options === void 0 ) options = {};
23816  
23817        var swiper = this;
23818  
23819        var ObserverFunc = Observer.func;
23820        var observer = new ObserverFunc(function (mutations) {
23821          // The observerUpdate event should only be triggered
23822          // once despite the number of mutations.  Additional
23823          // triggers are redundant and are very costly
23824          if (mutations.length === 1) {
23825            swiper.emit('observerUpdate', mutations[0]);
23826            return;
23827          }
23828          var observerUpdate = function observerUpdate() {
23829            swiper.emit('observerUpdate', mutations[0]);
23830          };
23831  
23832          if (win.requestAnimationFrame) {
23833            win.requestAnimationFrame(observerUpdate);
23834          } else {
23835            win.setTimeout(observerUpdate, 0);
23836          }
23837        });
23838  
23839        observer.observe(target, {
23840          attributes: typeof options.attributes === 'undefined' ? true : options.attributes,
23841          childList: typeof options.childList === 'undefined' ? true : options.childList,
23842          characterData: typeof options.characterData === 'undefined' ? true : options.characterData,
23843        });
23844  
23845        swiper.observer.observers.push(observer);
23846      },
23847      init: function init() {
23848        var swiper = this;
23849        if (!Support.observer || !swiper.params.observer) { return; }
23850        if (swiper.params.observeParents) {
23851          var containerParents = swiper.$el.parents();
23852          for (var i = 0; i < containerParents.length; i += 1) {
23853            swiper.observer.attach(containerParents[i]);
23854          }
23855        }
23856        // Observe container
23857        swiper.observer.attach(swiper.$el[0], { childList: swiper.params.observeSlideChildren });
23858  
23859        // Observe wrapper
23860        swiper.observer.attach(swiper.$wrapperEl[0], { attributes: false });
23861      },
23862      destroy: function destroy() {
23863        var swiper = this;
23864        swiper.observer.observers.forEach(function (observer) {
23865          observer.disconnect();
23866        });
23867        swiper.observer.observers = [];
23868      },
23869    };
23870  
23871    var Observer$1 = {
23872      name: 'observer',
23873      params: {
23874        observer: false,
23875        observeParents: false,
23876        observeSlideChildren: false,
23877      },
23878      create: function create() {
23879        var swiper = this;
23880        Utils.extend(swiper, {
23881          observer: {
23882            init: Observer.init.bind(swiper),
23883            attach: Observer.attach.bind(swiper),
23884            destroy: Observer.destroy.bind(swiper),
23885            observers: [],
23886          },
23887        });
23888      },
23889      on: {
23890        init: function init() {
23891          var swiper = this;
23892          swiper.observer.init();
23893        },
23894        destroy: function destroy() {
23895          var swiper = this;
23896          swiper.observer.destroy();
23897        },
23898      },
23899    };
23900  
23901    var Virtual = {
23902      update: function update(force) {
23903        var swiper = this;
23904        var ref = swiper.params;
23905        var slidesPerView = ref.slidesPerView;
23906        var slidesPerGroup = ref.slidesPerGroup;
23907        var centeredSlides = ref.centeredSlides;
23908        var ref$1 = swiper.params.virtual;
23909        var addSlidesBefore = ref$1.addSlidesBefore;
23910        var addSlidesAfter = ref$1.addSlidesAfter;
23911        var ref$2 = swiper.virtual;
23912        var previousFrom = ref$2.from;
23913        var previousTo = ref$2.to;
23914        var slides = ref$2.slides;
23915        var previousSlidesGrid = ref$2.slidesGrid;
23916        var renderSlide = ref$2.renderSlide;
23917        var previousOffset = ref$2.offset;
23918        swiper.updateActiveIndex();
23919        var activeIndex = swiper.activeIndex || 0;
23920  
23921        var offsetProp;
23922        if (swiper.rtlTranslate) { offsetProp = 'right'; }
23923        else { offsetProp = swiper.isHorizontal() ? 'left' : 'top'; }
23924  
23925        var slidesAfter;
23926        var slidesBefore;
23927        if (centeredSlides) {
23928          slidesAfter = Math.floor(slidesPerView / 2) + slidesPerGroup + addSlidesBefore;
23929          slidesBefore = Math.floor(slidesPerView / 2) + slidesPerGroup + addSlidesAfter;
23930        } else {
23931          slidesAfter = slidesPerView + (slidesPerGroup - 1) + addSlidesBefore;
23932          slidesBefore = slidesPerGroup + addSlidesAfter;
23933        }
23934        var from = Math.max((activeIndex || 0) - slidesBefore, 0);
23935        var to = Math.min((activeIndex || 0) + slidesAfter, slides.length - 1);
23936        var offset = (swiper.slidesGrid[from] || 0) - (swiper.slidesGrid[0] || 0);
23937  
23938        Utils.extend(swiper.virtual, {
23939          from: from,
23940          to: to,
23941          offset: offset,
23942          slidesGrid: swiper.slidesGrid,
23943        });
23944  
23945        function onRendered() {
23946          swiper.updateSlides();
23947          swiper.updateProgress();
23948          swiper.updateSlidesClasses();
23949          if (swiper.lazy && swiper.params.lazy.enabled) {
23950            swiper.lazy.load();
23951          }
23952        }
23953  
23954        if (previousFrom === from && previousTo === to && !force) {
23955          if (swiper.slidesGrid !== previousSlidesGrid && offset !== previousOffset) {
23956            swiper.slides.css(offsetProp, (offset + "px"));
23957          }
23958          swiper.updateProgress();
23959          return;
23960        }
23961        if (swiper.params.virtual.renderExternal) {
23962          swiper.params.virtual.renderExternal.call(swiper, {
23963            offset: offset,
23964            from: from,
23965            to: to,
23966            slides: (function getSlides() {
23967              var slidesToRender = [];
23968              for (var i = from; i <= to; i += 1) {
23969                slidesToRender.push(slides[i]);
23970              }
23971              return slidesToRender;
23972            }()),
23973          });
23974          onRendered();
23975          return;
23976        }
23977        var prependIndexes = [];
23978        var appendIndexes = [];
23979        if (force) {
23980          swiper.$wrapperEl.find(("." + (swiper.params.slideClass))).remove();
23981        } else {
23982          for (var i = previousFrom; i <= previousTo; i += 1) {
23983            if (i < from || i > to) {
23984              swiper.$wrapperEl.find(("." + (swiper.params.slideClass) + "[data-swiper-slide-index=\"" + i + "\"]")).remove();
23985            }
23986          }
23987        }
23988        for (var i$1 = 0; i$1 < slides.length; i$1 += 1) {
23989          if (i$1 >= from && i$1 <= to) {
23990            if (typeof previousTo === 'undefined' || force) {
23991              appendIndexes.push(i$1);
23992            } else {
23993              if (i$1 > previousTo) { appendIndexes.push(i$1); }
23994              if (i$1 < previousFrom) { prependIndexes.push(i$1); }
23995            }
23996          }
23997        }
23998        appendIndexes.forEach(function (index) {
23999          swiper.$wrapperEl.append(renderSlide(slides[index], index));
24000        });
24001        prependIndexes.sort(function (a, b) { return b - a; }).forEach(function (index) {
24002          swiper.$wrapperEl.prepend(renderSlide(slides[index], index));
24003        });
24004        swiper.$wrapperEl.children('.swiper-slide').css(offsetProp, (offset + "px"));
24005        onRendered();
24006      },
24007      renderSlide: function renderSlide(slide, index) {
24008        var swiper = this;
24009        var params = swiper.params.virtual;
24010        if (params.cache && swiper.virtual.cache[index]) {
24011          return swiper.virtual.cache[index];
24012        }
24013        var $slideEl = params.renderSlide
24014          ? $(params.renderSlide.call(swiper, slide, index))
24015          : $(("<div class=\"" + (swiper.params.slideClass) + "\" data-swiper-slide-index=\"" + index + "\">" + slide + "</div>"));
24016        if (!$slideEl.attr('data-swiper-slide-index')) { $slideEl.attr('data-swiper-slide-index', index); }
24017        if (params.cache) { swiper.virtual.cache[index] = $slideEl; }
24018        return $slideEl;
24019      },
24020      appendSlide: function appendSlide(slides) {
24021        var swiper = this;
24022        if (typeof slides === 'object' && 'length' in slides) {
24023          for (var i = 0; i < slides.length; i += 1) {
24024            if (slides[i]) { swiper.virtual.slides.push(slides[i]); }
24025          }
24026        } else {
24027          swiper.virtual.slides.push(slides);
24028        }
24029        swiper.virtual.update(true);
24030      },
24031      prependSlide: function prependSlide(slides) {
24032        var swiper = this;
24033        var activeIndex = swiper.activeIndex;
24034        var newActiveIndex = activeIndex + 1;
24035        var numberOfNewSlides = 1;
24036  
24037        if (Array.isArray(slides)) {
24038          for (var i = 0; i < slides.length; i += 1) {
24039            if (slides[i]) { swiper.virtual.slides.unshift(slides[i]); }
24040          }
24041          newActiveIndex = activeIndex + slides.length;
24042          numberOfNewSlides = slides.length;
24043        } else {
24044          swiper.virtual.slides.unshift(slides);
24045        }
24046        if (swiper.params.virtual.cache) {
24047          var cache = swiper.virtual.cache;
24048          var newCache = {};
24049          Object.keys(cache).forEach(function (cachedIndex) {
24050            var $cachedEl = cache[cachedIndex];
24051            var cachedElIndex = $cachedEl.attr('data-swiper-slide-index');
24052            if (cachedElIndex) {
24053              $cachedEl.attr('data-swiper-slide-index', parseInt(cachedElIndex, 10) + 1);
24054            }
24055            newCache[parseInt(cachedIndex, 10) + numberOfNewSlides] = $cachedEl;
24056          });
24057          swiper.virtual.cache = newCache;
24058        }
24059        swiper.virtual.update(true);
24060        swiper.slideTo(newActiveIndex, 0);
24061      },
24062      removeSlide: function removeSlide(slidesIndexes) {
24063        var swiper = this;
24064        if (typeof slidesIndexes === 'undefined' || slidesIndexes === null) { return; }
24065        var activeIndex = swiper.activeIndex;
24066        if (Array.isArray(slidesIndexes)) {
24067          for (var i = slidesIndexes.length - 1; i >= 0; i -= 1) {
24068            swiper.virtual.slides.splice(slidesIndexes[i], 1);
24069            if (swiper.params.virtual.cache) {
24070              delete swiper.virtual.cache[slidesIndexes[i]];
24071            }
24072            if (slidesIndexes[i] < activeIndex) { activeIndex -= 1; }
24073            activeIndex = Math.max(activeIndex, 0);
24074          }
24075        } else {
24076          swiper.virtual.slides.splice(slidesIndexes, 1);
24077          if (swiper.params.virtual.cache) {
24078            delete swiper.virtual.cache[slidesIndexes];
24079          }
24080          if (slidesIndexes < activeIndex) { activeIndex -= 1; }
24081          activeIndex = Math.max(activeIndex, 0);
24082        }
24083        swiper.virtual.update(true);
24084        swiper.slideTo(activeIndex, 0);
24085      },
24086      removeAllSlides: function removeAllSlides() {
24087        var swiper = this;
24088        swiper.virtual.slides = [];
24089        if (swiper.params.virtual.cache) {
24090          swiper.virtual.cache = {};
24091        }
24092        swiper.virtual.update(true);
24093        swiper.slideTo(0, 0);
24094      },
24095    };
24096  
24097    var Virtual$1 = {
24098      name: 'virtual',
24099      params: {
24100        virtual: {
24101          enabled: false,
24102          slides: [],
24103          cache: true,
24104          renderSlide: null,
24105          renderExternal: null,
24106          addSlidesBefore: 0,
24107          addSlidesAfter: 0,
24108        },
24109      },
24110      create: function create() {
24111        var swiper = this;
24112        Utils.extend(swiper, {
24113          virtual: {
24114            update: Virtual.update.bind(swiper),
24115            appendSlide: Virtual.appendSlide.bind(swiper),
24116            prependSlide: Virtual.prependSlide.bind(swiper),
24117            removeSlide: Virtual.removeSlide.bind(swiper),
24118            removeAllSlides: Virtual.removeAllSlides.bind(swiper),
24119            renderSlide: Virtual.renderSlide.bind(swiper),
24120            slides: swiper.params.virtual.slides,
24121            cache: {},
24122          },
24123        });
24124      },
24125      on: {
24126        beforeInit: function beforeInit() {
24127          var swiper = this;
24128          if (!swiper.params.virtual.enabled) { return; }
24129          swiper.classNames.push(((swiper.params.containerModifierClass) + "virtual"));
24130          var overwriteParams = {
24131            watchSlidesProgress: true,
24132          };
24133          Utils.extend(swiper.params, overwriteParams);
24134          Utils.extend(swiper.originalParams, overwriteParams);
24135  
24136          if (!swiper.params.initialSlide) {
24137            swiper.virtual.update();
24138          }
24139        },
24140        setTranslate: function setTranslate() {
24141          var swiper = this;
24142          if (!swiper.params.virtual.enabled) { return; }
24143          swiper.virtual.update();
24144        },
24145      },
24146    };
24147  
24148    var Keyboard = {
24149      handle: function handle(event) {
24150        var swiper = this;
24151        var rtl = swiper.rtlTranslate;
24152        var e = event;
24153        if (e.originalEvent) { e = e.originalEvent; } // jquery fix
24154        var kc = e.keyCode || e.charCode;
24155        // Directions locks
24156        if (!swiper.allowSlideNext && ((swiper.isHorizontal() && kc === 39) || (swiper.isVertical() && kc === 40) || kc === 34)) {
24157          return false;
24158        }
24159        if (!swiper.allowSlidePrev && ((swiper.isHorizontal() && kc === 37) || (swiper.isVertical() && kc === 38) || kc === 33)) {
24160          return false;
24161        }
24162        if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) {
24163          return undefined;
24164        }
24165        if (doc.activeElement && doc.activeElement.nodeName && (doc.activeElement.nodeName.toLowerCase() === 'input' || doc.activeElement.nodeName.toLowerCase() === 'textarea')) {
24166          return undefined;
24167        }
24168        if (swiper.params.keyboard.onlyInViewport && (kc === 33 || kc === 34 || kc === 37 || kc === 39 || kc === 38 || kc === 40)) {
24169          var inView = false;
24170          // Check that swiper should be inside of visible area of window
24171          if (swiper.$el.parents(("." + (swiper.params.slideClass))).length > 0 && swiper.$el.parents(("." + (swiper.params.slideActiveClass))).length === 0) {
24172            return undefined;
24173          }
24174          var windowWidth = win.innerWidth;
24175          var windowHeight = win.innerHeight;
24176          var swiperOffset = swiper.$el.offset();
24177          if (rtl) { swiperOffset.left -= swiper.$el[0].scrollLeft; }
24178          var swiperCoord = [
24179            [swiperOffset.left, swiperOffset.top],
24180            [swiperOffset.left + swiper.width, swiperOffset.top],
24181            [swiperOffset.left, swiperOffset.top + swiper.height],
24182            [swiperOffset.left + swiper.width, swiperOffset.top + swiper.height] ];
24183          for (var i = 0; i < swiperCoord.length; i += 1) {
24184            var point = swiperCoord[i];
24185            if (
24186              point[0] >= 0 && point[0] <= windowWidth
24187              && point[1] >= 0 && point[1] <= windowHeight
24188            ) {
24189              inView = true;
24190            }
24191          }
24192          if (!inView) { return undefined; }
24193        }
24194        if (swiper.isHorizontal()) {
24195          if (kc === 33 || kc === 34 || kc === 37 || kc === 39) {
24196            if (e.preventDefault) { e.preventDefault(); }
24197            else { e.returnValue = false; }
24198          }
24199          if (((kc === 34 || kc === 39) && !rtl) || ((kc === 33 || kc === 37) && rtl)) { swiper.slideNext(); }
24200          if (((kc === 33 || kc === 37) && !rtl) || ((kc === 34 || kc === 39) && rtl)) { swiper.slidePrev(); }
24201        } else {
24202          if (kc === 33 || kc === 34 || kc === 38 || kc === 40) {
24203            if (e.preventDefault) { e.preventDefault(); }
24204            else { e.returnValue = false; }
24205          }
24206          if (kc === 34 || kc === 40) { swiper.slideNext(); }
24207          if (kc === 33 || kc === 38) { swiper.slidePrev(); }
24208        }
24209        swiper.emit('keyPress', kc);
24210        return undefined;
24211      },
24212      enable: function enable() {
24213        var swiper = this;
24214        if (swiper.keyboard.enabled) { return; }
24215        $(doc).on('keydown', swiper.keyboard.handle);
24216        swiper.keyboard.enabled = true;
24217      },
24218      disable: function disable() {
24219        var swiper = this;
24220        if (!swiper.keyboard.enabled) { return; }
24221        $(doc).off('keydown', swiper.keyboard.handle);
24222        swiper.keyboard.enabled = false;
24223      },
24224    };
24225  
24226    var Keyboard$1 = {
24227      name: 'keyboard',
24228      params: {
24229        keyboard: {
24230          enabled: false,
24231          onlyInViewport: true,
24232        },
24233      },
24234      create: function create() {
24235        var swiper = this;
24236        Utils.extend(swiper, {
24237          keyboard: {
24238            enabled: false,
24239            enable: Keyboard.enable.bind(swiper),
24240            disable: Keyboard.disable.bind(swiper),
24241            handle: Keyboard.handle.bind(swiper),
24242          },
24243        });
24244      },
24245      on: {
24246        init: function init() {
24247          var swiper = this;
24248          if (swiper.params.keyboard.enabled) {
24249            swiper.keyboard.enable();
24250          }
24251        },
24252        destroy: function destroy() {
24253          var swiper = this;
24254          if (swiper.keyboard.enabled) {
24255            swiper.keyboard.disable();
24256          }
24257        },
24258      },
24259    };
24260  
24261    function isEventSupported() {
24262      var eventName = 'onwheel';
24263      var isSupported = eventName in doc;
24264  
24265      if (!isSupported) {
24266        var element = doc.createElement('div');
24267        element.setAttribute(eventName, 'return;');
24268        isSupported = typeof element[eventName] === 'function';
24269      }
24270  
24271      if (!isSupported
24272        && doc.implementation
24273        && doc.implementation.hasFeature
24274        // always returns true in newer browsers as per the standard.
24275        // @see http://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
24276        && doc.implementation.hasFeature('', '') !== true
24277      ) {
24278        // This is the only way to test support for the `wheel` event in IE9+.
24279        isSupported = doc.implementation.hasFeature('Events.wheel', '3.0');
24280      }
24281  
24282      return isSupported;
24283    }
24284    var Mousewheel = {
24285      lastScrollTime: Utils.now(),
24286      lastEventBeforeSnap: undefined,
24287      recentWheelEvents: [],
24288      event: function event() {
24289        if (win.navigator.userAgent.indexOf('firefox') > -1) { return 'DOMMouseScroll'; }
24290        return isEventSupported() ? 'wheel' : 'mousewheel';
24291      },
24292      normalize: function normalize(e) {
24293        // Reasonable defaults
24294        var PIXEL_STEP = 10;
24295        var LINE_HEIGHT = 40;
24296        var PAGE_HEIGHT = 800;
24297  
24298        var sX = 0;
24299        var sY = 0; // spinX, spinY
24300        var pX = 0;
24301        var pY = 0; // pixelX, pixelY
24302  
24303        // Legacy
24304        if ('detail' in e) {
24305          sY = e.detail;
24306        }
24307        if ('wheelDelta' in e) {
24308          sY = -e.wheelDelta / 120;
24309        }
24310        if ('wheelDeltaY' in e) {
24311          sY = -e.wheelDeltaY / 120;
24312        }
24313        if ('wheelDeltaX' in e) {
24314          sX = -e.wheelDeltaX / 120;
24315        }
24316  
24317        // side scrolling on FF with DOMMouseScroll
24318        if ('axis' in e && e.axis === e.HORIZONTAL_AXIS) {
24319          sX = sY;
24320          sY = 0;
24321        }
24322  
24323        pX = sX * PIXEL_STEP;
24324        pY = sY * PIXEL_STEP;
24325  
24326        if ('deltaY' in e) {
24327          pY = e.deltaY;
24328        }
24329        if ('deltaX' in e) {
24330          pX = e.deltaX;
24331        }
24332  
24333        if (e.shiftKey && !pX) { // if user scrolls with shift he wants horizontal scroll
24334          pX = pY;
24335          pY = 0;
24336        }
24337  
24338        if ((pX || pY) && e.deltaMode) {
24339          if (e.deltaMode === 1) { // delta in LINE units
24340            pX *= LINE_HEIGHT;
24341            pY *= LINE_HEIGHT;
24342          } else { // delta in PAGE units
24343            pX *= PAGE_HEIGHT;
24344            pY *= PAGE_HEIGHT;
24345          }
24346        }
24347  
24348        // Fall-back if spin cannot be determined
24349        if (pX && !sX) {
24350          sX = (pX < 1) ? -1 : 1;
24351        }
24352        if (pY && !sY) {
24353          sY = (pY < 1) ? -1 : 1;
24354        }
24355  
24356        return {
24357          spinX: sX,
24358          spinY: sY,
24359          pixelX: pX,
24360          pixelY: pY,
24361        };
24362      },
24363      handleMouseEnter: function handleMouseEnter() {
24364        var swiper = this;
24365        swiper.mouseEntered = true;
24366      },
24367      handleMouseLeave: function handleMouseLeave() {
24368        var swiper = this;
24369        swiper.mouseEntered = false;
24370      },
24371      handle: function handle(event) {
24372        var e = event;
24373        var swiper = this;
24374        var params = swiper.params.mousewheel;
24375  
24376        if (swiper.params.cssMode) {
24377          e.preventDefault();
24378        }
24379  
24380        if (!swiper.mouseEntered && !params.releaseOnEdges) { return true; }
24381  
24382        if (e.originalEvent) { e = e.originalEvent; } // jquery fix
24383        var delta = 0;
24384        var rtlFactor = swiper.rtlTranslate ? -1 : 1;
24385  
24386        var data = Mousewheel.normalize(e);
24387  
24388        if (params.forceToAxis) {
24389          if (swiper.isHorizontal()) {
24390            if (Math.abs(data.pixelX) > Math.abs(data.pixelY)) { delta = data.pixelX * rtlFactor; }
24391            else { return true; }
24392          } else if (Math.abs(data.pixelY) > Math.abs(data.pixelX)) { delta = data.pixelY; }
24393          else { return true; }
24394        } else {
24395          delta = Math.abs(data.pixelX) >
24395 Math.abs(data.pixelY) ? -data.pixelX * rtlFactor : -data.pixelY;
24396        }
24397  
24398        if (delta === 0) { return true; }
24399  
24400        if (params.invert) { delta = -delta; }
24401  
24402        if (!swiper.params.freeMode) {
24403          if (Utils.now() - swiper.mousewheel.lastScrollTime > 60) {
24404            if (delta < 0) {
24405              if ((!swiper.isEnd || swiper.params.loop) && !swiper.animating) {
24406                swiper.slideNext();
24407                swiper.emit('scroll', e);
24408              } else if (params.releaseOnEdges) { return true; }
24409            } else if ((!swiper.isBeginning || swiper.params.loop) && !swiper.animating) {
24410              swiper.slidePrev();
24411              swiper.emit('scroll', e);
24412            } else if (params.releaseOnEdges) { return true; }
24413          }
24414          swiper.mousewheel.lastScrollTime = (new win.Date()).getTime();
24415        } else {
24416          // Freemode or scrollContainer:
24417  
24418          // If we recently snapped after a momentum scroll, then ignore wheel events
24419          // to give time for the declereration to finish. Stop ignoring after 500 msecs
24420          // or if it's a new scroll (larger delta or inverse sign as last event before
24421          // an end-of-momentum snap).
24422          var newEvent = { time: Utils.now(), delta: Math.abs(delta), direction: Math.sign(delta) };
24423          var ref = swiper.mousewheel;
24424          var lastEventBeforeSnap = ref.lastEventBeforeSnap;
24425          var ignoreWheelEvents = lastEventBeforeSnap
24426            && newEvent.time < lastEventBeforeSnap.time + 500
24427            && newEvent.delta <= lastEventBeforeSnap.delta
24428            && newEvent.direction === lastEventBeforeSnap.direction;
24429          if (!ignoreWheelEvents) {
24430            swiper.mousewheel.lastEventBeforeSnap = undefined;
24431  
24432            if (swiper.params.loop) {
24433              swiper.loopFix();
24434            }
24435            var position = swiper.getTranslate() + (delta * params.sensitivity);
24436            var wasBeginning = swiper.isBeginning;
24437            var wasEnd = swiper.isEnd;
24438  
24439            if (position >= swiper.minTranslate()) { position = swiper.minTranslate(); }
24440            if (position <= swiper.maxTranslate()) { position = swiper.maxTranslate(); }
24441  
24442            swiper.setTransition(0);
24443            swiper.setTranslate(position);
24444            swiper.updateProgress();
24445            swiper.updateActiveIndex();
24446            swiper.updateSlidesClasses();
24447  
24448            if ((!wasBeginning && swiper.isBeginning) || (!wasEnd && swiper.isEnd)) {
24449              swiper.updateSlidesClasses();
24450            }
24451  
24452            if (swiper.params.freeModeSticky) {
24453              // When wheel scrolling starts with sticky (aka snap) enabled, then detect
24454              // the end of a momentum scroll by storing recent (N=15?) wheel events.
24455              // 1. do all N events have decreasing or same (absolute value) delta?
24456              // 2. did all N events arrive in the last M (M=500?) msecs?
24457              // 3. does the earliest event have an (absolute value) delta that's
24458              //    at least P (P=1?) larger than the most recent event's delta?
24459              // 4. does the latest event have a delta that's smaller than Q (Q=6?) pixels?
24460              // If 1-4 are "yes" then we're near the end of a momuntum scroll deceleration.
24461              // Snap immediately and ignore remaining wheel events in this scroll.
24462              // See comment above for "remaining wheel events in this scroll" determination.
24463              // If 1-4 aren't satisfied, then wait to snap until 500ms after the last event.
24464              clearTimeout(swiper.mousewheel.timeout);
24465              swiper.mousewheel.timeout = undefined;
24466              var recentWheelEvents = swiper.mousewheel.recentWheelEvents;
24467              if (recentWheelEvents.length >= 15) {
24468                recentWheelEvents.shift(); // only store the last N events
24469              }
24470              var prevEvent = recentWheelEvents.length ? recentWheelEvents[recentWheelEvents.length - 1] : undefined;
24471              var firstEvent = recentWheelEvents[0];
24472              recentWheelEvents.push(newEvent);
24473              if (prevEvent && (newEvent.delta > prevEvent.delta || newEvent.direction !== prevEvent.direction)) {
24474                // Increasing or reverse-sign delta means the user started scrolling again. Clear the wheel event log.
24475                recentWheelEvents.splice(0);
24476              } else if (recentWheelEvents.length >= 15
24477                  && newEvent.time - firstEvent.time < 500
24478                  && firstEvent.delta - newEvent.delta >= 1
24479                  && newEvent.delta <= 6
24480              ) {
24481                // We're at the end of the deceleration of a momentum scroll, so there's no need
24482                // to wait for more events. Snap ASAP on the next tick.
24483                // Also, because there's some remaining momentum we'll bias the snap in the
24484                // direction of the ongoing scroll because it's better UX for the scroll to snap
24485                // in the same direction as the scroll instead of reversing to snap.  Therefore,
24486                // if it's already scrolled more than 20% in the current direction, keep going.
24487                var snapToThreshold = delta > 0 ? 0.8 : 0.2;
24488                swiper.mousewheel.lastEventBeforeSnap = newEvent;
24489                recentWheelEvents.splice(0);
24490                swiper.mousewheel.timeout = Utils.nextTick(function () {
24491                  swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);
24492                }, 0); // no delay; move on next tick
24493              }
24494              if (!swiper.mousewheel.timeout) {
24495                // if we get here, then we haven't detected the end of a momentum scroll, so
24496                // we'll consider a scroll "complete" when there haven't been any wheel events
24497                // for 500ms.
24498                swiper.mousewheel.timeout = Utils.nextTick(function () {
24499                  var snapToThreshold = 0.5;
24500                  swiper.mousewheel.lastEventBeforeSnap = newEvent;
24501                  recentWheelEvents.splice(0);
24502                  swiper.slideToClosest(swiper.params.speed, true, undefined, snapToThreshold);
24503                }, 500);
24504              }
24505            }
24506  
24507            // Emit event
24508            if (!ignoreWheelEvents) { swiper.emit('scroll', e); }
24509  
24510            // Stop autoplay
24511            if (swiper.params.autoplay && swiper.params.autoplayDisableOnInteraction) { swiper.autoplay.stop(); }
24512            // Return page scroll on edge positions
24513            if (position === swiper.minTranslate() || position === swiper.maxTranslate()) { return true; }
24514          }
24515        }
24516  
24517        if (e.preventDefault) { e.preventDefault(); }
24518        else { e.returnValue = false; }
24519        return false;
24520      },
24521      enable: function enable() {
24522        var swiper = this;
24523        var event = Mousewheel.event();
24524        if (swiper.params.cssMode) {
24525          swiper.wrapperEl.removeEventListener(event, swiper.mousewheel.handle);
24526          return true;
24527        }
24528        if (!event) { return false; }
24529        if (swiper.mousewheel.enabled) { return false; }
24530        var target = swiper.$el;
24531        if (swiper.params.mousewheel.eventsTarged !== 'container') {
24532          target = $(swiper.params.mousewheel.eventsTarged);
24533        }
24534        target.on('mouseenter', swiper.mousewheel.handleMouseEnter);
24535        target.on('mouseleave', swiper.mousewheel.handleMouseLeave);
24536        target.on(event, swiper.mousewheel.handle);
24537        swiper.mousewheel.enabled = true;
24538        return true;
24539      },
24540      disable: function disable() {
24541        var swiper = this;
24542        var event = Mousewheel.event();
24543        if (swiper.params.cssMode) {
24544          swiper.wrapperEl.addEventListener(event, swiper.mousewheel.handle);
24545          return true;
24546        }
24547        if (!event) { return false; }
24548        if (!swiper.mousewheel.enabled) { return false; }
24549        var target = swiper.$el;
24550        if (swiper.params.mousewheel.eventsTarged !== 'container') {
24551          target = $(swiper.params.mousewheel.eventsTarged);
24552        }
24553        target.off(event, swiper.mousewheel.handle);
24554        swiper.mousewheel.enabled = false;
24555        return true;
24556      },
24557    };
24558  
24559    var Mousewheel$1 = {
24560      name: 'mousewheel',
24561      params: {
24562        mousewheel: {
24563          enabled: false,
24564          releaseOnEdges: false,
24565          invert: false,
vendor: 57,613 bytes, lines 24566-25970
24566          forceToAxis: false,
24567          sensitivity: 1,
24568          eventsTarged: 'container',
24569        },
24570      },
24571      create: function create() {
24572        var swiper = this;
24573        Utils.extend(swiper, {
24574          mousewheel: {
24575            enabled: false,
24576            enable: Mousewheel.enable.bind(swiper),
24577            disable: Mousewheel.disable.bind(swiper),
24578            handle: Mousewheel.handle.bind(swiper),
24579            handleMouseEnter: Mousewheel.handleMouseEnter.bind(swiper),
24580            handleMouseLeave: Mousewheel.handleMouseLeave.bind(swiper),
24581            lastScrollTime: Utils.now(),
24582            lastEventBeforeSnap: undefined,
24583            recentWheelEvents: [],
24584          },
24585        });
24586      },
24587      on: {
24588        init: function init() {
24589          var swiper = this;
24590          if (!swiper.params.mousewheel.enabled && swiper.params.cssMode) {
24591            swiper.mousewheel.disable();
24592          }
24593          if (swiper.params.mousewheel.enabled) { swiper.mousewheel.enable(); }
24594        },
24595        destroy: function destroy() {
24596          var swiper = this;
24597          if (swiper.params.cssMode) {
24598            swiper.mousewheel.enable();
24599          }
24600          if (swiper.mousewheel.enabled) { swiper.mousewheel.disable(); }
24601        },
24602      },
24603    };
24604  
24605    var Navigation = {
24606      update: function update() {
24607        // Update Navigation Buttons
24608        var swiper = this;
24609        var params = swiper.params.navigation;
24610  
24611        if (swiper.params.loop) { return; }
24612        var ref = swiper.navigation;
24613        var $nextEl = ref.$nextEl;
24614        var $prevEl = ref.$prevEl;
24615  
24616        if ($prevEl && $prevEl.length > 0) {
24617          if (swiper.isBeginning) {
24618            $prevEl.addClass(params.disabledClass);
24619          } else {
24620            $prevEl.removeClass(params.disabledClass);
24621          }
24622          $prevEl[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
24623        }
24624        if ($nextEl && $nextEl.length > 0) {
24625          if (swiper.isEnd) {
24626            $nextEl.addClass(params.disabledClass);
24627          } else {
24628            $nextEl.removeClass(params.disabledClass);
24629          }
24630          $nextEl[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
24631        }
24632      },
24633      onPrevClick: function onPrevClick(e) {
24634        var swiper = this;
24635        e.preventDefault();
24636        if (swiper.isBeginning && !swiper.params.loop) { return; }
24637        swiper.slidePrev();
24638      },
24639      onNextClick: function onNextClick(e) {
24640        var swiper = this;
24641        e.preventDefault();
24642        if (swiper.isEnd && !swiper.params.loop) { return; }
24643        swiper.slideNext();
24644      },
24645      init: function init() {
24646        var swiper = this;
24647        var params = swiper.params.navigation;
24648        if (!(params.nextEl || params.prevEl)) { return; }
24649  
24650        var $nextEl;
24651        var $prevEl;
24652        if (params.nextEl) {
24653          $nextEl = $(params.nextEl);
24654          if (
24655            swiper.params.uniqueNavElements
24656            && typeof params.nextEl === 'string'
24657            && $nextEl.length > 1
24658            && swiper.$el.find(params.nextEl).length === 1
24659          ) {
24660            $nextEl = swiper.$el.find(params.nextEl);
24661          }
24662        }
24663        if (params.prevEl) {
24664          $prevEl = $(params.prevEl);
24665          if (
24666            swiper.params.uniqueNavElements
24667            && typeof params.prevEl === 'string'
24668            && $prevEl.length > 1
24669            && swiper.$el.find(params.prevEl).length === 1
24670          ) {
24671            $prevEl = swiper.$el.find(params.prevEl);
24672          }
24673        }
24674  
24675        if ($nextEl && $nextEl.length > 0) {
24676          $nextEl.on('click', swiper.navigation.onNextClick);
24677        }
24678        if ($prevEl && $prevEl.length > 0) {
24679          $prevEl.on('click', swiper.navigation.onPrevClick);
24680        }
24681  
24682        Utils.extend(swiper.navigation, {
24683          $nextEl: $nextEl,
24684          nextEl: $nextEl && $nextEl[0],
24685          $prevEl: $prevEl,
24686          prevEl: $prevEl && $prevEl[0],
24687        });
24688      },
24689      destroy: function destroy() {
24690        var swiper = this;
24691        var ref = swiper.navigation;
24692        var $nextEl = ref.$nextEl;
24693        var $prevEl = ref.$prevEl;
24694        if ($nextEl && $nextEl.length) {
24695          $nextEl.off('click', swiper.navigation.onNextClick);
24696          $nextEl.removeClass(swiper.params.navigation.disabledClass);
24697        }
24698        if ($prevEl && $prevEl.length) {
24699          $prevEl.off('click', swiper.navigation.onPrevClick);
24700          $prevEl.removeClass(swiper.params.navigation.disabledClass);
24701        }
24702      },
24703    };
24704  
24705    var Navigation$1 = {
24706      name: 'navigation',
24707      params: {
24708        navigation: {
24709          nextEl: null,
24710          prevEl: null,
24711  
24712          hideOnClick: false,
24713          disabledClass: 'swiper-button-disabled',
24714          hiddenClass: 'swiper-button-hidden',
24715          lockClass: 'swiper-button-lock',
24716        },
24717      },
24718      create: function create() {
24719        var swiper = this;
24720        Utils.extend(swiper, {
24721          navigation: {
24722            init: Navigation.init.bind(swiper),
24723            update: Navigation.update.bind(swiper),
24724            destroy: Navigation.destroy.bind(swiper),
24725            onNextClick: Navigation.onNextClick.bind(swiper),
24726            onPrevClick: Navigation.onPrevClick.bind(swiper),
24727          },
24728        });
24729      },
24730      on: {
24731        init: function init() {
24732          var swiper = this;
24733          swiper.navigation.init();
24734          swiper.navigation.update();
24735        },
24736        toEdge: function toEdge() {
24737          var swiper = this;
24738          swiper.navigation.update();
24739        },
24740        fromEdge: function fromEdge() {
24741          var swiper = this;
24742          swiper.navigation.update();
24743        },
24744        destroy: function destroy() {
24745          var swiper = this;
24746          swiper.navigation.destroy();
24747        },
24748        click: function click(e) {
24749          var swiper = this;
24750          var ref = swiper.navigation;
24751          var $nextEl = ref.$nextEl;
24752          var $prevEl = ref.$prevEl;
24753          if (
24754            swiper.params.navigation.hideOnClick
24755            && !$(e.target).is($prevEl)
24756            && !$(e.target).is($nextEl)
24757          ) {
24758            var isHidden;
24759            if ($nextEl) {
24760              isHidden = $nextEl.hasClass(swiper.params.navigation.hiddenClass);
24761            } else if ($prevEl) {
24762              isHidden = $prevEl.hasClass(swiper.params.navigation.hiddenClass);
24763            }
24764            if (isHidden === true) {
24765              swiper.emit('navigationShow', swiper);
24766            } else {
24767              swiper.emit('navigationHide', swiper);
24768            }
24769            if ($nextEl) {
24770              $nextEl.toggleClass(swiper.params.navigation.hiddenClass);
24771            }
24772            if ($prevEl) {
24773              $prevEl.toggleClass(swiper.params.navigation.hiddenClass);
24774            }
24775          }
24776        },
24777      },
24778    };
24779  
24780    var Pagination = {
24781      update: function update() {
24782        // Render || Update Pagination bullets/items
24783        var swiper = this;
24784        var rtl = swiper.rtl;
24785        var params = swiper.params.pagination;
24786        if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) { return; }
24787        var slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
24788        var $el = swiper.pagination.$el;
24789        // Current/Total
24790        var current;
24791        var total = swiper.params.loop ? Math.ceil((slidesLength - (swiper.loopedSlides * 2)) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
24792        if (swiper.params.loop) {
24793          current = Math.ceil((swiper.activeIndex - swiper.loopedSlides) / swiper.params.slidesPerGroup);
24794          if (current > slidesLength - 1 - (swiper.loopedSlides * 2)) {
24795            current -= (slidesLength - (swiper.loopedSlides * 2));
24796          }
24797          if (current > total - 1) { current -= total; }
24798          if (current < 0 && swiper.params.paginationType !== 'bullets') { current = total + current; }
24799        } else if (typeof swiper.snapIndex !== 'undefined') {
24800          current = swiper.snapIndex;
24801        } else {
24802          current = swiper.activeIndex || 0;
24803        }
24804        // Types
24805        if (params.type === 'bullets' && swiper.pagination.bullets && swiper.pagination.bullets.length > 0) {
24806          var bullets = swiper.pagination.bullets;
24807          var firstIndex;
24808          var lastIndex;
24809          var midIndex;
24810          if (params.dynamicBullets) {
24811            swiper.pagination.bulletSize = bullets.eq(0)[swiper.isHorizontal() ? 'outerWidth' : 'outerHeight'](true);
24812            $el.css(swiper.isHorizontal() ? 'width' : 'height', ((swiper.pagination.bulletSize * (params.dynamicMainBullets + 4)) + "px"));
24813            if (params.dynamicMainBullets > 1 && swiper.previousIndex !== undefined) {
24814              swiper.pagination.dynamicBulletIndex += (current - swiper.previousIndex);
24815              if (swiper.pagination.dynamicBulletIndex > (params.dynamicMainBullets - 1)) {
24816                swiper.pagination.dynamicBulletIndex = params.dynamicMainBullets - 1;
24817              } else if (swiper.pagination.dynamicBulletIndex < 0) {
24818                swiper.pagination.dynamicBulletIndex = 0;
24819              }
24820            }
24821            firstIndex = current - swiper.pagination.dynamicBulletIndex;
24822            lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);
24823            midIndex = (lastIndex + firstIndex) / 2;
24824          }
24825          bullets.removeClass(((params.bulletActiveClass) + " " + (params.bulletActiveClass) + "-next " + (params.bulletActiveClass) + "-next-next " + (params.bulletActiveClass) + "-prev " + (params.bulletActiveClass) + "-prev-prev " + (params.bulletActiveClass) + "-main"));
24826          if ($el.length > 1) {
24827            bullets.each(function (index, bullet) {
24828              var $bullet = $(bullet);
24829              var bulletIndex = $bullet.index();
24830              if (bulletIndex === current) {
24831                $bullet.addClass(params.bulletActiveClass);
24832              }
24833              if (params.dynamicBullets) {
24834                if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {
24835                  $bullet.addClass(((params.bulletActiveClass) + "-main"));
24836                }
24837                if (bulletIndex === firstIndex) {
24838                  $bullet
24839                    .prev()
24840                    .addClass(((params.bulletActiveClass) + "-prev"))
24841                    .prev()
24842                    .addClass(((params.bulletActiveClass) + "-prev-prev"));
24843                }
24844                if (bulletIndex === lastIndex) {
24845                  $bullet
24846                    .next()
24847                    .addClass(((params.bulletActiveClass) + "-next"))
24848                    .next()
24849                    .addClass(((params.bulletActiveClass) + "-next-next"));
24850                }
24851              }
24852            });
24853          } else {
24854            var $bullet = bullets.eq(current);
24855            var bulletIndex = $bullet.index();
24856            $bullet.addClass(params.bulletActiveClass);
24857            if (params.dynamicBullets) {
24858              var $firstDisplayedBullet = bullets.eq(firstIndex);
24859              var $lastDisplayedBullet = bullets.eq(lastIndex);
24860              for (var i = firstIndex; i <= lastIndex; i += 1) {
24861                bullets.eq(i).addClass(((params.bulletActiveClass) + "-main"));
24862              }
24863              if (swiper.params.loop) {
24864                if (bulletIndex >= bullets.length - params.dynamicMainBullets) {
24865                  for (var i$1 = params.dynamicMainBullets; i$1 >= 0; i$1 -= 1) {
24866                    bullets.eq(bullets.length - i$1).addClass(((params.bulletActiveClass) + "-main"));
24867                  }
24868                  bullets.eq(bullets.length - params.dynamicMainBullets - 1).addClass(((params.bulletActiveClass) + "-prev"));
24869                } else {
24870                  $firstDisplayedBullet
24871                    .prev()
24872                    .addClass(((params.bulletActiveClass) + "-prev"))
24873                    .prev()
24874                    .addClass(((params.bulletActiveClass) + "-prev-prev"));
24875                  $lastDisplayedBullet
24876                    .next()
24877                    .addClass(((params.bulletActiveClass) + "-next"))
24878                    .next()
24879                    .addClass(((params.bulletActiveClass) + "-next-next"));
24880                }
24881              } else {
24882                $firstDisplayedBullet
24883                  .prev()
24884                  .addClass(((params.bulletActiveClass) + "-prev"))
24885                  .prev()
24886                  .addClass(((params.bulletActiveClass) + "-prev-prev"));
24887                $lastDisplayedBullet
24888                  .next()
24889                  .addClass(((params.bulletActiveClass) + "-next"))
24890                  .next()
24891                  .addClass(((params.bulletActiveClass) + "-next-next"));
24892              }
24893            }
24894          }
24895          if (params.dynamicBullets) {
24896            var dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);
24897            var bulletsOffset = (((swiper.pagination.bulletSize * dynamicBulletsLength) - (swiper.pagination.bulletSize)) / 2) - (midIndex * swiper.pagination.bulletSize);
24898            var offsetProp = rtl ? 'right' : 'left';
24899            bullets.css(swiper.isHorizontal() ? offsetProp : 'top', (bulletsOffset + "px"));
24900          }
24901        }
24902        if (params.type === 'fraction') {
24903          $el.find(("." + (params.currentClass))).text(params.formatFractionCurrent(current + 1));
24904          $el.find(("." + (params.totalClass))).text(params.formatFractionTotal(total));
24905        }
24906        if (params.type === 'progressbar') {
24907          var progressbarDirection;
24908          if (params.progressbarOpposite) {
24909            progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';
24910          } else {
24911            progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';
24912          }
24913          var scale = (current + 1) / total;
24914          var scaleX = 1;
24915          var scaleY = 1;
24916          if (progressbarDirection === 'horizontal') {
24917            scaleX = scale;
24918          } else {
24919            scaleY = scale;
24920          }
24921          $el.find(("." + (params.progressbarFillClass))).transform(("translate3d(0,0,0) scaleX(" + scaleX + ") scaleY(" + scaleY + ")")).transition(swiper.params.speed);
24922        }
24923        if (params.type === 'custom' && params.renderCustom) {
24924          $el.html(params.renderCustom(swiper, current + 1, total));
24925          swiper.emit('paginationRender', swiper, $el[0]);
24926        } else {
24927          swiper.emit('paginationUpdate', swiper, $el[0]);
24928        }
24929        $el[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
24930      },
24931      render: function render() {
24932        // Render Container
24933        var swiper = this;
24934        var params = swiper.params.pagination;
24935        if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) { return; }
24936        var slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
24937  
24938        var $el = swiper.pagination.$el;
24939        var paginationHTML = '';
24940        if (params.type === 'bullets') {
24941          var numberOfBullets = swiper.params.loop ? Math.ceil((slidesLength - (swiper.loopedSlides * 2)) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
24942          for (var i = 0; i < numberOfBullets; i += 1) {
24943            if (params.renderBullet) {
24944              paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);
24945            } else {
24946              paginationHTML += "<" + (params.bulletElement) + " class=\"" + (params.bulletClass) + "\"></" + (params.bulletElement) + ">";
24947            }
24948          }
24949          $el.html(paginationHTML);
24950          swiper.pagination.bullets = $el.find(("." + (params.bulletClass)));
24951        }
24952        if (params.type === 'fraction') {
24953          if (params.renderFraction) {
24954            paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);
24955          } else {
24956            paginationHTML = "<span class=\"" + (params.currentClass) + "\"></span>"
24957            + ' / '
24958            + "<span class=\"" + (params.totalClass) + "\"></span>";
24959          }
24960          $el.html(paginationHTML);
24961        }
24962        if (params.type === 'progressbar') {
24963          if (params.renderProgressbar) {
24964            paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);
24965          } else {
24966            paginationHTML = "<span class=\"" + (params.progressbarFillClass) + "\"></span>";
24967          }
24968          $el.html(paginationHTML);
24969        }
24970        if (params.type !== 'custom') {
24971          swiper.emit('paginationRender', swiper.pagination.$el[0]);
24972        }
24973      },
24974      init: function init() {
24975        var swiper = this;
24976        var params = swiper.params.pagination;
24977        if (!params.el) { return; }
24978  
24979        var $el = $(params.el);
24980        if ($el.length === 0) { return; }
24981  
24982        if (
24983          swiper.params.uniqueNavElements
24984          && typeof params.el === 'string'
24985          && $el.length > 1
24986          && swiper.$el.find(params.el).length === 1
24987        ) {
24988          $el = swiper.$el.find(params.el);
24989        }
24990  
24991        if (params.type === 'bullets' && params.clickable) {
24992          $el.addClass(params.clickableClass);
24993        }
24994  
24995        $el.addClass(params.modifierClass + params.type);
24996  
24997        if (params.type === 'bullets' && params.dynamicBullets) {
24998          $el.addClass(("" + (params.modifierClass) + (params.type) + "-dynamic"));
24999          swiper.pagination.dynamicBulletIndex = 0;
25000          if (params.dynamicMainBullets < 1) {
25001            params.dynamicMainBullets = 1;
25002          }
25003        }
25004        if (params.type === 'progressbar' && params.progressbarOpposite) {
25005          $el.addClass(params.progressbarOppositeClass);
25006        }
25007  
25008        if (params.clickable) {
25009          $el.on('click', ("." + (params.bulletClass)), function onClick(e) {
25010            e.preventDefault();
25011            var index = $(this).index() * swiper.params.slidesPerGroup;
25012            if (swiper.params.loop) { index += swiper.loopedSlides; }
25013            swiper.slideTo(index);
25014          });
25015        }
25016  
25017        Utils.extend(swiper.pagination, {
25018          $el: $el,
25019          el: $el[0],
25020        });
25021      },
25022      destroy: function destroy() {
25023        var swiper = this;
25024        var params = swiper.params.pagination;
25025        if (!params.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0) { return; }
25026        var $el = swiper.pagination.$el;
25027  
25028        $el.removeClass(params.hiddenClass);
25029        $el.removeClass(params.modifierClass + params.type);
25030        if (swiper.pagination.bullets) { swiper.pagination.bullets.removeClass(params.bulletActiveClass); }
25031        if (params.clickable) {
25032          $el.off('click', ("." + (params.bulletClass)));
25033        }
25034      },
25035    };
25036  
25037    var Pagination$1 = {
25038      name: 'pagination',
25039      params: {
25040        pagination: {
25041          el: null,
25042          bulletElement: 'span',
25043          clickable: false,
25044          hideOnClick: false,
25045          renderBullet: null,
25046          renderProgressbar: null,
25047          renderFraction: null,
25048          renderCustom: null,
25049          progressbarOpposite: false,
25050          type: 'bullets', // 'bullets' or 'progressbar' or 'fraction' or 'custom'
25051          dynamicBullets: false,
25052          dynamicMainBullets: 1,
25053          formatFractionCurrent: function (number) { return number; },
25054          formatFractionTotal: function (number) { return number; },
25055          bulletClass: 'swiper-pagination-bullet',
25056          bulletActiveClass: 'swiper-pagination-bullet-active',
25057          modifierClass: 'swiper-pagination-', // NEW
25058          currentClass: 'swiper-pagination-current',
25059          totalClass: 'swiper-pagination-total',
25060          hiddenClass: 'swiper-pagination-hidden',
25061          progressbarFillClass: 'swiper-pagination-progressbar-fill',
25062          progressbarOppositeClass: 'swiper-pagination-progressbar-opposite',
25063          clickableClass: 'swiper-pagination-clickable', // NEW
25064          lockClass: 'swiper-pagination-lock',
25065        },
25066      },
25067      create: function create() {
25068        var swiper = this;
25069        Utils.extend(swiper, {
25070          pagination: {
25071            init: Pagination.init.bind(swiper),
25072            render: Pagination.render.bind(swiper),
25073            update: Pagination.update.bind(swiper),
25074            destroy: Pagination.destroy.bind(swiper),
25075            dynamicBulletIndex: 0,
25076          },
25077        });
25078      },
25079      on: {
25080        init: function init() {
25081          var swiper = this;
25082          swiper.pagination.init();
25083          swiper.pagination.render();
25084          swiper.pagination.update();
25085        },
25086        activeIndexChange: function activeIndexChange() {
25087          var swiper = this;
25088          if (swiper.params.loop) {
25089            swiper.pagination.update();
25090          } else if (typeof swiper.snapIndex === 'undefined') {
25091            swiper.pagination.update();
25092          }
25093        },
25094        snapIndexChange: function snapIndexChange() {
25095          var swiper = this;
25096          if (!swiper.params.loop) {
25097            swiper.pagination.update();
25098          }
25099        },
25100        slidesLengthChange: function slidesLengthChange() {
25101          var swiper = this;
25102          if (swiper.params.loop) {
25103            swiper.pagination.render();
25104            swiper.pagination.update();
25105          }
25106        },
25107        snapGridLengthChange: function snapGridLengthChange() {
25108          var swiper = this;
25109          if (!swiper.params.loop) {
25110            swiper.pagination.render();
25111            swiper.pagination.update();
25112          }
25113        },
25114        destroy: function destroy() {
25115          var swiper = this;
25116          swiper.pagination.destroy();
25117        },
25118        click: function click(e) {
25119          var swiper = this;
25120          if (
25121            swiper.params.pagination.el
25122            && swiper.params.pagination.hideOnClick
25123            && swiper.pagination.$el.length > 0
25124            && !$(e.target).hasClass(swiper.params.pagination.bulletClass)
25125          ) {
25126            var isHidden = swiper.pagination.$el.hasClass(swiper.params.pagination.hiddenClass);
25127            if (isHidden === true) {
25128              swiper.emit('paginationShow', swiper);
25129            } else {
25130              swiper.emit('paginationHide', swiper);
25131            }
25132            swiper.pagination.$el.toggleClass(swiper.params.pagination.hiddenClass);
25133          }
25134        },
25135      },
25136    };
25137  
25138    var Scrollbar = {
25139      setTranslate: function setTranslate() {
25140        var swiper = this;
25141        if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) { return; }
25142        var scrollbar = swiper.scrollbar;
25143        var rtl = swiper.rtlTranslate;
25144        var progress = swiper.progress;
25145        var dragSize = scrollbar.dragSize;
25146        var trackSize = scrollbar.trackSize;
25147        var $dragEl = scrollbar.$dragEl;
25148        var $el = scrollbar.$el;
25149        var params = swiper.params.scrollbar;
25150  
25151        var newSize = dragSize;
25152        var newPos = (trackSize - dragSize) * progress;
25153        if (rtl) {
25154          newPos = -newPos;
25155          if (newPos > 0) {
25156            newSize = dragSize - newPos;
25157            newPos = 0;
25158          } else if (-newPos + dragSize > trackSize) {
25159            newSize = trackSize + newPos;
25160          }
25161        } else if (newPos < 0) {
25162          newSize = dragSize + newPos;
25163          newPos = 0;
25164        } else if (newPos + dragSize > trackSize) {
25165          newSize = trackSize - newPos;
25166        }
25167        if (swiper.isHorizontal()) {
25168          $dragEl.transform(("translate3d(" + newPos + "px, 0, 0)"));
25169          $dragEl[0].style.width = newSize + "px";
25170        } else {
25171          $dragEl.transform(("translate3d(0px, " + newPos + "px, 0)"));
25172          $dragEl[0].style.height = newSize + "px";
25173        }
25174        if (params.hide) {
25175          clearTimeout(swiper.scrollbar.timeout);
25176          $el[0].style.opacity = 1;
25177          swiper.scrollbar.timeout = setTimeout(function () {
25178            $el[0].style.opacity = 0;
25179            $el.transition(400);
25180          }, 1000);
25181        }
25182      },
25183      setTransition: function setTransition(duration) {
25184        var swiper = this;
25185        if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) { return; }
25186        swiper.scrollbar.$dragEl.transition(duration);
25187      },
25188      updateSize: function updateSize() {
25189        var swiper = this;
25190        if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) { return; }
25191  
25192        var scrollbar = swiper.scrollbar;
25193        var $dragEl = scrollbar.$dragEl;
25194        var $el = scrollbar.$el;
25195  
25196        $dragEl[0].style.width = '';
25197        $dragEl[0].style.height = '';
25198        var trackSize = swiper.isHorizontal() ? $el[0].offsetWidth : $el[0].offsetHeight;
25199  
25200        var divider = swiper.size / swiper.virtualSize;
25201        var moveDivider = divider * (trackSize / swiper.size);
25202        var dragSize;
25203        if (swiper.params.scrollbar.dragSize === 'auto') {
25204          dragSize = trackSize * divider;
25205        } else {
25206          dragSize = parseInt(swiper.params.scrollbar.dragSize, 10);
25207        }
25208  
25209        if (swiper.isHorizontal()) {
25210          $dragEl[0].style.width = dragSize + "px";
25211        } else {
25212          $dragEl[0].style.height = dragSize + "px";
25213        }
25214  
25215        if (divider >= 1) {
25216          $el[0].style.display = 'none';
25217        } else {
25218          $el[0].style.display = '';
25219        }
25220        if (swiper.params.scrollbar.hide) {
25221          $el[0].style.opacity = 0;
25222        }
25223        Utils.extend(scrollbar, {
25224          trackSize: trackSize,
25225          divider: divider,
25226          moveDivider: moveDivider,
25227          dragSize: dragSize,
25228        });
25229        scrollbar.$el[swiper.params.watchOverflow && swiper.isLocked ? 'addClass' : 'removeClass'](swiper.params.scrollbar.lockClass);
25230      },
25231      getPointerPosition: function getPointerPosition(e) {
25232        var swiper = this;
25233        if (swiper.isHorizontal()) {
25234          return ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].clientX : e.clientX);
25235        }
25236        return ((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].clientY : e.clientY);
25237      },
25238      setDragPosition: function setDragPosition(e) {
25239        var swiper = this;
25240        var scrollbar = swiper.scrollbar;
25241        var rtl = swiper.rtlTranslate;
25242        var $el = scrollbar.$el;
25243        var dragSize = scrollbar.dragSize;
25244        var trackSize = scrollbar.trackSize;
25245        var dragStartPos = scrollbar.dragStartPos;
25246  
25247        var positionRatio;
25248        positionRatio = ((scrollbar.getPointerPosition(e)) - $el.offset()[swiper.isHorizontal() ? 'left' : 'top']
25249          - (dragStartPos !== null ? dragStartPos : dragSize / 2)) / (trackSize - dragSize);
25250        positionRatio = Math.max(Math.min(positionRatio, 1), 0);
25251        if (rtl) {
25252          positionRatio = 1 - positionRatio;
25253        }
25254  
25255        var position = swiper.minTranslate() + ((swiper.maxTranslate() - swiper.minTranslate()) * positionRatio);
25256  
25257        swiper.updateProgress(position);
25258        swiper.setTranslate(position);
25259        swiper.updateActiveIndex();
25260        swiper.updateSlidesClasses();
25261      },
25262      onDragStart: function onDragStart(e) {
25263        var swiper = this;
25264        var params = swiper.params.scrollbar;
25265        var scrollbar = swiper.scrollbar;
25266        var $wrapperEl = swiper.$wrapperEl;
25267        var $el = scrollbar.$el;
25268        var $dragEl = scrollbar.$dragEl;
25269        swiper.scrollbar.isTouched = true;
25270        swiper.scrollbar.dragStartPos = (e.target === $dragEl[0] || e.target === $dragEl)
25271          ? scrollbar.getPointerPosition(e) - e.target.getBoundingClientRect()[swiper.isHorizontal() ? 'left' : 'top'] : null;
25272        e.preventDefault();
25273        e.stopPropagation();
25274  
25275        $wrapperEl.transition(100);
25276        $dragEl.transition(100);
25277        scrollbar.setDragPosition(e);
25278  
25279        clearTimeout(swiper.scrollbar.dragTimeout);
25280  
25281        $el.transition(0);
25282        if (params.hide) {
25283          $el.css('opacity', 1);
25284        }
25285        if (swiper.params.cssMode) {
25286          swiper.$wrapperEl.css('scroll-snap-type', 'none');
25287        }
25288        swiper.emit('scrollbarDragStart', e);
25289      },
25290      onDragMove: function onDragMove(e) {
25291        var swiper = this;
25292        var scrollbar = swiper.scrollbar;
25293        var $wrapperEl = swiper.$wrapperEl;
25294        var $el = scrollbar.$el;
25295        var $dragEl = scrollbar.$dragEl;
25296  
25297        if (!swiper.scrollbar.isTouched) { return; }
25298        if (e.preventDefault) { e.preventDefault(); }
25299        else { e.returnValue = false; }
25300        scrollbar.setDragPosition(e);
25301        $wrapperEl.transition(0);
25302        $el.transition(0);
25303        $dragEl.transition(0);
25304        swiper.emit('scrollbarDragMove', e);
25305      },
25306      onDragEnd: function onDragEnd(e) {
25307        var swiper = this;
25308  
25309        var params = swiper.params.scrollbar;
25310        var scrollbar = swiper.scrollbar;
25311        var $wrapperEl = swiper.$wrapperEl;
25312        var $el = scrollbar.$el;
25313  
25314        if (!swiper.scrollbar.isTouched) { return; }
25315        swiper.scrollbar.isTouched = false;
25316        if (swiper.params.cssMode) {
25317          swiper.$wrapperEl.css('scroll-snap-type', '');
25318          $wrapperEl.transition('');
25319        }
25320        if (params.hide) {
25321          clearTimeout(swiper.scrollbar.dragTimeout);
25322          swiper.scrollbar.dragTimeout = Utils.nextTick(function () {
25323            $el.css('opacity', 0);
25324            $el.transition(400);
25325          }, 1000);
25326        }
25327        swiper.emit('scrollbarDragEnd', e);
25328        if (params.snapOnRelease) {
25329          swiper.slideToClosest();
25330        }
25331      },
25332      enableDraggable: function enableDraggable() {
25333        var swiper = this;
25334        if (!swiper.params.scrollbar.el) { return; }
25335        var scrollbar = swiper.scrollbar;
25336        var touchEventsTouch = swiper.touchEventsTouch;
25337        var touchEventsDesktop = swiper.touchEventsDesktop;
25338        var params = swiper.params;
25339        var $el = scrollbar.$el;
25340        var target = $el[0];
25341        var activeListener = Support.passiveListener && params.passiveListeners ? { passive: false, capture: false } : false;
25342        var passiveListener = Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
25343        if (!Support.touch) {
25344          target.addEventListener(touchEventsDesktop.start, swiper.scrollbar.onDragStart, activeListener);
25345          doc.addEventListener(touchEventsDesktop.move, swiper.scrollbar.onDragMove, activeListener);
25346          doc.addEventListener(touchEventsDesktop.end, swiper.scrollbar.onDragEnd, passiveListener);
25347        } else {
25348          target.addEventListener(touchEventsTouch.start, swiper.scrollbar.onDragStart, activeListener);
25349          target.addEventListener(touchEventsTouch.move, swiper.scrollbar.onDragMove, activeListener);
25350          target.addEventListener(touchEventsTouch.end, swiper.scrollbar.onDragEnd, passiveListener);
25351        }
25352      },
25353      disableDraggable: function disableDraggable() {
25354        var swiper = this;
25355        if (!swiper.params.scrollbar.el) { return; }
25356        var scrollbar = swiper.scrollbar;
25357        var touchEventsTouch = swiper.touchEventsTouch;
25358        var touchEventsDesktop = swiper.touchEventsDesktop;
25359        var params = swiper.params;
25360        var $el = scrollbar.$el;
25361        var target = $el[0];
25362        var activeListener = Support.passiveListener && params.passiveListeners ? { passive: false, capture: false } : false;
25363        var passiveListener = Support.passiveListener && params.passiveListeners ? { passive: true, capture: false } : false;
25364        if (!Support.touch) {
25365          target.removeEventListener(touchEventsDesktop.start, swiper.scrollbar.onDragStart, activeListener);
25366          doc.removeEventListener(touchEventsDesktop.move, swiper.scrollbar.onDragMove, activeListener);
25367          doc.removeEventListener(touchEventsDesktop.end, swiper.scrollbar.onDragEnd, passiveListener);
25368        } else {
25369          target.removeEventListener(touchEventsTouch.start, swiper.scrollbar.onDragStart, activeListener);
25370          target.removeEventListener(touchEventsTouch.move, swiper.scrollbar.onDragMove, activeListener);
25371          target.removeEventListener(touchEventsTouch.end, swiper.scrollbar.onDragEnd, passiveListener);
25372        }
25373      },
25374      init: function init() {
25375        var swiper = this;
25376        if (!swiper.params.scrollbar.el) { return; }
25377        var scrollbar = swiper.scrollbar;
25378        var $swiperEl = swiper.$el;
25379        var params = swiper.params.scrollbar;
25380  
25381        var $el = $(params.el);
25382        if (swiper.params.uniqueNavElements && typeof params.el === 'string' && $el.length > 1 && $swiperEl.find(params.el).length === 1) {
25383          $el = $swiperEl.find(params.el);
25384        }
25385  
25386        var $dragEl = $el.find(("." + (swiper.params.scrollbar.dragClass)));
25387        if ($dragEl.length === 0) {
25388          $dragEl = $(("<div class=\"" + (swiper.params.scrollbar.dragClass) + "\"></div>"));
25389          $el.append($dragEl);
25390        }
25391  
25392        Utils.extend(scrollbar, {
25393          $el: $el,
25394          el: $el[0],
25395          $dragEl: $dragEl,
25396          dragEl: $dragEl[0],
25397        });
25398  
25399        if (params.draggable) {
25400          scrollbar.enableDraggable();
25401        }
25402      },
25403      destroy: function destroy() {
25404        var swiper = this;
25405        swiper.scrollbar.disableDraggable();
25406      },
25407    };
25408  
25409    var Scrollbar$1 = {
25410      name: 'scrollbar',
25411      params: {
25412        scrollbar: {
25413          el: null,
25414          dragSize: 'auto',
25415          hide: false,
25416          draggable: false,
25417          snapOnRelease: true,
25418          lockClass: 'swiper-scrollbar-lock',
25419          dragClass: 'swiper-scrollbar-drag',
25420        },
25421      },
25422      create: function create() {
25423        var swiper = this;
25424        Utils.extend(swiper, {
25425          scrollbar: {
25426            init: Scrollbar.init.bind(swiper),
25427            destroy: Scrollbar.destroy.bind(swiper),
25428            updateSize: Scrollbar.updateSize.bind(swiper),
25429            setTranslate: Scrollbar.setTranslate.bind(swiper),
25430            setTransition: Scrollbar.setTransition.bind(swiper),
25431            enableDraggable: Scrollbar.enableDraggable.bind(swiper),
25432            disableDraggable: Scrollbar.disableDraggable.bind(swiper),
25433            setDragPosition: Scrollbar.setDragPosition.bind(swiper),
25434            getPointerPosition: Scrollbar.getPointerPosition.bind(swiper),
25435            onDragStart: Scrollbar.onDragStart.bind(swiper),
25436            onDragMove: Scrollbar.onDragMove.bind(swiper),
25437            onDragEnd: Scrollbar.onDragEnd.bind(swiper),
25438            isTouched: false,
25439            timeout: null,
25440            dragTimeout: null,
25441          },
25442        });
25443      },
25444      on: {
25445        init: function init() {
25446          var swiper = this;
25447          swiper.scrollbar.init();
25448          swiper.scrollbar.updateSize();
25449          swiper.scrollbar.setTranslate();
25450        },
25451        update: function update() {
25452          var swiper = this;
25453          swiper.scrollbar.updateSize();
25454        },
25455        resize: function resize() {
25456          var swiper = this;
25457          swiper.scrollbar.updateSize();
25458        },
25459        observerUpdate: function observerUpdate() {
25460          var swiper = this;
25461          swiper.scrollbar.updateSize();
25462        },
25463        setTranslate: function setTranslate() {
25464          var swiper = this;
25465          swiper.scrollbar.setTranslate();
25466        },
25467        setTransition: function setTransition(duration) {
25468          var swiper = this;
25469          swiper.scrollbar.setTransition(duration);
25470        },
25471        destroy: function destroy() {
25472          var swiper = this;
25473          swiper.scrollbar.destroy();
25474        },
25475      },
25476    };
25477  
25478    var Parallax = {
25479      setTransform: function setTransform(el, progress) {
25480        var swiper = this;
25481        var rtl = swiper.rtl;
25482  
25483        var $el = $(el);
25484        var rtlFactor = rtl ? -1 : 1;
25485  
25486        var p = $el.attr('data-swiper-parallax') || '0';
25487        var x = $el.attr('data-swiper-parallax-x');
25488        var y = $el.attr('data-swiper-parallax-y');
25489        var scale = $el.attr('data-swiper-parallax-scale');
25490        var opacity = $el.attr('data-swiper-parallax-opacity');
25491  
25492        if (x || y) {
25493          x = x || '0';
25494          y = y || '0';
25495        } else if (swiper.isHorizontal()) {
25496          x = p;
25497          y = '0';
25498        } else {
25499          y = p;
25500          x = '0';
25501        }
25502  
25503        if ((x).indexOf('%') >= 0) {
25504          x = (parseInt(x, 10) * progress * rtlFactor) + "%";
25505        } else {
25506          x = (x * progress * rtlFactor) + "px";
25507        }
25508        if ((y).indexOf('%') >= 0) {
25509          y = (parseInt(y, 10) * progress) + "%";
25510        } else {
25511          y = (y * progress) + "px";
25512        }
25513  
25514        if (typeof opacity !== 'undefined' && opacity !== null) {
25515          var currentOpacity = opacity - ((opacity - 1) * (1 - Math.abs(progress)));
25516          $el[0].style.opacity = currentOpacity;
25517        }
25518        if (typeof scale === 'undefined' || scale === null) {
25519          $el.transform(("translate3d(" + x + ", " + y + ", 0px)"));
25520        } else {
25521          var currentScale = scale - ((scale - 1) * (1 - Math.abs(progress)));
25522          $el.transform(("translate3d(" + x + ", " + y + ", 0px) scale(" + currentScale + ")"));
25523        }
25524      },
25525      setTranslate: function setTranslate() {
25526        var swiper = this;
25527        var $el = swiper.$el;
25528        var slides = swiper.slides;
25529        var progress = swiper.progress;
25530        var snapGrid = swiper.snapGrid;
25531        $el.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]')
25532          .each(function (index, el) {
25533            swiper.parallax.setTransform(el, progress);
25534          });
25535        slides.each(function (slideIndex, slideEl) {
25536          var slideProgress = slideEl.progress;
25537          if (swiper.params.slidesPerGroup > 1 && swiper.params.slidesPerView !== 'auto') {
25538            slideProgress += Math.ceil(slideIndex / 2) - (progress * (snapGrid.length - 1));
25539          }
25540          slideProgress = Math.min(Math.max(slideProgress, -1), 1);
25541          $(slideEl).find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]')
25542            .each(function (index, el) {
25543              swiper.parallax.setTransform(el, slideProgress);
25544            });
25545        });
25546      },
25547      setTransition: function setTransition(duration) {
25548        if ( duration === void 0 ) duration = this.params.speed;
25549  
25550        var swiper = this;
25551        var $el = swiper.$el;
25552        $el.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]')
25553          .each(function (index, parallaxEl) {
25554            var $parallaxEl = $(parallaxEl);
25555            var parallaxDuration = parseInt($parallaxEl.attr('data-swiper-parallax-duration'), 10) || duration;
25556            if (duration === 0) { parallaxDuration = 0; }
25557            $parallaxEl.transition(parallaxDuration);
25558          });
25559      },
25560    };
25561  
25562    var Parallax$1 = {
25563      name: 'parallax',
25564      params: {
25565        parallax: {
25566          enabled: false,
25567        },
25568      },
25569      create: function create() {
25570        var swiper = this;
25571        Utils.extend(swiper, {
25572          parallax: {
25573            setTransform: Parallax.setTransform.bind(swiper),
25574            setTranslate: Parallax.setTranslate.bind(swiper),
25575            setTransition: Parallax.setTransition.bind(swiper),
25576          },
25577        });
25578      },
25579      on: {
25580        beforeInit: function beforeInit() {
25581          var swiper = this;
25582          if (!swiper.params.parallax.enabled) { return; }
25583          swiper.params.watchSlidesProgress = true;
25584          swiper.originalParams.watchSlidesProgress = true;
25585        },
25586        init: function init() {
25587          var swiper = this;
25588          if (!swiper.params.parallax.enabled) { return; }
25589          swiper.parallax.setTranslate();
25590        },
25591        setTranslate: function setTranslate() {
25592          var swiper = this;
25593          if (!swiper.params.parallax.enabled) { return; }
25594          swiper.parallax.setTranslate();
25595        },
25596        setTransition: function setTransition(duration) {
25597          var swiper = this;
25598          if (!swiper.params.parallax.enabled) { return; }
25599          swiper.parallax.setTransition(duration);
25600        },
25601      },
25602    };
25603  
25604    var Zoom = {
25605      // Calc Scale From Multi-touches
25606      getDistanceBetweenTouches: function getDistanceBetweenTouches(e) {
25607        if (e.targetTouches.length < 2) { return 1; }
25608        var x1 = e.targetTouches[0].pageX;
25609        var y1 = e.targetTouches[0].pageY;
25610        var x2 = e.targetTouches[1].pageX;
25611        var y2 = e.targetTouches[1].pageY;
25612        var distance = Math.sqrt((Math.pow( (x2 - x1), 2 )) + (Math.pow( (y2 - y1), 2 )));
25613        return distance;
25614      },
25615      // Events
25616      onGestureStart: function onGestureStart(e) {
25617        var swiper = this;
25618        var params = swiper.params.zoom;
25619        var zoom = swiper.zoom;
25620        var gesture = zoom.gesture;
25621        zoom.fakeGestureTouched = false;
25622        zoom.fakeGestureMoved = false;
25623        if (!Support.gestures) {
25624          if (e.type !== 'touchstart' || (e.type === 'touchstart' && e.targetTouches.length < 2)) {
25625            return;
25626          }
25627          zoom.fakeGestureTouched = true;
25628          gesture.scaleStart = Zoom.getDistanceBetweenTouches(e);
25629        }
25630        if (!gesture.$slideEl || !gesture.$slideEl.length) {
25631          gesture.$slideEl = $(e.target).closest('.swiper-slide');
25632          if (gesture.$slideEl.length === 0) { gesture.$slideEl = swiper.slides.eq(swiper.activeIndex); }
25633          gesture.$imageEl = gesture.$slideEl.find('img, svg, canvas');
25634          gesture.$imageWrapEl = gesture.$imageEl.parent(("." + (params.containerClass)));
25635          gesture.maxRatio = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
25636          if (gesture.$imageWrapEl.length === 0) {
25637            gesture.$imageEl = undefined;
25638            return;
25639          }
25640        }
25641        gesture.$imageEl.transition(0);
25642        swiper.zoom.isScaling = true;
25643      },
25644      onGestureChange: function onGestureChange(e) {
25645        var swiper = this;
25646        var params = swiper.params.zoom;
25647        var zoom = swiper.zoom;
25648        var gesture = zoom.gesture;
25649        if (!Support.gestures) {
25650          if (e.type !== 'touchmove' || (e.type === 'touchmove' && e.targetTouches.length < 2)) {
25651            return;
25652          }
25653          zoom.fakeGestureMoved = true;
25654          gesture.scaleMove = Zoom.getDistanceBetweenTouches(e);
25655        }
25656        if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25657        if (Support.gestures) {
25658          zoom.scale = e.scale * zoom.currentScale;
25659        } else {
25660          zoom.scale = (gesture.scaleMove / gesture.scaleStart) * zoom.currentScale;
25661        }
25662        if (zoom.scale > gesture.maxRatio) {
25663          zoom.scale = (gesture.maxRatio - 1) + (Math.pow( ((zoom.scale - gesture.maxRatio) + 1), 0.5 ));
25664        }
25665        if (zoom.scale < params.minRatio) {
25666          zoom.scale = (params.minRatio + 1) - (Math.pow( ((params.minRatio - zoom.scale) + 1), 0.5 ));
25667        }
25668        gesture.$imageEl.transform(("translate3d(0,0,0) scale(" + (zoom.scale) + ")"));
25669      },
25670      onGestureEnd: function onGestureEnd(e) {
25671        var swiper = this;
25672        var params = swiper.params.zoom;
25673        var zoom = swiper.zoom;
25674        var gesture = zoom.gesture;
25675        if (!Support.gestures) {
25676          if (!zoom.fakeGestureTouched || !zoom.fakeGestureMoved) {
25677            return;
25678          }
25679          if (e.type !== 'touchend' || (e.type === 'touchend' && e.changedTouches.length < 2 && !Device.android)) {
25680            return;
25681          }
25682          zoom.fakeGestureTouched = false;
25683          zoom.fakeGestureMoved = false;
25684        }
25685        if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25686        zoom.scale = Math.max(Math.min(zoom.scale, gesture.maxRatio), params.minRatio);
25687        gesture.$imageEl.transition(swiper.params.speed).transform(("translate3d(0,0,0) scale(" + (zoom.scale) + ")"));
25688        zoom.currentScale = zoom.scale;
25689        zoom.isScaling = false;
25690        if (zoom.scale === 1) { gesture.$slideEl = undefined; }
25691      },
25692      onTouchStart: function onTouchStart(e) {
25693        var swiper = this;
25694        var zoom = swiper.zoom;
25695        var gesture = zoom.gesture;
25696        var image = zoom.image;
25697        if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25698        if (image.isTouched) { return; }
25699        if (Device.android) { e.preventDefault(); }
25700        image.isTouched = true;
25701        image.touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
25702        image.touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
25703      },
25704      onTouchMove: function onTouchMove(e) {
25705        var swiper = this;
25706        var zoom = swiper.zoom;
25707        var gesture = zoom.gesture;
25708        var image = zoom.image;
25709        var velocity = zoom.velocity;
25710        if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25711        swiper.allowClick = false;
25712        if (!image.isTouched || !gesture.$slideEl) { return; }
25713  
25714        if (!image.isMoved) {
25715          image.width = gesture.$imageEl[0].offsetWidth;
25716          image.height = gesture.$imageEl[0].offsetHeight;
25717          image.startX = Utils.getTranslate(gesture.$imageWrapEl[0], 'x') || 0;
25718          image.startY = Utils.getTranslate(gesture.$imageWrapEl[0], 'y') || 0;
25719          gesture.slideWidth = gesture.$slideEl[0].offsetWidth;
25720          gesture.slideHeight = gesture.$slideEl[0].offsetHeight;
25721          gesture.$imageWrapEl.transition(0);
25722          if (swiper.rtl) {
25723            image.startX = -image.startX;
25724            image.startY = -image.startY;
25725          }
25726        }
25727        // Define if we need image drag
25728        var scaledWidth = image.width * zoom.scale;
25729        var scaledHeight = image.height * zoom.scale;
25730  
25731        if (scaledWidth < gesture.slideWidth && scaledHeight < gesture.slideHeight) { return; }
25732  
25733        image.minX = Math.min(((gesture.slideWidth / 2) - (scaledWidth / 2)), 0);
25734        image.maxX = -image.minX;
25735        image.minY = Math.min(((gesture.slideHeight / 2) - (scaledHeight / 2)), 0);
25736        image.maxY = -image.minY;
25737  
25738        image.touchesCurrent.x = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
25739        image.touchesCurrent.y = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
25740  
25741        if (!image.isMoved && !zoom.isScaling) {
25742          if (
25743            swiper.isHorizontal()
25744            && (
25745              (Math.floor(image.minX) === Math.floor(image.startX) && image.touchesCurrent.x < image.touchesStart.x)
25746              || (Math.floor(image.maxX) === Math.floor(image.startX) && image.touchesCurrent.x > image.touchesStart.x)
25747            )
25748          ) {
25749            image.isTouched = false;
25750            return;
25751          } if (
25752            !swiper.isHorizontal()
25753            && (
25754              (Math.floor(image.minY) === Math.floor(image.startY) && image.touchesCurrent.y < image.touchesStart.y)
25755              || (Math.floor(image.maxY) === Math.floor(image.startY) && image.touchesCurrent.y > image.touchesStart.y)
25756            )
25757          ) {
25758            image.isTouched = false;
25759            return;
25760          }
25761        }
25762        e.preventDefault();
25763        e.stopPropagation();
25764  
25765        image.isMoved = true;
25766        image.currentX = (image.touchesCurrent.x - image.touchesStart.x) + image.startX;
25767        image.currentY = (image.touchesCurrent.y - image.touchesStart.y) + image.startY;
25768  
25769        if (image.currentX < image.minX) {
25770          image.currentX = (image.minX + 1) - (Math.pow( ((image.minX - image.currentX) + 1), 0.8 ));
25771        }
25772        if (image.currentX > image.maxX) {
25773          image.currentX = (image.maxX - 1) + (Math.pow( ((image.currentX - image.maxX) + 1), 0.8 ));
25774        }
25775  
25776        if (image.currentY < image.minY) {
25777          image.currentY = (image.minY + 1) - (Math.pow( ((image.minY - image.currentY) + 1), 0.8 ));
25778        }
25779        if (image.currentY > image.maxY) {
25780          image.currentY = (image.maxY - 1) + (Math.pow( ((image.currentY - image.maxY) + 1), 0.8 ));
25781        }
25782  
25783        // Velocity
25784        if (!velocity.prevPositionX) { velocity.prevPositionX = image.touchesCurrent.x; }
25785        if (!velocity.prevPositionY) { velocity.prevPositionY = image.touchesCurrent.y; }
25786        if (!velocity.prevTime) { velocity.prevTime = Date.now(); }
25787        velocity.x = (image.touchesCurrent.x - velocity.prevPositionX) / (Date.now() - velocity.prevTime) / 2;
25788        velocity.y = (image.touchesCurrent.y - velocity.prevPositionY) / (Date.now() - velocity.prevTime) / 2;
25789        if (Math.abs(image.touchesCurrent.x - velocity.prevPositionX) < 2) { velocity.x = 0; }
25790        if (Math.abs(image.touchesCurrent.y - velocity.prevPositionY) < 2) { velocity.y = 0; }
25791        velocity.prevPositionX = image.touchesCurrent.x;
25792        velocity.prevPositionY = image.touchesCurrent.y;
25793        velocity.prevTime = Date.now();
25794  
25795        gesture.$imageWrapEl.transform(("translate3d(" + (image.currentX) + "px, " + (image.currentY) + "px,0)"));
25796      },
25797      onTouchEnd: function onTouchEnd() {
25798        var swiper = this;
25799        var zoom = swiper.zoom;
25800        var gesture = zoom.gesture;
25801        var image = zoom.image;
25802        var velocity = zoom.velocity;
25803        if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25804        if (!image.isTouched || !image.isMoved) {
25805          image.isTouched = false;
25806          image.isMoved = false;
25807          return;
25808        }
25809        image.isTouched = false;
25810        image.isMoved = false;
25811        var momentumDurationX = 300;
25812        var momentumDurationY = 300;
25813        var momentumDistanceX = velocity.x * momentumDurationX;
25814        var newPositionX = image.currentX + momentumDistanceX;
25815        var momentumDistanceY = velocity.y * momentumDurationY;
25816        var newPositionY = image.currentY + momentumDistanceY;
25817  
25818        // Fix duration
25819        if (velocity.x !== 0) { momentumDurationX = Math.abs((newPositionX - image.currentX) / velocity.x); }
25820        if (velocity.y !== 0) { momentumDurationY = Math.abs((newPositionY - image.currentY) / velocity.y); }
25821        var momentumDuration = Math.max(momentumDurationX, momentumDurationY);
25822  
25823        image.currentX = newPositionX;
25824        image.currentY = newPositionY;
25825  
25826        // Define if we need image drag
25827        var scaledWidth = image.width * zoom.scale;
25828        var scaledHeight = image.height * zoom.scale;
25829        image.minX = Math.min(((gesture.slideWidth / 2) - (scaledWidth / 2)), 0);
25830        image.maxX = -image.minX;
25831        image.minY = Math.min(((gesture.slideHeight / 2) - (scaledHeight / 2)), 0);
25832        image.maxY = -image.minY;
25833        image.currentX = Math.max(Math.min(image.currentX, image.maxX), image.minX);
25834        image.currentY = Math.max(Math.min(image.currentY, image.maxY), image.minY);
25835  
25836        gesture.$imageWrapEl.transition(momentumDuration).transform(("translate3d(" + (image.currentX) + "px, " + (image.currentY) + "px,0)"));
25837      },
25838      onTransitionEnd: function onTransitionEnd() {
25839        var swiper = this;
25840        var zoom = swiper.zoom;
25841        var gesture = zoom.gesture;
25842        if (gesture.$slideEl && swiper.previousIndex !== swiper.activeIndex) {
25843          gesture.$imageEl.transform('translate3d(0,0,0) scale(1)');
25844          gesture.$imageWrapEl.transform('translate3d(0,0,0)');
25845  
25846          zoom.scale = 1;
25847          zoom.currentScale = 1;
25848  
25849          gesture.$slideEl = undefined;
25850          gesture.$imageEl = undefined;
25851          gesture.$imageWrapEl = undefined;
25852        }
25853      },
25854      // Toggle Zoom
25855      toggle: function toggle(e) {
25856        var swiper = this;
25857        var zoom = swiper.zoom;
25858  
25859        if (zoom.scale && zoom.scale !== 1) {
25860          // Zoom Out
25861          zoom.out();
25862        } else {
25863          // Zoom In
25864          zoom.in(e);
25865        }
25866      },
25867      in: function in$1(e) {
25868        var swiper = this;
25869  
25870        var zoom = swiper.zoom;
25871        var params = swiper.params.zoom;
25872        var gesture = zoom.gesture;
25873        var image = zoom.image;
25874  
25875        if (!gesture.$slideEl) {
25876          gesture.$slideEl = swiper.clickedSlide ? $(swiper.clickedSlide) : swiper.slides.eq(swiper.activeIndex);
25877          gesture.$imageEl = gesture.$slideEl.find('img, svg, canvas');
25878          gesture.$imageWrapEl = gesture.$imageEl.parent(("." + (params.containerClass)));
25879        }
25880        if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25881  
25882        gesture.$slideEl.addClass(("" + (params.zoomedSlideClass)));
25883  
25884        var touchX;
25885        var touchY;
25886        var offsetX;
25887        var offsetY;
25888        var diffX;
25889        var diffY;
25890        var translateX;
25891        var translateY;
25892        var imageWidth;
25893        var imageHeight;
25894        var scaledWidth;
25895        var scaledHeight;
25896        var translateMinX;
25897        var translateMinY;
25898        var translateMaxX;
25899        var translateMaxY;
25900        var slideWidth;
25901        var slideHeight;
25902  
25903        if (typeof image.touchesStart.x === 'undefined' && e) {
25904          touchX = e.type === 'touchend' ? e.changedTouches[0].pageX : e.pageX;
25905          touchY = e.type === 'touchend' ? e.changedTouches[0].pageY : e.pageY;
25906        } else {
25907          touchX = image.touchesStart.x;
25908          touchY = image.touchesStart.y;
25909        }
25910  
25911        zoom.scale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
25912        zoom.currentScale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
25913        if (e) {
25914          slideWidth = gesture.$slideEl[0].offsetWidth;
25915          slideHeight = gesture.$slideEl[0].offsetHeight;
25916          offsetX = gesture.$slideEl.offset().left;
25917          offsetY = gesture.$slideEl.offset().top;
25918          diffX = (offsetX + (slideWidth / 2)) - touchX;
25919          diffY = (offsetY + (slideHeight / 2)) - touchY;
25920  
25921          imageWidth = gesture.$imageEl[0].offsetWidth;
25922          imageHeight = gesture.$imageEl[0].offsetHeight;
25923          scaledWidth = imageWidth * zoom.scale;
25924          scaledHeight = imageHeight * zoom.scale;
25925  
25926          translateMinX = Math.min(((slideWidth / 2) - (scaledWidth / 2)), 0);
25927          translateMinY = Math.min(((slideHeight / 2) - (scaledHeight / 2)), 0);
25928          translateMaxX = -translateMinX;
25929          translateMaxY = -translateMinY;
25930  
25931          translateX = diffX * zoom.scale;
25932          translateY = diffY * zoom.scale;
25933  
25934          if (translateX < translateMinX) {
25935            translateX = translateMinX;
25936          }
25937          if (translateX > translateMaxX) {
25938            translateX = translateMaxX;
25939          }
25940  
25941          if (translateY < translateMinY) {
25942            translateY = translateMinY;
25943          }
25944          if (translateY > translateMaxY) {
25945            translateY = translateMaxY;
25946          }
25947        } else {
25948          translateX = 0;
25949          translateY = 0;
25950        }
25951        gesture.$imageWrapEl.transition(300).transform(("translate3d(" + translateX + "px, " + translateY + "px,0)"));
25952        gesture.$imageEl.transition(300).transform(("translate3d(0,0,0) scale(" + (zoom.scale) + ")"));
25953      },
25954      out: function out() {
25955        var swiper = this;
25956  
25957        var zoom = swiper.zoom;
25958        var params = swiper.params.zoom;
25959        var gesture = zoom.gesture;
25960  
25961        if (!gesture.$slideEl) {
25962          gesture.$slideEl = swiper.clickedSlide ? $(swiper.clickedSlide) : swiper.slides.eq(swiper.activeIndex);
25963          gesture.$imageEl = gesture.$slideEl.find('img, svg, canvas');
25964          gesture.$imageWrapEl = gesture.$imageEl.parent(("." + (params.containerClass)));
25965        }
25966        if (!gesture.$imageEl || gesture.$imageEl.length === 0) { return; }
25967  
25968        zoom.scale = 1;
25969        zoom.currentScale = 1;
25970        gesture.$imageWrapEl.transition(300).transform('translate3d(0,
259700,0)');
25971        gesture.$imageEl.transition(300).transform('translate3d(0,0,0) scale(1)');
25972        gesture.$slideEl.removeClass(("" + (params.zoomedSlideClass)));
25973        gesture.$slideEl = undefined;
25974      },
25975      // Attach/Detach Events
25976      enable: function enable() {
25977        var swiper = this;
25978        var zoom = swiper.zoom;
25979        if (zoom.enabled) { return; }
25980        zoom.enabled = true;
25981  
25982        var passiveListener = swiper.touchEvents.start === 'touchstart' && Support.passiveListener && swiper.params.passiveListeners ? { passive: true, capture: false } : false;
25983        var activeListenerWithCapture = Support.passiveListener ? { passive: false, capture: true } : true;
25984  
25985        // Scale image
25986        if (Support.gestures) {
25987          swiper.$wrapperEl.on('gesturestart', '.swiper-slide', zoom.onGestureStart, passiveListener);
25988          swiper.$wrapperEl.on('gesturechange', '.swiper-slide', zoom.onGestureChange, passiveListener);
25989          swiper.$wrapperEl.on('gestureend', '.swiper-slide', zoom.onGestureEnd, passiveListener);
25990        } else if (swiper.touchEvents.start === 'touchstart') {
25991          swiper.$wrapperEl.on(swiper.touchEvents.start, '.swiper-slide', zoom.onGestureStart, passiveListener);
25992          swiper.$wrapperEl.on(swiper.touchEvents.move, '.swiper-slide', zoom.onGestureChange, activeListenerWithCapture);
25993          swiper.$wrapperEl.on(swiper.touchEvents.end, '.swiper-slide', zoom.onGestureEnd, passiveListener);
25994          if (swiper.touchEvents.cancel) {
25995            swiper.$wrapperEl.on(swiper.touchEvents.cancel, '.swiper-slide', zoom.onGestureEnd, passiveListener);
25996          }
25997        }
25998  
25999        // Move image
26000        swiper.$wrapperEl.on(swiper.touchEvents.move, ("." + (swiper.params.zoom.containerClass)), zoom.onTouchMove, activeListenerWithCapture);
26001      },
26002      disable: function disable() {
26003        var swiper = this;
26004        var zoom = swiper.zoom;
26005        if (!zoom.enabled) { return; }
26006  
26007        swiper.zoom.enabled = false;
26008  
26009        var passiveListener = swiper.touchEvents.start === 'touchstart' && Support.passiveListener && swiper.params.passiveListeners ? { passive: true, capture: false } : false;
26010        var activeListenerWithCapture = Support.passiveListener ? { passive: false, capture: true } : true;
26011  
26012        // Scale image
26013        if (Support.gestures) {
26014          swiper.$wrapperEl.off('gesturestart', '.swiper-slide', zoom.onGestureStart, passiveListener);
26015          swiper.$wrapperEl.off('gesturechange', '.swiper-slide', zoom.onGestureChange, passiveListener);
26016          swiper.$wrapperEl.off('gestureend', '.swiper-slide', zoom.onGestureEnd, passiveListener);
26017        } else if (swiper.touchEvents.start === 'touchstart') {
26018          swiper.$wrapperEl.off(swiper.touchEvents.start, '.swiper-slide', zoom.onGestureStart, passiveListener);
26019          swiper.$wrapperEl.off(swiper.touchEvents.move, '.swiper-slide', zoom.onGestureChange, activeListenerWithCapture);
26020          swiper.$wrapperEl.off(swiper.touchEvents.end, '.swiper-slide', zoom.onGestureEnd, passiveListener);
26021          if (swiper.touchEvents.cancel) {
26022            swiper.$wrapperEl.off(swiper.touchEvents.cancel, '.swiper-slide', zoom.onGestureEnd, passiveListener);
26023          }
26024        }
26025  
26026        // Move image
26027        swiper.$wrapperEl.off(swiper.touchEvents.move, ("." + (swiper.params.zoom.containerClass)), zoom.onTouchMove, activeListenerWithCapture);
26028      },
26029    };
26030  
26031    var Zoom$1 = {
26032      name: 'zoom',
26033      params: {
26034        zoom: {
26035          enabled: false,
26036          maxRatio: 3,
26037          minRatio: 1,
26038          toggle: true,
26039          containerClass: 'swiper-zoom-container',
26040          zoomedSlideClass: 'swiper-slide-zoomed',
26041        },
26042      },
26043      create: function create() {
26044        var swiper = this;
26045        var zoom = {
26046          enabled: false,
26047          scale: 1,
26048          currentScale: 1,
26049          isScaling: false,
26050          gesture: {
26051            $slideEl: undefined,
26052            slideWidth: undefined,
26053            slideHeight: undefined,
26054            $imageEl: undefined,
26055            $imageWrapEl: undefined,
26056            maxRatio: 3,
26057          },
26058          image: {
26059            isTouched: undefined,
26060            isMoved: undefined,
26061            currentX: undefined,
26062            currentY: undefined,
26063            minX: undefined,
26064            minY: undefined,
26065            maxX: undefined,
26066            maxY: undefined,
26067            width: undefined,
26068            height: undefined,
26069            startX: undefined,
26070            startY: undefined,
26071            touchesStart: {},
26072            touchesCurrent: {},
26073          },
26074          velocity: {
26075            x: undefined,
26076            y: undefined,
26077            prevPositionX: undefined,
26078            prevPositionY: undefined,
26079            prevTime: undefined,
26080          },
26081        };
26082  
26083        ('onGestureStart onGestureChange onGestureEnd onTouchStart onTouchMove onTouchEnd onTransitionEnd toggle enable disable in out').split(' ').forEach(function (methodName) {
26084          zoom[methodName] = Zoom[methodName].bind(swiper);
26085        });
26086        Utils.extend(swiper, {
26087          zoom: zoom,
vendor: 68,104 bytes, lines 26088-27767
26088        });
26089  
26090        var scale = 1;
26091        Object.defineProperty(swiper.zoom, 'scale', {
26092          get: function get() {
26093            return scale;
26094          },
26095          set: function set(value) {
26096            if (scale !== value) {
26097              var imageEl = swiper.zoom.gesture.$imageEl ? swiper.zoom.gesture.$imageEl[0] : undefined;
26098              var slideEl = swiper.zoom.gesture.$slideEl ? swiper.zoom.gesture.$slideEl[0] : undefined;
26099              swiper.emit('zoomChange', value, imageEl, slideEl);
26100            }
26101            scale = value;
26102          },
26103        });
26104      },
26105      on: {
26106        init: function init() {
26107          var swiper = this;
26108          if (swiper.params.zoom.enabled) {
26109            swiper.zoom.enable();
26110          }
26111        },
26112        destroy: function destroy() {
26113          var swiper = this;
26114          swiper.zoom.disable();
26115        },
26116        touchStart: function touchStart(e) {
26117          var swiper = this;
26118          if (!swiper.zoom.enabled) { return; }
26119          swiper.zoom.onTouchStart(e);
26120        },
26121        touchEnd: function touchEnd(e) {
26122          var swiper = this;
26123          if (!swiper.zoom.enabled) { return; }
26124          swiper.zoom.onTouchEnd(e);
26125        },
26126        doubleTap: function doubleTap(e) {
26127          var swiper = this;
26128          if (swiper.params.zoom.enabled && swiper.zoom.enabled && swiper.params.zoom.toggle) {
26129            swiper.zoom.toggle(e);
26130          }
26131        },
26132        transitionEnd: function transitionEnd() {
26133          var swiper = this;
26134          if (swiper.zoom.enabled && swiper.params.zoom.enabled) {
26135            swiper.zoom.onTransitionEnd();
26136          }
26137        },
26138        slideChange: function slideChange() {
26139          var swiper = this;
26140          if (swiper.zoom.enabled && swiper.params.zoom.enabled && swiper.params.cssMode) {
26141            swiper.zoom.onTransitionEnd();
26142          }
26143        },
26144      },
26145    };
26146  
26147    var Lazy = {
26148      loadInSlide: function loadInSlide(index, loadInDuplicate) {
26149        if ( loadInDuplicate === void 0 ) loadInDuplicate = true;
26150  
26151        var swiper = this;
26152        var params = swiper.params.lazy;
26153        if (typeof index === 'undefined') { return; }
26154        if (swiper.slides.length === 0) { return; }
26155        var isVirtual = swiper.virtual && swiper.params.virtual.enabled;
26156  
26157        var $slideEl = isVirtual
26158          ? swiper.$wrapperEl.children(("." + (swiper.params.slideClass) + "[data-swiper-slide-index=\"" + index + "\"]"))
26159          : swiper.slides.eq(index);
26160  
26161        var $images = $slideEl.find(("." + (params.elementClass) + ":not(." + (params.loadedClass) + "):not(." + (params.loadingClass) + ")"));
26162        if ($slideEl.hasClass(params.elementClass) && !$slideEl.hasClass(params.loadedClass) && !$slideEl.hasClass(params.loadingClass)) {
26163          $images = $images.add($slideEl[0]);
26164        }
26165        if ($images.length === 0) { return; }
26166  
26167        $images.each(function (imageIndex, imageEl) {
26168          var $imageEl = $(imageEl);
26169          $imageEl.addClass(params.loadingClass);
26170  
26171          var background = $imageEl.attr('data-background');
26172          var src = $imageEl.attr('data-src');
26173          var srcset = $imageEl.attr('data-srcset');
26174          var sizes = $imageEl.attr('data-sizes');
26175  
26176          swiper.loadImage($imageEl[0], (src || background), srcset, sizes, false, function () {
26177            if (typeof swiper === 'undefined' || swiper === null || !swiper || (swiper && !swiper.params) || swiper.destroyed) { return; }
26178            if (background) {
26179              $imageEl.css('background-image', ("url(\"" + background + "\")"));
26180              $imageEl.removeAttr('data-background');
26181            } else {
26182              if (srcset) {
26183                $imageEl.attr('srcset', srcset);
26184                $imageEl.removeAttr('data-srcset');
26185              }
26186              if (sizes) {
26187                $imageEl.attr('sizes', sizes);
26188                $imageEl.removeAttr('data-sizes');
26189              }
26190              if (src) {
26191                $imageEl.attr('src', src);
26192                $imageEl.removeAttr('data-src');
26193              }
26194            }
26195  
26196            $imageEl.addClass(params.loadedClass).removeClass(params.loadingClass);
26197            $slideEl.find(("." + (params.preloaderClass))).remove();
26198            if (swiper.params.loop && loadInDuplicate) {
26199              var slideOriginalIndex = $slideEl.attr('data-swiper-slide-index');
26200              if ($slideEl.hasClass(swiper.params.slideDuplicateClass)) {
26201                var originalSlide = swiper.$wrapperEl.children(("[data-swiper-slide-index=\"" + slideOriginalIndex + "\"]:not(." + (swiper.params.slideDuplicateClass) + ")"));
26202                swiper.lazy.loadInSlide(originalSlide.index(), false);
26203              } else {
26204                var duplicatedSlide = swiper.$wrapperEl.children(("." + (swiper.params.slideDuplicateClass) + "[data-swiper-slide-index=\"" + slideOriginalIndex + "\"]"));
26205                swiper.lazy.loadInSlide(duplicatedSlide.index(), false);
26206              }
26207            }
26208            swiper.emit('lazyImageReady', $slideEl[0], $imageEl[0]);
26209          });
26210  
26211          swiper.emit('lazyImageLoad', $slideEl[0], $imageEl[0]);
26212        });
26213      },
26214      load: function load() {
26215        var swiper = this;
26216        var $wrapperEl = swiper.$wrapperEl;
26217        var swiperParams = swiper.params;
26218        var slides = swiper.slides;
26219        var activeIndex = swiper.activeIndex;
26220        var isVirtual = swiper.virtual && swiperParams.virtual.enabled;
26221        var params = swiperParams.lazy;
26222  
26223        var slidesPerView = swiperParams.slidesPerView;
26224        if (slidesPerView === 'auto') {
26225          slidesPerView = 0;
26226        }
26227  
26228        function slideExist(index) {
26229          if (isVirtual) {
26230            if ($wrapperEl.children(("." + (swiperParams.slideClass) + "[data-swiper-slide-index=\"" + index + "\"]")).length) {
26231              return true;
26232            }
26233          } else if (slides[index]) { return true; }
26234          return false;
26235        }
26236        function slideIndex(slideEl) {
26237          if (isVirtual) {
26238            return $(slideEl).attr('data-swiper-slide-index');
26239          }
26240          return $(slideEl).index();
26241        }
26242  
26243        if (!swiper.lazy.initialImageLoaded) { swiper.lazy.initialImageLoaded = true; }
26244        if (swiper.params.watchSlidesVisibility) {
26245          $wrapperEl.children(("." + (swiperParams.slideVisibleClass))).each(function (elIndex, slideEl) {
26246            var index = isVirtual ? $(slideEl).attr('data-swiper-slide-index') : $(slideEl).index();
26247            swiper.lazy.loadInSlide(index);
26248          });
26249        } else if (slidesPerView > 1) {
26250          for (var i = activeIndex; i < activeIndex + slidesPerView; i += 1) {
26251            if (slideExist(i)) { swiper.lazy.loadInSlide(i); }
26252          }
26253        } else {
26254          swiper.lazy.loadInSlide(activeIndex);
26255        }
26256        if (params.loadPrevNext) {
26257          if (slidesPerView > 1 || (params.loadPrevNextAmount && params.loadPrevNextAmount > 1)) {
26258            var amount = params.loadPrevNextAmount;
26259            var spv = slidesPerView;
26260            var maxIndex = Math.min(activeIndex + spv + Math.max(amount, spv), slides.length);
26261            var minIndex = Math.max(activeIndex - Math.max(spv, amount), 0);
26262            // Next Slides
26263            for (var i$1 = activeIndex + slidesPerView; i$1 < maxIndex; i$1 += 1) {
26264              if (slideExist(i$1)) { swiper.lazy.loadInSlide(i$1); }
26265            }
26266            // Prev Slides
26267            for (var i$2 = minIndex; i$2 < activeIndex; i$2 += 1) {
26268              if (slideExist(i$2)) { swiper.lazy.loadInSlide(i$2); }
26269            }
26270          } else {
26271            var nextSlide = $wrapperEl.children(("." + (swiperParams.slideNextClass)));
26272            if (nextSlide.length > 0) { swiper.lazy.loadInSlide(slideIndex(nextSlide)); }
26273  
26274            var prevSlide = $wrapperEl.children(("." + (swiperParams.slidePrevClass)));
26275            if (prevSlide.length > 0) { swiper.lazy.loadInSlide(slideIndex(prevSlide)); }
26276          }
26277        }
26278      },
26279    };
26280  
26281    var Lazy$1 = {
26282      name: 'lazy',
26283      params: {
26284        lazy: {
26285          enabled: false,
26286          loadPrevNext: false,
26287          loadPrevNextAmount: 1,
26288          loadOnTransitionStart: false,
26289  
26290          elementClass: 'swiper-lazy',
26291          loadingClass: 'swiper-lazy-loading',
26292          loadedClass: 'swiper-lazy-loaded',
26293          preloaderClass: 'swiper-lazy-preloader',
26294        },
26295      },
26296      create: function create() {
26297        var swiper = this;
26298        Utils.extend(swiper, {
26299          lazy: {
26300            initialImageLoaded: false,
26301            load: Lazy.load.bind(swiper),
26302            loadInSlide: Lazy.loadInSlide.bind(swiper),
26303          },
26304        });
26305      },
26306      on: {
26307        beforeInit: function beforeInit() {
26308          var swiper = this;
26309          if (swiper.params.lazy.enabled && swiper.params.preloadImages) {
26310            swiper.params.preloadImages = false;
26311          }
26312        },
26313        init: function init() {
26314          var swiper = this;
26315          if (swiper.params.lazy.enabled && !swiper.params.loop && swiper.params.initialSlide === 0) {
26316            swiper.lazy.load();
26317          }
26318        },
26319        scroll: function scroll() {
26320          var swiper = this;
26321          if (swiper.params.freeMode && !swiper.params.freeModeSticky) {
26322            swiper.lazy.load();
26323          }
26324        },
26325        resize: function resize() {
26326          var swiper = this;
26327          if (swiper.params.lazy.enabled) {
26328            swiper.lazy.load();
26329          }
26330        },
26331        scrollbarDragMove: function scrollbarDragMove() {
26332          var swiper = this;
26333          if (swiper.params.lazy.enabled) {
26334            swiper.lazy.load();
26335          }
26336        },
26337        transitionStart: function transitionStart() {
26338          var swiper = this;
26339          if (swiper.params.lazy.enabled) {
26340            if (swiper.params.lazy.loadOnTransitionStart || (!swiper.params.lazy.loadOnTransitionStart && !swiper.lazy.initialImageLoaded)) {
26341              swiper.lazy.load();
26342            }
26343          }
26344        },
26345        transitionEnd: function transitionEnd() {
26346          var swiper = this;
26347          if (swiper.params.lazy.enabled && !swiper.params.lazy.loadOnTransitionStart) {
26348            swiper.lazy.load();
26349          }
26350        },
26351        slideChange: function slideChange() {
26352          var swiper = this;
26353          if (swiper.params.lazy.enabled && swiper.params.cssMode) {
26354            swiper.lazy.load();
26355          }
26356        },
26357      },
26358    };
26359  
26360    /* eslint no-bitwise: ["error", { "allow": [">>"] }] */
26361  
26362    var Controller = {
26363      LinearSpline: function LinearSpline(x, y) {
26364        var binarySearch = (function search() {
26365          var maxIndex;
26366          var minIndex;
26367          var guess;
26368          return function (array, val) {
26369            minIndex = -1;
26370            maxIndex = array.length;
26371            while (maxIndex - minIndex > 1) {
26372              guess = maxIndex + minIndex >> 1;
26373              if (array[guess] <= val) {
26374                minIndex = guess;
26375              } else {
26376                maxIndex = guess;
26377              }
26378            }
26379            return maxIndex;
26380          };
26381        }());
26382        this.x = x;
26383        this.y = y;
26384        this.lastIndex = x.length - 1;
26385        // Given an x value (x2), return the expected y2 value:
26386        // (x1,y1) is the known point before given value,
26387        // (x3,y3) is the known point after given value.
26388        var i1;
26389        var i3;
26390  
26391        this.interpolate = function interpolate(x2) {
26392          if (!x2) { return 0; }
26393  
26394          // Get the indexes of x1 and x3 (the array indexes before and after given x2):
26395          i3 = binarySearch(this.x, x2);
26396          i1 = i3 - 1;
26397  
26398          // We have our indexes i1 & i3, so we can calculate already:
26399          // y2 := ((x2−x1) × (y3−y1)) ÷ (x3−x1) + y1
26400          return (((x2 - this.x[i1]) * (this.y[i3] - this.y[i1])) / (this.x[i3] - this.x[i1])) + this.y[i1];
26401        };
26402        return this;
26403      },
26404      // xxx: for now i will just save one spline function to to
26405      getInterpolateFunction: function getInterpolateFunction(c) {
26406        var swiper = this;
26407        if (!swiper.controller.spline) {
26408          swiper.controller.spline = swiper.params.loop
26409            ? new Controller.LinearSpline(swiper.slidesGrid, c.slidesGrid)
26410            : new Controller.LinearSpline(swiper.snapGrid, c.snapGrid);
26411        }
26412      },
26413      setTranslate: function setTranslate(setTranslate$1, byController) {
26414        var swiper = this;
26415        var controlled = swiper.controller.control;
26416        var multiplier;
26417        var controlledTranslate;
26418        function setControlledTranslate(c) {
26419          // this will create an Interpolate function based on the snapGrids
26420          // x is the Grid of the scrolled scroller and y will be the controlled scroller
26421          // it makes sense to create this only once and recall it for the interpolation
26422          // the function does a lot of value caching for performance
26423          var translate = swiper.rtlTranslate ? -swiper.translate : swiper.translate;
26424          if (swiper.params.controller.by === 'slide') {
26425            swiper.controller.getInterpolateFunction(c);
26426            // i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid
26427            // but it did not work out
26428            controlledTranslate = -swiper.controller.spline.interpolate(-translate);
26429          }
26430  
26431          if (!controlledTranslate || swiper.params.controller.by === 'container') {
26432            multiplier = (c.maxTranslate() - c.minTranslate()) / (swiper.maxTranslate() - swiper.minTranslate());
26433            controlledTranslate = ((translate - swiper.minTranslate()) * multiplier) + c.minTranslate();
26434          }
26435  
26436          if (swiper.params.controller.inverse) {
26437            controlledTranslate = c.maxTranslate() - controlledTranslate;
26438          }
26439          c.updateProgress(controlledTranslate);
26440          c.setTranslate(controlledTranslate, swiper);
26441          c.updateActiveIndex();
26442          c.updateSlidesClasses();
26443        }
26444        if (Array.isArray(controlled)) {
26445          for (var i = 0; i < controlled.length; i += 1) {
26446            if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
26447              setControlledTranslate(controlled[i]);
26448            }
26449          }
26450        } else if (controlled instanceof Swiper && byController !== controlled) {
26451          setControlledTranslate(controlled);
26452        }
26453      },
26454      setTransition: function setTransition(duration, byController) {
26455        var swiper = this;
26456        var controlled = swiper.controller.control;
26457        var i;
26458        function setControlledTransition(c) {
26459          c.setTransition(duration, swiper);
26460          if (duration !== 0) {
26461            c.transitionStart();
26462            if (c.params.autoHeight) {
26463              Utils.nextTick(function () {
26464                c.updateAutoHeight();
26465              });
26466            }
26467            c.$wrapperEl.transitionEnd(function () {
26468              if (!controlled) { return; }
26469              if (c.params.loop && swiper.params.controller.by === 'slide') {
26470                c.loopFix();
26471              }
26472              c.transitionEnd();
26473            });
26474          }
26475        }
26476        if (Array.isArray(controlled)) {
26477          for (i = 0; i < controlled.length; i += 1) {
26478            if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
26479              setControlledTransition(controlled[i]);
26480            }
26481          }
26482        } else if (controlled instanceof Swiper && byController !== controlled) {
26483          setControlledTransition(controlled);
26484        }
26485      },
26486    };
26487    var Controller$1 = {
26488      name: 'controller',
26489      params: {
26490        controller: {
26491          control: undefined,
26492          inverse: false,
26493          by: 'slide', // or 'container'
26494        },
26495      },
26496      create: function create() {
26497        var swiper = this;
26498        Utils.extend(swiper, {
26499          controller: {
26500            control: swiper.params.controller.control,
26501            getInterpolateFunction: Controller.getInterpolateFunction.bind(swiper),
26502            setTranslate: Controller.setTranslate.bind(swiper),
26503            setTransition: Controller.setTransition.bind(swiper),
26504          },
26505        });
26506      },
26507      on: {
26508        update: function update() {
26509          var swiper = this;
26510          if (!swiper.controller.control) { return; }
26511          if (swiper.controller.spline) {
26512            swiper.controller.spline = undefined;
26513            delete swiper.controller.spline;
26514          }
26515        },
26516        resize: function resize() {
26517          var swiper = this;
26518          if (!swiper.controller.control) { return; }
26519          if (swiper.controller.spline) {
26520            swiper.controller.spline = undefined;
26521            delete swiper.controller.spline;
26522          }
26523        },
26524        observerUpdate: function observerUpdate() {
26525          var swiper = this;
26526          if (!swiper.controller.control) { return; }
26527          if (swiper.controller.spline) {
26528            swiper.controller.spline = undefined;
26529            delete swiper.controller.spline;
26530          }
26531        },
26532        setTranslate: function setTranslate(translate, byController) {
26533          var swiper = this;
26534          if (!swiper.controller.control) { return; }
26535          swiper.controller.setTranslate(translate, byController);
26536        },
26537        setTransition: function setTransition(duration, byController) {
26538          var swiper = this;
26539          if (!swiper.controller.control) { return; }
26540          swiper.controller.setTransition(duration, byController);
26541        },
26542      },
26543    };
26544  
26545    var a11y = {
26546      makeElFocusable: function makeElFocusable($el) {
26547        $el.attr('tabIndex', '0');
26548        return $el;
26549      },
26550      addElRole: function addElRole($el, role) {
26551        $el.attr('role', role);
26552        return $el;
26553      },
26554      addElLabel: function addElLabel($el, label) {
26555        $el.attr('aria-label', label);
26556        return $el;
26557      },
26558      disableEl: function disableEl($el) {
26559        $el.attr('aria-disabled', true);
26560        return $el;
26561      },
26562      enableEl: function enableEl($el) {
26563        $el.attr('aria-disabled', false);
26564        return $el;
26565      },
26566      onEnterKey: function onEnterKey(e) {
26567        var swiper = this;
26568        var params = swiper.params.a11y;
26569        if (e.keyCode !== 13) { return; }
26570        var $targetEl = $(e.target);
26571        if (swiper.navigation && swiper.navigation.$nextEl && $targetEl.is(swiper.navigation.$nextEl)) {
26572          if (!(swiper.isEnd && !swiper.params.loop)) {
26573            swiper.slideNext();
26574          }
26575          if (swiper.isEnd) {
26576            swiper.a11y.notify(params.lastSlideMessage);
26577          } else {
26578            swiper.a11y.notify(params.nextSlideMessage);
26579          }
26580        }
26581        if (swiper.navigation && swiper.navigation.$prevEl && $targetEl.is(swiper.navigation.$prevEl)) {
26582          if (!(swiper.isBeginning && !swiper.params.loop)) {
26583            swiper.slidePrev();
26584          }
26585          if (swiper.isBeginning) {
26586            swiper.a11y.notify(params.firstSlideMessage);
26587          } else {
26588            swiper.a11y.notify(params.prevSlideMessage);
26589          }
26590        }
26591        if (swiper.pagination && $targetEl.is(("." + (swiper.params.pagination.bulletClass)))) {
26592          $targetEl[0].click();
26593        }
26594      },
26595      notify: function notify(message) {
26596        var swiper = this;
26597        var notification = swiper.a11y.liveRegion;
26598        if (notification.length === 0) { return; }
26599        notification.html('');
26600        notification.html(message);
26601      },
26602      updateNavigation: function updateNavigation() {
26603        var swiper = this;
26604  
26605        if (swiper.params.loop) { return; }
26606        var ref = swiper.navigation;
26607        var $nextEl = ref.$nextEl;
26608        var $prevEl = ref.$prevEl;
26609  
26610        if ($prevEl && $prevEl.length > 0) {
26611          if (swiper.isBeginning) {
26612            swiper.a11y.disableEl($prevEl);
26613          } else {
26614            swiper.a11y.enableEl($prevEl);
26615          }
26616        }
26617        if ($nextEl && $nextEl.length > 0) {
26618          if (swiper.isEnd) {
26619            swiper.a11y.disableEl($nextEl);
26620          } else {
26621            swiper.a11y.enableEl($nextEl);
26622          }
26623        }
26624      },
26625      updatePagination: function updatePagination() {
26626        var swiper = this;
26627        var params = swiper.params.a11y;
26628        if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
26629          swiper.pagination.bullets.each(function (bulletIndex, bulletEl) {
26630            var $bulletEl = $(bulletEl);
26631            swiper.a11y.makeElFocusable($bulletEl);
26632            swiper.a11y.addElRole($bulletEl, 'button');
26633            swiper.a11y.addElLabel($bulletEl, params.paginationBulletMessage.replace(/{{index}}/, $bulletEl.index() + 1));
26634          });
26635        }
26636      },
26637      init: function init() {
26638        var swiper = this;
26639  
26640        swiper.$el.append(swiper.a11y.liveRegion);
26641  
26642        // Navigation
26643        var params = swiper.params.a11y;
26644        var $nextEl;
26645        var $prevEl;
26646        if (swiper.navigation && swiper.navigation.$nextEl) {
26647          $nextEl = swiper.navigation.$nextEl;
26648        }
26649        if (swiper.navigation && swiper.navigation.$prevEl) {
26650          $prevEl = swiper.navigation.$prevEl;
26651        }
26652        if ($nextEl) {
26653          swiper.a11y.makeElFocusable($nextEl);
26654          swiper.a11y.addElRole($nextEl, 'button');
26655          swiper.a11y.addElLabel($nextEl, params.nextSlideMessage);
26656          $nextEl.on('keydown', swiper.a11y.onEnterKey);
26657        }
26658        if ($prevEl) {
26659          swiper.a11y.makeElFocusable($prevEl);
26660          swiper.a11y.addElRole($prevEl, 'button');
26661          swiper.a11y.addElLabel($prevEl, params.prevSlideMessage);
26662          $prevEl.on('keydown', swiper.a11y.onEnterKey);
26663        }
26664  
26665        // Pagination
26666        if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
26667          swiper.pagination.$el.on('keydown', ("." + (swiper.params.pagination.bulletClass)), swiper.a11y.onEnterKey);
26668        }
26669      },
26670      destroy: function destroy() {
26671        var swiper = this;
26672        if (swiper.a11y.liveRegion && swiper.a11y.liveRegion.length > 0) { swiper.a11y.liveRegion.remove(); }
26673  
26674        var $nextEl;
26675        var $prevEl;
26676        if (swiper.navigation && swiper.navigation.$nextEl) {
26677          $nextEl = swiper.navigation.$nextEl;
26678        }
26679        if (swiper.navigation && swiper.navigation.$prevEl) {
26680          $prevEl = swiper.navigation.$prevEl;
26681        }
26682        if ($nextEl) {
26683          $nextEl.off('keydown', swiper.a11y.onEnterKey);
26684        }
26685        if ($prevEl) {
26686          $prevEl.off('keydown', swiper.a11y.onEnterKey);
26687        }
26688  
26689        // Pagination
26690        if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
26691          swiper.pagination.$el.off('keydown', ("." + (swiper.params.pagination.bulletClass)), swiper.a11y.onEnterKey);
26692        }
26693      },
26694    };
26695    var A11y = {
26696      name: 'a11y',
26697      params: {
26698        a11y: {
26699          enabled: true,
26700          notificationClass: 'swiper-notification',
26701          prevSlideMessage: 'Previous slide',
26702          nextSlideMessage: 'Next slide',
26703          firstSlideMessage: 'This is the first slide',
26704          lastSlideMessage: 'This is the last slide',
26705          paginationBulletMessage: 'Go to slide {{index}}',
26706        },
26707      },
26708      create: function create() {
26709        var swiper = this;
26710        Utils.extend(swiper, {
26711          a11y: {
26712            liveRegion: $(("<span class=\"" + (swiper.params.a11y.notificationClass) + "\" aria-live=\"assertive\" aria-atomic=\"true\"></span>")),
26713          },
26714        });
26715        Object.keys(a11y).forEach(function (methodName) {
26716          swiper.a11y[methodName] = a11y[methodName].bind(swiper);
26717        });
26718      },
26719      on: {
26720        init: function init() {
26721          var swiper = this;
26722          if (!swiper.params.a11y.enabled) { return; }
26723          swiper.a11y.init();
26724          swiper.a11y.updateNavigation();
26725        },
26726        toEdge: function toEdge() {
26727          var swiper = this;
26728          if (!swiper.params.a11y.enabled) { return; }
26729          swiper.a11y.updateNavigation();
26730        },
26731        fromEdge: function fromEdge() {
26732          var swiper = this;
26733          if (!swiper.params.a11y.enabled) { return; }
26734          swiper.a11y.updateNavigation();
26735        },
26736        paginationUpdate: function paginationUpdate() {
26737          var swiper = this;
26738          if (!swiper.params.a11y.enabled) { return; }
26739          swiper.a11y.updatePagination();
26740        },
26741        destroy: function destroy() {
26742          var swiper = this;
26743          if (!swiper.params.a11y.enabled) { return; }
26744          swiper.a11y.destroy();
26745        },
26746      },
26747    };
26748  
26749    var History = {
26750      init: function init() {
26751        var swiper = this;
26752        if (!swiper.params.history) { return; }
26753        if (!win.history || !win.history.pushState) {
26754          swiper.params.history.enabled = false;
26755          swiper.params.hashNavigation.enabled = true;
26756          return;
26757        }
26758        var history = swiper.history;
26759        history.initialized = true;
26760        history.paths = History.getPathValues();
26761        if (!history.paths.key && !history.paths.value) { return; }
26762        history.scrollToSlide(0, history.paths.value, swiper.params.runCallbacksOnInit);
26763        if (!swiper.params.history.replaceState) {
26764          win.addEventListener('popstate', swiper.history.setHistoryPopState);
26765        }
26766      },
26767      destroy: function destroy() {
26768        var swiper = this;
26769        if (!swiper.params.history.replaceState) {
26770          win.removeEventListener('popstate', swiper.history.setHistoryPopState);
26771        }
26772      },
26773      setHistoryPopState: function setHistoryPopState() {
26774        var swiper = this;
26775        swiper.history.paths = History.getPathValues();
26776        swiper.history.scrollToSlide(swiper.params.speed, swiper.history.paths.value, false);
26777      },
26778      getPathValues: function getPathValues() {
26779        var pathArray = win.location.pathname.slice(1).split('/').filter(function (part) { return part !== ''; });
26780        var total = pathArray.length;
26781        var key = pathArray[total - 2];
26782        var value = pathArray[total - 1];
26783        return { key: key, value: value };
26784      },
26785      setHistory: function setHistory(key, index) {
26786        var swiper = this;
26787        if (!swiper.history.initialized || !swiper.params.history.enabled) { return; }
26788        var slide = swiper.slides.eq(index);
26789        var value = History.slugify(slide.attr('data-history'));
26790        if (!win.location.pathname.includes(key)) {
26791          value = key + "/" + value;
26792        }
26793        var currentState = win.history.state;
26794        if (currentState && currentState.value === value) {
26795          return;
26796        }
26797        if (swiper.params.history.replaceState) {
26798          win.history.replaceState({ value: value }, null, value);
26799        } else {
26800          win.history.pushState({ value: value }, null, value);
26801        }
26802      },
26803      slugify: function slugify(text) {
26804        return text.toString()
26805          .replace(/\s+/g, '-')
26806          .replace(/[^\w-]+/g, '')
26807          .replace(/--+/g, '-')
26808          .replace(/^-+/, '')
26809          .replace(/-+$/, '');
26810      },
26811      scrollToSlide: function scrollToSlide(speed, value, runCallbacks) {
26812        var swiper = this;
26813        if (value) {
26814          for (var i = 0, length = swiper.slides.length; i < length; i += 1) {
26815            var slide = swiper.slides.eq(i);
26816            var slideHistory = History.slugify(slide.attr('data-history'));
26817            if (slideHistory === value && !slide.hasClass(swiper.params.slideDuplicateClass)) {
26818              var index = slide.index();
26819              swiper.slideTo(index, speed, runCallbacks);
26820            }
26821          }
26822        } else {
26823          swiper.slideTo(0, speed, runCallbacks);
26824        }
26825      },
26826    };
26827  
26828    var History$1 = {
26829      name: 'history',
26830      params: {
26831        history: {
26832          enabled: false,
26833          replaceState: false,
26834          key: 'slides',
26835        },
26836      },
26837      create: function create() {
26838        var swiper = this;
26839        Utils.extend(swiper, {
26840          history: {
26841            init: History.init.bind(swiper),
26842            setHistory: History.setHistory.bind(swiper),
26843            setHistoryPopState: History.setHistoryPopState.bind(swiper),
26844            scrollToSlide: History.scrollToSlide.bind(swiper),
26845            destroy: History.destroy.bind(swiper),
26846          },
26847        });
26848      },
26849      on: {
26850        init: function init() {
26851          var swiper = this;
26852          if (swiper.params.history.enabled) {
26853            swiper.history.init();
26854          }
26855        },
26856        destroy: function destroy() {
26857          var swiper = this;
26858          if (swiper.params.history.enabled) {
26859            swiper.history.destroy();
26860          }
26861        },
26862        transitionEnd: function transitionEnd() {
26863          var swiper = this;
26864          if (swiper.history.initialized) {
26865            swiper.history.setHistory(swiper.params.history.key, swiper.activeIndex);
26866          }
26867        },
26868        slideChange: function slideChange() {
26869          var swiper = this;
26870          if (swiper.history.initialized && swiper.params.cssMode) {
26871            swiper.history.setHistory(swiper.params.history.key, swiper.activeIndex);
26872          }
26873        },
26874      },
26875    };
26876  
26877    var HashNavigation = {
26878      onHashCange: function onHashCange() {
26879        var swiper = this;
26880        var newHash = doc.location.hash.replace('#', '');
26881        var activeSlideHash = swiper.slides.eq(swiper.activeIndex).attr('data-hash');
26882        if (newHash !== activeSlideHash) {
26883          var newIndex = swiper.$wrapperEl.children(("." + (swiper.params.slideClass) + "[data-hash=\"" + newHash + "\"]")).index();
26884          if (typeof newIndex === 'undefined') { return; }
26885          swiper.slideTo(newIndex);
26886        }
26887      },
26888      setHash: function setHash() {
26889        var swiper = this;
26890        if (!swiper.hashNavigation.initialized || !swiper.params.hashNavigation.enabled) { return; }
26891        if (swiper.params.hashNavigation.replaceState && win.history && win.history.replaceState) {
26892          win.history.replaceState(null, null, (("#" + (swiper.slides.eq(swiper.activeIndex).attr('data-hash'))) || ''));
26893        } else {
26894          var slide = swiper.slides.eq(swiper.activeIndex);
26895          var hash = slide.attr('data-hash') || slide.attr('data-history');
26896          doc.location.hash = hash || '';
26897        }
26898      },
26899      init: function init() {
26900        var swiper = this;
26901        if (!swiper.params.hashNavigation.enabled || (swiper.params.history && swiper.params.history.enabled)) { return; }
26902        swiper.hashNavigation.initialized = true;
26903        var hash = doc.location.hash.replace('#', '');
26904        if (hash) {
26905          var speed = 0;
26906          for (var i = 0, length = swiper.slides.length; i < length; i += 1) {
26907            var slide = swiper.slides.eq(i);
26908            var slideHash = slide.attr('data-hash') || slide.attr('data-history');
26909            if (slideHash === hash && !slide.hasClass(swiper.params.slideDuplicateClass)) {
26910              var index = slide.index();
26911              swiper.slideTo(index, speed, swiper.params.runCallbacksOnInit, true);
26912            }
26913          }
26914        }
26915        if (swiper.params.hashNavigation.watchState) {
26916          $(win).on('hashchange', swiper.hashNavigation.onHashCange);
26917        }
26918      },
26919      destroy: function destroy() {
26920        var swiper = this;
26921        if (swiper.params.hashNavigation.watchState) {
26922          $(win).off('hashchange', swiper.hashNavigation.onHashCange);
26923        }
26924      },
26925    };
26926    var HashNavigation$1 = {
26927      name: 'hash-navigation',
26928      params: {
26929        hashNavigation: {
26930          enabled: false,
26931          replaceState: false,
26932          watchState: false,
26933        },
26934      },
26935      create: function create() {
26936        var swiper = this;
26937        Utils.extend(swiper, {
26938          hashNavigation: {
26939            initialized: false,
26940            init: HashNavigation.init.bind(swiper),
26941            destroy: HashNavigation.destroy.bind(swiper),
26942            setHash: HashNavigation.setHash.bind(swiper),
26943            onHashCange: HashNavigation.onHashCange.bind(swiper),
26944          },
26945        });
26946      },
26947      on: {
26948        init: function init() {
26949          var swiper = this;
26950          if (swiper.params.hashNavigation.enabled) {
26951            swiper.hashNavigation.init();
26952          }
26953        },
26954        destroy: function destroy() {
26955          var swiper = this;
26956          if (swiper.params.hashNavigation.enabled) {
26957            swiper.hashNavigation.destroy();
26958          }
26959        },
26960        transitionEnd: function transitionEnd() {
26961          var swiper = this;
26962          if (swiper.hashNavigation.initialized) {
26963            swiper.hashNavigation.setHash();
26964          }
26965        },
26966        slideChange: function slideChange() {
26967          var swiper = this;
26968          if (swiper.hashNavigation.initialized && swiper.params.cssMode) {
26969            swiper.hashNavigation.setHash();
26970          }
26971        },
26972      },
26973    };
26974  
26975    /* eslint no-underscore-dangle: "off" */
26976  
26977    var Autoplay = {
26978      run: function run() {
26979        var swiper = this;
26980        var $activeSlideEl = swiper.slides.eq(swiper.activeIndex);
26981        var delay = swiper.params.autoplay.delay;
26982        if ($activeSlideEl.attr('data-swiper-autoplay')) {
26983          delay = $activeSlideEl.attr('data-swiper-autoplay') || swiper.params.autoplay.delay;
26984        }
26985        clearTimeout(swiper.autoplay.timeout);
26986        swiper.autoplay.timeout = Utils.nextTick(function () {
26987          if (swiper.params.autoplay.reverseDirection) {
26988            if (swiper.params.loop) {
26989              swiper.loopFix();
26990              swiper.slidePrev(swiper.params.speed, true, true);
26991              swiper.emit('autoplay');
26992            } else if (!swiper.isBeginning) {
26993              swiper.slidePrev(swiper.params.speed, true, true);
26994              swiper.emit('autoplay');
26995            } else if (!swiper.params.autoplay.stopOnLastSlide) {
26996              swiper.slideTo(swiper.slides.length - 1, swiper.params.speed, true, true);
26997              swiper.emit('autoplay');
26998            } else {
26999              swiper.autoplay.stop();
27000            }
27001          } else if (swiper.params.loop) {
27002            swiper.loopFix();
27003            swiper.slideNext(swiper.params.speed, true, true);
27004            swiper.emit('autoplay');
27005          } else if (!swiper.isEnd) {
27006            swiper.slideNext(swiper.params.speed, true, true);
27007            swiper.emit('autoplay');
27008          } else if (!swiper.params.autoplay.stopOnLastSlide) {
27009            swiper.slideTo(0, swiper.params.speed, true, true);
27010            swiper.emit('autoplay');
27011          } else {
27012            swiper.autoplay.stop();
27013          }
27014          if (swiper.params.cssMode && swiper.autoplay.running) { swiper.autoplay.run(); }
27015        }, delay);
27016      },
27017      start: function start() {
27018        var swiper = this;
27019        if (typeof swiper.autoplay.timeout !== 'undefined') { return false; }
27020        if (swiper.autoplay.running) { return false; }
27021        swiper.autoplay.running = true;
27022        swiper.emit('autoplayStart');
27023        swiper.autoplay.run();
27024        return true;
27025      },
27026      stop: function stop() {
27027        var swiper = this;
27028        if (!swiper.autoplay.running) { return false; }
27029        if (typeof swiper.autoplay.timeout === 'undefined') { return false; }
27030  
27031        if (swiper.autoplay.timeout) {
27032          clearTimeout(swiper.autoplay.timeout);
27033          swiper.autoplay.timeout = undefined;
27034        }
27035        swiper.autoplay.running = false;
27036        swiper.emit('autoplayStop');
27037        return true;
27038      },
27039      pause: function pause(speed) {
27040        var swiper = this;
27041        if (!swiper.autoplay.running) { return; }
27042        if (swiper.autoplay.paused) { return; }
27043        if (swiper.autoplay.timeout) { clearTimeout(swiper.autoplay.timeout); }
27044        swiper.autoplay.paused = true;
27045        if (speed === 0 || !swiper.params.autoplay.waitForTransition) {
27046          swiper.autoplay.paused = false;
27047          swiper.autoplay.run();
27048        } else {
27049          swiper.$wrapperEl[0].addEventListener('transitionend', swiper.autoplay.onTransitionEnd);
27050          swiper.$wrapperEl[0].addEventListener('webkitTransitionEnd', swiper.autoplay.onTransitionEnd);
27051        }
27052      },
27053    };
27054  
27055    var Autoplay$1 = {
27056      name: 'autoplay',
27057      params: {
27058        autoplay: {
27059          enabled: false,
27060          delay: 3000,
27061          waitForTransition: true,
27062          disableOnInteraction: true,
27063          stopOnLastSlide: false,
27064          reverseDirection: false,
27065        },
27066      },
27067      create: function create() {
27068        var swiper = this;
27069        Utils.extend(swiper, {
27070          autoplay: {
27071            running: false,
27072            paused: false,
27073            run: Autoplay.run.bind(swiper),
27074            start: Autoplay.start.bind(swiper),
27075            stop: Autoplay.stop.bind(swiper),
27076            pause: Autoplay.pause.bind(swiper),
27077            onVisibilityChange: function onVisibilityChange() {
27078              if (document.visibilityState === 'hidden' && swiper.autoplay.running) {
27079                swiper.autoplay.pause();
27080              }
27081              if (document.visibilityState === 'visible' && swiper.autoplay.paused) {
27082                swiper.autoplay.run();
27083                swiper.autoplay.paused = false;
27084              }
27085            },
27086            onTransitionEnd: function onTransitionEnd(e) {
27087              if (!swiper || swiper.destroyed || !swiper.$wrapperEl) { return; }
27088              if (e.target !== this) { return; }
27089              swiper.$wrapperEl[0].removeEventListener('transitionend', swiper.autoplay.onTransitionEnd);
27090              swiper.$wrapperEl[0].removeEventListener('webkitTransitionEnd', swiper.autoplay.onTransitionEnd);
27091              swiper.autoplay.paused = false;
27092              if (!swiper.autoplay.running) {
27093                swiper.autoplay.stop();
27094              } else {
27095                swiper.autoplay.run();
27096              }
27097            },
27098          },
27099        });
27100      },
27101      on: {
27102        init: function init() {
27103          var swiper = this;
27104          if (swiper.params.autoplay.enabled) {
27105            swiper.autoplay.start();
27106            document.addEventListener('visibilitychange', swiper.autoplay.onVisibilityChange);
27107          }
27108        },
27109        beforeTransitionStart: function beforeTransitionStart(speed, internal) {
27110          var swiper = this;
27111          if (swiper.autoplay.running) {
27112            if (internal || !swiper.params.autoplay.disableOnInteraction) {
27113              swiper.autoplay.pause(speed);
27114            } else {
27115              swiper.autoplay.stop();
27116            }
27117          }
27118        },
27119        sliderFirstMove: function sliderFirstMove() {
27120          var swiper = this;
27121          if (swiper.autoplay.running) {
27122            if (swiper.params.autoplay.disableOnInteraction) {
27123              swiper.autoplay.stop();
27124            } else {
27125              swiper.autoplay.pause();
27126            }
27127          }
27128        },
27129        touchEnd: function touchEnd() {
27130          var swiper = this;
27131          if (swiper.params.cssMode && swiper.autoplay.paused && !swiper.params.autoplay.disableOnInteraction) {
27132            swiper.autoplay.run();
27133          }
27134        },
27135        destroy: function destroy() {
27136          var swiper = this;
27137          if (swiper.autoplay.running) {
27138            swiper.autoplay.stop();
27139          }
27140          document.removeEventListener('visibilitychange', swiper.autoplay.onVisibilityChange);
27141        },
27142      },
27143    };
27144  
27145    var Fade = {
27146      setTranslate: function setTranslate() {
27147        var swiper = this;
27148        var slides = swiper.slides;
27149        for (var i = 0; i < slides.length; i += 1) {
27150          var $slideEl = swiper.slides.eq(i);
27151          var offset = $slideEl[0].swiperSlideOffset;
27152          var tx = -offset;
27153          if (!swiper.params.virtualTranslate) { tx -= swiper.translate; }
27154          var ty = 0;
27155          if (!swiper.isHorizontal()) {
27156            ty = tx;
27157            tx = 0;
27158          }
27159          var slideOpacity = swiper.params.fadeEffect.crossFade
27160            ? Math.max(1 - Math.abs($slideEl[0].progress), 0)
27161            : 1 + Math.min(Math.max($slideEl[0].progress, -1), 0);
27162          $slideEl
27163            .css({
27164              opacity: slideOpacity,
27165            })
27166            .transform(("translate3d(" + tx + "px, " + ty + "px, 0px)"));
27167        }
27168      },
27169      setTransition: function setTransition(duration) {
27170        var swiper = this;
27171        var slides = swiper.slides;
27172        var $wrapperEl = swiper.$wrapperEl;
27173        slides.transition(duration);
27174        if (swiper.params.virtualTranslate && duration !== 0) {
27175          var eventTriggered = false;
27176          slides.transitionEnd(function () {
27177            if (eventTriggered) { return; }
27178            if (!swiper || swiper.destroyed) { return; }
27179            eventTriggered = true;
27180            swiper.animating = false;
27181            var triggerEvents = ['webkitTransitionEnd', 'transitionend'];
27182            for (var i = 0; i < triggerEvents.length; i += 1) {
27183              $wrapperEl.trigger(triggerEvents[i]);
27184            }
27185          });
27186        }
27187      },
27188    };
27189  
27190    var EffectFade = {
27191      name: 'effect-fade',
27192      params: {
27193        fadeEffect: {
27194          crossFade: false,
27195        },
27196      },
27197      create: function create() {
27198        var swiper = this;
27199        Utils.extend(swiper, {
27200          fadeEffect: {
27201            setTranslate: Fade.setTranslate.bind(swiper),
27202            setTransition: Fade.setTransition.bind(swiper),
27203          },
27204        });
27205      },
27206      on: {
27207        beforeInit: function beforeInit() {
27208          var swiper = this;
27209          if (swiper.params.effect !== 'fade') { return; }
27210          swiper.classNames.push(((swiper.params.containerModifierClass) + "fade"));
27211          var overwriteParams = {
27212            slidesPerView: 1,
27213            slidesPerColumn: 1,
27214            slidesPerGroup: 1,
27215            watchSlidesProgress: true,
27216            spaceBetween: 0,
27217            virtualTranslate: true,
27218          };
27219          Utils.extend(swiper.params, overwriteParams);
27220          Utils.extend(swiper.originalParams, overwriteParams);
27221        },
27222        setTranslate: function setTranslate() {
27223          var swiper = this;
27224          if (swiper.params.effect !== 'fade') { return; }
27225          swiper.fadeEffect.setTranslate();
27226        },
27227        setTransition: function setTransition(duration) {
27228          var swiper = this;
27229          if (swiper.params.effect !== 'fade') { return; }
27230          swiper.fadeEffect.setTransition(duration);
27231        },
27232      },
27233    };
27234  
27235    var Cube = {
27236      setTranslate: function setTranslate() {
27237        var swiper = this;
27238        var $el = swiper.$el;
27239        var $wrapperEl = swiper.$wrapperEl;
27240        var slides = swiper.slides;
27241        var swiperWidth = swiper.width;
27242        var swiperHeight = swiper.height;
27243        var rtl = swiper.rtlTranslate;
27244        var swiperSize = swiper.size;
27245        var params = swiper.params.cubeEffect;
27246        var isHorizontal = swiper.isHorizontal();
27247        var isVirtual = swiper.virtual && swiper.params.virtual.enabled;
27248        var wrapperRotate = 0;
27249        var $cubeShadowEl;
27250        if (params.shadow) {
27251          if (isHorizontal) {
27252            $cubeShadowEl = $wrapperEl.find('.swiper-cube-shadow');
27253            if ($cubeShadowEl.length === 0) {
27254              $cubeShadowEl = $('<div class="swiper-cube-shadow"></div>');
27255              $wrapperEl.append($cubeShadowEl);
27256            }
27257            $cubeShadowEl.css({ height: (swiperWidth + "px") });
27258          } else {
27259            $cubeShadowEl = $el.find('.swiper-cube-shadow');
27260            if ($cubeShadowEl.length === 0) {
27261              $cubeShadowEl = $('<div class="swiper-cube-shadow"></div>');
27262              $el.append($cubeShadowEl);
27263            }
27264          }
27265        }
27266        for (var i = 0; i < slides.length; i += 1) {
27267          var $slideEl = slides.eq(i);
27268          var slideIndex = i;
27269          if (isVirtual) {
27270            slideIndex = parseInt($slideEl.attr('data-swiper-slide-index'), 10);
27271          }
27272          var slideAngle = slideIndex * 90;
27273          var round = Math.floor(slideAngle / 360);
27274          if (rtl) {
27275            slideAngle = -slideAngle;
27276            round = Math.floor(-slideAngle / 360);
27277          }
27278          var progress = Math.max(Math.min($slideEl[0].progress, 1), -1);
27279          var tx = 0;
27280          var ty = 0;
27281          var tz = 0;
27282          if (slideIndex % 4 === 0) {
27283            tx = -round * 4 * swiperSize;
27284            tz = 0;
27285          } else if ((slideIndex - 1) % 4 === 0) {
27286            tx = 0;
27287            tz = -round * 4 * swiperSize;
27288          } else if ((slideIndex - 2) % 4 === 0) {
27289            tx = swiperSize + (round * 4 * swiperSize);
27290            tz = swiperSize;
27291          } else if ((slideIndex - 3) % 4 === 0) {
27292            tx = -swiperSize;
27293            tz = (3 * swiperSize) + (swiperSize * 4 * round);
27294          }
27295          if (rtl) {
27296            tx = -tx;
27297          }
27298  
27299          if (!isHorizontal) {
27300            ty = tx;
27301            tx = 0;
27302          }
27303  
27304          var transform = "rotateX(" + (isHorizontal ? 0 : -slideAngle) + "deg) rotateY(" + (isHorizontal ? slideAngle : 0) + "deg) translate3d(" + tx + "px, " + ty + "px, " + tz + "px)";
27305          if (progress <= 1 && progress > -1) {
27306            wrapperRotate = (slideIndex * 90) + (progress * 90);
27307            if (rtl) { wrapperRotate = (-slideIndex * 90) - (progress * 90); }
27308          }
27309          $slideEl.transform(transform);
27310          if (params.slideShadows) {
27311            // Set shadows
27312            var shadowBefore = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
27313            var shadowAfter = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
27314            if (shadowBefore.length === 0) {
27315              shadowBefore = $(("<div class=\"swiper-slide-shadow-" + (isHorizontal ? 'left' : 'top') + "\"></div>"));
27316              $slideEl.append(shadowBefore);
27317            }
27318            if (shadowAfter.length === 0) {
27319              shadowAfter = $(("<div class=\"swiper-slide-shadow-" + (isHorizontal ? 'right' : 'bottom') + "\"></div>"));
27320              $slideEl.append(shadowAfter);
27321            }
27322            if (shadowBefore.length) { shadowBefore[0].style.opacity = Math.max(-progress, 0); }
27323            if (shadowAfter.length) { shadowAfter[0].style.opacity = Math.max(progress, 0); }
27324          }
27325        }
27326        $wrapperEl.css({
27327          '-webkit-transform-origin': ("50% 50% -" + (swiperSize / 2) + "px"),
27328          '-moz-transform-origin': ("50% 50% -" + (swiperSize / 2) + "px"),
27329          '-ms-transform-origin': ("50% 50% -" + (swiperSize / 2) + "px"),
27330          'transform-origin': ("50% 50% -" + (swiperSize / 2) + "px"),
27331        });
27332  
27333        if (params.shadow) {
27334          if (isHorizontal) {
27335            $cubeShadowEl.transform(("translate3d(0px, " + ((swiperWidth / 2) + params.shadowOffset) + "px, " + (-swiperWidth / 2) + "px) rotateX(90deg) rotateZ(0deg) scale(" + (params.shadowScale) + ")"));
27336          } else {
27337            var shadowAngle = Math.abs(wrapperRotate) - (Math.floor(Math.abs(wrapperRotate) / 90) * 90);
27338            var multiplier = 1.5 - (
27339              (Math.sin((shadowAngle * 2 * Math.PI) / 360) / 2)
27340              + (Math.cos((shadowAngle * 2 * Math.PI) / 360) / 2)
27341            );
27342            var scale1 = params.shadowScale;
27343            var scale2 = params.shadowScale / multiplier;
27344            var offset = params.shadowOffset;
27345            $cubeShadowEl.transform(("scale3d(" + scale1 + ", 1, " + scale2 + ") translate3d(0px, " + ((swiperHeight / 2) + offset) + "px, " + (-swiperHeight / 2 / scale2) + "px) rotateX(-90deg)"));
27346          }
27347        }
27348        var zFactor = (Browser.isSafari || Browser.isUiWebView) ? (-swiperSize / 2) : 0;
27349        $wrapperEl
27350          .transform(("translate3d(0px,0," + zFactor + "px) rotateX(" + (swiper.isHorizontal() ? 0 : wrapperRotate) + "deg) rotateY(" + (swiper.isHorizontal() ? -wrapperRotate : 0) + "deg)"));
27351      },
27352      setTransition: function setTransition(duration) {
27353        var swiper = this;
27354        var $el = swiper.$el;
27355        var slides = swiper.slides;
27356        slides
27357          .transition(duration)
27358          .find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left')
27359          .transition(duration);
27360        if (swiper.params.cubeEffect.shadow && !swiper.isHorizontal()) {
27361          $el.find('.swiper-cube-shadow').transition(duration);
27362        }
27363      },
27364    };
27365  
27366    var EffectCube = {
27367      name: 'effect-cube',
27368      params: {
27369        cubeEffect: {
27370          slideShadows: true,
27371          shadow: true,
27372          shadowOffset: 20,
27373          shadowScale: 0.94,
27374        },
27375      },
27376      create: function create() {
27377        var swiper = this;
27378        Utils.extend(swiper, {
27379          cubeEffect: {
27380            setTranslate: Cube.setTranslate.bind(swiper),
27381            setTransition: Cube.setTransition.bind(swiper),
27382          },
27383        });
27384      },
27385      on: {
27386        beforeInit: function beforeInit() {
27387          var swiper = this;
27388          if (swiper.params.effect !== 'cube') { return; }
27389          swiper.classNames.push(((swiper.params.containerModifierClass) + "cube"));
27390          swiper.classNames.push(((swiper.params.containerModifierClass) + "3d"));
27391          var overwriteParams = {
27392            slidesPerView: 1,
27393            slidesPerColumn: 1,
27394            slidesPerGroup: 1,
27395            watchSlidesProgress: true,
27396            resistanceRatio: 0,
27397            spaceBetween: 0,
27398            centeredSlides: false,
27399            virtualTranslate: true,
27400          };
27401          Utils.extend(swiper.params, overwriteParams);
27402          Utils.extend(swiper.originalParams, overwriteParams);
27403        },
27404        setTranslate: function setTranslate() {
27405          var swiper = this;
27406          if (swiper.params.effect !== 'cube') { return; }
27407          swiper.cubeEffect.setTranslate();
27408        },
27409        setTransition: function setTransition(duration) {
27410          var swiper = this;
27411          if (swiper.params.effect !== 'cube') { return; }
27412          swiper.cubeEffect.setTransition(duration);
27413        },
27414      },
27415    };
27416  
27417    var Flip = {
27418      setTranslate: function setTranslate() {
27419        var swiper = this;
27420        var slides = swiper.slides;
27421        var rtl = swiper.rtlTranslate;
27422        for (var i = 0; i < slides.length; i += 1) {
27423          var $slideEl = slides.eq(i);
27424          var progress = $slideEl[0].progress;
27425          if (swiper.params.flipEffect.limitRotation) {
27426            progress = Math.max(Math.min($slideEl[0].progress, 1), -1);
27427          }
27428          var offset = $slideEl[0].swiperSlideOffset;
27429          var rotate = -180 * progress;
27430          var rotateY = rotate;
27431          var rotateX = 0;
27432          var tx = -offset;
27433          var ty = 0;
27434          if (!swiper.isHorizontal()) {
27435            ty = tx;
27436            tx = 0;
27437            rotateX = -rotateY;
27438            rotateY = 0;
27439          } else if (rtl) {
27440            rotateY = -rotateY;
27441          }
27442  
27443          $slideEl[0].style.zIndex = -Math.abs(Math.round(progress)) + slides.length;
27444  
27445          if (swiper.params.flipEffect.slideShadows) {
27446            // Set shadows
27447            var shadowBefore = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
27448            var shadowAfter = swiper.isHorizontal() ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
27449            if (shadowBefore.length === 0) {
27450              shadowBefore = $(("<div class=\"swiper-slide-shadow-" + (swiper.isHorizontal() ? 'left' : 'top') + "\"></div>"));
27451              $slideEl.append(shadowBefore);
27452            }
27453            if (shadowAfter.length === 0) {
27454              shadowAfter = $(("<div class=\"swiper-slide-shadow-" + (swiper.isHorizontal() ? 'right' : 'bottom') + "\"></div>"));
27455              $slideEl.append(shadowAfter);
27456            }
27457            if (shadowBefore.length) { shadowBefore[0].style.opacity = Math.max(-progress, 0); }
27458            if (shadowAfter.length) { shadowAfter[0].style.opacity = Math.max(progress, 0); }
27459          }
27460          $slideEl
27461            .transform(("translate3d(" + tx + "px, " + ty + "px, 0px) rotateX(" + rotateX + "deg) rotateY(" + rotateY + "deg)"));
27462        }
27463      },
27464      setTransition: function setTransition(duration) {
27465        var swiper = this;
27466        var slides = swiper.slides;
27467        var activeIndex = swiper.activeIndex;
27468        var $wrapperEl = swiper.$wrapperEl;
27469        slides
27470          .transition(duration)
27471          .find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left')
27472          .transition(duration);
27473        if (swiper.params.virtualTranslate && duration !== 0) {
27474          var eventTriggered = false;
27475          // eslint-disable-next-line
27476          slides.eq(activeIndex).transitionEnd(function onTransitionEnd() {
27477            if (eventTriggered) { return; }
27478            if (!swiper || swiper.destroyed) { return; }
27479            // if (!$(this).hasClass(swiper.params.slideActiveClass)) return;
27480            eventTriggered = true;
27481            swiper.animating = false;
27482            var triggerEvents = ['webkitTransitionEnd', 'transitionend'];
27483            for (var i = 0; i < triggerEvents.length; i += 1) {
27484              $wrapperEl.trigger(triggerEvents[i]);
27485            }
27486          });
27487        }
27488      },
27489    };
27490  
27491    var EffectFlip = {
27492      name: 'effect-flip',
27493      params: {
27494        flipEffect: {
27495          slideShadows: true,
27496          limitRotation: true,
27497        },
27498      },
27499      create: function create() {
27500        var swiper = this;
27501        Utils.extend(swiper, {
27502          flipEffect: {
27503            setTranslate: Flip.setTranslate.bind(swiper),
27504            setTransition: Flip.setTransition.bind(swiper),
27505          },
27506        });
27507      },
27508      on: {
27509        beforeInit: function beforeInit() {
27510          var swiper = this;
27511          if (swiper.params.effect !== 'flip') { return; }
27512          swiper.classNames.push(((swiper.params.containerModifierClass) + "flip"));
27513          swiper.classNames.push(((swiper.params.containerModifierClass) + "3d"));
27514          var overwriteParams = {
27515            slidesPerView: 1,
27516            slidesPerColumn: 1,
27517            slidesPerGroup: 1,
27518            watchSlidesProgress: true,
27519            spaceBetween: 0,
27520            virtualTranslate: true,
27521          };
27522          Utils.extend(swiper.params, overwriteParams);
27523          Utils.extend(swiper.originalParams, overwriteParams);
27524        },
27525        setTranslate: function setTranslate() {
27526          var swiper = this;
27527          if (swiper.params.effect !== 'flip') { return; }
27528          swiper.flipEffect.setTranslate();
27529        },
27530        setTransition: function setTransition(duration) {
27531          var swiper = this;
27532          if (swiper.params.effect !== 'flip') { return; }
27533          swiper.flipEffect.setTransition(duration);
27534        },
27535      },
27536    };
27537  
27538    var Coverflow = {
27539      setTranslate: function setTranslate() {
27540        var swiper = this;
27541        var swiperWidth = swiper.width;
27542        var swiperHeight = swiper.height;
27543        var slides = swiper.slides;
27544        var $wrapperEl = swiper.$wrapperEl;
27545        var slidesSizesGrid = swiper.slidesSizesGrid;
27546        var params = swiper.params.coverflowEffect;
27547        var isHorizontal = swiper.isHorizontal();
27548        var transform = swiper.translate;
27549        var center = isHorizontal ? -transform + (swiperWidth / 2) : -transform + (swiperHeight / 2);
27550        var rotate = isHorizontal ? params.rotate : -params.rotate;
27551        var translate = params.depth;
27552        // Each slide offset from center
27553        for (var i = 0, length = slides.length; i < length; i += 1) {
27554          var $slideEl = slides.eq(i);
27555          var slideSize = slidesSizesGrid[i];
27556          var slideOffset = $slideEl[0].swiperSlideOffset;
27557          var offsetMultiplier = ((center - slideOffset - (slideSize / 2)) / slideSize) * params.modifier;
27558  
27559          var rotateY = isHorizontal ? rotate * offsetMultiplier : 0;
27560          var rotateX = isHorizontal ? 0 : rotate * offsetMultiplier;
27561          // var rotateZ = 0
27562          var translateZ = -translate * Math.abs(offsetMultiplier);
27563  
27564          var translateY = isHorizontal ? 0 : params.stretch * (offsetMultiplier);
27565          var translateX = isHorizontal ? params.stretch * (offsetMultiplier) : 0;
27566  
27567          // Fix for ultra small values
27568          if (Math.abs(translateX) < 0.001) { translateX = 0; }
27569          if (Math.abs(translateY) < 0.001) { translateY = 0; }
27570          if (Math.abs(translateZ) < 0.001) { translateZ = 0; }
27571          if (Math.abs(rotateY) < 0.001) { rotateY = 0; }
27572          if (Math.abs(rotateX) < 0.001) { rotateX = 0; }
27573  
27574          var slideTransform = "translate3d(" + translateX + "px," + translateY + "px," + translateZ + "px)  rotateX(" + rotateX + "deg) rotateY(" + rotateY + "deg)";
27575  
27576          $slideEl.transform(slideTransform);
27577          $slideEl[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1;
27578          if (params.slideShadows) {
27579            // Set shadows
27580            var $shadowBeforeEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-left') : $slideEl.find('.swiper-slide-shadow-top');
27581            var $shadowAfterEl = isHorizontal ? $slideEl.find('.swiper-slide-shadow-right') : $slideEl.find('.swiper-slide-shadow-bottom');
27582            if ($shadowBeforeEl.length === 0) {
27583              $shadowBeforeEl = $(("<div class=\"swiper-slide-shadow-" + (isHorizontal ? 'left' : 'top') + "\"></div>"));
27584              $slideEl.append($shadowBeforeEl);
27585            }
27586            if ($shadowAfterEl.length === 0) {
27587              $shadowAfterEl = $(("<div class=\"swiper-slide-shadow-" + (isHorizontal ? 'right' : 'bottom') + "\"></div>"));
27588              $slideEl.append($shadowAfterEl);
27589            }
27590            if ($shadowBeforeEl.length) { $shadowBeforeEl[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0; }
27591            if ($shadowAfterEl.length) { $shadowAfterEl[0].style.opacity = (-offsetMultiplier) > 0 ? -offsetMultiplier : 0; }
27592          }
27593        }
27594  
27595        // Set correct perspective for IE10
27596        if (Support.pointerEvents || Support.prefixedPointerEvents) {
27597          var ws = $wrapperEl[0].style;
27598          ws.perspectiveOrigin = center + "px 50%";
27599        }
27600      },
27601      setTransition: function setTransition(duration) {
27602        var swiper = this;
27603        swiper.slides
27604          .transition(duration)
27605          .find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left')
27606          .transition(duration);
27607      },
27608    };
27609  
27610    var EffectCoverflow = {
27611      name: 'effect-coverflow',
27612      params: {
27613        coverflowEffect: {
27614          rotate: 50,
27615          stretch: 0,
27616          depth: 100,
27617          modifier: 1,
27618          slideShadows: true,
27619        },
27620      },
27621      create: function create() {
27622        var swiper = this;
27623        Utils.extend(swiper, {
27624          coverflowEffect: {
27625            setTranslate: Coverflow.setTranslate.bind(swiper),
27626            setTransition: Coverflow.setTransition.bind(swiper),
27627          },
27628        });
27629      },
27630      on: {
27631        beforeInit: function beforeInit() {
27632          var swiper = this;
27633          if (swiper.params.effect !== 'coverflow') { return; }
27634  
27635          swiper.classNames.push(((swiper.params.containerModifierClass) + "coverflow"));
27636          swiper.classNames.push(((swiper.params.containerModifierClass) + "3d"));
27637  
27638          swiper.params.watchSlidesProgress = true;
27639          swiper.originalParams.watchSlidesProgress = true;
27640        },
27641        setTranslate: function setTranslate() {
27642          var swiper = this;
27643          if (swiper.params.effect !== 'coverflow') { return; }
27644          swiper.coverflowEffect.setTranslate();
27645        },
27646        setTransition: function setTransition(duration) {
27647          var swiper = this;
27648          if (swiper.params.effect !== 'coverflow') { return; }
27649          swiper.coverflowEffect.setTransition(duration);
27650        },
27651      },
27652    };
27653  
27654    var Thumbs = {
27655      init: function init() {
27656        var swiper = this;
27657        var ref = swiper.params;
27658        var thumbsParams = ref.thumbs;
27659        var SwiperClass = swiper.constructor;
27660        if (thumbsParams.swiper instanceof SwiperClass) {
27661          swiper.thumbs.swiper = thumbsParams.swiper;
27662          Utils.extend(swiper.thumbs.swiper.originalParams, {
27663            watchSlidesProgress: true,
27664            slideToClickedSlide: false,
27665          });
27666          Utils.extend(swiper.thumbs.swiper.params, {
27667            watchSlidesProgress: true,
27668            slideToClickedSlide: false,
27669          });
27670        } else if (Utils.isObject(thumbsParams.swiper)) {
27671          swiper.thumbs.swiper = new SwiperClass(Utils.extend({}, thumbsParams.swiper, {
27672            watchSlidesVisibility: true,
27673            watchSlidesProgress: true,
27674            slideToClickedSlide: false,
27675          }));
27676          swiper.thumbs.swiperCreated = true;
27677        }
27678        swiper.thumbs.swiper.$el.addClass(swiper.params.thumbs.thumbsContainerClass);
27679        swiper.thumbs.swiper.on('tap', swiper.thumbs.onThumbClick);
27680      },
27681      onThumbClick: function onThumbClick() {
27682        var swiper = this;
27683        var thumbsSwiper = swiper.thumbs.swiper;
27684        if (!thumbsSwiper) { return; }
27685        var clickedIndex = thumbsSwiper.clickedIndex;
27686        var clickedSlide = thumbsSwiper.clickedSlide;
27687        if (clickedSlide && $(clickedSlide).hasClass(swiper.params.thumbs.slideThumbActiveClass)) { return; }
27688        if (typeof clickedIndex === 'undefined' || clickedIndex === null) { return; }
27689        var slideToIndex;
27690        if (thumbsSwiper.params.loop) {
27691          slideToIndex = parseInt($(thumbsSwiper.clickedSlide).attr('data-swiper-slide-index'), 10);
27692        } else {
27693          slideToIndex = clickedIndex;
27694        }
27695        if (swiper.params.loop) {
27696          var currentIndex = swiper.activeIndex;
27697          if (swiper.slides.eq(currentIndex).hasClass(swiper.params.slideDuplicateClass)) {
27698            swiper.loopFix();
27699            // eslint-disable-next-line
27700            swiper._clientLeft = swiper.$wrapperEl[0].clientLeft;
27701            currentIndex = swiper.activeIndex;
27702          }
27703          var prevIndex = swiper.slides.eq(currentIndex).prevAll(("[data-swiper-slide-index=\"" + slideToIndex + "\"]")).eq(0).index();
27704          var nextIndex = swiper.slides.eq(currentIndex).nextAll(("[data-swiper-slide-index=\"" + slideToIndex + "\"]")).eq(0).index();
27705          if (typeof prevIndex === 'undefined') { slideToIndex = nextIndex; }
27706          else if (typeof nextIndex === 'undefined') { slideToIndex = prevIndex; }
27707          else if (nextIndex - currentIndex < currentIndex - prevIndex) { slideToIndex = nextIndex; }
27708          else { slideToIndex = prevIndex; }
27709        }
27710        swiper.slideTo(slideToIndex);
27711      },
27712      update: function update(initial) {
27713        var swiper = this;
27714        var thumbsSwiper = swiper.thumbs.swiper;
27715        if (!thumbsSwiper) { return; }
27716  
27717        var slidesPerView = thumbsSwiper.params.slidesPerView === 'auto'
27718          ? thumbsSwiper.slidesPerViewDynamic()
27719          : thumbsSwiper.params.slidesPerView;
27720  
27721        if (swiper.realIndex !== thumbsSwiper.realIndex) {
27722          var currentThumbsIndex = thumbsSwiper.activeIndex;
27723          var newThumbsIndex;
27724          if (thumbsSwiper.params.loop) {
27725            if (thumbsSwiper.slides.eq(currentThumbsIndex).hasClass(thumbsSwiper.params.slideDuplicateClass)) {
27726              thumbsSwiper.loopFix();
27727              // eslint-disable-next-line
27728              thumbsSwiper._clientLeft = thumbsSwiper.$wrapperEl[0].clientLeft;
27729              currentThumbsIndex = thumbsSwiper.activeIndex;
27730            }
27731            // Find actual thumbs index to slide to
27732            var prevThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).prevAll(("[data-swiper-slide-index=\"" + (swiper.realIndex) + "\"]")).eq(0).index();
27733            var nextThumbsIndex = thumbsSwiper.slides.eq(currentThumbsIndex).nextAll(("[data-swiper-slide-index=\"" + (swiper.realIndex) + "\"]")).eq(0).index();
27734            if (typeof prevThumbsIndex === 'undefined') { newThumbsIndex = nextThumbsIndex; }
27735            else if (typeof nextThumbsIndex === 'undefined') { newThumbsIndex = prevThumbsIndex; }
27736            else if (nextThumbsIndex - currentThumbsIndex === currentThumbsIndex - prevThumbsIndex) { newThumbsIndex = currentThumbsIndex; }
27737            else if (nextThumbsIndex - currentThumbsIndex < currentThumbsIndex - prevThumbsIndex) { newThumbsIndex = nextThumbsIndex; }
27738            else { newThumbsIndex = prevThumbsIndex; }
27739          } else {
27740            newThumbsIndex = swiper.realIndex;
27741          }
27742          if (thumbsSwiper.visibleSlidesIndexes && thumbsSwiper.visibleSlidesIndexes.indexOf(newThumbsIndex) < 0) {
27743            if (thumbsSwiper.params.centeredSlides) {
27744              if (newThumbsIndex > currentThumbsIndex) {
27745                newThumbsIndex = newThumbsIndex - Math.floor(slidesPerView / 2) + 1;
27746              } else {
27747                newThumbsIndex = newThumbsIndex + Math.floor(slidesPerView / 2) - 1;
27748              }
27749            } else if (newThumbsIndex > currentThumbsIndex) {
27750              newThumbsIndex = newThumbsIndex - slidesPerView + 1;
27751            }
27752            thumbsSwiper.slideTo(newThumbsIndex, initial ? 0 : undefined);
27753          }
27754        }
27755  
27756        // Activate thumbs
27757        var thumbsToActivate = 1;
27758        var thumbActiveClass = swiper.params.thumbs.slideThumbActiveClass;
27759  
27760        if (swiper.params.slidesPerView > 1 && !swiper.params.centeredSlides) {
27761          thumbsToActivate = swiper.params.slidesPerView;
27762        }
27763  
27764        thumbsSwiper.slides.removeClass(thumbActiveClass);
27765        if (thumbsSwiper.params.loop || (thumbsSwiper.params.virtual && thumbsSwiper.params.virtual.enabled)) {
27766          for (var i = 0; i < thumbsToActivate; i += 1) {
27767            thumbsSwiper.$wrapperEl.children(("[data-swiper-slide-index=\"" + (swiper.realIndex + i
27767) + "\"]")).addClass(thumbActiveClass);
27768          }
27769        } else {
27770          for (var i$1 = 0; i$1 < thumbsToActivate; i$1 += 1) {
27771            thumbsSwiper.slides.eq(swiper.realIndex + i$1).addClass(thumbActiveClass);
27772          }
27773        }
27774      },
27775    };
27776    var Thumbs$1 = {
27777      name: 'thumbs',
27778      params: {
27779        thumbs: {
27780          swiper: null,
27781          slideThumbActiveClass: 'swiper-slide-thumb-active',
27782          thumbsContainerClass: 'swiper-container-thumbs',
27783        },
27784      },
27785      create: function create() {
27786        var swiper = this;
27787        Utils.extend(swiper, {
27788          thumbs: {
27789            swiper: null,
27790            init: Thumbs.init.bind(swiper),
27791            update: Thumbs.update.bind(swiper),
27792            onThumbClick: Thumbs.onThumbClick.bind(swiper),
27793          },
27794        });
27795      },
27796      on: {
27797        beforeInit: function beforeInit() {
27798          var swiper = this;
27799          var ref = swiper.params;
27800          var thumbs = ref.thumbs;
27801          if (!thumbs || !thumbs.swiper) { return; }
27802          swiper.thumbs.init();
27803          swiper.thumbs.update(true);
27804        },
27805        slideChange: function slideChange() {
27806          var swiper = this;
27807          if (!swiper.thumbs.swiper) { return; }
27808          swiper.thumbs.update();
27809        },
27810        update: function update() {
27811          var swiper = this;
27812          if (!swiper.thumbs.swiper) { return; }
27813          swiper.thumbs.update();
27814        },
27815        resize: function resize() {
27816          var swiper = this;
27817          if (!swiper.thumbs.swiper) { return; }
27818          swiper.thumbs.update();
27819        },
27820        observerUpdate: function observerUpdate() {
27821          var swiper = this;
27822          if (!swiper.thumbs.swiper) { return; }
27823          swiper.thumbs.update();
27824        },
27825        setTransition: function setTransition(duration) {
27826          var swiper = this;
27827          var thumbsSwiper = swiper.thumbs.swiper;
27828          if (!thumbsSwiper) { return; }
27829          thumbsSwiper.setTransition(duration);
27830        },
27831        beforeDestroy: function beforeDestroy() {
27832          var swiper = this;
27833          var thumbsSwiper = swiper.thumbs.swiper;
27834          if (!thumbsSwiper) { return; }
27835          if (swiper.thumbs.swiperCreated && thumbsSwiper) {
27836            thumbsSwiper.destroy();
27837          }
27838        },
27839      },
27840    };
27841  
27842    // Swiper Class
27843  
27844    var components = [
27845      Device$1,
27846      Support$1,
27847      Browser$1,
27848      Resize,
27849      Observer$1,
27850      Virtual$1,
27851      Keyboard$1,
27852      Mousewheel$1,
27853      Navigation$1,
27854      Pagination$1,
27855      Scrollbar$1,
27856      Parallax$1,
27857      Zoom$1,
27858      Lazy$1,
27859      Controller$1,
27860      A11y,
27861      History$1,
27862      HashNavigation$1,
27863      Autoplay$1,
27864      EffectFade,
27865      EffectCube,
27866      EffectFlip,
27867      EffectCoverflow,
27868      Thumbs$1
27869    ];
27870  
27871    if (typeof Swiper.use === 'undefined') {
27872      Swiper.use = Swiper.Class.use;
27873      Swiper.installModule = Swiper.Class.installModule;
27874    }
27875  
27876    Swiper.use(components);
27877  
27878    return Swiper;
27879  
27880  }));
27881  //# sourceMappingURL=swiper.js.map
27882  /*
27883 * jQuery.appear
27884 * http://code.google.com/p/jquery-appear/
27885 *
27886 * Copyright (c) 2009 Michael Hixson
27887 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
27888*/
27889(function($){$.fn.appear=function(f,o){var s=$.extend({one:true},o);return this.each(function(){var t=$(this);t.appeared=false;if(!f){t.trigger('appear',s.data);return;}var w=$(window);var c=function(){if(!t.is(':visible')){t.appeared=false;return;}var a=w.scrollLeft();var b=w.scrollTop();var o=t.offset();var x=o.left;var y=o.top;if(y+t.height()>
27889=b&&y<=b+w.height()&&x+t.width()>=a&&x<=a+w.width()){if(!t.appeared)t.trigger('appear',s.data);}else{t.appeared=false;}};var m=function(){t.appeared=true;if(s.one){w.unbind('scroll',c);var i=$.inArray(c,$.fn.appear.checks);if(i>=0)$.fn.appear.checks.splice(i,1);}f.apply(this,arguments);};if(s.one)t.one('appear',s.data,m);else t.bind('appear',s.data,m);w.scroll(c);$.fn.appear.checks.push(c);(c)();});};$.extend($.fn.appear,{checks:[],timeout:null,checkAll:function(){var l=$.fn.appear.checks.length;if(l>0)while(l--)($.fn.appear.checks[l])();},run:function(){if($.fn.appear.timeout)clearTimeout($.fn.appear.timeout);$.fn.appear.timeout=setTimeout($.fn.appear.checkAll,20);}});$.each(['append','prepend','after','before','attr','removeAttr','addClass','removeClass','toggleClass','remove','css','show','hide'],function(i,n){var u=$.fn[n];if(u){$.fn[n]=function(){var r=u.apply(this,arguments);$.fn.appear.run();return r;}}});})(jQuery);+function ($) {
27890	$(function () {
27891		/*----------------------------------------------------*/
27892		/* MOBILE DETECT FUNCTION
27893		/*----------------------------------------------------*/
27894		var isMobile = {
27895			Android: function () {
27896				return navigator.userAgent.match(/Android/i);
27897			},
27898			BlackBerry: function () {
27899				return navigator.userAgent.match(/BlackBerry/i);
27900			},
27901			iOS: function () {
27902				return navigator.userAgent.match(/iPhone|iPad|iPod/i);
27903			},
27904			Opera: function () {
27905				return navigator.userAgent.match(/Opera Mini/i);
27906			},
27907			Windows: function () {
27908				return navigator.userAgent.match(/IEMobile/i);
27909			},
27910			any: function () {
27911				return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
27912			}
27913		};
27914
27915    	let $sel = $('[data-unicode="mdu_2aGmuzZ8IEV8fRRpPu0A"]');
27916	 
27917		/*----------------------------------------------------*/
27918		// Appear
27919		/*----------------------------------------------------*/
27920		$sel.appear(function() {
27921			
27922			$(this).each (function () {
27923				let $id = base62();
27924				let $self = $(this);
27925				let $obj = $self.children('.swiper-container');
27926				let opt = $obj.data();
27927				$obj.attr('id',$id).addClass($id);
27928
27929				let $objID = '#'+$id;
27930
27931				if(opt.paginationType=='no-paginatio') {
27932					$sel.find('.swiper-pagination').hide();
27933				}
27934				if(opt.scrollBar!='.swiper-scrollbar') {
27935					$sel.find('.swiper-scrollbar').hide();
27936				}
27937
27938				let widget_name = base62();
27939				Swiper.use({
27940					name: widget_name,
27941					params: {
27942						widget: {
27943							enabled: true
27944						},
27945					},
27946					create: function create() {
27947						// 把 [data-unicode="mdu_2aGmuzZ8IEV8fRRpPu0A"] 隱藏後 
27948						// 將 .widget-item > .main 的寛度指定給 swiper.$el 的 max-width
27949						function updateFixedWidth() {
27950							var swiper = this,
27951								$el = swiper.$el,
27952								$module = $($el[0]).closest('[data-unicode="mdu_2aGmuzZ8IEV8fRRpPu0A"]');
27953							$module.hide();
27954							if (isMobile.iOS() == null) { //iPhone會有畫面跳動的問題
27955								$el[0].style.maxWidth = $module.closest('.main').css('width');
27956							}
27957							$module.show();
27958						}
27959						this[widget_name] = {
27960							updateFixedWidth: updateFixedWidth.bind(this)
27961						};
27962					},
27963					on: {
27964						beforeInit: function beforeInit() {
27965							this[widget_name].updateFixedWidth();
27966						}
27967					},
27968				});
27969
27970				let swiper = new Swiper($objID, {
27971				  centeredSlides: opt.centeredSlides,
27972				  autoplay: {
27973				    delay: opt.autoplay,
27974				    disableOnInteraction: false,
27975				  },
27976				  speed: opt.speed,
27977				  freeMode: opt.freeMode,
27978				  slidesPerView: opt.lView,
27979				  watchSlidesVisibility : true,
27980				  spaceBetween: opt.lMargin,
27981				  breakpoints: {
27982				    320: {
27983				      slidesPerView: opt.xsView,
27984				      spaceBetween: opt.xsMargin,
27985				    },
27986				    640: {
27987				      slidesPerView: opt.sView,
27988				      spaceBetween: opt.sMargin,
27989				    },
27990				    768: {
27991				      slidesPerView: opt.mView,
27992				      spaceBetween: opt.mMargin,
27993				    },
27994				    1024: {
27995				      slidesPerView: opt.lView,
27996				      spaceBetween: opt.lMargin,
27997				    }
27998				  },
27999				  loop: opt.loop,
28000				  scrollbar: {
28001			    	  el: opt.scrollBar,
28002			    	  draggable: true,
28003			  	  },
28004				  pagination: {
28005				    el: '.' + opt.paginationType,
28006				    clickable: true,
28007				    type: opt.paginationType,
28008				  },
28009				  navigation: {
28010				    nextEl: '.swiper-button-next',
28011				    prevEl: '.swiper-button-prev',
28012				  },
28013				  grabCursor: true, // 游標為手掌
28014				  observer: true//,
28015				  //observeParents: true
28016				});
28017
28018				var DataKey = 'swiper.widget-item.resize';
28019				$(swiper.$el).each(function () {
28020					var data = $(this).data(DataKey);
28021					if(!data) {
28022						$(this).closest('.widget-item')
28023							.on('wdg.resizable.resize', {swiper: swiper, key: widget_name}, function (event, width) {	
28024								event.data.swiper[event.data.key].updateFixedWidth();
28025								event.data.swiper.emit('resize');
28026								event.data.swiper.emit('orientationchange');
28027							});
28028						$(this).closest('[data-rel="PagePreviewPanel"]')
28029							.on('device.changed', {swiper: swiper, key: widget_name}, function (event, device) {
28030
28031								switch(device) {
28032									case "tablet":
28033										window.innerWidth = 995;
28034										break;
28035									case "mobile":
28036										window.innerWidth = 376;
28037										break;
28038									default:
28039										window.innerWidth = '';
28040										break;
28041								}
28042
28043								event.data.swiper[event.data.key].updateFixedWidth();
28044								event.data.swiper.emit('resize');
28045								event.data.swiper.emit('orientationchange');
28046							});
28047						$(this).data(DataKey, true);
28048					}
28049				});
28050				
28051				if(!$(swiper).data('swiper.resize')) {
28052					window.addEventListener('resize', (function () {
28053						this[widget_name].updateFixedWidth();
28054						this.emit('resize');
28055						this.emit('orientationchange');
28056					}).bind(swiper));
28057					$(swiper).data('swiper.resize', true);
28058				}
28059	        });
28060
28061		});
28062
28063    });
28064}(jQuery);
28065
28066; })(jQuery);/* compress error:[4]function encode(int) {*/
28067

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.