;(function($) {var _proto = String.prototype;

if (typeof _proto.regxMatch !== 'function') {
    _proto.regxMatch = function regxMatch() {
        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
            regxStr = (typeof this === "string" || this instanceof String) ? this : "";
        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
            return x.trim();
        }).join(' ');
    }
}/**
 * 已經改變了整個 scrollPosStyler 的內核，請勿覆蓋
 * ======================================================================== */

/**
 * @license
 * ========================================================================
 * ScrollPos-Styler v0.7.1
 * https://github.com/acch/scrollpos-styler
 * ========================================================================
 * Copyright 2015 Achim Christ
 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
 * ======================================================================== */

// JSHint directives
/* exported ScrollPosStyler */
if (typeof window.ScrollOverSelfStyler === "undefined") {
    var ScrollOverSelfStyler = (function (document, window, $) {
        "use strict";

        /* ====================
         * private variables
         * ==================== */
        var scrollPosY = 0,
            busy = false,

            // toggle style / class when scrolling below this position (in px)
            scrollOffsetY = 1,

            // class used to apply scrollPosStyler to
            spsClass = "soss",

            // choose elements to apply style / class to
            elements = document.getElementsByClassName(spsClass),

            // style / class to apply to elements when above scroll position
            classAbove = "soss--abv",

            // style / class to apply to elements when below scroll position
            classBelow = "soss--blw",

            // tag to set custom scroll offset per element
            offsetTag = "data-soss-offset";

        
        var BlockSel = '.block-item',
            ShadowKey = "ScrollOverSelfStyler";

        /* ====================
         * private function to check scroll position
         * ==================== */
        function onScroll() {

            // ensure that events don't stack
            if (!busy) {

                // find elements to update
                var elementsToUpdate = getElementsToUpdate(false);
                if (elementsToUpdate.length > 0) {

                    // suspend accepting scroll events
                    busy = true;

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                }
            }
        }

        /* ====================
         * copy Element Shadow
         * ==================== */
        function copyElementShadow(init) {
            for (var i = 0; elements[i]; ++i) {
                var element = elements[i];
                if (!$(element).data(ShadowKey)) {
                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
                }
            }
        }

        /* ====================
         * private function to find elements to update
         * ==================== */
        function getElementsToUpdate(init) {
            var elementsToUpdate = [];
            copyElementShadow(init);

            // get current scroll position from window
            scrollPosY = window.pageYOffset;

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elements[i]; ++i) { // chrome workaround
                var element = elements[i],
                    $shadow = $(element).data(ShadowKey);

                // get offset from element, default to global option
                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
                    shScrollOffsetY = $shadow.offset().top;

                // check current state of element
                var elOnTop = element.classList.contains(classAbove);

                // check current is visible
                var elVisible = $(element).closest(BlockSel).is(':visible');

                // cols regx
                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));

                // if we were above, and are now below scroll position...
                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
                    
                    element.style.top = offsetTop + "px";
                    $shadow.css('height', $(element).css('height'));

                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classBelow + " " + regxMatchCol,
                        removeClass: classAbove
                    });

                    // if we were below, and are now above scroll position...
                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {


                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classAbove,
                        removeClass: classBelow + " " + regxMatchCol
                    });

                    $shadow.get(0).style.height = null;
                    element.style.top = null;
                }
            }

            return elementsToUpdate;
        }

        /* ====================
         * private function to update elements
         * ==================== */
        function updateElements(elementsToUpdate) {

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
                var map = elementsToUpdate[i];

                // add style / class to element
                //map.element.classList.add(map.addClass);
                //map.element.classList.remove(map.removeClass);
                $(map.element).addClass(map.addClass);
                $(map.element).removeClass(map.removeClass);
            }

            // resume accepting scroll events
            busy = false;
        }

        /* ====================
         * public function to initially style elements based on scroll position
         *
         * options:
         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
         *
         * ==================== */
        var pub = {
            init: function (options) {

                // suspend accepting scroll events
                busy = true;

                // merge options object with global options
                if (options) {
                    if (options.spsClass) {
                        spsClass = options.spsClass;
                        elements = document.getElementsByClassName(spsClass);
                    }
                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
                    classAbove = options.classAbove || classAbove;
                    classBelow = options.classBelow || classBelow;
                    offsetTag = options.offsetTag || offsetTag;
                }

                // ensure all elements have classAbove
                var elementsToUpdate = getElementsToUpdate(true);
                if (elementsToUpdate.length > 0) {

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                } else {

                    // resume accepting scroll events
                    busy = false;
                }
            }
        };

        // register for window scroll events
        $(window).on("scroll", onScroll);

        window.ScrollOverSelfStyler = pub;

        return pub;
    })(document, window, jQuery);
}

/* ====================
 * main initialization
 * ==================== */
$(function () {
    // defer initialization to allow browser to restore scroll position
    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
});if (typeof jQuery === 'undefined') {
    throw new Error('Block\'s JavaScript requires jQuery')
}

+function ($) {
    'use strict';
    var version = $.fn.jquery.split(' ')[0].split('.')
    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
    }
}(jQuery);


+function ($, win) {
    'use strict';

    var DataKey = 'blktabs',
        BlockSel = '.block-item',
        TabSel = '> .module-container .blk-tabs > ul',
        BtnSel = '> li',
        ValSel = ' > a[href^="#blk"]',
        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
        DestroyBeforeSymbol = 'destroyBeforeSymbol',
        Event = {
            ReplacedBefore: 'renderview.replace.before',
            ReplacedAfter: 'renderview.replace.after',
            BlockDestroy: 'destroy',
            BlockAppear: DataKey + '.block.appear',
            BlockHidden: DataKey + '.block.hidden',
            Click: {
                Window: 'blk-nav-in',
                Before: DataKey + '.tabs.click.before',
                After: DataKey + '.tabs.click.after'
            }
        },
        Options = {
            focus: 'active'
        };

    function BlockTabs(element, opts) {

        var self = this;
        this._opts = $.extend(Options, $(element).data(), opts);
        this._element = element;
        this._tabs = $(TabSel, element).get(0);

        // block 更新屬性值之後將會被置換
        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
            $(this).addClass(ReplacedBeforeSymbol);
            event.data.blktabs.resetTabStatus();
            $(this).removeClass(ReplacedBeforeSymbol);
            $.removeData(this, DataKey);
        });

        // block 被刪除前復原 tab 關聯的 block
        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
            $(this).addClass(DestroyBeforeSymbol);
            event.data.blktabs.resetTabStatus();
        });

        // block tabs click 事件
        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
            if ($(element).attr('href').startsWith('#')) {
                event.preventDefault();
                event.data.blktabs.tabClick(element);
                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
                    target: element,
                    detail: {
                        selector: $(element).attr('href')
                    }
                }));
            }
        });

        this.tabAppear().resetMyStatus();

        var bookmarkId = window.location.href.split('#').pop();
        if (this._element.id == bookmarkId) {
            // 錨點跳轉
            var blk = this;
            window.addEventListener("load", function (event) {

                var arrParentAndButton = function (blkId) {
                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
                    var pblk = tab.closest(BlockSel);
                    if (pblk.length > 0 && pblk.attr('id')) {
                        // 記錄&尋找
                        var r = arrParentAndButton(pblk.attr('id'));
                        r.push([pblk, tab]);
                        return r;
                    }
                    return [];
                };
                var arr = arrParentAndButton(blk._element.id);
                for (var i in arr)
                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));

                setTimeout(function () {
                    $("html, body").animate({
                        scrollTop: $(blk._element).offset().top
                    }, 500, 'swing', function () { });
                }, 0.5 * 1000);
            });
        }
    }

    var _proto = BlockTabs.prototype;

    _proto.tabAppear = function tabAppear() {
        if ($(BtnSel, this._tabs).length > 0)
            $(this._tabs).removeClass('d-none hide');
        return this;
    }


    // 取得 block tabs 所有關聯的 block target
    _proto.getTabSelector = function getTabSelector() {
        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
            return $(o).attr('href');
        }).get().join(',');
    }

    // 驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetTabStatus = function resetTabStatus(event) {
        $(this.getTabSelector()).each(function () {
            if ($(this).data(DataKey))
                $(this).data(DataKey).resetMyStatus();
        });
        return this;
    }

    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetMyStatus = function resetMyStatus() {
        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a

        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
            // 顯示 element
            this._element.style.setProperty('display', '');

            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
            if ($tabLink.length < 1)
                $tabLink = $(BtnSel + ValSel, this._tabs);
            this.tabClick($tabLink.get(0));
            $(this._element).trigger(Event.BlockAppear);
        }
        else {
            // 隱藏 element
            this._element.style.setProperty('display', 'none', 'important');
            $(this._element).trigger(Event.BlockHidden);
        }

        return this.resetTabStatus();
    }

    // 點擊 block tabs
    _proto.tabClick = function tabClick(currentBtn, closure) {

        // 點擊執行內容
        if ($.contains(this._element, currentBtn)) {

            // tab 切換前
            $(this._element).trigger(Event.Click.Before, [currentBtn]);

            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
            $(currentBtn).addClass(Options.focus);

            this.resetTabStatus();

            // tab 切換後
            $(this._element).trigger(Event.Click.After, [currentBtn]);

            if (typeof (closure) === "function")
                closure();
        }

        return this;
    }

    if (typeof $.fn.blockTab !== 'function') {

        $.fn.extend({
            blockTab: function (options) {
                this.filter(function (i, o) {
                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
                }).each(function (event) {
                    $(this).data(DataKey, new BlockTabs(this, options));
                });
            }
        });
    }

    $(function () {
        $(BlockSel).blockTab();
    });

}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
;(function($) {var _proto = String.prototype;

if (typeof _proto.regxMatch !== 'function') {
    _proto.regxMatch = function regxMatch() {
        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
            regxStr = (typeof this === "string" || this instanceof String) ? this : "";
        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
            return x.trim();
        }).join(' ');
    }
}/**
 * 已經改變了整個 scrollPosStyler 的內核，請勿覆蓋
 * ======================================================================== */

/**
 * @license
 * ========================================================================
 * ScrollPos-Styler v0.7.1
 * https://github.com/acch/scrollpos-styler
 * ========================================================================
 * Copyright 2015 Achim Christ
 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
 * ======================================================================== */

// JSHint directives
/* exported ScrollPosStyler */
if (typeof window.ScrollOverSelfStyler === "undefined") {
    var ScrollOverSelfStyler = (function (document, window, $) {
        "use strict";

        /* ====================
         * private variables
         * ==================== */
        var scrollPosY = 0,
            busy = false,

            // toggle style / class when scrolling below this position (in px)
            scrollOffsetY = 1,

            // class used to apply scrollPosStyler to
            spsClass = "soss",

            // choose elements to apply style / class to
            elements = document.getElementsByClassName(spsClass),

            // style / class to apply to elements when above scroll position
            classAbove = "soss--abv",

            // style / class to apply to elements when below scroll position
            classBelow = "soss--blw",

            // tag to set custom scroll offset per element
            offsetTag = "data-soss-offset";

        
        var BlockSel = '.block-item',
            ShadowKey = "ScrollOverSelfStyler";

        /* ====================
         * private function to check scroll position
         * ==================== */
        function onScroll() {

            // ensure that events don't stack
            if (!busy) {

                // find elements to update
                var elementsToUpdate = getElementsToUpdate(false);
                if (elementsToUpdate.length > 0) {

                    // suspend accepting scroll events
                    busy = true;

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                }
            }
        }

        /* ====================
         * copy Element Shadow
         * ==================== */
        function copyElementShadow(init) {
            for (var i = 0; elements[i]; ++i) {
                var element = elements[i];
                if (!$(element).data(ShadowKey)) {
                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
                }
            }
        }

        /* ====================
         * private function to find elements to update
         * ==================== */
        function getElementsToUpdate(init) {
            var elementsToUpdate = [];
            copyElementShadow(init);

            // get current scroll position from window
            scrollPosY = window.pageYOffset;

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elements[i]; ++i) { // chrome workaround
                var element = elements[i],
                    $shadow = $(element).data(ShadowKey);

                // get offset from element, default to global option
                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
                    shScrollOffsetY = $shadow.offset().top;

                // check current state of element
                var elOnTop = element.classList.contains(classAbove);

                // check current is visible
                var elVisible = $(element).closest(BlockSel).is(':visible');

                // cols regx
                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));

                // if we were above, and are now below scroll position...
                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
                    
                    element.style.top = offsetTop + "px";
                    $shadow.css('height', $(element).css('height'));

                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classBelow + " " + regxMatchCol,
                        removeClass: classAbove
                    });

                    // if we were below, and are now above scroll position...
                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {


                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classAbove,
                        removeClass: classBelow + " " + regxMatchCol
                    });

                    $shadow.get(0).style.height = null;
                    element.style.top = null;
                }
            }

            return elementsToUpdate;
        }

        /* ====================
         * private function to update elements
         * ==================== */
        function updateElements(elementsToUpdate) {

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
                var map = elementsToUpdate[i];

                // add style / class to element
                //map.element.classList.add(map.addClass);
                //map.element.classList.remove(map.removeClass);
                $(map.element).addClass(map.addClass);
                $(map.element).removeClass(map.removeClass);
            }

            // resume accepting scroll events
            busy = false;
        }

        /* ====================
         * public function to initially style elements based on scroll position
         *
         * options:
         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
         *
         * ==================== */
        var pub = {
            init: function (options) {

                // suspend accepting scroll events
                busy = true;

                // merge options object with global options
                if (options) {
                    if (options.spsClass) {
                        spsClass = options.spsClass;
                        elements = document.getElementsByClassName(spsClass);
                    }
                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
                    classAbove = options.classAbove || classAbove;
                    classBelow = options.classBelow || classBelow;
                    offsetTag = options.offsetTag || offsetTag;
                }

                // ensure all elements have classAbove
                var elementsToUpdate = getElementsToUpdate(true);
                if (elementsToUpdate.length > 0) {

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                } else {

                    // resume accepting scroll events
                    busy = false;
                }
            }
        };

        // register for window scroll events
        $(window).on("scroll", onScroll);

        window.ScrollOverSelfStyler = pub;

        return pub;
    })(document, window, jQuery);
}

