PageSourceSearch

https://go100tour.com/page-assert/scripts/89/zh-TW?t=639265381935587560

js go100tour.com collected 2026-10-04 04:08:11 UTC 1,255,098 bytes, 31,805 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;(function($) {var _proto = String.prototype;
3530
3531if (typeof _proto.regxMatch !== 'function') {
3532    _proto.regxMatch = function regxMatch() {
3533        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
3534            regxStr = (typeof this === "string" || this instanceof String) ? this 
3534: "";
3535        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
3536            return x.trim();
3537        }).join(' ');
3538    }
3539}/**
3540 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
3541 * ======================================================================== */
3542
3543/**
3544 * @license
3545 * ========================================================================
3546 * ScrollPos-Styler v0.7.1
3547 * https://github.com/acch/scrollpos-styler
3548 * ========================================================================
3549 * Copyright 2015 Achim Christ
3550 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
3551 * ======================================================================== */
3552
3553// JSHint directives
3554/* exported ScrollPosStyler */
3555if (typeof window.ScrollOverSelfStyler === "undefined") {
3556    var ScrollOverSelfStyler = (function (document, window, $) {
3557        "use strict";
3558
3559        /* ====================
3560         * private variables
3561         * ==================== */
3562        var scrollPosY = 0,
3563            busy = false,
3564
3565            // toggle style / class when scrolling below this position (in px)
3566            scrollOffsetY = 1,
3567
3568            // class used to apply scrollPosStyler to
3569            spsClass = "soss",
3570
3571            // choose elements to apply style / class to
3572            elements = document.getElementsByClassName(spsClass),
3573
3574            // style / class to apply to elements when above scroll position
3575            classAbove = "soss--abv",
3576
3577            // style / class to apply to elements when below scroll position
3578            classBelow = "soss--blw",
3579
3580            // tag to set custom scroll offset per element
3581            offsetTag = "data-soss-offset";
3582
3583        
3584        var BlockSel = '.block-item',
3585            ShadowKey = "ScrollOverSelfStyler";
3586
3587        /* ====================
3588         * private function to check scroll position
3589         * ==================== */
3590        function onScroll() {
3591
3592            // ensure that events don't stack
3593            if (!busy) {
3594
3595                // find elements to update
3596                var elementsToUpdate = getElementsToUpdate(false);
3597                if (elementsToUpdate.length > 0) {
3598
3599                    // suspend accepting scroll events
3600                    busy = true;
3601
3602                    // asynchronuously update elements
3603                    window.requestAnimationFrame(function () {
3604                        updateElements(elementsToUpdate);
3605                    });
3606                }
3607            }
3608        }
3609
3610        /* ====================
3611         * copy Element Shadow
3612         * ==================== */
3613        function copyElementShadow(init) {
3614            for (var i = 0; elements[i]; ++i) {
3615                var element = elements[i];
3616                if (!$(element).data(ShadowKey)) {
3617                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
3618                }
3619            }
3620        }
3621
3622        /* ====================
3623         * private function to find elements to update
3624         * ==================== */
3625        function getElementsToUpdate(init) {
3626            var elementsToUpdate = [];
3627            copyElementShadow(init);
3628
3629            // get current scroll position from window
3630            scrollPosY = window.pageYOffset;
3631
3632            // iterate over elements
3633            // for (var elem of elements) {
3634            for (var i = 0; elements[i]; ++i) { // chrome workaround
3635                var element = elements[i],
3636                    $shadow = $(element).data(ShadowKey);
3637
3638                // get offset from element, default to global option
3639                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
3640                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
3641                    shScrollOffsetY = $shadow.offset().top;
3642
3643                // check current state of element
3644                var elOnTop = element.classList.contains(classAbove);
3645
3646                // check current is visible
3647                var elVisible = $(element).closest(BlockSel).is(':visible');
3648
3649                // cols regx
3650                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
3651
3652                // if we were above, and are now below scroll position...
3653                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
3654                    
3655                    element.style.top = offsetTop + "px";
3656                    $shadow.css('height', $(element).css('height'));
3657
3658                    // remember element
3659                    elementsToUpdate.push({
3660                        element: element,
3661                        addClass: classBelow + " " + regxMatchCol,
3662                        removeClass: classAbove
3663                    });
3664
3665                    // if we were below, and are now above scroll position...
3666                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
3667
3668
3669                    // remember element
3670                    elementsToUpdate.push({
3671                        element: element,
3672                        addClass: classAbove,
3673                        removeClass: classBelow + " " + regxMatchCol
3674                    });
3675
3676                    $shadow.get(0).style.height = null;
3677                    element.style.top = null;
3678                }
3679            }
3680
3681            return elementsToUpdate;
3682        }
3683
3684        /* ====================
3685         * private function to update elements
3686         * ==================== */
3687        function updateElements(elementsToUpdate) {
3688
3689            // iterate over elements
3690            // for (var elem of elements) {
3691            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
3692                var map = elementsToUpdate[i];
3693
3694                // add style / class to element
3695                //map.element.classList.add(map.addClass);
3696                //map.element.classList.remove(map.removeClass);
3697                $(map.element).addClass(map.addClass);
3698                $(map.element).removeClass(map.removeClass);
3699            }
3700
3701            // resume accepting scroll events
3702            busy = false;
3703        }
3704
3705        /* ====================
3706         * public function to initially style elements based on scroll position
3707         *
3708         * options:
3709         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
3710         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
3711         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
3712         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
3713         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
3714         *
3715         * ==================== */
3716        var pub = {
3717            init: function (options) {
3718
3719                // suspend accepting scroll events
3720                busy = true;
3721
3722                // merge options object with global options
3723                if (options) {
3724                    if (options.spsClass) {
3725                        spsClass = options.spsClass;
3726                        elements = document.getElementsByClassName(spsClass);
3727                    }
3728                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
3729                    classAbove = options.classAbove || classAbove;
3730                    classBelow = options.classBelow || classBelow;
3731                    offsetTag = options.offsetTag || offsetTag;
3732                }
3733
3734                // ensure all elements have classAbove
3735                var elementsToUpdate = getElementsToUpdate(true);
3736                if (elementsToUpdate.length > 0) {
3737
3738                    // asynchronuously update elements
3739                    window.requestAnimationFrame(function () {
3740                        updateElements(elementsToUpdate);
3741                    });
3742                } else {
3743
3744                    // resume accepting scroll events
3745                    busy = false;
3746                }
3747            }
3748        };
3749
3750        // register for window scroll events
3751        $(window).on("scroll", onScroll);
3752
3753        window.ScrollOverSelfStyler = pub;
3754
3755        return pub;
3756    })(document, window, jQuery);
3757}
3758
3759/* ====================
3760 * main initialization
3761 * ==================== */
3762$(function () {
3763    // defer initialization to allow browser to restore scroll position
3764    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
3765});if (typeof jQuery === 'undefined') {
3766    throw new Error('Block\'s JavaScript requires jQuery')
3767}
3768
3769+function ($) {
3770    'use strict';
3771    var version = $.fn.jquery.split(' ')[0].split('.')
3772    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
3773        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
3774    }
3775}(jQuery);
3776
3777
3778+function ($, win) {
3779    'use strict';
3780
3781    var DataKey = 'blktabs',
3782        BlockSel = '.block-item',
3783        TabSel = '> .module-container .blk-tabs > ul',
3784        BtnSel = '> li',
3785        ValSel = ' > a[href^="#blk"]',
3786        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
3787        DestroyBeforeSymbol = 'destroyBeforeSymbol',
3788        Event = {
3789            ReplacedBefore: 'renderview.replace.before',
3790            ReplacedAfter: 'renderview.replace.after',
3791            BlockDestroy: 'destroy',
3792            BlockAppear: DataKey + '.block.appear',
3793            BlockHidden: DataKey + '.block.hidden',
3794            Click: {
3795                Window: 'blk-nav-in',
3796                Before: DataKey + '.tabs.click.before',
3797                After: DataKey + '.tabs.click.after'
3798            }
3799        },
3800        Options = {
3801            focus: 'active'
3802        };
3803
3804    function BlockTabs(element, opts) {
3805
3806        var self = this;
3807        this._opts = $.extend(Options, $(element).data(), opts);
3808        this._element = element;
3809        this._tabs = $(TabSel, element).get(0);
3810
3811        // block 更新屬性值之後將會被置換
3812        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
3813        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
3814        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
3815            $(this).addClass(ReplacedBeforeSymbol);
3816            event.data.blktabs.resetTabStatus();
3817            $(this).removeClass(ReplacedBeforeSymbol);
3818            $.removeData(this, DataKey);
3819        });
3820
3821        // block 被刪除前復原 tab 關聯的 block
3822        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
3823            $(this).addClass(DestroyBeforeSymbol);
3824            event.data.blktabs.resetTabStatus();
3825        });
3826
3827        // block tabs click 事件
3828        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
3829            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
3830            if ($(element).attr('href').startsWith('#')) {
3831                event.preventDefault();
3832                event.data.blktabs.tabClick(element);
3833                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
3834                    target: element,
3835                    detail: {
3836                        selector: $(element).attr('href')
3837                    }
3838                }));
3839            }
3840        });
3841
3842        this.tabAppear().resetMyStatus();
3843
3844        var bookmarkId = window.location.href.split('#').pop();
3845        if (this._element.id == bookmarkId) {
3846            // 錨點跳轉
3847            var blk = this;
3848            window.addEventListener("load", function (event) {
3849
3850                var arrParentAndButton = function (blkId) {
3851                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
3852                    var pblk = tab.closest(BlockSel);
3853                    if (pblk.length > 0 && pblk.attr('id')) {
3854                        // 記錄&尋找
3855                        var r = arrParentAndButton(pblk.attr('id'));
3856                        r.push([pblk, tab]);
3857                        return r;
3858                    }
3859                    return [];
3860                };
3861                var arr = arrParentAndButton(blk._element.id);
3862                for (var i in arr)
3863                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
3864
3865                setTimeout(function () {
3866                    $("html, body").animate({
3867                        scrollTop: $(blk._element).offset().top
3868                    }, 500, 'swing', function () { });
3869                }, 0.5 * 1000);
3870            });
3871        }
3872    }
3873
3874    var _proto = BlockTabs.prototype;
3875
3876    _proto.tabAppear = function tabAppear() {
3877        if ($(BtnSel, this._tabs).length > 0)
3878            $(this._tabs).removeClass('d-none hide');
3879        return this;
3880    }
3881
3882
3883    // 取得 block tabs 所有關聯的 block target
3884    _proto.getTabSelector = function getTabSelector() {
3885        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
3886            return $(o).attr('href');
3887        }).get().join(',');
3888    }
3889
3890    // 驅動所有關聯的 block target 執行 resetMyStatus
3891    _proto.resetTabStatus = function resetTabStatus(event) {
3892        $(this.getTabSelector()).each(function () {
3893            if ($(this).data(DataKey))
3894                $(this).data(DataKey).resetMyStatus();
3895        });
3896        return this;
3897    }
3898
3899    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
3900    _proto.resetMyStatus = function resetMyStatus() {
3901        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
3902            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
3903            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
3904            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
3905            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
3906            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
3907
3908        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
3909            // 顯示 element
3910            this._element.style.setProperty('display', '');
3911
3912            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
3913            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
3914            if ($tabLink.length < 1)
3915                $tabLink = $(BtnSel + ValSel, this._tabs);
3916            this.tabClick($tabLink.get(0));
3917            $(this._element).trigger(Event.BlockAppear);
3918        }
3919        else {
3920            // 隱藏 element
3921            this._element.style.setProperty('display', 'none', 'important');
3922            $(this._element).trigger(Event.BlockHidden);
3923        }
3924
3925        return this.resetTabStatus();
3926    }
3927
3928    // 點擊 block tabs
3929    _proto.tabClick = function tabClick(currentBtn, closure) {
3930
3931        // 點擊執行內容
3932        if ($.contains(this._element, currentBtn)) {
3933
3934            // tab 切換前
3935            $(this._element).trigger(Event.Click.Before, [currentBtn]);
3936
3937            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
3938            $(currentBtn).addClass(Options.focus);
3939
3940            this.resetTabStatus();
3941
3942            // tab 切換後
3943            $(this._element).trigger(Event.Click.After, [currentBtn]);
3944
3945            if (typeof (closure) === "function")
3946                closure();
3947        }
3948
3949        return this;
3950    }
3951
3952    if (typeof $.fn.blockTab !== 'function') {
3953
3954        $.fn.extend({
3955            blockTab: function (options) {
3956                this.filter(function (i, o) {
3957                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
3958                }).each(function (event) {
3959                    $(this).data(DataKey, new BlockTabs(this, options));
3960                });
3961            }
3962        });
3963    }
3964
3965    $(function () {
3966        $(BlockSel).blockTab();
3967    });
3968
3969}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
3970;(function($) {var _proto = String.prototype;
3971
3972if (typeof _proto.regxMatch !== 'function') {
3973    _proto.regxMatch = function regxMatch() {
3974        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
3975            regxStr = (typeof this === "string" || this instanceof String) ? this 
3975: "";
3976        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
3977            return x.trim();
3978        }).join(' ');
3979    }
3980}/**
3981 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
3982 * ======================================================================== */
3983
3984/**
3985 * @license
3986 * ========================================================================
3987 * ScrollPos-Styler v0.7.1
3988 * https://github.com/acch/scrollpos-styler
3989 * ========================================================================
3990 * Copyright 2015 Achim Christ
3991 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
3992 * ======================================================================== */
3993
3994// JSHint directives
3995/* exported ScrollPosStyler */
3996if (typeof window.ScrollOverSelfStyler === "undefined") {
3997    var ScrollOverSelfStyler = (function (document, window, $) {
3998        "use strict";
3999
4000        /* ====================
4001         * private variables
4002         * ==================== */
4003        var scrollPosY = 0,
4004            busy = false,
4005
4006            // toggle style / class when scrolling below this position (in px)
4007            scrollOffsetY = 1,
4008
4009            // class used to apply scrollPosStyler to
4010            spsClass = "soss",
4011
4012            // choose elements to apply style / class to
4013            elements = document.getElementsByClassName(spsClass),
4014
4015            // style / class to apply to elements when above scroll position
4016            classAbove = "soss--abv",
4017
4018            // style / class to apply to elements when below scroll position
4019            classBelow = "soss--blw",
4020
4021            // tag to set custom scroll offset per element
4022            offsetTag = "data-soss-offset";
4023
4024        
4025        var BlockSel = '.block-item',
4026            ShadowKey = "ScrollOverSelfStyler";
4027
4028        /* ====================
4029         * private function to check scroll position
4030         * ==================== */
4031        function onScroll() {
4032
4033            // ensure that events don't stack
4034            if (!busy) {
4035
4036                // find elements to update
4037                var elementsToUpdate = getElementsToUpdate(false);
4038                if (elementsToUpdate.length > 0) {
4039
4040                    // suspend accepting scroll events
4041                    busy = true;
4042
4043                    // asynchronuously update elements
4044                    window.requestAnimationFrame(function () {
4045                        updateElements(elementsToUpdate);
4046                    });
4047                }
4048            }
4049        }
4050
4051        /* ====================
4052         * copy Element Shadow
4053         * ==================== */
4054        function copyElementShadow(init) {
4055            for (var i = 0; elements[i]; ++i) {
4056                var element = elements[i];
4057                if (!$(element).data(ShadowKey)) {
4058                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
4059                }
4060            }
4061        }
4062
4063        /* ====================
4064         * private function to find elements to update
4065         * ==================== */
4066        function getElementsToUpdate(init) {
4067            var elementsToUpdate = [];
4068            copyElementShadow(init);
4069
4070            // get current scroll position from window
4071            scrollPosY = window.pageYOffset;
4072
4073            // iterate over elements
4074            // for (var elem of elements) {
4075            for (var i = 0; elements[i]; ++i) { // chrome workaround
4076                var element = elements[i],
4077                    $shadow = $(element).data(ShadowKey);
4078
4079                // get offset from element, default to global option
4080                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
4081                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
4082                    shScrollOffsetY = $shadow.offset().top;
4083
4084                // check current state of element
4085                var elOnTop = element.classList.contains(classAbove);
4086
4087                // check current is visible
4088                var elVisible = $(element).closest(BlockSel).is(':visible');
4089
4090                // cols regx
4091                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
4092
4093                // if we were above, and are now below scroll position...
4094                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
4095                    
4096                    element.style.top = offsetTop + "px";
4097                    $shadow.css('height', $(element).css('height'));
4098
4099                    // remember element
4100                    elementsToUpdate.push({
4101                        element: element,
4102                        addClass: classBelow + " " + regxMatchCol,
4103                        removeClass: classAbove
4104                    });
4105
4106                    // if we were below, and are now above scroll position...
4107                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
4108
4109
4110                    // remember element
4111                    elementsToUpdate.push({
4112                        element: element,
4113                        addClass: classAbove,
4114                        removeClass: classBelow + " " + regxMatchCol
4115                    });
4116
4117                    $shadow.get(0).style.height = null;
4118                    element.style.top = null;
4119                }
4120            }
4121
4122            return elementsToUpdate;
4123        }
4124
4125        /* ====================
4126         * private function to update elements
4127         * ==================== */
4128        function updateElements(elementsToUpdate) {
4129
4130            // iterate over elements
4131            // for (var elem of elements) {
4132            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
4133                var map = elementsToUpdate[i];
4134
4135                // add style / class to element
4136                //map.element.classList.add(map.addClass);
4137                //map.element.classList.remove(map.removeClass);
4138                $(map.element).addClass(map.addClass);
4139                $(map.element).removeClass(map.removeClass);
4140            }
4141
4142            // resume accepting scroll events
4143            busy = false;
4144        }
4145
4146        /* ====================
4147         * public function to initially style elements based on scroll position
4148         *
4149         * options:
4150         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
4151         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
4152         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
4153         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
4154         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
4155         *
4156         * ==================== */
4157        var pub = {
4158            init: function (options) {
4159
4160                // suspend accepting scroll events
4161                busy = true;
4162
4163                // merge options object with global options
4164                if (options) {
4165                    if (options.spsClass) {
4166                        spsClass = options.spsClass;
4167                        elements = document.getElementsByClassName(spsClass);
4168                    }
4169                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
4170                    classAbove = options.classAbove || classAbove;
4171                    classBelow = options.classBelow || classBelow;
4172                    offsetTag = options.offsetTag || offsetTag;
4173                }
4174
4175                // ensure all elements have classAbove
4176                var elementsToUpdate = getElementsToUpdate(true);
4177                if (elementsToUpdate.length > 0) {
4178
4179                    // asynchronuously update elements
4180                    window.requestAnimationFrame(function () {
4181                        updateElements(elementsToUpdate);
4182                    });
4183                } else {
4184
4185                    // resume accepting scroll events
4186                    busy = false;
4187                }
4188            }
4189        };
4190
4191        // register for window scroll events
4192        $(window).on("scroll", onScroll);
4193
4194        window.ScrollOverSelfStyler = pub;
4195
4196        return pub;
4197    })(document, window, jQuery);
4198}
4199
4200/* ====================
4201 * main initialization
4202 * ==================== */
4203$(function () {
4204    // defer initialization to allow browser to restore scroll position
4205    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
4206});if (typeof jQuery === 'undefined') {
4207    throw new Error('Block\'s JavaScript requires jQuery')
4208}
4209
4210+function ($) {
4211    'use strict';
4212    var version = $.fn.jquery.split(' ')[0].split('.')
4213    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
4214        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
4215    }
4216}(jQuery);
4217
4218
4219+function ($, win) {
4220    'use strict';
4221
4222    var DataKey = 'blktabs',
4223        BlockSel = '.block-item',
4224        TabSel = '> .module-container .blk-tabs > ul',
4225        BtnSel = '> li',
4226        ValSel = ' > a[href^="#blk"]',
4227        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
4228        DestroyBeforeSymbol = 'destroyBeforeSymbol',
4229        Event = {
4230            ReplacedBefore: 'renderview.replace.before',
4231            ReplacedAfter: 'renderview.replace.after',
4232            BlockDestroy: 'destroy',
4233            BlockAppear: DataKey + '.block.appear',
4234            BlockHidden: DataKey + '.block.hidden',
4235            Click: {
4236                Window: 'blk-nav-in',
4237                Before: DataKey + '.tabs.click.before',
4238                After: DataKey + '.tabs.click.after'
4239            }
4240        },
4241        Options = {
4242            focus: 'active'
4243        };
4244
4245    function BlockTabs(element, opts) {
4246
4247        var self = this;
4248        this._opts = $.extend(Options, $(element).data(), opts);
4249        this._element = element;
4250        this._tabs = $(TabSel, element).get(0);
4251
4252        // block 更新屬性值之後將會被置換
4253        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
4254        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
4255        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
4256            $(this).addClass(ReplacedBeforeSymbol);
4257            event.data.blktabs.resetTabStatus();
4258            $(this).removeClass(ReplacedBeforeSymbol);
4259            $.removeData(this, DataKey);
4260        });
4261
4262        // block 被刪除前復原 tab 關聯的 block
4263        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
4264            $(this).addClass(DestroyBeforeSymbol);
4265            event.data.blktabs.resetTabStatus();
4266        });
4267
4268        // block tabs click 事件
4269        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
4270            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
4271            if ($(element).attr('href').startsWith('#')) {
4272                event.preventDefault();
4273                event.data.blktabs.tabClick(element);
4274                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
4275                    target: element,
4276                    detail: {
4277                        selector: $(element).attr('href')
4278                    }
4279                }));
4280            }
4281        });
4282
4283        this.tabAppear().resetMyStatus();
4284
4285        var bookmarkId = window.location.href.split('#').pop();
4286        if (this._element.id == bookmarkId) {
4287            // 錨點跳轉
4288            var blk = this;
4289            window.addEventListener("load", function (event) {
4290
4291                var arrParentAndButton = function (blkId) {
4292                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
4293                    var pblk = tab.closest(BlockSel);
4294                    if (pblk.length > 0 && pblk.attr('id')) {
4295                        // 記錄&尋找
4296                        var r = arrParentAndButton(pblk.attr('id'));
4297                        r.push([pblk, tab]);
4298                        return r;
4299                    }
4300                    return [];
4301                };
4302                var arr = arrParentAndButton(blk._element.id);
4303                for (var i in arr)
4304                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
4305
4306                setTimeout(function () {
4307                    $("html, body").animate({
4308                        scrollTop: $(blk._element).offset().top
4309                    }, 500, 'swing', function () { });
4310                }, 0.5 * 1000);
4311            });
4312        }
4313    }
4314
4315    var _proto = BlockTabs.prototype;
4316
4317    _proto.tabAppear = function tabAppear() {
4318        if ($(BtnSel, this._tabs).length > 0)
4319            $(this._tabs).removeClass('d-none hide');
4320        return this;
4321    }
4322
4323
4324    // 取得 block tabs 所有關聯的 block target
4325    _proto.getTabSelector = function getTabSelector() {
4326        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
4327            return $(o).attr('href');
4328        }).get().join(',');
4329    }
4330
4331    // 驅動所有關聯的 block target 執行 resetMyStatus
4332    _proto.resetTabStatus = function resetTabStatus(event) {
4333        $(this.getTabSelector()).each(function () {
4334            if ($(this).data(DataKey))
4335                $(this).data(DataKey).resetMyStatus();
4336        });
4337        return this;
4338    }
4339
4340    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
4341    _proto.resetMyStatus = function resetMyStatus() {
4342        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
4343            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
4344            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
4345            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
4346            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
4347            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
4348
4349        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
4350            // 顯示 element
4351            this._element.style.setProperty('display', '');
4352
4353            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
4354            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
4355            if ($tabLink.length < 1)
4356                $tabLink = $(BtnSel + ValSel, this._tabs);
4357            this.tabClick($tabLink.get(0));
4358            $(this._element).trigger(Event.BlockAppear);
4359        }
4360        else {
4361            // 隱藏 element
4362            this._element.style.setProperty('display', 'none', 'important');
4363            $(this._element).trigger(Event.BlockHidden);
4364        }
4365
4366        return this.resetTabStatus();
4367    }
4368
4369    // 點擊 block tabs
4370    _proto.tabClick = function tabClick(currentBtn, closure) {
4371
4372        // 點擊執行內容
4373        if ($.contains(this._element, currentBtn)) {
4374
4375            // tab 切換前
4376            $(this._element).trigger(Event.Click.Before, [currentBtn]);
4377
4378            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
4379            $(currentBtn).addClass(Options.focus);
4380
4381            this.resetTabStatus();
4382
4383            // tab 切換後
4384            $(this._element).trigger(Event.Click.After, [currentBtn]);
4385
4386            if (typeof (closure) === "function")
4387                closure();
4388        }
4389
4390        return this;
4391    }
4392
4393    if (typeof $.fn.blockTab !== 'function') {
4394
4395        $.fn.extend({
4396            blockTab: function (options) {
4397                this.filter(function (i, o) {
4398                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
4399                }).each(function (event) {
4400                    $(this).data(DataKey, new BlockTabs(this, options));
4401                });
4402            }
4403        });
4404    }
4405
4406    $(function () {
4407        $(BlockSel).blockTab();
4408    });
4409
4410}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
4411;(function($) {var _proto = String.prototype;
4412
4413if (typeof _proto.regxMatch !== 'function') {
4414    _proto.regxMatch = function regxMatch() {
4415        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
4416            regxStr = (typeof this === "string" || this instanceof String) ? this 
4416: "";
4417        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
4418            return x.trim();
4419        }).join(' ');
4420    }
4421}/**
4422 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
4423 * ======================================================================== */
4424
4425/**
4426 * @license
4427 * ========================================================================
4428 * ScrollPos-Styler v0.7.1
4429 * https://github.com/acch/scrollpos-styler
4430 * ========================================================================
4431 * Copyright 2015 Achim Christ
4432 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
4433 * ======================================================================== */
4434
4435// JSHint directives
4436/* exported ScrollPosStyler */
4437if (typeof window.ScrollOverSelfStyler === "undefined") {
4438    var ScrollOverSelfStyler = (function (document, window, $) {
4439        "use strict";
4440
4441        /* ====================
4442         * private variables
4443         * ==================== */
4444        var scrollPosY = 0,
4445            busy = false,
4446
4447            // toggle style / class when scrolling below this position (in px)
4448            scrollOffsetY = 1,
4449
4450            // class used to apply scrollPosStyler to
4451            spsClass = "soss",
4452
4453            // choose elements to apply style / class to
4454            elements = document.getElementsByClassName(spsClass),
4455
4456            // style / class to apply to elements when above scroll position
4457            classAbove = "soss--abv",
4458
4459            // style / class to apply to elements when below scroll position
4460            classBelow = "soss--blw",
4461
4462            // tag to set custom scroll offset per element
4463            offsetTag = "data-soss-offset";
4464
4465        
4466        var BlockSel = '.block-item',
4467            ShadowKey = "ScrollOverSelfStyler";
4468
4469        /* ====================
4470         * private function to check scroll position
4471         * ==================== */
4472        function onScroll() {
4473
4474            // ensure that events don't stack
4475            if (!busy) {
4476
4477                // find elements to update
4478                var elementsToUpdate = getElementsToUpdate(false);
4479                if (elementsToUpdate.length > 0) {
4480
4481                    // suspend accepting scroll events
4482                    busy = true;
4483
4484                    // asynchronuously update elements
4485                    window.requestAnimationFrame(function () {
4486                        updateElements(elementsToUpdate);
4487                    });
4488                }
4489            }
4490        }
4491
4492        /* ====================
4493         * copy Element Shadow
4494         * ==================== */
4495        function copyElementShadow(init) {
4496            for (var i = 0; elements[i]; ++i) {
4497                var element = elements[i];
4498                if (!$(element).data(ShadowKey)) {
4499                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
4500                }
4501            }
4502        }
4503
4504        /* ====================
4505         * private function to find elements to update
4506         * ==================== */
4507        function getElementsToUpdate(init) {
4508            var elementsToUpdate = [];
4509            copyElementShadow(init);
4510
4511            // get current scroll position from window
4512            scrollPosY = window.pageYOffset;
4513
4514            // iterate over elements
4515            // for (var elem of elements) {
4516            for (var i = 0; elements[i]; ++i) { // chrome workaround
4517                var element = elements[i],
4518                    $shadow = $(element).data(ShadowKey);
4519
4520                // get offset from element, default to global option
4521                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
4522                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
4523                    shScrollOffsetY = $shadow.offset().top;
4524
4525                // check current state of element
4526                var elOnTop = element.classList.contains(classAbove);
4527
4528                // check current is visible
4529                var elVisible = $(element).closest(BlockSel).is(':visible');
4530
4531                // cols regx
4532                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
4533
4534                // if we were above, and are now below scroll position...
4535                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
4536                    
4537                    element.style.top = offsetTop + "px";
4538                    $shadow.css('height', $(element).css('height'));
4539
4540                    // remember element
4541                    elementsToUpdate.push({
4542                        element: element,
4543                        addClass: classBelow + " " + regxMatchCol,
4544                        removeClass: classAbove
4545                    });
4546
4547                    // if we were below, and are now above scroll position...
4548                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
4549
4550
4551                    // remember element
4552                    elementsToUpdate.push({
4553                        element: element,
4554                        addClass: classAbove,
4555                        removeClass: classBelow + " " + regxMatchCol
4556                    });
4557
4558                    $shadow.get(0).style.height = null;
4559                    element.style.top = null;
4560                }
4561            }
4562
4563            return elementsToUpdate;
4564        }
4565
4566        /* ====================
4567         * private function to update elements
4568         * ==================== */
4569        function updateElements(elementsToUpdate) {
4570
4571            // iterate over elements
4572            // for (var elem of elements) {
4573            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
4574                var map = elementsToUpdate[i];
4575
4576                // add style / class to element
4577                //map.element.classList.add(map.addClass);
4578                //map.element.classList.remove(map.removeClass);
4579                $(map.element).addClass(map.addClass);
4580                $(map.element).removeClass(map.removeClass);
4581            }
4582
4583            // resume accepting scroll events
4584            busy = false;
4585        }
4586
4587        /* ====================
4588         * public function to initially style elements based on scroll position
4589         *
4590         * options:
4591         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
4592         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
4593         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
4594         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
4595         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
4596         *
4597         * ==================== */
4598        var pub = {
4599            init: function (options) {
4600
4601                // suspend accepting scroll events
4602                busy = true;
4603
4604                // merge options object with global options
4605                if (options) {
4606                    if (options.spsClass) {
4607                        spsClass = options.spsClass;
4608                        elements = document.getElementsByClassName(spsClass);
4609                    }
4610                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
4611                    classAbove = options.classAbove || classAbove;
4612                    classBelow = options.classBelow || classBelow;
4613                    offsetTag = options.offsetTag || offsetTag;
4614                }
4615
4616                // ensure all elements have classAbove
4617                var elementsToUpdate = getElementsToUpdate(true);
4618                if (elementsToUpdate.length > 0) {
4619
4620                    // asynchronuously update elements
4621                    window.requestAnimationFrame(function () {
4622                        updateElements(elementsToUpdate);
4623                    });
4624                } else {
4625
4626                    // resume accepting scroll events
4627                    busy = false;
4628                }
4629            }
4630        };
4631
4632        // register for window scroll events
4633        $(window).on("scroll", onScroll);
4634
4635        window.ScrollOverSelfStyler = pub;
4636
4637        return pub;
4638    })(document, window, jQuery);
4639}
4640
4641/* ====================
4642 * main initialization
4643 * ==================== */
4644$(function () {
4645    // defer initialization to allow browser to restore scroll position
4646    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
4647});if (typeof jQuery === 'undefined') {
4648    throw new Error('Block\'s JavaScript requires jQuery')
4649}
4650
4651+function ($) {
4652    'use strict';
4653    var version = $.fn.jquery.split(' ')[0].split('.')
4654    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
4655        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
4656    }
4657}(jQuery);
4658
4659
4660+function ($, win) {
4661    'use strict';
4662
4663    var DataKey = 'blktabs',
4664        BlockSel = '.block-item',
4665        TabSel = '> .module-container .blk-tabs > ul',
4666        BtnSel = '> li',
4667        ValSel = ' > a[href^="#blk"]',
4668        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
4669        DestroyBeforeSymbol = 'destroyBeforeSymbol',
4670        Event = {
4671            ReplacedBefore: 'renderview.replace.before',
4672            ReplacedAfter: 'renderview.replace.after',
4673            BlockDestroy: 'destroy',
4674            BlockAppear: DataKey + '.block.appear',
4675            BlockHidden: DataKey + '.block.hidden',
4676            Click: {
4677                Window: 'blk-nav-in',
4678                Before: DataKey + '.tabs.click.before',
4679                After: DataKey + '.tabs.click.after'
4680            }
4681        },
4682        Options = {
4683            focus: 'active'
4684        };
4685
4686    function BlockTabs(element, opts) {
4687
4688        var self = this;
4689        this._opts = $.extend(Options, $(element).data(), opts);
4690        this._element = element;
4691        this._tabs = $(TabSel, element).get(0);
4692
4693        // block 更新屬性值之後將會被置換
4694        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
4695        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
4696        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
4697            $(this).addClass(ReplacedBeforeSymbol);
4698            event.data.blktabs.resetTabStatus();
4699            $(this).removeClass(ReplacedBeforeSymbol);
4700            $.removeData(this, DataKey);
4701        });
4702
4703        // block 被刪除前復原 tab 關聯的 block
4704        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
4705            $(this).addClass(DestroyBeforeSymbol);
4706            event.data.blktabs.resetTabStatus();
4707        });
4708
4709        // block tabs click 事件
4710        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
4711            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
4712            if ($(element).attr('href').startsWith('#')) {
4713                event.preventDefault();
4714                event.data.blktabs.tabClick(element);
4715                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
4716                    target: element,
4717                    detail: {
4718                        selector: $(element).attr('href')
4719                    }
4720                }));
4721            }
4722        });
4723
4724        this.tabAppear().resetMyStatus();
4725
4726        var bookmarkId = window.location.href.split('#').pop();
4727        if (this._element.id == bookmarkId) {
4728            // 錨點跳轉
4729            var blk = this;
4730            window.addEventListener("load", function (event) {
4731
4732                var arrParentAndButton = function (blkId) {
4733                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
4734                    var pblk = tab.closest(BlockSel);
4735                    if (pblk.length > 0 && pblk.attr('id')) {
4736                        // 記錄&尋找
4737                        var r = arrParentAndButton(pblk.attr('id'));
4738                        r.push([pblk, tab]);
4739                        return r;
4740                    }
4741                    return [];
4742                };
4743                var arr = arrParentAndButton(blk._element.id);
4744                for (var i in arr)
4745                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
4746
4747                setTimeout(function () {
4748                    $("html, body").animate({
4749                        scrollTop: $(blk._element).offset().top
4750                    }, 500, 'swing', function () { });
4751                }, 0.5 * 1000);
4752            });
4753        }
4754    }
4755
4756    var _proto = BlockTabs.prototype;
4757
4758    _proto.tabAppear = function tabAppear() {
4759        if ($(BtnSel, this._tabs).length > 0)
4760            $(this._tabs).removeClass('d-none hide');
4761        return this;
4762    }
4763
4764
4765    // 取得 block tabs 所有關聯的 block target
4766    _proto.getTabSelector = function getTabSelector() {
4767        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
4768            return $(o).attr('href');
4769        }).get().join(',');
4770    }
4771
4772    // 驅動所有關聯的 block target 執行 resetMyStatus
4773    _proto.resetTabStatus = function resetTabStatus(event) {
4774        $(this.getTabSelector()).each(function () {
4775            if ($(this).data(DataKey))
4776                $(this).data(DataKey).resetMyStatus();
4777        });
4778        return this;
4779    }
4780
4781    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
4782    _proto.resetMyStatus = function resetMyStatus() {
4783        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
4784            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
4785            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
4786            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
4787            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
4788            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
4789
4790        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
4791            // 顯示 element
4792            this._element.style.setProperty('display', '');
4793
4794            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
4795            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
4796            if ($tabLink.length < 1)
4797                $tabLink = $(BtnSel + ValSel, this._tabs);
4798            this.tabClick($tabLink.get(0));
4799            $(this._element).trigger(Event.BlockAppear);
4800        }
4801        else {
4802            // 隱藏 element
4803            this._element.style.setProperty('display', 'none', 'important');
4804            $(this._element).trigger(Event.BlockHidden);
4805        }
4806
4807        return this.resetTabStatus();
4808    }
4809
4810    // 點擊 block tabs
4811    _proto.tabClick = function tabClick(currentBtn, closure) {
4812
4813        // 點擊執行內容
4814        if ($.contains(this._element, currentBtn)) {
4815
4816            // tab 切換前
4817            $(this._element).trigger(Event.Click.Before, [currentBtn]);
4818
4819            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
4820            $(currentBtn).addClass(Options.focus);
4821
4822            this.resetTabStatus();
4823
4824            // tab 切換後
4825            $(this._element).trigger(Event.Click.After, [currentBtn]);
4826
4827            if (typeof (closure) === "function")
4828                closure();
4829        }
4830
4831        return this;
4832    }
4833
4834    if (typeof $.fn.blockTab !== 'function') {
4835
4836        $.fn.extend({
4837            blockTab: function (options) {
4838                this.filter(function (i, o) {
4839                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
4840                }).each(function (event) {
4841                    $(this).data(DataKey, new BlockTabs(this, options));
4842                });
4843            }
4844        });
4845    }
4846
4847    $(function () {
4848        $(BlockSel).blockTab();
4849    });
4850
4851}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
4852;(function($) {var _proto = String.prototype;
4853
4854if (typeof _proto.regxMatch !== 'function') {
4855    _proto.regxMatch = function regxMatch() {
4856        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
4857            regxStr = (typeof this === "string" || this instanceof String) ? this 
4857: "";
4858        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
4859            return x.trim();
4860        }).join(' ');
4861    }
4862}/**
4863 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
4864 * ======================================================================== */
4865
4866/**
4867 * @license
4868 * ========================================================================
4869 * ScrollPos-Styler v0.7.1
4870 * https://github.com/acch/scrollpos-styler
4871 * ========================================================================
4872 * Copyright 2015 Achim Christ
4873 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
4874 * ======================================================================== */
4875
4876// JSHint directives
4877/* exported ScrollPosStyler */
4878if (typeof window.ScrollOverSelfStyler === "undefined") {
4879    var ScrollOverSelfStyler = (function (document, window, $) {
4880        "use strict";
4881
4882        /* ====================
4883         * private variables
4884         * ==================== */
4885        var scrollPosY = 0,
4886            busy = false,
4887
4888            // toggle style / class when scrolling below this position (in px)
4889            scrollOffsetY = 1,
4890
4891            // class used to apply scrollPosStyler to
4892            spsClass = "soss",
4893
4894            // choose elements to apply style / class to
4895            elements = document.getElementsByClassName(spsClass),
4896
4897            // style / class to apply to elements when above scroll position
4898            classAbove = "soss--abv",
4899
4900            // style / class to apply to elements when below scroll position
4901            classBelow = "soss--blw",
4902
4903            // tag to set custom scroll offset per element
4904            offsetTag = "data-soss-offset";
4905
4906        
4907        var BlockSel = '.block-item',
4908            ShadowKey = "ScrollOverSelfStyler";
4909
4910        /* ====================
4911         * private function to check scroll position
4912         * ==================== */
4913        function onScroll() {
4914
4915            // ensure that events don't stack
4916            if (!busy) {
4917
4918                // find elements to update
4919                var elementsToUpdate = getElementsToUpdate(false);
4920                if (elementsToUpdate.length > 0) {
4921
4922                    // suspend accepting scroll events
4923                    busy = true;
4924
4925                    // asynchronuously update elements
4926                    window.requestAnimationFrame(function () {
4927                        updateElements(elementsToUpdate);
4928                    });
4929                }
4930            }
4931        }
4932
4933        /* ====================
4934         * copy Element Shadow
4935         * ==================== */
4936        function copyElementShadow(init) {
4937            for (var i = 0; elements[i]; ++i) {
4938                var element = elements[i];
4939                if (!$(element).data(ShadowKey)) {
4940                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
4941                }
4942            }
4943        }
4944
4945        /* ====================
4946         * private function to find elements to update
4947         * ==================== */
4948        function getElementsToUpdate(init) {
4949            var elementsToUpdate = [];
4950            copyElementShadow(init);
4951
4952            // get current scroll position from window
4953            scrollPosY = window.pageYOffset;
4954
4955            // iterate over elements
4956            // for (var elem of elements) {
4957            for (var i = 0; elements[i]; ++i) { // chrome workaround
4958                var element = elements[i],
4959                    $shadow = $(element).data(ShadowKey);
4960
4961                // get offset from element, default to global option
4962                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
4963                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
4964                    shScrollOffsetY = $shadow.offset().top;
4965
4966                // check current state of element
4967                var elOnTop = element.classList.contains(classAbove);
4968
4969                // check current is visible
4970                var elVisible = $(element).closest(BlockSel).is(':visible');
4971
4972                // cols regx
4973                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
4974
4975                // if we were above, and are now below scroll position...
4976                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
4977                    
4978                    element.style.top = offsetTop + "px";
4979                    $shadow.css('height', $(element).css('height'));
4980
4981                    // remember element
4982                    elementsToUpdate.push({
4983                        element: element,
4984                        addClass: classBelow + " " + regxMatchCol,
4985                        removeClass: classAbove
4986                    });
4987
4988                    // if we were below, and are now above scroll position...
4989                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
4990
4991
4992                    // remember element
4993                    elementsToUpdate.push({
4994                        element: element,
4995                        addClass: classAbove,
4996                        removeClass: classBelow + " " + regxMatchCol
4997                    });
4998
4999                    $shadow.get(0).style.height = null;
5000                    element.style.top = null;
5001                }
5002            }
5003
5004            return elementsToUpdate;
5005        }
5006
5007        /* ====================
5008         * private function to update elements
5009         * ==================== */
5010        function updateElements(elementsToUpdate) {
5011
5012            // iterate over elements
5013            // for (var elem of elements) {
5014            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
5015                var map = elementsToUpdate[i];
5016
5017                // add style / class to element
5018                //map.element.classList.add(map.addClass);
5019                //map.element.classList.remove(map.removeClass);
5020                $(map.element).addClass(map.addClass);
5021                $(map.element).removeClass(map.removeClass);
5022            }
5023
5024            // resume accepting scroll events
5025            busy = false;
5026        }
5027
5028        /* ====================
5029         * public function to initially style elements based on scroll position
5030         *
5031         * options:
5032         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
5033         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
5034         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
5035         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
5036         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
5037         *
5038         * ==================== */
5039        var pub = {
5040            init: function (options) {
5041
5042                // suspend accepting scroll events
5043                busy = true;
5044
5045                // merge options object with global options
5046                if (options) {
5047                    if (options.spsClass) {
5048                        spsClass = options.spsClass;
5049                        elements = document.getElementsByClassName(spsClass);
5050                    }
5051                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
5052                    classAbove = options.classAbove || classAbove;
5053                    classBelow = options.classBelow || classBelow;
5054                    offsetTag = options.offsetTag || offsetTag;
5055                }
5056
5057                // ensure all elements have classAbove
5058                var elementsToUpdate = getElementsToUpdate(true);
5059                if (elementsToUpdate.length > 0) {
5060
5061                    // asynchronuously update elements
5062                    window.requestAnimationFrame(function () {
5063                        updateElements(elementsToUpdate);
5064                    });
5065                } else {
5066
5067                    // resume accepting scroll events
5068                    busy = false;
5069                }
5070            }
5071        };
5072
5073        // register for window scroll events
5074        $(window).on("scroll", onScroll);
5075
5076        window.ScrollOverSelfStyler = pub;
5077
5078        return pub;
5079    })(document, window, jQuery);
5080}
5081
5082/* ====================
5083 * main initialization
5084 * ==================== */
5085$(function () {
5086    // defer initialization to allow browser to restore scroll position
5087    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
5088});if (typeof jQuery === 'undefined') {
5089    throw new Error('Block\'s JavaScript requires jQuery')
5090}
5091
5092+function ($) {
5093    'use strict';
5094    var version = $.fn.jquery.split(' ')[0].split('.')
5095    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
5096        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
5097    }
5098}(jQuery);
5099
5100
5101+function ($, win) {
5102    'use strict';
5103
5104    var DataKey = 'blktabs',
5105        BlockSel = '.block-item',
5106        TabSel = '> .module-container .blk-tabs > ul',
5107        BtnSel = '> li',
5108        ValSel = ' > a[href^="#blk"]',
5109        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
5110        DestroyBeforeSymbol = 'destroyBeforeSymbol',
5111        Event = {
5112            ReplacedBefore: 'renderview.replace.before',
5113            ReplacedAfter: 'renderview.replace.after',
5114            BlockDestroy: 'destroy',
5115            BlockAppear: DataKey + '.block.appear',
5116            BlockHidden: DataKey + '.block.hidden',
5117            Click: {
5118                Window: 'blk-nav-in',
5119                Before: DataKey + '.tabs.click.before',
5120                After: DataKey + '.tabs.click.after'
5121            }
5122        },
5123        Options = {
5124            focus: 'active'
5125        };
5126
5127    function BlockTabs(element, opts) {
5128
5129        var self = this;
5130        this._opts = $.extend(Options, $(element).data(), opts);
5131        this._element = element;
5132        this._tabs = $(TabSel, element).get(0);
5133
5134        // block 更新屬性值之後將會被置換
5135        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
5136        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
5137        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
5138            $(this).addClass(ReplacedBeforeSymbol);
5139            event.data.blktabs.resetTabStatus();
5140            $(this).removeClass(ReplacedBeforeSymbol);
5141            $.removeData(this, DataKey);
5142        });
5143
5144        // block 被刪除前復原 tab 關聯的 block
5145        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
5146            $(this).addClass(DestroyBeforeSymbol);
5147            event.data.blktabs.resetTabStatus();
5148        });
5149
5150        // block tabs click 事件
5151        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
5152            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
5153            if ($(element).attr('href').startsWith('#')) {
5154                event.preventDefault();
5155                event.data.blktabs.tabClick(element);
5156                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
5157                    target: element,
5158                    detail: {
5159                        selector: $(element).attr('href')
5160                    }
5161                }));
5162            }
5163        });
5164
5165        this.tabAppear().resetMyStatus();
5166
5167        var bookmarkId = window.location.href.split('#').pop();
5168        if (this._element.id == bookmarkId) {
5169            // 錨點跳轉
5170            var blk = this;
5171            window.addEventListener("load", function (event) {
5172
5173                var arrParentAndButton = function (blkId) {
5174                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
5175                    var pblk = tab.closest(BlockSel);
5176                    if (pblk.length > 0 && pblk.attr('id')) {
5177                        // 記錄&尋找
5178                        var r = arrParentAndButton(pblk.attr('id'));
5179                        r.push([pblk, tab]);
5180                        return r;
5181                    }
5182                    return [];
5183                };
5184                var arr = arrParentAndButton(blk._element.id);
5185                for (var i in arr)
5186                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
5187
5188                setTimeout(function () {
5189                    $("html, body").animate({
5190                        scrollTop: $(blk._element).offset().top
5191                    }, 500, 'swing', function () { });
5192                }, 0.5 * 1000);
5193            });
5194        }
5195    }
5196
5197    var _proto = BlockTabs.prototype;
5198
5199    _proto.tabAppear = function tabAppear() {
5200        if ($(BtnSel, this._tabs).length > 0)
5201            $(this._tabs).removeClass('d-none hide');
5202        return this;
5203    }
5204
5205
5206    // 取得 block tabs 所有關聯的 block target
5207    _proto.getTabSelector = function getTabSelector() {
5208        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
5209            return $(o).attr('href');
5210        }).get().join(',');
5211    }
5212
5213    // 驅動所有關聯的 block target 執行 resetMyStatus
5214    _proto.resetTabStatus = function resetTabStatus(event) {
5215        $(this.getTabSelector()).each(function () {
5216            if ($(this).data(DataKey))
5217                $(this).data(DataKey).resetMyStatus();
5218        });
5219        return this;
5220    }
5221
5222    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
5223    _proto.resetMyStatus = function resetMyStatus() {
5224        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
5225            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
5226            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
5227            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
5228            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
5229            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
5230
5231        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
5232            // 顯示 element
5233            this._element.style.setProperty('display', '');
5234
5235            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
5236            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
5237            if ($tabLink.length < 1)
5238                $tabLink = $(BtnSel + ValSel, this._tabs);
5239            this.tabClick($tabLink.get(0));
5240            $(this._element).trigger(Event.BlockAppear);
5241        }
5242        else {
5243            // 隱藏 element
5244            this._element.style.setProperty('display', 'none', 'important');
5245            $(this._element).trigger(Event.BlockHidden);
5246        }
5247
5248        return this.resetTabStatus();
5249    }
5250
5251    // 點擊 block tabs
5252    _proto.tabClick = function tabClick(currentBtn, closure) {
5253
5254        // 點擊執行內容
5255        if ($.contains(this._element, currentBtn)) {
5256
5257            // tab 切換前
5258            $(this._element).trigger(Event.Click.Before, [currentBtn]);
5259
5260            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
5261            $(currentBtn).addClass(Options.focus);
5262
5263            this.resetTabStatus();
5264
5265            // tab 切換後
5266            $(this._element).trigger(Event.Click.After, [currentBtn]);
5267
5268            if (typeof (closure) === "function")
5269                closure();
5270        }
5271
5272        return this;
5273    }
5274
5275    if (typeof $.fn.blockTab !== 'function') {
5276
5277        $.fn.extend({
5278            blockTab: function (options) {
5279                this.filter(function (i, o) {
5280                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
5281                }).each(function (event) {
5282                    $(this).data(DataKey, new BlockTabs(this, options));
5283                });
5284            }
5285        });
5286    }
5287
5288    $(function () {
5289        $(BlockSel).blockTab();
5290    });
5291
5292}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
5293;(function($) {var _proto = String.prototype;
5294
5295if (typeof _proto.regxMatch !== 'function') {
5296    _proto.regxMatch = function regxMatch() {
5297        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
5298            regxStr = (typeof this === "string" || this instanceof String) ? this 
5298: "";
5299        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
5300            return x.trim();
5301        }).join(' ');
5302    }
5303}/**
5304 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
5305 * ======================================================================== */
5306
5307/**
5308 * @license
5309 * ========================================================================
5310 * ScrollPos-Styler v0.7.1
5311 * https://github.com/acch/scrollpos-styler
5312 * ========================================================================
5313 * Copyright 2015 Achim Christ
5314 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
5315 * ======================================================================== */
5316
5317// JSHint directives
5318/* exported ScrollPosStyler */
5319if (typeof window.ScrollOverSelfStyler === "undefined") {
5320    var ScrollOverSelfStyler = (function (document, window, $) {
5321        "use strict";
5322
5323        /* ====================
5324         * private variables
5325         * ==================== */
5326        var scrollPosY = 0,
5327            busy = false,
5328
5329            // toggle style / class when scrolling below this position (in px)
5330            scrollOffsetY = 1,
5331
5332            // class used to apply scrollPosStyler to
5333            spsClass = "soss",
5334
5335            // choose elements to apply style / class to
5336            elements = document.getElementsByClassName(spsClass),
5337
5338            // style / class to apply to elements when above scroll position
5339            classAbove = "soss--abv",
5340
5341            // style / class to apply to elements when below scroll position
5342            classBelow = "soss--blw",
5343
5344            // tag to set custom scroll offset per element
5345            offsetTag = "data-soss-offset";
5346
5347        
5348        var BlockSel = '.block-item',
5349            ShadowKey = "ScrollOverSelfStyler";
5350
5351        /* ====================
5352         * private function to check scroll position
5353         * ==================== */
5354        function onScroll() {
5355
5356            // ensure that events don't stack
5357            if (!busy) {
5358
5359                // find elements to update
5360                var elementsToUpdate = getElementsToUpdate(false);
5361                if (elementsToUpdate.length > 0) {
5362
5363                    // suspend accepting scroll events
5364                    busy = true;
5365
5366                    // asynchronuously update elements
5367                    window.requestAnimationFrame(function () {
5368                        updateElements(elementsToUpdate);
5369                    });
5370                }
5371            }
5372        }
5373
5374        /* ====================
5375         * copy Element Shadow
5376         * ==================== */
5377        function copyElementShadow(init) {
5378            for (var i = 0; elements[i]; ++i) {
5379                var element = elements[i];
5380                if (!$(element).data(ShadowKey)) {
5381                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
5382                }
5383            }
5384        }
5385
5386        /* ====================
5387         * private function to find elements to update
5388         * ==================== */
5389        function getElementsToUpdate(init) {
5390            var elementsToUpdate = [];
5391            copyElementShadow(init);
5392
5393            // get current scroll position from window
5394            scrollPosY = window.pageYOffset;
5395
5396            // iterate over elements
5397            // for (var elem of elements) {
5398            for (var i = 0; elements[i]; ++i) { // chrome workaround
5399                var element = elements[i],
5400                    $shadow = $(element).data(ShadowKey);
5401
5402                // get offset from element, default to global option
5403                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
5404                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
5405                    shScrollOffsetY = $shadow.offset().top;
5406
5407                // check current state of element
5408                var elOnTop = element.classList.contains(classAbove);
5409
5410                // check current is visible
5411                var elVisible = $(element).closest(BlockSel).is(':visible');
5412
5413                // cols regx
5414                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
5415
5416                // if we were above, and are now below scroll position...
5417                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
5418                    
5419                    element.style.top = offsetTop + "px";
5420                    $shadow.css('height', $(element).css('height'));
5421
5422                    // remember element
5423                    elementsToUpdate.push({
5424                        element: element,
5425                        addClass: classBelow + " " + regxMatchCol,
5426                        removeClass: classAbove
5427                    });
5428
5429                    // if we were below, and are now above scroll position...
5430                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
5431
5432
5433                    // remember element
5434                    elementsToUpdate.push({
5435                        element: element,
5436                        addClass: classAbove,
5437                        removeClass: classBelow + " " + regxMatchCol
5438                    });
5439
5440                    $shadow.get(0).style.height = null;
5441                    element.style.top = null;
5442                }
5443            }
5444
5445            return elementsToUpdate;
5446        }
5447
5448        /* ====================
5449         * private function to update elements
5450         * ==================== */
5451        function updateElements(elementsToUpdate) {
5452
5453            // iterate over elements
5454            // for (var elem of elements) {
5455            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
5456                var map = elementsToUpdate[i];
5457
5458                // add style / class to element
5459                //map.element.classList.add(map.addClass);
5460                //map.element.classList.remove(map.removeClass);
5461                $(map.element).addClass(map.addClass);
5462                $(map.element).removeClass(map.removeClass);
5463            }
5464
5465            // resume accepting scroll events
5466            busy = false;
5467        }
5468
5469        /* ====================
5470         * public function to initially style elements based on scroll position
5471         *
5472         * options:
5473         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
5474         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
5475         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
5476         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
5477         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
5478         *
5479         * ==================== */
5480        var pub = {
5481            init: function (options) {
5482
5483                // suspend accepting scroll events
5484                busy = true;
5485
5486                // merge options object with global options
5487                if (options) {
5488                    if (options.spsClass) {
5489                        spsClass = options.spsClass;
5490                        elements = document.getElementsByClassName(spsClass);
5491                    }
5492                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
5493                    classAbove = options.classAbove || classAbove;
5494                    classBelow = options.classBelow || classBelow;
5495                    offsetTag = options.offsetTag || offsetTag;
5496                }
5497
5498                // ensure all elements have classAbove
5499                var elementsToUpdate = getElementsToUpdate(true);
5500                if (elementsToUpdate.length > 0) {
5501
5502                    // asynchronuously update elements
5503                    window.requestAnimationFrame(function () {
5504                        updateElements(elementsToUpdate);
5505                    });
5506                } else {
5507
5508                    // resume accepting scroll events
5509                    busy = false;
5510                }
5511            }
5512        };
5513
5514        // register for window scroll events
5515        $(window).on("scroll", onScroll);
5516
5517        window.ScrollOverSelfStyler = pub;
5518
5519        return pub;
5520    })(document, window, jQuery);
5521}
5522
5523/* ====================
5524 * main initialization
5525 * ==================== */
5526$(function () {
5527    // defer initialization to allow browser to restore scroll position
5528    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
5529});if (typeof jQuery === 'undefined') {
5530    throw new Error('Block\'s JavaScript requires jQuery')
5531}
5532
5533+function ($) {
5534    'use strict';
5535    var version = $.fn.jquery.split(' ')[0].split('.')
5536    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
5537        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
5538    }
5539}(jQuery);
5540
5541
5542+function ($, win) {
5543    'use strict';
5544
5545    var DataKey = 'blktabs',
5546        BlockSel = '.block-item',
5547        TabSel = '> .module-container .blk-tabs > ul',
5548        BtnSel = '> li',
5549        ValSel = ' > a[href^="#blk"]',
5550        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
5551        DestroyBeforeSymbol = 'destroyBeforeSymbol',
5552        Event = {
5553            ReplacedBefore: 'renderview.replace.before',
5554            ReplacedAfter: 'renderview.replace.after',
5555            BlockDestroy: 'destroy',
5556            BlockAppear: DataKey + '.block.appear',
5557            BlockHidden: DataKey + '.block.hidden',
5558            Click: {
5559                Window: 'blk-nav-in',
5560                Before: DataKey + '.tabs.click.before',
5561                After: DataKey + '.tabs.click.after'
5562            }
5563        },
5564        Options = {
5565            focus: 'active'
5566        };
5567
5568    function BlockTabs(element, opts) {
5569
5570        var self = this;
5571        this._opts = $.extend(Options, $(element).data(), opts);
5572        this._element = element;
5573        this._tabs = $(TabSel, element).get(0);
5574
5575        // block 更新屬性值之後將會被置換
5576        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
5577        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
5578        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
5579            $(this).addClass(ReplacedBeforeSymbol);
5580            event.data.blktabs.resetTabStatus();
5581            $(this).removeClass(ReplacedBeforeSymbol);
5582            $.removeData(this, DataKey);
5583        });
5584
5585        // block 被刪除前復原 tab 關聯的 block
5586        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
5587            $(this).addClass(DestroyBeforeSymbol);
5588            event.data.blktabs.resetTabStatus();
5589        });
5590
5591        // block tabs click 事件
5592        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
5593            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
5594            if ($(element).attr('href').startsWith('#')) {
5595                event.preventDefault();
5596                event.data.blktabs.tabClick(element);
5597                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
5598                    target: element,
5599                    detail: {
5600                        selector: $(element).attr('href')
5601                    }
5602                }));
5603            }
5604        });
5605
5606        this.tabAppear().resetMyStatus();
5607
5608        var bookmarkId = window.location.href.split('#').pop();
5609        if (this._element.id == bookmarkId) {
5610            // 錨點跳轉
5611            var blk = this;
5612            window.addEventListener("load", function (event) {
5613
5614                var arrParentAndButton = function (blkId) {
5615                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
5616                    var pblk = tab.closest(BlockSel);
5617                    if (pblk.length > 0 && pblk.attr('id')) {
5618                        // 記錄&尋找
5619                        var r = arrParentAndButton(pblk.attr('id'));
5620                        r.push([pblk, tab]);
5621                        return r;
5622                    }
5623                    return [];
5624                };
5625                var arr = arrParentAndButton(blk._element.id);
5626                for (var i in arr)
5627                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
5628
5629                setTimeout(function () {
5630                    $("html, body").animate({
5631                        scrollTop: $(blk._element).offset().top
5632                    }, 500, 'swing', function () { });
5633                }, 0.5 * 1000);
5634            });
5635        }
5636    }
5637
5638    var _proto = BlockTabs.prototype;
5639
5640    _proto.tabAppear = function tabAppear() {
5641        if ($(BtnSel, this._tabs).length > 0)
5642            $(this._tabs).removeClass('d-none hide');
5643        return this;
5644    }
5645
5646
5647    // 取得 block tabs 所有關聯的 block target
5648    _proto.getTabSelector = function getTabSelector() {
5649        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
5650            return $(o).attr('href');
5651        }).get().join(',');
5652    }
5653
5654    // 驅動所有關聯的 block target 執行 resetMyStatus
5655    _proto.resetTabStatus = function resetTabStatus(event) {
5656        $(this.getTabSelector()).each(function () {
5657            if ($(this).data(DataKey))
5658                $(this).data(DataKey).resetMyStatus();
5659        });
5660        return this;
5661    }
5662
5663    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
5664    _proto.resetMyStatus = function resetMyStatus() {
5665        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
5666            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
5667            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
5668            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
5669            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
5670            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
5671
5672        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
5673            // 顯示 element
5674            this._element.style.setProperty('display', '');
5675
5676            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
5677            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
5678            if ($tabLink.length < 1)
5679                $tabLink = $(BtnSel + ValSel, this._tabs);
5680            this.tabClick($tabLink.get(0));
5681            $(this._element).trigger(Event.BlockAppear);
5682        }
5683        else {
5684            // 隱藏 element
5685            this._element.style.setProperty('display', 'none', 'important');
5686            $(this._element).trigger(Event.BlockHidden);
5687        }
5688
5689        return this.resetTabStatus();
5690    }
5691
5692    // 點擊 block tabs
5693    _proto.tabClick = function tabClick(currentBtn, closure) {
5694
5695        // 點擊執行內容
5696        if ($.contains(this._element, currentBtn)) {
5697
5698            // tab 切換前
5699            $(this._element).trigger(Event.Click.Before, [currentBtn]);
5700
5701            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
5702            $(currentBtn).addClass(Options.focus);
5703
5704            this.resetTabStatus();
5705
5706            // tab 切換後
5707            $(this._element).trigger(Event.Click.After, [currentBtn]);
5708
5709            if (typeof (closure) === "function")
5710                closure();
5711        }
5712
5713        return this;
5714    }
5715
5716    if (typeof $.fn.blockTab !== 'function') {
5717
5718        $.fn.extend({
5719            blockTab: function (options) {
5720                this.filter(function (i, o) {
5721                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
5722                }).each(function (event) {
5723                    $(this).data(DataKey, new BlockTabs(this, options));
5724                });
5725            }
5726        });
5727    }
5728
5729    $(function () {
5730        $(BlockSel).blockTab();
5731    });
5732
5733}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
5734;(function($) {var _proto = String.prototype;
5735
5736if (typeof _proto.regxMatch !== 'function') {
5737    _proto.regxMatch = function regxMatch() {
5738        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
5739            regxStr = (typeof this === "string" || this instanceof String) ? this 
5739: "";
5740        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
5741            return x.trim();
5742        }).join(' ');
5743    }
5744}/**
5745 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
5746 * ======================================================================== */
5747
5748/**
5749 * @license
5750 * ========================================================================
5751 * ScrollPos-Styler v0.7.1
5752 * https://github.com/acch/scrollpos-styler
5753 * ========================================================================
5754 * Copyright 2015 Achim Christ
5755 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
5756 * ======================================================================== */
5757
5758// JSHint directives
5759/* exported ScrollPosStyler */
5760if (typeof window.ScrollOverSelfStyler === "undefined") {
5761    var ScrollOverSelfStyler = (function (document, window, $) {
5762        "use strict";
5763
5764        /* ====================
5765         * private variables
5766         * ==================== */
5767        var scrollPosY = 0,
5768            busy = false,
5769
5770            // toggle style / class when scrolling below this position (in px)
5771            scrollOffsetY = 1,
5772
5773            // class used to apply scrollPosStyler to
5774            spsClass = "soss",
5775
5776            // choose elements to apply style / class to
5777            elements = document.getElementsByClassName(spsClass),
5778
5779            // style / class to apply to elements when above scroll position
5780            classAbove = "soss--abv",
5781
5782            // style / class to apply to elements when below scroll position
5783            classBelow = "soss--blw",
5784
5785            // tag to set custom scroll offset per element
5786            offsetTag = "data-soss-offset";
5787
5788        
5789        var BlockSel = '.block-item',
5790            ShadowKey = "ScrollOverSelfStyler";
5791
5792        /* ====================
5793         * private function to check scroll position
5794         * ==================== */
5795        function onScroll() {
5796
5797            // ensure that events don't stack
5798            if (!busy) {
5799
5800                // find elements to update
5801                var elementsToUpdate = getElementsToUpdate(false);
5802                if (elementsToUpdate.length > 0) {
5803
5804                    // suspend accepting scroll events
5805                    busy = true;
5806
5807                    // asynchronuously update elements
5808                    window.requestAnimationFrame(function () {
5809                        updateElements(elementsToUpdate);
5810                    });
5811                }
5812            }
5813        }
5814
5815        /* ====================
5816         * copy Element Shadow
5817         * ==================== */
5818        function copyElementShadow(init) {
5819            for (var i = 0; elements[i]; ++i) {
5820                var element = elements[i];
5821                if (!$(element).data(ShadowKey)) {
5822                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
5823                }
5824            }
5825        }
5826
5827        /* ====================
5828         * private function to find elements to update
5829         * ==================== */
5830        function getElementsToUpdate(init) {
5831            var elementsToUpdate = [];
5832            copyElementShadow(init);
5833
5834            // get current scroll position from window
5835            scrollPosY = window.pageYOffset;
5836
5837            // iterate over elements
5838            // for (var elem of elements) {
5839            for (var i = 0; elements[i]; ++i) { // chrome workaround
5840                var element = elements[i],
5841                    $shadow = $(element).data(ShadowKey);
5842
5843                // get offset from element, default to global option
5844                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
5845                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
5846                    shScrollOffsetY = $shadow.offset().top;
5847
5848                // check current state of element
5849                var elOnTop = element.classList.contains(classAbove);
5850
5851                // check current is visible
5852                var elVisible = $(element).closest(BlockSel).is(':visible');
5853
5854                // cols regx
5855                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
5856
5857                // if we were above, and are now below scroll position...
5858                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
5859                    
5860                    element.style.top = offsetTop + "px";
5861                    $shadow.css('height', $(element).css('height'));
5862
5863                    // remember element
5864                    elementsToUpdate.push({
5865                        element: element,
5866                        addClass: classBelow + " " + regxMatchCol,
5867                        removeClass: classAbove
5868                    });
5869
5870                    // if we were below, and are now above scroll position...
5871                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
5872
5873
5874                    // remember element
5875                    elementsToUpdate.push({
5876                        element: element,
5877                        addClass: classAbove,
5878                        removeClass: classBelow + " " + regxMatchCol
5879                    });
5880
5881                    $shadow.get(0).style.height = null;
5882                    element.style.top = null;
5883                }
5884            }
5885
5886            return elementsToUpdate;
5887        }
5888
5889        /* ====================
5890         * private function to update elements
5891         * ==================== */
5892        function updateElements(elementsToUpdate) {
5893
5894            // iterate over elements
5895            // for (var elem of elements) {
5896            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
5897                var map = elementsToUpdate[i];
5898
5899                // add style / class to element
5900                //map.element.classList.add(map.addClass);
5901                //map.element.classList.remove(map.removeClass);
5902                $(map.element).addClass(map.addClass);
5903                $(map.element).removeClass(map.removeClass);
5904            }
5905
5906            // resume accepting scroll events
5907            busy = false;
5908        }
5909
5910        /* ====================
5911         * public function to initially style elements based on scroll position
5912         *
5913         * options:
5914         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
5915         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
5916         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
5917         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
5918         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
5919         *
5920         * ==================== */
5921        var pub = {
5922            init: function (options) {
5923
5924                // suspend accepting scroll events
5925                busy = true;
5926
5927                // merge options object with global options
5928                if (options) {
5929                    if (options.spsClass) {
5930                        spsClass = options.spsClass;
5931                        elements = document.getElementsByClassName(spsClass);
5932                    }
5933                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
5934                    classAbove = options.classAbove || classAbove;
5935                    classBelow = options.classBelow || classBelow;
5936                    offsetTag = options.offsetTag || offsetTag;
5937                }
5938
5939                // ensure all elements have classAbove
5940                var elementsToUpdate = getElementsToUpdate(true);
5941                if (elementsToUpdate.length > 0) {
5942
5943                    // asynchronuously update elements
5944                    window.requestAnimationFrame(function () {
5945                        updateElements(elementsToUpdate);
5946                    });
5947                } else {
5948
5949                    // resume accepting scroll events
5950                    busy = false;
5951                }
5952            }
5953        };
5954
5955        // register for window scroll events
5956        $(window).on("scroll", onScroll);
5957
5958        window.ScrollOverSelfStyler = pub;
5959
5960        return pub;
5961    })(document, window, jQuery);
5962}
5963
5964/* ====================
5965 * main initialization
5966 * ==================== */
5967$(function () {
5968    // defer initialization to allow browser to restore scroll position
5969    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
5970});if (typeof jQuery === 'undefined') {
5971    throw new Error('Block\'s JavaScript requires jQuery')
5972}
5973
5974+function ($) {
5975    'use strict';
5976    var version = $.fn.jquery.split(' ')[0].split('.')
5977    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
5978        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
5979    }
5980}(jQuery);
5981
5982
5983+function ($, win) {
5984    'use strict';
5985
5986    var DataKey = 'blktabs',
5987        BlockSel = '.block-item',
5988        TabSel = '> .module-container .blk-tabs > ul',
5989        BtnSel = '> li',
5990        ValSel = ' > a[href^="#blk"]',
5991        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
5992        DestroyBeforeSymbol = 'destroyBeforeSymbol',
5993        Event = {
5994            ReplacedBefore: 'renderview.replace.before',
5995            ReplacedAfter: 'renderview.replace.after',
5996            BlockDestroy: 'destroy',
5997            BlockAppear: DataKey + '.block.appear',
5998            BlockHidden: DataKey + '.block.hidden',
5999            Click: {
6000                Window: 'blk-nav-in',
6001                Before: DataKey + '.tabs.click.before',
6002                After: DataKey + '.tabs.click.after'
6003            }
6004        },
6005        Options = {
6006            focus: 'active'
6007        };
6008
6009    function BlockTabs(element, opts) {
6010
6011        var self = this;
6012        this._opts = $.extend(Options, $(element).data(), opts);
6013        this._element = element;
6014        this._tabs = $(TabSel, element).get(0);
6015
6016        // block 更新屬性值之後將會被置換
6017        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
6018        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
6019        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
6020            $(this).addClass(ReplacedBeforeSymbol);
6021            event.data.blktabs.resetTabStatus();
6022            $(this).removeClass(ReplacedBeforeSymbol);
6023            $.removeData(this, DataKey);
6024        });
6025
6026        // block 被刪除前復原 tab 關聯的 block
6027        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
6028            $(this).addClass(DestroyBeforeSymbol);
6029            event.data.blktabs.resetTabStatus();
6030        });
6031
6032        // block tabs click 事件
6033        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
6034            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
6035            if ($(element).attr('href').startsWith('#')) {
6036                event.preventDefault();
6037                event.data.blktabs.tabClick(element);
6038                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
6039                    target: element,
6040                    detail: {
6041                        selector: $(element).attr('href')
6042                    }
6043                }));
6044            }
6045        });
6046
6047        this.tabAppear().resetMyStatus();
6048
6049        var bookmarkId = window.location.href.split('#').pop();
6050        if (this._element.id == bookmarkId) {
6051            // 錨點跳轉
6052            var blk = this;
6053            window.addEventListener("load", function (event) {
6054
6055                var arrParentAndButton = function (blkId) {
6056                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
6057                    var pblk = tab.closest(BlockSel);
6058                    if (pblk.length > 0 && pblk.attr('id')) {
6059                        // 記錄&尋找
6060                        var r = arrParentAndButton(pblk.attr('id'));
6061                        r.push([pblk, tab]);
6062                        return r;
6063                    }
6064                    return [];
6065                };
6066                var arr = arrParentAndButton(blk._element.id);
6067                for (var i in arr)
6068                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
6069
6070                setTimeout(function () {
6071                    $("html, body").animate({
6072                        scrollTop: $(blk._element).offset().top
6073                    }, 500, 'swing', function () { });
6074                }, 0.5 * 1000);
6075            });
6076        }
6077    }
6078
6079    var _proto = BlockTabs.prototype;
6080
6081    _proto.tabAppear = function tabAppear() {
6082        if ($(BtnSel, this._tabs).length > 0)
6083            $(this._tabs).removeClass('d-none hide');
6084        return this;
6085    }
6086
6087
6088    // 取得 block tabs 所有關聯的 block target
6089    _proto.getTabSelector = function getTabSelector() {
6090        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
6091            return $(o).attr('href');
6092        }).get().join(',');
6093    }
6094
6095    // 驅動所有關聯的 block target 執行 resetMyStatus
6096    _proto.resetTabStatus = function resetTabStatus(event) {
6097        $(this.getTabSelector()).each(function () {
6098            if ($(this).data(DataKey))
6099                $(this).data(DataKey).resetMyStatus();
6100        });
6101        return this;
6102    }
6103
6104    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
6105    _proto.resetMyStatus = function resetMyStatus() {
6106        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
6107            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
6108            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
6109            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
6110            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
6111            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
6112
6113        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
6114            // 顯示 element
6115            this._element.style.setProperty('display', '');
6116
6117            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
6118            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
6119            if ($tabLink.length < 1)
6120                $tabLink = $(BtnSel + ValSel, this._tabs);
6121            this.tabClick($tabLink.get(0));
6122            $(this._element).trigger(Event.BlockAppear);
6123        }
6124        else {
6125            // 隱藏 element
6126            this._element.style.setProperty('display', 'none', 'important');
6127            $(this._element).trigger(Event.BlockHidden);
6128        }
6129
6130        return this.resetTabStatus();
6131    }
6132
6133    // 點擊 block tabs
6134    _proto.tabClick = function tabClick(currentBtn, closure) {
6135
6136        // 點擊執行內容
6137        if ($.contains(this._element, currentBtn)) {
6138
6139            // tab 切換前
6140            $(this._element).trigger(Event.Click.Before, [currentBtn]);
6141
6142            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
6143            $(currentBtn).addClass(Options.focus);
6144
6145            this.resetTabStatus();
6146
6147            // tab 切換後
6148            $(this._element).trigger(Event.Click.After, [currentBtn]);
6149
6150            if (typeof (closure) === "function")
6151                closure();
6152        }
6153
6154        return this;
6155    }
6156
6157    if (typeof $.fn.blockTab !== 'function') {
6158
6159        $.fn.extend({
6160            blockTab: function (options) {
6161                this.filter(function (i, o) {
6162                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
6163                }).each(function (event) {
6164                    $(this).data(DataKey, new BlockTabs(this, options));
6165                });
6166            }
6167        });
6168    }
6169
6170    $(function () {
6171        $(BlockSel).blockTab();
6172    });
6173
6174}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
6175;(function($) {var _proto = String.prototype;
6176
6177if (typeof _proto.regxMatch !== 'function') {
6178    _proto.regxMatch = function regxMatch() {
6179        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
6180            regxStr = (typeof this === "string" || this instanceof String) ? this 
6180: "";
6181        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
6182            return x.trim();
6183        }).join(' ');
6184    }
6185}/**
6186 * 已經改變了整個 scrollPosStyler 的內核,請勿覆蓋
6187 * ======================================================================== */
6188
6189/**
6190 * @license
6191 * ========================================================================
6192 * ScrollPos-Styler v0.7.1
6193 * https://github.com/acch/scrollpos-styler
6194 * ========================================================================
6195 * Copyright 2015 Achim Christ
6196 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
6197 * ======================================================================== */
6198
6199// JSHint directives
6200/* exported ScrollPosStyler */
6201if (typeof window.ScrollOverSelfStyler === "undefined") {
6202    var ScrollOverSelfStyler = (function (document, window, $) {
6203        "use strict";
6204
6205        /* ====================
6206         * private variables
6207         * ==================== */
6208        var scrollPosY = 0,
6209            busy = false,
6210
6211            // toggle style / class when scrolling below this position (in px)
6212            scrollOffsetY = 1,
6213
6214            // class used to apply scrollPosStyler to
6215            spsClass = "soss",
6216
6217            // choose elements to apply style / class to
6218            elements = document.getElementsByClassName(spsClass),
6219
6220            // style / class to apply to elements when above scroll position
6221            classAbove = "soss--abv",
6222
6223            // style / class to apply to elements when below scroll position
6224            classBelow = "soss--blw",
6225
6226            // tag to set custom scroll offset per element
6227            offsetTag = "data-soss-offset";
6228
6229        
6230        var BlockSel = '.block-item',
6231            ShadowKey = "ScrollOverSelfStyler";
6232
6233        /* ====================
6234         * private function to check scroll position
6235         * ==================== */
6236        function onScroll() {
6237
6238            // ensure that events don't stack
6239            if (!busy) {
6240
6241                // find elements to update
6242                var elementsToUpdate = getElementsToUpdate(false);
6243                if (elementsToUpdate.length > 0) {
6244
6245                    // suspend accepting scroll events
6246                    busy = true;
6247
6248                    // asynchronuously update elements
6249                    window.requestAnimationFrame(function () {
6250                        updateElements(elementsToUpdate);
6251                    });
6252                }
6253            }
6254        }
6255
6256        /* ====================
6257         * copy Element Shadow
6258         * ==================== */
6259        function copyElementShadow(init) {
6260            for (var i = 0; elements[i]; ++i) {
6261                var element = elements[i];
6262                if (!$(element).data(ShadowKey)) {
6263                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
6264                }
6265            }
6266        }
6267
6268        /* ====================
6269         * private function to find elements to update
6270         * ==================== */
6271        function getElementsToUpdate(init) {
6272            var elementsToUpdate = [];
6273            copyElementShadow(init);
6274
6275            // get current scroll position from window
6276            scrollPosY = window.pageYOffset;
6277
6278            // iterate over elements
6279            // for (var elem of elements) {
6280            for (var i = 0; elements[i]; ++i) { // chrome workaround
6281                var element = elements[i],
6282                    $shadow = $(element).data(ShadowKey);
6283
6284                // get offset from element, default to global option
6285                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
6286                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
6287                    shScrollOffsetY = $shadow.offset().top;
6288
6289                // check current state of element
6290                var elOnTop = element.classList.contains(classAbove);
6291
6292                // check current is visible
6293                var elVisible = $(element).closest(BlockSel).is(':visible');
6294
6295                // cols regx
6296                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));
6297
6298                // if we were above, and are now below scroll position...
6299                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
6300                    
6301                    element.style.top = offsetTop + "px";
6302                    $shadow.css('height', $(element).css('height'));
6303
6304                    // remember element
6305                    elementsToUpdate.push({
6306                        element: element,
6307                        addClass: classBelow + " " + regxMatchCol,
6308                        removeClass: classAbove
6309                    });
6310
6311                    // if we were below, and are now above scroll position...
6312                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
6313
6314
6315                    // remember element
6316                    elementsToUpdate.push({
6317                        element: element,
6318                        addClass: classAbove,
6319                        removeClass: classBelow + " " + regxMatchCol
6320                    });
6321
6322                    $shadow.get(0).style.height = null;
6323                    element.style.top = null;
6324                }
6325            }
6326
6327            return elementsToUpdate;
6328        }
6329
6330        /* ====================
6331         * private function to update elements
6332         * ==================== */
6333        function updateElements(elementsToUpdate) {
6334
6335            // iterate over elements
6336            // for (var elem of elements) {
6337            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
6338                var map = elementsToUpdate[i];
6339
6340                // add style / class to element
6341                //map.element.classList.add(map.addClass);
6342                //map.element.classList.remove(map.removeClass);
6343                $(map.element).addClass(map.addClass);
6344                $(map.element).removeClass(map.removeClass);
6345            }
6346
6347            // resume accepting scroll events
6348            busy = false;
6349        }
6350
6351        /* ====================
6352         * public function to initially style elements based on scroll position
6353         *
6354         * options:
6355         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
6356         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
6357         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
6358         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
6359         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
6360         *
6361         * ==================== */
6362        var pub = {
6363            init: function (options) {
6364
6365                // suspend accepting scroll events
6366                busy = true;
6367
6368                // merge options object with global options
6369                if (options) {
6370                    if (options.spsClass) {
6371                        spsClass = options.spsClass;
6372                        elements = document.getElementsByClassName(spsClass);
6373                    }
6374                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
6375                    classAbove = options.classAbove || classAbove;
6376                    classBelow = options.classBelow || classBelow;
6377                    offsetTag = options.offsetTag || offsetTag;
6378                }
6379
6380                // ensure all elements have classAbove
6381                var elementsToUpdate = getElementsToUpdate(true);
6382                if (elementsToUpdate.length > 0) {
6383
6384                    // asynchronuously update elements
6385                    window.requestAnimationFrame(function () {
6386                        updateElements(elementsToUpdate);
6387                    });
6388                } else {
6389
6390                    // resume accepting scroll events
6391                    busy = false;
6392                }
6393            }
6394        };
6395
6396        // register for window scroll events
6397        $(window).on("scroll", onScroll);
6398
6399        window.ScrollOverSelfStyler = pub;
6400
6401        return pub;
6402    })(document, window, jQuery);
6403}
6404
6405/* ====================
6406 * main initialization
6407 * ==================== */
6408$(function () {
6409    // defer initialization to allow browser to restore scroll position
6410    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
6411});if (typeof jQuery === 'undefined') {
6412    throw new Error('Block\'s JavaScript requires jQuery')
6413}
6414
6415+function ($) {
6416    'use strict';
6417    var version = $.fn.jquery.split(' ')[0].split('.')
6418    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
6419        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
6420    }
6421}(jQuery);
6422
6423
6424+function ($, win) {
6425    'use strict';
6426
6427    var DataKey = 'blktabs',
6428        BlockSel = '.block-item',
6429        TabSel = '> .module-container .blk-tabs > ul',
6430        BtnSel = '> li',
6431        ValSel = ' > a[href^="#blk"]',
6432        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
6433        DestroyBeforeSymbol = 'destroyBeforeSymbol',
6434        Event = {
6435            ReplacedBefore: 'renderview.replace.before',
6436            ReplacedAfter: 'renderview.replace.after',
6437            BlockDestroy: 'destroy',
6438            BlockAppear: DataKey + '.block.appear',
6439            BlockHidden: DataKey + '.block.hidden',
6440            Click: {
6441                Window: 'blk-nav-in',
6442                Before: DataKey + '.tabs.click.before',
6443                After: DataKey + '.tabs.click.after'
6444            }
6445        },
6446        Options = {
6447            focus: 'active'
6448        };
6449
6450    function BlockTabs(element, opts) {
6451
6452        var self = this;
6453        this._opts = $.extend(Options, $(element).data(), opts);
6454        this._element = element;
6455        this._tabs = $(TabSel, element).get(0);
6456
6457        // block 更新屬性值之後將會被置換
6458        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
6459        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
6460        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
6461            $(this).addClass(ReplacedBeforeSymbol);
6462            event.data.blktabs.resetTabStatus();
6463            $(this).removeClass(ReplacedBeforeSymbol);
6464            $.removeData(this, DataKey);
6465        });
6466
6467        // block 被刪除前復原 tab 關聯的 block
6468        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
6469            $(this).addClass(DestroyBeforeSymbol);
6470            event.data.blktabs.resetTabStatus();
6471        });
6472
6473        // block tabs click 事件
6474        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
6475            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
6476            if ($(element).attr('href').startsWith('#')) {
6477                event.preventDefault();
6478                event.data.blktabs.tabClick(element);
6479                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
6480                    target: element,
6481                    detail: {
6482                        selector: $(element).attr('href')
6483                    }
6484                }));
6485            }
6486        });
6487
6488        this.tabAppear().resetMyStatus();
6489
6490        var bookmarkId = window.location.href.split('#').pop();
6491        if (this._element.id == bookmarkId) {
6492            // 錨點跳轉
6493            var blk = this;
6494            window.addEventListener("load", function (event) {
6495
6496                var arrParentAndButton = function (blkId) {
6497                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
6498                    var pblk = tab.closest(BlockSel);
6499                    if (pblk.length > 0 && pblk.attr('id')) {
6500                        // 記錄&尋找
6501                        var r = arrParentAndButton(pblk.attr('id'));
6502                        r.push([pblk, tab]);
6503                        return r;
6504                    }
6505                    return [];
6506                };
6507                var arr = arrParentAndButton(blk._element.id);
6508                for (var i in arr)
6509                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));
6510
6511                setTimeout(function () {
6512                    $("html, body").animate({
6513                        scrollTop: $(blk._element).offset().top
6514                    }, 500, 'swing', function () { });
6515                }, 0.5 * 1000);
6516            });
6517        }
6518    }
6519
6520    var _proto = BlockTabs.prototype;
6521
6522    _proto.tabAppear = function tabAppear() {
6523        if ($(BtnSel, this._tabs).length > 0)
6524            $(this._tabs).removeClass('d-none hide');
6525        return this;
6526    }
6527
6528
6529    // 取得 block tabs 所有關聯的 block target
6530    _proto.getTabSelector = function getTabSelector() {
6531        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
6532            return $(o).attr('href');
6533        }).get().join(',');
6534    }
6535
6536    // 驅動所有關聯的 block target 執行 resetMyStatus
6537    _proto.resetTabStatus = function resetTabStatus(event) {
6538        $(this.getTabSelector()).each(function () {
6539            if ($(this).data(DataKey))
6540                $(this).data(DataKey).resetMyStatus();
6541        });
6542        return this;
6543    }
6544
6545    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
6546    _proto.resetMyStatus = function resetMyStatus() {
6547        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
6548            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
6549            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
6550            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
6551            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
6552            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a
6553
6554        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
6555            // 顯示 element
6556            this._element.style.setProperty('display', '');
6557
6558            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
6559            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
6560            if ($tabLink.length < 1)
6561                $tabLink = $(BtnSel + ValSel, this._tabs);
6562            this.tabClick($tabLink.get(0));
6563            $(this._element).trigger(Event.BlockAppear);
6564        }
6565        else {
6566            // 隱藏 element
6567            this._element.style.setProperty('display', 'none', 'important');
6568            $(this._element).trigger(Event.BlockHidden);
6569        }
6570
6571        return this.resetTabStatus();
6572    }
6573
6574    // 點擊 block tabs
6575    _proto.tabClick = function tabClick(currentBtn, closure) {
6576
6577        // 點擊執行內容
6578        if ($.contains(this._element, currentBtn)) {
6579
6580            // tab 切換前
6581            $(this._element).trigger(Event.Click.Before, [currentBtn]);
6582
6583            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
6584            $(currentBtn).addClass(Options.focus);
6585
6586            this.resetTabStatus();
6587
6588            // tab 切換後
6589            $(this._element).trigger(Event.Click.After, [currentBtn]);
6590
6591            if (typeof (closure) === "function")
6592                closure();
6593        }
6594
6595        return this;
6596    }
6597
6598    if (typeof $.fn.blockTab !== 'function') {
6599
6600        $.fn.extend({
6601            blockTab: function (options) {
6602                this.filter(function (i, o) {
6603                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
6604                }).each(function (event) {
6605                    $(this).data(DataKey, new BlockTabs(this, options));
6606                });
6607            }
6608        });
6609    }
6610
6611    $(function () {
6612        $(BlockSel).blockTab();
6613    });
6614
6615}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
6616/* MODULE 4d5d14c2-5508-4ce2-907f-f7133f76da2a, Version: 1.1.1 */
6617(function(a){a(function(){a(".mdu_hNWxgb93aU2y5VwIOopOcw").each(function(b){})})})(jQuery);
6618/* MODULE d0435c91-6b4a-44c2-8210-77336a6f6d9d, Version: 1.4.4 */
6619;(function($) {var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
6620
6621// NB: does not validate input
6622function encode(int) {
6623    if (int === 0) {
6624        return CHARSET[0];
6625    }
6626
6627    var res = "";
6628    while (int > 0) {
6629        res = CHARSET[int % 62] + res;
6630        int = Math.floor(int / 62);
6631    }
6632    return res;
6633};
6634
6635function decode(str) {
6636    var res = 0,
6637        length = str.length,
6638        i, char;
6639    for (i = 0; i < length; i++) {
6640        char = str.charCodeAt(i);
6641        if (char < 58) { // 0-9
6642            char = char - 48;
6643        } else if (char < 91) { // A-Z
6644            char = char - 29;
6645        } else { // a-z
6646            char = char - 87;
6647        }
6648        res += char * Math.pow(62, length - i - 1);
6649    }
6650    return res;
6651};
6652
6653function base62() {
6654    var id; //base62
6655    do {
6656      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
6657    } while (id.match(/^[0-9]/i) !== null);
6658    return id;
6659}(function($) {
6660    $(function() {
6661		// 是不是行動裝置
6662		var isMobile = false;
6663		if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
6664			isMobile = true;
6665		}
6666
6667    	$('[data-unicode="mdu_maTweYYxOU6LVnzYGkSjg"]').each (function () {
6668			$sel = $(this);
6669			var $id = base62();
6670	        $sel.attr('id',$id);
6671
6672	        var $navbarHoverBg = $sel.data('navbarHoverBg');
6673			var $navbarHoverColor = $sel.data('navbarHoverColor');
6674			var $dropdownHover = $sel.data('dropdownHover');
6675			$sel.find('[data-toggle="collapse"]').attr('data-target','#collapse_'+$id);
6676			$sel.find('#navbarSupportedContent').attr('id','collapse_'+$id);
6677        	
6678			$sel.prepend('<style type="text/css">'+
6679			'@media (any-hover: hover){'+
6680				'#'+$id+' .header-part .navbar-nav li a:hover {color:'+$navbarHoverColor+' !important;} '+
6681				'#'+$id+' .header-part .navbar-nav li a:hover {background-color:'+$navbarHoverBg+' !important;} '+
6682				'#'+$id+' .header-part .dropdown.show a:hover {background-color:'+$dropdownHover+' !important;}'+
6683			'}'+
6684			'#'+$id+' .header-part .dropdown.show {color:'+$navbarHoverColor+' !important;} '+
6685			'#'+$id+' .header-part .dropdown.show {background-color:'+$navbarHoverBg+' !important;} '+
6686			'#'+$id+' .dropdown-toggle::after{display: none;}'+
6687			'</style>');
6688			  
6689			function onthescroll() {
6690				var $sel = $(this);
6691				var scroll = $(window).scrollTop();
6692				$sel.children('nav').each(function () {
6693					var $nav = $(this);
6694					if(Math.round(scroll) == 0) {
6695						$nav.css('max-width', '')
6696						$nav.parent().css('min-height', '')
6697						$nav.removeClass('fixed-top').removeClass('m-auto');
6698					}
6699					else if(Math.round(scroll) > Math.round($nav.offset().top)) {
6700						$nav.parent().css('min-height', $nav.height() + "px")
6701						$nav.css('max-width', $nav.outerWidth() + "px")
6702						$nav.addClass('fixed-top m-auto');
6703					}
6704				});
6705			}
6706
6707			$(window).scroll(onthescroll.bind(this));
6708			
6709			if (isMobile){
6710				$sel.find('li.dropdown a').each(function(){
6711					var $hyperlink = $(this);
6712					$hyperlink.append('<div class="mobileTriggerButton"></div>');
6713				});
6714			}
6715			
6716			$('.mobileTriggerButton').on('click',function(){
6717				$mobTriBtn = $(this);
6718				var $dorpMenu = $mobTriBtn.closest('.nav-item').find('.dropdown-menu');
6719				console.log('hihihi')
6720				console.log($dorpMenu)
6721				console.log($dorpMenu.is(':hidden'))
6722				if ($dorpMenu.is(':hidden')){
6723					$dorpMenu.show();
6724				}else{
6725					$dorpMenu.hide();
6726				}
6727			});
6728			//$sel.find('li.dropdown a').click(function(){
6729			//	var $hyperlink = $(this);
6730			//	// 電腦版本(滑鼠移過去會展開) || 沒有子項目 || 展開狀態 => 跳轉
6731			//	if (!isMobile || !$hyperlink.siblings('.dropdown-menu').lengtn || $hyperlink.siblings('.dropdown-menu.show').lengtn)
6732			//		$('<a />').attr('target',$('#test').attr('target')).attr('href',$('#test').attr('href'))[0].click()
6733			//})
6734		});
6735    });
6736})(jQuery);; })(jQuery);/* compress error:[4]function encode(int) {*/
6737
6738/* MODULE 2efbc2f9-9f72-4e00-97ef-13398ef7c6f5, Version: 1.1.11 */
6739;(function($) {var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
6740
6741// NB: does not validate input
6742function encode(int) {
6743    if (int === 0) {
6744        return CHARSET[0];
6745    }
6746
6747    var res = "";
6748    while (int > 0) {
6749        res = CHARSET[int % 62] + res;
6750        int = Math.floor(int / 62);
6751    }
6752    return res;
6753};
6754
6755function decode(str) {
6756    var res = 0,
6757        length = str.length,
6758        i, char;
6759    for (i = 0; i < length; i++) {
6760        char = str.charCodeAt(i);
6761        if (char < 58) { // 0-9
6762            char = char - 48;
6763        } else if (char < 91) { // A-Z
6764            char = char - 29;
6765        } else { // a-z
6766            char = char - 87;
6767        }
6768        res += char * Math.pow(62, length - i - 1);
6769    }
6770    return res;
6771};
6772
6773function base62() {
6774    var id; //base62
6775    do {
6776      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
6777    } while (id.match(/^[0-9]/i) !== null);
6778    return id;
6779}/*!
6780 * jQuery1113 JavaScript Library v1.11.3
6781 * http://jQuery1113.com/
6782 *
6783 * Includes Sizzle.js
6784 * http://sizzlejs.com/
6785 *
6786 * Copyright 2005, 2014 jQuery1113 Foundation, Inc. and other contributors
6787 * Released under the MIT license
6788 * http://jQuery1113.org/license
6789 *
6790 * Date: 2015-04-28T16:19Z
6791 */
6792
6793(function( global, factory ) {
6794
6795	if ( typeof module === "object" && typeof module.exports === "object" ) {
6796		// For CommonJS and CommonJS-like environments where a proper window is present,
6797		// execute the factory and get jQuery1113
6798		// For environments that do not inherently posses a window with a document
6799		// (such as Node.js), expose a jQuery1113-making factory as module.exports
6800		// This accentuates the need for the creation of a real window
6801		// e.g. var jQuery1113 = require("jQuery1113")(window);
6802		// See ticket #14549 for more info
6803		module.exports = global.document ?
6804			factory( global, true ) :
6805			function( w ) {
6806				if ( !w.document ) {
6807					throw new Error( "jQuery1113 requires a window with a document" );
6808				}
6809				return factory( w );
6810			};
6811	} else {
6812		factory( global );
6813	}
6814
6815// Pass this if window is not defined yet
6816}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
6817
6818// Can't do this because several apps including ASP.NET trace
6819// the stack via arguments.caller.callee and Firefox dies if
6820// you try to trace through "use strict" call chains. (#13335)
6821// Support: Firefox 18+
6822//
6823
6824var deletedIds = [];
6825
6826var slice = deletedIds.slice;
6827
6828var concat = deletedIds.concat;
6829
6830var push = deletedIds.push;
6831
6832var indexOf = deletedIds.indexOf;
6833
6834var class2type = {};
6835
6836var toString = class2type.toString;
6837
6838var hasOwn = class2type.hasOwnProperty;
6839
6840var support = {};
6841
6842
6843
6844var
6845	version = "1.11.3",
6846
6847	// Define a local copy of jQuery1113
6848	jQuery1113 = function( selector, context ) {
6849		// The jQuery1113 object is actually just the init constructor 'enhanced'
6850		// Need init if jQuery1113 is called (just allow error to be thrown if not included)
6851		return new jQuery1113.fn.init( selector, context );
6852	},
6853
6854	// Support: Android<4.1, IE<9
6855	// Make sure we trim BOM and NBSP
6856	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
6857
6858	// Matches dashed string for camelizing
6859	rmsPrefix = /^-ms-/,
6860	rdashAlpha = /-([\da-z])/gi,
6861
6862	// Used by jQuery1113.camelCase as callback to replace()
6863	fcamelCase = function( all, letter ) {
6864		return letter.toUpperCase();
6865	};
6866
6867jQuery1113.fn = jQuery1113.prototype = {
6868	// The current version of jQuery1113 being used
6869	jQuery1113: version,
6870
6871	constructor: jQuery1113,
6872
6873	// Start with an empty selector
6874	selector: "",
6875
6876	// The default length of a jQuery1113 object is 0
6877	length: 0,
6878
6879	toArray: function() {
6880		return slice.call( this );
6881	},
6882
6883	// Get the Nth element in the matched element set OR
6884	// Get the whole matched element set as a clean array
6885	get: function( num ) {
6886		return num != null ?
6887
6888			// Return just the one element from the set
6889			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
6890
6891			// Return all the elements in a clean array
6892			slice.call( this );
6893	},
6894
6895	// Take an array of elements and push it onto the stack
6896	// (returning the new matched element set)
6897	pushStack: function( elems ) {
6898
6899		// Build a new jQuery1113 matched element set
6900		var ret = jQuery1113.merge( this.constructor(), elems );
6901
6902		// Add the old object onto the stack (as a reference)
vendor: 9,364 bytes, lines 6903-7283
6903		ret.prevObject = this;
6904		ret.context = this.context;
6905
6906		// Return the newly-formed element set
6907		return ret;
6908	},
6909
6910	// Execute a callback for every element in the matched set.
6911	// (You can seed the arguments with an array of args, but this is
6912	// only used internally.)
6913	each: function( callback, args ) {
6914		return jQuery1113.each( this, callback, args );
6915	},
6916
6917	map: function( callback ) {
6918		return this.pushStack( jQuery1113.map(this, function( elem, i ) {
6919			return callback.call( elem, i, elem );
6920		}));
6921	},
6922
6923	slice: function() {
6924		return this.pushStack( slice.apply( this, arguments ) );
6925	},
6926
6927	first: function() {
6928		return this.eq( 0 );
6929	},
6930
6931	last: function() {
6932		return this.eq( -1 );
6933	},
6934
6935	eq: function( i ) {
6936		var len = this.length,
6937			j = +i + ( i < 0 ? len : 0 );
6938		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
6939	},
6940
6941	end: function() {
6942		return this.prevObject || this.constructor(null);
6943	},
6944
6945	// For internal use only.
6946	// Behaves like an Array's method, not like a jQuery1113 method.
6947	push: push,
6948	sort: deletedIds.sort,
6949	splice: deletedIds.splice
6950};
6951
6952jQuery1113.extend = jQuery1113.fn.extend = function() {
6953	var src, copyIsArray, copy, name, options, clone,
6954		target = arguments[0] || {},
6955		i = 1,
6956		length = arguments.length,
6957		deep = false;
6958
6959	// Handle a deep copy situation
6960	if ( typeof target === "boolean" ) {
6961		deep = target;
6962
6963		// skip the boolean and the target
6964		target = arguments[ i ] || {};
6965		i++;
6966	}
6967
6968	// Handle case when target is a string or something (possible in deep copy)
6969	if ( typeof target !== "object" && !jQuery1113.isFunction(target) ) {
6970		target = {};
6971	}
6972
6973	// extend jQuery1113 itself if only one argument is passed
6974	if ( i === length ) {
6975		target = this;
6976		i--;
6977	}
6978
6979	for ( ; i < length; i++ ) {
6980		// Only deal with non-null/undefined values
6981		if ( (options = arguments[ i ]) != null ) {
6982			// Extend the base object
6983			for ( name in options ) {
6984				src = target[ name ];
6985				copy = options[ name ];
6986
6987				// Prevent never-ending loop
6988				if ( target === copy ) {
6989					continue;
6990				}
6991
6992				// Recurse if we're merging plain objects or arrays
6993				if ( deep && copy && ( jQuery1113.isPlainObject(copy) || (copyIsArray = jQuery1113.isArray(copy)) ) ) {
6994					if ( copyIsArray ) {
6995						copyIsArray = false;
6996						clone = src && jQuery1113.isArray(src) ? src : [];
6997
6998					} else {
6999						clone = src && jQuery1113.isPlainObject(src) ? src : {};
7000					}
7001
7002					// Never move original objects, clone them
7003					target[ name ] = jQuery1113.extend( deep, clone, copy );
7004
7005				// Don't bring in undefined values
7006				} else if ( copy !== undefined ) {
7007					target[ name ] = copy;
7008				}
7009			}
7010		}
7011	}
7012
7013	// Return the modified object
7014	return target;
7015};
7016
7017jQuery1113.extend({
7018	// Unique for each copy of jQuery1113 on the page
7019	expando: "jQuery1113" + ( version + Math.random() ).replace( /\D/g, "" ),
7020
7021	// Assume jQuery1113 is ready without the ready module
7022	isReady: true,
7023
7024	error: function( msg ) {
7025		throw new Error( msg );
7026	},
7027
7028	noop: function() {},
7029
7030	// See test/unit/core.js for details concerning isFunction.
7031	// Since version 1.3, DOM methods and functions like alert
7032	// aren't supported. They return false on IE (#2968).
7033	isFunction: function( obj ) {
7034		return jQuery1113.type(obj) === "function";
7035	},
7036
7037	isArray: Array.isArray || function( obj ) {
7038		return jQuery1113.type(obj) === "array";
7039	},
7040
7041	isWindow: function( obj ) {
7042		/* jshint eqeqeq: false */
7043		return obj != null && obj == obj.window;
7044	},
7045
7046	isNumeric: function( obj ) {
7047		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
7048		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
7049		// subtraction forces infinities to NaN
7050		// adding 1 corrects loss of precision from parseFloat (#15100)
7051		return !jQuery1113.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
7052	},
7053
7054	isEmptyObject: function( obj ) {
7055		var name;
7056		for ( name in obj ) {
7057			return false;
7058		}
7059		return true;
7060	},
7061
7062	isPlainObject: function( obj ) {
7063		var key;
7064
7065		// Must be an Object.
7066		// Because of IE, we also have to check the presence of the constructor property.
7067		// Make sure that DOM nodes and window objects don't pass through, as well
7068		if ( !obj || jQuery1113.type(obj) !== "object" || obj.nodeType || jQuery1113.isWindow( obj ) ) {
7069			return false;
7070		}
7071
7072		try {
7073			// Not own constructor property must be Object
7074			if ( obj.constructor &&
7075				!hasOwn.call(obj, "constructor") &&
7076				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
7077				return false;
7078			}
7079		} catch ( e ) {
7080			// IE8,9 Will throw exceptions on certain host objects #9897
7081			return false;
7082		}
7083
7084		// Support: IE<9
7085		// Handle iteration over inherited properties before own properties.
7086		if ( support.ownLast ) {
7087			for ( key in obj ) {
7088				return hasOwn.call( obj, key );
7089			}
7090		}
7091
7092		// Own properties are enumerated firstly, so to speed up,
7093		// if last one is own, then all properties are own.
7094		for ( key in obj ) {}
7095
7096		return key === undefined || hasOwn.call( obj, key );
7097	},
7098
7099	type: function( obj ) {
7100		if ( obj == null ) {
7101			return obj + "";
7102		}
7103		return typeof obj === "object" || typeof obj === "function" ?
7104			class2type[ toString.call(obj) ] || "object" :
7105			typeof obj;
7106	},
7107
7108	// Evaluates a script in a global context
7109	// Workarounds based on findings by Jim Driscoll
7110	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
7111	globalEval: function( data ) {
7112		if ( data && jQuery1113.trim( data ) ) {
7113			// We use execScript on Internet Explorer
7114			// We use an anonymous function so that context is window
7115			// rather than jQuery1113 in Firefox
7116			( window.execScript || function( data ) {
7117				window[ "eval" ].call( window, data );
7118			} )( data );
7119		}
7120	},
7121
7122	// Convert dashed to camelCase; used by the css and data modules
7123	// Microsoft forgot to hump their vendor prefix (#9572)
7124	camelCase: function( string ) {
7125		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
7126	},
7127
7128	nodeName: function( elem, name ) {
7129		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
7130	},
7131
7132	// args is for internal usage only
7133	each: function( obj, callback, args ) {
7134		var value,
7135			i = 0,
7136			length = obj.length,
7137			isArray = isArraylike( obj );
7138
7139		if ( args ) {
7140			if ( isArray ) {
7141				for ( ; i < length; i++ ) {
7142					value = callback.apply( obj[ i ], args );
7143
7144					if ( value === false ) {
7145						break;
7146					}
7147				}
7148			} else {
7149				for ( i in obj ) {
7150					value = callback.apply( obj[ i ], args );
7151
7152					if ( value === false ) {
7153						break;
7154					}
7155				}
7156			}
7157
7158		// A special, fast, case for the most common use of each
7159		} else {
7160			if ( isArray ) {
7161				for ( ; i < length; i++ ) {
7162					value = callback.call( obj[ i ], i, obj[ i ] );
7163
7164					if ( value === false ) {
7165						break;
7166					}
7167				}
7168			} else {
7169				for ( i in obj ) {
7170					value = callback.call( obj[ i ], i, obj[ i ] );
7171
7172					if ( value === false ) {
7173						break;
7174					}
7175				}
7176			}
7177		}
7178
7179		return obj;
7180	},
7181
7182	// Support: Android<4.1, IE<9
7183	trim: function( text ) {
7184		return text == null ?
7185			"" :
7186			( text + "" ).replace( rtrim, "" );
7187	},
7188
7189	// results is for internal usage only
7190	makeArray: function( arr, results ) {
7191		var ret = results || [];
7192
7193		if ( arr != null ) {
7194			if ( isArraylike( Object(arr) ) ) {
7195				jQuery1113.merge( ret,
7196					typeof arr === "string" ?
7197					[ arr ] : arr
7198				);
7199			} else {
7200				push.call( ret, arr );
7201			}
7202		}
7203
7204		return ret;
7205	},
7206
7207	inArray: function( elem, arr, i ) {
7208		var len;
7209
7210		if ( arr ) {
7211			if ( indexOf ) {
7212				return indexOf.call( arr, elem, i );
7213			}
7214
7215			len = arr.length;
7216			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
7217
7218			for ( ; i < len; i++ ) {
7219				// Skip accessing in sparse arrays
7220				if ( i in arr && arr[ i ] === elem ) {
7221					return i;
7222				}
7223			}
7224		}
7225
7226		return -1;
7227	},
7228
7229	merge: function( first, second ) {
7230		var len = +second.length,
7231			j = 0,
7232			i = first.length;
7233
7234		while ( j < len ) {
7235			first[ i++ ] = second[ j++ ];
7236		}
7237
7238		// Support: IE<9
7239		// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
7240		if ( len !== len ) {
7241			while ( second[j] !== undefined ) {
7242				first[ i++ ] = second[ j++ ];
7243			}
7244		}
7245
7246		first.length = i;
7247
7248		return first;
7249	},
7250
7251	grep: function( elems, callback, invert ) {
7252		var callbackInverse,
7253			matches = [],
7254			i = 0,
7255			length = elems.length,
7256			callbackExpect = !invert;
7257
7258		// Go through the array, only saving the items
7259		// that pass the validator function
7260		for ( ; i < length; i++ ) {
7261			callbackInverse = !callback( elems[ i ], i );
7262			if ( callbackInverse !== callbackExpect ) {
7263				matches.push( elems[ i ] );
7264			}
7265		}
7266
7267		return matches;
7268	},
7269
7270	// arg is for internal usage only
7271	map: function( elems, callback, arg ) {
7272		var value,
7273			i = 0,
7274			length = elems.length,
7275			isArray = isArraylike( elems ),
7276			ret = [];
7277
7278		// Go through the array, translating each of the items to their new values
7279		if ( isArray ) {
7280			for ( ; i < length; i++ ) {
7281				value = callback( elems[ i ], i, arg );
7282
7283				if ( value != null ) {
vendor: 27,588 bytes, lines 7284-8209
7284					ret.push( value );
7285				}
7286			}
7287
7288		// Go through every key on the object,
7289		} else {
7290			for ( i in elems ) {
7291				value = callback( elems[ i ], i, arg );
7292
7293				if ( value != null ) {
7294					ret.push( value );
7295				}
7296			}
7297		}
7298
7299		// Flatten any nested arrays
7300		return concat.apply( [], ret );
7301	},
7302
7303	// A global GUID counter for objects
7304	guid: 1,
7305
7306	// Bind a function to a context, optionally partially applying any
7307	// arguments.
7308	proxy: function( fn, context ) {
7309		var args, proxy, tmp;
7310
7311		if ( typeof context === "string" ) {
7312			tmp = fn[ context ];
7313			context = fn;
7314			fn = tmp;
7315		}
7316
7317		// Quick check to determine if target is callable, in the spec
7318		// this throws a TypeError, but we will just return undefined.
7319		if ( !jQuery1113.isFunction( fn ) ) {
7320			return undefined;
7321		}
7322
7323		// Simulated bind
7324		args = slice.call( arguments, 2 );
7325		proxy = function() {
7326			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
7327		};
7328
7329		// Set the guid of unique handler to the same of original handler, so it can be removed
7330		proxy.guid = fn.guid = fn.guid || jQuery1113.guid++;
7331
7332		return proxy;
7333	},
7334
7335	now: function() {
7336		return +( new Date() );
7337	},
7338
7339	// jQuery1113.support is not used in Core but other projects attach their
7340	// properties to it so it needs to exist.
7341	support: support
7342});
7343
7344// Populate the class2type map
7345jQuery1113.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
7346	class2type[ "[object " + name + "]" ] = name.toLowerCase();
7347});
7348
7349function isArraylike( obj ) {
7350
7351	// Support: iOS 8.2 (not reproducible in simulator)
7352	// `in` check used to prevent JIT error (gh-2145)
7353	// hasOwn isn't used here due to false negatives
7354	// regarding Nodelist length in IE
7355	var length = "length" in obj && obj.length,
7356		type = jQuery1113.type( obj );
7357
7358	if ( type === "function" || jQuery1113.isWindow( obj ) ) {
7359		return false;
7360	}
7361
7362	if ( obj.nodeType === 1 && length ) {
7363		return true;
7364	}
7365
7366	return type === "array" || length === 0 ||
7367		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
7368}
7369var Sizzle =
7370/*!
7371 * Sizzle CSS Selector Engine v2.2.0-pre
7372 * http://sizzlejs.com/
7373 *
7374 * Copyright 2008, 2014 jQuery1113 Foundation, Inc. and other contributors
7375 * Released under the MIT license
7376 * http://jQuery1113.org/license
7377 *
7378 * Date: 2014-12-16
7379 */
7380(function( window ) {
7381
7382var i,
7383	support,
7384	Expr,
7385	getText,
7386	isXML,
7387	tokenize,
7388	compile,
7389	select,
7390	outermostContext,
7391	sortInput,
7392	hasDuplicate,
7393
7394	// Local document vars
7395	setDocument,
7396	document,
7397	docElem,
7398	documentIsHTML,
7399	rbuggyQSA,
7400	rbuggyMatches,
7401	matches,
7402	contains,
7403
7404	// Instance-specific data
7405	expando = "sizzle" + 1 * new Date(),
7406	preferredDoc = window.document,
7407	dirruns = 0,
7408	done = 0,
7409	classCache = createCache(),
7410	tokenCache = createCache(),
7411	compilerCache = createCache(),
7412	sortOrder = function( a, b ) {
7413		if ( a === b ) {
7414			hasDuplicate = true;
7415		}
7416		return 0;
7417	},
7418
7419	// General-purpose constants
7420	MAX_NEGATIVE = 1 << 31,
7421
7422	// Instance methods
7423	hasOwn = ({}).hasOwnProperty,
7424	arr = [],
7425	pop = arr.pop,
7426	push_native = arr.push,
7427	push = arr.push,
7428	slice = arr.slice,
7429	// Use a stripped-down indexOf as it's faster than native
7430	// http://jsperf.com/thor-indexof-vs-for/5
7431	indexOf = function( list, elem ) {
7432		var i = 0,
7433			len = list.length;
7434		for ( ; i < len; i++ ) {
7435			if ( list[i] === elem ) {
7436				return i;
7437			}
7438		}
7439		return -1;
7440	},
7441
7442	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
7443
7444	// Regular expressions
7445
7446	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
7447	whitespace = "[\\x20\\t\\r\\n\\f]",
7448	// http://www.w3.org/TR/css3-syntax/#characters
7449	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
7450
7451	// Loosely modeled on CSS identifier characters
7452	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
7453	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
7454	identifier = characterEncoding.replace( "w", "w#" ),
7455
7456	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
7457	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
7458		// Operator (capture 2)
7459		"*([*^$|!~]?=)" + whitespace +
7460		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
7461		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
7462		"*\\]",
7463
7464	pseudos = ":(" + characterEncoding + ")(?:\\((" +
7465		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
7466		// 1. quoted (capture 3; capture 4 or capture 5)
7467		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
7468		// 2. simple (capture 6)
7469		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
7470		// 3. anything else (capture 2)
7471		".*" +
7472		")\\)|)",
7473
7474	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
7475	rwhitespace = new RegExp( whitespace + "+", "g" ),
7476	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
7477
7478	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
7479	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
7480
7481	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
7482
7483	rpseudo = new RegExp( pseudos ),
7484	ridentifier = new RegExp( "^" + identifier + "$" ),
7485
7486	matchExpr = {
7487		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
7488		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
7489		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
7490		"ATTR": new RegExp( "^" + attributes ),
7491		"PSEUDO": new RegExp( "^" + pseudos ),
7492		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
7493			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
7494			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
7495		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
7496		// For use in libraries implementing .is()
7497		// We use this for POS matching in `select`
7498		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
7499			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
7500	},
7501
7502	rinputs = /^(?:input|select|textarea|button)$/i,
7503	rheader = /^h\d$/i,
7504
7505	rnative = /^[^{]+\{\s*\[native \w/,
7506
7507	// Easily-parseable/retrievable ID or TAG or CLASS selectors
7508	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
7509
7510	rsibling = /[+~]/,
7511	rescape = /'|\\/g,
7512
7513	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
7514	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
7515	funescape = function( _, escaped, escapedWhitespace ) {
7516		var high = "0x" + escaped - 0x10000;
7517		// NaN means non-codepoint
7518		// Support: Firefox<24
7519		// Workaround erroneous numeric interpretation of +"0x"
7520		return high !== high || escapedWhitespace ?
7521			escaped :
7522			high < 0 ?
7523				// BMP codepoint
7524				String.fromCharCode( high + 0x10000 ) :
7525				// Supplemental Plane codepoint (surrogate pair)
7526				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
7527	},
7528
7529	// Used for iframes
7530	// See setDocument()
7531	// Removing the function wrapper causes a "Permission Denied"
7532	// error in IE
7533	unloadHandler = function() {
7534		setDocument();
7535	};
7536
7537// Optimize for push.apply( _, NodeList )
7538try {
7539	push.apply(
7540		(arr = slice.call( preferredDoc.childNodes )),
7541		preferredDoc.childNodes
7542	);
7543	// Support: Android<4.0
7544	// Detect silently failing push.apply
7545	arr[ preferredDoc.childNodes.length ].nodeType;
7546} catch ( e ) {
7547	push = { apply: arr.length ?
7548
7549		// Leverage slice if possible
7550		function( target, els ) {
7551			push_native.apply( target, slice.call(els) );
7552		} :
7553
7554		// Support: IE<9
7555		// Otherwise append directly
7556		function( target, els ) {
7557			var j = target.length,
7558				i = 0;
7559			// Can't trust NodeList.length
7560			while ( (target[j++] = els[i++]) ) {}
7561			target.length = j - 1;
7562		}
7563	};
7564}
7565
7566function Sizzle( selector, context, results, seed ) {
7567	var match, elem, m, nodeType,
7568		// QSA vars
7569		i, groups, old, nid, newContext, newSelector;
7570
7571	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
7572		setDocument( context );
7573	}
7574
7575	context = context || document;
7576	results = results || [];
7577	nodeType = context.nodeType;
7578
7579	if ( typeof selector !== "string" || !selector ||
7580		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
7581
7582		return results;
7583	}
7584
7585	if ( !seed && documentIsHTML ) {
7586
7587		// Try to shortcut find operations when possible (e.g., not under DocumentFragment)
7588		if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
7589			// Speed-up: Sizzle("#ID")
7590			if ( (m = match[1]) ) {
7591				if ( nodeType === 9 ) {
7592					elem = context.getElementById( m );
7593					// Check parentNode to catch when Blackberry 4.6 returns
7594					// nodes that are no longer in the document (jQuery1113 #6963)
7595					if ( elem && elem.parentNode ) {
7596						// Handle the case where IE, Opera, and Webkit return items
7597						// by name instead of ID
7598						if ( elem.id === m ) {
7599							results.push( elem );
7600							return results;
7601						}
7602					} else {
7603						return results;
7604					}
7605				} else {
7606					// Context is not a document
7607					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
7608						contains( context, elem ) && elem.id === m ) {
7609						results.push( elem );
7610						return results;
7611					}
7612				}
7613
7614			// Speed-up: Sizzle("TAG")
7615			} else if ( match[2] ) {
7616				push.apply( results, context.getElementsByTagName( selector ) );
7617				return results;
7618
7619			// Speed-up: Sizzle(".CLASS")
7620			} else if ( (m = match[3]) && support.getElementsByClassName ) {
7621				push.apply( results, context.getElementsByClassName( m ) );
7622				return results;
7623			}
7624		}
7625
7626		// QSA path
7627		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
7628			nid = old = expando;
7629			newContext = context;
7630			newSelector = nodeType !== 1 && selector;
7631
7632			// qSA works strangely on Element-rooted queries
7633			// We can work around this by specifying an extra ID on the root
7634			// and working up from there (Thanks to Andrew Dupont for the technique)
7635			// IE 8 doesn't work on object elements
7636			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
7637				groups = tokenize( selector );
7638
7639				if ( (old = context.getAttribute("id")) ) {
7640					nid = old.replace( rescape, "\\$&" );
7641				} else {
7642					context.setAttribute( "id", nid );
7643				}
7644				nid = "[id='" + nid + "'] ";
7645
7646				i = groups.length;
7647				while ( i-- ) {
7648					groups[i] = nid + toSelector( groups[i] );
7649				}
7650				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
7651				newSelector = groups.join(",");
7652			}
7653
7654			if ( newSelector ) {
7655				try {
7656					push.apply( results,
7657						newContext.querySelectorAll( newSelector )
7658					);
7659					return results;
7660				} catch(qsaError) {
7661				} finally {
7662					if ( !old ) {
7663						context.removeAttribute("id");
7664					}
7665				}
7666			}
7667		}
7668	}
7669
7670	// All others
7671	return select( selector.replace( rtrim, "$1" ), context, results, seed );
7672}
7673
7674/**
7675 * Create key-value caches of limited size
7676 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
7677 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
7678 *	deleting the oldest entry
7679 */
7680function createCache() {
7681	var keys = [];
7682
7683	function cache( key, value ) {
7684		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
7685		if ( keys.push( key + " " ) > Expr.cacheLength ) {
7686			// Only keep the most recent entries
7687			delete cache[ keys.shift() ];
7688		}
7689		return (cache[ key + " " ] = value);
7690	}
7691	return cache;
7692}
7693
7694/**
7695 * Mark a function for special use by Sizzle
7696 * @param {Function} fn The function to mark
7697 */
7698function markFunction( fn ) {
7699	fn[ expando ] = true;
7700	return fn;
7701}
7702
7703/**
7704 * Support testing using an element
7705 * @param {Function} fn Passed the created div and expects a boolean result
7706 */
7707function assert( fn ) {
7708	var div = document.createElement("div");
7709
7710	try {
7711		return !!fn( div );
7712	} catch (e) {
7713		return false;
7714	} finally {
7715		// Remove from its parent by default
7716		if ( div.parentNode ) {
7717			div.parentNode.removeChild( div );
7718		}
7719		// release memory in IE
7720		div = null;
7721	}
7722}
7723
7724/**
7725 * Adds the same handler for all of the specified attrs
7726 * @param {String} attrs Pipe-separated list of attributes
7727 * @param {Function} handler The method that will be applied
7728 */
7729function addHandle( attrs, handler ) {
7730	var arr = attrs.split("|"),
7731		i = attrs.length;
7732
7733	while ( i-- ) {
7734		Expr.attrHandle[ arr[i] ] = handler;
7735	}
7736}
7737
7738/**
7739 * Checks document order of two siblings
7740 * @param {Element} a
7741 * @param {Element} b
7742 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
7743 */
7744function siblingCheck( a, b ) {
7745	var cur = b && a,
7746		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
7747			( ~b.sourceIndex || MAX_NEGATIVE ) -
7748			( ~a.sourceIndex || MAX_NEGATIVE );
7749
7750	// Use IE sourceIndex if available on both nodes
7751	if ( diff ) {
7752		return diff;
7753	}
7754
7755	// Check if b follows a
7756	if ( cur ) {
7757		while ( (cur = cur.nextSibling) ) {
7758			if ( cur === b ) {
7759				return -1;
7760			}
7761		}
7762	}
7763
7764	return a ? 1 : -1;
7765}
7766
7767/**
7768 * Returns a function to use in pseudos for input types
7769 * @param {String} type
7770 */
7771function createInputPseudo( type ) {
7772	return function( elem ) {
7773		var name = elem.nodeName.toLowerCase();
7774		return name === "input" && elem.type === type;
7775	};
7776}
7777
7778/**
7779 * Returns a function to use in pseudos for buttons
7780 * @param {String} type
7781 */
7782function createButtonPseudo( type ) {
7783	return function( elem ) {
7784		var name = elem.nodeName.toLowerCase();
7785		return (name === "input" || name === "button") && elem.type === type;
7786	};
7787}
7788
7789/**
7790 * Returns a function to use in pseudos for positionals
7791 * @param {Function} fn
7792 */
7793function createPositionalPseudo( fn ) {
7794	return markFunction(function( argument ) {
7795		argument = +argument;
7796		return markFunction(function( seed, matches ) {
7797			var j,
7798				matchIndexes = fn( [], seed.length, argument ),
7799				i = matchIndexes.length;
7800
7801			// Match elements found at the specified indexes
7802			while ( i-- ) {
7803				if ( seed[ (j = matchIndexes[i]) ] ) {
7804					seed[j] = !(matches[j] = seed[j]);
7805				}
7806			}
7807		});
7808	});
7809}
7810
7811/**
7812 * Checks a node for validity as a Sizzle context
7813 * @param {Element|Object=} context
7814 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
7815 */
7816function testContext( context ) {
7817	return context && typeof context.getElementsByTagName !== "undefined" && context;
7818}
7819
7820// Expose support vars for convenience
7821support = Sizzle.support = {};
7822
7823/**
7824 * Detects XML nodes
7825 * @param {Element|Object} elem An element or a document
7826 * @returns {Boolean} True iff elem is a non-HTML XML node
7827 */
7828isXML = Sizzle.isXML = function( elem ) {
7829	// documentElement is verified for cases where it doesn't yet exist
7830	// (such as loading iframes in IE - #4833)
7831	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
7832	return documentElement ? documentElement.nodeName !== "HTML" : false;
7833};
7834
7835/**
7836 * Sets document-related variables once based on the current document
7837 * @param {Element|Object} [doc] An element or document object to use to set the document
7838 * @returns {Object} Returns the current document
7839 */
7840setDocument = Sizzle.setDocument = function( node ) {
7841	var hasCompare, parent,
7842		doc = node ? node.ownerDocument || node : preferredDoc;
7843
7844	// If no document and documentElement is available, return
7845	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
7846		return document;
7847	}
7848
7849	// Set our document
7850	document = doc;
7851	docElem = doc.documentElement;
7852	parent = doc.defaultView;
7853
7854	// Support: IE>8
7855	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
7856	// IE will throw "permission denied" error when accessing "document" variable, see jQuery1113 #13936
7857	// IE6-8 do not support the defaultView property so parent will be undefined
7858	if ( parent && parent !== parent.top ) {
7859		// IE11 does not have attachEvent, so all must suffer
7860		if ( parent.addEventListener ) {
7861			parent.addEventListener( "unload", unloadHandler, false );
7862		} else if ( parent.attachEvent ) {
7863			parent.attachEvent( "onunload", unloadHandler );
7864		}
7865	}
7866
7867	/* Support tests
7868	---------------------------------------------------------------------- */
7869	documentIsHTML = !isXML( doc );
7870
7871	/* Attributes
7872	---------------------------------------------------------------------- */
7873
7874	// Support: IE<8
7875	// Verify that getAttribute really returns attributes and not properties
7876	// (excepting IE8 booleans)
7877	support.attributes = assert(function( div ) {
7878		div.className = "i";
7879		return !div.getAttribute("className");
7880	});
7881
7882	/* getElement(s)By*
7883	---------------------------------------------------------------------- */
7884
7885	// Check if getElementsByTagName("*") returns only elements
7886	support.getElementsByTagName = assert(function( div ) {
7887		div.appendChild( doc.createComment("") );
7888		return !div.getElementsByTagName("*").length;
7889	});
7890
7891	// Support: IE<9
7892	support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
7893
7894	// Support: IE<10
7895	// Check if getElementById returns elements by name
7896	// The broken getElementById methods don't pick up programatically-set names,
7897	// so use a roundabout getElementsByName test
7898	support.getById = assert(function( div ) {
7899		docElem.appendChild( div ).id = expando;
7900		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
7901	});
7902
7903	// ID find and filter
7904	if ( support.getById ) {
7905		Expr.find["ID"] = function( id, context ) {
7906			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
7907				var m = context.getElementById( id );
7908				// Check parentNode to catch when Blackberry 4.6 returns
7909				// nodes that are no longer in the document #6963
7910				return m && m.parentNode ? [ m ] : [];
7911			}
7912		};
7913		Expr.filter["ID"] = function( id ) {
7914			var attrId = id.replace( runescape, funescape );
7915			return function( elem ) {
7916				return elem.getAttribute("id") === attrId;
7917			};
7918		};
7919	} else {
7920		// Support: IE6/7
7921		// getElementById is not reliable as a find shortcut
7922		delete Expr.find["ID"];
7923
7924		Expr.filter["ID"] =  function( id ) {
7925			var attrId = id.replace( runescape, funescape );
7926			return function( elem ) {
7927				var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
7928				return node && node.value === attrId;
7929			};
7930		};
7931	}
7932
7933	// Tag
7934	Expr.find["TAG"] = support.getElementsByTagName ?
7935		function( tag, context ) {
7936			if ( typeof context.getElementsByTagName !== "undefined" ) {
7937				return context.getElementsByTagName( tag );
7938
7939			// DocumentFragment nodes don't have gEBTN
7940			} else if ( support.qsa ) {
7941				return context.querySelectorAll( tag );
7942			}
7943		} :
7944
7945		function( tag, context ) {
7946			var elem,
7947				tmp = [],
7948				i = 0,
7949				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
7950				results = context.getElementsByTagName( tag );
7951
7952			// Filter out possible comments
7953			if ( tag === "*" ) {
7954				while ( (elem = results[i++]) ) {
7955					if ( elem.nodeType === 1 ) {
7956						tmp.push( elem );
7957					}
7958				}
7959
7960				return tmp;
7961			}
7962			return results;
7963		};
7964
7965	// Class
7966	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
7967		if ( documentIsHTML ) {
7968			return context.getElementsByClassName( className );
7969		}
7970	};
7971
7972	/* QSA/matchesSelector
7973	---------------------------------------------------------------------- */
7974
7975	// QSA and matchesSelector support
7976
7977	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
7978	rbuggyMatches = [];
7979
7980	// qSa(:focus) reports false when true (Chrome 21)
7981	// We allow this because of a bug in IE8/9 that throws an error
7982	// whenever `document.activeElement` is accessed on an iframe
7983	// So, we allow :focus to pass through QSA all the time to avoid the IE error
7984	// See http://bugs.jQuery1113.com/ticket/13378
7985	rbuggyQSA = [];
7986
7987	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
7988		// Build QSA regex
7989		// Regex strategy adopted from Diego Perini
7990		assert(function( div ) {
7991			// Select is set to empty string on purpose
7992			// This is to test IE's treatment of not explicitly
7993			// setting a boolean content attribute,
7994			// since its presence should be enough
7995			// http://bugs.jQuery1113.com/ticket/12359
7996			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
7997				"<select id='" + expando + "-\f]' msallowcapture=''>" +
7998				"<option selected=''></option></select>";
7999
8000			// Support: IE8, Opera 11-12.16
8001			// Nothing should be selected when empty strings follow ^= or $= or *=
8002			// The test attribute must be unknown in Opera but "safe" for WinRT
8003			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
8004			if ( div.querySelectorAll("[msallowcapture^='']").length ) {
8005				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
8006			}
8007
8008			// Support: IE8
8009			// Boolean attributes and "value" are not treated correctly
8010			if ( !div.querySelectorAll("[selected]").length ) {
8011				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
8012			}
8013
8014			// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
8015			if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
8016				rbuggyQSA.push("~=");
8017			}
8018
8019			// Webkit/Opera - :checked should return selected option elements
8020			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
8021			// IE8 throws error here and will not see later tests
8022			if ( !div.querySelectorAll(":checked").length ) {
8023				rbuggyQSA.push(":checked");
8024			}
8025
8026			// Support: Safari 8+, iOS 8+
8027			// https://bugs.webkit.org/show_bug.cgi?id=136851
8028			// In-page `selector#id sibing-combinator selector` fails
8029			if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
8030				rbuggyQSA.push(".#.+[+~]");
8031			}
8032		});
8033
8034		assert(function( div ) {
8035			// Support: Windows 8 Native Apps
8036			// The type and name attributes are restricted during .innerHTML assignment
8037			var input = doc.createElement("input");
8038			input.setAttribute( "type", "hidden" );
8039			div.appendChild( input ).setAttribute( "name", "D" );
8040
8041			// Support: IE8
8042			// Enforce case-sensitivity of name attribute
8043			if ( div.querySelectorAll("[name=d]").length ) {
8044				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
8045			}
8046
8047			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
8048			// IE8 throws error here and will not see later tests
8049			if ( !div.querySelectorAll(":enabled").length ) {
8050				rbuggyQSA.push( ":enabled", ":disabled" );
8051			}
8052
8053			// Opera 10-11 does not throw on post-comma invalid pseudos
8054			div.querySelectorAll("*,:x");
8055			rbuggyQSA.push(",.*:");
8056		});
8057	}
8058
8059	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
8060		docElem.webkitMatchesSelector ||
8061		docElem.mozMatchesSelector ||
8062		docElem.oMatchesSelector ||
8063		docElem.msMatchesSelector) )) ) {
8064
8065		assert(function( div ) {
8066			// Check to see if it's possible to do matchesSelector
8067			// on a disconnected node (IE 9)
8068			support.disconnectedMatch = matches.call( div, "div" );
8069
8070			// This should fail with an exception
8071			// Gecko does not error, returns false instead
8072			matches.call( div, "[s!='']:x" );
8073			rbuggyMatches.push( "!=", pseudos );
8074		});
8075	}
8076
8077	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
8078	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
8079
8080	/* Contains
8081	---------------------------------------------------------------------- */
8082	hasCompare = rnative.test( docElem.compareDocumentPosition );
8083
8084	// Element contains another
8085	// Purposefully does not implement inclusive descendent
8086	// As in, an element does not contain itself
8087	contains = hasCompare || rnative.test( docElem.contains ) ?
8088		function( a, b ) {
8089			var adown = a.nodeType === 9 ? a.documentElement : a,
8090				bup = b && b.parentNode;
8091			return a === bup || !!( bup && bup.nodeType === 1 && (
8092				adown.contains ?
8093					adown.contains( bup ) :
8094					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
8095			));
8096		} :
8097		function( a, b ) {
8098			if ( b ) {
8099				while ( (b = b.parentNode) ) {
8100					if ( b === a ) {
8101						return true;
8102					}
8103				}
8104			}
8105			return false;
8106		};
8107
8108	/* Sorting
8109	---------------------------------------------------------------------- */
8110
8111	// Document order sorting
8112	sortOrder = hasCompare ?
8113	function( a, b ) {
8114
8115		// Flag for duplicate removal
8116		if ( a === b ) {
8117			hasDuplicate = true;
8118			return 0;
8119		}
8120
8121		// Sort on method existence if only one input has compareDocumentPosition
8122		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
8123		if ( compare ) {
8124			return compare;
8125		}
8126
8127		// Calculate position if both inputs belong to the same document
8128		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
8129			a.compareDocumentPosition( b ) :
8130
8131			// Otherwise we know they are disconnected
8132			1;
8133
8134		// Disconnected nodes
8135		if ( compare & 1 ||
8136			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
8137
8138			// Choose the first element that is related to our preferred document
8139			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
8140				return -1;
8141			}
8142			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
8143				return 1;
8144			}
8145
8146			// Maintain original order
8147			return sortInput ?
8148				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
8149				0;
8150		}
8151
8152		return compare & 4 ? -1 : 1;
8153	} :
8154	function( a, b ) {
8155		// Exit early if the nodes are identical
8156		if ( a === b ) {
8157			hasDuplicate = true;
8158			return 0;
8159		}
8160
8161		var cur,
8162			i = 0,
8163			aup = a.parentNode,
8164			bup = b.parentNode,
8165			ap = [ a ],
8166			bp = [ b ];
8167
8168		// Parentless nodes are either documents or disconnected
8169		if ( !aup || !bup ) {
8170			return a === doc ? -1 :
8171				b === doc ? 1 :
8172				aup ? -1 :
8173				bup ? 1 :
8174				sortInput ?
8175				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
8176				0;
8177
8178		// If the nodes are siblings, we can do a quick check
8179		} else if ( aup === bup ) {
8180			return siblingCheck( a, b );
8181		}
8182
8183		// Otherwise we need full lists of their ancestors for comparison
8184		cur = a;
8185		while ( (cur = cur.parentNode) ) {
8186			ap.unshift( cur );
8187		}
8188		cur = b;
8189		while ( (cur = cur.parentNode) ) {
8190			bp.unshift( cur );
8191		}
8192
8193		// Walk down the tree looking for a discrepancy
8194		while ( ap[i] === bp[i] ) {
8195			i++;
8196		}
8197
8198		return i ?
8199			// Do a sibling check if the nodes have a common ancestor
8200			siblingCheck( ap[i], bp[i] ) :
8201
8202			// Otherwise nodes in our document sort first
8203			ap[i] === preferredDoc ? -1 :
8204			bp[i] === preferredDoc ? 1 :
8205			0;
8206	};
8207
8208	return doc;
8209};
vendor: 4,496 bytes, lines 8210-8382
8210
8211Sizzle.matches = function( expr, elements ) {
8212	return Sizzle( expr, null, null, elements );
8213};
8214
8215Sizzle.matchesSelector = function( elem, expr ) {
8216	// Set document vars if needed
8217	if ( ( elem.ownerDocument || elem ) !== document ) {
8218		setDocument( elem );
8219	}
8220
8221	// Make sure that attribute selectors are quoted
8222	expr = expr.replace( rattributeQuotes, "='$1']" );
8223
8224	if ( support.matchesSelector && documentIsHTML &&
8225		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
8226		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
8227
8228		try {
8229			var ret = matches.call( elem, expr );
8230
8231			// IE 9's matchesSelector returns false on disconnected nodes
8232			if ( ret || support.disconnectedMatch ||
8233					// As well, disconnected nodes are said to be in a document
8234					// fragment in IE 9
8235					elem.document && elem.document.nodeType !== 11 ) {
8236				return ret;
8237			}
8238		} catch (e) {}
8239	}
8240
8241	return Sizzle( expr, document, null, [ elem ] ).length > 0;
8242};
8243
8244Sizzle.contains = function( context, elem ) {
8245	// Set document vars if needed
8246	if ( ( context.ownerDocument || context ) !== document ) {
8247		setDocument( context );
8248	}
8249	return contains( context, elem );
8250};
8251
8252Sizzle.attr = function( elem, name ) {
8253	// Set document vars if needed
8254	if ( ( elem.ownerDocument || elem ) !== document ) {
8255		setDocument( elem );
8256	}
8257
8258	var fn = Expr.attrHandle[ name.toLowerCase() ],
8259		// Don't get fooled by Object.prototype properties (jQuery1113 #13807)
8260		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
8261			fn( elem, name, !documentIsHTML ) :
8262			undefined;
8263
8264	return val !== undefined ?
8265		val :
8266		support.attributes || !documentIsHTML ?
8267			elem.getAttribute( name ) :
8268			(val = elem.getAttributeNode(name)) && val.specified ?
8269				val.value :
8270				null;
8271};
8272
8273Sizzle.error = function( msg ) {
8274	throw new Error( "Syntax error, unrecognized expression: " + msg );
8275};
8276
8277/**
8278 * Document sorting and removing duplicates
8279 * @param {ArrayLike} results
8280 */
8281Sizzle.uniqueSort = function( results ) {
8282	var elem,
8283		duplicates = [],
8284		j = 0,
8285		i = 0;
8286
8287	// Unless we *know* we can detect duplicates, assume their presence
8288	hasDuplicate = !support.detectDuplicates;
8289	sortInput = !support.sortStable && results.slice( 0 );
8290	results.sort( sortOrder );
8291
8292	if ( hasDuplicate ) {
8293		while ( (elem = results[i++]) ) {
8294			if ( elem === results[ i ] ) {
8295				j = duplicates.push( i );
8296			}
8297		}
8298		while ( j-- ) {
8299			results.splice( duplicates[ j ], 1 );
8300		}
8301	}
8302
8303	// Clear input after sorting to release objects
8304	// See https://github.com/jQuery1113/sizzle/pull/225
8305	sortInput = null;
8306
8307	return results;
8308};
8309
8310/**
8311 * Utility function for retrieving the text value of an array of DOM nodes
8312 * @param {Array|Element} elem
8313 */
8314getText = Sizzle.getText = function( elem ) {
8315	var node,
8316		ret = "",
8317		i = 0,
8318		nodeType = elem.nodeType;
8319
8320	if ( !nodeType ) {
8321		// If no nodeType, this is expected to be an array
8322		while ( (node = elem[i++]) ) {
8323			// Do not traverse comment nodes
8324			ret += getText( node );
8325		}
8326	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
8327		// Use textContent for elements
8328		// innerText usage removed for consistency of new lines (jQuery1113 #11153)
8329		if ( typeof elem.textContent === "string" ) {
8330			return elem.textContent;
8331		} else {
8332			// Traverse its children
8333			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
8334				ret += getText( elem );
8335			}
8336		}
8337	} else if ( nodeType === 3 || nodeType === 4 ) {
8338		return elem.nodeValue;
8339	}
8340	// Do not include comment or processing instruction nodes
8341
8342	return ret;
8343};
8344
8345Expr = Sizzle.selectors = {
8346
8347	// Can be adjusted by the user
8348	cacheLength: 50,
8349
8350	createPseudo: markFunction,
8351
8352	match: matchExpr,
8353
8354	attrHandle: {},
8355
8356	find: {},
8357
8358	relative: {
8359		">": { dir: "parentNode", first: true },
8360		" ": { dir: "parentNode" },
8361		"+": { dir: "previousSibling", first: true },
8362		"~": { dir: "previousSibling" }
8363	},
8364
8365	preFilter: {
8366		"ATTR": function( match ) {
8367			match[1] = match[1].replace( runescape, funescape );
8368
8369			// Move the given value to match[3] whether quoted or unquoted
8370			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
8371
8372			if ( match[2] === "~=" ) {
8373				match[3] = " " + match[3] + " ";
8374			}
8375
8376			return match.slice( 0, 4 );
8377		},
8378
8379		"CHILD": function( match ) {
8380			/* matches from matchExpr["CHILD"]
8381				1 type (only|nth|...)
8382				2 what (child|of-type)
vendor: 10,120 bytes, lines 8383-8694
8383				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
8384				4 xn-component of xn+y argument ([+-]?\d*n|)
8385				5 sign of xn-component
8386				6 x of xn-component
8387				7 sign of y-component
8388				8 y of y-component
8389			*/
8390			match[1] = match[1].toLowerCase();
8391
8392			if ( match[1].slice( 0, 3 ) === "nth" ) {
8393				// nth-* requires argument
8394				if ( !match[3] ) {
8395					Sizzle.error( match[0] );
8396				}
8397
8398				// numeric x and y parameters for Expr.filter.CHILD
8399				// remember that false/true cast respectively to 0/1
8400				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
8401				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
8402
8403			// other types prohibit arguments
8404			} else if ( match[3] ) {
8405				Sizzle.error( match[0] );
8406			}
8407
8408			return match;
8409		},
8410
8411		"PSEUDO": function( match ) {
8412			var excess,
8413				unquoted = !match[6] && match[2];
8414
8415			if ( matchExpr["CHILD"].test( match[0] ) ) {
8416				return null;
8417			}
8418
8419			// Accept quoted arguments as-is
8420			if ( match[3] ) {
8421				match[2] = match[4] || match[5] || "";
8422
8423			// Strip excess characters from unquoted arguments
8424			} else if ( unquoted && rpseudo.test( unquoted ) &&
8425				// Get excess from tokenize (recursively)
8426				(excess = tokenize( unquoted, true )) &&
8427				// advance to the next closing parenthesis
8428				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
8429
8430				// excess is a negative index
8431				match[0] = match[0].slice( 0, excess );
8432				match[2] = unquoted.slice( 0, excess );
8433			}
8434
8435			// Return only captures needed by the pseudo filter method (type and argument)
8436			return match.slice( 0, 3 );
8437		}
8438	},
8439
8440	filter: {
8441
8442		"TAG": function( nodeNameSelector ) {
8443			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
8444			return nodeNameSelector === "*" ?
8445				function() { return true; } :
8446				function( elem ) {
8447					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
8448				};
8449		},
8450
8451		"CLASS": function( className ) {
8452			var pattern = classCache[ className + " " ];
8453
8454			return pattern ||
8455				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
8456				classCache( className, function( elem ) {
8457					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
8458				});
8459		},
8460
8461		"ATTR": function( name, operator, check ) {
8462			return function( elem ) {
8463				var result = Sizzle.attr( elem, name );
8464
8465				if ( result == null ) {
8466					return operator === "!=";
8467				}
8468				if ( !operator ) {
8469					return true;
8470				}
8471
8472				result += "";
8473
8474				return operator === "=" ? result === check :
8475					operator === "!=" ? result !== check :
8476					operator === "^=" ? check && result.indexOf( check ) === 0 :
8477					operator === "*=" ? check && result.indexOf( check ) > -1 :
8478					operator === "$=" ? check && result.slice( -check.length ) === check :
8479					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
8480					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
8481					false;
8482			};
8483		},
8484
8485		"CHILD": function( type, what, argument, first, last ) {
8486			var simple = type.slice( 0, 3 ) !== "nth",
8487				forward = type.slice( -4 ) !== "last",
8488				ofType = what === "of-type";
8489
8490			return first === 1 && last === 0 ?
8491
8492				// Shortcut for :nth-*(n)
8493				function( elem ) {
8494					return !!elem.parentNode;
8495				} :
8496
8497				function( elem, context, xml ) {
8498					var cache, outerCache, node, diff, nodeIndex, start,
8499						dir = simple !== forward ? "nextSibling" : "previousSibling",
8500						parent = elem.parentNode,
8501						name = ofType && elem.nodeName.toLowerCase(),
8502						useCache = !xml && !ofType;
8503
8504					if ( parent ) {
8505
8506						// :(first|last|only)-(child|of-type)
8507						if ( simple ) {
8508							while ( dir ) {
8509								node = elem;
8510								while ( (node = node[ dir ]) ) {
8511									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
8512										return false;
8513									}
8514								}
8515								// Reverse direction for :only-* (if we haven't yet done so)
8516								start = dir = type === "only" && !start && "nextSibling";
8517							}
8518							return true;
8519						}
8520
8521						start = [ forward ? parent.firstChild : parent.lastChild ];
8522
8523						// non-xml :nth-child(...) stores cache data on `parent`
8524						if ( forward && useCache ) {
8525							// Seek `elem` from a previously-cached index
8526							outerCache = parent[ expando ] || (parent[ expando ] = {});
8527							cache = outerCache[ type ] || [];
8528							nodeIndex = cache[0] === dirruns && cache[1];
8529							diff = cache[0] === dirruns && cache[2];
8530							node = nodeIndex && parent.childNodes[ nodeIndex ];
8531
8532							while ( (node = ++nodeIndex && node && node[ dir ] ||
8533
8534								// Fallback to seeking `elem` from the start
8535								(diff = nodeIndex = 0) || start.pop()) ) {
8536
8537								// When found, cache indexes on `parent` and break
8538								if ( node.nodeType === 1 && ++diff && node === elem ) {
8539									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
8540									break;
8541								}
8542							}
8543
8544						// Use previously-cached element index if available
8545						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
8546							diff = cache[1];
8547
8548						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
8549						} else {
8550							// Use the same loop as above to seek `elem` from the start
8551							while ( (node = ++nodeIndex && node && node[ dir ] ||
8552								(diff = nodeIndex = 0) || start.pop()) ) {
8553
8554								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
8555									// Cache the index of each encountered element
8556									if ( useCache ) {
8557										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
8558									}
8559
8560									if ( node === elem ) {
8561										break;
8562									}
8563								}
8564							}
8565						}
8566
8567						// Incorporate the offset, then check against cycle size
8568						diff -= last;
8569						return diff === first || ( diff % first === 0 && diff / first >= 0 );
8570					}
8571				};
8572		},
8573
8574		"PSEUDO": function( pseudo, argument ) {
8575			// pseudo-class names are case-insensitive
8576			// http://www.w3.org/TR/selectors/#pseudo-classes
8577			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
8578			// Remember that setFilters inherits from pseudos
8579			var args,
8580				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
8581					Sizzle.error( "unsupported pseudo: " + pseudo );
8582
8583			// The user may use createPseudo to indicate that
8584			// arguments are needed to create the filter function
8585			// just as Sizzle does
8586			if ( fn[ expando ] ) {
8587				return fn( argument );
8588			}
8589
8590			// But maintain support for old signatures
8591			if ( fn.length > 1 ) {
8592				args = [ pseudo, pseudo, "", argument ];
8593				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
8594					markFunction(function( seed, matches ) {
8595						var idx,
8596							matched = fn( seed, argument ),
8597							i = matched.length;
8598						while ( i-- ) {
8599							idx = indexOf( seed, matched[i] );
8600							seed[ idx ] = !( matches[ idx ] = matched[i] );
8601						}
8602					}) :
8603					function( elem ) {
8604						return fn( elem, 0, args );
8605					};
8606			}
8607
8608			return fn;
8609		}
8610	},
8611
8612	pseudos: {
8613		// Potentially complex pseudos
8614		"not": markFunction(function( selector ) {
8615			// Trim the selector passed to compile
8616			// to avoid treating leading and trailing
8617			// spaces as combinators
8618			var input = [],
8619				results = [],
8620				matcher = compile( selector.replace( rtrim, "$1" ) );
8621
8622			return matcher[ expando ] ?
8623				markFunction(function( seed, matches, context, xml ) {
8624					var elem,
8625						unmatched = matcher( seed, null, xml, [] ),
8626						i = seed.length;
8627
8628					// Match elements unmatched by `matcher`
8629					while ( i-- ) {
8630						if ( (elem = unmatched[i]) ) {
8631							seed[i] = !(matches[i] = elem);
8632						}
8633					}
8634				}) :
8635				function( elem, context, xml ) {
8636					input[0] = elem;
8637					matcher( input, null, xml, results );
8638					// Don't keep the element (issue #299)
8639					input[0] = null;
8640					return !results.pop();
8641				};
8642		}),
8643
8644		"has": markFunction(function( selector ) {
8645			return function( elem ) {
8646				return Sizzle( selector, elem ).length > 0;
8647			};
8648		}),
8649
8650		"contains": markFunction(function( text ) {
8651			text = text.replace( runescape, funescape );
8652			return function( elem ) {
8653				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
8654			};
8655		}),
8656
8657		// "Whether an element is represented by a :lang() selector
8658		// is based solely on the element's language value
8659		// being equal to the identifier C,
8660		// or beginning with the identifier C immediately followed by "-".
8661		// The matching of C against the element's language value is performed case-insensitively.
8662		// The identifier C does not have to be a valid language name."
8663		// http://www.w3.org/TR/selectors/#lang-pseudo
8664		"lang": markFunction( function( lang ) {
8665			// lang value must be a valid identifier
8666			if ( !ridentifier.test(lang || "") ) {
8667				Sizzle.error( "unsupported lang: " + lang );
8668			}
8669			lang = lang.replace( runescape, funescape ).toLowerCase();
8670			return function( elem ) {
8671				var elemLang;
8672				do {
8673					if ( (elemLang = documentIsHTML ?
8674						elem.lang :
8675						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
8676
8677						elemLang = elemLang.toLowerCase();
8678						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
8679					}
8680				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
8681				return false;
8682			};
8683		}),
8684
8685		// Miscellaneous
8686		"target": function( elem ) {
8687			var hash = window.location && window.location.hash;
8688			return hash && hash.slice( 1 ) === elem.id;
8689		},
8690
8691		"root": function( elem ) {
8692			return elem === docElem;
8693		},
8694
vendor: 5,418 bytes, lines 8695-8894
8695		"focus": function( elem ) {
8696			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
8697		},
8698
8699		// Boolean properties
8700		"enabled": function( elem ) {
8701			return elem.disabled === false;
8702		},
8703
8704		"disabled": function( elem ) {
8705			return elem.disabled === true;
8706		},
8707
8708		"checked": function( elem ) {
8709			// In CSS3, :checked should return both checked and selected elements
8710			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
8711			var nodeName = elem.nodeName.toLowerCase();
8712			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
8713		},
8714
8715		"selected": function( elem ) {
8716			// Accessing this property makes selected-by-default
8717			// options in Safari work properly
8718			if ( elem.parentNode ) {
8719				elem.parentNode.selectedIndex;
8720			}
8721
8722			return elem.selected === true;
8723		},
8724
8725		// Contents
8726		"empty": function( elem ) {
8727			// http://www.w3.org/TR/selectors/#empty-pseudo
8728			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
8729			//   but not by others (comment: 8; processing instruction: 7; etc.)
8730			// nodeType < 6 works because attributes (2) do not appear as children
8731			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
8732				if ( elem.nodeType < 6 ) {
8733					return false;
8734				}
8735			}
8736			return true;
8737		},
8738
8739		"parent": function( elem ) {
8740			return !Expr.pseudos["empty"]( elem );
8741		},
8742
8743		// Element/input types
8744		"header": function( elem ) {
8745			return rheader.test( elem.nodeName );
8746		},
8747
8748		"input": function( elem ) {
8749			return rinputs.test( elem.nodeName );
8750		},
8751
8752		"button": function( elem ) {
8753			var name = elem.nodeName.toLowerCase();
8754			return name === "input" && elem.type === "button" || name === "button";
8755		},
8756
8757		"text": function( elem ) {
8758			var attr;
8759			return elem.nodeName.toLowerCase() === "input" &&
8760				elem.type === "text" &&
8761
8762				// Support: IE<8
8763				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
8764				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
8765		},
8766
8767		// Position-in-collection
8768		"first": createPositionalPseudo(function() {
8769			return [ 0 ];
8770		}),
8771
8772		"last": createPositionalPseudo(function( matchIndexes, length ) {
8773			return [ length - 1 ];
8774		}),
8775
8776		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
8777			return [ argument < 0 ? argument + length : argument ];
8778		}),
8779
8780		"even": createPositionalPseudo(function( matchIndexes, length ) {
8781			var i = 0;
8782			for ( ; i < length; i += 2 ) {
8783				matchIndexes.push( i );
8784			}
8785			return matchIndexes;
8786		}),
8787
8788		"odd": createPositionalPseudo(function( matchIndexes, length ) {
8789			var i = 1;
8790			for ( ; i < length; i += 2 ) {
8791				matchIndexes.push( i );
8792			}
8793			return matchIndexes;
8794		}),
8795
8796		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
8797			var i = argument < 0 ? argument + length : argument;
8798			for ( ; --i >= 0; ) {
8799				matchIndexes.push( i );
8800			}
8801			return matchIndexes;
8802		}),
8803
8804		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
8805			var i = argument < 0 ? argument + length : argument;
8806			for ( ; ++i < length; ) {
8807				matchIndexes.push( i );
8808			}
8809			return matchIndexes;
8810		})
8811	}
8812};
8813
8814Expr.pseudos["nth"] = Expr.pseudos["eq"];
8815
8816// Add button/input type pseudos
8817for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
8818	Expr.pseudos[ i ] = createInputPseudo( i );
8819}
8820for ( i in { submit: true, reset: true } ) {
8821	Expr.pseudos[ i ] = createButtonPseudo( i );
8822}
8823
8824// Easy API for creating new setFilters
8825function setFilters() {}
8826setFilters.prototype = Expr.filters = Expr.pseudos;
8827Expr.setFilters = new setFilters();
8828
8829tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
8830	var matched, match, tokens, type,
8831		soFar, groups, preFilters,
8832		cached = tokenCache[ selector + " " ];
8833
8834	if ( cached ) {
8835		return parseOnly ? 0 : cached.slice( 0 );
8836	}
8837
8838	soFar = selector;
8839	groups = [];
8840	preFilters = Expr.preFilter;
8841
8842	while ( soFar ) {
8843
8844		// Comma and first run
8845		if ( !matched || (match = rcomma.exec( soFar )) ) {
8846			if ( match ) {
8847				// Don't consume trailing commas as valid
8848				soFar = soFar.slice( match[0].length ) || soFar;
8849			}
8850			groups.push( (tokens = []) );
8851		}
8852
8853		matched = false;
8854
8855		// Combinators
8856		if ( (match = rcombinators.exec( soFar )) ) {
8857			matched = match.shift();
8858			tokens.push({
8859				value: matched,
8860				// Cast descendant combinators to space
8861				type: match[0].replace( rtrim, " " )
8862			});
8863			soFar = soFar.slice( matched.length );
8864		}
8865
8866		// Filters
8867		for ( type in Expr.filter ) {
8868			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
8869				(match = preFilters[ type ]( match ))) ) {
8870				matched = match.shift();
8871				tokens.push({
8872					value: matched,
8873					type: type,
8874					matches: match
8875				});
8876				soFar = soFar.slice( matched.length );
8877			}
8878		}
8879
8880		if ( !matched ) {
8881			break;
8882		}
8883	}
8884
8885	// Return the length of the invalid excess
8886	// if we're just parsing
8887	// Otherwise, throw an error or return tokens
8888	return parseOnly ?
8889		soFar.length :
8890		soFar ?
8891			Sizzle.error( selector ) :
8892			// Cache the tokens
8893			tokenCache( selector, groups ).slice( 0 );
8894};
vendor: 11,230 bytes, lines 8895-9281
8895
8896function toSelector( tokens ) {
8897	var i = 0,
8898		len = tokens.length,
8899		selector = "";
8900	for ( ; i < len; i++ ) {
8901		selector += tokens[i].value;
8902	}
8903	return selector;
8904}
8905
8906function addCombinator( matcher, combinator, base ) {
8907	var dir = combinator.dir,
8908		checkNonElements = base && dir === "parentNode",
8909		doneName = done++;
8910
8911	return combinator.first ?
8912		// Check against closest ancestor/preceding element
8913		function( elem, context, xml ) {
8914			while ( (elem = elem[ dir ]) ) {
8915				if ( elem.nodeType === 1 || checkNonElements ) {
8916					return matcher( elem, context, xml );
8917				}
8918			}
8919		} :
8920
8921		// Check against all ancestor/preceding elements
8922		function( elem, context, xml ) {
8923			var oldCache, outerCache,
8924				newCache = [ dirruns, doneName ];
8925
8926			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
8927			if ( xml ) {
8928				while ( (elem = elem[ dir ]) ) {
8929					if ( elem.nodeType === 1 || checkNonElements ) {
8930						if ( matcher( elem, context, xml ) ) {
8931							return true;
8932						}
8933					}
8934				}
8935			} else {
8936				while ( (elem = elem[ dir ]) ) {
8937					if ( elem.nodeType === 1 || checkNonElements ) {
8938						outerCache = elem[ expando ] || (elem[ expando ] = {});
8939						if ( (oldCache = outerCache[ dir ]) &&
8940							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
8941
8942							// Assign to newCache so results back-propagate to previous elements
8943							return (newCache[ 2 ] = oldCache[ 2 ]);
8944						} else {
8945							// Reuse newcache so results back-propagate to previous elements
8946							outerCache[ dir ] = newCache;
8947
8948							// A match means we're done; a fail means we have to keep checking
8949							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
8950								return true;
8951							}
8952						}
8953					}
8954				}
8955			}
8956		};
8957}
8958
8959function elementMatcher( matchers ) {
8960	return matchers.length > 1 ?
8961		function( elem, context, xml ) {
8962			var i = matchers.length;
8963			while ( i-- ) {
8964				if ( !matchers[i]( elem, context, xml ) ) {
8965					return false;
8966				}
8967			}
8968			return true;
8969		} :
8970		matchers[0];
8971}
8972
8973function multipleContexts( selector, contexts, results ) {
8974	var i = 0,
8975		len = contexts.length;
8976	for ( ; i < len; i++ ) {
8977		Sizzle( selector, contexts[i], results );
8978	}
8979	return results;
8980}
8981
8982function condense( unmatched, map, filter, context, xml ) {
8983	var elem,
8984		newUnmatched = [],
8985		i = 0,
8986		len = unmatched.length,
8987		mapped = map != null;
8988
8989	for ( ; i < len; i++ ) {
8990		if ( (elem = unmatched[i]) ) {
8991			if ( !filter || filter( elem, context, xml ) ) {
8992				newUnmatched.push( elem );
8993				if ( mapped ) {
8994					map.push( i );
8995				}
8996			}
8997		}
8998	}
8999
9000	return newUnmatched;
9001}
9002
9003function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
9004	if ( postFilter && !postFilter[ expando ] ) {
9005		postFilter = setMatcher( postFilter );
9006	}
9007	if ( postFinder && !postFinder[ expando ] ) {
9008		postFinder = setMatcher( postFinder, postSelector );
9009	}
9010	return markFunction(function( seed, results, context, xml ) {
9011		var temp, i, elem,
9012			preMap = [],
9013			postMap = [],
9014			preexisting = results.length,
9015
9016			// Get initial elements from seed or context
9017			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
9018
9019			// Prefilter to get matcher input, preserving a map for seed-results synchronization
9020			matcherIn = preFilter && ( seed || !selector ) ?
9021				condense( elems, preMap, preFilter, context, xml ) :
9022				elems,
9023
9024			matcherOut = matcher ?
9025				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
9026				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
9027
9028					// ...intermediate processing is necessary
9029					[] :
9030
9031					// ...otherwise use results directly
9032					results :
9033				matcherIn;
9034
9035		// Find primary matches
9036		if ( matcher ) {
9037			matcher( matcherIn, matcherOut, context, xml );
9038		}
9039
9040		// Apply postFilter
9041		if ( postFilter ) {
9042			temp = condense( matcherOut, postMap );
9043			postFilter( temp, [], context, xml );
9044
9045			// Un-match failing elements by moving them back to matcherIn
9046			i = temp.length;
9047			while ( i-- ) {
9048				if ( (elem = temp[i]) ) {
9049					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
9050				}
9051			}
9052		}
9053
9054		if ( seed ) {
9055			if ( postFinder || preFilter ) {
9056				if ( postFinder ) {
9057					// Get the final matcherOut by condensing this intermediate into postFinder contexts
9058					temp = [];
9059					i = matcherOut.length;
9060					while ( i-- ) {
9061						if ( (elem = matcherOut[i]) ) {
9062							// Restore matcherIn since elem is not yet a final match
9063							temp.push( (matcherIn[i] = elem) );
9064						}
9065					}
9066					postFinder( null, (matcherOut = []), temp, xml );
9067				}
9068
9069				// Move matched elements from seed to results to keep them synchronized
9070				i = matcherOut.length;
9071				while ( i-- ) {
9072					if ( (elem = matcherOut[i]) &&
9073						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
9074
9075						seed[temp] = !(results[temp] = elem);
9076					}
9077				}
9078			}
9079
9080		// Add elements to results, through postFinder if defined
9081		} else {
9082			matcherOut = condense(
9083				matcherOut === results ?
9084					matcherOut.splice( preexisting, matcherOut.length ) :
9085					matcherOut
9086			);
9087			if ( postFinder ) {
9088				postFinder( null, results, matcherOut, xml );
9089			} else {
9090				push.apply( results, matcherOut );
9091			}
9092		}
9093	});
9094}
9095
9096function matcherFromTokens( tokens ) {
9097	var checkContext, matcher, j,
9098		len = tokens.length,
9099		leadingRelative = Expr.relative[ tokens[0].type ],
9100		implicitRelative = leadingRelative || Expr.relative[" "],
9101		i = leadingRelative ? 1 : 0,
9102
9103		// The foundational matcher ensures that elements are reachable from top-level context(s)
9104		matchContext = addCombinator( function( elem ) {
9105			return elem === checkContext;
9106		}, implicitRelative, true ),
9107		matchAnyContext = addCombinator( function( elem ) {
9108			return indexOf( checkContext, elem ) > -1;
9109		}, implicitRelative, true ),
9110		matchers = [ function( elem, context, xml ) {
9111			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
9112				(checkContext = context).nodeType ?
9113					matchContext( elem, context, xml ) :
9114					matchAnyContext( elem, context, xml ) );
9115			// Avoid hanging onto element (issue #299)
9116			checkContext = null;
9117			return ret;
9118		} ];
9119
9120	for ( ; i < len; i++ ) {
9121		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
9122			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
9123		} else {
9124			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
9125
9126			// Return special upon seeing a positional matcher
9127			if ( matcher[ expando ] ) {
9128				// Find the next relative operator (if any) for proper handling
9129				j = ++i;
9130				for ( ; j < len; j++ ) {
9131					if ( Expr.relative[ tokens[j].type ] ) {
9132						break;
9133					}
9134				}
9135				return setMatcher(
9136					i > 1 && elementMatcher( matchers ),
9137					i > 1 && toSelector(
9138						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
9139						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
9140					).replace( rtrim, "$1" ),
9141					matcher,
9142					i < j && matcherFromTokens( tokens.slice( i, j ) ),
9143					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
9144					j < len && toSelector( tokens )
9145				);
9146			}
9147			matchers.push( matcher );
9148		}
9149	}
9150
9151	return elementMatcher( matchers );
9152}
9153
9154function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
9155	var bySet = setMatchers.length > 0,
9156		byElement = elementMatchers.length > 0,
9157		superMatcher = function( seed, context, xml, results, outermost ) {
9158			var elem, j, matcher,
9159				matchedCount = 0,
9160				i = "0",
9161				unmatched = seed && [],
9162				setMatched = [],
9163				contextBackup = outermostContext,
9164				// We must always have either seed elements or outermost context
9165				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
9166				// Use integer dirruns iff this is the outermost matcher
9167				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
9168				len = elems.length;
9169
9170			if ( outermost ) {
9171				outermostContext = context !== document && context;
9172			}
9173
9174			// Add elements passing elementMatchers directly to results
9175			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
9176			// Support: IE<9, Safari
9177			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
9178			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
9179				if ( byElement && elem ) {
9180					j = 0;
9181					while ( (matcher = elementMatchers[j++]) ) {
9182						if ( matcher( elem, context, xml ) ) {
9183							results.push( elem );
9184							break;
9185						}
9186					}
9187					if ( outermost ) {
9188						dirruns = dirrunsUnique;
9189					}
9190				}
9191
9192				// Track unmatched elements for set filters
9193				if ( bySet ) {
9194					// They will have gone through all possible matchers
9195					if ( (elem = !matcher && elem) ) {
9196						matchedCount--;
9197					}
9198
9199					// Lengthen the array for every element, matched or not
9200					if ( seed ) {
9201						unmatched.push( elem );
9202					}
9203				}
9204			}
9205
9206			// Apply set filters to unmatched elements
9207			matchedCount += i;
9208			if ( bySet && i !== matchedCount ) {
9209				j = 0;
9210				while ( (matcher = setMatchers[j++]) ) {
9211					matcher( unmatched, setMatched, context, xml );
9212				}
9213
9214				if ( seed ) {
9215					// Reintegrate element matches to eliminate the need for sorting
9216					if ( matchedCount > 0 ) {
9217						while ( i-- ) {
9218							if ( !(unmatched[i] || setMatched[i]) ) {
9219								setMatched[i] = pop.call( results );
9220							}
9221						}
9222					}
9223
9224					// Discard index placeholder values to get only actual matches
9225					setMatched = condense( setMatched );
9226				}
9227
9228				// Add matches to results
9229				push.apply( results, setMatched );
9230
9231				// Seedless set matches succeeding multiple successful matchers stipulate sorting
9232				if ( outermost && !seed && setMatched.length > 0 &&
9233					( matchedCount + setMatchers.length ) > 1 ) {
9234
9235					Sizzle.uniqueSort( results );
9236				}
9237			}
9238
9239			// Override manipulation of globals by nested matchers
9240			if ( outermost ) {
9241				dirruns = dirrunsUnique;
9242				outermostContext = contextBackup;
9243			}
9244
9245			return unmatched;
9246		};
9247
9248	return bySet ?
9249		markFunction( superMatcher ) :
9250		superMatcher;
9251}
9252
9253compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
9254	var i,
9255		setMatchers = [],
9256		elementMatchers = [],
9257		cached = compilerCache[ selector + " " ];
9258
9259	if ( !cached ) {
9260		// Generate a function of recursive functions that can be used to check each element
9261		if ( !match ) {
9262			match = tokenize( selector );
9263		}
9264		i = match.length;
9265		while ( i-- ) {
9266			cached = matcherFromTokens( match[i] );
9267			if ( cached[ expando ] ) {
9268				setMatchers.push( cached );
9269			} else {
9270				elementMatchers.push( cached );
9271			}
9272		}
9273
9274		// Cache the compiled function
9275		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
9276
9277		// Save selector and tokenization
9278		cached.selector = selector;
9279	}
9280	return cached;
9281};
vendor: 185,445 bytes, lines 9282-15708
9282
9283/**
9284 * A low-level selection function that works with Sizzle's compiled
9285 *  selector functions
9286 * @param {String|Function} selector A selector or a pre-compiled
9287 *  selector function built with Sizzle.compile
9288 * @param {Element} context
9289 * @param {Array} [results]
9290 * @param {Array} [seed] A set of elements to match against
9291 */
9292select = Sizzle.select = function( selector, context, results, seed ) {
9293	var i, tokens, token, type, find,
9294		compiled = typeof selector === "function" && selector,
9295		match = !seed && tokenize( (selector = compiled.selector || selector) );
9296
9297	results = results || [];
9298
9299	// Try to minimize operations if there is no seed and only one group
9300	if ( match.length === 1 ) {
9301
9302		// Take a shortcut and set the context if the root selector is an ID
9303		tokens = match[0] = match[0].slice( 0 );
9304		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
9305				support.getById && context.nodeType === 9 && documentIsHTML &&
9306				Expr.relative[ tokens[1].type ] ) {
9307
9308			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
9309			if ( !context ) {
9310				return results;
9311
9312			// Precompiled matchers will still verify ancestry, so step up a level
9313			} else if ( compiled ) {
9314				context = context.parentNode;
9315			}
9316
9317			selector = selector.slice( tokens.shift().value.length );
9318		}
9319
9320		// Fetch a seed set for right-to-left matching
9321		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
9322		while ( i-- ) {
9323			token = tokens[i];
9324
9325			// Abort if we hit a combinator
9326			if ( Expr.relative[ (type = token.type) ] ) {
9327				break;
9328			}
9329			if ( (find = Expr.find[ type ]) ) {
9330				// Search, expanding context for leading sibling combinators
9331				if ( (seed = find(
9332					token.matches[0].replace( runescape, funescape ),
9333					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
9334				)) ) {
9335
9336					// If seed is empty or no tokens remain, we can return early
9337					tokens.splice( i, 1 );
9338					selector = seed.length && toSelector( tokens );
9339					if ( !selector ) {
9340						push.apply( results, seed );
9341						return results;
9342					}
9343
9344					break;
9345				}
9346			}
9347		}
9348	}
9349
9350	// Compile and execute a filtering function if one is not provided
9351	// Provide `match` to avoid retokenization if we modified the selector above
9352	( compiled || compile( selector, match ) )(
9353		seed,
9354		context,
9355		!documentIsHTML,
9356		results,
9357		rsibling.test( selector ) && testContext( context.parentNode ) || context
9358	);
9359	return results;
9360};
9361
9362// One-time assignments
9363
9364// Sort stability
9365support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
9366
9367// Support: Chrome 14-35+
9368// Always assume duplicates if they aren't passed to the comparison function
9369support.detectDuplicates = !!hasDuplicate;
9370
9371// Initialize against the default document
9372setDocument();
9373
9374// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
9375// Detached nodes confoundingly follow *each other*
9376support.sortDetached = assert(function( div1 ) {
9377	// Should return 1, but returns 4 (following)
9378	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
9379});
9380
9381// Support: IE<8
9382// Prevent attribute/property "interpolation"
9383// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
9384if ( !assert(function( div ) {
9385	div.innerHTML = "<a href='#'></a>";
9386	return div.firstChild.getAttribute("href") === "#" ;
9387}) ) {
9388	addHandle( "type|href|height|width", function( elem, name, isXML ) {
9389		if ( !isXML ) {
9390			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
9391		}
9392	});
9393}
9394
9395// Support: IE<9
9396// Use defaultValue in place of getAttribute("value")
9397if ( !support.attributes || !assert(function( div ) {
9398	div.innerHTML = "<input/>";
9399	div.firstChild.setAttribute( "value", "" );
9400	return div.firstChild.getAttribute( "value" ) === "";
9401}) ) {
9402	addHandle( "value", function( elem, name, isXML ) {
9403		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
9404			return elem.defaultValue;
9405		}
9406	});
9407}
9408
9409// Support: IE<9
9410// Use getAttributeNode to fetch booleans when getAttribute lies
9411if ( !assert(function( div ) {
9412	return div.getAttribute("disabled") == null;
9413}) ) {
9414	addHandle( booleans, function( elem, name, isXML ) {
9415		var val;
9416		if ( !isXML ) {
9417			return elem[ name ] === true ? name.toLowerCase() :
9418					(val = elem.getAttributeNode( name )) && val.specified ?
9419					val.value :
9420				null;
9421		}
9422	});
9423}
9424
9425return Sizzle;
9426
9427})( window );
9428
9429
9430
9431jQuery1113.find = Sizzle;
9432jQuery1113.expr = Sizzle.selectors;
9433jQuery1113.expr[":"] = jQuery1113.expr.pseudos;
9434jQuery1113.unique = Sizzle.uniqueSort;
9435jQuery1113.text = Sizzle.getText;
9436jQuery1113.isXMLDoc = Sizzle.isXML;
9437jQuery1113.contains = Sizzle.contains;
9438
9439
9440
9441var rneedsContext = jQuery1113.expr.match.needsContext;
9442
9443var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
9444
9445
9446
9447var risSimple = /^.[^:#\[\.,]*$/;
9448
9449// Implement the identical functionality for filter and not
9450function winnow( elements, qualifier, not ) {
9451	if ( jQuery1113.isFunction( qualifier ) ) {
9452		return jQuery1113.grep( elements, function( elem, i ) {
9453			/* jshint -W018 */
9454			return !!qualifier.call( elem, i, elem ) !== not;
9455		});
9456
9457	}
9458
9459	if ( qualifier.nodeType ) {
9460		return jQuery1113.grep( elements, function( elem ) {
9461			return ( elem === qualifier ) !== not;
9462		});
9463
9464	}
9465
9466	if ( typeof qualifier === "string" ) {
9467		if ( risSimple.test( qualifier ) ) {
9468			return jQuery1113.filter( qualifier, elements, not );
9469		}
9470
9471		qualifier = jQuery1113.filter( qualifier, elements );
9472	}
9473
9474	return jQuery1113.grep( elements, function( elem ) {
9475		return ( jQuery1113.inArray( elem, qualifier ) >= 0 ) !== not;
9476	});
9477}
9478
9479jQuery1113.filter = function( expr, elems, not ) {
9480	var elem = elems[ 0 ];
9481
9482	if ( not ) {
9483		expr = ":not(" + expr + ")";
9484	}
9485
9486	return elems.length === 1 && elem.nodeType === 1 ?
9487		jQuery1113.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
9488		jQuery1113.find.matches( expr, jQuery1113.grep( elems, function( elem ) {
9489			return elem.nodeType === 1;
9490		}));
9491};
9492
9493jQuery1113.fn.extend({
9494	find: function( selector ) {
9495		var i,
9496			ret = [],
9497			self = this,
9498			len = self.length;
9499
9500		if ( typeof selector !== "string" ) {
9501			return this.pushStack( jQuery1113( selector ).filter(function() {
9502				for ( i = 0; i < len; i++ ) {
9503					if ( jQuery1113.contains( self[ i ], this ) ) {
9504						return true;
9505					}
9506				}
9507			}) );
9508		}
9509
9510		for ( i = 0; i < len; i++ ) {
9511			jQuery1113.find( selector, self[ i ], ret );
9512		}
9513
9514		// Needed because $( selector, context ) becomes $( context ).find( selector )
9515		ret = this.pushStack( len > 1 ? jQuery1113.unique( ret ) : ret );
9516		ret.selector = this.selector ? this.selector + " " + selector : selector;
9517		return ret;
9518	},
9519	filter: function( selector ) {
9520		return this.pushStack( winnow(this, selector || [], false) );
9521	},
9522	not: function( selector ) {
9523		return this.pushStack( winnow(this, selector || [], true) );
9524	},
9525	is: function( selector ) {
9526		return !!winnow(
9527			this,
9528
9529			// If this is a positional/relative selector, check membership in the returned set
9530			// so $("p:first").is("p:last") won't return true for a doc with two "p".
9531			typeof selector === "string" && rneedsContext.test( selector ) ?
9532				jQuery1113( selector ) :
9533				selector || [],
9534			false
9535		).length;
9536	}
9537});
9538
9539
9540// Initialize a jQuery1113 object
9541
9542
9543// A central reference to the root jQuery1113(document)
9544var rootjQuery1113,
9545
9546	// Use the correct document accordingly with window argument (sandbox)
9547	document = window.document,
9548
9549	// A simple way to check for HTML strings
9550	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
9551	// Strict HTML recognition (#11290: must start with <)
9552	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
9553
9554	init = jQuery1113.fn.init = function( selector, context ) {
9555		var match, elem;
9556
9557		// HANDLE: $(""), $(null), $(undefined), $(false)
9558		if ( !selector ) {
9559			return this;
9560		}
9561
9562		// Handle HTML strings
9563		if ( typeof selector === "string" ) {
9564			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
9565				// Assume that strings that start and end with <> are HTML and skip the regex check
9566				match = [ null, selector, null ];
9567
9568			} else {
9569				match = rquickExpr.exec( selector );
9570			}
9571
9572			// Match html or make sure no context is specified for #id
9573			if ( match && (match[1] || !context) ) {
9574
9575				// HANDLE: $(html) -> $(array)
9576				if ( match[1] ) {
9577					context = context instanceof jQuery1113 ? context[0] : context;
9578
9579					// scripts is true for back-compat
9580					// Intentionally let the error be thrown if parseHTML is not present
9581					jQuery1113.merge( this, jQuery1113.parseHTML(
9582						match[1],
9583						context && context.nodeType ? context.ownerDocument || context : document,
9584						true
9585					) );
9586
9587					// HANDLE: $(html, props)
9588					if ( rsingleTag.test( match[1] ) && jQuery1113.isPlainObject( context ) ) {
9589						for ( match in context ) {
9590							// Properties of context are called as methods if possible
9591							if ( jQuery1113.isFunction( this[ match ] ) ) {
9592								this[ match ]( context[ match ] );
9593
9594							// ...and otherwise set as attributes
9595							} else {
9596								this.attr( match, context[ match ] );
9597							}
9598						}
9599					}
9600
9601					return this;
9602
9603				// HANDLE: $(#id)
9604				} else {
9605					elem = document.getElementById( match[2] );
9606
9607					// Check parentNode to catch when Blackberry 4.6 returns
9608					// nodes that are no longer in the document #6963
9609					if ( elem && elem.parentNode ) {
9610						// Handle the case where IE and Opera return items
9611						// by name instead of ID
9612						if ( elem.id !== match[2] ) {
9613							return rootjQuery1113.find( selector );
9614						}
9615
9616						// Otherwise, we inject the element directly into the jQuery1113 object
9617						this.length = 1;
9618						this[0] = elem;
9619					}
9620
9621					this.context = document;
9622					this.selector = selector;
9623					return this;
9624				}
9625
9626			// HANDLE: $(expr, $(...))
9627			} else if ( !context || context.jQuery1113 ) {
9628				return ( context || rootjQuery1113 ).find( selector );
9629
9630			// HANDLE: $(expr, context)
9631			// (which is just equivalent to: $(context).find(expr)
9632			} else {
9633				return this.constructor( context ).find( selector );
9634			}
9635
9636		// HANDLE: $(DOMElement)
9637		} else if ( selector.nodeType ) {
9638			this.context = this[0] = selector;
9639			this.length = 1;
9640			return this;
9641
9642		// HANDLE: $(function)
9643		// Shortcut for document ready
9644		} else if ( jQuery1113.isFunction( selector ) ) {
9645			return typeof rootjQuery1113.ready !== "undefined" ?
9646				rootjQuery1113.ready( selector ) :
9647				// Execute immediately if ready is not present
9648				selector( jQuery1113 );
9649		}
9650
9651		if ( selector.selector !== undefined ) {
9652			this.selector = selector.selector;
9653			this.context = selector.context;
9654		}
9655
9656		return jQuery1113.makeArray( selector, this );
9657	};
9658
9659// Give the init function the jQuery1113 prototype for later instantiation
9660init.prototype = jQuery1113.fn;
9661
9662// Initialize central reference
9663rootjQuery1113 = jQuery1113( document );
9664
9665
9666var rparentsprev = /^(?:parents|prev(?:Until|All))/,
9667	// methods guaranteed to produce a unique set when starting from a unique set
9668	guaranteedUnique = {
9669		children: true,
9670		contents: true,
9671		next: true,
9672		prev: true
9673	};
9674
9675jQuery1113.extend({
9676	dir: function( elem, dir, until ) {
9677		var matched = [],
9678			cur = elem[ dir ];
9679
9680		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery1113( cur ).is( until )) ) {
9681			if ( cur.nodeType === 1 ) {
9682				matched.push( cur );
9683			}
9684			cur = cur[dir];
9685		}
9686		return matched;
9687	},
9688
9689	sibling: function( n, elem ) {
9690		var r = [];
9691
9692		for ( ; n; n = n.nextSibling ) {
9693			if ( n.nodeType === 1 && n !== elem ) {
9694				r.push( n );
9695			}
9696		}
9697
9698		return r;
9699	}
9700});
9701
9702jQuery1113.fn.extend({
9703	has: function( target ) {
9704		var i,
9705			targets = jQuery1113( target, this ),
9706			len = targets.length;
9707
9708		return this.filter(function() {
9709			for ( i = 0; i < len; i++ ) {
9710				if ( jQuery1113.contains( this, targets[i] ) ) {
9711					return true;
9712				}
9713			}
9714		});
9715	},
9716
9717	closest: function( selectors, context ) {
9718		var cur,
9719			i = 0,
9720			l = this.length,
9721			matched = [],
9722			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
9723				jQuery1113( selectors, context || this.context ) :
9724				0;
9725
9726		for ( ; i < l; i++ ) {
9727			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
9728				// Always skip document fragments
9729				if ( cur.nodeType < 11 && (pos ?
9730					pos.index(cur) > -1 :
9731
9732					// Don't pass non-elements to Sizzle
9733					cur.nodeType === 1 &&
9734						jQuery1113.find.matchesSelector(cur, selectors)) ) {
9735
9736					matched.push( cur );
9737					break;
9738				}
9739			}
9740		}
9741
9742		return this.pushStack( matched.length > 1 ? jQuery1113.unique( matched ) : matched );
9743	},
9744
9745	// Determine the position of an element within
9746	// the matched set of elements
9747	index: function( elem ) {
9748
9749		// No argument, return index in parent
9750		if ( !elem ) {
9751			return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
9752		}
9753
9754		// index in selector
9755		if ( typeof elem === "string" ) {
9756			return jQuery1113.inArray( this[0], jQuery1113( elem ) );
9757		}
9758
9759		// Locate the position of the desired element
9760		return jQuery1113.inArray(
9761			// If it receives a jQuery1113 object, the first element is used
9762			elem.jQuery1113 ? elem[0] : elem, this );
9763	},
9764
9765	add: function( selector, context ) {
9766		return this.pushStack(
9767			jQuery1113.unique(
9768				jQuery1113.merge( this.get(), jQuery1113( selector, context ) )
9769			)
9770		);
9771	},
9772
9773	addBack: function( selector ) {
9774		return this.add( selector == null ?
9775			this.prevObject : this.prevObject.filter(selector)
9776		);
9777	}
9778});
9779
9780function sibling( cur, dir ) {
9781	do {
9782		cur = cur[ dir ];
9783	} while ( cur && cur.nodeType !== 1 );
9784
9785	return cur;
9786}
9787
9788jQuery1113.each({
9789	parent: function( elem ) {
9790		var parent = elem.parentNode;
9791		return parent && parent.nodeType !== 11 ? parent : null;
9792	},
9793	parents: function( elem ) {
9794		return jQuery1113.dir( elem, "parentNode" );
9795	},
9796	parentsUntil: function( elem, i, until ) {
9797		return jQuery1113.dir( elem, "parentNode", until );
9798	},
9799	next: function( elem ) {
9800		return sibling( elem, "nextSibling" );
9801	},
9802	prev: function( elem ) {
9803		return sibling( elem, "previousSibling" );
9804	},
9805	nextAll: function( elem ) {
9806		return jQuery1113.dir( elem, "nextSibling" );
9807	},
9808	prevAll: function( elem ) {
9809		return jQuery1113.dir( elem, "previousSibling" );
9810	},
9811	nextUntil: function( elem, i, until ) {
9812		return jQuery1113.dir( elem, "nextSibling", until );
9813	},
9814	prevUntil: function( elem, i, until ) {
9815		return jQuery1113.dir( elem, "previousSibling", until );
9816	},
9817	siblings: function( elem ) {
9818		return jQuery1113.sibling( ( elem.parentNode || {} ).firstChild, elem );
9819	},
9820	children: function( elem ) {
9821		return jQuery1113.sibling( elem.firstChild );
9822	},
9823	contents: function( elem ) {
9824		return jQuery1113.nodeName( elem, "iframe" ) ?
9825			elem.contentDocument || elem.contentWindow.document :
9826			jQuery1113.merge( [], elem.childNodes );
9827	}
9828}, function( name, fn ) {
9829	jQuery1113.fn[ name ] = function( until, selector ) {
9830		var ret = jQuery1113.map( this, fn, until );
9831
9832		if ( name.slice( -5 ) !== "Until" ) {
9833			selector = until;
9834		}
9835
9836		if ( selector && typeof selector === "string" ) {
9837			ret = jQuery1113.filter( selector, ret );
9838		}
9839
9840		if ( this.length > 1 ) {
9841			// Remove duplicates
9842			if ( !guaranteedUnique[ name ] ) {
9843				ret = jQuery1113.unique( ret );
9844			}
9845
9846			// Reverse order for parents* and prev-derivatives
9847			if ( rparentsprev.test( name ) ) {
9848				ret = ret.reverse();
9849			}
9850		}
9851
9852		return this.pushStack( ret );
9853	};
9854});
9855var rnotwhite = (/\S+/g);
9856
9857
9858
9859// String to Object options format cache
9860var optionsCache = {};
9861
9862// Convert String-formatted options into Object-formatted ones and store in cache
9863function createOptions( options ) {
9864	var object = optionsCache[ options ] = {};
9865	jQuery1113.each( options.match( rnotwhite ) || [], function( _, flag ) {
9866		object[ flag ] = true;
9867	});
9868	return object;
9869}
9870
9871/*
9872 * Create a callback list using the following parameters:
9873 *
9874 *	options: an optional list of space-separated options that will change how
9875 *			the callback list behaves or a more traditional option object
9876 *
9877 * By default a callback list will act like an event callback list and can be
9878 * "fired" multiple times.
9879 *
9880 * Possible options:
9881 *
9882 *	once:			will ensure the callback list can only be fired once (like a Deferred)
9883 *
9884 *	memory:			will keep track of previous values and will call any callback added
9885 *					after the list has been fired right away with the latest "memorized"
9886 *					values (like a Deferred)
9887 *
9888 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
9889 *
9890 *	stopOnFalse:	interrupt callings when a callback returns false
9891 *
9892 */
9893jQuery1113.Callbacks = function( options ) {
9894
9895	// Convert options from String-formatted to Object-formatted if needed
9896	// (we check in cache first)
9897	options = typeof options === "string" ?
9898		( optionsCache[ options ] || createOptions( options ) ) :
9899		jQuery1113.extend( {}, options );
9900
9901	var // Flag to know if list is currently firing
9902		firing,
9903		// Last fire value (for non-forgettable lists)
9904		memory,
9905		// Flag to know if list was already fired
9906		fired,
9907		// End of the loop when firing
9908		firingLength,
9909		// Index of currently firing callback (modified by remove if needed)
9910		firingIndex,
9911		// First callback to fire (used internally by add and fireWith)
9912		firingStart,
9913		// Actual callback list
9914		list = [],
9915		// Stack of fire calls for repeatable lists
9916		stack = !options.once && [],
9917		// Fire callbacks
9918		fire = function( data ) {
9919			memory = options.memory && data;
9920			fired = true;
9921			firingIndex = firingStart || 0;
9922			firingStart = 0;
9923			firingLength = list.length;
9924			firing = true;
9925			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
9926				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
9927					memory = false; // To prevent further calls using add
9928					break;
9929				}
9930			}
9931			firing = false;
9932			if ( list ) {
9933				if ( stack ) {
9934					if ( stack.length ) {
9935						fire( stack.shift() );
9936					}
9937				} else if ( memory ) {
9938					list = [];
9939				} else {
9940					self.disable();
9941				}
9942			}
9943		},
9944		// Actual Callbacks object
9945		self = {
9946			// Add a callback or a collection of callbacks to the list
9947			add: function() {
9948				if ( list ) {
9949					// First, we save the current length
9950					var start = list.length;
9951					(function add( args ) {
9952						jQuery1113.each( args, function( _, arg ) {
9953							var type = jQuery1113.type( arg );
9954							if ( type === "function" ) {
9955								if ( !options.unique || !self.has( arg ) ) {
9956									list.push( arg );
9957								}
9958							} else if ( arg && arg.length && type !== "string" ) {
9959								// Inspect recursively
9960								add( arg );
9961							}
9962						});
9963					})( arguments );
9964					// Do we need to add the callbacks to the
9965					// current firing batch?
9966					if ( firing ) {
9967						firingLength = list.length;
9968					// With memory, if we're not firing then
9969					// we should call right away
9970					} else if ( memory ) {
9971						firingStart = start;
9972						fire( memory );
9973					}
9974				}
9975				return this;
9976			},
9977			// Remove a callback from the list
9978			remove: function() {
9979				if ( list ) {
9980					jQuery1113.each( arguments, function( _, arg ) {
9981						var index;
9982						while ( ( index = jQuery1113.inArray( arg, list, index ) ) > -1 ) {
9983							list.splice( index, 1 );
9984							// Handle firing indexes
9985							if ( firing ) {
9986								if ( index <= firingLength ) {
9987									firingLength--;
9988								}
9989								if ( index <= firingIndex ) {
9990									firingIndex--;
9991								}
9992							}
9993						}
9994					});
9995				}
9996				return this;
9997			},
9998			// Check if a given callback is in the list.
9999			// If no argument is given, return whether or not list has callbacks attached.
10000			has: function( fn ) {
10001				return fn ? jQuery1113.inArray( fn, list ) > -1 : !!( list && list.length );
10002			},
10003			// Remove all callbacks from the list
10004			empty: function() {
10005				list = [];
10006				firingLength = 0;
10007				return this;
10008			},
10009			// Have the list do nothing anymore
10010			disable: function() {
10011				list = stack = memory = undefined;
10012				return this;
10013			},
10014			// Is it disabled?
10015			disabled: function() {
10016				return !list;
10017			},
10018			// Lock the list in its current state
10019			lock: function() {
10020				stack = undefined;
10021				if ( !memory ) {
10022					self.disable();
10023				}
10024				return this;
10025			},
10026			// Is it locked?
10027			locked: function() {
10028				return !stack;
10029			},
10030			// Call all callbacks with the given context and arguments
10031			fireWith: function( context, args ) {
10032				if ( list && ( !fired || stack ) ) {
10033					args = args || [];
10034					args = [ context, args.slice ? args.slice() : args ];
10035					if ( firing ) {
10036						stack.push( args );
10037					} else {
10038						fire( args );
10039					}
10040				}
10041				return this;
10042			},
10043			// Call all the callbacks with the given arguments
10044			fire: function() {
10045				self.fireWith( this, arguments );
10046				return this;
10047			},
10048			// To know if the callbacks have already been called at least once
10049			fired: function() {
10050				return !!fired;
10051			}
10052		};
10053
10054	return self;
10055};
10056
10057
10058jQuery1113.extend({
10059
10060	Deferred: function( func ) {
10061		var tuples = [
10062				// action, add listener, listener list, final state
10063				[ "resolve", "done", jQuery1113.Callbacks("once memory"), "resolved" ],
10064				[ "reject", "fail", jQuery1113.Callbacks("once memory"), "rejected" ],
10065				[ "notify", "progress", jQuery1113.Callbacks("memory") ]
10066			],
10067			state = "pending",
10068			promise = {
10069				state: function() {
10070					return state;
10071				},
10072				always: function() {
10073					deferred.done( arguments ).fail( arguments );
10074					return this;
10075				},
10076				then: function( /* fnDone, fnFail, fnProgress */ ) {
10077					var fns = arguments;
10078					return jQuery1113.Deferred(function( newDefer ) {
10079						jQuery1113.each( tuples, function( i, tuple ) {
10080							var fn = jQuery1113.isFunction( fns[ i ] ) && fns[ i ];
10081							// deferred[ done | fail | progress ] for forwarding actions to newDefer
10082							deferred[ tuple[1] ](function() {
10083								var returned = fn && fn.apply( this, arguments );
10084								if ( returned && jQuery1113.isFunction( returned.promise ) ) {
10085									returned.promise()
10086										.done( newDefer.resolve )
10087										.fail( newDefer.reject )
10088										.progress( newDefer.notify );
10089								} else {
10090									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
10091								}
10092							});
10093						});
10094						fns = null;
10095					}).promise();
10096				},
10097				// Get a promise for this deferred
10098				// If obj is provided, the promise aspect is added to the object
10099				promise: function( obj ) {
10100					return obj != null ? jQuery1113.extend( obj, promise ) : promise;
10101				}
10102			},
10103			deferred = {};
10104
10105		// Keep pipe for back-compat
10106		promise.pipe = promise.then;
10107
10108		// Add list-specific methods
10109		jQuery1113.each( tuples, function( i, tuple ) {
10110			var list = tuple[ 2 ],
10111				stateString = tuple[ 3 ];
10112
10113			// promise[ done | fail | progress ] = list.add
10114			promise[ tuple[1] ] = list.add;
10115
10116			// Handle state
10117			if ( stateString ) {
10118				list.add(function() {
10119					// state = [ resolved | rejected ]
10120					state = stateString;
10121
10122				// [ reject_list | resolve_list ].disable; progress_list.lock
10123				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
10124			}
10125
10126			// deferred[ resolve | reject | notify ]
10127			deferred[ tuple[0] ] = function() {
10128				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
10129				return this;
10130			};
10131			deferred[ tuple[0] + "With" ] = list.fireWith;
10132		});
10133
10134		// Make the deferred a promise
10135		promise.promise( deferred );
10136
10137		// Call given func if any
10138		if ( func ) {
10139			func.call( deferred, deferred );
10140		}
10141
10142		// All done!
10143		return deferred;
10144	},
10145
10146	// Deferred helper
10147	when: function( subordinate /* , ..., subordinateN */ ) {
10148		var i = 0,
10149			resolveValues = slice.call( arguments ),
10150			length = resolveValues.length,
10151
10152			// the count of uncompleted subordinates
10153			remaining = length !== 1 || ( subordinate && jQuery1113.isFunction( subordinate.promise ) ) ? length : 0,
10154
10155			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
10156			deferred = remaining === 1 ? subordinate : jQuery1113.Deferred(),
10157
10158			// Update function for both resolve and progress values
10159			updateFunc = function( i, contexts, values ) {
10160				return function( value ) {
10161					contexts[ i ] = this;
10162					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
10163					if ( values === progressValues ) {
10164						deferred.notifyWith( contexts, values );
10165
10166					} else if ( !(--remaining) ) {
10167						deferred.resolveWith( contexts, values );
10168					}
10169				};
10170			},
10171
10172			progressValues, progressContexts, resolveContexts;
10173
10174		// add listeners to Deferred subordinates; treat others as resolved
10175		if ( length > 1 ) {
10176			progressValues = new Array( length );
10177			progressContexts = new Array( length );
10178			resolveContexts = new Array( length );
10179			for ( ; i < length; i++ ) {
10180				if ( resolveValues[ i ] && jQuery1113.isFunction( resolveValues[ i ].promise ) ) {
10181					resolveValues[ i ].promise()
10182						.done( updateFunc( i, resolveContexts, resolveValues ) )
10183						.fail( deferred.reject )
10184						.progress( updateFunc( i, progressContexts, progressValues ) );
10185				} else {
10186					--remaining;
10187				}
10188			}
10189		}
10190
10191		// if we're not waiting on anything, resolve the master
10192		if ( !remaining ) {
10193			deferred.resolveWith( resolveContexts, resolveValues );
10194		}
10195
10196		return deferred.promise();
10197	}
10198});
10199
10200
10201// The deferred used on DOM ready
10202var readyList;
10203
10204jQuery1113.fn.ready = function( fn ) {
10205	// Add the callback
10206	jQuery1113.ready.promise().done( fn );
10207
10208	return this;
10209};
10210
10211jQuery1113.extend({
10212	// Is the DOM ready to be used? Set to true once it occurs.
10213	isReady: false,
10214
10215	// A counter to track how many items to wait for before
10216	// the ready event fires. See #6781
10217	readyWait: 1,
10218
10219	// Hold (or release) the ready event
10220	holdReady: function( hold ) {
10221		if ( hold ) {
10222			jQuery1113.readyWait++;
10223		} else {
10224			jQuery1113.ready( true );
10225		}
10226	},
10227
10228	// Handle when the DOM is ready
10229	ready: function( wait ) {
10230
10231		// Abort if there are pending holds or we're already ready
10232		if ( wait === true ? --jQuery1113.readyWait : jQuery1113.isReady ) {
10233			return;
10234		}
10235
10236		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
10237		if ( !document.body ) {
10238			return setTimeout( jQuery1113.ready );
10239		}
10240
10241		// Remember that the DOM is ready
10242		jQuery1113.isReady = true;
10243
10244		// If a normal DOM Ready event fired, decrement, and wait if need be
10245		if ( wait !== true && --jQuery1113.readyWait > 0 ) {
10246			return;
10247		}
10248
10249		// If there are functions bound, to execute
10250		readyList.resolveWith( document, [ jQuery1113 ] );
10251
10252		// Trigger any bound ready events
10253		if ( jQuery1113.fn.triggerHandler ) {
10254			jQuery1113( document ).triggerHandler( "ready" );
10255			jQuery1113( document ).off( "ready" );
10256		}
10257	}
10258});
10259
10260/**
10261 * Clean-up method for dom ready events
10262 */
10263function detach() {
10264	if ( document.addEventListener ) {
10265		document.removeEventListener( "DOMContentLoaded", completed, false );
10266		window.removeEventListener( "load", completed, false );
10267
10268	} else {
10269		document.detachEvent( "onreadystatechange", completed );
10270		window.detachEvent( "onload", completed );
10271	}
10272}
10273
10274/**
10275 * The ready event handler and self cleanup method
10276 */
10277function completed() {
10278	// readyState === "complete" is good enough for us to call the dom ready in oldIE
10279	if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
10280		detach();
10281		jQuery1113.ready();
10282	}
10283}
10284
10285jQuery1113.ready.promise = function( obj ) {
10286	if ( !readyList ) {
10287
10288		readyList = jQuery1113.Deferred();
10289
10290		// Catch cases where $(document).ready() is called after the browser event has already occurred.
10291		// we once tried to use readyState "interactive" here, but it caused issues like the one
10292		// discovered by ChrisS here: http://bugs.jQuery1113.com/ticket/12282#comment:15
10293		if ( document.readyState === "complete" ) {
10294			// Handle it asynchronously to allow scripts the opportunity to delay ready
10295			setTimeout( jQuery1113.ready );
10296
10297		// Standards-based browsers support DOMContentLoaded
10298		} else if ( document.addEventListener ) {
10299			// Use the handy event callback
10300			document.addEventListener( "DOMContentLoaded", completed, false );
10301
10302			// A fallback to window.onload, that will always work
10303			window.addEventListener( "load", completed, false );
10304
10305		// If IE event model is used
10306		} else {
10307			// Ensure firing before onload, maybe late but safe also for iframes
10308			document.attachEvent( "onreadystatechange", completed );
10309
10310			// A fallback to window.onload, that will always work
10311			window.attachEvent( "onload", completed );
10312
10313			// If IE and not a frame
10314			// continually check to see if the document is ready
10315			var top = false;
10316
10317			try {
10318				top = window.frameElement == null && document.documentElement;
10319			} catch(e) {}
10320
10321			if ( top && top.doScroll ) {
10322				(function doScrollCheck() {
10323					if ( !jQuery1113.isReady ) {
10324
10325						try {
10326							// Use the trick by Diego Perini
10327							// http://javascript.nwbox.com/IEContentLoaded/
10328							top.doScroll("left");
10329						} catch(e) {
10330							return setTimeout( doScrollCheck, 50 );
10331						}
10332
10333						// detach all dom ready events
10334						detach();
10335
10336						// and execute any waiting functions
10337						jQuery1113.ready();
10338					}
10339				})();
10340			}
10341		}
10342	}
10343	return readyList.promise( obj );
10344};
10345
10346
10347var strundefined = typeof undefined;
10348
10349
10350
10351// Support: IE<9
10352// Iteration over object's inherited properties before its own
10353var i;
10354for ( i in jQuery1113( support ) ) {
10355	break;
10356}
10357support.ownLast = i !== "0";
10358
10359// Note: most support tests are defined in their respective modules.
10360// false until the test is run
10361support.inlineBlockNeedsLayout = false;
10362
10363// Execute ASAP in case we need to set body.style.zoom
10364jQuery1113(function() {
10365	// Minified: var a,b,c,d
10366	var val, div, body, container;
10367
10368	body = document.getElementsByTagName( "body" )[ 0 ];
10369	if ( !body || !body.style ) {
10370		// Return for frameset docs that don't have a body
10371		return;
10372	}
10373
10374	// Setup
10375	div = document.createElement( "div" );
10376	container = document.createElement( "div" );
10377	container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
10378	body.appendChild( container ).appendChild( div );
10379
10380	if ( typeof div.style.zoom !== strundefined ) {
10381		// Support: IE<8
10382		// Check if natively block-level elements act like inline-block
10383		// elements when setting their display to 'inline' and giving
10384		// them layout
10385		div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
10386
10387		support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
10388		if ( val ) {
10389			// Prevent IE 6 from affecting layout for positioned elements #11048
10390			// Prevent IE from shrinking the body in IE 7 mode #12869
10391			// Support: IE<8
10392			body.style.zoom = 1;
10393		}
10394	}
10395
10396	body.removeChild( container );
10397});
10398
10399
10400
10401
10402(function() {
10403	var div = document.createElement( "div" );
10404
10405	// Execute the test only if not already executed in another module.
10406	if (support.deleteExpando == null) {
10407		// Support: IE<9
10408		support.deleteExpando = true;
10409		try {
10410			delete div.test;
10411		} catch( e ) {
10412			support.deleteExpando = false;
10413		}
10414	}
10415
10416	// Null elements to avoid leaks in IE.
10417	div = null;
10418})();
10419
10420
10421/**
10422 * Determines whether an object can have data
10423 */
10424jQuery1113.acceptData = function( elem ) {
10425	var noData = jQuery1113.noData[ (elem.nodeName + " ").toLowerCase() ],
10426		nodeType = +elem.nodeType || 1;
10427
10428	// Do not set data on non-element DOM nodes because it will not be cleared (#8335).
10429	return nodeType !== 1 && nodeType !== 9 ?
10430		false :
10431
10432		// Nodes accept data unless otherwise specified; rejection can be conditional
10433		!noData || noData !== true && elem.getAttribute("classid") === noData;
10434};
10435
10436
10437var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
10438	rmultiDash = /([A-Z])/g;
10439
10440function dataAttr( elem, key, data ) {
10441	// If nothing was found internally, try to fetch any
10442	// data from the HTML5 data-* attribute
10443	if ( data === undefined && elem.nodeType === 1 ) {
10444
10445		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
10446
10447		data = elem.getAttribute( name );
10448
10449		if ( typeof data === "string" ) {
10450			try {
10451				data = data === "true" ? true :
10452					data === "false" ? false :
10453					data === "null" ? null :
10454					// Only convert to a number if it doesn't change the string
10455					+data + "" === data ? +data :
10456					rbrace.test( data ) ? jQuery1113.parseJSON( data ) :
10457					data;
10458			} catch( e ) {}
10459
10460			// Make sure we set the data so it isn't changed later
10461			jQuery1113.data( elem, key, data );
10462
10463		} else {
10464			data = undefined;
10465		}
10466	}
10467
10468	return data;
10469}
10470
10471// checks a cache object for emptiness
10472function isEmptyDataObject( obj ) {
10473	var name;
10474	for ( name in obj ) {
10475
10476		// if the public data object is empty, the private is still empty
10477		if ( name === "data" && jQuery1113.isEmptyObject( obj[name] ) ) {
10478			continue;
10479		}
10480		if ( name !== "toJSON" ) {
10481			return false;
10482		}
10483	}
10484
10485	return true;
10486}
10487
10488function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
10489	if ( !jQuery1113.acceptData( elem ) ) {
10490		return;
10491	}
10492
10493	var ret, thisCache,
10494		internalKey = jQuery1113.expando,
10495
10496		// We have to handle DOM nodes and JS objects differently because IE6-7
10497		// can't GC object references properly across the DOM-JS boundary
10498		isNode = elem.nodeType,
10499
10500		// Only DOM nodes need the global jQuery1113 cache; JS object data is
10501		// attached directly to the object so GC can occur automatically
10502		cache = isNode ? jQuery1113.cache : elem,
10503
10504		// Only defining an ID for JS objects if its cache already exists allows
10505		// the code to shortcut on the same path as a DOM node with no cache
10506		id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
10507
10508	// Avoid doing any more work than we need to when trying to get data on an
10509	// object that has no data at all
10510	if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
10511		return;
10512	}
10513
10514	if ( !id ) {
10515		// Only DOM nodes need a new unique ID for each element since their data
10516		// ends up in the global cache
10517		if ( isNode ) {
10518			id = elem[ internalKey ] = deletedIds.pop() || jQuery1113.guid++;
10519		} else {
10520			id = internalKey;
10521		}
10522	}
10523
10524	if ( !cache[ id ] ) {
10525		// Avoid exposing jQuery1113 metadata on plain JS objects when the object
10526		// is serialized using JSON.stringify
10527		cache[ id ] = isNode ? {} : { toJSON: jQuery1113.noop };
10528	}
10529
10530	// An object can be passed to jQuery1113.data instead of a key/value pair; this gets
10531	// shallow copied over onto the existing cache
10532	if ( typeof name === "object" || typeof name === "function" ) {
10533		if ( pvt ) {
10534			cache[ id ] = jQuery1113.extend( cache[ id ], name );
10535		} else {
10536			cache[ id ].data = jQuery1113.extend( cache[ id ].data, name );
10537		}
10538	}
10539
10540	thisCache = cache[ id ];
10541
10542	// jQuery1113 data() is stored in a separate object inside the object's internal data
10543	// cache in order to avoid key collisions between internal data and user-defined
10544	// data.
10545	if ( !pvt ) {
10546		if ( !thisCache.data ) {
10547			thisCache.data = {};
10548		}
10549
10550		thisCache = thisCache.data;
10551	}
10552
10553	if ( data !== undefined ) {
10554		thisCache[ jQuery1113.camelCase( name ) ] = data;
10555	}
10556
10557	// Check for both converted-to-camel and non-converted data property names
10558	// If a data property was specified
10559	if ( typeof name === "string" ) {
10560
10561		// First Try to find as-is property data
10562		ret = thisCache[ name ];
10563
10564		// Test for null|undefined property data
10565		if ( ret == null ) {
10566
10567			// Try to find the camelCased property
10568			ret = thisCache[ jQuery1113.camelCase( name ) ];
10569		}
10570	} else {
10571		ret = thisCache;
10572	}
10573
10574	return ret;
10575}
10576
10577function internalRemoveData( elem, name, pvt ) {
10578	if ( !jQuery1113.acceptData( elem ) ) {
10579		return;
10580	}
10581
10582	var thisCache, i,
10583		isNode = elem.nodeType,
10584
10585		// See jQuery1113.data for more information
10586		cache = isNode ? jQuery1113.cache : elem,
10587		id = isNode ? elem[ jQuery1113.expando ] : jQuery1113.expando;
10588
10589	// If there is already no cache entry for this object, there is no
10590	// purpose in continuing
10591	if ( !cache[ id ] ) {
10592		return;
10593	}
10594
10595	if ( name ) {
10596
10597		thisCache = pvt ? cache[ id ] : cache[ id ].data;
10598
10599		if ( thisCache ) {
10600
10601			// Support array or space separated string names for data keys
10602			if ( !jQuery1113.isArray( name ) ) {
10603
10604				// try the string as a key before any manipulation
10605				if ( name in thisCache ) {
10606					name = [ name ];
10607				} else {
10608
10609					// split the camel cased version by spaces unless a key with the spaces exists
10610					name = jQuery1113.camelCase( name );
10611					if ( name in thisCache ) {
10612						name = [ name ];
10613					} else {
10614						name = name.split(" ");
10615					}
10616				}
10617			} else {
10618				// If "name" is an array of keys...
10619				// When data is initially created, via ("key", "val") signature,
10620				// keys will be converted to camelCase.
10621				// Since there is no way to tell _how_ a key was added, remove
10622				// both plain key and camelCase key. #12786
10623				// This will only penalize the array argument path.
10624				name = name.concat( jQuery1113.map( name, jQuery1113.camelCase ) );
10625			}
10626
10627			i = name.length;
10628			while ( i-- ) {
10629				delete thisCache[ name[i] ];
10630			}
10631
10632			// If there is no data left in the cache, we want to continue
10633			// and let the cache object itself get destroyed
10634			if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery1113.isEmptyObject(thisCache) ) {
10635				return;
10636			}
10637		}
10638	}
10639
10640	// See jQuery1113.data for more information
10641	if ( !pvt ) {
10642		delete cache[ id ].data;
10643
10644		// Don't destroy the parent cache unless the internal data object
10645		// had been the only thing left in it
10646		if ( !isEmptyDataObject( cache[ id ] ) ) {
10647			return;
10648		}
10649	}
10650
10651	// Destroy the cache
10652	if ( isNode ) {
10653		jQuery1113.cleanData( [ elem ], true );
10654
10655	// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
10656	/* jshint eqeqeq: false */
10657	} else if ( support.deleteExpando || cache != cache.window ) {
10658		/* jshint eqeqeq: true */
10659		delete cache[ id ];
10660
10661	// When all else fails, null
10662	} else {
10663		cache[ id ] = null;
10664	}
10665}
10666
10667jQuery1113.extend({
10668	cache: {},
10669
10670	// The following elements (space-suffixed to avoid Object.prototype collisions)
10671	// throw uncatchable exceptions if you attempt to set expando properties
10672	noData: {
10673		"applet ": true,
10674		"embed ": true,
10675		// ...but Flash objects (which have this classid) *can* handle expandos
10676		"object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
10677	},
10678
10679	hasData: function( elem ) {
10680		elem = elem.nodeType ? jQuery1113.cache[ elem[jQuery1113.expando] ] : elem[ jQuery1113.expando ];
10681		return !!elem && !isEmptyDataObject( elem );
10682	},
10683
10684	data: function( elem, name, data ) {
10685		return internalData( elem, name, data );
10686	},
10687
10688	removeData: function( elem, name ) {
10689		return internalRemoveData( elem, name );
10690	},
10691
10692	// For internal use only.
10693	_data: function( elem, name, data ) {
10694		return internalData( elem, name, data, true );
10695	},
10696
10697	_removeData: function( elem, name ) {
10698		return internalRemoveData( elem, name, true );
10699	}
10700});
10701
10702jQuery1113.fn.extend({
10703	data: function( key, value ) {
10704		var i, name, data,
10705			elem = this[0],
10706			attrs = elem && elem.attributes;
10707
10708		// Special expections of .data basically thwart jQuery1113.access,
10709		// so implement the relevant behavior ourselves
10710
10711		// Gets all values
10712		if ( key === undefined ) {
10713			if ( this.length ) {
10714				data = jQuery1113.data( elem );
10715
10716				if ( elem.nodeType === 1 && !jQuery1113._data( elem, "parsedAttrs" ) ) {
10717					i = attrs.length;
10718					while ( i-- ) {
10719
10720						// Support: IE11+
10721						// The attrs elements can be null (#14894)
10722						if ( attrs[ i ] ) {
10723							name = attrs[ i ].name;
10724							if ( name.indexOf( "data-" ) === 0 ) {
10725								name = jQuery1113.camelCase( name.slice(5) );
10726								dataAttr( elem, name, data[ name ] );
10727							}
10728						}
10729					}
10730					jQuery1113._data( elem, "parsedAttrs", true );
10731				}
10732			}
10733
10734			return data;
10735		}
10736
10737		// Sets multiple values
10738		if ( typeof key === "object" ) {
10739			return this.each(function() {
10740				jQuery1113.data( this, key );
10741			});
10742		}
10743
10744		return arguments.length > 1 ?
10745
10746			// Sets one value
10747			this.each(function() {
10748				jQuery1113.data( this, key, value );
10749			}) :
10750
10751			// Gets one value
10752			// Try to fetch any internally stored data first
10753			elem ? dataAttr( elem, key, jQuery1113.data( elem, key ) ) : undefined;
10754	},
10755
10756	removeData: function( key ) {
10757		return this.each(function() {
10758			jQuery1113.removeData( this, key );
10759		});
10760	}
10761});
10762
10763
10764jQuery1113.extend({
10765	queue: function( elem, type, data ) {
10766		var queue;
10767
10768		if ( elem ) {
10769			type = ( type || "fx" ) + "queue";
10770			queue = jQuery1113._data( elem, type );
10771
10772			// Speed up dequeue by getting out quickly if this is just a lookup
10773			if ( data ) {
10774				if ( !queue || jQuery1113.isArray(data) ) {
10775					queue = jQuery1113._data( elem, type, jQuery1113.makeArray(data) );
10776				} else {
10777					queue.push( data );
10778				}
10779			}
10780			return queue || [];
10781		}
10782	},
10783
10784	dequeue: function( elem, type ) {
10785		type = type || "fx";
10786
10787		var queue = jQuery1113.queue( elem, type ),
10788			startLength = queue.length,
10789			fn = queue.shift(),
10790			hooks = jQuery1113._queueHooks( elem, type ),
10791			next = function() {
10792				jQuery1113.dequeue( elem, type );
10793			};
10794
10795		// If the fx queue is dequeued, always remove the progress sentinel
10796		if ( fn === "inprogress" ) {
10797			fn = queue.shift();
10798			startLength--;
10799		}
10800
10801		if ( fn ) {
10802
10803			// Add a progress sentinel to prevent the fx queue from being
10804			// automatically dequeued
10805			if ( type === "fx" ) {
10806				queue.unshift( "inprogress" );
10807			}
10808
10809			// clear up the last queue stop function
10810			delete hooks.stop;
10811			fn.call( elem, next, hooks );
10812		}
10813
10814		if ( !startLength && hooks ) {
10815			hooks.empty.fire();
10816		}
10817	},
10818
10819	// not intended for public consumption - generates a queueHooks object, or returns the current one
10820	_queueHooks: function( elem, type ) {
10821		var key = type + "queueHooks";
10822		return jQuery1113._data( elem, key ) || jQuery1113._data( elem, key, {
10823			empty: jQuery1113.Callbacks("once memory").add(function() {
10824				jQuery1113._removeData( elem, type + "queue" );
10825				jQuery1113._removeData( elem, key );
10826			})
10827		});
10828	}
10829});
10830
10831jQuery1113.fn.extend({
10832	queue: function( type, data ) {
10833		var setter = 2;
10834
10835		if ( typeof type !== "string" ) {
10836			data = type;
10837			type = "fx";
10838			setter--;
10839		}
10840
10841		if ( arguments.length < setter ) {
10842			return jQuery1113.queue( this[0], type );
10843		}
10844
10845		return data === undefined ?
10846			this :
10847			this.each(function() {
10848				var queue = jQuery1113.queue( this, type, data );
10849
10850				// ensure a hooks for this queue
10851				jQuery1113._queueHooks( this, type );
10852
10853				if ( type === "fx" && queue[0] !== "inprogress" ) {
10854					jQuery1113.dequeue( this, type );
10855				}
10856			});
10857	},
10858	dequeue: function( type ) {
10859		return this.each(function() {
10860			jQuery1113.dequeue( this, type );
10861		});
10862	},
10863	clearQueue: function( type ) {
10864		return this.queue( type || "fx", [] );
10865	},
10866	// Get a promise resolved when queues of a certain type
10867	// are emptied (fx is the type by default)
10868	promise: function( type, obj ) {
10869		var tmp,
10870			count = 1,
10871			defer = jQuery1113.Deferred(),
10872			elements = this,
10873			i = this.length,
10874			resolve = function() {
10875				if ( !( --count ) ) {
10876					defer.resolveWith( elements, [ elements ] );
10877				}
10878			};
10879
10880		if ( typeof type !== "string" ) {
10881			obj = type;
10882			type = undefined;
10883		}
10884		type = type || "fx";
10885
10886		while ( i-- ) {
10887			tmp = jQuery1113._data( elements[ i ], type + "queueHooks" );
10888			if ( tmp && tmp.empty ) {
10889				count++;
10890				tmp.empty.add( resolve );
10891			}
10892		}
10893		resolve();
10894		return defer.promise( obj );
10895	}
10896});
10897var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
10898
10899var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
10900
10901var isHidden = function( elem, el ) {
10902		// isHidden might be called from jQuery1113#filter function;
10903		// in that case, element will be second argument
10904		elem = el || elem;
10905		return jQuery1113.css( elem, "display" ) === "none" || !jQuery1113.contains( elem.ownerDocument, elem );
10906	};
10907
10908
10909
10910// Multifunctional method to get and set values of a collection
10911// The value/s can optionally be executed if it's a function
10912var access = jQuery1113.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
10913	var i = 0,
10914		length = elems.length,
10915		bulk = key == null;
10916
10917	// Sets many values
10918	if ( jQuery1113.type( key ) === "object" ) {
10919		chainable = true;
10920		for ( i in key ) {
10921			jQuery1113.access( elems, fn, i, key[i], true, emptyGet, raw );
10922		}
10923
10924	// Sets one value
10925	} else if ( value !== undefined ) {
10926		chainable = true;
10927
10928		if ( !jQuery1113.isFunction( value ) ) {
10929			raw = true;
10930		}
10931
10932		if ( bulk ) {
10933			// Bulk operations run against the entire set
10934			if ( raw ) {
10935				fn.call( elems, value );
10936				fn = null;
10937
10938			// ...except when executing function values
10939			} else {
10940				bulk = fn;
10941				fn = function( elem, key, value ) {
10942					return bulk.call( jQuery1113( elem ), value );
10943				};
10944			}
10945		}
10946
10947		if ( fn ) {
10948			for ( ; i < length; i++ ) {
10949				fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
10950			}
10951		}
10952	}
10953
10954	return chainable ?
10955		elems :
10956
10957		// Gets
10958		bulk ?
10959			fn.call( elems ) :
10960			length ? fn( elems[0], key ) : emptyGet;
10961};
10962var rcheckableType = (/^(?:checkbox|radio)$/i);
10963
10964
10965
10966(function() {
10967	// Minified: var a,b,c
10968	var input = document.createElement( "input" ),
10969		div = document.createElement( "div" ),
10970		fragment = document.createDocumentFragment();
10971
10972	// Setup
10973	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
10974
10975	// IE strips leading whitespace when .innerHTML is used
10976	support.leadingWhitespace = div.firstChild.nodeType === 3;
10977
10978	// Make sure that tbody elements aren't automatically inserted
10979	// IE will insert them into empty tables
10980	support.tbody = !div.getElementsByTagName( "tbody" ).length;
10981
10982	// Make sure that link elements get serialized correctly by innerHTML
10983	// This requires a wrapper element in IE
10984	support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
10985
10986	// Makes sure cloning an html5 element does not cause problems
10987	// Where outerHTML is undefined, this still works
10988	support.html5Clone =
10989		document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
10990
10991	// Check if a disconnected checkbox will retain its checked
10992	// value of true after appended to the DOM (IE6/7)
10993	input.type = "checkbox";
10994	input.checked = true;
10995	fragment.appendChild( input );
10996	support.appendChecked = input.checked;
10997
10998	// Make sure textarea (and checkbox) defaultValue is properly cloned
10999	// Support: IE6-IE11+
11000	div.innerHTML = "<textarea>x</textarea>";
11001	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
11002
11003	// #11217 - WebKit loses check when the name is after the checked attribute
11004	fragment.appendChild( div );
11005	div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
11006
11007	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
11008	// old WebKit doesn't clone checked state correctly in fragments
11009	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
11010
11011	// Support: IE<9
11012	// Opera does not clone events (and typeof div.attachEvent === undefined).
11013	// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
11014	support.noCloneEvent = true;
11015	if ( div.attachEvent ) {
11016		div.attachEvent( "onclick", function() {
11017			support.noCloneEvent = false;
11018		});
11019
11020		div.cloneNode( true ).click();
11021	}
11022
11023	// Execute the test only if not already executed in another module.
11024	if (support.deleteExpando == null) {
11025		// Support: IE<9
11026		support.deleteExpando = true;
11027		try {
11028			delete div.test;
11029		} catch( e ) {
11030			support.deleteExpando = false;
11031		}
11032	}
11033})();
11034
11035
11036(function() {
11037	var i, eventName,
11038		div = document.createElement( "div" );
11039
11040	// Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
11041	for ( i in { submit: true, change: true, focusin: true }) {
11042		eventName = "on" + i;
11043
11044		if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
11045			// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
11046			div.setAttribute( eventName, "t" );
11047			support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
11048		}
11049	}
11050
11051	// Null elements to avoid leaks in IE.
11052	div = null;
11053})();
11054
11055
11056var rformElems = /^(?:input|select|textarea)$/i,
11057	rkeyEvent = /^key/,
11058	rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
11059	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
11060	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
11061
11062function returnTrue() {
11063	return true;
11064}
11065
11066function returnFalse() {
11067	return false;
11068}
11069
11070function safeActiveElement() {
11071	try {
11072		return document.activeElement;
11073	} catch ( err ) { }
11074}
11075
11076/*
11077 * Helper functions for managing events -- not part of the public interface.
11078 * Props to Dean Edwards' addEvent library for many of the ideas.
11079 */
11080jQuery1113.event = {
11081
11082	global: {},
11083
11084	add: function( elem, types, handler, data, selector ) {
11085		var tmp, events, t, handleObjIn,
11086			special, eventHandle, handleObj,
11087			handlers, type, namespaces, origType,
11088			elemData = jQuery1113._data( elem );
11089
11090		// Don't attach events to noData or text/comment nodes (but allow plain objects)
11091		if ( !elemData ) {
11092			return;
11093		}
11094
11095		// Caller can pass in an object of custom data in lieu of the handler
11096		if ( handler.handler ) {
11097			handleObjIn = handler;
11098			handler = handleObjIn.handler;
11099			selector = handleObjIn.selector;
11100		}
11101
11102		// Make sure that the handler has a unique ID, used to find/remove it later
11103		if ( !handler.guid ) {
11104			handler.guid = jQuery1113.guid++;
11105		}
11106
11107		// Init the element's event structure and main handler, if this is the first
11108		if ( !(events = elemData.events) ) {
11109			events = elemData.events = {};
11110		}
11111		if ( !(eventHandle = elemData.handle) ) {
11112			eventHandle = elemData.handle = function( e ) {
11113				// Discard the second event of a jQuery1113.event.trigger() and
11114				// when an event is called after a page has unloaded
11115				return typeof jQuery1113 !== strundefined && (!e || jQuery1113.event.triggered !== e.type) ?
11116					jQuery1113.event.dispatch.apply( eventHandle.elem, arguments ) :
11117					undefined;
11118			};
11119			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
11120			eventHandle.elem = elem;
11121		}
11122
11123		// Handle multiple events separated by a space
11124		types = ( types || "" ).match( rnotwhite ) || [ "" ];
11125		t = types.length;
11126		while ( t-- ) {
11127			tmp = rtypenamespace.exec( types[t] ) || [];
11128			type = origType = tmp[1];
11129			namespaces = ( tmp[2] || "" ).split( "." ).sort();
11130
11131			// There *must* be a type, no attaching namespace-only handlers
11132			if ( !type ) {
11133				continue;
11134			}
11135
11136			// If event changes its type, use the special event handlers for the changed type
11137			special = jQuery1113.event.special[ type ] || {};
11138
11139			// If selector defined, determine special event api type, otherwise given type
11140			type = ( selector ? special.delegateType : special.bindType ) || type;
11141
11142			// Update special based on newly reset type
11143			special = jQuery1113.event.special[ type ] || {};
11144
11145			// handleObj is passed to all event handlers
11146			handleObj = jQuery1113.extend({
11147				type: type,
11148				origType: origType,
11149				data: data,
11150				handler: handler,
11151				guid: handler.guid,
11152				selector: selector,
11153				needsContext: selector && jQuery1113.expr.match.needsContext.test( selector ),
11154				namespace: namespaces.join(".")
11155			}, handleObjIn );
11156
11157			// Init the event handler queue if we're the first
11158			if ( !(handlers = events[ type ]) ) {
11159				handlers = events[ type ] = [];
11160				handlers.delegateCount = 0;
11161
11162				// Only use addEventListener/attachEvent if the special events handler returns false
11163				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
11164					// Bind the global event handler to the element
11165					if ( elem.addEventListener ) {
11166						elem.addEventListener( type, eventHandle, false );
11167
11168					} else if ( elem.attachEvent ) {
11169						elem.attachEvent( "on" + type, eventHandle );
11170					}
11171				}
11172			}
11173
11174			if ( special.add ) {
11175				special.add.call( elem, handleObj );
11176
11177				if ( !handleObj.handler.guid ) {
11178					handleObj.handler.guid = handler.guid;
11179				}
11180			}
11181
11182			// Add to the element's handler list, delegates in front
11183			if ( selector ) {
11184				handlers.splice( handlers.delegateCount++, 0, handleObj );
11185			} else {
11186				handlers.push( handleObj );
11187			}
11188
11189			// Keep track of which events have ever been used, for event optimization
11190			jQuery1113.event.global[ type ] = true;
11191		}
11192
11193		// Nullify elem to prevent memory leaks in IE
11194		elem = null;
11195	},
11196
11197	// Detach an event or set of events from an element
11198	remove: function( elem, types, handler, selector, mappedTypes ) {
11199		var j, handleObj, tmp,
11200			origCount, t, events,
11201			special, handlers, type,
11202			namespaces, origType,
11203			elemData = jQuery1113.hasData( elem ) && jQuery1113._data( elem );
11204
11205		if ( !elemData || !(events = elemData.events) ) {
11206			return;
11207		}
11208
11209		// Once for each type.namespace in types; type may be omitted
11210		types = ( types || "" ).match( rnotwhite ) || [ "" ];
11211		t = types.length;
11212		while ( t-- ) {
11213			tmp = rtypenamespace.exec( types[t] ) || [];
11214			type = origType = tmp[1];
11215			namespaces = ( tmp[2] || "" ).split( "." ).sort();
11216
11217			// Unbind all events (on this namespace, if provided) for the element
11218			if ( !type ) {
11219				for ( type in events ) {
11220					jQuery1113.event.remove( elem, type + types[ t ], handler, selector, true );
11221				}
11222				continue;
11223			}
11224
11225			special = jQuery1113.event.special[ type ] || {};
11226			type = ( selector ? special.delegateType : special.bindType ) || type;
11227			handlers = events[ type ] || [];
11228			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
11229
11230			// Remove matching events
11231			origCount = j = handlers.length;
11232			while ( j-- ) {
11233				handleObj = handlers[ j ];
11234
11235				if ( ( mappedTypes || origType === handleObj.origType ) &&
11236					( !handler || handler.guid === handleObj.guid ) &&
11237					( !tmp || tmp.test( handleObj.namespace ) ) &&
11238					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
11239					handlers.splice( j, 1 );
11240
11241					if ( handleObj.selector ) {
11242						handlers.delegateCount--;
11243					}
11244					if ( special.remove ) {
11245						special.remove.call( elem, handleObj );
11246					}
11247				}
11248			}
11249
11250			// Remove generic event handler if we removed something and no more handlers exist
11251			// (avoids potential for endless recursion during removal of special event handlers)
11252			if ( origCount && !handlers.length ) {
11253				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
11254					jQuery1113.removeEvent( elem, type, elemData.handle );
11255				}
11256
11257				delete events[ type ];
11258			}
11259		}
11260
11261		// Remove the expando if it's no longer used
11262		if ( jQuery1113.isEmptyObject( events ) ) {
11263			delete elemData.handle;
11264
11265			// removeData also checks for emptiness and clears the expando if empty
11266			// so use it instead of delete
11267			jQuery1113._removeData( elem, "events" );
11268		}
11269	},
11270
11271	trigger: function( event, data, elem, onlyHandlers ) {
11272		var handle, ontype, cur,
11273			bubbleType, special, tmp, i,
11274			eventPath = [ elem || document ],
11275			type = hasOwn.call( event, "type" ) ? event.type : event,
11276			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
11277
11278		cur = tmp = elem = elem || document;
11279
11280		// Don't do events on text and comment nodes
11281		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
11282			return;
11283		}
11284
11285		// focus/blur morphs to focusin/out; ensure we're not firing them right now
11286		if ( rfocusMorph.test( type + jQuery1113.event.triggered ) ) {
11287			return;
11288		}
11289
11290		if ( type.indexOf(".") >= 0 ) {
11291			// Namespaced trigger; create a regexp to match event type in handle()
11292			namespaces = type.split(".");
11293			type = namespaces.shift();
11294			namespaces.sort();
11295		}
11296		ontype = type.indexOf(":") < 0 && "on" + type;
11297
11298		// Caller can pass in a jQuery1113.Event object, Object, or just an event type string
11299		event = event[ jQuery1113.expando ] ?
11300			event :
11301			new jQuery1113.Event( type, typeof event === "object" && event );
11302
11303		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery1113 (always true)
11304		event.isTrigger = onlyHandlers ? 2 : 3;
11305		event.namespace = namespaces.join(".");
11306		event.namespace_re = event.namespace ?
11307			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
11308			null;
11309
11310		// Clean up the event in case it is being reused
11311		event.result = undefined;
11312		if ( !event.target ) {
11313			event.target = elem;
11314		}
11315
11316		// Clone any incoming data and prepend the event, creating the handler arg list
11317		data = data == null ?
11318			[ event ] :
11319			jQuery1113.makeArray( data, [ event ] );
11320
11321		// Allow special events to draw outside the lines
11322		special = jQuery1113.event.special[ type ] || {};
11323		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
11324			return;
11325		}
11326
11327		// Determine event propagation path in advance, per W3C events spec (#9951)
11328		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
11329		if ( !onlyHandlers && !special.noBubble && !jQuery1113.isWindow( elem ) ) {
11330
11331			bubbleType = special.delegateType || type;
11332			if ( !rfocusMorph.test( bubbleType + type ) ) {
11333				cur = cur.parentNode;
11334			}
11335			for ( ; cur; cur = cur.parentNode ) {
11336				eventPath.push( cur );
11337				tmp = cur;
11338			}
11339
11340			// Only add window if we got to document (e.g., not plain obj or detached DOM)
11341			if ( tmp === (elem.ownerDocument || document) ) {
11342				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
11343			}
11344		}
11345
11346		// Fire handlers on the event path
11347		i = 0;
11348		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
11349
11350			event.type = i > 1 ?
11351				bubbleType :
11352				special.bindType || type;
11353
11354			// jQuery1113 handler
11355			handle = ( jQuery1113._data( cur, "events" ) || {} )[ event.type ] && jQuery1113._data( cur, "handle" );
11356			if ( handle ) {
11357				handle.apply( cur, data );
11358			}
11359
11360			// Native handler
11361			handle = ontype && cur[ ontype ];
11362			if ( handle && handle.apply && jQuery1113.acceptData( cur ) ) {
11363				event.result = handle.apply( cur, data );
11364				if ( event.result === false ) {
11365					event.preventDefault();
11366				}
11367			}
11368		}
11369		event.type = type;
11370
11371		// If nobody prevented the default action, do it now
11372		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
11373
11374			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
11375				jQuery1113.acceptData( elem ) ) {
11376
11377				// Call a native DOM method on the target with the same name name as the event.
11378				// Can't use an .isFunction() check here because IE6/7 fails that test.
11379				// Don't do default actions on window, that's where global variables be (#6170)
11380				if ( ontype && elem[ type ] && !jQuery1113.isWindow( elem ) ) {
11381
11382					// Don't re-trigger an onFOO event when we call its FOO() method
11383					tmp = elem[ ontype ];
11384
11385					if ( tmp ) {
11386						elem[ ontype ] = null;
11387					}
11388
11389					// Prevent re-triggering of the same event, since we already bubbled it above
11390					jQuery1113.event.triggered = type;
11391					try {
11392						elem[ type ]();
11393					} catch ( e ) {
11394						// IE<9 dies on focus/blur to hidden element (#1486,#12518)
11395						// only reproducible on winXP IE8 native, not IE9 in IE8 mode
11396					}
11397					jQuery1113.event.triggered = undefined;
11398
11399					if ( tmp ) {
11400						elem[ ontype ] = tmp;
11401					}
11402				}
11403			}
11404		}
11405
11406		return event.result;
11407	},
11408
11409	dispatch: function( event ) {
11410
11411		// Make a writable jQuery1113.Event from the native event object
11412		event = jQuery1113.event.fix( event );
11413
11414		var i, ret, handleObj, matched, j,
11415			handlerQueue = [],
11416			args = slice.call( arguments ),
11417			handlers = ( jQuery1113._data( this, "events" ) || {} )[ event.type ] || [],
11418			special = jQuery1113.event.special[ event.type ] || {};
11419
11420		// Use the fix-ed jQuery1113.Event rather than the (read-only) native event
11421		args[0] = event;
11422		event.delegateTarget = this;
11423
11424		// Call the preDispatch hook for the mapped type, and let it bail if desired
11425		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
11426			return;
11427		}
11428
11429		// Determine handlers
11430		handlerQueue = jQuery1113.event.handlers.call( this, event, handlers );
11431
11432		// Run delegates first; they may want to stop propagation beneath us
11433		i = 0;
11434		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
11435			event.currentTarget = matched.elem;
11436
11437			j = 0;
11438			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
11439
11440				// Triggered event must either 1) have no namespace, or
11441				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
11442				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
11443
11444					event.handleObj = handleObj;
11445					event.data = handleObj.data;
11446
11447					ret = ( (jQuery1113.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
11448							.apply( matched.elem, args );
11449
11450					if ( ret !== undefined ) {
11451						if ( (event.result = ret) === false ) {
11452							event.preventDefault();
11453							event.stopPropagation();
11454						}
11455					}
11456				}
11457			}
11458		}
11459
11460		// Call the postDispatch hook for the mapped type
11461		if ( special.postDispatch ) {
11462			special.postDispatch.call( this, event );
11463		}
11464
11465		return event.result;
11466	},
11467
11468	handlers: function( event, handlers ) {
11469		var sel, handleObj, matches, i,
11470			handlerQueue = [],
11471			delegateCount = handlers.delegateCount,
11472			cur = event.target;
11473
11474		// Find delegate handlers
11475		// Black-hole SVG <use> instance trees (#13180)
11476		// Avoid non-left-click bubbling in Firefox (#3861)
11477		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
11478
11479			/* jshint eqeqeq: false */
11480			for ( ; cur != this; cur = cur.parentNode || this ) {
11481				/* jshint eqeqeq: true */
11482
11483				// Don't check non-elements (#13208)
11484				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
11485				if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
11486					matches = [];
11487					for ( i = 0; i < delegateCount; i++ ) {
11488						handleObj = handlers[ i ];
11489
11490						// Don't conflict with Object.prototype properties (#13203)
11491						sel = handleObj.selector + " ";
11492
11493						if ( matches[ sel ] === undefined ) {
11494							matches[ sel ] = handleObj.needsContext ?
11495								jQuery1113( sel, this ).index( cur ) >= 0 :
11496								jQuery1113.find( sel, this, null, [ cur ] ).length;
11497						}
11498						if ( matches[ sel ] ) {
11499							matches.push( handleObj );
11500						}
11501					}
11502					if ( matches.length ) {
11503						handlerQueue.push({ elem: cur, handlers: matches });
11504					}
11505				}
11506			}
11507		}
11508
11509		// Add the remaining (directly-bound) handlers
11510		if ( delegateCount < handlers.length ) {
11511			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
11512		}
11513
11514		return handlerQueue;
11515	},
11516
11517	fix: function( event ) {
11518		if ( event[ jQuery1113.expando ] ) {
11519			return event;
11520		}
11521
11522		// Create a writable copy of the event object and normalize some properties
11523		var i, prop, copy,
11524			type = event.type,
11525			originalEvent = event,
11526			fixHook = this.fixHooks[ type ];
11527
11528		if ( !fixHook ) {
11529			this.fixHooks[ type ] = fixHook =
11530				rmouseEvent.test( type ) ? this.mouseHooks :
11531				rkeyEvent.test( type ) ? this.keyHooks :
11532				{};
11533		}
11534		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
11535
11536		event = new jQuery1113.Event( originalEvent );
11537
11538		i = copy.length;
11539		while ( i-- ) {
11540			prop = copy[ i ];
11541			event[ prop ] = originalEvent[ prop ];
11542		}
11543
11544		// Support: IE<9
11545		// Fix target property (#1925)
11546		if ( !event.target ) {
11547			event.target = originalEvent.srcElement || document;
11548		}
11549
11550		// Support: Chrome 23+, Safari?
11551		// Target should not be a text node (#504, #13143)
11552		if ( event.target.nodeType === 3 ) {
11553			event.target = event.target.parentNode;
11554		}
11555
11556		// Support: IE<9
11557		// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
11558		event.metaKey = !!event.metaKey;
11559
11560		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
11561	},
11562
11563	// Includes some event props shared by KeyEvent and MouseEvent
11564	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
11565
11566	fixHooks: {},
11567
11568	keyHooks: {
11569		props: "char charCode key keyCode".split(" "),
11570		filter: function( event, original ) {
11571
11572			// Add which for key events
11573			if ( event.which == null ) {
11574				event.which = original.charCode != null ? original.charCode : original.keyCode;
11575			}
11576
11577			return event;
11578		}
11579	},
11580
11581	mouseHooks: {
11582		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
11583		filter: function( event, original ) {
11584			var body, eventDoc, doc,
11585				button = original.button,
11586				fromElement = original.fromElement;
11587
11588			// Calculate pageX/Y if missing and clientX/Y available
11589			if ( event.pageX == null && original.clientX != null ) {
11590				eventDoc = event.target.ownerDocument || document;
11591				doc = eventDoc.documentElement;
11592				body = eventDoc.body;
11593
11594				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
11595				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
11596			}
11597
11598			// Add relatedTarget, if necessary
11599			if ( !event.relatedTarget && fromElement ) {
11600				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
11601			}
11602
11603			// Add which for click: 1 === left; 2 === middle; 3 === right
11604			// Note: button is not normalized, so don't use it
11605			if ( !event.which && button !== undefined ) {
11606				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
11607			}
11608
11609			return event;
11610		}
11611	},
11612
11613	special: {
11614		load: {
11615			// Prevent triggered image.load events from bubbling to window.load
11616			noBubble: true
11617		},
11618		focus: {
11619			// Fire native event if possible so blur/focus sequence is correct
11620			trigger: function() {
11621				if ( this !== safeActiveElement() && this.focus ) {
11622					try {
11623						this.focus();
11624						return false;
11625					} catch ( e ) {
11626						// Support: IE<9
11627						// If we error on focus to hidden element (#1486, #12518),
11628						// let .trigger() run the handlers
11629					}
11630				}
11631			},
11632			delegateType: "focusin"
11633		},
11634		blur: {
11635			trigger: function() {
11636				if ( this === safeActiveElement() && this.blur ) {
11637					this.blur();
11638					return false;
11639				}
11640			},
11641			delegateType: "focusout"
11642		},
11643		click: {
11644			// For checkbox, fire native event so checked state will be right
11645			trigger: function() {
11646				if ( jQuery1113.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
11647					this.click();
11648					return false;
11649				}
11650			},
11651
11652			// For cross-browser consistency, don't fire native .click() on links
11653			_default: function( event ) {
11654				return jQuery1113.nodeName( event.target, "a" );
11655			}
11656		},
11657
11658		beforeunload: {
11659			postDispatch: function( event ) {
11660
11661				// Support: Firefox 20+
11662				// Firefox doesn't alert if the returnValue field is not set.
11663				if ( event.result !== undefined && event.originalEvent ) {
11664					event.originalEvent.returnValue = event.result;
11665				}
11666			}
11667		}
11668	},
11669
11670	simulate: function( type, elem, event, bubble ) {
11671		// Piggyback on a donor event to simulate a different one.
11672		// Fake originalEvent to avoid donor's stopPropagation, but if the
11673		// simulated event prevents default then we do the same on the donor.
11674		var e = jQuery1113.extend(
11675			new jQuery1113.Event(),
11676			event,
11677			{
11678				type: type,
11679				isSimulated: true,
11680				originalEvent: {}
11681			}
11682		);
11683		if ( bubble ) {
11684			jQuery1113.event.trigger( e, null, elem );
11685		} else {
11686			jQuery1113.event.dispatch.call( elem, e );
11687		}
11688		if ( e.isDefaultPrevented() ) {
11689			event.preventDefault();
11690		}
11691	}
11692};
11693
11694jQuery1113.removeEvent = document.removeEventListener ?
11695	function( elem, type, handle ) {
11696		if ( elem.removeEventListener ) {
11697			elem.removeEventListener( type, handle, false );
11698		}
11699	} :
11700	function( elem, type, handle ) {
11701		var name = "on" + type;
11702
11703		if ( elem.detachEvent ) {
11704
11705			// #8545, #7054, preventing memory leaks for custom events in IE6-8
11706			// detachEvent needed property on element, by name of that event, to properly expose it to GC
11707			if ( typeof elem[ name ] === strundefined ) {
11708				elem[ name ] = null;
11709			}
11710
11711			elem.detachEvent( name, handle );
11712		}
11713	};
11714
11715jQuery1113.Event = function( src, props ) {
11716	// Allow instantiation without the 'new' keyword
11717	if ( !(this instanceof jQuery1113.Event) ) {
11718		return new jQuery1113.Event( src, props );
11719	}
11720
11721	// Event object
11722	if ( src && src.type ) {
11723		this.originalEvent = src;
11724		this.type = src.type;
11725
11726		// Events bubbling up the document may have been marked as prevented
11727		// by a handler lower down the tree; reflect the correct value.
11728		this.isDefaultPrevented = src.defaultPrevented ||
11729				src.defaultPrevented === undefined &&
11730				// Support: IE < 9, Android < 4.0
11731				src.returnValue === false ?
11732			returnTrue :
11733			returnFalse;
11734
11735	// Event type
11736	} else {
11737		this.type = src;
11738	}
11739
11740	// Put explicitly provided properties onto the event object
11741	if ( props ) {
11742		jQuery1113.extend( this, props );
11743	}
11744
11745	// Create a timestamp if incoming event doesn't have one
11746	this.timeStamp = src && src.timeStamp || jQuery1113.now();
11747
11748	// Mark it as fixed
11749	this[ jQuery1113.expando ] = true;
11750};
11751
11752// jQuery1113.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
11753// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
11754jQuery1113.Event.prototype = {
11755	isDefaultPrevented: returnFalse,
11756	isPropagationStopped: returnFalse,
11757	isImmediatePropagationStopped: returnFalse,
11758
11759	preventDefault: function() {
11760		var e = this.originalEvent;
11761
11762		this.isDefaultPrevented = returnTrue;
11763		if ( !e ) {
11764			return;
11765		}
11766
11767		// If preventDefault exists, run it on the original event
11768		if ( e.preventDefault ) {
11769			e.preventDefault();
11770
11771		// Support: IE
11772		// Otherwise set the returnValue property of the original event to false
11773		} else {
11774			e.returnValue = false;
11775		}
11776	},
11777	stopPropagation: function() {
11778		var e = this.originalEvent;
11779
11780		this.isPropagationStopped = returnTrue;
11781		if ( !e ) {
11782			return;
11783		}
11784		// If stopPropagation exists, run it on the original event
11785		if ( e.stopPropagation ) {
11786			e.stopPropagation();
11787		}
11788
11789		// Support: IE
11790		// Set the cancelBubble property of the original event to true
11791		e.cancelBubble = true;
11792	},
11793	stopImmediatePropagation: function() {
11794		var e = this.originalEvent;
11795
11796		this.isImmediatePropagationStopped = returnTrue;
11797
11798		if ( e && e.stopImmediatePropagation ) {
11799			e.stopImmediatePropagation();
11800		}
11801
11802		this.stopPropagation();
11803	}
11804};
11805
11806// Create mouseenter/leave events using mouseover/out and event-time checks
11807jQuery1113.each({
11808	mouseenter: "mouseover",
11809	mouseleave: "mouseout",
11810	pointerenter: "pointerover",
11811	pointerleave: "pointerout"
11812}, function( orig, fix ) {
11813	jQuery1113.event.special[ orig ] = {
11814		delegateType: fix,
11815		bindType: fix,
11816
11817		handle: function( event ) {
11818			var ret,
11819				target = this,
11820				related = event.relatedTarget,
11821				handleObj = event.handleObj;
11822
11823			// For mousenter/leave call the handler if related is outside the target.
11824			// NB: No relatedTarget if the mouse left/entered the browser window
11825			if ( !related || (related !== target && !jQuery1113.contains( target, related )) ) {
11826				event.type = handleObj.origType;
11827				ret = handleObj.handler.apply( this, arguments );
11828				event.type = fix;
11829			}
11830			return ret;
11831		}
11832	};
11833});
11834
11835// IE submit delegation
11836if ( !support.submitBubbles ) {
11837
11838	jQuery1113.event.special.submit = {
11839		setup: function() {
11840			// Only need this for delegated form submit events
11841			if ( jQuery1113.nodeName( this, "form" ) ) {
11842				return false;
11843			}
11844
11845			// Lazy-add a submit handler when a descendant form may potentially be submitted
11846			jQuery1113.event.add( this, "click._submit keypress._submit", function( e ) {
11847				// Node name check avoids a VML-related crash in IE (#9807)
11848				var elem = e.target,
11849					form = jQuery1113.nodeName( elem, "input" ) || jQuery1113.nodeName( elem, "button" ) ? elem.form : undefined;
11850				if ( form && !jQuery1113._data( form, "submitBubbles" ) ) {
11851					jQuery1113.event.add( form, "submit._submit", function( event ) {
11852						event._submit_bubble = true;
11853					});
11854					jQuery1113._data( form, "submitBubbles", true );
11855				}
11856			});
11857			// return undefined since we don't need an event listener
11858		},
11859
11860		postDispatch: function( event ) {
11861			// If form was submitted by the user, bubble the event up the tree
11862			if ( event._submit_bubble ) {
11863				delete event._submit_bubble;
11864				if ( this.parentNode && !event.isTrigger ) {
11865					jQuery1113.event.simulate( "submit", this.parentNode, event, true );
11866				}
11867			}
11868		},
11869
11870		teardown: function() {
11871			// Only need this for delegated form submit events
11872			if ( jQuery1113.nodeName( this, "form" ) ) {
11873				return false;
11874			}
11875
11876			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
11877			jQuery1113.event.remove( this, "._submit" );
11878		}
11879	};
11880}
11881
11882// IE change delegation and checkbox/radio fix
11883if ( !support.changeBubbles ) {
11884
11885	jQuery1113.event.special.change = {
11886
11887		setup: function() {
11888
11889			if ( rformElems.test( this.nodeName ) ) {
11890				// IE doesn't fire change on a check/radio until blur; trigger it on click
11891				// after a propertychange. Eat the blur-change in special.change.handle.
11892				// This still fires onchange a second time for check/radio after blur.
11893				if ( this.type === "checkbox" || this.type === "radio" ) {
11894					jQuery1113.event.add( this, "propertychange._change", function( event ) {
11895						if ( event.originalEvent.propertyName === "checked" ) {
11896							this._just_changed = true;
11897						}
11898					});
11899					jQuery1113.event.add( this, "click._change", function( event ) {
11900						if ( this._just_changed && !event.isTrigger ) {
11901							this._just_changed = false;
11902						}
11903						// Allow triggered, simulated change events (#11500)
11904						jQuery1113.event.simulate( "change", this, event, true );
11905					});
11906				}
11907				return false;
11908			}
11909			// Delegated event; lazy-add a change handler on descendant inputs
11910			jQuery1113.event.add( this, "beforeactivate._change", function( e ) {
11911				var elem = e.target;
11912
11913				if ( rformElems.test( elem.nodeName ) && !jQuery1113._data( elem, "changeBubbles" ) ) {
11914					jQuery1113.event.add( elem, "change._change", function( event ) {
11915						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
11916							jQuery1113.event.simulate( "change", this.parentNode, event, true );
11917						}
11918					});
11919					jQuery1113._data( elem, "changeBubbles", true );
11920				}
11921			});
11922		},
11923
11924		handle: function( event ) {
11925			var elem = event.target;
11926
11927			// Swallow native change events from checkbox/radio, we already triggered them above
11928			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
11929				return event.handleObj.handler.apply( this, arguments );
11930			}
11931		},
11932
11933		teardown: function() {
11934			jQuery1113.event.remove( this, "._change" );
11935
11936			return !rformElems.test( this.nodeName );
11937		}
11938	};
11939}
11940
11941// Create "bubbling" focus and blur events
11942if ( !support.focusinBubbles ) {
11943	jQuery1113.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
11944
11945		// Attach a single capturing handler on the document while someone wants focusin/focusout
11946		var handler = function( event ) {
11947				jQuery1113.event.simulate( fix, event.target, jQuery1113.event.fix( event ), true );
11948			};
11949
11950		jQuery1113.event.special[ fix ] = {
11951			setup: function() {
11952				var doc = this.ownerDocument || this,
11953					attaches = jQuery1113._data( doc, fix );
11954
11955				if ( !attaches ) {
11956					doc.addEventListener( orig, handler, true );
11957				}
11958				jQuery1113._data( doc, fix, ( attaches || 0 ) + 1 );
11959			},
11960			teardown: function() {
11961				var doc = this.ownerDocument || this,
11962					attaches = jQuery1113._data( doc, fix ) - 1;
11963
11964				if ( !attaches ) {
11965					doc.removeEventListener( orig, handler, true );
11966					jQuery1113._removeData( doc, fix );
11967				} else {
11968					jQuery1113._data( doc, fix, attaches );
11969				}
11970			}
11971		};
11972	});
11973}
11974
11975jQuery1113.fn.extend({
11976
11977	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
11978		var type, origFn;
11979
11980		// Types can be a map of types/handlers
11981		if ( typeof types === "object" ) {
11982			// ( types-Object, selector, data )
11983			if ( typeof selector !== "string" ) {
11984				// ( types-Object, data )
11985				data = data || selector;
11986				selector = undefined;
11987			}
11988			for ( type in types ) {
11989				this.on( type, selector, data, types[ type ], one );
11990			}
11991			return this;
11992		}
11993
11994		if ( data == null && fn == null ) {
11995			// ( types, fn )
11996			fn = selector;
11997			data = selector = undefined;
11998		} else if ( fn == null ) {
11999			if ( typeof selector === "string" ) {
12000				// ( types, selector, fn )
12001				fn = data;
12002				data = undefined;
12003			} else {
12004				// ( types, data, fn )
12005				fn = data;
12006				data = selector;
12007				selector = undefined;
12008			}
12009		}
12010		if ( fn === false ) {
12011			fn = returnFalse;
12012		} else if ( !fn ) {
12013			return this;
12014		}
12015
12016		if ( one === 1 ) {
12017			origFn = fn;
12018			fn = function( event ) {
12019				// Can use an empty set, since event contains the info
12020				jQuery1113().off( event );
12021				return origFn.apply( this, arguments );
12022			};
12023			// Use same guid so caller can remove using origFn
12024			fn.guid = origFn.guid || ( origFn.guid = jQuery1113.guid++ );
12025		}
12026		return this.each( function() {
12027			jQuery1113.event.add( this, types, fn, data, selector );
12028		});
12029	},
12030	one: function( types, selector, data, fn ) {
12031		return this.on( types, selector, data, fn, 1 );
12032	},
12033	off: function( types, selector, fn ) {
12034		var handleObj, type;
12035		if ( types && types.preventDefault && types.handleObj ) {
12036			// ( event )  dispatched jQuery1113.Event
12037			handleObj = types.handleObj;
12038			jQuery1113( types.delegateTarget ).off(
12039				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
12040				handleObj.selector,
12041				handleObj.handler
12042			);
12043			return this;
12044		}
12045		if ( typeof types === "object" ) {
12046			// ( types-object [, selector] )
12047			for ( type in types ) {
12048				this.off( type, selector, types[ type ] );
12049			}
12050			return this;
12051		}
12052		if ( selector === false || typeof selector === "function" ) {
12053			// ( types [, fn] )
12054			fn = selector;
12055			selector = undefined;
12056		}
12057		if ( fn === false ) {
12058			fn = returnFalse;
12059		}
12060		return this.each(function() {
12061			jQuery1113.event.remove( this, types, fn, selector );
12062		});
12063	},
12064
12065	trigger: function( type, data ) {
12066		return this.each(function() {
12067			jQuery1113.event.trigger( type, data, this );
12068		});
12069	},
12070	triggerHandler: function( type, data ) {
12071		var elem = this[0];
12072		if ( elem ) {
12073			return jQuery1113.event.trigger( type, data, elem, true );
12074		}
12075	}
12076});
12077
12078
12079function createSafeFragment( document ) {
12080	var list = nodeNames.split( "|" ),
12081		safeFrag = document.createDocumentFragment();
12082
12083	if ( safeFrag.createElement ) {
12084		while ( list.length ) {
12085			safeFrag.createElement(
12086				list.pop()
12087			);
12088		}
12089	}
12090	return safeFrag;
12091}
12092
12093var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
12094		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
12095	rinlinejQuery1113 = / jQuery1113\d+="(?:null|\d+)"/g,
12096	rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
12097	rleadingWhitespace = /^\s+/,
12098	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
12099	rtagName = /<([\w:]+)/,
12100	rtbody = /<tbody/i,
12101	rhtml = /<|&#?\w+;/,
12102	rnoInnerhtml = /<(?:script|style|link)/i,
12103	// checked="checked" or checked
12104	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
12105	rscriptType = /^$|\/(?:java|ecma)script/i,
12106	rscriptTypeMasked = /^true\/(.*)/,
12107	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
12108
12109	// We have to close these tags to support XHTML (#13200)
12110	wrapMap = {
12111		option: [ 1, "<select multiple='multiple'>", "</select>" ],
12112		legend: [ 1, "<fieldset>", "</fieldset>" ],
12113		area: [ 1, "<map>", "</map>" ],
12114		param: [ 1, "<object>", "</object>" ],
12115		thead: [ 1, "<table>", "</table>" ],
12116		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
12117		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
12118		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
12119
12120		// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
12121		// unless wrapped in a div with non-breaking characters in front of it.
12122		_default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>"  ]
12123	},
12124	safeFragment = createSafeFragment( document ),
12125	fragmentDiv = safeFragment.appendChild( document.createElement("div") );
12126
12127wrapMap.optgroup = wrapMap.option;
12128wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
12129wrapMap.th = wrapMap.td;
12130
12131function getAll( context, tag ) {
12132	var elems, elem,
12133		i = 0,
12134		found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
12135			typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
12136			undefined;
12137
12138	if ( !found ) {
12139		for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
12140			if ( !tag || jQuery1113.nodeName( elem, tag ) ) {
12141				found.push( elem );
12142			} else {
12143				jQuery1113.merge( found, getAll( elem, tag ) );
12144			}
12145		}
12146	}
12147
12148	return tag === undefined || tag && jQuery1113.nodeName( context, tag ) ?
12149		jQuery1113.merge( [ context ], found ) :
12150		found;
12151}
12152
12153// Used in buildFragment, fixes the defaultChecked property
12154function fixDefaultChecked( elem ) {
12155	if ( rcheckableType.test( elem.type ) ) {
12156		elem.defaultChecked = elem.checked;
12157	}
12158}
12159
12160// Support: IE<8
12161// Manipulating tables requires a tbody
12162function manipulationTarget( elem, content ) {
12163	return jQuery1113.nodeName( elem, "table" ) &&
12164		jQuery1113.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
12165
12166		elem.getElementsByTagName("tbody")[0] ||
12167			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
12168		elem;
12169}
12170
12171// Replace/restore the type attribute of script elements for safe DOM manipulation
12172function disableScript( elem ) {
12173	elem.type = (jQuery1113.find.attr( elem, "type" ) !== null) + "/" + elem.type;
12174	return elem;
12175}
12176function restoreScript( elem ) {
12177	var match = rscriptTypeMasked.exec( elem.type );
12178	if ( match ) {
12179		elem.type = match[1];
12180	} else {
12181		elem.removeAttribute("type");
12182	}
12183	return elem;
12184}
12185
12186// Mark scripts as having already been evaluated
12187function setGlobalEval( elems, refElements ) {
12188	var elem,
12189		i = 0;
12190	for ( ; (elem = elems[i]) != null; i++ ) {
12191		jQuery1113._data( elem, "globalEval", !refElements || jQuery1113._data( refElements[i], "globalEval" ) );
12192	}
12193}
12194
12195function cloneCopyEvent( src, dest ) {
12196
12197	if ( dest.nodeType !== 1 || !jQuery1113.hasData( src ) ) {
12198		return;
12199	}
12200
12201	var type, i, l,
12202		oldData = jQuery1113._data( src ),
12203		curData = jQuery1113._data( dest, oldData ),
12204		events = oldData.events;
12205
12206	if ( events ) {
12207		delete curData.handle;
12208		curData.events = {};
12209
12210		for ( type in events ) {
12211			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
12212				jQuery1113.event.add( dest, type, events[ type ][ i ] );
12213			}
12214		}
12215	}
12216
12217	// make the cloned public data object a copy from the original
12218	if ( curData.data ) {
12219		curData.data = jQuery1113.extend( {}, curData.data );
12220	}
12221}
12222
12223function fixCloneNodeIssues( src, dest ) {
12224	var nodeName, e, data;
12225
12226	// We do not need to do anything for non-Elements
12227	if ( dest.nodeType !== 1 ) {
12228		return;
12229	}
12230
12231	nodeName = dest.nodeName.toLowerCase();
12232
12233	// IE6-8 copies events bound via attachEvent when using cloneNode.
12234	if ( !support.noCloneEvent && dest[ jQuery1113.expando ] ) {
12235		data = jQuery1113._data( dest );
12236
12237		for ( e in data.events ) {
12238			jQuery1113.removeEvent( dest, e, data.handle );
12239		}
12240
12241		// Event data gets referenced instead of copied if the expando gets copied too
12242		dest.removeAttribute( jQuery1113.expando );
12243	}
12244
12245	// IE blanks contents when cloning scripts, and tries to evaluate newly-set text
12246	if ( nodeName === "script" && dest.text !== src.text ) {
12247		disableScript( dest ).text = src.text;
12248		restoreScript( dest );
12249
12250	// IE6-10 improperly clones children of object elements using classid.
12251	// IE10 throws NoModificationAllowedError if parent is null, #12132.
12252	} else if ( nodeName === "object" ) {
12253		if ( dest.parentNode ) {
12254			dest.outerHTML = src.outerHTML;
12255		}
12256
12257		// This path appears unavoidable for IE9. When cloning an object
12258		// element in IE9, the outerHTML strategy above is not sufficient.
12259		// If the src has innerHTML and the destination does not,
12260		// copy the src.innerHTML into the dest.innerHTML. #10324
12261		if ( support.html5Clone && ( src.innerHTML && !jQuery1113.trim(dest.innerHTML) ) ) {
12262			dest.innerHTML = src.innerHTML;
12263		}
12264
12265	} else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
12266		// IE6-8 fails to persist the checked state of a cloned checkbox
12267		// or radio button. Worse, IE6-7 fail to give the cloned element
12268		// a checked appearance if the defaultChecked value isn't also set
12269
12270		dest.defaultChecked = dest.checked = src.checked;
12271
12272		// IE6-7 get confused and end up setting the value of a cloned
12273		// checkbox/radio button to an empty string instead of "on"
12274		if ( dest.value !== src.value ) {
12275			dest.value = src.value;
12276		}
12277
12278	// IE6-8 fails to return the selected option to the default selected
12279	// state when cloning options
12280	} else if ( nodeName === "option" ) {
12281		dest.defaultSelected = dest.selected = src.defaultSelected;
12282
12283	// IE6-8 fails to set the defaultValue to the correct value when
12284	// cloning other types of input fields
12285	} else if ( nodeName === "input" || nodeName === "textarea" ) {
12286		dest.defaultValue = src.defaultValue;
12287	}
12288}
12289
12290jQuery1113.extend({
12291	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
12292		var destElements, node, clone, i, srcElements,
12293			inPage = jQuery1113.contains( elem.ownerDocument, elem );
12294
12295		if ( support.html5Clone || jQuery1113.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
12296			clone = elem.cloneNode( true );
12297
12298		// IE<=8 does not properly clone detached, unknown element nodes
12299		} else {
12300			fragmentDiv.innerHTML = elem.outerHTML;
12301			fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
12302		}
12303
12304		if ( (!support.noCloneEvent || !support.noCloneChecked) &&
12305				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery1113.isXMLDoc(elem) ) {
12306
12307			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
12308			destElements = getAll( clone );
12309			srcElements = getAll( elem );
12310
12311			// Fix all IE cloning issues
12312			for ( i = 0; (node = srcElements[i]) != null; ++i ) {
12313				// Ensure that the destination node is not null; Fixes #9587
12314				if ( destElements[i] ) {
12315					fixCloneNodeIssues( node, destElements[i] );
12316				}
12317			}
12318		}
12319
12320		// Copy the events from the original to the clone
12321		if ( dataAndEvents ) {
12322			if ( deepDataAndEvents ) {
12323				srcElements = srcElements || getAll( elem );
12324				destElements = destElements || getAll( clone );
12325
12326				for ( i = 0; (node = srcElements[i]) != null; i++ ) {
12327					cloneCopyEvent( node, destElements[i] );
12328				}
12329			} else {
12330				cloneCopyEvent( elem, clone );
12331			}
12332		}
12333
12334		// Preserve script evaluation history
12335		destElements = getAll( clone, "script" );
12336		if ( destElements.length > 0 ) {
12337			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
12338		}
12339
12340		destElements = srcElements = node = null;
12341
12342		// Return the cloned set
12343		return clone;
12344	},
12345
12346	buildFragment: function( elems, context, scripts, selection ) {
12347		var j, elem, contains,
12348			tmp, tag, tbody, wrap,
12349			l = elems.length,
12350
12351			// Ensure a safe fragment
12352			safe = createSafeFragment( context ),
12353
12354			nodes = [],
12355			i = 0;
12356
12357		for ( ; i < l; i++ ) {
12358			elem = elems[ i ];
12359
12360			if ( elem || elem === 0 ) {
12361
12362				// Add nodes directly
12363				if ( jQuery1113.type( elem ) === "object" ) {
12364					jQuery1113.merge( nodes, elem.nodeType ? [ elem ] : elem );
12365
12366				// Convert non-html into a text node
12367				} else if ( !rhtml.test( elem ) ) {
12368					nodes.push( context.createTextNode( elem ) );
12369
12370				// Convert html into DOM nodes
12371				} else {
12372					tmp = tmp || safe.appendChild( context.createElement("div") );
12373
12374					// Deserialize a standard representation
12375					tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
12376					wrap = wrapMap[ tag ] || wrapMap._default;
12377
12378					tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
12379
12380					// Descend through wrappers to the right content
12381					j = wrap[0];
12382					while ( j-- ) {
12383						tmp = tmp.lastChild;
12384					}
12385
12386					// Manually add leading whitespace removed by IE
12387					if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
12388						nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
12389					}
12390
12391					// Remove IE's autoinserted <tbody> from table fragments
12392					if ( !support.tbody ) {
12393
12394						// String was a <table>, *may* have spurious <tbody>
12395						elem = tag === "table" && !rtbody.test( elem ) ?
12396							tmp.firstChild :
12397
12398							// String was a bare <thead> or <tfoot>
12399							wrap[1] === "<table>" && !rtbody.test( elem ) ?
12400								tmp :
12401								0;
12402
12403						j = elem && elem.childNodes.length;
12404						while ( j-- ) {
12405							if ( jQuery1113.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
12406								elem.removeChild( tbody );
12407							}
12408						}
12409					}
12410
12411					jQuery1113.merge( nodes, tmp.childNodes );
12412
12413					// Fix #12392 for WebKit and IE > 9
12414					tmp.textContent = "";
12415
12416					// Fix #12392 for oldIE
12417					while ( tmp.firstChild ) {
12418						tmp.removeChild( tmp.firstChild );
12419					}
12420
12421					// Remember the top-level container for proper cleanup
12422					tmp = safe.lastChild;
12423				}
12424			}
12425		}
12426
12427		// Fix #11356: Clear elements from fragment
12428		if ( tmp ) {
12429			safe.removeChild( tmp );
12430		}
12431
12432		// Reset defaultChecked for any radios and checkboxes
12433		// about to be appended to the DOM in IE 6/7 (#8060)
12434		if ( !support.appendChecked ) {
12435			jQuery1113.grep( getAll( nodes, "input" ), fixDefaultChecked );
12436		}
12437
12438		i = 0;
12439		while ( (elem = nodes[ i++ ]) ) {
12440
12441			// #4087 - If origin and destination elements are the same, and this is
12442			// that element, do not do anything
12443			if ( selection && jQuery1113.inArray( elem, selection ) !== -1 ) {
12444				continue;
12445			}
12446
12447			contains = jQuery1113.contains( elem.ownerDocument, elem );
12448
12449			// Append to fragment
12450			tmp = getAll( safe.appendChild( elem ), "script" );
12451
12452			// Preserve script evaluation history
12453			if ( contains ) {
12454				setGlobalEval( tmp );
12455			}
12456
12457			// Capture executables
12458			if ( scripts ) {
12459				j = 0;
12460				while ( (elem = tmp[ j++ ]) ) {
12461					if ( rscriptType.test( elem.type || "" ) ) {
12462						scripts.push( elem );
12463					}
12464				}
12465			}
12466		}
12467
12468		tmp = null;
12469
12470		return safe;
12471	},
12472
12473	cleanData: function( elems, /* internal */ acceptData ) {
12474		var elem, type, id, data,
12475			i = 0,
12476			internalKey = jQuery1113.expando,
12477			cache = jQuery1113.cache,
12478			deleteExpando = support.deleteExpando,
12479			special = jQuery1113.event.special;
12480
12481		for ( ; (elem = elems[i]) != null; i++ ) {
12482			if ( acceptData || jQuery1113.acceptData( elem ) ) {
12483
12484				id = elem[ internalKey ];
12485				data = id && cache[ id ];
12486
12487				if ( data ) {
12488					if ( data.events ) {
12489						for ( type in data.events ) {
12490							if ( special[ type ] ) {
12491								jQuery1113.event.remove( elem, type );
12492
12493							// This is a shortcut to avoid jQuery1113.event.remove's overhead
12494							} else {
12495								jQuery1113.removeEvent( elem, type, data.handle );
12496							}
12497						}
12498					}
12499
12500					// Remove cache only if it was not already removed by jQuery1113.event.remove
12501					if ( cache[ id ] ) {
12502
12503						delete cache[ id ];
12504
12505						// IE does not allow us to delete expando properties from nodes,
12506						// nor does it have a removeAttribute function on Document nodes;
12507						// we must handle all of these cases
12508						if ( deleteExpando ) {
12509							delete elem[ internalKey ];
12510
12511						} else if ( typeof elem.removeAttribute !== strundefined ) {
12512							elem.removeAttribute( internalKey );
12513
12514						} else {
12515							elem[ internalKey ] = null;
12516						}
12517
12518						deletedIds.push( id );
12519					}
12520				}
12521			}
12522		}
12523	}
12524});
12525
12526jQuery1113.fn.extend({
12527	text: function( value ) {
12528		return access( this, function( value ) {
12529			return value === undefined ?
12530				jQuery1113.text( this ) :
12531				this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
12532		}, null, value, arguments.length );
12533	},
12534
12535	append: function() {
12536		return this.domManip( arguments, function( elem ) {
12537			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
12538				var target = manipulationTarget( this, elem );
12539				target.appendChild( elem );
12540			}
12541		});
12542	},
12543
12544	prepend: function() {
12545		return this.domManip( arguments, function( elem ) {
12546			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
12547				var target = manipulationTarget( this, elem );
12548				target.insertBefore( elem, target.firstChild );
12549			}
12550		});
12551	},
12552
12553	before: function() {
12554		return this.domManip( arguments, function( elem ) {
12555			if ( this.parentNode ) {
12556				this.parentNode.insertBefore( elem, this );
12557			}
12558		});
12559	},
12560
12561	after: function() {
12562		return this.domManip( arguments, function( elem ) {
12563			if ( this.parentNode ) {
12564				this.parentNode.insertBefore( elem, this.nextSibling );
12565			}
12566		});
12567	},
12568
12569	remove: function( selector, keepData /* Internal Use Only */ ) {
12570		var elem,
12571			elems = selector ? jQuery1113.filter( selector, this ) : this,
12572			i = 0;
12573
12574		for ( ; (elem = elems[i]) != null; i++ ) {
12575
12576			if ( !keepData && elem.nodeType === 1 ) {
12577				jQuery1113.cleanData( getAll( elem ) );
12578			}
12579
12580			if ( elem.parentNode ) {
12581				if ( keepData && jQuery1113.contains( elem.ownerDocument, elem ) ) {
12582					setGlobalEval( getAll( elem, "script" ) );
12583				}
12584				elem.parentNode.removeChild( elem );
12585			}
12586		}
12587
12588		return this;
12589	},
12590
12591	empty: function() {
12592		var elem,
12593			i = 0;
12594
12595		for ( ; (elem = this[i]) != null; i++ ) {
12596			// Remove element nodes and prevent memory leaks
12597			if ( elem.nodeType === 1 ) {
12598				jQuery1113.cleanData( getAll( elem, false ) );
12599			}
12600
12601			// Remove any remaining nodes
12602			while ( elem.firstChild ) {
12603				elem.removeChild( elem.firstChild );
12604			}
12605
12606			// If this is a select, ensure that it displays empty (#12336)
12607			// Support: IE<9
12608			if ( elem.options && jQuery1113.nodeName( elem, "select" ) ) {
12609				elem.options.length = 0;
12610			}
12611		}
12612
12613		return this;
12614	},
12615
12616	clone: function( dataAndEvents, deepDataAndEvents ) {
12617		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
12618		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
12619
12620		return this.map(function() {
12621			return jQuery1113.clone( this, dataAndEvents, deepDataAndEvents );
12622		});
12623	},
12624
12625	html: function( value ) {
12626		return access( this, function( value ) {
12627			var elem = this[ 0 ] || {},
12628				i = 0,
12629				l = this.length;
12630
12631			if ( value === undefined ) {
12632				return elem.nodeType === 1 ?
12633					elem.innerHTML.replace( rinlinejQuery1113, "" ) :
12634					undefined;
12635			}
12636
12637			// See if we can take a shortcut and just use innerHTML
12638			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
12639				( support.htmlSerialize || !rnoshimcache.test( value )  ) &&
12640				( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
12641				!wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
12642
12643				value = value.replace( rxhtmlTag, "<$1></$2>" );
12644
12645				try {
12646					for (; i < l; i++ ) {
12647						// Remove element nodes and prevent memory leaks
12648						elem = this[i] || {};
12649						if ( elem.nodeType === 1 ) {
12650							jQuery1113.cleanData( getAll( elem, false ) );
12651							elem.innerHTML = value;
12652						}
12653					}
12654
12655					elem = 0;
12656
12657				// If using innerHTML throws an exception, use the fallback method
12658				} catch(e) {}
12659			}
12660
12661			if ( elem ) {
12662				this.empty().append( value );
12663			}
12664		}, null, value, arguments.length );
12665	},
12666
12667	replaceWith: function() {
12668		var arg = arguments[ 0 ];
12669
12670		// Make the changes, replacing each context element with the new content
12671		this.domManip( arguments, function( elem ) {
12672			arg = this.parentNode;
12673
12674			jQuery1113.cleanData( getAll( this ) );
12675
12676			if ( arg ) {
12677				arg.replaceChild( elem, this );
12678			}
12679		});
12680
12681		// Force removal if there was no new content (e.g., from empty arguments)
12682		return arg && (arg.length || arg.nodeType) ? this : this.remove();
12683	},
12684
12685	detach: function( selector ) {
12686		return this.remove( selector, true );
12687	},
12688
12689	domManip: function( args, callback ) {
12690
12691		// Flatten any nested arrays
12692		args = concat.apply( [], args );
12693
12694		var first, node, hasScripts,
12695			scripts, doc, fragment,
12696			i = 0,
12697			l = this.length,
12698			set = this,
12699			iNoClone = l - 1,
12700			value = args[0],
12701			isFunction = jQuery1113.isFunction( value );
12702
12703		// We can't cloneNode fragments that contain checked, in WebKit
12704		if ( isFunction ||
12705				( l > 1 && typeof value === "string" &&
12706					!support.checkClone && rchecked.test( value ) ) ) {
12707			return this.each(function( index ) {
12708				var self = set.eq( index );
12709				if ( isFunction ) {
12710					args[0] = value.call( this, index, self.html() );
12711				}
12712				self.domManip( args, callback );
12713			});
12714		}
12715
12716		if ( l ) {
12717			fragment = jQuery1113.buildFragment( args, this[ 0 ].ownerDocument, false, this );
12718			first = fragment.firstChild;
12719
12720			if ( fragment.childNodes.length === 1 ) {
12721				fragment = first;
12722			}
12723
12724			if ( first ) {
12725				scripts = jQuery1113.map( getAll( fragment, "script" ), disableScript );
12726				hasScripts = scripts.length;
12727
12728				// Use the original fragment for the last item instead of the first because it can end up
12729				// being emptied incorrectly in certain situations (#8070).
12730				for ( ; i < l; i++ ) {
12731					node = fragment;
12732
12733					if ( i !== iNoClone ) {
12734						node = jQuery1113.clone( node, true, true );
12735
12736						// Keep references to cloned scripts for later restoration
12737						if ( hasScripts ) {
12738							jQuery1113.merge( scripts, getAll( node, "script" ) );
12739						}
12740					}
12741
12742					callback.call( this[i], node, i );
12743				}
12744
12745				if ( hasScripts ) {
12746					doc = scripts[ scripts.length - 1 ].ownerDocument;
12747
12748					// Reenable scripts
12749					jQuery1113.map( scripts, restoreScript );
12750
12751					// Evaluate executable scripts on first document insertion
12752					for ( i = 0; i < hasScripts; i++ ) {
12753						node = scripts[ i ];
12754						if ( rscriptType.test( node.type || "" ) &&
12755							!jQuery1113._data( node, "globalEval" ) && jQuery1113.contains( doc, node ) ) {
12756
12757							if ( node.src ) {
12758								// Optional AJAX dependency, but won't run scripts if not present
12759								if ( jQuery1113._evalUrl ) {
12760									jQuery1113._evalUrl( node.src );
12761								}
12762							} else {
12763								jQuery1113.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
12764							}
12765						}
12766					}
12767				}
12768
12769				// Fix #11809: Avoid leaking memory
12770				fragment = first = null;
12771			}
12772		}
12773
12774		return this;
12775	}
12776});
12777
12778jQuery1113.each({
12779	appendTo: "append",
12780	prependTo: "prepend",
12781	insertBefore: "before",
12782	insertAfter: "after",
12783	replaceAll: "replaceWith"
12784}, function( name, original ) {
12785	jQuery1113.fn[ name ] = function( selector ) {
12786		var elems,
12787			i = 0,
12788			ret = [],
12789			insert = jQuery1113( selector ),
12790			last = insert.length - 1;
12791
12792		for ( ; i <= last; i++ ) {
12793			elems = i === last ? this : this.clone(true);
12794			jQuery1113( insert[i] )[ original ]( elems );
12795
12796			// Modern browsers can apply jQuery1113 collections as arrays, but oldIE needs a .get()
12797			push.apply( ret, elems.get() );
12798		}
12799
12800		return this.pushStack( ret );
12801	};
12802});
12803
12804
12805var iframe,
12806	elemdisplay = {};
12807
12808/**
12809 * Retrieve the actual display of a element
12810 * @param {String} name nodeName of the element
12811 * @param {Object} doc Document object
12812 */
12813// Called only from within defaultDisplay
12814function actualDisplay( name, doc ) {
12815	var style,
12816		elem = jQuery1113( doc.createElement( name ) ).appendTo( doc.body ),
12817
12818		// getDefaultComputedStyle might be reliably used only on attached element
12819		display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
12820
12821			// Use of this method is a temporary fix (more like optmization) until something better comes along,
12822			// since it was removed from specification and supported only in FF
12823			style.display : jQuery1113.css( elem[ 0 ], "display" );
12824
12825	// We don't have any data stored on the element,
12826	// so use "detach" method as fast way to get rid of the element
12827	elem.detach();
12828
12829	return display;
12830}
12831
12832/**
12833 * Try to determine the default display value of an element
12834 * @param {String} nodeName
12835 */
12836function defaultDisplay( nodeName ) {
12837	var doc = document,
12838		display = elemdisplay[ nodeName ];
12839
12840	if ( !display ) {
12841		display = actualDisplay( nodeName, doc );
12842
12843		// If the simple way fails, read from inside an iframe
12844		if ( display === "none" || !display ) {
12845
12846			// Use the already-created iframe if possible
12847			iframe = (iframe || jQuery1113( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
12848
12849			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
12850			doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
12851
12852			// Support: IE
12853			doc.write();
12854			doc.close();
12855
12856			display = actualDisplay( nodeName, doc );
12857			iframe.detach();
12858		}
12859
12860		// Store the correct default display
12861		elemdisplay[ nodeName ] = display;
12862	}
12863
12864	return display;
12865}
12866
12867
12868(function() {
12869	var shrinkWrapBlocksVal;
12870
12871	support.shrinkWrapBlocks = function() {
12872		if ( shrinkWrapBlocksVal != null ) {
12873			return shrinkWrapBlocksVal;
12874		}
12875
12876		// Will be changed later if needed.
12877		shrinkWrapBlocksVal = false;
12878
12879		// Minified: var b,c,d
12880		var div, body, container;
12881
12882		body = document.getElementsByTagName( "body" )[ 0 ];
12883		if ( !body || !body.style ) {
12884			// Test fired too early or in an unsupported environment, exit.
12885			return;
12886		}
12887
12888		// Setup
12889		div = document.createElement( "div" );
12890		container = document.createElement( "div" );
12891		container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
12892		body.appendChild( container ).appendChild( div );
12893
12894		// Support: IE6
12895		// Check if elements with layout shrink-wrap their children
12896		if ( typeof div.style.zoom !== strundefined ) {
12897			// Reset CSS: box-sizing; display; margin; border
12898			div.style.cssText =
12899				// Support: Firefox<29, Android 2.3
12900				// Vendor-prefix box-sizing
12901				"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
12902				"box-sizing:content-box;display:block;margin:0;border:0;" +
12903				"padding:1px;width:1px;zoom:1";
12904			div.appendChild( document.createElement( "div" ) ).style.width = "5px";
12905			shrinkWrapBlocksVal = div.offsetWidth !== 3;
12906		}
12907
12908		body.removeChild( container );
12909
12910		return shrinkWrapBlocksVal;
12911	};
12912
12913})();
12914var rmargin = (/^margin/);
12915
12916var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
12917
12918
12919
12920var getStyles, curCSS,
12921	rposition = /^(top|right|bottom|left)$/;
12922
12923if ( window.getComputedStyle ) {
12924	getStyles = function( elem ) {
12925		// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
12926		// IE throws on elements created in popups
12927		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
12928		if ( elem.ownerDocument.defaultView.opener ) {
12929			return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
12930		}
12931
12932		return window.getComputedStyle( elem, null );
12933	};
12934
12935	curCSS = function( elem, name, computed ) {
12936		var width, minWidth, maxWidth, ret,
12937			style = elem.style;
12938
12939		computed = computed || getStyles( elem );
12940
12941		// getPropertyValue is only needed for .css('filter') in IE9, see #12537
12942		ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
12943
12944		if ( computed ) {
12945
12946			if ( ret === "" && !jQuery1113.contains( elem.ownerDocument, elem ) ) {
12947				ret = jQuery1113.style( elem, name );
12948			}
12949
12950			// A tribute to the "awesome hack by Dean Edwards"
12951			// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
12952			// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
12953			// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
12954			if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
12955
12956				// Remember the original values
12957				width = style.width;
12958				minWidth = style.minWidth;
12959				maxWidth = style.maxWidth;
12960
12961				// Put in the new values to get a computed value out
12962				style.minWidth = style.maxWidth = style.width = ret;
12963				ret = computed.width;
12964
12965				// Revert the changed values
12966				style.width = width;
12967				style.minWidth = minWidth;
12968				style.maxWidth = maxWidth;
12969			}
12970		}
12971
12972		// Support: IE
12973		// IE returns zIndex value as an integer.
12974		return ret === undefined ?
12975			ret :
12976			ret + "";
12977	};
12978} else if ( document.documentElement.currentStyle ) {
12979	getStyles = function( elem ) {
12980		return elem.currentStyle;
12981	};
12982
12983	curCSS = function( elem, name, computed ) {
12984		var left, rs, rsLeft, ret,
12985			style = elem.style;
12986
12987		computed = computed || getStyles( elem );
12988		ret = computed ? computed[ name ] : undefined;
12989
12990		// Avoid setting ret to empty string here
12991		// so we don't default to auto
12992		if ( ret == null && style && style[ name ] ) {
12993			ret = style[ name ];
12994		}
12995
12996		// From the awesome hack by Dean Edwards
12997		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
12998
12999		// If we're not dealing with a regular pixel number
13000		// but a number that has a weird ending, we need to convert it to pixels
13001		// but not position css attributes, as those are proportional to the parent element instead
13002		// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
13003		if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
13004
13005			// Remember the original values
13006			left = style.left;
13007			rs = elem.runtimeStyle;
13008			rsLeft = rs && rs.left;
13009
13010			// Put in the new values to get a computed value out
13011			if ( rsLeft ) {
13012				rs.left = elem.currentStyle.left;
13013			}
13014			style.left = name === "fontSize" ? "1em" : ret;
13015			ret = style.pixelLeft + "px";
13016
13017			// Revert the changed values
13018			style.left = left;
13019			if ( rsLeft ) {
13020				rs.left = rsLeft;
13021			}
13022		}
13023
13024		// Support: IE
13025		// IE returns zIndex value as an integer.
13026		return ret === undefined ?
13027			ret :
13028			ret + "" || "auto";
13029	};
13030}
13031
13032
13033
13034
13035function addGetHookIf( conditionFn, hookFn ) {
13036	// Define the hook, we'll check on the first run if it's really needed.
13037	return {
13038		get: function() {
13039			var condition = conditionFn();
13040
13041			if ( condition == null ) {
13042				// The test was not ready at this point; screw the hook this time
13043				// but check again when needed next time.
13044				return;
13045			}
13046
13047			if ( condition ) {
13048				// Hook not needed (or it's not possible to use it due to missing dependency),
13049				// remove it.
13050				// Since there are no other hooks for marginRight, remove the whole object.
13051				delete this.get;
13052				return;
13053			}
13054
13055			// Hook needed; redefine it so that the support test is not executed again.
13056
13057			return (this.get = hookFn).apply( this, arguments );
13058		}
13059	};
13060}
13061
13062
13063(function() {
13064	// Minified: var b,c,d,e,f,g, h,i
13065	var div, style, a, pixelPositionVal, boxSizingReliableVal,
13066		reliableHiddenOffsetsVal, reliableMarginRightVal;
13067
13068	// Setup
13069	div = document.createElement( "div" );
13070	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
13071	a = div.getElementsByTagName( "a" )[ 0 ];
13072	style = a && a.style;
13073
13074	// Finish early in limited (non-browser) environments
13075	if ( !style ) {
13076		return;
13077	}
13078
13079	style.cssText = "float:left;opacity:.5";
13080
13081	// Support: IE<9
13082	// Make sure that element opacity exists (as opposed to filter)
13083	support.opacity = style.opacity === "0.5";
13084
13085	// Verify style float existence
13086	// (IE uses styleFloat instead of cssFloat)
13087	support.cssFloat = !!style.cssFloat;
13088
13089	div.style.backgroundClip = "content-box";
13090	div.cloneNode( true ).style.backgroundClip = "";
13091	support.clearCloneStyle = div.style.backgroundClip === "content-box";
13092
13093	// Support: Firefox<29, Android 2.3
13094	// Vendor-prefix box-sizing
13095	support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
13096		style.WebkitBoxSizing === "";
13097
13098	jQuery1113.extend(support, {
13099		reliableHiddenOffsets: function() {
13100			if ( reliableHiddenOffsetsVal == null ) {
13101				computeStyleTests();
13102			}
13103			return reliableHiddenOffsetsVal;
13104		},
13105
13106		boxSizingReliable: function() {
13107			if ( boxSizingReliableVal == null ) {
13108				computeStyleTests();
13109			}
13110			return boxSizingReliableVal;
13111		},
13112
13113		pixelPosition: function() {
13114			if ( pixelPositionVal == null ) {
13115				computeStyleTests();
13116			}
13117			return pixelPositionVal;
13118		},
13119
13120		// Support: Android 2.3
13121		reliableMarginRight: function() {
13122			if ( reliableMarginRightVal == null ) {
13123				computeStyleTests();
13124			}
13125			return reliableMarginRightVal;
13126		}
13127	});
13128
13129	function computeStyleTests() {
13130		// Minified: var b,c,d,j
13131		var div, body, container, contents;
13132
13133		body = document.getElementsByTagName( "body" )[ 0 ];
13134		if ( !body || !body.style ) {
13135			// Test fired too early or in an unsupported environment, exit.
13136			return;
13137		}
13138
13139		// Setup
13140		div = document.createElement( "div" );
13141		container = document.createElement( "div" );
13142		container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
13143		body.appendChild( container ).appendChild( div );
13144
13145		div.style.cssText =
13146			// Support: Firefox<29, Android 2.3
13147			// Vendor-prefix box-sizing
13148			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
13149			"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
13150			"border:1px;padding:1px;width:4px;position:absolute";
13151
13152		// Support: IE<9
13153		// Assume reasonable values in the absence of getComputedStyle
13154		pixelPositionVal = boxSizingReliableVal = false;
13155		reliableMarginRightVal = true;
13156
13157		// Check for getComputedStyle so that this code is not run in IE<9.
13158		if ( window.getComputedStyle ) {
13159			pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
13160			boxSizingReliableVal =
13161				( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
13162
13163			// Support: Android 2.3
13164			// Div with explicit width and no margin-right incorrectly
13165			// gets computed margin-right based on width of container (#3333)
13166			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
13167			contents = div.appendChild( document.createElement( "div" ) );
13168
13169			// Reset CSS: box-sizing; display; margin; border; padding
13170			contents.style.cssText = div.style.cssText =
13171				// Support: Firefox<29, Android 2.3
13172				// Vendor-prefix box-sizing
13173				"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
13174				"box-sizing:content-box;display:block;margin:0;border:0;padding:0";
13175			contents.style.marginRight = contents.style.width = "0";
13176			div.style.width = "1px";
13177
13178			reliableMarginRightVal =
13179				!parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
13180
13181			div.removeChild( contents );
13182		}
13183
13184		// Support: IE8
13185		// Check if table cells still have offsetWidth/Height when they are set
13186		// to display:none and there are still other visible table cells in a
13187		// table row; if so, offsetWidth/Height are not reliable for use when
13188		// determining if an element has been hidden directly using
13189		// display:none (it is still safe to use offsets if a parent element is
13190		// hidden; don safety goggles and see bug #4512 for more information).
13191		div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
13192		contents = div.getElementsByTagName( "td" );
13193		contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
13194		reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
13195		if ( reliableHiddenOffsetsVal ) {
13196			contents[ 0 ].style.display = "";
13197			contents[ 1 ].style.display = "none";
13198			reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
13199		}
13200
13201		body.removeChild( container );
13202	}
13203
13204})();
13205
13206
13207// A method for quickly swapping in/out CSS properties to get correct calculations.
13208jQuery1113.swap = function( elem, options, callback, args ) {
13209	var ret, name,
13210		old = {};
13211
13212	// Remember the old values, and insert the new ones
13213	for ( name in options ) {
13214		old[ name ] = elem.style[ name ];
13215		elem.style[ name ] = options[ name ];
13216	}
13217
13218	ret = callback.apply( elem, args || [] );
13219
13220	// Revert the old values
13221	for ( name in options ) {
13222		elem.style[ name ] = old[ name ];
13223	}
13224
13225	return ret;
13226};
13227
13228
13229var
13230		ralpha = /alpha\([^)]*\)/i,
13231	ropacity = /opacity\s*=\s*([^)]*)/,
13232
13233	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
13234	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
13235	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
13236	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
13237	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
13238
13239	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
13240	cssNormalTransform = {
13241		letterSpacing: "0",
13242		fontWeight: "400"
13243	},
13244
13245	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
13246
13247
13248// return a css property mapped to a potentially vendor prefixed property
13249function vendorPropName( style, name ) {
13250
13251	// shortcut for names that are not vendor prefixed
13252	if ( name in style ) {
13253		return name;
13254	}
13255
13256	// check for vendor prefixed names
13257	var capName = name.charAt(0).toUpperCase() + name.slice(1),
13258		origName = name,
13259		i = cssPrefixes.length;
13260
13261	while ( i-- ) {
13262		name = cssPrefixes[ i ] + capName;
13263		if ( name in style ) {
13264			return name;
13265		}
13266	}
13267
13268	return origName;
13269}
13270
13271function showHide( elements, show ) {
13272	var display, elem, hidden,
13273		values = [],
13274		index = 0,
13275		length = elements.length;
13276
13277	for ( ; index < length; index++ ) {
13278		elem = elements[ index ];
13279		if ( !elem.style ) {
13280			continue;
13281		}
13282
13283		values[ index ] = jQuery1113._data( elem, "olddisplay" );
13284		display = elem.style.display;
13285		if ( show ) {
13286			// Reset the inline display of this element to learn if it is
13287			// being hidden by cascaded rules or not
13288			if ( !values[ index ] && display === "none" ) {
13289				elem.style.display = "";
13290			}
13291
13292			// Set elements which have been overridden with display: none
13293			// in a stylesheet to whatever the default browser style is
13294			// for such an element
13295			if ( elem.style.display === "" && isHidden( elem ) ) {
13296				values[ index ] = jQuery1113._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
13297			}
13298		} else {
13299			hidden = isHidden( elem );
13300
13301			if ( display && display !== "none" || !hidden ) {
13302				jQuery1113._data( elem, "olddisplay", hidden ? display : jQuery1113.css( elem, "display" ) );
13303			}
13304		}
13305	}
13306
13307	// Set the display of most of the elements in a second loop
13308	// to avoid the constant reflow
13309	for ( index = 0; index < length; index++ ) {
13310		elem = elements[ index ];
13311		if ( !elem.style ) {
13312			continue;
13313		}
13314		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
13315			elem.style.display = show ? values[ index ] || "" : "none";
13316		}
13317	}
13318
13319	return elements;
13320}
13321
13322function setPositiveNumber( elem, value, subtract ) {
13323	var matches = rnumsplit.exec( value );
13324	return matches ?
13325		// Guard against undefined "subtract", e.g., when used as in cssHooks
13326		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
13327		value;
13328}
13329
13330function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
13331	var i = extra === ( isBorderBox ? "border" : "content" ) ?
13332		// If we already have the right measurement, avoid augmentation
13333		4 :
13334		// Otherwise initialize for horizontal or vertical properties
13335		name === "width" ? 1 : 0,
13336
13337		val = 0;
13338
13339	for ( ; i < 4; i += 2 ) {
13340		// both box models exclude margin, so add it if we want it
13341		if ( extra === "margin" ) {
13342			val += jQuery1113.css( elem, extra + cssExpand[ i ], true, styles );
13343		}
13344
13345		if ( isBorderBox ) {
13346			// border-box includes padding, so remove it if we want content
13347			if ( extra === "content" ) {
13348				val -= jQuery1113.css( elem, "padding" + cssExpand[ i ], true, styles );
13349			}
13350
13351			// at this point, extra isn't border nor margin, so remove border
13352			if ( extra !== "margin" ) {
13353				val -= jQuery1113.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
13354			}
13355		} else {
13356			// at this point, extra isn't content, so add padding
13357			val += jQuery1113.css( elem, "padding" + cssExpand[ i ], true, styles );
13358
13359			// at this point, extra isn't content nor padding, so add border
13360			if ( extra !== "padding" ) {
13361				val += jQuery1113.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
13362			}
13363		}
13364	}
13365
13366	return val;
13367}
13368
13369function getWidthOrHeight( elem, name, extra ) {
13370
13371	// Start with offset property, which is equivalent to the border-box value
13372	var valueIsBorderBox = true,
13373		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
13374		styles = getStyles( elem ),
13375		isBorderBox = support.boxSizing && jQuery1113.css( elem, "boxSizing", false, styles ) === "border-box";
13376
13377	// some non-html elements return undefined for offsetWidth, so check for null/undefined
13378	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
13379	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
13380	if ( val <= 0 || val == null ) {
13381		// Fall back to computed then uncomputed css if necessary
13382		val = curCSS( elem, name, styles );
13383		if ( val < 0 || val == null ) {
13384			val = elem.style[ name ];
13385		}
13386
13387		// Computed unit is not pixels. Stop here and return.
13388		if ( rnumnonpx.test(val) ) {
13389			return val;
13390		}
13391
13392		// we need the check for style in case a browser which returns unreliable values
13393		// for getComputedStyle silently falls back to the reliable elem.style
13394		valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
13395
13396		// Normalize "", auto, and prepare for extra
13397		val = parseFloat( val ) || 0;
13398	}
13399
13400	// use the active box-sizing model to add/subtract irrelevant styles
13401	return ( val +
13402		augmentWidthOrHeight(
13403			elem,
13404			name,
13405			extra || ( isBorderBox ? "border" : "content" ),
13406			valueIsBorderBox,
13407			styles
13408		)
13409	) + "px";
13410}
13411
13412jQuery1113.extend({
13413	// Add in style property hooks for overriding the default
13414	// behavior of getting and setting a style property
13415	cssHooks: {
13416		opacity: {
13417			get: function( elem, computed ) {
13418				if ( computed ) {
13419					// We should always get a number back from opacity
13420					var ret = curCSS( elem, "opacity" );
13421					return ret === "" ? "1" : ret;
13422				}
13423			}
13424		}
13425	},
13426
13427	// Don't automatically add "px" to these possibly-unitless properties
13428	cssNumber: {
13429		"columnCount": true,
13430		"fillOpacity": true,
13431		"flexGrow": true,
13432		"flexShrink": true,
13433		"fontWeight": true,
13434		"lineHeight": true,
13435		"opacity": true,
13436		"order": true,
13437		"orphans": true,
13438		"widows": true,
13439		"zIndex": true,
13440		"zoom": true
13441	},
13442
13443	// Add in properties whose names you wish to fix before
13444	// setting or getting the value
13445	cssProps: {
13446		// normalize float css property
13447		"float": support.cssFloat ? "cssFloat" : "styleFloat"
13448	},
13449
13450	// Get and set the style property on a DOM Node
13451	style: function( elem, name, value, extra ) {
13452		// Don't set styles on text and comment nodes
13453		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
13454			return;
13455		}
13456
13457		// Make sure that we're working with the right name
13458		var ret, type, hooks,
13459			origName = jQuery1113.camelCase( name ),
13460			style = elem.style;
13461
13462		name = jQuery1113.cssProps[ origName ] || ( jQuery1113.cssProps[ origName ] = vendorPropName( style, origName ) );
13463
13464		// gets hook for the prefixed version
13465		// followed by the unprefixed version
13466		hooks = jQuery1113.cssHooks[ name ] || jQuery1113.cssHooks[ origName ];
13467
13468		// Check if we're setting a value
13469		if ( value !== undefined ) {
13470			type = typeof value;
13471
13472			// convert relative number strings (+= or -=) to relative numbers. #7345
13473			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
13474				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery1113.css( elem, name ) );
13475				// Fixes bug #9237
13476				type = "number";
13477			}
13478
13479			// Make sure that null and NaN values aren't set. See: #7116
13480			if ( value == null || value !== value ) {
13481				return;
13482			}
13483
13484			// If a number was passed in, add 'px' to the (except for certain CSS properties)
13485			if ( type === "number" && !jQuery1113.cssNumber[ origName ] ) {
13486				value += "px";
13487			}
13488
13489			// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
13490			// but it would mean to define eight (for every problematic property) identical functions
13491			if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
13492				style[ name ] = "inherit";
13493			}
13494
13495			// If a hook was provided, use that value, otherwise just set the specified value
13496			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
13497
13498				// Support: IE
13499				// Swallow errors from 'invalid' CSS values (#5509)
13500				try {
13501					style[ name ] = value;
13502				} catch(e) {}
13503			}
13504
13505		} else {
13506			// If a hook was provided get the non-computed value from there
13507			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
13508				return ret;
13509			}
13510
13511			// Otherwise just get the value from the style object
13512			return style[ name ];
13513		}
13514	},
13515
13516	css: function( elem, name, extra, styles ) {
13517		var num, val, hooks,
13518			origName = jQuery1113.camelCase( name );
13519
13520		// Make sure that we're working with the right name
13521		name = jQuery1113.cssProps[ origName ] || ( jQuery1113.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
13522
13523		// gets hook for the prefixed version
13524		// followed by the unprefixed version
13525		hooks = jQuery1113.cssHooks[ name ] || jQuery1113.cssHooks[ origName ];
13526
13527		// If a hook was provided get the computed value from there
13528		if ( hooks && "get" in hooks ) {
13529			val = hooks.get( elem, true, extra );
13530		}
13531
13532		// Otherwise, if a way to get the computed value exists, use that
13533		if ( val === undefined ) {
13534			val = curCSS( elem, name, styles );
13535		}
13536
13537		//convert "normal" to computed value
13538		if ( val === "normal" && name in cssNormalTransform ) {
13539			val = cssNormalTransform[ name ];
13540		}
13541
13542		// Return, converting to number if forced or a qualifier was provided and val looks numeric
13543		if ( extra === "" || extra ) {
13544			num = parseFloat( val );
13545			return extra === true || jQuery1113.isNumeric( num ) ? num || 0 : val;
13546		}
13547		return val;
13548	}
13549});
13550
13551jQuery1113.each([ "height", "width" ], function( i, name ) {
13552	jQuery1113.cssHooks[ name ] = {
13553		get: function( elem, computed, extra ) {
13554			if ( computed ) {
13555				// certain elements can have dimension info if we invisibly show them
13556				// however, it must have a current display style that would benefit from this
13557				return rdisplayswap.test( jQuery1113.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
13558					jQuery1113.swap( elem, cssShow, function() {
13559						return getWidthOrHeight( elem, name, extra );
13560					}) :
13561					getWidthOrHeight( elem, name, extra );
13562			}
13563		},
13564
13565		set: function( elem, value, extra ) {
13566			var styles = extra && getStyles( elem );
13567			return setPositiveNumber( elem, value, extra ?
13568				augmentWidthOrHeight(
13569					elem,
13570					name,
13571					extra,
13572					support.boxSizing && jQuery1113.css( elem, "boxSizing", false, styles ) === "border-box",
13573					styles
13574				) : 0
13575			);
13576		}
13577	};
13578});
13579
13580if ( !support.opacity ) {
13581	jQuery1113.cssHooks.opacity = {
13582		get: function( elem, computed ) {
13583			// IE uses filters for opacity
13584			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
13585				( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
13586				computed ? "1" : "";
13587		},
13588
13589		set: function( elem, value ) {
13590			var style = elem.style,
13591				currentStyle = elem.currentStyle,
13592				opacity = jQuery1113.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
13593				filter = currentStyle && currentStyle.filter || style.filter || "";
13594
13595			// IE has trouble with opacity if it does not have layout
13596			// Force it by setting the zoom level
13597			style.zoom = 1;
13598
13599			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
13600			// if value === "", then remove inline opacity #12685
13601			if ( ( value >= 1 || value === "" ) &&
13602					jQuery1113.trim( filter.replace( ralpha, "" ) ) === "" &&
13603					style.removeAttribute ) {
13604
13605				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
13606				// if "filter:" is present at all, clearType is disabled, we want to avoid this
13607				// style.removeAttribute is IE Only, but so apparently is this code path...
13608				style.removeAttribute( "filter" );
13609
13610				// if there is no filter style applied in a css rule or unset inline opacity, we are done
13611				if ( value === "" || currentStyle && !currentStyle.filter ) {
13612					return;
13613				}
13614			}
13615
13616			// otherwise, set new filter values
13617			style.filter = ralpha.test( filter ) ?
13618				filter.replace( ralpha, opacity ) :
13619				filter + " " + opacity;
13620		}
13621	};
13622}
13623
13624jQuery1113.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
13625	function( elem, computed ) {
13626		if ( computed ) {
13627			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
13628			// Work around by temporarily setting element display to inline-block
13629			return jQuery1113.swap( elem, { "display": "inline-block" },
13630				curCSS, [ elem, "marginRight" ] );
13631		}
13632	}
13633);
13634
13635// These hooks are used by animate to expand properties
13636jQuery1113.each({
13637	margin: "",
13638	padding: "",
13639	border: "Width"
13640}, function( prefix, suffix ) {
13641	jQuery1113.cssHooks[ prefix + suffix ] = {
13642		expand: function( value ) {
13643			var i = 0,
13644				expanded = {},
13645
13646				// assumes a single number if not a string
13647				parts = typeof value === "string" ? value.split(" ") : [ value ];
13648
13649			for ( ; i < 4; i++ ) {
13650				expanded[ prefix + cssExpand[ i ] + suffix ] =
13651					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
13652			}
13653
13654			return expanded;
13655		}
13656	};
13657
13658	if ( !rmargin.test( prefix ) ) {
13659		jQuery1113.cssHooks[ prefix + suffix ].set = setPositiveNumber;
13660	}
13661});
13662
13663jQuery1113.fn.extend({
13664	css: function( name, value ) {
13665		return access( this, function( elem, name, value ) {
13666			var styles, len,
13667				map = {},
13668				i = 0;
13669
13670			if ( jQuery1113.isArray( name ) ) {
13671				styles = getStyles( elem );
13672				len = name.length;
13673
13674				for ( ; i < len; i++ ) {
13675					map[ name[ i ] ] = jQuery1113.css( elem, name[ i ], false, styles );
13676				}
13677
13678				return map;
13679			}
13680
13681			return value !== undefined ?
13682				jQuery1113.style( elem, name, value ) :
13683				jQuery1113.css( elem, name );
13684		}, name, value, arguments.length > 1 );
13685	},
13686	show: function() {
13687		return showHide( this, true );
13688	},
13689	hide: function() {
13690		return showHide( this );
13691	},
13692	toggle: function( state ) {
13693		if ( typeof state === "boolean" ) {
13694			return state ? this.show() : this.hide();
13695		}
13696
13697		return this.each(function() {
13698			if ( isHidden( this ) ) {
13699				jQuery1113( this ).show();
13700			} else {
13701				jQuery1113( this ).hide();
13702			}
13703		});
13704	}
13705});
13706
13707
13708function Tween( elem, options, prop, end, easing ) {
13709	return new Tween.prototype.init( elem, options, prop, end, easing );
13710}
13711jQuery1113.Tween = Tween;
13712
13713Tween.prototype = {
13714	constructor: Tween,
13715	init: function( elem, options, prop, end, easing, unit ) {
13716		this.elem = elem;
13717		this.prop = prop;
13718		this.easing = easing || "swing";
13719		this.options = options;
13720		this.start = this.now = this.cur();
13721		this.end = end;
13722		this.unit = unit || ( jQuery1113.cssNumber[ prop ] ? "" : "px" );
13723	},
13724	cur: function() {
13725		var hooks = Tween.propHooks[ this.prop ];
13726
13727		return hooks && hooks.get ?
13728			hooks.get( this ) :
13729			Tween.propHooks._default.get( this );
13730	},
13731	run: function( percent ) {
13732		var eased,
13733			hooks = Tween.propHooks[ this.prop ];
13734
13735		if ( this.options.duration ) {
13736			this.pos = eased = jQuery1113.easing[ this.easing ](
13737				percent, this.options.duration * percent, 0, 1, this.options.duration
13738			);
13739		} else {
13740			this.pos = eased = percent;
13741		}
13742		this.now = ( this.end - this.start ) * eased + this.start;
13743
13744		if ( this.options.step ) {
13745			this.options.step.call( this.elem, this.now, this );
13746		}
13747
13748		if ( hooks && hooks.set ) {
13749			hooks.set( this );
13750		} else {
13751			Tween.propHooks._default.set( this );
13752		}
13753		return this;
13754	}
13755};
13756
13757Tween.prototype.init.prototype = Tween.prototype;
13758
13759Tween.propHooks = {
13760	_default: {
13761		get: function( tween ) {
13762			var result;
13763
13764			if ( tween.elem[ tween.prop ] != null &&
13765				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
13766				return tween.elem[ tween.prop ];
13767			}
13768
13769			// passing an empty string as a 3rd parameter to .css will automatically
13770			// attempt a parseFloat and fallback to a string if the parse fails
13771			// so, simple values such as "10px" are parsed to Float.
13772			// complex values such as "rotate(1rad)" are returned as is.
13773			result = jQuery1113.css( tween.elem, tween.prop, "" );
13774			// Empty strings, null, undefined and "auto" are converted to 0.
13775			return !result || result === "auto" ? 0 : result;
13776		},
13777		set: function( tween ) {
13778			// use step hook for back compat - use cssHook if its there - use .style if its
13779			// available and use plain properties where available
13780			if ( jQuery1113.fx.step[ tween.prop ] ) {
13781				jQuery1113.fx.step[ tween.prop ]( tween );
13782			} else if ( tween.elem.style && ( tween.elem.style[ jQuery1113.cssProps[ tween.prop ] ] != null || jQuery1113.cssHooks[ tween.prop ] ) ) {
13783				jQuery1113.style( tween.elem, tween.prop, tween.now + tween.unit );
13784			} else {
13785				tween.elem[ tween.prop ] = tween.now;
13786			}
13787		}
13788	}
13789};
13790
13791// Support: IE <=9
13792// Panic based approach to setting things on disconnected nodes
13793
13794Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
13795	set: function( tween ) {
13796		if ( tween.elem.nodeType && tween.elem.parentNode ) {
13797			tween.elem[ tween.prop ] = tween.now;
13798		}
13799	}
13800};
13801
13802jQuery1113.easing = {
13803	linear: function( p ) {
13804		return p;
13805	},
13806	swing: function( p ) {
13807		return 0.5 - Math.cos( p * Math.PI ) / 2;
13808	}
13809};
13810
13811jQuery1113.fx = Tween.prototype.init;
13812
13813// Back Compat <1.8 extension point
13814jQuery1113.fx.step = {};
13815
13816
13817
13818
13819var
13820	fxNow, timerId,
13821	rfxtypes = /^(?:toggle|show|hide)$/,
13822	rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
13823	rrun = /queueHooks$/,
13824	animationPrefilters = [ defaultPrefilter ],
13825	tweeners = {
13826		"*": [ function( prop, value ) {
13827			var tween = this.createTween( prop, value ),
13828				target = tween.cur(),
13829				parts = rfxnum.exec( value ),
13830				unit = parts && parts[ 3 ] || ( jQuery1113.cssNumber[ prop ] ? "" : "px" ),
13831
13832				// Starting value computation is required for potential unit mismatches
13833				start = ( jQuery1113.cssNumber[ prop ] || unit !== "px" && +target ) &&
13834					rfxnum.exec( jQuery1113.css( tween.elem, prop ) ),
13835				scale = 1,
13836				maxIterations = 20;
13837
13838			if ( start && start[ 3 ] !== unit ) {
13839				// Trust units reported by jQuery1113.css
13840				unit = unit || start[ 3 ];
13841
13842				// Make sure we update the tween properties later on
13843				parts = parts || [];
13844
13845				// Iteratively approximate from a nonzero starting point
13846				start = +target || 1;
13847
13848				do {
13849					// If previous iteration zeroed out, double until we get *something*
13850					// Use a string for doubling factor so we don't accidentally see scale as unchanged below
13851					scale = scale || ".5";
13852
13853					// Adjust and apply
13854					start = start / scale;
13855					jQuery1113.style( tween.elem, prop, start + unit );
13856
13857				// Update scale, tolerating zero or NaN from tween.cur()
13858				// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
13859				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
13860			}
13861
13862			// Update tween properties
13863			if ( parts ) {
13864				start = tween.start = +start || +target || 0;
13865				tween.unit = unit;
13866				// If a +=/-= token was provided, we're doing a relative animation
13867				tween.end = parts[ 1 ] ?
13868					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
13869					+parts[ 2 ];
13870			}
13871
13872			return tween;
13873		} ]
13874	};
13875
13876// Animations created synchronously will run synchronously
13877function createFxNow() {
13878	setTimeout(function() {
13879		fxNow = undefined;
13880	});
13881	return ( fxNow = jQuery1113.now() );
13882}
13883
13884// Generate parameters to create a standard animation
13885function genFx( type, includeWidth ) {
13886	var which,
13887		attrs = { height: type },
13888		i = 0;
13889
13890	// if we include width, step value is 1 to do all cssExpand values,
13891	// if we don't include width, step value is 2 to skip over Left and Right
13892	includeWidth = includeWidth ? 1 : 0;
13893	for ( ; i < 4 ; i += 2 - includeWidth ) {
13894		which = cssExpand[ i ];
13895		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
13896	}
13897
13898	if ( includeWidth ) {
13899		attrs.opacity = attrs.width = type;
13900	}
13901
13902	return attrs;
13903}
13904
13905function createTween( value, prop, animation ) {
13906	var tween,
13907		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
13908		index = 0,
13909		length = collection.length;
13910	for ( ; index < length; index++ ) {
13911		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
13912
13913			// we're done with this property
13914			return tween;
13915		}
13916	}
13917}
13918
13919function defaultPrefilter( elem, props, opts ) {
13920	/* jshint validthis: true */
13921	var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
13922		anim = this,
13923		orig = {},
13924		style = elem.style,
13925		hidden = elem.nodeType && isHidden( elem ),
13926		dataShow = jQuery1113._data( elem, "fxshow" );
13927
13928	// handle queue: false promises
13929	if ( !opts.queue ) {
13930		hooks = jQuery1113._queueHooks( elem, "fx" );
13931		if ( hooks.unqueued == null ) {
13932			hooks.unqueued = 0;
13933			oldfire = hooks.empty.fire;
13934			hooks.empty.fire = function() {
13935				if ( !hooks.unqueued ) {
13936					oldfire();
13937				}
13938			};
13939		}
13940		hooks.unqueued++;
13941
13942		anim.always(function() {
13943			// doing this makes sure that the complete handler will be called
13944			// before this completes
13945			anim.always(function() {
13946				hooks.unqueued--;
13947				if ( !jQuery1113.queue( elem, "fx" ).length ) {
13948					hooks.empty.fire();
13949				}
13950			});
13951		});
13952	}
13953
13954	// height/width overflow pass
13955	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
13956		// Make sure that nothing sneaks out
13957		// Record all 3 overflow attributes because IE does not
13958		// change the overflow attribute when overflowX and
13959		// overflowY are set to the same value
13960		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
13961
13962		// Set display property to inline-block for height/width
13963		// animations on inline elements that are having width/height animated
13964		display = jQuery1113.css( elem, "display" );
13965
13966		// Test default display if display is currently "none"
13967		checkDisplay = display === "none" ?
13968			jQuery1113._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
13969
13970		if ( checkDisplay === "inline" && jQuery1113.css( elem, "float" ) === "none" ) {
13971
13972			// inline-level elements accept inline-block;
13973			// block-level elements need to be inline with layout
13974			if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
13975				style.display = "inline-block";
13976			} else {
13977				style.zoom = 1;
13978			}
13979		}
13980	}
13981
13982	if ( opts.overflow ) {
13983		style.overflow = "hidden";
13984		if ( !support.shrinkWrapBlocks() ) {
13985			anim.always(function() {
13986				style.overflow = opts.overflow[ 0 ];
13987				style.overflowX = opts.overflow[ 1 ];
13988				style.overflowY = opts.overflow[ 2 ];
13989			});
13990		}
13991	}
13992
13993	// show/hide pass
13994	for ( prop in props ) {
13995		value = props[ prop ];
13996		if ( rfxtypes.exec( value ) ) {
13997			delete props[ prop ];
13998			toggle = toggle || value === "toggle";
13999			if ( value === ( hidden ? "hide" : "show" ) ) {
14000
14001				// 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
14002				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
14003					hidden = true;
14004				} else {
14005					continue;
14006				}
14007			}
14008			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery1113.style( elem, prop );
14009
14010		// Any non-fx value stops us from restoring the original display value
14011		} else {
14012			display = undefined;
14013		}
14014	}
14015
14016	if ( !jQuery1113.isEmptyObject( orig ) ) {
14017		if ( dataShow ) {
14018			if ( "hidden" in dataShow ) {
14019				hidden = dataShow.hidden;
14020			}
14021		} else {
14022			dataShow = jQuery1113._data( elem, "fxshow", {} );
14023		}
14024
14025		// store state if its toggle - enables .stop().toggle() to "reverse"
14026		if ( toggle ) {
14027			dataShow.hidden = !hidden;
14028		}
14029		if ( hidden ) {
14030			jQuery1113( elem ).show();
14031		} else {
14032			anim.done(function() {
14033				jQuery1113( elem ).hide();
14034			});
14035		}
14036		anim.done(function() {
14037			var prop;
14038			jQuery1113._removeData( elem, "fxshow" );
14039			for ( prop in orig ) {
14040				jQuery1113.style( elem, prop, orig[ prop ] );
14041			}
14042		});
14043		for ( prop in orig ) {
14044			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
14045
14046			if ( !( prop in dataShow ) ) {
14047				dataShow[ prop ] = tween.start;
14048				if ( hidden ) {
14049					tween.end = tween.start;
14050					tween.start = prop === "width" || prop === "height" ? 1 : 0;
14051				}
14052			}
14053		}
14054
14055	// If this is a noop like .hide().hide(), restore an overwritten display value
14056	} else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
14057		style.display = display;
14058	}
14059}
14060
14061function propFilter( props, specialEasing ) {
14062	var index, name, easing, value, hooks;
14063
14064	// camelCase, specialEasing and expand cssHook pass
14065	for ( index in props ) {
14066		name = jQuery1113.camelCase( index );
14067		easing = specialEasing[ name ];
14068		value = props[ index ];
14069		if ( jQuery1113.isArray( value ) ) {
14070			easing = value[ 1 ];
14071			value = props[ index ] = value[ 0 ];
14072		}
14073
14074		if ( index !== name ) {
14075			props[ name ] = value;
14076			delete props[ index ];
14077		}
14078
14079		hooks = jQuery1113.cssHooks[ name ];
14080		if ( hooks && "expand" in hooks ) {
14081			value = hooks.expand( value );
14082			delete props[ name ];
14083
14084			// not quite $.extend, this wont overwrite keys already present.
14085			// also - reusing 'index' from above because we have the correct "name"
14086			for ( index in value ) {
14087				if ( !( index in props ) ) {
14088					props[ index ] = value[ index ];
14089					specialEasing[ index ] = easing;
14090				}
14091			}
14092		} else {
14093			specialEasing[ name ] = easing;
14094		}
14095	}
14096}
14097
14098function Animation( elem, properties, options ) {
14099	var result,
14100		stopped,
14101		index = 0,
14102		length = animationPrefilters.length,
14103		deferred = jQuery1113.Deferred().always( function() {
14104			// don't match elem in the :animated selector
14105			delete tick.elem;
14106		}),
14107		tick = function() {
14108			if ( stopped ) {
14109				return false;
14110			}
14111			var currentTime = fxNow || createFxNow(),
14112				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
14113				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
14114				temp = remaining / animation.duration || 0,
14115				percent = 1 - temp,
14116				index = 0,
14117				length = animation.tweens.length;
14118
14119			for ( ; index < length ; index++ ) {
14120				animation.tweens[ index ].run( percent );
14121			}
14122
14123			deferred.notifyWith( elem, [ animation, percent, remaining ]);
14124
14125			if ( percent < 1 && length ) {
14126				return remaining;
14127			} else {
14128				deferred.resolveWith( elem, [ animation ] );
14129				return false;
14130			}
14131		},
14132		animation = deferred.promise({
14133			elem: elem,
14134			props: jQuery1113.extend( {}, properties ),
14135			opts: jQuery1113.extend( true, { specialEasing: {} }, options ),
14136			originalProperties: properties,
14137			originalOptions: options,
14138			startTime: fxNow || createFxNow(),
14139			duration: options.duration,
14140			tweens: [],
14141			createTween: function( prop, end ) {
14142				var tween = jQuery1113.Tween( elem, animation.opts, prop, end,
14143						animation.opts.specialEasing[ prop ] || animation.opts.easing );
14144				animation.tweens.push( tween );
14145				return tween;
14146			},
14147			stop: function( gotoEnd ) {
14148				var index = 0,
14149					// if we are going to the end, we want to run all the tweens
14150					// otherwise we skip this part
14151					length = gotoEnd ? animation.tweens.length : 0;
14152				if ( stopped ) {
14153					return this;
14154				}
14155				stopped = true;
14156				for ( ; index < length ; index++ ) {
14157					animation.tweens[ index ].run( 1 );
14158				}
14159
14160				// resolve when we played the last frame
14161				// otherwise, reject
14162				if ( gotoEnd ) {
14163					deferred.resolveWith( elem, [ animation, gotoEnd ] );
14164				} else {
14165					deferred.rejectWith( elem, [ animation, gotoEnd ] );
14166				}
14167				return this;
14168			}
14169		}),
14170		props = animation.props;
14171
14172	propFilter( props, animation.opts.specialEasing );
14173
14174	for ( ; index < length ; index++ ) {
14175		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
14176		if ( result ) {
14177			return result;
14178		}
14179	}
14180
14181	jQuery1113.map( props, createTween, animation );
14182
14183	if ( jQuery1113.isFunction( animation.opts.start ) ) {
14184		animation.opts.start.call( elem, animation );
14185	}
14186
14187	jQuery1113.fx.timer(
14188		jQuery1113.extend( tick, {
14189			elem: elem,
14190			anim: animation,
14191			queue: animation.opts.queue
14192		})
14193	);
14194
14195	// attach callbacks from options
14196	return animation.progress( animation.opts.progress )
14197		.done( animation.opts.done, animation.opts.complete )
14198		.fail( animation.opts.fail )
14199		.always( animation.opts.always );
14200}
14201
14202jQuery1113.Animation = jQuery1113.extend( Animation, {
14203	tweener: function( props, callback ) {
14204		if ( jQuery1113.isFunction( props ) ) {
14205			callback = props;
14206			props = [ "*" ];
14207		} else {
14208			props = props.split(" ");
14209		}
14210
14211		var prop,
14212			index = 0,
14213			length = props.length;
14214
14215		for ( ; index < length ; index++ ) {
14216			prop = props[ index ];
14217			tweeners[ prop ] = tweeners[ prop ] || [];
14218			tweeners[ prop ].unshift( callback );
14219		}
14220	},
14221
14222	prefilter: function( callback, prepend ) {
14223		if ( prepend ) {
14224			animationPrefilters.unshift( callback );
14225		} else {
14226			animationPrefilters.push( callback );
14227		}
14228	}
14229});
14230
14231jQuery1113.speed = function( speed, easing, fn ) {
14232	var opt = speed && typeof speed === "object" ? jQuery1113.extend( {}, speed ) : {
14233		complete: fn || !fn && easing ||
14234			jQuery1113.isFunction( speed ) && speed,
14235		duration: speed,
14236		easing: fn && easing || easing && !jQuery1113.isFunction( easing ) && easing
14237	};
14238
14239	opt.duration = jQuery1113.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
14240		opt.duration in jQuery1113.fx.speeds ? jQuery1113.fx.speeds[ opt.duration ] : jQuery1113.fx.speeds._default;
14241
14242	// normalize opt.queue - true/undefined/null -> "fx"
14243	if ( opt.queue == null || opt.queue === true ) {
14244		opt.queue = "fx";
14245	}
14246
14247	// Queueing
14248	opt.old = opt.complete;
14249
14250	opt.complete = function() {
14251		if ( jQuery1113.isFunction( opt.old ) ) {
14252			opt.old.call( this );
14253		}
14254
14255		if ( opt.queue ) {
14256			jQuery1113.dequeue( this, opt.queue );
14257		}
14258	};
14259
14260	return opt;
14261};
14262
14263jQuery1113.fn.extend({
14264	fadeTo: function( speed, to, easing, callback ) {
14265
14266		// show any hidden elements after setting opacity to 0
14267		return this.filter( isHidden ).css( "opacity", 0 ).show()
14268
14269			// animate to the value specified
14270			.end().animate({ opacity: to }, speed, easing, callback );
14271	},
14272	animate: function( prop, speed, easing, callback ) {
14273		var empty = jQuery1113.isEmptyObject( prop ),
14274			optall = jQuery1113.speed( speed, easing, callback ),
14275			doAnimation = function() {
14276				// Operate on a copy of prop so per-property easing won't be lost
14277				var anim = Animation( this, jQuery1113.extend( {}, prop ), optall );
14278
14279				// Empty animations, or finishing resolves immediately
14280				if ( empty || jQuery1113._data( this, "finish" ) ) {
14281					anim.stop( true );
14282				}
14283			};
14284			doAnimation.finish = doAnimation;
14285
14286		return empty || optall.queue === false ?
14287			this.each( doAnimation ) :
14288			this.queue( optall.queue, doAnimation );
14289	},
14290	stop: function( type, clearQueue, gotoEnd ) {
14291		var stopQueue = function( hooks ) {
14292			var stop = hooks.stop;
14293			delete hooks.stop;
14294			stop( gotoEnd );
14295		};
14296
14297		if ( typeof type !== "string" ) {
14298			gotoEnd = clearQueue;
14299			clearQueue = type;
14300			type = undefined;
14301		}
14302		if ( clearQueue && type !== false ) {
14303			this.queue( type || "fx", [] );
14304		}
14305
14306		return this.each(function() {
14307			var dequeue = true,
14308				index = type != null && type + "queueHooks",
14309				timers = jQuery1113.timers,
14310				data = jQuery1113._data( this );
14311
14312			if ( index ) {
14313				if ( data[ index ] && data[ index ].stop ) {
14314					stopQueue( data[ index ] );
14315				}
14316			} else {
14317				for ( index in data ) {
14318					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
14319						stopQueue( data[ index ] );
14320					}
14321				}
14322			}
14323
14324			for ( index = timers.length; index--; ) {
14325				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
14326					timers[ index ].anim.stop( gotoEnd );
14327					dequeue = false;
14328					timers.splice( index, 1 );
14329				}
14330			}
14331
14332			// start the next in the queue if the last step wasn't forced
14333			// timers currently will call their complete callbacks, which will dequeue
14334			// but only if they were gotoEnd
14335			if ( dequeue || !gotoEnd ) {
14336				jQuery1113.dequeue( this, type );
14337			}
14338		});
14339	},
14340	finish: function( type ) {
14341		if ( type !== false ) {
14342			type = type || "fx";
14343		}
14344		return this.each(function() {
14345			var index,
14346				data = jQuery1113._data( this ),
14347				queue = data[ type + "queue" ],
14348				hooks = data[ type + "queueHooks" ],
14349				timers = jQuery1113.timers,
14350				length = queue ? queue.length : 0;
14351
14352			// enable finishing flag on private data
14353			data.finish = true;
14354
14355			// empty the queue first
14356			jQuery1113.queue( this, type, [] );
14357
14358			if ( hooks && hooks.stop ) {
14359				hooks.stop.call( this, true );
14360			}
14361
14362			// look for any active animations, and finish them
14363			for ( index = timers.length; index--; ) {
14364				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
14365					timers[ index ].anim.stop( true );
14366					timers.splice( index, 1 );
14367				}
14368			}
14369
14370			// look for any animations in the old queue and finish them
14371			for ( index = 0; index < length; index++ ) {
14372				if ( queue[ index ] && queue[ index ].finish ) {
14373					queue[ index ].finish.call( this );
14374				}
14375			}
14376
14377			// turn off finishing flag
14378			delete data.finish;
14379		});
14380	}
14381});
14382
14383jQuery1113.each([ "toggle", "show", "hide" ], function( i, name ) {
14384	var cssFn = jQuery1113.fn[ name ];
14385	jQuery1113.fn[ name ] = function( speed, easing, callback ) {
14386		return speed == null || typeof speed === "boolean" ?
14387			cssFn.apply( this, arguments ) :
14388			this.animate( genFx( name, true ), speed, easing, callback );
14389	};
14390});
14391
14392// Generate shortcuts for custom animations
14393jQuery1113.each({
14394	slideDown: genFx("show"),
14395	slideUp: genFx("hide"),
14396	slideToggle: genFx("toggle"),
14397	fadeIn: { opacity: "show" },
14398	fadeOut: { opacity: "hide" },
14399	fadeToggle: { opacity: "toggle" }
14400}, function( name, props ) {
14401	jQuery1113.fn[ name ] = function( speed, easing, callback ) {
14402		return this.animate( props, speed, easing, callback );
14403	};
14404});
14405
14406jQuery1113.timers = [];
14407jQuery1113.fx.tick = function() {
14408	var timer,
14409		timers = jQuery1113.timers,
14410		i = 0;
14411
14412	fxNow = jQuery1113.now();
14413
14414	for ( ; i < timers.length; i++ ) {
14415		timer = timers[ i ];
14416		// Checks the timer has not already been removed
14417		if ( !timer() && timers[ i ] === timer ) {
14418			timers.splice( i--, 1 );
14419		}
14420	}
14421
14422	if ( !timers.length ) {
14423		jQuery1113.fx.stop();
14424	}
14425	fxNow = undefined;
14426};
14427
14428jQuery1113.fx.timer = function( timer ) {
14429	jQuery1113.timers.push( timer );
14430	if ( timer() ) {
14431		jQuery1113.fx.start();
14432	} else {
14433		jQuery1113.timers.pop();
14434	}
14435};
14436
14437jQuery1113.fx.interval = 13;
14438
14439jQuery1113.fx.start = function() {
14440	if ( !timerId ) {
14441		timerId = setInterval( jQuery1113.fx.tick, jQuery1113.fx.interval );
14442	}
14443};
14444
14445jQuery1113.fx.stop = function() {
14446	clearInterval( timerId );
14447	timerId = null;
14448};
14449
14450jQuery1113.fx.speeds = {
14451	slow: 600,
14452	fast: 200,
14453	// Default speed
14454	_default: 400
14455};
14456
14457
14458// Based off of the plugin by Clint Helfers, with permission.
14459// http://blindsignals.com/index.php/2009/07/jQuery1113-delay/
14460jQuery1113.fn.delay = function( time, type ) {
14461	time = jQuery1113.fx ? jQuery1113.fx.speeds[ time ] || time : time;
14462	type = type || "fx";
14463
14464	return this.queue( type, function( next, hooks ) {
14465		var timeout = setTimeout( next, time );
14466		hooks.stop = function() {
14467			clearTimeout( timeout );
14468		};
14469	});
14470};
14471
14472
14473(function() {
14474	// Minified: var a,b,c,d,e
14475	var input, div, select, a, opt;
14476
14477	// Setup
14478	div = document.createElement( "div" );
14479	div.setAttribute( "className", "t" );
14480	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
14481	a = div.getElementsByTagName("a")[ 0 ];
14482
14483	// First batch of tests.
14484	select = document.createElement("select");
14485	opt = select.appendChild( document.createElement("option") );
14486	input = div.getElementsByTagName("input")[ 0 ];
14487
14488	a.style.cssText = "top:1px";
14489
14490	// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
14491	support.getSetAttribute = div.className !== "t";
14492
14493	// Get the style information from getAttribute
14494	// (IE uses .cssText instead)
14495	support.style = /top/.test( a.getAttribute("style") );
14496
14497	// Make sure that URLs aren't manipulated
14498	// (IE normalizes it by default)
14499	support.hrefNormalized = a.getAttribute("href") === "/a";
14500
14501	// Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
14502	support.checkOn = !!input.value;
14503
14504	// Make sure that a selected-by-default option has a working selected property.
14505	// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
14506	support.optSelected = opt.selected;
14507
14508	// Tests for enctype support on a form (#6743)
14509	support.enctype = !!document.createElement("form").enctype;
14510
14511	// Make sure that the options inside disabled selects aren't marked as disabled
14512	// (WebKit marks them as disabled)
14513	select.disabled = true;
14514	support.optDisabled = !opt.disabled;
14515
14516	// Support: IE8 only
14517	// Check if we can trust getAttribute("value")
14518	input = document.createElement( "input" );
14519	input.setAttribute( "value", "" );
14520	support.input = input.getAttribute( "value" ) === "";
14521
14522	// Check if an input maintains its value after becoming a radio
14523	input.value = "t";
14524	input.setAttribute( "type", "radio" );
14525	support.radioValue = input.value === "t";
14526})();
14527
14528
14529var rreturn = /\r/g;
14530
14531jQuery1113.fn.extend({
14532	val: function( value ) {
14533		var hooks, ret, isFunction,
14534			elem = this[0];
14535
14536		if ( !arguments.length ) {
14537			if ( elem ) {
14538				hooks = jQuery1113.valHooks[ elem.type ] || jQuery1113.valHooks[ elem.nodeName.toLowerCase() ];
14539
14540				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
14541					return ret;
14542				}
14543
14544				ret = elem.value;
14545
14546				return typeof ret === "string" ?
14547					// handle most common string cases
14548					ret.replace(rreturn, "") :
14549					// handle cases where value is null/undef or number
14550					ret == null ? "" : ret;
14551			}
14552
14553			return;
14554		}
14555
14556		isFunction = jQuery1113.isFunction( value );
14557
14558		return this.each(function( i ) {
14559			var val;
14560
14561			if ( this.nodeType !== 1 ) {
14562				return;
14563			}
14564
14565			if ( isFunction ) {
14566				val = value.call( this, i, jQuery1113( this ).val() );
14567			} else {
14568				val = value;
14569			}
14570
14571			// Treat null/undefined as ""; convert numbers to string
14572			if ( val == null ) {
14573				val = "";
14574			} else if ( typeof val === "number" ) {
14575				val += "";
14576			} else if ( jQuery1113.isArray( val ) ) {
14577				val = jQuery1113.map( val, function( value ) {
14578					return value == null ? "" : value + "";
14579				});
14580			}
14581
14582			hooks = jQuery1113.valHooks[ this.type ] || jQuery1113.valHooks[ this.nodeName.toLowerCase() ];
14583
14584			// If set returns undefined, fall back to normal setting
14585			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
14586				this.value = val;
14587			}
14588		});
14589	}
14590});
14591
14592jQuery1113.extend({
14593	valHooks: {
14594		option: {
14595			get: function( elem ) {
14596				var val = jQuery1113.find.attr( elem, "value" );
14597				return val != null ?
14598					val :
14599					// Support: IE10-11+
14600					// option.text throws exceptions (#14686, #14858)
14601					jQuery1113.trim( jQuery1113.text( elem ) );
14602			}
14603		},
14604		select: {
14605			get: function( elem ) {
14606				var value, option,
14607					options = elem.options,
14608					index = elem.selectedIndex,
14609					one = elem.type === "select-one" || index < 0,
14610					values = one ? null : [],
14611					max = one ? index + 1 : options.length,
14612					i = index < 0 ?
14613						max :
14614						one ? index : 0;
14615
14616				// Loop through all the selected options
14617				for ( ; i < max; i++ ) {
14618					option = options[ i ];
14619
14620					// oldIE doesn't update selected after form reset (#2551)
14621					if ( ( option.selected || i === index ) &&
14622							// Don't return options that are disabled or in a disabled optgroup
14623							( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
14624							( !option.parentNode.disabled || !jQuery1113.nodeName( option.parentNode, "optgroup" ) ) ) {
14625
14626						// Get the specific value for the option
14627						value = jQuery1113( option ).val();
14628
14629						// We don't need an array for one selects
14630						if ( one ) {
14631							return value;
14632						}
14633
14634						// Multi-Selects return an array
14635						values.push( value );
14636					}
14637				}
14638
14639				return values;
14640			},
14641
14642			set: function( elem, value ) {
14643				var optionSet, option,
14644					options = elem.options,
14645					values = jQuery1113.makeArray( value ),
14646					i = options.length;
14647
14648				while ( i-- ) {
14649					option = options[ i ];
14650
14651					if ( jQuery1113.inArray( jQuery1113.valHooks.option.get( option ), values ) >= 0 ) {
14652
14653						// Support: IE6
14654						// When new option element is added to select box we need to
14655						// force reflow of newly added node in order to workaround delay
14656						// of initialization properties
14657						try {
14658							option.selected = optionSet = true;
14659
14660						} catch ( _ ) {
14661
14662							// Will be executed only in IE6
14663							option.scrollHeight;
14664						}
14665
14666					} else {
14667						option.selected = false;
14668					}
14669				}
14670
14671				// Force browsers to behave consistently when non-matching value is set
14672				if ( !optionSet ) {
14673					elem.selectedIndex = -1;
14674				}
14675
14676				return options;
14677			}
14678		}
14679	}
14680});
14681
14682// Radios and checkboxes getter/setter
14683jQuery1113.each([ "radio", "checkbox" ], function() {
14684	jQuery1113.valHooks[ this ] = {
14685		set: function( elem, value ) {
14686			if ( jQuery1113.isArray( value ) ) {
14687				return ( elem.checked = jQuery1113.inArray( jQuery1113(elem).val(), value ) >= 0 );
14688			}
14689		}
14690	};
14691	if ( !support.checkOn ) {
14692		jQuery1113.valHooks[ this ].get = function( elem ) {
14693			// Support: Webkit
14694			// "" is returned instead of "on" if a value isn't specified
14695			return elem.getAttribute("value") === null ? "on" : elem.value;
14696		};
14697	}
14698});
14699
14700
14701
14702
14703var nodeHook, boolHook,
14704	attrHandle = jQuery1113.expr.attrHandle,
14705	ruseDefault = /^(?:checked|selected)$/i,
14706	getSetAttribute = support.getSetAttribute,
14707	getSetInput = support.input;
14708
14709jQuery1113.fn.extend({
14710	attr: function( name, value ) {
14711		return access( this, jQuery1113.attr, name, value, arguments.length > 1 );
14712	},
14713
14714	removeAttr: function( name ) {
14715		return this.each(function() {
14716			jQuery1113.removeAttr( this, name );
14717		});
14718	}
14719});
14720
14721jQuery1113.extend({
14722	attr: function( elem, name, value ) {
14723		var hooks, ret,
14724			nType = elem.nodeType;
14725
14726		// don't get/set attributes on text, comment and attribute nodes
14727		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
14728			return;
14729		}
14730
14731		// Fallback to prop when attributes are not supported
14732		if ( typeof elem.getAttribute === strundefined ) {
14733			return jQuery1113.prop( elem, name, value );
14734		}
14735
14736		// All attributes are lowercase
14737		// Grab necessary hook if one is defined
14738		if ( nType !== 1 || !jQuery1113.isXMLDoc( elem ) ) {
14739			name = name.toLowerCase();
14740			hooks = jQuery1113.attrHooks[ name ] ||
14741				( jQuery1113.expr.match.bool.test( name ) ? boolHook : nodeHook );
14742		}
14743
14744		if ( value !== undefined ) {
14745
14746			if ( value === null ) {
14747				jQuery1113.removeAttr( elem, name );
14748
14749			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
14750				return ret;
14751
14752			} else {
14753				elem.setAttribute( name, value + "" );
14754				return value;
14755			}
14756
14757		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
14758			return ret;
14759
14760		} else {
14761			ret = jQuery1113.find.attr( elem, name );
14762
14763			// Non-existent attributes return null, we normalize to undefined
14764			return ret == null ?
14765				undefined :
14766				ret;
14767		}
14768	},
14769
14770	removeAttr: function( elem, value ) {
14771		var name, propName,
14772			i = 0,
14773			attrNames = value && value.match( rnotwhite );
14774
14775		if ( attrNames && elem.nodeType === 1 ) {
14776			while ( (name = attrNames[i++]) ) {
14777				propName = jQuery1113.propFix[ name ] || name;
14778
14779				// Boolean attributes get special treatment (#10870)
14780				if ( jQuery1113.expr.match.bool.test( name ) ) {
14781					// Set corresponding property to false
14782					if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
14783						elem[ propName ] = false;
14784					// Support: IE<9
14785					// Also clear defaultChecked/defaultSelected (if appropriate)
14786					} else {
14787						elem[ jQuery1113.camelCase( "default-" + name ) ] =
14788							elem[ propName ] = false;
14789					}
14790
14791				// See #9699 for explanation of this approach (setting first, then removal)
14792				} else {
14793					jQuery1113.attr( elem, name, "" );
14794				}
14795
14796				elem.removeAttribute( getSetAttribute ? name : propName );
14797			}
14798		}
14799	},
14800
14801	attrHooks: {
14802		type: {
14803			set: function( elem, value ) {
14804				if ( !support.radioValue && value === "radio" && jQuery1113.nodeName(elem, "input") ) {
14805					// Setting the type on a radio button after the value resets the value in IE6-9
14806					// Reset value to default in case type is set after value during creation
14807					var val = elem.value;
14808					elem.setAttribute( "type", value );
14809					if ( val ) {
14810						elem.value = val;
14811					}
14812					return value;
14813				}
14814			}
14815		}
14816	}
14817});
14818
14819// Hook for boolean attributes
14820boolHook = {
14821	set: function( elem, value, name ) {
14822		if ( value === false ) {
14823			// Remove boolean attributes when set to false
14824			jQuery1113.removeAttr( elem, name );
14825		} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
14826			// IE<8 needs the *property* name
14827			elem.setAttribute( !getSetAttribute && jQuery1113.propFix[ name ] || name, name );
14828
14829		// Use defaultChecked and defaultSelected for oldIE
14830		} else {
14831			elem[ jQuery1113.camelCase( "default-" + name ) ] = elem[ name ] = true;
14832		}
14833
14834		return name;
14835	}
14836};
14837
14838// Retrieve booleans specially
14839jQuery1113.each( jQuery1113.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
14840
14841	var getter = attrHandle[ name ] || jQuery1113.find.attr;
14842
14843	attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
14844		function( elem, name, isXML ) {
14845			var ret, handle;
14846			if ( !isXML ) {
14847				// Avoid an infinite loop by temporarily removing this function from the getter
14848				handle = attrHandle[ name ];
14849				attrHandle[ name ] = ret;
14850				ret = getter( elem, name, isXML ) != null ?
14851					name.toLowerCase() :
14852					null;
14853				attrHandle[ name ] = handle;
14854			}
14855			return ret;
14856		} :
14857		function( elem, name, isXML ) {
14858			if ( !isXML ) {
14859				return elem[ jQuery1113.camelCase( "default-" + name ) ] ?
14860					name.toLowerCase() :
14861					null;
14862			}
14863		};
14864});
14865
14866// fix oldIE attroperties
14867if ( !getSetInput || !getSetAttribute ) {
14868	jQuery1113.attrHooks.value = {
14869		set: function( elem, value, name ) {
14870			if ( jQuery1113.nodeName( elem, "input" ) ) {
14871				// Does not return so that setAttribute is also used
14872				elem.defaultValue = value;
14873			} else {
14874				// Use nodeHook if defined (#1954); otherwise setAttribute is fine
14875				return nodeHook && nodeHook.set( elem, value, name );
14876			}
14877		}
14878	};
14879}
14880
14881// IE6/7 do not support getting/setting some attributes with get/setAttribute
14882if ( !getSetAttribute ) {
14883
14884	// Use this for any attribute in IE6/7
14885	// This fixes almost every IE6/7 issue
14886	nodeHook = {
14887		set: function( elem, value, name ) {
14888			// Set the existing or create a new attribute node
14889			var ret = elem.getAttributeNode( name );
14890			if ( !ret ) {
14891				elem.setAttributeNode(
14892					(ret = elem.ownerDocument.createAttribute( name ))
14893				);
14894			}
14895
14896			ret.value = value += "";
14897
14898			// Break association with cloned elements by also using setAttribute (#9646)
14899			if ( name === "value" || value === elem.getAttribute( name ) ) {
14900				return value;
14901			}
14902		}
14903	};
14904
14905	// Some attributes are constructed with empty-string values when not defined
14906	attrHandle.id = attrHandle.name = attrHandle.coords =
14907		function( elem, name, isXML ) {
14908			var ret;
14909			if ( !isXML ) {
14910				return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
14911					ret.value :
14912					null;
14913			}
14914		};
14915
14916	// Fixing value retrieval on a button requires this module
14917	jQuery1113.valHooks.button = {
14918		get: function( elem, name ) {
14919			var ret = elem.getAttributeNode( name );
14920			if ( ret && ret.specified ) {
14921				return ret.value;
14922			}
14923		},
14924		set: nodeHook.set
14925	};
14926
14927	// Set contenteditable to false on removals(#10429)
14928	// Setting to empty string throws an error as an invalid value
14929	jQuery1113.attrHooks.contenteditable = {
14930		set: function( elem, value, name ) {
14931			nodeHook.set( elem, value === "" ? false : value, name );
14932		}
14933	};
14934
14935	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
14936	// This is for removals
14937	jQuery1113.each([ "width", "height" ], function( i, name ) {
14938		jQuery1113.attrHooks[ name ] = {
14939			set: function( elem, value ) {
14940				if ( value === "" ) {
14941					elem.setAttribute( name, "auto" );
14942					return value;
14943				}
14944			}
14945		};
14946	});
14947}
14948
14949if ( !support.style ) {
14950	jQuery1113.attrHooks.style = {
14951		get: function( elem ) {
14952			// Return undefined in the case of empty string
14953			// Note: IE uppercases css property names, but if we were to .toLowerCase()
14954			// .cssText, that would destroy case senstitivity in URL's, like in "background"
14955			return elem.style.cssText || undefined;
14956		},
14957		set: function( elem, value ) {
14958			return ( elem.style.cssText = value + "" );
14959		}
14960	};
14961}
14962
14963
14964
14965
14966var rfocusable = /^(?:input|select|textarea|button|object)$/i,
14967	rclickable = /^(?:a|area)$/i;
14968
14969jQuery1113.fn.extend({
14970	prop: function( name, value ) {
14971		return access( this, jQuery1113.prop, name, value, arguments.length > 1 );
14972	},
14973
14974	removeProp: function( name ) {
14975		name = jQuery1113.propFix[ name ] || name;
14976		return this.each(function() {
14977			// try/catch handles cases where IE balks (such as removing a property on window)
14978			try {
14979				this[ name ] = undefined;
14980				delete this[ name ];
14981			} catch( e ) {}
14982		});
14983	}
14984});
14985
14986jQuery1113.extend({
14987	propFix: {
14988		"for": "htmlFor",
14989		"class": "className"
14990	},
14991
14992	prop: function( elem, name, value ) {
14993		var ret, hooks, notxml,
14994			nType = elem.nodeType;
14995
14996		// don't get/set properties on text, comment and attribute nodes
14997		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
14998			return;
14999		}
15000
15001		notxml = nType !== 1 || !jQuery1113.isXMLDoc( elem );
15002
15003		if ( notxml ) {
15004			// Fix name and attach hooks
15005			name = jQuery1113.propFix[ name ] || name;
15006			hooks = jQuery1113.propHooks[ name ];
15007		}
15008
15009		if ( value !== undefined ) {
15010			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
15011				ret :
15012				( elem[ name ] = value );
15013
15014		} else {
15015			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
15016				ret :
15017				elem[ name ];
15018		}
15019	},
15020
15021	propHooks: {
15022		tabIndex: {
15023			get: function( elem ) {
15024				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
15025				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
15026				// Use proper attribute retrieval(#12072)
15027				var tabindex = jQuery1113.find.attr( elem, "tabindex" );
15028
15029				return tabindex ?
15030					parseInt( tabindex, 10 ) :
15031					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
15032						0 :
15033						-1;
15034			}
15035		}
15036	}
15037});
15038
15039// Some attributes require a special call on IE
15040// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
15041if ( !support.hrefNormalized ) {
15042	// href/src property should get the full normalized URL (#10299/#12915)
15043	jQuery1113.each([ "href", "src" ], function( i, name ) {
15044		jQuery1113.propHooks[ name ] = {
15045			get: function( elem ) {
15046				return elem.getAttribute( name, 4 );
15047			}
15048		};
15049	});
15050}
15051
15052// Support: Safari, IE9+
15053// mis-reports the default selected property of an option
15054// Accessing the parent's selectedIndex property fixes it
15055if ( !support.optSelected ) {
15056	jQuery1113.propHooks.selected = {
15057		get: function( elem ) {
15058			var parent = elem.parentNode;
15059
15060			if ( parent ) {
15061				parent.selectedIndex;
15062
15063				// Make sure that it also works with optgroups, see #5701
15064				if ( parent.parentNode ) {
15065					parent.parentNode.selectedIndex;
15066				}
15067			}
15068			return null;
15069		}
15070	};
15071}
15072
15073jQuery1113.each([
15074	"tabIndex",
15075	"readOnly",
15076	"maxLength",
15077	"cellSpacing",
15078	"cellPadding",
15079	"rowSpan",
15080	"colSpan",
15081	"useMap",
15082	"frameBorder",
15083	"contentEditable"
15084], function() {
15085	jQuery1113.propFix[ this.toLowerCase() ] = this;
15086});
15087
15088// IE6/7 call enctype encoding
15089if ( !support.enctype ) {
15090	jQuery1113.propFix.enctype = "encoding";
15091}
15092
15093
15094
15095
15096var rclass = /[\t\r\n\f]/g;
15097
15098jQuery1113.fn.extend({
15099	addClass: function( value ) {
15100		var classes, elem, cur, clazz, j, finalValue,
15101			i = 0,
15102			len = this.length,
15103			proceed = typeof value === "string" && value;
15104
15105		if ( jQuery1113.isFunction( value ) ) {
15106			return this.each(function( j ) {
15107				jQuery1113( this ).addClass( value.call( this, j, this.className ) );
15108			});
15109		}
15110
15111		if ( proceed ) {
15112			// The disjunction here is for better compressibility (see removeClass)
15113			classes = ( value || "" ).match( rnotwhite ) || [];
15114
15115			for ( ; i < len; i++ ) {
15116				elem = this[ i ];
15117				cur = elem.nodeType === 1 && ( elem.className ?
15118					( " " + elem.className + " " ).replace( rclass, " " ) :
15119					" "
15120				);
15121
15122				if ( cur ) {
15123					j = 0;
15124					while ( (clazz = classes[j++]) ) {
15125						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
15126							cur += clazz + " ";
15127						}
15128					}
15129
15130					// only assign if different to avoid unneeded rendering.
15131					finalValue = jQuery1113.trim( cur );
15132					if ( elem.className !== finalValue ) {
15133						elem.className = finalValue;
15134					}
15135				}
15136			}
15137		}
15138
15139		return this;
15140	},
15141
15142	removeClass: function( value ) {
15143		var classes, elem, cur, clazz, j, finalValue,
15144			i = 0,
15145			len = this.length,
15146			proceed = arguments.length === 0 || typeof value === "string" && value;
15147
15148		if ( jQuery1113.isFunction( value ) ) {
15149			return this.each(function( j ) {
15150				jQuery1113( this ).removeClass( value.call( this, j, this.className ) );
15151			});
15152		}
15153		if ( proceed ) {
15154			classes = ( value || "" ).match( rnotwhite ) || [];
15155
15156			for ( ; i < len; i++ ) {
15157				elem = this[ i ];
15158				// This expression is here for better compressibility (see addClass)
15159				cur = elem.nodeType === 1 && ( elem.className ?
15160					( " " + elem.className + " " ).replace( rclass, " " ) :
15161					""
15162				);
15163
15164				if ( cur ) {
15165					j = 0;
15166					while ( (clazz = classes[j++]) ) {
15167						// Remove *all* instances
15168						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
15169							cur = cur.replace( " " + clazz + " ", " " );
15170						}
15171					}
15172
15173					// only assign if different to avoid unneeded rendering.
15174					finalValue = value ? jQuery1113.trim( cur ) : "";
15175					if ( elem.className !== finalValue ) {
15176						elem.className = finalValue;
15177					}
15178				}
15179			}
15180		}
15181
15182		return this;
15183	},
15184
15185	toggleClass: function( value, stateVal ) {
15186		var type = typeof value;
15187
15188		if ( typeof stateVal === "boolean" && type === "string" ) {
15189			return stateVal ? this.addClass( value ) : this.removeClass( value );
15190		}
15191
15192		if ( jQuery1113.isFunction( value ) ) {
15193			return this.each(function( i ) {
15194				jQuery1113( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
15195			});
15196		}
15197
15198		return this.each(function() {
15199			if ( type === "string" ) {
15200				// toggle individual class names
15201				var className,
15202					i = 0,
15203					self = jQuery1113( this ),
15204					classNames = value.match( rnotwhite ) || [];
15205
15206				while ( (className = classNames[ i++ ]) ) {
15207					// check each className given, space separated list
15208					if ( self.hasClass( className ) ) {
15209						self.removeClass( className );
15210					} else {
15211						self.addClass( className );
15212					}
15213				}
15214
15215			// Toggle whole class name
15216			} else if ( type === strundefined || type === "boolean" ) {
15217				if ( this.className ) {
15218					// store className if set
15219					jQuery1113._data( this, "__className__", this.className );
15220				}
15221
15222				// If the element has a class name or if we're passed "false",
15223				// then remove the whole classname (if there was one, the above saved it).
15224				// Otherwise bring back whatever was previously saved (if anything),
15225				// falling back to the empty string if nothing was stored.
15226				this.className = this.className || value === false ? "" : jQuery1113._data( this, "__className__" ) || "";
15227			}
15228		});
15229	},
15230
15231	hasClass: function( selector ) {
15232		var className = " " + selector + " ",
15233			i = 0,
15234			l = this.length;
15235		for ( ; i < l; i++ ) {
15236			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
15237				return true;
15238			}
15239		}
15240
15241		return false;
15242	}
15243});
15244
15245
15246
15247
15248// Return jQuery1113 for attributes-only inclusion
15249
15250
15251jQuery1113.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
15252	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
15253	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
15254
15255	// Handle event binding
15256	jQuery1113.fn[ name ] = function( data, fn ) {
15257		return arguments.length > 0 ?
15258			this.on( name, null, data, fn ) :
15259			this.trigger( name );
15260	};
15261});
15262
15263jQuery1113.fn.extend({
15264	hover: function( fnOver, fnOut ) {
15265		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
15266	},
15267
15268	bind: function( types, data, fn ) {
15269		return this.on( types, null, data, fn );
15270	},
15271	unbind: function( types, fn ) {
15272		return this.off( types, null, fn );
15273	},
15274
15275	delegate: function( selector, types, data, fn ) {
15276		return this.on( types, selector, data, fn );
15277	},
15278	undelegate: function( selector, types, fn ) {
15279		// ( namespace ) or ( selector, types [, fn] )
15280		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
15281	}
15282});
15283
15284
15285var nonce = jQuery1113.now();
15286
15287var rquery = (/\?/);
15288
15289
15290
15291var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
15292
15293jQuery1113.parseJSON = function( data ) {
15294	// Attempt to parse using the native JSON parser first
15295	if ( window.JSON && window.JSON.parse ) {
15296		// Support: Android 2.3
15297		// Workaround failure to string-cast null input
15298		return window.JSON.parse( data + "" );
15299	}
15300
15301	var requireNonComma,
15302		depth = null,
15303		str = jQuery1113.trim( data + "" );
15304
15305	// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
15306	// after removing valid tokens
15307	return str && !jQuery1113.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
15308
15309		// Force termination if we see a misplaced comma
15310		if ( requireNonComma && comma ) {
15311			depth = 0;
15312		}
15313
15314		// Perform no more replacements after returning to outermost depth
15315		if ( depth === 0 ) {
15316			return token;
15317		}
15318
15319		// Commas must not follow "[", "{", or ","
15320		requireNonComma = open || comma;
15321
15322		// Determine new depth
15323		// array/object open ("[" or "{"): depth += true - false (increment)
15324		// array/object close ("]" or "}"): depth += false - true (decrement)
15325		// other cases ("," or primitive): depth += true - true (numeric cast)
15326		depth += !close - !open;
15327
15328		// Remove this token
15329		return "";
15330	}) ) ?
15331		( Function( "return " + str ) )() :
15332		jQuery1113.error( "Invalid JSON: " + data );
15333};
15334
15335
15336// Cross-browser xml parsing
15337jQuery1113.parseXML = function( data ) {
15338	var xml, tmp;
15339	if ( !data || typeof data !== "string" ) {
15340		return null;
15341	}
15342	try {
15343		if ( window.DOMParser ) { // Standard
15344			tmp = new DOMParser();
15345			xml = tmp.parseFromString( data, "text/xml" );
15346		} else { // IE
15347			xml = new ActiveXObject( "Microsoft.XMLDOM" );
15348			xml.async = "false";
15349			xml.loadXML( data );
15350		}
15351	} catch( e ) {
15352		xml = undefined;
15353	}
15354	if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
15355		jQuery1113.error( "Invalid XML: " + data );
15356	}
15357	return xml;
15358};
15359
15360
15361var
15362	// Document location
15363	ajaxLocParts,
15364	ajaxLocation,
15365
15366	rhash = /#.*$/,
15367	rts = /([?&])_=[^&]*/,
15368	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
15369	// #7653, #8125, #8152: local protocol detection
15370	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
15371	rnoContent = /^(?:GET|HEAD)$/,
15372	rprotocol = /^\/\//,
15373	rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
15374
15375	/* Prefilters
15376	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
15377	 * 2) These are called:
15378	 *    - BEFORE asking for a transport
15379	 *    - AFTER param serialization (s.data is a string if s.processData is true)
15380	 * 3) key is the dataType
15381	 * 4) the catchall symbol "*" can be used
15382	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
15383	 */
15384	prefilters = {},
15385
15386	/* Transports bindings
15387	 * 1) key is the dataType
15388	 * 2) the catchall symbol "*" can be used
15389	 * 3) selection will start with transport dataType and THEN go to "*" if needed
15390	 */
15391	transports = {},
15392
15393	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
15394	allTypes = "*/".concat("*");
15395
15396// #8138, IE may throw an exception when accessing
15397// a field from window.location if document.domain has been set
15398try {
15399	ajaxLocation = location.href;
15400} catch( e ) {
15401	// Use the href attribute of an A element
15402	// since IE will modify it given document.location
15403	ajaxLocation = document.createElement( "a" );
15404	ajaxLocation.href = "";
15405	ajaxLocation = ajaxLocation.href;
15406}
15407
15408// Segment location into parts
15409ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
15410
15411// Base "constructor" for jQuery1113.ajaxPrefilter and jQuery1113.ajaxTransport
15412function addToPrefiltersOrTransports( structure ) {
15413
15414	// dataTypeExpression is optional and defaults to "*"
15415	return function( dataTypeExpression, func ) {
15416
15417		if ( typeof dataTypeExpression !== "string" ) {
15418			func = dataTypeExpression;
15419			dataTypeExpression = "*";
15420		}
15421
15422		var dataType,
15423			i = 0,
15424			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
15425
15426		if ( jQuery1113.isFunction( func ) ) {
15427			// For each dataType in the dataTypeExpression
15428			while ( (dataType = dataTypes[i++]) ) {
15429				// Prepend if requested
15430				if ( dataType.charAt( 0 ) === "+" ) {
15431					dataType = dataType.slice( 1 ) || "*";
15432					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
15433
15434				// Otherwise append
15435				} else {
15436					(structure[ dataType ] = structure[ dataType ] || []).push( func );
15437				}
15438			}
15439		}
15440	};
15441}
15442
15443// Base inspection function for prefilters and transports
15444function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
15445
15446	var inspected = {},
15447		seekingTransport = ( structure === transports );
15448
15449	function inspect( dataType ) {
15450		var selected;
15451		inspected[ dataType ] = true;
15452		jQuery1113.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
15453			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
15454			if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
15455				options.dataTypes.unshift( dataTypeOrTransport );
15456				inspect( dataTypeOrTransport );
15457				return false;
15458			} else if ( seekingTransport ) {
15459				return !( selected = dataTypeOrTransport );
15460			}
15461		});
15462		return selected;
15463	}
15464
15465	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
15466}
15467
15468// A special extend for ajax options
15469// that takes "flat" options (not to be deep extended)
15470// Fixes #9887
15471function ajaxExtend( target, src ) {
15472	var deep, key,
15473		flatOptions = jQuery1113.ajaxSettings.flatOptions || {};
15474
15475	for ( key in src ) {
15476		if ( src[ key ] !== undefined ) {
15477			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
15478		}
15479	}
15480	if ( deep ) {
15481		jQuery1113.extend( true, target, deep );
15482	}
15483
15484	return target;
15485}
15486
15487/* Handles responses to an ajax request:
15488 * - finds the right dataType (mediates between content-type and expected dataType)
15489 * - returns the corresponding response
15490 */
15491function ajaxHandleResponses( s, jqXHR, responses ) {
15492	var firstDataType, ct, finalDataType, type,
15493		contents = s.contents,
15494		dataTypes = s.dataTypes;
15495
15496	// Remove auto dataType and get content-type in the process
15497	while ( dataTypes[ 0 ] === "*" ) {
15498		dataTypes.shift();
15499		if ( ct === undefined ) {
15500			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
15501		}
15502	}
15503
15504	// Check if we're dealing with a known content-type
15505	if ( ct ) {
15506		for ( type in contents ) {
15507			if ( contents[ type ] && contents[ type ].test( ct ) ) {
15508				dataTypes.unshift( type );
15509				break;
15510			}
15511		}
15512	}
15513
15514	// Check to see if we have a response for the expected dataType
15515	if ( dataTypes[ 0 ] in responses ) {
15516		finalDataType = dataTypes[ 0 ];
15517	} else {
15518		// Try convertible dataTypes
15519		for ( type in responses ) {
15520			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
15521				finalDataType = type;
15522				break;
15523			}
15524			if ( !firstDataType ) {
15525				firstDataType = type;
15526			}
15527		}
15528		// Or just use first one
15529		finalDataType = finalDataType || firstDataType;
15530	}
15531
15532	// If we found a dataType
15533	// We add the dataType to the list if needed
15534	// and return the corresponding response
15535	if ( finalDataType ) {
15536		if ( finalDataType !== dataTypes[ 0 ] ) {
15537			dataTypes.unshift( finalDataType );
15538		}
15539		return responses[ finalDataType ];
15540	}
15541}
15542
15543/* Chain conversions given the request and the original response
15544 * Also sets the responseXXX fields on the jqXHR instance
15545 */
15546function ajaxConvert( s, response, jqXHR, isSuccess ) {
15547	var conv2, current, conv, tmp, prev,
15548		converters = {},
15549		// Work with a copy of dataTypes in case we need to modify it for conversion
15550		dataTypes = s.dataTypes.slice();
15551
15552	// Create converters map with lowercased keys
15553	if ( dataTypes[ 1 ] ) {
15554		for ( conv in s.converters ) {
15555			converters[ conv.toLowerCase() ] = s.converters[ conv ];
15556		}
15557	}
15558
15559	current = dataTypes.shift();
15560
15561	// Convert to each sequential dataType
15562	while ( current ) {
15563
15564		if ( s.responseFields[ current ] ) {
15565			jqXHR[ s.responseFields[ current ] ] = response;
15566		}
15567
15568		// Apply the dataFilter if provided
15569		if ( !prev && isSuccess && s.dataFilter ) {
15570			response = s.dataFilter( response, s.dataType );
15571		}
15572
15573		prev = current;
15574		current = dataTypes.shift();
15575
15576		if ( current ) {
15577
15578			// There's only work to do if current dataType is non-auto
15579			if ( current === "*" ) {
15580
15581				current = prev;
15582
15583			// Convert response if prev dataType is non-auto and differs from current
15584			} else if ( prev !== "*" && prev !== current ) {
15585
15586				// Seek a direct converter
15587				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
15588
15589				// If none found, seek a pair
15590				if ( !conv ) {
15591					for ( conv2 in converters ) {
15592
15593						// If conv2 outputs current
15594						tmp = conv2.split( " " );
15595						if ( tmp[ 1 ] === current ) {
15596
15597							// If prev can be converted to accepted input
15598							conv = converters[ prev + " " + tmp[ 0 ] ] ||
15599								converters[ "* " + tmp[ 0 ] ];
15600							if ( conv ) {
15601								// Condense equivalence converters
15602								if ( conv === true ) {
15603									conv = converters[ conv2 ];
15604
15605								// Otherwise, insert the intermediate dataType
15606								} else if ( converters[ conv2 ] !== true ) {
15607									current = tmp[ 0 ];
15608									dataTypes.unshift( tmp[ 1 ] );
15609								}
15610								break;
15611							}
15612						}
15613					}
15614				}
15615
15616				// Apply converter (if not an equivalence)
15617				if ( conv !== true ) {
15618
15619					// Unless errors are allowed to bubble, catch and return them
15620					if ( conv && s[ "throws" ] ) {
15621						response = conv( response );
15622					} else {
15623						try {
15624							response = conv( response );
15625						} catch ( e ) {
15626							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
15627						}
15628					}
15629				}
15630			}
15631		}
15632	}
15633
15634	return { state: "success", data: response };
15635}
15636
15637jQuery1113.extend({
15638
15639	// Counter for holding the number of active queries
15640	active: 0,
15641
15642	// Last-Modified header cache for next request
15643	lastModified: {},
15644	etag: {},
15645
15646	ajaxSettings: {
15647		url: ajaxLocation,
15648		type: "GET",
15649		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
15650		global: true,
15651		processData: true,
15652		async: true,
15653		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
15654		/*
15655		timeout: 0,
15656		data: null,
15657		dataType: null,
15658		username: null,
15659		password: null,
15660		cache: null,
15661		throws: false,
15662		traditional: false,
15663		headers: {},
15664		*/
15665
15666		accepts: {
15667			"*": allTypes,
15668			text: "text/plain",
15669			html: "text/html",
15670			xml: "application/xml, text/xml",
15671			json: "application/json, text/javascript"
15672		},
15673
15674		contents: {
15675			xml: /xml/,
15676			html: /html/,
15677			json: /json/
15678		},
15679
15680		responseFields: {
15681			xml: "responseXML",
15682			text: "responseText",
15683			json: "responseJSON"
15684		},
15685
15686		// Data converters
15687		// Keys separate source (or catchall "*") and destination types with a single space
15688		converters: {
15689
15690			// Convert anything to text
15691			"* text": String,
15692
15693			// Text to html (true = no transformation)
15694			"text html": true,
15695
15696			// Evaluate text as a json expression
15697			"text json": jQuery1113.parseJSON,
15698
15699			// Parse text as xml
15700			"text xml": jQuery1113.parseXML
15701		},
15702
15703		// For options that shouldn't be deep extended:
15704		// you can add your own custom options here if
15705		// and when you create one that shouldn't be
15706		// deep extended (see ajaxExtend)
15707		flatOptions: {
15708			url: true,
vendor: 6,167 bytes, lines 15709-15911
15709			context: true
15710		}
15711	},
15712
15713	// Creates a full fledged settings object into target
15714	// with both ajaxSettings and settings fields.
15715	// If target is omitted, writes into ajaxSettings.
15716	ajaxSetup: function( target, settings ) {
15717		return settings ?
15718
15719			// Building a settings object
15720			ajaxExtend( ajaxExtend( target, jQuery1113.ajaxSettings ), settings ) :
15721
15722			// Extending ajaxSettings
15723			ajaxExtend( jQuery1113.ajaxSettings, target );
15724	},
15725
15726	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
15727	ajaxTransport: addToPrefiltersOrTransports( transports ),
15728
15729	// Main method
15730	ajax: function( url, options ) {
15731
15732		// If url is an object, simulate pre-1.5 signature
15733		if ( typeof url === "object" ) {
15734			options = url;
15735			url = undefined;
15736		}
15737
15738		// Force options to be an object
15739		options = options || {};
15740
15741		var // Cross-domain detection vars
15742			parts,
15743			// Loop variable
15744			i,
15745			// URL without anti-cache param
15746			cacheURL,
15747			// Response headers as string
15748			responseHeadersString,
15749			// timeout handle
15750			timeoutTimer,
15751
15752			// To know if global events are to be dispatched
15753			fireGlobals,
15754
15755			transport,
15756			// Response headers
15757			responseHeaders,
15758			// Create the final options object
15759			s = jQuery1113.ajaxSetup( {}, options ),
15760			// Callbacks context
15761			callbackContext = s.context || s,
15762			// Context for global events is callbackContext if it is a DOM node or jQuery1113 collection
15763			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jQuery1113 ) ?
15764				jQuery1113( callbackContext ) :
15765				jQuery1113.event,
15766			// Deferreds
15767			deferred = jQuery1113.Deferred(),
15768			completeDeferred = jQuery1113.Callbacks("once memory"),
15769			// Status-dependent callbacks
15770			statusCode = s.statusCode || {},
15771			// Headers (they are sent all at once)
15772			requestHeaders = {},
15773			requestHeadersNames = {},
15774			// The jqXHR state
15775			state = 0,
15776			// Default abort message
15777			strAbort = "canceled",
15778			// Fake xhr
15779			jqXHR = {
15780				readyState: 0,
15781
15782				// Builds headers hashtable if needed
15783				getResponseHeader: function( key ) {
15784					var match;
15785					if ( state === 2 ) {
15786						if ( !responseHeaders ) {
15787							responseHeaders = {};
15788							while ( (match = rheaders.exec( responseHeadersString )) ) {
15789								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
15790							}
15791						}
15792						match = responseHeaders[ key.toLowerCase() ];
15793					}
15794					return match == null ? null : match;
15795				},
15796
15797				// Raw string
15798				getAllResponseHeaders: function() {
15799					return state === 2 ? responseHeadersString : null;
15800				},
15801
15802				// Caches the header
15803				setRequestHeader: function( name, value ) {
15804					var lname = name.toLowerCase();
15805					if ( !state ) {
15806						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
15807						requestHeaders[ name ] = value;
15808					}
15809					return this;
15810				},
15811
15812				// Overrides response content-type header
15813				overrideMimeType: function( type ) {
15814					if ( !state ) {
15815						s.mimeType = type;
15816					}
15817					return this;
15818				},
15819
15820				// Status-dependent callbacks
15821				statusCode: function( map ) {
15822					var code;
15823					if ( map ) {
15824						if ( state < 2 ) {
15825							for ( code in map ) {
15826								// Lazy-add the new callback in a way that preserves old ones
15827								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
15828							}
15829						} else {
15830							// Execute the appropriate callbacks
15831							jqXHR.always( map[ jqXHR.status ] );
15832						}
15833					}
15834					return this;
15835				},
15836
15837				// Cancel the request
15838				abort: function( statusText ) {
15839					var finalText = statusText || strAbort;
15840					if ( transport ) {
15841						transport.abort( finalText );
15842					}
15843					done( 0, finalText );
15844					return this;
15845				}
15846			};
15847
15848		// Attach deferreds
15849		deferred.promise( jqXHR ).complete = completeDeferred.add;
15850		jqXHR.success = jqXHR.done;
15851		jqXHR.error = jqXHR.fail;
15852
15853		// Remove hash character (#7531: and string promotion)
15854		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
15855		// Handle falsy url in the settings object (#10093: consistency with old signature)
15856		// We also use the url parameter if available
15857		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
15858
15859		// Alias method option to type as per ticket #12004
15860		s.type = options.method || options.type || s.method || s.type;
15861
15862		// Extract dataTypes list
15863		s.dataTypes = jQuery1113.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
15864
15865		// A cross-domain request is in order when we have a protocol:host:port mismatch
15866		if ( s.crossDomain == null ) {
15867			parts = rurl.exec( s.url.toLowerCase() );
15868			s.crossDomain = !!( parts &&
15869				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
15870					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
15871						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
15872			);
15873		}
15874
15875		// Convert data if not already a string
15876		if ( s.data && s.processData && typeof s.data !== "string" ) {
15877			s.data = jQuery1113.param( s.data, s.traditional );
15878		}
15879
15880		// Apply prefilters
15881		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
15882
15883		// If request was aborted inside a prefilter, stop there
15884		if ( state === 2 ) {
15885			return jqXHR;
15886		}
15887
15888		// We can fire global events as of now if asked to
15889		// Don't fire events if jQuery1113.event is undefined in an AMD-usage scenario (#15118)
15890		fireGlobals = jQuery1113.event && s.global;
15891
15892		// Watch for a new set of requests
15893		if ( fireGlobals && jQuery1113.active++ === 0 ) {
15894			jQuery1113.event.trigger("ajaxStart");
15895		}
15896
15897		// Uppercase the type
15898		s.type = s.type.toUpperCase();
15899
15900		// Determine if request has content
15901		s.hasContent = !rnoContent.test( s.type );
15902
15903		// Save the URL in case we're toying with the If-Modified-Since
15904		// and/or If-None-Match header later on
15905		cacheURL = s.url;
15906
15907		// More options handling for requests with no content
15908		if ( !s.hasContent ) {
15909
15910			// If data is available, append data to url
15911			if ( s.data ) {
vendor: 36,256 bytes, lines 15912-17175
15912				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
15913				// #9682: remove data so that it's not used in an eventual retry
15914				delete s.data;
15915			}
15916
15917			// Add anti-cache in url if needed
15918			if ( s.cache === false ) {
15919				s.url = rts.test( cacheURL ) ?
15920
15921					// If there is already a '_' parameter, set its value
15922					cacheURL.replace( rts, "$1_=" + nonce++ ) :
15923
15924					// Otherwise add one to the end
15925					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
15926			}
15927		}
15928
15929		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
15930		if ( s.ifModified ) {
15931			if ( jQuery1113.lastModified[ cacheURL ] ) {
15932				jqXHR.setRequestHeader( "If-Modified-Since", jQuery1113.lastModified[ cacheURL ] );
15933			}
15934			if ( jQuery1113.etag[ cacheURL ] ) {
15935				jqXHR.setRequestHeader( "If-None-Match", jQuery1113.etag[ cacheURL ] );
15936			}
15937		}
15938
15939		// Set the correct header, if data is being sent
15940		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
15941			jqXHR.setRequestHeader( "Content-Type", s.contentType );
15942		}
15943
15944		// Set the Accepts header for the server, depending on the dataType
15945		jqXHR.setRequestHeader(
15946			"Accept",
15947			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
15948				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
15949				s.accepts[ "*" ]
15950		);
15951
15952		// Check for headers option
15953		for ( i in s.headers ) {
15954			jqXHR.setRequestHeader( i, s.headers[ i ] );
15955		}
15956
15957		// Allow custom headers/mimetypes and early abort
15958		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
15959			// Abort if not done already and return
15960			return jqXHR.abort();
15961		}
15962
15963		// aborting is no longer a cancellation
15964		strAbort = "abort";
15965
15966		// Install callbacks on deferreds
15967		for ( i in { success: 1, error: 1, complete: 1 } ) {
15968			jqXHR[ i ]( s[ i ] );
15969		}
15970
15971		// Get transport
15972		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
15973
15974		// If no transport, we auto-abort
15975		if ( !transport ) {
15976			done( -1, "No Transport" );
15977		} else {
15978			jqXHR.readyState = 1;
15979
15980			// Send global event
15981			if ( fireGlobals ) {
15982				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
15983			}
15984			// Timeout
15985			if ( s.async && s.timeout > 0 ) {
15986				timeoutTimer = setTimeout(function() {
15987					jqXHR.abort("timeout");
15988				}, s.timeout );
15989			}
15990
15991			try {
15992				state = 1;
15993				transport.send( requestHeaders, done );
15994			} catch ( e ) {
15995				// Propagate exception as error if not done
15996				if ( state < 2 ) {
15997					done( -1, e );
15998				// Simply rethrow otherwise
15999				} else {
16000					throw e;
16001				}
16002			}
16003		}
16004
16005		// Callback for when everything is done
16006		function done( status, nativeStatusText, responses, headers ) {
16007			var isSuccess, success, error, response, modified,
16008				statusText = nativeStatusText;
16009
16010			// Called once
16011			if ( state === 2 ) {
16012				return;
16013			}
16014
16015			// State is "done" now
16016			state = 2;
16017
16018			// Clear timeout if it exists
16019			if ( timeoutTimer ) {
16020				clearTimeout( timeoutTimer );
16021			}
16022
16023			// Dereference transport for early garbage collection
16024			// (no matter how long the jqXHR object will be used)
16025			transport = undefined;
16026
16027			// Cache response headers
16028			responseHeadersString = headers || "";
16029
16030			// Set readyState
16031			jqXHR.readyState = status > 0 ? 4 : 0;
16032
16033			// Determine if successful
16034			isSuccess = status >= 200 && status < 300 || status === 304;
16035
16036			// Get response data
16037			if ( responses ) {
16038				response = ajaxHandleResponses( s, jqXHR, responses );
16039			}
16040
16041			// Convert no matter what (that way responseXXX fields are always set)
16042			response = ajaxConvert( s, response, jqXHR, isSuccess );
16043
16044			// If successful, handle type chaining
16045			if ( isSuccess ) {
16046
16047				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
16048				if ( s.ifModified ) {
16049					modified = jqXHR.getResponseHeader("Last-Modified");
16050					if ( modified ) {
16051						jQuery1113.lastModified[ cacheURL ] = modified;
16052					}
16053					modified = jqXHR.getResponseHeader("etag");
16054					if ( modified ) {
16055						jQuery1113.etag[ cacheURL ] = modified;
16056					}
16057				}
16058
16059				// if no content
16060				if ( status === 204 || s.type === "HEAD" ) {
16061					statusText = "nocontent";
16062
16063				// if not modified
16064				} else if ( status === 304 ) {
16065					statusText = "notmodified";
16066
16067				// If we have data, let's convert it
16068				} else {
16069					statusText = response.state;
16070					success = response.data;
16071					error = response.error;
16072					isSuccess = !error;
16073				}
16074			} else {
16075				// We extract error from statusText
16076				// then normalize statusText and status for non-aborts
16077				error = statusText;
16078				if ( status || !statusText ) {
16079					statusText = "error";
16080					if ( status < 0 ) {
16081						status = 0;
16082					}
16083				}
16084			}
16085
16086			// Set data for the fake xhr object
16087			jqXHR.status = status;
16088			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
16089
16090			// Success/Error
16091			if ( isSuccess ) {
16092				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
16093			} else {
16094				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
16095			}
16096
16097			// Status-dependent callbacks
16098			jqXHR.statusCode( statusCode );
16099			statusCode = undefined;
16100
16101			if ( fireGlobals ) {
16102				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
16103					[ jqXHR, s, isSuccess ? success : error ] );
16104			}
16105
16106			// Complete
16107			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
16108
16109			if ( fireGlobals ) {
16110				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
16111				// Handle the global AJAX counter
16112				if ( !( --jQuery1113.active ) ) {
16113					jQuery1113.event.trigger("ajaxStop");
16114				}
16115			}
16116		}
16117
16118		return jqXHR;
16119	},
16120
16121	getJSON: function( url, data, callback ) {
16122		return jQuery1113.get( url, data, callback, "json" );
16123	},
16124
16125	getScript: function( url, callback ) {
16126		return jQuery1113.get( url, undefined, callback, "script" );
16127	}
16128});
16129
16130jQuery1113.each( [ "get", "post" ], function( i, method ) {
16131	jQuery1113[ method ] = function( url, data, callback, type ) {
16132		// shift arguments if data argument was omitted
16133		if ( jQuery1113.isFunction( data ) ) {
16134			type = type || callback;
16135			callback = data;
16136			data = undefined;
16137		}
16138
16139		return jQuery1113.ajax({
16140			url: url,
16141			type: method,
16142			dataType: type,
16143			data: data,
16144			success: callback
16145		});
16146	};
16147});
16148
16149
16150jQuery1113._evalUrl = function( url ) {
16151	return jQuery1113.ajax({
16152		url: url,
16153		type: "GET",
16154		dataType: "script",
16155		async: false,
16156		global: false,
16157		"throws": true
16158	});
16159};
16160
16161
16162jQuery1113.fn.extend({
16163	wrapAll: function( html ) {
16164		if ( jQuery1113.isFunction( html ) ) {
16165			return this.each(function(i) {
16166				jQuery1113(this).wrapAll( html.call(this, i) );
16167			});
16168		}
16169
16170		if ( this[0] ) {
16171			// The elements to wrap the target around
16172			var wrap = jQuery1113( html, this[0].ownerDocument ).eq(0).clone(true);
16173
16174			if ( this[0].parentNode ) {
16175				wrap.insertBefore( this[0] );
16176			}
16177
16178			wrap.map(function() {
16179				var elem = this;
16180
16181				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
16182					elem = elem.firstChild;
16183				}
16184
16185				return elem;
16186			}).append( this );
16187		}
16188
16189		return this;
16190	},
16191
16192	wrapInner: function( html ) {
16193		if ( jQuery1113.isFunction( html ) ) {
16194			return this.each(function(i) {
16195				jQuery1113(this).wrapInner( html.call(this, i) );
16196			});
16197		}
16198
16199		return this.each(function() {
16200			var self = jQuery1113( this ),
16201				contents = self.contents();
16202
16203			if ( contents.length ) {
16204				contents.wrapAll( html );
16205
16206			} else {
16207				self.append( html );
16208			}
16209		});
16210	},
16211
16212	wrap: function( html ) {
16213		var isFunction = jQuery1113.isFunction( html );
16214
16215		return this.each(function(i) {
16216			jQuery1113( this ).wrapAll( isFunction ? html.call(this, i) : html );
16217		});
16218	},
16219
16220	unwrap: function() {
16221		return this.parent().each(function() {
16222			if ( !jQuery1113.nodeName( this, "body" ) ) {
16223				jQuery1113( this ).replaceWith( this.childNodes );
16224			}
16225		}).end();
16226	}
16227});
16228
16229
16230jQuery1113.expr.filters.hidden = function( elem ) {
16231	// Support: Opera <= 12.12
16232	// Opera reports offsetWidths and offsetHeights less than zero on some elements
16233	return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
16234		(!support.reliableHiddenOffsets() &&
16235			((elem.style && elem.style.display) || jQuery1113.css( elem, "display" )) === "none");
16236};
16237
16238jQuery1113.expr.filters.visible = function( elem ) {
16239	return !jQuery1113.expr.filters.hidden( elem );
16240};
16241
16242
16243
16244
16245var r20 = /%20/g,
16246	rbracket = /\[\]$/,
16247	rCRLF = /\r?\n/g,
16248	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
16249	rsubmittable = /^(?:input|select|textarea|keygen)/i;
16250
16251function buildParams( prefix, obj, traditional, add ) {
16252	var name;
16253
16254	if ( jQuery1113.isArray( obj ) ) {
16255		// Serialize array item.
16256		jQuery1113.each( obj, function( i, v ) {
16257			if ( traditional || rbracket.test( prefix ) ) {
16258				// Treat each array item as a scalar.
16259				add( prefix, v );
16260
16261			} else {
16262				// Item is non-scalar (array or object), encode its numeric index.
16263				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
16264			}
16265		});
16266
16267	} else if ( !traditional && jQuery1113.type( obj ) === "object" ) {
16268		// Serialize object item.
16269		for ( name in obj ) {
16270			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
16271		}
16272
16273	} else {
16274		// Serialize scalar item.
16275		add( prefix, obj );
16276	}
16277}
16278
16279// Serialize an array of form elements or a set of
16280// key/values into a query string
16281jQuery1113.param = function( a, traditional ) {
16282	var prefix,
16283		s = [],
16284		add = function( key, value ) {
16285			// If value is a function, invoke it and return its value
16286			value = jQuery1113.isFunction( value ) ? value() : ( value == null ? "" : value );
16287			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
16288		};
16289
16290	// Set traditional to true for jQuery1113 <= 1.3.2 behavior.
16291	if ( traditional === undefined ) {
16292		traditional = jQuery1113.ajaxSettings && jQuery1113.ajaxSettings.traditional;
16293	}
16294
16295	// If an array was passed in, assume that it is an array of form elements.
16296	if ( jQuery1113.isArray( a ) || ( a.jQuery1113 && !jQuery1113.isPlainObject( a ) ) ) {
16297		// Serialize the form elements
16298		jQuery1113.each( a, function() {
16299			add( this.name, this.value );
16300		});
16301
16302	} else {
16303		// If traditional, encode the "old" way (the way 1.3.2 or older
16304		// did it), otherwise encode params recursively.
16305		for ( prefix in a ) {
16306			buildParams( prefix, a[ prefix ], traditional, add );
16307		}
16308	}
16309
16310	// Return the resulting serialization
16311	return s.join( "&" ).replace( r20, "+" );
16312};
16313
16314jQuery1113.fn.extend({
16315	serialize: function() {
16316		return jQuery1113.param( this.serializeArray() );
16317	},
16318	serializeArray: function() {
16319		return this.map(function() {
16320			// Can add propHook for "elements" to filter or add form elements
16321			var elements = jQuery1113.prop( this, "elements" );
16322			return elements ? jQuery1113.makeArray( elements ) : this;
16323		})
16324		.filter(function() {
16325			var type = this.type;
16326			// Use .is(":disabled") so that fieldset[disabled] works
16327			return this.name && !jQuery1113( this ).is( ":disabled" ) &&
16328				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
16329				( this.checked || !rcheckableType.test( type ) );
16330		})
16331		.map(function( i, elem ) {
16332			var val = jQuery1113( this ).val();
16333
16334			return val == null ?
16335				null :
16336				jQuery1113.isArray( val ) ?
16337					jQuery1113.map( val, function( val ) {
16338						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
16339					}) :
16340					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
16341		}).get();
16342	}
16343});
16344
16345
16346// Create the request object
16347// (This is still attached to ajaxSettings for backward compatibility)
16348jQuery1113.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
16349	// Support: IE6+
16350	function() {
16351
16352		// XHR cannot access local files, always use ActiveX for that case
16353		return !this.isLocal &&
16354
16355			// Support: IE7-8
16356			// oldIE XHR does not support non-RFC2616 methods (#13240)
16357			// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
16358			// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
16359			// Although this check for six methods instead of eight
16360			// since IE also does not support "trace" and "connect"
16361			/^(get|post|head|put|delete|options)$/i.test( this.type ) &&
16362
16363			createStandardXHR() || createActiveXHR();
16364	} :
16365	// For all other browsers, use the standard XMLHttpRequest object
16366	createStandardXHR;
16367
16368var xhrId = 0,
16369	xhrCallbacks = {},
16370	xhrSupported = jQuery1113.ajaxSettings.xhr();
16371
16372// Support: IE<10
16373// Open requests must be manually aborted on unload (#5280)
16374// See https://support.microsoft.com/kb/2856746 for more info
16375if ( window.attachEvent ) {
16376	window.attachEvent( "onunload", function() {
16377		for ( var key in xhrCallbacks ) {
16378			xhrCallbacks[ key ]( undefined, true );
16379		}
16380	});
16381}
16382
16383// Determine support properties
16384support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
16385xhrSupported = support.ajax = !!xhrSupported;
16386
16387// Create transport if the browser can provide an xhr
16388if ( xhrSupported ) {
16389
16390	jQuery1113.ajaxTransport(function( options ) {
16391		// Cross domain only allowed if supported through XMLHttpRequest
16392		if ( !options.crossDomain || support.cors ) {
16393
16394			var callback;
16395
16396			return {
16397				send: function( headers, complete ) {
16398					var i,
16399						xhr = options.xhr(),
16400						id = ++xhrId;
16401
16402					// Open the socket
16403					xhr.open( options.type, options.url, options.async, options.username, options.password );
16404
16405					// Apply custom fields if provided
16406					if ( options.xhrFields ) {
16407						for ( i in options.xhrFields ) {
16408							xhr[ i ] = options.xhrFields[ i ];
16409						}
16410					}
16411
16412					// Override mime type if needed
16413					if ( options.mimeType && xhr.overrideMimeType ) {
16414						xhr.overrideMimeType( options.mimeType );
16415					}
16416
16417					// X-Requested-With header
16418					// For cross-domain requests, seeing as conditions for a preflight are
16419					// akin to a jigsaw puzzle, we simply never set it to be sure.
16420					// (it can always be set on a per-request basis or even using ajaxSetup)
16421					// For same-domain requests, won't change header if already provided.
16422					if ( !options.crossDomain && !headers["X-Requested-With"] ) {
16423						headers["X-Requested-With"] = "XMLHttpRequest";
16424					}
16425
16426					// Set headers
16427					for ( i in headers ) {
16428						// Support: IE<9
16429						// IE's ActiveXObject throws a 'Type Mismatch' exception when setting
16430						// request header to a null-value.
16431						//
16432						// To keep consistent with other XHR implementations, cast the value
16433						// to string and ignore `undefined`.
16434						if ( headers[ i ] !== undefined ) {
16435							xhr.setRequestHeader( i, headers[ i ] + "" );
16436						}
16437					}
16438
16439					// Do send the request
16440					// This may raise an exception which is actually
16441					// handled in jQuery1113.ajax (so no try/catch here)
16442					xhr.send( ( options.hasContent && options.data ) || null );
16443
16444					// Listener
16445					callback = function( _, isAbort ) {
16446						var status, statusText, responses;
16447
16448						// Was never called and is aborted or complete
16449						if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
16450							// Clean up
16451							delete xhrCallbacks[ id ];
16452							callback = undefined;
16453							xhr.onreadystatechange = jQuery1113.noop;
16454
16455							// Abort manually if needed
16456							if ( isAbort ) {
16457								if ( xhr.readyState !== 4 ) {
16458									xhr.abort();
16459								}
16460							} else {
16461								responses = {};
16462								status = xhr.status;
16463
16464								// Support: IE<10
16465								// Accessing binary-data responseText throws an exception
16466								// (#11426)
16467								if ( typeof xhr.responseText === "string" ) {
16468									responses.text = xhr.responseText;
16469								}
16470
16471								// Firefox throws an exception when accessing
16472								// statusText for faulty cross-domain requests
16473								try {
16474									statusText = xhr.statusText;
16475								} catch( e ) {
16476									// We normalize with Webkit giving an empty statusText
16477									statusText = "";
16478								}
16479
16480								// Filter status for non standard behaviors
16481
16482								// If the request is local and we have data: assume a success
16483								// (success with no data won't get notified, that's the best we
16484								// can do given current implementations)
16485								if ( !status && options.isLocal && !options.crossDomain ) {
16486									status = responses.text ? 200 : 404;
16487								// IE - #1450: sometimes returns 1223 when it should be 204
16488								} else if ( status === 1223 ) {
16489									status = 204;
16490								}
16491							}
16492						}
16493
16494						// Call complete if needed
16495						if ( responses ) {
16496							complete( status, statusText, responses, xhr.getAllResponseHeaders() );
16497						}
16498					};
16499
16500					if ( !options.async ) {
16501						// if we're in sync mode we fire the callback
16502						callback();
16503					} else if ( xhr.readyState === 4 ) {
16504						// (IE6 & IE7) if it's in cache and has been
16505						// retrieved directly we need to fire the callback
16506						setTimeout( callback );
16507					} else {
16508						// Add to the list of active xhr callbacks
16509						xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
16510					}
16511				},
16512
16513				abort: function() {
16514					if ( callback ) {
16515						callback( undefined, true );
16516					}
16517				}
16518			};
16519		}
16520	});
16521}
16522
16523// Functions to create xhrs
16524function createStandardXHR() {
16525	try {
16526		return new window.XMLHttpRequest();
16527	} catch( e ) {}
16528}
16529
16530function createActiveXHR() {
16531	try {
16532		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
16533	} catch( e ) {}
16534}
16535
16536
16537
16538
16539// Install script dataType
16540jQuery1113.ajaxSetup({
16541	accepts: {
16542		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
16543	},
16544	contents: {
16545		script: /(?:java|ecma)script/
16546	},
16547	converters: {
16548		"text script": function( text ) {
16549			jQuery1113.globalEval( text );
16550			return text;
16551		}
16552	}
16553});
16554
16555// Handle cache's special case and global
16556jQuery1113.ajaxPrefilter( "script", function( s ) {
16557	if ( s.cache === undefined ) {
16558		s.cache = false;
16559	}
16560	if ( s.crossDomain ) {
16561		s.type = "GET";
16562		s.global = false;
16563	}
16564});
16565
16566// Bind script tag hack transport
16567jQuery1113.ajaxTransport( "script", function(s) {
16568
16569	// This transport only deals with cross domain requests
16570	if ( s.crossDomain ) {
16571
16572		var script,
16573			head = document.head || jQuery1113("head")[0] || document.documentElement;
16574
16575		return {
16576
16577			send: function( _, callback ) {
16578
16579				script = document.createElement("script");
16580
16581				script.async = true;
16582
16583				if ( s.scriptCharset ) {
16584					script.charset = s.scriptCharset;
16585				}
16586
16587				script.src = s.url;
16588
16589				// Attach handlers for all browsers
16590				script.onload = script.onreadystatechange = function( _, isAbort ) {
16591
16592					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
16593
16594						// Handle memory leak in IE
16595						script.onload = script.onreadystatechange = null;
16596
16597						// Remove the script
16598						if ( script.parentNode ) {
16599							script.parentNode.removeChild( script );
16600						}
16601
16602						// Dereference the script
16603						script = null;
16604
16605						// Callback if not abort
16606						if ( !isAbort ) {
16607							callback( 200, "success" );
16608						}
16609					}
16610				};
16611
16612				// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
16613				// Use native DOM manipulation to avoid our domManip AJAX trickery
16614				head.insertBefore( script, head.firstChild );
16615			},
16616
16617			abort: function() {
16618				if ( script ) {
16619					script.onload( undefined, true );
16620				}
16621			}
16622		};
16623	}
16624});
16625
16626
16627
16628
16629var oldCallbacks = [],
16630	rjsonp = /(=)\?(?=&|$)|\?\?/;
16631
16632// Default jsonp settings
16633jQuery1113.ajaxSetup({
16634	jsonp: "callback",
16635	jsonpCallback: function() {
16636		var callback = oldCallbacks.pop() || ( jQuery1113.expando + "_" + ( nonce++ ) );
16637		this[ callback ] = true;
16638		return callback;
16639	}
16640});
16641
16642// Detect, normalize options and install callbacks for jsonp requests
16643jQuery1113.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
16644
16645	var callbackName, overwritten, responseContainer,
16646		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
16647			"url" :
16648			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
16649		);
16650
16651	// Handle iff the expected data type is "jsonp" or we have a parameter to set
16652	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
16653
16654		// Get callback name, remembering preexisting value associated with it
16655		callbackName = s.jsonpCallback = jQuery1113.isFunction( s.jsonpCallback ) ?
16656			s.jsonpCallback() :
16657			s.jsonpCallback;
16658
16659		// Insert callback into url or form data
16660		if ( jsonProp ) {
16661			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
16662		} else if ( s.jsonp !== false ) {
16663			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
16664		}
16665
16666		// Use data converter to retrieve json after script execution
16667		s.converters["script json"] = function() {
16668			if ( !responseContainer ) {
16669				jQuery1113.error( callbackName + " was not called" );
16670			}
16671			return responseContainer[ 0 ];
16672		};
16673
16674		// force json dataType
16675		s.dataTypes[ 0 ] = "json";
16676
16677		// Install callback
16678		overwritten = window[ callbackName ];
16679		window[ callbackName ] = function() {
16680			responseContainer = arguments;
16681		};
16682
16683		// Clean-up function (fires after converters)
16684		jqXHR.always(function() {
16685			// Restore preexisting value
16686			window[ callbackName ] = overwritten;
16687
16688			// Save back as free
16689			if ( s[ callbackName ] ) {
16690				// make sure that re-using the options doesn't screw things around
16691				s.jsonpCallback = originalSettings.jsonpCallback;
16692
16693				// save the callback name for future use
16694				oldCallbacks.push( callbackName );
16695			}
16696
16697			// Call if it was a function and we have a response
16698			if ( responseContainer && jQuery1113.isFunction( overwritten ) ) {
16699				overwritten( responseContainer[ 0 ] );
16700			}
16701
16702			responseContainer = overwritten = undefined;
16703		});
16704
16705		// Delegate to script
16706		return "script";
16707	}
16708});
16709
16710
16711
16712
16713// data: string of html
16714// context (optional): If specified, the fragment will be created in this context, defaults to document
16715// keepScripts (optional): If true, will include scripts passed in the html string
16716jQuery1113.parseHTML = function( data, context, keepScripts ) {
16717	if ( !data || typeof data !== "string" ) {
16718		return null;
16719	}
16720	if ( typeof context === "boolean" ) {
16721		keepScripts = context;
16722		context = false;
16723	}
16724	context = context || document;
16725
16726	var parsed = rsingleTag.exec( data ),
16727		scripts = !keepScripts && [];
16728
16729	// Single tag
16730	if ( parsed ) {
16731		return [ context.createElement( parsed[1] ) ];
16732	}
16733
16734	parsed = jQuery1113.buildFragment( [ data ], context, scripts );
16735
16736	if ( scripts && scripts.length ) {
16737		jQuery1113( scripts ).remove();
16738	}
16739
16740	return jQuery1113.merge( [], parsed.childNodes );
16741};
16742
16743
16744// Keep a copy of the old load method
16745var _load = jQuery1113.fn.load;
16746
16747/**
16748 * Load a url into a page
16749 */
16750jQuery1113.fn.load = function( url, params, callback ) {
16751	if ( typeof url !== "string" && _load ) {
16752		return _load.apply( this, arguments );
16753	}
16754
16755	var selector, response, type,
16756		self = this,
16757		off = url.indexOf(" ");
16758
16759	if ( off >= 0 ) {
16760		selector = jQuery1113.trim( url.slice( off, url.length ) );
16761		url = url.slice( 0, off );
16762	}
16763
16764	// If it's a function
16765	if ( jQuery1113.isFunction( params ) ) {
16766
16767		// We assume that it's the callback
16768		callback = params;
16769		params = undefined;
16770
16771	// Otherwise, build a param string
16772	} else if ( params && typeof params === "object" ) {
16773		type = "POST";
16774	}
16775
16776	// If we have elements to modify, make the request
16777	if ( self.length > 0 ) {
16778		jQuery1113.ajax({
16779			url: url,
16780
16781			// if "type" variable is undefined, then "GET" method will be used
16782			type: type,
16783			dataType: "html",
16784			data: params
16785		}).done(function( responseText ) {
16786
16787			// Save response for use in complete callback
16788			response = arguments;
16789
16790			self.html( selector ?
16791
16792				// If a selector was specified, locate the right elements in a dummy div
16793				// Exclude scripts to avoid IE 'Permission Denied' errors
16794				jQuery1113("<div>").append( jQuery1113.parseHTML( responseText ) ).find( selector ) :
16795
16796				// Otherwise use the full result
16797				responseText );
16798
16799		}).complete( callback && function( jqXHR, status ) {
16800			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
16801		});
16802	}
16803
16804	return this;
16805};
16806
16807
16808
16809
16810// Attach a bunch of functions for handling common AJAX events
16811jQuery1113.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
16812	jQuery1113.fn[ type ] = function( fn ) {
16813		return this.on( type, fn );
16814	};
16815});
16816
16817
16818
16819
16820jQuery1113.expr.filters.animated = function( elem ) {
16821	return jQuery1113.grep(jQuery1113.timers, function( fn ) {
16822		return elem === fn.elem;
16823	}).length;
16824};
16825
16826
16827
16828
16829
16830var docElem = window.document.documentElement;
16831
16832/**
16833 * Gets a window from an element
16834 */
16835function getWindow( elem ) {
16836	return jQuery1113.isWindow( elem ) ?
16837		elem :
16838		elem.nodeType === 9 ?
16839			elem.defaultView || elem.parentWindow :
16840			false;
16841}
16842
16843jQuery1113.offset = {
16844	setOffset: function( elem, options, i ) {
16845		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
16846			position = jQuery1113.css( elem, "position" ),
16847			curElem = jQuery1113( elem ),
16848			props = {};
16849
16850		// set position first, in-case top/left are set even on static elem
16851		if ( position === "static" ) {
16852			elem.style.position = "relative";
16853		}
16854
16855		curOffset = curElem.offset();
16856		curCSSTop = jQuery1113.css( elem, "top" );
16857		curCSSLeft = jQuery1113.css( elem, "left" );
16858		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
16859			jQuery1113.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
16860
16861		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
16862		if ( calculatePosition ) {
16863			curPosition = curElem.position();
16864			curTop = curPosition.top;
16865			curLeft = curPosition.left;
16866		} else {
16867			curTop = parseFloat( curCSSTop ) || 0;
16868			curLeft = parseFloat( curCSSLeft ) || 0;
16869		}
16870
16871		if ( jQuery1113.isFunction( options ) ) {
16872			options = options.call( elem, i, curOffset );
16873		}
16874
16875		if ( options.top != null ) {
16876			props.top = ( options.top - curOffset.top ) + curTop;
16877		}
16878		if ( options.left != null ) {
16879			props.left = ( options.left - curOffset.left ) + curLeft;
16880		}
16881
16882		if ( "using" in options ) {
16883			options.using.call( elem, props );
16884		} else {
16885			curElem.css( props );
16886		}
16887	}
16888};
16889
16890jQuery1113.fn.extend({
16891	offset: function( options ) {
16892		if ( arguments.length ) {
16893			return options === undefined ?
16894				this :
16895				this.each(function( i ) {
16896					jQuery1113.offset.setOffset( this, options, i );
16897				});
16898		}
16899
16900		var docElem, win,
16901			box = { top: 0, left: 0 },
16902			elem = this[ 0 ],
16903			doc = elem && elem.ownerDocument;
16904
16905		if ( !doc ) {
16906			return;
16907		}
16908
16909		docElem = doc.documentElement;
16910
16911		// Make sure it's not a disconnected DOM node
16912		if ( !jQuery1113.contains( docElem, elem ) ) {
16913			return box;
16914		}
16915
16916		// If we don't have gBCR, just use 0,0 rather than error
16917		// BlackBerry 5, iOS 3 (original iPhone)
16918		if ( typeof elem.getBoundingClientRect !== strundefined ) {
16919			box = elem.getBoundingClientRect();
16920		}
16921		win = getWindow( doc );
16922		return {
16923			top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
16924			left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
16925		};
16926	},
16927
16928	position: function() {
16929		if ( !this[ 0 ] ) {
16930			return;
16931		}
16932
16933		var offsetParent, offset,
16934			parentOffset = { top: 0, left: 0 },
16935			elem = this[ 0 ];
16936
16937		// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
16938		if ( jQuery1113.css( elem, "position" ) === "fixed" ) {
16939			// we assume that getBoundingClientRect is available when computed position is fixed
16940			offset = elem.getBoundingClientRect();
16941		} else {
16942			// Get *real* offsetParent
16943			offsetParent = this.offsetParent();
16944
16945			// Get correct offsets
16946			offset = this.offset();
16947			if ( !jQuery1113.nodeName( offsetParent[ 0 ], "html" ) ) {
16948				parentOffset = offsetParent.offset();
16949			}
16950
16951			// Add offsetParent borders
16952			parentOffset.top  += jQuery1113.css( offsetParent[ 0 ], "borderTopWidth", true );
16953			parentOffset.left += jQuery1113.css( offsetParent[ 0 ], "borderLeftWidth", true );
16954		}
16955
16956		// Subtract parent offsets and element margins
16957		// note: when an element has margin: auto the offsetLeft and marginLeft
16958		// are the same in Safari causing offset.left to incorrectly be 0
16959		return {
16960			top:  offset.top  - parentOffset.top - jQuery1113.css( elem, "marginTop", true ),
16961			left: offset.left - parentOffset.left - jQuery1113.css( elem, "marginLeft", true)
16962		};
16963	},
16964
16965	offsetParent: function() {
16966		return this.map(function() {
16967			var offsetParent = this.offsetParent || docElem;
16968
16969			while ( offsetParent && ( !jQuery1113.nodeName( offsetParent, "html" ) && jQuery1113.css( offsetParent, "position" ) === "static" ) ) {
16970				offsetParent = offsetParent.offsetParent;
16971			}
16972			return offsetParent || docElem;
16973		});
16974	}
16975});
16976
16977// Create scrollLeft and scrollTop methods
16978jQuery1113.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
16979	var top = /Y/.test( prop );
16980
16981	jQuery1113.fn[ method ] = function( val ) {
16982		return access( this, function( elem, method, val ) {
16983			var win = getWindow( elem );
16984
16985			if ( val === undefined ) {
16986				return win ? (prop in win) ? win[ prop ] :
16987					win.document.documentElement[ method ] :
16988					elem[ method ];
16989			}
16990
16991			if ( win ) {
16992				win.scrollTo(
16993					!top ? val : jQuery1113( win ).scrollLeft(),
16994					top ? val : jQuery1113( win ).scrollTop()
16995				);
16996
16997			} else {
16998				elem[ method ] = val;
16999			}
17000		}, method, val, arguments.length, null );
17001	};
17002});
17003
17004// Add the top/left cssHooks using jQuery1113.fn.position
17005// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
17006// getComputedStyle returns percent when specified for top/left/bottom/right
17007// rather than make the css module depend on the offset module, we just check for it here
17008jQuery1113.each( [ "top", "left" ], function( i, prop ) {
17009	jQuery1113.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
17010		function( elem, computed ) {
17011			if ( computed ) {
17012				computed = curCSS( elem, prop );
17013				// if curCSS returns percentage, fallback to offset
17014				return rnumnonpx.test( computed ) ?
17015					jQuery1113( elem ).position()[ prop ] + "px" :
17016					computed;
17017			}
17018		}
17019	);
17020});
17021
17022
17023// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
17024jQuery1113.each( { Height: "height", Width: "width" }, function( name, type ) {
17025	jQuery1113.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
17026		// margin is only for outerHeight, outerWidth
17027		jQuery1113.fn[ funcName ] = function( margin, value ) {
17028			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
17029				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
17030
17031			return access( this, function( elem, type, value ) {
17032				var doc;
17033
17034				if ( jQuery1113.isWindow( elem ) ) {
17035					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
17036					// isn't a whole lot we can do. See pull request at this URL for discussion:
17037					// https://github.com/jQuery1113/jQuery1113/pull/764
17038					return elem.document.documentElement[ "client" + name ];
17039				}
17040
17041				// Get document width or height
17042				if ( elem.nodeType === 9 ) {
17043					doc = elem.documentElement;
17044
17045					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
17046					// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
17047					return Math.max(
17048						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
17049						elem.body[ "offset" + name ], doc[ "offset" + name ],
17050						doc[ "client" + name ]
17051					);
17052				}
17053
17054				return value === undefined ?
17055					// Get width or height on the element, requesting but not forcing parseFloat
17056					jQuery1113.css( elem, type, extra ) :
17057
17058					// Set width or height on the element
17059					jQuery1113.style( elem, type, value, extra );
17060			}, type, chainable ? margin : undefined, chainable, null );
17061		};
17062	});
17063});
17064
17065
17066// The number of elements contained in the matched element set
17067jQuery1113.fn.size = function() {
17068	return this.length;
17069};
17070
17071jQuery1113.fn.andSelf = jQuery1113.fn.addBack;
17072
17073
17074
17075
17076// Register as a named AMD module, since jQuery1113 can be concatenated with other
17077// files that may use define, but not via a proper concatenation script that
17078// understands anonymous AMD modules. A named AMD is safest and most robust
17079// way to register. Lowercase jQuery1113 is used because AMD module names are
17080// derived from file names, and jQuery1113 is normally delivered in a lowercase
17081// file name. Do this after creating the global so that if an AMD module wants
17082// to call noConflict to hide this version of jQuery1113, it will work.
17083
17084// Note that for maximum portability, libraries that are not jQuery1113 should
17085// declare themselves as anonymous modules, and avoid setting a global if an
17086// AMD loader is present. jQuery1113 is a special case. For more information, see
17087// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
17088
17089if ( typeof define === "function" && define.amd ) {
17090	define( "jQuery1113", [], function() {
17091		return jQuery1113;
17092	});
17093}
17094
17095
17096
17097
17098var
17099	// Map over jQuery1113 in case of overwrite
17100	_jQuery1113 = window.jQuery1113,
17101
17102	// Map over the $ in case of overwrite
17103	_$ = window.$;
17104
17105jQuery1113.noConflict = function( deep ) {
17106	if ( window.$ === jQuery1113 ) {
17107		window.$ = _$;
17108	}
17109
17110	if ( deep && window.jQuery1113 === jQuery1113 ) {
17111		window.jQuery1113 = _jQuery1113;
17112	}
17113
17114	return jQuery1113;
17115};
17116
17117// Expose jQuery1113 and $ identifiers, even in
17118// AMD (#7102#comment:10, https://github.com/jQuery1113/jQuery1113/pull/557)
17119// and CommonJS for browser emulators (#13566)
17120if ( typeof noGlobal === strundefined ) {
17121	window.jQuery1113 = window.$ = jQuery1113;
17122}
17123
17124
17125
17126
17127return jQuery1113;
17128
17129}));
17130
17131
17132var j = jQuery1113.noConflict();! function(e) {
17133    var i = {
17134        logo_align: "left",
17135        links_align: "left",
17136        socialBar_align: "left",
17137        searchBar_align: "right",
17138        trigger: "hover",
17139        effect: "fade",
17140        effect_speed: 400,
17141        sibling: !0,
17142        outside_click_close: !0,
17143        top_fixed: !1,
17144        sticky_header: !1,
17145        sticky_header_height: 200,
17146        menu_position: "horizontal",
17147        full_width: !0,
17148        mobile_settings: {
17149            collapse: !1,
17150            sibling: !0,
17151            scrollBar: !0,
17152            scrollBar_height: 400,
17153            top_fixed: !1,
17154            sticky_header: !1,
17155            sticky_header_height: 200
17156        }
17157    };
17158    e.fn.megaMenu = function(o) {
17159        return o = e.extend({}, i, o || {}), this.each(function() {
17160            var i, s = e(this),
17161                t = "ul",
17162                n = "li",
17163                a = "a",
17164                r = s.find(".menu-logo"),
17165                l = r.children(n),
17166                d = s.find(".menu-links"),
17167                c = d.children(n),
17168                f = s.find(".menu-social-bar"),
17169                _ = s.find(".menu-search-bar"),
17170                p = ".menu-mobile-collapse-trigger",
17171                g = ".mobileTriggerButton",
17172                u = ".desktopTriggerButton",
17173                h = "active",
17174                m = "activeTrigger",
17175                b = "activeTriggerMobile",
17176                v = ".mg-drop-down-multilevel, .mg-drop-down, .mg-drop-down-tab-bar",
17177                C = "desktopTopFixed",
17178                w = "mobileTopFixed",
17179                k = "menuFullWidth",
17180                y = s.find(".menu-contact-form"),
17181                x = y.find(".nav_form_notification");
17182            i = {
17183                contact_form_ajax: function() {
17184                    e(y).submit(function(i) {
17185                        var o = e(this);
17186                        i.preventDefault();
17187                        var s = e(this).serialize();
17188                        o.find("button i.fa").css("display", "inline-block"), e.ajax({
17189                            type: "POST",
17190                            url: e(this).attr("action"),
17191                            data: s
17192                        }).done(function(e) {
17193                            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")
17194                        }).fail(function(e) {
17195                            "" !== e.responseText && x.text("Error"), o.find("button i.fa").css("display", "none")
17196                        })
17197                    })
17198                },
17199                menu_full_width: function() {
17200                    o.full_width === !0 && s.addClass(k)
17201                },
17202                logo_Align: function() {
17203                    "right" === o.logo_align ? r.addClass("menu-logo-align-right") : r.removeClass("menu-logo-align-right")
17204                },
17205                links_Align: function() {
17206                    "right" === o.links_align ? d.addClass("menu-links-align-right") : d.removeClass("menu-links-align-right")
17207                },
17208                social_bar_Align: function() {
17209                    "right" === o.socialBar_align ? f.addClass("menu-social-bar-right") : f.removeClass("menu-social-bar-right")
17210                },
17211                search_bar_Align: function() {
17212                    "left" === o.searchBar_align ? _.addClass("menu-search-bar-left") : _.removeClass("menu-search-bar-left")
17213                },
17214                collapse_trigger_button: function() {
17215                    if (o.mobile_settings.collapse === !0) {
17216                        l.append('<div class="menu-mobile-collapse-trigger"><span></span></div>');
17217                        var i = d.add(f);
17218                        i.hide(0), _.addClass(h), s.find(p).on("click", function() {
17219                            return i.is(":hidden") ? (e(this).addClass(h), i.show(0)) : (e(this).removeClass(h), i.hide(0)), !1
17220                        })
17221                    }
17222                },
17223                switch_effect_remove: function() {
17224                    s.find(v).removeClass("effect-fade effect-scale effect-expand-top effect-expand-bottom effect-expand-left effect-expand-right")
17225                },
17226                switch_effects: function() {
17227                    switch (o.effect) {
17228                        case "fade":
17229                            this.switch_effect_remove(), s.find(v).addClass("effect-fade");
17230                            break;
17231                        case "scale":
17232                            this.switch_effect_remove(), s.find(v).addClass("effect-scale");
17233                            break;
17234                        case "expand-top":
17235                            this.switch_effect_remove(), s.find(v).addClass("effect-expand-top");
17236                            break;
17237                        case "expand-bottom":
17238                            this.switch_effect_remove(), s.find(v).addClass("effect-expand-bottom");
17239                            break;
17240                        case "expand-left":
17241                            this.switch_effect_remove(), s.find(v).addClass("effect-expand-left");
17242                            break;
17243                        case "expand-right":
17244                            this.switch_effect_remove(), s.find(v).addClass("effect-expand-right")
17245                    }
17246                },
17247                transition_delay: function() {
17248                    s.find(v).css({
17249                        webkitTransition: "all " + o.effect_speed + "ms ease ",
17250                        transition: "all " + o.effect_speed + "ms ease "
17251                    })
17252                },
17253                hover_trigger: function() {
17254                    "hover" === o.trigger && (i.transition_delay(), s.find(v).parents(n).addClass("hoverTrigger"), i.switch_effects())
17255                },
17256                mobile_trigger: function() {
17257                    0 === s.find(".mobileTriggerButton").length && s.find(v).prev(a).append('<div class="mobileTriggerButton"></div>'), 
17258                    s.find(g).each(function(){
17259                        $this=$(this);
17260                        $menuBox = $(this).parents('li').find('.megamenu_box');
17261                        //檢查有沒有副清單的內容
17262                        var menuBoxChildCount = 0;
17263                        $menuBox.children().each(function(){
17264                            if($(this).attr('class').toLowerCase() !== 'clearfix'){
17265                                menuBoxChildCount = menuBoxChildCount + 1;
17266                                return;
17267                            }
17268                        });
17269                        if (menuBoxChildCount === 0)
17270                            $this.parent().siblings('.mg-drop-down').removeClass('effect-fade');
17271                        $this.off("click").on("click", function() {
17272                            var i = e(this),
17273                                r = i.parents(a),
17274                                l = r.next(v);
17275                            //副清單沒有東西時,點這個div也觸發父node a
17276                            menuBoxChildCount === 0 ? r[0].click():"";
17277                            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
17278                        });
17279                    }), s.find("i.fa.fa-indicator").on("click", function() {
17280                        return !1
17281                    }),s.find(v).prev(a).on("click", function(el) {
17282                        var i = e(this),
17283                            l = i.next(v);
17284                        var iUrl = i.attr('href').trim().toLowerCase();
17285                        if (iUrl.startsWith('#') || iUrl.startsWith('javascript'))
17286                            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
17287                    })
17288                },
17289                click_trigger: function() {
17290                    "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) {
17291                        i.stopPropagation(), i.stopImmediatePropagation();
17292                        var r = e(this),
17293                            l = r.parents(a),
17294                            d = l.next(v);
17295                        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))
17296                    }))
17297                },
17298                outside_close: function() {
17299                    o.outside_click_close === !0 && "click" === o.trigger && s.find(v).is(":visible") ? e(document).off("
17299click").on("click", function(e) {
17300                        s.is(e.target) || 0 !== s.has(e.target).length || (s.find(v).removeClass(h), c.removeClass("activeTrigger"))
17301                    }) : e(document).off("click")
17302                },
17303                scroll_bar: function() {
17304                    o.mobile_settings.scrollBar === !0 && d.css({
17305                        maxHeight: o.mobile_settings.scrollBar_height + "px",
17306                        overflow: "auto"
17307                    })
17308                },
17309                top_Fixed: function() {
17310                    o.top_fixed === !0 ? s.addClass(C) : s.removeClass(C), o.mobile_settings.top_fixed ? s.addClass(w) : s.removeClass(w)
17311                },
17312                sticky_Header: function() {
17313                    var i = e(window),
17314                        t = !0,
17315                        n = !0;
17316                    s.find(v).is(":hidden") ? (i.off("scroll"), o.mobile_settings.sticky_header === !0 && o.top_fixed === !1 && i.on("scroll", function() {
17317                        i.scrollTop() > o.mobile_settings.sticky_header_height ? n === !0 && (s.addClass(w), n = !1) : n === !1 && (s.removeClass(w), n = !0)
17318                    })) : (i.off("scroll"), o.sticky_header === !0 && "horizontal" === o.menu_position && o.top_fixed === !1 && i.on("scroll", function() {
17319                        i.scrollTop() > o.sticky_header_height ? t === !0 && (s.fadeOut(200, function() {
17320                            e(this).addClass(C).fadeIn(200)
17321                        }), t = !1) : t === !1 && (s.fadeOut(200, function() {
17322                            e(this).removeClass(C).fadeIn(200)
17323                        }), t = !0)
17324                    }))
17325                },
17326                position: function() {
17327                    "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")
17328                },
17329                destroy_menu: function() {
17330                    s.find(v).parents(n).removeClass("hoverTrigger"), s.find(v).parents(n).removeClass("ClickTrigger")
17331                }
17332            }, 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() {
17333                i.outside_close(), i.sticky_Header()
17334            })
17335        })
17336    }
17337}(jQuery1113);(function($) {
17338    $(function() {
17339        
17340        var $sel = $('[data-unicode="mdu_AlDbPJ38W0OMN0X6I9c3ww"]');
17341        
17342        $sel.find('.menu-links > li.main-hover').hover(function () {
17343            if($(this).data('main-hover'))
17344                $(this).css('background', $(this).data('main-hover'));
17345        }, function () {
17346            if($(this).data('main-recovery'))
17347                $(this).css('background', $(this).data('main-recovery'));
17348            else
17349                $(this).css('background', '');
17350        })
17351
17352        $sel.find('.menu-links > li .list_box ul li a.sub-hover').hover(function () {
17353            if($(this).data('sub-hover'))
17354                $(this).css('color', $(this).data('sub-hover'));
17355        }, function () {
17356            if($(this).data('sub-recovery'))
17357                $(this).css('color', $(this).data('sub-recovery'));
17358            else
17359                $(this).css('color', '');
17360        });
17361
17362        //下拉選單沒有內容就不顯示
17363        $sel.find('.menu-links > li').each(function(){
17364            //ˇ箭頭的icon
17365            $icon = $(this).children('a').first().children('.fa-angle-down');
17366            $dropdown = $(this).find('.mg-drop-down');
17367            $menuBox = $(this).find('.megamenu_box');
17368            //menuBox空的話不需要顯示
17369            if($menuBox.children().length == 0)
17370            {
17371                $dropdown.addClass('d-none')
17372                $icon.addClass('d-none');
17373                return;
17374            }else {
17375                var menuBoxChildCount = 0;
17376                $menuBox.children().each(function(){
17377                    if($(this).attr('class').toLowerCase() !== 'clearfix'){
17378                        menuBoxChildCount = menuBoxChildCount + 1;
17379                        return;
17380                    }
17381                });
17382                //除了<div class='clearfix'></div>以外沒有東西的話不需要顯示。(備註:.clearfix這個目前不管怎樣都會生成20221004)
17383                if (menuBoxChildCount == 0){
17384                    $dropdown.addClass('d-none')
17385                    $icon.addClass('d-none');
17386                }
17387            }
17388        });
17389
17390        // menu initialize
17391        $sel.children('nav.mega-menu').megaMenu({
17392            // MOBILE MODE SETTINGS
17393            mobile_settings: {
17394                collapse: true,
17395                sibling: true,
17396                scrollBar: true,
17397                scrollBar_height: 400,
17398                top_fixed: false,
17399                sticky_header: false,
17400                sticky_header_height: 200
17401            }
17402        });
17403
17404    });
17405})(jQuery1113);
17406
17407; })(jQuery);/* compress error:[4]function encode(int) {*/
17408
17409/* MODULE 00c188ed-cbd7-4c68-87dd-d3e4f1ac9a2e, Version: 1.0.7 */
17410;(function($) {var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
17411
17412// NB: does not validate input
17413function encode(int) {
17414    if (int === 0) {
17415        return CHARSET[0];
17416    }
17417
17418    var res = "";
17419    while (int > 0) {
17420        res = CHARSET[int % 62] + res;
17421        int = Math.floor(int / 62);
17422    }
17423    return res;
17424};
17425
17426function decode(str) {
17427    var res = 0,
17428        length = str.length,
17429        i, char;
17430    for (i = 0; i < length; i++) {
17431        char = str.charCodeAt(i);
17432        if (char < 58) { // 0-9
17433            char = char - 48;
17434        } else if (char < 91) { // A-Z
17435            char = char - 29;
17436        } else { // a-z
17437            char = char - 87;
17438        }
17439        res += char * Math.pow(62, length - i - 1);
17440    }
17441    return res;
17442};
17443
17444function base62() {
17445    var id; //base62
17446    do {
17447      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
17448    } while (id.match(/^[0-9]/i) !== null);
17449    return id;
17450}(function($) {
17451    $(function() {
17452    	$('[data-unicode="mdu_3jF6Pic8kUeJ2ULe7Rgtw"]').each (function () {
17453		  var $sel = $(this);
17454		  var id; //base62
17455		      do {
17456		        id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
17457		      } while (id.match(/^[0-9]/i) !== null);
17458		  $sel.attr('id',id);
17459
17460		  $sel.children('.btm-btn').each (function (i) {
17461			  	var $sel2 = $(this);
17462			  	var id2 = id+'_'+i;
17463			  	$sel2.addClass(id2);
17464			  	if($sel2.hasClass('open-btn')) {
17465			  		$sel2.attr('id',id2);
17466			  		$sel2.next('div').attr('id',id2+'_box');
17467			  		$sel2.next('div').children('.close-line').attr('id',id2+'_close');
17468			  	}
17469
17470			  	var $fontColor = $sel2.data('fontColor');
17471			  	var $nowColor = $sel2.data('nowColor');
17472			  	var $img = $sel2.data('img');
17473			  	var $nowImg = $sel2.data('nowImg');
17474			  	var $imgY = $sel2.data('imgY');
17475			  	var $imgSize = $sel2.data('imgSize');
17476
17477			  	$sel.prepend('<style type="text/css">'+
17478		        '#'+id+' '+'.'+id2+' {background: url("'+$img+'") no-repeat center '+$imgY+'; background-size: '+$imgSize+';}'+
17479		        '\n'+'#'+id+' '+'.'+id2+'-now {color: '+$nowColor+' !important; background: #eee url("'+$nowImg+'") no-repeat center '+$imgY+'; background-size: '+$imgSize+';}'+
17480		      	'</style>');
17481
17482		  });
17483
17484		  $('.open-btn').on('click', function () {
17485	            var $btnID = $(this).attr('id');
17486	            var $boxID = $btnID + '_box';
17487	            var $btnClass = $(this).attr('class');
17488	            var $btnNowClass = $btnID+'-now';
17489	            var $closeLineID = $(this).next('div').find('.close-line').attr('id');
17490
17491	            $('.open-btn[class$="-now"]').each (function () {
17492	            	var $orgClass = $(this).attr('class');
17493	            	var $repClass = $orgClass.replace('-now','');
17494	            	$(this).removeClass().addClass($repClass);
17495	            });
17496
17497	            $(this).toggleClass($btnNowClass);
17498	            
17499	            $('.open-box').not('#'+$boxID).hide();
17500	            $('#'+$boxID).toggle('show');
17501
17502	            $('#'+$closeLineID).on('click', function () {
17503	            	$('#'+$boxID).hide();
17504	            	$('#'+$btnID).removeClass().addClass($btnClass);
17505	      	  	});
17506
17507      	  });
17508
17509
17510		});
17511
17512    });
17513})(jQuery);
17514
17515; })(jQuery);/* compress error:[4]function encode(int) {*/
17516
17517/* MODULE 51efd658-95fe-4b29-bc4c-603c6613e893, Version: 1.0.8 */
17518(function(a){(function(b){b(function(){var e=b('[data-unicode="mdu_ZHeG8jCdJ0iEMSS6D06M0w"]');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);
17519/* MODULE ebe73f1b-af22-4d91-9ffe-a3edf5e4248b, Version: 2.1.12 */
17520(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_VHUVgxI6jE28AOoaBRtpBQ"]');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);
17521/* MODULE 94105903-4a46-498d-8b55-7c28d991e678, Version: 1.1.16 */
17522;(function($) {; var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
17523
vendor: 21,598 bytes, lines 17524-17567
17524// NB: does not validate input
17525function encode(int) {
17526    if (int === 0) {
17527        return CHARSET[0];
17528    }
17529
17530    var res = "";
17531    while (int > 0) {
17532        res = CHARSET[int % 62] + res;
17533        int = Math.floor(int / 62);
17534    }
17535    return res;
17536};
17537
17538function decode(str) {
17539    var res = 0,
17540        length = str.length,
17541        i, char;
17542    for (i = 0; i < length; i++) {
17543        char = str.charCodeAt(i);
17544        if (char < 58) { // 0-9
17545            char = char - 48;
17546        } else if (char < 91) { // A-Z
17547            char = char - 29;
17548        } else { // a-z
17549            char = char - 87;
17550        }
17551        res += char * Math.pow(62, length - i - 1);
17552    }
17553    return res;
17554};
17555
17556function base62() {
17557    var id; //base62
17558    do {
17559      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
17560    } while (id.match(/^[0-9]/i) !== null);
17561    return id;
17562}/*! Hammer.JS - v2.0.8 - 2016-04-23
17563 * http://hammerjs.github.io/
17564 *
17565 * Copyright (c) 2016 Jorik Tangelder;
17566 * Licensed under the MIT license */
17567!function (a, b, c, d) { "use strict"; function e(a, b, c) { return setTimeout(j(a, c), b) } function f(a, b, c) { return Array.isArray(a) ? (g(a, c[b], c), !0) : !1 } function g(a, b, c) { var e; if (a) if (a.forEach) a.forEach(b, c); else if (a.length !== d) for (e = 0; e < a.length;)b.call(c, a[e], e, a), e++; else for (e in a) a.hasOwnProperty(e) && b.call(c, a[e], e, a) } function h(b, c, d) { var e = "DEPRECATED METHOD: " + c + "\n" + d + " AT \n"; return function () { var c = new Error("get-stack-trace"), d = c && c.stack ? c.stack.replace(/^[^\(]+?[\n$]/gm, "").replace(/^\s+at\s+/gm, "").replace(/^Object.<anonymous>\s*\(/gm, "{anonymous}()@") : "Unknown Stack Trace", f = a.console && (a.console.warn || a.console.log); return f && f.call(a.console, e, d), b.apply(this, arguments) } } function i(a, b, c) { var d, e = b.prototype; d = a.prototype = Object.create(e), d.constructor = a, d._super = e, c && la(d, c) } function j(a, b) { return function () { return a.apply(b, arguments) } } function k(a, b) { return typeof a == oa ? a.apply(b ? b[0] || d : d, b) : a } function l(a, b) { return a === d ? b : a } function m(a, b, c) { g(q(b), function (b) { a.addEventListener(b, c, !1) }) } function n(a, b, c) { g(q(b), function (b) { a.removeEventListener(b, c, !1) }) } function o(a, b) { for (; a;) { if (a == b) return !0; a = a.parentNode } return !1 } function p(a, b) { return a.indexOf(b) > -1 } function q(a) { return a.trim().split(/\s+/g) } function r(a, b, c) { if (a.indexOf && !c) return a.indexOf(b); for (var d = 0; d < a.length;) { if (c && a[d][c] == b || !c && a[d] === b) return d; d++ } return -1 } function s(a) { return Array.prototype.slice.call(a, 0) } function t(a, b, c) { for (var d = [], e = [], f = 0; f < a.length;) { var g = b ? a[f][b] : a[f]; r(e, g) < 0 && d.push(a[f]), e[f] = g, f++ } return c && (d = b ? d.sort(function (a, c) { return a[b] > c[b] }) : d.sort()), d } function u(a, b) { for (var c, e, f = b[0].toUpperCase() + b.slice(1), g = 0; g < ma.length;) { if (c = ma[g], e = c ? c + f : b, e in a) return e; g++ } return d } function v() { return ua++ } function w(b) { var c = b.ownerDocument || b; return c.defaultView || c.parentWindow || a } function x(a, b) { var c = this; this.manager = a, this.callback = b, this.element = a.element, this.target = a.options.inputTarget, this.domHandler = function (b) { k(a.options.enable, [a]) && c.handler(b) }, this.init() } function y(a) { var b, c = a.options.inputClass; return new (b = c ? c : xa ? M : ya ? P : wa ? R : L)(a, z) } function z(a, b, c) { var d = c.pointers.length, e = c.changedPointers.length, f = b & Ea && d - e === 0, g = b & (Ga | Ha) && d - e === 0; c.isFirst = !!f, c.isFinal = !!g, f && (a.session = {}), c.eventType = b, A(a, c), a.emit("hammer.input", c), a.recognize(c), a.session.prevInput = c } function A(a, b) { var c = a.session, d = b.pointers, e = d.length; c.firstInput || (c.firstInput = D(b)), e > 1 && !c.firstMultiple ? c.firstMultiple = D(b) : 1 === e && (c.firstMultiple = !1); var f = c.firstInput, g = c.firstMultiple, h = g ? g.center : f.center, i = b.center = E(d); b.timeStamp = ra(), b.deltaTime = b.timeStamp - f.timeStamp, b.angle = I(h, i), b.distance = H(h, i), B(c, b), b.offsetDirection = G(b.deltaX, b.deltaY); var j = F(b.deltaTime, b.deltaX, b.deltaY); b.overallVelocityX = j.x, b.overallVelocityY = j.y, b.overallVelocity = qa(j.x) > qa(j.y) ? j.x : j.y, b.scale = g ? K(g.pointers, d) : 1, b.rotation = g ? J(g.pointers, d) : 0, b.maxPointers = c.prevInput ? b.pointers.length > c.prevInput.maxPointers ? b.pointers.length : c.prevInput.maxPointers : b.pointers.length, C(c, b); var k = a.element; o(b.srcEvent.target, k) && (k = b.srcEvent.target), b.target = k } function B(a, b) { var c = b.center, d = a.offsetDelta || {}, e = a.prevDelta || {}, f = a.prevInput || {}; b.eventType !== Ea && f.eventType !== Ga || (e = a.prevDelta = { x: f.deltaX || 0, y: f.deltaY || 0 }, d = a.offsetDelta = { x: c.x, y: c.y }), b.deltaX = e.x + (c.x - d.x), b.deltaY = e.y + (c.y - d.y) } function C(a, b) { var c, e, f, g, h = a.lastInterval || b, i = b.timeStamp - h.timeStamp; if (b.eventType != Ha && (i > Da || h.velocity === d)) { var j = b.deltaX - h.deltaX, k = b.deltaY - h.deltaY, l = F(i, j, k); e = l.x, f = l.y, c = qa(l.x) > qa(l.y) ? l.x : l.y, g = G(j, k), a.lastInterval = b } else c = h.velocity, e = h.velocityX, f = h.velocityY, g = h.direction; b.velocity = c, b.velocityX = e, b.velocityY = f, b.direction = g } function D(a) { for (var b = [], c = 0; c < a.pointers.length;)b[c] = { clientX: pa(a.pointers[c].clientX), clientY: pa(a.pointers[c].clientY) }, c++; return { timeStamp: ra(), pointers: b, center: E(b), deltaX: a.deltaX, deltaY: a.deltaY } } function E(a) { var b = a.length; if (1 === b) return { x: pa(a[0].clientX), y: pa(a[0].clientY) }; for (var c = 0, d = 0, e = 0; b > e;)c += a[e].clientX, d += a[e].clientY, e++; return { x: pa(c / b), y: pa(d / b) } } function F(a, b, c) { return { x: b / a || 0, y: c / a || 0 } } function G(a, b) { return a === b ? Ia : qa(a) >= qa(b) ? 0 > a ? Ja : Ka : 0 > b ? La : Ma } function H(a, b, c) { c || (c = Qa); var d = b[c[0]] - a[c[0]], e = b[c[1]] - a[c[1]]; return Math.sqrt(d * d + e * e) } function I(a, b, c) { c || (c = Qa); var d = b[c[0]] - a[c[0]], e = b[c[1]] - a[c[1]]; return 180 * Math.atan2(e, d) / Math.PI } function J(a, b) { return I(b[1], b[0], Ra) + I(a[1], a[0], Ra) } function K(a, b) { return H(b[0], b[1], Ra) / H(a[0], a[1], Ra) } function L() { this.evEl = Ta, this.evWin = Ua, this.pressed = !1, x.apply(this, arguments) } function M() { this.evEl = Xa, this.evWin = Ya, x.apply(this, arguments), this.store = this.manager.session.pointerEvents = [] } function N() { this.evTarget = $a, this.evWin = _a, this.started = !1, x.apply(this, arguments) } function O(a, b) { var c = s(a.touches), d = s(a.changedTouches); return b & (Ga | Ha) && (c = t(c.concat(d), "identifier", !0)), [c, d] } function P() { this.evTarget = bb, this.targetIds = {}, x.apply(this, arguments) } function Q(a, b) { var c = s(a.touches), d = this.targetIds; if (b & (Ea | Fa) && 1 === c.length) return d[c[0].identifier] = !0, [c, c]; var e, f, g = s(a.changedTouches), h = [], i = this.target; if (f = c.filter(function (a) { return o(a.target, i) }), b === Ea) for (e = 0; e < f.length;)d[f[e].identifier] = !0, e++; for (e = 0; e < g.length;)d[g[e].identifier] && h.push(g[e]), b & (Ga | Ha) && delete d[g[e].identifier], e++; return h.length ? [t(f.concat(h), "identifier", !0), h] : void 0 } function R() { x.apply(this, arguments); var a = j(this.handler, this); this.touch = new P(this.manager, a), this.mouse = new L(this.manager, a), this.primaryTouch = null, this.lastTouches = [] } function S(a, b) { a & Ea ? (this.primaryTouch = b.changedPointers[0].identifier, T.call(this, b)) : a & (Ga | Ha) && T.call(this, b) } function T(a) { var b = a.changedPointers[0]; if (b.identifier === this.primaryTouch) { var c = { x: b.clientX, y: b.clientY }; this.lastTouches.push(c); var d = this.lastTouches, e = function () { var a = d.indexOf(c); a > -1 && d.splice(a, 1) }; setTimeout(e, cb) } } function U(a) { for (var b = a.srcEvent.clientX, c = a.srcEvent.clientY, d = 0; d < this.lastTouches.length; d++) { var e = this.lastTouches[d], f = Math.abs(b - e.x), g = Math.abs(c - e.y); if (db >= f && db >= g) return !0 } return !1 } function V(a, b) { this.manager = a, this.set(b) } function W(a) { if (p(a, jb)) return jb; var b = p(a, kb), c = p(a, lb); return b && c ? jb : b || c ? b ? kb : lb : p(a, ib) ? ib : hb } function X() { if (!fb) return !1; var b = {}, c = a.CSS && a.CSS.supports; return ["auto", "manipulation", "pan-y", "pan-x", "pan-x pan-y", "none"].forEach(function (d) { b[d] = c ? a.CSS.supports("touch-action", d) : !0 }), b } function Y(a) { this.options = la({}, this.defaults, a || {}), this.id = v(), this.manager = null, this.options.enable = l(this.options.enable, !0), this.state = nb, this.simultaneous = {}, this.requireFail = [] } function Z(a) { return a & sb ? "cancel" : a & qb ? "end" : a & pb ? "move" : a & ob ? "start" : "" } function $(a) { return a == Ma ? "down" : a == La ? "up" : a == Ja ? "left" : a == Ka ? "right" : "" } function _(a, b) { var c = b.manager; return c ? c.get(a) : a } function aa() { Y.apply(this, arguments) } function ba() { aa.apply(this, arguments), this.pX = null, this.pY = null } function ca() { aa.apply(this, arguments) } function da() { Y.apply(this, arguments), this._timer = null, this._input = null } function ea() { aa.apply(this, arguments) } function fa() { aa.apply(this, arguments) } function ga() { Y.apply(this, arguments), this.pTime = !1, this.pCenter = !1, this._timer = null, this._input = null, this.count = 0 } function ha(a, b) { return b = b || {}, b.recognizers = l(b.recognizers, ha.defaults.preset), new ia(a, b) } function ia(a, b) { this.options = la({}, ha.defaults, b || {}), this.options.inputTarget = this.options.inputTarget || a, this.handlers = {}, this.session = {}, this.recognizers = [], this.oldCssProps = {}, this.element = a, this.input = y(this), this.touchAction = new V(this, this.options.touchAction), ja(this, !0), g(this.options.recognizers, function (a) { var b = this.add(new a[0](a[1])); a[2] && b.recognizeWith(a[2]), a[3] && b.requireFailure(a[3]) }, this) } function ja(a, b) { var c = a.element; if (c.style) { var d; g(a.options.cssProps, function (e, f) { d = u(c.style, f), b ? (a.oldCssProps[d] = c.style[d], c.style[d] = e) : c.style[d] = a.oldCssProps[d] || "" }), b || (a.oldCssProps = {}) } } function ka(a, c) { var d = b.createEvent("Event"); d.initEvent(a, !0, !0), d.gesture = c, c.target.dispatchEvent(d) } var la, ma = ["", "webkit", "Moz", "MS", "ms", "o"], na = b.createElement("div"), oa = "function", pa = Math.round, qa = Math.abs, ra = Date.now; la = "function" != typeof Object.assign ? function (a) { if (a === d || null === a) throw new TypeError("Cannot convert undefined or null to object"); for (var b = Object(a), c = 1; c < arguments.length; c++) { var e = arguments[c]; if (e !== d && null !== e) for (var f in e) e.hasOwnProperty(f) && (b[f] = e[f]) } return b } : Object.assign; var sa = h(function (a, b, c) { for (var e = Object.keys(b), f = 0; f < e.length;)(!c || c && a[e[f]] === d) && (a[e[f]] = b[e[f]]), f++; return a }, "extend", "Use `assign`."), ta = h(function (a, b) { return sa(a, b, !0) }, "merge", "Use `assign`."), ua = 1, va = /mobile|tablet|ip(ad|hone|od)|android/i, wa = "ontouchstart" in a, xa = u(a, "PointerEvent") !== d, ya = wa && va.test(navigator.userAgent), za = "touch", Aa = "pen", Ba = "mouse", Ca = "kinect", Da = 25, Ea = 1, Fa = 2, Ga = 4, Ha = 8, Ia = 1, Ja = 2, Ka = 4, La = 8, Ma = 16, Na = Ja | Ka, Oa = La | Ma, Pa = Na | Oa, Qa = ["x", "y"], Ra = ["clientX", "clientY"]; x.prototype = { handler: function () { }, init: function () { this.evEl && m(this.element, this.evEl, this.domHandler), this.evTarget && m(this.target, this.evTarget, this.domHandler), this.evWin && m(w(this.element), this.evWin, this.domHandler) }, destroy: function () { this.evEl && n(this.element, this.evEl, this.domHandler), this.evTarget && n(this.target, this.evTarget, this.domHandler), this.evWin && n(w(this.element), this.evWin, this.domHandler) } }; var Sa = { mousedown: Ea, mousemove: Fa, mouseup: Ga }, Ta = "mousedown", Ua = "mousemove mouseup"; i(L, x, { handler: function (a) { var b = Sa[a.type]; b & Ea && 0 === a.button && (this.pressed = !0), b & Fa && 1 !== a.which && (b = Ga), this.pressed && (b & Ga && (this.pressed = !1), this.callback(this.manager, b, { pointers: [a], changedPointers: [a], pointerType: Ba, srcEvent: a })) } }); var Va = { pointerdown: Ea, pointermove: Fa, pointerup: Ga, pointercancel: Ha, pointerout: Ha }, Wa = { 2: za, 3: Aa, 4: Ba, 5: Ca }, Xa = "pointerdown", Ya = "pointermove pointerup pointercancel"; a.MSPointerEvent && !a.PointerEvent && (Xa = "MSPointerDown", Ya = "MSPointerMove MSPointerUp MSPointerCancel"), i(M, x, { handler: function (a) { var b = this.store, c = !1, d = a.type.toLowerCase().replace("ms", ""), e = Va[d], f = Wa[a.pointerType] || a.pointerType, g = f == za, h = r(b, a.pointerId, "pointerId"); e & Ea && (0 === a.button || g) ? 0 > h && (b.push(a), h = b.length - 1) : e & (Ga | Ha) && (c = !0), 0 > h || (b[h] = a, this.callback(this.manager, e, { pointers: b, changedPointers: [a], pointerType: f, srcEvent: a }), c && b.splice(h, 1)) } }); var Za = { touchstart: Ea, touchmove: Fa, touchend: Ga, touchcancel: Ha }, $a = "touchstart", _a = "touchstart touchmove touchend touchcancel"; i(N, x, { handler: function (a) { var b = Za[a.type]; if (b === Ea && (this.started = !0), this.started) { var c = O.call(this, a, b); b & (Ga | Ha) && c[0].length - c[1].length === 0 && (this.started = !1), this.callback(this.manager, b, { pointers: c[0], changedPointers: c[1], pointerType: za, srcEvent: a }) } } }); var ab = { touchstart: Ea, touchmove: Fa, touchend: Ga, touchcancel: Ha }, bb = "touchstart touchmove touchend touchcancel"; i(P, x, { handler: function (a) { var b = ab[a.type], c = Q.call(this, a, b); c && this.callback(this.manager, b, { pointers: c[0], changedPointers: c[1], pointerType: za, srcEvent: a }) } }); var cb = 2500, db = 25; i(R, x, { handler: function (a, b, c) { var d = c.pointerType == za, e = c.pointerType == Ba; if (!(e && c.sourceCapabilities && c.sourceCapabilities.firesTouchEvents)) { if (d) S.call(this, b, c); else if (e && U.call(this, c)) return; this.callback(a, b, c) } }, destroy: function () { this.touch.destroy(), this.mouse.destroy() } }); var eb = u(na.style, "touchAction"), fb = eb !== d, gb = "compute", hb = "auto", ib = "manipulation", jb = "none", kb = "pan-x", lb = "pan-y", mb = X(); V.prototype = { set: function (a) { a == gb && (a = this.compute()), fb && this.manager.element.style && mb[a] && (this.manager.element.style[eb] = a), this.actions = a.toLowerCase().trim() }, update: function () { this.set(this.manager.options.touchAction) }, compute: function () { var a = []; return g(this.manager.recognizers, function (b) { k(b.options.enable, [b]) && (a = a.concat(b.getTouchAction())) }), W(a.join(" ")) }, preventDefaults: function (a) { var b = a.srcEvent, c = a.offsetDirection; if (this.manager.session.prevented) return void b.preventDefault(); var d = this.actions, e = p(d, jb) && !mb[jb], f = p(d, lb) && !mb[lb], g = p(d, kb) && !mb[kb]; if (e) { var h = 1 === a.pointers.length, i = a.distance < 2, j = a.deltaTime < 250; if (h && i && j) return } return g && f ? void 0 : e || f && c & Na || g && c & Oa ? this.preventSrc(b) : void 0 }, preventSrc: function (a) { this.manager.session.prevented = !0, a.preventDefault() } }; var nb = 1, ob = 2, pb = 4, qb = 8, rb = qb, sb = 16, tb = 32; Y.prototype = { defaults: {}, set: function (a) { return la(this.options, a), this.manager && this.manager.touchAction.update(), this }, recognizeWith: function (a) { if (f(a, "recognizeWith", this)) return this; var b = this.simultaneous; return a = _(a, this), b[a.id] || (b[a.id] = a, a.recognizeWith(this)), this }, dropRecognizeWith: function (a) { return f(a, "dropRecognizeWith", this) ? this : (a = _(a, this), delete this.simultaneous[a.id], this) }, requireFailure: function (a) { if (f(a, "requireFailure", this)) return this; var b = this.requireFail; return a = _(a, this), -1 === r(b, a) && (b.push(a), a.requireFailure(this)), this }, dropRequireFailure: function (a) { if (f(a, "dropRequireFailure", this)) return this; a = _(a, this); var b = r(this.requireFail, a); return b > -1 && this.requireFail.splice(b, 1), this }, hasRequireFailures: function () { return this.requireFail.length > 0 }, canRecognizeWith: function (a) { return !!this.simultaneous[a.id] }, emit: function (a) { function b(b) { c.manager.emit(b, a) } var c = this, d = this.state; qb > d && b(c.options.event + Z(d)), b(c.options.event), a.additionalEvent && b(a.additionalEvent), d >= qb && b(c.options.event + Z(d)) }, tryEmit: function (a) { return this.canEmit() ? this.emit(a) : void (this.state = tb) }, canEmit: function () { for (var a = 0; a < this.requireFail.length;) { if (!(this.requireFail[a].state & (tb | nb))) return !1; a++ } return !0 }, recognize: function (a) { var b = la({}, a); return k(this.options.enable, [this, b]) ? (this.state & (rb | sb | tb) && (this.state = nb), this.state = this.process(b), void (this.state & (ob | pb | qb | sb) && this.tryEmit(b))) : (this.reset(), void (this.state = tb)) }, process: function (a) { }, getTouchAction: function () { }, reset: function () { } }, i(aa, Y, { defaults: { pointers: 1 }, attrTest: function (a) { var b = this.options.pointers; return 0 === b || a.pointers.length === b }, process: function (a) { var b = this.state, c = a.eventType, d = b & (ob | pb), e = this.attrTest(a); return d && (c & Ha || !e) ? b | sb : d || e ? c & Ga ? b | qb : b & ob ? b | pb : ob : tb } }), i(ba, aa, { defaults: { event: "pan", threshold: 10, pointers: 1, direction: Pa }, getTouchAction: function () { var a = this.options.direction, b = []; return a & Na && b.push(lb), a & Oa && b.push(kb), b }, directionTest: function (a) { var b = this.options, c = !0, d = a.distance, e = a.direction, f = a.deltaX, g = a.deltaY; return e & b.direction || (b.direction & Na ? (e = 0 === f ? Ia : 0 > f ? Ja : Ka, c = f != this.pX, d = Math.abs(a.deltaX)) : (e = 0 === g ? Ia : 0 > g ? La : Ma, c = g != this.pY, d = Math.abs(a.deltaY))), a.direction = e, c && d > b.threshold && e & b.direction }, attrTest: function (a) { return aa.prototype.attrTest.call(this, a) && (this.state & ob || !(this.state & ob) && this.directionTest(a)) }, emit: function (a) { this.pX = a.deltaX, this.pY = a.deltaY; var b = $(a.direction); b && (a.additionalEvent = this.options.event + b), this._super.emit.call(this, a) } }), i(ca, aa, { defaults: { event: "pinch", threshold: 0, pointers: 2 }, getTouchAction: function () { return [jb] }, attrTest: function (a) { return this._super.attrTest.call(this, a) && (Math.abs(a.scale - 1) > this.options.threshold || this.state & ob) }, emit: function (a) { if (1 !== a.scale) { var b = a.scale < 1 ? "in" : "out"; a.additionalEvent = this.options.event + b } this._super.emit.call(this, a) } }), i(da, Y, { defaults: { event: "press", pointers: 1, time: 251, threshold: 9 }, getTouchAction: function () { return [hb] }, process: function (a) { var b = this.options, c = a.pointers.length === b.pointers, d = a.distance < b.threshold, f = a.deltaTime > b.time; if (this._input = a, !d || !c || a.eventType & (Ga | Ha) && !f) this.reset(); else if (a.eventType & Ea) this.reset(), this._timer = e(function () { this.state = rb, this.tryEmit() }, b.time, this); else if (a.eventType & Ga) return rb; return tb }, reset: function () { clearTimeout(this._timer) }, emit: function (a) { this.state === rb && (a && a.eventType & Ga ? this.manager.emit(this.options.event + "up", a) : (this._input.timeStamp = ra(), this.manager.emit(this.options.event, this._input))) } }), i(ea, aa, { defaults: { event: "rotate", threshold: 0, pointers: 2 }, getTouchAction: function () { return [jb] }, attrTest: function (a) { return this._super.attrTest.call(this, a) && (Math.abs(a.rotation) > this.options.threshold || this.state & ob) } }), i(fa, aa, { defaults: { event: "swipe", threshold: 10, velocity: .3, direction: Na | Oa, pointers: 1 }, getTouchAction: function () { return ba.prototype.getTouchAction.call(this) }, attrTest: function (a) { var b, c = this.options.direction; return c & (Na | Oa) ? b = a.overallVelocity : c & Na ? b = a.overallVelocityX : c & Oa && (b = a.overallVelocityY), this._super.attrTest.call(this, a) && c & a.offsetDirection && a.distance > this.options.threshold && a.maxPointers == this.options.pointers && qa(b) > this.options.velocity && a.eventType & Ga }, emit: function (a) { var b = $(a.offsetDirection); b && this.manager.emit(this.options.event + b, a), this.manager.emit(this.options.event, a) } }), i(ga, Y, { defaults: { event: "tap", pointers: 1, taps: 1, interval: 300, time: 250, threshold: 9, posThreshold: 10 }, getTouchAction: function () { return [ib] }, process: function (a) { var b = this.options, c = a.pointers.length === b.pointers, d = a.distance < b.threshold, f = a.deltaTime < b.time; if (this.reset(), a.eventType & Ea && 0 === this.count) return this.failTimeout(); if (d && f && c) { if (a.eventType != Ga) return this.failTimeout(); var g = this.pTime ? a.timeStamp - this.pTime < b.interval : !0, h = !this.pCenter || H(this.pCenter, a.center) < b.posThreshold;
17567 this.pTime = a.timeStamp, this.pCenter = a.center, h && g ? this.count += 1 : this.count = 1, this._input = a; var i = this.count % b.taps; if (0 === i) return this.hasRequireFailures() ? (this._timer = e(function () { this.state = rb, this.tryEmit() }, b.interval, this), ob) : rb } return tb }, failTimeout: function () { return this._timer = e(function () { this.state = tb }, this.options.interval, this), tb }, reset: function () { clearTimeout(this._timer) }, emit: function () { this.state == rb && (this._input.tapCount = this.count, this.manager.emit(this.options.event, this._input)) } }), ha.VERSION = "2.0.8", ha.defaults = { domEvents: !1, touchAction: gb, enable: !0, inputTarget: null, inputClass: null, preset: [[ea, { enable: !1 }], [ca, { enable: !1 }, ["rotate"]], [fa, { direction: Na }], [ba, { direction: Na }, ["swipe"]], [ga], [ga, { event: "doubletap", taps: 2 }, ["tap"]], [da]], cssProps: { userSelect: "none", touchSelect: "none", touchCallout: "none", contentZooming: "none", userDrag: "none", tapHighlightColor: "rgba(0,0,0,0)" } }; var ub = 1, vb = 2; ia.prototype = { set: function (a) { return la(this.options, a), a.touchAction && this.touchAction.update(), a.inputTarget && (this.input.destroy(), this.input.target = a.inputTarget, this.input.init()), this }, stop: function (a) { this.session.stopped = a ? vb : ub }, recognize: function (a) { var b = this.session; if (!b.stopped) { this.touchAction.preventDefaults(a); var c, d = this.recognizers, e = b.curRecognizer; (!e || e && e.state & rb) && (e = b.curRecognizer = null); for (var f = 0; f < d.length;)c = d[f], b.stopped === vb || e && c != e && !c.canRecognizeWith(e) ? c.reset() : c.recognize(a), !e && c.state & (ob | pb | qb) && (e = b.curRecognizer = c), f++ } }, get: function (a) { if (a instanceof Y) return a; for (var b = this.recognizers, c = 0; c < b.length; c++)if (b[c].options.event == a) return b[c]; return null }, add: function (a) { if (f(a, "add", this)) return this; var b = this.get(a.options.event); return b && this.remove(b), this.recognizers.push(a), a.manager = this, this.touchAction.update(), a }, remove: function (a) { if (f(a, "remove", this)) return this; if (a = this.get(a)) { var b = this.recognizers, c = r(b, a); -1 !== c && (b.splice(c, 1), this.touchAction.update()) } return this }, on: function (a, b) { if (a !== d && b !== d) { var c = this.handlers; return g(q(a), function (a) { c[a] = c[a] || [], c[a].push(b) }), this } }, off: function (a, b) { if (a !== d) { var c = this.handlers; return g(q(a), function (a) { b ? c[a] && c[a].splice(r(c[a], b), 1) : delete c[a] }), this } }, emit: function (a, b) { this.options.domEvents && ka(a, b); var c = this.handlers[a] && this.handlers[a].slice(); if (c && c.length) { b.type = a, b.preventDefault = function () { b.srcEvent.preventDefault() }; for (var d = 0; d < c.length;)c[d](b), d++ } }, destroy: function () { this.element && ja(this, !1), this.handlers = {}, this.session = {}, this.input.destroy(), this.element = null } }, la(ha, { INPUT_START: Ea, INPUT_MOVE: Fa, INPUT_END: Ga, INPUT_CANCEL: Ha, STATE_POSSIBLE: nb, STATE_BEGAN: ob, STATE_CHANGED: pb, STATE_ENDED: qb, STATE_RECOGNIZED: rb, STATE_CANCELLED: sb, STATE_FAILED: tb, DIRECTION_NONE: Ia, DIRECTION_LEFT: Ja, DIRECTION_RIGHT: Ka, DIRECTION_UP: La, DIRECTION_DOWN: Ma, DIRECTION_HORIZONTAL: Na, DIRECTION_VERTICAL: Oa, DIRECTION_ALL: Pa, Manager: ia, Input: x, TouchAction: V, TouchInput: P, MouseInput: L, PointerEventInput: M, TouchMouseInput: R, SingleTouchInput: N, Recognizer: Y, AttrRecognizer: aa, Tap: ga, Pan: ba, Swipe: fa, Pinch: ca, Rotate: ea, Press: da, on: m, off: n, each: g, merge: ta, extend: sa, assign: la, inherit: i, bindFn: j, prefixed: u }); var wb = "undefined" != typeof a ? a : "undefined" != typeof self ? self : {}; wb.Hammer = ha, "function" == typeof define && define.amd ? define(function () { return ha }) : "undefined" != typeof module && module.exports ? module.exports = ha : a[c] = ha }(window, document, "Hammer");
17568//# sourceMappingURL=hammer.min.js.map
17569
17570(function (factory) {
17571    if (typeof define === 'function' && define.amd) {
17572        define(['jquery', 'hammerjs'], factory);
17573    } else if (typeof exports === 'object') {
17574        factory(require('jquery'), require('hammerjs'));
17575    } else {
17576        factory(jQuery, Hammer);
17577    }
17578}(function ($, Hammer) {
17579    function hammerify(el, options) {
17580        var $el = $(el);
17581        if (!$el.data("hammer")) {
17582            $el.data("hammer", new Hammer($el[0], options));
17583        }
17584    }
17585
17586    $.fn.hammer = function (options) {
17587        return this.each(function () {
17588            hammerify(this, options);
17589        });
17590    };
17591
17592    // extend the emit method to also trigger jQuery events
17593    Hammer.Manager.prototype.emit = (function (originalEmit) {
17594        return function (type, data) {
17595            originalEmit.call(this, type, data);
17596            $(this.element).trigger({
17597                type: type,
17598                gesture: data
17599            });
17600        };
17601    })(Hammer.Manager.prototype.emit);
17602}));
17603
17604(function ($) {
17605    $(function () {
17606        let $sel = $('[data-unicode="mdu_UZ6Cm36k0aPN7SiJpJhIw"]');
17607        $sel.each(function () {
17608            let $id = base62();
17609            let $self = $(this);
17610            $self.children('.carousel').attr('id', $id);
17611
17612            function runBs4Slider() {
17613                $("#" + $id).find('.carousel-indicators li').attr('data-target', '#' + $id);
17614                $("#" + $id).find('.carousel-control-prev').attr('href', '#' + $id);
17615                $("#" + $id).find('.carousel-control-next').attr('href', '#' + $id);
17616                $("#" + $id).find('.carousel-item:first').addClass('active');
17617                $("#" + $id).find('.carousel-ctl:first').addClass('active');
17618
17619                $("#" + $id).hammer().on('swipeleft', function () {
17620                    $(this).carousel('next');
17621                });
17622
17623                $("#" + $id).hammer().on('swiperight', function () {
17624                    $(this).carousel('prev');
17625                });
17626            }
17627
17628            function lazyBs4Slider() {
17629                var lazyLoadBs4Slider = new LazyLoad({
17630                    elements_selector: '#' + $id + ' .lazyload'
17631                });
17632
17633                lazyLoadBs4Slider.loadAll();
17634            }
17635
17636            function lazyBs4SliderGo(callback) {
17637                var lazyRunBs4Slider = new LazyLoad({
17638                    elements_selector: '#' + $id + ' .lazyload',
17639                    callback_loaded: function () {
17640                        $("#" + $id).find('.carousel-indicators li').each(function (index) {
17641                            $(this).attr('data-slide-to', index);
17642                        });
17643                        lazyBs4Slider();
17644                    }
17645                });
17646                callback();
17647            }
17648
17649            lazyBs4SliderGo(runBs4Slider);
17650
17651            let lazyloadTimer;
17652            function lazyloadMonitor() {
17653                if (lazyloadTimer) {
17654                    clearTimeout(lazyloadTimer);
17655                }
17656            
17657                lazyloadTimer = setTimeout(function () {
17658                    let $carouselInner = $('.carousel-inner', $self);
17659                    let $divHolder = $('.lazyload-placeholder', $self);
17660                    let padding = $(window).width() < 575 ? $carouselInner.data("spadding") : $carouselInner.data("cpadding");
17661                    if (padding && $divHolder?.length > 0) {
17662                        $divHolder.attr("style", "padding-bottom: " + padding);
17663                    }
17664
17665                    let scrollTop = $(window).scrollTop();
17666
17667                    $(".lazyload ", $self).each(function () {
17668                        let $img = $(this);
17669                        if ($img.offset().top < (window.innerHeight + scrollTop)) {
17670                            $img.attr("src", $img.data("src"));
17671                            if(this.complete){
17672                                // 判斷填補區塊是否存在,存在就移除
17673                                if ($divHolder?.length > 0) {
17674                                    $('.lazyload-placeholder', $self).remove();
17675                                }
17676
17677                                // 圖片顯示的過度效果
17678                                $img.removeClass("d-none");
17679                                $img.css({
17680                                    "opacity": 0,
17681                                    "transition": "opacity 1s ease-in-out"
17682                                });
17683                                setTimeout(function () {
17684                                    $img.css("opacity", 1);
17685                                }, 10);
17686                                $img.removeClass('lazyload');
17687                            }
17688                        }
17689                    });
17690                    if ($(".lazyload", $self).length == 0) {
17691                        console.log("off scroll")
17692                        $(document).off("scroll", lazyloadMonitor);
17693                        $(window).off("resize", lazyloadMonitor);
17694                        $(window).off("orientationchange", lazyloadMonitor);
17695                    }
17696                }, 20);
17697            }
17698
17699            $(window).on("load", function () {
17700                let $divHolder = $('.lazyload-placeholder', $self);
17701                let $carouselImg = $('img', $self);
17702                console.log($carouselImg);
17703                console.log($carouselImg.first().css("opacity"))
17704                if(
17705                    $carouselImg?.length > 0 && 
17706                    $carouselImg.first().css("opacity") === "1" && 
17707                    $divHolder?.length > 0
17708                ){
17709                    $divHolder.remove();
17710                }
17711            });
17712
17713            lazyloadMonitor();
17714            $(document).on("scroll", lazyloadMonitor);
17715            $(window).on("resize", lazyloadMonitor);
17716            $(window).on("orientationchange", lazyloadMonitor);
17717        });
17718    });
17719})(jQuery);; })(jQuery);/* compress error:[4]function encode(int) {*/
17720
17721/* MODULE 9e1d73c9-71ba-4925-a9a0-c97e617537ed, Version: 1.0.54 */
17722;(function($) {; var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
17723
17724// NB: does not validate input
17725function encode(int) {
17726    if (int === 0) {
17727        return CHARSET[0];
17728    }
17729
17730    var res = "";
17731    while (int > 0) {
17732        res = CHARSET[int % 62] + res;
17733        int = Math.floor(int / 62);
17734    }
17735    return res;
17736};
17737
17738function decode(str) {
17739    var res = 0,
17740        length = str.length,
17741        i, char;
17742    for (i = 0; i < length; i++) {
17743        char = str.charCodeAt(i);
17744        if (char < 58) { // 0-9
17745            char = char - 48;
17746        } else if (char < 91) { // A-Z
17747            char = char - 29;
17748        } else { // a-z
17749            char = char - 87;
17750        }
17751        res += char * Math.pow(62, length - i - 1);
17752    }
17753    return res;
17754};
17755
17756function base62() {
17757    var id; //base62
17758    do {
17759      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
17760    } while (id.match(/^[0-9]/i) !== null);
17761    return id;
17762}/*!
17763 * Datepicker for Bootstrap v1.9.0 (https://github.com/uxsolutions/bootstrap-datepicker)
17764 *
17765 * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
17766 */
17767
17768(function(factory){
17769    if (typeof define === 'function' && define.amd) {
17770        define(['jquery'], factory);
17771    } else if (typeof exports === 'object') {
17772        factory(require('jquery'));
17773    } else {
17774        factory(jQuery);
17775    }
17776}(function($, undefined){
17777	function UTCDate(){
17778		return new Date(Date.UTC.apply(Date, arguments));
17779	}
17780	function UTCToday(){
17781		var today = new Date();
17782		return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
17783	}
17784	function isUTCEquals(date1, date2) {
17785		return (
17786			date1.getUTCFullYear() === date2.getUTCFullYear() &&
17787			date1.getUTCMonth() === date2.getUTCMonth() &&
17788			date1.getUTCDate() === date2.getUTCDate()
17789		);
17790	}
17791	function alias(method, deprecationMsg){
17792		return function(){
17793			if (deprecationMsg !== undefined) {
17794				$.fn.datepicker.deprecated(deprecationMsg);
17795			}
17796
17797			return this[method].apply(this, arguments);
17798		};
17799	}
17800	function isValidDate(d) {
17801		return d && !isNaN(d.getTime());
17802	}
17803
17804	var DateArray = (function(){
17805		var extras = {
17806			get: function(i){
17807				return this.slice(i)[0];
17808			},
17809			contains: function(d){
17810				// Array.indexOf is not cross-browser;
17811				// $.inArray doesn't work with Dates
17812				var val = d && d.valueOf();
17813				for (var i=0, l=this.length; i < l; i++)
17814          // Use date arithmetic to allow dates with different times to match
17815          if (0 <= this[i].valueOf() - val && this[i].valueOf() - val < 1000*60*60*24)
17816						return i;
17817				return -1;
17818			},
17819			remove: function(i){
17820				this.splice(i,1);
17821			},
17822			replace: function(new_array){
17823				if (!new_array)
17824					return;
17825				if (!$.isArray(new_array))
17826					new_array = [new_array];
17827				this.clear();
17828				this.push.apply(this, new_array);
17829			},
17830			clear: function(){
17831				this.length = 0;
17832			},
17833			copy: function(){
17834				var a = new DateArray();
17835				a.replace(this);
17836				return a;
17837			}
17838		};
17839
17840		return function(){
17841			var a = [];
17842			a.push.apply(a, arguments);
17843			$.extend(a, extras);
17844			return a;
17845		};
17846	})();
17847
17848
17849	// Picker object
17850
17851	var Datepicker = function(element, options){
17852		$.data(element, 'datepicker', this);
17853
17854		this._events = [];
17855		this._secondaryEvents = [];
17856
17857		this._process_options(options);
17858
17859		this.dates = new DateArray();
17860		this.viewDate = this.o.defaultViewDate;
17861		this.focusDate = null;
17862
17863		this.element = $(element);
17864		this.isInput = this.element.is('input');
17865		this.inputField = this.isInput ? this.element : this.element.find('input');
17866		this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .input-group-append, .input-group-prepend, .btn') : false;
17867		if (this.component && this.component.length === 0)
17868			this.component = false;
17869		this.isInline = !this.component && this.element.is('div');
17870
17871		this.picker = $(DPGlobal.template);
17872
17873		// Checking templates and inserting
17874		if (this._check_template(this.o.templates.leftArrow)) {
17875			this.picker.find('.prev').html(this.o.templates.leftArrow);
17876		}
17877
17878		if (this._check_template(this.o.templates.rightArrow)) {
17879			this.picker.find('.next').html(this.o.templates.rightArrow);
17880		}
17881
17882		this._buildEvents();
17883		this._attachEvents();
17884
17885		if (this.isInline){
vendor: 56,186 bytes, lines 17886-19785
17886			this.picker.addClass('datepicker-inline').appendTo(this.element);
17887		}
17888		else {
17889			this.picker.addClass('datepicker-dropdown dropdown-menu');
17890		}
17891
17892		if (this.o.rtl){
17893			this.picker.addClass('datepicker-rtl');
17894		}
17895
17896		if (this.o.calendarWeeks) {
17897			this.picker.find('.datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear')
17898				.attr('colspan', function(i, val){
17899					return Number(val) + 1;
17900				});
17901		}
17902
17903		this._process_options({
17904			startDate: this._o.startDate,
17905			endDate: this._o.endDate,
17906			daysOfWeekDisabled: this.o.daysOfWeekDisabled,
17907			daysOfWeekHighlighted: this.o.daysOfWeekHighlighted,
17908			datesDisabled: this.o.datesDisabled
17909		});
17910
17911		this._allow_update = false;
17912		this.setViewMode(this.o.startView);
17913		this._allow_update = true;
17914
17915		this.fillDow();
17916		this.fillMonths();
17917
17918		this.update();
17919
17920		if (this.isInline){
17921			this.show();
17922		}
17923	};
17924
17925	Datepicker.prototype = {
17926		constructor: Datepicker,
17927
17928		_resolveViewName: function(view){
17929			$.each(DPGlobal.viewModes, function(i, viewMode){
17930				if (view === i || $.inArray(view, viewMode.names) !== -1){
17931					view = i;
17932					return false;
17933				}
17934			});
17935
17936			return view;
17937		},
17938
17939		_resolveDaysOfWeek: function(daysOfWeek){
17940			if (!$.isArray(daysOfWeek))
17941				daysOfWeek = daysOfWeek.split(/[,\s]*/);
17942			return $.map(daysOfWeek, Number);
17943		},
17944
17945		_check_template: function(tmp){
17946			try {
17947				// If empty
17948				if (tmp === undefined || tmp === "") {
17949					return false;
17950				}
17951				// If no html, everything ok
17952				if ((tmp.match(/[<>]/g) || []).length <= 0) {
17953					return true;
17954				}
17955				// Checking if html is fine
17956				var jDom = $(tmp);
17957				return jDom.length > 0;
17958			}
17959			catch (ex) {
17960				return false;
17961			}
17962		},
17963
17964		_process_options: function(opts){
17965			// Store raw options for reference
17966			this._o = $.extend({}, this._o, opts);
17967			// Processed options
17968			var o = this.o = $.extend({}, this._o);
17969
17970			// Check if "de-DE" style date is available, if not language should
17971			// fallback to 2 letter code eg "de"
17972			var lang = o.language;
17973			if (!dates[lang]){
17974				lang = lang.split('-')[0];
17975				if (!dates[lang])
17976					lang = defaults.language;
17977			}
17978			o.language = lang;
17979
17980			// Retrieve view index from any aliases
17981			o.startView = this._resolveViewName(o.startView);
17982			o.minViewMode = this._resolveViewName(o.minViewMode);
17983			o.maxViewMode = this._resolveViewName(o.maxViewMode);
17984
17985			// Check view is between min and max
17986			o.startView = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, o.startView));
17987
17988			// true, false, or Number > 0
17989			if (o.multidate !== true){
17990				o.multidate = Number(o.multidate) || false;
17991				if (o.multidate !== false)
17992					o.multidate = Math.max(0, o.multidate);
17993			}
17994			o.multidateSeparator = String(o.multidateSeparator);
17995
17996			o.weekStart %= 7;
17997			o.weekEnd = (o.weekStart + 6) % 7;
17998
17999			var format = DPGlobal.parseFormat(o.format);
18000			if (o.startDate !== -Infinity){
18001				if (!!o.startDate){
18002					if (o.startDate instanceof Date)
18003						o.startDate = this._local_to_utc(this._zero_time(o.startDate));
18004					else
18005						o.startDate = DPGlobal.parseDate(o.startDate, format, o.language, o.assumeNearbyYear);
18006				}
18007				else {
18008					o.startDate = -Infinity;
18009				}
18010			}
18011			if (o.endDate !== Infinity){
18012				if (!!o.endDate){
18013					if (o.endDate instanceof Date)
18014						o.endDate = this._local_to_utc(this._zero_time(o.endDate));
18015					else
18016						o.endDate = DPGlobal.parseDate(o.endDate, format, o.language, o.assumeNearbyYear);
18017				}
18018				else {
18019					o.endDate = Infinity;
18020				}
18021			}
18022
18023			o.daysOfWeekDisabled = this._resolveDaysOfWeek(o.daysOfWeekDisabled||[]);
18024			o.daysOfWeekHighlighted = this._resolveDaysOfWeek(o.daysOfWeekHighlighted||[]);
18025
18026			o.datesDisabled = o.datesDisabled||[];
18027			if (!$.isArray(o.datesDisabled)) {
18028				o.datesDisabled = o.datesDisabled.split(',');
18029			}
18030			o.datesDisabled = $.map(o.datesDisabled, function(d){
18031				return DPGlobal.parseDate(d, format, o.language, o.assumeNearbyYear);
18032			});
18033
18034			var plc = String(o.orientation).toLowerCase().split(/\s+/g),
18035				_plc = o.orientation.toLowerCase();
18036			plc = $.grep(plc, function(word){
18037				return /^auto|left|right|top|bottom$/.test(word);
18038			});
18039			o.orientation = {x: 'auto', y: 'auto'};
18040			if (!_plc || _plc === 'auto')
18041				; // no action
18042			else if (plc.length === 1){
18043				switch (plc[0]){
18044					case 'top':
18045					case 'bottom':
18046						o.orientation.y = plc[0];
18047						break;
18048					case 'left':
18049					case 'right':
18050						o.orientation.x = plc[0];
18051						break;
18052				}
18053			}
18054			else {
18055				_plc = $.grep(plc, function(word){
18056					return /^left|right$/.test(word);
18057				});
18058				o.orientation.x = _plc[0] || 'auto';
18059
18060				_plc = $.grep(plc, function(word){
18061					return /^top|bottom$/.test(word);
18062				});
18063				o.orientation.y = _plc[0] || 'auto';
18064			}
18065			if (o.defaultViewDate instanceof Date || typeof o.defaultViewDate === 'string') {
18066				o.defaultViewDate = DPGlobal.parseDate(o.defaultViewDate, format, o.language, o.assumeNearbyYear);
18067			} else if (o.defaultViewDate) {
18068				var year = o.defaultViewDate.year || new Date().getFullYear();
18069				var month = o.defaultViewDate.month || 0;
18070				var day = o.defaultViewDate.day || 1;
18071				o.defaultViewDate = UTCDate(year, month, day);
18072			} else {
18073				o.defaultViewDate = UTCToday();
18074			}
18075		},
18076		_applyEvents: function(evs){
18077			for (var i=0, el, ch, ev; i < evs.length; i++){
18078				el = evs[i][0];
18079				if (evs[i].length === 2){
18080					ch = undefined;
18081					ev = evs[i][1];
18082				} else if (evs[i].length === 3){
18083					ch = evs[i][1];
18084					ev = evs[i][2];
18085				}
18086				el.on(ev, ch);
18087			}
18088		},
18089		_unapplyEvents: function(evs){
18090			for (var i=0, el, ev, ch; i < evs.length; i++){
18091				el = evs[i][0];
18092				if (evs[i].length === 2){
18093					ch = undefined;
18094					ev = evs[i][1];
18095				} else if (evs[i].length === 3){
18096					ch = evs[i][1];
18097					ev = evs[i][2];
18098				}
18099				el.off(ev, ch);
18100			}
18101		},
18102		_buildEvents: function(){
18103            var events = {
18104                keyup: $.proxy(function(e){
18105                    if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
18106                        this.update();
18107                }, this),
18108                keydown: $.proxy(this.keydown, this),
18109                paste: $.proxy(this.paste, this)
18110            };
18111
18112            if (this.o.showOnFocus === true) {
18113                events.focus = $.proxy(this.show, this);
18114            }
18115
18116            if (this.isInput) { // single input
18117                this._events = [
18118                    [this.element, events]
18119                ];
18120            }
18121            // component: input + button
18122            else if (this.component && this.inputField.length) {
18123                this._events = [
18124                    // For components that are not readonly, allow keyboard nav
18125                    [this.inputField, events],
18126                    [this.component, {
18127                        click: $.proxy(this.show, this)
18128                    }]
18129                ];
18130            }
18131			else {
18132				this._events = [
18133					[this.element, {
18134						click: $.proxy(this.show, this),
18135						keydown: $.proxy(this.keydown, this)
18136					}]
18137				];
18138			}
18139			this._events.push(
18140				// Component: listen for blur on element descendants
18141				[this.element, '*', {
18142					blur: $.proxy(function(e){
18143						this._focused_from = e.target;
18144					}, this)
18145				}],
18146				// Input: listen for blur on element
18147				[this.element, {
18148					blur: $.proxy(function(e){
18149						this._focused_from = e.target;
18150					}, this)
18151				}]
18152			);
18153
18154			if (this.o.immediateUpdates) {
18155				// Trigger input updates immediately on changed year/month
18156				this._events.push([this.element, {
18157					'changeYear changeMonth': $.proxy(function(e){
18158						this.update(e.date);
18159					}, this)
18160				}]);
18161			}
18162
18163			this._secondaryEvents = [
18164				[this.picker, {
18165					click: $.proxy(this.click, this)
18166				}],
18167				[this.picker, '.prev, .next', {
18168					click: $.proxy(this.navArrowsClick, this)
18169				}],
18170				[this.picker, '.day:not(.disabled)', {
18171					click: $.proxy(this.dayCellClick, this)
18172				}],
18173				[$(window), {
18174					resize: $.proxy(this.place, this)
18175				}],
18176				[$(document), {
18177					'mousedown touchstart': $.proxy(function(e){
18178						// Clicked outside the datepicker, hide it
18179						if (!(
18180							this.element.is(e.target) ||
18181							this.element.find(e.target).length ||
18182							this.picker.is(e.target) ||
18183							this.picker.find(e.target).length ||
18184							this.isInline
18185						)){
18186							this.hide();
18187						}
18188					}, this)
18189				}]
18190			];
18191		},
18192		_attachEvents: function(){
18193			this._detachEvents();
18194			this._applyEvents(this._events);
18195		},
18196		_detachEvents: function(){
18197			this._unapplyEvents(this._events);
18198		},
18199		_attachSecondaryEvents: function(){
18200			this._detachSecondaryEvents();
18201			this._applyEvents(this._secondaryEvents);
18202		},
18203		_detachSecondaryEvents: function(){
18204			this._unapplyEvents(this._secondaryEvents);
18205		},
18206		_trigger: function(event, altdate){
18207			var date = altdate || this.dates.get(-1),
18208				local_date = this._utc_to_local(date);
18209
18210			this.element.trigger({
18211				type: event,
18212				date: local_date,
18213				viewMode: this.viewMode,
18214				dates: $.map(this.dates, this._utc_to_local),
18215				format: $.proxy(function(ix, format){
18216					if (arguments.length === 0){
18217						ix = this.dates.length - 1;
18218						format = this.o.format;
18219					} else if (typeof ix === 'string'){
18220						format = ix;
18221						ix = this.dates.length - 1;
18222					}
18223					format = format || this.o.format;
18224					var date = this.dates.get(ix);
18225					return DPGlobal.formatDate(date, format, this.o.language);
18226				}, this)
18227			});
18228		},
18229
18230		show: function(){
18231			if (this.inputField.is(':disabled') || (this.inputField.prop('readonly') && this.o.enableOnReadonly === false))
18232				return;
18233			if (!this.isInline)
18234				this.picker.appendTo(this.o.container);
18235			this.place();
18236			this.picker.show();
18237			this._attachSecondaryEvents();
18238			this._trigger('show');
18239			if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) {
18240				$(this.element).blur();
18241			}
18242			return this;
18243		},
18244
18245		hide: function(){
18246			if (this.isInline || !this.picker.is(':visible'))
18247				return this;
18248			this.focusDate = null;
18249			this.picker.hide().detach();
18250			this._detachSecondaryEvents();
18251			this.setViewMode(this.o.startView);
18252
18253			if (this.o.forceParse && this.inputField.val())
18254				this.setValue();
18255			this._trigger('hide');
18256			return this;
18257		},
18258
18259		destroy: function(){
18260			this.hide();
18261			this._detachEvents();
18262			this._detachSecondaryEvents();
18263			this.picker.remove();
18264			delete this.element.data().datepicker;
18265			if (!this.isInput){
18266				delete this.element.data().date;
18267			}
18268			return this;
18269		},
18270
18271		paste: function(e){
18272			var dateString;
18273			if (e.originalEvent.clipboardData && e.originalEvent.clipboardData.types
18274				&& $.inArray('text/plain', e.originalEvent.clipboardData.types) !== -1) {
18275				dateString = e.originalEvent.clipboardData.getData('text/plain');
18276			} else if (window.clipboardData) {
18277				dateString = window.clipboardData.getData('Text');
18278			} else {
18279				return;
18280			}
18281			this.setDate(dateString);
18282			this.update();
18283			e.preventDefault();
18284		},
18285
18286		_utc_to_local: function(utc){
18287			if (!utc) {
18288				return utc;
18289			}
18290
18291			var local = new Date(utc.getTime() + (utc.getTimezoneOffset() * 60000));
18292
18293			if (local.getTimezoneOffset() !== utc.getTimezoneOffset()) {
18294				local = new Date(utc.getTime() + (local.getTimezoneOffset() * 60000));
18295			}
18296
18297			return local;
18298		},
18299		_local_to_utc: function(local){
18300			return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000));
18301		},
18302		_zero_time: function(local){
18303			return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
18304		},
18305		_zero_utc_time: function(utc){
18306			return utc && UTCDate(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());
18307		},
18308
18309		getDates: function(){
18310			return $.map(this.dates, this._utc_to_local);
18311		},
18312
18313		getUTCDates: function(){
18314			return $.map(this.dates, function(d){
18315				return new Date(d);
18316			});
18317		},
18318
18319		getDate: function(){
18320			return this._utc_to_local(this.getUTCDate());
18321		},
18322
18323		getUTCDate: function(){
18324			var selected_date = this.dates.get(-1);
18325			if (selected_date !== undefined) {
18326				return new Date(selected_date);
18327			} else {
18328				return null;
18329			}
18330		},
18331
18332		clearDates: function(){
18333			this.inputField.val('');
18334			this.update();
18335			this._trigger('changeDate');
18336
18337			if (this.o.autoclose) {
18338				this.hide();
18339			}
18340		},
18341
18342		setDates: function(){
18343			var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
18344			this.update.apply(this, args);
18345			this._trigger('changeDate');
18346			this.setValue();
18347			return this;
18348		},
18349
18350		setUTCDates: function(){
18351			var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
18352			this.setDates.apply(this, $.map(args, this._utc_to_local));
18353			return this;
18354		},
18355
18356		setDate: alias('setDates'),
18357		setUTCDate: alias('setUTCDates'),
18358		remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead'),
18359
18360		setValue: function(){
18361			var formatted = this.getFormattedDate();
18362			this.inputField.val(formatted);
18363			return this;
18364		},
18365
18366		getFormattedDate: function(format){
18367			if (format === undefined)
18368				format = this.o.format;
18369
18370			var lang = this.o.language;
18371			return $.map(this.dates, function(d){
18372				return DPGlobal.formatDate(d, format, lang);
18373			}).join(this.o.multidateSeparator);
18374		},
18375
18376		getStartDate: function(){
18377			return this.o.startDate;
18378		},
18379
18380		setStartDate: function(startDate){
18381			this._process_options({startDate: startDate});
18382			this.update();
18383			this.updateNavArrows();
18384			return this;
18385		},
18386
18387		getEndDate: function(){
18388			return this.o.endDate;
18389		},
18390
18391		setEndDate: function(endDate){
18392			this._process_options({endDate: endDate});
18393			this.update();
18394			this.updateNavArrows();
18395			return this;
18396		},
18397
18398		setDaysOfWeekDisabled: function(daysOfWeekDisabled){
18399			this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
18400			this.update();
18401			return this;
18402		},
18403
18404		setDaysOfWeekHighlighted: function(daysOfWeekHighlighted){
18405			this._process_options({daysOfWeekHighlighted: daysOfWeekHighlighted});
18406			this.update();
18407			return this;
18408		},
18409
18410		setDatesDisabled: function(datesDisabled){
18411			this._process_options({datesDisabled: datesDisabled});
18412			this.update();
18413			return this;
18414		},
18415
18416		place: function(){
18417			if (this.isInline)
18418				return this;
18419			var calendarWidth = this.picker.outerWidth(),
18420				calendarHeight = this.picker.outerHeight(),
18421				visualPadding = 10,
18422				container = $(this.o.container),
18423				windowWidth = container.width(),
18424				scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(),
18425				appendOffset = container.offset();
18426
18427			var parentsZindex = [0];
18428			this.element.parents().each(function(){
18429				var itemZIndex = $(this).css('z-index');
18430				if (itemZIndex !== 'auto' && Number(itemZIndex) !== 0) parentsZindex.push(Number(itemZIndex));
18431			});
18432			var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset;
18433			var offset = this.component ? this.component.parent().offset() : this.element.offset();
18434			var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
18435			var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
18436			var left = offset.left - appendOffset.left;
18437			var top = offset.top - appendOffset.top;
18438
18439			if (this.o.container !== 'body') {
18440				top += scrollTop;
18441			}
18442
18443			this.picker.removeClass(
18444				'datepicker-orient-top datepicker-orient-bottom '+
18445				'datepicker-orient-right datepicker-orient-left'
18446			);
18447
18448			if (this.o.orientation.x !== 'auto'){
18449				this.picker.addClass('datepicker-orient-' + this.o.orientation.x);
18450				if (this.o.orientation.x === 'right')
18451					left -= calendarWidth - width;
18452			}
18453			// auto x orientation is best-placement: if it crosses a window
18454			// edge, fudge it sideways
18455			else {
18456				if (offset.left < 0) {
18457					// component is outside the window on the left side. Move it into visible range
18458					this.picker.addClass('datepicker-orient-left');
18459					left -= offset.left - visualPadding;
18460				} else if (left + calendarWidth > windowWidth) {
18461					// the calendar passes the widow right edge. Align it to component right side
18462					this.picker.addClass('datepicker-orient-right');
18463					left += width - calendarWidth;
18464				} else {
18465					if (this.o.rtl) {
18466						// Default to right
18467						this.picker.addClass('datepicker-orient-right');
18468					} else {
18469						// Default to left
18470						this.picker.addClass('datepicker-orient-left');
18471					}
18472				}
18473			}
18474
18475			// auto y orientation is best-situation: top or bottom, no fudging,
18476			// decision based on which shows more of the calendar
18477			var yorient = this.o.orientation.y,
18478				top_overflow;
18479			if (yorient === 'auto'){
18480				top_overflow = -scrollTop + top - calendarHeight;
18481				yorient = top_overflow < 0 ? 'bottom' : 'top';
18482			}
18483
18484			this.picker.addClass('datepicker-orient-' + yorient);
18485			if (yorient === 'top')
18486				top -= calendarHeight + parseInt(this.picker.css('padding-top'));
18487			else
18488				top += height;
18489
18490			if (this.o.rtl) {
18491				var right = windowWidth - (left + width);
18492				this.picker.css({
18493					top: top,
18494					right: right,
18495					zIndex: zIndex
18496				});
18497			} else {
18498				this.picker.css({
18499					top: top,
18500					left: left,
18501					zIndex: zIndex
18502				});
18503			}
18504			return this;
18505		},
18506
18507		_allow_update: true,
18508		update: function(){
18509			if (!this._allow_update)
18510				return this;
18511
18512			var oldDates = this.dates.copy(),
18513				dates = [],
18514				fromArgs = false;
18515			if (arguments.length){
18516				$.each(arguments, $.proxy(function(i, date){
18517					if (date instanceof Date)
18518						date = this._local_to_utc(date);
18519					dates.push(date);
18520				}, this));
18521				fromArgs = true;
18522			} else {
18523				dates = this.isInput
18524						? this.element.val()
18525						: this.element.data('date') || this.inputField.val();
18526				if (dates && this.o.multidate)
18527					dates = dates.split(this.o.multidateSeparator);
18528				else
18529					dates = [dates];
18530				delete this.element.data().date;
18531			}
18532
18533			dates = $.map(dates, $.proxy(function(date){
18534				return DPGlobal.parseDate(date, this.o.format, this.o.language, this.o.assumeNearbyYear);
18535			}, this));
18536			dates = $.grep(dates, $.proxy(function(date){
18537				return (
18538					!this.dateWithinRange(date) ||
18539					!date
18540				);
18541			}, this), true);
18542			this.dates.replace(dates);
18543
18544			if (this.o.updateViewDate) {
18545				if (this.dates.length)
18546					this.viewDate = new Date(this.dates.get(-1));
18547				else if (this.viewDate < this.o.startDate)
18548					this.viewDate = new Date(this.o.startDate);
18549				else if (this.viewDate > this.o.endDate)
18550					this.viewDate = new Date(this.o.endDate);
18551				else
18552					this.viewDate = this.o.defaultViewDate;
18553			}
18554
18555			if (fromArgs){
18556				// setting date by clicking
18557				this.setValue();
18558				this.element.change();
18559			}
18560			else if (this.dates.length){
18561				// setting date by typing
18562				if (String(oldDates) !== String(this.dates) && fromArgs) {
18563					this._trigger('changeDate');
18564					this.element.change();
18565				}
18566			}
18567			if (!this.dates.length && oldDates.length) {
18568				this._trigger('clearDate');
18569				this.element.change();
18570			}
18571
18572			this.fill();
18573			return this;
18574		},
18575
18576		fillDow: function(){
18577      if (this.o.showWeekDays) {
18578			var dowCnt = this.o.weekStart,
18579				html = '<tr>';
18580			if (this.o.calendarWeeks){
18581				html += '<th class="cw">&#160;</th>';
18582			}
18583			while (dowCnt < this.o.weekStart + 7){
18584				html += '<th class="dow';
18585        if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) !== -1)
18586          html += ' disabled';
18587        html += '">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
18588			}
18589			html += '</tr>';
18590			this.picker.find('.datepicker-days thead').append(html);
18591      }
18592		},
18593
18594		fillMonths: function(){
18595      var localDate = this._utc_to_local(this.viewDate);
18596			var html = '';
18597			var focused;
18598			for (var i = 0; i < 12; i++){
18599				focused = localDate && localDate.getMonth() === i ? ' focused' : '';
18600				html += '<span class="month' + focused + '">' + dates[this.o.language].monthsShort[i] + '</span>';
18601			}
18602			this.picker.find('.datepicker-months td').html(html);
18603		},
18604
18605		setRange: function(range){
18606			if (!range || !range.length)
18607				delete this.range;
18608			else
18609				this.range = $.map(range, function(d){
18610					return d.valueOf();
18611				});
18612			this.fill();
18613		},
18614
18615		getClassNames: function(date){
18616			var cls = [],
18617				year = this.viewDate.getUTCFullYear(),
18618				month = this.viewDate.getUTCMonth(),
18619				today = UTCToday();
18620			if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){
18621				cls.push('old');
18622			} else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
18623				cls.push('new');
18624			}
18625			if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
18626				cls.push('focused');
18627			// Compare internal UTC date with UTC today, not local today
18628			if (this.o.todayHighlight && isUTCEquals(date, today)) {
18629				cls.push('today');
18630			}
18631			if (this.dates.contains(date) !== -1)
18632				cls.push('active');
18633			if (!this.dateWithinRange(date)){
18634				cls.push('disabled');
18635			}
18636			if (this.dateIsDisabled(date)){
18637				cls.push('disabled', 'disabled-date');
18638			}
18639			if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1){
18640				cls.push('highlighted');
18641			}
18642
18643			if (this.range){
18644				if (date > this.range[0] && date < this.range[this.range.length-1]){
18645					cls.push('range');
18646				}
18647				if ($.inArray(date.valueOf(), this.range) !== -1){
18648					cls.push('selected');
18649				}
18650				if (date.valueOf() === this.range[0]){
18651          cls.push('range-start');
18652        }
18653        if (date.valueOf() === this.range[this.range.length-1]){
18654          cls.push('range-end');
18655        }
18656			}
18657			return cls;
18658		},
18659
18660		_fill_yearsView: function(selector, cssClass, factor, year, startYear, endYear, beforeFn){
18661			var html = '';
18662			var step = factor / 10;
18663			var view = this.picker.find(selector);
18664			var startVal = Math.floor(year / factor) * factor;
18665			var endVal = startVal + step * 9;
18666			var focusedVal = Math.floor(this.viewDate.getFullYear() / step) * step;
18667			var selected = $.map(this.dates, function(d){
18668				return Math.floor(d.getUTCFullYear() / step) * step;
18669			});
18670
18671			var classes, tooltip, before;
18672			for (var currVal = startVal - step; currVal <= endVal + step; currVal += step) {
18673				classes = [cssClass];
18674				tooltip = null;
18675
18676				if (currVal === startVal - step) {
18677					classes.push('old');
18678				} else if (currVal === endVal + step) {
18679					classes.push('new');
18680				}
18681				if ($.inArray(currVal, selected) !== -1) {
18682					classes.push('active');
18683				}
18684				if (currVal < startYear || currVal > endYear) {
18685					classes.push('disabled');
18686				}
18687				if (currVal === focusedVal) {
18688				  classes.push('focused');
18689        }
18690
18691				if (beforeFn !== $.noop) {
18692					before = beforeFn(new Date(currVal, 0, 1));
18693					if (before === undefined) {
18694						before = {};
18695					} else if (typeof before === 'boolean') {
18696						before = {enabled: before};
18697					} else if (typeof before === 'string') {
18698						before = {classes: before};
18699					}
18700					if (before.enabled === false) {
18701						classes.push('disabled');
18702					}
18703					if (before.classes) {
18704						classes = classes.concat(before.classes.split(/\s+/));
18705					}
18706					if (before.tooltip) {
18707						tooltip = before.tooltip;
18708					}
18709				}
18710
18711				html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + currVal + '</span>';
18712			}
18713
18714			view.find('.datepicker-switch').text(startVal + '-' + endVal);
18715			view.find('td').html(html);
18716		},
18717
18718		fill: function(){
18719			var d = new Date(this.viewDate),
18720				year = d.getUTCFullYear(),
18721				month = d.getUTCMonth(),
18722				startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
18723				startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
18724				endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
18725				endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
18726				todaytxt = dates[this.o.language].today || dates['en'].today || '',
18727				cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
18728        titleFormat = dates[this.o.language].titleFormat || dates['en'].titleFormat,
18729        todayDate = UTCToday(),
18730        titleBtnVisible = (this.o.todayBtn === true || this.o.todayBtn === 'linked') && todayDate >= this.o.startDate && todayDate <= this.o.endDate && !this.weekOfDateIsDisabled(todayDate),
18731				tooltip,
18732				before;
18733			if (isNaN(year) || isNaN(month))
18734				return;
18735			this.picker.find('.datepicker-days .datepicker-switch')
18736						.text(DPGlobal.formatDate(d, titleFormat, this.o.language));
18737			this.picker.find('tfoot .today')
18738						.text(todaytxt)
18739            .css('display', titleBtnVisible ? 'table-cell' : 'none');
18740			this.picker.find('tfoot .clear')
18741						.text(cleartxt)
18742						.css('display', this.o.clearBtn === true ? 'table-cell' : 'none');
18743			this.picker.find('thead .datepicker-title')
18744						.text(this.o.title)
18745						.css('display', typeof this.o.title === 'string' && this.o.title !== '' ? 'table-cell' : 'none');
18746			this.updateNavArrows();
18747			this.fillMonths();
18748			var prevMonth = UTCDate(year, month, 0),
18749				day = prevMonth.getUTCDate();
18750			prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);
18751			var nextMonth = new Date(prevMonth);
18752			if (prevMonth.getUTCFullYear() < 100){
18753        nextMonth.setUTCFullYear(prevMonth.getUTCFullYear());
18754      }
18755			nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
18756			nextMonth = nextMonth.valueOf();
18757			var html = [];
18758			var weekDay, clsName;
18759			while (prevMonth.valueOf() < nextMonth){
18760				weekDay = prevMonth.getUTCDay();
18761				if (weekDay === this.o.weekStart){
18762					html.push('<tr>');
18763					if (this.o.calendarWeeks){
18764						// ISO 8601: First week contains first thursday.
18765						// ISO also states week starts on Monday, but we can be more abstract here.
18766						var
18767							// Start of current week: based on weekstart/current date
18768							ws = new Date(+prevMonth + (this.o.weekStart - weekDay - 7) % 7 * 864e5),
18769							// Thursday of this week
18770							th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
18771							// First Thursday of year, year from thursday
18772							yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay()) % 7 * 864e5),
18773							// Calendar week: ms between thursdays, div ms per day, div 7 days
18774							calWeek = (th - yth) / 864e5 / 7 + 1;
18775						html.push('<td class="cw">'+ calWeek +'</td>');
18776					}
18777				}
18778				clsName = this.getClassNames(prevMonth);
18779				clsName.push('day');
18780
18781				var content = prevMonth.getUTCDate();
18782
18783				if (this.o.beforeShowDay !== $.noop){
18784					before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
18785					if (before === undefined)
18786						before = {};
18787					else if (typeof before === 'boolean')
18788						before = {enabled: before};
18789					else if (typeof before === 'string')
18790						before = {classes: before};
18791					if (before.enabled === false)
18792						clsName.push('disabled');
18793					if (before.classes)
18794						clsName = clsName.concat(before.classes.split(/\s+/));
18795					if (before.tooltip)
18796						tooltip = before.tooltip;
18797					if (before.content)
18798						content = before.content;
18799				}
18800
18801				//Check if uniqueSort exists (supported by jquery >=1.12 and >=2.2)
18802				//Fallback to unique function for older jquery versions
18803				if ($.isFunction($.uniqueSort)) {
18804					clsName = $.uniqueSort(clsName);
18805				} else {
18806					clsName = $.unique(clsName);
18807				}
18808
18809				html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + ' data-date="' + prevMonth.getTime().toString() + '">' + content + '</td>');
18810				tooltip = null;
18811				if (weekDay === this.o.weekEnd){
18812					html.push('</tr>');
18813				}
18814				prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
18815			}
18816			this.picker.find('.datepicker-days tbody').html(html.join(''));
18817
18818			var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months';
18819			var months = this.picker.find('.datepicker-months')
18820						.find('.datepicker-switch')
18821							.text(this.o.maxViewMode < 2 ? monthsTitle : year)
18822							.end()
18823						.find('tbody span').removeClass('active');
18824
18825			$.each(this.dates, function(i, d){
18826				if (d.getUTCFullYear() === year)
18827					months.eq(d.getUTCMonth()).addClass('active');
18828			});
18829
18830			if (year < startYear || year > endYear){
18831				months.addClass('disabled');
18832			}
18833			if (year === startYear){
18834				months.slice(0, startMonth).addClass('disabled');
18835			}
18836			if (year === endYear){
18837				months.slice(endMonth+1).addClass('disabled');
18838			}
18839
18840			if (this.o.beforeShowMonth !== $.noop){
18841				var that = this;
18842				$.each(months, function(i, month){
18843          var moDate = new Date(year, i, 1);
18844          var before = that.o.beforeShowMonth(moDate);
18845					if (before === undefined)
18846						before = {};
18847					else if (typeof before === 'boolean')
18848						before = {enabled: before};
18849					else if (typeof before === 'string')
18850						before = {classes: before};
18851					if (before.enabled === false && !$(month).hasClass('disabled'))
18852					    $(month).addClass('disabled');
18853					if (before.classes)
18854					    $(month).addClass(before.classes);
18855					if (before.tooltip)
18856					    $(month).prop('title', before.tooltip);
18857				});
18858			}
18859
18860			// Generating decade/years picker
18861			this._fill_yearsView(
18862				'.datepicker-years',
18863				'year',
18864				10,
18865				year,
18866				startYear,
18867				endYear,
18868				this.o.beforeShowYear
18869			);
18870
18871			// Generating century/decades picker
18872			this._fill_yearsView(
18873				'.datepicker-decades',
18874				'decade',
18875				100,
18876				year,
18877				startYear,
18878				endYear,
18879				this.o.beforeShowDecade
18880			);
18881
18882			// Generating millennium/centuries picker
18883			this._fill_yearsView(
18884				'.datepicker-centuries',
18885				'century',
18886				1000,
18887				year,
18888				startYear,
18889				endYear,
18890				this.o.beforeShowCentury
18891			);
18892		},
18893
18894		updateNavArrows: function(){
18895			if (!this._allow_update)
18896				return;
18897
18898			var d = new Date(this.viewDate),
18899				year = d.getUTCFullYear(),
18900				month = d.getUTCMonth(),
18901				startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
18902				startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
18903				endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
18904				endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
18905				prevIsDisabled,
18906				nextIsDisabled,
18907				factor = 1;
18908			switch (this.viewMode){
18909				case 4:
18910					factor *= 10;
18911					/* falls through */
18912				case 3:
18913					factor *= 10;
18914					/* falls through */
18915				case 2:
18916					factor *= 10;
18917					/* falls through */
18918				case 1:
18919					prevIsDisabled = Math.floor(year / factor) * factor <= startYear;
18920					nextIsDisabled = Math.floor(year / factor) * factor + factor > endYear;
18921					break;
18922				case 0:
18923					prevIsDisabled = year <= startYear && month <= startMonth;
18924					nextIsDisabled = year >= endYear && month >= endMonth;
18925					break;
18926			}
18927
18928			this.picker.find('.prev').toggleClass('disabled', prevIsDisabled);
18929			this.picker.find('.next').toggleClass('disabled', nextIsDisabled);
18930		},
18931
18932		click: function(e){
18933			e.preventDefault();
18934			e.stopPropagation();
18935
18936			var target, dir, day, year, month;
18937			target = $(e.target);
18938
18939			// Clicked on the switch
18940			if (target.hasClass('datepicker-switch') && this.viewMode !== this.o.maxViewMode){
18941				this.setViewMode(this.viewMode + 1);
18942			}
18943
18944			// Clicked on today button
18945			if (target.hasClass('today') && !target.hasClass('day')){
18946				this.setViewMode(0);
18947				this._setDate(UTCToday(), this.o.todayBtn === 'linked' ? null : 'view');
18948			}
18949
18950			// Clicked on clear button
18951			if (target.hasClass('clear')){
18952				this.clearDates();
18953			}
18954
18955			if (!target.hasClass('disabled')){
18956				// Clicked on a month, year, decade, century
18957				if (target.hasClass('month')
18958						|| target.hasClass('year')
18959						|| target.hasClass('decade')
18960						|| target.hasClass('century')) {
18961					this.viewDate.setUTCDate(1);
18962
18963					day = 1;
18964					if (this.viewMode === 1){
18965						month = target.parent().find('span').index(target);
18966						year = this.viewDate.getUTCFullYear();
18967						this.viewDate.setUTCMonth(month);
18968					} else {
18969						month = 0;
18970						year = Number(target.text());
18971						this.viewDate.setUTCFullYear(year);
18972					}
18973
18974					this._trigger(DPGlobal.viewModes[this.viewMode - 1].e, this.viewDate);
18975
18976					if (this.viewMode === this.o.minViewMode){
18977						this._setDate(UTCDate(year, month, day));
18978					} else {
18979						this.setViewMode(this.viewMode - 1);
18980						this.fill();
18981					}
18982				}
18983			}
18984
18985			if (this.picker.is(':visible') && this._focused_from){
18986				this._focused_from.focus();
18987			}
18988			delete this._focused_from;
18989		},
18990
18991		dayCellClick: function(e){
18992			var $target = $(e.currentTarget);
18993			var timestamp = $target.data('date');
18994			var date = new Date(timestamp);
18995
18996			if (this.o.updateViewDate) {
18997				if (date.getUTCFullYear() !== this.viewDate.getUTCFullYear()) {
18998					this._trigger('changeYear', this.viewDate);
18999				}
19000
19001				if (date.getUTCMonth() !== this.viewDate.getUTCMonth()) {
19002					this._trigger('changeMonth', this.viewDate);
19003				}
19004			}
19005			this._setDate(date);
19006		},
19007
19008		// Clicked on prev or next
19009		navArrowsClick: function(e){
19010			var $target = $(e.currentTarget);
19011			var dir = $target.hasClass('prev') ? -1 : 1;
19012			if (this.viewMode !== 0){
19013				dir *= DPGlobal.viewModes[this.viewMode].navStep * 12;
19014			}
19015			this.viewDate = this.moveMonth(this.viewDate, dir);
19016			this._trigger(DPGlobal.viewModes[this.viewMode].e, this.viewDate);
19017			this.fill();
19018		},
19019
19020		_toggle_multidate: function(date){
19021			var ix = this.dates.contains(date);
19022			if (!date){
19023				this.dates.clear();
19024			}
19025
19026			if (ix !== -1){
19027				if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive){
19028					this.dates.remove(ix);
19029				}
19030			} else if (this.o.multidate === false) {
19031				this.dates.clear();
19032				this.dates.push(date);
19033			}
19034			else {
19035				this.dates.push(date);
19036			}
19037
19038			if (typeof this.o.multidate === 'number')
19039				while (this.dates.length > this.o.multidate)
19040					this.dates.remove(0);
19041		},
19042
19043		_setDate: function(date, which){
19044			if (!which || which === 'date')
19045				this._toggle_multidate(date && new Date(date));
19046			if ((!which && this.o.updateViewDate) || which === 'view')
19047				this.viewDate = date && new Date(date);
19048
19049			this.fill();
19050			this.setValue();
19051			if (!which || which !== 'view') {
19052				this._trigger('changeDate');
19053			}
19054			this.inputField.trigger('change');
19055			if (this.o.autoclose && (!which || which === 'date')){
19056				this.hide();
19057			}
19058		},
19059
19060		moveDay: function(date, dir){
19061			var newDate = new Date(date);
19062			newDate.setUTCDate(date.getUTCDate() + dir);
19063
19064			return newDate;
19065		},
19066
19067		moveWeek: function(date, dir){
19068			return this.moveDay(date, dir * 7);
19069		},
19070
19071		moveMonth: function(date, dir){
19072			if (!isValidDate(date))
19073				return this.o.defaultViewDate;
19074			if (!dir)
19075				return date;
19076			var new_date = new Date(date.valueOf()),
19077				day = new_date.getUTCDate(),
19078				month = new_date.getUTCMonth(),
19079				mag = Math.abs(dir),
19080				new_month, test;
19081			dir = dir > 0 ? 1 : -1;
19082			if (mag === 1){
19083				test = dir === -1
19084					// If going back one month, make sure month is not current month
19085					// (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
19086					? function(){
19087						return new_date.getUTCMonth() === month;
19088					}
19089					// If going forward one month, make sure month is as expected
19090					// (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
19091					: function(){
19092						return new_date.getUTCMonth() !== new_month;
19093					};
19094				new_month = month + dir;
19095				new_date.setUTCMonth(new_month);
19096				// Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
19097				new_month = (new_month + 12) % 12;
19098			}
19099			else {
19100				// For magnitudes >1, move one month at a time...
19101				for (var i=0; i < mag; i++)
19102					// ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
19103					new_date = this.moveMonth(new_date, dir);
19104				// ...then reset the day, keeping it in the new month
19105				new_month = new_date.getUTCMonth();
19106				new_date.setUTCDate(day);
19107				test = function(){
19108					return new_month !== new_date.getUTCMonth();
19109				};
19110			}
19111			// Common date-resetting loop -- if date is beyond end of month, make it
19112			// end of month
19113			while (test()){
19114				new_date.setUTCDate(--day);
19115				new_date.setUTCMonth(new_month);
19116			}
19117			return new_date;
19118		},
19119
19120		moveYear: function(date, dir){
19121			return this.moveMonth(date, dir*12);
19122		},
19123
19124		moveAvailableDate: function(date, dir, fn){
19125			do {
19126				date = this[fn](date, dir);
19127
19128				if (!this.dateWithinRange(date))
19129					return false;
19130
19131				fn = 'moveDay';
19132			}
19133			while (this.dateIsDisabled(date));
19134
19135			return date;
19136		},
19137
19138		weekOfDateIsDisabled: function(date){
19139			return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1;
19140		},
19141
19142		dateIsDisabled: function(date){
19143			return (
19144				this.weekOfDateIsDisabled(date) ||
19145				$.grep(this.o.datesDisabled, function(d){
19146					return isUTCEquals(date, d);
19147				}).length > 0
19148			);
19149		},
19150
19151		dateWithinRange: function(date){
19152			return date >= this.o.startDate && date <= this.o.endDate;
19153		},
19154
19155		keydown: function(e){
19156			if (!this.picker.is(':visible')){
19157				if (e.keyCode === 40 || e.keyCode === 27) { // allow down to re-show picker
19158					this.show();
19159					e.stopPropagation();
19160        }
19161				return;
19162			}
19163			var dateChanged = false,
19164				dir, newViewDate,
19165				focusDate = this.focusDate || this.viewDate;
19166			switch (e.keyCode){
19167				case 27: // escape
19168					if (this.focusDate){
19169						this.focusDate = null;
19170						this.viewDate = this.dates.get(-1) || this.viewDate;
19171						this.fill();
19172					}
19173					else
19174						this.hide();
19175					e.preventDefault();
19176					e.stopPropagation();
19177					break;
19178				case 37: // left
19179				case 38: // up
19180				case 39: // right
19181				case 40: // down
19182					if (!this.o.keyboardNavigation || this.o.daysOfWeekDisabled.length === 7)
19183						break;
19184					dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1;
19185          if (this.viewMode === 0) {
19186  					if (e.ctrlKey){
19187  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
19188
19189  						if (newViewDate)
19190  							this._trigger('changeYear', this.viewDate);
19191  					} else if (e.shiftKey){
19192  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
19193
19194  						if (newViewDate)
19195  							this._trigger('changeMonth', this.viewDate);
19196  					} else if (e.keyCode === 37 || e.keyCode === 39){
19197  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay');
19198  					} else if (!this.weekOfDateIsDisabled(focusDate)){
19199  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek');
19200  					}
19201          } else if (this.viewMode === 1) {
19202            if (e.keyCode === 38 || e.keyCode === 40) {
19203              dir = dir * 4;
19204            }
19205            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
19206          } else if (this.viewMode === 2) {
19207            if (e.keyCode === 38 || e.keyCode === 40) {
19208              dir = dir * 4;
19209            }
19210            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
19211          }
19212					if (newViewDate){
19213						this.focusDate = this.viewDate = newViewDate;
19214						this.setValue();
19215						this.fill();
19216						e.preventDefault();
19217					}
19218					break;
19219				case 13: // enter
19220					if (!this.o.forceParse)
19221						break;
19222					focusDate = this.focusDate || this.dates.get(-1) || this.viewDate;
19223					if (this.o.keyboardNavigation) {
19224						this._toggle_multidate(focusDate);
19225						dateChanged = true;
19226					}
19227					this.focusDate = null;
19228					this.viewDate = this.dates.get(-1) || this.viewDate;
19229					this.setValue();
19230					this.fill();
19231					if (this.picker.is(':visible')){
19232						e.preventDefault();
19233						e.stopPropagation();
19234						if (this.o.autoclose)
19235							this.hide();
19236					}
19237					break;
19238				case 9: // tab
19239					this.focusDate = null;
19240					this.viewDate = this.dates.get(-1) || this.viewDate;
19241					this.fill();
19242					this.hide();
19243					break;
19244			}
19245			if (dateChanged){
19246				if (this.dates.length)
19247					this._trigger('changeDate');
19248				else
19249					this._trigger('clearDate');
19250				this.inputField.trigger('change');
19251			}
19252		},
19253
19254		setViewMode: function(viewMode){
19255			this.viewMode = viewMode;
19256			this.picker
19257				.children('div')
19258				.hide()
19259				.filter('.datepicker-' + DPGlobal.viewModes[this.viewMode].clsName)
19260					.show();
19261			this.updateNavArrows();
19262      this._trigger('changeViewMode', new Date(this.viewDate));
19263		}
19264	};
19265
19266	var DateRangePicker = function(element, options){
19267		$.data(element, 'datepicker', this);
19268		this.element = $(element);
19269		this.inputs = $.map(options.inputs, function(i){
19270			return i.jquery ? i[0] : i;
19271		});
19272		delete options.inputs;
19273
19274		this.keepEmptyValues = options.keepEmptyValues;
19275		delete options.keepEmptyValues;
19276
19277		datepickerPlugin.call($(this.inputs), options)
19278			.on('changeDate', $.proxy(this.dateUpdated, this));
19279
19280		this.pickers = $.map(this.inputs, function(i){
19281			return $.data(i, 'datepicker');
19282		});
19283		this.updateDates();
19284	};
19285	DateRangePicker.prototype = {
19286		updateDates: function(){
19287			this.dates = $.map(this.pickers, function(i){
19288				return i.getUTCDate();
19289			});
19290			this.updateRanges();
19291		},
19292		updateRanges: function(){
19293			var range = $.map(this.dates, function(d){
19294				return d.valueOf();
19295			});
19296			$.each(this.pickers, function(i, p){
19297				p.setRange(range);
19298			});
19299		},
19300		clearDates: function(){
19301			$.each(this.pickers, function(i, p){
19302				p.clearDates();
19303			});
19304		},
19305		dateUpdated: function(e){
19306			// `this.updating` is a workaround for preventing infinite recursion
19307			// between `changeDate` triggering and `setUTCDate` calling.  Until
19308			// there is a better mechanism.
19309			if (this.updating)
19310				return;
19311			this.updating = true;
19312
19313			var dp = $.data(e.target, 'datepicker');
19314
19315			if (dp === undefined) {
19316				return;
19317			}
19318
19319			var new_date = dp.getUTCDate(),
19320				keep_empty_values = this.keepEmptyValues,
19321				i = $.inArray(e.target, this.inputs),
19322				j = i - 1,
19323				k = i + 1,
19324				l = this.inputs.length;
19325			if (i === -1)
19326				return;
19327
19328			$.each(this.pickers, function(i, p){
19329				if (!p.getUTCDate() && (p === dp || !keep_empty_values))
19330					p.setUTCDate(new_date);
19331			});
19332
19333			if (new_date < this.dates[j]){
19334				// Date being moved earlier/left
19335				while (j >= 0 && new_date < this.dates[j]){
19336					this.pickers[j--].setUTCDate(new_date);
19337				}
19338			} else if (new_date > this.dates[k]){
19339				// Date being moved later/right
19340				while (k < l && new_date > this.dates[k]){
19341					this.pickers[k++].setUTCDate(new_date);
19342				}
19343			}
19344			this.updateDates();
19345
19346			delete this.updating;
19347		},
19348		destroy: function(){
19349			$.map(this.pickers, function(p){ p.destroy(); });
19350			$(this.inputs).off('changeDate', this.dateUpdated);
19351			delete this.element.data().datepicker;
19352		},
19353		remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead')
19354	};
19355
19356	function opts_from_el(el, prefix){
19357		// Derive options from element data-attrs
19358		var data = $(el).data(),
19359			out = {}, inkey,
19360			replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])');
19361		prefix = new RegExp('^' + prefix.toLowerCase());
19362		function re_lower(_,a){
19363			return a.toLowerCase();
19364		}
19365		for (var key in data)
19366			if (prefix.test(key)){
19367				inkey = key.replace(replace, re_lower);
19368				out[inkey] = data[key];
19369			}
19370		return out;
19371	}
19372
19373	function opts_from_locale(lang){
19374		// Derive options from locale plugins
19375		var out = {};
19376		// Check if "de-DE" style date is available, if not language should
19377		// fallback to 2 letter code eg "de"
19378		if (!dates[lang]){
19379			lang = lang.split('-')[0];
19380			if (!dates[lang])
19381				return;
19382		}
19383		var d = dates[lang];
19384		$.each(locale_opts, function(i,k){
19385			if (k in d)
19386				out[k] = d[k];
19387		});
19388		return out;
19389	}
19390
19391	var old = $.fn.datepicker;
19392	var datepickerPlugin = function(option){
19393		var args = Array.apply(null, arguments);
19394		args.shift();
19395		var internal_return;
19396		this.each(function(){
19397			var $this = $(this),
19398				data = $this.data('datepicker'),
19399				options = typeof option === 'object' && option;
19400			if (!data){
19401				var elopts = opts_from_el(this, 'date'),
19402					// Preliminary otions
19403					xopts = $.extend({}, defaults, elopts, options),
19404					locopts = opts_from_locale(xopts.language),
19405					// Options priority: js args, data-attrs, locales, defaults
19406					opts = $.extend({}, defaults, locopts, elopts, options);
19407				if ($this.hasClass('input-daterange') || opts.inputs){
19408					$.extend(opts, {
19409						inputs: opts.inputs || $this.find('input').toArray()
19410					});
19411					data = new DateRangePicker(this, opts);
19412				}
19413				else {
19414					data = new Datepicker(this, opts);
19415				}
19416				$this.data('datepicker', data);
19417			}
19418			if (typeof option === 'string' && typeof data[option] === 'function'){
19419				internal_return = data[option].apply(data, args);
19420			}
19421		});
19422
19423		if (
19424			internal_return === undefined ||
19425			internal_return instanceof Datepicker ||
19426			internal_return instanceof DateRangePicker
19427		)
19428			return this;
19429
19430		if (this.length > 1)
19431			throw new Error('Using only allowed for the collection of a single element (' + option + ' function)');
19432		else
19433			return internal_return;
19434	};
19435	$.fn.datepicker = datepickerPlugin;
19436
19437	var defaults = $.fn.datepicker.defaults = {
19438		assumeNearbyYear: false,
19439		autoclose: false,
19440		beforeShowDay: $.noop,
19441		beforeShowMonth: $.noop,
19442		beforeShowYear: $.noop,
19443		beforeShowDecade: $.noop,
19444		beforeShowCentury: $.noop,
19445		calendarWeeks: false,
19446		clearBtn: false,
19447		toggleActive: false,
19448		daysOfWeekDisabled: [],
19449		daysOfWeekHighlighted: [],
19450		datesDisabled: [],
19451		endDate: Infinity,
19452		forceParse: true,
19453		format: 'mm/dd/yyyy',
19454		keepEmptyValues: false,
19455		keyboardNavigation: true,
19456		language: 'en',
19457		minViewMode: 0,
19458		maxViewMode: 4,
19459		multidate: false,
19460		multidateSeparator: ',',
19461		orientation: "auto",
19462		rtl: false,
19463		startDate: -Infinity,
19464		startView: 0,
19465		todayBtn: false,
19466		todayHighlight: false,
19467		updateViewDate: true,
19468		weekStart: 0,
19469		disableTouchKeyboard: false,
19470		enableOnReadonly: true,
19471		showOnFocus: true,
19472		zIndexOffset: 10,
19473		container: 'body',
19474		immediateUpdates: false,
19475		title: '',
19476		templates: {
19477			leftArrow: '&#x00AB;',
19478			rightArrow: '&#x00BB;'
19479		},
19480    showWeekDays: true
19481	};
19482	var locale_opts = $.fn.datepicker.locale_opts = [
19483		'format',
19484		'rtl',
19485		'weekStart'
19486	];
19487	$.fn.datepicker.Constructor = Datepicker;
19488	var dates = $.fn.datepicker.dates = {
19489		en: {
19490			days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
19491			daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
19492			daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
19493			months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
19494			monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
19495			today: "Today",
19496			clear: "Clear",
19497			titleFormat: "MM yyyy"
19498		}
19499	};
19500
19501	var DPGlobal = {
19502		viewModes: [
19503			{
19504				names: ['days', 'month'],
19505				clsName: 'days',
19506				e: 'changeMonth'
19507			},
19508			{
19509				names: ['months', 'year'],
19510				clsName: 'months',
19511				e: 'changeYear',
19512				navStep: 1
19513			},
19514			{
19515				names: ['years', 'decade'],
19516				clsName: 'years',
19517				e: 'changeDecade',
19518				navStep: 10
19519			},
19520			{
19521				names: ['decades', 'century'],
19522				clsName: 'decades',
19523				e: 'changeCentury',
19524				navStep: 100
19525			},
19526			{
19527				names: ['centuries', 'millennium'],
19528				clsName: 'centuries',
19529				e: 'changeMillennium',
19530				navStep: 1000
19531			}
19532		],
19533		validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
19534		nonpunctuation: /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,
19535		parseFormat: function(format){
19536			if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function')
19537                return format;
19538            // IE treats \0 as a string end in inputs (truncating the value),
19539			// so it's a bad format delimiter, anyway
19540			var separators = format.replace(this.validParts, '\0').split('\0'),
19541				parts = format.match(this.validParts);
19542			if (!separators || !separators.length || !parts || parts.length === 0){
19543				throw new Error("Invalid date format.");
19544			}
19545			return {separators: separators, parts: parts};
19546		},
19547		parseDate: function(date, format, language, assumeNearby){
19548			if (!date)
19549				return undefined;
19550			if (date instanceof Date)
19551				return date;
19552			if (typeof format === 'string')
19553				format = DPGlobal.parseFormat(format);
19554			if (format.toValue)
19555				return format.toValue(date, format, language);
19556			var fn_map = {
19557					d: 'moveDay',
19558					m: 'moveMonth',
19559					w: 'moveWeek',
19560					y: 'moveYear'
19561				},
19562				dateAliases = {
19563					yesterday: '-1d',
19564					today: '+0d',
19565					tomorrow: '+1d'
19566				},
19567				parts, part, dir, i, fn;
19568			if (date in dateAliases){
19569				date = dateAliases[date];
19570			}
19571			if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(date)){
19572				parts = date.match(/([\-+]\d+)([dmwy])/gi);
19573				date = new Date();
19574				for (i=0; i < parts.length; i++){
19575					part = parts[i].match(/([\-+]\d+)([dmwy])/i);
19576					dir = Number(part[1]);
19577					fn = fn_map[part[2].toLowerCase()];
19578					date = Datepicker.prototype[fn](date, dir);
19579				}
19580				return Datepicker.prototype._zero_utc_time(date);
19581			}
19582
19583			parts = date && date.match(this.nonpunctuation) || [];
19584
19585			function applyNearbyYear(year, threshold){
19586				if (threshold === true)
19587					threshold = 10;
19588
19589				// if year is 2 digits or less, than the user most likely is trying to get a recent century
19590				if (year < 100){
19591					year += 2000;
19592					// if the new year is more than threshold years in advance, use last century
19593					if (year > ((new Date()).getFullYear()+threshold)){
19594						year -= 100;
19595					}
19596				}
19597
19598				return year;
19599			}
19600
19601			var parsed = {},
19602				setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
19603				setters_map = {
19604					yyyy: function(d,v){
19605						return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
19606					},
19607					m: function(d,v){
19608						if (isNaN(d))
19609							return d;
19610						v -= 1;
19611						while (v < 0) v += 12;
19612						v %= 12;
19613						d.setUTCMonth(v);
19614						while (d.getUTCMonth() !== v)
19615							d.setUTCDate(d.getUTCDate()-1);
19616						return d;
19617					},
19618					d: function(d,v){
19619						return d.setUTCDate(v);
19620					}
19621				},
19622				val, filtered;
19623			setters_map['yy'] = setters_map['yyyy'];
19624			setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
19625			setters_map['dd'] = setters_map['d'];
19626			date = UTCToday();
19627			var fparts = format.parts.slice();
19628			// Remove noop parts
19629			if (parts.length !== fparts.length){
19630				fparts = $(fparts).filter(function(i,p){
19631					return $.inArray(p, setters_order) !== -1;
19632				}).toArray();
19633			}
19634			// Process remainder
19635			function match_part(){
19636				var m = this.slice(0, parts[i].length),
19637					p = parts[i].slice(0, m.length);
19638				return m.toLowerCase() === p.toLowerCase();
19639			}
19640			if (parts.length === fparts.length){
19641				var cnt;
19642				for (i=0, cnt = fparts.length; i < cnt; i++){
19643					val = parseInt(parts[i], 10);
19644					part = fparts[i];
19645					if (isNaN(val)){
19646						switch (part){
19647							case 'MM':
19648								filtered = $(dates[language].months).filter(match_part);
19649								val = $.inArray(filtered[0], dates[language].months) + 1;
19650								break;
19651							case 'M':
19652								filtered = $(dates[language].monthsShort).filter(match_part);
19653								val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
19654								break;
19655						}
19656					}
19657					parsed[part] = val;
19658				}
19659				var _date, s;
19660				for (i=0; i < setters_order.length; i++){
19661					s = setters_order[i];
19662					if (s in parsed && !isNaN(parsed[s])){
19663						_date = new Date(date);
19664						setters_map[s](_date, parsed[s]);
19665						if (!isNaN(_date))
19666							date = _date;
19667					}
19668				}
19669			}
19670			return date;
19671		},
19672		formatDate: function(date, format, language){
19673			if (!date)
19674				return '';
19675			if (typeof format === 'string')
19676				format = DPGlobal.parseFormat(format);
19677			if (format.toDisplay)
19678                return format.toDisplay(date, format, language);
19679            var val = {
19680				d: date.getUTCDate(),
19681				D: dates[language].daysShort[date.getUTCDay()],
19682				DD: dates[language].days[date.getUTCDay()],
19683				m: date.getUTCMonth() + 1,
19684				M: dates[language].monthsShort[date.getUTCMonth()],
19685				MM: dates[language].months[date.getUTCMonth()],
19686				yy: date.getUTCFullYear().toString().substring(2),
19687				yyyy: date.getUTCFullYear()
19688			};
19689			val.dd = (val.d < 10 ? '0' : '') + val.d;
19690			val.mm = (val.m < 10 ? '0' : '') + val.m;
19691			date = [];
19692			var seps = $.extend([], format.separators);
19693			for (var i=0, cnt = format.parts.length; i <= cnt; i++){
19694				if (seps.length)
19695					date.push(seps.shift());
19696				date.push(val[format.parts[i]]);
19697			}
19698			return date.join('');
19699		},
19700		headTemplate: '<thead>'+
19701			              '<tr>'+
19702			                '<th colspan="7" class="datepicker-title"></th>'+
19703			              '</tr>'+
19704							'<tr>'+
19705								'<th class="prev">'+defaults.templates.leftArrow+'</th>'+
19706								'<th colspan="5" class="datepicker-switch"></th>'+
19707								'<th class="next">'+defaults.templates.rightArrow+'</th>'+
19708							'</tr>'+
19709						'</thead>',
19710		contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
19711		footTemplate: '<tfoot>'+
19712							'<tr>'+
19713								'<th colspan="7" class="today"></th>'+
19714							'</tr>'+
19715							'<tr>'+
19716								'<th colspan="7" class="clear"></th>'+
19717							'</tr>'+
19718						'</tfoot>'
19719	};
19720	DPGlobal.template = '<div class="datepicker">'+
19721							'<div class="datepicker-days">'+
19722								'<table class="table-condensed">'+
19723									DPGlobal.headTemplate+
19724									'<tbody></tbody>'+
19725									DPGlobal.footTemplate+
19726								'</table>'+
19727							'</div>'+
19728							'<div class="datepicker-months">'+
19729								'<table class="table-condensed">'+
19730									DPGlobal.headTemplate+
19731									DPGlobal.contTemplate+
19732									DPGlobal.footTemplate+
19733								'</table>'+
19734							'</div>'+
19735							'<div class="datepicker-years">'+
19736								'<table class="table-condensed">'+
19737									DPGlobal.headTemplate+
19738									DPGlobal.contTemplate+
19739									DPGlobal.footTemplate+
19740								'</table>'+
19741							'</div>'+
19742							'<div class="datepicker-decades">'+
19743								'<table class="table-condensed">'+
19744									DPGlobal.headTemplate+
19745									DPGlobal.contTemplate+
19746									DPGlobal.footTemplate+
19747								'</table>'+
19748							'</div>'+
19749							'<div class="datepicker-centuries">'+
19750								'<table class="table-condensed">'+
19751									DPGlobal.headTemplate+
19752									DPGlobal.contTemplate+
19753									DPGlobal.footTemplate+
19754								'</table>'+
19755							'</div>'+
19756						'</div>';
19757
19758	$.fn.datepicker.DPGlobal = DPGlobal;
19759
19760
19761	/* DATEPICKER NO CONFLICT
19762	* =================== */
19763
19764	$.fn.datepicker.noConflict = function(){
19765		$.fn.datepicker = old;
19766		return this;
19767	};
19768
19769	/* DATEPICKER VERSION
19770	 * =================== */
19771	$.fn.datepicker.version = '1.9.0';
19772
19773	$.fn.datepicker.deprecated = function(msg){
19774		var console = window.console;
19775		if (console && console.warn) {
19776			console.warn('DEPRECATED: ' + msg);
19777		}
19778	};
19779
19780
19781	/* DATEPICKER DATA-API
19782	* ================== */
19783
19784	$(document).on(
19785		'focus.datepicker.data-api click.datepicker.data-api',
19786		'[data-provide="datepicker"]',
19787		function(e){
19788			var $this = $(this);
19789			if ($this.data('datepicker'))
19790				return;
19791			e.preventDefault();
19792			// component click requires us to explicitly show it
19793			datepickerPlugin.call($this, 'show');
19794		}
19795	);
19796	$(function(){
19797		datepickerPlugin.call($('[data-provide="datepicker-inline"]'));
19798	});
19799
19800}));
19801!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
19802// version 2.1.7 Build: 371
19803// © Denis Ineshin, 2017
19804// https://github.com/IonDen
19805//
19806// Project page:    http://ionden.com/a/plugins/ion.rangeSlider/en.html
19807// GitHub page:     https://github.com/IonDen/ion.rangeSlider
19808//
19809// Released under MIT licence:
19810// http://ionden.com/a/plugins/licence-en.html
19811// =====================================================================================================================
19812//-------------------------------------------------- resizeInput
19813function resizeInput() {
19814    $('.resize_input').each(function(){
19815        $(this).attr('size', $(this).val().length);
19816    });
19817}
19818
19819;(function(factory) {
19820    if (typeof define === "function" && define.amd) {
19821        define(["jquery"], function (jQuery) {
19822            return factory(jQuery, document, window, navigator);
19823        });
19824    } else if (typeof exports === "object") {
19825        factory(require("jquery"), document, window, navigator);
19826    } else {
19827        factory(jQuery, document, window, navigator);
19828    }
19829} (function ($, document, window, navigator, undefined) {
19830    "use strict";
19831
19832    // =================================================================================================================
19833    // Service
19834
19835    var plugin_count = 0;
19836
19837    // IE8 fix
19838    var is_old_ie = (function () {
19839        var n = navigator.userAgent,
19840            r = /msie\s\d+/i,
19841            v;
19842        if (n.search(r) > 0) {
19843            v = r.exec(n).toString();
19844            v = v.split(" ")[1];
19845            if (v < 9) {
19846                $("html").addClass("lt-ie9");
19847                return true;
19848            }
19849        }
19850        return false;
19851    } ());
19852    if (!Function.prototype.bind) {
19853        Function.prototype.bind = function bind(that) {
19854
19855            var target = this;
19856            var slice = [].slice;
19857
19858            if (typeof target != "function") {
19859                throw new TypeError();
19860            }
19861
19862            var args = slice.call(arguments, 1),
19863                bound = function () {
19864
19865                    if (this instanceof bound) {
19866
19867                        var F = function(){};
19868                        F.prototype = target.prototype;
19869                        var self = new F();
19870
19871                        var result = target.apply(
19872                            self,
19873                            args.concat(slice.call(arguments))
19874                        );
19875                        if (Object(result) === result) {
19876                            return result;
19877                        }
19878                        return self;
19879
19880                    } else {
19881
19882                        return target.apply(
19883                            that,
19884                            args.concat(slice.call(arguments))
19885                        );
19886
19887                    }
19888
19889                };
19890
19891            return bound;
19892        };
19893    }
19894    if (!Array.prototype.indexOf) {
19895        Array.prototype.indexOf = function(searchElement, fromIndex) {
19896            var k;
19897            if (this == null) {
19898                throw new TypeError('"this" is null or not defined');
19899            }
19900            var O = Object(this);
19901            var len = O.length >>> 0;
19902            if (len === 0) {
19903                return -1;
19904            }
19905            var n = +fromIndex || 0;
19906            if (Math.abs(n) === Infinity) {
19907                n = 0;
19908            }
19909            if (n >= len) {
19910                return -1;
19911            }
19912            k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
19913            while (k < len) {
19914                if (k in O && O[k] === searchElement) {
19915                    return k;
19916                }
19917                k++;
19918            }
19919            return -1;
19920        };
19921    }
19922
19923
19924
19925    // =================================================================================================================
19926    // Template
19927
19928    var base_html =
19929        '<span class="irs">' +
19930        '<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>' +
19931        '<span class="irs-min">0</span><span class="irs-max">1</span>' +
19932        '<span class="irs-from">0</span><span class="irs-to">0</span><span class="irs-single">0</span>' +
19933        '</span>' +
19934        '<span class="irs-grid"></span>' +
19935        '<span class="irs-bar"></span>';
19936
19937    var single_html =
19938        '<span class="irs-bar-edge"></span>' +
19939        '<span class="irs-shadow shadow-single"></span>' +
19940        '<span class="irs-slider single"></span>';
19941
19942    var double_html =
19943        '<span class="irs-shadow shadow-from"></span>' +
19944        '<span class="irs-shadow shadow-to"></span>' +
19945        '<span class="irs-slider from"></span>' +
19946        '<span class="irs-slider to"></span>';
19947
19948    var disable_html =
19949        '<span class="irs-disable-mask"></span>';
19950
19951
19952
19953    // =================================================================================================================
19954    // Core
19955
19956    /**
19957     * Main plugin constructor
19958     *
19959     * @param input {Object} link to base input element
19960     * @param options {Object} slider config
19961     * @param plugin_count {Number}
19962     * @constructor
19963     */
19964    var IonRangeSlider = function (input, options, plugin_count) {
19965        this.VERSION = "2.1.7";
19966        this.input = input;
19967        this.plugin_count = plugin_count;
19968        this.current_plugin = 0;
19969        this.calc_count = 0;
19970        this.update_tm = 0;
19971        this.old_from = 0;
19972        this.old_to = 0;
19973        this.old_min_interval = null;
19974        this.raf_id = null;
19975        this.dragging = false;
19976        this.force_redraw = false;
19977        this.no_diapason = false;
19978        this.is_key = false;
19979        this.is_update = false;
19980        this.is_start = true;
19981        this.is_finish = false;
19982        this.is_active = false;
19983        this.is_resize = false;
19984        this.is_click = false;
19985
19986        options = options || {};
19987
19988        // cache for links to all DOM elements
19989        this.$cache = {
19990            win: $(window),
19991            body: $(document.body),
19992            input: $(input),
19993            cont: null,
19994            rs: null,
19995            min: null,
19996            max: null,
19997            from: null,
19998            to: null,
19999            single: null,
20000            bar: null,
20001            line: null,
20002            s_single: null,
20003            s_from: null,
20004            s_to: null,
20005            shad_single: null,
20006            shad_from: null,
20007            shad_to: null,
20008            edge: null,
20009            grid: null,
20010            grid_labels: []
20011        };
20012
20013        // storage for measure variables
20014        this.coords = {
20015            // left
20016            x_gap: 0,
20017            x_pointer: 0,
20018
20019            // width
20020            w_rs: 0,
20021            w_rs_old: 0,
20022            w_handle: 0,
20023
20024            // percents
20025            p_gap: 0,
20026            p_gap_left: 0,
20027            p_gap_right: 0,
20028            p_step: 0,
20029            p_pointer: 0,
20030            p_handle: 0,
20031            p_single_fake: 0,
20032            p_single_real: 0,
20033            p_from_fake: 0,
20034            p_from_real: 0,
20035            p_to_fake: 0,
20036            p_to_real: 0,
20037            p_bar_x: 0,
20038            p_bar_w: 0,
20039
20040            // grid
20041            grid_gap: 0,
20042            big_num: 0,
20043            big: [],
20044            big_w: [],
20045            big_p: [],
20046            big_x: []
20047        };
20048
20049        // storage for labels measure variables
20050        this.labels = {
20051            // width
20052            w_min: 0,
20053            w_max: 0,
20054            w_from: 0,
20055            w_to: 0,
20056            w_single: 0,
20057
20058            // percents
20059            p_min: 0,
20060            p_max: 0,
20061            p_from_fake: 0,
20062            p_from_left: 0,
20063            p_to_fake: 0,
20064            p_to_left: 0,
20065            p_single_fake: 0,
20066            p_single_left: 0
20067        };
20068
20069
20070
20071        /**
20072         * get and validate config
20073         */
20074        var $inp = this.$cache.input,
20075            val = $inp.prop("value"),
20076            config, config_from_data, prop;
20077
20078        // default config
20079        config = {
20080            type: "single",
20081
20082            min: 10,
20083            max: 100,
20084            from: null,
20085            to: null,
20086            step: 1,
20087
20088            min_interval: 0,
20089            max_interval: 0,
20090            drag_interval: false,
20091
20092            values: [],
20093            p_values: [],
20094
20095            from_fixed: false,
20096            from_min: null,
20097            from_max: null,
20098            from_shadow: false,
20099
20100            to_fixed: false,
20101            to_min: null,
20102            to_max: null,
20103            to_shadow: false,
20104
20105            prettify_enabled: true,
20106            prettify_separator: " ",
20107            prettify: null,
20108
20109            force_edges: false,
20110
20111            keyboard: false,
20112            keyboard_step: 5,
20113
20114            grid: false,
20115            grid_margin: true,
20116            grid_num: 4,
20117            grid_snap: false,
20118
20119            hide_min_max: false,
20120            hide_from_to: false,
20121
20122            prefix: "",
20123            postfix: "",
20124            max_postfix: "",
20125            decorate_both: true,
20126            values_separator: " — ",
20127
20128            input_values_separator: ";",
20129
20130            disable: false,
20131
20132            onStart: null,
20133            onChange: null,
20134            onFinish: null,
20135            onUpdate: null
20136        };
20137
20138
20139        // check if base element is input
20140        if ($inp[0].nodeName !== "INPUT") {
20141            console && console.warn && console.warn("Base element should be <input>!", $inp[0]);
20142        }
20143
20144
20145        // config from data-attributes extends js config
20146        config_from_data = {
20147            type: $inp.data("type"),
20148
20149            min: $inp.data("min"),
20150            max: $inp.data("max"),
20151            from: $inp.data("from"),
20152            to: $inp.data("to"),
20153            step: $inp.data("step"),
20154
20155            min_interval: $inp.data("minInterval"),
20156            max_interval: $inp.data("maxInterval"),
20157            drag_interval: $inp.data("dragInterval"),
20158
20159            values: $inp.data("values"),
20160
20161            from_fixed: $inp.data("fromFixed"),
20162            from_min: $inp.data("fromMin"),
20163            from_max: $inp.data("fromMax"),
20164            from_shadow: $inp.data("fromShadow"),
20165
20166            to_fixed: $inp.data("toFixed"),
20167            to_min: $inp.data("toMin"),
20168            to_max: $inp.data("toMax"),
20169            to_shadow: $inp.data("toShadow"),
20170
20171            prettify_enabled: $inp.data("prettifyEnabled"),
20172            prettify_separator: $inp.data("prettifySeparator"),
20173
20174            force_edges: $inp.data("forceEdges"),
20175
20176            keyboard: $inp.data("keyboard"),
20177            keyboard_step: $inp.data("keyboardStep"),
20178
20179            grid: $inp.data("grid"),
20180            grid_margin: $inp.data("gridMargin"),
20181            grid_num: $inp.data("gridNum"),
20182            grid_snap: $inp.data("gridSnap"),
20183
20184            hide_min_max: $inp.data("hideMinMax"),
20185            hide_from_to: $inp.data("hideFromTo"),
20186
20187            prefix: $inp.data("prefix"),
20188            postfix: $inp.data("postfix"),
20189            max_postfix: $inp.data("maxPostfix"),
20190            decorate_both: $inp.data("decorateBoth"),
20191            values_separator: $inp.data("valuesSeparator"),
20192
20193            input_values_separator: $inp.data("inputValuesSeparator"),
20194
20195            disable: $inp.data("disable")
20196        };
20197        config_from_data.values = config_from_data.values && config_from_data.values.split(",");
20198
20199        for (prop in config_from_data) {
20200            if (config_from_data.hasOwnProperty(prop)) {
20201                if (config_from_data[prop] === undefined || config_from_data[prop] === "") {
20202                    delete config_from_data[prop];
20203                }
20204            }
20205        }
20206
20207
20208        // input value extends default config
20209        if (val !== undefined && val !== "") {
20210            val = val.split(config_from_data.input_values_separator || options.input_values_separator || ";");
20211
20212            if (val[0] && val[0] == +val[0]) {
20213                val[0] = +val[0];
20214            }
20215            if (val[1] && val[1] == +val[1]) {
20216                val[1] = +val[1];
20217            }
20218
20219            if (options && options.values && options.values.length) {
20220                config.from = val[0] && options.values.indexOf(val[0]);
20221                config.to = val[1] && options.values.indexOf(val[1]);
20222            } else {
20223                config.from = val[0] && +val[0];
20224                config.to = val[1] && +val[1];
20225            }
20226        }
20227
20228
20229
20230        // js config extends default config
20231        $.extend(config, options);
20232
20233
20234        // data config extends config
20235        $.extend(config, config_from_data);
20236        this.options = config;
20237
20238
20239
20240        // validate config, to be sure that all data types are correct
20241        this.update_check = {};
20242        this.validate();
20243
20244
20245
20246        // default result object, returned to callbacks
20247        this.result = {
20248            input: this.$cache.input,
20249            slider: null,
20250
20251            min: this.options.min,
20252            max: this.options.max,
20253
20254            from: this.options.from,
20255            from_percent: 0,
20256            from_value: null,
20257
20258            to: this.options.to,
20259            to_percent: 0,
20260            to_value: null
20261        };
20262
20263
20264
20265        this.init();
20266    };
20267
20268    IonRangeSlider.prototype = {
20269
20270        /**
20271         * Starts or updates the plugin instance
20272         *
20273         * @param [is_update] {boolean}
20274         */
20275        init: function (is_update) {
20276            this.no_diapason = false;
20277            this.coords.p_step = this.convertToPercent(this.options.step, true);
20278
20279            this.target = "base";
20280
20281            this.toggleInput();
20282            this.append();
20283            this.setMinMax();
20284
20285            if (is_update) {
20286                this.force_redraw = true;
20287                this.calc(true);
20288
20289                // callbacks called
20290                this.callOnUpdate();
20291            } else {
20292                this.force_redraw = true;
20293                this.calc(true);
20294
20295                // callbacks called
20296                this.callOnStart();
20297            }
20298
20299            this.updateScene();
20300        },
20301
20302        /**
20303         * Appends slider template to a DOM
20304         */
20305        append: function () {
20306            var container_html = '<span class="irs js-irs-' + this.plugin_count + '"></span>';
20307            this.$cache.input.before(container_html);
20308            this.$cache.input.prop("readonly", true);
20309            this.$cache.cont = this.$cache.input.prev();
20310            this.result.slider = this.$cache.cont;
20311
20312            this.$cache.cont.html(base_html);
20313            this.$cache.rs = this.$cache.cont.find(".irs");
20314            this.$cache.min = this.$cache.cont.find(".irs-min");
20315            this.$cache.max = this.$cache.cont.find(".irs-max");
20316            this.$cache.from = this.$cache.cont.find(".irs-from");
20317            this.$cache.to = this.$cache.cont.find(".irs-to");
20318            this.$cache.single = this.$cache.cont.find(".irs-single");
20319            this.$cache.bar = this.$cache.cont.find(".irs-bar");
20320            this.$cache.line = this.$cache.cont.find(".irs-line");
20321            this.$cache.grid = this.$cache.cont.find(".irs-grid");
20322
20323            if (this.options.type === "single") {
20324                this.$cache.cont.append(single_html);
20325                this.$cache.edge = this.$cache.cont.find(".irs-bar-edge");
20326                this.$cache.s_single = this.$cache.cont.find(".single");
20327                this.$cache.from[0].style.visibility = "hidden";
20328                this.$cache.to[0].style.visibility = "hidden";
20329                this.$cache.shad_single = this.$cache.cont.find(".shadow-single");
20330            } else {
20331                this.$cache.cont.append(double_html);
20332                this.$cache.s_from = this.$cache.cont.find(".from");
20333                this.$cache.s_to = this.$cache.cont.find(".to");
20334                this.$cache.shad_from = this.$cache.cont.find(".shadow-from");
20335                this.$cache.shad_to = this.$cache.cont.find(".shadow-to");
20336
20337                this.setTopHandler();
20338            }
20339
20340            if (this.options.hide_from_to) {
20341                this.$cache.from[0].style.display = "none";
20342                this.$cache.to[0].style.display = "none";
20343                this.$cache.single[0].style.display = "none";
20344            }
20345
20346            this.appendGrid();
20347
20348            if (this.options.disable) {
20349                this.appendDisableMask();
20350                this.$cache.input[0].disabled = true;
20351            } else {
20352                this.$cache.cont.removeClass("irs-disabled");
20353                this.$cache.input[0].disabled = false;
20354                this.bindEvents();
20355            }
20356
20357            if (this.options.drag_interval) {
20358                this.$cache.bar[0].style.cursor = "ew-resize";
20359            }
20360        },
20361
20362        /**
20363         * Determine which handler has a priority
20364         * works only for double slider type
20365         */
20366        setTopHandler: function () {
20367            var min = this.options.min,
20368                max = this.options.max,
20369                from = this.options.from,
20370                to = this.options.to;
20371
20372            if (from > min && to === max) {
20373                this.$cache.s_from.addClass("type_last");
20374            } else if (to < max) {
20375                this.$cache.s_to.addClass("type_last");
20376            }
20377        },
20378
20379        /**
20380         * Determine which handles was clicked last
20381         * and which handler should have hover effect
20382         *
20383         * @param target {String}
20384         */
20385        changeLevel: function (target) {
20386            switch (target) {
20387                case "single":
20388                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_single_fake);
20389                    break;
20390                case "from":
20391                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake);
20392                    this.$cache.s_from.addClass("state_hover");
20393                    this.$cache.s_from.addClass("type_last");
20394                    this.$cache.s_to.removeClass("type_last");
20395                    break;
20396                case "to":
20397                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_to_fake);
20398                    this.$cache.s_to.addClass("state_hover");
20399                    this.$cache.s_to.addClass("type_last");
20400                    this.$cache.s_from.removeClass("type_last");
20401                    break;
20402                case "both":
20403                    this.coords.p_gap_left = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake);
20404                    this.coords.p_gap_right = this.toFixed(this.coords.p_to_fake - this.coords.p_pointer);
20405                    this.$cache.s_to.removeClass("type_last");
20406                    this.$cache.s_from.removeClass("type_last");
20407                    break;
20408            }
20409        },
20410
20411        /**
20412         * Then slider is disabled
20413         * appends extra layer with opacity
20414         */
20415        appendDisableMask: function () {
20416            this.$cache.cont.append(disable_html);
20417            this.$cache.cont.addClass("irs-disabled");
20418        },
20419
20420        /**
20421         * Remove slider instance
20422         * and ubind all events
20423         */
20424        remove: function () {
20425            this.$cache.cont.remove();
20426            this.$cache.cont = null;
20427
20428            this.$cache.line.off("keydown.irs_" + this.plugin_count);
20429
20430            this.$cache.body.off("touchmove.irs_" + this.plugin_count);
20431            this.$cache.body.off("mousemove.irs_" + this.plugin_count);
20432
20433            this.$cache.win.off("touchend.irs_" + this.plugin_count);
20434            this.$cache.win.off("mouseup.irs_" + this.plugin_count);
20435
20436            if (is_old_ie) {
20437                this.$cache.body.off("mouseup.irs_" + this.plugin_count);
20438                this.$cache.body.off("mouseleave.irs_" + this.plugin_count);
20439            }
20440
20441            this.$cache.grid_labels = [];
20442            this.coords.big = [];
20443            this.coords.big_w = [];
20444            this.coords.big_p = [];
20445            this.coords.big_x = [];
20446
20447            cancelAnimationFrame(this.raf_id);
20448        },
20449
20450        /**
20451         * bind all slider events
20452         */
20453        bindEvents: function () {
20454            if (this.no_diapason) {
20455                return;
20456            }
20457
20458            this.$cache.body.on("touchmove.irs_" + this.plugin_count, this.pointerMove.bind(this));
20459            this.$cache.body.on("mousemove.irs_" + this.plugin_count, this.pointerMove.bind(this));
20460
20461            this.$cache.win.on("touchend.irs_" + this.plugin_count, this.pointerUp.bind(this));
20462            this.$cache.win.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
20463
20464            this.$cache.line.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
20465            this.$cache.line.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
20466
20467            if (this.options.drag_interval && this.options.type === "double") {
20468                this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
20469                this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
20470            } else {
20471                this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
20472                this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
20473            }
20474
20475            if (this.options.type === "single") {
20476                this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
20477                this.$cache.s_single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
20478                this.$cache.shad_single.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
20479
20480                this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
20481                this.$cache.s_single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
20482                this.$cache.edge.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
20483                this.$cache.shad_single.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
20484            } else {
20485                this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, null));
20486                this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, null));
20487
20488                this.$cache.from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
20489                this.$cache.s_from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
20490                this.$cache.to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
20491                this.$cache.s_to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
20492                this.$cache.shad_from.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
20493                this.$cache.shad_to.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
20494
20495                this.$cache.from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
20496                this.$cache.s_from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
20497                this.$cache.to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
20498                this.$cache.s_to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
20499                this.$cache.shad_from.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
20500                this.$cache.shad_to.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
20501            }
20502
20503            if (this.options.keyboard) {
20504                this.$cache.line.on("keydown.irs_" + this.plugin_count, this.key.bind(this, "keyboard"));
20505            }
20506
20507            if (is_old_ie) {
20508                this.$cache.body.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
20509                this.$cache.body.on("mouseleave.irs_" + this.plugin_count, this.pointerUp.bind(this));
20510            }
20511        },
20512
20513        /**
20514         * Mousemove or touchmove
20515         * only for handlers
20516         *
20517         * @param e {Object} event object
20518         */
20519        pointerMove: function (e) {
20520            if (!this.dragging) {
20521                return;
20522            }
20523
20524            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
20525            this.coords.x_pointer = x - this.coords.x_gap;
20526
20527            this.calc();
20528        },
20529
20530        /**
20531         * Mouseup or touchend
20532         * only for handlers
20533         *
20534         * @param e {Object} event object
20535         */
20536        pointerUp: function (e) {
20537            if (this.current_plugin !== this.plugin_count) {
20538                return;
20539            }
20540
20541            if (this.is_active) {
20542                this.is_active = false;
20543            } else {
20544                return;
20545            }
20546
20547            this.$cache.cont.find(".state_hover").removeClass("state_hover");
20548
20549            this.force_redraw = true;
20550
20551            if (is_old_ie) {
20552                $("*").prop("unselectable", false);
20553            }
20554
20555            this.updateScene();
20556            this.restoreOriginalMinInterval();
20557
20558            // callbacks call
20559            if ($.contains(this.$cache.cont[0], e.target) || this.dragging) {
20560                this.callOnFinish();
20561            }
20562            
20563            this.dragging = false;
20564        },
20565
20566        /**
20567         * Mousedown or touchstart
20568         * only for handlers
20569         *
20570         * @param target {String|null}
20571         * @param e {Object} event object
20572         */
20573        pointerDown: function (target, e) {
20574            e.preventDefault();
20575            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
20576            if (e.button === 2) {
20577                return;
20578            }
20579
20580            if (target === "both") {
20581                this.setTempMinInterval();
20582            }
20583
20584            if (!target) {
20585                target = this.target || "from";
20586            }
20587
20588            this.current_plugin = this.plugin_count;
20589            this.target = target;
20590
20591            this.is_active = true;
20592            this.dragging = true;
20593
20594            this.coords.x_gap = this.$cache.rs.offset().left;
20595            this.coords.x_pointer = x - this.coords.x_gap;
20596
20597            this.calcPointerPercent();
20598            this.changeLevel(target);
20599
20600            if (is_old_ie) {
20601                $("*").prop("unselectable", true);
20602            }
20603
20604            this.$cache.line.trigger("focus");
20605
20606            this.updateScene();
20607        },
20608
20609        /**
20610         * Mousedown or touchstart
20611         * for other slider elements, like diapason line
20612         *
20613         * @param target {String}
20614         * @param e {Object} event object
20615         */
20616        pointerClick: function (target, e) {
20617            e.preventDefault();
20618            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
20619            if (e.button === 2) {
20620                return;
20621            }
20622
20623            this.current_plugin = this.plugin_count;
20624            this.target = target;
20625
20626            this.is_click = true;
20627            this.coords.x_gap = this.$cache.rs.offset().left;
20628            this.coords.x_pointer = +(x - this.coords.x_gap).toFixed();
20629
20630            this.force_redraw = true;
20631            this.calc();
20632
20633            this.$cache.line.trigger("focus");
20634        },
20635
20636        /**
20637         * Keyborard controls for focused slider
20638         *
20639         * @param target {String}
20640         * @param e {Object} event object
20641         * @returns {boolean|undefined}
20642         */
20643        key: function (target, e) {
20644            if (this.current_plugin !== this.plugin_count || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
20645                return;
20646            }
20647
20648            switch (e.which) {
20649                case 83: // W
20650                case 65: // A
20651                case 40: // DOWN
20652                case 37: // LEFT
20653                    e.preventDefault();
20654                    this.moveByKey(false);
20655                    break;
20656
20657                case 87: // S
20658                case 68: // D
20659                case 38: // UP
20660                case 39: // RIGHT
20661                    e.preventDefault();
20662                    this.moveByKey(true);
20663                    break;
20664            }
20665
20666            return true;
20667        },
20668
20669        /**
20670         * Move by key. Beta
20671         * @todo refactor than have plenty of time
20672         *
20673         * @param right {boolean} direction to move
20674         */
20675        moveByKey: function (right) {
20676            var p = this.coords.p_pointer;
20677
20678            if (right) {
20679                p += this.options.keyboard_step;
20680            } else {
20681                p -= this.options.keyboard_step;
20682            }
20683
20684            this.coords.x_pointer = this.toFixed(this.coords.w_rs / 100 * p);
20685            this.is_key = true;
20686            this.calc();
20687        },
20688
20689        /**
20690         * Set visibility and content
20691         * of Min and Max labels
20692         */
20693        setMinMax: function () {
20694            if (!this.options) {
20695                return;
20696            }
20697
20698            if (this.options.hide_min_max) {
20699                this.$cache.min[0].style.display = "none";
20700                this.$cache.max[0].style.display = "none";
20701                return;
20702            }
20703
20704            if (this.options.values.length) {
20705                this.$cache.min.html(this.decorate(this.options.p_values[this.options.min]));
20706                this.$cache.max.html(this.decorate(this.options.p_values[this.options.max]));
20707            } else {
20708                this.$cache.min.html(this.decorate(this._prettify(this.options.min), this.options.min));
20709                this.$cache.max.html(this.decorate(this._prettify(this.options.max), this.options.max));
20710            }
20711
20712            this.labels.w_min = this.$cache.min.outerWidth(false);
20713            this.labels.w_max = this.$cache.max.outerWidth(false);
20714        },
20715
20716        /**
20717         * Then dragging interval, prevent interval collapsing
20718         * using min_interval option
20719         */
20720        setTempMinInterval: function () {
20721            var interval = this.result.to - this.result.from;
20722
20723            if (this.old_min_interval === null) {
20724                this.old_min_interval = this.options.min_interval;
20725            }
20726
20727            this.options.min_interval = interval;
20728        },
20729
20730        /**
20731         * Restore min_interval option to original
20732         */
20733        restoreOriginalMinInterval: function () {
20734            if (this.old_min_interval !== null) {
20735                this.options.min_interval = this.old_min_interval;
20736                this.old_min_interval = null;
20737            }
20738        },
20739
20740
20741
20742        // =============================================================================================================
20743        // Calculations
20744
20745        /**
20746         * All calculations and measures start here
20747         *
20748         * @param update {boolean=}
20749         */
20750        calc: function (update) {
20751            if (!this.options) {
20752                return;
20753            }
20754
20755            this.calc_count++;
20756
20757            if (this.calc_count === 10 || update) {
20758                this.calc_count = 0;
20759                this.coords.w_rs = this.$cache.rs.outerWidth(false);
20760
20761                this.calcHandlePercent();
20762            }
20763
20764            if (!this.coords.w_rs) {
20765                return;
20766            }
20767
20768            this.calcPointerPercent();
20769            var handle_x = this.getHandleX();
20770
20771
20772            if (this.target === "both") {
20773                this.coords.p_gap = 0;
20774                handle_x = this.getHandleX();
20775            }
20776
20777            if (this.target === "click") {
20778                this.coords.p_gap = this.coords.p_handle / 2;
20779                handle_x = this.getHandleX();
20780
20781                if (this.options.drag_interval) {
20782                    this.target = "both_one";
20783                } else {
20784                    this.target = this.chooseHandle(handle_x);
20785                }
20786            }
20787
20788            switch (this.target) {
20789                case "base":
20790                    var w = (this.options.max - this.options.min) / 100,
20791                        f = (this.result.from - this.options.min) / w,
20792                        t = (this.result.to - this.options.min) / w;
20793
20794                    this.coords.p_single_real = this.toFixed(f);
20795                    this.coords.p_from_real = this.toFixed(f);
20796                    this.coords.p_to_real = this.toFixed(t);
20797
20798                    this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
20799                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
20800                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
20801
20802                    this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real);
20803                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
20804                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
20805
20806                    this.target = null;
20807
20808                    break;
20809
20810                case "single":
20811                    if (this.options.from_fixed) {
20812                        break;
20813                    }
20814
20815                    this.coords.p_single_real = this.convertToRealPercent(handle_x);
20816                    this.coords.p_single_real = this.calcWithStep(this.coords.p_single_real);
20817                    this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
20818
20819                    this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real);
20820
20821                    break;
20822
20823                case "from":
20824                    if (this.options.from_fixed) {
20825                        break;
20826                    }
20827
20828                    this.coords.p_from_real = this.convertToRealPercent(handle_x);
20829                    this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real);
20830                    if (this.coords.p_from_real > this.coords.p_to_real) {
20831                        this.coords.p_from_real = this.coords.p_to_real;
20832                    }
20833                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
20834                    this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
20835                    this.coords.p_from_real = this.checkMaxInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
20836
20837                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
20838
20839                    break;
20840
20841                case "to":
20842                    if (this.options.to_fixed) {
20843                        break;
20844                    }
20845
20846                    this.coords.p_to_real = this.convertToRealPercent(handle_x);
20847                    this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real);
20848                    if (this.coords.p_to_real < this.coords.p_from_real) {
20849                        this.coords.p_to_real = this.coords.p_from_real;
20850                    }
20851                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
20852                    this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
20853                    this.coords.p_to_real = this.checkMaxInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
20854
20855                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
20856
20857                    break;
20858
20859                case "both":
20860                    if (this.options.from_fixed || this.options.to_fixed) {
20861                        break;
20862                    }
20863
20864                    handle_x = this.toFixed(handle_x + (this.coords.p_handle * 0.001));
20865
20866                    this.coords.p_from_real = this.convertToRealPercent(handle_x) - this.coords.p_gap_left;
20867                    this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real);
20868                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
20869                    this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
20870                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
20871
20872                    this.coords.p_to_real = this.convertToRealPercent(handle_x) + this.coords.p_gap_right;
20873                    this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real);
20874                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
20875                    this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
20876                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
20877
20878                    break;
20879
20880                case "both_one":
20881                    if (this.options.from_fixed || this.options.to_fixed) {
20882                        break;
20883                    }
20884
20885                    var real_x = this.convertToRealPercent(handle_x),
20886                        from = this.result.from_percent,
20887                        to = this.result.to_percent,
20888                        full = to - from,
20889                        half = full / 2,
20890                        new_from = real_x - half,
20891                        new_to = real_x + half;
20892
20893                    if (new_from < 0) {
20894                        new_from = 0;
20895                        new_to = new_from + full;
20896                    }
20897
20898                    if (new_to > 100) {
20899                        new_to = 100;
20900                        new_from = new_to - full;
20901                    }
20902
20903                    this.coords.p_from_real = this.calcWithStep(new_from);
20904                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
20905                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
20906
20907                    this.coords.p_to_real = this.calcWithStep(new_to);
20908                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
20909                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
20910
20911                    break;
20912            }
20913
20914            if (this.options.type === "single") {
20915                this.coords.p_bar_x = (this.coords.p_handle / 2);
20916                this.coords.p_bar_w = this.coords.p_single_fake;
20917
20918                this.result.from_percent = this.coords.p_single_real;
20919                this.result.from = this.convertToValue(this.coords.p_single_real);
20920
20921                if (this.options.values.length) {
20922                    this.result.from_value = this.options.values[this.result.from];
20923                }
20924            } else {
20925                this.coords.p_bar_x = this.toFixed(this.coords.p_from_fake + (this.coords.p_handle / 2));
20926                this.coords.p_bar_w = this.toFixed(this.coords.p_to_fake - this.coords.p_from_fake);
20927
20928                this.result.from_percent = this.coords.p_from_real;
20929                this.result.from = this.convertToValue(this.coords.p_from_real);
20930                this.result.to_percent = this.coords.p_to_real;
20931                this.result.to = this.convertToValue(this.coords.p_to_real);
20932
20933                if (this.options.values.length) {
20934                    this.result.from_value = this.options.values[this.result.from];
20935                    this.result.to_value = this.options.values[this.result.to];
20936                }
20937            }
20938
20939            this.calcMinMax();
20940            this.calcLabels();
20941        },
20942
20943
20944        /**
20945         * calculates pointer X in percent
20946         */
20947        calcPointerPercent: function () {
20948            if (!this.coords.w_rs) {
20949                this.coords.p_pointer = 0;
20950                return;
20951            }
20952
20953            if (this.coords.x_pointer < 0 || isNaN(this.coords.x_pointer)  ) {
20954                this.coords.x_pointer = 0;
20955            } else if (this.coords.x_pointer > this.coords.w_rs) {
20956                this.coords.x_pointer = this.coords.w_rs;
20957            }
20958
20959            this.coords.p_pointer = this.toFixed(this.coords.x_pointer / this.coords.w_rs * 100);
20960        },
20961
20962        convertToRealPercent: function (fake) {
20963            var full = 100 - this.coords.p_handle;
20964            return fake / full * 100;
20965        },
20966
20967        convertToFakePercent: function (real) {
20968            var full = 100 - this.coords.p_handle;
20969            return real / 100 * full;
20970        },
20971
20972        getHandleX: function () {
20973            var max = 100 - this.coords.p_handle,
20974                x = this.toFixed(this.coords.p_pointer - this.coords.p_gap);
20975
20976            if (x < 0) {
20977                x = 0;
20978            } else if (x > max) {
20979                x = max;
20980            }
20981
20982            return x;
20983        },
20984
20985        calcHandlePercent: function () {
20986            if (this.options.type === "single") {
20987                this.coords.w_handle = this.$cache.s_single.outerWidth(false);
20988            } else {
20989                this.coords.w_handle = this.$cache.s_from.outerWidth(false);
20990            }
20991
20992            this.coords.p_handle = this.toFixed(this.coords.w_handle / this.coords.w_rs * 100);
20993        },
20994
20995        /**
20996         * Find closest handle to pointer click
20997         *
20998         * @param real_x {Number}
20999         * @returns {String}
21000         */
21001        chooseHandle: function (real_x) {
21002            if (this.options.type === "single") {
21003                return "single";
21004            } else {
21005                var m_point = this.coords.p_from_real + ((this.coords.p_to_real - this.coords.p_from_real) / 2);
21006                if (real_x >= m_point) {
21007                    return this.options.to_fixed ? "from" : "to";
21008                } else {
21009                    return this.options.from_fixed ? "to" : "from";
21010                }
21011            }
21012        },
21013
21014        /**
21015         * Measure Min and Max labels width in percent
21016         */
21017        calcMinMax: function () {
21018            if (!this.coords.w_rs) {
21019                return;
21020            }
21021
21022            this.labels.p_min = this.labels.w_min / this.coords.w_rs * 100;
21023            this.labels.p_max = this.labels.w_max / this.coords.w_rs * 100;
21024        },
21025
21026        /**
21027         * Measure labels width and X in percent
21028         */
21029        calcLabels: function () {
21030            if (!this.coords.w_rs || this.options.hide_from_to) {
21031                return;
21032            }
21033
21034            if (this.options.type === "single") {
21035
21036                this.labels.w_single = this.$cache.single.outerWidth(false);
21037                this.labels.p_single_fake = this.labels.w_single / this.coords.w_rs * 100;
21038                this.labels.p_single_left = this.coords.p_single_fake + (this.coords.p_handle / 2) - (this.labels.p_single_fake / 2);
21039                this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single_fake);
21040
21041            } else {
21042
21043                this.labels.w_from = this.$cache.from.outerWidth(false);
21044                this.labels.p_from_fake = this.labels.w_from / this.coords.w_rs * 100;
21045                this.labels.p_from_left = this.coords.p_from_fake + (this.coords.p_handle / 2) - (this.labels.p_from_fake / 2);
21046                this.labels.p_from_left = this.toFixed(this.labels.p_from_left);
21047                this.labels.p_from_left = this.checkEdges(this.labels.p_from_left, this.labels.p_from_fake);
21048
21049                this.labels.w_to = this.$cache.to.outerWidth(false);
21050                this.labels.p_to_fake = this.labels.w_to / this.coords.w_rs * 100;
21051                this.labels.p_to_left = this.coords.p_to_fake + (this.coords.p_handle / 2) - (this.labels.p_to_fake / 2);
21052                this.labels.p_to_left = this.toFixed(this.labels.p_to_left);
21053                this.labels.p_to_left = this.checkEdges(this.labels.p_to_left, this.labels.p_to_fake);
21054
21055                this.labels.w_single = this.$cache.single.outerWidth(false);
21056                this.labels.p_single_fake = this.labels.w_single / this.coords.w_rs * 100;
21057                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);
21058                this.labels.p_single_left = this.toFixed(this.labels.p_single_left);
21059                this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single_fake);
21060
21061            }
21062        },
21063
21064
21065
21066        // =============================================================================================================
21067        // Drawings
21068
21069        /**
21070         * Main function called in request animation frame
21071         * to update everything
21072         */
21073        updateScene: function () {
21074            if (this.raf_id) {
21075                cancelAnimationFrame(this.raf_id);
21076                this.raf_id = null;
21077            }
21078
21079            clearTimeout(this.update_tm);
21080            this.update_tm = null;
21081
21082            if (!this.options) {
21083                return;
21084            }
21085
21086            this.drawHandles();
21087
21088            if (this.is_active) {
21089                this.raf_id = requestAnimationFrame(this.updateScene.bind(this));
21090            } else {
21091                this.update_tm = setTimeout(this.updateScene.bind(this), 300);
21092            }
21093        },
21094
21095        /**
21096         * Draw handles
21097         */
21098        drawHandles: function () {
21099            this.coords.w_rs = this.$cache.rs.outerWidth(false);
21100
21101            if (!this.coords.w_rs) {
21102                return;
21103            }
21104
21105            if (this.coords.w_rs !== this.coords.w_rs_old) {
21106                this.target = "base";
21107                this.is_resize = true;
21108            }
21109
21110            if (this.coords.w_rs !== this.coords.w_rs_old || this.force_redraw) {
21111                this.setMinMax();
21112                this.calc(true);
21113                this.drawLabels();
21114                if (this.options.grid) {
21115                    this.calcGridMargin();
21116                    this.calcGridLabels();
21117                }
21118                this.force_redraw = true;
21119                this.coords.w_rs_old = this.coords.w_rs;
21120                this.drawShadow();
21121            }
21122
21123            if (!this.coords.w_rs) {
21124                return;
21125            }
21126
21127            if (!this.dragging && !this.force_redraw && !this.is_key) {
21128                return;
21129            }
21130
21131            if (this.old_from !== this.result.from || this.old_to !== this.result.to || this.force_redraw || this.is_key) {
21132
21133                this.drawLabels();
21134
21135                this.$cache.bar[0].style.left = this.coords.p_bar_x + "%";
21136                this.$cache.bar[0].style.width = this.coords.p_bar_w + "%";
21137
21138                if (this.options.type === "single") {
21139                    this.$cache.s_single[0].style.left = this.coords.p_single_fake + "%";
21140
21141                    this.$cache.single[0].style.left = this.labels.p_single_left + "%";
21142                } else {
21143                    this.$cache.s_from[0].style.left = this.coords.p_from_fake + "%";
21144                    this.$cache.s_to[0].style.left = this.coords.p_to_fake + "%";
21145
21146                    if (this.old_from !== this.result.from || this.force_redraw) {
21147                        this.$cache.from[0].style.left = this.labels.p_from_left + "%";
21148                    }
21149                    if (this.old_to !== this.result.to || this.force_redraw) {
21150                        this.$cache.to[0].style.left = this.labels.p_to_left + "%";
21151                    }
21152
21153                    this.$cache.single[0].style.left = this.labels.p_single_left + "%";
21154                }
21155
21156                this.writeToInput();
21157
21158                if ((this.old_from !== this.result.from || this.old_to !== this.result.to) && !this.is_start) {
21159                    this.$cache.input.trigger("change");
21160                    this.$cache.input.trigger("input");
21161                }
21162
21163                this.old_from = this.result.from;
21164                this.old_to = this.result.to;
21165
21166                // callbacks call
21167                if (!this.is_resize && !this.is_update && !this.is_start && !this.is_finish) {
21168                    this.callOnChange();
21169                }
21170                if (this.is_key || this.is_click) {
21171                    this.is_key = false;
21172                    this.is_click = false;
21173                    this.callOnFinish();
21174                }
21175
21176                this.is_update = false;
21177                this.is_resize = false;
21178                this.is_finish = false;
21179            }
21180
21181            this.is_start = false;
21182            this.is_key = false;
21183            this.is_click = false;
21184            this.force_redraw = false;
21185        },
21186
21187        /**
21188         * Draw labels
21189         * measure labels collisions
21190         * collapse close labels
21191         */
21192        drawLabels: function () {
21193            if (!this.options) {
21194                return;
21195            }
21196
21197            var values_num = this.options.values.length,
21198                p_values = this.options.p_values,
21199                text_single,
21200                text_from,
21201                text_to;
21202
21203            if (this.options.hide_from_to) {
21204                return;
21205            }
21206
21207            if (this.options.type === "single") {
21208
21209                if (values_num) {
21210                    text_single = this.decorate(p_values[this.result.from]);
21211                    this.$cache.single.html(text_single);
21212                } else {
21213                    text_single = this.decorate(this._prettify(this.result.from), this.result.from);
21214                    this.$cache.single.html(text_single);
21215                }
21216
21217                this.calcLabels();
21218
21219                if (this.labels.p_single_left < this.labels.p_min + 1) {
21220                    this.$cache.min[0].style.visibility = "hidden";
21221                } else {
21222                    this.$cache.min[0].style.visibility = "visible";
21223                }
21224
21225                if (this.labels.p_single_left + this.labels.p_single_fake > 100 - this.labels.p_max - 1) {
21226                    this.$cache.max[0].style.visibility = "hidden";
21227                } else {
21228                    this.$cache.max[0].style.visibility = "visible";
21229                }
21230
21231            } else {
21232
21233                if (values_num) {
21234
21235                    if (this.options.decorate_both) {
21236                        text_single = this.decorate(p_values[this.result.from]);
21237                        text_single += this.options.values_separator;
21238                        text_single += this.decorate(p_values[this.result.to]);
21239                    } else {
21240                        text_single = this.decorate(p_values[this.result.from] + this.options.values_separator + p_values[this.result.to]);
21241                    }
21242                    text_from = this.decorate(p_values[this.result.from]);
21243                    text_to = this.decorate(p_values[this.result.to]);
21244
21245                    this.$cache.single.html(text_single);
21246                    this.$cache.from.html(text_from);
21247                    this.$cache.to.html(text_to);
21248
21249                } else {
21250
21251                    if (this.options.decorate_both) {
21252                        text_single = this.decorate(this._prettify(this.result.from), this.result.from);
21253                        text_single += this.options.values_separator;
21254                        text_single += this.decorate(this._prettify(this.result.to), this.result.to);
21255                    } else {
21256                        text_single = this.decorate(this._prettify(this.result.from) + this.options.values_separator + this._prettify(this.result.to), this.result.to);
21257                    }
21258                    text_from = this.decorate(this._prettify(this.result.from), this.result.from);
21259                    text_to = this.decorate(this._prettify(this.result.to), this.result.to);
21260
21261                    this.$cache.single.html(text_single);
21262                    this.$cache.from.html(text_from);
21263                    this.$cache.to.html(text_to);
21264
21265                }
21266
21267                this.calcLabels();
21268
21269                var min = Math.min(this.labels.p_single_left, this.labels.p_from_left),
21270                    single_left = this.labels.p_single_left + this.labels.p_single_fake,
21271                    to_left = this.labels.p_to_left + this.labels.p_to_fake,
21272                    max = Math.max(single_left, to_left);
21273
21274                if (this.labels.p_from_left + this.labels.p_from_fake >= this.labels.p_to_left) {
21275                    this.$cache.from[0].style.visibility = "hidden";
21276                    this.$cache.to[0].style.visibility = "hidden";
21277                    this.$cache.single[0].style.visibility = "visible";
21278
21279                    if (this.result.from === this.result.to) {
21280                        if (this.target === "from") {
21281                            this.$cache.from[0].style.visibility = "visible";
21282                        } else if (this.target === "to") {
21283                            this.$cache.to[0].style.visibility = "visible";
21284                        } else if (!this.target) {
21285                            this.$cache.from[0].style.visibility = "visible";
21286                        }
21287                        this.$cache.single[0].style.visibility = "hidden";
21288                        max = to_left;
21289                    } else {
21290                        this.$cache.from[0].style.visibility = "hidden";
21291                        this.$cache.to[0].style.visibility = "hidden";
21292                        this.$cache.single[0].style.visibility = "visible";
21293                        max = Math.max(single_left, to_left);
21294                    }
21295                } else {
21296                    this.$cache.from[0].style.visibility = "visible";
21297                    this.$cache.to[0].style.visibility = "visible";
21298                    this.$cache.single[0].style.visibility = "hidden";
21299                }
21300
21301                if (min < this.labels.p_min + 1) {
21302                    this.$cache.min[0].style.visibility = "hidden";
21303                } else {
21304                    this.$cache.min[0].style.visibility = "visible";
21305                }
21306
21307                if (max > 100 - this.labels.p_max - 1) {
21308                    this.$cache.max[0].style.visibility = "hidden";
21309                } else {
21310                    this.$cache.max[0].style.visibility = "visible";
21311                }
21312
21313            }
21314        },
21315
21316        /**
21317         * Draw shadow intervals
21318         */
21319        drawShadow: function () {
21320            var o = this.options,
21321                c = this.$cache,
21322
21323                is_from_min = typeof o.from_min === "number" && !isNaN(o.from_min),
21324                is_from_max = typeof o.from_max === "number" && !isNaN(o.from_max),
21325                is_to_min = typeof o.to_min === "number" && !isNaN(o.to_min),
21326                is_to_max = typeof o.to_max === "number" && !isNaN(o.to_max),
21327
21328                from_min,
21329                from_max,
21330                to_min,
21331                to_max;
21332
21333            if (o.type === "single") {
21334                if (o.from_shadow && (is_from_min || is_from_max)) {
21335                    from_min = this.convertToPercent(is_from_min ? o.from_min : o.min);
21336                    from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min;
21337                    from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
21338                    from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
21339                    from_min = from_min + (this.coords.p_handle / 2);
21340
21341                    c.shad_single[0].style.display = "block";
21342                    c.shad_single[0].style.left = from_min + "%";
21343                    c.shad_single[0].style.width = from_max + "%";
21344                } else {
21345                    c.shad_single[0].style.display = "none";
21346                }
21347            } else {
21348                if (o.from_shadow && (is_from_min || is_from_max)) {
21349                    from_min = this.convertToPercent(is_from_min ? o.from_min : o.min);
21350                    from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min;
21351                    from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
21352                    from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
21353                    from_min = from_min + (this.coords.p_handle / 2);
21354
21355                    c.shad_from[0].style.display = "block";
21356                    c.shad_from[0].style.left = from_min + "%";
21357                    c.shad_from[0].style.width = from_max + "%";
21358                } else {
21359                    c.shad_from[0].style.display = "none";
21360                }
21361
21362                if (o.to_shadow && (is_to_min || is_to_max)) {
21363                    to_min = this.convertToPercent(is_to_min ? o.to_min : o.min);
21364                    to_max = this.convertToPercent(is_to_max ? o.to_max : o.max) - to_min;
21365                    to_min = this.toFixed(to_min - (this.coords.p_handle / 100 * to_min));
21366                    to_max = this.toFixed(to_max - (this.coords.p_handle / 100 * to_max));
21367                    to_min = to_min + (this.coords.p_handle / 2);
21368
21369                    c.shad_to[0].style.display = "block";
21370                    c.shad_to[0].style.left = to_min + "%";
21371                    c.shad_to[0].style.width = to_max + "%";
21372                } else {
21373                    c.shad_to[0].style.display = "none";
21374                }
21375            }
21376        },
21377
21378
21379
21380        /**
21381         * Write values to input element
21382         */
21383        writeToInput: function () {
21384            if (this.options.type === "single") {
21385                if (this.options.values.length) {
21386                    this.$cache.input.prop("value", this.result.from_value);
21387                } else {
21388                    this.$cache.input.prop("value", this.result.from);
21389                }
21390                this.$cache.input.data("from", this.result.from);
21391            } else {
21392                if (this.options.values.length) {
21393                    this.$cache.input.prop("value", this.result.from_value + this.options.input_values_separator + this.result.to_value);
21394                } else {
21395                    this.$cache.input.prop("value", this.result.from + this.options.input_values_separator + this.result.to);
21396                }
21397                this.$cache.input.data("from", this.result.from);
21398                this.$cache.input.data("to", this.result.to);
21399            }
21400        },
21401
21402
21403
21404        // =============================================================================================================
21405        // Callbacks
21406
21407        callOnStart: function () {
21408            this.writeToInput();
21409
21410            if (this.options.onStart && typeof this.options.onStart === "function") {
21411                this.options.onStart(this.result);
21412            }
21413        },
21414        callOnChange: function () {
21415            this.writeToInput();
21416
21417            if (this.options.onChange && typeof this.options.onChange === "function") {
21418                this.options.onChange(this.result);
21419            }
21420        },
21421        callOnFinish: function () {
21422            this.writeToInput();
21423
21424            if (this.options.onFinish && typeof this.options.onFinish === "function") {
21425                this.options.onFinish(this.result);
21426            }
21427        },
21428        callOnUpdate: function () {
21429            this.writeToInput();
21430
21431            if (this.options.onUpdate && typeof this.options.onUpdate === "function") {
21432                this.options.onUpdate(this.result);
21433            }
21434        },
21435
21436
21437
21438
21439        // =============================================================================================================
21440        // Service methods
21441
21442        toggleInput: function () {
21443            this.$cache.input.toggleClass("irs-hidden-input");
21444        },
21445
21446        /**
21447         * Convert real value to percent
21448         *
21449         * @param value {Number} X in real
21450         * @param no_min {boolean=} don't use min value
21451         * @returns {Number} X in percent
21452         */
21453        convertToPercent: function (value, no_min) {
21454            var diapason = this.options.max - this.options.min,
21455                one_percent = diapason / 100,
21456                val, percent;
21457
21458            if (!diapason) {
21459                this.no_diapason = true;
21460                return 0;
21461            }
21462
21463            if (no_min) {
21464                val = value;
21465            } else {
21466                val = value - this.options.min;
21467            }
21468
21469            percent = val / one_percent;
21470
21471            return this.toFixed(percent);
21472        },
21473
21474        /**
21475         * Convert percent to real values
21476         *
21477         * @param percent {Number} X in percent
21478         * @returns {Number} X in real
21479         */
21480        convertToValue: function (percent) {
21481            var min = this.options.min,
21482                max = this.options.max,
21483                min_decimals = min.toString().split(".")[1],
21484                max_decimals = max.toString().split(".")[1],
21485                min_length, max_length,
21486                avg_decimals = 0,
21487                abs = 0;
21488
21489            if (percent === 0) {
21490                return this.options.min;
21491            }
21492            if (percent === 100) {
21493                return this.options.max;
21494            }
21495
21496
21497            if (min_decimals) {
21498                min_length = min_decimals.length;
21499                avg_decimals = min_length;
21500            }
21501            if (max_decimals) {
21502                max_length = max_decimals.length;
21503                avg_decimals = max_length;
21504            }
21505            if (min_length && max_length) {
21506                avg_decimals = (min_length >= max_length) ? min_length : max_length;
21507            }
21508
21509            if (min < 0) {
21510                abs = Math.abs(min);
21511                min = +(min + abs).toFixed(avg_decimals);
21512                max = +(max + abs).toFixed(avg_decimals);
21513            }
21514
21515            var number = ((max - min) / 100 * percent) + min,
21516                string = this.options.step.toString().split(".")[1],
21517                result;
21518
21519            if (string) {
21520                number = +number.toFixed(string.length);
21521            } else {
21522                number = number / this.options.step;
21523                number = number * this.options.step;
21524
21525                number = +number.toFixed(0);
21526            }
21527
21528            if (abs) {
21529                number -= abs;
21530            }
21531
21532            if (string) {
21533                result = +number.toFixed(string.length);
21534            } else {
21535                result = this.toFixed(number);
21536            }
21537
21538            if (result < this.options.min) {
21539                result = this.options.min;
21540            } else if (result > this.options.max) {
21541                result = this.options.max;
21542            }
21543
21544            return result;
21545        },
21546
21547        /**
21548         * Round percent value with step
21549         *
21550         * @param percent {Number}
21551         * @returns percent {Number} rounded
21552         */
21553        calcWithStep: function (percent) {
21554            var rounded = Math.round(percent / this.coords.p_step) * this.coords.p_step;
21555
21556            if (rounded > 100) {
21557                rounded = 100;
21558            }
21559            if (percent === 100) {
21560                rounded = 100;
21561            }
21562
21563            return this.toFixed(rounded);
21564        },
21565
21566        checkMinInterval: function (p_current, p_next, type) {
21567            var o = this.options,
21568                current,
21569                next;
21570
21571            if (!o.min_interval) {
21572                return p_current;
21573            }
21574
21575            current = this.convertToValue(p_current);
21576            next = this.convertToValue(p_next);
21577
21578            if (type === "from") {
21579
21580                if (next - current < o.min_interval) {
21581                    current = next - o.min_interval;
21582                }
21583
21584            } else {
21585
21586                if (current - next < o.min_interval) {
21587                    current = next + o.min_interval;
21588                }
21589
21590            }
21591
21592            return this.convertToPercent(current);
21593        },
21594
21595        checkMaxInterval: function (p_current, p_next, type) {
21596            var o = this.options,
21597                current,
21598                next;
21599
21600            if (!o.max_interval) {
21601                return p_current;
21602            }
21603
21604            current = this.convertToValue(p_current);
21605            next = this.convertToValue(p_next);
21606
21607            if (type === "from") {
21608
21609                if (next - current > o.max_interval) {
21610                    current = next - o.max_interval;
21611                }
21612
21613            } else {
21614
21615                if (current - next > o.max_interval) {
21616                    current = next + o.max_interval;
21617                }
21618
21619            }
21620
21621            return this.convertToPercent(current);
21622        },
21623
21624        checkDiapason: function (p_num, min, max) {
21625            var num = this.convertToValue(p_num),
21626                o = this.options;
21627
21628            if (typeof min !== "number") {
21629                min = o.min;
21630            }
21631
21632            if (typeof max !== "number") {
21633                max = o.max;
21634            }
21635
21636            if (num < min) {
21637                num = min;
21638            }
21639
21640            if (num > max) {
21641                num = max;
21642            }
21643
21644            return this.convertToPercent(num);
21645        },
21646
21647        toFixed: function (num) {
21648            num = num.toFixed(20);
21649            return +num;
21650        },
21651
21652        _prettify: function (num) {
21653            if (!this.options.prettify_enabled) {
21654                return num;
21655            }
21656
21657            if (this.options.prettify && typeof this.options.prettify === "function") {
21658                return this.options.prettify(num);
21659            } else {
21660                return this.prettify(num);
21661            }
21662        },
21663
21664        prettify: function (num) {
21665            var n = num.toString();
21666            return n.replace(/(\d{1,3}(?=(?:\d\d\d)+(?!\d)))/g, "$1" + this.options.prettify_separator);
21667        },
21668
21669        checkEdges: function (left, width) {
21670            if (!this.options.force_edges) {
21671                return this.toFixed(left);
21672            }
21673
21674            if (left < 0) {
21675                left = 0;
21676            } else if (left > 100 - width) {
21677                left = 100 - width;
21678            }
21679
21680            return this.toFixed(left);
21681        },
21682
21683        validate: function () {
21684            var o = this.options,
21685                r = this.result,
21686                v = o.values,
21687                vl = v.length,
21688                value,
21689                i;
21690
21691            if (typeof o.min === "string") o.min = +o.min;
21692            if (typeof o.max === "string") o.max = +o.max;
21693            if (typeof o.from === "string") o.from = +o.from;
21694            if (typeof o.to === "string") o.to = +o.to;
21695            if (typeof o.step === "string") o.step = +o.step;
21696
21697            if (typeof o.from_min === "string") o.from_min = +o.from_min;
21698            if (typeof o.from_max === "string") o.from_max = +o.from_max;
21699            if (typeof o.to_min === "string") o.to_min = +o.to_min;
21700            if (typeof o.to_max === "string") o.to_max = +o.to_max;
21701
21702            if (typeof o.keyboard_step === "string") o.keyboard_step = +o.keyboard_step;
21703            if (typeof o.grid_num === "string") o.grid_num = +o.grid_num;
21704
21705            if (o.max < o.min) {
21706                o.max = o.min;
21707            }
21708
21709            if (vl) {
21710                o.p_values = [];
21711                o.min = 0;
21712                o.max = vl - 1;
21713                o.step = 1;
21714                o.grid_num = o.max;
21715                o.grid_snap = true;
21716
21717                for (i = 0; i < vl; i++) {
21718                    value = +v[i];
21719
21720                    if (!isNaN(value)) {
21721                        v[i] = value;
21722                        value = this._prettify(value);
21723                    } else {
21724                        value = v[i];
21725                    }
21726
21727                    o.p_values.push(value);
21728                }
21729            }
21730
21731            if (typeof o.from !== "number" || isNaN(o.from)) {
21732                o.from = o.min;
21733            }
21734
21735            if (typeof o.to !== "number" || isNaN(o.to)) {
21736                o.to = o.max;
21737            }
21738
21739            if (o.type === "single") {
21740
21741                if (o.from < o.min) o.from = o.min;
21742                if (o.from > o.max) o.from = o.max;
21743
21744            } else {
21745
21746                if (o.from < o.min) o.from = o.min;
21747                if (o.from > o.max) o.from = o.max;
21748
21749                if (o.to < o.min) o.to = o.min;
21750                if (o.to > o.max) o.to = o.max;
21751
21752                if (this.update_check.from) {
21753
21754                    if (this.update_check.from !== o.from) {
21755                        if (o.from > o.to) o.from = o.to;
21756                    }
21757                    if (this.update_check.to !== o.to) {
21758                        if (o.to < o.from) o.to = o.from;
21759                    }
21760
21761                }
21762
21763                if (o.from > o.to) o.from = o.to;
21764                if (o.to < o.from) o.to = o.from;
21765
21766            }
21767
21768            if (typeof o.step !== "number" || isNaN(o.step) || !o.step || o.step < 0) {
21769                o.step = 1;
21770            }
21771
21772            if (typeof o.keyboard_step !== "number" || isNaN(o.keyboard_step) || !o.keyboard_step || o.keyboard_step < 0) {
21773                o.keyboard_step = 5;
21774            }
21775
21776            if (typeof o.from_min === "number" && o.from < o.from_min) {
21777                o.from = o.from_min;
21778            }
21779
21780            if (typeof o.from_max === "number" && o.from > o.from_max) {
21781                o.from = o.from_max;
21782            }
21783
21784            if (typeof o.to_min === "number" && o.to < o.to_min) {
21785                o.to = o.to_min;
21786            }
21787
21788            if (typeof o.to_max === "number" && o.from > o.to_max) {
21789                o.to = o.to_max;
21790            }
21791
21792            if (r) {
21793                if (r.min !== o.min) {
21794                    r.min = o.min;
21795                }
21796
21797                if (r.max !== o.max) {
21798                    r.max = o.max;
21799                }
21800
21801                if (r.from < r.min || r.from > r.max) {
21802                    r.from = o.from;
21803                }
21804
21805                if (r.to < r.min || r.to > r.max) {
21806                    r.to = o.to;
21807                }
21808            }
21809
21810            if (typeof o.min_interval !== "number" || isNaN(o.min_interval) || !o.min_interval || o.min_interval < 0) {
21811                o.min_interval = 0;
21812            }
21813
21814            if (typeof o.max_interval !== "number" || isNaN(o.max_interval) || !o.max_interval || o.max_interval < 0) {
21815                o.max_interval = 0;
21816            }
21817
21818            if (o.min_interval && o.min_interval > o.max - o.min) {
21819                o.min_interval = o.max - o.min;
21820            }
21821
21822            if (o.max_interval && o.max_interval > o.max - o.min) {
21823                o.max_interval = o.max - o.min;
21824            }
21825        },
21826
21827        decorate: function (num, original) {
21828            var decorated = "",
21829                o = this.options;
21830
21831            if (o.prefix) {
21832                decorated += o.prefix;
21833            }
21834
21835            decorated += num;
21836
21837            if (o.max_postfix) {
21838                if (o.values.length && num === o.p_values[o.max]) {
21839                    decorated += o.max_postfix;
21840                    if (o.postfix) {
21841                        decorated += " ";
21842                    }
21843                } else if (original === o.max) {
21844                    decorated += o.max_postfix;
21845                    if (o.postfix) {
21846                        decorated += " ";
21847                    }
21848                }
21849            }
21850
21851            if (o.postfix) {
21852                decorated += o.postfix;
21853            }
21854
21855            return decorated;
21856        },
21857
21858        updateFrom: function () {
21859            this.result.from = this.options.from;
21860            this.result.from_percent = this.convertToPercent(this.result.from);
21861            if (this.options.values) {
21862                this.result.from_value = this.options.values[this.result.from];
21863            }
21864        },
21865
21866        updateTo: function () {
21867            this.result.to = this.options.to;
21868            this.result.to_percent = this.convertToPercent(this.result.to);
21869            if (this.options.values) {
21870                this.result.to_value = this.options.values[this.result.to];
21871            }
21872        },
21873
21874        updateResult: function () {
21875            this.result.min = this.options.min;
21876            this.result.max = this.options.max;
21877            this.updateFrom();
21878            this.updateTo();
21879        },
21880
21881
21882        // =============================================================================================================
21883        // Grid
21884
21885        appendGrid: function () {
21886            if (!this.options.grid) {
21887                return;
21888            }
21889
21890            var o = this.options,
21891                i, z,
21892
21893                total = o.max - o.min,
21894                big_num = o.grid_num,
21895                big_p = 0,
21896                big_w = 0,
21897
21898                small_max = 4,
21899                local_small_max,
21900                small_p,
21901                small_w = 0,
21902
21903                result,
21904                html = '';
21905
21906
21907
21908            this.calcGridMargin();
21909
21910            if (o.grid_snap) {
21911
21912                if (total > 50) {
21913                    big_num = 50 / o.step;
21914                    big_p = this.toFixed(o.step / 0.5);
21915                } else {
21916                    big_num = total / o.step;
21917                    big_p = this.toFixed(o.step / (total / 100));
21918                }
21919
21920            } else {
21921                big_p = this.toFixed(100 / big_num);
21922            }
21923
21924            if (big_num > 4) {
21925                small_max = 3;
21926            }
21927            if (big_num > 7) {
21928                small_max = 2;
21929            }
21930            if (big_num > 14) {
21931                small_max = 1;
21932            }
21933            if (big_num > 28) {
21934                small_max = 0;
21935            }
21936
21937            for (i = 0; i < big_num + 1; i++) {
21938                local_small_max = small_max;
21939
21940                big_w = this.toFixed(big_p * i);
21941
21942                if (big_w > 100) {
21943                    big_w = 100;
21944
21945                    local_small_max -= 2;
21946                    if (local_small_max < 0) {
21947                        local_small_max = 0;
21948                    }
21949                }
21950                this.coords.big[i] = big_w;
21951
21952                small_p = (big_w - (big_p * (i - 1))) / (local_small_max + 1);
21953
21954                for (z = 1; z <= local_small_max; z++) {
21955                    if (big_w === 0) {
21956                        break;
21957                    }
21958
21959                    small_w = this.toFixed(big_w - (small_p * z));
21960
21961                    html += '<span class="irs-grid-pol small" style="left: ' + small_w + '%"></span>';
21962                }
21963
21964                html += '<span class="irs-grid-pol" style="left: ' + big_w + '%"></span>';
21965
21966                result = this.convertToValue(big_w);
21967                if (o.values.length) {
21968                    result = o.p_values[result];
21969                } else {
21970                    result = this._prettify(result);
21971                }
21972
21973                html += '<span class="irs-grid-text js-grid-text-' + i + '" style="left: ' + big_w + '%">' + result + '</span>';
21974            }
21975            this.coords.big_num = Math.ceil(big_num + 1);
21976
21977
21978
21979            this.$cache.cont.addClass("irs-with-grid");
21980            this.$cache.grid.html(html);
21981            this.cacheGridLabels();
21982        },
21983
21984        cacheGridLabels: function () {
21985            var $label, i,
21986                num = this.coords.big_num;
21987
21988            for (i = 0; i < num; i++) {
21989                $label = this.$cache.grid.find(".js-grid-text-" + i);
21990                this.$cache.grid_labels.push($label);
21991            }
21992
21993            this.calcGridLabels();
21994        },
21995
21996        calcGridLabels: function () {
21997            var i, label, start = [], finish = [],
21998                num = this.coords.big_num;
21999
22000            for (i = 0; i < num; i++) {
22001                this.coords.big_w[i] = this.$cache.grid_labels[i].outerWidth(false);
22002                this.coords.big_p[i] = this.toFixed(this.coords.big_w[i] / this.coords.w_rs * 100);
22003                this.coords.big_x[i] = this.toFixed(this.coords.big_p[i] / 2);
22004
22005                start[i] = this.toFixed(this.coords.big[i] - this.coords.big_x[i]);
22006                finish[i] = this.toFixed(start[i] + this.coords.big_p[i]);
22007            }
22008
22009            if (this.options.force_edges) {
22010                if (start[0] < -this.coords.grid_gap) {
22011                    start[0] = -this.coords.grid_gap;
22012                    finish[0] = this.toFixed(start[0] + this.coords.big_p[0]);
22013
22014                    this.coords.big_x[0] = this.coords.grid_gap;
22015                }
22016
22017                if (finish[num - 1] > 100 + this.coords.grid_gap) {
22018                    finish[num - 1] = 100 + this.coords.grid_gap;
22019                    start[num - 1] = this.toFixed(finish[num - 1] - this.coords.big_p[num - 1]);
22020
22021                    this.coords.big_x[num - 1] = this.toFixed(this.coords.big_p[num - 1] - this.coords.grid_gap);
22022                }
22023            }
22024
22025            this.calcGridCollision(2, start, finish);
22026            this.calcGridCollision(4, start, finish);
22027
22028            for (i = 0; i < num; i++) {
22029                label = this.$cache.grid_labels[i][0];
22030
22031                if (this.coords.big_x[i] !== Number.POSITIVE_INFINITY) {
22032                    label.style.marginLeft = -this.coords.big_x[i] + "%";
22033                }
22034            }
22035        },
22036
22037        // Collisions Calc Beta
22038        // TODO: Refactor then have plenty of time
22039        calcGridCollision: function (step, start, finish) {
22040            var i, next_i, label,
22041                num = this.coords.big_num;
22042
22043            for (i = 0; i < num; i += step) {
22044                next_i = i + (step / 2);
22045                if (next_i >= num) {
22046                    break;
22047                }
22048
22049                label = this.$cache.grid_labels[next_i][0];
22050
22051                if (finish[i] <= start[next_i]) {
22052                    label.style.visibility = "visible";
22053                } else {
22054                    label.style.visibility = "hidden";
22055                }
22056            }
22057        },
22058
22059        calcGridMargin: function () {
22060            if (!this.options.grid_margin) {
22061                return;
22062            }
22063
22064            this.coords.w_rs = this.$cache.rs.outerWidth(false);
22065            if (!this.coords.w_rs) {
22066                return;
22067            }
22068
22069            if (this.options.type === "single") {
22070                this.coords.w_handle = this.$cache.s_single.outerWidth(false);
22071            } else {
22072                this.coords.w_handle = this.$cache.s_from.outerWidth(false);
22073            }
22074            this.coords.p_handle = this.toFixed(this.coords.w_handle  / this.coords.w_rs * 100);
22075            this.coords.grid_gap = this.toFixed((this.coords.p_handle / 2) - 0.1);
22076
22077            this.$cache.grid[0].style.width = this.toFixed(100 - this.coords.p_handle) + "%";
22078            this.$cache.grid[0].style.left = this.coords.grid_gap + "%";
22079        },
22080
22081
22082
22083        // =============================================================================================================
22084        // Public methods
22085
22086        update: function (options) {
22087            if (!this.input) {
22088                return;
22089            }
22090
22091            this.is_update = true;
22092
22093            this.options.from = this.result.from;
22094            this.options.to = this.result.to;
22095            this.update_check.from = this.result.from;
22096            this.update_check.to = this.result.to;
22097
22098            this.options = $.extend(this.options, options);
22099            this.validate();
22100            this.updateResult(options);
22101
22102            this.toggleInput();
22103            this.remove();
22104            this.init(true);
22105        },
22106
22107        reset: function () {
22108            if (!this.input) {
22109                return;
22110            }
22111
22112            this.updateResult();
22113            this.update();
22114        },
22115
22116        destroy: function () {
22117            if (!this.input) {
22118                return;
22119            }
22120
22121            this.toggleInput();
22122            this.$cache.input.prop("readonly", false);
22123            $.data(this.input, "ionRangeSlider", null);
22124
22125            this.remove();
22126            this.input = null;
22127            this.options = null;
22128        }
22129    };
22130
22131    $.fn.ionRangeSlider = function (options) {
22132        return this.each(function() {
22133            if (!$.data(this, "ionRangeSlider")) {
22134                $.data(this, "ionRangeSlider", new IonRangeSlider(this, options, plugin_count++));
22135            }
22136        });
22137    };
22138
22139
22140
22141    // =================================================================================================================
22142    // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
22143    // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
22144
22145    // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
22146
22147    // MIT license
22148
22149    (function() {
22150        var lastTime = 0;
22151        var vendors = ['ms', 'moz', 'webkit', 'o'];
22152        for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
22153            window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
22154            window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
22155                || window[vendors[x]+'CancelRequestAnimationFrame'];
22156        }
22157
22158        if (!window.requestAnimationFrame)
22159            window.requestAnimationFrame = function(callback, element) {
22160                var currTime = new Date().getTime();
22161                var timeToCall = Math.max(0, 16 - (currTime - lastTime));
22162                var id = window.setTimeout(function() { callback(currTime + timeToCall); },
22163                    timeToCall);
22164                lastTime = currTime + timeToCall;
22165                return id;
22166            };
22167
22168        if (!window.cancelAnimationFrame)
22169            window.cancelAnimationFrame = function(id) {
22170                clearTimeout(id);
22171            };
22172    }());
22173
22174}));
22175
22176
22177
22178// Trigger
22179
22180$(function () {
22181  
22182        var $range = $(".js-range-slider"),
22183            $inputFrom = $(".js-input-from"),
22184            $inputTo = $(".js-input-to"),
22185            instance,
22186            min = 0,
22187            max = 1000000,
22188            from = 0,
22189            to = 0;
22190
22191        $range.ionRangeSlider({
22192            type: "double",
22193            min: min,
22194            max: max,
22195            from: 20000,
22196            to: 500000,
22197          prefix: '$ ',
22198            onStart: updateInputs,
22199            onChange: updateInputs,
22200            step: 50000,
22201            prettify_enabled: true,
22202            prettify_separator: ".",
22203          values_separator: " - ",
22204          force_edges: true
22205          
22206
22207        });
22208
22209        instance = $range.data("ionRangeSlider");
22210
22211        function updateInputs (data) {
22212            from = data.from;
22213            to = data.to;
22214            
22215            $inputFrom.prop("value", from).keyup(resizeInput).each(resizeInput);
22216            $inputTo.prop("value", to).keyup(resizeInput).each(resizeInput);
22217        }
22218
22219        $inputFrom.on("input", function () {
22220            var val = $(this).prop("value");
22221            
22222            // validate
22223            if (val < min) {
22224                val = min;
22225            } else if (val > to) {
22226                val = to;
22227            }
22228            
22229            instance.update({
22230                from: val
22231            });
22232        });
22233
22234        $inputTo.on("input", function () {
22235            var val = $(this).prop("value");
22236            
22237            // validate
22238            if (val < from) {
22239                val = from;
22240            } else if (val > max) {
22241                val = max;
22242            }
22243            
22244            instance.update({
22245                to: val
22246            });
22247        });
22248
22249});$(function () {
22250    let $sel = $('[data-unicode="mdu_FS4sfpAlX0OE6dIb5WERmw"]');
22251    $sel.each(async function () {
22252        let $id = base62();
22253        $(this).find('form').attr('id', $id);
22254
22255        // 初始化設定資料
22256        let settingData = [];
22257        await initFormSettings($id).then(data => settingData = data);
22258
22259        // -----------------------------------
22260        // 出發起迄設定
22261        let $startDate = $('#' + $id).find('.date-start');
22262        let $endDate = $('#' + $id).find('.date-end');
22263        $('#' + $id).find('.date-start , .date-end').datepicker({
22264            format: "yyyy/mm/dd",
22265            clearBtn: true,
22266            autoclose: true,
22267            toggleActive: true,
22268            language: "zh-TW",
22269            defaultDate: new Date(),
22270            startDate: new Date()
22271        });
22272
22273        //日期區間設定
22274        let startDateOffset = getSettingValue(settingData, "SEARCH_SDATE_OFFSET");
22275        console.log('startDateOffset: ' + startDateOffset);
22276        startDateOffset = Math.min(parseInt(startDateOffset), 60);
22277        console.log('startDateOffset: ' + startDateOffset);
22278        let $daterange = $('#' + $id).find('#daterange_value');
22279        let daterange = 0;
22280        if ($daterange.val() !== '' && !isNaN(parseInt($daterange.val()))) {
22281            daterange = parseInt($daterange.val());
22282        } else {
22283            daterange = getSettingValue(settingData, "SEARCH_DATE_INTERVAL");
22284            daterange = parseInt(daterange || "0");
22285        }
22286
22287        let date = new Date(new Date().getTime() + startDateOffset * 24 * 60 * 60 * 1000);
22288        let month = (date.getMonth() + 1) + daterange;
22289        let yaer = date.getFullYear();
22290        if (month > 12) {           //是否超過12月判斷
22291            yaer += Math.floor(month / 12);
22292            month = (month % 12);
22293        }
22294        date.setFullYear(yaer);
22295        date.setMonth(month - 1);
22296        $startDate.datepicker('setDate', new Date(new Date().getTime() + startDateOffset * 24 * 60 * 60 * 1000));
22297        $endDate.datepicker('setDate', date);
22298
22299        // 結束日期的選擇變化
22300        $endDate.datepicker().on('blur', function (e) {
22301            console.log($endDate.datepicker('getDate'));
22302            console.log($startDate.datepicker('getDate'));
22303            if ($endDate.datepicker('getDate') < $startDate.datepicker('getDate')) {
22304                alert("出發期間迄日不可小於出發期間起日");
22305                $endDate.datepicker('setDate', $startDate.datepicker('getDate'));  // 重置結束日期爲起始日期
22306            }
22307        });
22308        // -----------------------------------
22309
22310
22311        $('#' + $id).find('.icon-collect').on('click', function () {
22312            $(this).toggleClass('active');
22313        });
22314
22315        // 載入出發地(出境機場)
22316        let $port = $('#' + $id).find('[name="port_cd"]');
22317        $.post($port.data('url'), {}, function (data) {
22318            $port.find('option:not(.empty)').remove();
22319            for (var i = 0; i < data.length; i++) {
22320                $port.append($("<option></option>").attr("value", data[i].OptValue).text(data[i].OptText));
22321                if (data[i].Selected)
22322                    $port.val(data[i].OptValue);
22323            }
22324        }, "json");
22325
22326        // 載入航空公司
22327        /*let $flight = $('#'+$id).find('[name="carr_cd"]');
22328        $.post($flight.data('url'), { }, function (data) {
22329            $flight.find('option:not(.empty)').remove();
22330            for (var i in data) {
22331                $flight.append($("<option></option>").attr("value", data[i].OptValue).text(data[i].OptText));
22332                if (data[i].Selected)
22333                    $$flight.val(data[i].OptValue);
22334            }
22335        }, "json");*/
22336
22337        // 載入大分類
22338        let $regm = $('#' + $id).find('[name="regm_cd"]');
22339        $.post($regm.data('url'), {}, function (data) {
22340            $regm.find('option:not(.empty)').remove();
22341            for (var i = 0; i < data.length; i++) {
22342                $regm.append($("<option></option>").attr("value", data[i].Value).text(data[i].Text));
22343                if (data[i].Selected)
22344                    $regm.val(data[i].Value);
22345            }
22346        }, "json");
22347
22348        //選取大分類後 更改小分類+出發地選項
22349        $('#' + $id).find('[name="regm_cd"]').on('change', function () {
22350            var $regs = $('#' + $id).find('[name="regs_cd"]');
22351            $regs.find('option:not(.empty)').remove();
22352            if ($(this).val() === undefined || $(this).val() == null || $(this).val().length <= 0 || $(this).val() === '') {
22353                $regs.append($("<option></option>").attr("value", '').text('不限'));
22354            }
22355            else {
22356                $.post($(this).data('url') + '?c_type=S', { regm_cd: $(this).val() }, function (data) {
22357                    $regs.find('option:not(.empty)').remove();
22358                    for (var i = 0; i < data.length; i++) {
22359                        $regs.append($("<option></option>").attr("value", data[i].Value).text(data[i].Text));
22360                        if (data[i].Selected)
22361                            $regs.val(data[i].Value);
22362                    }
22363                }, "json");
22364                changePortSelect();
22365            }
22366        }).trigger('change');
22367
22368        //選取小分類後 更改出發地選項
22369        $('#' + $id).find('[name="regs_cd"]').on('change', function () {
22370            changePortSelect();
22371        });
22372
22373        //可報名CHECKBOX觸發
22374        let $signup_st = $('#' + $id).find('[name="signup_st"]');
22375        $('#' + $id).find('[name="_isJoin"]').on('change', function () {
22376            if ($(this).is(':checked')) {
22377                $signup_st.val('3')
22378            } else {
22379                $signup_st.val('')
22380            }
22381        });
22382
22383        // -----------------------------------
22384        // 保證出發字漾吃 ZC 站台設定
22385        let guaranteeText = getSettingValue(settingData, "DSP_GUARANTEE_TXT");
22386        if(
22387            guaranteeText !== null &&
22388            guaranteeText !== undefined &&
22389            guaranteeText !== '' &&
22390            guaranteeText !== 'null' &&
22391            guaranteeText !== 'undefined'
22392          ) $('#' + $id).find("#GuaranteeText").text(guaranteeText);
22393
22394        //保證出發CHECKBOX觸發
22395        let $promo = $('#' + $id).find('[name="promo"]');
22396        $('#' + $id).find('[name="_isPromote"]').on('change', function () {
22397            if ($(this).is(':checked')) {
22398                $promo.val('G')
22399            } else {
22400                $promo.val('')
22401            }
22402        });
22403        // -----------------------------------
22404
22405        // 依照當前所選的大小分類,取得正確的啟程地(機場/港口)下拉選單
22406        function changePortSelect() {
22407            var $port = $('#' + $id).find('[name="port_cd"]');
22408            var regmCd = $('#' + $id).find('[name="regm_cd"] :selected').val(); // 大分類代碼
22409            var regsCd = $('#' + $id).find('[name="regs_cd"] :selected').val(); // 小分類代碼
22410            var portCd = $('#' + $id).find('[name="port_cd"] :selected').val(); // 當前啟程地代碼(如果連動時,要刷新成"不限"的話,把這個改成空值就好)
22411
22412            $.post($port.data('url'), { regm_cd: regmCd, regs_cd: regsCd, port_cd: portCd }, function (data) {
22413                $port.find('option:not(.empty)').remove();
22414                for (var i = 0; i < data.length; i++) {
22415                    $port.append($("<option></option>").attr("value", data[i].OptValue).text(data[i].OptText));
22416                    if (data[i].IsSelected)
22417                        $port.val(data[i].OptValue);
22418
22419                }
22420            }, "json");
22421        }        
22422
22423        //手機版語音輸入
22424        function micButton() {
22425            return $("#" + $id).find(".mic_icon .fa-microphone");
22426        }
22427
22428        function filterKeyword() {
22429            return $("#" + $id).find("#filterKeyword")[0];
22430        }
22431
22432        // 檢查瀏覽器是否支援 webkitSpeechRecognition
22433        if ("webkitSpeechRecognition" in window) {
22434            //Web Speech API
22435            const recognition = new webkitSpeechRecognition();
22436
22437            function startSpeechRecognition() {
22438
22439                // 設置識別語言為中文
22440                recognition.lang = "zh-TW";
22441
22442                // 設置連續識別模式
22443                recognition.continuous = true;
22444
22445                // 設置識別結果是否包含中間結果
22446                recognition.interimResults = false;
22447
22448                // 定義搜尋計時器變量
22449                let searchTimer = null;
22450
22451                // 監聽語音識別結果
22452                recognition.onresult = function (event) {
22453                    const result = event.results[event.resultIndex][
224530].transcript;
22454                    filterKeyword().value = result;
22455
22456                    // 取消搜尋計時器
22457                    clearTimeout(searchTimer);
22458
22459                    // 啟動新的搜尋計時器
22460                    searchTimer = setTimeout(() => {
22461                        performSearch();
22462                    }, 1000);
22463                };
22464
22465                // 監聽語音識別結束事件
22466                recognition.onend = () => {
22467                    // 停止語音識別
22468                    recognitionStop();
22469                };
22470
22471                // 監聽語音識別錯誤事件
22472                recognition.onerror = (event) => {
22473                    console.error(`語音識別錯誤:${event.error}`);
22474                    // 停止語音識別
22475                    recognitionStop();
22476                };
22477                // 定義搜索
22478                function performSearch() {
22479                    $("#" + $id).find('.search-btn').click();
22480                }
22481
22482                // 監聽使用者停止說話事件
22483                recognition.onspeechend = () => {
22484                    // 停止語音識別
22485                    recognitionStop();
22486
22487                    // 取消搜尋計時器
22488                    if (searchTimer !== null) {
22489                        clearTimeout(searchTimer);
22490                    }
22491
22492                    // 啟動新的搜尋計時器
22493                    searchTimer = setTimeout(() => {
22494                        performSearch();
22495                    }, 500);
22496                };
22497
22498                // 設置語音識別超時,如果使用者沒有在6秒內說話,則停止語音識別
22499                setTimeout(() => {
22500                    recognitionStop();
22501                }, 6000);
22502
22503                // 啟動語音識別
22504                recognitionStart();
22505            }
22506
22507            //控制Icon
22508            function setIconVisibility(micIconVisible, chartIconVisible) {
22509                $('.micIcon').css('visibility', micIconVisible ? 'visible' : 'hidden');
22510                $('.chartIcon').css('visibility', chartIconVisible ? 'visible' : 'hidden');
22511            }
22512
22513            //控制語音輸入
22514            function recognitionStart() {
22515                recognition.start();
22516                setIconVisibility(false, true);
22517            }
22518
22519            function recognitionStop() {
22520                recognition.stop();
22521                setIconVisibility(true, false);
22522            }
22523            //--------------------------------------------------Web Speech API Modal
22524            micButton().on('click', function () {
22525
22526                // 設定燈箱開啟時禁止滑動
22527                $('body').css('overflow', 'hidden');
22528
22529                // 設定燈箱樣式
22530                const dialog = $('<div></div>').css({
22531                    position: 'fixed',
22532                    bottom: '-50%', // 設定起始位置
22533                    left: '0',
22534                    width: '100%',
22535                    height: '30%',
22536                    background: '#fff',
22537                    boxShadow: '0 0 10px rgba(0, 0, 0, 0.5)',
22538                    borderTopLeftRadius: '10px',
22539                    borderTopRightRadius: '10px'
22540                });
22541
22542                // 文字標題
22543                const message = $('<div>請說</div>').css({
22544                    position: 'absolute',
22545                    top: '20%',
22546                    left: '50%',
22547                    transform: 'translate(-50%, -50%)',
22548                    fontSize: '20px',
22549                    fontWeight: 'bold'
22550                });
22551                dialog.append(message);
22552
22553                // 文字內容1
22554                const grayText1 = $('<div>請說出您要搜尋的關鍵字</div>').css({
22555                    color: '#777',
22556                    fontSize: '15px',
22557                    position: 'absolute',
22558                    top: '35%',
22559                    left: '50%',
22560                    transform: 'translate(-50%, -50%)'
22561                });
22562                dialog.append(grayText1);
22563
22564                // 文字內容2
22565                const grayText2 = $('<div>例如:東京、奧地利、巴里島...</div>').css({
22566                    color: '#777',
22567                    fontSize: '15px',
22568                    position: 'absolute',
22569                    top: '55%',
22570                    left: '50%',
22571                    transform: 'translate(-50%, -50%)'
22572                });
22573                dialog.append(grayText2);
22574
22575                // 麥克風 Icon
22576                const micIcon = $('<div class="micIcon"><i class="fa fa-microphone"></i></div>').css({
22577                    position: 'absolute',
22578                    top: '75%',
22579                    left: '50%',
22580                    transform: 'translate(-50%, -50%)'
22581                });
22582                micIcon.find('i').css({
22583                    color: '#777',
22584                    fontSize: '40px'
22585                });
22586                dialog.append(micIcon);
22587                micIcon.on('click', startSpeechRecognition);
22588
22589                // 波型 Icon
22590                for (let i = 1; i <= 4; i++) {
22591                    const chartIcon = $('<div class="chartIcon"><i class="fa fa-align-center"></i></div>').css({
22592                        position: 'absolute',
22593                        top: '70%',
22594                        left: (28 + i * 7) + '%',
22595                    });
22596                    chartIcon.find('i').css({
22597                        color: '#777',
22598                        fontSize: '33px',
22599                        transform: i % 2 == 1 ? 'rotate(-90deg)' : 'rotate(90deg)'
22600                    });
22601                    dialog.append(chartIcon);
22602                }
22603
22604                // 設定半透明背景樣式
22605                const body = $('body');
22606                const bg = $('<div></div>');
22607                bg.css({
22608                    'position': 'fixed',
22609                    'top': '0',
22610                    'left': '0',
22611                    'width': '100%',
22612                    'height': '100%',
22613                    'background-color': 'rgba(0, 0, 0, 0.5)'
22614                });
22615
22616                const wrapper = $('<div></div>');
22617                wrapper.css({
22618                    'position': 'fixed',
22619                    'top': '0',
22620                    'left': '0',
22621                    'width': '100%',
22622                    'height': '100%',
22623                    'z-index': '9998'
22624                });
22625                wrapper.append(bg);
22626                wrapper.append(dialog);
22627                body.append(wrapper);
22628
22629                // 關閉按鈕
22630                const closeButton = $('<button>&times;</button>');
22631                closeButton.css({
22632                    position: 'absolute',
22633                    top: '10px',
22634                    right: '10px',
22635                    border: 'none',
22636                    background: 'none',
22637                    fontSize: '30px',
22638                    cursor: 'pointer'
22639                });
22640                dialog.append(closeButton);
22641
22642                // 燈箱動畫
22643                const dialogHeight = $(dialog).outerHeight();
22644                $(dialog).css('bottom', '-' + dialogHeight + 'px');
22645                setTimeout(function () {
22646                    $(dialog).css({
22647                        'transition': 'bottom 0.3s ease-out',
22648                        'bottom': '0'
22649                    });
22650                }, 10);
22651                const closeDialog = function () {
22652                    recognition.stop();
22653                    $(dialog).css('bottom', '-' + dialogHeight + 'px');
22654                    setTimeout(function () {
22655                        $(bg).remove();
22656                        $(dialog).remove();
22657                        $(wrapper).remove();
22658                        $('body').css('overflow', 'auto');
22659                    }, 300);
22660                }
22661                $(closeButton).on('click', closeDialog);
22662                $(bg).on('click', closeDialog);
22663                startSpeechRecognition();
22664            });
22665        } else {
22666            console.error("Your browser doesn't support webkitSpeechRecognition");
22667        }
22668
22669        //防止URL直接帶入NaN
22670        let $travelType = $('#' + $id).find('#travel_type');
22671        if ($travelType.val() === "NaN") {
22672            $travelType.val('');
22673        }
22674
22675        // 取得 WebSetting 資料
22676        async function initFormSettings($id) {
22677            let settingUrl = $('#' + $id).data('setting-url');
22678            try {
22679                let response = await postJsonAsync(settingUrl);
22680                return response.Data || [];
22681            } catch (e) {
22682                console.error("載入設定失敗:", e);
22683                return [];
22684            }
22685        }
22686
22687        // 取指定站台設定的 key - value
22688        function getSettingValue(dataArray, key) {
22689            const item = dataArray.find(x => x.Key === key);
22690            return item ? item.Value : null;
22691        }
22692
22693        function postJsonAsync(url, data = {}) {
22694            return new Promise((resolve, reject) => {
22695                $.post({
22696                    url: url,
22697                    data: JSON.stringify(data),
22698                    contentType: "application/json",
22699                    dataType: "json",
22700                    success: resolve,
22701                    error: reject
22702                });
22703            });
22704        }
22705    });
22706})
22707
22708
22709
22710; })(jQuery);/* compress error:[4]function encode(int) {*/
22711
22712/* MODULE de67a8c9-47a3-4168-a3e6-d3d74e242e42, Version: 1.0.51 */
22713;(function($) {; var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
22714
22715// NB: does not validate input
22716function encode(int) {
22717    if (int === 0) {
22718        return CHARSET[0];
22719    }
22720
22721    var res = "";
22722    while (int > 0) {
22723        res = CHARSET[int % 62] + res;
22724        int = Math.floor(int / 62);
22725    }
22726    return res;
22727};
22728
22729function decode(str) {
22730    var res = 0,
22731        length = str.length,
22732        i, char;
22733    for (i = 0; i < length; i++) {
22734        char = str.charCodeAt(i);
22735        if (char < 58) { // 0-9
22736            char = char - 48;
22737        } else if (char < 91) { // A-Z
22738            char = char - 29;
22739        } else { // a-z
22740            char = char - 87;
22741        }
22742        res += char * Math.pow(62, length - i - 1);
22743    }
22744    return res;
22745};
22746
22747function base62() {
22748    var id; //base62
22749    do {
22750      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
22751    } while (id.match(/^[0-9]/i) !== null);
22752    return id;
22753}; var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
22754
22755// NB: does not validate input
22756function encode(int) {
22757    if (int === 0) {
22758        return CHARSET[0];
22759    }
22760
22761    var res = "";
22762    while (int > 0) {
22763        res = CHARSET[int % 62] + res;
22764        int = Math.floor(int / 62);
22765    }
22766    return res;
22767};
22768
22769function decode(str) {
22770    var res = 0,
22771        length = str.length,
22772        i, char;
22773    for (i = 0; i < length; i++) {
22774        char = str.charCodeAt(i);
22775        if (char < 58) { // 0-9
22776            char = char - 48;
22777        } else if (char < 91) { // A-Z
22778            char = char - 29;
22779        } else { // a-z
22780            char = char - 87;
22781        }
22782        res += char * Math.pow(62, length - i - 1);
22783    }
22784    return res;
22785};
22786
22787function base62() {
22788    var id; //base62
22789    do {
22790      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
22791    } while (id.match(/^[0-9]/i) !== null);
22792    return id;
22793}/*!
22794 * Datepicker for Bootstrap v1.9.0 (https://github.com/uxsolutions/bootstrap-datepicker)
22795 *
22796 * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
22797 */
22798
22799(function(factory){
22800    if (typeof define === 'function' && define.amd) {
22801        define(['jquery'], factory);
22802    } else if (typeof exports === 'object') {
22803        factory(require('jquery'));
22804    } else {
22805        factory(jQuery);
22806    }
22807}(function($, undefined){
22808	function UTCDate(){
22809		return new Date(Date.UTC.apply(Date, arguments));
22810	}
22811	function UTCToday(){
22812		var today = new Date();
22813		return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
22814	}
22815	function isUTCEquals(date1, date2) {
22816		return (
22817			date1.getUTCFullYear() === date2.getUTCFullYear() &&
22818			date1.getUTCMonth() === date2.getUTCMonth() &&
22819			date1.getUTCDate() === date2.getUTCDate()
22820		);
22821	}
22822	function alias(method, deprecationMsg){
22823		return function(){
22824			if (deprecationMsg !== undefined) {
22825				$.fn.datepicker.deprecated(deprecationMsg);
22826			}
22827
22828			return this[method].apply(this, arguments);
22829		};
22830	}
22831	function isValidDate(d) {
22832		return d && !isNaN(d.getTime());
22833	}
22834
22835	var DateArray = (function(){
22836		var extras = {
22837			get: function(i){
22838				return this.slice(i)[0];
22839			},
22840			contains: function(d){
22841				// Array.indexOf is not cross-browser;
22842				// $.inArray doesn't work with Dates
22843				var val = d && d.valueOf();
22844				for (var i=0, l=this.length; i < l; i++)
22845          // Use date arithmetic to allow dates with different times to match
22846          if (0 <= this[i].valueOf() - val && this[i].valueOf() - val < 1000*60*60*24)
22847						return i;
22848				return -1;
22849			},
22850			remove: function(i){
22851				this.splice(i,1);
22852			},
22853			replace: function(new_array){
22854				if (!new_array)
22855					return;
22856				if (!$.isArray(new_array))
22857					new_array = [new_array];
22858				this.clear();
22859				this.push.apply(this, new_array);
22860			},
22861			clear: function(){
22862				this.length = 0;
22863			},
22864			copy: function(){
22865				var a = new DateArray();
22866				a.replace(this);
22867				return a;
22868			}
22869		};
22870
22871		return function(){
22872			var a = [];
22873			a.push.apply(a, arguments);
22874			$.extend(a, extras);
22875			return a;
22876		};
22877	})();
22878
22879
22880	// Picker object
22881
22882	var Datepicker = function(element, options){
22883		$.data(element, 'datepicker', this);
22884
22885		this._events = [];
22886		this._secondaryEvents = [];
22887
22888		this._process_options(options);
22889
22890		this.dates = new DateArray();
22891		this.viewDate = this.o.defaultViewDate;
22892		this.focusDate = null;
22893
22894		this.element = $(element);
22895		this.isInput = this.element.is('input');
22896		this.inputField = this.isInput ? this.element : this.element.find('input');
22897		this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .input-group-append, .input-group-prepend, .btn') : false;
22898		if (this.component && this.component.length === 0)
22899			this.component = false;
22900		this.isInline = !this.component && this.element.is('div');
22901
22902		this.picker = $(DPGlobal.template);
22903
22904		// Checking templates and inserting
22905		if (this._check_template(this.o.templates.leftArrow)) {
22906			this.picker.find('.prev').html(this.o.templates.leftArrow);
22907		}
22908
22909		if (this._check_template(this.o.templates.rightArrow)) {
22910			this.picker.find('.next').html(this.o.templates.rightArrow);
22911		}
22912
22913		this._buildEvents();
22914		this._attachEvents();
22915
22916		if (this.isInline){
vendor: 56,186 bytes, lines 22917-24816
22917			this.picker.addClass('datepicker-inline').appendTo(this.element);
22918		}
22919		else {
22920			this.picker.addClass('datepicker-dropdown dropdown-menu');
22921		}
22922
22923		if (this.o.rtl){
22924			this.picker.addClass('datepicker-rtl');
22925		}
22926
22927		if (this.o.calendarWeeks) {
22928			this.picker.find('.datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear')
22929				.attr('colspan', function(i, val){
22930					return Number(val) + 1;
22931				});
22932		}
22933
22934		this._process_options({
22935			startDate: this._o.startDate,
22936			endDate: this._o.endDate,
22937			daysOfWeekDisabled: this.o.daysOfWeekDisabled,
22938			daysOfWeekHighlighted: this.o.daysOfWeekHighlighted,
22939			datesDisabled: this.o.datesDisabled
22940		});
22941
22942		this._allow_update = false;
22943		this.setViewMode(this.o.startView);
22944		this._allow_update = true;
22945
22946		this.fillDow();
22947		this.fillMonths();
22948
22949		this.update();
22950
22951		if (this.isInline){
22952			this.show();
22953		}
22954	};
22955
22956	Datepicker.prototype = {
22957		constructor: Datepicker,
22958
22959		_resolveViewName: function(view){
22960			$.each(DPGlobal.viewModes, function(i, viewMode){
22961				if (view === i || $.inArray(view, viewMode.names) !== -1){
22962					view = i;
22963					return false;
22964				}
22965			});
22966
22967			return view;
22968		},
22969
22970		_resolveDaysOfWeek: function(daysOfWeek){
22971			if (!$.isArray(daysOfWeek))
22972				daysOfWeek = daysOfWeek.split(/[,\s]*/);
22973			return $.map(daysOfWeek, Number);
22974		},
22975
22976		_check_template: function(tmp){
22977			try {
22978				// If empty
22979				if (tmp === undefined || tmp === "") {
22980					return false;
22981				}
22982				// If no html, everything ok
22983				if ((tmp.match(/[<>]/g) || []).length <= 0) {
22984					return true;
22985				}
22986				// Checking if html is fine
22987				var jDom = $(tmp);
22988				return jDom.length > 0;
22989			}
22990			catch (ex) {
22991				return false;
22992			}
22993		},
22994
22995		_process_options: function(opts){
22996			// Store raw options for reference
22997			this._o = $.extend({}, this._o, opts);
22998			// Processed options
22999			var o = this.o = $.extend({}, this._o);
23000
23001			// Check if "de-DE" style date is available, if not language should
23002			// fallback to 2 letter code eg "de"
23003			var lang = o.language;
23004			if (!dates[lang]){
23005				lang = lang.split('-')[0];
23006				if (!dates[lang])
23007					lang = defaults.language;
23008			}
23009			o.language = lang;
23010
23011			// Retrieve view index from any aliases
23012			o.startView = this._resolveViewName(o.startView);
23013			o.minViewMode = this._resolveViewName(o.minViewMode);
23014			o.maxViewMode = this._resolveViewName(o.maxViewMode);
23015
23016			// Check view is between min and max
23017			o.startView = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, o.startView));
23018
23019			// true, false, or Number > 0
23020			if (o.multidate !== true){
23021				o.multidate = Number(o.multidate) || false;
23022				if (o.multidate !== false)
23023					o.multidate = Math.max(0, o.multidate);
23024			}
23025			o.multidateSeparator = String(o.multidateSeparator);
23026
23027			o.weekStart %= 7;
23028			o.weekEnd = (o.weekStart + 6) % 7;
23029
23030			var format = DPGlobal.parseFormat(o.format);
23031			if (o.startDate !== -Infinity){
23032				if (!!o.startDate){
23033					if (o.startDate instanceof Date)
23034						o.startDate = this._local_to_utc(this._zero_time(o.startDate));
23035					else
23036						o.startDate = DPGlobal.parseDate(o.startDate, format, o.language, o.assumeNearbyYear);
23037				}
23038				else {
23039					o.startDate = -Infinity;
23040				}
23041			}
23042			if (o.endDate !== Infinity){
23043				if (!!o.endDate){
23044					if (o.endDate instanceof Date)
23045						o.endDate = this._local_to_utc(this._zero_time(o.endDate));
23046					else
23047						o.endDate = DPGlobal.parseDate(o.endDate, format, o.language, o.assumeNearbyYear);
23048				}
23049				else {
23050					o.endDate = Infinity;
23051				}
23052			}
23053
23054			o.daysOfWeekDisabled = this._resolveDaysOfWeek(o.daysOfWeekDisabled||[]);
23055			o.daysOfWeekHighlighted = this._resolveDaysOfWeek(o.daysOfWeekHighlighted||[]);
23056
23057			o.datesDisabled = o.datesDisabled||[];
23058			if (!$.isArray(o.datesDisabled)) {
23059				o.datesDisabled = o.datesDisabled.split(',');
23060			}
23061			o.datesDisabled = $.map(o.datesDisabled, function(d){
23062				return DPGlobal.parseDate(d, format, o.language, o.assumeNearbyYear);
23063			});
23064
23065			var plc = String(o.orientation).toLowerCase().split(/\s+/g),
23066				_plc = o.orientation.toLowerCase();
23067			plc = $.grep(plc, function(word){
23068				return /^auto|left|right|top|bottom$/.test(word);
23069			});
23070			o.orientation = {x: 'auto', y: 'auto'};
23071			if (!_plc || _plc === 'auto')
23072				; // no action
23073			else if (plc.length === 1){
23074				switch (plc[0]){
23075					case 'top':
23076					case 'bottom':
23077						o.orientation.y = plc[0];
23078						break;
23079					case 'left':
23080					case 'right':
23081						o.orientation.x = plc[0];
23082						break;
23083				}
23084			}
23085			else {
23086				_plc = $.grep(plc, function(word){
23087					return /^left|right$/.test(word);
23088				});
23089				o.orientation.x = _plc[0] || 'auto';
23090
23091				_plc = $.grep(plc, function(word){
23092					return /^top|bottom$/.test(word);
23093				});
23094				o.orientation.y = _plc[0] || 'auto';
23095			}
23096			if (o.defaultViewDate instanceof Date || typeof o.defaultViewDate === 'string') {
23097				o.defaultViewDate = DPGlobal.parseDate(o.defaultViewDate, format, o.language, o.assumeNearbyYear);
23098			} else if (o.defaultViewDate) {
23099				var year = o.defaultViewDate.year || new Date().getFullYear();
23100				var month = o.defaultViewDate.month || 0;
23101				var day = o.defaultViewDate.day || 1;
23102				o.defaultViewDate = UTCDate(year, month, day);
23103			} else {
23104				o.defaultViewDate = UTCToday();
23105			}
23106		},
23107		_applyEvents: function(evs){
23108			for (var i=0, el, ch, ev; i < evs.length; i++){
23109				el = evs[i][0];
23110				if (evs[i].length === 2){
23111					ch = undefined;
23112					ev = evs[i][1];
23113				} else if (evs[i].length === 3){
23114					ch = evs[i][1];
23115					ev = evs[i][2];
23116				}
23117				el.on(ev, ch);
23118			}
23119		},
23120		_unapplyEvents: function(evs){
23121			for (var i=0, el, ev, ch; i < evs.length; i++){
23122				el = evs[i][0];
23123				if (evs[i].length === 2){
23124					ch = undefined;
23125					ev = evs[i][1];
23126				} else if (evs[i].length === 3){
23127					ch = evs[i][1];
23128					ev = evs[i][2];
23129				}
23130				el.off(ev, ch);
23131			}
23132		},
23133		_buildEvents: function(){
23134            var events = {
23135                keyup: $.proxy(function(e){
23136                    if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
23137                        this.update();
23138                }, this),
23139                keydown: $.proxy(this.keydown, this),
23140                paste: $.proxy(this.paste, this)
23141            };
23142
23143            if (this.o.showOnFocus === true) {
23144                events.focus = $.proxy(this.show, this);
23145            }
23146
23147            if (this.isInput) { // single input
23148                this._events = [
23149                    [this.element, events]
23150                ];
23151            }
23152            // component: input + button
23153            else if (this.component && this.inputField.length) {
23154                this._events = [
23155                    // For components that are not readonly, allow keyboard nav
23156                    [this.inputField, events],
23157                    [this.component, {
23158                        click: $.proxy(this.show, this)
23159                    }]
23160                ];
23161            }
23162			else {
23163				this._events = [
23164					[this.element, {
23165						click: $.proxy(this.show, this),
23166						keydown: $.proxy(this.keydown, this)
23167					}]
23168				];
23169			}
23170			this._events.push(
23171				// Component: listen for blur on element descendants
23172				[this.element, '*', {
23173					blur: $.proxy(function(e){
23174						this._focused_from = e.target;
23175					}, this)
23176				}],
23177				// Input: listen for blur on element
23178				[this.element, {
23179					blur: $.proxy(function(e){
23180						this._focused_from = e.target;
23181					}, this)
23182				}]
23183			);
23184
23185			if (this.o.immediateUpdates) {
23186				// Trigger input updates immediately on changed year/month
23187				this._events.push([this.element, {
23188					'changeYear changeMonth': $.proxy(function(e){
23189						this.update(e.date);
23190					}, this)
23191				}]);
23192			}
23193
23194			this._secondaryEvents = [
23195				[this.picker, {
23196					click: $.proxy(this.click, this)
23197				}],
23198				[this.picker, '.prev, .next', {
23199					click: $.proxy(this.navArrowsClick, this)
23200				}],
23201				[this.picker, '.day:not(.disabled)', {
23202					click: $.proxy(this.dayCellClick, this)
23203				}],
23204				[$(window), {
23205					resize: $.proxy(this.place, this)
23206				}],
23207				[$(document), {
23208					'mousedown touchstart': $.proxy(function(e){
23209						// Clicked outside the datepicker, hide it
23210						if (!(
23211							this.element.is(e.target) ||
23212							this.element.find(e.target).length ||
23213							this.picker.is(e.target) ||
23214							this.picker.find(e.target).length ||
23215							this.isInline
23216						)){
23217							this.hide();
23218						}
23219					}, this)
23220				}]
23221			];
23222		},
23223		_attachEvents: function(){
23224			this._detachEvents();
23225			this._applyEvents(this._events);
23226		},
23227		_detachEvents: function(){
23228			this._unapplyEvents(this._events);
23229		},
23230		_attachSecondaryEvents: function(){
23231			this._detachSecondaryEvents();
23232			this._applyEvents(this._secondaryEvents);
23233		},
23234		_detachSecondaryEvents: function(){
23235			this._unapplyEvents(this._secondaryEvents);
23236		},
23237		_trigger: function(event, altdate){
23238			var date = altdate || this.dates.get(-1),
23239				local_date = this._utc_to_local(date);
23240
23241			this.element.trigger({
23242				type: event,
23243				date: local_date,
23244				viewMode: this.viewMode,
23245				dates: $.map(this.dates, this._utc_to_local),
23246				format: $.proxy(function(ix, format){
23247					if (arguments.length === 0){
23248						ix = this.dates.length - 1;
23249						format = this.o.format;
23250					} else if (typeof ix === 'string'){
23251						format = ix;
23252						ix = this.dates.length - 1;
23253					}
23254					format = format || this.o.format;
23255					var date = this.dates.get(ix);
23256					return DPGlobal.formatDate(date, format, this.o.language);
23257				}, this)
23258			});
23259		},
23260
23261		show: function(){
23262			if (this.inputField.is(':disabled') || (this.inputField.prop('readonly') && this.o.enableOnReadonly === false))
23263				return;
23264			if (!this.isInline)
23265				this.picker.appendTo(this.o.container);
23266			this.place();
23267			this.picker.show();
23268			this._attachSecondaryEvents();
23269			this._trigger('show');
23270			if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) {
23271				$(this.element).blur();
23272			}
23273			return this;
23274		},
23275
23276		hide: function(){
23277			if (this.isInline || !this.picker.is(':visible'))
23278				return this;
23279			this.focusDate = null;
23280			this.picker.hide().detach();
23281			this._detachSecondaryEvents();
23282			this.setViewMode(this.o.startView);
23283
23284			if (this.o.forceParse && this.inputField.val())
23285				this.setValue();
23286			this._trigger('hide');
23287			return this;
23288		},
23289
23290		destroy: function(){
23291			this.hide();
23292			this._detachEvents();
23293			this._detachSecondaryEvents();
23294			this.picker.remove();
23295			delete this.element.data().datepicker;
23296			if (!this.isInput){
23297				delete this.element.data().date;
23298			}
23299			return this;
23300		},
23301
23302		paste: function(e){
23303			var dateString;
23304			if (e.originalEvent.clipboardData && e.originalEvent.clipboardData.types
23305				&& $.inArray('text/plain', e.originalEvent.clipboardData.types) !== -1) {
23306				dateString = e.originalEvent.clipboardData.getData('text/plain');
23307			} else if (window.clipboardData) {
23308				dateString = window.clipboardData.getData('Text');
23309			} else {
23310				return;
23311			}
23312			this.setDate(dateString);
23313			this.update();
23314			e.preventDefault();
23315		},
23316
23317		_utc_to_local: function(utc){
23318			if (!utc) {
23319				return utc;
23320			}
23321
23322			var local = new Date(utc.getTime() + (utc.getTimezoneOffset() * 60000));
23323
23324			if (local.getTimezoneOffset() !== utc.getTimezoneOffset()) {
23325				local = new Date(utc.getTime() + (local.getTimezoneOffset() * 60000));
23326			}
23327
23328			return local;
23329		},
23330		_local_to_utc: function(local){
23331			return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000));
23332		},
23333		_zero_time: function(local){
23334			return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
23335		},
23336		_zero_utc_time: function(utc){
23337			return utc && UTCDate(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());
23338		},
23339
23340		getDates: function(){
23341			return $.map(this.dates, this._utc_to_local);
23342		},
23343
23344		getUTCDates: function(){
23345			return $.map(this.dates, function(d){
23346				return new Date(d);
23347			});
23348		},
23349
23350		getDate: function(){
23351			return this._utc_to_local(this.getUTCDate());
23352		},
23353
23354		getUTCDate: function(){
23355			var selected_date = this.dates.get(-1);
23356			if (selected_date !== undefined) {
23357				return new Date(selected_date);
23358			} else {
23359				return null;
23360			}
23361		},
23362
23363		clearDates: function(){
23364			this.inputField.val('');
23365			this.update();
23366			this._trigger('changeDate');
23367
23368			if (this.o.autoclose) {
23369				this.hide();
23370			}
23371		},
23372
23373		setDates: function(){
23374			var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
23375			this.update.apply(this, args);
23376			this._trigger('changeDate');
23377			this.setValue();
23378			return this;
23379		},
23380
23381		setUTCDates: function(){
23382			var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
23383			this.setDates.apply(this, $.map(args, this._utc_to_local));
23384			return this;
23385		},
23386
23387		setDate: alias('setDates'),
23388		setUTCDate: alias('setUTCDates'),
23389		remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead'),
23390
23391		setValue: function(){
23392			var formatted = this.getFormattedDate();
23393			this.inputField.val(formatted);
23394			return this;
23395		},
23396
23397		getFormattedDate: function(format){
23398			if (format === undefined)
23399				format = this.o.format;
23400
23401			var lang = this.o.language;
23402			return $.map(this.dates, function(d){
23403				return DPGlobal.formatDate(d, format, lang);
23404			}).join(this.o.multidateSeparator);
23405		},
23406
23407		getStartDate: function(){
23408			return this.o.startDate;
23409		},
23410
23411		setStartDate: function(startDate){
23412			this._process_options({startDate: startDate});
23413			this.update();
23414			this.updateNavArrows();
23415			return this;
23416		},
23417
23418		getEndDate: function(){
23419			return this.o.endDate;
23420		},
23421
23422		setEndDate: function(endDate){
23423			this._process_options({endDate: endDate});
23424			this.update();
23425			this.updateNavArrows();
23426			return this;
23427		},
23428
23429		setDaysOfWeekDisabled: function(daysOfWeekDisabled){
23430			this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
23431			this.update();
23432			return this;
23433		},
23434
23435		setDaysOfWeekHighlighted: function(daysOfWeekHighlighted){
23436			this._process_options({daysOfWeekHighlighted: daysOfWeekHighlighted});
23437			this.update();
23438			return this;
23439		},
23440
23441		setDatesDisabled: function(datesDisabled){
23442			this._process_options({datesDisabled: datesDisabled});
23443			this.update();
23444			return this;
23445		},
23446
23447		place: function(){
23448			if (this.isInline)
23449				return this;
23450			var calendarWidth = this.picker.outerWidth(),
23451				calendarHeight = this.picker.outerHeight(),
23452				visualPadding = 10,
23453				container = $(this.o.container),
23454				windowWidth = container.width(),
23455				scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(),
23456				appendOffset = container.offset();
23457
23458			var parentsZindex = [0];
23459			this.element.parents().each(function(){
23460				var itemZIndex = $(this).css('z-index');
23461				if (itemZIndex !== 'auto' && Number(itemZIndex) !== 0) parentsZindex.push(Number(itemZIndex));
23462			});
23463			var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset;
23464			var offset = this.component ? this.component.parent().offset() : this.element.offset();
23465			var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
23466			var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
23467			var left = offset.left - appendOffset.left;
23468			var top = offset.top - appendOffset.top;
23469
23470			if (this.o.container !== 'body') {
23471				top += scrollTop;
23472			}
23473
23474			this.picker.removeClass(
23475				'datepicker-orient-top datepicker-orient-bottom '+
23476				'datepicker-orient-right datepicker-orient-left'
23477			);
23478
23479			if (this.o.orientation.x !== 'auto'){
23480				this.picker.addClass('datepicker-orient-' + this.o.orientation.x);
23481				if (this.o.orientation.x === 'right')
23482					left -= calendarWidth - width;
23483			}
23484			// auto x orientation is best-placement: if it crosses a window
23485			// edge, fudge it sideways
23486			else {
23487				if (offset.left < 0) {
23488					// component is outside the window on the left side. Move it into visible range
23489					this.picker.addClass('datepicker-orient-left');
23490					left -= offset.left - visualPadding;
23491				} else if (left + calendarWidth > windowWidth) {
23492					// the calendar passes the widow right edge. Align it to component right side
23493					this.picker.addClass('datepicker-orient-right');
23494					left += width - calendarWidth;
23495				} else {
23496					if (this.o.rtl) {
23497						// Default to right
23498						this.picker.addClass('datepicker-orient-right');
23499					} else {
23500						// Default to left
23501						this.picker.addClass('datepicker-orient-left');
23502					}
23503				}
23504			}
23505
23506			// auto y orientation is best-situation: top or bottom, no fudging,
23507			// decision based on which shows more of the calendar
23508			var yorient = this.o.orientation.y,
23509				top_overflow;
23510			if (yorient === 'auto'){
23511				top_overflow = -scrollTop + top - calendarHeight;
23512				yorient = top_overflow < 0 ? 'bottom' : 'top';
23513			}
23514
23515			this.picker.addClass('datepicker-orient-' + yorient);
23516			if (yorient === 'top')
23517				top -= calendarHeight + parseInt(this.picker.css('padding-top'));
23518			else
23519				top += height;
23520
23521			if (this.o.rtl) {
23522				var right = windowWidth - (left + width);
23523				this.picker.css({
23524					top: top,
23525					right: right,
23526					zIndex: zIndex
23527				});
23528			} else {
23529				this.picker.css({
23530					top: top,
23531					left: left,
23532					zIndex: zIndex
23533				});
23534			}
23535			return this;
23536		},
23537
23538		_allow_update: true,
23539		update: function(){
23540			if (!this._allow_update)
23541				return this;
23542
23543			var oldDates = this.dates.copy(),
23544				dates = [],
23545				fromArgs = false;
23546			if (arguments.length){
23547				$.each(arguments, $.proxy(function(i, date){
23548					if (date instanceof Date)
23549						date = this._local_to_utc(date);
23550					dates.push(date);
23551				}, this));
23552				fromArgs = true;
23553			} else {
23554				dates = this.isInput
23555						? this.element.val()
23556						: this.element.data('date') || this.inputField.val();
23557				if (dates && this.o.multidate)
23558					dates = dates.split(this.o.multidateSeparator);
23559				else
23560					dates = [dates];
23561				delete this.element.data().date;
23562			}
23563
23564			dates = $.map(dates, $.proxy(function(date){
23565				return DPGlobal.parseDate(date, this.o.format, this.o.language, this.o.assumeNearbyYear);
23566			}, this));
23567			dates = $.grep(dates, $.proxy(function(date){
23568				return (
23569					!this.dateWithinRange(date) ||
23570					!date
23571				);
23572			}, this), true);
23573			this.dates.replace(dates);
23574
23575			if (this.o.updateViewDate) {
23576				if (this.dates.length)
23577					this.viewDate = new Date(this.dates.get(-1));
23578				else if (this.viewDate < this.o.startDate)
23579					this.viewDate = new Date(this.o.startDate);
23580				else if (this.viewDate > this.o.endDate)
23581					this.viewDate = new Date(this.o.endDate);
23582				else
23583					this.viewDate = this.o.defaultViewDate;
23584			}
23585
23586			if (fromArgs){
23587				// setting date by clicking
23588				this.setValue();
23589				this.element.change();
23590			}
23591			else if (this.dates.length){
23592				// setting date by typing
23593				if (String(oldDates) !== String(this.dates) && fromArgs) {
23594					this._trigger('changeDate');
23595					this.element.change();
23596				}
23597			}
23598			if (!this.dates.length && oldDates.length) {
23599				this._trigger('clearDate');
23600				this.element.change();
23601			}
23602
23603			this.fill();
23604			return this;
23605		},
23606
23607		fillDow: function(){
23608      if (this.o.showWeekDays) {
23609			var dowCnt = this.o.weekStart,
23610				html = '<tr>';
23611			if (this.o.calendarWeeks){
23612				html += '<th class="cw">&#160;</th>';
23613			}
23614			while (dowCnt < this.o.weekStart + 7){
23615				html += '<th class="dow';
23616        if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) !== -1)
23617          html += ' disabled';
23618        html += '">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
23619			}
23620			html += '</tr>';
23621			this.picker.find('.datepicker-days thead').append(html);
23622      }
23623		},
23624
23625		fillMonths: function(){
23626      var localDate = this._utc_to_local(this.viewDate);
23627			var html = '';
23628			var focused;
23629			for (var i = 0; i < 12; i++){
23630				focused = localDate && localDate.getMonth() === i ? ' focused' : '';
23631				html += '<span class="month' + focused + '">' + dates[this.o.language].monthsShort[i] + '</span>';
23632			}
23633			this.picker.find('.datepicker-months td').html(html);
23634		},
23635
23636		setRange: function(range){
23637			if (!range || !range.length)
23638				delete this.range;
23639			else
23640				this.range = $.map(range, function(d){
23641					return d.valueOf();
23642				});
23643			this.fill();
23644		},
23645
23646		getClassNames: function(date){
23647			var cls = [],
23648				year = this.viewDate.getUTCFullYear(),
23649				month = this.viewDate.getUTCMonth(),
23650				today = UTCToday();
23651			if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){
23652				cls.push('old');
23653			} else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
23654				cls.push('new');
23655			}
23656			if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
23657				cls.push('focused');
23658			// Compare internal UTC date with UTC today, not local today
23659			if (this.o.todayHighlight && isUTCEquals(date, today)) {
23660				cls.push('today');
23661			}
23662			if (this.dates.contains(date) !== -1)
23663				cls.push('active');
23664			if (!this.dateWithinRange(date)){
23665				cls.push('disabled');
23666			}
23667			if (this.dateIsDisabled(date)){
23668				cls.push('disabled', 'disabled-date');
23669			}
23670			if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1){
23671				cls.push('highlighted');
23672			}
23673
23674			if (this.range){
23675				if (date > this.range[0] && date < this.range[this.range.length-1]){
23676					cls.push('range');
23677				}
23678				if ($.inArray(date.valueOf(), this.range) !== -1){
23679					cls.push('selected');
23680				}
23681				if (date.valueOf() === this.range[0]){
23682          cls.push('range-start');
23683        }
23684        if (date.valueOf() === this.range[this.range.length-1]){
23685          cls.push('range-end');
23686        }
23687			}
23688			return cls;
23689		},
23690
23691		_fill_yearsView: function(selector, cssClass, factor, year, startYear, endYear, beforeFn){
23692			var html = '';
23693			var step = factor / 10;
23694			var view = this.picker.find(selector);
23695			var startVal = Math.floor(year / factor) * factor;
23696			var endVal = startVal + step * 9;
23697			var focusedVal = Math.floor(this.viewDate.getFullYear() / step) * step;
23698			var selected = $.map(this.dates, function(d){
23699				return Math.floor(d.getUTCFullYear() / step) * step;
23700			});
23701
23702			var classes, tooltip, before;
23703			for (var currVal = startVal - step; currVal <= endVal + step; currVal += step) {
23704				classes = [cssClass];
23705				tooltip = null;
23706
23707				if (currVal === startVal - step) {
23708					classes.push('old');
23709				} else if (currVal === endVal + step) {
23710					classes.push('new');
23711				}
23712				if ($.inArray(currVal, selected) !== -1) {
23713					classes.push('active');
23714				}
23715				if (currVal < startYear || currVal > endYear) {
23716					classes.push('disabled');
23717				}
23718				if (currVal === focusedVal) {
23719				  classes.push('focused');
23720        }
23721
23722				if (beforeFn !== $.noop) {
23723					before = beforeFn(new Date(currVal, 0, 1));
23724					if (before === undefined) {
23725						before = {};
23726					} else if (typeof before === 'boolean') {
23727						before = {enabled: before};
23728					} else if (typeof before === 'string') {
23729						before = {classes: before};
23730					}
23731					if (before.enabled === false) {
23732						classes.push('disabled');
23733					}
23734					if (before.classes) {
23735						classes = classes.concat(before.classes.split(/\s+/));
23736					}
23737					if (before.tooltip) {
23738						tooltip = before.tooltip;
23739					}
23740				}
23741
23742				html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + currVal + '</span>';
23743			}
23744
23745			view.find('.datepicker-switch').text(startVal + '-' + endVal);
23746			view.find('td').html(html);
23747		},
23748
23749		fill: function(){
23750			var d = new Date(this.viewDate),
23751				year = d.getUTCFullYear(),
23752				month = d.getUTCMonth(),
23753				startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
23754				startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
23755				endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
23756				endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
23757				todaytxt = dates[this.o.language].today || dates['en'].today || '',
23758				cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
23759        titleFormat = dates[this.o.language].titleFormat || dates['en'].titleFormat,
23760        todayDate = UTCToday(),
23761        titleBtnVisible = (this.o.todayBtn === true || this.o.todayBtn === 'linked') && todayDate >= this.o.startDate && todayDate <= this.o.endDate && !this.weekOfDateIsDisabled(todayDate),
23762				tooltip,
23763				before;
23764			if (isNaN(year) || isNaN(month))
23765				return;
23766			this.picker.find('.datepicker-days .datepicker-switch')
23767						.text(DPGlobal.formatDate(d, titleFormat, this.o.language));
23768			this.picker.find('tfoot .today')
23769						.text(todaytxt)
23770            .css('display', titleBtnVisible ? 'table-cell' : 'none');
23771			this.picker.find('tfoot .clear')
23772						.text(cleartxt)
23773						.css('display', this.o.clearBtn === true ? 'table-cell' : 'none');
23774			this.picker.find('thead .datepicker-title')
23775						.text(this.o.title)
23776						.css('display', typeof this.o.title === 'string' && this.o.title !== '' ? 'table-cell' : 'none');
23777			this.updateNavArrows();
23778			this.fillMonths();
23779			var prevMonth = UTCDate(year, month, 0),
23780				day = prevMonth.getUTCDate();
23781			prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);
23782			var nextMonth = new Date(prevMonth);
23783			if (prevMonth.getUTCFullYear() < 100){
23784        nextMonth.setUTCFullYear(prevMonth.getUTCFullYear());
23785      }
23786			nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
23787			nextMonth = nextMonth.valueOf();
23788			var html = [];
23789			var weekDay, clsName;
23790			while (prevMonth.valueOf() < nextMonth){
23791				weekDay = prevMonth.getUTCDay();
23792				if (weekDay === this.o.weekStart){
23793					html.push('<tr>');
23794					if (this.o.calendarWeeks){
23795						// ISO 8601: First week contains first thursday.
23796						// ISO also states week starts on Monday, but we can be more abstract here.
23797						var
23798							// Start of current week: based on weekstart/current date
23799							ws = new Date(+prevMonth + (this.o.weekStart - weekDay - 7) % 7 * 864e5),
23800							// Thursday of this week
23801							th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
23802							// First Thursday of year, year from thursday
23803							yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay()) % 7 * 864e5),
23804							// Calendar week: ms between thursdays, div ms per day, div 7 days
23805							calWeek = (th - yth) / 864e5 / 7 + 1;
23806						html.push('<td class="cw">'+ calWeek +'</td>');
23807					}
23808				}
23809				clsName = this.getClassNames(prevMonth);
23810				clsName.push('day');
23811
23812				var content = prevMonth.getUTCDate();
23813
23814				if (this.o.beforeShowDay !== $.noop){
23815					before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
23816					if (before === undefined)
23817						before = {};
23818					else if (typeof before === 'boolean')
23819						before = {enabled: before};
23820					else if (typeof before === 'string')
23821						before = {classes: before};
23822					if (before.enabled === false)
23823						clsName.push('disabled');
23824					if (before.classes)
23825						clsName = clsName.concat(before.classes.split(/\s+/));
23826					if (before.tooltip)
23827						tooltip = before.tooltip;
23828					if (before.content)
23829						content = before.content;
23830				}
23831
23832				//Check if uniqueSort exists (supported by jquery >=1.12 and >=2.2)
23833				//Fallback to unique function for older jquery versions
23834				if ($.isFunction($.uniqueSort)) {
23835					clsName = $.uniqueSort(clsName);
23836				} else {
23837					clsName = $.unique(clsName);
23838				}
23839
23840				html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + ' data-date="' + prevMonth.getTime().toString() + '">' + content + '</td>');
23841				tooltip = null;
23842				if (weekDay === this.o.weekEnd){
23843					html.push('</tr>');
23844				}
23845				prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
23846			}
23847			this.picker.find('.datepicker-days tbody').html(html.join(''));
23848
23849			var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months';
23850			var months = this.picker.find('.datepicker-months')
23851						.find('.datepicker-switch')
23852							.text(this.o.maxViewMode < 2 ? monthsTitle : year)
23853							.end()
23854						.find('tbody span').removeClass('active');
23855
23856			$.each(this.dates, function(i, d){
23857				if (d.getUTCFullYear() === year)
23858					months.eq(d.getUTCMonth()).addClass('active');
23859			});
23860
23861			if (year < startYear || year > endYear){
23862				months.addClass('disabled');
23863			}
23864			if (year === startYear){
23865				months.slice(0, startMonth).addClass('disabled');
23866			}
23867			if (year === endYear){
23868				months.slice(endMonth+1).addClass('disabled');
23869			}
23870
23871			if (this.o.beforeShowMonth !== $.noop){
23872				var that = this;
23873				$.each(months, function(i, month){
23874          var moDate = new Date(year, i, 1);
23875          var before = that.o.beforeShowMonth(moDate);
23876					if (before === undefined)
23877						before = {};
23878					else if (typeof before === 'boolean')
23879						before = {enabled: before};
23880					else if (typeof before === 'string')
23881						before = {classes: before};
23882					if (before.enabled === false && !$(month).hasClass('disabled'))
23883					    $(month).addClass('disabled');
23884					if (before.classes)
23885					    $(month).addClass(before.classes);
23886					if (before.tooltip)
23887					    $(month).prop('title', before.tooltip);
23888				});
23889			}
23890
23891			// Generating decade/years picker
23892			this._fill_yearsView(
23893				'.datepicker-years',
23894				'year',
23895				10,
23896				year,
23897				startYear,
23898				endYear,
23899				this.o.beforeShowYear
23900			);
23901
23902			// Generating century/decades picker
23903			this._fill_yearsView(
23904				'.datepicker-decades',
23905				'decade',
23906				100,
23907				year,
23908				startYear,
23909				endYear,
23910				this.o.beforeShowDecade
23911			);
23912
23913			// Generating millennium/centuries picker
23914			this._fill_yearsView(
23915				'.datepicker-centuries',
23916				'century',
23917				1000,
23918				year,
23919				startYear,
23920				endYear,
23921				this.o.beforeShowCentury
23922			);
23923		},
23924
23925		updateNavArrows: function(){
23926			if (!this._allow_update)
23927				return;
23928
23929			var d = new Date(this.viewDate),
23930				year = d.getUTCFullYear(),
23931				month = d.getUTCMonth(),
23932				startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
23933				startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
23934				endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
23935				endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
23936				prevIsDisabled,
23937				nextIsDisabled,
23938				factor = 1;
23939			switch (this.viewMode){
23940				case 4:
23941					factor *= 10;
23942					/* falls through */
23943				case 3:
23944					factor *= 10;
23945					/* falls through */
23946				case 2:
23947					factor *= 10;
23948					/* falls through */
23949				case 1:
23950					prevIsDisabled = Math.floor(year / factor) * factor <= startYear;
23951					nextIsDisabled = Math.floor(year / factor) * factor + factor > endYear;
23952					break;
23953				case 0:
23954					prevIsDisabled = year <= startYear && month <= startMonth;
23955					nextIsDisabled = year >= endYear && month >= endMonth;
23956					break;
23957			}
23958
23959			this.picker.find('.prev').toggleClass('disabled', prevIsDisabled);
23960			this.picker.find('.next').toggleClass('disabled', nextIsDisabled);
23961		},
23962
23963		click: function(e){
23964			e.preventDefault();
23965			e.stopPropagation();
23966
23967			var target, dir, day, year, month;
23968			target = $(e.target);
23969
23970			// Clicked on the switch
23971			if (target.hasClass('datepicker-switch') && this.viewMode !== this.o.maxViewMode){
23972				this.setViewMode(this.viewMode + 1);
23973			}
23974
23975			// Clicked on today button
23976			if (target.hasClass('today') && !target.hasClass('day')){
23977				this.setViewMode(0);
23978				this._setDate(UTCToday(), this.o.todayBtn === 'linked' ? null : 'view');
23979			}
23980
23981			// Clicked on clear button
23982			if (target.hasClass('clear')){
23983				this.clearDates();
23984			}
23985
23986			if (!target.hasClass('disabled')){
23987				// Clicked on a month, year, decade, century
23988				if (target.hasClass('month')
23989						|| target.hasClass('year')
23990						|| target.hasClass('decade')
23991						|| target.hasClass('century')) {
23992					this.viewDate.setUTCDate(1);
23993
23994					day = 1;
23995					if (this.viewMode === 1){
23996						month = target.parent().find('span').index(target);
23997						year = this.viewDate.getUTCFullYear();
23998						this.viewDate.setUTCMonth(month);
23999					} else {
24000						month = 0;
24001						year = Number(target.text());
24002						this.viewDate.setUTCFullYear(year);
24003					}
24004
24005					this._trigger(DPGlobal.viewModes[this.viewMode - 1].e, this.viewDate);
24006
24007					if (this.viewMode === this.o.minViewMode){
24008						this._setDate(UTCDate(year, month, day));
24009					} else {
24010						this.setViewMode(this.viewMode - 1);
24011						this.fill();
24012					}
24013				}
24014			}
24015
24016			if (this.picker.is(':visible') && this._focused_from){
24017				this._focused_from.focus();
24018			}
24019			delete this._focused_from;
24020		},
24021
24022		dayCellClick: function(e){
24023			var $target = $(e.currentTarget);
24024			var timestamp = $target.data('date');
24025			var date = new Date(timestamp);
24026
24027			if (this.o.updateViewDate) {
24028				if (date.getUTCFullYear() !== this.viewDate.getUTCFullYear()) {
24029					this._trigger('changeYear', this.viewDate);
24030				}
24031
24032				if (date.getUTCMonth() !== this.viewDate.getUTCMonth()) {
24033					this._trigger('changeMonth', this.viewDate);
24034				}
24035			}
24036			this._setDate(date);
24037		},
24038
24039		// Clicked on prev or next
24040		navArrowsClick: function(e){
24041			var $target = $(e.currentTarget);
24042			var dir = $target.hasClass('prev') ? -1 : 1;
24043			if (this.viewMode !== 0){
24044				dir *= DPGlobal.viewModes[this.viewMode].navStep * 12;
24045			}
24046			this.viewDate = this.moveMonth(this.viewDate, dir);
24047			this._trigger(DPGlobal.viewModes[this.viewMode].e, this.viewDate);
24048			this.fill();
24049		},
24050
24051		_toggle_multidate: function(date){
24052			var ix = this.dates.contains(date);
24053			if (!date){
24054				this.dates.clear();
24055			}
24056
24057			if (ix !== -1){
24058				if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive){
24059					this.dates.remove(ix);
24060				}
24061			} else if (this.o.multidate === false) {
24062				this.dates.clear();
24063				this.dates.push(date);
24064			}
24065			else {
24066				this.dates.push(date);
24067			}
24068
24069			if (typeof this.o.multidate === 'number')
24070				while (this.dates.length > this.o.multidate)
24071					this.dates.remove(0);
24072		},
24073
24074		_setDate: function(date, which){
24075			if (!which || which === 'date')
24076				this._toggle_multidate(date && new Date(date));
24077			if ((!which && this.o.updateViewDate) || which === 'view')
24078				this.viewDate = date && new Date(date);
24079
24080			this.fill();
24081			this.setValue();
24082			if (!which || which !== 'view') {
24083				this._trigger('changeDate');
24084			}
24085			this.inputField.trigger('change');
24086			if (this.o.autoclose && (!which || which === 'date')){
24087				this.hide();
24088			}
24089		},
24090
24091		moveDay: function(date, dir){
24092			var newDate = new Date(date);
24093			newDate.setUTCDate(date.getUTCDate() + dir);
24094
24095			return newDate;
24096		},
24097
24098		moveWeek: function(date, dir){
24099			return this.moveDay(date, dir * 7);
24100		},
24101
24102		moveMonth: function(date, dir){
24103			if (!isValidDate(date))
24104				return this.o.defaultViewDate;
24105			if (!dir)
24106				return date;
24107			var new_date = new Date(date.valueOf()),
24108				day = new_date.getUTCDate(),
24109				month = new_date.getUTCMonth(),
24110				mag = Math.abs(dir),
24111				new_month, test;
24112			dir = dir > 0 ? 1 : -1;
24113			if (mag === 1){
24114				test = dir === -1
24115					// If going back one month, make sure month is not current month
24116					// (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
24117					? function(){
24118						return new_date.getUTCMonth() === month;
24119					}
24120					// If going forward one month, make sure month is as expected
24121					// (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
24122					: function(){
24123						return new_date.getUTCMonth() !== new_month;
24124					};
24125				new_month = month + dir;
24126				new_date.setUTCMonth(new_month);
24127				// Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
24128				new_month = (new_month + 12) % 12;
24129			}
24130			else {
24131				// For magnitudes >1, move one month at a time...
24132				for (var i=0; i < mag; i++)
24133					// ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
24134					new_date = this.moveMonth(new_date, dir);
24135				// ...then reset the day, keeping it in the new month
24136				new_month = new_date.getUTCMonth();
24137				new_date.setUTCDate(day);
24138				test = function(){
24139					return new_month !== new_date.getUTCMonth();
24140				};
24141			}
24142			// Common date-resetting loop -- if date is beyond end of month, make it
24143			// end of month
24144			while (test()){
24145				new_date.setUTCDate(--day);
24146				new_date.setUTCMonth(new_month);
24147			}
24148			return new_date;
24149		},
24150
24151		moveYear: function(date, dir){
24152			return this.moveMonth(date, dir*12);
24153		},
24154
24155		moveAvailableDate: function(date, dir, fn){
24156			do {
24157				date = this[fn](date, dir);
24158
24159				if (!this.dateWithinRange(date))
24160					return false;
24161
24162				fn = 'moveDay';
24163			}
24164			while (this.dateIsDisabled(date));
24165
24166			return date;
24167		},
24168
24169		weekOfDateIsDisabled: function(date){
24170			return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1;
24171		},
24172
24173		dateIsDisabled: function(date){
24174			return (
24175				this.weekOfDateIsDisabled(date) ||
24176				$.grep(this.o.datesDisabled, function(d){
24177					return isUTCEquals(date, d);
24178				}).length > 0
24179			);
24180		},
24181
24182		dateWithinRange: function(date){
24183			return date >= this.o.startDate && date <= this.o.endDate;
24184		},
24185
24186		keydown: function(e){
24187			if (!this.picker.is(':visible')){
24188				if (e.keyCode === 40 || e.keyCode === 27) { // allow down to re-show picker
24189					this.show();
24190					e.stopPropagation();
24191        }
24192				return;
24193			}
24194			var dateChanged = false,
24195				dir, newViewDate,
24196				focusDate = this.focusDate || this.viewDate;
24197			switch (e.keyCode){
24198				case 27: // escape
24199					if (this.focusDate){
24200						this.focusDate = null;
24201						this.viewDate = this.dates.get(-1) || this.viewDate;
24202						this.fill();
24203					}
24204					else
24205						this.hide();
24206					e.preventDefault();
24207					e.stopPropagation();
24208					break;
24209				case 37: // left
24210				case 38: // up
24211				case 39: // right
24212				case 40: // down
24213					if (!this.o.keyboardNavigation || this.o.daysOfWeekDisabled.length === 7)
24214						break;
24215					dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1;
24216          if (this.viewMode === 0) {
24217  					if (e.ctrlKey){
24218  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
24219
24220  						if (newViewDate)
24221  							this._trigger('changeYear', this.viewDate);
24222  					} else if (e.shiftKey){
24223  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
24224
24225  						if (newViewDate)
24226  							this._trigger('changeMonth', this.viewDate);
24227  					} else if (e.keyCode === 37 || e.keyCode === 39){
24228  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay');
24229  					} else if (!this.weekOfDateIsDisabled(focusDate)){
24230  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek');
24231  					}
24232          } else if (this.viewMode === 1) {
24233            if (e.keyCode === 38 || e.keyCode === 40) {
24234              dir = dir * 4;
24235            }
24236            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
24237          } else if (this.viewMode === 2) {
24238            if (e.keyCode === 38 || e.keyCode === 40) {
24239              dir = dir * 4;
24240            }
24241            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
24242          }
24243					if (newViewDate){
24244						this.focusDate = this.viewDate = newViewDate;
24245						this.setValue();
24246						this.fill();
24247						e.preventDefault();
24248					}
24249					break;
24250				case 13: // enter
24251					if (!this.o.forceParse)
24252						break;
24253					focusDate = this.focusDate || this.dates.get(-1) || this.viewDate;
24254					if (this.o.keyboardNavigation) {
24255						this._toggle_multidate(focusDate);
24256						dateChanged = true;
24257					}
24258					this.focusDate = null;
24259					this.viewDate = this.dates.get(-1) || this.viewDate;
24260					this.setValue();
24261					this.fill();
24262					if (this.picker.is(':visible')){
24263						e.preventDefault();
24264						e.stopPropagation();
24265						if (this.o.autoclose)
24266							this.hide();
24267					}
24268					break;
24269				case 9: // tab
24270					this.focusDate = null;
24271					this.viewDate = this.dates.get(-1) || this.viewDate;
24272					this.fill();
24273					this.hide();
24274					break;
24275			}
24276			if (dateChanged){
24277				if (this.dates.length)
24278					this._trigger('changeDate');
24279				else
24280					this._trigger('clearDate');
24281				this.inputField.trigger('change');
24282			}
24283		},
24284
24285		setViewMode: function(viewMode){
24286			this.viewMode = viewMode;
24287			this.picker
24288				.children('div')
24289				.hide()
24290				.filter('.datepicker-' + DPGlobal.viewModes[this.viewMode].clsName)
24291					.show();
24292			this.updateNavArrows();
24293      this._trigger('changeViewMode', new Date(this.viewDate));
24294		}
24295	};
24296
24297	var DateRangePicker = function(element, options){
24298		$.data(element, 'datepicker', this);
24299		this.element = $(element);
24300		this.inputs = $.map(options.inputs, function(i){
24301			return i.jquery ? i[0] : i;
24302		});
24303		delete options.inputs;
24304
24305		this.keepEmptyValues = options.keepEmptyValues;
24306		delete options.keepEmptyValues;
24307
24308		datepickerPlugin.call($(this.inputs), options)
24309			.on('changeDate', $.proxy(this.dateUpdated, this));
24310
24311		this.pickers = $.map(this.inputs, function(i){
24312			return $.data(i, 'datepicker');
24313		});
24314		this.updateDates();
24315	};
24316	DateRangePicker.prototype = {
24317		updateDates: function(){
24318			this.dates = $.map(this.pickers, function(i){
24319				return i.getUTCDate();
24320			});
24321			this.updateRanges();
24322		},
24323		updateRanges: function(){
24324			var range = $.map(this.dates, function(d){
24325				return d.valueOf();
24326			});
24327			$.each(this.pickers, function(i, p){
24328				p.setRange(range);
24329			});
24330		},
24331		clearDates: function(){
24332			$.each(this.pickers, function(i, p){
24333				p.clearDates();
24334			});
24335		},
24336		dateUpdated: function(e){
24337			// `this.updating` is a workaround for preventing infinite recursion
24338			// between `changeDate` triggering and `setUTCDate` calling.  Until
24339			// there is a better mechanism.
24340			if (this.updating)
24341				return;
24342			this.updating = true;
24343
24344			var dp = $.data(e.target, 'datepicker');
24345
24346			if (dp === undefined) {
24347				return;
24348			}
24349
24350			var new_date = dp.getUTCDate(),
24351				keep_empty_values = this.keepEmptyValues,
24352				i = $.inArray(e.target, this.inputs),
24353				j = i - 1,
24354				k = i + 1,
24355				l = this.inputs.length;
24356			if (i === -1)
24357				return;
24358
24359			$.each(this.pickers, function(i, p){
24360				if (!p.getUTCDate() && (p === dp || !keep_empty_values))
24361					p.setUTCDate(new_date);
24362			});
24363
24364			if (new_date < this.dates[j]){
24365				// Date being moved earlier/left
24366				while (j >= 0 && new_date < this.dates[j]){
24367					this.pickers[j--].setUTCDate(new_date);
24368				}
24369			} else if (new_date > this.dates[k]){
24370				// Date being moved later/right
24371				while (k < l && new_date > this.dates[k]){
24372					this.pickers[k++].setUTCDate(new_date);
24373				}
24374			}
24375			this.updateDates();
24376
24377			delete this.updating;
24378		},
24379		destroy: function(){
24380			$.map(this.pickers, function(p){ p.destroy(); });
24381			$(this.inputs).off('changeDate', this.dateUpdated);
24382			delete this.element.data().datepicker;
24383		},
24384		remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead')
24385	};
24386
24387	function opts_from_el(el, prefix){
24388		// Derive options from element data-attrs
24389		var data = $(el).data(),
24390			out = {}, inkey,
24391			replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])');
24392		prefix = new RegExp('^' + prefix.toLowerCase());
24393		function re_lower(_,a){
24394			return a.toLowerCase();
24395		}
24396		for (var key in data)
24397			if (prefix.test(key)){
24398				inkey = key.replace(replace, re_lower);
24399				out[inkey] = data[key];
24400			}
24401		return out;
24402	}
24403
24404	function opts_from_locale(lang){
24405		// Derive options from locale plugins
24406		var out = {};
24407		// Check if "de-DE" style date is available, if not language should
24408		// fallback to 2 letter code eg "de"
24409		if (!dates[lang]){
24410			lang = lang.split('-')[0];
24411			if (!dates[lang])
24412				return;
24413		}
24414		var d = dates[lang];
24415		$.each(locale_opts, function(i,k){
24416			if (k in d)
24417				out[k] = d[k];
24418		});
24419		return out;
24420	}
24421
24422	var old = $.fn.datepicker;
24423	var datepickerPlugin = function(option){
24424		var args = Array.apply(null, arguments);
24425		args.shift();
24426		var internal_return;
24427		this.each(function(){
24428			var $this = $(this),
24429				data = $this.data('datepicker'),
24430				options = typeof option === 'object' && option;
24431			if (!data){
24432				var elopts = opts_from_el(this, 'date'),
24433					// Preliminary otions
24434					xopts = $.extend({}, defaults, elopts, options),
24435					locopts = opts_from_locale(xopts.language),
24436					// Options priority: js args, data-attrs, locales, defaults
24437					opts = $.extend({}, defaults, locopts, elopts, options);
24438				if ($this.hasClass('input-daterange') || opts.inputs){
24439					$.extend(opts, {
24440						inputs: opts.inputs || $this.find('input').toArray()
24441					});
24442					data = new DateRangePicker(this, opts);
24443				}
24444				else {
24445					data = new Datepicker(this, opts);
24446				}
24447				$this.data('datepicker', data);
24448			}
24449			if (typeof option === 'string' && typeof data[option] === 'function'){
24450				internal_return = data[option].apply(data, args);
24451			}
24452		});
24453
24454		if (
24455			internal_return === undefined ||
24456			internal_return instanceof Datepicker ||
24457			internal_return instanceof DateRangePicker
24458		)
24459			return this;
24460
24461		if (this.length > 1)
24462			throw new Error('Using only allowed for the collection of a single element (' + option + ' function)');
24463		else
24464			return internal_return;
24465	};
24466	$.fn.datepicker = datepickerPlugin;
24467
24468	var defaults = $.fn.datepicker.defaults = {
24469		assumeNearbyYear: false,
24470		autoclose: false,
24471		beforeShowDay: $.noop,
24472		beforeShowMonth: $.noop,
24473		beforeShowYear: $.noop,
24474		beforeShowDecade: $.noop,
24475		beforeShowCentury: $.noop,
24476		calendarWeeks: false,
24477		clearBtn: false,
24478		toggleActive: false,
24479		daysOfWeekDisabled: [],
24480		daysOfWeekHighlighted: [],
24481		datesDisabled: [],
24482		endDate: Infinity,
24483		forceParse: true,
24484		format: 'mm/dd/yyyy',
24485		keepEmptyValues: false,
24486		keyboardNavigation: true,
24487		language: 'en',
24488		minViewMode: 0,
24489		maxViewMode: 4,
24490		multidate: false,
24491		multidateSeparator: ',',
24492		orientation: "auto",
24493		rtl: false,
24494		startDate: -Infinity,
24495		startView: 0,
24496		todayBtn: false,
24497		todayHighlight: false,
24498		updateViewDate: true,
24499		weekStart: 0,
24500		disableTouchKeyboard: false,
24501		enableOnReadonly: true,
24502		showOnFocus: true,
24503		zIndexOffset: 10,
24504		container: 'body',
24505		immediateUpdates: false,
24506		title: '',
24507		templates: {
24508			leftArrow: '&#x00AB;',
24509			rightArrow: '&#x00BB;'
24510		},
24511    showWeekDays: true
24512	};
24513	var locale_opts = $.fn.datepicker.locale_opts = [
24514		'format',
24515		'rtl',
24516		'weekStart'
24517	];
24518	$.fn.datepicker.Constructor = Datepicker;
24519	var dates = $.fn.datepicker.dates = {
24520		en: {
24521			days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
24522			daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
24523			daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
24524			months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
24525			monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
24526			today: "Today",
24527			clear: "Clear",
24528			titleFormat: "MM yyyy"
24529		}
24530	};
24531
24532	var DPGlobal = {
24533		viewModes: [
24534			{
24535				names: ['days', 'month'],
24536				clsName: 'days',
24537				e: 'changeMonth'
24538			},
24539			{
24540				names: ['months', 'year'],
24541				clsName: 'months',
24542				e: 'changeYear',
24543				navStep: 1
24544			},
24545			{
24546				names: ['years', 'decade'],
24547				clsName: 'years',
24548				e: 'changeDecade',
24549				navStep: 10
24550			},
24551			{
24552				names: ['decades', 'century'],
24553				clsName: 'decades',
24554				e: 'changeCentury',
24555				navStep: 100
24556			},
24557			{
24558				names: ['centuries', 'millennium'],
24559				clsName: 'centuries',
24560				e: 'changeMillennium',
24561				navStep: 1000
24562			}
24563		],
24564		validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
24565		nonpunctuation: /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,
24566		parseFormat: function(format){
24567			if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function')
24568                return format;
24569            // IE treats \0 as a string end in inputs (truncating the value),
24570			// so it's a bad format delimiter, anyway
24571			var separators = format.replace(this.validParts, '\0').split('\0'),
24572				parts = format.match(this.validParts);
24573			if (!separators || !separators.length || !parts || parts.length === 0){
24574				throw new Error("Invalid date format.");
24575			}
24576			return {separators: separators, parts: parts};
24577		},
24578		parseDate: function(date, format, language, assumeNearby){
24579			if (!date)
24580				return undefined;
24581			if (date instanceof Date)
24582				return date;
24583			if (typeof format === 'string')
24584				format = DPGlobal.parseFormat(format);
24585			if (format.toValue)
24586				return format.toValue(date, format, language);
24587			var fn_map = {
24588					d: 'moveDay',
24589					m: 'moveMonth',
24590					w: 'moveWeek',
24591					y: 'moveYear'
24592				},
24593				dateAliases = {
24594					yesterday: '-1d',
24595					today: '+0d',
24596					tomorrow: '+1d'
24597				},
24598				parts, part, dir, i, fn;
24599			if (date in dateAliases){
24600				date = dateAliases[date];
24601			}
24602			if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(date)){
24603				parts = date.match(/([\-+]\d+)([dmwy])/gi);
24604				date = new Date();
24605				for (i=0; i < parts.length; i++){
24606					part = parts[i].match(/([\-+]\d+)([dmwy])/i);
24607					dir = Number(part[1]);
24608					fn = fn_map[part[2].toLowerCase()];
24609					date = Datepicker.prototype[fn](date, dir);
24610				}
24611				return Datepicker.prototype._zero_utc_time(date);
24612			}
24613
24614			parts = date && date.match(this.nonpunctuation) || [];
24615
24616			function applyNearbyYear(year, threshold){
24617				if (threshold === true)
24618					threshold = 10;
24619
24620				// if year is 2 digits or less, than the user most likely is trying to get a recent century
24621				if (year < 100){
24622					year += 2000;
24623					// if the new year is more than threshold years in advance, use last century
24624					if (year > ((new Date()).getFullYear()+threshold)){
24625						year -= 100;
24626					}
24627				}
24628
24629				return year;
24630			}
24631
24632			var parsed = {},
24633				setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
24634				setters_map = {
24635					yyyy: function(d,v){
24636						return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
24637					},
24638					m: function(d,v){
24639						if (isNaN(d))
24640							return d;
24641						v -= 1;
24642						while (v < 0) v += 12;
24643						v %= 12;
24644						d.setUTCMonth(v);
24645						while (d.getUTCMonth() !== v)
24646							d.setUTCDate(d.getUTCDate()-1);
24647						return d;
24648					},
24649					d: function(d,v){
24650						return d.setUTCDate(v);
24651					}
24652				},
24653				val, filtered;
24654			setters_map['yy'] = setters_map['yyyy'];
24655			setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
24656			setters_map['dd'] = setters_map['d'];
24657			date = UTCToday();
24658			var fparts = format.parts.slice();
24659			// Remove noop parts
24660			if (parts.length !== fparts.length){
24661				fparts = $(fparts).filter(function(i,p){
24662					return $.inArray(p, setters_order) !== -1;
24663				}).toArray();
24664			}
24665			// Process remainder
24666			function match_part(){
24667				var m = this.slice(0, parts[i].length),
24668					p = parts[i].slice(0, m.length);
24669				return m.toLowerCase() === p.toLowerCase();
24670			}
24671			if (parts.length === fparts.length){
24672				var cnt;
24673				for (i=0, cnt = fparts.length; i < cnt; i++){
24674					val = parseInt(parts[i], 10);
24675					part = fparts[i];
24676					if (isNaN(val)){
24677						switch (part){
24678							case 'MM':
24679								filtered = $(dates[language].months).filter(match_part);
24680								val = $.inArray(filtered[0], dates[language].months) + 1;
24681								break;
24682							case 'M':
24683								filtered = $(dates[language].monthsShort).filter(match_part);
24684								val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
24685								break;
24686						}
24687					}
24688					parsed[part] = val;
24689				}
24690				var _date, s;
24691				for (i=0; i < setters_order.length; i++){
24692					s = setters_order[i];
24693					if (s in parsed && !isNaN(parsed[s])){
24694						_date = new Date(date);
24695						setters_map[s](_date, parsed[s]);
24696						if (!isNaN(_date))
24697							date = _date;
24698					}
24699				}
24700			}
24701			return date;
24702		},
24703		formatDate: function(date, format, language){
24704			if (!date)
24705				return '';
24706			if (typeof format === 'string')
24707				format = DPGlobal.parseFormat(format);
24708			if (format.toDisplay)
24709                return format.toDisplay(date, format, language);
24710            var val = {
24711				d: date.getUTCDate(),
24712				D: dates[language].daysShort[date.getUTCDay()],
24713				DD: dates[language].days[date.getUTCDay()],
24714				m: date.getUTCMonth() + 1,
24715				M: dates[language].monthsShort[date.getUTCMonth()],
24716				MM: dates[language].months[date.getUTCMonth()],
24717				yy: date.getUTCFullYear().toString().substring(2),
24718				yyyy: date.getUTCFullYear()
24719			};
24720			val.dd = (val.d < 10 ? '0' : '') + val.d;
24721			val.mm = (val.m < 10 ? '0' : '') + val.m;
24722			date = [];
24723			var seps = $.extend([], format.separators);
24724			for (var i=0, cnt = format.parts.length; i <= cnt; i++){
24725				if (seps.length)
24726					date.push(seps.shift());
24727				date.push(val[format.parts[i]]);
24728			}
24729			return date.join('');
24730		},
24731		headTemplate: '<thead>'+
24732			              '<tr>'+
24733			                '<th colspan="7" class="datepicker-title"></th>'+
24734			              '</tr>'+
24735							'<tr>'+
24736								'<th class="prev">'+defaults.templates.leftArrow+'</th>'+
24737								'<th colspan="5" class="datepicker-switch"></th>'+
24738								'<th class="next">'+defaults.templates.rightArrow+'</th>'+
24739							'</tr>'+
24740						'</thead>',
24741		contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
24742		footTemplate: '<tfoot>'+
24743							'<tr>'+
24744								'<th colspan="7" class="today"></th>'+
24745							'</tr>'+
24746							'<tr>'+
24747								'<th colspan="7" class="clear"></th>'+
24748							'</tr>'+
24749						'</tfoot>'
24750	};
24751	DPGlobal.template = '<div class="datepicker">'+
24752							'<div class="datepicker-days">'+
24753								'<table class="table-condensed">'+
24754									DPGlobal.headTemplate+
24755									'<tbody></tbody>'+
24756									DPGlobal.footTemplate+
24757								'</table>'+
24758							'</div>'+
24759							'<div class="datepicker-months">'+
24760								'<table class="table-condensed">'+
24761									DPGlobal.headTemplate+
24762									DPGlobal.contTemplate+
24763									DPGlobal.footTemplate+
24764								'</table>'+
24765							'</div>'+
24766							'<div class="datepicker-years">'+
24767								'<table class="table-condensed">'+
24768									DPGlobal.headTemplate+
24769									DPGlobal.contTemplate+
24770									DPGlobal.footTemplate+
24771								'</table>'+
24772							'</div>'+
24773							'<div class="datepicker-decades">'+
24774								'<table class="table-condensed">'+
24775									DPGlobal.headTemplate+
24776									DPGlobal.contTemplate+
24777									DPGlobal.footTemplate+
24778								'</table>'+
24779							'</div>'+
24780							'<div class="datepicker-centuries">'+
24781								'<table class="table-condensed">'+
24782									DPGlobal.headTemplate+
24783									DPGlobal.contTemplate+
24784									DPGlobal.footTemplate+
24785								'</table>'+
24786							'</div>'+
24787						'</div>';
24788
24789	$.fn.datepicker.DPGlobal = DPGlobal;
24790
24791
24792	/* DATEPICKER NO CONFLICT
24793	* =================== */
24794
24795	$.fn.datepicker.noConflict = function(){
24796		$.fn.datepicker = old;
24797		return this;
24798	};
24799
24800	/* DATEPICKER VERSION
24801	 * =================== */
24802	$.fn.datepicker.version = '1.9.0';
24803
24804	$.fn.datepicker.deprecated = function(msg){
24805		var console = window.console;
24806		if (console && console.warn) {
24807			console.warn('DEPRECATED: ' + msg);
24808		}
24809	};
24810
24811
24812	/* DATEPICKER DATA-API
24813	* ================== */
24814
24815	$(document).on(
24816		'focus.datepicker.data-api click.datepicker.data-api',
24817		'[data-provide="datepicker"]',
24818		function(e){
24819			var $this = $(this);
24820			if ($this.data('datepicker'))
24821				return;
24822			e.preventDefault();
24823			// component click requires us to explicitly show it
24824			datepickerPlugin.call($this, 'show');
24825		}
24826	);
24827	$(function(){
24828		datepickerPlugin.call($('[data-provide="datepicker-inline"]'));
24829	});
24830
24831}));
24832!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); 
24833//��������������
24834// ����ƴ������ĸ�б� ���б������20902������,������� ToChineseSpell
24835//����ʹ��,������¼���ַ���Unicode���뷶ΧΪ19968��40869, XDesigner ����
24836var strChineseFirstPY = "YDYQSXMWZSSXJBYMGCCZQPSSQBYCDSCDQLDYLYBSSJGYZZJJFKCCLZDHWDWZJLJPFYYNWJJTMYHZWZHFLZPPQHGSCYYYNJQYXXGJHHSDSJNKKTMOMLCRXYPSNQSECCQZGGLLYJLMYZZSECYKYYHQWJSSGGYXYZYJWWKDJHYCHMYXJTLXJYQBYXZLDWRDJRWYSRLDZJPCBZJJBRCFTLECZSTZFXXZHTRQHYBDLYCZSSYMMRFMYQZPWWJJYFCRWFDFZQPYDDWYXKYJAWJFFXYPSFTZYHHYZYSWCJYXSCLCXXWZZXNBGNNXBXLZSZSBSGPYSYZDHMDZBQBZCWDZZYYTZHBTSYYBZGNTNXQYWQSKBPHHLXGYBFMJEBJHHGQTJCYSXSTKZHLYCKGLYSMZXYALMELDCCXGZYRJXSDLTYZCQKCNNJWHJTZZCQLJSTSTBNXBTYXCEQXGKWJYFLZQLYHYXSPSFXLMPBYSXXXYDJCZYLLLSJXFHJXPJBTFFYABYXBHZZBJYZLWLCZGGBTSSMDTJZXPTHYQTGLJSCQFZKJZJQNLZWLSLHDZBWJNCJZYZSQQYCQYR
24836ZCJJWYBRTWPYFTWEXCSKDZCTBZHYZZYYJXZCFFZZMJYXXSDZZOTTBZLQWFCKSZSXFYRLNYJMBDTHJXSQQCCSBXYYTSYFBXDZTGBCNSLCYZZPSAZYZZSCJCSHZQYDXLBPJLLMQXTYDZXSQJTZPXLCGLQTZWJBHCTSYJSFXYEJJTLBGXSXJMYJQQPFZASYJNTYDJXKJCDJSZCBARTDCLYJQMWNQNCLLLKBYBZZSYHQQLTWLCCXTXLLZNTYLNEWYZYXCZXXGRKRMTCNDNJTSYYSSDQDGHSDBJGHRWRQLYBGLXHLGTGXBQJDZPYJSJYJCTMRNYMGRZJCZGJMZMGXMPRYXKJNYMSGMZJYMKMFXMLDTGFBHCJHKYLPFMDXLQJJSMTQGZSJLQDLDGJYCALCMZCSDJLLNXDJFFFFJCZFMZFFPFKHKGDPSXKTACJDHHZDDCRRCFQYJKQCCWJDXHWJLYLLZGCFCQDSMLZPBJJPLSBCJGGDCKKDEZSQCCKJGCGKDJTJDLZYCXKLQSCGJCLTFPCQCZGWPJDQYZJJBYJHSJDZWGFSJGZKQCCZLLPSPKJGQJHZZLJPLGJGJJTHJJYJZCZMLZLYQBGJWMLJKXZDZNJQSYZMLJLLJKYWXMKJLHSKJGBMCLYYMKXJQLBMLLKMDXXKWYXYSLMLPSJQQJQXYXFJTJDXMXXLLCXQBSYJBGWYMBGGBCYXPJYGPEPFGDJGBHBNSQJYZJKJKHXQFGQZKFHYGKHDKLLSDJQXPQYKYBNQSXQNSZSWHBSXWHXWBZZXDMNSJBSBKBBZKLYLXGWXDRWYQZMYWSJQLCJXXJXKJEQXSCYETLZHLYYYSDZPAQYZCMTLSHTZCFYZYXYLJSDCJQAGYSLCQLYYYSHMRQQKLDXZSCSSSYDYCJYSFSJBFRSSZQSBXXPXJYSDRCKGJLGDKZJZBDKTCSYQPYHSTCLDJDHMXMCGXYZHJDDTMHLTXZXYLYMOHYJCLTYFBQQXPFBDFHHTKSQHZYYWCNXXCRWHOWGYJLEGWDQCWGFJYCSNTMYTOLBYGWQWESJPWNMLRYDZSZTXYQPZGCWXHNGPYXSHMYQJXZTDPPBFYHZHTJYFDZWKGKZBLDNTSXHQEEGZZYLZMMZYJZGXZXKHKSTXNXXWYLYAPSTHXDWHZYMPXAGKYDXBHNHXKDPJNMYHYLPMGOCSLNZHKXXLPZZLBMLSFBHHGYGYYGGBHSCYAQTYWLXTZQCEZYDQDQMMHTKLLSZHLSJZWFYHQSWSCWLQAZYNYTLSXTHAZNKZZSZZLAXXZWWCTGQQTDDYZTCCHYQZFLXPSLZYGPZSZNGLNDQTBDLXGTCTAJDKYWNSYZLJHHZZCWNYYZYWMHYCHHYXHJKZWSXHZYXLYSKQYSPSLYZWMYPPKBYGLKZHTYXAXQSYSHXASMCHKDSCRSWJPWXSGZJLWWSCHSJHSQNHCSEGNDAQTBAALZZMSSTDQJCJKTSCJAXPLGGXHHGXXZCXPDMMHLDGTYBYSJMXHMRCPXXJZCKZXSHMLQXXTTHXWZFKHCCZDYTCJYXQHLXDHYPJQXYLSYYDZOZJNYXQEZYSQYAYXWYPDGXDDXSPPYZNDLTWRHXYDXZZJHTCXMCZLHPYYYYMHZLLHNXMYLLLMDCPPXHMXDKYCYRDLTXJCHHZZXZLCCLYLNZSHZJZZLNNRLWHYQSNJHXYNTTTKYJPYCHHYEGKCTTWLGQRLGGTGTYGYHPYHYLQYQGCWYQKPYYYTTTTLHYHLLTYTTSPLKYZXGZWGPYDSSZZDQXSKCQNMJJZZBXYQMJRTFFBTKHZKBXLJJKDXJTLBWFZPPTKQTZTGPDGNTPJYFALQMKGXBDCLZFHZCLLLLADPMXDJHLCCLGYHDZFGYDDGCYYFGYDXKSSEBDHYKDKDKHNAXXYBPBYYHXZQGAFFQYJXDMLJCSQZLLPCHBSXGJYNDYBYQSPZWJLZKSDDTACTBXZDYZYPJZQSJNKKTKNJDJGYYPGTLFYQKASDNTCYHBLWDZHBBYDWJRYGKZYHEYYFJMSDTYFZJJHGCXPLXHLDWXXJKYTCYKSSSMTWCTTQZLPBSZDZWZXGZAGYKTYWXLHLSPBCLLOQMMZSSLCMBJCSZZKYDCZJGQQDSMCYTZQQLWZQZXSSFPTTFQMDDZDSHDTDWFHTDYZJYQJQKYPBDJYYXTLJHDRQXXXHAYDHRJLKLYTWHLLRLLRCXYLBWSRSZZSYMKZZHHKYHXKSMDSYDYCJPBZBSQLFCXXXNXKXWYWSDZYQOGGQMMYHCDZTTFJYYBGSTTTYBYKJDHKYXBELHTYPJQNFXFDYKZHQKZBYJTZBXHFDXKDASWTAWAJLDYJSFHBLDNNTNQJTJNCHXFJSRFWHZFMDRYJYJWZPDJKZYJYMPCYZNYNXFBYTFYFWYGDBNZZZDNYTXZEMMQBSQEHXFZMBMFLZZSRXYMJGSXWZJSPRYDJSJGXHJJGLJJYNZZJXHGXKYMLPYYYCXYTWQZSWHWLYRJLPXSLSXMFSWWKLCTNXNYNPSJSZHDZEPTXMYYWXYYSYWLXJQZQXZDCLEEELMCPJPCLWBXSQHFWWTFFJTNQJHJQDXHWLBYZNFJLALKYYJLDXHHYCSTYYWNRJYXYWTRMDRQHWQCMFJDYZMHMYYXJWMYZQZXTLMRSPWWCHAQBXYGZYPXYYRRCLMPYMGKSJSZYSRMYJSNXTPLNBAPPYPYLXYYZKYNLDZYJZCZNNLMZHHARQMPGWQTZMXXMLLHGDZXYHXKYXYCJMFFYYHJFSBSSQLXXNDYCANNMTCJCYPRRNYTYQNYYMBMSXNDLYLYSLJRLXYSXQMLLYZLZJJJKYZZCSFBZXXMSTBJGNXYZHLXNMCWSCYZYFZLXBRNNNYLBNRTGZQYSATSWRYHYJZMZDHZGZDWYBSSCSKXSYHYTXXGCQGXZZSHYXJSCRHMKKBXCZJYJYMKQHZJFNBHMQHYSNJNZYBKNQMCLGQHWLZNZSWXKHLJHYYBQLBFCDSXDLDSPFZPSKJYZWZXZDDXJSMMEGJSCSSMGCLXXKYYYLNYPWWWGYDKZJGGGZGGSYCKNJWNJPCXBJJTQTJWDSSPJXZXNZXUMELPXFSXTLLXCLJXJJLJZXCTPSWXLYDHLYQRWHSYCSQYYBYAYWJJJQFWQCQQCJQGXALDBZZYJGKGXPLTZYFXJLTPADKYQHPMATLCPDCKBMTXYBHKLENXDLEEGQDYMSAWHZMLJTWYGXLYQZLJEEYYBQQFFNLYXRDSCTGJGXYYNKLLYQKCCTLHJLQMKKZGCYYGLLLJDZGYDHZWXPYSJBZKDZGYZZHYWYFQYTYZSZYEZZLYMHJJHTSMQWYZLKYYWZCSRKQYTLTDXWCTYJKLWSQZWBDCQYNCJSRSZJLKCDCDTLZZZACQQZZDDXYPLXZBQJYLZLLLQDDZQJYJYJZYXNYYYNYJXKXDAZWYRDLJYYYRJLXLLDYXJCYWYWNQCCLDDNYYYNYCKCZHXXCCLGZQJGKWPPCQQJYSBZZXYJSQPXJPZBSBDSFNSFPZXHDWZTDWPPTFLZZBZDMYYPQJRSDZSQZSQXBDGCPZSWDWCSQZGMDHZXMWWFYBPDGPHTMJTHZSMMBGZMBZJCFZWFZBBZMQCFMBDMCJXLGPNJBBXGYHYYJGPTZGZMQBQTCGYXJXLWZKYDPDYMGCFTPFXYZTZXDZXTGKMTYBBCLBJASKYTSSQYYMSZXFJEWLXLLSZBQJJJAKLYLXLYCCTSXMCWFKKKBSXLLLLJYXTYLTJYYTDPJHNHNNKBYQNFQYYZBYYESSESSGDYHFHWTCJBSDZZTFDMXHCNJZYMQWSRYJDZJQPDQBBSTJGGFBKJBXTGQHNGWJXJGDLLTHZHHYYYYYYSXWTYYYCCBDBPYPZYCCZYJPZYWCBDLFWZCWJDXXHYHLHWZZXJTCZLCDPXUJCZZZLYXJJTXPHFXWPYWXZPTDZZBDZCYHJHMLXBQXSBYLRDTGJRRCTTTHYTCZWMXFYTWWZCWJWXJYWCSKYBZSCCTZQNHXNWXXKHKFHTSWOCCJYBCMPZZYKBNNZPBZHHZDLSYDDYTYFJPXYNGFXBYQXCBHXCPSXTYZDMKYSNXSXLHKMZXLYHDHKWHXXSSKQYHHCJYXGLHZXCSNHEKDTGZXQYPKDHEXTYKCNYMYYYPKQYYYKXZLTHJQTBYQHXBMYHSQCKWWYLLHCYYLNNEQXQWMCFBDCCMLJGGXDQKTLXKGNQCDGZJWYJJLYHHQTTTNWCHMXCXWHWSZJYDJCCDBQCDGDNYXZTHCQRXCBHZTQCBXWGQWYYBXHMBYMYQTYEXMQKYAQYRGYZSLFYKKQHYSSQYSHJGJCNXKZYCXSBXYXHYYLSTYCXQTHYSMGSCPMMGCCCCCMTZTASMGQZJHKLOSQYLSWTMXSYQKDZLJQQYPLSYCZTCQQPBBQJZCLPKHQZYYXXDTDDTSJCXFFLLCHQXMJLWCJCXTSPYCXNDTJSHJWXDQQJSKXYAMYLSJHMLALYKXCYYDMNMDQMXMCZNNCYB
24836ZKKYFLMCHCMLHXRCJJHSYLNMTJZGZGYWJXSRXCWJGJQHQZDQJDCJJZKJKGDZQGJJYJYLXZXXCDQHHHEYTMHLFSBDJSYYSHFYSTCZQLPBDRFRZTZYKYWHSZYQKWDQZRKMSYNBCRXQBJYFAZPZZEDZCJYWBCJWHYJBQSZYWRYSZPTDKZPFPBNZTKLQYHBBZPNPPTYZZYBQNYDCPJMMCYCQMCYFZZDCMNLFPBPLNGQJTBTTNJZPZBBZNJKLJQYLNBZQHKSJZNGGQSZZKYXSHPZSNBCGZKDDZQANZHJKDRTLZLSWJLJZLYWTJNDJZJHXYAYNCBGTZCSSQMNJPJYTYSWXZFKWJQTKHTZPLBHSNJZSYZBWZZZZLSYLSBJHDWWQPSLMMFBJDWAQYZTCJTBNNWZXQXCDSLQGDSDPDZHJTQQPSWLYYJZLGYXYZLCTCBJTKTYCZJTQKBSJLGMGZDMCSGPYNJZYQYYKNXRPWSZXMTNCSZZYXYBYHYZAXYWQCJTLLCKJJTJHGDXDXYQYZZBYWDLWQCGLZGJGQRQZCZSSBCRPCSKYDZNXJSQGXSSJMYDNSTZTPBDLTKZWXQWQTZEXNQCZGWEZKSSBYBRTSSSLCCGBPSZQSZLCCGLLLZXHZQTHCZMQGYZQZNMCOCSZJMMZSQPJYGQLJYJPPLDXRGZYXCCSXHSHGTZNLZWZKJCXTCFCJXLBMQBCZZWPQDNHXLJCTHYZLGYLNLSZZPCXDSCQQHJQKSXZPBAJYEMSMJTZDXLCJYRYYNWJBNGZZTMJXLTBSLYRZPYLSSCNXPHLLHYLLQQZQLXYMRSYCXZLMMCZLTZSDWTJJLLNZGGQXPFSKYGYGHBFZPDKMWGHCXMSGDXJMCJZDYCABXJDLNBCDQYGSKYDQTXDJJYXMSZQAZDZFSLQXYJSJZYLBTXXWXQQZBJZUFBBLYLWDSLJHXJYZJWTDJCZFQZQZZDZSXZZQLZCDZFJHYSPYMPQZMLPPLFFXJJNZZYLSJEYQZFPFZKSYWJJJHRDJZZXTXXGLGHYDXCSKYSWMMZCWYBAZBJKSHFHJCXMHFQHYXXYZFTSJYZFXYXPZLCHMZMBXHZZSXYFYMNCWDABAZLXKTCSHHXKXJJZJSTHYGXSXYYHHHJWXKZXSSBZZWHHHCWTZZZPJXSNXQQJGZYZYWLLCWXZFXXYXYHXMKYYSWSQMNLNAYCYSPMJKHWCQHYLAJJMZXHMMCNZHBHXCLXTJPLTXYJHDYYLTTXFSZHYXXSJBJYAYRSMXYPLCKDUYHLXRLNLLSTYZYYQYGYHHSCCSMZCTZQXKYQFPYYRPFFLKQUNTSZLLZMWWTCQQYZWTLLMLMPWMBZSSTZRBPDDTLQJJBXZCSRZQQYGWCSXFWZLXCCRSZDZMCYGGDZQSGTJSWLJMYMMZYHFBJDGYXCCPSHXNZCSBSJYJGJMPPWAFFYFNXHYZXZYLREMZGZCYZSSZDLLJCSQFNXZKPTXZGXJJGFMYYYSNBTYLBNLHPFZDCYFBMGQRRSSSZXYSGTZRNYDZZCDGPJAFJFZKNZBLCZSZPSGCYCJSZLMLRSZBZZLDLSLLYSXSQZQLYXZLSKKBRXBRBZCYCXZZZEEYFGKLZLYYHGZSGZLFJHGTGWKRAAJYZKZQTSSHJJXDCYZUYJLZYRZDQQHGJZXSSZBYKJPBFRTJXLLFQWJHYLQTYMBLPZDXTZYGBDHZZRBGXHWNJTJXLKSCFSMWLSDQYSJTXKZSCFWJLBXFTZLLJZLLQBLSQMQQCGCZFPBPHZCZJLPYYGGDTGWDCFCZQYYYQYSSCLXZSKLZZZGFFCQNWGLHQYZJJCZLQZZYJPJZZBPDCCMHJGXDQDGDLZQMFGPSYTSDYFWWDJZJYSXYYCZCYHZWPBYKXRYLYBHKJKSFXTZJMMCKHLLTNYYMSYXYZPYJQYCSYCWMTJJKQYRHLLQXPSGTLYYCLJSCPXJYZFNMLRGJJTYZBXYZMSJYJHHFZQMSYXRSZCWTLRTQZSSTKXGQKGSPTGCZNJSJCQCXHMXGGZTQYDJKZDLBZSXJLHYQGGGTHQSZPYHJHHGYYGKGGCWJZZYLCZLXQSFTGZSLLLMLJSKCTBLLZZSZMMNYTPZSXQHJCJYQXYZXZQZCPSHKZZYSXCDFGMWQRLLQXRFZTLYSTCTMJCXJJXHJNXTNRZTZFQYHQGLLGCXSZSJDJLJCYDSJTLNYXHSZXCGJZYQPYLFHDJSBPCCZHJJJQZJQDYBSSLLCMYTTMQTBHJQNNYGKYRQYQMZGCJKPDCGMYZHQLLSLLCLMHOLZGDYYFZSLJCQZLYLZQJESHNYLLJXGJXLYSYYYXNBZLJSSZCQQCJYLLZLTJYLLZLLBNYLGQCHXYYXOXCXQKYJXXXYKLXSXXYQXCYKQXQCSGYXXYQXYGYTQOHXHXPYXXXULCYEYCHZZCBWQBBWJQZSCSZSSLZYLKDESJZWMYMCYTSDSXXSCJPQQSQYLYYZYCMDJDZYWCBTJSYDJKCYDDJLBDJJSODZYSYXQQYXDHHGQQYQHDYXWGMMMAJDYBBBPPBCMUUPLJZSMTXERXJMHQNUTPJDCBSSMSSSTKJTSSMMTRCPLZSZMLQDSDMJMQPNQDXCFYNBFSDQXYXHYAYKQYDDLQYYYSSZBYDSLNTFQTZQPZMCHDHCZCWFDXTMYQSPHQYYXSRGJCWTJTZZQMGWJJTJHTQJBBHWZPXXHYQFXXQYWYYHYSCDYDHHQMNMTMWCPBSZPPZZGLMZFOLLCFWHMMSJZTTDHZZYFFYTZZGZYSKYJXQYJZQBHMBZZLYGHGFMSHPZFZSNCLPBQSNJXZSLXXFPMTYJYGBXLLDLXPZJYZJYHHZCYWHJYLSJEXFSZZYWXKZJLUYDTMLYMQJPWXYHXSKTQJEZRPXXZHHMHWQPWQLYJJQJJZSZCPHJLCHHNXJLQWZJHBMZYXBDHHYPZLHLHLGFWLCHYYTLHJXCJMSCPXSTKPNHQXSRTYXXTESYJCTLSSLSTDLLLWWYHDHRJZSFGXTSYCZYNYHTDHWJSLHTZDQDJZXX
24836QHGYLTZPHCSQFCLNJTCLZPFSTPDYNYLGMJLLYCQHYSSHCHYLHQYQTMZYPBYWRFQYKQSYSLZDQJMPXYYSSRHZJNYWTQDFZBWWTWWRXCWHGYHXMKMYYYQMSMZHNGCEPMLQQMTCWCTMMPXJPJJHFXYYZSXZHTYBMSTSYJTTQQQYYLHYNPYQZLCYZHZWSMYLKFJXLWGXYPJYTYSYXYMZCKTTWLKSMZSYLMPWLZWXWQZSSAQSYXYRHSSNTSRAPXCPWCMGDXHXZDZYFJHGZTTSBJHGYZSZYSMYCLLLXBTYXHBBZJKSSDMALXHYCFYGMQYPJYCQXJLLLJGSLZGQLYCJCCZOTYXMTMTTLLWTGPXYMZMKLPSZZZXHKQYSXCTYJZYHXSHYXZKXLZWPSQPYHJWPJPWXQQYLXSDHMRSLZZYZWTTCYXYSZZSHBSCCSTPLWSSCJCHNLCGCHSSPHYLHFHHXJSXYLLNYLSZDHZXYLSXLWZYKCLDYAXZCMDDYSPJTQJZLNWQPSSSWCTSTSZLBLNXSMNYYMJQBQHRZWTYYDCHQLXKPZWBGQYBKFCMZWPZLLYYLSZYDWHXPSBCMLJBSCGBHXLQHYRLJXYSWXWXZSLDFHLSLYNJLZYFLYJYCDRJLFSYZFSLLCQYQFGJYHYXZLYLMSTDJCYHBZLLNWLXXYGYYHSMGDHXXHHLZZJZXCZZZCYQZFNGWPYLCPKPYYPMCLQKDGXZGGWQBDXZZKZFBXXLZXJTPJPTTBYTSZZDWSLCHZHSLTYXHQLHYXXXYYZYSWTXZKHLXZXZPYHGCHKCFSYHUTJRLXFJXPTZTWHPLYXFCRHXSHXKYXXYHZQDXQWULHYHMJTBFLKHTXCWHJFWJCFPQRYQXCYYYQYGRPYWSGSUNGWCHKZDXYFLXXHJJBYZWTSXXNCYJJYMSWZJQRMHXZWFQSYLZJZGBHYNSLBGTTCSYBYXXWXYHXYYXNSQYXMQYWRGYQLXBBZLJSYLPSYTJZYHYZAWLRORJMKSCZJXXXYXCHDYXRYXXJDTSQFXLYLTSFFYXLMTYJMJUYYYXLTZCSXQZQHZXLYYXZHDNBRXXXJCTYHLBRLMBRLLAXKYLLLJLYXXLYCRYLCJTGJCMTLZLLCYZZPZPCYAWHJJFYBDYYZSMPCKZDQYQPBPCJPDCYZMDPBCYYDYCNNPLMTMLRMFMMGWYZBSJGYGSMZQQQZTXMKQWGXLLPJGZBQCDJJJFPKJKCXBLJMSWMDTQJXLDLPPBXCWRCQFBFQJCZAHZGMYKPHYYHZYKNDKZMBPJYXPXYHLFPNYYGXJDBKXNXHJMZJXSTRSTLDXSKZYSYBZXJLXYSLBZYSLHXJPFXPQNBYLLJQKYGZMCYZZYMCCSLCLHZFWFWYXZMWSXTYNXJHPYYMCYSPMHYSMYDYSHQYZCHMJJMZCAAGCFJBBHPLYZYLXXSDJGXDHKXXTXXNBHRMLYJSLTXMRHNLXQJXYZLLYSWQGDLBJHDCGJYQYCMHWFMJYBMBYJYJWYMDPWHXQLDYGPDFXXBCGJSPCKRSSYZJMSLBZZJFLJJJLGXZGYXYXLSZQYXBEXYXHGCXBPLDYHWETTWWCJMBTXCHXYQXLLXFLYXLLJLSSFWDPZSMYJCLMWYTCZPCHQEKCQBWLCQYDPLQPPQZQFJQDJHYMMCXTXDRMJWRHXCJZYLQXDYYNHYYHRSLSRSYWWZJYMTLTLLGTQCJZYABTCKZCJYCCQLJZQXALMZYHYWLWDXZXQDLLQSHGPJFJLJHJABCQZDJGTKHSSTCYJLPSWZLXZXRWGLDLZRLZXTGSLLLLZLYXXWGDZYGBDPHZPBRLWSXQBPFDWOFMWHLYPCBJCCLDMBZPBZZLCYQXLDOMZBLZWPDWYYGDSTTHCSQSCCRSSSYSLFYBFNTYJSZDFNDPDHDZZMBBLSLCMYFFGTJJQWFTMTPJWFNLBZCMMJTGBDZLQLPYFHYYMJYLSDCHDZJWJCCTLJCLDTLJJCPDDSQDSSZYBNDBJLGGJZXSXNLYCYBJXQYCBYLZCFZPPGKCXZDZFZTJJFJSJXZBNZYJQTTYJYHTYCZHYMDJXTTMPXSPLZCDWSLSHXYPZGTFMLCJTYCBPMGDKWYCYZCDSZZYHFLYCTYGWHKJYYLSJCXGYWJCBLLCSNDDBTZBSCLYZCZZSSQDLLMQYYHFSLQLLXFTYHABXGWNYWYYPLLSDLDLLBJCYXJZMLHLJDXYYQYTDLLLBUGBFDFBBQJZZMDPJHGCLGMJJPGAEHHBWCQXAXHHHZCHXYPHJAXHLPHJPGPZJQCQZGJJZZUZDMQYYBZZPHYHYBWHAZYJHYKFGDPFQSDLZMLJXKXGALXZDAGLMDGXMWZQYXXDXXPFDMMSSYMPFMDMMKXKSYZYSHDZKXSYSMMZZZMSYDNZZCZXFPLSTMZDNMXCKJMZTYYMZMZZMSXHHDCZJEMXXKLJSTLWLSQLYJZLLZJSSDPPMHNLZJCZYHMXXHGZCJMDHXTKGRMXFWMCGMWKDTKSXQMMMFZZYDKMSCLCMPCGMHSPXQPZDSSLCXKYXTWLWJYAHZJGZQMCSNXYYMMPMLKJXMHLMLQMXCTKZMJQYSZJSYSZHSYJZJCDAJZYBSDQJZGWZQQXFKDMSDJLFWEHKZQKJPEYPZYSZCDWYJFFMZZYLTTDZZEFMZLBNPPLPLPEPSZALLTYLKCKQZKGENQLWAGYXYDPXLHSXQQWQCQXQCLHYXXMLYCCWLYMQYSKGCHLCJNSZKPYZKCQZQLJPDMDZHLASXLBYDWQLWDNBQCRYDDZTJYBKBWSZDXDTNPJDTCTQDFXQQMGNXECLTTBKPWSLCTYQLPWYZZKLPYGZCQQPLLKCCYLPQMZCZQCLJSLQZDJXLDDHPZQDLJJXZQDXYZQKZLJCYQDYJPPYPQYKJYRMPCBYMCXKLLZLLFQPYLLLMBSGLCYSSLRSYSQTMXYXZQZFDZUYSYZTFFMZZSMZQHZSSCCMLYXWTPZGXZJGZGSJSGKDDHTQGGZLLBJDZLCBCHYXYZHZFYWXYZYMSDBZZYJGTSMTFXQYXQSTDGSLNXDLRYZZLRYYLXQHTXSRTZNGZXBNQQZFMYKMZJBZYMKBPNLYZPBLMCNQYZZZSJZHJCTZKHYZZJRDYZHNPXGLFZTLKGJTCTSSYLLGZRZBBQZZKLPKLCZYSSUYXBJFPNJZZXCDWXZYJXZZDJJKGGRSRJKMSMZJLSJYWQSKYHQJSXPJZZZLSNSHRNYPZTWCHKLPSRZLZXYJQXQKYSJYCZTLQZYBBYBWZPQDWWYZCYTJCJXCKCWDKKZXSGKDZXWWYYJQYYTCYTDLLXWKCZKKLCCLZCQQDZLQLCSFQCHQHSFSMQZZLNBJJZBSJHTSZDYSJQJPDLZCDCWJKJZZLPYCGMZWDJJBSJQZSYZYHHXJPBJYDSSXDZNCGLQMBTSFSBPDZDLZNFGFJGFSMPXJQLMBLGQCYYXBQKDJJQYRFKZTJDHCZKLBSDZCFJTPLLJGXHYXZCSSZZXSTJYGKGCKGYOQXJPLZPBPGTGYJZGHZQZZLBJLSQFZGKQQJZGYCZBZQTLDXRJXBSXXPZXHYZYCLWDXJJHXMFDZPFZHQHQMQGKSLYHTYCGFRZGNQXCLPDLBZCSCZQLLJBLHBZCYPZZPPDYMZZSGYHCKCPZJGSLJLNSCDSLDLXBMSTLDDFJMKDJDHZLZXLSZQPQPGJLLYBDSZGQLBZLSLKYYHZTTNTJYQTZZPSZQZTLLJTYYLLQLLQYZQLBDZLSLYYZYMDFSZSNHLXZNCZQZPBWSKRFBSYZMTHBLGJPMCZZLSTLXSHTCSYZLZBLFEQHLXFLCJLYLJQCBZLZJHHSSTBRMHXZHJZCLXFNBGXGTQJCZTMSFZKJMSSNXLJKBHSJXNTNLZDNTLMSJXGZJYJCZXYJYJWRWWQNZTNFJSZPZSHZJFYRDJSFSZJZBJFZQZZHZLXFYSBZQLZSGYFTZDCSZXZJBQMSZKJRHYJZCKMJKHCHGTXKXQGLXPXFXTRTYLXJXHDTSJXHJZJXZWZLCQSBTXWXGXTXXHXFTSDKFJHZYJFJXRZSDLLLTQSQQZQWZXSYQTWGWBZCGZLLYZBCLMQQTZHZXZXLJFRMYZFLXYSQXXJKXRMQDZDMMYYBSQBHGZMWFWXGMXLZPYYTGZYCCDXYZXYWGSYJYZNBHPZJSQSYXSXRTFYZGRHZTXSZZTHCBFCLSYXZLZQ
24836MZLMPLMXZJXSFLBYZMYQHXJSXRXSQZZZSSLYFRCZJRCRXHHZXQYDYHXSJJHZCXZBTYNSYSXJBQLPXZQPYMLXZKYXLXCJLCYSXXZZLXDLLLJJYHZXGYJWKJRWYHCPSGNRZLFZWFZZNSXGXFLZSXZZZBFCSYJDBRJKRDHHGXJLJJTGXJXXSTJTJXLYXQFCSGSWMSBCTLQZZWLZZKXJMLTMJYHSDDBXGZHDLBMYJFRZFSGCLYJBPMLYSMSXLSZJQQHJZFXGFQFQBPXZGYYQXGZTCQWYLTLGWSGWHRLFSFGZJMGMGBGTJFSYZZGZYZAFLSSPMLPFLCWBJZCLJJMZLPJJLYMQDMYYYFBGYGYZMLYZDXQYXRQQQHSYYYQXYLJTYXFSFSLLGNQCYHYCWFHCCCFXPYLYPLLZYXXXXXKQHHXSHJZCFZSCZJXCPZWHHHHHAPYLQALPQAFYHXDYLUKMZQGGGDDESRNNZLTZGCHYPPYSQJJHCLLJTOLNJPZLJLHYMHEYDYDSQYCDDHGZUNDZCLZYZLLZNTNYZGSLHSLPJJBDGWXPCDUTJCKLKCLWKLLCASSTKZZDNQNTTLYYZSSYSSZZRYLJQKCQDHHCRXRZYDGRGCWCGZQFFFPPJFZYNAKRGYWYQPQXXFKJTSZZXSWZDDFBBXTBGTZKZNPZZPZXZPJSZBMQHKCYXYLDKLJNYPKYGHGDZJXXEAHPNZKZTZCMXCXMMJXNKSZQNMNLWBWWXJKYHCPSTMCSQTZJYXTPCTPDTNNPGLLLZSJLSPBLPLQHDTNJNLYYRSZFFJFQWDPHZDWMRZCCLODAXNSSNYZRESTYJWJYJDBCFXNMWTTBYLWSTSZGYBLJPXGLBOCLHPCBJLTMXZLJYLZXCLTPNCLCKXTPZJSWCYXSFYSZDKNTLBYJCYJLLSTGQCBXRYZXBXKLYLHZLQZLNZCXWJZLJZJNCJHXMNZZGJZZXTZJXYCYYCXXJYYXJJXSSSJSTSSTTPPGQTCSXWZDCSYFPTFBFHFBBLZJCLZZDBXGCXLQPXKFZFLSYLTUWBMQJHSZBMDDBCYSCCLDXYCDDQLYJJWMQLLCSGLJJSYFPYYCCYLTJANTJJPWYCMMGQYYSXDXQMZHSZXPFTWWZQSWQRFKJLZJQQYFBRXJHHFWJJZYQAZMYFRHCYYBYQWLPEXCCZSTYRLTTDMQLYKMBBGMYYJPRKZNPBSXYXBHYZDJDNGHPMFSGMWFZMFQMMBCMZZCJJLCNUXYQLMLRYGQZCYXZLWJGCJCGGMCJNFYZZJHYCPRRCMTZQZXHFQGTJXCCJEAQCRJYHPLQLSZDJRBCQHQDYRHYLYXJSYMHZYDWLDFRYHBPYDTSSCNWBXGLPZMLZZTQSSCPJMXXYCSJYTYCGHYCJWYRXXLFEMWJNMKLLSWTXHYYYNCMMCWJDQDJZGLLJWJRKHPZGGFLCCSCZMCBLTBHBQJXQDSPDJZZGKGLFQYWBZYZJLTSTDHQHCTCBCHFLQMPWDSHYYTQWCNZZJTLBYMBPDYYYXSQKXWYYFLXXNCWCXYPMAELYKKJMZZZBRXYYQJFLJPFHHHYTZZXSGQQMHSPGDZQWBWPJHZJDYSCQWZKTXXSQLZYYMYSDZGRXCKKUJLWPYSYSCSYZLRMLQSYLJXBCXTLWDQZPCYCYKPPPNSXFYZJJRCEMHSZMSXLXGLRWGCSTLRSXBZGBZGZTCPLUJLSLYLYMTXMTZPALZXPXJTJWTCYYZLBLXBZLQMYLXPGHDSLSSDMXMBDZZSXWHAMLCZCPJMCNHJYSNSYGCHSKQMZZQDLLKABLWJXSFMOCDXJRRLYQZKJMYBYQLYHETFJZFRFKSRYXFJTWDSXXSYSQJYSLYXWJHSNLXYYXHBHAWHHJZXWMYLJCSSLKYDZTXBZSYFDXGXZJKHSXXYBSSXDPYNZWRPTQZCZENYGCXQFJYKJBZMLJCMQQXUOXSLYXXLYLLJDZBTYMHPFSTTQQWLHOKYBLZZALZXQLHZWRRQHLSTMYPYXJJXMQSJFNBXYXYJXXYQYLTHYLQYFMLKLJTMLLHSZWKZHLJMLHLJKLJSTLQXYLMBHHLNLZXQJHXCFXXLHYHJJGBYZZKBXSCQDJQDSUJZYYHZHHMGSXCSYMXFEBCQWWRBPYYJQTYZCYQYQQZYHMWFFHGZFRJFCDPXNTQYZPDYKHJLFRZXPPXZDBBGZQSTLGDGYLCQMLCHHMFYWLZYXKJLYPQHSYWMQQGQZMLZJNSQXJQSYJYCBEHSXFSZPXZWFLLBCYYJDYTDTHWZSFJMQQYJLMQXXLLDTTKHHYBFPWTYYSQQWNQWLGWDEBZWCMYGCULKJXTMXMYJSXHYBRWFYMWFRXYQMXYSZTZZTFYKMLDHQDXWYYNLCRYJBLPSXCXYWLSPRRJWXHQYPHTYDNXHHMMYWYTZCSQMTSSCCDALWZTCPQPYJLLQZYJSWXMZZMMYLMXCLMXCZMXMZSQTZPPQQBLPGXQZHFLJJHYTJSRXWZXSCCDLXTYJDCQJXSLQYCLZXLZZXMXQRJMHRHZJBHMFLJLMLCLQNLDXZLLLPYPSYJYSXCQQDCMQJZZXHNPNXZMEKMXHYKYQLXSXTXJYYHWDCWDZHQYYBGYBCYSCFGPSJNZDYZZJZXRZRQJJYMCANYRJTLDPPYZBSTJKXXZYPFDWFGZZRPYMTNGXZQBYXNBUFNQKRJQZMJEGRZGYCLKXZDSKKNSXKCLJSPJYYZLQQJYBZSSQLLLKJXTBKTYLCCDDBLSPPFYLGYDTZJYQGGKQTTFZXBDKTYYHYBBFYTYYBCLPDYTGDHRYRNJSPTCSNYJQHKLLLZSLYDXXWBCJQSPXBPJZJCJDZFFXXBRMLAZHCSNDLBJDSZBLPRZTSWSBXBCLLXXLZDJZSJPYLYXXYFTFFFBHJJXGBYXJPMMMPSSJZJMTLYZJXSWXTYLEDQPJMYGQZJGDJLQJWJQLLSJGJGYGMSCLJJXDTYGJQJQJCJZCJGDZZSXQGSJGGCXHQXSNQLZZBXHSGZXCXYLJXYXYYDFQQJHJFXDHCTXJYRXYSQTJXYEFYYSSYYJXNCYZXFXMSYSZXYYSCHSHXZZZGZZZGFJDLTYLNPZGYJYZYYQZPBXQBDZTZCZYXXYHHSQXSHDHGQHJHGYWSZTMZMLHYXGEBTYLZKQWYTJZRCLEKYSTDBCYKQQSAYXCJXWWGSBHJYZYDHCSJKQCXSWXFLTYNYZPZCCZJQTZWJQDZZZQZLJJXLSBHPYXXPSXSHHEZTXFPTLQYZZXHYTXNCFZYYHXGNXMYWXTZSJPTHHGYMXMXQZXTSBCZYJYXXTYYZYPCQLMMSZMJZZLLZXGXZAAJZYXJMZXWDXZSXZDZXLEYJJZQBHZWZZZQTZPSXZTDSXJJJZNYAZPHXYYSRNQDTHZHYYKYJHDZXZLSWCLYBZYECWCYCRYLCXNHZYDZYDYJDFRJJHTRSQTXYXJRJHOJYNXELXSFSFJZGHPZSXZSZDZCQZBYYKLSGSJHCZSHDGQGXYZGXCHXZJWYQWGYHKSSEQZZNDZFKWYSSTCLZSTSYMCDHJXXYWEYXCZAYDMPXMDSXYBSQMJMZJMTZQLPJYQZCGQHXJHHLXXHLHDLDJQCLDWBSXFZZYYSCHTYTYYBHECXHYKGJPXHHYZJFXHWHBDZFYZBCAPNPGNYDMSXHMMMMAMYNBYJTMPXYYMCTHJBZYFCGTYHWPHFTWZZEZSBZEGPFMTSKFTYCMHFLLHGPZJXZJGZJYXZSBBQSCZZLZCCSTPGXMJSFTCCZJZDJXCYBZLFCJSYZFGSZLYBCWZZBYZDZYPSWYJZXZBDSYUXLZZBZFYGCZXBZHZFTPBGZGEJBSTGKDMFHYZZJHZLLZZGJQZLSFDJSSCBZGPDLFZFZSZYZYZSYGCXSNXXCHCZXTZZLJFZGQSQYXZJQDCCZTQCDXZJYQJQCHXZTDLGSCXZSYQJQTZWLQDQZTQCHQQJZYEZZZPBWKDJFCJPZTYPQYQTTYNLMBDKTJZPQZQZZFPZSBNJLGYJDXJDZZKZGQKXDLPZJTCJDQBXDJQJSTCKNXBXZMSLYJCQMTJQWWCJQNJNLLLHJCWQTBZQYDZCZPZZDZYDDCYZZZCCJTTJFZDPRRTZTJDCQTQZDTJNPLZBCLLCTZSXKJZQZPZLBZRBTJDCXFCZDBCCJJLTQQPLDCGZDBBZJCQDCJWYNLLZYZCCDWLLXWZLXRXNTQQCZXKQLSGDFQTDDGLRLAJJTKUYMKQLLTZYTDYYCZGJWYXDXFRSKSTQTENQMRKQZHHQKDLDAZFKYPBGGPZREBZZYKZZSPEGJXGYKQZZZSLYSYYYZWFQZYLZZLZHWCHKYPQGNPGBLPLRRJYXCCSYYHSFZFYBZYYTGZXYLXCZWXXZJZBLFFLGSKHYJZEYJHLPLLLLCZGXDRZELRHGKLZZYHZLYQSZZJZQLJZFLNBHGWLCZCFJYSPYXZLZLXGCCPZBLLCYBBBBUBBCBPCRNNZCZYRBFSRLDCGQYYQXYGMQZWTZYTYJXYFWTEHZZJYWLCCNTZYJJZDEDPZDZTSYQJHDYMBJNYJZLXTSSTPHNDJXXBYXQTZQDDTJTDYYTGWSCSZQFLSHLGLBCZPHDLYZJYCKWTYTYLBNYTSDSYCCTYSZYYEBHEXHQDTWNYGYCLXTSZYSTQMYGZAZCCS
24836ZZDSLZCLZRQXYYELJSBYMXSXZTEMBBLLYYLLYTDQYSHYMRQWKFKBFXNXSBYCHXBWJYHTQBPBSBWDZYLKGZSKYHXQZJXHXJXGNLJKZLYYCDXLFYFGHLJGJYBXQLYBXQPQGZTZPLNCYPXDJYQYDYMRBESJYYHKXXSTMXRCZZYWXYQYBMCLLYZHQYZWQXDBXBZWZMSLPDMYSKFMZKLZCYQYCZLQXFZZYDQZPZYGYJYZMZXDZFYFYTTQTZHGSPCZMLCCYTZXJCYTJMKSLPZHYSNZLLYTPZCTZZCKTXDHXXTQCYFKSMQCCYYAZHTJPCYLZLYJBJXTPNYLJYYNRXSYLMMNXJSMYBCSYSYLZYLXJJQYLDZLPQBFZZBLFNDXQKCZFYWHGQMRDSXYCYTXNQQJZYYPFZXDYZFPRXEJDGYQBXRCNFYYQPGHYJDYZXGRHTKYLNWDZNTSMPKLBTHBPYSZBZTJZSZZJTYYXZPHSSZZBZCZPTQFZMYFLYPYBBJQXZMXXDJMTSYSKKBJZXHJCKLPSMKYJZCXTMLJYXRZZQSLXXQPYZXMKYXXXJCLJPRMYYGADYSKQLSNDHYZKQXZYZTCGHZTLMLWZYBWSYCTBHJHJFCWZTXWYTKZLXQSHLYJZJXTMPLPYCGLTBZZTLZJCYJGDTCLKLPLLQPJMZPAPXYZLKKTKDZCZZBNZDYDYQZJYJGMCTXLTGXSZLMLHBGLKFWNWZHDXUHLFMKYSLGXDTWWFRJEJZTZHYDXYKSHWFZCQSHKTMQQHTZHYMJDJSKHXZJZBZZXYMPAGQMSTPXLSKLZYNWRTSQLSZBPSPSGZWYHTLKSSSWHZZLYYTNXJGMJSZSUFWNLSOZTXGXLSAMMLBWLDSZYLAKQCQCTMYCFJBSLXCLZZCLXXKSBZQCLHJPSQPLSXXCKSLNHPSFQQYTXYJZLQLDXZQJZDYYDJNZPTUZDSKJFSLJHYLZSQZLBTXYDGTQFDBYAZXDZHZJNHHQBYKNXJJQCZMLLJZKSPLDYCLBBLXKLELXJLBQYCXJXGCNLCQPLZLZYJTZLJGYZDZPLTQCSXFDMNYCXGBTJDCZNBGBQYQJWGKFHTNPYQZQGBKPBBYZMTJDYTBLSQMPSXTBNPDXKLEMYYCJYNZCTLDYKZZXDDXHQSHDGMZSJYCCTAYRZLPYLTLKXSLZCGGEXCLFXLKJRTLQJAQZNCMBYDKKCXGLCZJZXJHPTDJJMZQYKQSECQZDSHHADMLZFMMZBGNTJNNLGBYJBRBTMLBYJDZXLCJLPLDLPCQDHLXZLYCBLCXZZJADJLNZMMSSSMYBHBSQKBHRSXXJMXSDZNZPXLGBRHWGGFCXGMSKLLTSJYYCQLTSKYWYYHYWXBXQYWPYWYKQLSQPTNTKHQCWDQKTWPXXHCPTHTWUMSSYHBWCRWXHJMKMZNGWTMLKFGHKJYLSYYCXWHYECLQHKQHTTQKHFZLDXQWYZYYDESBPKYRZPJFYYZJCEQDZZDLATZBBFJLLCXDLMJSSXEGYGSJQXCWBXSSZPDYZCXDNYXPPZYDLYJCZPLTXLSXYZYRXCYYYDYLWWNZSAHJSYQYHGYWWAXTJZDAXYSRLTDPSSYYFNEJDXYZHLXLLLZQZSJNYQYQQXYJGHZGZCYJCHZLYCDSHWSHJZYJXCLLNXZJJYYXNFXMWFPYLCYLLABWDDHWDXJMCXZTZPMLQZHSFHZYNZTLLDYWLSLXHYMMYLMBWWKYXYADTXYLLDJPYBPWUXJMWMLLSAFDLLYFLBHHHBQQLTZJCQJLDJTFFKMMMBYTHYGDCQRDDWRQJXNBYSNWZDBYYTBJHPYBYTTJXAAHGQDQTMYSTQXKBTZPKJLZRBEQQSSMJJBDJOTGTBXPGBKTLHQXJJJCTHXQDWJLWRFWQGWSHCKRYSWGFTGYGBXSDWDWRFHWYTJJXXXJYZYSLPYYYPAYXHYDQKXSHXYXGSKQHYWFDDDPPLCJLQQEEWXKSYYKDYPLTJTHKJLTCYYHHJTTPLTZZCDLTHQKZXQYSTEEYWYYZYXXYYSTTJKLLPZMCYHQGXYHSRMBXPLLNQYDQHXSXXWGDQBSHYLLPJJJTHYJKYPPTHYYKTYEZYENMDSHLCRPQFDGFXZPSFTLJXXJBSWYYSKSFLXLPPLBBBLBSFXFYZBSJSSYLPBBFFFFSSCJDSTZSXZRYYSYFFSYZYZBJTBCTSBSDHRTJJBYTCXYJEYLXCBNEBJDSYXYKGSJZBXBYTFZWGENYHHTHZHHXFWGCSTBGXKLSXYWMTMBYXJSTZSCDYQRCYTWXZFHMYMCXLZNSDJTTTXRYCFYJSBSDYERXJLJXBBDEYNJGHXGCKGSCYMBLXJMSZNSKGXFBNBPTHFJAAFXYXFPXMYPQDTZCXZZPXRSYWZDLYBBKTYQPQJPZYPZJZNJPZJLZZFYSBTTSLMPTZRTDXQSJEHBZYLZDHLJSQMLHTXTJECXSLZZSPKTLZKQQYFSYGYWPCPQFHQHYTQXZKRSGTTSQCZLPTXCDYYZXSQZSLXLZMYCPCQBZYXHBSXLZDLTCDXTYLZJYYZPZYZLTXJSJXHLPMYTXCQRBLZSSFJZZTNJYTXMYJHLHPPLCYXQJQQKZZSCPZKSWALQSBLCCZJSXGWWWYGYKTJBBZTDKHXHKGTGPBKQYSLPXPJCKBMLLXDZSTBKLGGQKQLSBKKTFXRMDKBFTPZFRTBBRFERQGXYJPZSSTLBZTPSZQZSJDHLJQLZBPMSMMSXLQQNHKNBLRDDNXXDHDDJCYYGYLXGZLXSYGMQQGKHBPMXYXLYTQWLWGCPBMQXCYZYDRJBHTDJYHQSHTMJSBYPLWHLZFFNYPMHXXHPLTBQPFBJWQDBYGPNZTPFZJGSDDTQSHZEAWZZYLLTYYBWJKXXGHLFKXDJTMSZSQYNZGGSWQSPHTLSSKMCLZXYSZQZXNCJDQGZDLFNYKLJCJLLZLMZZNHYDSSHTHZZLZZBBHQZWWYCRZHLYQQJBEYFXXXWHSRXWQHWPSLMSSKZTTYGYQQWRSLALHMJTQJSMXQBJJZJXZYZKXBYQXBJXSHZTSFJLXMXZXFGHKZSZGGYLCLSARJYHSLLLMZXELGLXYDJYTLFBHBPNLYZFBBHPTGJKWETZHKJJXZXXGLLJLSTGSHJJYQLQZFKCGNNDJSSZFDBCTWWSEQFHQJBSAQTGYPQLBXBMMYWXGSLZHGLZGQYFLZBYFZJFRYSFMBYZHQGFWZSYFYJJPHZBYYZFFWODGRLMFTWLBZGYCQXCDJYGZYYYYTYTYDWEGAZYHXJLZYYHLRMGRXXZCLHNELJJTJTPWJYBJJBXJJTJTEEKHWSLJPLPSFYZPQQBDLQJJTYYQLYZKDKSQJYYQZLDQTGJQYZJSUCMRYQTHTEJMFCTYHYPKMHYZWJDQFHYYXWSHCTXRLJHQXHCCYYYJLTKTTYTMXGTCJTZAYYOCZLYLBSZYWJYTSJYHBYSHFJLYGJXXTMZYYLTXXYPZLXYJZYZYYPNHMYMDYYLBLHLSYYQQLLNJJYMSOYQBZGDLYXYLCQYXTSZEGXHZGLHWBLJHEYXTWQMAKBPQCGYSHHEGQCMWYYWLJYJHYYZLLJJYLHZYHMGSLJLJXCJJYCLYCJPCPZJZJMMYLCQLNQLJQJSXYJMLSZLJQLYCMMHCFMMFPQQMFYLQMCFFQMMMMHMZNFHHJGTTHHKHSLNCHHYQDXTMMQDCYZYXYQMYQYLTDCYYYZAZZCYMZYDLZFFFMMYCQZWZZMABTBYZTDMNZZGGDFTYPCGQYTTSSFFWFDTZQSSYSTWXJHXYTSXXYLBYQHWWKXHZXWZNNZZJZJJQJCCCHYYXBZXZCYZTLLCQXYNJYCYYCYNZZQYYYEWYCZDCJYCCHYJLBTZYYCQWMPWPYMLGKDLDLGKQQBGYCHJXY";
24837//�˴���¼��375��������,
24838var oMultiDiff = { "19969": "DZ", "19975": "WM", "19988": "QJ", "20048": "YL", "20056": "SC", "20060": "NM", "20094": "QG", "20127": "QJ", "20167": "QC", "20193": "YG", "20250": "KH", "20256": "ZC", "20282": "SC", "20285": "QJG", "20291": "TD", "20314": "YD", "20340": "NE", "20375": "TD", "20389": "YJ", "20391": "CZ", "20415": "PB", "20446": "YS", "20447": "SQ", "20504": "TC", "20608": "KG", "20854": "QJ", "20857": "ZC", "20911": "PF", "20504": "TC", "20608": "KG", "20854": "QJ", "20857": "ZC", "20911": "PF", "20985": "AW", "21032": "PB", "21048": "XQ", "21049": "SC", "21089": "YS", "21119": "JC", "21242": "SB", "21273": "SC", "21305": "YP", "21306": "QO", "21330": "ZC", "21333": "SDC", "21345": "QK", "21378": "CA", "21397": "SC", "21414": "XS", "21442": "SC", "21477": "JG", "21480": "TD", "21484": "ZS", "21494": "YX", "21505": "YX", "21512": "HG", "21523": "XH", "21537": "PB", "21542": "PF", "21549": "KH", "21571": "E", "21574": "DA", "21588": "TD", "21589": "O", "21618": "ZC", "21621": "KHA", "21632": "ZJ", "21654": "KG", "21679": "LKG", "21683": "KH", "21710": "A", "21719": "YH", "21734": "WOE", "21769": "A", "21780": "WN", "21804": "XH", "21834": "A", "21899": "ZD", "21903": "RN", "21908": "WO", "21939": "ZC", "21956": "SA", "21964": "YA", "21970": "TD", "22003": "A", "22031": "JG", "22040": "XS", "22060": "ZC", "22066": "ZC", "22079": "MH", "22129": "XJ", "22179": "XA", "22237": "NJ", "22244": "TD", "22280": "JQ", "22300": "YH", "22313": "XW", "22331": "YQ", "22343": "YJ", "22351": "PH", "22395": "DC", "22412": "TD", "22484": "PB", "22500": "PB", "22534": "ZD", "22549": "DH", "22561": "PB", "22612": "TD", "22771": "KQ", "22831": "HB", "22841": "JG", "22855": "QJ", "22865": "XQ", "23013": "ML", "23081": "WM", "23487": "SX", "23558": "QJ", "23561": "YW", "23586": "YW", "23614": "YW", "23615": "SN", "23631": "PB", "23646": "ZS", "23663": "ZT", "23673": "YG", "23762": "TD", "23769": "ZS", "23780": "QJ", "23884": "QK", "24055": "XH", "24113": "DC", "24162": "ZC", "24191": "GA", "24273": "QJ", "24324": "NL", "24377": "TD", "24378": "QJ", "24439": "PF", "24554": "ZS", "24683": "TD", "24694": "WE", "24733": "LK", "24925": "TN", "25094": "ZG", "25100": "XQ", "25103": "XH", "25153": "PB", "25170": "PB", "25179": "KG", "25203": "PB", "25240": "ZS", "25282": "FB", "25303": "NA", "25324": "KG", "25341": "ZY", "25373": "WZ", "25375": "XJ", "25384": "A", "25457": "A", "25528": "SD", "25530": "SC", "25552": "TD", "25774": "ZC", "25874": "ZC", "26044"
24838: "YW", "26080": "WM", "26292": "PB", "26333": "PB", "26355": "ZY", "26366": "CZ", "26397": "ZC", "26399": "QJ", "26415": "ZS", "26451": "SB", "26526": "ZC", "26552": "JG", "26561": "TD", "26588": "JG", "26597": "CZ", "26629": "ZS", "26638": "YL", "26646": "XQ", "26653": "KG", "26657": "XJ", "26727": "HG", "26894": "ZC", "26937": "ZS", "26946": "ZC", "26999": "KJ", "27099": "KJ", "27449": "YQ", "27481": "XS", "27542": "ZS", "27663": "ZS", "27748": "TS", "27784": "SC", "27788": "ZD", "27795": "TD", "27812": "O", "27850": "PB", "27852": "MB", "27895": "SL", "27898": "PL", "27973": "QJ", "27981": "KH", "27986": "HX", "27994": "XJ", "28044": "YC", "28065": "WG", "28177": "SM", "28267": "QJ", "28291": "KH", "28337": "ZQ", "28463": "TL", "28548": "DC", "28601": "TD", "28689": "PB", "28805": "JG", "28820": "QG", "28846": "PB", "28952": "TD", "28975": "ZC", "29100": "A", "29325": "QJ", "29575": "SL", "29602": "FB", "30010": "TD", "30044": "CX", "30058": "PF", "30091": "YSP", "30111": "YN", "30229": "XJ", "30427": "SC", "30465": "SX", "30631": "YQ", "30655": "QJ", "30684": "QJG", "30707": "SD", "30729": "XH", "30796": "LG", "30917": "PB", "31074": "NM", "31085": "JZ", "31109": "SC", "31181": "ZC", "31192": "MLB", "31293": "JQ", "3
248381400": "YX", "31584": "YJ", "31896": "ZN", "31909": "ZY", "31995": "XJ", "32321": "PF", "32327": "ZY", "32418": "HG", "32420": "XQ", "32421": "HG", "32438": "LG", "32473": "GJ", "32488": "TD", "32521": "QJ", "32527": "PB", "32562": "ZSQ", "32564": "JZ", "32735": "ZD", "32793": "PB", "33071": "PF", "33098": "XL", "33100": "YA", "33152": "PB", "33261": "CX", "33324": "BP", "33333": "TD", "33406": "YA", "33426": "WM", "33432": "PB", "33445": "JG", "33486": "ZN", "33493": "TS", "33507": "QJ", "33540": "QJ", "33544": "ZC", "33564": "XQ", "33617": "YT", "33632": "QJ", "33636": "XH", "33637": "YX", "33694": "WG", "33705": "PF", "33728": "YW", "33882": "SR", "34067": "WM", "34074": "YW", "34121": "QJ", "34255": "ZC", "34259": "XL", "34425": "JH", "34430": "XH", "34485": "KH", "34503": "YS", "34532": "HG", "34552": "XS", "34558": "YE", "34593": "ZL", "34660": "YQ", "34892": "XH", "34928": "SC", "34999": "QJ", "35048": "PB", "35059": "SC", "35098": "ZC", "35203": "TQ", "35265": "JX", "35299": "JX", "35782": "SZ", "35828": "YS", "35830": "E", "35843": "TD", "35895": "YG", "35977": "MH", "36158": "JG", "36228": "QJ", "36426": "XQ", "36466": "DC", "36710": "JC", "36711": "ZYG", "36767": "PB", "36866": "SK", "36951": "YW", "37034": "YX", "37063": "XH", "37218": "ZC", "37325": "ZC", "38063": "PB", "38079": "TD", "38085": "QY", "38107": "DC", "38116": "TD", "38123": "YD", "38224": "HG", "38241": "XTC", "38271": "ZC", "38415": "YE", "38426": "KH", "38461": "YD", "38463": "AE", "38466": "PB", "38477": "XJ", "38518": "YT", "38551": "WK", "38585": "ZC", "38704": "XS", "38739": "LJ", "38761": "GJ", "38808": "SQ", "39048": "JG", "39049": "XJ", "39052": "HG", "39076": "CZ", "39271": "XT", "39534": "TD", "39552": "TD", "39584": "PB", "39647": "SB", "39730": "LG", "39748": "TPB", "40109": "ZQ", "40479": "ND", "40516": "HG", "40536": "HG", "40583": "QJ", "40765": "YQ", "40784": "QJ", "40840": "YK", "40863": "QJG" };
24839//����,�����ַ���  
24840//����ֵ:ƴ������ĸ������  
24841function makePy(str) {
24842    if (typeof (str) != "string")
24843        throw new Error(-1, "����makePy��Ҫ�ַ������Ͳ���!");
24844    var arrResult = new Array(); //�������������  
24845    for (var i = 0, len = str.length; i < len; i++) {
24846        //���unicode��  
24847        var ch = str.charAt(i);
24848        //����unicode���Ƿ��ڴ����Χ֮��,���򷵻ظ����ӳ���ֵ�ƴ������ĸ,���������������������  
24849        arrResult.push(checkCh(ch));
24850    }
24851    //����arrResult,�������п��ܵ�ƴ������ĸ������  
24852    return mkRslt(arrResult);
24853}
24854function checkCh(ch) {
24855    var uni = ch.charCodeAt(0);
24856    //������ں��ִ����Χ֮��,����ԭ�ַ�,Ҳ���Ե����Լ��Ĵ������  
24857    if (uni > 40869 || uni < 19968)
24858        return ch; //dealWithOthers(ch);  
24859    //����Ƿ��Ƕ�����,�ǰ������ִ���,���Ǿ�ֱ����strChineseFirstPY�ַ������Ҷ�Ӧ������ĸ  
24860    return (oMultiDiff[uni] ? oMultiDiff[uni] : (strChineseFirstPY.charAt(uni - 19968)));
24861}
24862function mkRslt(arr) {
24863    var arrRslt = [""];
24864    for (var i = 0, len = arr.length; i < len; i++) {
24865        var str = arr[i];
24866        var strlen = str.length;
24867        if (strlen == 1) {
24868            for (var k = 0; k < arrRslt.length; k++) {
24869                arrRslt[k] += str;
24870            }
24871        } else {
24872            var tmpArr = arrRslt.slice(0);
24873            arrRslt = [];
24874            for (k = 0; k < strlen; k++) {
24875                //����һ����ͬ��arrRslt  
24876                var tmp = tmpArr.slice(0);
24877                //�ѵ�ǰ�ַ�str[k]��ӵ�ÿ��Ԫ��ĩβ  
24878                for (var j = 0; j < tmp.length; j++) {
24879                    tmp[j] += str.charAt(k);
24880                }
24881                //�Ѹ��Ʋ��޸ĺ���������ӵ�arrRslt��  
24882                arrRslt = arrRslt.concat(tmp);
24883            }
24884        }
24885    }
24886    return arrRslt;
24887}// Ion.RangeSlider
24888// version 2.1.7 Build: 371
24889// © Denis Ineshin, 2017
24890// https://github.com/IonDen
24891//
24892// Project page:    http://ionden.com/a/plugins/ion.rangeSlider/en.html
24893// GitHub page:     https://github.com/IonDen/ion.rangeSlider
24894//
24895// Released under MIT licence:
24896// http://ionden.com/a/plugins/licence-en.html
24897// =====================================================================================================================
24898//-------------------------------------------------- resizeInput
24899function resizeInput() {
24900    $('.resize_input').each(function(){
24901        $(this).attr('size', $(this).val().length);
24902    });
24903}
24904
24905;(function(factory) {
24906    if (typeof define === "function" && define.amd) {
24907        define(["jquery"], function (jQuery) {
24908            return factory(jQuery, document, window, navigator);
24909        });
24910    } else if (typeof exports === "object") {
24911        factory(require("jquery"), document, window, navigator);
24912    } else {
24913        factory(jQuery, document, window, navigator);
24914    }
24915} (function ($, document, window, navigator, undefined) {
24916    "use strict";
24917
24918    // =================================================================================================================
24919    // Service
24920
24921    var plugin_count = 0;
24922
24923    // IE8 fix
24924    var is_old_ie = (function () {
24925        var n = navigator.userAgent,
24926            r = /msie\s\d+/i,
24927            v;
24928        if (n.search(r) > 0) {
24929            v = r.exec(n).toString();
24930            v = v.split(" ")[1];
24931            if (v < 9) {
24932                $("html").addClass("lt-ie9");
24933                return true;
24934            }
24935        }
24936        return false;
24937    } ());
24938    if (!Function.prototype.bind) {
24939        Function.prototype.bind = function bind(that) {
24940
24941            var target = this;
24942            var slice = [].slice;
24943
24944            if (typeof target != "function") {
24945                throw new TypeError();
24946            }
24947
24948            var args = slice.call(arguments, 1),
24949                bound = function () {
24950
24951                    if (this instanceof bound) {
24952
24953                        var F = function(){};
24954                        F.prototype = target.prototype;
24955                        var self = new F();
24956
24957                        var result = target.apply(
24958                            self,
24959                            args.concat(slice.call(arguments))
24960                        );
24961                        if (Object(result) === result) {
24962                            return result;
24963                        }
24964                        return self;
24965
24966                    } else {
24967
24968                        return target.apply(
24969                            that,
24970                            args.concat(slice.call(arguments))
24971                        );
24972
24973                    }
24974
24975                };
24976
24977            return bound;
24978        };
24979    }
24980    if (!Array.prototype.indexOf) {
24981        Array.prototype.indexOf = function(searchElement, fromIndex) {
24982            var k;
24983            if (this == null) {
24984                throw new TypeError('"this" is null or not defined');
24985            }
24986            var O = Object(this);
24987            var len = O.length >>> 0;
24988            if (len === 0) {
24989                return -1;
24990            }
24991            var n = +fromIndex || 0;
24992            if (Math.abs(n) === Infinity) {
24993                n = 0;
24994            }
24995            if (n >= len) {
24996                return -1;
24997            }
24998            k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
24999            while (k < len) {
25000                if (k in O && O[k] === searchElement) {
25001                    return k;
25002                }
25003                k++;
25004            }
25005            return -1;
25006        };
25007    }
25008
25009
25010
25011    // =================================================================================================================
25012    // Template
25013
25014    var base_html =
25015        '<span class="irs">' +
25016        '<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>' +
25017        '<span class="irs-min">0</span><span class="irs-max">1</span>' +
25018        '<span class="irs-from">0</span><span class="irs-to">0</span><span class="irs-single">0</span>' +
25019        '</span>' +
25020        '<span class="irs-grid"></span>' +
25021        '<span class="irs-bar"></span>';
25022
25023    var single_html =
25024        '<span class="irs-bar-edge"></span>' +
25025        '<span class="irs-shadow shadow-single"></span>' +
25026        '<span class="irs-slider single"></span>';
25027
25028    var double_html =
25029        '<span class="irs-shadow shadow-from"></span>' +
25030        '<span class="irs-shadow shadow-to"></span>' +
25031        '<span class="irs-slider from"></span>' +
25032        '<span class="irs-slider to"></span>';
25033
25034    var disable_html =
25035        '<span class="irs-disable-mask"></span>';
25036
25037
25038
25039    // =================================================================================================================
25040    // Core
25041
25042    /**
25043     * Main plugin constructor
25044     *
25045     * @param input {Object} link to base input element
25046     * @param options {Object} slider config
25047     * @param plugin_count {Number}
25048     * @constructor
25049     */
25050    var IonRangeSlider = function (input, options, plugin_count) {
25051        this.VERSION = "2.1.7";
25052        this.input = input;
25053        this.plugin_count = plugin_count;
25054        this.current_plugin = 0;
25055        this.calc_count = 0;
25056        this.update_tm = 0;
25057        this.old_from = 0;
25058        this.old_to = 0;
25059        this.old_min_interval = null;
25060        this.raf_id = null;
25061        this.dragging = false;
25062        this.force_redraw = false;
25063        this.no_diapason = false;
25064        this.is_key = false;
25065        this.is_update = false;
25066        this.is_start = true;
25067        this.is_finish = false;
25068        this.is_active = false;
25069        this.is_resize = false;
25070        this.is_click = false;
25071
25072        options = options || {};
25073
25074        // cache for links to all DOM elements
25075        this.$cache = {
25076            win: $(window),
25077            body: $(document.body),
25078            input: $(input),
25079            cont: null,
25080            rs: null,
25081            min: null,
25082            max: null,
25083            from: null,
25084            to: null,
25085            single: null,
25086            bar: null,
25087            line: null,
25088            s_single: null,
25089            s_from: null,
25090            s_to: null,
25091            shad_single: null,
25092            shad_from: null,
25093            shad_to: null,
25094            edge: null,
25095            grid: null,
25096            grid_labels: []
25097        };
25098
25099        // storage for measure variables
25100        this.coords = {
25101            // left
25102            x_gap: 0,
25103            x_pointer: 0,
25104
25105            // width
25106            w_rs: 0,
25107            w_rs_old: 0,
25108            w_handle: 0,
25109
25110            // percents
25111            p_gap: 0,
25112            p_gap_left: 0,
25113            p_gap_right: 0,
25114            p_step: 0,
25115            p_pointer: 0,
25116            p_handle: 0,
25117            p_single_fake: 0,
25118            p_single_real: 0,
25119            p_from_fake: 0,
25120            p_from_real: 0,
25121            p_to_fake: 0,
25122            p_to_real: 0,
25123            p_bar_x: 0,
25124            p_bar_w: 0,
25125
25126            // grid
25127            grid_gap: 0,
25128            big_num: 0,
25129            big: [],
25130            big_w: [],
25131            big_p: [],
25132            big_x: []
25133        };
25134
25135        // storage for labels measure variables
25136        this.labels = {
25137            // width
25138            w_min: 0,
25139            w_max: 0,
25140            w_from: 0,
25141            w_to: 0,
25142            w_single: 0,
25143
25144            // percents
25145            p_min: 0,
25146            p_max: 0,
25147            p_from_fake: 0,
25148            p_from_left: 0,
25149            p_to_fake: 0,
25150            p_to_left: 0,
25151            p_single_fake: 0,
25152            p_single_left: 0
25153        };
25154
25155
25156
25157        /**
25158         * get and validate config
25159         */
25160        var $inp = this.$cache.input,
25161            val = $inp.prop("value"),
25162            config, config_from_data, prop;
25163
25164        // default config
25165        config = {
25166            type: "single",
25167
25168            min: 10,
25169            max: 100,
25170            from: null,
25171            to: null,
25172            step: 1,
25173
25174            min_interval: 0,
25175            max_interval: 0,
25176            drag_interval: false,
25177
25178            values: [],
25179            p_values: [],
25180
25181            from_fixed: false,
25182            from_min: null,
25183            from_max: null,
25184            from_shadow: false,
25185
25186            to_fixed: false,
25187            to_min: null,
25188            to_max: null,
25189            to_shadow: false,
25190
25191            prettify_enabled: true,
25192            prettify_separator: " ",
25193            prettify: null,
25194
25195            force_edges: false,
25196
25197            keyboard: false,
25198            keyboard_step: 5,
25199
25200            grid: false,
25201            grid_margin: true,
25202            grid_num: 4,
25203            grid_snap: false,
25204
25205            hide_min_max: false,
25206            hide_from_to: false,
25207
25208            prefix: "",
25209            postfix: "",
25210            max_postfix: "",
25211            decorate_both: true,
25212            values_separator: " — ",
25213
25214            input_values_separator: ";",
25215
25216            disable: false,
25217
25218            onStart: null,
25219            onChange: null,
25220            onFinish: null,
25221            onUpdate: null
25222        };
25223
25224
25225        // check if base element is input
25226        if ($inp[0].nodeName !== "INPUT") {
25227            console && console.warn && console.warn("Base element should be <input>!", $inp[0]);
25228        }
25229
25230
25231        // config from data-attributes extends js config
25232        config_from_data = {
25233            type: $inp.data("type"),
25234
25235            min: $inp.data("min"),
25236            max: $inp.data("max"),
25237            from: $inp.data("from"),
25238            to: $inp.data("to"),
25239            step: $inp.data("step"),
25240
25241            min_interval: $inp.data("minInterval"),
25242            max_interval: $inp.data("maxInterval"),
25243            drag_interval: $inp.data("dragInterval"),
25244
25245            values: $inp.data("values"),
25246
25247            from_fixed: $inp.data("fromFixed"),
25248            from_min: $inp.data("fromMin"),
25249            from_max: $inp.data("fromMax"),
25250            from_shadow: $inp.data("fromShadow"),
25251
25252            to_fixed: $inp.data("toFixed"),
25253            to_min: $inp.data("toMin"),
25254            to_max: $inp.data("toMax"),
25255            to_shadow: $inp.data("toShadow"),
25256
25257            prettify_enabled: $inp.data("prettifyEnabled"),
25258            prettify_separator: $inp.data("prettifySeparator"),
25259
25260            force_edges: $inp.data("forceEdges"),
25261
25262            keyboard: $inp.data("keyboard"),
25263            keyboard_step: $inp.data("keyboardStep"),
25264
25265            grid: $inp.data("grid"),
25266            grid_margin: $inp.data("gridMargin"),
25267            grid_num: $inp.data("gridNum"),
25268            grid_snap: $inp.data("gridSnap"),
25269
25270            hide_min_max: $inp.data("hideMinMax"),
25271            hide_from_to: $inp.data("hideFromTo"),
25272
25273            prefix: $inp.data("prefix"),
25274            postfix: $inp.data("postfix"),
25275            max_postfix: $inp.data("maxPostfix"),
25276            decorate_both: $inp.data("decorateBoth"),
25277            values_separator: $inp.data("valuesSeparator"),
25278
25279            input_values_separator: $inp.data("inputValuesSeparator"),
25280
25281            disable: $inp.data("disable")
25282        };
25283        config_from_data.values = config_from_data.values && config_from_data.values.split(",");
25284
25285        for (prop in config_from_data) {
25286            if (config_from_data.hasOwnProperty(prop)) {
25287                if (config_from_data[prop] === undefined || config_from_data[prop] === "") {
25288                    delete config_from_data[prop];
25289                }
25290            }
25291        }
25292
25293
25294        // input value extends default config
25295        if (val !== undefined && val !== "") {
25296            val = val.split(config_from_data.input_values_separator || options.input_values_separator || ";");
25297
25298            if (val[0] && val[0] == +val[0]) {
25299                val[0] = +val[0];
25300            }
25301            if (val[1] && val[1] == +val[1]) {
25302                val[1] = +val[1];
25303            }
25304
25305            if (options && options.values && options.values.length) {
25306                config.from = val[0] && options.values.indexOf(val[0]);
25307                config.to = val[1] && options.values.indexOf(val[1]);
25308            } else {
25309                config.from = val[0] && +val[0];
25310                config.to = val[1] && +val[1];
25311            }
25312        }
25313
25314
25315
25316        // js config extends default config
25317        $.extend(config, options);
25318
25319
25320        // data config extends config
25321        $.extend(config, config_from_data);
25322        this.options = config;
25323
25324
25325
25326        // validate config, to be sure that all data types are correct
25327        this.update_check = {};
25328        this.validate();
25329
25330
25331
25332        // default result object, returned to callbacks
25333        this.result = {
25334            input: this.$cache.input,
25335            slider: null,
25336
25337            min: this.options.min,
25338            max: this.options.max,
25339
25340            from: this.options.from,
25341            from_percent: 0,
25342            from_value: null,
25343
25344            to: this.options.to,
25345            to_percent: 0,
25346            to_value: null
25347        };
25348
25349
25350
25351        this.init();
25352    };
25353
25354    IonRangeSlider.prototype = {
25355
25356        /**
25357         * Starts or updates the plugin instance
25358         *
25359         * @param [is_update] {boolean}
25360         */
25361        init: function (is_update) {
25362            this.no_diapason = false;
25363            this.coords.p_step = this.convertToPercent(this.options.step, true);
25364
25365            this.target = "base";
25366
25367            this.toggleInput();
25368            this.append();
25369            this.setMinMax();
25370
25371            if (is_update) {
25372                this.force_redraw = true;
25373                this.calc(true);
25374
25375                // callbacks called
25376                this.callOnUpdate();
25377            } else {
25378                this.force_redraw = true;
25379                this.calc(true);
25380
25381                // callbacks called
25382                this.callOnStart();
25383            }
25384
25385            this.updateScene();
25386        },
25387
25388        /**
25389         * Appends slider template to a DOM
25390         */
25391        append: function () {
25392            var container_html = '<span class="irs js-irs-' + this.plugin_count + '"></span>';
25393            this.$cache.input.before(container_html);
25394            this.$cache.input.prop("readonly", true);
25395            this.$cache.cont = this.$cache.input.prev();
25396            this.result.slider = this.$cache.cont;
25397
25398            this.$cache.cont.html(base_html);
25399            this.$cache.rs = this.$cache.cont.find(".irs");
25400            this.$cache.min = this.$cache.cont.find(".irs-min");
25401            this.$cache.max = this.$cache.cont.find(".irs-max");
25402            this.$cache.from = this.$cache.cont.find(".irs-from");
25403            this.$cache.to = this.$cache.cont.find(".irs-to");
25404            this.$cache.single = this.$cache.cont.find(".irs-single");
25405            this.$cache.bar = this.$cache.cont.find(".irs-bar");
25406            this.$cache.line = this.$cache.cont.find(".irs-line");
25407            this.$cache.grid = this.$cache.cont.find(".irs-grid");
25408
25409            if (this.options.type === "single") {
25410                this.$cache.cont.append(single_html);
25411                this.$cache.edge = this.$cache.cont.find(".irs-bar-edge");
25412                this.$cache.s_single = this.$cache.cont.find(".single");
25413                this.$cache.from[0].style.visibility = "hidden";
25414                this.$cache.to[0].style.visibility = "hidden";
25415                this.$cache.shad_single = this.$cache.cont.find(".shadow-single");
25416            } else {
25417                this.$cache.cont.append(double_html);
25418                this.$cache.s_from = this.$cache.cont.find(".from");
25419                this.$cache.s_to = this.$cache.cont.find(".to");
25420                this.$cache.shad_from = this.$cache.cont.find(".shadow-from");
25421                this.$cache.shad_to = this.$cache.cont.find(".shadow-to");
25422
25423                this.setTopHandler();
25424            }
25425
25426            if (this.options.hide_from_to) {
25427                this.$cache.from[0].style.display = "none";
25428                this.$cache.to[0].style.display = "none";
25429                this.$cache.single[0].style.display = "none";
25430            }
25431
25432            this.appendGrid();
25433
25434            if (this.options.disable) {
25435                this.appendDisableMask();
25436                this.$cache.input[0].disabled = true;
25437            } else {
25438                this.$cache.cont.removeClass("irs-disabled");
25439                this.$cache.input[0].disabled = false;
25440                this.bindEvents();
25441            }
25442
25443            if (this.options.drag_interval) {
25444                this.$cache.bar[0].style.cursor = "ew-resize";
25445            }
25446        },
25447
25448        /**
25449         * Determine which handler has a priority
25450         * works only for double slider type
25451         */
25452        setTopHandler: function () {
25453            var min = this.options.min,
25454                max = this.options.max,
25455                from = this.options.from,
25456                to = this.options.to;
25457
25458            if (from > min && to === max) {
25459                this.$cache.s_from.addClass("type_last");
25460            } else if (to < max) {
25461                this.$cache.s_to.addClass("type_last");
25462            }
25463        },
25464
25465        /**
25466         * Determine which handles was clicked last
25467         * and which handler should have hover effect
25468         *
25469         * @param target {String}
25470         */
25471        changeLevel: function (target) {
25472            switch (target) {
25473                case "single":
25474                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_single_fake);
25475                    break;
25476                case "from":
25477                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake);
25478                    this.$cache.s_from.addClass("state_hover");
25479                    this.$cache.s_from.addClass("type_last");
25480                    this.$cache.s_to.removeClass("type_last");
25481                    break;
25482                case "to":
25483                    this.coords.p_gap = this.toFixed(this.coords.p_pointer - this.coords.p_to_fake);
25484                    this.$cache.s_to.addClass("state_hover");
25485                    this.$cache.s_to.addClass("type_last");
25486                    this.$cache.s_from.removeClass("type_last");
25487                    break;
25488                case "both":
25489                    this.coords.p_gap_left = this.toFixed(this.coords.p_pointer - this.coords.p_from_fake);
25490                    this.coords.p_gap_right = this.toFixed(this.coords.p_to_fake - this.coords.p_pointer);
25491                    this.$cache.s_to.removeClass("type_last");
25492                    this.$cache.s_from.removeClass("type_last");
25493                    break;
25494            }
25495        },
25496
25497        /**
25498         * Then slider is disabled
25499         * appends extra layer with opacity
25500         */
25501        appendDisableMask: function () {
25502            this.$cache.cont.append(disable_html);
25503            this.$cache.cont.addClass("irs-disabled");
25504        },
25505
25506        /**
25507         * Remove slider instance
25508         * and ubind all events
25509         */
25510        remove: function () {
25511            this.$cache.cont.remove();
25512            this.$cache.cont = null;
25513
25514            this.$cache.line.off("keydown.irs_" + this.plugin_count);
25515
25516            this.$cache.body.off("touchmove.irs_" + this.plugin_count);
25517            this.$cache.body.off("mousemove.irs_" + this.plugin_count);
25518
25519            this.$cache.win.off("touchend.irs_" + this.plugin_count);
25520            this.$cache.win.off("mouseup.irs_" + this.plugin_count);
25521
25522            if (is_old_ie) {
25523                this.$cache.body.off("mouseup.irs_" + this.plugin_count);
25524                this.$cache.body.off("mouseleave.irs_" + this.plugin_count);
25525            }
25526
25527            this.$cache.grid_labels = [];
25528            this.coords.big = [];
25529            this.coords.big_w = [];
25530            this.coords.big_p = [];
25531            this.coords.big_x = [];
25532
25533            cancelAnimationFrame(this.raf_id);
25534        },
25535
25536        /**
25537         * bind all slider events
25538         */
25539        bindEvents: function () {
25540            if (this.no_diapason) {
25541                return;
25542            }
25543
25544            this.$cache.body.on("touchmove.irs_" + this.plugin_count, this.pointerMove.bind(this));
25545            this.$cache.body.on("mousemove.irs_" + this.plugin_count, this.pointerMove.bind(this));
25546
25547            this.$cache.win.on("touchend.irs_" + this.plugin_count, this.pointerUp.bind(this));
25548            this.$cache.win.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
25549
25550            this.$cache.line.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
25551            this.$cache.line.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
25552
25553            if (this.options.drag_interval && this.options.type === "double") {
25554                this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
25555                this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "both"));
25556            } else {
25557                this.$cache.bar.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
25558                this.$cache.bar.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
25559            }
25560
25561            if (this.options.type === "single") {
25562                this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
25563                this.$cache.s_single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
25564                this.$cache.shad_single.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
25565
25566                this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
25567                this.$cache.s_single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "single"));
25568                this.$cache.edge.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
25569                this.$cache.shad_single.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
25570            } else {
25571                this.$cache.single.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, null));
25572                this.$cache.single.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, null));
25573
25574                this.$cache.from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
25575                this.$cache.s_from.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
25576                this.$cache.to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
25577                this.$cache.s_to.on("touchstart.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
25578                this.$cache.shad_from.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
25579                this.$cache.shad_to.on("touchstart.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
25580
25581                this.$cache.from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
25582                this.$cache.s_from.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "from"));
25583                this.$cache.to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
25584                this.$cache.s_to.on("mousedown.irs_" + this.plugin_count, this.pointerDown.bind(this, "to"));
25585                this.$cache.shad_from.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
25586                this.$cache.shad_to.on("mousedown.irs_" + this.plugin_count, this.pointerClick.bind(this, "click"));
25587            }
25588
25589            if (this.options.keyboard) {
25590                this.$cache.line.on("keydown.irs_" + this.plugin_count, this.key.bind(this, "keyboard"));
25591            }
25592
25593            if (is_old_ie) {
25594                this.$cache.body.on("mouseup.irs_" + this.plugin_count, this.pointerUp.bind(this));
25595                this.$cache.body.on("mouseleave.irs_" + this.plugin_count, this.pointerUp.bind(this));
25596            }
25597        },
25598
25599        /**
25600         * Mousemove or touchmove
25601         * only for handlers
25602         *
25603         * @param e {Object} event object
25604         */
25605        pointerMove: function (e) {
25606            if (!this.dragging) {
25607                return;
25608            }
25609
25610            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
25611            this.coords.x_pointer = x - this.coords.x_gap;
25612
25613            this.calc();
25614        },
25615
25616        /**
25617         * Mouseup or touchend
25618         * only for handlers
25619         *
25620         * @param e {Object} event object
25621         */
25622        pointerUp: function (e) {
25623            if (this.current_plugin !== this.plugin_count) {
25624                return;
25625            }
25626
25627            if (this.is_active) {
25628                this.is_active = false;
25629            } else {
25630                return;
25631            }
25632
25633            this.$cache.cont.find(".state_hover").removeClass("state_hover");
25634
25635            this.force_redraw = true;
25636
25637            if (is_old_ie) {
25638                $("*").prop("unselectable", false);
25639            }
25640
25641            this.updateScene();
25642            this.restoreOriginalMinInterval();
25643
25644            // callbacks call
25645            if ($.contains(this.$cache.cont[0], e.target) || this.dragging) {
25646                this.callOnFinish();
25647            }
25648            
25649            this.dragging = false;
25650        },
25651
25652        /**
25653         * Mousedown or touchstart
25654         * only for handlers
25655         *
25656         * @param target {String|null}
25657         * @param e {Object} event object
25658         */
25659        pointerDown: function (target, e) {
25660            e.preventDefault();
25661            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
25662            if (e.button === 2) {
25663                return;
25664            }
25665
25666            if (target === "both") {
25667                this.setTempMinInterval();
25668            }
25669
25670            if (!target) {
25671                target = this.target || "from";
25672            }
25673
25674            this.current_plugin = this.plugin_count;
25675            this.target = target;
25676
25677            this.is_active = true;
25678            this.dragging = true;
25679
25680            this.coords.x_gap = this.$cache.rs.offset().left;
25681            this.coords.x_pointer = x - this.coords.x_gap;
25682
25683            this.calcPointerPercent();
25684            this.changeLevel(target);
25685
25686            if (is_old_ie) {
25687                $("*").prop("unselectable", true);
25688            }
25689
25690            this.$cache.line.trigger("focus");
25691
25692            this.updateScene();
25693        },
25694
25695        /**
25696         * Mousedown or touchstart
25697         * for other slider elements, like diapason line
25698         *
25699         * @param target {String}
25700         * @param e {Object} event object
25701         */
25702        pointerClick: function (target, e) {
25703            e.preventDefault();
25704            var x = e.pageX || e.originalEvent.touches && e.originalEvent.touches[0].pageX;
25705            if (e.button === 2) {
25706                return;
25707            }
25708
25709            this.current_plugin = this.plugin_count;
25710            this.target = target;
25711
25712            this.is_click = true;
25713            this.coords.x_gap = this.$cache.rs.offset().left;
25714            this.coords.x_pointer = +(x - this.coords.x_gap).toFixed();
25715
25716            this.force_redraw = true;
25717            this.calc();
25718
25719            this.$cache.line.trigger("focus");
25720        },
25721
25722        /**
25723         * Keyborard controls for focused slider
25724         *
25725         * @param target {String}
25726         * @param e {Object} event object
25727         * @returns {boolean|undefined}
25728         */
25729        key: function (target, e) {
25730            if (this.current_plugin !== this.plugin_count || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
25731                return;
25732            }
25733
25734            switch (e.which) {
25735                case 83: // W
25736                case 65: // A
25737                case 40: // DOWN
25738                case 37: // LEFT
25739                    e.preventDefault();
25740                    this.moveByKey(false);
25741                    break;
25742
25743                case 87: // S
25744                case 68: // D
25745                case 38: // UP
25746                case 39: // RIGHT
25747                    e.preventDefault();
25748                    this.moveByKey(true);
25749                    break;
25750            }
25751
25752            return true;
25753        },
25754
25755        /**
25756         * Move by key. Beta
25757         * @todo refactor than have plenty of time
25758         *
25759         * @param right {boolean} direction to move
25760         */
25761        moveByKey: function (right) {
25762            var p = this.coords.p_pointer;
25763
25764            if (right) {
25765                p += this.options.keyboard_step;
25766            } else {
25767                p -= this.options.keyboard_step;
25768            }
25769
25770            this.coords.x_pointer = this.toFixed(this.coords.w_rs / 100 * p);
25771            this.is_key = true;
25772            this.calc();
25773        },
25774
25775        /**
25776         * Set visibility and content
25777         * of Min and Max labels
25778         */
25779        setMinMax: function () {
25780            if (!this.options) {
25781                return;
25782            }
25783
25784            if (this.options.hide_min_max) {
25785                this.$cache.min[0].style.display = "none";
25786                this.$cache.max[0].style.display = "none";
25787                return;
25788            }
25789
25790            if (this.options.values.length) {
25791                this.$cache.min.html(this.decorate(this.options.p_values[this.options.min]));
25792                this.$cache.max.html(this.decorate(this.options.p_values[this.options.max]));
25793            } else {
25794                this.$cache.min.html(this.decorate(this._prettify(this.options.min), this.options.min));
25795                this.$cache.max.html(this.decorate(this._prettify(this.options.max), this.options.max));
25796            }
25797
25798            this.labels.w_min = this.$cache.min.outerWidth(false);
25799            this.labels.w_max = this.$cache.max.outerWidth(false);
25800        },
25801
25802        /**
25803         * Then dragging interval, prevent interval collapsing
25804         * using min_interval option
25805         */
25806        setTempMinInterval: function () {
25807            var interval = this.result.to - this.result.from;
25808
25809            if (this.old_min_interval === null) {
25810                this.old_min_interval = this.options.min_interval;
25811            }
25812
25813            this.options.min_interval = interval;
25814        },
25815
25816        /**
25817         * Restore min_interval option to original
25818         */
25819        restoreOriginalMinInterval: function () {
25820            if (this.old_min_interval !== null) {
25821                this.options.min_interval = this.old_min_interval;
25822                this.old_min_interval = null;
25823            }
25824        },
25825
25826
25827
25828        // =============================================================================================================
25829        // Calculations
25830
25831        /**
25832         * All calculations and measures start here
25833         *
25834         * @param update {boolean=}
25835         */
25836        calc: function (update) {
25837            if (!this.options) {
25838                return;
25839            }
25840
25841            this.calc_count++;
25842
25843            if (this.calc_count === 10 || update) {
25844                this.calc_count = 0;
25845                this.coords.w_rs = this.$cache.rs.outerWidth(false);
25846
25847                this.calcHandlePercent();
25848            }
25849
25850            if (!this.coords.w_rs) {
25851                return;
25852            }
25853
25854            this.calcPointerPercent();
25855            var handle_x = this.getHandleX();
25856
25857
25858            if (this.target === "both") {
25859                this.coords.p_gap = 0;
25860                handle_x = this.getHandleX();
25861            }
25862
25863            if (this.target === "click") {
25864                this.coords.p_gap = this.coords.p_handle / 2;
25865                handle_x = this.getHandleX();
25866
25867                if (this.options.drag_interval) {
25868                    this.target = "both_one";
25869                } else {
25870                    this.target = this.chooseHandle(handle_x);
25871                }
25872            }
25873
25874            switch (this.target) {
25875                case "base":
25876                    var w = (this.options.max - this.options.min) / 100,
25877                        f = (this.result.from - this.options.min) / w,
25878                        t = (this.result.to - this.options.min) / w;
25879
25880                    this.coords.p_single_real = this.toFixed(f);
25881                    this.coords.p_from_real = this.toFixed(f);
25882                    this.coords.p_to_real = this.toFixed(t);
25883
25884                    this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
25885                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
25886                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
25887
25888                    this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real);
25889                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
25890                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
25891
25892                    this.target = null;
25893
25894                    break;
25895
25896                case "single":
25897                    if (this.options.from_fixed) {
25898                        break;
25899                    }
25900
25901                    this.coords.p_single_real = this.convertToRealPercent(handle_x);
25902                    this.coords.p_single_real = this.calcWithStep(this.coords.p_single_real);
25903                    this.coords.p_single_real = this.checkDiapason(this.coords.p_single_real, this.options.from_min, this.options.from_max);
25904
25905                    this.coords.p_single_fake = this.convertToFakePercent(this.coords.p_single_real);
25906
25907                    break;
25908
25909                case "from":
25910                    if (this.options.from_fixed) {
25911                        break;
25912                    }
25913
25914                    this.coords.p_from_real = this.convertToRealPercent(handle_x);
25915                    this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real);
25916                    if (this.coords.p_from_real > this.coords.p_to_real) {
25917                        this.coords.p_from_real = this.coords.p_to_real;
25918                    }
25919                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
25920                    this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
25921                    this.coords.p_from_real = this.checkMaxInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
25922
25923                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
25924
25925                    break;
25926
25927                case "to":
25928                    if (this.options.to_fixed) {
25929                        break;
25930                    }
25931
25932                    this.coords.p_to_real = this.convertToRealPercent(handle_x);
25933                    this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real);
25934                    if (this.coords.p_to_real < this.coords.p_from_real) {
25935                        this.coords.p_to_real = this.coords.p_from_real;
25936                    }
25937                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
25938                    this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
25939                    this.coords.p_to_real = this.checkMaxInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
25940
25941                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
25942
25943                    break;
25944
25945                case "both":
25946                    if (this.options.from_fixed || this.options.to_fixed) {
25947                        break;
25948                    }
25949
25950                    handle_x = this.toFixed(handle_x + (this.coords.p_handle * 0.001));
25951
25952                    this.coords.p_from_real = this.convertToRealPercent(handle_x) - this.coords.p_gap_left;
25953                    this.coords.p_from_real = this.calcWithStep(this.coords.p_from_real);
25954                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
25955                    this.coords.p_from_real = this.checkMinInterval(this.coords.p_from_real, this.coords.p_to_real, "from");
25956                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
25957
25958                    this.coords.p_to_real = this.convertToRealPercent(handle_x) + this.coords.p_gap_right;
25959                    this.coords.p_to_real = this.calcWithStep(this.coords.p_to_real);
25960                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
25961                    this.coords.p_to_real = this.checkMinInterval(this.coords.p_to_real, this.coords.p_from_real, "to");
25962                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
25963
25964                    break;
25965
25966                case "both_one":
25967                    if (this.options.from_fixed || this.options.to_fixed) {
25968                        break;
25969                    }
25970
25971                    var real_x = this.convertToRealPercent(handle_x),
25972                        from = this.result.from_percent,
25973                        to = this.result.to_percent,
25974                        full = to - from,
25975                        half = full / 2,
25976                        new_from = real_x - half,
25977                        new_to = real_x + half;
25978
25979                    if (new_from < 0) {
25980                        new_from = 0;
25981                        new_to = new_from + full;
25982                    }
25983
25984                    if (new_to > 100) {
25985                        new_to = 100;
25986                        new_from = new_to - full;
25987                    }
25988
25989                    this.coords.p_from_real = this.calcWithStep(new_from);
25990                    this.coords.p_from_real = this.checkDiapason(this.coords.p_from_real, this.options.from_min, this.options.from_max);
25991                    this.coords.p_from_fake = this.convertToFakePercent(this.coords.p_from_real);
25992
25993                    this.coords.p_to_real = this.calcWithStep(new_to);
25994                    this.coords.p_to_real = this.checkDiapason(this.coords.p_to_real, this.options.to_min, this.options.to_max);
25995                    this.coords.p_to_fake = this.convertToFakePercent(this.coords.p_to_real);
25996
25997                    break;
25998            }
25999
26000            if (this.options.type === "single") {
26001                this.coords.p_bar_x = (this.coords.p_handle / 2);
26002                this.coords.p_bar_w = this.coords.p_single_fake;
26003
26004                this.result.from_percent = this.coords.p_single_real;
26005                this.result.from = this.convertToValue(this.coords.p_single_real);
26006
26007                if (this.options.values.length) {
26008                    this.result.from_value = this.options.values[this.result.from];
26009                }
26010            } else {
26011                this.coords.p_bar_x = this.toFixed(this.coords.p_from_fake + (this.coords.p_handle / 2));
26012                this.coords.p_bar_w = this.toFixed(this.coords.p_to_fake - this.coords.p_from_fake);
26013
26014                this.result.from_percent = this.coords.p_from_real;
26015                this.result.from = this.convertToValue(this.coords.p_from_real);
26016                this.result.to_percent = this.coords.p_to_real;
26017                this.result.to = this.convertToValue(this.coords.p_to_real);
26018
26019                if (this.options.values.length) {
26020                    this.result.from_value = this.options.values[this.result.from];
26021                    this.result.to_value = this.options.values[this.result.to];
26022                }
26023            }
26024
26025            this.calcMinMax();
26026            this.calcLabels();
26027        },
26028
26029
26030        /**
26031         * calculates pointer X in percent
26032         */
26033        calcPointerPercent: function () {
26034            if (!this.coords.w_rs) {
26035                this.coords.p_pointer = 0;
26036                return;
26037            }
26038
26039            if (this.coords.x_pointer < 0 || isNaN(this.coords.x_pointer)  ) {
26040                this.coords.x_pointer = 0;
26041            } else if (this.coords.x_pointer > this.coords.w_rs) {
26042                this.coords.x_pointer = this.coords.w_rs;
26043            }
26044
26045            this.coords.p_pointer = this.toFixed(this.coords.x_pointer / this.coords.w_rs * 100);
26046        },
26047
26048        convertToRealPercent: function (fake) {
26049            var full = 100 - this.coords.p_handle;
26050            return fake / full * 100;
26051        },
26052
26053        convertToFakePercent: function (real) {
26054            var full = 100 - this.coords.p_handle;
26055            return real / 100 * full;
26056        },
26057
26058        getHandleX: function () {
26059            var max = 100 - this.coords.p_handle,
26060                x = this.toFixed(this.coords.p_pointer - this.coords.p_gap);
26061
26062            if (x < 0) {
26063                x = 0;
26064            } else if (x > max) {
26065                x = max;
26066            }
26067
26068            return x;
26069        },
26070
26071        calcHandlePercent: function () {
26072            if (this.options.type === "single") {
26073                this.coords.w_handle = this.$cache.s_single.outerWidth(false);
26074            } else {
26075                this.coords.w_handle = this.$cache.s_from.outerWidth(false);
26076            }
26077
26078            this.coords.p_handle = this.toFixed(this.coords.w_handle / this.coords.w_rs * 100);
26079        },
26080
26081        /**
26082         * Find closest handle to pointer click
26083         *
26084         * @param real_x {Number}
26085         * @returns {String}
26086         */
26087        chooseHandle: function (real_x) {
26088            if (this.options.type === "single") {
26089                return "single";
26090            } else {
26091                var m_point = this.coords.p_from_real + ((this.coords.p_to_real - this.coords.p_from_real) / 2);
26092                if (real_x >= m_point) {
26093                    return this.options.to_fixed ? "from" : "to";
26094                } else {
26095                    return this.options.from_fixed ? "to" : "from";
26096                }
26097            }
26098        },
26099
26100        /**
26101         * Measure Min and Max labels width in percent
26102         */
26103        calcMinMax: function () {
26104            if (!this.coords.w_rs) {
26105                return;
26106            }
26107
26108            this.labels.p_min = this.labels.w_min / this.coords.w_rs * 100;
26109            this.labels.p_max = this.labels.w_max / this.coords.w_rs * 100;
26110        },
26111
26112        /**
26113         * Measure labels width and X in percent
26114         */
26115        calcLabels: function () {
26116            if (!this.coords.w_rs || this.options.hide_from_to) {
26117                return;
26118            }
26119
26120            if (this.options.type === "single") {
26121
26122                this.labels.w_single = this.$cache.single.outerWidth(false);
26123                this.labels.p_single_fake = this.labels.w_single / this.coords.w_rs * 100;
26124                this.labels.p_single_left = this.coords.p_single_fake + (this.coords.p_handle / 2) - (this.labels.p_single_fake / 2);
26125                this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single_fake);
26126
26127            } else {
26128
26129                this.labels.w_from = this.$cache.from.outerWidth(false);
26130                this.labels.p_from_fake = this.labels.w_from / this.coords.w_rs * 100;
26131                this.labels.p_from_left = this.coords.p_from_fake + (this.coords.p_handle / 2) - (this.labels.p_from_fake / 2);
26132                this.labels.p_from_left = this.toFixed(this.labels.p_from_left);
26133                this.labels.p_from_left = this.checkEdges(this.labels.p_from_left, this.labels.p_from_fake);
26134
26135                this.labels.w_to = this.$cache.to.outerWidth(false);
26136                this.labels.p_to_fake = this.labels.w_to / this.coords.w_rs * 100;
26137                this.labels.p_to_left = this.coords.p_to_fake + (this.coords.p_handle / 2) - (this.labels.p_to_fake / 2);
26138                this.labels.p_to_left = this.toFixed(this.labels.p_to_left);
26139                this.labels.p_to_left = this.checkEdges(this.labels.p_to_left, this.labels.p_to_fake);
26140
26141                this.labels.w_single = this.$cache.single.outerWidth(false);
26142                this.labels.p_single_fake = this.labels.w_single / this.coords.w_rs * 100;
26143                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);
26144                this.labels.p_single_left = this.toFixed(this.labels.p_single_left);
26145                this.labels.p_single_left = this.checkEdges(this.labels.p_single_left, this.labels.p_single_fake);
26146
26147            }
26148        },
26149
26150
26151
26152        // =============================================================================================================
26153        // Drawings
26154
26155        /**
26156         * Main function called in request animation frame
26157         * to update everything
26158         */
26159        updateScene: function () {
26160            if (this.raf_id) {
26161                cancelAnimationFrame(this.raf_id);
26162                this.raf_id = null;
26163            }
26164
26165            clearTimeout(this.update_tm);
26166            this.update_tm = null;
26167
26168            if (!this.options) {
26169                return;
26170            }
26171
26172            this.drawHandles();
26173
26174            if (this.is_active) {
26175                this.raf_id = requestAnimationFrame(this.updateScene.bind(this));
26176            } else {
26177                this.update_tm = setTimeout(this.updateScene.bind(this), 300);
26178            }
26179        },
26180
26181        /**
26182         * Draw handles
26183         */
26184        drawHandles: function () {
26185            this.coords.w_rs = this.$cache.rs.outerWidth(false);
26186
26187            if (!this.coords.w_rs) {
26188                return;
26189            }
26190
26191            if (this.coords.w_rs !== this.coords.w_rs_old) {
26192                this.target = "base";
26193                this.is_resize = true;
26194            }
26195
26196            if (this.coords.w_rs !== this.coords.w_rs_old || this.force_redraw) {
26197                this.setMinMax();
26198                this.calc(true);
26199                this.drawLabels();
26200                if (this.options.grid) {
26201                    this.calcGridMargin();
26202                    this.calcGridLabels();
26203                }
26204                this.force_redraw = true;
26205                this.coords.w_rs_old = this.coords.w_rs;
26206                this.drawShadow();
26207            }
26208
26209            if (!this.coords.w_rs) {
26210                return;
26211            }
26212
26213            if (!this.dragging && !this.force_redraw && !this.is_key) {
26214                return;
26215            }
26216
26217            if (this.old_from !== this.result.from || this.old_to !== this.result.to || this.force_redraw || this.is_key) {
26218
26219                this.drawLabels();
26220
26221                this.$cache.bar[0].style.left = this.coords.p_bar_x + "%";
26222                this.$cache.bar[0].style.width = this.coords.p_bar_w + "%";
26223
26224                if (this.options.type === "single") {
26225                    this.$cache.s_single[0].style.left = this.coords.p_single_fake + "%";
26226
26227                    this.$cache.single[0].style.left = this.labels.p_single_left + "%";
26228                } else {
26229                    this.$cache.s_from[0].style.left = this.coords.p_from_fake + "%";
26230                    this.$cache.s_to[0].style.left = this.coords.p_to_fake + "%";
26231
26232                    if (this.old_from !== this.result.from || this.force_redraw) {
26233                        this.$cache.from[0].style.left = this.labels.p_from_left + "%";
26234                    }
26235                    if (this.old_to !== this.result.to || this.force_redraw) {
26236                        this.$cache.to[0].style.left = this.labels.p_to_left + "%";
26237                    }
26238
26239                    this.$cache.single[0].style.left = this.labels.p_single_left + "%";
26240                }
26241
26242                this.writeToInput();
26243
26244                if ((this.old_from !== this.result.from || this.old_to !== this.result.to) && !this.is_start) {
26245                    this.$cache.input.trigger("change");
26246                    this.$cache.input.trigger("input");
26247                }
26248
26249                this.old_from = this.result.from;
26250                this.old_to = this.result.to;
26251
26252                // callbacks call
26253                if (!this.is_resize && !this.is_update && !this.is_start && !this.is_finish) {
26254                    this.callOnChange();
26255                }
26256                if (this.is_key || this.is_click) {
26257                    this.is_key = false;
26258                    this.is_click = false;
26259                    this.callOnFinish();
26260                }
26261
26262                this.is_update = false;
26263                this.is_resize = false;
26264                this.is_finish = false;
26265            }
26266
26267            this.is_start = false;
26268            this.is_key = false;
26269            this.is_click = false;
26270            this.force_redraw = false;
26271        },
26272
26273        /**
26274         * Draw labels
26275         * measure labels collisions
26276         * collapse close labels
26277         */
26278        drawLabels: function () {
26279            if (!this.options) {
26280                return;
26281            }
26282
26283            var values_num = this.options.values.length,
26284                p_values = this.options.p_values,
26285                text_single,
26286                text_from,
26287                text_to;
26288
26289            if (this.options.hide_from_to) {
26290                return;
26291            }
26292
26293            if (this.options.type === "single") {
26294
26295                if (values_num) {
26296                    text_single = this.decorate(p_values[this.result.from]);
26297                    this.$cache.single.html(text_single);
26298                } else {
26299                    text_single = this.decorate(this._prettify(this.result.from), this.result.from);
26300                    this.$cache.single.html(text_single);
26301                }
26302
26303                this.calcLabels();
26304
26305                if (this.labels.p_single_left < this.labels.p_min + 1) {
26306                    this.$cache.min[0].style.visibility = "hidden";
26307                } else {
26308                    this.$cache.min[0].style.visibility = "visible";
26309                }
26310
26311                if (this.labels.p_single_left + this.labels.p_single_fake > 100 - this.labels.p_max - 1) {
26312                    this.$cache.max[0].style.visibility = "hidden";
26313                } else {
26314                    this.$cache.max[0].style.visibility = "visible";
26315                }
26316
26317            } else {
26318
26319                if (values_num) {
26320
26321                    if (this.options.decorate_both) {
26322                        text_single = this.decorate(p_values[this.result.from]);
26323                        text_single += this.options.values_separator;
26324                        text_single += this.decorate(p_values[this.result.to]);
26325                    } else {
26326                        text_single = this.decorate(p_values[this.result.from] + this.options.values_separator + p_values[this.result.to]);
26327                    }
26328                    text_from = this.decorate(p_values[this.result.from]);
26329                    text_to = this.decorate(p_values[this.result.to]);
26330
26331                    this.$cache.single.html(text_single);
26332                    this.$cache.from.html(text_from);
26333                    this.$cache.to.html(text_to);
26334
26335                } else {
26336
26337                    if (this.options.decorate_both) {
26338                        text_single = this.decorate(this._prettify(this.result.from), this.result.from);
26339                        text_single += this.options.values_separator;
26340                        text_single += this.decorate(this._prettify(this.result.to), this.result.to);
26341                    } else {
26342                        text_single = this.decorate(this._prettify(this.result.from) + this.options.values_separator + this._prettify(this.result.to), this.result.to);
26343                    }
26344                    text_from = this.decorate(this._prettify(this.result.from), this.result.from);
26345                    text_to = this.decorate(this._prettify(this.result.to), this.result.to);
26346
26347                    this.$cache.single.html(text_single);
26348                    this.$cache.from.html(text_from);
26349                    this.$cache.to.html(text_to);
26350
26351                }
26352
26353                this.calcLabels();
26354
26355                var min = Math.min(this.labels.p_single_left, this.labels.p_from_left),
26356                    single_left = this.labels.p_single_left + this.labels.p_single_fake,
26357                    to_left = this.labels.p_to_left + this.labels.p_to_fake,
26358                    max = Math.max(single_left, to_left);
26359
26360                if (this.labels.p_from_left + this.labels.p_from_fake >= this.labels.p_to_left) {
26361                    this.$cache.from[0].style.visibility = "hidden";
26362                    this.$cache.to[0].style.visibility = "hidden";
26363                    this.$cache.single[0].style.visibility = "visible";
26364
26365                    if (this.result.from === this.result.to) {
26366                        if (this.target === "from") {
26367                            this.$cache.from[0].style.visibility = "visible";
26368                        } else if (this.target === "to") {
26369                            this.$cache.to[0].style.visibility = "visible";
26370                        } else if (!this.target) {
26371                            this.$cache.from[0].style.visibility = "visible";
26372                        }
26373                        this.$cache.single[0].style.visibility = "hidden";
26374                        max = to_left;
26375                    } else {
26376                        this.$cache.from[0].style.visibility = "hidden";
26377                        this.$cache.to[0].style.visibility = "hidden";
26378                        this.$cache.single[0].style.visibility = "visible";
26379                        max = Math.max(single_left, to_left);
26380                    }
26381                } else {
26382                    this.$cache.from[0].style.visibility = "visible";
26383                    this.$cache.to[0].style.visibility = "visible";
26384                    this.$cache.single[0].style.visibility = "hidden";
26385                }
26386
26387                if (min < this.labels.p_min + 1) {
26388                    this.$cache.min[0].style.visibility = "hidden";
26389                } else {
26390                    this.$cache.min[0].style.visibility = "visible";
26391                }
26392
26393                if (max > 100 - this.labels.p_max - 1) {
26394                    this.$cache.max[0].style.visibility = "hidden";
26395                } else {
26396                    this.$cache.max[0].style.visibility = "visible";
26397                }
26398
26399            }
26400        },
26401
26402        /**
26403         * Draw shadow intervals
26404         */
26405        drawShadow: function () {
26406            var o = this.options,
26407                c = this.$cache,
26408
26409                is_from_min = typeof o.from_min === "number" && !isNaN(o.from_min),
26410                is_from_max = typeof o.from_max === "number" && !isNaN(o.from_max),
26411                is_to_min = typeof o.to_min === "number" && !isNaN(o.to_min),
26412                is_to_max = typeof o.to_max === "number" && !isNaN(o.to_max),
26413
26414                from_min,
26415                from_max,
26416                to_min,
26417                to_max;
26418
26419            if (o.type === "single") {
26420                if (o.from_shadow && (is_from_min || is_from_max)) {
26421                    from_min = this.convertToPercent(is_from_min ? o.from_min : o.min);
26422                    from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min;
26423                    from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
26424                    from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
26425                    from_min = from_min + (this.coords.p_handle / 2);
26426
26427                    c.shad_single[0].style.display = "block";
26428                    c.shad_single[0].style.left = from_min + "%";
26429                    c.shad_single[0].style.width = from_max + "%";
26430                } else {
26431                    c.shad_single[0].style.display = "none";
26432                }
26433            } else {
26434                if (o.from_shadow && (is_from_min || is_from_max)) {
26435                    from_min = this.convertToPercent(is_from_min ? o.from_min : o.min);
26436                    from_max = this.convertToPercent(is_from_max ? o.from_max : o.max) - from_min;
26437                    from_min = this.toFixed(from_min - (this.coords.p_handle / 100 * from_min));
26438                    from_max = this.toFixed(from_max - (this.coords.p_handle / 100 * from_max));
26439                    from_min = from_min + (this.coords.p_handle / 2);
26440
26441                    c.shad_from[0].style.display = "block";
26442                    c.shad_from[0].style.left = from_min + "%";
26443                    c.shad_from[0].style.width = from_max + "%";
26444                } else {
26445                    c.shad_from[0].style.display = "none";
26446                }
26447
26448                if (o.to_shadow && (is_to_min || is_to_max)) {
26449                    to_min = this.convertToPercent(is_to_min ? o.to_min : o.min);
26450                    to_max = this.convertToPercent(is_to_max ? o.to_max : o.max) - to_min;
26451                    to_min = this.toFixed(to_min - (this.coords.p_handle / 100 * to_min));
26452                    to_max = this.toFixed(to_max - (this.coords.p_handle / 100 * to_max));
26453                    to_min = to_min + (this.coords.p_handle / 2);
26454
26455                    c.shad_to[0].style.display = "block";
26456                    c.shad_to[0].style.left = to_min + "%";
26457                    c.shad_to[0].style.width = to_max + "%";
26458                } else {
26459                    c.shad_to[0].style.display = "none";
26460                }
26461            }
26462        },
26463
26464
26465
26466        /**
26467         * Write values to input element
26468         */
26469        writeToInput: function () {
26470            if (this.options.type === "single") {
26471                if (this.options.values.length) {
26472                    this.$cache.input.prop("value", this.result.from_value);
26473                } else {
26474                    this.$cache.input.prop("value", this.result.from);
26475                }
26476                this.$cache.input.data("from", this.result.from);
26477            } else {
26478                if (this.options.values.length) {
26479                    this.$cache.input.prop("value", this.result.from_value + this.options.input_values_separator + this.result.to_value);
26480                } else {
26481                    this.$cache.input.prop("value", this.result.from + this.options.input_values_separator + this.result.to);
26482                }
26483                this.$cache.input.data("from", this.result.from);
26484                this.$cache.input.data("to", this.result.to);
26485            }
26486        },
26487
26488
26489
26490        // =============================================================================================================
26491        // Callbacks
26492
26493        callOnStart: function () {
26494            this.writeToInput();
26495
26496            if (this.options.onStart && typeof this.options.onStart === "function") {
26497                this.options.onStart(this.result);
26498            }
26499        },
26500        callOnChange: function () {
26501            this.writeToInput();
26502
26503            if (this.options.onChange && typeof this.options.onChange === "function") {
26504                this.options.onChange(this.result);
26505            }
26506        },
26507        callOnFinish: function () {
26508            this.writeToInput();
26509
26510            if (this.options.onFinish && typeof this.options.onFinish === "function") {
26511                this.options.onFinish(this.result);
26512            }
26513        },
26514        callOnUpdate: function () {
26515            this.writeToInput();
26516
26517            if (this.options.onUpdate && typeof this.options.onUpdate === "function") {
26518                this.options.onUpdate(this.result);
26519            }
26520        },
26521
26522
26523
26524
26525        // =============================================================================================================
26526        // Service methods
26527
26528        toggleInput: function () {
26529            this.$cache.input.toggleClass("irs-hidden-input");
26530        },
26531
26532        /**
26533         * Convert real value to percent
26534         *
26535         * @param value {Number} X in real
26536         * @param no_min {boolean=} don't use min value
26537         * @returns {Number} X in percent
26538         */
26539        convertToPercent: function (value, no_min) {
26540            var diapason = this.options.max - this.options.min,
26541                one_percent = diapason / 100,
26542                val, percent;
26543
26544            if (!diapason) {
26545                this.no_diapason = true;
26546                return 0;
26547            }
26548
26549            if (no_min) {
26550                val = value;
26551            } else {
26552                val = value - this.options.min;
26553            }
26554
26555            percent = val / one_percent;
26556
26557            return this.toFixed(percent);
26558        },
26559
26560        /**
26561         * Convert percent to real values
26562         *
26563         * @param percent {Number} X in percent
26564         * @returns {Number} X in real
26565         */
26566        convertToValue: function (percent) {
26567            var min = this.options.min,
26568                max = this.options.max,
26569                min_decimals = min.toString().split(".")[1],
26570                max_decimals = max.toString().split(".")[1],
26571                min_length, max_length,
26572                avg_decimals = 0,
26573                abs = 0;
26574
26575            if (percent === 0) {
26576                return this.options.min;
26577            }
26578            if (percent === 100) {
26579                return this.options.max;
26580            }
26581
26582
26583            if (min_decimals) {
26584                min_length = min_decimals.length;
26585                avg_decimals = min_length;
26586            }
26587            if (max_decimals) {
26588                max_length = max_decimals.length;
26589                avg_decimals = max_length;
26590            }
26591            if (min_length && max_length) {
26592                avg_decimals = (min_length >= max_length) ? min_length : max_length;
26593            }
26594
26595            if (min < 0) {
26596                abs = Math.abs(min);
26597                min = +(min + abs).toFixed(avg_decimals);
26598                max = +(max + abs).toFixed(avg_decimals);
26599            }
26600
26601            var number = ((max - min) / 100 * percent) + min,
26602                string = this.options.step.toString().split(".")[1],
26603                result;
26604
26605            if (string) {
26606                number = +number.toFixed(string.length);
26607            } else {
26608                number = number / this.options.step;
26609                number = number * this.options.step;
26610
26611                number = +number.toFixed(0);
26612            }
26613
26614            if (abs) {
26615                number -= abs;
26616            }
26617
26618            if (string) {
26619                result = +number.toFixed(string.length);
26620            } else {
26621                result = this.toFixed(number);
26622            }
26623
26624            if (result < this.options.min) {
26625                result = this.options.min;
26626            } else if (result > this.options.max) {
26627                result = this.options.max;
26628            }
26629
26630            return result;
26631        },
26632
26633        /**
26634         * Round percent value with step
26635         *
26636         * @param percent {Number}
26637         * @returns percent {Number} rounded
26638         */
26639        calcWithStep: function (percent) {
26640            var rounded = Math.round(percent / this.coords.p_step) * this.coords.p_step;
26641
26642            if (rounded > 100) {
26643                rounded = 100;
26644            }
26645            if (percent === 100) {
26646                rounded = 100;
26647            }
26648
26649            return this.toFixed(rounded);
26650        },
26651
26652        checkMinInterval: function (p_current, p_next, type) {
26653            var o = this.options,
26654                current,
26655                next;
26656
26657            if (!o.min_interval) {
26658                return p_current;
26659            }
26660
26661            current = this.convertToValue(p_current);
26662            next = this.convertToValue(p_next);
26663
26664            if (type === "from") {
26665
26666                if (next - current < o.min_interval) {
26667                    current = next - o.min_interval;
26668                }
26669
26670            } else {
26671
26672                if (current - next < o.min_interval) {
26673                    current = next + o.min_interval;
26674                }
26675
26676            }
26677
26678            return this.convertToPercent(current);
26679        },
26680
26681        checkMaxInterval: function (p_current, p_next, type) {
26682            var o = this.options,
26683                current,
26684                next;
26685
26686            if (!o.max_interval) {
26687                return p_current;
26688            }
26689
26690            current = this.convertToValue(p_current);
26691            next = this.convertToValue(p_next);
26692
26693            if (type === "from") {
26694
26695                if (next - current > o.max_interval) {
26696                    current = next - o.max_interval;
26697                }
26698
26699            } else {
26700
26701                if (current - next > o.max_interval) {
26702                    current = next + o.max_interval;
26703                }
26704
26705            }
26706
26707            return this.convertToPercent(current);
26708        },
26709
26710        checkDiapason: function (p_num, min, max) {
26711            var num = this.convertToValue(p_num),
26712                o = this.options;
26713
26714            if (typeof min !== "number") {
26715                min = o.min;
26716            }
26717
26718            if (typeof max !== "number") {
26719                max = o.max;
26720            }
26721
26722            if (num < min) {
26723                num = min;
26724            }
26725
26726            if (num > max) {
26727                num = max;
26728            }
26729
26730            return this.convertToPercent(num);
26731        },
26732
26733        toFixed: function (num) {
26734            num = num.toFixed(20);
26735            return +num;
26736        },
26737
26738        _prettify: function (num) {
26739            if (!this.options.prettify_enabled) {
26740                return num;
26741            }
26742
26743            if (this.options.prettify && typeof this.options.prettify === "function") {
26744                return this.options.prettify(num);
26745            } else {
26746                return this.prettify(num);
26747            }
26748        },
26749
26750        prettify: function (num) {
26751            var n = num.toString();
26752            return n.replace(/(\d{1,3}(?=(?:\d\d\d)+(?!\d)))/g, "$1" + this.options.prettify_separator);
26753        },
26754
26755        checkEdges: function (left, width) {
26756            if (!this.options.force_edges) {
26757                return this.toFixed(left);
26758            }
26759
26760            if (left < 0) {
26761                left = 0;
26762            } else if (left > 100 - width) {
26763                left = 100 - width;
26764            }
26765
26766            return this.toFixed(left);
26767        },
26768
26769        validate: function () {
26770            var o = this.options,
26771                r = this.result,
26772                v = o.values,
26773                vl = v.length,
26774                value,
26775                i;
26776
26777            if (typeof o.min === "string") o.min = +o.min;
26778            if (typeof o.max === "string") o.max = +o.max;
26779            if (typeof o.from === "string") o.from = +o.from;
26780            if (typeof o.to === "string") o.to = +o.to;
26781            if (typeof o.step === "string") o.step = +o.step;
26782
26783            if (typeof o.from_min === "string") o.from_min = +o.from_min;
26784            if (typeof o.from_max === "string") o.from_max = +o.from_max;
26785            if (typeof o.to_min === "string") o.to_min = +o.to_min;
26786            if (typeof o.to_max === "string") o.to_max = +o.to_max;
26787
26788            if (typeof o.keyboard_step === "string") o.keyboard_step = +o.keyboard_step;
26789            if (typeof o.grid_num === "string") o.grid_num = +o.grid_num;
26790
26791            if (o.max < o.min) {
26792                o.max = o.min;
26793            }
26794
26795            if (vl) {
26796                o.p_values = [];
26797                o.min = 0;
26798                o.max = vl - 1;
26799                o.step = 1;
26800                o.grid_num = o.max;
26801                o.grid_snap = true;
26802
26803                for (i = 0; i < vl; i++) {
26804                    value = +v[i];
26805
26806                    if (!isNaN(value)) {
26807                        v[i] = value;
26808                        value = this._prettify(value);
26809                    } else {
26810                        value = v[i];
26811                    }
26812
26813                    o.p_values.push(value);
26814                }
26815            }
26816
26817            if (typeof o.from !== "number" || isNaN(o.from)) {
26818                o.from = o.min;
26819            }
26820
26821            if (typeof o.to !== "number" || isNaN(o.to)) {
26822                o.to = o.max;
26823            }
26824
26825            if (o.type === "single") {
26826
26827                if (o.from < o.min) o.from = o.min;
26828                if (o.from > o.max) o.from = o.max;
26829
26830            } else {
26831
26832                if (o.from < o.min) o.from = o.min;
26833                if (o.from > o.max) o.from = o.max;
26834
26835                if (o.to < o.min) o.to = o.min;
26836                if (o.to > o.max) o.to = o.max;
26837
26838                if (this.update_check.from) {
26839
26840                    if (this.update_check.from !== o.from) {
26841                        if (o.from > o.to) o.from = o.to;
26842                    }
26843                    if (this.update_check.to !== o.to) {
26844                        if (o.to < o.from) o.to = o.from;
26845                    }
26846
26847                }
26848
26849                if (o.from > o.to) o.from = o.to;
26850                if (o.to < o.from) o.to = o.from;
26851
26852            }
26853
26854            if (typeof o.step !== "number" || isNaN(o.step) || !o.step || o.step < 0) {
26855                o.step = 1;
26856            }
26857
26858            if (typeof o.keyboard_step !== "number" || isNaN(o.keyboard_step) || !o.keyboard_step || o.keyboard_step < 0) {
26859                o.keyboard_step = 5;
26860            }
26861
26862            if (typeof o.from_min === "number" && o.from < o.from_min) {
26863                o.from = o.from_min;
26864            }
26865
26866            if (typeof o.from_max === "number" && o.from > o.from_max) {
26867                o.from = o.from_max;
26868            }
26869
26870            if (typeof o.to_min === "number" && o.to < o.to_min) {
26871                o.to = o.to_min;
26872            }
26873
26874            if (typeof o.to_max === "number" && o.from > o.to_max) {
26875                o.to = o.to_max;
26876            }
26877
26878            if (r) {
26879                if (r.min !== o.min) {
26880                    r.min = o.min;
26881                }
26882
26883                if (r.max !== o.max) {
26884                    r.max = o.max;
26885                }
26886
26887                if (r.from < r.min || r.from > r.max) {
26888                    r.from = o.from;
26889                }
26890
26891                if (r.to < r.min || r.to > r.max) {
26892                    r.to = o.to;
26893                }
26894            }
26895
26896            if (typeof o.min_interval !== "number" || isNaN(o.min_interval) || !o.min_interval || o.min_interval < 0) {
26897                o.min_interval = 0;
26898            }
26899
26900            if (typeof o.max_interval !== "number" || isNaN(o.max_interval) || !o.max_interval || o.max_interval < 0) {
26901                o.max_interval = 0;
26902            }
26903
26904            if (o.min_interval && o.min_interval > o.max - o.min) {
26905                o.min_interval = o.max - o.min;
26906            }
26907
26908            if (o.max_interval && o.max_interval > o.max - o.min) {
26909                o.max_interval = o.max - o.min;
26910            }
26911        },
26912
26913        decorate: function (num, original) {
26914            var decorated = "",
26915                o = this.options;
26916
26917            if (o.prefix) {
26918                decorated += o.prefix;
26919            }
26920
26921            decorated += num;
26922
26923            if (o.max_postfix) {
26924                if (o.values.length && num === o.p_values[o.max]) {
26925                    decorated += o.max_postfix;
26926                    if (o.postfix) {
26927                        decorated += " ";
26928                    }
26929                } else if (original === o.max) {
26930                    decorated += o.max_postfix;
26931                    if (o.postfix) {
26932                        decorated += " ";
26933                    }
26934                }
26935            }
26936
26937            if (o.postfix) {
26938                decorated += o.postfix;
26939            }
26940
26941            return decorated;
26942        },
26943
26944        updateFrom: function () {
26945            this.result.from = this.options.from;
26946            this.result.from_percent = this.convertToPercent(this.result.from);
26947            if (this.options.values) {
26948                this.result.from_value = this.options.values[this.result.from];
26949            }
26950        },
26951
26952        updateTo: function () {
26953            this.result.to = this.options.to;
26954            this.result.to_percent = this.convertToPercent(this.result.to);
26955            if (this.options.values) {
26956                this.result.to_value = this.options.values[this.result.to];
26957            }
26958        },
26959
26960        updateResult: function () {
26961            this.result.min = this.options.min;
26962            this.result.max = this.options.max;
26963            this.updateFrom();
26964            this.updateTo();
26965        },
26966
26967
26968        // =============================================================================================================
26969        // Grid
26970
26971        appendGrid: function () {
26972            if (!this.options.grid) {
26973                return;
26974            }
26975
26976            var o = this.options,
26977                i, z,
26978
26979                total = o.max - o.min,
26980                big_num = o.grid_num,
26981                big_p = 0,
26982                big_w = 0,
26983
26984                small_max = 4,
26985                local_small_max,
26986                small_p,
26987                small_w = 0,
26988
26989                result,
26990                html = '';
26991
26992
26993
26994            this.calcGridMargin();
26995
26996            if (o.grid_snap) {
26997
26998                if (total > 50) {
26999                    big_num = 50 / o.step;
27000                    big_p = this.toFixed(o.step / 0.5);
27001                } else {
27002                    big_num = total / o.step;
27003                    big_p = this.toFixed(o.step / (total / 100));
27004                }
27005
27006            } else {
27007                big_p = this.toFixed(100 / big_num);
27008            }
27009
27010            if (big_num > 4) {
27011                small_max = 3;
27012            }
27013            if (big_num > 7) {
27014                small_max = 2;
27015            }
27016            if (big_num > 14) {
27017                small_max = 1;
27018            }
27019            if (big_num > 28) {
27020                small_max = 0;
27021            }
27022
27023            for (i = 0; i < big_num + 1; i++) {
27024                local_small_max = small_max;
27025
27026                big_w = this.toFixed(big_p * i);
27027
27028                if (big_w > 100) {
27029                    big_w = 100;
27030
27031                    local_small_max -= 2;
27032                    if (local_small_max < 0) {
27033                        local_small_max = 0;
27034                    }
27035                }
27036                this.coords.big[i] = big_w;
27037
27038                small_p = (big_w - (big_p * (i - 1))) / (local_small_max + 1);
27039
27040                for (z = 1; z <= local_small_max; z++) {
27041                    if (big_w === 0) {
27042                        break;
27043                    }
27044
27045                    small_w = this.toFixed(big_w - (small_p * z));
27046
27047                    html += '<span class="irs-grid-pol small" style="left: ' + small_w + '%"></span>';
27048                }
27049
27050                html += '<span class="irs-grid-pol" style="left: ' + big_w + '%"></span>';
27051
27052                result = this.convertToValue(big_w);
27053                if (o.values.length) {
27054                    result = o.p_values[result];
27055                } else {
27056                    result = this._prettify(result);
27057                }
27058
27059                html += '<span class="irs-grid-text js-grid-text-' + i + '" style="left: ' + big_w + '%">' + result + '</span>';
27060            }
27061            this.coords.big_num = Math.ceil(big_num + 1);
27062
27063
27064
27065            this.$cache.cont.addClass("irs-with-grid");
27066            this.$cache.grid.html(html);
27067            this.cacheGridLabels();
27068        },
27069
27070        cacheGridLabels: function () {
27071            var $label, i,
27072                num = this.coords.big_num;
27073
27074            for (i = 0; i < num; i++) {
27075                $label = this.$cache.grid.find(".js-grid-text-" + i);
27076                this.$cache.grid_labels.push($label);
27077            }
27078
27079            this.calcGridLabels();
27080        },
27081
27082        calcGridLabels: function () {
27083            var i, label, start = [], finish = [],
27084                num = this.coords.big_num;
27085
27086            for (i = 0; i < num; i++) {
27087                this.coords.big_w[i] = this.$cache.grid_labels[i].outerWidth(false);
27088                this.coords.big_p[i] = this.toFixed(this.coords.big_w[i] / this.coords.w_rs * 100);
27089                this.coords.big_x[i] = this.toFixed(this.coords.big_p[i] / 2);
27090
27091                start[i] = this.toFixed(this.coords.big[i] - this.coords.big_x[i]);
27092                finish[i] = this.toFixed(start[i] + this.coords.big_p[i]);
27093            }
27094
27095            if (this.options.force_edges) {
27096                if (start[0] < -this.coords.grid_gap) {
27097                    start[0] = -this.coords.grid_gap;
27098                    finish[0] = this.toFixed(start[0] + this.coords.big_p[0]);
27099
27100                    this.coords.big_x[0] = this.coords.grid_gap;
27101                }
27102
27103                if (finish[num - 1] > 100 + this.coords.grid_gap) {
27104                    finish[num - 1] = 100 + this.coords.grid_gap;
27105                    start[num - 1] = this.toFixed(finish[num - 1] - this.coords.big_p[num - 1]);
27106
27107                    this.coords.big_x[num - 1] = this.toFixed(this.coords.big_p[num - 1] - this.coords.grid_gap);
27108                }
27109            }
27110
27111            this.calcGridCollision(2, start, finish);
27112            this.calcGridCollision(4, start, finish);
27113
27114            for (i = 0; i < num; i++) {
27115                label = this.$cache.grid_labels[i][0];
27116
27117                if (this.coords.big_x[i] !== Number.POSITIVE_INFINITY) {
27118                    label.style.marginLeft = -this.coords.big_x[i] + "%";
27119                }
27120            }
27121        },
27122
27123        // Collisions Calc Beta
27124        // TODO: Refactor then have plenty of time
27125        calcGridCollision: function (step, start, finish) {
27126            var i, next_i, label,
27127                num = this.coords.big_num;
27128
27129            for (i = 0; i < num; i += step) {
27130                next_i = i + (step / 2);
27131                if (next_i >= num) {
27132                    break;
27133                }
27134
27135                label = this.$cache.grid_labels[next_i][0];
27136
27137                if (finish[i] <= start[next_i]) {
27138                    label.style.visibility = "visible";
27139                } else {
27140                    label.style.visibility = "hidden";
27141                }
27142            }
27143        },
27144
27145        calcGridMargin: function () {
27146            if (!this.options.grid_margin) {
27147                return;
27148            }
27149
27150            this.coords.w_rs = this.$cache.rs.outerWidth(false);
27151            if (!this.coords.w_rs) {
27152                return;
27153            }
27154
27155            if (this.options.type === "single") {
27156                this.coords.w_handle = this.$cache.s_single.outerWidth(false);
27157            } else {
27158                this.coords.w_handle = this.$cache.s_from.outerWidth(false);
27159            }
27160            this.coords.p_handle = this.toFixed(this.coords.w_handle  / this.coords.w_rs * 100);
27161            this.coords.grid_gap = this.toFixed((this.coords.p_handle / 2) - 0.1);
27162
27163            this.$cache.grid[0].style.width = this.toFixed(100 - this.coords.p_handle) + "%";
27164            this.$cache.grid[0].style.left = this.coords.grid_gap + "%";
27165        },
27166
27167
27168
27169        // =============================================================================================================
27170        // Public methods
27171
27172        update: function (options) {
27173            if (!this.input) {
27174                return;
27175            }
27176
27177            this.is_update = true;
27178
27179            this.options.from = this.result.from;
27180            this.options.to = this.result.to;
27181            this.update_check.from = this.result.from;
27182            this.update_check.to = this.result.to;
27183
27184            this.options = $.extend(this.options, options);
27185            this.validate();
27186            this.updateResult(options);
27187
27188            this.toggleInput();
27189            this.remove();
27190            this.init(true);
27191        },
27192
27193        reset: function () {
27194            if (!this.input) {
27195                return;
27196            }
27197
27198            this.updateResult();
27199            this.update();
27200        },
27201
27202        destroy: function () {
27203            if (!this.input) {
27204                return;
27205            }
27206
27207            this.toggleInput();
27208            this.$cache.input.prop("readonly", false);
27209            $.data(this.input, "ionRangeSlider", null);
27210
27211            this.remove();
27212            this.input = null;
27213            this.options = null;
27214        }
27215    };
27216
27217    $.fn.ionRangeSlider = function (options) {
27218        return this.each(function() {
27219            if (!$.data(this, "ionRangeSlider")) {
27220                $.data(this, "ionRangeSlider", new IonRangeSlider(this, options, plugin_count++));
27221            }
27222        });
27223    };
27224
27225
27226
27227    // =================================================================================================================
27228    // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
27229    // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
27230
27231    // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
27232
27233    // MIT license
27234
27235    (function() {
27236        var lastTime = 0;
27237        var vendors = ['ms', 'moz', 'webkit', 'o'];
27238        for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
27239            window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
27240            window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
27241                || window[vendors[x]+'CancelRequestAnimationFrame'];
27242        }
27243
27244        if (!window.requestAnimationFrame)
27245            window.requestAnimationFrame = function(callback, element) {
27246                var currTime = new Date().getTime();
27247                var timeToCall = Math.max(0, 16 - (currTime - lastTime));
27248                var id = window.setTimeout(function() { callback(currTime + timeToCall); },
27249                    timeToCall);
27250                lastTime = currTime + timeToCall;
27251                return id;
27252            };
27253
27254        if (!window.cancelAnimationFrame)
27255            window.cancelAnimationFrame = function(id) {
27256                clearTimeout(id);
27257            };
27258    }());
27259
27260}));
27261
27262
27263
27264// Trigger
27265
27266$(function () {
27267  
27268        var $range = $(".js-range-slider"),
27269            $inputFrom = $(".js-input-from"),
27270            $inputTo = $(".js-input-to"),
27271            instance,
27272            min = 0,
27273            max = 1000000,
27274            from = 0,
27275            to = 0;
27276
27277        $range.ionRangeSlider({
27278            type: "double",
27279            min: min,
27280            max: max,
27281            from: 20000,
27282            to: 500000,
27283          prefix: '$ ',
27284            onStart: updateInputs,
27285            onChange: updateInputs,
27286            step: 50000,
27287            prettify_enabled: true,
27288            prettify_separator: ".",
27289          values_separator: " - ",
27290          force_edges: true
27291          
27292
27293        });
27294
27295        instance = $range.data("ionRangeSlider");
27296
27297        function updateInputs (data) {
27298            from = data.from;
27299            to = data.to;
27300            
27301            $inputFrom.prop("value", from).keyup(resizeInput).each(resizeInput);
27302            $inputTo.prop("value", to).keyup(resizeInput).each(resizeInput);
27303        }
27304
27305        $inputFrom.on("input", function () {
27306            var val = $(this).prop("value");
27307            
27308            // validate
27309            if (val < min) {
27310                val = min;
27311            } else if (val > to) {
27312                val = to;
27313            }
27314            
27315            instance.update({
27316                from: val
27317            });
27318        });
27319
27320        $inputTo.on("input", function () {
27321            var val = $(this).prop("value");
27322            
27323            // validate
27324            if (val < from) {
27325                val = from;
27326            } else if (val > max) {
27327                val = max;
27328            }
27329            
27330            instance.update({
27331                to: val
27332            });
27333        });
27334
27335});$(function () {
27336    let $sel = $('[data-unicode="mdu_2veuzibqk0e0gEOxBS0qFg"]');
27337    $sel.each (async function () {
27338        let $id = base62();
27339        $(this).find('form').attr('id',$id);
27340
27341        // 初始化設定資料
27342        let settingData = [];
27343        await initFormSettings($id).then(data => settingData = data);
27344        console.log('websetting data: ' + settingData);
27345
27346        // -----------------------------------
27347        // 出發起迄設定
27348        let $startDate = $('#' + $id).find('.date-start');
27349        let $endDate = $('#' + $id).find('.date-end');
27350        let pickerDate = new Date();
27351        $('#'+$id).find('.date-start , .date-end').datepicker({
27352            format: "yyyy/mm/dd",
27353            startDate: new Date(),
27354            clearBtn: true,
27355            autoclose: true,
27356            toggleActive: true,
27357            defaultDate: new Date(),
27358            language:"zh-TW"
27359        });
27360
27361        //日期區間設定
27362        let startDateOffset = getSettingValue(settingData, "SEARCH_SDATE_OFFSET");
27363        console.log('startDateOffset: ' + startDateOffset);
27364        startDateOffset = Math.min(parseInt(startDateOffset), 60);
27365        console.log('startDateOffset: ' + startDateOffset);
27366        let $daterange = $('#' + $id).find('#daterange_value');
27367        let daterange = 0;
27368        if ($daterange.val() !== '' && !isNaN(parseInt($daterange.val()))) {
27369            daterange = parseInt($daterange.val());
27370        } else {
27371            daterange = getSettingValue(settingData, "SEARCH_DATE_INTERVAL");
27372            daterange = parseInt(daterange || "0");
27373             console.log('daterange: ' + daterange);
27374        }
27375        
27376        let date = new Date(new Date().getTime() + startDateOffset * 24 * 60 * 60 * 1000);
27377        let month = (date.getMonth() + 1) + daterange;
27378        let yaer = date.getFullYear();
27379        if (month > 12) {           //是否超過12月判斷
27380            yaer += Math.floor(month / 12);
27381            month = (month % 12);
27382        }
27383        date.setFullYear(yaer);
27384        date.setMonth(month - 1);
27385
27386        $startDate.datepicker('setDate', new Date(new Date().getTime() + startDateOffset * 24 * 60 * 60 * 1000));//出發時間
27387        $endDate.datepicker('setDate', date);//目的地時間
27388        
27389        // 結束日期的選擇變化
27390        $endDate.datepicker().on('blur', function (e) {
27391            if ($endDate.datepicker('getDate') < $startDate.datepicker('getDate')) {
27392                alert("出發期間迄日不可小於出發期間起日");
27393                $endDate.datepicker('setDate', $startDate.datepicker('getDate'));  // 重置結束日期爲起始日期
27394            }
27395        });
27396        // -----------------------------------
27397
27398        let $depregions = $('#'+$id).find('[data-inputtype="depregions"]');
27399        $depregions.attr('id','depregions_'+$id+'_');
27400        $.post($depregions.data('url'), { }, function (data) {
27401            $depregions.areaSelector(data);
27402        }, "json");
27403
27404        let $depregionscode = $('#'+$id).find('[data-inputtype="depregionscode"]');
27405        $depregionscode.attr('id','depregions_'+$id+'_code');
27406
27407        let $regions = $('#'+$id).find('[data-inputtype="regions"]');
27408        $regions.attr('id','regions'+$id+'_');
27409        $.post($regions.data('url'), { }, function (data) {
27410            $regions.areaSelector(data);
27411        }, "json");
27412
27413        let $regionscode = $('#'+$id).find('[data-inputtype="regionscode"]');
27414        $regionscode.attr('id','regions'+$id+'_code');
27415
27416        $depregions.on("change", function () {
27417            if ($depregions.val().trim() == "")
27418                $depregionscode.val("");
27419
27420            var dCode = $depregionscode.val().split("-");
27421            var dData = { "DepRegmCode": dCode[0], "DepRegsCode": dCode[1] };
27422            $.ajax({
27423                url: $regions.data("url"),
27424                data: dData,
27425                type: 'POST',
27426                dataType: 'json',
27427                success: function (data) {
27428                    $regions.siblings('.area_content').remove();
27429                    $regions.val('');
27430                    $regionscode.val('');
27431                    $regions.areaSelector(data);
27432                },
27433                error: function (error) {
27434                    console.log(error);
27435                }
27436            });
27437        });
27438
27439        // 可報名CHECKBOX觸發
27440        $('#IsJoin').on('change', function() {
27441            if ($(this).is(':checked')) {
27442                $(this).val('true');
27443            } else {
27444                $(this).val('');
27445            }
27446        });
27447
27448        // -----------------------------------
27449        // 保證出發字漾吃 ZC 站台設定
27450        let guaranteeText = getSettingValue(settingData, "DSP_GUARANTEE_TXT");
27451        console.log('guaranteeText: ' + guaranteeText);
27452        if (guaranteeText !== '' || !isNaN(guaranteeText))
27453            $('#'+$id).find("#GuaranteeText").text(guaranteeText);
27454        
27455        // 保證出發CHECKBOX觸發
27456        $('#IsGuarantee').on('change', function() {
27457            if ($(this).is(':checked')) {
27458                $(this).val('true');
27459            } else {
27460                $(this).val('');
27461            }
27462        });
27463        // -----------------------------------
27464
27465        jQuery.fn.areaSelector = function (argument) {
27466
27467            var areaData; //默認地區資訊
27468            var thisId = $(this).attr("id");
27469            var contentId = thisId + 'AreaContent';
27470            var mainRegs;
27471            var twoRegs;
27472            var isTopLavel;
27473            if (argument) {
27474                areaData = argument;
27475            } else {
27476                //默認地區資訊
27477                areaData = [
27478                    { name: '台北', code: 'TPE', mcode: 'TWN', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27479                    { name: '基隆', code: 'HSZ', mcode: 'TWN', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27480                    { name: '新北', code: 'TPQ', mcode: 'TWN', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27481                    { name: '三重', code: '0001', mcode: 'TWN', std: 0, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27482                    { name: '永和', code: '0002', mcode: 'TWN', std: 0, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27483                    { name: '板橋', code: '0003', mcode: 'TWN', std: 0, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27484                    { name: '桃園', code: 'TYC', mcode: 'TWN', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27485                    { name: '新竹', code: 'HSZ', mcode: 'TWN', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27486                    { name: '台中', code: '21', mcode: 'TWM', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27487                    { name: '烏日', code: '22', mcode: 'TWM', std: 0, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27488                    { name: '彰化', code: '22', mcode: 'TWM', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27489                    { name: '南投', code: '23', mcode: 'TWM', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27490                    { name: '雲林', code: '24', mcode: 'TWM', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27491                    { name: '虎尾', code: '22', mcode: 'TWM', std: 0, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27492                    { name: '苗栗', code: '25', mcode: 'TWM', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '01' }] }] },
27493                    { name: '高雄', code: '31', mcode: 'TWS', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '02' }] }] },
27494                    { name: '台南', code: '32', mcode: 'TWS', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '03' }] }] },
27495                    { name: '屏東', code: '33', mcode: 'TWS', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '02' }] }] },
27496                    { name: '嘉義', code: '34', mcode: 'TWS', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '05' }] }] },
27497                    { name: '枋寮', code: '35', mcode: 'TWS', std: 0, state: [{ name: '', code: '01', city: [{ name: '', code: '04' }] }] },
27498                    { name: '宜蘭', code: '41', mcode: 'TWE', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '02' }] }] },
27499                    { name: '花蓮', code: '42', mcode: 'TWE', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '02' }] }] },
27500                    { name: '台東', code: '43', mcode: 'TWE', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '02' }] }] },
27501                    { name: '澎湖', code: '51', mcode: 'TWI', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '02' }] }] },
27502                    { name: '馬祖', code: '52', mcode: 'TWI', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '02' }] }] },
27503                    { name: '金門', code: '53', mcode: 'TWI', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '02' }] }] },
27504                    { name: '蘭嶼', code: '54', mcode: 'TWO', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '02' }] }] },
27505                    { name: 'ç¶ å³¶', code: '55', mcode: 'TWO', std: 1, state: [{ name: '', code: '01', city: [{ name: '', code: '04' }] }] }
27506                ]
27507            };
27508
27509            //input框點擊事件
27510            $(this).on('click', function () {
27511                $("#" + contentId).addClass('isBlock');
27512                if (isTopLavel) {
27513                    var $selector = $('#' + contentId + ' div.area_menu ul li').first();
27514                    $selector.addClass('isClick').siblings().removeClass('isClick');
27515                    $('#show' + contentId + $selector.attr("id")).addClass('isBlock').siblings().removeClass('isBlock')
27516                }
27517            })
27518
27519            //非選擇地區即關閉下拉框
27520            $(document).mouseup(function (e) {
27521                var _con = $("#" + contentId);
27522                if (!_con.is(e.target) && _con.has(e.target).length === 0)
27523                    $("#" + contentId).removeClass('isBlock')
27524            });
27525
27526            createAreaContent();
27527            setAreaName();
27528
27529            //初始化地區選擇框
27530            function createAreaContent() {
27531                isTopLavel = (areaData.filter(e => e.istoplavel == true)?.length > 0) ? true : false;
27532                if (isTopLavel) 
27533                {
27534                    mainRegs = areaData
27535                        .filter(function (e) { return e.mtype == 'R' })
27536                        .map(function (e) { return e.mname })
27537                        .reduce(function (prev, cur) { return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev; }, []);
27538                    twoRegs = areaData
27539                        .filter(function (e) { return e.mtype == 'F' })
27540                        .map(function (e) { return e.mname })
27541                        .reduce(function (prev, cur) { return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev; }, []);
27542                }
27543                else {
27544                    mainRegs = areaData
27545                        .map(function (e) { return e.mname })
27546                        .reduce(function (prev, cur) { return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev; }, []);
27547                }
27548
27549                var html = '';
27550                html += '<div class="area_content" id="' + contentId + '">';
27551                html += '<div class="area_data_content">';
27552                html += '    <div class="area_menu">';
27553                if (isTopLavel) {
27554                    html += '<ul>';
27555                    if (mainRegs.length > 0)
27556                        html += '    <li id="Main" class="isClick">城市快搜</li>';
27557
27558                    if (twoRegs?.length > 0)
27559                        html += '    <li id="Two">
27559主題旅遊</li>';
27560
27561                    html += '</ul>';
27562                }
27563                html += '    </div>';
27564
27565                var data_string = "";
27566                if (mainRegs.length > 0) {
27567                    html += '<div id="show' + contentId + 'Main" class="area_data data_province isBlock">';
27568                    mainRegs.forEach(function (item, i) {
27569                        // 城市快搜-大分類
27570                        if (isTopLavel) {
27571                            var mainItem = areaData.find(function (e) { return (e.mname == item); });
27572                            if (mainItem != undefined) {
27573                                data_string = ' data-areacode="' + mainItem.mcode + '" style="cursor: pointer"';
27574                            }
27575                        }
27576                        html += '    <div class="data_Part part_' + (i + 1) + '">';
27577                        html += '         <a class="part_type"' + data_string + '>' + item + '</a>';
27578                        html += '         <ul></ul>';
27579                        html += '     </div>';
27580                    });
27581                    html += '</div>';
27582                }
27583                if (twoRegs?.length > 0) {
27584                    html += '<div id="show' + contentId +'Two" class="area_data data_region">';
27585                    twoRegs.forEach(function (item, i) {
27586                        html += '    <div class="data_Part part_' + (i + 1) + '">';
27587                        html += '         <a class="part_type">' + item + '</a>';
27588                        html += '         <ul></ul>';
27589                        html += '     </div>';
27590                    });
27591                    html += '</div>';
27592                }
27593
27594                html += '</div></div>';
27595
27596                $('#' + thisId).after(html);
27597                if (isTopLavel) {
27598                    bindMainAreaEvent();
27599                }
27600                createProvince();
27601            }
27602
27603            function setAreaName()
27604             {
27605                if ($("#" + thisId + "code").val() != "") 
27606                    {
27607                    var row = areaData.filter(function (e) { return (e.mcode + '-' + e.scode) == $("#" + thisId + "code").val() });
27608                    $("#" + thisId).val(row[0].sname);
27609                }
27610            }
27611
27612            //切換頁籤
27613            $(document).on('click', '#' + contentId + ' div.area_menu ul li', function () {
27614                $(this).addClass('isClick').siblings().removeClass('isClick');
27615                $('#show' + contentId + $(this).attr("id")).addClass('isBlock').siblings().removeClass('isBlock')
27616            })
27617
27618
27619            /*選擇操作響應*/
27620            function replyOperation(tp) {
27621                var cssName;
27622                var theRegion;
27623                var theRegCode;
27624
27625                switch (tp) {
27626                    case 'p': cssName = 'data_province'; break;
27627                    case 'r': cssName = 'data_region'; break;
27628                    default:
27629                }
27630                $(document).on('click', '#' + contentId + ' .' + cssName + ' li', function () {
27631                    theRegion = $(this).children('a').text();
27632                    theRegCode = $(this).children('a').attr('data-areacode');
27633
27634                    $('#' + thisId).val(theRegion);
27635                    $('#' + thisId + 'code').val(theRegCode); //取回選擇的值
27636                    $('#' + contentId).removeClass('isBlock');
27637                    $(".data_region").removeClass('isBlock');
27638                    resetMenu();
27639
27640                    $('#' + thisId).trigger('change');
27641                });
27642            }
27643
27644            // 城市快搜-大分類 點擊
27645            function bindMainAreaEvent() {
27646                $('#' + contentId).find('a.part_type[data-areacode]').on('click', function () {
27647                    theRegion = $(this).text();
27648                    theRegCode = $(this).attr('data-areacode');
27649
27650                    $('#' + thisId).val(theRegion);
27651                    $('#' + thisId + 'code').val(theRegCode);
27652                    $('#' + contentId).removeClass('isBlock');
27653                    $(".data_region").removeClass('isBlock');
27654                    resetMenu();
27655
27656                    $('#' + thisId).trigger('change');
27657                });
27658            }
27659
27660            function resetMenu() {
27661                $('#' + contentId + ' div.area_menu ul li').each(function (e) {
27662                    $(this).removeClass('isClick');
27663                    if (e == 0)
27664                        $(this).addClass('isClick');
27665                });
27666                $('#' + thisId).addClass('isBlock');
27667            }
27668
27669            //創建出發地/目的地
27670            function createProvince() {
27671                var areaHtml = '';
27672
27673                mainRegs?.forEach(function (item, i) {
27674                    areaHtml = '';
27675                    var areas = areaData.filter(function (e) { return (e.mname == item); });
27676                    areas.forEach(function (e) {
27677                        areaHtml += '<li>
27677<a data-areacode="' + e.mcode + '-' + e.scode + '">' + e.sname + '</a></li>';
27678                    });
27679                    $('#' + contentId + ' .data_province .part_' + (i + 1) + ' ul').html(areaHtml);
27680                });
27681                twoRegs?.forEach(function (item, i) {
27682                    areaHtml = '';
27683                    var areas = areaData.filter(function (e) { return (e.mname == item); });
27684                    areas.forEach(function (e) {
27685                        areaHtml += '<li><a data-areacode="' + e.mcode + '-' + e.scode + '">' + e.sname + '</a></li>';
27686                    });
27687                    $('#show'+ contentId +'Two .part_' + (i + 1) + ' ul').html(areaHtml);
27688                });
27689
27690                if (mainRegs?.length > 0) replyOperation('p');
27691                if (twoRegs?.length > 0) replyOperation('r');
27692            }
27693        }
27694
27695        // 檢查瀏覽器是否支援 webkitSpeechRecognition
27696        if ("webkitSpeechRecognition" in window) {
27697            //Web Speech API
27698            const recognition = new webkitSpeechRecognition();
27699
27700            function startSpeechRecognition() {
27701
27702                // 設置識別語言為中文
27703                recognition.lang = "zh-TW";
27704
27705                // 設置連續識別模式
27706                recognition.continuous = true;
27707
27708                // 設置識別結果是否包含中間結果
27709                recognition.interimResults = false;
27710
27711                // 定義搜尋計時器變量
27712                let searchTimer = null;
27713
27714                // 監聽語音識別結果
27715                recognition.onresult = function (event) {
27716                    const result = event.results[event.resultIndex][0].transcript;
27717                    filterKeyword().value = result;
27718
27719                    // 取消搜尋計時器
27720                    clearTimeout(searchTimer);
27721
27722                    // 啟動新的搜尋計時器
27723                    searchTimer = setTimeout(() => {
27724                        performSearch();
27725                    }, 1000);
27726                };
27727
27728                // 監聽語音識別結束事件
27729                recognition.onend = () => {
27730                    // 停止語音識別
27731                    recognitionStop();
27732                };
27733
27734                // 監聽語音識別錯誤事件
27735                recognition.onerror = (event) => {
27736                    console.error(`語音識別錯誤:${event.error}`);
27737                    // 停止語音識別
27738                    recognitionStop();
27739                };
27740                // 定義搜索
27741                function performSearch() {
27742                    $("#" + $id).find('.search-btn').click();
27743                }
27744
27745                // 監聽使用者停止說話事件
27746                recognition.onspeechend = () => {
27747                    // 停止語音識別
27748                    recognitionStop();
27749
27750                    // 取消搜尋計時器
27751                    if (searchTimer !== null) {
27752                        clearTimeout(searchTimer);
27753                    }
27754
27755                    // 啟動新的搜尋計時器
27756                    searchTimer = setTimeout(() => {
27757                        performSearch();
27758                    }, 500);
27759                };
27760
27761                // 設置語音識別超時,如果使用者沒有在6秒內說話,則停止語音識別
27762                setTimeout(() => {
27763                    recognitionStop();
27764                }, 6000);
27765
27766                // 啟動語音識別
27767                recognitionStart();
27768            }
27769
27770            //控制Icon
27771            function setIconVisibility(micIconVisible, chartIconVisible) {
27772                $('.micIcon').css('visibility', micIconVisible ? 'visible' : 'hidden');
27773                $('.chartIcon').css('visibility', chartIconVisible ? 'visible' : 'hidden');
27774            }
27775
27776            //控制語音輸入
27777            function recognitionStart() {
27778                recognition.start();
27779                setIconVisibility(false, true);
27780            }
27781
27782            function recognitionStop() {
27783                recognition.stop();
27784                setIconVisibility(true, false);
27785            }
27786            //--------------------------------------------------Web Speech API Modal
27787            micButton().on('click', function () {
27788
27789                // 設定燈箱開啟時禁止滑動
27790                $('body').css('overflow', 'hidden');
27791
27792                // 設定燈箱樣式
27793                const dialog = $('<div></div>').css({
27794                    position: 'fixed',
27795                    bottom: '-50%', // 設定起始位置
27796                    left: '0',
27797                    width: '100%',
27798                    height: '30%',
27799                    background: '#fff',
27800                    boxShadow: '0 0 10px rgba(0, 0, 0, 0.5)',
27801                    borderTopLeftRadius: '10px',
27802                    borderTopRightRadius: '10px'
27803                });
27804
27805                // 文字標題
27806                const message = $('<div>請說</div>').css({
27807                    position: 'absolute',
27808                    top: '20%',
27809                    left: '50%',
27810                    transform: 'translate(-50%, -50%)',
27811                    fontSize: '20px',
27812                    fontWeight: 'bold'
27813                });
27814                dialog.append(message);
27815
27816                // 文字內容1
27817                const grayText1 = $('<div>請說出您要搜尋的關鍵字</div>').css({
27818                    color: '#777',
27819                    fontSize: '15px',
27820                    position: 'absolute',
27821                    top: '35%',
27822                    left: '50%',
27823                    transform: 'translate(-50%, -50%)'
27824                });
27825                dialog.append(grayText1);
27826
27827                // 文字內容2
27828                const grayText2 = $('<div>例如:東京、奧地利、巴里島...</div>').css({
27829                    color: '#777',
27830                    fontSize: '15px',
27831                    position: 'absolute',
27832                    top: '55%',
27833                    left: '50%',
27834                    transform: 'translate(-50%, -50%)'
27835                });
27836                dialog.append(grayText2);
27837
27838                // 麥克風 Icon
27839                const micIcon = $('<div class="micIcon"><i class="fa fa-microphone"></i></div>').css({
27840                    position: 'absolute',
27841                    top: '75%',
27842                    left: '50%',
27843                    transform: 'translate(-50%, -50%)'
27844                });
27845                micIcon.find('i').css({
27846                    color:'#777',
27847                    fontSize: '40px'
27848                });
27849                dialog.append(micIcon);
27850                micIcon.on('click', startSpeechRecognition);
27851
27852                // 波型 Icon
27853                for (let i = 1; i <= 4; i++) {
27854                    const chartIcon = $('<div class="chartIcon"><i class="fa fa-align-center"></i></div>').css({
27855                        position: 'absolute',
27856                        top: '70%',
27857                        left: (28 + i * 7) + '%',
27858                    });
27859                    chartIcon.find('i').css({
27860                        color: '#777',
27861                        fontSize: '33px',
27862                        transform: i % 2 == 1 ? 'rotate(-90deg)' : 'rotate(90deg)'
27863                    });
27864                    dialog.append(chartIcon);
27865                }
27866
27867                // 設定半透明背景樣式
27868                const body = $('body');
27869                const bg = $('<div></div>');
27870                bg.css({
27871                    'position': 'fixed',
27872                    'top': '0',
27873                    'left': '0',
27874                    'width': '100%',
27875                    'height': '100%',
27876                    'background-color': 'rgba(0, 0, 0, 0.5)'
27877                });
27878
27879                const wrapper = $('<div></div>');
27880                wrapper.css({
27881                    'position': 'fixed',
27882                    'top': '0',
27883                    'left': '0',
27884                    'width': '100%',
27885                    'height': '100%',
27886                    'z-index': '9998'
27887                });
27888                wrapper.append(bg);
27889                wrapper.append(dialog);
27890                body.append(wrapper);
27891
27892                // 關閉按鈕
27893                const closeButton = $('<button>&times;</button>');
27894                closeButton.css({
27895                    position: 'absolute',
27896                    top: '10px',
27897                    right: '10px',
27898                    border: 'none',
27899                    background: 'none',
27900                    fontSize: '30px',
27901                    cursor: 'pointer'
27902                });
27903                dialog.append(closeButton);
27904
27905                // 燈箱動畫
27906                const dialogHeight = $(dialog).outerHeight();
27907                $(dialog).css('bottom', '-' + dialogHeight + 'px');
27908                setTimeout(function () {
27909                    $(dialog).css({
27910                        'transition': 'bottom 0.3s ease-out',
27911                        'bottom': '0'
27912                    });
27913                }, 10);
27914                const closeDialog = function () {
27915                    recognition.stop();
27916                    $(dialog).css('bottom', '-' + dialogHeight + 'px');
27917                    setTimeout(function () {
27918                        $(bg).remove();
27919                        $(dialog).remove();
27920                        $(wrapper).remove();
27921                        $('body').css('overflow', 'auto');
27922                    }, 300);
27923                }
27924                $(closeButton).on('click', closeDialog);
27925                $(bg).on('click', closeDialog);
27926                startSpeechRecognition();
27927            });
27928        } else {
27929            console.error("Your browser doesn't support webkitSpeechRecognition");
27930        }
27931
27932        //防止URL直接帶入NaN
27933        let $travelType = $('#'+$id).find('#travel_type');
27934        if($travelType.attr('name') === "NaN") 
27935        {
27936            $travelType.attr('name','');
27937        }
27938
27939        //手機版語音輸入
27940        function micButton() {
27941            return $("#" + $id).find(".mic_icon .fa-microphone");
27942        }
27943
27944        function filterKeyword() {
27945            return $("#" + $id).find("#Filter_Keyword")[0];
27946        }
27947
27948        // 取得 WebSetting 資料
27949        async function initFormSettings($id) {
27950            let settingUrl = $('#' + $id).data('setting-url');
27951            try {
27952                let response = await postJsonAsync(settingUrl);
27953                console.log('websetting data: ' + response);
27954                return response.Data || [];
27955            } catch (e) {
27956                console.error("載入設定失敗:", e);
27957                return [];
27958            }
27959        }
27960
27961        // 取指定站台設定的 key - value
27962        function getSettingValue(dataArray, key) {
27963            const item = dataArray.find(x => x.Key === key);
27964            return item ? item.Value : null;
27965        }
27966
27967        function postJsonAsync(url, data = {}) {
27968            return new Promise((resolve, reject) => {
27969                $.post({
27970                    url: url,
27971                    data: JSON.stringify(data),
27972                    contentType: "application/json",
27973                    dataType: "json",
27974                    success: resolve,
27975                    error: reject
27976                });
27977            });
27978        }
27979    });
27980
27981}); })(jQuery);/* compress error:[4]function encode(int) {*/
27982
27983/* MODULE e473bc81-4061-49f5-8b09-d51e32e0ebe3, Version: 2.1.8 */
27984;(function($) {/*
27985 * File: iframeResizer.js
27986 * Desc: Force iframes to size to content.
27987 * Requires: iframeResizer.contentWindow.js to be loaded into the target frame.
27988 * Doc: https://github.com/davidjbradshaw/iframe-resizer
27989 * Author: David J. Bradshaw - [email protected]
27990 * Contributor: Jure Mav - [email protected]
27991 * Contributor: Reed Dadoune - [email protected]
27992 */
27993
27994(function(undefined) {
27995    'use strict';
27996  
27997    if (typeof window === 'undefined') return; // don't run for server side render
27998  
27999    var count = 0,
28000      logEnabled = false,
28001      hiddenCheckEnabled = false,
28002      msgHeader = 'message',
28003      msgHeaderLen = msgHeader.length,
28004      msgId = '[iFrameSizer]', //Must match iframe msg ID
28005      msgIdLen = msgId.length,
28006      pagePosition = null,
28007      requestAnimationFrame = window.requestAnimationFrame,
28008      resetRequiredMethods = {
28009        max: 1,
28010        scroll: 1,
28011        bodyScroll: 1,
28012        documentElementScroll: 1
28013      },
28014      settings = {},
28015      timer = null,
28016      logId = 'Host Page',
28017      defaults = {
28018        autoResize: true,
28019        bodyBackground: null,
28020        bodyMargin: null,
28021        bodyMarginV1: 8,
28022        bodyPadding: null,
28023        checkOrigin: true,
28024        inPageLinks: false,
28025        enablePublicMethods: true,
28026        heightCalculationMethod: 'bodyOffset',
28027        id: 'iFrameResizer',
28028        interval: 32,
28029        log: false,
28030        maxHeight: Infinity,
28031        maxWidth: Infinity,
28032        minHeight: 0,
28033        minWidth: 0,
28034        resizeFrom: 'parent',
28035        scrolling: false,
28036        sizeHeight: true,
28037        sizeWidth: false,
28038        warningTimeout: 5000,
28039        tolerance: 0,
28040        widthCalculationMethod: 'scroll',
28041        closedCallback: function() {},
28042        initCallback: function() {},
28043        messageCallback: function() {
28044          warn('MessageCallback function not defined');
28045        },
28046        resizedCallback: function() {},
28047        scrollCallback: function() {
28048          return true;
28049        }
28050      };
28051  
28052    function getMutationObserver() {
28053      return window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
28054    }
28055  
28056    function addEventListener(obj, evt, func) {
28057      /* istanbul ignore else */ // Not testable in PhantonJS
28058      if ('addEventListener' in window) {
28059        obj.addEventListener(evt, func, false);
28060      } else if ('attachEvent' in window) {
28061        //IE
28062        obj.attachEvent('on' + evt, func);
28063      }
28064    }
28065  
28066    function removeEventListener(el, evt, func) {
28067      /* istanbul ignore else */ // Not testable in phantonJS
28068      if ('removeEventListener' in window) {
28069        el.removeEventListener(evt, func, false);
28070      } else if ('detachEvent' in window) {
28071        //IE
28072        el.detachEvent('on' + evt, func);
28073      }
28074    }
28075  
28076    function setupRequestAnimationFrame() {
28077      var vendors = ['moz', 'webkit', 'o', 'ms'],
28078        x;
28079  
28080      // Remove vendor prefixing if prefixed and break early if not
28081      for (x = 0; x < vendors.length && !requestAnimationFrame; x += 1) {
28082        requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
28083      }
28084  
28085      if (!requestAnimationFrame) {
28086        log('setup', 'RequestAnimationFrame not supported');
28087      }
28088    }
28089  
28090    function getMyID(iframeId) {
28091      var retStr = 'Host page: ' + iframeId;
28092  
28093      if (window.top !== window.self) {
28094        if (window.parentIFrame && window.parentIFrame.getId) {
28095          retStr = window.parentIFrame.getId() + ': ' + iframeId;
28096        } else {
28097          retStr = 'Nested host page: ' + iframeId;
28098        }
28099      }
28100  
28101      return retStr;
28102    }
28103  
28104    function formatLogHeader(iframeId) {
28105      return msgId + '[' + getMyID(iframeId) + ']';
28106    }
28107  
28108    function isLogEnabled(iframeId) {
28109      return settings[iframeId] ? settings[iframeId].log : logEnabled;
28110    }
28111  
28112    function log(iframeId, msg) {
28113      output('log', iframeId, msg, isLogEnabled(iframeId));
28114    }
28115  
28116    function info(iframeId, msg) {
28117      output('info', iframeId, msg, isLogEnabled(iframeId));
28118    }
28119  
28120    function warn(iframeId, msg) {
28121      output('warn', iframeId, msg, true);
28122    }
28123  
28124    function output(type, iframeId, msg, enabled) {
28125      
28126    }
28127  
28128    function iFrameListener(event) {
28129      function resizeIFrame() {
28130        function resize() {
28131          setSize(messageData);
28132          setPagePosition(iframeId);
28133          callback('resizedCallback', messageData);
28134        }
28135  
28136        ensureInRange('Height');
28137        ensureInRange('Width');
28138  
28139        syncResize(resize, messageData, 'init');
28140      }
28141  
28142      function processMsg() {
28143        var data = msg.substr(msgIdLen).split(':');
28144  
28145        return {
28146          iframe: settings[data[0]] && settings[data[0]].iframe,
28147          id: data[0],
28148          height: data[1],
28149          width: data[2],
28150          type: data[3]
28151        };
28152      }
28153  
28154      function ensureInRange(Dimension) {
28155        var max = Number(settings[iframeId]['max' + Dimension]),
28156          min = Number(settings[iframeId]['min' + Dimension]),
28157          dimension = Dimension.toLowerCase(),
28158          size = Number(messageData[dimension]);
28159  
28160        log(
28161          iframeId,
28162          'Checking ' + dimension + ' is in range ' + min + '-' + max
28163        );
28164  
28165        if (size < min) {
28166          size = min;
28167          log(iframeId, 'Set ' + dimension + ' to min value');
28168        }
28169  
28170        if (size > max) {
28171          size = max;
28172          log(iframeId, 'Set ' + dimension + ' to max value');
28173        }
28174  
28175        messageData[dimension] = '' + size;
28176      }
28177  
28178      function isMessageFromIFrame() {
28179        function checkAllowedOrigin() {
28180          function checkList() {
28181            var i = 0,
28182              retCode = false;
28183  
28184            log(
28185              iframeId,
28186              'Checking connection is from allowed list of origins: ' +
28187                checkOrigin
28188            );
28189  
28190            for (; i < checkOrigin.length; i++) {
28191              if (checkOrigin[i] === origin) {
28192                retCode = true;
28193                break;
28194              }
28195            }
28196            return retCode;
28197          }
28198  
28199          function checkSingle() {
28200            var remoteHost = settings[iframeId] && settings[iframeId].remoteHost;
28201            log(iframeId, 'Checking connection is from: ' + remoteHost);
28202            return origin === remoteHost;
28203          }
28204  
28205          return checkOrigin.constructor === Array ? checkList() : checkSingle();
28206        }
28207  
28208        var origin = event.origin,
28209          checkOrigin = settings[iframeId] && settings[iframeId].checkOrigin;
28210  
28211        if (checkOrigin && '' + origin !== 'null' && !checkAllowedOrigin()) {
28212          throw new Error(
28213            'Unexpected message received from: ' +
28214              origin +
28215              ' for ' +
28216              messageData.iframe.id +
28217              '. Message was: ' +
28218              event.data +
28219              '. This error can be disabled by setting the checkOrigin: false option or by providing of array of trusted domains.'
28220          );
28221        }
28222  
28223        return true;
28224      }
28225  
28226      function isMessageForUs() {
28227        return (
28228          msgId === ('' + msg).substr(0, msgIdLen) &&
28229          msg.substr(msgIdLen).split(':')[0] in settings
28230        ); //''+Protects against non-string msg
28231      }
28232  
28233      function isMessageFromMetaParent() {
28234        //Test if this message is from a parent above us. This is an ugly test, however, updating
28235        //the message format would break backwards compatibity.
28236        var retCode = messageData.type in { true: 1, false: 1, undefined: 1 };
28237  
28238        if (retCode) {
28239          log(iframeId, 'Ignoring init message from meta parent page');
28240        }
28241  
28242        return retCode;
28243      }
28244  
28245      function getMsgBody(offset) {
28246        return msg.substr(msg.indexOf(':') + msgHeaderLen + offset);
28247      }
28248  
28249      function forwardMsgFromIFrame(msgBody) {
28250        log(
28251          iframeId,
28252          'MessageCallback passed: {iframe: ' +
28253            messageData.iframe.id +
28254            ', message: ' +
28255            msgBody +
28256            '}'
28257        );
28258        callback('messageCallback', {
28259          iframe: messageData.iframe,
28260          message: JSON.parse(msgBody)
28261        });
28262        log(iframeId, '--');
28263      }
28264  
28265      function getPageInfo() {
28266        var bodyPosition = document.body.getBoundingClientRect(),
28267          iFramePosition = messageData.iframe.getBoundingClientRect();
28268  
28269        return JSON.stringify({
28270          iframeHeight: iFramePosition.height,
28271          iframeWidth: iFramePosition.width,
28272          clientHeight: Math.max(
28273            document.documentElement.clientHeight,
28274            window.innerHeight || 0
28275          ),
28276          clientWidth: Math.max(
28277            document.documentElement.clientWidth,
28278            window.innerWidth || 0
28279          ),
28280          offsetTop: parseInt(iFramePosition.top - bodyPosition.top, 10),
28281          offsetLeft: parseInt(iFramePosition.left - bodyPosition.left, 10),
28282          scrollTop: window.pageYOffset,
28283          scrollLeft: window.pageXOffset
28284        });
28285      }
28286  
28287      function sendPageInfoToIframe(iframe, iframeId) {
28288        function debouncedTrigger() {
28289          trigger(
28290            'Send Page Info',
28291            'pageInfo:' + getPageInfo(),
28292            iframe,
28293            iframeId
28294          );
28295        }
28296        debounceFrameEvents(debouncedTrigger, 32, iframeId);
28297      }
28298  
28299      function startPageInfoMonitor() {
28300        function setListener(type, func) {
28301          function sendPageInfo() {
28302            if (settings[id]) {
28303              sendPageInfoToIframe(settings[id].iframe, id);
28304            } else {
28305              stop();
28306            }
28307          }
28308  
28309          ['scroll', 'resize'].forEach(function(evt) {
28310            log(id, type + evt + ' listener for sendPageInfo');
28311            func(window, evt, sendPageInfo);
28312          });
28313        }
28314  
28315        function stop() {
28316          setListener('Remove ', removeEventListener);
28317        }
28318  
28319        function start() {
28320          setListener('Add ', addEventListener);
28321        }
28322  
28323        var id = iframeId; //Create locally scoped copy of iFrame ID
28324  
28325        start();
28326  
28327        if (settings[id]) {
28328          settings[id].stopPageInfo = stop;
28329        }
28330      }
28331  
28332      function stopPageInfoMonitor() {
28333        if (settings[iframeId] && settings[iframeId].stopPageInfo) {
28334          settings[iframeId].stopPageInfo();
28335          delete settings[iframeId].stopPageInfo;
28336        }
28337      }
28338  
28339      function checkIFrameExists() {
28340        var retBool = true;
28341  
28342        if (null === messageData.iframe) {
28343          warn(iframeId, 'IFrame (' + messageData.id + ') not found');
28344          retBool = false;
28345        }
28346        return retBool;
28347      }
28348  
28349      function getElementPosition(target) {
28350        var iFramePosition = target.getBoundingClientRect();
28351  
28352        getPagePosition(iframeId);
28353  
28354        return {
28355          x: Math.floor(Number(iFramePosition.left) + Number(pagePosition.x)),
28356          y: Math.floor(Number(iFramePosition.top) + Number(pagePosition.y))
28357        };
28358      }
28359  
28360      function scrollRequestFromChild(addOffset) {
28361        /* istanbul ignore next */ //Not testable in Karma
28362        function reposition() {
28363          pagePosition = newPosition;
28364          scrollTo();
28365          log(iframeId, '--');
28366        }
28367  
28368        function calcOffset() {
28369          return {
28370            x: Number(messageData.width) + offset.x,
28371            y: Number(messageData.height) + offset.y
28372          };
28373        }
28374  
28375        function scrollParent() {
28376          if (window.parentIFrame) {
28377            window.parentIFrame['scrollTo' + (addOffset ? 'Offset' : '')](
28378              newPosition.x,
28379              newPosition.y
28380            );
28381          } else {
28382            warn(
28383              iframeId,
28384              'Unable to scroll to requested position, window.parentIFrame not found'
28385            );
28386          }
28387        }
28388  
28389        var offset = addOffset
28390            ? getElementPosition(messageData.iframe)
28391            : { x: 0, y: 0 },
28392          newPosition = calcOffset();
28393  
28394        log(
28395          iframeId,
28396          'Reposition requested from iFrame (offset x:' +
28397            offset.x +
28398            ' y:' +
28399            offset.y +
28400            ')'
28401        );
28402  
28403        if (window.top !== window.self) {
28404          scrollParent();
28405        } else {
28406          reposition();
28407        }
28408      }
28409  
28410      function scrollTo() {
28411        if (false !== callback('scrollCallback', pagePosition)) {
28412          setPagePosition(iframeId);
28413        } else {
28414          unsetPagePosition();
28415        }
28416      }
28417  
28418      function findTarget(location) {
28419        function jumpToTarget() {
28420          var jumpPosition = getElementPosition(target);
28421  
28422          log(
28423            iframeId,
28424            'Moving to in page link (#' +
28425              hash +
28426              ') at x: ' +
28427              jumpPosition.x +
28428              ' y: ' +
28429              jumpPosition.y
28430          );
28431          pagePosition = {
28432            x: jumpPosition.x,
28433            y: jumpPosition.y
28434          };
28435  
28436          scrollTo();
28437          log(iframeId, '--');
28438        }
28439  
28440        function jumpToParent() {
28441          if (window.parentIFrame) {
28442            window.parentIFrame.moveToAnchor(hash);
28443          } else {
28444            log(
28445              iframeId,
28446              'In page link #' +
28447                hash +
28448                ' not found and window.parentIFrame not found'
28449            );
28450          }
28451        }
28452  
28453        var hash = location.split('#')[1] || '',
28454          hashData = decodeURIComponent(hash),
28455          target =
28456            document.getElementById(hashData) ||
28457            document.getElementsByName(hashData)[0];
28458  
28459        if (target) {
28460          jumpToTarget();
28461        } else if (window.top !== window.self) {
28462          jumpToParent();
28463        } else {
28464          log(iframeId, 'In page link #' + hash + ' not found');
28465        }
28466      }
28467  
28468      function callback(funcName, val) {
28469        return chkCallback(iframeId, funcName, val);
28470      }
28471  
28472      function actionMsg() {
28473        if (settings[iframeId] && settings[iframeId].firstRun) firstRun();
28474  
28475        switch (messageData.type) {
28476          case 'close':
28477            if (settings[iframeId].closeRequestCallback)
28478              chkCallback(
28479                iframeId,
28480                'closeRequestCallback',
28481                settings[iframeId].iframe
28482              );
28483            else closeIFrame(messageData.iframe);
28484            break;
28485          case 'message':
28486            forwardMsgFromIFrame(getMsgBody(6));
28487            break;
28488          case 'scrollTo':
28489            scrollRequestFromChild(false);
28490            break;
28491          case 'scrollToOffset':
28492            scrollRequestFromChild(true);
28493            break;
28494          case 'pageInfo':
28495            sendPageInfoToIframe(
28496              settings[iframeId] && settings[iframeId].iframe,
28497              iframeId
28498            );
28499            startPageInfoMonitor();
28500            break;
28501          case 'pageInfoStop':
28502            stopPageInfoMonitor();
28503            break;
28504          case 'inPageLink':
28505            findTarget(getMsgBody(9));
28506            break;
28507          case 'reset':
28508            resetIFrame(messageData);
28509            break;
28510          case 'init':
28511            resizeIFrame();
28512            callback('initCallback', messageData.iframe);
28513            break;
28514          default:
28515            resizeIFrame();
28516        }
28517      }
28518  
28519      function hasSettings(iframeId) {
28520        var retBool = true;
28521  
28522        if (!settings[iframeId]) {
28523          retBool = false;
28524          warn(
28525            messageData.type +
28526              ' No settings for ' +
28527              iframeId +
28528              '. Message was: ' +
28529              msg
28530          );
28531        }
28532  
28533        return retBool;
28534      }
28535  
28536      function iFrameReadyMsgReceived() {
28537        for (var iframeId in settings) {
28538          trigger(
28539            'iFrame requested init',
28540            createOutgoingMsg(iframeId),
28541            document.getElementById(iframeId),
28542            iframeId
28543          );
28544        }
28545      }
28546  
28547      function firstRun() {
28548        if (settings[iframeId]) {
28549          settings[iframeId].firstRun = false;
28550        }
28551      }
28552  
28553      function clearWarningTimeout() {
28554        if (settings[iframeId]) {
28555          clearTimeout(settings[iframeId].msgTimeout);
28556          settings[iframeId].warningTimeout = 0;
28557        }
28558      }
28559  
28560      var msg = event.data,
28561        messageData = {},
28562        iframeId = null;
28563  
28564      if ('[iFrameResizerChild]Ready' === msg) {
28565        iFrameReadyMsgReceived();
28566      } else if (isMessageForUs()) {
28567        messageData = processMsg();
28568        iframeId = logId = messageData.id;
28569        if (settings[iframeId]) {
28570          settings[iframeId].loaded = true;
28571        }
28572  
28573        if (!isMessageFromMetaParent() && hasSettings(iframeId)) {
28574          log(iframeId, 'Received: ' + msg);
28575  
28576          if (checkIFrameExists() && isMessageFromIFrame()) {
28577            actionMsg();
28578          }
28579        }
28580      } else {
28581        info(iframeId, 'Ignored: ' + msg);
28582      }
28583    }
28584  
28585    function chkCallback(iframeId, funcName, val) {
28586      var func = null,
28587        retVal = null;
28588  
28589      if (settings[iframeId]) {
28590        func = settings[iframeId][funcName];
28591  
28592        if ('function' === typeof func) {
28593          retVal = func(val);
28594        } else {
28595          throw new TypeError(
28596            funcName + ' on iFrame[' + iframeId + '] is not a function'
28597          );
28598        }
28599      }
28600  
28601      return retVal;
28602    }
28603  
28604    function removeIframeListeners(iframe) {
28605      var iframeId = iframe.id;
28606      delete settings[iframeId];
28607    }
28608  
28609    function closeIFrame(iframe) {
28610      var iframeId = iframe.id;
28611      log(iframeId, 'Removing iFrame: ' + iframeId);
28612  
28613      try {
28614        // Catch race condition error with React
28615        if (iframe.parentNode) {
28616          iframe.parentNode.removeChild(iframe);
28617        }
28618      } catch (e) {}
28619  
28620      chkCallback(iframeId, 'closedCallback', iframeId);
28621      log(iframeId, '--');
28622      removeIframeListeners(iframe);
28623    }
28624  
28625    function getPagePosition(iframeId) {
28626      if (null === pagePosition) {
28627        pagePosition = {
28628          x:
28629            window.pageXOffset !== undefined
28630              ? window.pageXOffset
28631              : document.documentElement.scrollLeft,
28632          y:
28633            window.pageYOffset !== undefined
28634              ? window.pageYOffset
28635              : document.documentElement.scrollTop
28636        };
28637        log(
28638          iframeId,
28639          'Get page position: ' + pagePosition.x + ',' + pagePosition.y
28640        );
28641      }
28642    }
28643  
28644    function setPagePosition(iframeId) {
28645      if (null !== pagePosition) {
28646        window.scrollTo(pagePosition.x, pagePosition.y);
28647        log(
28648          iframeId,
28649          'Set page position: ' + pagePosition.x + ',' + pagePosition.y
28650        );
28651        unsetPagePosition();
28652      }
28653    }
28654  
28655    function unsetPagePosition() {
28656      pagePosition = null;
28657    }
28658  
28659    function resetIFrame(messageData) {
28660      function reset() {
28661        setSize(messageData);
28662        trigger('reset', 'reset', messageData.iframe, messageData.id);
28663      }
28664  
28665      log(
28666        messageData.id,
28667        'Size reset requested by ' +
28668          ('init' === messageData.type ? 'host page' : 'iFrame')
28669      );
28670      getPagePosition(messageData.id);
28671      syncResize(reset, messageData, 'reset');
28672    }
28673  
28674    function setSize(messageData) {
28675      function setDimension(dimension) {
28676        if (!messageData.id) {
28677          log('undefined', 'messageData id not set');
28678          return;
28679        }
28680        messageData.iframe.style[dimension] = messageData[dimension] + 'px';
28681        log(
28682          messageData.id,
28683          'IFrame (' +
28684            iframeId +
28685            ') ' +
28686            dimension +
28687            ' set to ' +
28688            messageData[dimension] +
28689            'px'
28690        );
28691      }
28692  
28693      function chkZero(dimension) {
28694        //FireFox sets dimension of hidden iFrames to zero.
28695        //So if we detect that set up an event to check for
28696        //when iFrame becomes visible.
28697  
28698        /* istanbul ignore next */ //Not testable in PhantomJS
28699        if (!hiddenCheckEnabled && '0' === messageData[dimension]) {
28700          hiddenCheckEnabled = true;
28701          log(iframeId, 'Hidden iFrame detected, creating visibility listener');
28702          fixHiddenIFrames();
28703        }
28704      }
28705  
28706      function processDimension(dimension) {
28707        setDimension(dimension);
28708        chkZero(dimension);
28709      }
28710  
28711      var iframeId = messageData.iframe.id;
28712  
28713      if (settings[iframeId]) {
28714        if (settings[iframeId].sizeHeight) {
28715          processDimension('height');
28716        }
28717        if (settings[iframeId].sizeWidth) {
28718          processDimension('width');
28719        }
28720      }
28721    }
28722  
28723    function syncResize(func, messageData, doNotSync) {
28724      /* istanbul ignore if */ //Not testable in PhantomJS
28725      if (doNotSync !== messageData.type && requestAnimationFrame) {
28726        log(messageData.id, 'Requesting animation frame');
28727        requestAnimationFrame(func);
28728      } else {
28729        func();
28730      }
28731    }
28732  
28733    function trigger(calleeMsg, msg, iframe, id, noResponseWarning) {
28734      function postMessageToIFrame() {
28735        var target = settings[id] && settings[id].targetOrigin;
28736        log(
28737          id,
28738          '[' +
28739            calleeMsg +
28740            '] Sending msg to iframe[' +
28741            id +
28742            '] (' +
28743            msg +
28744            ') targetOrigin: ' +
28745            target
28746        );
28747        iframe.contentWindow.postMessage(msgId + msg, target);
28748      }
28749  
28750      function iFrameNotFound() {
28751        warn(id, '[' + calleeMsg + '] IFrame(' + id + ') not found');
28752      }
28753  
28754      function chkAndSend() {
28755        if (
28756          iframe &&
28757          'contentWindow' in iframe &&
28758          null !== iframe.contentWindow
28759        ) {
28760          //Null test for PhantomJS
28761          postMessageToIFrame();
28762        } else {
28763          iFrameNotFound();
28764        }
28765      }
28766  
28767      function warnOnNoResponse() {
28768        function warning() {
28769          if (settings[id] && !settings[id].loaded && !errorShown) {
28770            errorShown = true;
28771            warn(
28772              id,
28773              'IFrame has not responded within ' +
28774                settings[id].warningTimeout / 1000 +
28775                ' seconds. Check iFrameResizer.contentWindow.js has been loaded in iFrame. This message can be ignored if everything is working, or you can set the warningTimeout option to a higher value or zero to suppress this warning.'
28776            );
28777          }
28778        }
28779  
28780        if (
28781          !!noResponseWarning &&
28782          settings[id] &&
28783          !!settings[id].warningTimeout
28784        ) {
28785          settings[id].msgTimeout = setTimeout(
28786            warning,
28787            settings[id].warningTimeout
28788          );
28789        }
28790      }
28791  
28792      var errorShown = false;
28793  
28794      id = id || iframe.id;
28795  
28796      if (settings[id]) {
28797        chkAndSend();
28798        warnOnNoResponse();
28799      }
28800    }
28801  
28802    function createOutgoingMsg(iframeId) {
28803      return (
28804        iframeId +
28805        ':' +
28806        settings[iframeId].bodyMarginV1 +
28807        ':' +
28808        settings[iframeId].sizeWidth +
28809        ':' +
28810        settings[iframeId].log +
28811        ':' +
28812        settings[iframeId].interval +
28813        ':' +
28814        settings[iframeId].enablePublicMethods +
28815        ':' +
28816        settings[iframeId].autoResize +
28817        ':' +
28818        settings[iframeId].bodyMargin +
28819        ':' +
28820        settings[iframeId].heightCalculationMethod +
28821        ':' +
28822        settings[iframeId].bodyBackground +
28823        ':' +
28824        settings[iframeId].bodyPadding +
28825        ':' +
28826        settings[iframeId].tolerance +
28827        ':' +
28828        settings[iframeId].inPageLinks +
28829        ':' +
28830        settings[iframeId].resizeFrom +
28831        ':' +
28832        settings[iframeId].widthCalculationMethod
28833      );
28834    }
28835  
28836    function setupIFrame(iframe, options) {
28837      function setLimits() {
28838        function addStyle(style) {
28839          if (
28840            Infinity !== settings[iframeId][style] &&
28841            0 !== settings[iframeId][style]
28842          ) {
28843            iframe.style[style] = settings[iframeId][style] + 'px';
28844            log(
28845              iframeId,
28846              'Set ' + style + ' = ' + settings[iframeId][style] + 'px'
28847            );
28848          }
28849        }
28850  
28851        function chkMinMax(dimension) {
28852          if (
28853            settings[iframeId]['min' + dimension] >
28854            settings[iframeId]['max' + dimension]
28855          ) {
28856            throw new Error(
28857              'Value for min' +
28858                dimension +
28859                ' can not be greater than max' +
28860                dimension
28861            );
28862          }
28863        }
28864  
28865        chkMinMax('Height');
28866        chkMinMax('Width');
28867  
28868        addStyle('maxHeight');
28869        addStyle('minHeight');
28870        addStyle('maxWidth');
28871        addStyle('minWidth');
28872      }
28873  
28874      function newId() {
28875        var id = (options && options.id) || defaults.id + count++;
28876        if (null !== document.getElementById(id)) {
28877          id = id + count++;
28878        }
28879        return id;
28880      }
28881  
28882      function ensureHasId(iframeId) {
28883        logId = iframeId;
28884        if ('' === iframeId) {
28885          iframe.id = iframeId = newId();
28886          logEnabled = (options || {}).log;
28887          logId = iframeId;
28888          log(
28889            iframeId,
28890            'Added missing iframe ID: ' + iframeId + ' (' + iframe.src + ')'
28891          );
28892        }
28893  
28894        return iframeId;
28895      }
28896  
28897      function setScrolling() {
28898        log(
28899          iframeId,
28900          'IFrame scrolling ' +
28901            (settings[iframeId] && settings[iframeId].scrolling
28902              ? 'enabled'
28903              : 'disabled') +
28904            ' for ' +
28905            iframeId
28906        );
28907        iframe.style.overflow =
28908          false === (settings[iframeId] && settings[iframeId].scrolling)
28909            ? 'hidden'
28910            : 'auto';
28911        switch (settings[iframeId] && settings[iframeId].scrolling) {
28912          case 'omit':
28913            break;
28914          case true:
28915            iframe.scrolling = 'yes';
28916            break;
28917          case false:
28918            iframe.scrolling = 'no';
28919            break;
28920          default:
28921            iframe.scrolling = settings[iframeId]
28922              ? settings[iframeId].scrolling
28923              : 'no';
28924        }
28925      }
28926  
28927      //The V1 iFrame script expects an int, where as in V2 expects a CSS
28928      //string value such as '1px 3em', so if we have an int for V2, set V1=V2
28929      //and then convert V2 to a string PX value.
28930      function setupBodyMarginValues() {
28931        if (
28932          'number' ===
28933            typeof (settings[iframeId] && settings[iframeId].bodyMargin) ||
28934          '0' === (settings[iframeId] && settings[iframeId].bodyMargin)
28935        ) {
28936          settings[iframeId].bodyMarginV1 = settings[iframeId].bodyMargin;
28937          settings[iframeId].bodyMargin =
28938            '' + settings[iframeId].bodyMargin + 'px';
28939        }
28940      }
28941  
28942      function checkReset() {
28943        // Reduce scope of firstRun to function, because IE8's JS execution
28944        // context stack is borked and this value gets externally
28945        // changed midway through running this function!!!
28946        var firstRun = settings[iframeId] && settings[iframeId].firstRun,
28947          resetRequertMethod =
28948            settings[iframeId] &&
28949            settings[iframeId].heightCalculationMethod in resetRequiredMethods;
28950  
28951        if (!firstRun && resetRequertMethod) {
28952          resetIFrame({ iframe: iframe, height: 0, width: 0, type: 'init' });
28953        }
28954      }
28955  
28956      function setupIFrameObject() {
28957        if (Function.prototype.bind && settings[iframeId]) {
28958          //Ignore unpolyfilled IE8.
28959          settings[iframeId].iframe.iFrameResizer = {
28960            close: closeIFrame.bind(null, settings[iframeId].iframe),
28961  
28962            removeListeners: removeIframeListeners.bind(
28963              null,
28964              settings[iframeId].iframe
28965            ),
28966  
28967            resize: trigger.bind(
28968              null,
28969              'Window resize',
28970              'resize',
28971              settings[iframeId].iframe
28972            ),
28973  
28974            moveToAnchor: function(anchor) {
28975              trigger(
28976                'Move to anchor',
28977                'moveToAnchor:' + anchor,
28978                settings[iframeId].iframe,
28979                iframeId
28980              );
28981            },
28982  
28983            sendMessage: function(message) {
28984              message = JSON.stringify(message);
28985              trigger(
28986                'Send Message',
28987                'message:' + message,
28988                settings[iframeId].iframe,
28989                iframeId
28990              );
28991            }
28992          };
28993        }
28994      }
28995  
28996      //We have to call trigger twice, as we can not be sure if all
28997      //iframes have completed loading when this code runs. The
28998      //event listener also catches the page changing in the iFrame.
28999      function init(msg) {
29000        function iFrameLoaded() {
29001          trigger('iFrame.onload', msg, iframe, undefined, true);
29002          checkReset();
29003        }
29004  
29005        function createDestroyObserver(MutationObserver) {
29006          if (!iframe.parentNode) {
29007            return;
29008          }
29009  
29010          var destroyObserver = new MutationObserver(function (mutations) {
29011            mutations.forEach(function (mutation) {
29012              var removedNodes = Array.prototype.slice.call(mutation.removedNodes); // Transform NodeList into an Array
29013              removedNodes.forEach(function (removedNode) {
29014                if (removedNode === iframe) {
29015                  closeIFrame(iframe);
29016                }
29017              });
29018            });
29019          });
29020          destroyObserver.observe(iframe.parentNode, {
29021            childList: true
29022          });
29023        }
29024  
29025        var MutationObserver = getMutationObserver();
29026        if (MutationObserver) {
29027          createDestroyObserver(MutationObserver);
29028        }
29029  
29030        addEventListener(iframe, 'load', iFrameLoaded);
29031        trigger('init', msg, iframe, undefined, true);
29032      }
29033  
29034      function checkOptions(options) {
29035        if ('object' !== typeof options) {
29036          throw new TypeError('Options is not an object');
29037        }
29038      }
29039  
29040      function copyOptions(options) {
29041        for (var option in defaults) {
29042          if (defaults.hasOwnProperty(option)) {
29043            settings[iframeId][option] = options.hasOwnProperty(option)
29044              ? options[option]
29045              : defaults[option];
29046          }
29047        }
29048      }
29049  
29050      function getTargetOrigin(remoteHost) {
29051        return '' === remoteHost || 'file://' === remoteHost ? '*' : remoteHost;
29052      }
29053  
29054      function processOptions(options) {
29055        options = options || {};
29056        settings[iframeId] = {
29057          firstRun: true,
29058          iframe: iframe,
29059          remoteHost: iframe.src
29060            .split('/')
29061            .slice(0, 3)
29062            .join('/')
29063        };
29064  
29065        checkOptions(options);
29066        copyOptions(options);
29067  
29068        if (settings[iframeId]) {
29069          settings[iframeId].targetOrigin =
29070            true === settings[iframeId].checkOrigin
29071              ? getTargetOrigin(settings[iframeId].remoteHost)
29072              : '*';
29073        }
29074      }
29075  
29076      function beenHere() {
29077        return iframeId in settings && 'iFrameResizer' in iframe;
29078      }
29079  
29080      var iframeId = ensureHasId(iframe.id);
29081  
29082      if (!beenHere()) {
29083        processOptions(options);
29084        setScrolling();
29085        setLimits();
29086        setupBodyMarginValues();
29087        init(createOutgoingMsg(iframeId));
29088        setupIFrameObject();
29089      } else {
29090        warn(iframeId, 'Ignored iFrame, already setup.');
29091      }
29092    }
29093  
29094    function debouce(fn, time) {
29095      if (null === timer) {
29096        timer = setTimeout(function() {
29097          timer = null;
29098          fn();
29099        }, time);
29100      }
29101    }
29102  
29103    var frameTimer = {};
29104    function debounceFrameEvents(fn, time, frameId) {
29105      if (!frameTimer[frameId]) {
29106        frameTimer[frameId] = setTimeout(function() {
29107          frameTimer[frameId] = null;
29108          fn();
29109        }, time);
29110      }
29111    } //Not testable in PhantomJS
29112  
29113    /* istanbul ignore next */ function fixHiddenIFrames() {
29114      function checkIFrames() {
29115        function checkIFrame(settingId) {
29116          function chkDimension(dimension) {
29117            return (
29118              '0px' ===
29119              (settings[settingId] && settings[settingId].iframe.style[dimension])
29120            );
29121          }
29122  
29123          function isVisible(el) {
29124            return null !== el.offsetParent;
29125          }
29126  
29127          if (
29128            settings[settingId] &&
29129            isVisible(settings[settingId].iframe) &&
29130            (chkDimension('height') || chkDimension('width'))
29131          ) {
29132            trigger(
29133              'Visibility change',
29134              'resize',
29135              settings[settingId].iframe,
29136              settingId
29137            );
29138          }
29139        }
29140  
29141        for (var settingId in settings) {
29142          checkIFrame(settingId);
29143        }
29144      }
29145  
29146      function mutationObserved(mutations) {
29147        log(
29148          'window',
29149          'Mutation observed: ' + mutations[0].target + ' ' + mutations[0].type
29150        );
29151        debouce(checkIFrames, 16);
29152      }
29153  
29154      function createMutationObserver() {
29155        var target = document.querySelector('body'),
29156          config = {
29157            attributes: true,
29158            attributeOldValue: false,
29159            characterData: true,
29160            characterDataOldValue: false,
29161            childList: true,
29162            subtree: true
29163          },
29164          observer = new MutationObserver(mutationObserved);
29165  
29166        observer.observe(target, config);
29167      }
29168  
29169      var MutationObserver = getMutationObserver();
29170      if (MutationObserver) {
29171        createMutationObserver();
29172      }
29173    }
29174  
29175    function resizeIFrames(event) {
29176      function resize() {
29177        sendTriggerMsg('Window ' + event, 'resize');
29178      }
29179  
29180      log('window', 'Trigger event: ' + event);
29181      debouce(resize, 16);
29182    } //Not testable in PhantomJS
29183  
29184    /* istanbul ignore next */ function tabVisible() {
29185      function resize() {
29186        sendTriggerMsg('Tab Visable', 'resize');
29187      }
29188  
29189      if ('hidden' !== document.visibilityState) {
29190        log('document', 'Trigger event: Visiblity change');
29191        debouce(resize, 16);
29192      }
29193    }
29194  
29195    function sendTriggerMsg(eventName, event) {
29196      function isIFrameResizeEnabled(iframeId) {
29197        return (
29198          settings[iframeId] &&
29199          'parent' === settings[iframeId].resizeFrom &&
29200          settings[iframeId].autoResize &&
29201          !settings[iframeId].firstRun
29202        );
29203      }
29204  
29205      for (var iframeId in settings) {
29206        if (isIFrameResizeEnabled(iframeId)) {
29207          trigger(eventName, event, document.getElementById(iframeId), iframeId);
29208        }
29209      }
29210    }
29211  
29212    function setupEventListeners() {
29213      addEventListener(window, 'message', iFrameListener);
29214  
29215      addEventListener(window, 'resize', function() {
29216        resizeIFrames('resize');
29217      });
29218  
29219      addEventListener(document, 'visibilitychange', tabVisible);
29220      addEventListener(document, '-webkit-visibilitychange', tabVisible); //Andriod 4.4
29221      addEventListener(window, 'focusin', function() {
29222        resizeIFrames('focus');
29223      }); //IE8-9
29224      addEventListener(window, 'focus', function() {
29225        resizeIFrames('focus');
29226      });
29227    }
29228  
29229    function factory() {
29230      function init(options, element) {
29231        function chkType() {
29232          if (!element.tagName) {
29233            throw new TypeError('Object is not a valid DOM element');
29234          } else if ('IFRAME' !== element.tagName.toUpperCase()) {
29235            throw new TypeError(
29236              'Expected <IFRAME> tag, found <' + element.tagName + '>'
29237            );
29238          }
29239        }
29240  
29241        if (element) {
29242          chkType();
29243          setupIFrame(element, options);
29244          iFrames.push(element);
29245        }
29246      }
29247  
29248      function warnDeprecatedOptions(options) {
29249        if (options && options.enablePublicMethods) {
29250          warn(
29251            'enablePublicMethods option has been removed, public methods are now always available in the iFrame'
29252          );
29253        }
29254      }
29255  
29256      var iFrames;
29257  
29258      setupRequestAnimationFrame();
29259      setupEventListeners();
29260  
29261      return function iFrameResizeF(options, target) {
29262        iFrames = []; //Only return iFrames past in on this call
29263  
29264        warnDeprecatedOptions(options);
29265  
29266        switch (typeof target) {
29267          case 'undefined':
29268          case 'string':
29269            Array.prototype.forEach.call(
29270              document.querySelectorAll(target || 'iframe'),
29271              init.bind(undefined, options)
29272            );
29273            break;
29274          case 'object':
29275            init(options, target);
29276            break;
29277          default:
29278            throw new TypeError('Unexpected data type (' + typeof target + ')');
29279        }
29280  
29281        return iFrames;
29282      };
29283    }
29284  
29285    function createJQueryPublicMethod($) {
29286      if (!$.fn) {
29287        info('', 'Unable to bind to jQuery, it is not fully loaded.');
29288      } else if (!$.fn.iFrameResize) {
29289        $.fn.iFrameResize = function $iFrameResizeF(options) {
29290          function init(index, element) {
29291            setupIFrame(element, options);
29292          }
29293  
29294          return this.filter('iframe')
29295            .each(init)
29296            .end();
29297        };
29298      }
29299    }
29300  
29301    if (window.jQuery) {
29302      createJQueryPublicMethod(window.jQuery);
29303    }
29304  
29305    if (typeof define === 'function' && define.amd) {
29306      define([], factory);
29307    } else if (typeof module === 'object' && typeof module.exports === 'object') {
29308      //Node for browserfy
29309      module.exports = factory();
29310    }
29311    window.iFrameResize = window.iFrameResize || factory();
29312  })();/*!
29313 * Datepicker for Bootstrap v1.8.0 (https://github.com/uxsolutions/bootstrap-datepicker)
29314 *
29315 * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
29316 */
29317
29318(function(factory){
29319    if (typeof define === 'function' && define.amd) {
29320        define(['jquery'], factory);
29321    } else if (typeof exports === 'object') {
29322        factory(require('jquery'));
29323    } else {
29324        factory(jQuery);
29325    }
29326}(function($, undefined){
29327	function UTCDate(){
29328		return new Date(Date.UTC.apply(Date, arguments));
29329	}
29330	function UTCToday(){
29331		var today = new Date();
29332		return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
29333	}
29334	function isUTCEquals(date1, date2) {
29335		return (
29336			date1.getUTCFullYear() === date2.getUTCFullYear() &&
29337			date1.getUTCMonth() === date2.getUTCMonth() &&
29338			date1.getUTCDate() === date2.getUTCDate()
29339		);
29340	}
29341	function alias(method, deprecationMsg){
29342		return function(){
29343			if (deprecationMsg !== undefined) {
29344				$.fn.datepicker.deprecated(deprecationMsg);
29345			}
29346
29347			return this[method].apply(this, arguments);
29348		};
29349	}
29350	function isValidDate(d) {
29351		return d && !isNaN(d.getTime());
29352	}
29353
29354	var DateArray = (function(){
29355		var extras = {
29356			get: function(i){
29357				return this.slice(i)[0];
29358			},
vendor: 14,415 bytes, lines 29359-29899
29359			contains: function(d){
29360				// Array.indexOf is not cross-browser;
29361				// $.inArray doesn't work with Dates
29362				var val = d && d.valueOf();
29363				for (var i=0, l=this.length; i < l; i++)
29364          // Use date arithmetic to allow dates with different times to match
29365          if (0 <= this[i].valueOf() - val && this[i].valueOf() - val < 1000*60*60*24)
29366						return i;
29367				return -1;
29368			},
29369			remove: function(i){
29370				this.splice(i,1);
29371			},
29372			replace: function(new_array){
29373				if (!new_array)
29374					return;
29375				if (!$.isArray(new_array))
29376					new_array = [new_array];
29377				this.clear();
29378				this.push.apply(this, new_array);
29379			},
29380			clear: function(){
29381				this.length = 0;
29382			},
29383			copy: function(){
29384				var a = new DateArray();
29385				a.replace(this);
29386				return a;
29387			}
29388		};
29389
29390		return function(){
29391			var a = [];
29392			a.push.apply(a, arguments);
29393			$.extend(a, extras);
29394			return a;
29395		};
29396	})();
29397
29398
29399	// Picker object
29400
29401	var Datepicker = function(element, options){
29402		$.data(element, 'datepicker', this);
29403		this._process_options(options);
29404
29405		this.dates = new DateArray();
29406		this.viewDate = this.o.defaultViewDate;
29407		this.focusDate = null;
29408
29409		this.element = $(element);
29410		this.isInput = this.element.is('input');
29411		this.inputField = this.isInput ? this.element : this.element.find('input');
29412		this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false;
29413		if (this.component && this.component.length === 0)
29414			this.component = false;
29415		this.isInline = !this.component && this.element.is('div');
29416
29417		this.picker = $(DPGlobal.template);
29418
29419		// Checking templates and inserting
29420		if (this._check_template(this.o.templates.leftArrow)) {
29421			this.picker.find('.prev').html(this.o.templates.leftArrow);
29422		}
29423
29424		if (this._check_template(this.o.templates.rightArrow)) {
29425			this.picker.find('.next').html(this.o.templates.rightArrow);
29426		}
29427
29428		this._buildEvents();
29429		this._attachEvents();
29430
29431		if (this.isInline){
29432			this.picker.addClass('datepicker-inline').appendTo(this.element);
29433		}
29434		else {
29435			this.picker.addClass('datepicker-dropdown dropdown-menu');
29436		}
29437
29438		if (this.o.rtl){
29439			this.picker.addClass('datepicker-rtl');
29440		}
29441
29442		if (this.o.calendarWeeks) {
29443			this.picker.find('.datepicker-days .datepicker-switch, thead .datepicker-title, tfoot .today, tfoot .clear')
29444				.attr('colspan', function(i, val){
29445					return Number(val) + 1;
29446				});
29447		}
29448
29449		this._process_options({
29450			startDate: this._o.startDate,
29451			endDate: this._o.endDate,
29452			daysOfWeekDisabled: this.o.daysOfWeekDisabled,
29453			daysOfWeekHighlighted: this.o.daysOfWeekHighlighted,
29454			datesDisabled: this.o.datesDisabled
29455		});
29456
29457		this._allow_update = false;
29458		this.setViewMode(this.o.startView);
29459		this._allow_update = true;
29460
29461		this.fillDow();
29462		this.fillMonths();
29463
29464		this.update();
29465
29466		if (this.isInline){
29467			this.show();
29468		}
29469	};
29470
29471	Datepicker.prototype = {
29472		constructor: Datepicker,
29473
29474		_resolveViewName: function(view){
29475			$.each(DPGlobal.viewModes, function(i, viewMode){
29476				if (view === i || $.inArray(view, viewMode.names) !== -1){
29477					view = i;
29478					return false;
29479				}
29480			});
29481
29482			return view;
29483		},
29484
29485		_resolveDaysOfWeek: function(daysOfWeek){
29486			if (!$.isArray(daysOfWeek))
29487				daysOfWeek = daysOfWeek.split(/[,\s]*/);
29488			return $.map(daysOfWeek, Number);
29489		},
29490
29491		_check_template: function(tmp){
29492			try {
29493				// If empty
29494				if (tmp === undefined || tmp === "") {
29495					return false;
29496				}
29497				// If no html, everything ok
29498				if ((tmp.match(/[<>]/g) || []).length <= 0) {
29499					return true;
29500				}
29501				// Checking if html is fine
29502				var jDom = $(tmp);
29503				return jDom.length > 0;
29504			}
29505			catch (ex) {
29506				return false;
29507			}
29508		},
29509
29510		_process_options: function(opts){
29511			// Store raw options for reference
29512			this._o = $.extend({}, this._o, opts);
29513			// Processed options
29514			var o = this.o = $.extend({}, this._o);
29515
29516			// Check if "de-DE" style date is available, if not language should
29517			// fallback to 2 letter code eg "de"
29518			var lang = o.language;
29519			if (!dates[lang]){
29520				lang = lang.split('-')[0];
29521				if (!dates[lang])
29522					lang = defaults.language;
29523			}
29524			o.language = lang;
29525
29526			// Retrieve view index from any aliases
29527			o.startView = this._resolveViewName(o.startView);
29528			o.minViewMode = this._resolveViewName(o.minViewMode);
29529			o.maxViewMode = this._resolveViewName(o.maxViewMode);
29530
29531			// Check view is between min and max
29532			o.startView = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, o.startView));
29533
29534			// true, false, or Number > 0
29535			if (o.multidate !== true){
29536				o.multidate = Number(o.multidate) || false;
29537				if (o.multidate !== false)
29538					o.multidate = Math.max(0, o.multidate);
29539			}
29540			o.multidateSeparator = String(o.multidateSeparator);
29541
29542			o.weekStart %= 7;
29543			o.weekEnd = (o.weekStart + 6) % 7;
29544
29545			var format = DPGlobal.parseFormat(o.format);
29546			if (o.startDate !== -Infinity){
29547				if (!!o.startDate){
29548					if (o.startDate instanceof Date)
29549						o.startDate = this._local_to_utc(this._zero_time(o.startDate));
29550					else
29551						o.startDate = DPGlobal.parseDate(o.startDate, format, o.language, o.assumeNearbyYear);
29552				}
29553				else {
29554					o.startDate = -Infinity;
29555				}
29556			}
29557			if (o.endDate !== Infinity){
29558				if (!!o.endDate){
29559					if (o.endDate instanceof Date)
29560						o.endDate = this._local_to_utc(this._zero_time(o.endDate));
29561					else
29562						o.endDate = DPGlobal.parseDate(o.endDate, format, o.language, o.assumeNearbyYear);
29563				}
29564				else {
29565					o.endDate = Infinity;
29566				}
29567			}
29568
29569			o.daysOfWeekDisabled = this._resolveDaysOfWeek(o.daysOfWeekDisabled||[]);
29570			o.daysOfWeekHighlighted = this._resolveDaysOfWeek(o.daysOfWeekHighlighted||[]);
29571
29572			o.datesDisabled = o.datesDisabled||[];
29573			if (!$.isArray(o.datesDisabled)) {
29574				o.datesDisabled = o.datesDisabled.split(',');
29575			}
29576			o.datesDisabled = $.map(o.datesDisabled, function(d){
29577				return DPGlobal.parseDate(d, format, o.language, o.assumeNearbyYear);
29578			});
29579
29580			var plc = String(o.orientation).toLowerCase().split(/\s+/g),
29581				_plc = o.orientation.toLowerCase();
29582			plc = $.grep(plc, function(word){
29583				return /^auto|left|right|top|bottom$/.test(word);
29584			});
29585			o.orientation = {x: 'auto', y: 'auto'};
29586			if (!_plc || _plc === 'auto')
29587				; // no action
29588			else if (plc.length === 1){
29589				switch (plc[0]){
29590					case 'top':
29591					case 'bottom':
29592						o.orientation.y = plc[0];
29593						break;
29594					case 'left':
29595					case 'right':
29596						o.orientation.x = plc[0];
29597						break;
29598				}
29599			}
29600			else {
29601				_plc = $.grep(plc, function(word){
29602					return /^left|right$/.test(word);
29603				});
29604				o.orientation.x = _plc[0] || 'auto';
29605
29606				_plc = $.grep(plc, function(word){
29607					return /^top|bottom$/.test(word);
29608				});
29609				o.orientation.y = _plc[0] || 'auto';
29610			}
29611			if (o.defaultViewDate instanceof Date || typeof o.defaultViewDate === 'string') {
29612				o.defaultViewDate = DPGlobal.parseDate(o.defaultViewDate, format, o.language, o.assumeNearbyYear);
29613			} else if (o.defaultViewDate) {
29614				var year = o.defaultViewDate.year || new Date().getFullYear();
29615				var month = o.defaultViewDate.month || 0;
29616				var day = o.defaultViewDate.day || 1;
29617				o.defaultViewDate = UTCDate(year, month, day);
29618			} else {
29619				o.defaultViewDate = UTCToday();
29620			}
29621		},
29622		_events: [],
29623		_secondaryEvents: [],
29624		_applyEvents: function(evs){
29625			for (var i=0, el, ch, ev; i < evs.length; i++){
29626				el = evs[i][0];
29627				if (evs[i].length === 2){
29628					ch = undefined;
29629					ev = evs[i][1];
29630				} else if (evs[i].length === 3){
29631					ch = evs[i][1];
29632					ev = evs[i][2];
29633				}
29634				el.on(ev, ch);
29635			}
29636		},
29637		_unapplyEvents: function(evs){
29638			for (var i=0, el, ev, ch; i < evs.length; i++){
29639				el = evs[i][0];
29640				if (evs[i].length === 2){
29641					ch = undefined;
29642					ev = evs[i][1];
29643				} else if (evs[i].length === 3){
29644					ch = evs[i][1];
29645					ev = evs[i][2];
29646				}
29647				el.off(ev, ch);
29648			}
29649		},
29650		_buildEvents: function(){
29651            var events = {
29652                keyup: $.proxy(function(e){
29653                    if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
29654                        this.update();
29655                }, this),
29656                keydown: $.proxy(this.keydown, this),
29657                paste: $.proxy(this.paste, this)
29658            };
29659
29660            if (this.o.showOnFocus === true) {
29661                events.focus = $.proxy(this.show, this);
29662            }
29663
29664            if (this.isInput) { // single input
29665                this._events = [
29666                    [this.element, events]
29667                ];
29668            }
29669            // component: input + button
29670            else if (this.component && this.inputField.length) {
29671                this._events = [
29672                    // For components that are not readonly, allow keyboard nav
29673                    [this.inputField, events],
29674                    [this.component, {
29675                        click: $.proxy(this.show, this)
29676                    }]
29677                ];
29678            }
29679			else {
29680				this._events = [
29681					[this.element, {
29682						click: $.proxy(this.show, this),
29683						keydown: $.proxy(this.keydown, this)
29684					}]
29685				];
29686			}
29687			this._events.push(
29688				// Component: listen for blur on element descendants
29689				[this.element, '*', {
29690					blur: $.proxy(function(e){
29691						this._focused_from = e.target;
29692					}, this)
29693				}],
29694				// Input: listen for blur on element
29695				[this.element, {
29696					blur: $.proxy(function(e){
29697						this._focused_from = e.target;
29698					}, this)
29699				}]
29700			);
29701
29702			if (this.o.immediateUpdates) {
29703				// Trigger input updates immediately on changed year/month
29704				this._events.push([this.element, {
29705					'changeYear changeMonth': $.proxy(function(e){
29706						this.update(e.date);
29707					}, this)
29708				}]);
29709			}
29710
29711			this._secondaryEvents = [
29712				[this.picker, {
29713					click: $.proxy(this.click, this)
29714				}],
29715				[this.picker, '.prev, .next', {
29716					click: $.proxy(this.navArrowsClick, this)
29717				}],
29718				[this.picker, '.day:not(.disabled)', {
29719					click: $.proxy(this.dayCellClick, this)
29720				}],
29721				[$(window), {
29722					resize: $.proxy(this.place, this)
29723				}],
29724				[$(document), {
29725					'mousedown touchstart': $.proxy(function(e){
29726						// Clicked outside the datepicker, hide it
29727						if (!(
29728							this.element.is(e.target) ||
29729							this.element.find(e.target).length ||
29730							this.picker.is(e.target) ||
29731							this.picker.find(e.target).length ||
29732							this.isInline
29733						)){
29734							this.hide();
29735						}
29736					}, this)
29737				}]
29738			];
29739		},
29740		_attachEvents: function(){
29741			this._detachEvents();
29742			this._applyEvents(this._events);
29743		},
29744		_detachEvents: function(){
29745			this._unapplyEvents(this._events);
29746		},
29747		_attachSecondaryEvents: function(){
29748			this._detachSecondaryEvents();
29749			this._applyEvents(this._secondaryEvents);
29750		},
29751		_detachSecondaryEvents: function(){
29752			this._unapplyEvents(this._secondaryEvents);
29753		},
29754		_trigger: function(event, altdate){
29755			var date = altdate || this.dates.get(-1),
29756				local_date = this._utc_to_local(date);
29757
29758			this.element.trigger({
29759				type: event,
29760				date: local_date,
29761				viewMode: this.viewMode,
29762				dates: $.map(this.dates, this._utc_to_local),
29763				format: $.proxy(function(ix, format){
29764					if (arguments.length === 0){
29765						ix = this.dates.length - 1;
29766						format = this.o.format;
29767					} else if (typeof ix === 'string'){
29768						format = ix;
29769						ix = this.dates.length - 1;
29770					}
29771					format = format || this.o.format;
29772					var date = this.dates.get(ix);
29773					return DPGlobal.formatDate(date, format, this.o.language);
29774				}, this)
29775			});
29776		},
29777
29778		show: function(){
29779			if (this.inputField.prop('disabled') || (this.inputField.prop('readonly') && this.o.enableOnReadonly === false))
29780				return;
29781			if (!this.isInline)
29782				this.picker.appendTo(this.o.container);
29783			this.place();
29784			this.picker.show();
29785			this._attachSecondaryEvents();
29786			this._trigger('show');
29787			if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) {
29788				$(this.element).blur();
29789			}
29790			return this;
29791		},
29792
29793		hide: function(){
29794			if (this.isInline || !this.picker.is(':visible'))
29795				return this;
29796			this.focusDate = null;
29797			this.picker.hide().detach();
29798			this._detachSecondaryEvents();
29799			this.setViewMode(this.o.startView);
29800
29801			if (this.o.forceParse && this.inputField.val())
29802				this.setValue();
29803			this._trigger('hide');
29804			return this;
29805		},
29806
29807		destroy: function(){
29808			this.hide();
29809			this._detachEvents();
29810			this._detachSecondaryEvents();
29811			this.picker.remove();
29812			delete this.element.data().datepicker;
29813			if (!this.isInput){
29814				delete this.element.data().date;
29815			}
29816			return this;
29817		},
29818
29819		paste: function(e){
29820			var dateString;
29821			if (e.originalEvent.clipboardData && e.originalEvent.clipboardData.types
29822				&& $.inArray('text/plain', e.originalEvent.clipboardData.types) !== -1) {
29823				dateString = e.originalEvent.clipboardData.getData('text/plain');
29824			} else if (window.clipboardData) {
29825				dateString = window.clipboardData.getData('Text');
29826			} else {
29827				return;
29828			}
29829			this.setDate(dateString);
29830			this.update();
29831			e.preventDefault();
29832		},
29833
29834		_utc_to_local: function(utc){
29835			if (!utc) {
29836				return utc;
29837			}
29838
29839			var local = new Date(utc.getTime() + (utc.getTimezoneOffset() * 60000));
29840
29841			if (local.getTimezoneOffset() !== utc.getTimezoneOffset()) {
29842				local = new Date(utc.getTime() + (local.getTimezoneOffset() * 60000));
29843			}
29844
29845			return local;
29846		},
29847		_local_to_utc: function(local){
29848			return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000));
29849		},
29850		_zero_time: function(local){
29851			return local && new Date(local.getFullYear(), local.getMonth(), local.getDate());
29852		},
29853		_zero_utc_time: function(utc){
29854			return utc && UTCDate(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate());
29855		},
29856
29857		getDates: function(){
29858			return $.map(this.dates, this._utc_to_local);
29859		},
29860
29861		getUTCDates: function(){
29862			return $.map(this.dates, function(d){
29863				return new Date(d);
29864			});
29865		},
29866
29867		getDate: function(){
29868			return this._utc_to_local(this.getUTCDate());
29869		},
29870
29871		getUTCDate: function(){
29872			var selected_date = this.dates.get(-1);
29873			if (selected_date !== undefined) {
29874				return new Date(selected_date);
29875			} else {
29876				return null;
29877			}
29878		},
29879
29880		clearDates: function(){
29881			this.inputField.val('');
29882			this.update();
29883			this._trigger('changeDate');
29884
29885			if (this.o.autoclose) {
29886				this.hide();
29887			}
29888		},
29889
29890		setDates: function(){
29891			var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
29892			this.update.apply(this, args);
29893			this._trigger('changeDate');
29894			this.setValue();
29895			return this;
29896		},
29897
29898		setUTCDates: function(){
29899			var args = $
vendor: 11,373 bytes, lines 29899-30275
29899.isArray(arguments[0]) ? arguments[0] : arguments;
29900			this.setDates.apply(this, $.map(args, this._utc_to_local));
29901			return this;
29902		},
29903
29904		setDate: alias('setDates'),
29905		setUTCDate: alias('setUTCDates'),
29906		remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead'),
29907
29908		setValue: function(){
29909			var formatted = this.getFormattedDate();
29910			this.inputField.val(formatted);
29911			return this;
29912		},
29913
29914		getFormattedDate: function(format){
29915			if (format === undefined)
29916				format = this.o.format;
29917
29918			var lang = this.o.language;
29919			return $.map(this.dates, function(d){
29920				return DPGlobal.formatDate(d, format, lang);
29921			}).join(this.o.multidateSeparator);
29922		},
29923
29924		getStartDate: function(){
29925			return this.o.startDate;
29926		},
29927
29928		setStartDate: function(startDate){
29929			this._process_options({startDate: startDate});
29930			this.update();
29931			this.updateNavArrows();
29932			return this;
29933		},
29934
29935		getEndDate: function(){
29936			return this.o.endDate;
29937		},
29938
29939		setEndDate: function(endDate){
29940			this._process_options({endDate: endDate});
29941			this.update();
29942			this.updateNavArrows();
29943			return this;
29944		},
29945
29946		setDaysOfWeekDisabled: function(daysOfWeekDisabled){
29947			this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
29948			this.update();
29949			return this;
29950		},
29951
29952		setDaysOfWeekHighlighted: function(daysOfWeekHighlighted){
29953			this._process_options({daysOfWeekHighlighted: daysOfWeekHighlighted});
29954			this.update();
29955			return this;
29956		},
29957
29958		setDatesDisabled: function(datesDisabled){
29959			this._process_options({datesDisabled: datesDisabled});
29960			this.update();
29961			return this;
29962		},
29963
29964		place: function(){
29965			if (this.isInline)
29966				return this;
29967			var calendarWidth = this.picker.outerWidth(),
29968				calendarHeight = this.picker.outerHeight(),
29969				visualPadding = 10,
29970				container = $(this.o.container),
29971				windowWidth = container.width(),
29972				scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(),
29973				appendOffset = container.offset();
29974
29975			var parentsZindex = [0];
29976			this.element.parents().each(function(){
29977				var itemZIndex = $(this).css('z-index');
29978				if (itemZIndex !== 'auto' && Number(itemZIndex) !== 0) parentsZindex.push(Number(itemZIndex));
29979			});
29980			var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset;
29981			var offset = this.component ? this.component.parent().offset() : this.element.offset();
29982			var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
29983			var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
29984			var left = offset.left - appendOffset.left;
29985			var top = offset.top - appendOffset.top;
29986
29987			if (this.o.container !== 'body') {
29988				top += scrollTop;
29989			}
29990
29991			this.picker.removeClass(
29992				'datepicker-orient-top datepicker-orient-bottom '+
29993				'datepicker-orient-right datepicker-orient-left'
29994			);
29995
29996			if (this.o.orientation.x !== 'auto'){
29997				this.picker.addClass('datepicker-orient-' + this.o.orientation.x);
29998				if (this.o.orientation.x === 'right')
29999					left -= calendarWidth - width;
30000			}
30001			// auto x orientation is best-placement: if it crosses a window
30002			// edge, fudge it sideways
30003			else {
30004				if (offset.left < 0) {
30005					// component is outside the window on the left side. Move it into visible range
30006					this.picker.addClass('datepicker-orient-left');
30007					left -= offset.left - visualPadding;
30008				} else if (left + calendarWidth > windowWidth) {
30009					// the calendar passes the widow right edge. Align it to component right side
30010					this.picker.addClass('datepicker-orient-right');
30011					left += width - calendarWidth;
30012				} else {
30013					if (this.o.rtl) {
30014						// Default to right
30015						this.picker.addClass('datepicker-orient-right');
30016					} else {
30017						// Default to left
30018						this.picker.addClass('datepicker-orient-left');
30019					}
30020				}
30021			}
30022
30023			// auto y orientation is best-situation: top or bottom, no fudging,
30024			// decision based on which shows more of the calendar
30025			var yorient = this.o.orientation.y,
30026				top_overflow;
30027			if (yorient === 'auto'){
30028				top_overflow = -scrollTop + top - calendarHeight;
30029				yorient = top_overflow < 0 ? 'bottom' : 'top';
30030			}
30031
30032			this.picker.addClass('datepicker-orient-' + yorient);
30033			if (yorient === 'top')
30034				top -= calendarHeight + parseInt(this.picker.css('padding-top'));
30035			else
30036				top += height;
30037
30038			if (this.o.rtl) {
30039				var right = windowWidth - (left + width);
30040				this.picker.css({
30041					top: top,
30042					right: right,
30043					zIndex: zIndex
30044				});
30045			} else {
30046				this.picker.css({
30047					top: top,
30048					left: left,
30049					zIndex: zIndex
30050				});
30051			}
30052			return this;
30053		},
30054
30055		_allow_update: true,
30056		update: function(){
30057			if (!this._allow_update)
30058				return this;
30059
30060			var oldDates = this.dates.copy(),
30061				dates = [],
30062				fromArgs = false;
30063			if (arguments.length){
30064				$.each(arguments, $.proxy(function(i, date){
30065					if (date instanceof Date)
30066						date = this._local_to_utc(date);
30067					dates.push(date);
30068				}, this));
30069				fromArgs = true;
30070			} else {
30071				dates = this.isInput
30072						? this.element.val()
30073						: this.element.data('date') || this.inputField.val();
30074				if (dates && this.o.multidate)
30075					dates = dates.split(this.o.multidateSeparator);
30076				else
30077					dates = [dates];
30078				delete this.element.data().date;
30079			}
30080
30081			dates = $.map(dates, $.proxy(function(date){
30082				return DPGlobal.parseDate(date, this.o.format, this.o.language, this.o.assumeNearbyYear);
30083			}, this));
30084			dates = $.grep(dates, $.proxy(function(date){
30085				return (
30086					!this.dateWithinRange(date) ||
30087					!date
30088				);
30089			}, this), true);
30090			this.dates.replace(dates);
30091
30092			if (this.o.updateViewDate) {
30093				if (this.dates.length)
30094					this.viewDate = new Date(this.dates.get(-1));
30095				else if (this.viewDate < this.o.startDate)
30096					this.viewDate = new Date(this.o.startDate);
30097				else if (this.viewDate > this.o.endDate)
30098					this.viewDate = new Date(this.o.endDate);
30099				else
30100					this.viewDate = this.o.defaultViewDate;
30101			}
30102
30103			if (fromArgs){
30104				// setting date by clicking
30105				this.setValue();
30106				this.element.change();
30107			}
30108			else if (this.dates.length){
30109				// setting date by typing
30110				if (String(oldDates) !== String(this.dates) && fromArgs) {
30111					this._trigger('changeDate');
30112					this.element.change();
30113				}
30114			}
30115			if (!this.dates.length && oldDates.length) {
30116				this._trigger('clearDate');
30117				this.element.change();
30118			}
30119
30120			this.fill();
30121			return this;
30122		},
30123
30124		fillDow: function(){
30125      if (this.o.showWeekDays) {
30126			var dowCnt = this.o.weekStart,
30127				html = '<tr>';
30128			if (this.o.calendarWeeks){
30129				html += '<th class="cw">&#160;</th>';
30130			}
30131			while (dowCnt < this.o.weekStart + 7){
30132				html += '<th class="dow';
30133        if ($.inArray(dowCnt, this.o.daysOfWeekDisabled) !== -1)
30134          html += ' disabled';
30135        html += '">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
30136			}
30137			html += '</tr>';
30138			this.picker.find('.datepicker-days thead').append(html);
30139      }
30140		},
30141
30142		fillMonths: function(){
30143      var localDate = this._utc_to_local(this.viewDate);
30144			var html = '';
30145			var focused;
30146			for (var i = 0; i < 12; i++){
30147				focused = localDate && localDate.getMonth() === i ? ' focused' : '';
30148				html += '<span class="month' + focused + '">' + dates[this.o.language].monthsShort[i] + '</span>';
30149			}
30150			this.picker.find('.datepicker-months td').html(html);
30151		},
30152
30153		setRange: function(range){
30154			if (!range || !range.length)
30155				delete this.range;
30156			else
30157				this.range = $.map(range, function(d){
30158					return d.valueOf();
30159				});
30160			this.fill();
30161		},
30162
30163		getClassNames: function(date){
30164			var cls = [],
30165				year = this.viewDate.getUTCFullYear(),
30166				month = this.viewDate.getUTCMonth(),
30167				today = UTCToday();
30168			if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){
30169				cls.push('old');
30170			} else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){
30171				cls.push('new');
30172			}
30173			if (this.focusDate && date.valueOf() === this.focusDate.valueOf())
30174				cls.push('focused');
30175			// Compare internal UTC date with UTC today, not local today
30176			if (this.o.todayHighlight && isUTCEquals(date, today)) {
30177				cls.push('today');
30178			}
30179			if (this.dates.contains(date) !== -1)
30180				cls.push('active');
30181			if (!this.dateWithinRange(date)){
30182				cls.push('disabled');
30183			}
30184			if (this.dateIsDisabled(date)){
30185				cls.push('disabled', 'disabled-date');
30186			}
30187			if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1){
30188				cls.push('highlighted');
30189			}
30190
30191			if (this.range){
30192				if (date > this.range[0] && date < this.range[this.range.length-1]){
30193					cls.push('range');
30194				}
30195				if ($.inArray(date.valueOf(), this.range) !== -1){
30196					cls.push('selected');
30197				}
30198				if (date.valueOf() === this.range[0]){
30199          cls.push('range-start');
30200        }
30201        if (date.valueOf() === this.range[this.range.length-1]){
30202          cls.push('range-end');
30203        }
30204			}
30205			return cls;
30206		},
30207
30208		_fill_yearsView: function(selector, cssClass, factor, year, startYear, endYear, beforeFn){
30209			var html = '';
30210			var step = factor / 10;
30211			var view = this.picker.find(selector);
30212			var startVal = Math.floor(year / factor) * factor;
30213			var endVal = startVal + step * 9;
30214			var focusedVal = Math.floor(this.viewDate.getFullYear() / step) * step;
30215			var selected = $.map(this.dates, function(d){
30216				return Math.floor(d.getUTCFullYear() / step) * step;
30217			});
30218
30219			var classes, tooltip, before;
30220			for (var currVal = startVal - step; currVal <= endVal + step; currVal += step) {
30221				classes = [cssClass];
30222				tooltip = null;
30223
30224				if (currVal === startVal - step) {
30225					classes.push('old');
30226				} else if (currVal === endVal + step) {
30227					classes.push('new');
30228				}
30229				if ($.inArray(currVal, selected) !== -1) {
30230					classes.push('active');
30231				}
30232				if (currVal < startYear || currVal > endYear) {
30233					classes.push('disabled');
30234				}
30235				if (currVal === focusedVal) {
30236				  classes.push('focused');
30237        }
30238
30239				if (beforeFn !== $.noop) {
30240					before = beforeFn(new Date(currVal, 0, 1));
30241					if (before === undefined) {
30242						before = {};
30243					} else if (typeof before === 'boolean') {
30244						before = {enabled: before};
30245					} else if (typeof before === 'string') {
30246						before = {classes: before};
30247					}
30248					if (before.enabled === false) {
30249						classes.push('disabled');
30250					}
30251					if (before.classes) {
30252						classes = classes.concat(before.classes.split(/\s+/));
30253					}
30254					if (before.tooltip) {
30255						tooltip = before.tooltip;
30256					}
30257				}
30258
30259				html += '<span class="' + classes.join(' ') + '"' + (tooltip ? ' title="' + tooltip + '"' : '') + '>' + currVal + '</span>';
30260			}
30261
30262			view.find('.datepicker-switch').text(startVal + '-' + endVal);
30263			view.find('td').html(html);
30264		},
30265
30266		fill: function(){
30267			var d = new Date(this.viewDate),
30268				year = d.getUTCFullYear(),
30269				month = d.getUTCMonth(),
30270				startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
30271				startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
30272				endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
30273				endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
30274				todaytxt = dates[this.o.language].today || dates['en'].today || '',
30275				cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
vendor: 5,592 bytes, lines 30276-30445
30276				titleFormat = dates[this.o.language].titleFormat || dates['en'].titleFormat,
30277				tooltip,
30278				before;
30279			if (isNaN(year) || isNaN(month))
30280				return;
30281			this.picker.find('.datepicker-days .datepicker-switch')
30282						.text(DPGlobal.formatDate(d, titleFormat, this.o.language));
30283			this.picker.find('tfoot .today')
30284						.text(todaytxt)
30285						.css('display', this.o.todayBtn === true || this.o.todayBtn === 'linked' ? 'table-cell' : 'none');
30286			this.picker.find('tfoot .clear')
30287						.text(cleartxt)
30288						.css('display', this.o.clearBtn === true ? 'table-cell' : 'none');
30289			this.picker.find('thead .datepicker-title')
30290						.text(this.o.title)
30291						.css('display', typeof this.o.title === 'string' && this.o.title !== '' ? 'table-cell' : 'none');
30292			this.updateNavArrows();
30293			this.fillMonths();
30294			var prevMonth = UTCDate(year, month, 0),
30295				day = prevMonth.getUTCDate();
30296			prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7);
30297			var nextMonth = new Date(prevMonth);
30298			if (prevMonth.getUTCFullYear() < 100){
30299        nextMonth.setUTCFullYear(prevMonth.getUTCFullYear());
30300      }
30301			nextMonth.setUTCDate(nextMonth.getUTCDate() + 42);
30302			nextMonth = nextMonth.valueOf();
30303			var html = [];
30304			var weekDay, clsName;
30305			while (prevMonth.valueOf() < nextMonth){
30306				weekDay = prevMonth.getUTCDay();
30307				if (weekDay === this.o.weekStart){
30308					html.push('<tr>');
30309					if (this.o.calendarWeeks){
30310						// ISO 8601: First week contains first thursday.
30311						// ISO also states week starts on Monday, but we can be more abstract here.
30312						var
30313							// Start of current week: based on weekstart/current date
30314							ws = new Date(+prevMonth + (this.o.weekStart - weekDay - 7) % 7 * 864e5),
30315							// Thursday of this week
30316							th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
30317							// First Thursday of year, year from thursday
30318							yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay()) % 7 * 864e5),
30319							// Calendar week: ms between thursdays, div ms per day, div 7 days
30320							calWeek = (th - yth) / 864e5 / 7 + 1;
30321						html.push('<td class="cw">'+ calWeek +'</td>');
30322					}
30323				}
30324				clsName = this.getClassNames(prevMonth);
30325				clsName.push('day');
30326
30327				var content = prevMonth.getUTCDate();
30328
30329				if (this.o.beforeShowDay !== $.noop){
30330					before = this.o.beforeShowDay(this._utc_to_local(prevMonth));
30331					if (before === undefined)
30332						before = {};
30333					else if (typeof before === 'boolean')
30334						before = {enabled: before};
30335					else if (typeof before === 'string')
30336						before = {classes: before};
30337					if (before.enabled === false)
30338						clsName.push('disabled');
30339					if (before.classes)
30340						clsName = clsName.concat(before.classes.split(/\s+/));
30341					if (before.tooltip)
30342						tooltip = before.tooltip;
30343					if (before.content)
30344						content = before.content;
30345				}
30346
30347				//Check if uniqueSort exists (supported by jquery >=1.12 and >=2.2)
30348				//Fallback to unique function for older jquery versions
30349				if ($.isFunction($.uniqueSort)) {
30350					clsName = $.uniqueSort(clsName);
30351				} else {
30352					clsName = $.unique(clsName);
30353				}
30354
30355				html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + ' data-date="' + prevMonth.getTime().toString() + '">' + content + '</td>');
30356				tooltip = null;
30357				if (weekDay === this.o.weekEnd){
30358					html.push('</tr>');
30359				}
30360				prevMonth.setUTCDate(prevMonth.getUTCDate() + 1);
30361			}
30362			this.picker.find('.datepicker-days tbody').html(html.join(''));
30363
30364			var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months';
30365			var months = this.picker.find('.datepicker-months')
30366						.find('.datepicker-switch')
30367							.text(this.o.maxViewMode < 2 ? monthsTitle : year)
30368							.end()
30369						.find('tbody span').removeClass('active');
30370
30371			$.each(this.dates, function(i, d){
30372				if (d.getUTCFullYear() === year)
30373					months.eq(d.getUTCMonth()).addClass('active');
30374			});
30375
30376			if (year < startYear || year > endYear){
30377				months.addClass('disabled');
30378			}
30379			if (year === startYear){
30380				months.slice(0, startMonth).addClass('disabled');
30381			}
30382			if (year === endYear){
30383				months.slice(endMonth+1).addClass('disabled');
30384			}
30385
30386			if (this.o.beforeShowMonth !== $.noop){
30387				var that = this;
30388				$.each(months, function(i, month){
30389          var moDate = new Date(year, i, 1);
30390          var before = that.o.beforeShowMonth(moDate);
30391					if (before === undefined)
30392						before = {};
30393					else if (typeof before === 'boolean')
30394						before = {enabled: before};
30395					else if (typeof before === 'string')
30396						before = {classes: before};
30397					if (before.enabled === false && !$(month).hasClass('disabled'))
30398					    $(month).addClass('disabled');
30399					if (before.classes)
30400					    $(month).addClass(before.classes);
30401					if (before.tooltip)
30402					    $(month).prop('title', before.tooltip);
30403				});
30404			}
30405
30406			// Generating decade/years picker
30407			this._fill_yearsView(
30408				'.datepicker-years',
30409				'year',
30410				10,
30411				year,
30412				startYear,
30413				endYear,
30414				this.o.beforeShowYear
30415			);
30416
30417			// Generating century/decades picker
30418			this._fill_yearsView(
30419				'.datepicker-decades',
30420				'decade',
30421				100,
30422				year,
30423				startYear,
30424				endYear,
30425				this.o.beforeShowDecade
30426			);
30427
30428			// Generating millennium/centuries picker
30429			this._fill_yearsView(
30430				'.datepicker-centuries',
30431				'century',
30432				1000,
30433				year,
30434				startYear,
30435				endYear,
30436				this.o.beforeShowCentury
30437			);
30438		},
30439
30440		updateNavArrows: function(){
30441			if (!this._allow_update)
30442				return;
30443
30444			var d = new Date(this.viewDate),
30445				year = d.getUTCFullYear(),
30446				month = d.getUTCMonth(),
30447				startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity,
30448				startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity,
30449				endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity,
30450				endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity,
30451				prevIsDisabled,
30452				nextIsDisabled,
30453				factor = 1;
30454			switch (this.viewMode){
30455				case 4:
30456					factor *= 10;
30457					/* falls through */
30458				case 3:
30459					factor *= 10;
30460					/* falls through */
30461				case 2:
30462					factor *= 10;
30463					/* falls through */
30464				case 1:
30465					prevIsDisabled = Math.floor(year / factor) * factor < startYear;
30466					nextIsDisabled = Math.floor(year / factor) * factor + factor > endYear;
30467					break;
30468				case 0:
30469					prevIsDisabled = year <= startYear && month < startMonth;
30470					nextIsDisabled = year >= endYear && month >
vendor: 11,149 bytes, lines 30470-30881
30470 endMonth;
30471					break;
30472			}
30473
30474			this.picker.find('.prev').toggleClass('disabled', prevIsDisabled);
30475			this.picker.find('.next').toggleClass('disabled', nextIsDisabled);
30476		},
30477
30478		click: function(e){
30479			e.preventDefault();
30480			e.stopPropagation();
30481
30482			var target, dir, day, year, month;
30483			target = $(e.target);
30484
30485			// Clicked on the switch
30486			if (target.hasClass('datepicker-switch') && this.viewMode !== this.o.maxViewMode){
30487				this.setViewMode(this.viewMode + 1);
30488			}
30489
30490			// Clicked on today button
30491			if (target.hasClass('today') && !target.hasClass('day')){
30492				this.setViewMode(0);
30493				this._setDate(UTCToday(), this.o.todayBtn === 'linked' ? null : 'view');
30494			}
30495
30496			// Clicked on clear button
30497			if (target.hasClass('clear')){
30498				this.clearDates();
30499			}
30500
30501			if (!target.hasClass('disabled')){
30502				// Clicked on a month, year, decade, century
30503				if (target.hasClass('month')
30504						|| target.hasClass('year')
30505						|| target.hasClass('decade')
30506						|| target.hasClass('century')) {
30507					this.viewDate.setUTCDate(1);
30508
30509					day = 1;
30510					if (this.viewMode === 1){
30511						month = target.parent().find('span').index(target);
30512						year = this.viewDate.getUTCFullYear();
30513						this.viewDate.setUTCMonth(month);
30514					} else {
30515						month = 0;
30516						year = Number(target.text());
30517						this.viewDate.setUTCFullYear(year);
30518					}
30519
30520					this._trigger(DPGlobal.viewModes[this.viewMode - 1].e, this.viewDate);
30521
30522					if (this.viewMode === this.o.minViewMode){
30523						this._setDate(UTCDate(year, month, day));
30524					} else {
30525						this.setViewMode(this.viewMode - 1);
30526						this.fill();
30527					}
30528				}
30529			}
30530
30531			if (this.picker.is(':visible') && this._focused_from){
30532				this._focused_from.focus();
30533			}
30534			delete this._focused_from;
30535		},
30536
30537		dayCellClick: function(e){
30538			var $target = $(e.currentTarget);
30539			var timestamp = $target.data('date');
30540			var date = new Date(timestamp);
30541
30542			if (this.o.updateViewDate) {
30543				if (date.getUTCFullYear() !== this.viewDate.getUTCFullYear()) {
30544					this._trigger('changeYear', this.viewDate);
30545				}
30546
30547				if (date.getUTCMonth() !== this.viewDate.getUTCMonth()) {
30548					this._trigger('changeMonth', this.viewDate);
30549				}
30550			}
30551			this._setDate(date);
30552		},
30553
30554		// Clicked on prev or next
30555		navArrowsClick: function(e){
30556			var $target = $(e.currentTarget);
30557			var dir = $target.hasClass('prev') ? -1 : 1;
30558			if (this.viewMode !== 0){
30559				dir *= DPGlobal.viewModes[this.viewMode].navStep * 12;
30560			}
30561			this.viewDate = this.moveMonth(this.viewDate, dir);
30562			this._trigger(DPGlobal.viewModes[this.viewMode].e, this.viewDate);
30563			this.fill();
30564		},
30565
30566		_toggle_multidate: function(date){
30567			var ix = this.dates.contains(date);
30568			if (!date){
30569				this.dates.clear();
30570			}
30571
30572			if (ix !== -1){
30573				if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive){
30574					this.dates.remove(ix);
30575				}
30576			} else if (this.o.multidate === false) {
30577				this.dates.clear();
30578				this.dates.push(date);
30579			}
30580			else {
30581				this.dates.push(date);
30582			}
30583
30584			if (typeof this.o.multidate === 'number')
30585				while (this.dates.length > this.o.multidate)
30586					this.dates.remove(0);
30587		},
30588
30589		_setDate: function(date, which){
30590			if (!which || which === 'date')
30591				this._toggle_multidate(date && new Date(date));
30592			if ((!which && this.o.updateViewDate) || which === 'view')
30593				this.viewDate = date && new Date(date);
30594
30595			this.fill();
30596			this.setValue();
30597			if (!which || which !== 'view') {
30598				this._trigger('changeDate');
30599			}
30600			this.inputField.trigger('change');
30601			if (this.o.autoclose && (!which || which === 'date')){
30602				this.hide();
30603			}
30604		},
30605
30606		moveDay: function(date, dir){
30607			var newDate = new Date(date);
30608			newDate.setUTCDate(date.getUTCDate() + dir);
30609
30610			return newDate;
30611		},
30612
30613		moveWeek: function(date, dir){
30614			return this.moveDay(date, dir * 7);
30615		},
30616
30617		moveMonth: function(date, dir){
30618			if (!isValidDate(date))
30619				return this.o.defaultViewDate;
30620			if (!dir)
30621				return date;
30622			var new_date = new Date(date.valueOf()),
30623				day = new_date.getUTCDate(),
30624				month = new_date.getUTCMonth(),
30625				mag = Math.abs(dir),
30626				new_month, test;
30627			dir = dir > 0 ? 1 : -1;
30628			if (mag === 1){
30629				test = dir === -1
30630					// If going back one month, make sure month is not current month
30631					// (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)
30632					? function(){
30633						return new_date.getUTCMonth() === month;
30634					}
30635					// If going forward one month, make sure month is as expected
30636					// (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)
30637					: function(){
30638						return new_date.getUTCMonth() !== new_month;
30639					};
30640				new_month = month + dir;
30641				new_date.setUTCMonth(new_month);
30642				// Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11
30643				new_month = (new_month + 12) % 12;
30644			}
30645			else {
30646				// For magnitudes >1, move one month at a time...
30647				for (var i=0; i < mag; i++)
30648					// ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...
30649					new_date = this.moveMonth(new_date, dir);
30650				// ...then reset the day, keeping it in the new month
30651				new_month = new_date.getUTCMonth();
30652				new_date.setUTCDate(day);
30653				test = function(){
30654					return new_month !== new_date.getUTCMonth();
30655				};
30656			}
30657			// Common date-resetting loop -- if date is beyond end of month, make it
30658			// end of month
30659			while (test()){
30660				new_date.setUTCDate(--day);
30661				new_date.setUTCMonth(new_month);
30662			}
30663			return new_date;
30664		},
30665
30666		moveYear: function(date, dir){
30667			return this.moveMonth(date, dir*12);
30668		},
30669
30670		moveAvailableDate: function(date, dir, fn){
30671			do {
30672				date = this[fn](date, dir);
30673
30674				if (!this.dateWithinRange(date))
30675					return false;
30676
30677				fn = 'moveDay';
30678			}
30679			while (this.dateIsDisabled(date));
30680
30681			return date;
30682		},
30683
30684		weekOfDateIsDisabled: function(date){
30685			return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1;
30686		},
30687
30688		dateIsDisabled: function(date){
30689			return (
30690				this.weekOfDateIsDisabled(date) ||
30691				$.grep(this.o.datesDisabled, function(d){
30692					return isUTCEquals(date, d);
30693				}).length > 0
30694			);
30695		},
30696
30697		dateWithinRange: function(date){
30698			return date >= this.o.startDate && date <= this.o.endDate;
30699		},
30700
30701		keydown: function(e){
30702			if (!this.picker.is(':visible')){
30703				if (e.keyCode === 40 || e.keyCode === 27) { // allow down to re-show picker
30704					this.show();
30705					e.stopPropagation();
30706        }
30707				return;
30708			}
30709			var dateChanged = false,
30710				dir, newViewDate,
30711				focusDate = this.focusDate || this.viewDate;
30712			switch (e.keyCode){
30713				case 27: // escape
30714					if (this.focusDate){
30715						this.focusDate = null;
30716						this.viewDate = this.dates.get(-1) || this.viewDate;
30717						this.fill();
30718					}
30719					else
30720						this.hide();
30721					e.preventDefault();
30722					e.stopPropagation();
30723					break;
30724				case 37: // left
30725				case 38: // up
30726				case 39: // right
30727				case 40: // down
30728					if (!this.o.keyboardNavigation || this.o.daysOfWeekDisabled.length === 7)
30729						break;
30730					dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1;
30731          if (this.viewMode === 0) {
30732  					if (e.ctrlKey){
30733  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
30734
30735  						if (newViewDate)
30736  							this._trigger('changeYear', this.viewDate);
30737  					} else if (e.shiftKey){
30738  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
30739
30740  						if (newViewDate)
30741  							this._trigger('changeMonth', this.viewDate);
30742  					} else if (e.keyCode === 37 || e.keyCode === 39){
30743  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay');
30744  					} else if (!this.weekOfDateIsDisabled(focusDate)){
30745  						newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek');
30746  					}
30747          } else if (this.viewMode === 1) {
30748            if (e.keyCode === 38 || e.keyCode === 40) {
30749              dir = dir * 4;
30750            }
30751            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth');
30752          } else if (this.viewMode === 2) {
30753            if (e.keyCode === 38 || e.keyCode === 40) {
30754              dir = dir * 4;
30755            }
30756            newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear');
30757          }
30758					if (newViewDate){
30759						this.focusDate = this.viewDate = newViewDate;
30760						this.setValue();
30761						this.fill();
30762						e.preventDefault();
30763					}
30764					break;
30765				case 13: // enter
30766					if (!this.o.forceParse)
30767						break;
30768					focusDate = this.focusDate || this.dates.get(-1) || this.viewDate;
30769					if (this.o.keyboardNavigation) {
30770						this._toggle_multidate(focusDate);
30771						dateChanged = true;
30772					}
30773					this.focusDate = null;
30774					this.viewDate = this.dates.get(-1) || this.viewDate;
30775					this.setValue();
30776					this.fill();
30777					if (this.picker.is(':visible')){
30778						e.preventDefault();
30779						e.stopPropagation();
30780						if (this.o.autoclose)
30781							this.hide();
30782					}
30783					break;
30784				case 9: // tab
30785					this.focusDate = null;
30786					this.viewDate = this.dates.get(-1) || this.viewDate;
30787					this.fill();
30788					this.hide();
30789					break;
30790			}
30791			if (dateChanged){
30792				if (this.dates.length)
30793					this._trigger('changeDate');
30794				else
30795					this._trigger('clearDate');
30796				this.inputField.trigger('change');
30797			}
30798		},
30799
30800		setViewMode: function(viewMode){
30801			this.viewMode = viewMode;
30802			this.picker
30803				.children('div')
30804				.hide()
30805				.filter('.datepicker-' + DPGlobal.viewModes[this.viewMode].clsName)
30806					.show();
30807			this.updateNavArrows();
30808      this._trigger('changeViewMode', new Date(this.viewDate));
30809		}
30810	};
30811
30812	var DateRangePicker = function(element, options){
30813		$.data(element, 'datepicker', this);
30814		this.element = $(element);
30815		this.inputs = $.map(options.inputs, function(i){
30816			return i.jquery ? i[0] : i;
30817		});
30818		delete options.inputs;
30819
30820		this.keepEmptyValues = options.keepEmptyValues;
30821		delete options.keepEmptyValues;
30822
30823		datepickerPlugin.call($(this.inputs), options)
30824			.on('changeDate', $.proxy(this.dateUpdated, this));
30825
30826		this.pickers = $.map(this.inputs, function(i){
30827			return $.data(i, 'datepicker');
30828		});
30829		this.updateDates();
30830	};
30831	DateRangePicker.prototype = {
30832		updateDates: function(){
30833			this.dates = $.map(this.pickers, function(i){
30834				return i.getUTCDate();
30835			});
30836			this.updateRanges();
30837		},
30838		updateRanges: function(){
30839			var range = $.map(this.dates, function(d){
30840				return d.valueOf();
30841			});
30842			$.each(this.pickers, function(i, p){
30843				p.setRange(range);
30844			});
30845		},
30846		clearDates: function(){
30847			$.each(this.pickers, function(i, p){
30848				p.clearDates();
30849			});
30850		},
30851		dateUpdated: function(e){
30852			// `this.updating` is a workaround for preventing infinite recursion
30853			// between `changeDate` triggering and `setUTCDate` calling.  Until
30854			// there is a better mechanism.
30855			if (this.updating)
30856				return;
30857			this.updating = true;
30858
30859			var dp = $.data(e.target, 'datepicker');
30860
30861			if (dp === undefined) {
30862				return;
30863			}
30864
30865			var new_date = dp.getUTCDate(),
30866				keep_empty_values = this.keepEmptyValues,
30867				i = $.inArray(e.target, this.inputs),
30868				j = i - 1,
30869				k = i + 1,
30870				l = this.inputs.length;
30871			if (i === -1)
30872				return;
30873
30874			$.each(this.pickers, function(i, p){
30875				if (!p.getUTCDate() && (p === dp || !keep_empty_values))
30876					p.setUTCDate(new_date);
30877			});
30878
30879			if (new_date < this.dates[j]){
30880				// Date being moved earlier/left
30881				while (j >= 0 && new_date < this.dates[j]
vendor: 12,604 bytes, lines 30881-31331
30881){
30882					this.pickers[j--].setUTCDate(new_date);
30883				}
30884			} else if (new_date > this.dates[k]){
30885				// Date being moved later/right
30886				while (k < l && new_date > this.dates[k]){
30887					this.pickers[k++].setUTCDate(new_date);
30888				}
30889			}
30890			this.updateDates();
30891
30892			delete this.updating;
30893		},
30894		destroy: function(){
30895			$.map(this.pickers, function(p){ p.destroy(); });
30896			$(this.inputs).off('changeDate', this.dateUpdated);
30897			delete this.element.data().datepicker;
30898		},
30899		remove: alias('destroy', 'Method `remove` is deprecated and will be removed in version 2.0. Use `destroy` instead')
30900	};
30901
30902	function opts_from_el(el, prefix){
30903		// Derive options from element data-attrs
30904		var data = $(el).data(),
30905			out = {}, inkey,
30906			replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])');
30907		prefix = new RegExp('^' + prefix.toLowerCase());
30908		function re_lower(_,a){
30909			return a.toLowerCase();
30910		}
30911		for (var key in data)
30912			if (prefix.test(key)){
30913				inkey = key.replace(replace, re_lower);
30914				out[inkey] = data[key];
30915			}
30916		return out;
30917	}
30918
30919	function opts_from_locale(lang){
30920		// Derive options from locale plugins
30921		var out = {};
30922		// Check if "de-DE" style date is available, if not language should
30923		// fallback to 2 letter code eg "de"
30924		if (!dates[lang]){
30925			lang = lang.split('-')[0];
30926			if (!dates[lang])
30927				return;
30928		}
30929		var d = dates[lang];
30930		$.each(locale_opts, function(i,k){
30931			if (k in d)
30932				out[k] = d[k];
30933		});
30934		return out;
30935	}
30936
30937	var old = $.fn.datepicker;
30938	var datepickerPlugin = function(option){
30939		var args = Array.apply(null, arguments);
30940		args.shift();
30941		var internal_return;
30942		this.each(function(){
30943			var $this = $(this),
30944				data = $this.data('datepicker'),
30945				options = typeof option === 'object' && option;
30946			if (!data){
30947				var elopts = opts_from_el(this, 'date'),
30948					// Preliminary otions
30949					xopts = $.extend({}, defaults, elopts, options),
30950					locopts = opts_from_locale(xopts.language),
30951					// Options priority: js args, data-attrs, locales, defaults
30952					opts = $.extend({}, defaults, locopts, elopts, options);
30953				if ($this.hasClass('input-daterange') || opts.inputs){
30954					$.extend(opts, {
30955						inputs: opts.inputs || $this.find('input').toArray()
30956					});
30957					data = new DateRangePicker(this, opts);
30958				}
30959				else {
30960					data = new Datepicker(this, opts);
30961				}
30962				$this.data('datepicker', data);
30963			}
30964			if (typeof option === 'string' && typeof data[option] === 'function'){
30965				internal_return = data[option].apply(data, args);
30966			}
30967		});
30968
30969		if (
30970			internal_return === undefined ||
30971			internal_return instanceof Datepicker ||
30972			internal_return instanceof DateRangePicker
30973		)
30974			return this;
30975
30976		if (this.length > 1)
30977			throw new Error('Using only allowed for the collection of a single element (' + option + ' function)');
30978		else
30979			return internal_return;
30980	};
30981	$.fn.datepicker = datepickerPlugin;
30982
30983	var defaults = $.fn.datepicker.defaults = {
30984		assumeNearbyYear: false,
30985		autoclose: false,
30986		beforeShowDay: $.noop,
30987		beforeShowMonth: $.noop,
30988		beforeShowYear: $.noop,
30989		beforeShowDecade: $.noop,
30990		beforeShowCentury: $.noop,
30991		calendarWeeks: false,
30992		clearBtn: false,
30993		toggleActive: false,
30994		daysOfWeekDisabled: [],
30995		daysOfWeekHighlighted: [],
30996		datesDisabled: [],
30997		endDate: Infinity,
30998		forceParse: true,
30999		format: 'mm/dd/yyyy',
31000		keepEmptyValues: false,
31001		keyboardNavigation: true,
31002		language: 'en',
31003		minViewMode: 0,
31004		maxViewMode: 4,
31005		multidate: false,
31006		multidateSeparator: ',',
31007		orientation: "auto",
31008		rtl: false,
31009		startDate: -Infinity,
31010		startView: 0,
31011		todayBtn: false,
31012		todayHighlight: false,
31013		updateViewDate: true,
31014		weekStart: 0,
31015		disableTouchKeyboard: false,
31016		enableOnReadonly: true,
31017		showOnFocus: true,
31018		zIndexOffset: 20,
31019		container: 'body',
31020		immediateUpdates: false,
31021		title: '',
31022		templates: {
31023			leftArrow: '&#x00AB;',
31024			rightArrow: '&#x00BB;'
31025		},
31026    showWeekDays: true
31027	};
31028	var locale_opts = $.fn.datepicker.locale_opts = [
31029		'format',
31030		'rtl',
31031		'weekStart'
31032	];
31033	$.fn.datepicker.Constructor = Datepicker;
31034	var dates = $.fn.datepicker.dates = {
31035		en: {
31036			days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
31037			daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
31038			daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
31039			months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
31040			monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
31041			today: "Today",
31042			clear: "Clear",
31043			titleFormat: "MM yyyy"
31044		}
31045	};
31046
31047	var DPGlobal = {
31048		viewModes: [
31049			{
31050				names: ['days', 'month'],
31051				clsName: 'days',
31052				e: 'changeMonth'
31053			},
31054			{
31055				names: ['months', 'year'],
31056				clsName: 'months',
31057				e: 'changeYear',
31058				navStep: 1
31059			},
31060			{
31061				names: ['years', 'decade'],
31062				clsName: 'years',
31063				e: 'changeDecade',
31064				navStep: 10
31065			},
31066			{
31067				names: ['decades', 'century'],
31068				clsName: 'decades',
31069				e: 'changeCentury',
31070				navStep: 100
31071			},
31072			{
31073				names: ['centuries', 'millennium'],
31074				clsName: 'centuries',
31075				e: 'changeMillennium',
31076				navStep: 1000
31077			}
31078		],
31079		validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g,
31080		nonpunctuation: /[^ -\/:-@\u5e74\u6708\u65e5\[-`{-~\t\n\r]+/g,
31081		parseFormat: function(format){
31082			if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function')
31083                return format;
31084            // IE treats \0 as a string end in inputs (truncating the value),
31085			// so it's a bad format delimiter, anyway
31086			var separators = format.replace(this.validParts, '\0').split('\0'),
31087				parts = format.match(this.validParts);
31088			if (!separators || !separators.length || !parts || parts.length === 0){
31089				throw new Error("Invalid date format.");
31090			}
31091			return {separators: separators, parts: parts};
31092		},
31093		parseDate: function(date, format, language, assumeNearby){
31094			if (!date)
31095				return undefined;
31096			if (date instanceof Date)
31097				return date;
31098			if (typeof format === 'string')
31099				format = DPGlobal.parseFormat(format);
31100			if (format.toValue)
31101				return format.toValue(date, format, language);
31102			var fn_map = {
31103					d: 'moveDay',
31104					m: 'moveMonth',
31105					w: 'moveWeek',
31106					y: 'moveYear'
31107				},
31108				dateAliases = {
31109					yesterday: '-1d',
31110					today: '+0d',
31111					tomorrow: '+1d'
31112				},
31113				parts, part, dir, i, fn;
31114			if (date in dateAliases){
31115				date = dateAliases[date];
31116			}
31117			if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/i.test(date)){
31118				parts = date.match(/([\-+]\d+)([dmwy])/gi);
31119				date = new Date();
31120				for (i=0; i < parts.length; i++){
31121					part = parts[i].match(/([\-+]\d+)([dmwy])/i);
31122					dir = Number(part[1]);
31123					fn = fn_map[part[2].toLowerCase()];
31124					date = Datepicker.prototype[fn](date, dir);
31125				}
31126				return Datepicker.prototype._zero_utc_time(date);
31127			}
31128
31129			parts = date && date.match(this.nonpunctuation) || [];
31130
31131			function applyNearbyYear(year, threshold){
31132				if (threshold === true)
31133					threshold = 10;
31134
31135				// if year is 2 digits or less, than the user most likely is trying to get a recent century
31136				if (year < 100){
31137					year += 2000;
31138					// if the new year is more than threshold years in advance, use last century
31139					if (year > ((new Date()).getFullYear()+threshold)){
31140						year -= 100;
31141					}
31142				}
31143
31144				return year;
31145			}
31146
31147			var parsed = {},
31148				setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'],
31149				setters_map = {
31150					yyyy: function(d,v){
31151						return d.setUTCFullYear(assumeNearby ? applyNearbyYear(v, assumeNearby) : v);
31152					},
31153					m: function(d,v){
31154						if (isNaN(d))
31155							return d;
31156						v -= 1;
31157						while (v < 0) v += 12;
31158						v %= 12;
31159						d.setUTCMonth(v);
31160						while (d.getUTCMonth() !== v)
31161							d.setUTCDate(d.getUTCDate()-1);
31162						return d;
31163					},
31164					d: function(d,v){
31165						return d.setUTCDate(v);
31166					}
31167				},
31168				val, filtered;
31169			setters_map['yy'] = setters_map['yyyy'];
31170			setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
31171			setters_map['dd'] = setters_map['d'];
31172			date = UTCToday();
31173			var fparts = format.parts.slice();
31174			// Remove noop parts
31175			if (parts.length !== fparts.length){
31176				fparts = $(fparts).filter(function(i,p){
31177					return $.inArray(p, setters_order) !== -1;
31178				}).toArray();
31179			}
31180			// Process remainder
31181			function match_part(){
31182				var m = this.slice(0, parts[i].length),
31183					p = parts[i].slice(0, m.length);
31184				return m.toLowerCase() === p.toLowerCase();
31185			}
31186			if (parts.length === fparts.length){
31187				var cnt;
31188				for (i=0, cnt = fparts.length; i < cnt; i++){
31189					val = parseInt(parts[i], 10);
31190					part = fparts[i];
31191					if (isNaN(val)){
31192						switch (part){
31193							case 'MM':
31194								filtered = $(dates[language].months).filter(match_part);
31195								val = $.inArray(filtered[0], dates[language].months) + 1;
31196								break;
31197							case 'M':
31198								filtered = $(dates[language].monthsShort).filter(match_part);
31199								val = $.inArray(filtered[0], dates[language].monthsShort) + 1;
31200								break;
31201						}
31202					}
31203					parsed[part] = val;
31204				}
31205				var _date, s;
31206				for (i=0; i < setters_order.length; i++){
31207					s = setters_order[i];
31208					if (s in parsed && !isNaN(parsed[s])){
31209						_date = new Date(date);
31210						setters_map[s](_date, parsed[s]);
31211						if (!isNaN(_date))
31212							date = _date;
31213					}
31214				}
31215			}
31216			return date;
31217		},
31218		formatDate: function(date, format, language){
31219			if (!date)
31220				return '';
31221			if (typeof format === 'string')
31222				format = DPGlobal.parseFormat(format);
31223			if (format.toDisplay)
31224                return format.toDisplay(date, format, language);
31225            var val = {
31226				d: date.getUTCDate(),
31227				D: dates[language].daysShort[date.getUTCDay()],
31228				DD: dates[language].days[date.getUTCDay()],
31229				m: date.getUTCMonth() + 1,
31230				M: dates[language].monthsShort[date.getUTCMonth()],
31231				MM: dates[language].months[date.getUTCMonth()],
31232				yy: date.getUTCFullYear().toString().substring(2),
31233				yyyy: date.getUTCFullYear()
31234			};
31235			val.dd = (val.d < 10 ? '0' : '') + val.d;
31236			val.mm = (val.m < 10 ? '0' : '') + val.m;
31237			date = [];
31238			var seps = $.extend([], format.separators);
31239			for (var i=0, cnt = format.parts.length; i <= cnt; i++){
31240				if (seps.length)
31241					date.push(seps.shift());
31242				date.push(val[format.parts[i]]);
31243			}
31244			return date.join('');
31245		},
31246		headTemplate: '<thead>'+
31247			              '<tr>'+
31248			                '<th colspan="7" class="datepicker-title"></th>'+
31249			              '</tr>'+
31250							'<tr>'+
31251								'<th class="prev">'+defaults.templates.leftArrow+'</th>'+
31252								'<th colspan="5" class="datepicker-switch"></th>'+
31253								'<th class="next">'+defaults.templates.rightArrow+'</th>'+
31254							'</tr>'+
31255						'</thead>',
31256		contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
31257		footTemplate: '<tfoot>'+
31258							'<tr>'+
31259								'<th colspan="7" class="today"></th>'+
31260							'</tr>'+
31261							'<tr>'+
31262								'<th colspan="7" class="clear"></th>'+
31263							'</tr>'+
31264						'</tfoot>'
31265	};
31266	DPGlobal.template = '<div class="datepicker">'+
31267							'<div class="datepicker-days">'+
31268								'<table class="table-condensed">'+
31269									DPGlobal.headTemplate+
31270									'<tbody></tbody>'+
31271									DPGlobal.footTemplate+
31272								'</table>'+
31273							'</div>'+
31274							'<div class="datepicker-months">'+
31275								'<table class="table-condensed">'+
31276									DPGlobal.headTemplate+
31277									DPGlobal.contTemplate+
31278									DPGlobal.footTemplate+
31279								'</table>'+
31280							'</div>'+
31281							'<div class="datepicker-years">'+
31282								'<table class="table-condensed">'+
31283									DPGlobal.headTemplate+
31284									DPGlobal.contTemplate+
31285									DPGlobal.footTemplate+
31286								'</table>'+
31287							'</div>'+
31288							'<div class="datepicker-decades">'+
31289								'<table class="table-condensed">'+
31290									DPGlobal.headTemplate+
31291									DPGlobal.contTemplate+
31292									DPGlobal.footTemplate+
31293								'</table>'+
31294							'</div>'+
31295							'<div class="datepicker-centuries">'+
31296								'<table class="table-condensed">'+
31297									DPGlobal.headTemplate+
31298									DPGlobal.contTemplate+
31299									DPGlobal.footTemplate+
31300								'</table>'+
31301							'</div>'+
31302						'</div>';
31303
31304	$.fn.datepicker.DPGlobal = DPGlobal;
31305
31306
31307	/* DATEPICKER NO CONFLICT
31308	* =================== */
31309
31310	$.fn.datepicker.noConflict = function(){
31311		$.fn.datepicker = old;
31312		return this;
31313	};
31314
31315	/* DATEPICKER VERSION
31316	 * =================== */
31317	$.fn.datepicker.version = '1.8.0';
31318
31319	$.fn.datepicker.deprecated = function(msg){
31320		var console = window.console;
31321		if (console && console.warn) {
31322			console.warn('DEPRECATED: ' + msg);
31323		}
31324	};
31325
31326
31327	/* DATEPICKER DATA-API
31328	* ================== */
31329
31330	$(document).on(
31331		'focus.datepicker.data-api click.datepicker.data-api',
31332		'[data-provide="datepicker"]',
31333		function(e){
31334			var $this = $(this);
31335			if ($this.data('datepicker'))
31336				return;
31337			e.preventDefault();
31338			// component click requires us to explicitly show it
31339			datepickerPlugin.call($this, 'show');
31340		}
31341	);
31342	$(function(){
31343		datepickerPlugin.call($('[data-provide="datepicker-inline"]'));
31344	});
31345
31346}));
31347
31348
31349/**
31350 * Traditional Chinese translation for bootstrap-datepicker
31351 * Rung-Sheng Jang <[email protected]>
31352 * FrankWu  <[email protected]> Fix more appropriate use of Traditional Chinese habit
31353 */
31354(function($){
31355	$.fn.datepicker.dates['zh-TW'] = {
31356		days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
31357		daysShort: ["週日", "週一", "週二", "週三", "週四", "週五", "週六", "週日"],
31358		daysMin:  ["日", "一", "二", "三", "四", "五", "六", "日"],
31359		months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
31360		monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
31361		today: "今天",
31362		format: "yyyy年mm月dd日",
31363		weekStart: 1
31364	};
31365}(jQuery));(function($) {
31366    $(function() {
31367        $sel = $('[data-unicode="mdu_C9VtfBP030aBhYYvMyiZtQ"]');
31368        $sel.find('iframe').iFrameResize({
31369            log: false,
31370            messageCallback: function (event) {
31371                if(event.message.receiver === 'cross.datepicker'+event.message.url) {
31372                    var offset = $('[src^="' + event.message.url + '"]').offset();
31373                    var tmp = $.extend({
31374                        "language": "zh-TW",
31375                        "position": "absolute",
31376                        "format": "mm/dd/yyyy"
31377                    }, event.message);
31378                    tmp.top = offset.top + event.message.offset.top;
31379                    tmp.left = offset.left + event.message.offset.left;
31380                    $('.cross-dp-input').datepicker('destroy').remove();
31381                    $('<input class="cross-dp-input">')
31382                        .val(event.message.value || "")
31383                        .css(tmp)
31384                        .appendTo(document.body)
31385                        .datepicker(tmp)
31386                        .on('changeDate', function (e) {
31387                            event.iframe.iFrameResizer.sendMessage({
31388                                receiver: 'cross.datepicker.callback'+event.message.url,
31389                                date: $(this).val(),
31390                                selector: event.message.selector
31391                            }, "*");
31392                            $(this).datepicker('destroy').remove();
31393                        })
31394                        .on('hide', function (e) {
31395                            $(this).remove();
31396                        })
31397                        .focus().css("visibility", "hidden");
31398                }
31399            }
31400        });
31401
31402    });
31403
31404})(jQuery);
31405
31406; })(jQuery);/* compress error:[253]var retCode = messageData.type in { true: 1, false: 1, undefined: 1 };*/
31407
31408/* MODULE 3a0d7da1-9bad-41da-bb89-64bd1e0eddc8, Version: 1.1.3 */
31409;(function($) {; var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
31410
31411// NB: does not validate input
31412function encode(int) {
31413    if (int === 0) {
31414        return CHARSET[0];
31415    }
31416
31417    var res = "";
31418    while (int > 0) {
31419        res = CHARSET[int % 62] + res;
31420        int = Math.floor(int / 62);
31421    }
31422    return res;
31423};
31424
31425function decode(str) {
31426    var res = 0,
31427        length = str.length,
31428        i, char;
31429    for (i = 0; i < length; i++) {
31430        char = str.charCodeAt(i);
31431        if (char < 58) { // 0-9
31432            char = char - 48;
31433        } else if (char < 91) { // A-Z
31434            char = char - 29;
31435        } else { // a-z
31436            char = char - 87;
31437        }
31438        res += char * Math.pow(62, length - i - 1);
31439    }
31440    return res;
31441};
31442
31443function base62() {
31444    var id; //base62
31445    do {
31446      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
31447    } while (id.match(/^[0-9]/i) !== null);
31448    return id;
31449}/**
31450 * Swiper 11.2.10
31451 * Most modern mobile touch slider and framework with hardware accelerated transitions
31452 * https://swiperjs.com
31453 *
31454 * Copyright 2014-2025 Vladimir Kharlampidi
31455 *
31456 * Released under the MIT License
31457 *
31458 * Released on: June 28, 2025
31459 */
31460
31461var Swiper=function(){"use strict";function e(e){return null!==e&&"object"==typeof e&&"constructor"in e&&e.constructor===Object}function t(s,a){void 0===s&&(s={}),void 0===a&&(a={});const i=["__proto__","constructor","prototype"];Object.keys(a).filter((e=>
vendor: 4,922 bytes, line 31461
31461i.indexOf(e)<0)).forEach((i=>{void 0===s[i]?s[i]=a[i]:e(a[i])&&e(s[i])&&Object.keys(a[i]).length>0&&t(s[i],a[i])}))}const s={body:{},addEventListener(){},removeEventListener(){},activeElement:{blur(){},nodeName:""},querySelector:()=>null,querySelectorAll:()=>[],getElementById:()=>null,createEvent:()=>({initEvent(){}}),createElement:()=>({children:[],childNodes:[],style:{},setAttribute(){},getElementsByTagName:()=>[]}),createElementNS:()=>({}),importNode:()=>null,location:{hash:"",host:"",hostname:"",href:"",origin:"",pathname:"",protocol:"",search:""}};function a(){const e="undefined"!=typeof document?document:{};return t(e,s),e}const i={document:s,navigator:{userAgent:""},location:{hash:"",host:"",hostname:"",href:"",origin:"",pathname:"",protocol:"",search:""},history:{replaceState(){},pushState(){},go(){},back(){}},CustomEvent:function(){return this},addEventListener(){},removeEventListener(){},getComputedStyle:()=>({getPropertyValue:()=>""}),Image(){},Date(){},screen:{},setTimeout(){},clearTimeout(){},matchMedia:()=>({}),requestAnimationFrame:e=>"undefined"==typeof setTimeout?(e(),null):setTimeout(e,0),cancelAnimationFrame(e){"undefined"!=typeof setTimeout&&clearTimeout(e)}};function r(){const e="undefined"!=typeof window?window:{};return t(e,i),e}function n(e){return void 0===e&&(e=""),e.trim().split(" ").filter((e=>!!e.trim()))}function l(e,t){return void 0===t&&(t=0),setTimeout(e,t)}function o(){return Date.now()}function d(e,t){void 0===t&&(t="x");const s=r();let a,i,n;const l=function(e){const t=r();let s;return t.getComputedStyle&&(s=t.getComputedStyle(e,null)),!s&&e.currentStyle&&(s=e.currentStyle),s||(s=e.style),s}(e);return s.WebKitCSSMatrix?(i=l.transform||l.webkitTransform,i.split(",").length>6&&(i=i.split(", ").map((e=>e.replace(",","."))).join(", ")),n=new s.WebKitCSSMatrix("none"===i?"":i)):(n=l.MozTransform||l.OTransform||l.MsTransform||l.msTransform||l.transform||l.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,"),a=n.toString().split(",")),"x"===t&&(i=s.WebKitCSSMatrix?n.m41:16===a.length?parseFloat(a[12]):parseFloat(a[4])),"y"===t&&(i=s.WebKitCSSMatrix?n.m42:16===a.length?parseFloat(a[13]):parseFloat(a[5])),i||0}function c(e){return"object"==typeof e&&null!==e&&e.constructor&&"Object"===Object.prototype.toString.call(e).slice(8,-1)}function p(){const e=Object(arguments.length<=0?void 0:arguments[0]),t=["__proto__","constructor","prototype"];for(let a=1;a<arguments.length;a+=1){const i=a<0||arguments.length<=a?void 0:arguments[a];if(null!=i&&(s=i,!("undefined"!=typeof window&&void 0!==window.HTMLElement?s instanceof HTMLElement:s&&(1===s.nodeType||11===s.nodeType)))){const s=Object.keys(Object(i)).filter((e=>t.indexOf(e)<0));for(let t=0,a=s.length;t<a;t+=1){const a=s[t],r=Object.getOwnPropertyDescriptor(i,a);void 0!==r&&r.enumerable&&(c(e[a])&&c(i[a])?i[a].__swiper__?e[a]=i[a]:p(e[a],i[a]):!c(e[a])&&c(i[a])?(e[a]={},i[a].__swiper__?e[a]=i[a]:p(e[a],i[a])):e[a]=i[a])}}}var s;return e}function u(e,t,s){e.style.setProperty(t,s)}function m(e){let{swiper:t,targetPosition:s,side:a}=e;const i=r(),n=-t.translate;let l,o=null;const d=t.params.speed;t.wrapperEl.style.scrollSnapType="none",i.cancelAnimationFrame(t.cssModeFrameID);const c=s>n?"next":"prev",p=(e,t)=>"next"===c&&e>=t||"prev"===c&&e<=t,u=()=>{l=(new Date).getTime(),null===o&&(o=l);const e=Math.max(Math.min((l-o)/d,1),0),r=.5-Math.cos(e*Math.PI)/2;let c=n+r*(s-n);if(p(c,s)&&(c=s),t.wrapperEl.scrollTo({[a]:c}),p(c,s))return t.wrapperEl.style.overflow="hidden",t.wrapperEl.style.scrollSnapType="",setTimeout((()=>{t.wrapperEl.style.overflow="",t.wrapperEl.scrollTo({[a]:c})})),void i.cancelAnimationFrame(t.cssModeFrameID);t.cssModeFrameID=i.requestAnimationFrame(u)};u()}function h(e){return e.querySelector(".swiper-slide-transform")||e.shadowRoot&&e.shadowRoot.querySelector(".swiper-slide-transform")||e}function f(e,t){void 0===t&&(t="");const s=r(),a=[...e.children];return s.HTMLSlotElement&&e instanceof HTMLSlotElement&&a.push(...e.assignedElements()),t?a.filter((e=>e.matches(t))):a}function g(e){try{return void console.warn(e)}catch(e){}}function v(e,t){void 0===t&&(t=[]);const s=document.createElement(e);return s.classList.add(...Array.isArray(t)?t:n(t)),s}function w(e){const t=r(),s=a(),i=e.getBoundingClientRect(),n=s.body,l=e.clientTop||n.clientTop||0,o=e.clientLeft||n.clientLeft||0,d=e===t?t.scrollY:e.scrollTop,c=e===t?t.scrollX:e.scrollLeft;return{top:i.top+d-l,left:i.left+c-o}}function b(e,t){return r().getComputedStyle(e,null).getPropertyValue(t)}function y(e){let t,s=e;if(s){for(t=0;null!==(s=s.previousSibling);)1===s.nodeType&&(t+=1);return t}}function E(e,t){const s=[];let a=e.parentElement;for(;a;)t?a.matches(t)&&s.push(a):s.push(a),a=a.parentElement;return s}function x(e,t){t&&e.addEventListener("transitionend",(function s(a){a.target===e&&(t.call(e,a),e.removeEventListener("transitionend",s))}))}function S(e,t,s){const a=r();
vendor: 4,280 bytes, line 31461
31461return s?e["width"===t?"offsetWidth":"offsetHeight"]+parseFloat(a.getComputedStyle(e,null).getPropertyValue("width"===t?"margin-right":"margin-top"))+parseFloat(a.getComputedStyle(e,null).getPropertyValue("width"===t?"margin-left":"margin-bottom")):e.offsetWidth}function T(e){return(Array.isArray(e)?e:[e]).filter((e=>!!e))}function M(e){return t=>Math.abs(t)>0&&e.browser&&e.browser.need3dFix&&Math.abs(t)%90==0?t+.001:t}function C(e,t){void 0===t&&(t=""),"undefined"!=typeof trustedTypes?e.innerHTML=trustedTypes.createPolicy("html",{createHTML:e=>e}).createHTML(t):e.innerHTML=t}let P,L,I;function z(){return P||(P=function(){const e=r(),t=a();return{smoothScroll:t.documentElement&&t.documentElement.style&&"scrollBehavior"in t.documentElement.style,touch:!!("ontouchstart"in e||e.DocumentTouch&&t instanceof e.DocumentTouch)}}()),P}function A(e){return void 0===e&&(e={}),L||(L=function(e){let{userAgent:t}=void 0===e?{}:e;const s=z(),a=r(),i=a.navigator.platform,n=t||a.navigator.userAgent,l={ios:!1,android:!1},o=a.screen.width,d=a.screen.height,c=n.match(/(Android);?[\s\/]+([\d.]+)?/);let p=n.match(/(iPad).*OS\s([\d_]+)/);const u=n.match(/(iPod)(.*OS\s([\d_]+))?/),m=!p&&n.match(/(iPhone\sOS|iOS)\s([\d_]+)/),h="Win32"===i;let f="MacIntel"===i;return!p&&f&&s.touch&&["1024x1366","1366x1024","834x1194","1194x834","834x1112","1112x834","768x1024","1024x768","820x1180","1180x820","810x1080","1080x810"].indexOf(`${o}x${d}`)>=0&&(p=n.match(/(Version)\/([\d.]+)/),p||(p=[0,1,"13_0_0"]),f=!1),c&&!h&&(l.os="android",l.android=!0),(p||m||u)&&(l.os="ios",l.ios=!0),l}(e)),L}function $(){return I||(I=function(){const e=r(),t=A();let s=!1;function a(){const t=e.navigator.userAgent.toLowerCase();return t.indexOf("safari")>=0&&t.indexOf("chrome")<0&&t.indexOf("android")<0}if(a()){const t=String(e.navigator.userAgent);if(t.includes("Version/")){const[e,a]=t.split("Version/")[1].split(" ")[0].split(".").map((e=>Number(e)));s=e<16||16===e&&a<2}}const i=/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(e.navigator.userAgent),n=a();return{isSafari:s||n,needPerspectiveFix:s,need3dFix:n||i&&t.ios,isWebView:i}}()),I}var k={on(e,t,s){const a=this;if(!a.eventsListeners||a.destroyed)return a;if("function"!=typeof t)return a;const i=s?"unshift":"push";return e.split(" ").forEach((e=>{a.eventsListeners[e]||(a.eventsListeners[e]=[]),a.eventsListeners[e][i](t)})),a},once(e,t,s){const a=this;if(!a.eventsListeners||a.destroyed)return a;if("function"!=typeof t)return a;function i(){a.off(e,i),i.__emitterProxy&&delete i.__emitterProxy;for(var s=arguments.length,r=new Array(s),n=0;n<s;n++)r[n]=arguments[n];t.apply(a,r)}return i.__emitterProxy=t,a.on(e,i,s)},onAny(e,t){const s=this;if(!s.eventsListeners||s.destroyed)return s;if("function"!=typeof e)return s;const a=t?"unshift":"push";return s.eventsAnyListeners.indexOf(e)<0&&s.eventsAnyListeners[a](e),s},offAny(e){const t=this;if(!t.eventsListeners||t.destroyed)return t;if(!t.eventsAnyListeners)return t;const s=t.eventsAnyListeners.indexOf(e);return s>=0&&t.eventsAnyListeners.splice(s,1),t},off(e,t){const s=this;return!s.eventsListeners||s.destroyed?s:s.eventsListeners?(e.split(" ").forEach((e=>{void 0===t?s.eventsListeners[e]=[]:s.eventsListeners[e]&&s.eventsListeners[e].forEach(((a,i)=>{(a===t||a.__emitterProxy&&a.__emitterProxy===t)&&s.eventsListeners[e].splice(i,1)}))})),s):s},emit(){const e=this;if(!e.eventsListeners||e.destroyed)return e;if(!e.eventsListeners)return e;let t,s,a;for(var i=arguments.length,r=new Array(i),n=0;n<i;n++)r[n]=arguments[n];"string"==typeof r[0]||Array.isArray(r[0])?(t=r[0],s=r.slice(1,r.length),a=e):(t=r[0].events,s=r[0].data,a=r[0].context||e),s.unshift(a);return(Array.isArray(t)?t:t.split(" ")).forEach((t=>{e.eventsAnyListeners&&e.eventsAnyListeners.length&&e.eventsAnyListeners.forEach((e=>{e.apply(a,[t,...s])})),e.eventsListeners&&e.eventsListeners[t]&&e.eventsListeners[t].forEach((e=>{e.apply(a,s)}))})),e}};const O=(e,t,s)=>{t&&!e.classList.contains(s)?e.classList.add(s):!t&&e.classList.contains(s)&&e.classList.remove(s)};const D=(e,t,s)=>{t&&!e.classList.contains(s)?e.classList.add(s):!t&&e.classList.contains(s)&&e.classList.remove(s)};const G=(e,t)=>{if(!e||e.destroyed||!e.params)return;const s=t.closest(e.isElement?"swiper-slide":`.${e.params.slideClass}`);
vendor: 3,160 bytes, line 31461
31461if(s){let t=s.querySelector(`.${e.params.lazyPreloaderClass}`);!t&&e.isElement&&(s.shadowRoot?t=s.shadowRoot.querySelector(`.${e.params.lazyPreloaderClass}`):requestAnimationFrame((()=>{s.shadowRoot&&(t=s.shadowRoot.querySelector(`.${e.params.lazyPreloaderClass}`),t&&t.remove())}))),t&&t.remove()}},X=(e,t)=>{if(!e.slides[t])return;const s=e.slides[t].querySelector('[loading="lazy"]');s&&s.removeAttribute("loading")},Y=e=>{if(!e||e.destroyed||!e.params)return;let t=e.params.lazyPreloadPrevNext;const s=e.slides.length;if(!s||!t||t<0)return;t=Math.min(t,s);const a="auto"===e.params.slidesPerView?e.slidesPerViewDynamic():Math.ceil(e.params.slidesPerView),i=e.activeIndex;if(e.params.grid&&e.params.grid.rows>1){const s=i,r=[s-t];return r.push(...Array.from({length:t}).map(((e,t)=>s+a+t))),void e.slides.forEach(((t,s)=>{r.includes(t.column)&&X(e,s)}))}const r=i+a-1;if(e.params.rewind||e.params.loop)for(let a=i-t;a<=r+t;a+=1){const t=(a%s+s)%s;(t<i||t>r)&&X(e,t)}else for(let a=Math.max(i-t,0);a<=Math.min(r+t,s-1);a+=1)a!==i&&(a>r||a<i)&&X(e,a)};var B={updateSize:function(){const e=this;let t,s;const a=e.el;t=void 0!==e.params.width&&null!==e.params.width?e.params.width:a.clientWidth,s=void 0!==e.params.height&&null!==e.params.height?e.params.height:a.clientHeight,0===t&&e.isHorizontal()||0===s&&e.isVertical()||(t=t-parseInt(b(a,"padding-left")||0,10)-parseInt(b(a,"padding-right")||0,10),s=s-parseInt(b(a,"padding-top")||0,10)-parseInt(b(a,"padding-bottom")||0,10),Number.isNaN(t)&&(t=0),Number.isNaN(s)&&(s=0),Object.assign(e,{width:t,height:s,size:e.isHorizontal()?t:s}))},updateSlides:function(){const e=this;function t(t,s){return parseFloat(t.getPropertyValue(e.getDirectionLabel(s))||0)}const s=e.params,{wrapperEl:a,slidesEl:i,size:r,rtlTranslate:n,wrongRTL:l}=e,o=e.virtual&&s.virtual.enabled,d=o?e.virtual.slides.length:e.slides.length,c=f(i,`.${e.params.slideClass}, swiper-slide`),p=o?e.virtual.slides.length:c.length;let m=[];const h=[],g=[];let v=s.slidesOffsetBefore;"function"==typeof v&&(v=s.slidesOffsetBefore.call(e));let w=s.slidesOffsetAfter;"function"==typeof w&&(w=s.slidesOffsetAfter.call(e));const y=e.snapGrid.length,E=e.slidesGrid.length;let x=s.spaceBetween,T=-v,M=0,C=0;if(void 0===r)return;"string"==typeof x&&x.indexOf("%")>=0?x=parseFloat(x.replace("%",""))/100*r:"string"==typeof x&&(x=parseFloat(x)),e.virtualSize=-x,c.forEach((e=>{n?e.style.marginLeft="":e.style.marginRight="",e.style.marginBottom="",e.style.marginTop=""})),s.centeredSlides&&s.cssMode&&(u(a,"--swiper-centered-offset-before",""),u(a,"--swiper-centered-offset-after",""));const P=s.grid&&s.grid.rows>1&&e.grid;let L;P?e.grid.initSlides(c):e.grid&&e.grid.unsetSlides();const I="auto"===s.slidesPerView&&s.breakpoints&&Object.keys(s.breakpoints).filter((e=>void 0!==s.breakpoints[e].slidesPerView)).length>0;for(let a=0;a<p;a+=1){let i;if(L=0,c[a]&&(i=c[a]),P&&e.grid.updateSlide(a,i,c),!c[a]||"none"!==b(i,"display")){if("auto"===s.slidesPerView){I&&(c[a].style[e.getDirectionLabel("width")]="");const r=getComputedStyle(i),n=i.style.transform,l=i.style.webkitTransform;if(n&&(i.style.transform="none"),l&&(i.style.webkitTransform="none"),s.roun
vendor: 8,754 bytes, line 31461
31461dLengths)L=e.isHorizontal()?S(i,"width",!0):S(i,"height",!0);else{const e=t(r,"width"),s=t(r,"padding-left"),a=t(r,"padding-right"),n=t(r,"margin-left"),l=t(r,"margin-right"),o=r.getPropertyValue("box-sizing");if(o&&"border-box"===o)L=e+n+l;else{const{clientWidth:t,offsetWidth:r}=i;L=e+s+a+n+l+(r-t)}}n&&(i.style.transform=n),l&&(i.style.webkitTransform=l),s.roundLengths&&(L=Math.floor(L))}else L=(r-(s.slidesPerView-1)*x)/s.slidesPerView,s.roundLengths&&(L=Math.floor(L)),c[a]&&(c[a].style[e.getDirectionLabel("width")]=`${L}px`);c[a]&&(c[a].swiperSlideSize=L),g.push(L),s.centeredSlides?(T=T+L/2+M/2+x,0===M&&0!==a&&(T=T-r/2-x),0===a&&(T=T-r/2-x),Math.abs(T)<.001&&(T=0),s.roundLengths&&(T=Math.floor(T)),C%s.slidesPerGroup==0&&m.push(T),h.push(T)):(s.roundLengths&&(T=Math.floor(T)),(C-Math.min(e.params.slidesPerGroupSkip,C))%e.params.slidesPerGroup==0&&m.push(T),h.push(T),T=T+L+x),e.virtualSize+=L+x,M=L,C+=1}}if(e.virtualSize=Math.max(e.virtualSize,r)+w,n&&l&&("slide"===s.effect||"coverflow"===s.effect)&&(a.style.width=`${e.virtualSize+x}px`),s.setWrapperSize&&(a.style[e.getDirectionLabel("width")]=`${e.virtualSize+x}px`),P&&e.grid.updateWrapperSize(L,m),!s.centeredSlides){const t=[];for(let a=0;a<m.length;a+=1){let i=m[a];s.roundLengths&&(i=Math.floor(i)),m[a]<=e.virtualSize-r&&t.push(i)}m=t,Math.floor(e.virtualSize-r)-Math.floor(m[m.length-1])>1&&m.push(e.virtualSize-r)}if(o&&s.loop){const t=g[0]+x;if(s.slidesPerGroup>1){const a=Math.ceil((e.virtual.slidesBefore+e.virtual.slidesAfter)/s.slidesPerGroup),i=t*s.slidesPerGroup;for(let e=0;e<a;e+=1)m.push(m[m.length-1]+i)}for(let a=0;a<e.virtual.slidesBefore+e.virtual.slidesAfter;a+=1)1===s.slidesPerGroup&&m.push(m[m.length-1]+t),h.push(h[h.length-1]+t),e.virtualSize+=t}if(0===m.length&&(m=[0]),0!==x){const t=e.isHorizontal()&&n?"marginLeft":e.getDirectionLabel("marginRight");c.filter(((e,t)=>!(s.cssMode&&!s.loop)||t!==c.length-1)).forEach((e=>{e.style[t]=`${x}px`}))}if(s.centeredSlides&&s.centeredSlidesBounds){let e=0;g.forEach((t=>{e+=t+(x||0)})),e-=x;const t=e>r?e-r:0;m=m.map((e=>e<=0?-v:e>t?t+w:e))}if(s.centerInsufficientSlides){let e=0;g.forEach((t=>{e+=t+(x||0)})),e-=x;const t=(s.slidesOffsetBefore||0)+(s.slidesOffsetAfter||0);if(e+t<r){const s=(r-e-t)/2;m.forEach(((e,t)=>{m[t]=e-s})),h.forEach(((e,t)=>{h[t]=e+s}))}}if(Object.assign(e,{slides:c,snapGrid:m,slidesGrid:h,slidesSizesGrid:g}),s.centeredSlides&&s.cssMode&&!s.centeredSlidesBounds){u(a,"--swiper-centered-offset-before",-m[0]+"px"),u(a,"--swiper-centered-offset-after",e.size/2-g[g.length-1]/2+"px");const t=-e.snapGrid[0],s=-e.slidesGrid[0];e.snapGrid=e.snapGrid.map((e=>e+t)),e.slidesGrid=e.slidesGrid.map((e=>e+s))}if(p!==d&&e.emit("slidesLengthChange"),m.length!==y&&(e.params.watchOverflow&&e.checkOverflow(),e.emit("snapGridLengthChange")),h.length!==E&&e.emit("slidesGridLengthChange"),s.watchSlidesProgress&&e.updateSlidesOffset(),e.emit("slidesUpdated"),!(o||s.cssMode||"slide"!==s.effect&&"fade"!==s.effect)){const t=`${s.containerModifierClass}backface-hidden`,a=e.el.classList.contains(t);p<=s.maxBackfaceHiddenSlides?a||e.el.classList.add(t):a&&e.el.classList.remove(t)}},updateAutoHeight:function(e){const t=this,s=[],a=t.virtual&&t.params.virtual.enabled;let i,r=0;"number"==typeof e?t.setTransition(e):!0===e&&t.setTransition(t.params.speed);const n=e=>a?t.slides[t.getSlideIndexByData(e)]:t.slides[e];if("auto"!==t.params.slidesPerView&&t.params.slidesPerView>1)if(t.params.centeredSlides)(t.visibleSlides||[]).forEach((e=>{s.push(e)}));else for(i=0;i<Math.ceil(t.params.slidesPerView);i+=1){const e=t.activeIndex+i;if(e>t.slides.length&&!a)break;s.push(n(e))}else s.push(n(t.activeIndex));for(i=0;i<s.length;i+=1)if(void 0!==s[i]){const e=s[i].offsetHeight;r=e>r?e:r}(r||0===r)&&(t.wrapperEl.style.height=`${r}px`)},updateSlidesOffset:function(){const e=this,t=e.slides,s=e.isElement?e.isHorizontal()?e.wrapperEl.offsetLeft:e.wrapperEl.offsetTop:0;for(let a=0;a<t.length;a+=1)t[a].swiperSlideOffset=(e.isHorizontal()?t[a].offsetLeft:t[a].offsetTop)-s-e.cssOverflowAdjustment()},updateSlidesProgress:function(e){void 0===e&&(e=this&&this.translate||0);const t=this,s=t.params,{slides:a,rtlTranslate:i,snapGrid:r}=t;if(0===a.length)return;void 0===a[0].swiperSlideOffset&&t.updateSlidesOffset();let n=-e;i&&(n=e),t.visibleSlidesIndexes=[],t.visibleSlides=[];let l=s.spaceBetween;"string"==typeof l&&l.indexOf("%")>=0?l=parseFloat(l.replace("%",""))/100*t.size:"string"==typeof l&&(l=parseFloat(l));for(let e=0;e<a.length;e+=1){const o=a[e];let d=o.swiperSlideOffset;s.cssMode&&s.centeredSlides&&(d-=a[0].swiperSlideOffset);const c=(n+(s.centeredSlides?t.minTranslate():0)-d)/(o.swiperSlideSize+l),p=(n-r[0]+(s.centeredSlides?t.minTranslate():0)-d)/(o.swiperSlideSize+l),u=-(n-d),m=u+t.slidesSizesGrid[e],h=u>=0&&u<=t.size-t.slidesSizesGrid[e],f=u>=0&&u<t.size-1||m>1&&m<=t.size||u<=0&&m>=t.size;f&&(t.visibleSlides.push(o),t.visibleSlidesIndexes.push(e)),O(o,f,s.slideVisibleClass),O(o,h,s.slideFullyVisibleClass),o.progress=i?-c:c,o.originalProgress=i?-p:p}},updateProgress:function(e){const t=this;if(void 0===e){const s=t.rtlTranslate?-1:1;e=t&&t.translate&&t.translate*s||0}const s=t.params,a=t.maxTranslate()-t.minTranslate();let{progress:i,isBeginning:r,isEnd:n,progressLoop:l}=t;const o=r,d=n;if(0===a)i=0,r=!0,n=!0;else{i=(e-t.minTranslate())/a;const s=Math.abs(e-t.minTranslate())<1,l=Math.abs(e-t.maxTranslate())<1;r=s||i<=0,n=l||i>=1,s&&(i=0),l&&(i=1)}if(s.loop){const s=t.getSlideIndexByData(0),a=t.getSlideIndexByData(t.slides.length-1),i=t.slidesGrid[s],r=t.slidesGrid[a],n=t.slidesGrid[t.slidesGrid.length-1],o=Math.abs(e);l=o>=i?(o-i)/n:(o+n-r)/n,l>1&&(l-=1)}Object.assign(t,{progress:i,progressLoop:l,isBeginning:r,isEnd:n}),(s.watchSlidesProgress||s.centeredSlides&&s.autoHeight)&&t.updateSlidesProgress(e),r&&!o&&t.emit("reachBeginning toEdge"),n&&!d&&t.emit("reachEnd toEdge"),(o&&!r||d&&!n)&&t.emit("fromEdge"),t.emit("progress",i)},updateSlidesClasses:function(){const e=this,{slides:t,params:s,slidesEl:a,activeIndex:i}=e,r=e.virtual&&s.virtual.enabled,n=e.grid&&s.grid&&s.grid.rows>1,l=e=>f(a,`.${s.slideClass}${e}, swiper-slide${e}`)[0];let o,d,c;if(r)if(s.loop){let t=i-e.virtual.slidesBefore;t<0&&(t=e.virtual.slides.length+t),t>=e.virtual.slides.length&&(t-=e.virtual.slides.length),o=l(`[data-swiper-slide-index="${t}"]`)}else o=l(`[data-swiper-slide-index="${i}"]`);else n?(o=t.find((e=>e.column===i)),c=t.find((e=>e.column===i+1)),d=t.find((e=>e.column===i-1))):o=t[i];o&&(n||(c=function(e,t){const s=[];for(;e.nextElementSibling;){const a=e.nextElementSibling;t?a.matches(t)&&s.push(a):s.push(a),e=a}return s}(o,`.${s.slideClass}, swiper-slide`)[0],s.loop&&!c&&(c=t[0]),d=function(e,t){const s=[];for(;e.previousElementSibling;){const a=e.previousElementSibling;t?a.matches(t)&&s.push(a):s.push(a),e=a}return s}(o,`.${s.slideClass}, swiper-slide`)[0],s.loop&&0===!d&&(d=t[t.length-1]))),t.forEach((e=>{D(e,e===o,s.slideActiveClass),D(e,e===c,s.slideNextClass),D(e,e===d,s.slidePrevClass)})),e.emitSlidesClasses()},updateActiveIndex:function(e){const t=this,s=t.rtlTranslate?t.translate:-t.translate,{snapGrid:a,params:i,activeIndex:r,realIndex:n,snapIndex:l}=t;let o,d=e;const c=e=>{let s=e-t.virtual.slidesBefore;return s<0&&(s=t.virtual.slides.length+s),s>=t.virtual.slides.length&&(s-=t.virtual.slides.length),s};if(void 0===d&&(d=function(e){const{slidesGrid:t,params:s}=e,a=e.rtlTranslate?e.translate:-e.translate;let i;for(let e=0;e<t.length;e+=1)void 0!==t[e+1]?a>=t[e]&&a<t[e+1]-(t[e+1]-t[e])/2?i=e:a>=t[e]&&a<t[e+1]&&(i=e+1):a>=t[e]&&(i=e);return s.normalizeSlideIndex&&(i<0||void 0===i)&&(i=0),i}(t)),a.indexOf(s)>=0)o=a.indexOf(s);else{const e=Math.min(i.slidesPerGroupSkip,d);o=e+Math.floor((d-e)/i.slidesPerGroup)}if(o>=a.length&&(o=a.length-1),d===r&&!t.params.loop)return void(o!==l&&(t.snapIndex=o,t.emit("snapIndexChange")));if(d===r&&t.params.loop&&t.virtual&&t.params.virtual.enabled)return void(t.realIndex=c(d));const p=t.grid&&i.grid&&i.grid.rows>1;let u;if(t.virtual&&i.virtual.enabled&&i.loop)u=c(d);else if(p){const e=t.slides.find((e=>e.column===d));let s=parseInt(e.getAttribute("data-swiper-slide-index"),10);Number.isNaN(s)&&(s=Math.max(t.slides.indexOf(e),0)),u=Math.floor(s/i.grid.rows)}else if(t.slides[d]){const e=t.slides[d].getAttribute("data-swiper-slide-index");u=e?parseInt(e,10):d}else u=d;Object.assign(t,{previousSnapIndex:l,snapIndex:o,previousRealIndex:n,realIndex:u,previousIndex:r,activeIndex:d}),t.initialized&&Y(t),t.emit("activeIndexChange"),t.emit("snapIndexChange"),(t.initialized||t.params.runCallbacksOnInit)&&(n!==u&&t.emit("realIndexChange"),t.emit("slideChange"))},updateClickedSlide:function(e,t){const s=this,a=s.params;let i=e.closest(`.${a.slideClass}, swiper-slide`);!i&&s.isElement&&t&&t.length>
vendor: 4,410 bytes, line 31461
314611&&t.includes(e)&&[...t.slice(t.indexOf(e)+1,t.length)].forEach((e=>{!i&&e.matches&&e.matches(`.${a.slideClass}, swiper-slide`)&&(i=e)}));let r,n=!1;if(i)for(let e=0;e<s.slides.length;e+=1)if(s.slides[e]===i){n=!0,r=e;break}if(!i||!n)return s.clickedSlide=void 0,void(s.clickedIndex=void 0);s.clickedSlide=i,s.virtual&&s.params.virtual.enabled?s.clickedIndex=parseInt(i.getAttribute("data-swiper-slide-index"),10):s.clickedIndex=r,a.slideToClickedSlide&&void 0!==s.clickedIndex&&s.clickedIndex!==s.activeIndex&&s.slideToClickedSlide()}};var H={getTranslate:function(e){void 0===e&&(e=this.isHorizontal()?"x":"y");const{params:t,rtlTranslate:s,translate:a,wrapperEl:i}=this;if(t.virtualTranslate)return s?-a:a;if(t.cssMode)return a;let r=d(i,e);return r+=this.cssOverflowAdjustment(),s&&(r=-r),r||0},setTranslate:function(e,t){const s=this,{rtlTranslate:a,params:i,wrapperEl:r,progress:n}=s;let l,o=0,d=0;s.isHorizontal()?o=a?-e:e:d=e,i.roundLengths&&(o=Math.floor(o),d=Math.floor(d)),s.previousTranslate=s.translate,s.translate=s.isHorizontal()?o:d,i.cssMode?r[s.isHorizontal()?"scrollLeft":"scrollTop"]=s.isHorizontal()?-o:-d:i.virtualTranslate||(s.isHorizontal()?o-=s.cssOverflowAdjustment():d-=s.cssOverflowAdjustment(),r.style.transform=`translate3d(${o}px, ${d}px, 0px)`);const c=s.maxTranslate()-s.minTranslate();l=0===c?0:(e-s.minTranslate())/c,l!==n&&s.updateProgress(e),s.emit("setTranslate",s.translate,t)},minTranslate:function(){return-this.snapGrid[0]},maxTranslate:function(){return-this.snapGrid[this.snapGrid.length-1]},translateTo:function(e,t,s,a,i){void 0===e&&(e=0),void 0===t&&(t=this.params.speed),void 0===s&&(s=!0),void 0===a&&(a=!0);const r=this,{params:n,wrapperEl:l}=r;if(r.animating&&n.preventInteractionOnTransition)return!1;const o=r.minTranslate(),d=r.maxTranslate();let c;if(c=a&&e>o?o:a&&e<d?d:e,r.updateProgress(c),n.cssMode){const e=r.isHorizontal();if(0===t)l[e?"scrollLeft":"scrollTop"]=-c;else{if(!r.support.smoothScroll)return m({swiper:r,targetPosition:-c,side:e?"left":"top"}),!0;l.scrollTo({[e?"left":"top"]:-c,behavior:"smooth"})}return!0}return 0===t?(r.setTransition(0),r.setTranslate(c),s&&(r.emit("beforeTransitionStart",t,i),r.emit("transitionEnd"))):(r.setTransition(t),r.setTranslate(c),s&&(r.emit("beforeTransitionStart",t,i),r.emit("transitionStart")),r.animating||(r.animating=!0,r.onTranslateToWrapperTransitionEnd||(r.onTranslateToWrapperTransitionEnd=function(e){r&&!r.destroyed&&e.target===this&&(r.wrapperEl.removeEventListener("transitionend",r.onTranslateToWrapperTransitionEnd),r.onTranslateToWrapperTransitionEnd=null,delete r.onTranslateToWrapperTransitionEnd,r.animating=!1,s&&r.emit("transitionEnd"))}),r.wrapperEl.addEventListener("transitionend",r.onTranslateToWrapperTransitionEnd))),!0}};function N(e){let{swiper:t,runCallbacks:s,direction:a,step:i}=e;const{activeIndex:r,previousIndex:n}=t;let l=a;l||(l=r>n?"next":r<n?"prev":"reset"),t.emit(`transition${i}`),s&&"reset"===l?t.emit(`slideResetTransition${i}`):s&&r!==n&&(t.emit(`slideChangeTransition${i}`),"next"===l?t.emit(`slideNextTransition${i}`):t.emit(`slidePrevTransition${i}`))}var R={slideTo:function(e,t,s,a,i){void 0===e&&(e=0),void 0===s&&(s=!0),"string"==typeof e&&(e=parseInt(e,10));const r=this;let n=e;n<0&&(n=0);const{params:l,snapGrid:o,slidesGrid:d,previousIndex:c,activeIndex:p,rtlTranslate:u,wrapperEl:h,enabled:f}=r;if(!f&&!a&&!i||r.destroyed||r.animating&&l.preventInteractionOnTransition)return!1;void 0===t&&(t=r.params.speed);const g=Math.min(r.params.slidesPerGroupSkip,n);let v=g+Math.floor((n-g)/r.params.slidesPerGroup);v>=o.length&&(v=o.length-1);const w=-o[v];if(l.normalizeSlideIndex)for(let e=0;e<d.length;e+=1){const t=-Math.floor(100*w),s=Math.floor(100*d[e]),a=Math.floor(100*d[e+1]);void 0!==d[e+1]?t>=s&&t<a-(a-s)/2?n=e:t>=s&&t<a&&(n=e+1):t>=s&&(n=e)}if(r.initialized&&n!==p){if(!r.allowSlideNext&&(u?w>r.translate&&w>r.minTranslate():w<r.translate&&w<r.minTranslate()))return!1;if(!r.allowSlidePrev&&w>r.translate&&w>r.maxTranslate()&&(p||0)!==n)return!1}let b;n!==(c||0)&&s&&r.emit("beforeSlideChangeStart"),r.updateProgress(w),b=n>p?"next":n<p?"prev":"reset";const y=r.virtual&&r.params.virtual.enabled;if(!(y&&i)&&(u&&-w===r.translate||!u&&w===r.translate))return r.updateActiveIndex(n),l.autoHeight&&r.updateAutoHeight(),r.updateSlidesClasses(),"slide"!==l.effect&&r.setTranslate(w),"reset"!==b&&(r.transitionStart(s,b),r.transitionEnd(s,b)),!1;
vendor: 6,463 bytes, line 31461
31461if(l.cssMode){const e=r.isHorizontal(),s=u?w:-w;if(0===t)y&&(r.wrapperEl.style.scrollSnapType="none",r._immediateVirtual=!0),y&&!r._cssModeVirtualInitialSet&&r.params.initialSlide>0?(r._cssModeVirtualInitialSet=!0,requestAnimationFrame((()=>{h[e?"scrollLeft":"scrollTop"]=s}))):h[e?"scrollLeft":"scrollTop"]=s,y&&requestAnimationFrame((()=>{r.wrapperEl.style.scrollSnapType="",r._immediateVirtual=!1}));else{if(!r.support.smoothScroll)return m({swiper:r,targetPosition:s,side:e?"left":"top"}),!0;h.scrollTo({[e?"left":"top"]:s,behavior:"smooth"})}return!0}const E=$().isSafari;return y&&!i&&E&&r.isElement&&r.virtual.update(!1,!1,n),r.setTransition(t),r.setTranslate(w),r.updateActiveIndex(n),r.updateSlidesClasses(),r.emit("beforeTransitionStart",t,a),r.transitionStart(s,b),0===t?r.transitionEnd(s,b):r.animating||(r.animating=!0,r.onSlideToWrapperTransitionEnd||(r.onSlideToWrapperTransitionEnd=function(e){r&&!r.destroyed&&e.target===this&&(r.wrapperEl.removeEventListener("transitionend",r.onSlideToWrapperTransitionEnd),r.onSlideToWrapperTransitionEnd=null,delete r.onSlideToWrapperTransitionEnd,r.transitionEnd(s,b))}),r.wrapperEl.addEventListener("transitionend",r.onSlideToWrapperTransitionEnd)),!0},slideToLoop:function(e,t,s,a){if(void 0===e&&(e=0),void 0===s&&(s=!0),"string"==typeof e){e=parseInt(e,10)}const i=this;if(i.destroyed)return;void 0===t&&(t=i.params.speed);const r=i.grid&&i.params.grid&&i.params.grid.rows>1;let n=e;if(i.params.loop)if(i.virtual&&i.params.virtual.enabled)n+=i.virtual.slidesBefore;else{let e;if(r){const t=n*i.params.grid.rows;e=i.slides.find((e=>1*e.getAttribute("data-swiper-slide-index")===t)).column}else e=i.getSlideIndexByData(n);const t=r?Math.ceil(i.slides.length/i.params.grid.rows):i.slides.length,{centeredSlides:s}=i.params;let l=i.params.slidesPerView;"auto"===l?l=i.slidesPerViewDynamic():(l=Math.ceil(parseFloat(i.params.slidesPerView,10)),s&&l%2==0&&(l+=1));let o=t-e<l;if(s&&(o=o||e<Math.ceil(l/2)),a&&s&&"auto"!==i.params.slidesPerView&&!r&&(o=!1),o){const a=s?e<i.activeIndex?"prev":"next":e-i.activeIndex-1<i.params.slidesPerView?"next":"prev";i.loopFix({direction:a,slideTo:!0,activeSlideIndex:"next"===a?e+1:e-t+1,slideRealIndex:"next"===a?i.realIndex:void 0})}if(r){const e=n*i.params.grid.rows;n=i.slides.find((t=>1*t.getAttribute("data-swiper-slide-index")===e)).column}else n=i.getSlideIndexByData(n)}return requestAnimationFrame((()=>{i.slideTo(n,t,s,a)})),i},slideNext:function(e,t,s){void 0===t&&(t=!0);const a=this,{enabled:i,params:r,animating:n}=a;if(!i||a.destroyed)return a;void 0===e&&(e=a.params.speed);let l=r.slidesPerGroup;"auto"===r.slidesPerView&&1===r.slidesPerGroup&&r.slidesPerGroupAuto&&(l=Math.max(a.slidesPerViewDynamic("current",!0),1));const o=a.activeIndex<r.slidesPerGroupSkip?1:l,d=a.virtual&&r.virtual.enabled;if(r.loop){if(n&&!d&&r.loopPreventsSliding)return!1;if(a.loopFix({direction:"next"}),a._clientLeft=a.wrapperEl.clientLeft,a.activeIndex===a.slides.length-1&&r.cssMode)return requestAnimationFrame((()=>{a.slideTo(a.activeIndex+o,e,t,s)})),!0}return r.rewind&&a.isEnd?a.slideTo(0,e,t,s):a.slideTo(a.activeIndex+o,e,t,s)},slidePrev:function(e,t,s){void 0===t&&(t=!0);const a=this,{params:i,snapGrid:r,slidesGrid:n,rtlTranslate:l,enabled:o,animating:d}=a;if(!o||a.destroyed)return a;void 0===e&&(e=a.params.speed);const c=a.virtual&&i.virtual.enabled;if(i.loop){if(d&&!c&&i.loopPreventsSliding)return!1;a.loopFix({direction:"prev"}),a._clientLeft=a.wrapperEl.clientLeft}function p(e){return e<0?-Math.floor(Math.abs(e)):Math.floor(e)}const u=p(l?a.translate:-a.translate),m=r.map((e=>p(e))),h=i.freeMode&&i.freeMode.enabled;let f=r[m.indexOf(u)-1];if(void 0===f&&(i.cssMode||h)){let e;r.forEach(((t,s)=>{u>=t&&(e=s)})),void 0!==e&&(f=h?r[e]:r[e>0?e-1:e])}let g=0;if(void 0!==f&&(g=n.indexOf(f),g<0&&(g=a.activeIndex-1),"auto"===i.slidesPerView&&1===i.slidesPerGroup&&i.slidesPerGroupAuto&&(g=g-a.slidesPerViewDynamic("previous",!0)+1,g=Math.max(g,0))),i.rewind&&a.isBeginning){const i=a.params.virtual&&a.params.virtual.enabled&&a.virtual?a.virtual.slides.length-1:a.slides.length-1;return a.slideTo(i,e,t,s)}return i.loop&&0===a.activeIndex&&i.cssMode?(requestAnimationFrame((()=>{a.slideTo(g,e,t,s)})),!0):a.slideTo(g,e,t,s)},slideReset:function(e,t,s){void 0===t&&(t=!0);const a=this;if(!a.destroyed)return void 0===e&&(e=a.params.speed),a.slideTo(a.activeIndex,e,t,s)},slideToClosest:function(e,t,s,a){void 0===t&&(t=!0),void 0===a&&(a=.5);const i=this;if(i.destroyed)return;void 0===e&&(e=i.params.speed);let r=i.activeIndex;const n=Math.min(i.params.slidesPerGroupSkip,r),l=n+Math.floor((r-n)/i.params.slidesPerGroup),o=i.rtlTranslate?i.translate:-i.translate;if(o>=i.snapGrid[l]){const e=i.snapGrid[l];o-e>(i.snapGrid[l+1]-e)*a&&(r+=i.params.slidesPerGroup)}else{const e=i.snapGrid[l-1];o-e<=(i.snapGrid[l]-e)*a&&(r-=i.params.slidesPerGroup)}return r=Math.max(r,0),r=Math.min(r,i.slidesGrid.length-1),i.slideTo(r,e,t,s)},slideToClickedSlide:function(){const e=this;if(e.destroyed)return;const{params:t,slidesEl:s}=e,a="auto"===t.slidesPerView?e.slidesPerViewDynamic():t.slidesPerView;let i,r=e.getSlideIndexWhenGrid(e.clickedIndex);const n=e.isElement?"swiper-slide":`.${t.slideClass}`,o=e.grid&&e.params.grid&&e.params.grid.rows>1;if(t.loop){if(e.animating)return;i=parseInt(e.clickedSlide.getAttribute("data-swiper-slide-index"),10),t.centeredSlides?e.slideToLoop(i):r>(o?(e.slides.length-a)/2-(e.params.grid.rows-1):e.slides.length-a)?(e.loopFix(),r=e.getSlideIndex(f(s,`${n}[data-swiper-slide-index="${i}"]`)[0]),l((()=>{e.slideTo(r)}))):e.slideTo(r)}else e.slideTo(r)}};var _={loopCreate:function(e,t){const s=this,{params:a,slidesEl:i}=s;if(!a.loop||s.virtual&&s.params.virtual.enabled)return;const r=()=>{f(i,`.${a.slideClass}, swiper-slide`).forEach(((e,t)=>{e.setAttribute("data-swiper-slide-index",t)}))},n=s.grid&&a.grid&&a.grid.rows>1;a.loopAddBlankSlides&&(a.slidesPerGroup>1||n)&&(()=>{const e=f(i,`.${a.slideBlankClass}`);e.forEach((e=>{e.remove()})),e.length>0&&(s.recalcSlides(),s.updateSlides())})();const l=a.slidesPerGroup*(n?a.grid.rows:1),o=s.slides.length%l!=0,d=n&&s.slides.length%a.grid.rows!=0,c=e=>{for(let t=0;t<e;t+=1){const e=s.isElement?v("swiper-slide",[a.slideBlankClass]):v("div",[a.slideClass,a.slideBlankClass]);s.slidesEl.append(e)}};if(o){if(a.loopAddBlankSlides){c(l-s.slides.length%l),s.recalcSlides(),s.updateSlides()}else g("Swiper Loop Warning: The number of slides is not even to slidesPerGroup, loop mode may 
31461not function properly. You need to add more slides (or make duplicates, or empty slides)");r()}else if(d){if(a.loopAddBlankSlides){c(a.grid.rows-s.slides.length%a.grid.rows),s.recalcSlides(),s.updateSlides()}else g("Swiper Loop Warning: The number of slides is not even to grid.rows, loop mode may not function properly. You need to add more slides (or make duplicates, or empty slides)");r()}else r();s.loopFix({slideRealIndex:e,direction:a.centeredSlides?void 0:"next",initial:t})},loopFix:function(e){let{slideRealIndex:t,slideTo:s=!0,direction:a,setTranslate:i,activeSlideIndex:r,initial:n,byController:l,byMousewheel:o}=void 0===e?{}:e;const d=this;if(!d.params.loop)return;d.emit("beforeLoopFix");const{slides:c,allowSlidePrev:p,allowSlideNext:u,slidesEl:m,params:h}=d,{centeredSlides:f,initialSlide:v}=h;if(d.allowSlidePrev=!0,d.allowSlideNext=!0,d.virtual&&h.virtual.enabled)return s&&(h.centeredSlides||0!==d.snapIndex?h.centeredSlides&&d.snapIndex<h.slidesPerView?d.slideTo(d.virtual.slides.length+d.snapIndex,0,!1,!0):d.snapIndex===d.snapGrid.length-1&&d.slideTo(d.virtual.slidesBefore,0,!1,!0):d.slideTo(d.virtual.slides.length,0,!1,!0)),d.allowSlidePrev=p,d.allowSlideNext=u,void d.emit("loopFix");let w=h.slidesPerView;"auto"===w?w=d.slidesPerViewDynamic():(w=Math.ceil(parseFloat(h.slidesPerView,10)),f&&w%2==0&&(w+=1));const b=h.slidesPerGroupAuto?w:h.slidesPerGroup;let y=f?Math.max(b,Math.ceil(w/2)):b;y%b!=0&&(y+=b-y%b),y+=h.loopAdditionalSlides,d.loopedSlides=y;const E=d.grid&&h.grid&&h.grid.rows>1;c.length<w+y||"cards"===d.params.effect&&c.length<w+2*y?g("Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled or not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters"):E&&"row"===h.grid.fill&&g("Swiper Loop Warning: Loop mode is not compatible with grid.fill = `row`");const x=[],S=[],T=E?Math.ceil(c.length/h.grid.rows):c.length,M=n&&T-v<w&&!f;let C=M?v:d.activeIndex;void 0===r?r=d.getSlideIndex(c.find((e=>e.classList.contains(h.slideActiveClass)))):C=r;const P="next"===a||!a,L="prev"===a||!a;let I=0,z=0;const A=(E?c[r].column:r)+(f&&void 0===i?-w/2+.5:0);if(A<y){I=Math.max(y-A,b);for(let e=0;e<y-A;e+=1){const t=e-Math.floor(e/T)*T;if(E){const e=T-t-1;for(let t=c.length-1;t>=0;t-=1)c[t].column===e&&x.push(t)}else x.push(T-t-1)}}else if(A+w>T-y){z=Math.max(A-(T-2*y),b),M&&(z=Math.max(z,w-T+v+1));for(let e=0;e<z;e+=1){const t=e-Math.floor(e/T)*T;E?c.forEach(((e,s)=>{e.column===t&&S.push(s)})):S.push(t)}}if(d.__preventObserver__=!0,requestAnimationFrame((()=>{d.__preventObserver__=!1})),"cards"===d.params.effect&&c.length<w+2*y&&(S.includes(r)&&S.splice(S.indexOf(r),1),x.includes(r)&&x.splice(x.indexOf(r),1)),L&&x.forEach((e=>{c[e].swiperLoopMoveDOM=!0,m.prepend(c[e]),c[e].swiperLoopMoveDOM=!1})),P&&S.forEach((e=>{c[e].swiperLoopMoveDOM=!0,m.append(c[e]),c[e].swiperLoopMoveDOM=!1})),d.recalcSlides(),"auto"===h.slidesPerView?d.updateSlides():E&&(x.length>0&&L||S.length>0&&P)&&d.slides.forEach(((e,t)=>{d.grid.updateSlide(t,e,d.slides)})),h.watchSlidesProgress&&d.updateSlidesOffset(),s)if(x.length>0&&L){if(void 0===t){const e=d.slidesGrid[C],t=d.slidesGrid[C+I]-e;o?d.setTranslate(d.translate-t):(d.slideTo(C+Math.ceil(I),0,!1,!0),i&&(d.touchEventsData.startTranslate=d.touchEventsData.startTranslate-t,d.touchEventsData.currentTranslate=d.touchEventsData.currentTranslate-t))}else if(i){const e=E?x.length/h.grid.rows:x.length;d.slideTo(d.activeIndex+e,0,!1,!0),d.touchEventsData.currentTranslate=d.translate}}else if(S.length>0&&P)if(void 0===t){const e=d.slidesGrid[C],t=d.slidesGrid[C-z]-e;o?d.setTranslate(d.translate-t):(d.slideTo(C-z,0,!1,!0),i&&(d.touchEventsData.startTranslate=d.touchEventsData.startTranslate-t,d.touchEventsData.currentTranslate=d.touchEventsData.currentTranslate-t))}else{const e=E?S.length/h.grid.rows:S.length;d.slideTo(d.activeIndex-e,0,!1,!0)}if(d.allowSlidePrev=p,d.allowSlideNext=u,d.controller&&d.controller.control&&!l){const e={slideRealIndex:t,direction:a,setTranslate:i,activeSlideIndex:r,byController:!0};Array.isArray(d.controller.control)?d.controller.control.forEach((t=>{!t.destroyed&&t.params.loop&&t.loopFix({...e,slideTo:t.params.slidesPerView===h.slidesPerView&&s})})):d.controller.control instanceof d.constructor&&d.controller.control.params.loop&&d.controller.control.loopFix({...e,slideTo:d.controller.control.params.slidesPerView===h.slidesPerView&&s})}d.emit("loopFix")},loopDestroy:function(){const e=this,{params:t,slidesEl:s}=e;if(!t.loop||!s||e.virtual&&e.params.virtual.enabled)return;e.recalcSlides();const a=[];
vendor: 3,381 bytes, line 31461
31461e.slides.forEach((e=>{const t=void 0===e.swiperSlideIndex?1*e.getAttribute("data-swiper-slide-index"):e.swiperSlideIndex;a[t]=e})),e.slides.forEach((e=>{e.removeAttribute("data-swiper-slide-index")})),a.forEach((e=>{s.append(e)})),e.recalcSlides(),e.slideTo(e.realIndex,0)}};function q(e,t,s){const a=r(),{params:i}=e,n=i.edgeSwipeDetection,l=i.edgeSwipeThreshold;return!n||!(s<=l||s>=a.innerWidth-l)||"prevent"===n&&(t.preventDefault(),!0)}function V(e){const t=this,s=a();let i=e;i.originalEvent&&(i=i.originalEvent);const n=t.touchEventsData;if("pointerdown"===i.type){if(null!==n.pointerId&&n.pointerId!==i.pointerId)return;n.pointerId=i.pointerId}else"touchstart"===i.type&&1===i.targetTouches.length&&(n.touchId=i.targetTouches[0].identifier);if("touchstart"===i.type)return void q(t,i,i.targetTouches[0].pageX);const{params:l,touches:d,enabled:c}=t;if(!c)return;if(!l.simulateTouch&&"mouse"===i.pointerType)return;if(t.animating&&l.preventInteractionOnTransition)return;!t.animating&&l.cssMode&&l.loop&&t.loopFix();let p=i.target;if("wrapper"===l.touchEventsTarget&&!function(e,t){const s=r();let a=t.contains(e);!a&&s.HTMLSlotElement&&t instanceof HTMLSlotElement&&(a=[...t.assignedElements()].includes(e),a||(a=function(e,t){const s=[t];for(;s.length>0;){const t=s.shift();if(e===t)return!0;s.push(...t.children,...t.shadowRoot?t.shadowRoot.children:[],...t.assignedElements?t.assignedElements():[])}}(e,t)));return a}(p,t.wrapperEl))return;if("which"in i&&3===i.which)return;if("button"in i&&i.button>0)return;if(n.isTouched&&n.isMoved)return;const u=!!l.noSwipingClass&&""!==l.noSwipingClass,m=i.composedPath?i.composedPath():i.path;u&&i.target&&i.target.shadowRoot&&m&&(p=m[0]);const h=l.noSwipingSelector?l.noSwipingSelector:`.${l.noSwipingClass}`,f=!(!i.target||!i.target.shadowRoot);if(l.noSwiping&&(f?function(e,t){return void 0===t&&(t=this),function t(s){if(!s||s===a()||s===r())return null;s.assignedSlot&&(s=s.assignedSlot);const i=s.closest(e);return i||s.getRootNode?i||t(s.getRootNode().host):null}(t)}(h,p):p.closest(h)))return void(t.allowClick=!0);if(l.swipeHandler&&!p.closest(l.swipeHandler))return;d.currentX=i.pageX,d.currentY=i.pageY;const g=d.currentX,v=d.currentY;if(!q(t,i,g))return;Object.assign(n,{isTouched:!0,isMoved:!1,allowTouchCallbacks:!0,isScrolling:void 0,startMoving:void 0}),d.startX=g,d.startY=v,n.touchStartTime=o(),t.allowClick=!0,t.updateSize(),t.swipeDirection=void 0,l.threshold>0&&(n.allowThresholdMove=!1);let w=!0;p.matches(n.focusableElements)&&(w=!1,"SELECT"===p.nodeName&&(n.isTouched=!1)),s.activeElement&&s.activeElement.matches(n.focusableElements)&&s.activeElement!==p&&("mouse"===i.pointerType||"mouse"!==i.pointerType&&!p.matches(n.focusableElements))&&s.activeElement.blur();const b=w&&t.allowTouchMove&&l.touchStartPreventDefault;!l.touchStartForcePreventDefault&&!b||p.isContentEditable||i.preventDefault(),l.freeMode&&l.freeMode.enabled&&t.freeMode&&t.animating&&!l.cssMode&&t.freeMode.onTouchStart(),t.emit("touchStart",i)}function F(e){const t=a(),s=this,i=s.touchEventsData,{params:r,touches:n,rtlTranslate:l,enabled:d}=s;if(!d)return;if(!r.simulateTouch&&"mouse"===e.pointerType)return;let c,p=e;if(p.originalEvent&&(p=p.originalEvent),"pointermove"===p.type){if(null!==i.touchId)return;if(p.pointerId!==i.pointerId)return}if("touchmove"===p.type){if(c=[...p.changedTouches].find((e=>e.identifier===i.touchId)
vendor: 5,269 bytes, line 31461
31461),!c||c.identifier!==i.touchId)return}else c=p;if(!i.isTouched)return void(i.startMoving&&i.isScrolling&&s.emit("touchMoveOpposite",p));const u=c.pageX,m=c.pageY;if(p.preventedByNestedSwiper)return n.startX=u,void(n.startY=m);if(!s.allowTouchMove)return p.target.matches(i.focusableElements)||(s.allowClick=!1),void(i.isTouched&&(Object.assign(n,{startX:u,startY:m,currentX:u,currentY:m}),i.touchStartTime=o()));if(r.touchReleaseOnEdges&&!r.loop)if(s.isVertical()){if(m<n.startY&&s.translate<=s.maxTranslate()||m>n.startY&&s.translate>=s.minTranslate())return i.isTouched=!1,void(i.isMoved=!1)}else{if(l&&(u>n.startX&&-s.translate<=s.maxTranslate()||u<n.startX&&-s.translate>=s.minTranslate()))return;if(!l&&(u<n.startX&&s.translate<=s.maxTranslate()||u>n.startX&&s.translate>=s.minTranslate()))return}if(t.activeElement&&t.activeElement.matches(i.focusableElements)&&t.activeElement!==p.target&&"mouse"!==p.pointerType&&t.activeElement.blur(),t.activeElement&&p.target===t.activeElement&&p.target.matches(i.focusableElements))return i.isMoved=!0,void(s.allowClick=!1);i.allowTouchCallbacks&&s.emit("touchMove",p),n.previousX=n.currentX,n.previousY=n.currentY,n.currentX=u,n.currentY=m;const h=n.currentX-n.startX,f=n.currentY-n.startY;if(s.params.threshold&&Math.sqrt(h**2+f**2)<s.params.threshold)return;if(void 0===i.isScrolling){let e;s.isHorizontal()&&n.currentY===n.startY||s.isVertical()&&n.currentX===n.startX?i.isScrolling=!1:h*h+f*f>=25&&(e=180*Math.atan2(Math.abs(f),Math.abs(h))/Math.PI,i.isScrolling=s.isHorizontal()?e>r.touchAngle:90-e>r.touchAngle)}if(i.isScrolling&&s.emit("touchMoveOpposite",p),void 0===i.startMoving&&(n.currentX===n.startX&&n.currentY===n.startY||(i.startMoving=!0)),i.isScrolling||"touchmove"===p.type&&i.preventTouchMoveFromPointerMove)return void(i.isTouched=!1);if(!i.startMoving)return;s.allowClick=!1,!r.cssMode&&p.cancelable&&p.preventDefault(),r.touchMoveStopPropagation&&!r.nested&&p.stopPropagation();let g=s.isHorizontal()?h:f,v=s.isHorizontal()?n.currentX-n.previousX:n.currentY-n.previousY;r.oneWayMovement&&(g=Math.abs(g)*(l?1:-1),v=Math.abs(v)*(l?1:-1)),n.diff=g,g*=r.touchRatio,l&&(g=-g,v=-v);const w=s.touchesDirection;s.swipeDirection=g>0?"prev":"next",s.touchesDirection=v>0?"prev":"next";const b=s.params.loop&&!r.cssMode,y="next"===s.touchesDirection&&s.allowSlideNext||"prev"===s.touchesDirection&&s.allowSlidePrev;if(!i.isMoved){if(b&&y&&s.loopFix({direction:s.swipeDirection}),i.startTranslate=s.getTranslate(),s.setTransition(0),s.animating){const e=new window.CustomEvent("transitionend",{bubbles:!0,cancelable:!0,detail:{bySwiperTouchMove:!0}});s.wrapperEl.dispatchEvent(e)}i.allowMomentumBounce=!1,!r.grabCursor||!0!==s.allowSlideNext&&!0!==s.allowSlidePrev||s.setGrabCursor(!0),s.emit("sliderFirstMove",p)}if((new Date).getTime(),!1!==r._loopSwapReset&&i.isMoved&&i.allowThresholdMove&&w!==s.touchesDirection&&b&&y&&Math.abs(g)>=1)return Object.assign(n,{startX:u,startY:m,currentX:u,currentY:m,startTranslate:i.currentTranslate}),i.loopSwapReset=!0,void(i.startTranslate=i.currentTranslate);s.emit("sliderMove",p),i.isMoved=!0,i.currentTranslate=g+i.startTranslate;let E=!0,x=r.resistanceRatio;if(r.touchReleaseOnEdges&&(x=0),g>0?(b&&y&&i.allowThresholdMove&&i.currentTranslate>(r.centeredSlides?s.minTranslate()-s.slidesSizesGrid[s.activeIndex+1]-("auto"!==r.slidesPerView&&s.slides.length-r.slidesPerView>=2?s.slidesSizesGrid[s.activeIndex+1]+s.params.spaceBetween:0)-s.params.spaceBetween:s.minTranslate())&&s.loopFix({direction:"prev",setTranslate:!0,activeSlideIndex:0}),i.currentTranslate>s.minTranslate()&&(E=!1,r.resistance&&(i.currentTranslate=s.minTranslate()-1+(-s.minTranslate()+i.startTranslate+g)**x))):g<0&&(b&&y&&i.allowThresholdMove&&i.currentTranslate<(r.centeredSlides?s.maxTranslate()+s.slidesSizesGrid[s.slidesSizesGrid.length-1]+s.params.spaceBetween+("auto"!==r.slidesPerView&&s.slides.length-r.slidesPerView>=2?s.slidesSizesGrid[s.slidesSizesGrid.length-1]+s.params.spaceBetween:0):s.maxTranslate())&&s.loopFix({direction:"next",setTranslate:!0,activeSlideIndex:s.slides.length-("auto"===r.slidesPerView?s.slidesPerViewDynamic():Math.ceil(parseFloat(r.slidesPerView,10)))}),i.currentTranslate<s.maxTranslate()&&(E=!1,r.resistance&&(i.currentTranslate=s.maxTranslate()+1-(s.maxTranslate()-i.startTranslate-g)**x))),E&&(p.preventedByNestedSwiper=!0),!s.allowSlideNext&&"next"===s.swipeDirection&&i.currentTranslate<i.startTranslate&&(i.currentTranslate=i.startTranslate),!s.allowSlidePrev&&"prev"===s.swipeDirection&&i.currentTranslate>i.startTranslate&&(i.currentTranslate=i.startTranslate),s.allowSlidePrev||s.allowSlideNext||(i.currentTranslate=i.startTranslate),r.threshold>0){if(!(Math.abs(g)>r.threshold||i.allowThresholdMove))return void(i.currentTranslate=i.startTranslate);if(!i.allowThresholdMove)return i.allowThresholdMove=!0,n.startX=n.currentX,n.startY=n.currentY,i.currentTranslate=i.startTranslate,void(n.diff=s.isHorizontal()?n.currentX-n.startX:n.currentY-n.startY)}r.followFinger&&!r.cssMode&&((r.freeMode&&r.freeMode.enabled&&s.freeMode||r.watchSlidesProgress)&&(s.updateActiveIndex(),s.updateSlidesClasses()),r.freeMode&&r.freeMode.enabled&&s.freeMode&&s.freeMode.onTouchMove(),s.updateProgress(i.currentTranslate),s.setTranslate(i.currentTranslate))}function 
vendor: 4,379 bytes, line 31461
31461W(e){const t=this,s=t.touchEventsData;let a,i=e;i.originalEvent&&(i=i.originalEvent);if("touchend"===i.type||"touchcancel"===i.type){if(a=[...i.changedTouches].find((e=>e.identifier===s.touchId)),!a||a.identifier!==s.touchId)return}else{if(null!==s.touchId)return;if(i.pointerId!==s.pointerId)return;a=i}if(["pointercancel","pointerout","pointerleave","contextmenu"].includes(i.type)){if(!(["pointercancel","contextmenu"].includes(i.type)&&(t.browser.isSafari||t.browser.isWebView)))return}s.pointerId=null,s.touchId=null;const{params:r,touches:n,rtlTranslate:d,slidesGrid:c,enabled:p}=t;if(!p)return;if(!r.simulateTouch&&"mouse"===i.pointerType)return;if(s.allowTouchCallbacks&&t.emit("touchEnd",i),s.allowTouchCallbacks=!1,!s.isTouched)return s.isMoved&&r.grabCursor&&t.setGrabCursor(!1),s.isMoved=!1,void(s.startMoving=!1);r.grabCursor&&s.isMoved&&s.isTouched&&(!0===t.allowSlideNext||!0===t.allowSlidePrev)&&t.setGrabCursor(!1);const u=o(),m=u-s.touchStartTime;if(t.allowClick){const e=i.path||i.composedPath&&i.composedPath();t.updateClickedSlide(e&&e[0]||i.target,e),t.emit("tap click",i),m<300&&u-s.lastClickTime<300&&t.emit("doubleTap doubleClick",i)}if(s.lastClickTime=o(),l((()=>{t.destroyed||(t.allowClick=!0)})),!s.isTouched||!s.isMoved||!t.swipeDirection||0===n.diff&&!s.loopSwapReset||s.currentTranslate===s.startTranslate&&!s.loopSwapReset)return s.isTouched=!1,s.isMoved=!1,void(s.startMoving=!1);let h;if(s.isTouched=!1,s.isMoved=!1,s.startMoving=!1,h=r.followFinger?d?t.translate:-t.translate:-s.currentTranslate,r.cssMode)return;if(r.freeMode&&r.freeMode.enabled)return void t.freeMode.onTouchEnd({currentPos:h});const f=h>=-t.maxTranslate()&&!t.params.loop;let g=0,v=t.slidesSizesGrid[0];for(let e=0;e<c.length;e+=e<r.slidesPerGroupSkip?1:r.slidesPerGroup){const t=e<r.slidesPerGroupSkip-1?1:r.slidesPerGroup;void 0!==c[e+t]?(f||h>=c[e]&&h<c[e+t])&&(g=e,v=c[e+t]-c[e]):(f||h>=c[e])&&(g=e,v=c[c.length-1]-c[c.length-2])}let w=null,b=null;r.rewind&&(t.isBeginning?b=r.virtual&&r.virtual.enabled&&t.virtual?t.virtual.slides.length-1:t.slides.length-1:t.isEnd&&(w=0));const y=(h-c[g])/v,E=g<r.slidesPerGroupSkip-1?1:r.slidesPerGroup;if(m>r.longSwipesMs){if(!r.longSwipes)return void t.slideTo(t.activeIndex);"next"===t.swipeDirection&&(y>=r.longSwipesRatio?t.slideTo(r.rewind&&t.isEnd?w:g+E):t.slideTo(g)),"prev"===t.swipeDirection&&(y>1-r.longSwipesRatio?t.slideTo(g+E):null!==b&&y<0&&Math.abs(y)>r.longSwipesRatio?t.slideTo(b):t.slideTo(g))}else{if(!r.shortSwipes)return void t.slideTo(t.activeIndex);t.navigation&&(i.target===t.navigation.nextEl||i.target===t.navigation.prevEl)?i.target===t.navigation.nextEl?t.slideTo(g+E):t.slideTo(g):("next"===t.swipeDirection&&t.slideTo(null!==w?w:g+E),"prev"===t.swipeDirection&&t.slideTo(null!==b?b:g))}}function j(){const e=this,{params:t,el:s}=e;if(s&&0===s.offsetWidth)return;t.breakpoints&&e.setBreakpoint();const{allowSlideNext:a,allowSlidePrev:i,snapGrid:r}=e,n=e.virtual&&e.params.virtual.enabled;e.allowSlideNext=!0,e.allowSlidePrev=!0,e.updateSize(),e.updateSlides(),e.updateSlidesClasses();const l=n&&t.loop;!("auto"===t.slidesPerView||t.slidesPerView>1)||!e.isEnd||e.isBeginning||e.params.centeredSlides||l?e.params.loop&&!n?e.slideToLoop(e.realIndex,0,!1,!0):e.slideTo(e.activeIndex,0,!1,!0):e.slideTo(e.slides.length-1,0,!1,!0),e.autoplay&&e.autoplay.running&&e.autoplay.paused&&(clearTimeout(e.autoplay.resizeTimeout),e.autoplay.resizeTimeout=setTimeout((()=>{e.autoplay&&e.autoplay.running&&e.autoplay.paused&&e.autoplay.resume()}),500)),e.allowSlidePrev=i,e.allowSlideNext=a,e.params.watchOverflow&&r!==e.snapGrid&&e.checkOverflow()}function U(e){const t=this;t.enabled&&(t.allowClick||(t.params.preventClicks&&e.preventDefault(),t.params.preventClicksPropagation&&t.animating&&(e.stopPropagation(),e.stopImmediatePropagation())))}function K(){const e=this,{wrapperEl:t,rtlTranslate:s,enabled:a}=e;if(!a)return;let i;e.previousTranslate=e.translate,e.isHorizontal()?e.translate=-t.scrollLeft:e.translate=-t.scrollTop,0===e.translate&&(e.translate=0),e.updateActiveIndex(),e.updateSlidesClasses();const r=e.maxTranslate()-e.minTranslate();i=0===r?0:(e.translate-e.minTranslate())/r,i!==e.progress&&e.updateProgress(s?-e.translate:e.translate),e.emit("setTranslate",e.translate,!1)}function Z(e){const t=this;G(t,e.target),t.params.cssMode||"auto"!==t.params.slidesPerView&&!t.params.autoHeight||t.update(
vendor: 5,575 bytes, line 31461
31461)}function Q(){const e=this;e.documentTouchHandlerProceeded||(e.documentTouchHandlerProceeded=!0,e.params.touchReleaseOnEdges&&(e.el.style.touchAction="auto"))}const J=(e,t)=>{const s=a(),{params:i,el:r,wrapperEl:n,device:l}=e,o=!!i.nested,d="on"===t?"addEventListener":"removeEventListener",c=t;r&&"string"!=typeof r&&(s[d]("touchstart",e.onDocumentTouchStart,{passive:!1,capture:o}),r[d]("touchstart",e.onTouchStart,{passive:!1}),r[d]("pointerdown",e.onTouchStart,{passive:!1}),s[d]("touchmove",e.onTouchMove,{passive:!1,capture:o}),s[d]("pointermove",e.onTouchMove,{passive:!1,capture:o}),s[d]("touchend",e.onTouchEnd,{passive:!0}),s[d]("pointerup",e.onTouchEnd,{passive:!0}),s[d]("pointercancel",e.onTouchEnd,{passive:!0}),s[d]("touchcancel",e.onTouchEnd,{passive:!0}),s[d]("pointerout",e.onTouchEnd,{passive:!0}),s[d]("pointerleave",e.onTouchEnd,{passive:!0}),s[d]("contextmenu",e.onTouchEnd,{passive:!0}),(i.preventClicks||i.preventClicksPropagation)&&r[d]("click",e.onClick,!0),i.cssMode&&n[d]("scroll",e.onScroll),i.updateOnWindowResize?e[c](l.ios||l.android?"resize orientationchange observerUpdate":"resize observerUpdate",j,!0):e[c]("observerUpdate",j,!0),r[d]("load",e.onLoad,{capture:!0}))};const ee=(e,t)=>e.grid&&t.grid&&t.grid.rows>1;var te={init:!0,direction:"horizontal",oneWayMovement:!1,swiperElementNodeName:"SWIPER-CONTAINER",touchEventsTarget:"wrapper",initialSlide:0,speed:300,cssMode:!1,updateOnWindowResize:!0,resizeObserver:!0,nested:!1,createElements:!1,eventsPrefix:"swiper",enabled:!0,focusableElements:"input, select, option, textarea, button, video, label",width:null,height:null,preventInteractionOnTransition:!1,userAgent:null,url:null,edgeSwipeDetection:!1,edgeSwipeThreshold:20,autoHeight:!1,setWrapperSize:!1,virtualTranslate:!1,effect:"slide",breakpoints:void 0,breakpointsBase:"window",spaceBetween:0,slidesPerView:1,slidesPerGroup:1,slidesPerGroupSkip:0,slidesPerGroupAuto:!1,centeredSlides:!1,centeredSlidesBounds:!1,slidesOffsetBefore:0,slidesOffsetAfter:0,normalizeSlideIndex:!0,centerInsufficientSlides:!1,watchOverflow:!0,roundLengths:!1,touchRatio:1,touchAngle:45,simulateTouch:!0,shortSwipes:!0,longSwipes:!0,longSwipesRatio:.5,longSwipesMs:300,followFinger:!0,allowTouchMove:!0,threshold:5,touchMoveStopPropagation:!1,touchStartPreventDefault:!0,touchStartForcePreventDefault:!1,touchReleaseOnEdges:!1,uniqueNavElements:!0,resistance:!0,resistanceRatio:.85,watchSlidesProgress:!1,grabCursor:!1,preventClicks:!0,preventClicksPropagation:!0,slideToClickedSlide:!1,loop:!1,loopAddBlankSlides:!0,loopAdditionalSlides:0,loopPreventsSliding:!0,rewind:!1,allowSlidePrev:!0,allowSlideNext:!0,swipeHandler:null,noSwiping:!0,noSwipingClass:"swiper-no-swiping",noSwipingSelector:null,passiveListeners:!0,maxBackfaceHiddenSlides:10,containerModifierClass:"swiper-",slideClass:"swiper-slide",slideBlankClass:"swiper-slide-blank",slideActiveClass:"swiper-slide-active",slideVisibleClass:"swiper-slide-visible",slideFullyVisibleClass:"swiper-slide-fully-visible",slideNextClass:"swiper-slide-next",slidePrevClass:"swiper-slide-prev",wrapperClass:"swiper-wrapper",lazyPreloaderClass:"swiper-lazy-preloader",lazyPreloadPrevNext:0,runCallbacksOnInit:!0,_emitClasses:!1};function se(e,t){return function(s){void 0===s&&(s={});const a=Object.keys(s)[0],i=s[a];"object"==typeof i&&null!==i?(!0===e[a]&&(e[a]={enabled:!0}),"navigation"===a&&e[a]&&e[a].enabled&&!e[a].prevEl&&!e[a].nextEl&&(e[a].auto=!0),["pagination","scrollbar"].indexOf(a)>=0&&e[a]&&e[a].enabled&&!e[a].el&&(e[a].auto=!0),a in e&&"enabled"in i?("object"!=typeof e[a]||"enabled"in e[a]||(e[a].enabled=!0),e[a]||(e[a]={enabled:!1}),p(t,s)):p(t,s)):p(t,s)}}const ae={eventsEmitter:k,update:B,translate:H,transition:{setTransition:function(e,t){const s=this;s.params.cssMode||(s.wrapperEl.style.transitionDuration=`${e}ms`,s.wrapperEl.style.transitionDelay=0===e?"0ms":""),s.emit("setTransition",e,t)},transitionStart:function(e,t){void 0===e&&(e=!0);const s=this,{params:a}=s;a.cssMode||(a.autoHeight&&s.updateAutoHeight(),N({swiper:s,runCallbacks:e,direction:t,step:"Start"}))},transitionEnd:function(e,t){void 0===e&&(e=!0);const s=this,{params:a}=s;s.animating=!1,a.cssMode||(s.setTransition(0),N({swiper:s,runCallbacks:e,direction:t,step:"End"}))}},slide:R,loop:_,grabCursor:{setGrabCursor:function(e){const t=this;if(!t.params.simulateTouch||t.params.watchOverflow&&t.isLocked||t.params.cssMode)return;const s="container"===t.params.touchEventsTarget?t.el:t.wrapperEl;t.isElement&&(t.__preventObserver__=!0),s.style.cursor="move",s.style.cursor=e?"grabbing":"grab",t.isElement&&requestAnimationFrame((()=>{t.__preventObserver__=!1}))},unsetGrabCursor:function(){const e=this;e.params.watchOverflow&&e.isLocked||e.params.cssMode||(e.isElement&&(e.__preventObserver__=!0),e["container"===e.params.touchEventsTarget?"el":"wrapperEl"].style.cursor="",e.isElement&&requestAnimationFrame((()=>{e.__preventObserver__=!1})))}},events:{attachEvents:function(){const e=this,{params:t}=e;e.onTouchStart=V.bind(e),e.onTouchMove=F.bind(e),e.onTouchEnd=W.bind(e),e.onDocumentTouchStart=Q.bind(e),t.cssMode&&(e.onScroll=K.bind(e)),e.onClick=U.bind(e),e.onLoad=Z.bind(e),J(e,"on")},detachEvents:function(){J(this,"off")}},breakpoints:{setBreakpoint:function(){const e=this,{realIndex:t,initialized:s,params:i,el:r}=e,n=i.breakpoints;if(!n||n&&0===Object.keys(n).length)return;const l=a(),o="window"!==i.breakpointsBase&&i.breakpointsBase?"container":i.breakpointsBase,d=["window","container"].includes(i.breakpointsBase)||!i.breakpointsBase?e.el:l.querySelector(i.breakpointsBase),c=e.getBreakp
vendor: 3,981 bytes, line 31461
31461oint(n,o,d);if(!c||e.currentBreakpoint===c)return;const u=(c in n?n[c]:void 0)||e.originalParams,m=ee(e,i),h=ee(e,u),f=e.params.grabCursor,g=u.grabCursor,v=i.enabled;m&&!h?(r.classList.remove(`${i.containerModifierClass}grid`,`${i.containerModifierClass}grid-column`),e.emitContainerClasses()):!m&&h&&(r.classList.add(`${i.containerModifierClass}grid`),(u.grid.fill&&"column"===u.grid.fill||!u.grid.fill&&"column"===i.grid.fill)&&r.classList.add(`${i.containerModifierClass}grid-column`),e.emitContainerClasses()),f&&!g?e.unsetGrabCursor():!f&&g&&e.setGrabCursor(),["navigation","pagination","scrollbar"].forEach((t=>{if(void 0===u[t])return;const s=i[t]&&i[t].enabled,a=u[t]&&u[t].enabled;s&&!a&&e[t].disable(),!s&&a&&e[t].enable()}));const w=u.direction&&u.direction!==i.direction,b=i.loop&&(u.slidesPerView!==i.slidesPerView||w),y=i.loop;w&&s&&e.changeDirection(),p(e.params,u);const E=e.params.enabled,x=e.params.loop;Object.assign(e,{allowTouchMove:e.params.allowTouchMove,allowSlideNext:e.params.allowSlideNext,allowSlidePrev:e.params.allowSlidePrev}),v&&!E?e.disable():!v&&E&&e.enable(),e.currentBreakpoint=c,e.emit("_beforeBreakpoint",u),s&&(b?(e.loopDestroy(),e.loopCreate(t),e.updateSlides()):!y&&x?(e.loopCreate(t),e.updateSlides()):y&&!x&&e.loopDestroy()),e.emit("breakpoint",u)},getBreakpoint:function(e,t,s){if(void 0===t&&(t="window"),!e||"container"===t&&!s)return;let a=!1;const i=r(),n="window"===t?i.innerHeight:s.clientHeight,l=Object.keys(e).map((e=>{if("string"==typeof e&&0===e.indexOf("@")){const t=parseFloat(e.substr(1));return{value:n*t,point:e}}return{value:e,point:e}}));l.sort(((e,t)=>parseInt(e.value,10)-parseInt(t.value,10)));for(let e=0;e<l.length;e+=1){const{point:r,value:n}=l[e];"window"===t?i.matchMedia(`(min-width: ${n}px)`).matches&&(a=r):n<=s.clientWidth&&(a=r)}return a||"max"}},checkOverflow:{checkOverflow:function(){const e=this,{isLocked:t,params:s}=e,{slidesOffsetBefore:a}=s;if(a){const t=e.slides.length-1,s=e.slidesGrid[t]+e.slidesSizesGrid[t]+2*a;e.isLocked=e.size>s}else e.isLocked=1===e.snapGrid.length;!0===s.allowSlideNext&&(e.allowSlideNext=!e.isLocked),!0===s.allowSlidePrev&&(e.allowSlidePrev=!e.isLocked),t&&t!==e.isLocked&&(e.isEnd=!1),t!==e.isLocked&&e.emit(e.isLocked?"lock":"unlock")}},classes:{addClasses:function(){const e=this,{classNames:t,params:s,rtl:a,el:i,device:r}=e,n=function(e,t){const s=[];return e.forEach((e=>{"object"==typeof e?Object.keys(e).forEach((a=>{e[a]&&s.push(t+a)})):"string"==typeof e&&s.push(t+e)})),s}(["initialized",s.direction,{"free-mode":e.params.freeMode&&s.freeMode.enabled},{autoheight:s.autoHeight},{rtl:a},{grid:s.grid&&s.grid.rows>1},{"grid-column":s.grid&&s.grid.rows>1&&"column"===s.grid.fill},{android:r.android},{ios:r.ios},{"css-mode":s.cssMode},{centered:s.cssMode&&s.centeredSlides},{"watch-progress":s.watchSlidesProgress}],s.containerModifierClass);t.push(...n),i.classList.add(...t),e.emitContainerClasses()},removeClasses:function(){const{el:e,classNames:t}=this;e&&"string"!=typeof e&&(e.classList.remove(...t),this.emitContainerClasses())}}},ie={};class re{constructor(){let e,t;for(var s=arguments.length,i=new Array(s),r=0;r<s;r++)i[r]=arguments[r];1===i.length&&i[0].constructor&&"Object"===Object.prototype.toString.call(i[0]).slice(8,-1)?t=i[0]:[e,t]=i,t||(t={}),t=p({},t),e&&!t.el&&(t.el=e);const n=a();if(t.el&&"string"==typeof t.el&&n.querySelectorAll(t.el).length>1){const e=[];return n.querySelectorAll(t.el).forEach((s=>{const a=p({},t,{el:s});e.push(new re(a))})),e}const l=this;l.__swiper__=!0,l.support=z(),l.device=A({userAgent:t.userAgent}),l.browser=$(),l.eventsListeners={},l.eventsAnyListeners=[],l.modules=[...l.__modules__],t.modules&&Array.isArray(t.modules)&&l.modules.push(...t.modules);const o={};l.modules.forEach((e=>{e({params:t,swiper:l,extendParams:se(t,o),on:l.on.bind(l),once:l.once.bind(l),off:l.off.bind(l),emit:l.emit.bind(l)})}));const d=p({},te,o);return l.params=p({},d,ie,t),l.originalParams=p({},l.params),l.passedParams=p({}
vendor: 4,848 bytes, line 31461
31461,t),l.params&&l.params.on&&Object.keys(l.params.on).forEach((e=>{l.on(e,l.params.on[e])})),l.params&&l.params.onAny&&l.onAny(l.params.onAny),Object.assign(l,{enabled:l.params.enabled,el:e,classNames:[],slides:[],slidesGrid:[],snapGrid:[],slidesSizesGrid:[],isHorizontal:()=>"horizontal"===l.params.direction,isVertical:()=>"vertical"===l.params.direction,activeIndex:0,realIndex:0,isBeginning:!0,isEnd:!1,translate:0,previousTranslate:0,progress:0,velocity:0,animating:!1,cssOverflowAdjustment(){return Math.trunc(this.translate/2**23)*2**23},allowSlideNext:l.params.allowSlideNext,allowSlidePrev:l.params.allowSlidePrev,touchEventsData:{isTouched:void 0,isMoved:void 0,allowTouchCallbacks:void 0,touchStartTime:void 0,isScrolling:void 0,currentTranslate:void 0,startTranslate:void 0,allowThresholdMove:void 0,focusableElements:l.params.focusableElements,lastClickTime:0,clickTimeout:void 0,velocities:[],allowMomentumBounce:void 0,startMoving:void 0,pointerId:null,touchId:null},allowClick:!0,allowTouchMove:l.params.allowTouchMove,touches:{startX:0,startY:0,currentX:0,currentY:0,diff:0},imagesToLoad:[],imagesLoaded:0}),l.emit("_swiper"),l.params.init&&l.init(),l}getDirectionLabel(e){return this.isHorizontal()?e:{width:"height","margin-top":"margin-left","margin-bottom ":"margin-right","margin-left":"margin-top","margin-right":"margin-bottom","padding-left":"padding-top","padding-right":"padding-bottom",marginRight:"marginBottom"}[e]}getSlideIndex(e){const{slidesEl:t,params:s}=this,a=y(f(t,`.${s.slideClass}, swiper-slide`)[0]);return y(e)-a}getSlideIndexByData(e){return this.getSlideIndex(this.slides.find((t=>1*t.getAttribute("data-swiper-slide-index")===e)))}getSlideIndexWhenGrid(e){return this.grid&&this.params.grid&&this.params.grid.rows>1&&("column"===this.params.grid.fill?e=Math.floor(e/this.params.grid.rows):"row"===this.params.grid.fill&&(e%=Math.ceil(this.slides.length/this.params.grid.rows))),e}recalcSlides(){const{slidesEl:e,params:t}=this;this.slides=f(e,`.${t.slideClass}, swiper-slide`)}enable(){const e=this;e.enabled||(e.enabled=!0,e.params.grabCursor&&e.setGrabCursor(),e.emit("enable"))}disable(){const e=this;e.enabled&&(e.enabled=!1,e.params.grabCursor&&e.unsetGrabCursor(),e.emit("disable"))}setProgress(e,t){const s=this;e=Math.min(Math.max(e,0),1);const a=s.minTranslate(),i=(s.maxTranslate()-a)*e+a;s.translateTo(i,void 0===t?0:t),s.updateActiveIndex(),s.updateSlidesClasses()}emitContainerClasses(){const e=this;if(!e.params._emitClasses||!e.el)return;const t=e.el.className.split(" ").filter((t=>0===t.indexOf("swiper")||0===t.indexOf(e.params.containerModifierClass)));e.emit("_containerClasses",t.join(" "))}getSlideClasses(e){const t=this;return t.destroyed?"":e.className.split(" ").filter((e=>0===e.indexOf("swiper-slide")||0===e.indexOf(t.params.slideClass))).join(" ")}emitSlidesClasses(){const e=this;if(!e.params._emitClasses||!e.el)return;const t=[];e.slides.forEach((s=>{const a=e.getSlideClasses(s);t.push({slideEl:s,classNames:a}),e.emit("_slideClass",s,a)})),e.emit("_slideClasses",t)}slidesPerViewDynamic(e,t){void 0===e&&(e="current"),void 0===t&&(t=!1);const{params:s,slides:a,slidesGrid:i,slidesSizesGrid:r,size:n,activeIndex:l}=this;let o=1;if("number"==typeof s.slidesPerView)return s.slidesPerView;if(s.centeredSlides){let e,t=a[l]?Math.ceil(a[l].swiperSlideSize):0;for(let s=l+1;s<a.length;s+=1)a[s]&&!e&&(t+=Math.ceil(a[s].swiperSlideSize),o+=1,t>n&&(e=!0));for(let s=l-1;s>=0;s-=1)a[s]&&!e&&(t+=a[s].swiperSlideSize,o+=1,t>n&&(e=!0))}else if("current"===e)for(let e=l+1;e<a.length;e+=1){(t?i[e]+r[e]-i[l]<n:i[e]-i[l]<n)&&(o+=1)}else for(let e=l-1;e>=0;e-=1){i[l]-i[e]<n&&(o+=1)}return o}update(){const e=this;if(!e||e.destroyed)return;const{snapGrid:t,params:s}=e;function a(){const t=e.rtlTranslate?-1*e.translate:e.translate,s=Math.min(Math.max(t,e.maxTranslate()),e.minTranslate());e.setTranslate(s),e.updateActiveIndex(),e.updateSlidesClasses()}let i;if(s.breakpoints&&e.setBreakpoint(),[...e.el.querySelectorAll('[loading="lazy"]')].forEach((t=>{t.complete&&G(e,t)})),e.updateSize(),e.updateSlides(),e.updateProgress(),e.updateSlidesClasses(),s.freeMode&&s.freeMode.enabled&&!s.cssMode)a(),s.autoHeight&&e.updateAutoHeight();else{if(("auto"===s.slidesPerView||s.slidesPerView>1)&&e.isEnd&&!s.centeredSlides){const t=e.virtual&&s.virtual.enabled?e.virtual.slides:e.slides;i=e.slideTo(t.length-1,0,!1,!0)}else i=e.slideTo(e.activeIndex,0,!1,!0);i||a()}s.watchOverflow&&t!==e.snapGrid&&e.checkOverflow(),e.emit("update")}changeDirection(e,t){void 0===t&&(t=!0);const s=this,a=s.params.direction;return e||(e="horizontal"===a?"vertical":"horizontal"),e===a||"horizontal"!==e&&"vertical"!==e||(s.el.classList.remove(`${s.params.containerModifierClass}${a}`),s.el.classList.add(`${s.params.containerModifierClass}${e}`),s.emitContainerClasses(),s.params.direction=e,s.slides.forEac
vendor: 4,493 bytes, line 31461
31461h((t=>{"vertical"===e?t.style.width="":t.style.height=""})),s.emit("changeDirection"),t&&s.update()),s}changeLanguageDirection(e){const t=this;t.rtl&&"rtl"===e||!t.rtl&&"ltr"===e||(t.rtl="rtl"===e,t.rtlTranslate="horizontal"===t.params.direction&&t.rtl,t.rtl?(t.el.classList.add(`${t.params.containerModifierClass}rtl`),t.el.dir="rtl"):(t.el.classList.remove(`${t.params.containerModifierClass}rtl`),t.el.dir="ltr"),t.update())}mount(e){const t=this;if(t.mounted)return!0;let s=e||t.params.el;if("string"==typeof s&&(s=document.querySelector(s)),!s)return!1;s.swiper=t,s.parentNode&&s.parentNode.host&&s.parentNode.host.nodeName===t.params.swiperElementNodeName.toUpperCase()&&(t.isElement=!0);const a=()=>`.${(t.params.wrapperClass||"").trim().split(" ").join(".")}`;let i=(()=>{if(s&&s.shadowRoot&&s.shadowRoot.querySelector){return s.shadowRoot.querySelector(a())}return f(s,a())[0]})();return!i&&t.params.createElements&&(i=v("div",t.params.wrapperClass),s.append(i),f(s,`.${t.params.slideClass}`).forEach((e=>{i.append(e)}))),Object.assign(t,{el:s,wrapperEl:i,slidesEl:t.isElement&&!s.parentNode.host.slideSlots?s.parentNode.host:i,hostEl:t.isElement?s.parentNode.host:s,mounted:!0,rtl:"rtl"===s.dir.toLowerCase()||"rtl"===b(s,"direction"),rtlTranslate:"horizontal"===t.params.direction&&("rtl"===s.dir.toLowerCase()||"rtl"===b(s,"direction")),wrongRTL:"-webkit-box"===b(i,"display")}),!0}init(e){const t=this;if(t.initialized)return t;if(!1===t.mount(e))return t;t.emit("beforeInit"),t.params.breakpoints&&t.setBreakpoint(),t.addClasses(),t.updateSize(),t.updateSlides(),t.params.watchOverflow&&t.checkOverflow(),t.params.grabCursor&&t.enabled&&t.setGrabCursor(),t.params.loop&&t.virtual&&t.params.virtual.enabled?t.slideTo(t.params.initialSlide+t.virtual.slidesBefore,0,t.params.runCallbacksOnInit,!1,!0):t.slideTo(t.params.initialSlide,0,t.params.runCallbacksOnInit,!1,!0),t.params.loop&&t.loopCreate(void 0,!0),t.attachEvents();const s=[...t.el.querySelectorAll('[loading="lazy"]')];return t.isElement&&s.push(...t.hostEl.querySelectorAll('[loading="lazy"]')),s.forEach((e=>{e.complete?G(t,e):e.addEventListener("load",(e=>{G(t,e.target)}))})),Y(t),t.initialized=!0,Y(t),t.emit("init"),t.emit("afterInit"),t}destroy(e,t){void 0===e&&(e=!0),void 0===t&&(t=!0);const s=this,{params:a,el:i,wrapperEl:r,slides:n}=s;return void 0===s.params||s.destroyed||(s.emit("beforeDestroy"),s.initialized=!1,s.detachEvents(),a.loop&&s.loopDestroy(),t&&(s.removeClasses(),i&&"string"!=typeof i&&i.removeAttribute("style"),r&&r.removeAttribute("style"),n&&n.length&&n.forEach((e=>{e.classList.remove(a.slideVisibleClass,a.slideFullyVisibleClass,a.slideActiveClass,a.slideNextClass,a.slidePrevClass),e.removeAttribute("style"),e.removeAttribute("data-swiper-slide-index")}))),s.emit("destroy"),Object.keys(s.eventsListeners).forEach((e=>{s.off(e)})),!1!==e&&(s.el&&"string"!=typeof s.el&&(s.el.swiper=null),function(e){const t=e;Object.keys(t).forEach((e=>{try{t[e]=null}catch(e){}try{delete t[e]}catch(e){}}))}(s)),s.destroyed=!0),null}static extendDefaults(e){p(ie,e)}static get extendedDefaults(){return ie}static get defaults(){return te}static installModule(e){re.prototype.__modules__||(re.prototype.__modules__=[]);const t=re.prototype.__modules__;"function"==typeof e&&t.indexOf(e)<0&&t.push(e)}static use(e){return Array.isArray(e)?(e.forEach((e=>re.installModule(e))),re):(re.installModule(e),re)}}function ne(e,t,s,a){return e.params.createElements&&Object.keys(a).forEach((i=>{if(!s[i]&&!0===s.auto){let r=f(e.el,`.${a[i]}`)[0];r||(r=v("div",a[i]),r.className=a[i],e.el.append(r)),s[i]=r,t[i]=r}})),s}function le(e){return void 0===e&&(e=""),`.${e.trim().replace(/([\.:!+\/()[\]])/g,"\\$1").replace(/ /g,".")}`}function oe(e){const t=this,{params:s,slidesEl:a}=t;s.loop&&t.loopDestroy();const i=e=>{if("string"==typeof e){const t=document.createElement("div");C(t,e),a.append(t.children[0]),C(t,"")}else a.append(e)};if("object"==typeof e&&"length"in e)for(let t=0;t<e.length;t+=1)e[t]&&i(e[t]);else i(e);t.recalcSlides(),s.loop&&t.loopCreate(),s.observer&&!t.isElement||t.update()}function de(e){const t=this,{params:s,activeIndex:a,slidesEl:i}=t;s.loop&&t.loopDestroy();let r=a+1;const n=e=>{if("string"==typeof e){const t=document.createElement("div");C(t,e),i.prepend(t.children[0]),C(t,"")}else i.prepend(e)};if("object"==typeof e&&"length"in e){for(let t=0;t<e.length;t+=1)e[t]&&n(e[t]);r=a+e.length}else n(e);t.recalcSlides(),s.loop&&t.loopCreate(),s.observer&&!t.isElement||t.update(
vendor: 7,243 bytes, line 31461
31461),t.slideTo(r,0,!1)}function ce(e,t){const s=this,{params:a,activeIndex:i,slidesEl:r}=s;let n=i;a.loop&&(n-=s.loopedSlides,s.loopDestroy(),s.recalcSlides());const l=s.slides.length;if(e<=0)return void s.prependSlide(t);if(e>=l)return void s.appendSlide(t);let o=n>e?n+1:n;const d=[];for(let t=l-1;t>=e;t-=1){const e=s.slides[t];e.remove(),d.unshift(e)}if("object"==typeof t&&"length"in t){for(let e=0;e<t.length;e+=1)t[e]&&r.append(t[e]);o=n>e?n+t.length:n}else r.append(t);for(let e=0;e<d.length;e+=1)r.append(d[e]);s.recalcSlides(),a.loop&&s.loopCreate(),a.observer&&!s.isElement||s.update(),a.loop?s.slideTo(o+s.loopedSlides,0,!1):s.slideTo(o,0,!1)}function pe(e){const t=this,{params:s,activeIndex:a}=t;let i=a;s.loop&&(i-=t.loopedSlides,t.loopDestroy());let r,n=i;if("object"==typeof e&&"length"in e){for(let s=0;s<e.length;s+=1)r=e[s],t.slides[r]&&t.slides[r].remove(),r<n&&(n-=1);n=Math.max(n,0)}else r=e,t.slides[r]&&t.slides[r].remove(),r<n&&(n-=1),n=Math.max(n,0);t.recalcSlides(),s.loop&&t.loopCreate(),s.observer&&!t.isElement||t.update(),s.loop?t.slideTo(n+t.loopedSlides,0,!1):t.slideTo(n,0,!1)}function ue(){const e=this,t=[];for(let s=0;s<e.slides.length;s+=1)t.push(s);e.removeSlide(t)}function me(e){const{effect:t,swiper:s,on:a,setTranslate:i,setTransition:r,overwriteParams:n,perspective:l,recreateShadows:o,getEffectParams:d}=e;let c;a("beforeInit",(()=>{if(s.params.effect!==t)return;s.classNames.push(`${s.params.containerModifierClass}${t}`),l&&l()&&s.classNames.push(`${s.params.containerModifierClass}3d`);const e=n?n():{};Object.assign(s.params,e),Object.assign(s.originalParams,e)})),a("setTranslate _virtualUpdated",(()=>{s.params.effect===t&&i()})),a("setTransition",((e,a)=>{s.params.effect===t&&r(a)})),a("transitionEnd",(()=>{if(s.params.effect===t&&o){if(!d||!d().slideShadows)return;s.slides.forEach((e=>{e.querySelectorAll(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").forEach((e=>e.remove()))})),o()}})),a("virtualUpdate",(()=>{s.params.effect===t&&(s.slides.length||(c=!0),requestAnimationFrame((()=>{c&&s.slides&&s.slides.length&&(i(),c=!1)})))}))}function he(e,t){const s=h(t);return s!==t&&(s.style.backfaceVisibility="hidden",s.style["-webkit-backface-visibility"]="hidden"),s}function fe(e){let{swiper:t,duration:s,transformElements:a,allSlides:i}=e;const{activeIndex:r}=t;if(t.params.virtualTranslate&&0!==s){let e,s=!1;e=i?a:a.filter((e=>{const s=e.classList.contains("swiper-slide-transform")?(e=>{if(!e.parentElement)return t.slides.find((t=>t.shadowRoot&&t.shadowRoot===e.parentNode));return e.parentElement})(e):e;return t.getSlideIndex(s)===r})),e.forEach((e=>{x(e,(()=>{if(s)return;if(!t||t.destroyed)return;s=!0,t.animating=!1;const e=new window.CustomEvent("transitionend",{bubbles:!0,cancelable:!0});t.wrapperEl.dispatchEvent(e)}))}))}}function ge(e,t,s){const a=`swiper-slide-shadow${s?`-${s}`:""}${e?` swiper-slide-shadow-${e}`:""}`,i=h(t);let r=i.querySelector(`.${a.split(" ").join(".")}`);return r||(r=v("div",a.split(" ")),i.append(r)),r}Object.keys(ae).forEach((e=>{Object.keys(ae[e]).forEach((t=>{re.prototype[t]=ae[e][t]}))})),re.use([function(e){let{swiper:t,on:s,emit:a}=e;const i=r();let n=null,l=null;const o=()=>{t&&!t.destroyed&&t.initialized&&(a("beforeResize"),a("resize"))},d=()=>{t&&!t.destroyed&&t.initialized&&a("orientationchange")};s("init",(()=>{t.params.resizeObserver&&void 0!==i.ResizeObserver?t&&!t.destroyed&&t.initialized&&(n=new ResizeObserver((e=>{l=i.requestAnimationFrame((()=>{const{width:s,height:a}=t;let i=s,r=a;e.forEach((e=>{let{contentBoxSize:s,contentRect:a,target:n}=e;n&&n!==t.el||(i=a?a.width:(s[0]||s).inlineSize,r=a?a.height:(s[0]||s).blockSize)})),i===s&&r===a||o()}))})),n.observe(t.el)):(i.addEventListener("resize",o),i.addEventListener("orientationchange",d))})),s("destroy",(()=>{l&&i.cancelAnimationFrame(l),n&&n.unobserve&&t.el&&(n.unobserve(t.el),n=null),i.removeEventListener("resize",o),i.removeEventListener("orientationchange",d)}))},function(e){let{swiper:t,extendParams:s,on:a,emit:i}=e;const n=[],l=r(),o=function(e,s){void 0===s&&(s={});const a=new(l.MutationObserver||l.WebkitMutationObserver)((e=>{if(t.__preventObserver__)return;if(1===e.length)return void i("observerUpdate",e[0]);const s=function(){i("observerUpdate",e[0])};l.requestAnimationFrame?l.requestAnimationFrame(s):l.setTimeout(s,0)}));a.observe(e,{attributes:void 0===s.attributes||s.attributes,childList:t.isElement||(void 0===s.childList||s).childList,characterData:void 0===s.characterData||s.characterData}),n.push(a)};s({observer:!1,observeParents:!1,observeSlideChildren:!1}),a("init",(()=>{if(t.params.observer){if(t.params.observeParents){const e=E(t.hostEl);for(let t=0;t<e.length;t+=1)o(e[t])}o(t.hostEl,{childList:t.params.observeSlideChildren}),o(t.wrapperEl,{attributes:!1})}})),a("destroy",(()=>{n.forEach((e=>{e.disconnect()})),n.splice(0,n.length)}))}]);const ve=[function(e){let t,{swiper:s,extendParams:i,on:r,emit:n}=e;i({virtual:{enabled:!1,slides:[],cache:!0,renderSlide:null,renderExternal:null,renderExternalUpdate:!0,addSlidesBefore:0,addSlidesAfter:0}});const l=a();s.virtual={cache:{},from:void 0,to:void 0,slides:[],offset:0,slidesGrid:[]};const o=l.createElement("div");function d(e,t){const a=s.params.virtual;if(a.cache&&s.virtual.cache[t])return s.virtual.cache[t];let i;return a.renderSlide?(i=a.renderSlide.call(s,e,t),"string"==typeof i&&(C(o,i),i=o.children[0])):i=s.isElement?v("swiper-slide"):v("div",s.params.slideClass),i.setAttribute("data-swiper-slide-index",t),a.renderSlide||C(i,e),a.cache&&(s.virtual.cache[t]=i),i}function c(e,t,a){const{slidesPerView:i,slidesPerGroup:r,centeredSlides:l,loop:o,initialSlide:c}=s.params;if(t&&!o&&c>0)return;const{addSlidesBefore:p,addSlidesAfter:u}=s.params.virtual,{from:m,to:h,slides:g,slidesGrid:v,offset:w}=s.virtual;s.params.cssMode||s.updateActiveIndex();const b=void 0===a?s.activeIndex||0:a;let y,E,x;y=s.rtlTranslate?"right":s.isHorizontal()?"left":"top",l?(E=Math.floor(i/2)+r+u,x=Math.floor(i/2)+r+p):(E=i+(r-1)+u,x=(o?i:r)+p);let S=b-x,T=b+E;o||(S=Math.max(S,0),T=Math.min(T,g.length-1));let M=(s.slidesGrid[S]||0)-(s.slidesGrid[0]||0);function C(){s.updateSlides(),s.updateProgress(),s.updateSlidesClasses(),n("virtualUpdate")}if(o&&b>=x?(S-=x,l||(M+=s.slidesGrid[0])):o&&b<x&&(S=-x,l&&(M+=s.slidesGrid[0])),Object.assign(s.virtual,{from:S,to:T,offset:M,slidesGrid:s.slidesGrid,slidesBefore:x,slidesAfter:E}),m===S&&h===T&&!e)return s.slidesGrid!==v&&M!==w&&s.slides.forEach((e=>{e.style[y]=M-Math.abs(s.cssOverflowAdjustment())+"px"})),s.updateProgress(),void n("virtualUpdate");if(s.params.virtual.renderExternal)return s.params.virtual.renderExternal.call(s,{offset:M,from:S,to:T,slides:function(){const e=[];for(let t=S;t<=T;t+=1)e.push(g[t]);return e}()}),void(s.params.virtual.renderExternalUpdate?C():n("virtualUpdate"));const P=[],L=[],I=e=>{let t=e;return e<0?t=g.length+e:t>=g.length&&(t-=g.length),t};if(e)s.slides.filter((e=>e.matches(`.${s.params.slideClass}, swiper-slide`))).forEach((e=>{e.remove()}));else for(let e=m;e<=h;e+=1)if(e<S||e>T){const t=I(e);s.slides.filter((e=>e.matches(`.${s.params.slideClass}[data-swiper-slide-index="${t}"], swiper-slide[data-swiper-slide-index="${t}
31461"]`))).forEach((e=>{e.remove()}))}const z=o?-g.length:0,A=o?2*g.length:g.length;for(let t=z;t<A;t+=1)if(t>=S&&t<=T){const s=I(t);void 0===h||e?L.push(s):(t>h&&L.push(s),t<m&&P.push(s))}if(L.forEach((e=>{s.slidesEl.append(d(g[e],e))})),o)for(let e=P.length-1;e>=0;e-=1){const t=P[e];s.slidesEl.prepend(d(g[t],t))}else P.sort(((e,t)=>t-e)),P.forEach((e=>{s.slidesEl.prepend(d(g[e],e))}));f(s.slidesEl,".swiper-slide, swiper-slide").forEach((e=>{e.style[y]=M-Math.abs(s.cssOverflowAdjustment())+"px"})),C()}r("beforeInit",(()=>{if(!s.params.virtual.enabled)return;let e;if(void 0===s.passedParams.virtual.slides){const t=[...s.slidesEl.children].filter((e=>e.matches(`.${s.params.slideClass}, swiper-slide`)));t&&t.length&&(s.virtual.slides=[...t],e=!0,t.forEach(((e,t)=>{e.setAttribute("data-swiper-slide-index",t),s.virtual.cache[t]=e,e.remove()})))}e||(s.virtual.slides=s.params.virtual.slides),s.classNames.push(`${s.params.containerModifierClass}virtual`),s.params.watchSlidesProgress=!0,s.originalParams.watchSlidesProgress=!0,c(!1,!0)})),r("setTranslate",(()=>{s.params.virtual.enabled&&(s.params.cssMode&&!s._immediateVirtual?(clearTimeout(t),t=setTimeout((()=>{c()}),100)):c())})),r("init update resize",(()=>{s.params.virtual.enabled&&s.params.cssMode&&u(s.wrapperEl,"--swiper-virtual-size",`${s.virtualSize}px`)})),Object.assign(s.virtual,{appendSlide:function(e){if("object"==typeof e&&"length"in e)for(let t=0;t<e.length;t+=1)e[t]&&s.virtual.slides.push(e[t]);else s.virtual.slides.push(e);c(!0)},prependSlide:function(e){const t=s.activeIndex;let a=t+1,i=1;if(Array.isArray(e)){for(let t=0;t<e.length;t+=1)e[t]&&s.virtual.slides.unshift(e[t]);a=t+e.length,i=e.length}else s.virtual.slides.unshift(e);if(s.params.virtual.cache){const e=s.virtual.cache,t={};Object.keys(e).forEach((s=>{const a=e[s],r=a.getAttribute("data-swiper-slide-index");r&&a.setAttribute("data-swiper-slide-index",parseInt(r,10)+i),t[parseInt(s,10)+i]=a})),s.virtual.cache=t}c(!0),s.slideTo(a,0)},removeSlide:function(e){if(null==e)return;let t=s.activeIndex;if(Array.isArray(e))for(let a=e.length-1;a>=0;a-=1)s.params.virtual.cache&&(delete s.virtual.cache[e[a]],Object.keys(s.virtual.cache).forEach((t=>{t>e&&(s.virtual.cache[t-1]=s.virtual.cache[t],s.virtual.cache[t-1].setAttribute("data-swiper-slide-index",t-1),delete s.virtual.cache[t])}))),s.virtual.slides.splice(e[a],1),e[a]<t&&(t-=1),t=Math.max(t,0);else s.params.virtual.cache&&(delete s.virtual.cache[e],Object.keys(s.virtual.cache).forEach((t=>{t>e&&(s.virtual.cache[t-1]=s.virtual.cache[t],s.virtual.cache[t-1].setAttribute("data-swiper-slide-index",t-1),delete s.virtual.cache[t])}))),s.virtual.slides.splice(e,1),e<t&&(t-=1),t=Math.max(t,0);c(!0),s.slideTo(t,0)},removeAllSlides:function(){s.virtual.slides=[],s.params.virtual.cache&&(s.virtual.cache={}),c(!0),s.slideTo(0,0)},update:c})},function(e){let{swiper:t,extendParams:s,on:i,emit:n}=e;const l=a(),o=r();function d(e){if(!t.enabled)return;const{rtlTranslate:s}=t;let a=e;a.originalEvent&&(a=a.originalEvent);const i=a.keyCode||a.charCode,r=t.params.keyboard.pageUpDown,d=r&&33===i,c=r&&34===i,p=37===i,u=39===i,m=38===i,h=40===i;if(!t.allowSlideNext&&(t.isHorizontal()&&u||t.isVertical()&&h||c))return!1;if(!t.allowSlidePrev&&(t.isHorizontal()&&p||t.isVertical()&&m||d))return!1;if(!(a.shiftKey||a.altKey||a.ctrlKey||a.metaKey||l.activeElement&&(l.activeElement.isContentEditable||l.activeElement.nodeName&&("input"===l.activeElement.nodeName.toLowerCase()||"textarea"===l.activeElement.nodeName.toLowerCase())))){if(t.params.keyboard.onlyInViewport&&(d||c||p||u||m||h)){let e=!1;if(E(t.el,`.${t.params.slideClass}, swiper-slide`).length>0&&0===E(t.el,`.${t.params.slideActiveClass}`).length)return;const a=t.el,i=a.clientWidth,r=a.clientHeight,n=o.innerWidth,l=o.innerHeight,d=w(a);s&&(d.left-=a.scrollLeft);const c=[[d.left,d.top],[d.left+i,d.top],[d.left,d.top+r],[d.left+i,d.top+r]];for(let t=0;t<c.length;t+=1){const s=c[t];if(s[0]>=0&&s[0]<=n&&s[1]>=0&&s[1]<=l){if(0===s[0]&&0===s[1])continue;e=!0}}if(!e)return}t.isHorizontal()?((d||c||p||u)&&(a.preventDefault?a.preventDefault():a.returnValue=!1),((c||u)&&!s||(d||p)&&s)&&t.slideNext(),((d||p)&&!s||(c||u)&&s)&&t.slidePrev()):((d||c||m||h)&&(a.preventDefault?a.preventDefault():a.returnValue=!1),(c||h)&&t.slideNext(),(d||m)&&t.slidePrev()),n("keyPress",i)}}function c(){t.keyboard.enabled||(l.addEventListener("keydown",d),t.keyboard.enabled=!0)}function p(){t.keyboard.enabled&&(l.removeEventListener("keydown",d),t.keyboard.enabled=!1)}t.keyboard={enabled:!1},s({keyboard:{enabled:!1,onlyInViewport:!0,pageUpDown:!0}}),i("init",(()=>{t.params.keyboard.enabled&&c()})),i("destroy",(()=>{t.keyboard.enabled&&p()})),Object.assign(t.keyboard,{enable:c,disable:p})},function(e){let{swiper:t,extendParams:s,on:a,emit:i}=e;const n=r();let d;s({mousewheel:{enabled:!1,releaseOnEdges:!1,invert:!1,forceToAxis:!1,sensitivity:1,eventsTarget:"container",thresholdDelta:null,thresholdTime:null,noMousewheelClass:"swiper-no-mousewheel"}}),t.mousewheel={enabled:!1};let c,p=o();const u=[];function m(){t.enabled&&(t.mouseEntered=!0)}function h(){t.enabled&&(t.mouseEntered=!1)}function f(e){return!(t.params.mousewheel.thresholdDelta&&e.delta<t.params.mousewheel.thresholdDelta)&&(!(t.params.mousewheel.thresholdTime&&o()-p<t.params.mousewheel.thresholdTime)&&(e.delta>=6&&o()-p<60||(e.direction<0?t.isEnd&&!t.params.loop||t.animating||(t.slideNext(),i("scroll",e.raw)):t.isBeginning&&!t.params.loop||t.animating||(t.slidePrev(),i("scroll",e.raw)),p=(new n.Date).getTime(),!1)))}function g(e){let s=e,a=!0;if(!t.enabled)return;if(e.target.closest(`.${t.params.mousewheel.noMousewheelClass}`))return;const r=t.params.mousewheel;t.params.cssMode&&s.preventDefault();let n=t.el;"container"!==t.params.mousewheel.eventsTarget&&(n=document.querySelector(t.params.mousewheel.eventsTarget));const p=n&&n.contains(s.target);if(!t.mouseEntered&&!p&&!r.releaseOnEdges)return!0;s.originalEvent&&(s=s.originalEvent);let m=0;const h=t.rtlTranslate?-1:1,g=function(e){let t=0,s=0,a=0,i=0;return"detail"in e&&(s=e.detail),"wheelDelta"in e&&(s=-e.wheelDelta/120),"wheelDeltaY"in e&&(s=-e.wheelDeltaY/120
vendor: 4,794 bytes, line 31461
31461),"wheelDeltaX"in e&&(t=-e.wheelDeltaX/120),"axis"in e&&e.axis===e.HORIZONTAL_AXIS&&(t=s,s=0),a=10*t,i=10*s,"deltaY"in e&&(i=e.deltaY),"deltaX"in e&&(a=e.deltaX),e.shiftKey&&!a&&(a=i,i=0),(a||i)&&e.deltaMode&&(1===e.deltaMode?(a*=40,i*=40):(a*=800,i*=800)),a&&!t&&(t=a<1?-1:1),i&&!s&&(s=i<1?-1:1),{spinX:t,spinY:s,pixelX:a,pixelY:i}}(s);if(r.forceToAxis)if(t.isHorizontal()){if(!(Math.abs(g.pixelX)>Math.abs(g.pixelY)))return!0;m=-g.pixelX*h}else{if(!(Math.abs(g.pixelY)>Math.abs(g.pixelX)))return!0;m=-g.pixelY}else m=Math.abs(g.pixelX)>Math.abs(g.pixelY)?-g.pixelX*h:-g.pixelY;if(0===m)return!0;r.invert&&(m=-m);let v=t.getTranslate()+m*r.sensitivity;if(v>=t.minTranslate()&&(v=t.minTranslate()),v<=t.maxTranslate()&&(v=t.maxTranslate()),a=!!t.params.loop||!(v===t.minTranslate()||v===t.maxTranslate()),a&&t.params.nested&&s.stopPropagation(),t.params.freeMode&&t.params.freeMode.enabled){const e={time:o(),delta:Math.abs(m),direction:Math.sign(m)},a=c&&e.time<c.time+500&&e.delta<=c.delta&&e.direction===c.direction;if(!a){c=void 0;let n=t.getTranslate()+m*r.sensitivity;const o=t.isBeginning,p=t.isEnd;if(n>=t.minTranslate()&&(n=t.minTranslate()),n<=t.maxTranslate()&&(n=t.maxTranslate()),t.setTransition(0),t.setTranslate(n),t.updateProgress(),t.updateActiveIndex(),t.updateSlidesClasses(),(!o&&t.isBeginning||!p&&t.isEnd)&&t.updateSlidesClasses(),t.params.loop&&t.loopFix({direction:e.direction<0?"next":"prev",byMousewheel:!0}),t.params.freeMode.sticky){clearTimeout(d),d=void 0,u.length>=15&&u.shift();const s=u.length?u[u.length-1]:void 0,a=u[0];if(u.push(e),s&&(e.delta>s.delta||e.direction!==s.direction))u.splice(0);else if(u.length>=15&&e.time-a.time<500&&a.delta-e.delta>=1&&e.delta<=6){const s=m>0?.8:.2;c=e,u.splice(0),d=l((()=>{!t.destroyed&&t.params&&t.slideToClosest(t.params.speed,!0,void 0,s)}),0)}d||(d=l((()=>{if(t.destroyed||!t.params)return;c=e,u.splice(0),t.slideToClosest(t.params.speed,!0,void 0,.5)}),500))}if(a||i("scroll",s),t.params.autoplay&&t.params.autoplay.disableOnInteraction&&t.autoplay.stop(),r.releaseOnEdges&&(n===t.minTranslate()||n===t.maxTranslate()))return!0}}else{const s={time:o(),delta:Math.abs(m),direction:Math.sign(m),raw:e};u.length>=2&&u.shift();const a=u.length?u[u.length-1]:void 0;if(u.push(s),a?(s.direction!==a.direction||s.delta>a.delta||s.time>a.time+150)&&f(s):f(s),function(e){const s=t.params.mousewheel;if(e.direction<0){if(t.isEnd&&!t.params.loop&&s.releaseOnEdges)return!0}else if(t.isBeginning&&!t.params.loop&&s.releaseOnEdges)return!0;return!1}(s))return!0}return s.preventDefault?s.preventDefault():s.returnValue=!1,!1}function v(e){let s=t.el;"container"!==t.params.mousewheel.eventsTarget&&(s=document.querySelector(t.params.mousewheel.eventsTarget)),s[e]("mouseenter",m),s[e]("mouseleave",h),s[e]("wheel",g)}function w(){return t.params.cssMode?(t.wrapperEl.removeEventListener("wheel",g),!0):!t.mousewheel.enabled&&(v("addEventListener"),t.mousewheel.enabled=!0,!0)}function b(){return t.params.cssMode?(t.wrapperEl.addEventListener(event,g),!0):!!t.mousewheel.enabled&&(v("removeEventListener"),t.mousewheel.enabled=!1,!0)}a("init",(()=>{!t.params.mousewheel.enabled&&t.params.cssMode&&b(),t.params.mousewheel.enabled&&w()})),a("destroy",(()=>{t.params.cssMode&&w(),t.mousewheel.enabled&&b()})),Object.assign(t.mousewheel,{enable:w,disable:b})},function(e){let{swiper:t,extendParams:s,on:a,emit:i}=e;function r(e){let s;return e&&"string"==typeof e&&t.isElement&&(s=t.el.querySelector(e)||t.hostEl.querySelector(e),s)?s:(e&&("string"==typeof e&&(s=[...document.querySelectorAll(e)]),t.params.uniqueNavElements&&"string"==typeof e&&s&&s.length>1&&1===t.el.querySelectorAll(e).length?s=t.el.querySelector(e):s&&1===s.length&&(s=s[0])),e&&!s?e:s)}function n(e,s){const a=t.params.navigation;(e=T(e)).forEach((e=>{e&&(e.classList[s?"add":"remove"](...a.disabledClass.split(" ")),"BUTTON"===e.tagName&&(e.disabled=s),t.params.watchOverflow&&t.enabled&&e.classList[t.isLocked?"add":"remove"](a.lockClass))}))}function l(){const{nextEl:e,prevEl:s}=t.navigation;if(t.params.loop)return n(s,!1),void n(e,!1);n(s,t.isBeginning&&!t.params.rewind),n(e,t.isEnd&&!t.params.rewind)}function o(e){e.preventDefault(),(!t.isBeginning||t.params.loop||t.params.rewind)&&(t.slidePrev(),i("navigationPrev"))}function d(e){e.preventDefault(),(!t.isEnd||t.params.loop||t.params.rewind)&&(t.slideNext(),i("navigationNext"))}function c(){const e=t.params.navigation;if(t.params.navigation=ne(t,t.originalParams.navigation,t.params.navigation,{nextEl:"swiper-button-next",prevEl:"swiper-button-prev"}),!e.nextEl&&!e.prevEl)return;let s=r(e.nextEl),a=r(e.prevEl);Object.assign(t.navigation,{nextEl:s,prevEl:a}),s=T(s),a=T(a);const i=(s,a)=>{s&&s.addEventListener("click","next"===a?d:o),!t.enabled&&s&&s.classList.add(...e.lockClass.split(" "))};
vendor: 4,373 bytes, line 31461
31461s.forEach((e=>i(e,"next"))),a.forEach((e=>i(e,"prev")))}function p(){let{nextEl:e,prevEl:s}=t.navigation;e=T(e),s=T(s);const a=(e,s)=>{e.removeEventListener("click","next"===s?d:o),e.classList.remove(...t.params.navigation.disabledClass.split(" "))};e.forEach((e=>a(e,"next"))),s.forEach((e=>a(e,"prev")))}s({navigation:{nextEl:null,prevEl:null,hideOnClick:!1,disabledClass:"swiper-button-disabled",hiddenClass:"swiper-button-hidden",lockClass:"swiper-button-lock",navigationDisabledClass:"swiper-navigation-disabled"}}),t.navigation={nextEl:null,prevEl:null},a("init",(()=>{!1===t.params.navigation.enabled?u():(c(),l())})),a("toEdge fromEdge lock unlock",(()=>{l()})),a("destroy",(()=>{p()})),a("enable disable",(()=>{let{nextEl:e,prevEl:s}=t.navigation;e=T(e),s=T(s),t.enabled?l():[...e,...s].filter((e=>!!e)).forEach((e=>e.classList.add(t.params.navigation.lockClass)))})),a("click",((e,s)=>{let{nextEl:a,prevEl:r}=t.navigation;a=T(a),r=T(r);const n=s.target;let l=r.includes(n)||a.includes(n);if(t.isElement&&!l){const e=s.path||s.composedPath&&s.composedPath();e&&(l=e.find((e=>a.includes(e)||r.includes(e))))}if(t.params.navigation.hideOnClick&&!l){if(t.pagination&&t.params.pagination&&t.params.pagination.clickable&&(t.pagination.el===n||t.pagination.el.contains(n)))return;let e;a.length?e=a[0].classList.contains(t.params.navigation.hiddenClass):r.length&&(e=r[0].classList.contains(t.params.navigation.hiddenClass)),i(!0===e?"navigationShow":"navigationHide"),[...a,...r].filter((e=>!!e)).forEach((e=>e.classList.toggle(t.params.navigation.hiddenClass)))}}));const u=()=>{t.el.classList.add(...t.params.navigation.navigationDisabledClass.split(" ")),p()};Object.assign(t.navigation,{enable:()=>{t.el.classList.remove(...t.params.navigation.navigationDisabledClass.split(" ")),c(),l()},disable:u,update:l,init:c,destroy:p})},function(e){let{swiper:t,extendParams:s,on:a,emit:i}=e;const r="swiper-pagination";let n;s({pagination:{el:null,bulletElement:"span",clickable:!1,hideOnClick:!1,renderBullet:null,renderProgressbar:null,renderFraction:null,renderCustom:null,progressbarOpposite:!1,type:"bullets",dynamicBullets:!1,dynamicMainBullets:1,formatFractionCurrent:e=>e,formatFractionTotal:e=>e,bulletClass:`${r}-bullet`,bulletActiveClass:`${r}-bullet-active`,modifierClass:`${r}-`,currentClass:`${r}-current`,totalClass:`${r}-total`,hiddenClass:`${r}-hidden`,progressbarFillClass:`${r}-progressbar-fill`,progressbarOppositeClass:`${r}-progressbar-opposite`,clickableClass:`${r}-clickable`,lockClass:`${r}-lock`,horizontalClass:`${r}-horizontal`,verticalClass:`${r}-vertical`,paginationDisabledClass:`${r}-disabled`}}),t.pagination={el:null,bullets:[]};let l=0;function o(){return!t.params.pagination.el||!t.pagination.el||Array.isArray(t.pagination.el)&&0===t.pagination.el.length}function d(e,s){const{bulletActiveClass:a}=t.params.pagination;e&&(e=e[("prev"===s?"previous":"next")+"ElementSibling"])&&(e.classList.add(`${a}-${s}`),(e=e[("prev"===s?"previous":"next")+"ElementSibling"])&&e.classList.add(`${a}-${s}-${s}`))}function c(e){const s=e.target.closest(le(t.params.pagination.bulletClass));if(!s)return;e.preventDefault();const a=y(s)*t.params.slidesPerGroup;if(t.params.loop){if(t.realIndex===a)return;const e=(i=t.realIndex,r=a,n=t.slides.length,(r%=n)==1+(i%=n)?"next":r===i-1?"previous":void 0);"next"===e?t.slideNext():"previous"===e?t.slidePrev():t.slideToLoop(a)}else t.slideTo(a);var i,r,n}function p(){const e=t.rtl,s=t.params.pagination;if(o())return;let a,r,c=t.pagination.el;c=T(c);const p=t.virtual&&t.params.virtual.enabled?t.virtual.slides.length:t.slides.length,u=t.params.loop?Math.ceil(p/t.params.slidesPerGroup):t.snapGrid.length;if(t.params.loop?(r=t.previousRealIndex||0,a=t.params.slidesPerGroup>1?Math.floor(t.realIndex/t.params.slidesPerGroup):t.realIndex):void 0!==t.snapIndex?(a=t.snapIndex,r=t.previousSnapIndex):(r=t.previousIndex||0,a=t.activeIndex||0),"bullets"===s.type&&t.pagination.bullets&&t.pagination.bullets.length>0){const i=t.pagination.bullets;let o,p,u;if(s.dynamicBullets&&(n=S(i[0],t.isHorizontal()?"width":"height",!0),c.forEach((e=>{e.style[t.isHorizontal()?"width":"height"]=n*(s.dynamicMainBullets+4)+"px"})),s.dynamicMainBullets>1&&void 0!==r&&(l+=a-(r||0),l>s.dynamicMainBullets-1?l=s.dynamicMainBullets-1:l<0&&(l=0)),o=Math.max(a-l,0),p=o+(Math.min(i.length,s.dynamicMainBullets)-1),u=(p+o)/2),i.forEac
vendor: 9,756 bytes, line 31461
31461h((e=>{const t=[...["","-next","-next-next","-prev","-prev-prev","-main"].map((e=>`${s.bulletActiveClass}${e}`))].map((e=>"string"==typeof e&&e.includes(" ")?e.split(" "):e)).flat();e.classList.remove(...t)})),c.length>1)i.forEach((e=>{const i=y(e);i===a?e.classList.add(...s.bulletActiveClass.split(" ")):t.isElement&&e.setAttribute("part","bullet"),s.dynamicBullets&&(i>=o&&i<=p&&e.classList.add(...`${s.bulletActiveClass}-main`.split(" ")),i===o&&d(e,"prev"),i===p&&d(e,"next"))}));else{const e=i[a];if(e&&e.classList.add(...s.bulletActiveClass.split(" ")),t.isElement&&i.forEach(((e,t)=>{e.setAttribute("part",t===a?"bullet-active":"bullet")})),s.dynamicBullets){const e=i[o],t=i[p];for(let e=o;e<=p;e+=1)i[e]&&i[e].classList.add(...`${s.bulletActiveClass}-main`.split(" "));d(e,"prev"),d(t,"next")}}if(s.dynamicBullets){const a=Math.min(i.length,s.dynamicMainBullets+4),r=(n*a-n)/2-u*n,l=e?"right":"left";i.forEach((e=>{e.style[t.isHorizontal()?l:"top"]=`${r}px`}))}}c.forEach(((e,r)=>{if("fraction"===s.type&&(e.querySelectorAll(le(s.currentClass)).forEach((e=>{e.textContent=s.formatFractionCurrent(a+1)})),e.querySelectorAll(le(s.totalClass)).forEach((e=>{e.textContent=s.formatFractionTotal(u)}))),"progressbar"===s.type){let i;i=s.progressbarOpposite?t.isHorizontal()?"vertical":"horizontal":t.isHorizontal()?"horizontal":"vertical";const r=(a+1)/u;let n=1,l=1;"horizontal"===i?n=r:l=r,e.querySelectorAll(le(s.progressbarFillClass)).forEach((e=>{e.style.transform=`translate3d(0,0,0) scaleX(${n}) scaleY(${l})`,e.style.transitionDuration=`${t.params.speed}ms`}))}"custom"===s.type&&s.renderCustom?(C(e,s.renderCustom(t,a+1,u)),0===r&&i("paginationRender",e)):(0===r&&i("paginationRender",e),i("paginationUpdate",e)),t.params.watchOverflow&&t.enabled&&e.classList[t.isLocked?"add":"remove"](s.lockClass)}))}function u(){const e=t.params.pagination;if(o())return;const s=t.virtual&&t.params.virtual.enabled?t.virtual.slides.length:t.grid&&t.params.grid.rows>1?t.slides.length/Math.ceil(t.params.grid.rows):t.slides.length;let a=t.pagination.el;a=T(a);let r="";if("bullets"===e.type){let a=t.params.loop?Math.ceil(s/t.params.slidesPerGroup):t.snapGrid.length;t.params.freeMode&&t.params.freeMode.enabled&&a>s&&(a=s);for(let s=0;s<a;s+=1)e.renderBullet?r+=e.renderBullet.call(t,s,e.bulletClass):r+=`<${e.bulletElement} ${t.isElement?'part="bullet"':""} class="${e.bulletClass}"></${e.bulletElement}>`}"fraction"===e.type&&(r=e.renderFraction?e.renderFraction.call(t,e.currentClass,e.totalClass):`<span class="${e.currentClass}"></span> / <span class="${e.totalClass}"></span>`),"progressbar"===e.type&&(r=e.renderProgressbar?e.renderProgressbar.call(t,e.progressbarFillClass):`<span class="${e.progressbarFillClass}"></span>`),t.pagination.bullets=[],a.forEach((s=>{"custom"!==e.type&&C(s,r||""),"bullets"===e.type&&t.pagination.bullets.push(...s.querySelectorAll(le(e.bulletClass)))})),"custom"!==e.type&&i("paginationRender",a[0])}function m(){t.params.pagination=ne(t,t.originalParams.pagination,t.params.pagination,{el:"swiper-pagination"});const e=t.params.pagination;if(!e.el)return;let s;"string"==typeof e.el&&t.isElement&&(s=t.el.querySelector(e.el)),s||"string"!=typeof e.el||(s=[...document.querySelectorAll(e.el)]),s||(s=e.el),s&&0!==s.length&&(t.params.uniqueNavElements&&"string"==typeof e.el&&Array.isArray(s)&&s.length>1&&(s=[...t.el.querySelectorAll(e.el)],s.length>1&&(s=s.find((e=>E(e,".swiper")[0]===t.el)))),Array.isArray(s)&&1===s.length&&(s=s[0]),Object.assign(t.pagination,{el:s}),s=T(s),s.forEach((s=>{"bullets"===e.type&&e.clickable&&s.classList.add(...(e.clickableClass||"").split(" ")),s.classList.add(e.modifierClass+e.type),s.classList.add(t.isHorizontal()?e.horizontalClass:e.verticalClass),"bullets"===e.type&&e.dynamicBullets&&(s.classList.add(`${e.modifierClass}${e.type}-dynamic`),l=0,e.dynamicMainBullets<1&&(e.dynamicMainBullets=1)),"progressbar"===e.type&&e.progressbarOpposite&&s.classList.add(e.progressbarOppositeClass),e.clickable&&s.addEventListener("click",c),t.enabled||s.classList.add(e.lockClass)})))}function h(){const e=t.params.pagination;if(o())return;let s=t.pagination.el;s&&(s=T(s),s.forEach((s=>{s.classList.remove(e.hiddenClass),s.classList.remove(e.modifierClass+e.type),s.classList.remove(t.isHorizontal()?e.horizontalClass:e.verticalClass),e.clickable&&(s.classList.remove(...(e.clickableClass||"").split(" ")),s.removeEventListener("click",c))}))),t.pagination.bullets&&t.pagination.bullets.forEach((t=>t.classList.remove(...e.bulletActiveClass.split(" "))))}a("changeDirection",(()=>{if(!t.pagination||!t.pagination.el)return;const e=t.params.pagination;let{el:s}=t.pagination;s=T(s),s.forEach((s=>{s.classList.remove(e.horizontalClass,e.verticalClass),s.classList.add(t.isHorizontal()?e.horizontalClass:e.verticalClass)}))})),a("init",(()=>{!1===t.params.pagination.enabled?f():(m(),u(),p())})),a("activeIndexChange",(()=>{void 0===t.snapIndex&&p()})),a("snapIndexChange",(()=>{p()})),a("snapGridLengthChange",(()=>{u(),p()})),a("destroy",(()=>{h()})),a("enable disable",(()=>{let{el:e}=t.pagination;e&&(e=T(e),e.forEach((e=>e.classList[t.enabled?"remove":"add"](t.params.pagination.lockClass))))})),a("lock unlock",(()=>{p()})),a("click",((e,s)=>{const a=s.target,r=T(t.pagination.el);if(t.params.pagination.el&&t.params.pagination.hideOnClick&&r&&r.length>0&&!a.classList.contains(t.params.pagination.bulletClass)){if(t.navigation&&(t.navigation.nextEl&&a===t.navigation.nextEl||t.navigation.prevEl&&a===t.navigation.prevEl))return;const e=r[0].classList.contains(t.params.pagination.hiddenClass);i(!0===e?"paginationShow":"paginationHide"),r.forEach((e=>e.classList.toggle(t.params.pagination.hiddenClass)))}}));const f=()=>{t.el.classList.add(t.params.pagination.paginationDisabledClass);let{el:e}=t.pagination;e&&(e=T(e),e.forEach((e=>e.classList.add(t.params.pagination.paginationDisabledClass)))),h()};Object.assign(t.pagination,{enable:()=>{t.el.classList.remove(t.params.pagination.paginationDisabledClass);let{el:e}=t.pagination;e&&(e=T(e),e.forEach((e=>e.classList.remove(t.params.pagination.paginationDisabledClass)))),m(),u(),p()},disable:f,render:u,update:p,init:m,destroy:h})},function(e){let{swiper:t,extendParams:s,on:i,emit:r}=e;const o=a();let d,c,p,u,m=!1,h=null,f=null;function g(){if(!t.params.scrollbar.el||!t.scrollbar.el)return;const{scrollbar:e,rtlTranslate:s}=t,{dragEl:a,el:i}=e,r=t.params.scrollbar,n=t.params.loop?t.progressLoop:t.progress;let l=c,o=(p-c)*n;s?(o=-o,o>0?(l=c-o,o=0):-o+c>p&&(l=p+o)):o<0?(l=c+o,o=0):o+c>p&&(l=p-o),t.isHorizontal()?(a.style.transform=`translate3d(${o}px, 0, 0)`,a.style.width=`${l}px`):(a.style.transform=`translate3d(0px, ${o}px, 0)`,a.style.height=`${l}px`),r.hide&&(clearTimeout(h),i.style.opacity=1,h=setTimeout((()=>{i.style.opacity=0,i.style.transitionDuration="400ms"}),1e3))}function b(){if(!t.params.scrollbar.el||!t.scrollbar.el)return;const{scrollbar:e}=t,{dragEl:s,el:a}=e;s.style.width="",s.style.height="",p=t.isHorizontal()?a.offsetWidth:a.offsetHeight,u=t.size/(t.virtualSize+t.params.slidesOffsetBefore-(t.params.centeredSlides?t.snapGrid[0]:0)),c="auto"===t.params.scrollbar.dragSize?p*u:parseInt(t.params.scrollbar.dragSize,10),t.isHorizontal()?s.style.width=`${c}px`:s.style.height=`${c}px`,a.style.display=u>=1?"none":"",t.params.scrollbar.hide&&(a.style.opacity=0),t.params.watchOverflow&&t.enabled&&e.el.classList[t.isLocked?"add":"remove"](t.params.scrollbar.lockClass)}function y(e){return t.isHorizontal()?e.clientX:e.clientY}function E(e){const{scrollbar:s,rtlTranslate:a}=t,{el:i}=s;let r;r=(y(e)-w(i)[t.isHorizontal()?"left":"top"]-(null!==d?d:c/2))/(p-c),r=Math.max(Math.min(r,1),0),a&&(r=1-r);const n=t.minTranslate()+(t.maxTranslate()-t.minTranslate())*r;t.updateProgress(n),t.setTranslate(n),t.updateActiveIndex(),t.updateSlidesClasses()}function x(e){const s=t.params.scrollbar,{scrollbar:a,wrapperEl:i}=t,{el:n,dragEl:l}=a;m=!0,d=e.target===l?y(e)-e.target.getBoundingClientRect()[t.isHorizontal()?"left":"top"]:null,e.preventDefault(),e.stopPropagation(),i.style.transitionDuration="100ms",l.style.transitionDuration="100ms",E(e),clearTimeout(f),n.style.transitionDuration="0ms",s.hide&&(n.style.opacity=1),t.params.cssMode&&(t.wrapperEl.style["scroll-snap-type"]="none"),r("scrollbarDragStart",e)}function S(e){const{scrollbar:s,wrapperEl:a}=t,{el:i,dragEl:n}=s;m&&(e.preventDefault&&e.cancelable?e.preventDefault():e.returnValue=!1,E(e),a.style.transitionDuration="0ms",i.style.transitionDuration="0ms",n.style.transitionDuration="0ms",r("scrollbarDragMove",e))}function M(e){const s=t.params.scrollbar,{scrollbar:a,wrapperEl:i}=t,{el:n}=a;m&&(m=!1,t.params.cssMode&&(t.wrapperEl.style["scroll-snap-type"]="",i.style.transitionDuration=""),s.hide&&(clearTimeout(f),f=l((()=>{n.style.opacity=0,n.style.transitionDuration="400ms"}),1e3)),r("scrollbarDragEnd",e),s.snapOnRelease&&t.slideToClosest())}function C(e){const{scrollbar:s,params:a}=t,i=s.el;if(!i)return;const r=i,n=!!a.passiveListeners&&{passive:!1,capture:!1},l=!!a.passiveListeners&&{passive:!0,capture:!1};if(!r)return;const d="on"===e?"addEventListener":"removeEventListener";r[d]("pointerdown",x,n),o[d]("pointermove",S,n),o[d]("pointerup",M,l)}function P(){const{scrollbar:e,el:s}=t;t.params.scrollbar=ne(t,t.originalParams.scrollbar,t.params.scrollbar,{el:"swiper-scrollbar"});const a=t.params.scrollbar;if(!a.el)return;let i,r;if("string"==typeof a.el&&t.isElement&&(i=t.el.querySelector(a.el)),i||"string"!=typeof a.el)i||(i=a.el);else if(i=o.querySelectorAll(a.el),!i.length)return;t.params.uniqueNavElements&&"string"==typeof a.el&&i.length>1&&1===s.querySelectorAll(a.el).length&&(i=s.querySelector(a.el)),i.length>0&&(i=i[0]),i.classList.add(t.isHorizontal()?a.horizontalClass:a.verticalClass),i&&(r=i.querySelector(l
vendor: 3,921 bytes, line 31461
31461e(t.params.scrollbar.dragClass)),r||(r=v("div",t.params.scrollbar.dragClass),i.append(r))),Object.assign(e,{el:i,dragEl:r}),a.draggable&&t.params.scrollbar.el&&t.scrollbar.el&&C("on"),i&&i.classList[t.enabled?"remove":"add"](...n(t.params.scrollbar.lockClass))}function L(){const e=t.params.scrollbar,s=t.scrollbar.el;s&&s.classList.remove(...n(t.isHorizontal()?e.horizontalClass:e.verticalClass)),t.params.scrollbar.el&&t.scrollbar.el&&C("off")}s({scrollbar:{el:null,dragSize:"auto",hide:!1,draggable:!1,snapOnRelease:!0,lockClass:"swiper-scrollbar-lock",dragClass:"swiper-scrollbar-drag",scrollbarDisabledClass:"swiper-scrollbar-disabled",horizontalClass:"swiper-scrollbar-horizontal",verticalClass:"swiper-scrollbar-vertical"}}),t.scrollbar={el:null,dragEl:null},i("changeDirection",(()=>{if(!t.scrollbar||!t.scrollbar.el)return;const e=t.params.scrollbar;let{el:s}=t.scrollbar;s=T(s),s.forEach((s=>{s.classList.remove(e.horizontalClass,e.verticalClass),s.classList.add(t.isHorizontal()?e.horizontalClass:e.verticalClass)}))})),i("init",(()=>{!1===t.params.scrollbar.enabled?I():(P(),b(),g())})),i("update resize observerUpdate lock unlock changeDirection",(()=>{b()})),i("setTranslate",(()=>{g()})),i("setTransition",((e,s)=>{!function(e){t.params.scrollbar.el&&t.scrollbar.el&&(t.scrollbar.dragEl.style.transitionDuration=`${e}ms`)}(s)})),i("enable disable",(()=>{const{el:e}=t.scrollbar;e&&e.classList[t.enabled?"remove":"add"](...n(t.params.scrollbar.lockClass))})),i("destroy",(()=>{L()}));const I=()=>{t.el.classList.add(...n(t.params.scrollbar.scrollbarDisabledClass)),t.scrollbar.el&&t.scrollbar.el.classList.add(...n(t.params.scrollbar.scrollbarDisabledClass)),L()};Object.assign(t.scrollbar,{enable:()=>{t.el.classList.remove(...n(t.params.scrollbar.scrollbarDisabledClass)),t.scrollbar.el&&t.scrollbar.el.classList.remove(...n(t.params.scrollbar.scrollbarDisabledClass)),P(),b(),g()},disable:I,updateSize:b,setTranslate:g,init:P,destroy:L})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({parallax:{enabled:!1}});const i="[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y], [data-swiper-parallax-opacity], [data-swiper-parallax-scale]",r=(e,s)=>{const{rtl:a}=t,i=a?-1:1,r=e.getAttribute("data-swiper-parallax")||"0";let n=e.getAttribute("data-swiper-parallax-x"),l=e.getAttribute("data-swiper-parallax-y");const o=e.getAttribute("data-swiper-parallax-scale"),d=e.getAttribute("data-swiper-parallax-opacity"),c=e.getAttribute("data-swiper-parallax-rotate");if(n||l?(n=n||"0",l=l||"0"):t.isHorizontal()?(n=r,l="0"):(l=r,n="0"),n=n.indexOf("%")>=0?parseInt(n,10)*s*i+"%":n*s*i+"px",l=l.indexOf("%")>=0?parseInt(l,10)*s+"%":l*s+"px",null!=d){const t=d-(d-1)*(1-Math.abs(s));e.style.opacity=t}let p=`translate3d(${n}, ${l}, 0px)`;if(null!=o){p+=` scale(${o-(o-1)*(1-Math.abs(s))})`}if(c&&null!=c){p+=` rotate(${c*s*-1}deg)`}e.style.transform=p},n=()=>{const{el:e,slides:s,progress:a,snapGrid:n,isElement:l}=t,o=f(e,i);t.isElement&&o.push(...f(t.hostEl,i)),o.forEach((e=>{r(e,a)})),s.forEach(((e,s)=>{let l=e.progress;t.params.slidesPerGroup>1&&"auto"!==t.params.slidesPerView&&(l+=Math.ceil(s/2)-a*(n.length-1)),l=Math.min(Math.max(l,-1),1),e.querySelectorAll(`${i}, [data-swiper-parallax-rotate]`).forEach((e=>{r(e,l)}))}))};a("beforeInit",(()=>{t.params.parallax.enabled&&(t.params.watchSlidesProgress=!0,t.originalParams.watchSlidesProgress=!0)})),a("init",(()=>{t.params.parallax.enabled&&n()})),a("setTranslate",(()=>{t.params.parallax.enabled&&n()})),a("setTransition",((e,s)=>{t.params.parallax.enabled&&function(e){void 0===e&&(e=t.params.speed);const{el:s,hostEl:a}=t,r=[...s.querySelectorAll(i)];t.isElement&&r.push(...a.querySelectorAll(i)),r.forEach((t=>{let s=parseInt(t.getAttribute("data-swiper-parallax-duration"),10)||e;0===e&&(s=0),t.style.transitionDuration=`${s}ms`}))}(s)}))},function(e){let{swiper:t,extendParams:s,on:a,emit:i}=e;const n=r();s({zoom:{enabled:!1,
31461limitToOriginalSize:!1,maxRatio:3,minRatio:1,panOnMouseMove:!1,toggle:!0,containerClass:"swiper-zoom-container",zoomedSlideClass:"swiper-slide-zoomed"}}),t.zoom={enabled:!1};let l=1,o=!1,c=!1,p={x:0,y:0};const u=-3;let m,h;const g=[],v={originX:0,originY:0,slideEl:void 0,slideWidth:void 0,slideHeight:void 0,imageEl:void 0,imageWrapEl:void 0,maxRatio:3},b={isTouched:void 0,isMoved:void 0,currentX:void 0,currentY:void 0,minX:void 0,minY:void 0,maxX:void 0,maxY:void 0,width:void 0,height:void 0,startX:void 0,startY:void 0,touchesStart:{},touchesCurrent:{}},y={x:void 0,y:void 0,prevPositionX:void 0,prevPositionY:void 0,prevTime:void 0};let x,S=1;function T(){if(g.length<2)return 1;const e=g[0].pageX,t=g[0].pageY,s=g[1].pageX,a=g[1].pageY;return Math.sqrt((s-e)**2+(a-t)**2)}function M(){const e=t.params.zoom,s=v.imageWrapEl.getAttribute("data-swiper-zoom")||e.maxRatio;if(e.limitToOriginalSize&&v.imageEl&&v.imageEl.naturalWidth){const e=v.imageEl.naturalWidth/v.imageEl.offsetWidth;return Math.min(e,s)}return s}function C(e){const s=t.isElement?"swiper-slide":`.${t.params.slideClass}`;return!!e.target.matches(s)||t.slides.filter((t=>t.contains(e.target))).length>0}function P(e){const s=`.${t.params.zoom.containerClass}`;return!!e.target.matches(s)||[...t.hostEl.querySelectorAll(s)].filter((t=>t.contains(e.target))).length>0}function L(e){if("mouse"===e.pointerType&&g.splice(0,g.length),!C(e))return;const s=t.params.zoom;if(m=!1,h=!1,g.push(e),!(g.length<2)){if(m=!0,v.scaleStart=T(),!v.slideEl){v.slideEl=e.target.closest(`.${t.params.slideClass}, swiper-slide`),v.slideEl||(v.slideEl=t.slides[t.activeIndex]);let a=v.slideEl.querySelector(`.${s.containerClass}`);if(a&&(a=a.querySelectorAll("picture, img, svg, canvas, .swiper-zoom-target")[0]),v.imageEl=a,v.imageWrapEl=a?E(v.imageEl,`.${s.containerClass}`)[0]:void 0,!v.imageWrapEl)return void(v.imageEl=void 0);v.maxRatio=M()}if(v.imageEl){const[e,t]=function(){if(g.length<2)return{x:null,y:null};const e=v.imageEl.getBoundingClientRect();return[(g[0].pageX+(g[1].pageX-g[0].pageX)/2-e.x-n.scrollX)/l,(g[0].pageY+(g[1].pageY-g[0].pageY)/2-e.y-n.scrollY)/l]}();v.originX=e,v.originY=t,v.imageEl.style.transitionDuration="0ms"}o=!0}}function I(e){if(!C(e))return;const s=t.params.zoom,a=t.zoom,i=g.findIndex((t=>t.pointerId===e.pointerId));i>=0&&(g[i]=e),g.length<2||(h=!0,v.scaleMove=T(),v.imageEl&&(a.scale=v.scaleMove/v.scaleStart*l,a.scale>v.maxRatio&&(a.scale=v.maxRatio-1+(a.scale-v.maxRatio+1)**.5),a.scale<s.minRatio&&(a.scale=s.minRatio+1-(s.minRatio-a.scale+1)**.5),v.imageEl.style.transform=`translate3d(0,0,0) scale(${a.scale})`))}function z(e){if(!C(e))return;if("mouse"===e.pointerType&&"pointerout"===e.type)return;const s=t.params.zoom,a=t.zoom,i=g.findIndex((t=>t.pointerId===e.pointerId));i>=0&&g.splice(i,1),m&&h&&(m=!1,h=!1,v.imageEl&&(a.scale=Math.max(Math.min(a.scale,v.maxRatio),s.minRatio),v.imageEl.style.transitionDuration=`${t.params.speed}ms`,v.imageEl.style.transform=`translate3d(0,0,0) scale(${a.scale})`,l=a.scale,o=!1,a.scale>1&&v.slideEl?v.slideEl.classList.add(`${s.zoomedSlideClass}`):a.scale<=1&&v.slideEl&&v.slideEl.classList.remove(`${s.zoomedSlideClass}`),1===a.scale&&(v.originX=0,v.originY=0,v.slideEl=void 0)))}function A(){t.touchEventsData.preventTouchMoveFromPointerMove=!1}function $(e){const s="mouse"===e.pointerType&&t.params.zoom.panOnMouseMove;if(!C(e)||!P(e))return;const a=t.zoom;if(!v.imageEl)return;if(!b.isTouched||!v.slideEl)return void(s&&O(e));if(s)return void O(e);b.isMoved||(b.width=v.imageEl.offsetWidth||v.imageEl.clientWidth,b.height=v.imageEl.offsetHeight||v.imageEl.clientHeight,b.startX=d(v.imageWrapEl,"x")||0,b.startY=d(v.imageWrapEl,"y")||0,v.slideWidth=v.slideEl.offsetWidth,v.slideHeight=v.slideEl.offsetHeight,v.imageWrapEl.style.transitionDuration="0ms");const i=b.width*a.scale,r=b.height*a.scale;b.minX=Math.min(v.slideWidth/2-i/2,0),b.maxX=-b.minX,b.minY=Math.min(v.slideHeight/2-r/2,0),b.maxY=-b.minY,b.touchesCurrent.x=g.length>0?g[0].pageX:e.pageX,b.touchesCurrent.y=g.length>0?g[0].pageY:e.pageY;if(Math.max(Math.abs(b.touchesCurrent.x-b.touchesStart.x),Math.abs(b.touchesCurrent.y-b.touchesStart.y))>5&&(t.allowClick=!1),!b.isMoved&&!o){if(t.isHorizontal()&&(Math.floor(b.minX)===Math.floor(b.startX)&&b.touchesCurrent.x<b.touchesStart.x||Math.floor(b.maxX)===Math.floor(b.startX)&&b.touchesCurrent.x>b.touchesStart.x))return b.isTouched=!1,void A();if(!t.isHorizontal()&&(Math.floor(b.minY)===Math.floor(b.startY)&&b.touchesCurrent.y<b.touchesStart.y||Math.floor(b.maxY)===Math.floor(b.startY)&&b.touchesCurrent.y>b.touchesStart.y))return b.isTouched=!1,void A()}e.cancelable&&e.preventDefault(),e.stopPropagation(),clearTimeout(x),t.touchEventsData.preventTouchMoveFromPointerMove=!0,x=setTimeout((()=>{t.destroyed||A()})),b.isMoved=!0;const n=(a.scale-l)/(v.maxRatio-t.params.zoom.minRatio),{originX:c,originY:p}=v;b.currentX=b.touchesCurrent.x-b.touchesStart.x+b.startX+n*(b.width-2*c),b.currentY=b.touchesCurrent.y-b.touchesStart.y+b.startY+n*(b.height-2*p),b.currentX<b.minX&&(b.currentX=b.minX+1-(b.minX-b.currentX+1)**.8),b.currentX>b.maxX&&(b.currentX=b.maxX-1+(b.currentX-b.maxX+1)**.8),b.currentY<b.minY&&(b.currentY=b.minY+1-(b.minY-b.currentY+1)**.8),b.currentY>b.maxY&&(b.currentY=b.maxY-1+(b.currentY-b.maxY+1)**.8),y.prevPositionX||(y.prevPositionX=b.touchesCurrent.x),y.prevPositionY||(y.prevPositionY=b.touchesCurrent.y),y.prevTime||(y.prevTime=Date.now()),y.x=(b.touchesCurrent.x-y.prevPositionX)/(Date.now()-y.prevTime)/2,y.y=(b.touchesCurrent.y-y.prevPositionY)/(Date.now()-y.prevTime)/2,Math.abs(b.touchesCurrent.x-y.prevPositionX)<2&&(y.x=0),Math.abs(b.touchesCurrent.y-y.prevPositionY)<2&&(y.y=0),y.prevPositionX=b.touchesCurrent.x,y.prevPositionY=b.touchesCurrent.y,y.prevTime=Date.now(),v.imageWrapEl.style.transform=`translate3d(${b.currentX}px, ${b.currentY}px,0)`}function k(){const e=t.zoom;v.slideEl&&t.activeIndex!==t.slides.indexOf(v.slideEl)&&(v.imageEl&&(v.imageEl.style.transform="translate3d(0,
314610,0) scale(1)"),v.imageWrapEl&&(v.imageWrapEl.style.transform="translate3d(0,0,0)"),v.slideEl.classList.remove(`${t.params.zoom.zoomedSlideClass}`),e.scale=1,l=1,v.slideEl=void 0,v.imageEl=void 0,v.imageWrapEl=void 0,v.originX=0,v.originY=0)}function O(e){if(l<=1||!v.imageWrapEl)return;if(!C(e)||!P(e))return;const t=n.getComputedStyle(v.imageWrapEl).transform,s=new n.DOMMatrix(t);if(!c)return c=!0,p.x=e.clientX,p.y=e.clientY,b.startX=s.e,b.startY=s.f,b.width=v.imageEl.offsetWidth||v.imageEl.clientWidth,b.height=v.imageEl.offsetHeight||v.imageEl.clientHeight,v.slideWidth=v.slideEl.offsetWidth,void(v.slideHeight=v.slideEl.offsetHeight);const a=(e.clientX-p.x)*u,i=(e.clientY-p.y)*u,r=b.width*l,o=b.height*l,d=v.slideWidth,m=v.slideHeight,h=Math.min(d/2-r/2,0),f=-h,g=Math.min(m/2-o/2,0),w=-g,y=Math.max(Math.min(b.startX+a,f),h),E=Math.max(Math.min(b.startY+i,w),g);v.imageWrapEl.style.transitionDuration="0ms",v.imageWrapEl.style.transform=`translate3d(${y}px, ${E}px, 0)`,p.x=e.clientX,p.y=e.clientY,b.startX=y,b.startY=E,b.currentX=y,b.currentY=E}function D(e){const s=t.zoom,a=t.params.zoom;if(!v.slideEl){e&&e.target&&(v.slideEl=e.target.closest(`.${t.params.slideClass}, swiper-slide`)),v.slideEl||(t.params.virtual&&t.params.virtual.enabled&&t.virtual?v.slideEl=f(t.slidesEl,`.${t.params.slideActiveClass}`)[0]:v.slideEl=t.slides[t.activeIndex]);let s=v.slideEl.querySelector(`.${a.containerClass}`);s&&(s=s.querySelectorAll("picture, img, svg, canvas, .swiper-zoom-target")[0]),v.imageEl=s,v.imageWrapEl=s?E(v.imageEl,`.${a.containerClass}`)[0]:void 0}if(!v.imageEl||!v.imageWrapEl)return;let i,r,o,d,c,p,u,m,h,g,y,x,S,T,C,P,L,I;t.params.cssMode&&(t.wrapperEl.style.overflow="hidden",t.wrapperEl.style.touchAction="none"),v.slideEl.classList.add(`${a.zoomedSlideClass}`),void 0===b.touchesStart.x&&e?(i=e.pageX,r=e.pageY):(i=b.touchesStart.x,r=b.touchesStart.y);const z=l,A="number"==typeof e?e:null;1===l&&A&&(i=void 0,r=void 0,b.touchesStart.x=void 0,b.touchesStart.y=void 0);const $=M();s.scale=A||$,l=A||$,!e||1===l&&A?(u=0,m=0):(L=v.slideEl.offsetWidth,I=v.slideEl.offsetHeight,o=w(v.slideEl).left+n.scrollX,d=w(v.slideEl).top+n.scrollY,c=o+L/2-i,p=d+I/2-r,h=v.imageEl.offsetWidth||v.imageEl.clientWidth,g=v.imageEl.offsetHeight||v.imageEl.clientHeight,y=h*s.scale,x=g*s.scale,S=Math.min(L/2-y/2,0),T=Math.min(I/2-x/2,0),C=-S,P=-T,z>0&&A&&"number"==typeof b.currentX&&"number"==typeof b.currentY?(u=b.currentX*s.scale/z,m=b.currentY*s.scale/z):(u=c*s.scale,m=p*s.scale),u<S&&(u=S),u>C&&(u=C),m<T&&(m=T),m>P&&(m=P)),A&&1===s.scale&&(v.originX=0,v.originY=0),b.currentX=u,b.currentY=m,v.imageWrapEl.style.transitionDuration="300ms",v.imageWrapEl.style.transform=`translate3d(${u}px, ${m}px,0)`,v.imageEl.style.transitionDuration="300ms",v.imageEl.style.transform=`translate3d(0,0,0) scale(${s.scale})`}function G(){const e=t.zoom,s=t.params.zoom;if(!v.slideEl){t.params.virtual&&t.params.virtual.enabled&&t.virtual?v.slideEl=f(t.slidesEl,`.${t.params.slideActiveClass}`)[0]:v.slideEl=t.slides[t.activeIndex];let e=v.slideEl.querySelector(`.${s.containerClass}`);e&&(e=e.querySelectorAll("picture, img, svg, canvas, .swiper-zoom-target")[0]),v.imageEl=e,v.imageWrapEl=e?E(v.imageEl,`.${s.containerClass}`)[0]:void 0}v.imageEl&&v.imageWrapEl&&(t.params.cssMode&&(t.wrapperEl.style.overflow="",t.wrapperEl.style.touchAction=""),e.scale=1,l=1,b.currentX=void 0,b.currentY=void 0,b.touchesStart.x=void 0,b.touchesStart.y=void 0,v.imageWrapEl.style.transitionDuration="300ms",v.imageWrapEl.style.transform="translate3d(0,0,0)",v.imageEl.style.transitionDuration="300ms",v.imageEl.style.transform="translate3d(0,0,0) scale(1)",v.slideEl.classList.remove(`${s.zoomedSlideClass}`),v.slideEl=void 0,v.originX=0,v.originY=0,t.params.zoom.panOnMouseMove&&(p={x:0,y:0},c&&(c=!1,b.startX=0,b.startY=0)))}function X(e){const s=t.zoom;s.scale&&1!==s.scale?G():D(e)}function Y(){return{passiveListener:!!t.params.passiveListeners&&{passive:!0,capture:!1},activeListenerWithCapture:!t.params.passiveListeners||{passive:!1,capture:!0}}}function B(){const e=t.zoom;if(e.enabled)return;e.enabled=!0;const{passiveListener:s,activeListenerWithCapture:a}=Y();t.wrapperEl.addEventListener("pointerdown",L,s),t.wrapperEl.addEventListener("pointermove",I,a),["pointerup","pointercancel","pointerout"].forEach((e=>{t.wrapperEl.addEventListener(e,z,s)})),t.wrapperEl.addEventListener("pointermove",$,a)}function H(){const e=t.zoom;if(!e.enabled)return;e.enabled=!1;const{passiveListener:s,activeListenerWithCapture:a}=Y();t.wrapperEl.removeEventListener("pointerdown",L,s),t.wrapperEl.removeEventListener("pointermove",I,a),["pointerup","pointercancel","pointerout"].forEach((e=>{t.wrapperEl.removeEventListener(e,z,s)})),t.wrapperEl.removeEventListener("pointermove",$,a)}Object.defineProperty(t.zoom,"scale",{get:()=>S,set(e){if(S!==e){const t=v.imageEl,s=v.slideEl;i("zoomChange",e,t,s)}S=e}}),a("init",(()=>{t.params.zoom.enabled&&B()})),a("destroy",(()=>{H()})),a("touchStart",((e,s)=>{t.zoom.enabled&&function(e){const s=t.device;if(!v.imageEl)return;if(b.isTouched)return;s.android&&e.cancelable&&e.preventDefault(),b.isTouched=!0;const a=g.length>0?g[0]:e;b.touchesStart.x=a.pageX,b.touchesStart.y=a.pageY}(s)})),a("touchEnd",((e,s)=>{t.zoom.enabled&&function(){const e=t.zoom;if(g.length=0,!v.imageEl)return;if(!b.isTouched||!b.isMoved)return b.isTouched=!1,void(b.isMoved=!1);b.isTouched=!1,b.isMoved=!1;let s=300,a=300;const i=y.x*s,r=b.currentX+i,n=y.y*a,l=b.currentY+n;0!==y.x&&(s=Math.abs((r-b.currentX)/y.x)),0!==y.y&&(a=Math.abs((l-b.currentY)/y.y));const o=Math.max(s,a);b.currentX=r,b.currentY=l;const d=b.width*e.scale,c=b.height*e.scale;b.minX=Math.min(v.slideWidth/2-d/2,0),b.maxX=-b.minX,b.minY=Math.min(v.slideHeight/2-c/2,0),b.maxY=-b.minY,b.currentX=Math.max(Math.min(b.currentX,b.maxX),b.minX),b.currentY=Math.max(Math.min(b.currentY,b.maxY),b.minY),v.imageWrapEl.style.transitionDuration=`${o}ms`,v.imageWrapEl.style.transform=`translate3d(${b.currentX}px, ${b.currentY}px,0)`}()})),a("doubleTap",((e,s)=>{!t.animating&&t.params.zoom.enabled&&t.zoom.enabled&&t.params.zoom.toggle&&X(s)})),a("transitionEnd",(()=>{t.zoom.enabled&&t.params.zoom.enabled&&k()})),a("slideChange",(()=>{t.zoom.enabled&&t.params.zoom.enabled&&t.params.cssMode&&k()})),Object.assign(t.zoom,{enable:B,disable:H,in:D,out:G,toggle:X})},function(e){let{swiper:t,extendParams:s,on:a}=e;function i(e,t){const s=function(){let e,t,s;return(a,i)=>{for(t=-1,e=a.length;e-t>1;)s=e+t>>1,a[s]<=i?t=s:e=s;return e}}();let a,i;return this.x=e,this.y=t,this.lastIndex=e.length-1,this.interpolate=function(e){return e?(i=s(this.x,e),a=i-1,(e-this.x[a])*(this.y[i]-this.y[a])/(this.x[i]-this.x[a])+this.y[a]):0},this}function r(){t.controller.control&&t.controller.spline&&(t.controller.spline=void 0,delete t.controller.spline)}s({controller:{control:void 0,inverse:!1,by:"slide"}}),t.controller={control:void 0},a("beforeInit",(()=>{if("undefined"!=typeof window&&("string"==typeof t.params.controller.control||t.params.controller.control instanceof HTMLElement)){("string"==typeof t.params.controller.control?[...document.querySelectorAll(t.params.controller.control)]:[t.params.controller.control]).forEac
31461h((e=>{if(t.controller.control||(t.controller.control=[]),e&&e.swiper)t.controller.control.push(e.swiper);else if(e){const s=`${t.params.eventsPrefix}init`,a=i=>{t.controller.control.push(i.detail[0]),t.update(),e.removeEventListener(s,a)};e.addEventListener(s,a)}}))}else t.controller.control=t.params.controller.control})),a("update",(()=>{r()})),a("resize",(()=>{r()})),a("observerUpdate",(()=>{r()})),a("setTranslate",((e,s,a)=>{t.controller.control&&!t.controller.control.destroyed&&t.controller.setTranslate(s,a)})),a("setTransition",((e,s,a)=>{t.controller.control&&!t.controller.control.destroyed&&t.controller.setTransition(s,a)})),Object.assign(t.controller,{setTranslate:function(e,s){const a=t.controller.control;let r,n;const l=t.constructor;function o(e){if(e.destroyed)return;const s=t.rtlTranslate?-t.translate:t.translate;"slide"===t.params.controller.by&&(!function(e){t.controller.spline=t.params.loop?new i(t.slidesGrid,e.slidesGrid):new i(t.snapGrid,e.snapGrid)}(e),n=-t.controller.spline.interpolate(-s)),n&&"container"!==t.params.controller.by||(r=(e.maxTranslate()-e.minTranslate())/(t.maxTranslate()-t.minTranslate()),!Number.isNaN(r)&&Number.isFinite(r)||(r=1),n=(s-t.minTranslate())*r+e.minTranslate()),t.params.controller.inverse&&(n=e.maxTranslate()-n),e.updateProgress(n),e.setTranslate(n,t),e.updateActiveIndex(),e.updateSlidesClasses()}if(Array.isArray(a))for(let e=0;e<a.length;e+=1)a[e]!==s&&a[e]instanceof l&&o(a[e]);else a instanceof l&&s!==a&&o(a)},setTransition:function(e,s){const a=t.constructor,i=t.controller.control;let r;function n(s){s.destroyed||(s.setTransition(e,t),0!==e&&(s.transitionStart(),s.params.autoHeight&&l((()=>{s.updateAutoHeight()})),x(s.wrapperEl,(()=>{i&&s.transitionEnd()}))))}if(Array.isArray(i))for(r=0;r<i.length;r+=1)i[r]!==s&&i[r]instanceof a&&n(i[r]);else i instanceof a&&s!==i&&n(i)}})},function(e){let{swiper:t,extendParams:s,on:i}=e;s({a11y:{enabled:!0,notificationClass:"swiper-notification",prevSlideMessage:"Previous slide",nextSlideMessage:"Next slide",firstSlideMessage:"This is the first slide",lastSlideMessage:"This is the last slide",paginationBulletMessage:"Go to slide {{index}}",slideLabelMessage:"{{index}} / {{slidesLength}}",containerMessage:null,containerRoleDescriptionMessage:null,containerRole:null,itemRoleDescriptionMessage:null,slideRole:"group",id:null,scrollOnFocus:!0}}),t.a11y={clicked:!1};let r,n,l=null,o=(new Date).getTime();function d(e){const t=l;0!==t.length&&C(t,e)}function c(e){(e=T(e)).forEach((e=>{e.setAttribute("tabIndex","0")}))}function p(e){(e=T(e)).forEach((e=>{e.setAttribute("tabIndex","-1")}))}function u(e,t){(e=T(e)).forEach((e=>{e.setAttribute("role",t)}))}function m(e,t){(e=T(e)).forEach((e=>{e.setAttribute("aria-roledescription",t)}))}function h(e,t){(e=T(e)).forEach((e=>{e.setAttribute("aria-label",t)}))}function f(e){(e=T(e)).forEach((e=>{e.setAttribute("aria-disabled",!0)}))}function g(e){(e=T(e)).forEach((e=>{e.setAttribute("aria-disabled",!1)}))}function w(e){if(13!==e.keyCode&&32!==e.keyCode)return;const s=t.params.a11y,a=e.target;if(!t.pagination||!t.pagination.el||a!==t.pagination.el&&!t.pagination.el.contains(e.target)||e.target.matches(le(t.params.pagination.bulletClass))){if(t.navigation&&t.navigation.prevEl&&t.navigation.nextEl){const e=T(t.navigation.prevEl);T(t.navigation.nextEl).includes(a)&&(t.isEnd&&!t.params.loop||t.slideNext(),t.isEnd?d(s.lastSlideMessage):d(s.nextSlideMessage)),e.includes(a)&&(t.isBeginning&&!t.params.loop||t.slidePrev(),t.isBeginning?d(s.firstSlideMessage):d(s.prevSlideMessage))}t.pagination&&a.matches(le(t.params.pagination.bulletClass))&&a.click()}}function b(){return t.pagination&&t.pagination.bullets&&t.pagination.bullets.length}function E(){return b()&&t.params.pagination.clickable}const x=(e,t,s)=>{c(e),"BUTTON"!==e.tagName&&(u(e,"button"),e.addEventListener("keydown",w)),h(e,s),function(e,t){(e=T(e)).forEach((e=>{e.setAttribute("aria-controls",t)}))}(e,t)},S=e=>{n&&n!==e.target&&!n.contains(e.target)&&(r=!0),t.a11y.clicked=!0},M=()=>{r=!1,requestAnimationFrame((()=>{requestAnimationFrame((()=>{t.destroyed||(t.a11y.clicked=!1)}))}))},P=e=>{o=(new Date).getTime()},L=e=>{if(t.a11y.clicked||!t.params.a11y.scrollOnFocus)return;if((new Date).getTime()-o<100)return;const s=e.target.closest(`.${t.params.slideClass}, swiper-slide`);if(!s||!t.slides.includes(s))return;n=s;const a=t.slides.indexOf(s)===t.activeIndex,i=t.params.watchSlidesProgress&&t.visibleSlides&&t.visibleSlides.includes(s);a||i||e.sourceCapabilities&&e.sourceCapabilities.firesTouchEvents||(t.isHorizontal()?t.el.scrollLeft=0:t.el.scrollTop=0,requestAnimationFrame((()=>
31461{r||(t.params.loop?t.slideToLoop(t.getSlideIndexWhenGrid(parseInt(s.getAttribute("data-swiper-slide-index"))),0):t.slideTo(t.getSlideIndexWhenGrid(t.slides.indexOf(s)),0),r=!1)})))},I=()=>{const e=t.params.a11y;e.itemRoleDescriptionMessage&&m(t.slides,e.itemRoleDescriptionMessage),e.slideRole&&u(t.slides,e.slideRole);const s=t.slides.length;e.slideLabelMessage&&t.slides.forEach(((a,i)=>{const r=t.params.loop?parseInt(a.getAttribute("data-swiper-slide-index"),10):i;h(a,e.slideLabelMessage.replace(/\{\{index\}\}/,r+1).replace(/\{\{slidesLength\}\}/,s))}))},z=()=>{const e=t.params.a11y;t.el.append(l);const s=t.el;e.containerRoleDescriptionMessage&&m(s,e.containerRoleDescriptionMessage),e.containerMessage&&h(s,e.containerMessage),e.containerRole&&u(s,e.containerRole);const i=t.wrapperEl,r=e.id||i.getAttribute("id")||`swiper-wrapper-${n=16,void 0===n&&(n=16),"x".repeat(n).replace(/x/g,(()=>Math.round(16*Math.random()).toString(16)))}`;var n;const o=t.params.autoplay&&t.params.autoplay.enabled?"off":"polite";var d;d=r,T(i).forEach((e=>{e.setAttribute("id",d)})),function(e,t){(e=T(e)).forEach((e=>{e.setAttribute("aria-live",t)}))}(i,o),I();let{nextEl:c,prevEl:p}=t.navigation?t.navigation:{};if(c=T(c),p=T(p),c&&c.forEach((t=>x(t,r,e.nextSlideMessage))),p&&p.forEach((t=>x(t,r,e.prevSlideMessage))),E()){T(t.pagination.el).forEach((e=>{e.addEventListener("keydown",w)}
vendor: 27,247 bytes, line 31461
31461))}a().addEventListener("visibilitychange",P),t.el.addEventListener("focus",L,!0),t.el.addEventListener("focus",L,!0),t.el.addEventListener("pointerdown",S,!0),t.el.addEventListener("pointerup",M,!0)};i("beforeInit",(()=>{l=v("span",t.params.a11y.notificationClass),l.setAttribute("aria-live","assertive"),l.setAttribute("aria-atomic","true")})),i("afterInit",(()=>{t.params.a11y.enabled&&z()})),i("slidesLengthChange snapGridLengthChange slidesGridLengthChange",(()=>{t.params.a11y.enabled&&I()})),i("fromEdge toEdge afterInit lock unlock",(()=>{t.params.a11y.enabled&&function(){if(t.params.loop||t.params.rewind||!t.navigation)return;const{nextEl:e,prevEl:s}=t.navigation;s&&(t.isBeginning?(f(s),p(s)):(g(s),c(s))),e&&(t.isEnd?(f(e),p(e)):(g(e),c(e)))}()})),i("paginationUpdate",(()=>{t.params.a11y.enabled&&function(){const e=t.params.a11y;b()&&t.pagination.bullets.forEach((s=>{t.params.pagination.clickable&&(c(s),t.params.pagination.renderBullet||(u(s,"button"),h(s,e.paginationBulletMessage.replace(/\{\{index\}\}/,y(s)+1)))),s.matches(le(t.params.pagination.bulletActiveClass))?s.setAttribute("aria-current","true"):s.removeAttribute("aria-current")}))}()})),i("destroy",(()=>{t.params.a11y.enabled&&function(){l&&l.remove();let{nextEl:e,prevEl:s}=t.navigation?t.navigation:{};e=T(e),s=T(s),e&&e.forEach((e=>e.removeEventListener("keydown",w))),s&&s.forEach((e=>e.removeEventListener("keydown",w))),E()&&T(t.pagination.el).forEach((e=>{e.removeEventListener("keydown",w)}));a().removeEventListener("visibilitychange",P),t.el&&"string"!=typeof t.el&&(t.el.removeEventListener("focus",L,!0),t.el.removeEventListener("pointerdown",S,!0),t.el.removeEventListener("pointerup",M,!0))}()}))},function(e){let{swiper:t,extendParams:s,on:a}=e;s({history:{enabled:!1,root:"",replaceState:!1,key:"slides",keepQuery:!1}});let i=!1,n={};const l=e=>e.toString().replace(/\s+/g,"-").replace(/[^\w-]+/g,"").replace(/--+/g,"-").replace(/^-+/,"").replace(/-+$/,""),o=e=>{const t=r();let s;s=e?new URL(e):t.location;const a=s.pathname.slice(1).split("/").filter((e=>""!==e)),i=a.length;return{key:a[i-2],value:a[i-1]}},d=(e,s)=>{const a=r();if(!i||!t.params.history.enabled)return;let n;n=t.params.url?new URL(t.params.url):a.location;const o=t.virtual&&t.params.virtual.enabled?t.slidesEl.querySelector(`[data-swiper-slide-index="${s}"]`):t.slides[s];let d=l(o.getAttribute("data-history"));if(t.params.history.root.length>0){let s=t.params.history.root;"/"===s[s.length-1]&&(s=s.slice(0,s.length-1)),d=`${s}/${e?`${e}/`:""}${d}`}else n.pathname.includes(e)||(d=`${e?`${e}/`:""}${d}`);t.params.history.keepQuery&&(d+=n.search);const c=a.history.state;c&&c.value===d||(t.params.history.replaceState?a.history.replaceState({value:d},null,d):a.history.pushState({value:d},null,d))},c=(e,s,a)=>{if(s)for(let i=0,r=t.slides.length;i<r;i+=1){const r=t.slides[i];if(l(r.getAttribute("data-history"))===s){const s=t.getSlideIndex(r);t.slideTo(s,e,a)}}else t.slideTo(0,e,a)},p=()=>{n=o(t.params.url),c(t.params.speed,n.value,!1)};a("init",(()=>{t.params.history.enabled&&(()=>{const e=r();if(t.params.history){if(!e.history||!e.history.pushState)return t.params.history.enabled=!1,void(t.params.hashNavigation.enabled=!0);i=!0,n=o(t.params.url),n.key||n.value?(c(0,n.value,t.params.runCallbacksOnInit),t.params.history.replaceState||e.addEventListener("popstate",p)):t.params.history.replaceState||e.addEventListener("popstate",p)}})()})),a("destroy",(()=>{t.params.history.enabled&&(()=>{const e=r();t.params.history.replaceState||e.removeEventListener("popstate",p)})()})),a("transitionEnd _freeModeNoMomentumRelease",(()=>{i&&d(t.params.history.key,t.activeIndex)})),a("slideChange",(()=>{i&&t.params.cssMode&&d(t.params.history.key,t.activeIndex)}))},function(e){let{swiper:t,extendParams:s,emit:i,on:n}=e,l=!1;const o=a(),d=r();s({hashNavigation:{enabled:!1,replaceState:!1,watchState:!1,getSlideIndex(e,s){if(t.virtual&&t.params.virtual.enabled){const e=t.slides.find((e=>e.getAttribute("data-hash")===s));if(!e)return 0;return parseInt(e.getAttribute("data-swiper-slide-index"),10)}return t.getSlideIndex(f(t.slidesEl,`.${t.params.slideClass}[data-hash="${s}"], swiper-slide[data-hash="${s}"]`)[0])}}});const c=()=>{i("hashChange");const e=o.location.hash.replace("#",""),s=t.virtual&&t.params.virtual.enabled?t.slidesEl.querySelector(`[data-swiper-slide-index="${t.activeIndex}"]`):t.slides[t.activeIndex];if(e!==(s?s.getAttribute("data-hash"):"")){const s=t.params.hashNavigation.getSlideIndex(t,e);if(void 0===s||Number.isNaN(s))return;t.slideTo(s)}},p=()=>{if(!l||!t.params.hashNavigation.enabled)return;const e=t.virtual&&t.params.virtual.enabled?t.slidesEl.querySelector(`[data-swiper-slide-index="${t.activeIndex}"]`):t.slides[t.activeIndex],s=e?e.getAttribute("data-hash")||e.getAttribute("data-history"):"";t.params.hashNavigation.replaceState&&d.history&&d.history.replaceState?(d.history.replaceState(null,null,`#${s}`||""),i("hashSet")):(o.location.hash=s||"",i("hashSet"))};n("init",(()=>{t.params.hashNavigation.enabled&&(()=>{if(!t.params.hashNavigation.enabled||t.params.history&&t.params.history.enabled)return;l=!0;const e=o.location.hash.replace("#","");if(e){const s=0,a=t.params.hashNavigation.getSlideIndex(t,e);t.slideTo(a||0,s,t.params.runCallbacksOnInit,!0)}t.params.hashNavigation.watchState&&d.addEventListener("hashchange",c)})()})),n("destroy",(()=>{t.params.hashNavigation.enabled&&t.params.hashNavigation.watchState&&d.removeEventListener("hashchange",c)})),n("transitionEnd _freeModeNoMomentumRelease",(()=>{l&&p()})),n("slideChange",(()=>{l&&t.params.cssMode&&p()}))},function(e){let t,s,{swiper:i,extendParams:r,on:n,emit:l,params:o}=e;i.autoplay={running:!1,paused:!1,timeLeft:0},r({autoplay:{enabled:!1,delay:3e3,waitForTransition:!0,disableOnInteraction:!1,stopOnLastSlide:!1,reverseDirection:!1,pauseOnMouseEnter:!1}});let d,c,p,u,m,h,f,g,v=o&&o.autoplay?o.autoplay.delay:3e3,w=o&&o.autoplay?o.autoplay.delay:3e3,b=(new Date).getTime();function y(e){i&&!i.destroyed&&i.wrapperEl&&e.target===i.wrapperEl&&(i.wrapperEl.removeEventListener("transitionend",y),g||e.detail&&e.detail.bySwiperTouchMove||C())}const E=()=>{if(i.destroyed||!i.autoplay.running)return;i.autoplay.paused?c=!0:c&&(w=d,c=!1);const e=i.autoplay.paused?d:b+w-(new Date).getTime();i.autoplay.timeLeft=e,l("autoplayTimeLeft",e,e/v),s=requestAnimationFrame((()=>{E()}))},x=e=>{if(i.destroyed||!i.autoplay.running)return;cancelAnimationFrame(s),E();let a=void 0===e?i.params.autoplay.delay:e;v=i.params.autoplay.delay,w=i.params.autoplay.delay;const r=(()=>{let e;if(e=i.virtual&&i.params.virtual.enabled?i.slides.find((e=>e.classList.contains("swiper-slide-active"))):i.slides[i.activeIndex],!e)return;return parseInt(e.getAttribute("data-swiper-autoplay"),10)})();!Number.isNaN(r)&&r>0&&void 0===e&&(a=r,v=r,w=r),d=a;const n=i.params.speed,o=()=>{i&&!i.destroyed&&(i.params.autoplay.reverseDirection?!i.isBeginning||i.params.loop||i.params.rewind?(i.slidePrev(n,!0,!0),l("autoplay")):i.params.autoplay.stopOnLastSlide||(i.slideTo(i.slides.length-1,n,!0,!0),l("autoplay")):!i.isEnd||i.params.loop||i.params.rewind?(i.slideNext(n,!0,!0),l("autoplay")):i.params.autoplay.stopOnLastSlide||(i.slideTo(0,n,!0,!0),l("autoplay")),i.params.cssMode&&(b=(new Date).getTime(),requestAnimationFrame((()=>{x()}))))};return a>0?(clearTimeout(t),t=setTimeout((()=>{o()}),a)):requestAnimationFrame((()=>{o()})),a},S=()=>{b=(new Date).getTime(),i.autoplay.running=!0,x(),l("autoplayStart")},T=()=>{i.autoplay.running=!1,clearTimeout(t),cancelAnimationFrame(s),l("autoplayStop")},M=(e,s)=>{if(i.destroyed||!i.autoplay.running)return;clearTimeout(t),e||(f=!0);const a=()=>{l("autoplayPause"),i.params.autoplay.waitForTransition?i.wrapperEl.addEventListener("transitionend",y):C()};if(i.autoplay.paused=!0,s)return h&&(d=i.params.autoplay.delay),h=!1,void a();const r=d||i.params.autoplay.delay;d=r-((new Date).getTime()-b),i.isEnd&&d<0&&!i.params.loop||(d<0&&(d=0),a())},C=()=>{i.isEnd&&d<0&&!i.params.loop||i.destroyed||!i.autoplay.running||(b=(new Date).getTime(),f?(f=!1,x(d)):x(),i.autoplay.paused=!1,l("autoplayResume"))},P=()=>{if(i.destroyed||!i.autoplay.running)return;const e=a();"hidden"===e.visibilityState&&(f=!0,M(!0)),"visible"===e.visibilityState&&C()},L=e=>{"mouse"===e.pointerType&&(f=!0,g=!0,i.animating||i.autoplay.paused||M(!0))},I=e=>{"mouse"===e.pointerType&&(g=!1,i.autoplay.paused&&C())};n("init",(()=>{i.params.autoplay.enabled&&(i.params.autoplay.pauseOnMouseEnter&&(i.el.addEventListener("pointerenter",L),i.el.addEventListener("pointerleave",I)),a().addEventListener("visibilitychange",P),S())})),n("destroy",(()=>{i.el&&"string"!=typeof i.el&&(i.el.removeEventListener("pointerenter",L),i.el.removeEventListener("pointerleave",I)),a().removeEventListener("visibilitychange",P),i.autoplay.running&&T()})),n("_freeModeStaticRelease",(()=>{(u||f)&&C()})),n("_freeModeNoMomentumRelease",(()=>{i.params.autoplay.disableOnInteraction?T():M(!0,!0)})),n("beforeTransitionStart",((e,t,s)=>{!i.destroyed&&i.autoplay.running&&(s||!i.params.autoplay.disableOnInteraction?M(!0,!0):T())})),n("sliderFirstMove",(()=>{!i.destroyed&&i.autoplay.running&&(i.params.autoplay.disableOnInteraction?T():(p=!0,u=!1,f=!1,m=setTimeout((()=>{f=!0,u=!0,M(!0)}),200)))})),n("touchEnd",(()=>{if(!i.destroyed&&i.autoplay.running&&p){if(clearTimeout(m),clearTimeout(t),i.params.autoplay.disableOnInteraction)return u=!1,void(p=!1);u&&i.params.cssMode&&C(),u=!1,p=!1}})),n("slideChange",(()=>{!i.destroyed&&i.autoplay.running&&(h=!0)})),Object.assign(i.autoplay,{start:S,stop:T,pause:M,resume:C})},function(e){let{swiper:t,extendParams:s,on:i}=e;s({thumbs:{swiper:null,multipleActiveThumbs:!0,autoScrollOffset:0,slideThumbActiveClass:"swiper-slide-thumb-active",thumbsContainerClass:"swiper-thumbs"}});let r=!1,n=!1;function l(){const e=t.thumbs.swiper;if(!e||e.destroyed)return;const s=e.clickedIndex,a=e.clickedSlide;if(a&&a.classList.contains(t.params.thumbs.slideThumbActiveClass))return;if(null==s)return;let i;i=e.params.loop?parseInt(e.clickedSlide.getAttribute("data-swiper-slide-index"),10):s,t.params.loop?t.slideToLoop(i):t.slideTo(i)}function o(){const{thumbs:e}=t.params;if(r)return!1;r=!0;const s=t.constructor;if(e.swiper instanceof s){if(e.swiper.destroyed)return r=!1,!1;t.thumbs.swiper=e.swiper,Object.assign(t.thumbs.swiper.originalParams,{watchSlidesProgress:!0,slideToClickedSlide:!1}),Object.assign(t.thumbs.swiper.params,{watchSlidesProgress:!0,slideToClickedSlide:!1}),t.thumbs.swiper.update()}else if(c(e.swiper)){const a=Object.assign({},e.swiper);Object.assign(a,{watchSlidesProgress:!0,slideToClickedSlide:!1}),t.thumbs.swiper=new s(a),n=!0}return t.thumbs.swiper.el.classList.add(t.params.thumbs.thumbsContainerClass),t.thumbs.swiper.on("tap",l),!0}function d(e){const s=t.thumbs.swiper;if(!s||s.destroyed)return;const a="auto"===s.params.slidesPerView?s.slidesPerViewDynamic():s.params.slidesPerView;let i=1;const r=t.params.thumbs.slideThumbActiveClass;if(t.params.slidesPerView>1&&!t.params.centeredSlides&&(i=t.params.slidesPerView),t.params.thumbs.multipleActiveThumbs||(i=1),i=Math.floor(i),s.slides.forEach((e=>e.classList.remove(r))),s.params.loop||s.params.virtual&&s.params.virtual.enabled)for(let e=0;e<i;e+=1)f(s.slidesEl,`[data-swiper-slide-index="${t.realIndex+e}"]`).forEach((e=>{e.classList.add(r)}));else for(let e=0;e<i;e+=1)s.slides[t.realIndex+e]&&s.slides[t.realIndex+e].classList.add(r);const n=t.params.thumbs.autoScrollOffset,l=n&&!s.params.loop;if(t.realIndex!==s.realIndex||l){const i=s.activeIndex;let r,o;if(s.params.loop){const e=s.slides.find((e=>e.getAttribute("data-swiper-slide-index")===`${t.realIndex}`));r=s.slides.indexOf(e),o=t.activeIndex>t.previousIndex?"next":"prev"}else r=t.realIndex,o=r>t.previousIndex?"next":"prev";l&&(r+="next"===o?n:-1*n),s.visibleSlidesIndexes&&s.visibleSlidesIndexes.indexOf(r)<0&&(s.params.centeredSlides?r=r>i?r-Math.floor(a/2)+1:r+Math.floor(a/2)-1:r>i&&s.params.slidesPerGroup,s.slideTo(r,e?0:void 0))}}t.thumbs={swiper:null},i("beforeInit",(()=>{const{thumbs:e}=t.params;if(e&&e.swiper)if("string"==typeof e.swiper||e.swiper instanceof HTMLElement){const s=a(),i=()=>{const a="string"==typeof e.swiper?s.querySelector(e.swiper):e.swiper;if(a&&a.swiper)e.swiper=a.swiper,o(),d(!0);else if(a){const s=`${t.params.eventsPrefix}init`,i=r=>{e.swiper=r.detail[0],a.removeEventListener(s,i),o(),d(!0),e.swiper.update(),t.update()};a.addEventListener(s,i)}return a},r=()=>{if(t.destroyed)return;i()||requestAnimationFrame(r)};requestAnimationFrame(r)}else o(),d(!0)})),i("slideChange update resize observerUpdate",(()=>{d()})),i("setTransition",((e,s)=>{const a=t.thumbs.swiper;a&&!a.destroyed&&a.setTransition(s)})),i("beforeDestroy",(()=>{const e=t.thumbs.swiper;e&&!e.destroyed&&n&&e.destroy()})),Object.assign(t.thumbs,{init:o,update:d})},function(e){let{swiper:t,extendParams:s,emit:a,once:i}=e;s({freeMode:{enabled:!1,momentum:!0,momentumRatio:1,momentumBounce:!0,momentumBounceRatio:1,momentumVelocityRatio:1,sticky:!1,minimumVelocity:.02}}),Object.assign(t,{freeMode:{onTouchStart:function(){if(t.params.cssMode)return;const e=t.getTranslate();t.setTranslate(e),t.setTransition(0),t.touchEventsData.velocities.length=0,t.freeMode.onTouchEnd({currentPos:t.rtl?t.translate:-t.translate})},onTouchMove:function(){if(t.params.cssMode)return;const{touchEventsData:e,touches:s}=t;0===e.velocities.length&&e.velocities.push({position:s[t.isHorizontal()?"startX":"startY"],time:e.touchStartTime}),e.velocities.push({position:s[t.isHorizontal()?"currentX":"currentY"],time:o()})},onTouchEnd:function(e){let{currentPos:s}=e;if(t.params.cssMode)return;const{params:r,wrapperEl:n,rtlTranslate:l,snapGrid:d,touchEventsData:c}=t,p=o()-c.touchStartTime;if(s<-t.minTranslate())t.slideTo(t.activeIndex);else if(s>-t.maxTranslate())t.slides.length<d.length?t.slideTo(d.length-1):t.slideTo(t.slides.length-1);else{if(r.freeMode.momentum){if(c.velocities.length>1){const e=c.velocities.pop(),s=c.velocities.pop(),a=e.position-s.position,i=e.time-s.time;t.velocity=a/i,t.velocity/=2,Math.abs(t.velocity)<r.freeMode.minimumVelocity&&(t.velocity=0),(i>150||o()-e.time>300)&&(t.velocity=0)}else t.velocity=0;t.velocity*=r.freeMode.momentumVelocityRatio,c.velocities.length=0;let e=1e3*r.freeMode.momentumRatio;const s=t.velocity*e;let p=t.translate+s;l&&(p=-p);let u,m=!1;const h=20*Math.abs(t.velocity)*r.freeMode.momentumBounceRatio;let f;if(p<t.maxTranslate())r.freeMode.momentumBounce?(p+t.maxTranslate()<-h&&(p=t.maxTranslate()-h),u=t.maxTranslate(),m=!0,c.allowMomentumBounce=!0):p=t.maxTranslate(),r.loop&&r.centeredSlides&&(f=!0);else if(p>t.minTranslate())r.freeMode.momentumBounce?(p-t.minTranslate()>h&&(p=t.minTranslate()+h),u=t.minTranslate(),m=!0,c.allowMomentumBounce=!0):p=t.minTranslate(),r.loop&&r.centeredSlides&&(f=!0);else if(r.freeMode.sticky){let e;for(let t=0;t<d.length;t+=1)if(d[t]>-p){e=t;break}p=Math.abs(d[e]-p)<Math.abs(d[e-1]-p)||"next"===t.swipeDirection?d[e]:d[e-1],p=-p}if(f&&i("transitionEnd",(()=>{t.loopFix()})),0!==t.velocity){if(e=l?Math.abs((-p-t.translate)/t.velocity):Math.abs((p-t.translate)/t.velocity),r.freeMode.sticky){const s=Math.abs((l?-p:p)-t.translate),a=t.slidesSizesGrid[t.activeIndex];e=s<a?r.speed:s<2*a?1.5*r.speed:2.5*r.speed}}else if(r.freeMode.sticky)return void t.slideToClosest();r.freeMode.momentumBounce&&m?(t.updateProgress(u),t.setTransition(e),t.setTranslate(p),t.transitionStart(!0,t.swipeDirection),t.animating=!0,x(n,(()=>{t&&!t.destroyed&&c.allowMomentumBounce&&(a("momentumBounce"),t.setTransition(r.speed),setTimeout((()=>{t.setTranslate(u),x(n,(()=>{t&&!t.destroyed&&t.transitionEnd()}))}),0))}))):t.velocity?(a("_freeModeNoMomentumRelease"),t.updateProgress(p),t.setTransition(e),t.setTranslate(p),t.transitionStart(!0,t.swipeDirection),t.animating||(t.animating=!0,x(n,(()=>{t&&!t.destroyed&&t.transitionEnd()})))):t.updateProgress(p),t.updateActiveIndex(),t.updateSlidesClasses()}else{if(r.freeMode.sticky)return void t.slideToClosest();r.freeMode&&a("_freeModeNoMomentumRelease")}(!r.freeMode.momentum||p>=r.longSwipesMs)&&(a("_freeModeStaticRelease"),t.updateProgress(),t.updateActiveIndex(),t.updateSlidesClasses())}}}})},function(e){let t,s,a,i,{swiper:r,extendParams:n,on:l}=e;n({grid:{rows:1,fill:"column"}});const o=()=>{let e=r.params.spaceBetween;return"string"==typeof e&&e.indexOf("%")>=0?e=parseFloat(e.replace("%",""))/100*r.size:"string"==typeof e&&(e=parseFloat(e)),e};l("init",(()=>{i=r.params.grid&&r.params.grid.rows>1})),l("update",(()=>{const{params:e,el:t}=r,s=e.grid&&e.grid.rows>1;i&&!s?(t.classList.remove(`${e.containerModifierClass}grid`,`${e.containerModifierClass}grid-column`),a=1,r.emitContainerClasses()):!i&&s&&(t.classList.add(`${e.containerModifierClass}grid`),"column"===e.grid.fill&&t.classList.add(`${e.containerModifierClass}grid-column`),r.emitContainerClasses()),i=s})),r.grid={initSlides:e=>{const{slidesPerView:i}=r.params,{rows:n,fill:l}=r.params.grid,o=r.virtual&&r.params.virtual.enabled?r.virtual.slides.length:e.length;a=Math.floor(o/n),t=Math.floor(o/n)===o/n?o:Math.ceil(o/n)*n,"auto"!==i&&"row"===l&&(t=Math.max(t,i*n)),s=t/n},unsetSlides:()=>{r.slides&&r.slides.forEach((e=>{e.swiperSlideGridSet&&(e.style.height="",e.style[r.getDirectionLabel("margin-top")]="")}))},updateSlide:(e,i,n)=>{const{slidesPerGroup:l}=r.params,d=o(),{rows:c,fill:p}=r.params.grid,u=r.virtual&&r.params.virtual.enabled?r.virtual.slides.length:n.length;let m,h,f;if("row"===p&&l>1){const s=Math.floor(e/(l*c)),a=e-c*l*s,r=0===s?l:Math.min(Math.ceil((u-s*c*l)/c),l);f=Math.floor(a/r),h=a-f*r+s*l,m=h+f*t/c,i.style.order=m}else"column"===p?(h=Math.floor(e/c),f=e-h*c,(h>a||h===a&&f===c-1)&&(f+=1,f>=c&&(f=0,h+=1))):(f=Math.floor(e/s),h=e-f*s);i.row=f,i.column=h,i.style.height=`calc((100% - ${(c-1)*d}px) / ${c})`,i.style[r.getDirectionLabel("margin-top")]=0!==f?d&&`${d}px`:"",i.swiperSlideGridSet=!0},updateWrapperSize:(e,s)=>{const{centeredSlides:a,roundLengths:i}=r.params,n=o(),{rows:l}=r.params.grid;if(r.virtualSize=(e+n)*t,r.virtualSize=Math.ceil(r.virtualSize/l)-n,r.params.cssMode||(r.wrapperEl.style[r.getDirectionLabel("width")]=`${r.virtualSize+n}px`),a){const e=[];for(let t=0;t<s.length;t+=1){let a=s[t];i&&(a=Math.floor(a)),s[t]<r.virtualSize+s[0]&&e.push(a)}s.splice(0,s.length),s.push(...e)}}}},function(e){let{swiper:t}=e;Object.assign(t,{appendSlide:oe.bind(t),prependSlide:de.bind(t),addSlide:ce.bind(t),removeSlide:pe.bind(t),removeAllSlides:ue.bind(t)})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({fadeEffect:{crossFade:!1}}),me({effect:"fade",swiper:t,on:a,setTranslate:()=>{const{slides:e}=t;t.params.fadeEffect;for(let s=0;s<e.length;s+=1){const e=t.slides[s];let a=-e.swiperSlideOffset;t.params.virtualTranslate||(a-=t.translate);let i=0;t.isHorizontal()||(i=a,a=0);const r=t.params.fadeEffect.crossFade?Math.max(1-Math.abs(e.progress),0):1+Math.min(Math.max(e.progress,-1),0),n=he(0,e);n.style.opacity=r,n.style.transform=`translate3d(${a}px, ${i}px, 0px)`}},setTransition:e=>{const s=t.slides.map((e=>h(e)));s.forEach((t=>{t.style.transitionDuration=`${e}ms`})),fe({swiper:t,duration:e,transformElements:s,allSlides:!0})},overwriteParams:()=>({slidesPerView:1,slidesPerGroup:1,watchSlidesProgress:!0,spaceBetween:0,virtualTranslate:!t.params.cssMode})})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({cubeEffect:{slideShadows:!0,shadow:!0,shadowOffset:20,shadowScale:.94}});const i=(e,t,s)=>{let a=s?e.querySelector(".swiper-slide-shadow-left"):e.querySelector(".swiper-slide-shadow-top"),i=s?e.querySelector(".swiper-slide-shadow-right"):e.querySelector(".swiper-slide-shadow-bottom");a||(a=v("div",("swiper-slide-shadow-cube swiper-slide-shadow-"+(s?"left":"top")).split(" ")),e.append(a)),i||(i=v("div",("swiper-slide-shadow-cube swiper-slide-shadow-"+(s?"right":"bottom")).split(" ")),e.append(i)),a&&(a.style.opacity=Math.max(-t,0)),i&&(i.style.opacity=Math.max(t,0))};me({effect:"cube",swiper:t,on:a,setTranslate:()=>{const{el:e,wrapperEl:s,slides:a,width:r,height:n,rtlTranslate:l,size:o,browser:d}=t,c=M(t),p=t.params.cubeEffect,u=t.isHorizontal(),m=t.virtual&&t.params.virtual.enabled;let h,f=0;p.shadow&&(u?(h=t.wrapperEl.querySelector(".swiper-cube-shadow"),h||(h=v("div","swiper-cube-shadow"),t.wrapperEl.append(h)),h.style.height=`${r}px`):(h=e.querySelector(".swiper-cube-shadow"),h||(h=v("div","swiper-cube-shadow"),e.append(h))));for(let e=0;e<a.length;e+=1){const t=a[e];let s=e;m&&(s=parseInt(t.getAttribute("data-swiper-slide-index"),10));let r=90*s,n=Math.floor(r/360);l&&(r=-r,n=Math.floor(-r/360));const d=Math.max(Math.min(t.progress,1),-1);let h=0,g=0,v=0;s%4==0?(h=4*-n*o,v=0):(s-1)%4==0?(h=0,v=4*-n*o):(s-2)%4==0?(h=o+4*n*o,v=o):(s-3)%4==0&&(h=-o,v=3*o+4*o*n),l&&(h=-h),u||(g=h,h=0);const w=`rotateX(${c(u?0:-r)}deg) rotateY(${c(u?r:0)}deg) translate3d(${h}px, ${g}px, ${v}px)`;d<=1&&d>-1&&(f=90*s+90*d,l&&(f=90*-s-90*d)),t.style.transform=w,p.slideShadows&&i(t,d,u)}if(s.style.transformOrigin=`50% 50% -${o/2}px`,s.style["-webkit-transform-origin"]=`50% 50% -${o/2}px`,p.shadow)if(u)h.style.transform=`translate3d(0px, ${r/2+p.shadowOffset}px, ${-r/2}px) rotateX(89.99deg) rotateZ(0deg) scale(${p.shadowScale})`;else{const e=Math.abs(f)-90*Math.floor(Math.abs(f)/90),t=1.5-(Math.sin(2*e*Math.PI/360)/2+Math.cos(2*e*Math.PI/360)/2),s=p.shadowScale,a=p.shadowScale/t,i=p.shadowOffset;h.style.transform=`scale3d(${s}, 1, ${a}) translate3d(0px, ${n/2+i}px, ${-n/2/a}px) rotateX(-89.99deg)`}const g=(d.isSafari||d.isWebView)&&d.needPerspectiveFix?-o/2:0;s.style.transform=`translate3d(0px,0,${g}px) rotateX(${c(t.isHorizontal()?0:f)}deg) rotateY(${c(t.isHorizontal()?-f:0)}deg)`,s.style.setProperty("--swiper-cube-translate-z",`${g}px`)},setTransition:e=>{const{el:s,slides:a}=t;if(a.forEach((t=>{t.style.transitionDuration=`${e}ms`,t.querySelectorAll(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").forEach((t=>{t.style.transitionDuration=`${e}ms`}))})),t.params.cubeEffect.shadow&&!t.isHorizontal()){const t=s.querySelector(".swiper-cube-shadow");t&&(t.style.transitionDuration=`${e}ms`)}},recreateShadows:()=>{const e=t.isHorizontal();t.slides.forEach((t=>{const s=Math.max(Math.min(t.progress,1),-1);i(t,s,e)}))},getEffectParams:()=>t.params.cubeEffect,perspective:()=>!0,overwriteParams:()=>({slidesPerView:1,slidesPerGroup:1,watchSlidesProgress:!0,resistanceRatio:0,spaceBetween:0,centeredSlides:!1,virtualTranslate:!0})})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({flipEffect:{slideShadows:!0,limitRotation:!0}});const i=(e,s)=>{let a=t.isHorizontal()?e.querySelector(".swiper-slide-shadow-left"):e.querySelector(".swiper-slide-shadow-top"),i=t.isHorizontal()?e.querySelector(".swiper-slide-shadow-right"):e.querySelector(".swiper-slide-shadow-bottom");a||(a=ge("flip",e,t.isHorizontal()?"left":"top")),i||(i=ge("flip",e,t.isHorizontal()?"right":"bottom")),a&&(a.style.opacity=Math.max(-s,0)),i&&(i.style.opacity=Math.max(s,0))};me({effect:"flip",swiper:t,on:a,setTranslate:()=>{const{slides:e,rtlTranslate:s}=t,a=t.params.flipEffect,r=M(t);for(let n=0;n<e.length;n+=1){const l=e[n];let o=l.progress;t.params.flipEffect.limitRotation&&(o=Math.max(Math.min(l.progress,1),-1));const d=l.swiperSlideOffset;let c=-180*o,p=0,u=t.params.cssMode?-d-t.translate:-d,m=0;t.isHorizontal()?s&&(c=-c):(m=u,u=0,p=-c,c=0),l.style.zIndex=-Math.abs(Math.round(o))+e.length,a.slideShadows&&i(l,o);const h=`translate3d(${u}px, ${m}px, 0px) rotateX(${r(p)}deg) rotateY(${r(c)}deg)`;he(0,l).style.transform=h}},setTransition:e=>{const s=t.slides.map((e=>h(e)));s.forEach((t=>{t.style.transitionDuration=`${e}ms`,t.querySelectorAll(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").forEach((t=>{t.style.transitionDuration=`${e}ms`}))})),fe({swiper:t,duration:e,transformElements:s})},recreateShadows:()=>{t.params.flipEffect,t.slides.forEach((e=>{let s=e.progress;t.params.flipEffect.limitRotation&&(s=Math.max(Math.min(e.progress,1),-1)),i(e,s)}))},getEffectParams:()=>t.params.flipEffect,perspective:()=>!0,overwriteParams:()=>({slidesPerView:1,slidesPerGroup:1,watchSlidesProgress:!0,spaceBetween:0,virtualTranslate:!t.params.cssMode})})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({coverflowEffect:{rotate:50,stretch:0,depth:100,scale:1,modifier:1,slideShadows:!0}}),me({effect:"coverflow",swiper:t,on:a,setTranslate:()=>{const{width:e,height:s,slides:a,slidesSizesGrid:i}=t,r=t.params.coverflowEffect,n=t.isHorizontal(),l=t.translate,o=n?e/2-l:s/2-l,d=n?r.rotate:-r.rotate,c=r.depth,p=M(t);for(let e=0,t=a.length;e<t;e+=1){const t=a[e],s=i[e],l=(o-t.swiperSlideOffset-s/2)/s,u="function"==typeof r.modifier?r.modifier(l):l*r.modifier;let m=n?d*u:0,h=n?0:d*u,f=-c*Math.abs(u),g=r.stretch;"string"==typeof g&&-1!==g.indexOf("%")&&(g=parseFloat(r.stretch)/100*s);let v=n?0:g*u,w=n?g*u:0,b=1-(1-r.scale)*Math.abs(u);Math.abs(w)<.001&&(w=0),Math.abs(v)<.001&&(v=0),Math.abs(f)<.001&&(f=0),Math.abs(m)<.001&&(m=0),Math.abs(h)<.001&&(h=0),Math.abs(b)<.001&&(b=0);const y=`translate3d(${w}px,${v}px,${f}px)  rotateX(${p(h)}deg) rotateY(${p(m)}deg) scale(${b})`;if(he(0,t).style.transform=y,t.style.zIndex=1-Math.abs(Math.round(u)),r.slideShadows){let e=n?t.querySelector(".swiper-slide-shadow-left"):t.querySelector(".swiper-slide-shadow-top"),s=n?t.querySelector(".swiper-slide-shadow-right"):t.querySelector(".swiper-slide-shadow-bottom");e||(e=ge("coverflow",t,n?"left":"top")),s||(s=ge("coverflow",t,n?"right":"bottom")),e&&(e.style.opacity=u>0?u:0),s&&(s.style.opacity=-u>0?-u:0)}}},setTransition:e=>{t.slides.map((e=>h(e))).forEach((t=>{t.style.transitionDuration=`${e}ms`,t.querySelectorAll(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").forEach((t=>{t.style.transitionDuration=`${e}ms`}))}))},perspective:()=>!0,overwriteParams:()=>({watchSlidesProgress:!0})})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({creativeEffect:{limitProgress:1,shadowPerProgress:!1,progressMultiplier:1,perspective:!0,prev:{translate:[0,0,0],rotate:[0,0,0],opacity:1,scale:1},next:{translate:[0,0,0],rotate:[0,0,0],opacity:1,scale:1}}});const i=e=>"string"==typeof e?e:`${e}px`;me({effect:"creative",swiper:t,on:a,setTranslate:()=>{const{slides:e,wrapperEl:s,slidesSizesGrid:a}=t,r=t.params.creativeEffect,{progressMultiplier:n}=r,l=t.params.centeredSlides,o=M(t);if(l){const e=a[0]/2-t.params.slidesOffsetBefore||0;s.style.transform=`translateX(calc(50% - ${e}px))`}for(let s=0;s<e.length;s+=1){const a=e[s],d=a.progress,c=Math.min(Math.max(a.progress,-r.limitProgress),r.limitProgress);let p=c;l||(p=Math.min(Math.max(a.originalProgress,-r.limitProgress),r.limitProgress));const u=a.swiperSlideOffset,m=[t.params.cssMode?-u-t.translate:-u,0,0],h=[0,0,0];let f=!1;t.isHorizontal()||(m[1]=m[0],m[0]=0);let g={translate:[0,0,0],rotate:[0,0,0],scale:1,opacity:1};c<0?(g=r.next,f=!0):c>0&&(g=r.prev,f=!0),m.forEach(((e,t)=>{m[t]=`calc(${e}px + (${i(g.translate[t])} * ${Math.abs(c*n)}))`})),h.forEach(((e,t)=>{let s=g.rotate[t]*Math.abs(c*n);h[t]=s})),a.style.zIndex=-Math.abs(Math.round(d))+e.length;const v=m.join(", "),w=`rotateX(${o(h[0])}deg) rotateY(${o(h[1])}deg) rotateZ(${o(h[2])}deg)`,b=p<0?`scale(${1+(1-g.scale)*p*n})`:`scale(${1-(1-g.scale)*p*n}
31461)`,y=p<0?1+(1-g.opacity)*p*n:1-(1-g.opacity)*p*n,E=`translate3d(${v}) ${w} ${b}`;if(f&&g.shadow||!f){let e=a.querySelector(".swiper-slide-shadow");if(!e&&g.shadow&&(e=ge("creative",a)),e){const t=r.shadowPerProgress?c*(1/r.limitProgress):c;e.style.opacity=Math.min(Math.max(Math.abs(t),0),1)}}const x=he(0,a);x.style.transform=E,x.style.opacity=y,g.origin&&(x.style.transformOrigin=g.origin)}},setTransition:e=>{const s=t.slides.map((e=>h(e)));s.forEach((t=>{t.style.transitionDuration=`${e}ms`,t.querySelectorAll(".swiper-slide-shadow").forEach((t=>{t.style.transitionDuration=`${e}ms`}))})),fe({swiper:t,duration:e,transformElements:s,allSlides:!0})},perspective:()=>t.params.creativeEffect.perspective,overwriteParams:()=>({watchSlidesProgress:!0,virtualTranslate:!t.params.cssMode})})},function(e){let{swiper:t,extendParams:s,on:a}=e;s({cardsEffect:{slideShadows:!0,rotate:!0,perSlideRotate:2,perSlideOffset:8}}),me({effect:"cards",swiper:t,on:a,setTranslate:()=>{const{slides:e,activeIndex:s,rtlTranslate:a}=t,i=t.params.cardsEffect,{startTranslate:r,isTouched:n}=t.touchEventsData,l=a?-t.translate:t.translate;for(let o=0;o<e.length;o+=1){const d=e[o],c=d.progress,p=Math.min(Math.max(c,-4),4);let u=d.swiperSlideOffset;t.params.centeredSlides&&!t.params.cssMode&&(t.wrapperEl.style.transform=`translateX(${t.minTranslate()}px)`),t.params.centeredSlides&&t.params.cssMode&&(u-=e[0].swiperSlideOffset);let m=t.params.cssMode?-u-t.translate:-u,h=0;const f=-100*Math.abs(p);let g=1,v=-i.perSlideRotate*p,w=i.perSlideOffset-.75*Math.abs(p);const b=t.virtual&&t.params.virtual.enabled?t.virtual.from+o:o,y=(b===s||b===s-1)&&p>0&&p<1&&(n||t.params.cssMode)&&l<r,E=(b===s||b===s+1)&&p<0&&p>-1&&(n||t.params.cssMode)&&l>r;if(y||E){const e=(1-Math.abs((Math.abs(p)-.5)/.5))**.5;v+=-28*p*e,g+=-.5*e,w+=96*e,h=-25*e*Math.abs(p)+"%"}if(m=p<0?`calc(${m}px ${a?"-":"+"} (${w*Math.abs(p)}%))`:p>0?`calc(${m}px ${a?"-":"+"} (-${w*Math.abs(p)}%))`:`${m}px`,!t.isHorizontal()){const e=h;h=m,m=e}const x=p<0?""+(1+(1-g)*p):""+(1-(1-g)*p),S=`\n        translate3d(${m}, ${h}, ${f}px)\n        rotateZ(${i.rotate?a?-v:v:0}deg)\n        scale(${x})\n      `;if(i.slideShadows){let e=d.querySelector(".swiper-slide-shadow");e||(e=ge("cards",d)),e&&(e.style.opacity=Math.min(Math.max((Math.abs(p)-.5)/.5,0),1))}d.style.zIndex=-Math.abs(Math.round(c))+e.length;he(0,d).style.transform=S}},setTransition:e=>{const s=t.slides.map((e=>h(e)));s.forEach((t=>{t.style.transitionDuration=`${e}ms`,t.querySelectorAll(".swiper-slide-shadow").forEach((t=>{t.style.transitionDuration=`${e}ms`}))})),fe({swiper:t,duration:e,transformElements:s})},perspective:()=>!0,overwriteParams:()=>({_loopSwapReset:!1,watchSlidesProgress:!0,loopAdditionalSlides:t.params.cardsEffect.rotate?3:2,centeredSlides:!0,virtualTranslate:!t.params.cssMode})})}];return re.use(ve),re}();
31462//# sourceMappingURL=swiper-bundle.min.js.map
31463/*
31464 * jQuery.appear
31465 * http://code.google.com/p/jquery-appear/
31466 *
31467 * Copyright (c) 2009 Michael Hixson
31468 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
31469*/
31470(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()>
31470=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 ($) {
31471	$(function () {
31472		/*----------------------------------------------------*/
31473		/* MOBILE DETECT FUNCTION
31474		/*----------------------------------------------------*/
31475		var isMobile = {
31476			Android: function () {
31477				return navigator.userAgent.match(/Android/i);
31478			},
31479			BlackBerry: function () {
31480				return navigator.userAgent.match(/BlackBerry/i);
31481			},
31482			iOS: function () {
31483				return navigator.userAgent.match(/iPhone|iPad|iPod/i);
31484			},
31485			Opera: function () {
31486				return navigator.userAgent.match(/Opera Mini/i);
31487			},
31488			Windows: function () {
31489				return navigator.userAgent.match(/IEMobile/i);
31490			},
31491			any: function () {
31492				return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
31493			}
31494		};
31495
31496    	let $sel = $('[data-unicode="mdu_TcsmjWMPYUqjLauvaMPxDg"]');
31497
31498		// 是後台環境才設定延遲載入
31499		if (window.SiteEnvironment && typeof window.SiteEnvironment.RootPath !== 'undefined') {
31500			setTimeout(appearModel,50);
31501		} else {
31502			appearModel();
31503		}
31504
31505		/*----------------------------------------------------*/
31506		// Appear
31507		/*----------------------------------------------------*/
31508		function appearModel(){
31509			$sel.appear(function() {
31510			
31511				$(this).each (function () {
31512					let $id = base62();
31513					let $self = $(this);
31514					let $obj = $self.children('.swiper');
31515					let opt = $obj.data();
31516					$obj.attr('id',$id).addClass($id);
31517
31518					let $objID = '#'+$id;
31519
31520					if(opt.paginationType=='no-pagination') {
31521						$sel.find('.swiper-pagination').hide();
31522					}
31523					if(opt.scrollBar!='.swiper-scrollbar') {
31524						$sel.find('.swiper-scrollbar').hide();
31525					}
31526
31527					let swiper = new Swiper($objID, {
31528						centeredSlides: opt.centeredSlides,
31529						autoplay: opt.autoplay ? { delay: opt.autoplay, disableOnInteraction: true } : false,
31530						speed: opt.speed,
31531						freeMode: opt.freeMode,
31532						slidesPerView: opt.lView,
31533						watchSlidesVisibility: true,
31534						spaceBetween: opt.lMargin,
31535						breakpoints: {
31536							320: { slidesPerView: opt.xsView, spaceBetween: opt.xsMargin },
31537							640: { slidesPerView: opt.sView, spaceBetween: opt.sMargin },
31538							768: { slidesPerView: opt.mView, spaceBetween: opt.mMargin },
31539							1024: { slidesPerView: opt.lView, spaceBetween: opt.lMargin }
31540						},
31541						loop: opt.loop,
31542						scrollbar: opt.scrollBar ? { el: opt.scrollBar, draggable: true } : false,
31543						pagination: (opt.paginationType && opt.paginationType !== 'no-paginatio') ? {
31544						  el: '.' + opt.paginationType,
31545						  clickable: true,
31546						  type: opt.paginationType
31547						} : false,
31548						navigation: {
31549						  nextEl: '.swiper-button-next',
31550						  prevEl: '.swiper-button-prev',
31551						},
31552						grabCursor: true,
31553						observer: true,
31554					});
31555
31556					swiper.updateFixedWidth = function () {
31557						const $el = swiper.el;
31558						const $module = $($el).closest('[data-unicode="mdu_TcsmjWMPYUqjLauvaMPxDg"]');
31559						$module.hide();
31560						if (isMobile.iOS() == null) { // iPhone 會有畫面跳動
31561						  $el.style.maxWidth = $module.closest('.main').css('width');
31562						}
31563						$module.show();
31564					};
31565		  
31566					// 初始化呼叫
31567					swiper.updateFixedWidth();
31568		  
31569					// Swiper 初始化事件
31570					swiper.on('beforeInit', () => {
31571						swiper.updateFixedWidth();
31572					});
31573
31574					// widget-item resize 事件
31575					const DataKey = 'swiper.widget-item.resize';
31576					$(swiper.el).each(function () {
31577						const data = $(this).data(DataKey);
31578						if (!data) {
31579							$(this).closest('.widget-item')
31580							.on('wdg.resizable.resize', { swiper: swiper }, function (event) {
31581								event.data.swiper.updateFixedWidth();
31582								event.data.swiper.emit('resize');
31583								event.data.swiper.emit('orientationchange');
31584							});
31585		  
31586							$(this).closest('[data-rel="PagePreviewPanel"]')
31587							.on('device.changed', { swiper: swiper }, function (event, device) {
31588								switch (device) {
31589									case 'tablet': window.innerWidth = 995; break;
31590									case 'mobile': window.innerWidth = 376; break;
31591									default: window.innerWidth = ''; break;
31592								}
31593								event.data.swiper.updateFixedWidth();
31594								event.data.swiper.emit('resize');
31595								event.data.swiper.emit('orientationchange');
31596							});
31597		  
31598							$(this).data(DataKey, true);
31599						}
31600					});
31601		  
31602					// window resize 事件
31603					if (!$(swiper).data('swiper.resize')) {
31604						window.addEventListener('resize', (function () {
31605							this.updateFixedWidth();
31606							this.emit('resize');
31607							this.emit('orientationchange');
31608						}).bind(swiper));
31609						$(swiper).data('swiper.resize', true);
31610					}
31611				});
31612			});
31613		}
31614    });
31615}(jQuery);
31616
31617; })(jQuery);/* compress error:[4]function encode(int) {*/
31618
31619/* MODULE 9a9911e7-6ea1-4e2f-bf89-a3d5b054cafd, Version: 2.0.2 */
31620;(function($) {; var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
31621
31622// NB: does not validate input
31623function encode(int) {
31624    if (int === 0) {
31625        return CHARSET[0];
31626    }
31627
31628    var res = "";
31629    while (int > 0) {
31630        res = CHARSET[int % 62] + res;
31631        int = Math.floor(int / 62);
31632    }
31633    return res;
31634};
31635
31636function decode(str) {
31637    var res = 0,
31638        length = str.length,
31639        i, char;
31640    for (i = 0; i < length; i++) {
31641        char = str.charCodeAt(i);
31642        if (char < 58) { // 0-9
31643            char = char - 48;
31644        } else if (char < 91) { // A-Z
31645            char = char - 29;
31646        } else { // a-z
31647            char = char - 87;
31648        }
31649        res += char * Math.pow(62, length - i - 1);
31650    }
31651    return res;
31652};
31653
31654function base62() {
31655    var id; //base62
31656    do {
31657      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
31658    } while (id.match(/^[0-9]/i) !== null);
31659    return id;
31660}if (typeof jQuery === 'undefined') {
31661    throw new Error('More Button\'s JavaScript requires jQuery')
31662}
31663
31664+function ($) {
31665    'use strict';
31666    var version = $.fn.jquery.split(' ')[0].split('.')
31667    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
31668        throw new Error('More Button\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
31669    }
31670}(jQuery);
31671
31672+function ($) {
31673    'use strict';
31674
31675    var DATA_KEY = 'widget.moreButton',
31676        OPTS = {
31677			defaultShow: 9, // 一開始顯示的數量
31678			elementSel: '[data-rel="moreButton"]',
31679			itemSel: '.item-box',
31680			moreSel: '.more.btn'
31681        };
31682
31683    function MoreButton(element, opts) {
31684
31685        var self = this;
31686        this._element = element;
31687		this._opts = $.extend(OPTS, $(this._element).data(), opts);
31688		
31689		var $items =  $(this._opts.itemSel, this._element);
31690		// 顯示或隱藏 btn
31691		($items.length > this._opts.defaultShow) ? $(this._opts.moreSel, this._element).show() : $(this._opts.moreSel, this._element).hide();
31692		// 超過一開始顯示的數量的項目隱藏
31693		$items.slice(this._opts.defaultShow).hide();
31694		// 點擊更多按鈕
31695		$(this._element).on('click', this._opts.moreSel, { $items: $items }, function(event) {
31696			event.preventDefault()
31697			event.data.$items.filter(":hidden").slideDown();
31698			$(this).hide();
31699		});
31700    }
31701
31702    var _proto = MoreButton.prototype;
31703
31704    if(typeof $.fn.moreButton !== "function") {
31705        $.fn.moreButton = function() {
31706            return this.each(function() {
31707                if (!$(this).data(DATA_KEY))
31708                    $(this).data(DATA_KEY, new MoreButton(this, {}));
31709            });
31710        };
31711    }
31712    
31713    $(function () {
31714        // do something onload...
31715        $(OPTS.elementSel).moreButton();
31716	})
31717
31718}(jQuery);(function($) {
31719    $(function() {
31720
31721	    let $sel = $('[data-unicode="mdu_Qy5nPjTr5kCOzXiq5Taq0A"]');
31722	    $sel.each (function () {
31723	    	let $id = base62();
31724	    	let $self = $(this).attr('id',$id);
31725	    	var lazyLoadInstance = new LazyLoad({
31726	    	elements_selector: '#'+$id+' .lazyload',
31727	    	callback_loaded: function() {
31728		        	$self.moreButton({
31729						// defaultShow: 9,          // 預設顯示數量, 可以在html屬性指定 data-default-show="6"
31730						// itemSel: '.item-box',    // 項目選擇器, 可以在html屬性指定 data-item-sel=".item-box"
31731						// moreSel: '.more.btn'     // 更多按鈕, 可以在html屬性指定 data-more-sel=".more.btn"
31732			        });
31733	    		}
31734	    	});
31735	    });
31736
31737  	});
31738})(jQuery);
31739
31740; })(jQuery);/* compress error:[4]function encode(int) {*/
31741
31742/* MODULE 5ebb02cf-e34c-4ba0-806b-3fd72571ee0e, Version: 1.9.6 */
31743;(function($) {; var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
31744
31745// NB: does not validate input
31746function encode(int) {
31747    if (int === 0) {
31748        return CHARSET[0];
31749    }
31750
31751    var res = "";
31752    while (int > 0) {
31753        res = CHARSET[int % 62] + res;
31754        int = Math.floor(int / 62);
31755    }
31756    return res;
31757};
31758
31759function decode(str) {
31760    var res = 0,
31761        length = str.length,
31762        i, char;
31763    for (i = 0; i < length; i++) {
31764        char = str.charCodeAt(i);
31765        if (char < 58) { // 0-9
31766            char = char - 48;
31767        } else if (char < 91) { // A-Z
31768            char = char - 29;
31769        } else { // a-z
31770            char = char - 87;
31771        }
31772        res += char * Math.pow(62, length - i - 1);
31773    }
31774    return res;
31775};
31776
31777function base62() {
31778    var id; //base62
31779    do {
31780      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
31781    } while (id.match(/^[0-9]/i) !== null);
31782    return id;
31783}(function($) {
31784    $(function() {
31785        let $sel = $('[data-unicode="mdu_tza70pfvE02kcR2VE5D6mQ"]');
31786        $sel.each (function () {
31787            let $id = base62();
31788            let $self = $(this).attr('id',$id);
31789            let $dataHover = $self.find('.link-list').data('hover');
31790            let $dataRecovery = $self.find('.link-list').data('recovery');
31791            $self.find('.hover-color').hover(function () {
31792                if($dataHover)
31793                    $(this).css('color', $dataHover);
31794            }, function () {
31795                if($dataRecovery)
31796                    $(this).css('color', $dataRecovery);
31797                else
31798                    $(this).css('color', '');
31799            })
31800        });
31801
31802    });
31803})(jQuery);
31804; })(jQuery);/* compress error:[4]function encode(int) {*/
31805

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.