/* ====================
 * main initialization
 * ==================== */
$(function () {
    // defer initialization to allow browser to restore scroll position
    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
});if (typeof jQuery === 'undefined') {
    throw new Error('Block\'s JavaScript requires jQuery')
}

+function ($) {
    'use strict';
    var version = $.fn.jquery.split(' ')[0].split('.')
    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
    }
}(jQuery);


+function ($, win) {
    'use strict';

    var DataKey = 'blktabs',
        BlockSel = '.block-item',
        TabSel = '> .module-container .blk-tabs > ul',
        BtnSel = '> li',
        ValSel = ' > a[href^="#blk"]',
        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
        DestroyBeforeSymbol = 'destroyBeforeSymbol',
        Event = {
            ReplacedBefore: 'renderview.replace.before',
            ReplacedAfter: 'renderview.replace.after',
            BlockDestroy: 'destroy',
            BlockAppear: DataKey + '.block.appear',
            BlockHidden: DataKey + '.block.hidden',
            Click: {
                Window: 'blk-nav-in',
                Before: DataKey + '.tabs.click.before',
                After: DataKey + '.tabs.click.after'
            }
        },
        Options = {
            focus: 'active'
        };

    function BlockTabs(element, opts) {

        var self = this;
        this._opts = $.extend(Options, $(element).data(), opts);
        this._element = element;
        this._tabs = $(TabSel, element).get(0);

        // block 更新屬性值之後將會被置換
        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
            $(this).addClass(ReplacedBeforeSymbol);
            event.data.blktabs.resetTabStatus();
            $(this).removeClass(ReplacedBeforeSymbol);
            $.removeData(this, DataKey);
        });

        // block 被刪除前復原 tab 關聯的 block
        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
            $(this).addClass(DestroyBeforeSymbol);
            event.data.blktabs.resetTabStatus();
        });

        // block tabs click 事件
        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
            if ($(element).attr('href').startsWith('#')) {
                event.preventDefault();
                event.data.blktabs.tabClick(element);
                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
                    target: element,
                    detail: {
                        selector: $(element).attr('href')
                    }
                }));
            }
        });

        this.tabAppear().resetMyStatus();

        var bookmarkId = window.location.href.split('#').pop();
        if (this._element.id == bookmarkId) {
            // 錨點跳轉
            var blk = this;
            window.addEventListener("load", function (event) {

                var arrParentAndButton = function (blkId) {
                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
                    var pblk = tab.closest(BlockSel);
                    if (pblk.length > 0 && pblk.attr('id')) {
                        // 記錄&尋找
                        var r = arrParentAndButton(pblk.attr('id'));
                        r.push([pblk, tab]);
                        return r;
                    }
                    return [];
                };
                var arr = arrParentAndButton(blk._element.id);
                for (var i in arr)
                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));

                setTimeout(function () {
                    $("html, body").animate({
                        scrollTop: $(blk._element).offset().top
                    }, 500, 'swing', function () { });
                }, 0.5 * 1000);
            });
        }
    }

    var _proto = BlockTabs.prototype;

    _proto.tabAppear = function tabAppear() {
        if ($(BtnSel, this._tabs).length > 0)
            $(this._tabs).removeClass('d-none hide');
        return this;
    }


    // 取得 block tabs 所有關聯的 block target
    _proto.getTabSelector = function getTabSelector() {
        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
            return $(o).attr('href');
        }).get().join(',');
    }

    // 驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetTabStatus = function resetTabStatus(event) {
        $(this.getTabSelector()).each(function () {
            if ($(this).data(DataKey))
                $(this).data(DataKey).resetMyStatus();
        });
        return this;
    }

    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetMyStatus = function resetMyStatus() {
        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a

        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
            // 顯示 element
            this._element.style.setProperty('display', '');

            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
            if ($tabLink.length < 1)
                $tabLink = $(BtnSel + ValSel, this._tabs);
            this.tabClick($tabLink.get(0));
            $(this._element).trigger(Event.BlockAppear);
        }
        else {
            // 隱藏 element
            this._element.style.setProperty('display', 'none', 'important');
            $(this._element).trigger(Event.BlockHidden);
        }

        return this.resetTabStatus();
    }

    // 點擊 block tabs
    _proto.tabClick = function tabClick(currentBtn, closure) {

        // 點擊執行內容
        if ($.contains(this._element, currentBtn)) {

            // tab 切換前
            $(this._element).trigger(Event.Click.Before, [currentBtn]);

            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
            $(currentBtn).addClass(Options.focus);

            this.resetTabStatus();

            // tab 切換後
            $(this._element).trigger(Event.Click.After, [currentBtn]);

            if (typeof (closure) === "function")
                closure();
        }

        return this;
    }

    if (typeof $.fn.blockTab !== 'function') {

        $.fn.extend({
            blockTab: function (options) {
                this.filter(function (i, o) {
                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
                }).each(function (event) {
                    $(this).data(DataKey, new BlockTabs(this, options));
                });
            }
        });
    }

    $(function () {
        $(BlockSel).blockTab();
    });

}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
;(function($) {var _proto = String.prototype;

if (typeof _proto.regxMatch !== 'function') {
    _proto.regxMatch = function regxMatch() {
        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
            regxStr = (typeof this === "string" || this instanceof String) ? this : "";
        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
            return x.trim();
        }).join(' ');
    }
}/**
 * 已經改變了整個 scrollPosStyler 的內核，請勿覆蓋
 * ======================================================================== */

/**
 * @license
 * ========================================================================
 * ScrollPos-Styler v0.7.1
 * https://github.com/acch/scrollpos-styler
 * ========================================================================
 * Copyright 2015 Achim Christ
 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
 * ======================================================================== */

// JSHint directives
/* exported ScrollPosStyler */
if (typeof window.ScrollOverSelfStyler === "undefined") {
    var ScrollOverSelfStyler = (function (document, window, $) {
        "use strict";

        /* ====================
         * private variables
         * ==================== */
        var scrollPosY = 0,
            busy = false,

            // toggle style / class when scrolling below this position (in px)
            scrollOffsetY = 1,

            // class used to apply scrollPosStyler to
            spsClass = "soss",

            // choose elements to apply style / class to
            elements = document.getElementsByClassName(spsClass),

            // style / class to apply to elements when above scroll position
            classAbove = "soss--abv",

            // style / class to apply to elements when below scroll position
            classBelow = "soss--blw",

            // tag to set custom scroll offset per element
            offsetTag = "data-soss-offset";

        
        var BlockSel = '.block-item',
            ShadowKey = "ScrollOverSelfStyler";

        /* ====================
         * private function to check scroll position
         * ==================== */
        function onScroll() {

            // ensure that events don't stack
            if (!busy) {

                // find elements to update
                var elementsToUpdate = getElementsToUpdate(false);
                if (elementsToUpdate.length > 0) {

                    // suspend accepting scroll events
                    busy = true;

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                }
            }
        }

        /* ====================
         * copy Element Shadow
         * ==================== */
        function copyElementShadow(init) {
            for (var i = 0; elements[i]; ++i) {
                var element = elements[i];
                if (!$(element).data(ShadowKey)) {
                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
                }
            }
        }

        /* ====================
         * private function to find elements to update
         * ==================== */
        function getElementsToUpdate(init) {
            var elementsToUpdate = [];
            copyElementShadow(init);

            // get current scroll position from window
            scrollPosY = window.pageYOffset;

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elements[i]; ++i) { // chrome workaround
                var element = elements[i],
                    $shadow = $(element).data(ShadowKey);

                // get offset from element, default to global option
                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
                    shScrollOffsetY = $shadow.offset().top;

                // check current state of element
                var elOnTop = element.classList.contains(classAbove);

                // check current is visible
                var elVisible = $(element).closest(BlockSel).is(':visible');

                // cols regx
                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));

                // if we were above, and are now below scroll position...
                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
                    
                    element.style.top = offsetTop + "px";
                    $shadow.css('height', $(element).css('height'));

                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classBelow + " " + regxMatchCol,
                        removeClass: classAbove
                    });

                    // if we were below, and are now above scroll position...
                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {


                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classAbove,
                        removeClass: classBelow + " " + regxMatchCol
                    });

                    $shadow.get(0).style.height = null;
                    element.style.top = null;
                }
            }

            return elementsToUpdate;
        }

        /* ====================
         * private function to update elements
         * ==================== */
        function updateElements(elementsToUpdate) {

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
                var map = elementsToUpdate[i];

                // add style / class to element
                //map.element.classList.add(map.addClass);
                //map.element.classList.remove(map.removeClass);
                $(map.element).addClass(map.addClass);
                $(map.element).removeClass(map.removeClass);
            }

            // resume accepting scroll events
            busy = false;
        }

        /* ====================
         * public function to initially style elements based on scroll position
         *
         * options:
         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
         *
         * ==================== */
        var pub = {
            init: function (options) {

                // suspend accepting scroll events
                busy = true;

                // merge options object with global options
                if (options) {
                    if (options.spsClass) {
                        spsClass = options.spsClass;
                        elements = document.getElementsByClassName(spsClass);
                    }
                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
                    classAbove = options.classAbove || classAbove;
                    classBelow = options.classBelow || classBelow;
                    offsetTag = options.offsetTag || offsetTag;
                }

                // ensure all elements have classAbove
                var elementsToUpdate = getElementsToUpdate(true);
                if (elementsToUpdate.length > 0) {

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                } else {

                    // resume accepting scroll events
                    busy = false;
                }
            }
        };

        // register for window scroll events
        $(window).on("scroll", onScroll);

        window.ScrollOverSelfStyler = pub;

        return pub;
    })(document, window, jQuery);
}

/* ====================
 * main initialization
 * ==================== */
$(function () {
    // defer initialization to allow browser to restore scroll position
    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
});if (typeof jQuery === 'undefined') {
    throw new Error('Block\'s JavaScript requires jQuery')
}

+function ($) {
    'use strict';
    var version = $.fn.jquery.split(' ')[0].split('.')
    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
    }
}(jQuery);


+function ($, win) {
    'use strict';

    var DataKey = 'blktabs',
        BlockSel = '.block-item',
        TabSel = '> .module-container .blk-tabs > ul',
        BtnSel = '> li',
        ValSel = ' > a[href^="#blk"]',
        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
        DestroyBeforeSymbol = 'destroyBeforeSymbol',
        Event = {
            ReplacedBefore: 'renderview.replace.before',
            ReplacedAfter: 'renderview.replace.after',
            BlockDestroy: 'destroy',
            BlockAppear: DataKey + '.block.appear',
            BlockHidden: DataKey + '.block.hidden',
            Click: {
                Window: 'blk-nav-in',
                Before: DataKey + '.tabs.click.before',
                After: DataKey + '.tabs.click.after'
            }
        },
        Options = {
            focus: 'active'
        };

    function BlockTabs(element, opts) {

        var self = this;
        this._opts = $.extend(Options, $(element).data(), opts);
        this._element = element;
        this._tabs = $(TabSel, element).get(0);

        // block 更新屬性值之後將會被置換
        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
            $(this).addClass(ReplacedBeforeSymbol);
            event.data.blktabs.resetTabStatus();
            $(this).removeClass(ReplacedBeforeSymbol);
            $.removeData(this, DataKey);
        });

        // block 被刪除前復原 tab 關聯的 block
        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
            $(this).addClass(DestroyBeforeSymbol);
            event.data.blktabs.resetTabStatus();
        });

        // block tabs click 事件
        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
            if ($(element).attr('href').startsWith('#')) {
                event.preventDefault();
                event.data.blktabs.tabClick(element);
                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
                    target: element,
                    detail: {
                        selector: $(element).attr('href')
                    }
                }));
            }
        });

        this.tabAppear().resetMyStatus();

        var bookmarkId = window.location.href.split('#').pop();
        if (this._element.id == bookmarkId) {
            // 錨點跳轉
            var blk = this;
            window.addEventListener("load", function (event) {

                var arrParentAndButton = function (blkId) {
                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
                    var pblk = tab.closest(BlockSel);
                    if (pblk.length > 0 && pblk.attr('id')) {
                        // 記錄&尋找
                        var r = arrParentAndButton(pblk.attr('id'));
                        r.push([pblk, tab]);
                        return r;
                    }
                    return [];
                };
                var arr = arrParentAndButton(blk._element.id);
                for (var i in arr)
                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));

                setTimeout(function () {
                    $("html, body").animate({
                        scrollTop: $(blk._element).offset().top
                    }, 500, 'swing', function () { });
                }, 0.5 * 1000);
            });
        }
    }

    var _proto = BlockTabs.prototype;

    _proto.tabAppear = function tabAppear() {
        if ($(BtnSel, this._tabs).length > 0)
            $(this._tabs).removeClass('d-none hide');
        return this;
    }


    // 取得 block tabs 所有關聯的 block target
    _proto.getTabSelector = function getTabSelector() {
        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
            return $(o).attr('href');
        }).get().join(',');
    }

    // 驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetTabStatus = function resetTabStatus(event) {
        $(this.getTabSelector()).each(function () {
            if ($(this).data(DataKey))
                $(this).data(DataKey).resetMyStatus();
        });
        return this;
    }

    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetMyStatus = function resetMyStatus() {
        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a

        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
            // 顯示 element
            this._element.style.setProperty('display', '');

            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
            if ($tabLink.length < 1)
                $tabLink = $(BtnSel + ValSel, this._tabs);
            this.tabClick($tabLink.get(0));
            $(this._element).trigger(Event.BlockAppear);
        }
        else {
            // 隱藏 element
            this._element.style.setProperty('display', 'none', 'important');
            $(this._element).trigger(Event.BlockHidden);
        }

        return this.resetTabStatus();
    }

    // 點擊 block tabs
    _proto.tabClick = function tabClick(currentBtn, closure) {

        // 點擊執行內容
        if ($.contains(this._element, currentBtn)) {

            // tab 切換前
            $(this._element).trigger(Event.Click.Before, [currentBtn]);

            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
            $(currentBtn).addClass(Options.focus);

            this.resetTabStatus();

            // tab 切換後
            $(this._element).trigger(Event.Click.After, [currentBtn]);

            if (typeof (closure) === "function")
                closure();
        }

        return this;
    }

    if (typeof $.fn.blockTab !== 'function') {

        $.fn.extend({
            blockTab: function (options) {
                this.filter(function (i, o) {
                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
                }).each(function (event) {
                    $(this).data(DataKey, new BlockTabs(this, options));
                });
            }
        });
    }

    $(function () {
        $(BlockSel).blockTab();
    });

}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
;(function($) {var _proto = String.prototype;

if (typeof _proto.regxMatch !== 'function') {
    _proto.regxMatch = function regxMatch() {
        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
            regxStr = (typeof this === "string" || this instanceof String) ? this : "";
        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
            return x.trim();
        }).join(' ');
    }
}/**
 * 已經改變了整個 scrollPosStyler 的內核，請勿覆蓋
 * ======================================================================== */

/**
 * @license
 * ========================================================================
 * ScrollPos-Styler v0.7.1
 * https://github.com/acch/scrollpos-styler
 * ========================================================================
 * Copyright 2015 Achim Christ
 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
 * ======================================================================== */

// JSHint directives
/* exported ScrollPosStyler */
if (typeof window.ScrollOverSelfStyler === "undefined") {
    var ScrollOverSelfStyler = (function (document, window, $) {
        "use strict";

        /* ====================
         * private variables
         * ==================== */
        var scrollPosY = 0,
            busy = false,

            // toggle style / class when scrolling below this position (in px)
            scrollOffsetY = 1,

            // class used to apply scrollPosStyler to
            spsClass = "soss",

            // choose elements to apply style / class to
            elements = document.getElementsByClassName(spsClass),

            // style / class to apply to elements when above scroll position
            classAbove = "soss--abv",

            // style / class to apply to elements when below scroll position
            classBelow = "soss--blw",

            // tag to set custom scroll offset per element
            offsetTag = "data-soss-offset";

        
        var BlockSel = '.block-item',
            ShadowKey = "ScrollOverSelfStyler";

        /* ====================
         * private function to check scroll position
         * ==================== */
        function onScroll() {

            // ensure that events don't stack
            if (!busy) {

                // find elements to update
                var elementsToUpdate = getElementsToUpdate(false);
                if (elementsToUpdate.length > 0) {

                    // suspend accepting scroll events
                    busy = true;

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                }
            }
        }

        /* ====================
         * copy Element Shadow
         * ==================== */
        function copyElementShadow(init) {
            for (var i = 0; elements[i]; ++i) {
                var element = elements[i];
                if (!$(element).data(ShadowKey)) {
                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
                }
            }
        }

        /* ====================
         * private function to find elements to update
         * ==================== */
        function getElementsToUpdate(init) {
            var elementsToUpdate = [];
            copyElementShadow(init);

            // get current scroll position from window
            scrollPosY = window.pageYOffset;

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elements[i]; ++i) { // chrome workaround
                var element = elements[i],
                    $shadow = $(element).data(ShadowKey);

                // get offset from element, default to global option
                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
                    shScrollOffsetY = $shadow.offset().top;

                // check current state of element
                var elOnTop = element.classList.contains(classAbove);

                // check current is visible
                var elVisible = $(element).closest(BlockSel).is(':visible');

                // cols regx
                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));

                // if we were above, and are now below scroll position...
                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
                    
                    element.style.top = offsetTop + "px";
                    $shadow.css('height', $(element).css('height'));

                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classBelow + " " + regxMatchCol,
                        removeClass: classAbove
                    });

                    // if we were below, and are now above scroll position...
                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {


                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classAbove,
                        removeClass: classBelow + " " + regxMatchCol
                    });

                    $shadow.get(0).style.height = null;
                    element.style.top = null;
                }
            }

            return elementsToUpdate;
        }

        /* ====================
         * private function to update elements
         * ==================== */
        function updateElements(elementsToUpdate) {

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
                var map = elementsToUpdate[i];

                // add style / class to element
                //map.element.classList.add(map.addClass);
                //map.element.classList.remove(map.removeClass);
                $(map.element).addClass(map.addClass);
                $(map.element).removeClass(map.removeClass);
            }

            // resume accepting scroll events
            busy = false;
        }

        /* ====================
         * public function to initially style elements based on scroll position
         *
         * options:
         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
         *
         * ==================== */
        var pub = {
            init: function (options) {

                // suspend accepting scroll events
                busy = true;

                // merge options object with global options
                if (options) {
                    if (options.spsClass) {
                        spsClass = options.spsClass;
                        elements = document.getElementsByClassName(spsClass);
                    }
                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
                    classAbove = options.classAbove || classAbove;
                    classBelow = options.classBelow || classBelow;
                    offsetTag = options.offsetTag || offsetTag;
                }

                // ensure all elements have classAbove
                var elementsToUpdate = getElementsToUpdate(true);
                if (elementsToUpdate.length > 0) {

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                } else {

                    // resume accepting scroll events
                    busy = false;
                }
            }
        };

        // register for window scroll events
        $(window).on("scroll", onScroll);

        window.ScrollOverSelfStyler = pub;

        return pub;
    })(document, window, jQuery);
}

/* ====================
 * main initialization
 * ==================== */
$(function () {
    // defer initialization to allow browser to restore scroll position
    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
});if (typeof jQuery === 'undefined') {
    throw new Error('Block\'s JavaScript requires jQuery')
}

+function ($) {
    'use strict';
    var version = $.fn.jquery.split(' ')[0].split('.')
    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
    }
}(jQuery);


+function ($, win) {
    'use strict';

    var DataKey = 'blktabs',
        BlockSel = '.block-item',
        TabSel = '> .module-container .blk-tabs > ul',
        BtnSel = '> li',
        ValSel = ' > a[href^="#blk"]',
        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
        DestroyBeforeSymbol = 'destroyBeforeSymbol',
        Event = {
            ReplacedBefore: 'renderview.replace.before',
            ReplacedAfter: 'renderview.replace.after',
            BlockDestroy: 'destroy',
            BlockAppear: DataKey + '.block.appear',
            BlockHidden: DataKey + '.block.hidden',
            Click: {
                Window: 'blk-nav-in',
                Before: DataKey + '.tabs.click.before',
                After: DataKey + '.tabs.click.after'
            }
        },
        Options = {
            focus: 'active'
        };

    function BlockTabs(element, opts) {

        var self = this;
        this._opts = $.extend(Options, $(element).data(), opts);
        this._element = element;
        this._tabs = $(TabSel, element).get(0);

        // block 更新屬性值之後將會被置換
        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
            $(this).addClass(ReplacedBeforeSymbol);
            event.data.blktabs.resetTabStatus();
            $(this).removeClass(ReplacedBeforeSymbol);
            $.removeData(this, DataKey);
        });

        // block 被刪除前復原 tab 關聯的 block
        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
            $(this).addClass(DestroyBeforeSymbol);
            event.data.blktabs.resetTabStatus();
        });

        // block tabs click 事件
        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
            if ($(element).attr('href').startsWith('#')) {
                event.preventDefault();
                event.data.blktabs.tabClick(element);
                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
                    target: element,
                    detail: {
                        selector: $(element).attr('href')
                    }
                }));
            }
        });

        this.tabAppear().resetMyStatus();

        var bookmarkId = window.location.href.split('#').pop();
        if (this._element.id == bookmarkId) {
            // 錨點跳轉
            var blk = this;
            window.addEventListener("load", function (event) {

                var arrParentAndButton = function (blkId) {
                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
                    var pblk = tab.closest(BlockSel);
                    if (pblk.length > 0 && pblk.attr('id')) {
                        // 記錄&尋找
                        var r = arrParentAndButton(pblk.attr('id'));
                        r.push([pblk, tab]);
                        return r;
                    }
                    return [];
                };
                var arr = arrParentAndButton(blk._element.id);
                for (var i in arr)
                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));

                setTimeout(function () {
                    $("html, body").animate({
                        scrollTop: $(blk._element).offset().top
                    }, 500, 'swing', function () { });
                }, 0.5 * 1000);
            });
        }
    }

    var _proto = BlockTabs.prototype;

    _proto.tabAppear = function tabAppear() {
        if ($(BtnSel, this._tabs).length > 0)
            $(this._tabs).removeClass('d-none hide');
        return this;
    }


    // 取得 block tabs 所有關聯的 block target
    _proto.getTabSelector = function getTabSelector() {
        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
            return $(o).attr('href');
        }).get().join(',');
    }

    // 驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetTabStatus = function resetTabStatus(event) {
        $(this.getTabSelector()).each(function () {
            if ($(this).data(DataKey))
                $(this).data(DataKey).resetMyStatus();
        });
        return this;
    }

    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetMyStatus = function resetMyStatus() {
        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a

        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
            // 顯示 element
            this._element.style.setProperty('display', '');

            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
            if ($tabLink.length < 1)
                $tabLink = $(BtnSel + ValSel, this._tabs);
            this.tabClick($tabLink.get(0));
            $(this._element).trigger(Event.BlockAppear);
        }
        else {
            // 隱藏 element
            this._element.style.setProperty('display', 'none', 'important');
            $(this._element).trigger(Event.BlockHidden);
        }

        return this.resetTabStatus();
    }

    // 點擊 block tabs
    _proto.tabClick = function tabClick(currentBtn, closure) {

        // 點擊執行內容
        if ($.contains(this._element, currentBtn)) {

            // tab 切換前
            $(this._element).trigger(Event.Click.Before, [currentBtn]);

            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
            $(currentBtn).addClass(Options.focus);

            this.resetTabStatus();

            // tab 切換後
            $(this._element).trigger(Event.Click.After, [currentBtn]);

            if (typeof (closure) === "function")
                closure();
        }

        return this;
    }

    if (typeof $.fn.blockTab !== 'function') {

        $.fn.extend({
            blockTab: function (options) {
                this.filter(function (i, o) {
                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
                }).each(function (event) {
                    $(this).data(DataKey, new BlockTabs(this, options));
                });
            }
        });
    }

    $(function () {
        $(BlockSel).blockTab();
    });

}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
;(function($) {var _proto = String.prototype;

if (typeof _proto.regxMatch !== 'function') {
    _proto.regxMatch = function regxMatch() {
        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
            regxStr = (typeof this === "string" || this instanceof String) ? this : "";
        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
            return x.trim();
        }).join(' ');
    }
}/**
 * 已經改變了整個 scrollPosStyler 的內核，請勿覆蓋
 * ======================================================================== */

/**
 * @license
 * ========================================================================
 * ScrollPos-Styler v0.7.1
 * https://github.com/acch/scrollpos-styler
 * ========================================================================
 * Copyright 2015 Achim Christ
 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
 * ======================================================================== */

// JSHint directives
/* exported ScrollPosStyler */
if (typeof window.ScrollOverSelfStyler === "undefined") {
    var ScrollOverSelfStyler = (function (document, window, $) {
        "use strict";

        /* ====================
         * private variables
         * ==================== */
        var scrollPosY = 0,
            busy = false,

            // toggle style / class when scrolling below this position (in px)
            scrollOffsetY = 1,

            // class used to apply scrollPosStyler to
            spsClass = "soss",

            // choose elements to apply style / class to
            elements = document.getElementsByClassName(spsClass),

            // style / class to apply to elements when above scroll position
            classAbove = "soss--abv",

            // style / class to apply to elements when below scroll position
            classBelow = "soss--blw",

            // tag to set custom scroll offset per element
            offsetTag = "data-soss-offset";

        
        var BlockSel = '.block-item',
            ShadowKey = "ScrollOverSelfStyler";

        /* ====================
         * private function to check scroll position
         * ==================== */
        function onScroll() {

            // ensure that events don't stack
            if (!busy) {

                // find elements to update
                var elementsToUpdate = getElementsToUpdate(false);
                if (elementsToUpdate.length > 0) {

                    // suspend accepting scroll events
                    busy = true;

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                }
            }
        }

        /* ====================
         * copy Element Shadow
         * ==================== */
        function copyElementShadow(init) {
            for (var i = 0; elements[i]; ++i) {
                var element = elements[i];
                if (!$(element).data(ShadowKey)) {
                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
                }
            }
        }

        /* ====================
         * private function to find elements to update
         * ==================== */
        function getElementsToUpdate(init) {
            var elementsToUpdate = [];
            copyElementShadow(init);

            // get current scroll position from window
            scrollPosY = window.pageYOffset;

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elements[i]; ++i) { // chrome workaround
                var element = elements[i],
                    $shadow = $(element).data(ShadowKey);

                // get offset from element, default to global option
                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
                    shScrollOffsetY = $shadow.offset().top;

                // check current state of element
                var elOnTop = element.classList.contains(classAbove);

                // check current is visible
                var elVisible = $(element).closest(BlockSel).is(':visible');

                // cols regx
                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));

                // if we were above, and are now below scroll position...
                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
                    
                    element.style.top = offsetTop + "px";
                    $shadow.css('height', $(element).css('height'));

                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classBelow + " " + regxMatchCol,
                        removeClass: classAbove
                    });

                    // if we were below, and are now above scroll position...
                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {


                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classAbove,
                        removeClass: classBelow + " " + regxMatchCol
                    });

                    $shadow.get(0).style.height = null;
                    element.style.top = null;
                }
            }

            return elementsToUpdate;
        }

        /* ====================
         * private function to update elements
         * ==================== */
        function updateElements(elementsToUpdate) {

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
                var map = elementsToUpdate[i];

                // add style / class to element
                //map.element.classList.add(map.addClass);
                //map.element.classList.remove(map.removeClass);
                $(map.element).addClass(map.addClass);
                $(map.element).removeClass(map.removeClass);
            }

            // resume accepting scroll events
            busy = false;
        }

        /* ====================
         * public function to initially style elements based on scroll position
         *
         * options:
         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
         *
         * ==================== */
        var pub = {
            init: function (options) {

                // suspend accepting scroll events
                busy = true;

                // merge options object with global options
                if (options) {
                    if (options.spsClass) {
                        spsClass = options.spsClass;
                        elements = document.getElementsByClassName(spsClass);
                    }
                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
                    classAbove = options.classAbove || classAbove;
                    classBelow = options.classBelow || classBelow;
                    offsetTag = options.offsetTag || offsetTag;
                }

                // ensure all elements have classAbove
                var elementsToUpdate = getElementsToUpdate(true);
                if (elementsToUpdate.length > 0) {

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                } else {

                    // resume accepting scroll events
                    busy = false;
                }
            }
        };

        // register for window scroll events
        $(window).on("scroll", onScroll);

        window.ScrollOverSelfStyler = pub;

        return pub;
    })(document, window, jQuery);
}

/* ====================
 * main initialization
 * ==================== */
$(function () {
    // defer initialization to allow browser to restore scroll position
    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
});if (typeof jQuery === 'undefined') {
    throw new Error('Block\'s JavaScript requires jQuery')
}

+function ($) {
    'use strict';
    var version = $.fn.jquery.split(' ')[0].split('.')
    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
    }
}(jQuery);


+function ($, win) {
    'use strict';

    var DataKey = 'blktabs',
        BlockSel = '.block-item',
        TabSel = '> .module-container .blk-tabs > ul',
        BtnSel = '> li',
        ValSel = ' > a[href^="#blk"]',
        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
        DestroyBeforeSymbol = 'destroyBeforeSymbol',
        Event = {
            ReplacedBefore: 'renderview.replace.before',
            ReplacedAfter: 'renderview.replace.after',
            BlockDestroy: 'destroy',
            BlockAppear: DataKey + '.block.appear',
            BlockHidden: DataKey + '.block.hidden',
            Click: {
                Window: 'blk-nav-in',
                Before: DataKey + '.tabs.click.before',
                After: DataKey + '.tabs.click.after'
            }
        },
        Options = {
            focus: 'active'
        };

    function BlockTabs(element, opts) {

        var self = this;
        this._opts = $.extend(Options, $(element).data(), opts);
        this._element = element;
        this._tabs = $(TabSel, element).get(0);

        // block 更新屬性值之後將會被置換
        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
            $(this).addClass(ReplacedBeforeSymbol);
            event.data.blktabs.resetTabStatus();
            $(this).removeClass(ReplacedBeforeSymbol);
            $.removeData(this, DataKey);
        });

        // block 被刪除前復原 tab 關聯的 block
        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
            $(this).addClass(DestroyBeforeSymbol);
            event.data.blktabs.resetTabStatus();
        });

        // block tabs click 事件
        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
            if ($(element).attr('href').startsWith('#')) {
                event.preventDefault();
                event.data.blktabs.tabClick(element);
                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
                    target: element,
                    detail: {
                        selector: $(element).attr('href')
                    }
                }));
            }
        });

        this.tabAppear().resetMyStatus();

        var bookmarkId = window.location.href.split('#').pop();
        if (this._element.id == bookmarkId) {
            // 錨點跳轉
            var blk = this;
            window.addEventListener("load", function (event) {

                var arrParentAndButton = function (blkId) {
                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
                    var pblk = tab.closest(BlockSel);
                    if (pblk.length > 0 && pblk.attr('id')) {
                        // 記錄&尋找
                        var r = arrParentAndButton(pblk.attr('id'));
                        r.push([pblk, tab]);
                        return r;
                    }
                    return [];
                };
                var arr = arrParentAndButton(blk._element.id);
                for (var i in arr)
                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));

                setTimeout(function () {
                    $("html, body").animate({
                        scrollTop: $(blk._element).offset().top
                    }, 500, 'swing', function () { });
                }, 0.5 * 1000);
            });
        }
    }

    var _proto = BlockTabs.prototype;

    _proto.tabAppear = function tabAppear() {
        if ($(BtnSel, this._tabs).length > 0)
            $(this._tabs).removeClass('d-none hide');
        return this;
    }


    // 取得 block tabs 所有關聯的 block target
    _proto.getTabSelector = function getTabSelector() {
        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
            return $(o).attr('href');
        }).get().join(',');
    }

    // 驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetTabStatus = function resetTabStatus(event) {
        $(this.getTabSelector()).each(function () {
            if ($(this).data(DataKey))
                $(this).data(DataKey).resetMyStatus();
        });
        return this;
    }

    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetMyStatus = function resetMyStatus() {
        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a

        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
            // 顯示 element
            this._element.style.setProperty('display', '');

            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
            if ($tabLink.length < 1)
                $tabLink = $(BtnSel + ValSel, this._tabs);
            this.tabClick($tabLink.get(0));
            $(this._element).trigger(Event.BlockAppear);
        }
        else {
            // 隱藏 element
            this._element.style.setProperty('display', 'none', 'important');
            $(this._element).trigger(Event.BlockHidden);
        }

        return this.resetTabStatus();
    }

    // 點擊 block tabs
    _proto.tabClick = function tabClick(currentBtn, closure) {

        // 點擊執行內容
        if ($.contains(this._element, currentBtn)) {

            // tab 切換前
            $(this._element).trigger(Event.Click.Before, [currentBtn]);

            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
            $(currentBtn).addClass(Options.focus);

            this.resetTabStatus();

            // tab 切換後
            $(this._element).trigger(Event.Click.After, [currentBtn]);

            if (typeof (closure) === "function")
                closure();
        }

        return this;
    }

    if (typeof $.fn.blockTab !== 'function') {

        $.fn.extend({
            blockTab: function (options) {
                this.filter(function (i, o) {
                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
                }).each(function (event) {
                    $(this).data(DataKey, new BlockTabs(this, options));
                });
            }
        });
    }

    $(function () {
        $(BlockSel).blockTab();
    });

}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
;(function($) {var _proto = String.prototype;

if (typeof _proto.regxMatch !== 'function') {
    _proto.regxMatch = function regxMatch() {
        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
            regxStr = (typeof this === "string" || this instanceof String) ? this : "";
        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
            return x.trim();
        }).join(' ');
    }
}/**
 * 已經改變了整個 scrollPosStyler 的內核，請勿覆蓋
 * ======================================================================== */

/**
 * @license
 * ========================================================================
 * ScrollPos-Styler v0.7.1
 * https://github.com/acch/scrollpos-styler
 * ========================================================================
 * Copyright 2015 Achim Christ
 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
 * ======================================================================== */

// JSHint directives
/* exported ScrollPosStyler */
if (typeof window.ScrollOverSelfStyler === "undefined") {
    var ScrollOverSelfStyler = (function (document, window, $) {
        "use strict";

        /* ====================
         * private variables
         * ==================== */
        var scrollPosY = 0,
            busy = false,

            // toggle style / class when scrolling below this position (in px)
            scrollOffsetY = 1,

            // class used to apply scrollPosStyler to
            spsClass = "soss",

            // choose elements to apply style / class to
            elements = document.getElementsByClassName(spsClass),

            // style / class to apply to elements when above scroll position
            classAbove = "soss--abv",

            // style / class to apply to elements when below scroll position
            classBelow = "soss--blw",

            // tag to set custom scroll offset per element
            offsetTag = "data-soss-offset";

        
        var BlockSel = '.block-item',
            ShadowKey = "ScrollOverSelfStyler";

        /* ====================
         * private function to check scroll position
         * ==================== */
        function onScroll() {

            // ensure that events don't stack
            if (!busy) {

                // find elements to update
                var elementsToUpdate = getElementsToUpdate(false);
                if (elementsToUpdate.length > 0) {

                    // suspend accepting scroll events
                    busy = true;

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                }
            }
        }

        /* ====================
         * copy Element Shadow
         * ==================== */
        function copyElementShadow(init) {
            for (var i = 0; elements[i]; ++i) {
                var element = elements[i];
                if (!$(element).data(ShadowKey)) {
                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
                }
            }
        }

        /* ====================
         * private function to find elements to update
         * ==================== */
        function getElementsToUpdate(init) {
            var elementsToUpdate = [];
            copyElementShadow(init);

            // get current scroll position from window
            scrollPosY = window.pageYOffset;

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elements[i]; ++i) { // chrome workaround
                var element = elements[i],
                    $shadow = $(element).data(ShadowKey);

                // get offset from element, default to global option
                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
                    shScrollOffsetY = $shadow.offset().top;

                // check current state of element
                var elOnTop = element.classList.contains(classAbove);

                // check current is visible
                var elVisible = $(element).closest(BlockSel).is(':visible');

                // cols regx
                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));

                // if we were above, and are now below scroll position...
                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
                    
                    element.style.top = offsetTop + "px";
                    $shadow.css('height', $(element).css('height'));

                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classBelow + " " + regxMatchCol,
                        removeClass: classAbove
                    });

                    // if we were below, and are now above scroll position...
                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {


                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classAbove,
                        removeClass: classBelow + " " + regxMatchCol
                    });

                    $shadow.get(0).style.height = null;
                    element.style.top = null;
                }
            }

            return elementsToUpdate;
        }

        /* ====================
         * private function to update elements
         * ==================== */
        function updateElements(elementsToUpdate) {

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
                var map = elementsToUpdate[i];

                // add style / class to element
                //map.element.classList.add(map.addClass);
                //map.element.classList.remove(map.removeClass);
                $(map.element).addClass(map.addClass);
                $(map.element).removeClass(map.removeClass);
            }

            // resume accepting scroll events
            busy = false;
        }

        /* ====================
         * public function to initially style elements based on scroll position
         *
         * options:
         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
         *
         * ==================== */
        var pub = {
            init: function (options) {

                // suspend accepting scroll events
                busy = true;

                // merge options object with global options
                if (options) {
                    if (options.spsClass) {
                        spsClass = options.spsClass;
                        elements = document.getElementsByClassName(spsClass);
                    }
                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
                    classAbove = options.classAbove || classAbove;
                    classBelow = options.classBelow || classBelow;
                    offsetTag = options.offsetTag || offsetTag;
                }

                // ensure all elements have classAbove
                var elementsToUpdate = getElementsToUpdate(true);
                if (elementsToUpdate.length > 0) {

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                } else {

                    // resume accepting scroll events
                    busy = false;
                }
            }
        };

        // register for window scroll events
        $(window).on("scroll", onScroll);

        window.ScrollOverSelfStyler = pub;

        return pub;
    })(document, window, jQuery);
}

/* ====================
 * main initialization
 * ==================== */
$(function () {
    // defer initialization to allow browser to restore scroll position
    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
});if (typeof jQuery === 'undefined') {
    throw new Error('Block\'s JavaScript requires jQuery')
}

+function ($) {
    'use strict';
    var version = $.fn.jquery.split(' ')[0].split('.')
    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
    }
}(jQuery);


+function ($, win) {
    'use strict';

    var DataKey = 'blktabs',
        BlockSel = '.block-item',
        TabSel = '> .module-container .blk-tabs > ul',
        BtnSel = '> li',
        ValSel = ' > a[href^="#blk"]',
        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
        DestroyBeforeSymbol = 'destroyBeforeSymbol',
        Event = {
            ReplacedBefore: 'renderview.replace.before',
            ReplacedAfter: 'renderview.replace.after',
            BlockDestroy: 'destroy',
            BlockAppear: DataKey + '.block.appear',
            BlockHidden: DataKey + '.block.hidden',
            Click: {
                Window: 'blk-nav-in',
                Before: DataKey + '.tabs.click.before',
                After: DataKey + '.tabs.click.after'
            }
        },
        Options = {
            focus: 'active'
        };

    function BlockTabs(element, opts) {

        var self = this;
        this._opts = $.extend(Options, $(element).data(), opts);
        this._element = element;
        this._tabs = $(TabSel, element).get(0);

        // block 更新屬性值之後將會被置換
        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
            $(this).addClass(ReplacedBeforeSymbol);
            event.data.blktabs.resetTabStatus();
            $(this).removeClass(ReplacedBeforeSymbol);
            $.removeData(this, DataKey);
        });

        // block 被刪除前復原 tab 關聯的 block
        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
            $(this).addClass(DestroyBeforeSymbol);
            event.data.blktabs.resetTabStatus();
        });

        // block tabs click 事件
        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
            if ($(element).attr('href').startsWith('#')) {
                event.preventDefault();
                event.data.blktabs.tabClick(element);
                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
                    target: element,
                    detail: {
                        selector: $(element).attr('href')
                    }
                }));
            }
        });

        this.tabAppear().resetMyStatus();

        var bookmarkId = window.location.href.split('#').pop();
        if (this._element.id == bookmarkId) {
            // 錨點跳轉
            var blk = this;
            window.addEventListener("load", function (event) {

                var arrParentAndButton = function (blkId) {
                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
                    var pblk = tab.closest(BlockSel);
                    if (pblk.length > 0 && pblk.attr('id')) {
                        // 記錄&尋找
                        var r = arrParentAndButton(pblk.attr('id'));
                        r.push([pblk, tab]);
                        return r;
                    }
                    return [];
                };
                var arr = arrParentAndButton(blk._element.id);
                for (var i in arr)
                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));

                setTimeout(function () {
                    $("html, body").animate({
                        scrollTop: $(blk._element).offset().top
                    }, 500, 'swing', function () { });
                }, 0.5 * 1000);
            });
        }
    }

    var _proto = BlockTabs.prototype;

    _proto.tabAppear = function tabAppear() {
        if ($(BtnSel, this._tabs).length > 0)
            $(this._tabs).removeClass('d-none hide');
        return this;
    }


    // 取得 block tabs 所有關聯的 block target
    _proto.getTabSelector = function getTabSelector() {
        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
            return $(o).attr('href');
        }).get().join(',');
    }

    // 驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetTabStatus = function resetTabStatus(event) {
        $(this.getTabSelector()).each(function () {
            if ($(this).data(DataKey))
                $(this).data(DataKey).resetMyStatus();
        });
        return this;
    }

    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetMyStatus = function resetMyStatus() {
        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a

        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
            // 顯示 element
            this._element.style.setProperty('display', '');

            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
            if ($tabLink.length < 1)
                $tabLink = $(BtnSel + ValSel, this._tabs);
            this.tabClick($tabLink.get(0));
            $(this._element).trigger(Event.BlockAppear);
        }
        else {
            // 隱藏 element
            this._element.style.setProperty('display', 'none', 'important');
            $(this._element).trigger(Event.BlockHidden);
        }

        return this.resetTabStatus();
    }

    // 點擊 block tabs
    _proto.tabClick = function tabClick(currentBtn, closure) {

        // 點擊執行內容
        if ($.contains(this._element, currentBtn)) {

            // tab 切換前
            $(this._element).trigger(Event.Click.Before, [currentBtn]);

            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
            $(currentBtn).addClass(Options.focus);

            this.resetTabStatus();

            // tab 切換後
            $(this._element).trigger(Event.Click.After, [currentBtn]);

            if (typeof (closure) === "function")
                closure();
        }

        return this;
    }

    if (typeof $.fn.blockTab !== 'function') {

        $.fn.extend({
            blockTab: function (options) {
                this.filter(function (i, o) {
                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
                }).each(function (event) {
                    $(this).data(DataKey, new BlockTabs(this, options));
                });
            }
        });
    }

    $(function () {
        $(BlockSel).blockTab();
    });

}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
;(function($) {var _proto = String.prototype;

if (typeof _proto.regxMatch !== 'function') {
    _proto.regxMatch = function regxMatch() {
        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
            regxStr = (typeof this === "string" || this instanceof String) ? this : "";
        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
            return x.trim();
        }).join(' ');
    }
}/**
 * 已經改變了整個 scrollPosStyler 的內核，請勿覆蓋
 * ======================================================================== */

/**
 * @license
 * ========================================================================
 * ScrollPos-Styler v0.7.1
 * https://github.com/acch/scrollpos-styler
 * ========================================================================
 * Copyright 2015 Achim Christ
 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
 * ======================================================================== */

// JSHint directives
/* exported ScrollPosStyler */
if (typeof window.ScrollOverSelfStyler === "undefined") {
    var ScrollOverSelfStyler = (function (document, window, $) {
        "use strict";

        /* ====================
         * private variables
         * ==================== */
        var scrollPosY = 0,
            busy = false,

            // toggle style / class when scrolling below this position (in px)
            scrollOffsetY = 1,

            // class used to apply scrollPosStyler to
            spsClass = "soss",

            // choose elements to apply style / class to
            elements = document.getElementsByClassName(spsClass),

            // style / class to apply to elements when above scroll position
            classAbove = "soss--abv",

            // style / class to apply to elements when below scroll position
            classBelow = "soss--blw",

            // tag to set custom scroll offset per element
            offsetTag = "data-soss-offset";

        
        var BlockSel = '.block-item',
            ShadowKey = "ScrollOverSelfStyler";

        /* ====================
         * private function to check scroll position
         * ==================== */
        function onScroll() {

            // ensure that events don't stack
            if (!busy) {

                // find elements to update
                var elementsToUpdate = getElementsToUpdate(false);
                if (elementsToUpdate.length > 0) {

                    // suspend accepting scroll events
                    busy = true;

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                }
            }
        }

        /* ====================
         * copy Element Shadow
         * ==================== */
        function copyElementShadow(init) {
            for (var i = 0; elements[i]; ++i) {
                var element = elements[i];
                if (!$(element).data(ShadowKey)) {
                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
                }
            }
        }

        /* ====================
         * private function to find elements to update
         * ==================== */
        function getElementsToUpdate(init) {
            var elementsToUpdate = [];
            copyElementShadow(init);

            // get current scroll position from window
            scrollPosY = window.pageYOffset;

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elements[i]; ++i) { // chrome workaround
                var element = elements[i],
                    $shadow = $(element).data(ShadowKey);

                // get offset from element, default to global option
                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
                    shScrollOffsetY = $shadow.offset().top;

                // check current state of element
                var elOnTop = element.classList.contains(classAbove);

                // check current is visible
                var elVisible = $(element).closest(BlockSel).is(':visible');

                // cols regx
                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));

                // if we were above, and are now below scroll position...
                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
                    
                    element.style.top = offsetTop + "px";
                    $shadow.css('height', $(element).css('height'));

                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classBelow + " " + regxMatchCol,
                        removeClass: classAbove
                    });

                    // if we were below, and are now above scroll position...
                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {


                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classAbove,
                        removeClass: classBelow + " " + regxMatchCol
                    });

                    $shadow.get(0).style.height = null;
                    element.style.top = null;
                }
            }

            return elementsToUpdate;
        }

        /* ====================
         * private function to update elements
         * ==================== */
        function updateElements(elementsToUpdate) {

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
                var map = elementsToUpdate[i];

                // add style / class to element
                //map.element.classList.add(map.addClass);
                //map.element.classList.remove(map.removeClass);
                $(map.element).addClass(map.addClass);
                $(map.element).removeClass(map.removeClass);
            }

            // resume accepting scroll events
            busy = false;
        }

        /* ====================
         * public function to initially style elements based on scroll position
         *
         * options:
         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
         *
         * ==================== */
        var pub = {
            init: function (options) {

                // suspend accepting scroll events
                busy = true;

                // merge options object with global options
                if (options) {
                    if (options.spsClass) {
                        spsClass = options.spsClass;
                        elements = document.getElementsByClassName(spsClass);
                    }
                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
                    classAbove = options.classAbove || classAbove;
                    classBelow = options.classBelow || classBelow;
                    offsetTag = options.offsetTag || offsetTag;
                }

                // ensure all elements have classAbove
                var elementsToUpdate = getElementsToUpdate(true);
                if (elementsToUpdate.length > 0) {

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                } else {

                    // resume accepting scroll events
                    busy = false;
                }
            }
        };

        // register for window scroll events
        $(window).on("scroll", onScroll);

        window.ScrollOverSelfStyler = pub;

        return pub;
    })(document, window, jQuery);
}

/* ====================
 * main initialization
 * ==================== */
$(function () {
    // defer initialization to allow browser to restore scroll position
    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
});if (typeof jQuery === 'undefined') {
    throw new Error('Block\'s JavaScript requires jQuery')
}

+function ($) {
    'use strict';
    var version = $.fn.jquery.split(' ')[0].split('.')
    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
    }
}(jQuery);


+function ($, win) {
    'use strict';

    var DataKey = 'blktabs',
        BlockSel = '.block-item',
        TabSel = '> .module-container .blk-tabs > ul',
        BtnSel = '> li',
        ValSel = ' > a[href^="#blk"]',
        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
        DestroyBeforeSymbol = 'destroyBeforeSymbol',
        Event = {
            ReplacedBefore: 'renderview.replace.before',
            ReplacedAfter: 'renderview.replace.after',
            BlockDestroy: 'destroy',
            BlockAppear: DataKey + '.block.appear',
            BlockHidden: DataKey + '.block.hidden',
            Click: {
                Window: 'blk-nav-in',
                Before: DataKey + '.tabs.click.before',
                After: DataKey + '.tabs.click.after'
            }
        },
        Options = {
            focus: 'active'
        };

    function BlockTabs(element, opts) {

        var self = this;
        this._opts = $.extend(Options, $(element).data(), opts);
        this._element = element;
        this._tabs = $(TabSel, element).get(0);

        // block 更新屬性值之後將會被置換
        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
            $(this).addClass(ReplacedBeforeSymbol);
            event.data.blktabs.resetTabStatus();
            $(this).removeClass(ReplacedBeforeSymbol);
            $.removeData(this, DataKey);
        });

        // block 被刪除前復原 tab 關聯的 block
        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
            $(this).addClass(DestroyBeforeSymbol);
            event.data.blktabs.resetTabStatus();
        });

        // block tabs click 事件
        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
            if ($(element).attr('href').startsWith('#')) {
                event.preventDefault();
                event.data.blktabs.tabClick(element);
                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
                    target: element,
                    detail: {
                        selector: $(element).attr('href')
                    }
                }));
            }
        });

        this.tabAppear().resetMyStatus();

        var bookmarkId = window.location.href.split('#').pop();
        if (this._element.id == bookmarkId) {
            // 錨點跳轉
            var blk = this;
            window.addEventListener("load", function (event) {

                var arrParentAndButton = function (blkId) {
                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
                    var pblk = tab.closest(BlockSel);
                    if (pblk.length > 0 && pblk.attr('id')) {
                        // 記錄&尋找
                        var r = arrParentAndButton(pblk.attr('id'));
                        r.push([pblk, tab]);
                        return r;
                    }
                    return [];
                };
                var arr = arrParentAndButton(blk._element.id);
                for (var i in arr)
                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));

                setTimeout(function () {
                    $("html, body").animate({
                        scrollTop: $(blk._element).offset().top
                    }, 500, 'swing', function () { });
                }, 0.5 * 1000);
            });
        }
    }

    var _proto = BlockTabs.prototype;

    _proto.tabAppear = function tabAppear() {
        if ($(BtnSel, this._tabs).length > 0)
            $(this._tabs).removeClass('d-none hide');
        return this;
    }


    // 取得 block tabs 所有關聯的 block target
    _proto.getTabSelector = function getTabSelector() {
        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
            return $(o).attr('href');
        }).get().join(',');
    }

    // 驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetTabStatus = function resetTabStatus(event) {
        $(this.getTabSelector()).each(function () {
            if ($(this).data(DataKey))
                $(this).data(DataKey).resetMyStatus();
        });
        return this;
    }

    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetMyStatus = function resetMyStatus() {
        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a

        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
            // 顯示 element
            this._element.style.setProperty('display', '');

            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
            if ($tabLink.length < 1)
                $tabLink = $(BtnSel + ValSel, this._tabs);
            this.tabClick($tabLink.get(0));
            $(this._element).trigger(Event.BlockAppear);
        }
        else {
            // 隱藏 element
            this._element.style.setProperty('display', 'none', 'important');
            $(this._element).trigger(Event.BlockHidden);
        }

        return this.resetTabStatus();
    }

    // 點擊 block tabs
    _proto.tabClick = function tabClick(currentBtn, closure) {

        // 點擊執行內容
        if ($.contains(this._element, currentBtn)) {

            // tab 切換前
            $(this._element).trigger(Event.Click.Before, [currentBtn]);

            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
            $(currentBtn).addClass(Options.focus);

            this.resetTabStatus();

            // tab 切換後
            $(this._element).trigger(Event.Click.After, [currentBtn]);

            if (typeof (closure) === "function")
                closure();
        }

        return this;
    }

    if (typeof $.fn.blockTab !== 'function') {

        $.fn.extend({
            blockTab: function (options) {
                this.filter(function (i, o) {
                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
                }).each(function (event) {
                    $(this).data(DataKey, new BlockTabs(this, options));
                });
            }
        });
    }

    $(function () {
        $(BlockSel).blockTab();
    });

}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
;(function($) {var _proto = String.prototype;

if (typeof _proto.regxMatch !== 'function') {
    _proto.regxMatch = function regxMatch() {
        var content = (arguments.length > 1) ? arguments[1] : arguments[0] || "",
            regxStr = (typeof this === "string" || this instanceof String) ? this : "";
        return (content.match(new RegExp(regxStr, "g")) || []).map(function (x) {
            return x.trim();
        }).join(' ');
    }
}/**
 * 已經改變了整個 scrollPosStyler 的內核，請勿覆蓋
 * ======================================================================== */

/**
 * @license
 * ========================================================================
 * ScrollPos-Styler v0.7.1
 * https://github.com/acch/scrollpos-styler
 * ========================================================================
 * Copyright 2015 Achim Christ
 * Licensed under MIT (https://github.com/acch/scrollpos-styler/blob/master/LICENSE)
 * ======================================================================== */

// JSHint directives
/* exported ScrollPosStyler */
if (typeof window.ScrollOverSelfStyler === "undefined") {
    var ScrollOverSelfStyler = (function (document, window, $) {
        "use strict";

        /* ====================
         * private variables
         * ==================== */
        var scrollPosY = 0,
            busy = false,

            // toggle style / class when scrolling below this position (in px)
            scrollOffsetY = 1,

            // class used to apply scrollPosStyler to
            spsClass = "soss",

            // choose elements to apply style / class to
            elements = document.getElementsByClassName(spsClass),

            // style / class to apply to elements when above scroll position
            classAbove = "soss--abv",

            // style / class to apply to elements when below scroll position
            classBelow = "soss--blw",

            // tag to set custom scroll offset per element
            offsetTag = "data-soss-offset";

        
        var BlockSel = '.block-item',
            ShadowKey = "ScrollOverSelfStyler";

        /* ====================
         * private function to check scroll position
         * ==================== */
        function onScroll() {

            // ensure that events don't stack
            if (!busy) {

                // find elements to update
                var elementsToUpdate = getElementsToUpdate(false);
                if (elementsToUpdate.length > 0) {

                    // suspend accepting scroll events
                    busy = true;

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                }
            }
        }

        /* ====================
         * copy Element Shadow
         * ==================== */
        function copyElementShadow(init) {
            for (var i = 0; elements[i]; ++i) {
                var element = elements[i];
                if (!$(element).data(ShadowKey)) {
                    $(element).data(ShadowKey, $('<div>').insertBefore(element));
                }
            }
        }

        /* ====================
         * private function to find elements to update
         * ==================== */
        function getElementsToUpdate(init) {
            var elementsToUpdate = [];
            copyElementShadow(init);

            // get current scroll position from window
            scrollPosY = window.pageYOffset;

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elements[i]; ++i) { // chrome workaround
                var element = elements[i],
                    $shadow = $(element).data(ShadowKey);

                // get offset from element, default to global option
                var offsetTop = parseInt(element.getAttribute(offsetTag), 10);
                var elScrollOffsetY = isNaN(offsetTop) ? scrollOffsetY : offsetTop,
                    shScrollOffsetY = $shadow.offset().top;

                // check current state of element
                var elOnTop = element.classList.contains(classAbove);

                // check current is visible
                var elVisible = $(element).closest(BlockSel).is(':visible');

                // cols regx
                var regxMatchCol = "col-([lg-|md-]*)([0-9]+\\s|[0-9]+$)".regxMatch($(element).closest(BlockSel).attr('class'));

                // if we were above, and are now below scroll position...
                if (elVisible && (init || elOnTop) && scrollPosY > (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {
                    
                    element.style.top = offsetTop + "px";
                    $shadow.css('height', $(element).css('height'));

                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classBelow + " " + regxMatchCol,
                        removeClass: classAbove
                    });

                    // if we were below, and are now above scroll position...
                } else if (!elVisible || (init || !elOnTop) && scrollPosY <= (shScrollOffsetY - parseInt(elScrollOffsetY, 10))) {


                    // remember element
                    elementsToUpdate.push({
                        element: element,
                        addClass: classAbove,
                        removeClass: classBelow + " " + regxMatchCol
                    });

                    $shadow.get(0).style.height = null;
                    element.style.top = null;
                }
            }

            return elementsToUpdate;
        }

        /* ====================
         * private function to update elements
         * ==================== */
        function updateElements(elementsToUpdate) {

            // iterate over elements
            // for (var elem of elements) {
            for (var i = 0; elementsToUpdate[i]; ++i) { // chrome workaround
                var map = elementsToUpdate[i];

                // add style / class to element
                //map.element.classList.add(map.addClass);
                //map.element.classList.remove(map.removeClass);
                $(map.element).addClass(map.addClass);
                $(map.element).removeClass(map.removeClass);
            }

            // resume accepting scroll events
            busy = false;
        }

        /* ====================
         * public function to initially style elements based on scroll position
         *
         * options:
         *    scrollOffsetY (number): default scroll position in px to trigger the style. Default is 1.
         *    spsClass (string): classname used to determine which elements to style. Default is 'sps'.
         *    classAbove (string): classname added to the elements when the window is scrolled above the defined position. Default is 'sps--abv'.
         *    classBelow (string): classname added to the elements when the window is scrolled below the defined position. Default is 'sps--blw'.
         *    offsetTag (string): HTML tag used on the element to specify a scrollOffsetY other than the default.
         *
         * ==================== */
        var pub = {
            init: function (options) {

                // suspend accepting scroll events
                busy = true;

                // merge options object with global options
                if (options) {
                    if (options.spsClass) {
                        spsClass = options.spsClass;
                        elements = document.getElementsByClassName(spsClass);
                    }
                    scrollOffsetY = options.scrollOffsetY || scrollOffsetY;
                    classAbove = options.classAbove || classAbove;
                    classBelow = options.classBelow || classBelow;
                    offsetTag = options.offsetTag || offsetTag;
                }

                // ensure all elements have classAbove
                var elementsToUpdate = getElementsToUpdate(true);
                if (elementsToUpdate.length > 0) {

                    // asynchronuously update elements
                    window.requestAnimationFrame(function () {
                        updateElements(elementsToUpdate);
                    });
                } else {

                    // resume accepting scroll events
                    busy = false;
                }
            }
        };

        // register for window scroll events
        $(window).on("scroll", onScroll);

        window.ScrollOverSelfStyler = pub;

        return pub;
    })(document, window, jQuery);
}

/* ====================
 * main initialization
 * ==================== */
$(function () {
    // defer initialization to allow browser to restore scroll position
    window.setTimeout(window.ScrollOverSelfStyler.init, 1);
});if (typeof jQuery === 'undefined') {
    throw new Error('Block\'s JavaScript requires jQuery')
}

+function ($) {
    'use strict';
    var version = $.fn.jquery.split(' ')[0].split('.')
    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
        throw new Error('Block\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
    }
}(jQuery);


+function ($, win) {
    'use strict';

    var DataKey = 'blktabs',
        BlockSel = '.block-item',
        TabSel = '> .module-container .blk-tabs > ul',
        BtnSel = '> li',
        ValSel = ' > a[href^="#blk"]',
        ReplacedBeforeSymbol = 'replacedBeforeSymbol',
        DestroyBeforeSymbol = 'destroyBeforeSymbol',
        Event = {
            ReplacedBefore: 'renderview.replace.before',
            ReplacedAfter: 'renderview.replace.after',
            BlockDestroy: 'destroy',
            BlockAppear: DataKey + '.block.appear',
            BlockHidden: DataKey + '.block.hidden',
            Click: {
                Window: 'blk-nav-in',
                Before: DataKey + '.tabs.click.before',
                After: DataKey + '.tabs.click.after'
            }
        },
        Options = {
            focus: 'active'
        };

    function BlockTabs(element, opts) {

        var self = this;
        this._opts = $.extend(Options, $(element).data(), opts);
        this._element = element;
        this._tabs = $(TabSel, element).get(0);

        // block 更新屬性值之後將會被置換
        // 在這之前必須先把被 tabs 選擇到的 block 還原顯示
        // event.renderview.replace.before 事件可以參考 page-item-render-view.js
        $(this._element).on(Event.ReplacedBefore, { blktabs: this }, function (event) {
            $(this).addClass(ReplacedBeforeSymbol);
            event.data.blktabs.resetTabStatus();
            $(this).removeClass(ReplacedBeforeSymbol);
            $.removeData(this, DataKey);
        });

        // block 被刪除前復原 tab 關聯的 block
        $(this._element).on(Event.BlockDestroy, { blktabs: this }, function (event) {
            $(this).addClass(DestroyBeforeSymbol);
            event.data.blktabs.resetTabStatus();
        });

        // block tabs click 事件
        $(BtnSel, this._tabs).on('click', { blktabs: this }, function (event) {
            var element = $(event.target).is('li') ? $(ValSel, event.target).get(0) : event.target;
            if ($(element).attr('href').startsWith('#')) {
                event.preventDefault();
                event.data.blktabs.tabClick(element);
                win.dispatchEvent(new CustomEvent(Event.Click.Window, {
                    target: element,
                    detail: {
                        selector: $(element).attr('href')
                    }
                }));
            }
        });

        this.tabAppear().resetMyStatus();

        var bookmarkId = window.location.href.split('#').pop();
        if (this._element.id == bookmarkId) {
            // 錨點跳轉
            var blk = this;
            window.addEventListener("load", function (event) {

                var arrParentAndButton = function (blkId) {
                    var tab = $(BlockSel + ' [href^="#' + blkId + '"]');
                    var pblk = tab.closest(BlockSel);
                    if (pblk.length > 0 && pblk.attr('id')) {
                        // 記錄&尋找
                        var r = arrParentAndButton(pblk.attr('id'));
                        r.push([pblk, tab]);
                        return r;
                    }
                    return [];
                };
                var arr = arrParentAndButton(blk._element.id);
                for (var i in arr)
                    arr[i][0].data(DataKey).tabClick(arr[i][1].get(0));

                setTimeout(function () {
                    $("html, body").animate({
                        scrollTop: $(blk._element).offset().top
                    }, 500, 'swing', function () { });
                }, 0.5 * 1000);
            });
        }
    }

    var _proto = BlockTabs.prototype;

    _proto.tabAppear = function tabAppear() {
        if ($(BtnSel, this._tabs).length > 0)
            $(this._tabs).removeClass('d-none hide');
        return this;
    }


    // 取得 block tabs 所有關聯的 block target
    _proto.getTabSelector = function getTabSelector() {
        return $(BtnSel + ValSel, this._tabs).map(function (i, o) {
            return $(o).attr('href');
        }).get().join(',');
    }

    // 驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetTabStatus = function resetTabStatus(event) {
        $(this.getTabSelector()).each(function () {
            if ($(this).data(DataKey))
                $(this).data(DataKey).resetMyStatus();
        });
        return this;
    }

    // 向上檢查 Block 本身需不需要顯示, 並驅動所有關聯的 block target 執行 resetMyStatus
    _proto.resetMyStatus = function resetMyStatus() {
        var sel1 = BlockSel + ':visible:not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel1 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 而且是顯示在畫面的 blkTab li >  a
            sel2 = BlockSel + ':not(.' + ReplacedBeforeSymbol + ') [href$="' + this._element.id + '"]',
            // sel2 是指那些指向 this._element(非ReplacedBeforeSymbol) 本身, 不管是否顯示在畫面的 blkTab li >  a
            sel3 = BlockSel + '.' + DestroyBeforeSymbol + ' [href$="' + this._element.id + '"]';
            // sel3 是指那些指向即將被刪除的 this._element 本身的 blkTab li >  a

        if ($(sel1).hasClass(Options.focus) || $(sel2).length < 1 || $(sel3).length > 0) {
            // 顯示 element
            this._element.style.setProperty('display', '');

            // 點擊第一個 tab 或者顯示原本已經被點擊的 tab
            let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);
            if ($tabLink.length < 1)
                $tabLink = $(BtnSel + ValSel, this._tabs);
            this.tabClick($tabLink.get(0));
            $(this._element).trigger(Event.BlockAppear);
        }
        else {
            // 隱藏 element
            this._element.style.setProperty('display', 'none', 'important');
            $(this._element).trigger(Event.BlockHidden);
        }

        return this.resetTabStatus();
    }

    // 點擊 block tabs
    _proto.tabClick = function tabClick(currentBtn, closure) {

        // 點擊執行內容
        if ($.contains(this._element, currentBtn)) {

            // tab 切換前
            $(this._element).trigger(Event.Click.Before, [currentBtn]);

            $(BtnSel + ValSel, this._tabs).removeClass(Options.focus);
            $(currentBtn).addClass(Options.focus);

            this.resetTabStatus();

            // tab 切換後
            $(this._element).trigger(Event.Click.After, [currentBtn]);

            if (typeof (closure) === "function")
                closure();
        }

        return this;
    }

    if (typeof $.fn.blockTab !== 'function') {

        $.fn.extend({
            blockTab: function (options) {
                this.filter(function (i, o) {
                    return !$(o).data(DataKey) || $(o).data(DataKey)._element != o;
                }).each(function (event) {
                    $(this).data(DataKey, new BlockTabs(this, options));
                });
            }
        });
    }

    $(function () {
        $(BlockSel).blockTab();
    });

}(jQuery, window);; })(jQuery);/* compress error:[385]let $tabLink = $(BtnSel + ValSel + '.' + Options.focus, this._tabs);*/
/* MODULE d0435c91-6b4a-44c2-8210-77336a6f6d9d, Version: 1.4.1 */
;(function($) {var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");

// NB: does not validate input
function encode(int) {
    if (int === 0) {
        return CHARSET[0];
    }

    var res = "";
    while (int > 0) {
        res = CHARSET[int % 62] + res;
        int = Math.floor(int / 62);
    }
    return res;
};

function decode(str) {
    var res = 0,
        length = str.length,
        i, char;
    for (i = 0; i < length; i++) {
        char = str.charCodeAt(i);
        if (char < 58) { // 0-9
            char = char - 48;
        } else if (char < 91) { // A-Z
            char = char - 29;
        } else { // a-z
            char = char - 87;
        }
        res += char * Math.pow(62, length - i - 1);
    }
    return res;
};

function base62() {
    var id; //base62
    do {
      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
    } while (id.match(/^[0-9]/i) !== null);
    return id;
}(function($) {
    $(function() {
    	$('[data-unicode="mdu_zWEVIxXlXkaAZ0AOGqhHuQ"]').each (function () {
			$sel = $(this);
			var $id = base62();
	        $sel.attr('id',$id);

	        var $navbarHoverBg = $sel.data('navbarHoverBg');
			var $navbarHoverColor = $sel.data('navbarHoverColor');
			var $dropdownHover = $sel.data('dropdownHover');
			$sel.find('[data-toggle="collapse"]').attr('data-target','#collapse_'+$id);
			$sel.find('#navbarSupportedContent').attr('id','collapse_'+$id);
        	
        	$sel.prepend('<style type="text/css">'+
	        '#'+$id+' .header-part .navbar-nav li a:hover {color:'+$navbarHoverColor+' !important;} '+
	        '#'+$id+' .header-part .navbar-nav li a:hover {background-color:'+$navbarHoverBg+' !important;} '+
	        '#'+$id+' .header-part .dropdown.show {color:'+$navbarHoverColor+' !important;} '+
	        '#'+$id+' .header-part .dropdown.show {background-color:'+$navbarHoverBg+' !important;} '+
	        '#'+$id+' .header-part .dropdown.show a:hover {background-color:'+$dropdownHover+' !important;}'
			+'</style>');
			  
			function onthescroll() {
				var $sel = $(this);
				var scroll = $(window).scrollTop();
				$sel.children('nav').each(function () {
					var $nav = $(this);
					if(Math.round(scroll) == 0) {
						$nav.css('max-width', '')
						$nav.parent().css('min-height', '')
						$nav.removeClass('fixed-top').removeClass('m-auto');
					}
					else if(Math.round(scroll) > Math.round($nav.offset().top)) {
						$nav.parent().css('min-height', $nav.height() + "px")
						$nav.css('max-width', $nav.outerWidth() + "px")
						$nav.addClass('fixed-top m-auto');
					}
				});
			}

			$(window).scroll(onthescroll.bind(this));
		});
    });
})(jQuery);; })(jQuery);/* compress error:[4]function encode(int) {*/

/* MODULE 4d5d14c2-5508-4ce2-907f-f7133f76da2a, Version: 1.1.1 */
(function(a){a(function(){a(".mdu_ixpuyQfSU7UwZ75sYHzQ").each(function(b){})})})(jQuery);
/* MODULE bc4f5320-b349-431d-b5c0-4b52b12fed62, Version: 2.3.5 */
;(function($) {var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");

// NB: does not validate input
function encode(int) {
    if (int === 0) {
        return CHARSET[0];
    }

    var res = "";
    while (int > 0) {
        res = CHARSET[int % 62] + res;
        int = Math.floor(int / 62);
    }
    return res;
};

function decode(str) {
    var res = 0,
        length = str.length,
        i, char;
    for (i = 0; i < length; i++) {
        char = str.charCodeAt(i);
        if (char < 58) { // 0-9
            char = char - 48;
        } else if (char < 91) { // A-Z
            char = char - 29;
        } else { // a-z
            char = char - 87;
        }
        res += char * Math.pow(62, length - i - 1);
    }
    return res;
};(function($) {
	$(function() {

		$('[data-unicode="mdu_fSaWcKR4J0SK7mfrEGGtQ"]').each (function () {

			var $sel = $(this);
			var $color2 = $(this).data('li-after');
			var $color3 = $(this).data('hover-li');
			var $color4 = $(this).data('hover-hover');
			var id; //base62
		        do {
		          id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
		        } while (id.match(/^[0-9]/i) !== null);
		    $sel.attr('id',id);

			$sel.on('click', '.menu-button', function(event){
				$(this).next('ul').toggleClass('open');
			});

			var $sel2 = $sel.children('.responsive-drop-down-menu').children('ul').children('li');
			$sel2.on('click', function(){
				$sel2.removeClass('active').addClass('off');
				$(this).removeClass('off').addClass('active');

				if($('.has-sub')) {
					$('.off').children('ul').removeAttr('style');
					$(this).children('ul').css("display","block");

					$(this).find('a').on('click', function(){
						$(this).next('ul').css("display","block");
					});
				}
			});

			$sel.prepend('<style type="text/css">'+
				'#'+id+' .responsive-drop-down-menu > ul > li > ul > li {background:'+$color2+' !important;} '+
				'#'+id+' .responsive-drop-down-menu > ul > li:after {background:'+$color2+' !important;} '+
				'#'+id+' .responsive-drop-down-menu ul li ul li:hover:after {background:'+$color2+' !important;} '+
				'#'+id+' .responsive-drop-down-menu ul li ul li.active:after {background:'+$color2+' !important;} '+
				'#'+id+' .responsive-drop-down-menu ul li ul li:hover > ul > li {background:'+$color3+' !important;} '+
				'#'+id+' .responsive-drop-down-menu > ul > li:hover > ul > li:hover {background:'+$color3+' !important;} '+
				'#'+id+' .responsive-drop-down-menu ul li ul li:hover > ul > li:hover {background:'+$color4+' !important;}'
			+'</style>');
/*
			if($sel.data('li-after'))
	        	$sel.prepend('<style type="text/css">#'+id+' .responsive-drop-down-menu > ul > li:after, #'+id+' .full-menu .responsive-drop-down-menu ul li ul li:hover:after, #'+id+ '.full-menu .responsive-drop-down-menu ul li ul li.active:after {background:'+$(this).data('li-after')+ !important;'}</style>');
	        if($sel.data('hover-li'))
	        	$sel.prepend('<style type="text/css">#'+id+' .full-menu .responsive-drop-down-menu ul li ul li:hover > ul > li, #'+id+ '.full-menu .responsive-drop-down-menu > ul > li:hover > ul > li:hover {background:'+$(this).data('hover-li')+' !important;}</style>');
	        if($sel.data('hover-hover'))
	        	$sel.prepend('<style type="text/css">#'+id+' .full-menu .responsive-drop-down-menu ul li ul li:hover > ul > li:hover {background:'+$(this).data('hover-hover')+' !important;}</style>');
*/
		});

	});
})(jQuery);
; })(jQuery);/* compress error:[4]function encode(int) {*/

/* MODULE 00c188ed-cbd7-4c68-87dd-d3e4f1ac9a2e, Version: 1.0.7 */
;(function($) {var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");

// NB: does not validate input
function encode(int) {
    if (int === 0) {
        return CHARSET[0];
    }

    var res = "";
    while (int > 0) {
        res = CHARSET[int % 62] + res;
        int = Math.floor(int / 62);
    }
    return res;
};

function decode(str) {
    var res = 0,
        length = str.length,
        i, char;
    for (i = 0; i < length; i++) {
        char = str.charCodeAt(i);
        if (char < 58) { // 0-9
            char = char - 48;
        } else if (char < 91) { // A-Z
            char = char - 29;
        } else { // a-z
            char = char - 87;
        }
        res += char * Math.pow(62, length - i - 1);
    }
    return res;
};

function base62() {
    var id; //base62
    do {
      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
    } while (id.match(/^[0-9]/i) !== null);
    return id;
}(function($) {
    $(function() {
    	$('[data-unicode="mdu_BdWUgPtDtEyiOxg4ogUdMg"]').each (function () {
		  var $sel = $(this);
		  var id; //base62
		      do {
		        id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
		      } while (id.match(/^[0-9]/i) !== null);
		  $sel.attr('id',id);

		  $sel.children('.btm-btn').each (function (i) {
			  	var $sel2 = $(this);
			  	var id2 = id+'_'+i;
			  	$sel2.addClass(id2);
			  	if($sel2.hasClass('open-btn')) {
			  		$sel2.attr('id',id2);
			  		$sel2.next('div').attr('id',id2+'_box');
			  		$sel2.next('div').children('.close-line').attr('id',id2+'_close');
			  	}

			  	var $fontColor = $sel2.data('fontColor');
			  	var $nowColor = $sel2.data('nowColor');
			  	var $img = $sel2.data('img');
			  	var $nowImg = $sel2.data('nowImg');
			  	var $imgY = $sel2.data('imgY');
			  	var $imgSize = $sel2.data('imgSize');

			  	$sel.prepend('<style type="text/css">'+
		        '#'+id+' '+'.'+id2+' {background: url("'+$img+'") no-repeat center '+$imgY+'; background-size: '+$imgSize+';}'+
		        '\n'+'#'+id+' '+'.'+id2+'-now {color: '+$nowColor+' !important; background: #eee url("'+$nowImg+'") no-repeat center '+$imgY+'; background-size: '+$imgSize+';}'+
		      	'</style>');

		  });

		  $('.open-btn').on('click', function () {
	            var $btnID = $(this).attr('id');
	            var $boxID = $btnID + '_box';
	            var $btnClass = $(this).attr('class');
	            var $btnNowClass = $btnID+'-now';
	            var $closeLineID = $(this).next('div').find('.close-line').attr('id');

	            $('.open-btn[class$="-now"]').each (function () {
	            	var $orgClass = $(this).attr('class');
	            	var $repClass = $orgClass.replace('-now','');
	            	$(this).removeClass().addClass($repClass);
	            });

	            $(this).toggleClass($btnNowClass);
	            
	            $('.open-box').not('#'+$boxID).hide();
	            $('#'+$boxID).toggle('show');

	            $('#'+$closeLineID).on('click', function () {
	            	$('#'+$boxID).hide();
	            	$('#'+$btnID).removeClass().addClass($btnClass);
	      	  	});

      	  });


		});

    });
})(jQuery);

; })(jQuery);/* compress error:[4]function encode(int) {*/

/* MODULE 58743bdd-4834-4c24-8654-c9add486cba1, Version: 1.2.6 */
(function(a){(function(b){b(function(){b('[data-unicode="mdu_BrLf6K1K0kWJYBBkZy8NWA"]').each(function(){var c=b(this);c.find(".footer-sample a").hover(function(){var d=c.data("hover");b(this).css("color",d)},function(){var d=c.data("link");b(this).css("color",d)})})})})(jQuery)})(jQuery);
/* MODULE 94105903-4a46-498d-8b55-7c28d991e678, Version: 1.1.11 */
;(function($) {; var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");

// NB: does not validate input
function encode(int) {
    if (int === 0) {
        return CHARSET[0];
    }

    var res = "";
    while (int > 0) {
        res = CHARSET[int % 62] + res;
        int = Math.floor(int / 62);
    }
    return res;
};

function decode(str) {
    var res = 0,
        length = str.length,
        i, char;
    for (i = 0; i < length; i++) {
        char = str.charCodeAt(i);
        if (char < 58) { // 0-9
            char = char - 48;
        } else if (char < 91) { // A-Z
            char = char - 29;
        } else { // a-z
            char = char - 87;
        }
        res += char * Math.pow(62, length - i - 1);
    }
    return res;
};

function base62() {
    var id; //base62
    do {
      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
    } while (id.match(/^[0-9]/i) !== null);
    return id;
}/*! Hammer.JS - v2.0.8 - 2016-04-23
 * http://hammerjs.github.io/
 *
 * Copyright (c) 2016 Jorik Tangelder;
 * Licensed under the MIT license */
!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;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");
//# sourceMappingURL=hammer.min.js.map

(function(factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery', 'hammerjs'], factory);
    } else if (typeof exports === 'object') {
        factory(require('jquery'), require('hammerjs'));
    } else {
        factory(jQuery, Hammer);
    }
}(function($, Hammer) {
    function hammerify(el, options) {
        var $el = $(el);
        if(!$el.data("hammer")) {
            $el.data("hammer", new Hammer($el[0], options));
        }
    }

    $.fn.hammer = function(options) {
        return this.each(function() {
            hammerify(this, options);
        });
    };

    // extend the emit method to also trigger jQuery events
    Hammer.Manager.prototype.emit = (function(originalEmit) {
        return function(type, data) {
            originalEmit.call(this, type, data);
            $(this.element).trigger({
                type: type,
                gesture: data
            });
        };
    })(Hammer.Manager.prototype.emit);
}));


(function($) {
    $(function() {
    	let $sel = $('[data-unicode="mdu_9Iu5OSvpN0XY2tSlQsmpw"]');
        $sel.each (function () {
          let $id = base62();
    	  let $self = $(this);
    	  $self.children('.carousel').attr('id',$id);

			function runBs4Slider () {
				$("#"+$id).find('.carousel-indicators li').attr('data-target','#'+$id);
				$("#"+$id).find('.carousel-control-prev').attr('href','#'+$id);
				$("#"+$id).find('.carousel-control-next').attr('href','#'+$id);
				$("#"+$id).find('.carousel-item:first-child').addClass('active');
				$("#"+$id).find('.carousel-ctl:first-child').addClass('active');

				$("#"+$id).hammer().on('swipeleft', function(){  
				$(this).carousel('next');  
				});  

				$("#"+$id).hammer().on('swiperight', function(){  
				$(this).carousel('prev');
				});
			}
          
        	function lazyBs4Slider () {
        		var lazyLoadBs4Slider = new LazyLoad({
		            elements_selector: '#'+$id+' .lazyload'
	            });

				lazyLoadBs4Slider.loadAll();
			}
			function lazyBs4SliderGo (callback) {
				var lazyRunBs4Slider = new LazyLoad({
					elements_selector: '#'+$id+' .lazyload',
					callback_loaded: function() {
						$("#"+$id).find('.carousel-indicators li').each (function (index) {
				        	$(this).attr('data-slide-to', index);
				        });
						lazyBs4Slider();
					}
				});
				callback();
			}
			lazyBs4SliderGo(runBs4Slider);

        });

    });
})(jQuery);

; })(jQuery);/* compress error:[4]function encode(int) {*/

/* MODULE f03d32d0-b28d-4580-8460-3adfc9a12677, Version: 1.3.20 */
(function(a){(function(b){b(function(){var c=new LazyLoad({elements_selector:".lazypic"})})})(jQuery)})(jQuery);
/* MODULE c25db670-6826-4e3a-97b6-7a6ff192b176, Version: 1.1.7 */
;(function($) {; var CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");

// NB: does not validate input
function encode(int) {
    if (int === 0) {
        return CHARSET[0];
    }

    var res = "";
    while (int > 0) {
        res = CHARSET[int % 62] + res;
        int = Math.floor(int / 62);
    }
    return res;
};

function decode(str) {
    var res = 0,
        length = str.length,
        i, char;
    for (i = 0; i < length; i++) {
        char = str.charCodeAt(i);
        if (char < 58) { // 0-9
            char = char - 48;
        } else if (char < 91) { // A-Z
            char = char - 29;
        } else { // a-z
            char = char - 87;
        }
        res += char * Math.pow(62, length - i - 1);
    }
    return res;
};

function base62() {
    var id; //base62
    do {
      id = encode(Math.floor(Math.random() * Math.pow(1000, 4) + 1));
    } while (id.match(/^[0-9]/i) !== null);
    return id;
}if (typeof jQuery === 'undefined') {
    throw new Error('More Button\'s JavaScript requires jQuery')
}

+function ($) {
    'use strict';
    var version = $.fn.jquery.split(' ')[0].split('.')
    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
        throw new Error('More Button\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
    }
}(jQuery);

+function ($) {
    'use strict';

    var DATA_KEY = 'widget.moreButton',
        OPTS = {
			defaultShow: 9, // 一開始顯示的數量
			elementSel: '[data-rel="moreButton"]',
			itemSel: '.item-box',
			moreSel: '.more.btn'
        };

    function MoreButton(element, opts) {

        var self = this;
        this._element = element;
		this._opts = $.extend(OPTS, $(this._element).data(), opts);
		
		var $items =  $(this._opts.itemSel, this._element);
		// 顯示或隱藏 btn
		($items.length > this._opts.defaultShow) ? $(this._opts.moreSel, this._element).show() : $(this._opts.moreSel, this._element).hide();
		// 超過一開始顯示的數量的項目隱藏
		$items.slice(this._opts.defaultShow).hide();
		// 點擊更多按鈕
		$(this._element).on('click', this._opts.moreSel, { $items: $items }, function(event) {
			event.preventDefault()
			event.data.$items.filter(":hidden").slideDown();
			$(this).hide();
		});
    }

    var _proto = MoreButton.prototype;

    if(typeof $.fn.moreButton !== "function") {
        $.fn.moreButton = function() {
            return this.each(function() {
                if (!$(this).data(DATA_KEY))
                    $(this).data(DATA_KEY, new MoreButton(this, {}));
            });
        };
    }
    
    $(function () {
        // do something onload...
        $(OPTS.elementSel).moreButton();
	})

}(jQuery);(function($) {
    $(function() {

	    let $sel = $('[data-unicode="mdu_Q3sPT5e50kyFpVmz9td8FA"]');
	    $sel.each (function () {
	    	let $id = base62();
	    	let $self = $(this).attr('id',$id);
	    	var lazyLoadInstance = new LazyLoad({
	    	elements_selector: '#'+$id+' .lazyload',
	    	callback_loaded: function() {
		        	$self.moreButton({
						// defaultShow: 9,          // 預設顯示數量, 可以在html屬性指定 data-default-show="6"
						// itemSel: '.item-box',    // 項目選擇器, 可以在html屬性指定 data-item-sel=".item-box"
						// moreSel: '.more.btn'     // 更多按鈕, 可以在html屬性指定 data-more-sel=".more.btn"
			        });
	    		}
	    	});
	    });

  	});
})(jQuery);

; })(jQuery);/* compress error:[4]function encode(int) {*/

