PageSourceSearch

https://www.levecchiecantine.it/wp-content/themes/jupiter/assets/js/core-scripts.6.10.6.js?ver=1697610140

js levecchiecantine.it collected 2026-10-06 12:18:04 UTC 554,474 bytes, 18,231 lines download raw bytes

1(function($) {// v5 namespace 
2var MK = {
3	api 		: {},
4	ui 			: {},
5	component 	: {},
6};
7
8// Global 
9window.MK = MK;
10'use strict';
11
12
13console.log( 23423 );
14/**
15 * Copyright Marc J. Schmidt. See the LICENSE file at the top-level
16 * directory of this distribution and at
17 * https://github.com/marcj/css-element-queries/blob/master/LICENSE.
18 */
19(function (root, factory) {
20    if (typeof define === "function" && define.amd) {
21        define(factory);
22    } else if (typeof exports === "object") {
23        module.exports = factory();
24    } else {
25        root.ResizeSensor = factory();
26    }
27}(typeof window !== 'undefined' ? window : this, function () {
28
29    // Make sure it does not throw in a SSR (Server Side Rendering) situation
30    if (typeof window === "undefined") {
31        return null;
32    }
33    // Only used for the dirty checking, so the event callback count is limited to max 1 call per fps per sensor.
34    // In combination with the event based resize sensor this saves cpu time, because the sensor is too fast and
35    // would generate too many unnecessary events.
36    var requestAnimationFrame = window.requestAnimationFrame ||
37        window.mozRequestAnimationFrame ||
38        window.webkitRequestAnimationFrame ||
39        function (fn) {
40            return window.setTimeout(fn, 20);
41        };
42
43    /**
44     * Iterate over each of the provided element(s).
45     *
46     * @param {HTMLElement|HTMLElement[]} elements
47     * @param {Function}                  callback
48     */
49    function forEachElement(elements, callback){
50        var elementsType = Object.prototype.toString.call(elements);
51        var isCollectionTyped = ('[object Array]' === elementsType
52            || ('[object NodeList]' === elementsType)
53            || ('[object HTMLCollection]' === elementsType)
54            || ('[object Object]' === elementsType)
55            || ('undefined' !== typeof jQuery && elements instanceof jQuery) //jquery
56            || ('undefined' !== typeof Elements && elements instanceof Elements) //mootools
57        );
58        var i = 0, j = elements.length;
59        if (isCollectionTyped) {
60            for (; i < j; i++) {
61                callback(elements[i]);
62            }
63        } else {
64            callback(elements);
65        }
66    }
67
68    /**
69    * Get element size
70    * @param {HTMLElement} element
71    * @returns {Object} {width, height}
72    */
73    function getElementSize(element) {
74        if (!element.getBoundingClientRect) {
75            return {
76                width: element.offsetWidth,
77                height: element.offsetHeight
78            }
79        }
80
81        var rect = element.getBoundingClientRect();
82        return {
83            width: Math.round(rect.width),
84            height: Math.round(rect.height)
85        }
86    }
87
88    /**
89     * Class for dimension change detection.
90     *
91     * @param {Element|Element[]|Elements|jQuery} element
92     * @param {Function} callback
93     *
94     * @constructor
95     */
96    var ResizeSensor = function(element, callback) {
97        /**
98         *
99         * @constructor
100         */
101        function EventQueue() {
102            var q = [];
103            this.add = function(ev) {
104                q.push(ev);
105            };
106
107            var i, j;
108            this.call = function() {
109                for (i = 0, j = q.length; i < j; i++) {
110                    q[i].call();
111                }
112            };
113
114            this.remove = function(ev) {
115                var newQueue = [];
116                for(i = 0, j = q.length; i < j; i++) {
117                    if(q[i] !== ev) newQueue.push(q[i]);
118                }
119                q = newQueue;
120            };
121
122            this.length = function() {
123                return q.length;
124            }
125        }
126
127        /**
128         *
129         * @param {HTMLElement} element
130         * @param {Function}    resized
131         */
132        function attachResizeEvent(element, resized) {
133            if (!element) return;
134            if (element.resizedAttached) {
135                element.resizedAttached.add(resized);
136                return;
137            }
138
139            element.resizedAttached = new EventQueue();
140            element.resizedAttached.add(resized);
141
142            element.resizeSensor = document.createElement('div');
143            element.resizeSensor.dir = 'ltr';
144            element.resizeSensor.className = 'resize-sensor';
145            var style = 'position: absolute; left: -10px; top: -10px; right: 0; bottom: 0; overflow: hidden; z-index: -1; visibility: hidden;';
146            var styleChild = 'position: absolute; left: 0; top: 0; transition: 0s;';
147
148            element.resizeSensor.style.cssText = style;
149            element.resizeSensor.innerHTML =
150                '<div class="resize-sensor-expand" style="' + style + '">' +
151                    '<div style="' + styleChild + '"></div>' +
152                '</div>' +
153                '<div class="resize-sensor-shrink" style="' + style + '">' +
154                    '<div style="' + styleChild + ' width: 200%; height: 200%"></div>' +
155                '</div>';
156            element.appendChild(element.resizeSensor);
157
158            var position = window.getComputedStyle(element).getPropertyPriority('position');
159            if ('absolute' !== position && 'relative' !== position && 'fixed' !== position) {
160                element.style.position = 'relative';
161            }
162
163            var expand = element.resizeSensor.childNodes[0];
164            var expandChild = expand.childNodes[0];
165            var shrink = element.resizeSensor.childNodes[1];
166            var dirty, rafId, newWidth, newHeight;
167            var size = getElementSize(element);
168            var lastWidth = size.width;
169            var lastHeight = size.height;
170
171            var reset = function() {
172                //set display to block, necessary otherwise hidden elements won't ever work
173                var invisible = element.offsetWidth === 0 && element.offsetHeight === 0;
174
175                if (invisible) {
176                    var saveDisplay = element.style.display;
177                    element.style.display = 'block';
178                }
179
180                expandChild.style.width = '100000px';
181                expandChild.style.height = '100000px';
182
183                expand.scrollLeft = 100000;
184                expand.scrollTop = 100000;
185
186                shrink.scrollLeft = 100000;
187                shrink.scrollTop = 100000;
188
189                if (invisible) {
190                    element.style.display = saveDisplay;
191                }
192            };
193            element.resizeSensor.resetSensor = reset;
194
195            var onResized = function() {
196                rafId = 0;
197
198                if (!dirty) return;
199
200                lastWidth = newWidth;
201                lastHeight = newHeight;
202
203                if (element.resizedAttached) {
204                    element.resizedAttached.call();
205                }
206            };
207
208            var onScroll = function() {
209                var size = getElementSize(element);
210                var newWidth = size.width;
211                var newHeight = size.height;
212                dirty = newWidth != lastWidth || newHeight != lastHeight;
213
214                if (dirty && !rafId) {
215                    rafId = requestAnimationFrame(onResized);
216                }
217
218                reset();
219            };
220
221            var addEvent = function(el, name, cb) {
222                if (el.attachEvent) {
223                    el.attachEvent('on' + name, cb);
224                } else {
225                    el.addEventListener(name, cb);
226                }
227            };
228
229            addEvent(expand, 'scroll', onScroll);
230            addEvent(shrink, 'scroll', onScroll);
231
232			// Fix for custom Elements
233			requestAnimationFrame(reset);
234        }
235
236        forEachElement(element, function(elem){
237            attachResizeEvent(elem, callback);
238        });
239
240        this.detach = function(ev) {
241            ResizeSensor.detach(element, ev);
242        };
243
244        this.reset = function() {
245            element.resizeSensor.resetSensor();
246        };
247    };
248
249    ResizeSensor.reset = function(element, ev) {
250        forEachElement(element, function(elem){
251            elem.resizeSensor.resetSensor();
252        });
253    };
254
255    ResizeSensor.detach = function(element, ev) {
256        forEachElement(element, function(elem){
257            if (!elem) return;
258            if(elem.resizedAttached && typeof ev === "function"){
259                elem.resizedAttached.remove(ev);
260                if(elem.resizedAttached.length()) return;
261            }
262            if (elem.resizeSensor) {
263                if (elem.contains(elem.resizeSensor)) {
264                    elem.removeChild(elem.resizeSensor);
265                }
266                delete elem.resizeSensor;
267                delete elem.resizedAttached;
268            }
269        });
270    };
271
272    return ResizeSensor;
273
274}));
275
276'use strict';
277
278/**
279 * Copyright Marc J. Schmidt. See the LICENSE file at the top-level
280 * directory of this distribution and at
281 * https://github.com/marcj/css-element-queries/blob/master/LICENSE.
282 */
283(function (root, factory) {
284    if (typeof define === "function" && define.amd) {
285        define(['./ResizeSensor.js'], factory);
286    } else if (typeof exports === "object") {
287        module.exports = factory(require('./ResizeSensor.js'));
288    } else {
289        root.ElementQueries = factory(root.ResizeSensor);
290        root.ElementQueries.listen();
291    }
292}(typeof window !== 'undefined' ? window : this, function (ResizeSensor) {
293
294    /**
295     *
296     * @type {Function}
297     * @constructor
298     */
299    var ElementQueries = function () {
300        //<style> element with our dynamically created styles
301        var cssStyleElement;
302
303        //all rules found for element queries
304        var allQueries = {};
305
306        //association map to identify which selector belongs to a element from the animationstart event.
307        var idToSelectorMapping = [];
308
309        /**
310         *
311         * @param element
312         * @returns {Number}
313         */
314        function getEmSize(element) {
315            if (!element) {
316                element = document.documentElement;
317            }
318            var fontSize = window.getComputedStyle(element, null).fontSize;
319            return parseFloat(fontSize) || 16;
320        }
321
322        /**
323         * Get element size
324         * @param {HTMLElement} element
325         * @returns {Object} {width, height}
326         */
327        function getElementSize(element) {
328            if (!element.getBoundingClientRect) {
329                return {
330                    width: element.offsetWidth,
331                    height: element.offsetHeight
332                }
333            }
334
335            var rect = element.getBoundingClientRect();
336            return {
337                width: Math.round(rect.width),
338                height: Math.round(rect.height)
339            }
340        }
341
342        /**
343         *
344         * @copyright https://github.com/Mr0grog/element-query/blob/master/LICENSE
345         *
346         * @param {HTMLElement} element
347         * @param {*} value
348         * @returns {*}
349         */
350        function convertToPx(element, value) {
351            var numbers = value.split(/\d/);
352            var units = numbers[numbers.length - 1];
353            value = parseFloat(value);
354            switch (units) {
355                case "px":
356                    return value;
357                case "em":
358                    return value * getEmSize(element);
359                case "rem":
360                    return value * getEmSize();
361                // Viewport units!
362                // According to http://quirksmode.org/mobile/tableViewport.html
363                // documentElement.clientWidth/Height gets us the most reliable info
364                case "vw":
365                    return value * document.documentElement.clientWidth / 100;
366                case "vh":
367                    return value * document.documentElement.clientHeight / 100;
368                case "vmin":
369                case "vmax":
370                    var vw = document.documentElement.clientWidth / 100;
371                    var vh = document.documentElement.clientHeight / 100;
372                    var chooser = Math[units === "vmin" ? "min" : "max"];
373                    return value * chooser(vw, vh);
374                default:
375                    return value;
376                // for now, not supporting physical units (since they are just a set number of px)
377                // or ex/ch (getting accurate measurements is hard)
378            }
379        }
380
381        /**
382         *
383         * @param {HTMLElement} element
384         * @param {String} id
385         * @constructor
386         */
387        function SetupInformation(element, id) {
388            this.element = element;
389            var key, option, elementSize, value, actualValue, attrValues, attrValue, attrName;
390
391            var attributes = ['min-width', 'min-height', 'max-width', 'max-height'];
392
393            /**
394             * Extracts the computed width/height and sets to min/max- attribute.
395             */
396            this.call = function () {
397                // extract current dimensions
398                elementSize = getElementSize(this.element);
399
400                attrValues = {};
401
402                for (key in allQueries[id]) {
403                    if (!allQueries[id].hasOwnProperty(key)) {
404                        continue;
405                    }
406                    option = allQueries[id][key];
407
408                    value = convertToPx(this.element, option.value);
409
410                    actualValue = option.property === 'width' ? elementSize.width : elementSize.height;
411                    attrName = option.mode + '-' + option.property;
412                    attrValue = '';
413
414                    if (option.mode === 'min' && actualValue >= value) {
415                        attrValue += option.value;
416                    }
417
418                    if (option.mode === 'max' && actualValue <= value) {
419                        attrValue += option.value;
420                    }
421
422                    if (!attrValues[attrName]) attrValues[attrName] = '';
423                    if (attrValue && -1 === (' ' + attrValues[attrName] + ' ').indexOf(' ' + attrValue + ' ')) {
424                        attrValues[attrName] += ' ' + attrValue;
425                    }
426                }
427
428                for (var k in attributes) {
429                    if (!attributes.hasOwnProperty(k)) continue;
430
431                    if (attrValues[attributes[k]]) {
432                        this.element.setAttribute(attributes[k], attrValues[attributes[k]].substr(1));
433                    } else {
434                        this.element.removeAttribute(attributes[k]);
435                    }
436                }
437            };
438        }
439
440        /**
441         * @param {HTMLElement} element
442         * @param {Object}      id
443         */
444        function setupElement(element, id) {
445            if (!element.elementQueriesSetupInformation) {
446                element.elementQueriesSetupInformation = new SetupInformation(element, id);
447            }
448            if (!element.elementQueriesSensor) {
449                element.elementQueriesSensor = new ResizeSensor(element, function () {
450                    element.elementQueriesSetupInformation.call();
451                });
452            }
453
454            element.elementQueriesSetupInformation.call();
455        }
456
457        /**
458         * Stores rules to the selector that should be applied once resized.
459         *
460         * @param {String} selector
461         * @param {String} mode min|max
462         * @param {String} property width|height
463         * @param {String} value
464         */
465        function queueQuery(selector, mode, property, value) {
466            if (typeof(allQueries[selector]) === 'undefined') {
467                allQueries[selector] = [];
468                // add animation to trigger animationstart event, so we know exactly when a element appears in the DOM
469
470                var id = idToSelectorMapping.length;
471                cssStyleElement.innerHTML += '\n' + selector + ' {animation: 0.1s element-queries;}';
472                cssStyleElement.innerHTML += '\n' + selector + ' > .resize-sensor {min-width: '+id+'px;}';
473                idToSelectorMapping.push(selector);
474            }
475
476            allQueries[selector].push({
477                mode: mode,
478                property: property,
479                value: value
480            });
481        }
482
483        function getQuery(container) {
484            var query;
485            if (document.querySelectorAll) query = (container) ? container.querySelectorAll.bind(container) : document.querySelectorAll.bind(document);
486            if (!query && 'undefined' !== typeof $$) query = $$;
487            if (!query && 'undefined' !== typeof jQuery) query = jQuery;
488
489            if (!query) {
490                throw 'No document.querySelectorAll, jQuery or Mootools\'s $$ found.';
491            }
492
493            return query;
494        }
495
496        /**
497         * If animationStart didn't catch a new element in the DOM, we can manually search for it
498         */
499        function findElementQueriesElements(container) {
500            var query = getQuery(container);
501
502            for (var selector in allQueries) if (allQueries.hasOwnProperty(mode)) {
503                // find all elements based on the extract query selector from the element query rule
504                var elements = query(selector, container);
505
506                for (var i = 0, j = elements.length; i < j; i++) {
507                    setupElement(elements[i], selector);
508                }
509            }
510        }
511
512        /**
513         *
514         * @param {HTMLElement} element
515         */
516        function attachResponsiveImage(element) {
517            var children = [];
518            var rules = [];
519            var sources = [];
520            var defaultImageId = 0;
521            var lastActiveImage = -1;
522            var loadedImages = [];
523
524            for (var i in element.children) {
525                if (!element.children.hasOwnProperty(i)) continue;
526
527                if (element.children[i].tagName && element.children[i].tagName.toLowerCase() === 'img') {
528                    children.push(element.children[i]);
529
530                    var minWidth = element.children[i].getAttribute('min-width') || element.children[i].getAttribute('data-min-width');
531                    //var minHeight = element.children[i].getAttribute('min-height') || element.children[i].getAttribute('data-min-height');
532                    var src = element.children[i].getAttribute('data-src') || element.children[i].getAttribute('url');
533
534                    sources.push(src);
535
536                    var rule = {
537                        minWidth: minWidth
538                    };
539
540                    rules.push(rule);
541
542                    if (!minWidth) {
543                        defaultImageId = children.length - 1;
544                        element.children[i].style.display = 'block';
545                    } else {
546                        element.children[i].style.display = 'none';
547                    }
548                }
549            }
550
551            lastActiveImage = defaultImageId;
552
553            function check() {
554                var imageToDisplay = false, i;
555
556                for (i in children) {
557                    if (!children.hasOwnProperty(i)) continue;
558
559                    if (rules[i].minWidth) {
560                        if (element.offsetWidth > rules[i].minWidth) {
561                            imageToDisplay = i;
562                        }
563                    }
564                }
565
566                if (!imageToDisplay) {
567                    //no rule matched, show default
568                    imageToDisplay = defaultImageId;
569                }
570
571                if (lastActiveImage !== imageToDisplay) {
572                    //image change
573
574                    if (!loadedImages[imageToDisplay]) {
575                        //image has not been loaded yet, we need to load the image first in memory to prevent flash of
576                        //no content
577
578                        var image = new Image();
579                        image.onload = function () {
580                            children[imageToDisplay].src = sources[imageToDisplay];
581
582                            children[lastActiveImage].style.display = 'none';
583                            children[imageToDisplay].style.display = 'block';
584
585                            loadedImages[imageToDisplay] = true;
586
587                            lastActiveImage = imageToDisplay;
588                        };
589
590                        image.src = sources[imageToDisplay];
591                    } else {
592                        children[lastActiveImage].style.display = 'none';
593                        children[imageToDisplay].style.display = 'block';
594                        lastActiveImage = imageToDisplay;
595                    }
596                } else {
597                    //make sure for initial check call the .src is set correctly
598                    children[imageToDisplay].src = sources[imageToDisplay];
599                }
600            }
601
602            element.resizeSensor = new ResizeSensor(element, check);
603            check();
604        }
605
606        function findResponsiveImages() {
607            var query = getQuery();
608
609            var elements = query('[data-responsive-image],[responsive-image]');
610            for (var i = 0, j = elements.length; i < j; i++) {
611                attachResponsiveImage(elements[i]);
612            }
613        }
614
615        var regex = /,?[\s\t]*([^,\n]*?)((?:\[[\s\t]*?(?:min|max)-(?:width|height)[\s\t]*?[~$\^]?=[\s\t]*?"[^"]*?"[\s\t]*?])+)([^,\n\s\{]*)/mg
615i;
616        var attrRegex = /\[[\s\t]*?(min|max)-(width|height)[\s\t]*?[~$\^]?=[\s\t]*?"([^"]*?)"[\s\t]*?]/mgi;
617
618        /**
619         * @param {String} css
620         */
621        function extractQuery(css) {
622            var match, smatch, attrs, attrMatch;
623
624            css = css.replace(/'/g, '"');
625            while (null !== (match = regex.exec(css))) {
626                smatch = match[1] + match[3];
627                attrs = match[2];
628
629                while (null !== (attrMatch = attrRegex.exec(attrs))) {
630                    queueQuery(smatch, attrMatch[1], attrMatch[2], attrMatch[3]);
631                }
632            }
633        }
634
635        /**
636         * @param {CssRule[]|String} rules
637         */
638        function readRules(rules) {
639            var selector = '';
640
641            if (!rules) {
642                return;
643            }
644
645            if ('string' === typeof rules) {
646                rules = rules.toLowerCase();
647                if (-1 !== rules.indexOf('min-width') || -1 !== rules.indexOf('max-width')) {
648                    extractQuery(rules);
649                }
650            } else {
651                for (var i = 0, j = rules.length; i < j; i++) {
652                    if (1 === rules[i].type) {
653                        selector = rules[i].selectorText || rules[i].cssText;
654                        if (-1 !== selector.indexOf('min-height') || -1 !== selector.indexOf('max-height')) {
655                            extractQuery(selector);
656                        } else if (-1 !== selector.indexOf('min-width') || -1 !== selector.indexOf('max-width')) {
657                            extractQuery(selector);
658                        }
659                    } else if (4 === rules[i].type) {
660                        readRules(rules[i].cssRules || rules[i].rules);
661                    } else if (3 === rules[i].type) {
662                        readRules(rules[i].styleSheet.cssRules);
663                    }
664                }
665            }
666        }
667
668        var defaultCssInjected = false;
669
670        /**
671         * Searches all css rules and setups the event listener to all elements with element query rules..
672         */
673        this.init = function () {
674            var animationStart = 'animationstart';
675            if (typeof document.documentElement.style['webkitAnimationName'] !== 'undefined') {
676                animationStart = 'webkitAnimationStart';
677            } else if (typeof document.documentElement.style['MozAnimationName'] !== 'undefined') {
678                animationStart = 'mozanimationstart';
679            } else if (typeof document.documentElement.style['OAnimationName'] !== 'undefined') {
680                animationStart = 'oanimationstart';
681            }
682
683            document.body.addEventListener(animationStart, function (e) {
684                var element = e.target;
685                var styles = window.getComputedStyle(element, null);
686
687                if (-1 !== styles.getPropertyValue('animation-name').indexOf('element-queries')) {
688                    element.elementQueriesSensor = new ResizeSensor(element, function () {
689                        if (element.elementQueriesSetupInformation) {
690                            element.elementQueriesSetupInformation.call();
691                        }
692                    });
693
694                    var sensorStyles = window.getComputedStyle(element.resizeSensor, null);
695                    var id = sensorStyles.getPropertyValue('min-width');
696                    id = parseInt(id.replace('px', ''));
697                    setupElement(e.target, idToSelectorMapping[id]);
698                }
699            });
700
701            if (!defaultCssInjected) {
702                cssStyleElement = document.createElement('style');
703                cssStyleElement.type = 'text/css';
704                cssStyleElement.innerHTML = '[responsive-image] > img, [data-responsive-image] {overflow: hidden; padding: 0; } [responsive-image] > img, [data-responsive-image] > img {width: 100%;}';
705
706                //safari wants at least one rule in keyframes to start working
707                cssStyleElement.innerHTML += '\n@keyframes element-queries { 0% { visibility: inherit; } }';
708                document.getElementsByTagName('head')[0].appendChild(cssStyleElement);
709                defaultCssInjected = true;
710            }
711
712            for (var i = 0, j = document.styleSheets.length; i < j; i++) {
713                try {
714                    if (document.styleSheets[i].href && 0 === document.styleSheets[i].href.indexOf('file://')) {
715                        console.log("CssElementQueries: unable to parse local css files, " + document.styleSheets[i].href);
716                    }
717
718                    readRules(document.styleSheets[i].cssRules || document.styleSheets[i].rules || document.styleSheets[i].cssText);
719                } catch (e) {
720                }
721            }
722
723            // findElementQueriesElements();
724            findResponsiveImages();
725        };
726
727        /**
728         * Go through all collected rules (readRules()) and attach the resize-listener.
729         * Not necessary to call it manually, since we detect automatically when new elements
730         * are available in the DOM. However, sometimes handy for dirty DOM modifications.
731         *
732         * @param {HTMLElement} container only elements of the container are considered (document.body if not set)
733         */
734        this.findElementQueriesElements = function (container) {
735            findElementQueriesElements(container);
736        };
737
738        this.update = function () {
739            this.init();
740        };
741    };
742
743    ElementQueries.update = function () {
744        ElementQueries.instance.update();
745    };
746
747    /**
748     * Removes all sensor and elementquery information from the element.
749     *
750     * @param {HTMLElement} element
751     */
752    ElementQueries.detach = function (element) {
753        if (element.elementQueriesSetupInformation) {
754            //element queries
755            element.elementQueriesSensor.detach();
756            delete element.elementQueriesSetupInformation;
757            delete element.elementQueriesSensor;
758
759        } else if (element.resizeSensor) {
760            //responsive image
761
762            element.resizeSensor.detach();
763            delete element.resizeSensor;
764        }
765    };
766
767    ElementQueries.init = function () {
768        if (!ElementQueries.instance) {
769            ElementQueries.instance = new ElementQueries();
770        }
771
772        ElementQueries.instance.init();
773    };
774
775    var domLoaded = function (callback) {
776        /* Mozilla, Chrome, Opera */
777        if (document.addEventListener) {
778            document.addEventListener('DOMContentLoaded', callback, false);
779        }
780        /* Safari, iCab, Konqueror */
781        else if (/KHTML|WebKit|iCab/i.test(navigator.userAgent)) {
782            var DOMLoadTimer = setInterval(function () {
783                if (/loaded|complete/i.test(document.readyState)) {
784                    callback();
785                    clearInterval(DOMLoadTimer);
786                }
787            }, 10);
788        }
789        /* Other web browsers */
790        else window.onload = callback;
791    };
792
793    ElementQueries.findElementQueriesElements = function (container) {
794        ElementQueries.instance.findElementQueriesElements(container);
795    };
796
797    ElementQueries.listen = function () {
798        domLoaded(ElementQueries.init);
799    };
800
801    return ElementQueries;
802
803}));
804
805(function($) {
806	'use strict';
807
808	$.exists = function(selector) {
809	    return ($(selector).length > 0);
810	};
811
812	/**
813	 * Helper to enable caching async scripts
814	 * https://api.jquery.com/jquery.getscript/
815	 * http://www.vrdmn.com/2013/07/overriding-jquerygetscript-to-include.html
816	 * 
817	 * @param  {String}   script url
818	 * @param  {Function} callback     
819	 */
820	$.getCachedScript = function( url ) {
821		var options = {
822			dataType: "script",
823			cache: true,
824			url: url
825		};
826	 
827	    // Use $.ajax() since it is more flexible than $.getScript
828	    // Return the jqXHR object so we can chain callbacks
829	  	return $.ajax( options );
830	};
831
832
833
834	// Fn to allow an event to fire after all images are loaded
835	// usage:
836	// $.ajax({
837	//     cache: false,
838	//     url: 'ajax/content.php',
839	//     success: function(data) {
840	//         $('#divajax').html(data).imagesLoaded().then(function(){
841	//             // do stuff after images are loaded here
842	//         });
843	//     }
844	// });
845	$.fn.mk_imagesLoaded = function () {
846
847	    // Edit: in strict mode, the var keyword is needed
848	    var $imgs = this.find('img[src!=""]');
849	    // if there's no images, just return an already resolved promise
850	    if (!$imgs.length) {return $.Deferred().resolve().promise();}
851
852	    // for each image, add a deferred object to the array which resolves when the image is loaded (or if loading fails)
853	    var dfds = [];  
854	    $imgs.each(function(){
855	        var dfd = $.Deferred();
856	        dfds.push(dfd);
857	        var img = new Image();
858	        img.onload = function(){dfd.resolve();};
859	        img.onerror = function(){dfd.resolve();};
860	        img.src = this.src;
861	    });
862
863	    // return a master promise object which will resolve when all the deferred objects have resolved
864	    // IE - when all the images are loaded
865	    return $.when.apply($,dfds);
866
867	};
868
869}(jQuery));
870/**
871* Detect Element Resize
872*
873* https://github.com/sdecima/javascript-detect-element-resize
874* Sebastian Decima
875*
876* version: 0.5.3
877**/
878
879(function () {
880	var attachEvent = document.attachEvent,
881		stylesCreated = false;
882	
883	if (!attachEvent) {
884		var requestFrame = (function(){
885			var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
886								function(fn){ return window.setTimeout(fn, 20); };
887			return function(fn){ return raf(fn); };
888		})();
889		
890		var cancelFrame = (function(){
891			var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
892								   window.clearTimeout;
893		  return function(id){ return cancel(id); };
894		})();
895
896		function resetTriggers(element){
897			var triggers = element.__resizeTriggers__,
898				expand = triggers.firstElementChild,
899				contract = triggers.lastElementChild,
900				expandChild = expand.firstElementChild;
901			contract.scrollLeft = contract.scrollWidth;
902			contract.scrollTop = contract.scrollHeight;
903			expandChild.style.width = expand.offsetWidth + 1 + 'px';
904			expandChild.style.height = expand.offsetHeight + 1 + 'px';
905			expand.scrollLeft = expand.scrollWidth;
906			expand.scrollTop = expand.scrollHeight;
907		};
908
909		function checkTriggers(element){
910			return element.offsetWidth != element.__resizeLast__.width ||
911						 element.offsetHeight != element.__resizeLast__.height;
912		}
913		
914		function scrollListener(e){
915			var element = this;
916			resetTriggers(this);
917			if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);
918			this.__resizeRAF__ = requestFrame(function(){
919				if (checkTriggers(element)) {
920					element.__resizeLast__.width = element.offsetWidth;
921					element.__resizeLast__.height = element.offsetHeight;
922					element.__resizeListeners__.forEach(function(fn){
923						fn.call(element, e);
924					});
925				}
926			});
927		};
928		
929		/* Detect CSS Animations support to detect element display/re-attach */
930		var animation = false,
931			animationstring = 'animation',
932			keyframeprefix = '',
933			animationstartevent = 'animationstart',
934			domPrefixes = 'Webkit Moz O ms'.split(' '),
935			startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '),
936			pfx  = '';
937		{
938			var elm = document.createElement('fakeelement');
939			if( elm.style.animationName !== undefined ) { animation = true; }    
940			
941			if( animation === false ) {
942				for( var i = 0; i < domPrefixes.length; i++ ) {
943					if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
944						pfx = domPrefixes[ i ];
945						animationstring = pfx + 'Animation';
946						keyframeprefix = '-' + pfx.toLowerCase() + '-';
947						animationstartevent = startEvents[ i ];
948						animation = true;
949						break;
950					}
951				}
952			}
953		}
954		
955		var animationName = 'resizeanim';
956		var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
957		var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
958	}
959	
960	function createStyles() {
961		if (!stylesCreated) {
962			//opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360
963			var css = (animationKeyframes ? animationKeyframes : '') +
964					'.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' +
965					'.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }',
966				head = document.head || document.getElementsByTagName('head')[0],
967				style = document.createElement('style');
968			
969			style.type = 'text/css';
970			if (style.styleSheet) {
971				style.styleSheet.cssText = css;
972			} else {
973				style.appendChild(document.createTextNode(css));
974			}
975
976			head.appendChild(style);
977			stylesCreated = true;
978		}
979	}
980	
981	window.addResizeListener = function(element, fn){
982		if (attachEvent) element.attachEvent('onresize', fn);
983		else {
984			if (!element.__resizeTriggers__) {
985				if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
986				createStyles();
987				element.__resizeLast__ = {};
988				element.__resizeListeners__ = [];
989				(element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers';
990				element.__resizeTriggers__.innerHTML = '<div class="expand-trigger"><div></div></div>' +
991																						'<div class="contract-trigger"></div>';
992				element.appendChild(element.__resizeTriggers__);
993				resetTriggers(element);
994				element.addEventListener('scroll', scrollListener, true);
995				
996				/* Listen for a css animation to detect element display/re-attach */
997				animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function(e) {
998					if(e.animationName == animationName)
999						resetTriggers(element);
1000				});
1001			}
1002			element.__resizeListeners__.push(fn);
1003		}
1004	};
1005	
1006	window.removeResizeListener = function(element, fn){
1007		if (attachEvent) element.detachEvent('onresize', fn);
1008		else {
1009			element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
1010			if (!element.__resizeListeners__.length) {
1011					element.removeEventListener('scroll', scrollListener);
1012					element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__);
1013			}
1014		}
1015	}
1016})();
1017/**
1018* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
1019*/
1020;(function(window, document) {
1021/*jshint evil:true */
1022  /** version */
1023  var version = '3.7.3';
1024
1025  /** Preset options */
1026  var options = window.html5 || {};
1027
1028  /** Used to skip problem elements */
1029  var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
1030
1031  /** Not all elements can be cloned in IE **/
1032  var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
1033
1034  /** Detect whether the browser supports default html5 styles */
1035  var supportsHtml5Styles;
1036
1037  /** Name of the expando, to work with multiple documents or to re-shiv one document */
1038  var expando = '_html5shiv';
1039
1040  /** The id for the the documents expando */
1041  var expanID = 0;
1042
1043  /** Cached data for each document */
1044  var expandoData = {};
1045
1046  /** Detect whether the browser supports unknown elements */
1047  var supportsUnknownElements;
1048
1049  (function() {
1050    try {
1051        var a = document.createElement('a');
1052        a.innerHTML = '<xyz></xyz>';
1053        //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
1054        supportsHtml5Styles = ('hidden' in a);
1055
1056        supportsUnknownElements = a.childNodes.length == 1 || (function() {
1057          // assign a false positive if unable to shiv
1058          (document.createElement)('a');
1059          var frag = document.createDocumentFragment();
1060          return (
1061            typeof frag.cloneNode == 'undefined' ||
1062            typeof frag.createDocumentFragment == 'undefined' ||
1063            typeof frag.createElement == 'undefined'
1064          );
1065        }());
1066    } catch(e) {
1067      // assign a false positive if detection fails => unable to shiv
1068      supportsHtml5Styles = true;
1069      supportsUnknownElements = true;
1070    }
1071
1072  }());
1073
1074  /*--------------------------------------------------------------------------*/
1075
1076  /**
1077   * Creates a style sheet with the given CSS text and adds it to the document.
1078   * @private
1079   * @param {Document} ownerDocument The document.
1080   * @param {String} cssText The CSS text.
1081   * @returns {StyleSheet} The style element.
1082   */
1083  function addStyleSheet(ownerDocument, cssText) {
1084    var p = ownerDocument.createElement('p'),
1085        parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
1086
1087    p.innerHTML = 'x<style>' + cssText + '</style>';
1088    return parent.insertBefore(p.lastChild, parent.firstChild);
1089  }
1090
1091  /**
1092   * Returns the value of `html5.elements` as an array.
1093   * @private
1094   * @returns {Array} An array of shived element node names.
1095   */
1096  function getElements() {
1097    var elements = html5.elements;
1098    return typeof elements == 'string' ? elements.split(' ') : elements;
1099  }
1100
1101  /**
1102   * Extends the built-in list of html5 elements
1103   * @memberOf html5
1104   * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
1105   * @param {Document} ownerDocument The context document.
1106   */
1107  function addElements(newElements, ownerDocument) {
1108    var elements = html5.elements;
1109    if(typeof elements != 'string'){
1110      elements = elements.join(' ');
1111    }
1112    if(typeof newElements != 'string'){
1113      newElements = newElements.join(' ');
1114    }
1115    html5.elements = elements +' '+ newElements;
1116    shivDocument(ownerDocument);
1117  }
1118
1119   /**
1120   * Returns the data associated to the given document
1121   * @private
1122   * @param {Document} ownerDocument The document.
1123   * @returns {Object} An object of data.
1124   */
1125  function getExpandoData(ownerDocument) {
1126    var data = expandoData[ownerDocument[expando]];
1127    if (!data) {
1128        data = {};
1129        expanID++;
1130        ownerDocument[expando] = expanID;
1131        expandoData[expanID] = data;
1132    }
1133    return data;
1134  }
1135
1136  /**
1137   * returns a shived element for the given nodeName and document
1138   * @memberOf html5
1139   * @param {String} nodeName name of the element
1140   * @param {Document|DocumentFrag
vendor: 6,335 bytes, lines 1140-1342
1140ment} ownerDocument The context document.
1141   * @returns {Object} The shived element.
1142   */
1143  function createElement(nodeName, ownerDocument, data){
1144    if (!ownerDocument) {
1145        ownerDocument = document;
1146    }
1147    if(supportsUnknownElements){
1148        return ownerDocument.createElement(nodeName);
1149    }
1150    if (!data) {
1151        data = getExpandoData(ownerDocument);
1152    }
1153    var node;
1154
1155    if (data.cache[nodeName]) {
1156        node = data.cache[nodeName].cloneNode();
1157    } else if (saveClones.test(nodeName)) {
1158        node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
1159    } else {
1160        node = data.createElem(nodeName);
1161    }
1162
1163    // Avoid adding some elements to fragments in IE < 9 because
1164    // * Attributes like `name` or `type` cannot be set/changed once an element
1165    //   is inserted into a document/fragment
1166    // * Link elements with `src` attributes that are inaccessible, as with
1167    //   a 403 response, will cause the tab/window to crash
1168    // * Script elements appended to fragments will execute when their `src`
1169    //   or `text` property is set
1170    return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
1171  }
1172
1173  /**
1174   * returns a shived DocumentFragment for the given document
1175   * @memberOf html5
1176   * @param {Document} ownerDocument The context document.
1177   * @returns {Object} The shived DocumentFragment.
1178   */
1179  function createDocumentFragment(ownerDocument, data){
1180    if (!ownerDocument) {
1181        ownerDocument = document;
1182    }
1183    if(supportsUnknownElements){
1184        return ownerDocument.createDocumentFragment();
1185    }
1186    data = data || getExpandoData(ownerDocument);
1187    var clone = data.frag.cloneNode(),
1188        i = 0,
1189        elems = getElements(),
1190        l = elems.length;
1191    for(;i<l;i++){
1192        clone.createElement(elems[i]);
1193    }
1194    return clone;
1195  }
1196
1197  /**
1198   * Shivs the `createElement` and `createDocumentFragment` methods of the document.
1199   * @private
1200   * @param {Document|DocumentFragment} ownerDocument The document.
1201   * @param {Object} data of the document.
1202   */
1203  function shivMethods(ownerDocument, data) {
1204    if (!data.cache) {
1205        data.cache = {};
1206        data.createElem = ownerDocument.createElement;
1207        data.createFrag = ownerDocument.createDocumentFragment;
1208        data.frag = data.createFrag();
1209    }
1210
1211
1212    ownerDocument.createElement = function(nodeName) {
1213      //abort shiv
1214      if (!html5.shivMethods) {
1215          return data.createElem(nodeName);
1216      }
1217      return createElement(nodeName, ownerDocument, data);
1218    };
1219
1220    ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
1221      'var n=f.cloneNode(),c=n.createElement;' +
1222      'h.shivMethods&&(' +
1223        // unroll the `createElement` calls
1224        getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
1225          data.createElem(nodeName);
1226          data.frag.createElement(nodeName);
1227          return 'c("' + nodeName + '")';
1228        }) +
1229      ');return n}'
1230    )(html5, data.frag);
1231  }
1232
1233  /*--------------------------------------------------------------------------*/
1234
1235  /**
1236   * Shivs the given document.
1237   * @memberOf html5
1238   * @param {Document} ownerDocument The document to shiv.
1239   * @returns {Document} The shived document.
1240   */
1241  function shivDocument(ownerDocument) {
1242    if (!ownerDocument) {
1243        ownerDocument = document;
1244    }
1245    var data = getExpandoData(ownerDocument);
1246
1247    if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
1248      data.hasCSS = !!addStyleSheet(ownerDocument,
1249        // corrects block display not defined in IE6/7/8/9
1250        'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
1251        // adds styling not present in IE6/7/8/9
1252        'mark{background:#FF0;color:#000}' +
1253        // hides non-rendered elements
1254        'template{display:none}'
1255      );
1256    }
1257    if (!supportsUnknownElements) {
1258      shivMethods(ownerDocument, data);
1259    }
1260    return ownerDocument;
1261  }
1262
1263  /*--------------------------------------------------------------------------*/
1264
1265  /**
1266   * The `html5` object is exposed so that more elements can be shived and
1267   * existing shiving can be detected on iframes.
1268   * @type Object
1269   * @example
1270   *
1271   * // options can be changed before the script is included
1272   * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
1273   */
1274  var html5 = {
1275
1276    /**
1277     * An array or space separated string of node names of the elements to shiv.
1278     * @memberOf html5
1279     * @type Array|String
1280     */
1281    'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
1282
1283    /**
1284     * current version of html5shiv
1285     */
1286    'version': version,
1287
1288    /**
1289     * A flag to indicate that the HTML5 style sheet should be inserted.
1290     * @memberOf html5
1291     * @type Boolean
1292     */
1293    'shivCSS': (options.shivCSS !== false),
1294
1295    /**
1296     * Is equal to true if a browser supports creating unknown/HTML5 elements
1297     * @memberOf html5
1298     * @type boolean
1299     */
1300    'supportsUnknownElements': supportsUnknownElements,
1301
1302    /**
1303     * A flag to indicate that the document's `createElement` and `createDocumentFragment`
1304     * methods should be overwritten.
1305     * @memberOf html5
1306     * @type Boolean
1307     */
1308    'shivMethods': (options.shivMethods !== false),
1309
1310    /**
1311     * A string to describe the type of `html5` object ("default" or "default print").
1312     * @memberOf html5
1313     * @type String
1314     */
1315    'type': 'default',
1316
1317    // shivs the document according to the specified `html5` object options
1318    'shivDocument': shivDocument,
1319
1320    //creates a shived element
1321    createElement: createElement,
1322
1323    //creates a shived documentFragment
1324    createDocumentFragment: createDocumentFragment,
1325
1326    //extends list of elements
1327    addElements: addElements
1328  };
1329
1330  /*--------------------------------------------------------------------------*/
1331
1332  // expose html5
1333  window.html5 = html5;
1334
1335  // shiv the document
1336  shivDocument(document);
1337
1338  if(typeof module == 'object' && module.exports){
1339    module.exports = html5;
1340  }
1341
1342}(typeof window !== "undefined" ? window : this, document));
1343/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. Dual MIT/BSD license */
1344
1345window.matchMedia || (window.matchMedia = function() {
1346    "use strict";
1347
1348    // For browsers that support matchMedium api such as IE 9 and webkit
1349    var styleMedia = (window.styleMedia || window.media);
1350
1351    // For those that don't support matchMedium
1352    if (!styleMedia) {
1353        var style       = document.createElement('style'),
1354            script      = document.getElementsByTagName('script')[0],
1355            info        = null;
1356
1357        style.type  = 'text/css';
1358        style.id    = 'matchmediajs-test';
1359
1360        script.parentNode.insertBefore(style, script);
1361
1362        // 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers
1363        info = ('getComputedStyle' in window) && window.getComputedStyle(style, null) || style.currentStyle;
1364
1365        styleMedia = {
1366            matchMedium: function(media) {
1367                var text = '@media ' + media + '{ #matchmediajs-test { width: 1px; } }';
1368
1369                // 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers
1370                if (style.styleSheet) {
1371                    style.styleSheet.cssText = text;
1372                } else {
1373                    style.textContent = text;
1374                }
1375
1376                // Test if media query is true or false
1377                return info.width === '1px';
1378            }
1379        };
1380    }
1381
1382    return function(media) {
1383        return {
1384            matches: styleMedia.matchMedium(media || 'all'),
1385            media: media || 'all'
1386        };
1387    };
1388}());
1389
1390/*!
1391 * The MIT License
1392 *
1393 * Copyright (c) 2012 James Allardice
1394 *
1395 * Permission is hereby granted, free of charge, to any person obtaining a copy
1396 * of this software and associated documentation files (the "Software"), to
1397 * deal in the Software without restriction, including without limitation the
1398 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1399 * sell copies of the Software, and to permit persons to whom the Software is
1400 * furnished to do so, subject to the following conditions:
1401 *
1402 * The above copyright notice and this permission notice shall be included in
1403 * all copies or substantial portions of the Software.
1404 *
1405 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1406 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1407 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1408 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1409 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1410 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
1411 * IN THE SOFTWARE.
1412 */
1413
1414( function ( global ) {
1415
1416  'use strict';
1417
1418  //
1419  // Test for support. We do this as early as possible to optimise for browsers
1420  // that have native support for the attribute.
1421  //
1422
1423  var test = document.createElement('input');
1424  var nativeSupport = test.placeholder !== void 0;
1425
1426  global.Placeholders = {
1427    nativeSupport: nativeSupport,
1428    disable: nativeSupport ? noop : disablePlaceholders,
1429    enable: nativeSupport ? noop : enablePlaceholders
1430  };
1431
1432  if ( nativeSupport ) {
1433    return;
1434  }
1435
1436  //
1437  // If we reach this point then the browser does not have native support for
1438  // the attribute.
1439  //
1440
1441  // The list of input element types that support the placeholder attribute.
1442  var validTypes = [
1443    'text',
1444    'search',
1445    'url',
1446    'tel',
1447    'email',
1448    'password',
1449    'number',
1450    'textarea'
1451  ];
1452
1453  // The list of keycodes that are not allowed when the polyfill is configured
1454  // to hide-on-input.
1455  var badKeys = [
1456
1457    // The following keys all cause the caret to jump to the end of the input
1458    // value.
1459
1460    27, // Escape
1461    33, // Page up
1462    34, // Page down
1463    35, // End
1464    36, // Home
1465
1466    // Arrow keys allow you to move the caret manually, which should be
1467    // prevented when the placeholder is visible.
1468
1469    37, // Left
1470    38, // Up
1471    39, // Right
1472    40, // Down
1473
1474    // The following keys allow you to modify the placeholder text by removing
1475    // characters, which should be prevented when the placeholder is visible.
1476
1477    8, // Backspace
1478    46 // Delete
1479  ];
1480
1481  // Styling variables.
1482  var placeholderStyleColor = '#ccc';
1483  var placeholderClassName = 'placeholdersjs';
1484  var classNameRegExp = new RegExp('(?:^|\\s)' + placeholderClassName + '(?!\\S)');
1485
1486  // The various data-* attributes used by the polyfill.
1487  var ATTR_CURRENT_VAL = 'data-placeholder-value';
1488  var ATTR_ACTIVE = 'data-placeholder-active';
1489  var ATTR_INPUT_TYPE = 'data-placeholder-type';
1490  var ATTR_FORM_HANDLED = 'data-placeholder-submit';
1491  var ATTR_EVENTS_BOUND = 'data-placeholder-bound';
1492  var ATTR_OPTION_FOCUS = 'data-placeholder-focus';
1493  var ATTR_OPTION_LIVE = 'data-placeholder-live';
1494  var ATTR_MAXLENGTH = 'data-placeholder-maxlength';
1495
1496  // Various other variables used throughout the rest of the script.
1497  var UPDATE_INTERVAL = 100;
1498  var head = document.getElementsByTagName('head')[ 0 ];
1499  var root = document.documentElement;
1500  var Placeholders = global.Placeholders;
1501  var keydownVal;
1502
1503  // Get references to all the input and textarea elements currently in the DOM
1504  // (live NodeList objects to we only need to do this once).
1505  var inputs = document.getElementsByTagName('input');
1506  var textareas = document.getElementsByTagName('textarea');
1507
1508  // Get any settings declared as data-* attributes on the root element.
1509  // Currently the only options are whether to hide the placeholder on focus
1510  // or input and whether to auto-update.
1511  var hideOnInput = root.getAttribute(ATTR_OPTION_FOCUS) === 'false';
1512  var liveUpdates = root.getAttribute(ATTR_OPTION_LIVE) !== 'false';
1513
1514  // Create style element for placeholder styles (instead of directly setting
1515  // style properties on elements - allows for better flexibility alongside
1516  // user-defined styles).
1517  var styleElem = document.createElement('style');
1518  styleElem.type = 'text/css';
1519
1520  // Create style rules as text node.
1521  var styleRules = document.createTextNode(
1522    '.' + placeholderClassName + ' {' +
1523      'color:' + placeholderStyleColor + ';' +
1524    '}'
1525  );
1526
1527  // Append style rules to newly created stylesheet.
1528  if ( styleElem.styleSheet ) {
1529    styleElem.styleSheet.cssText = styleRules.nodeValue;
1530  } else {
1531    styleElem.appendChild(styleRules);
1532  }
1533
1534  // Prepend new style element to the head (before any existing stylesheets,
1535  // so user-defined rules take precedence).
1536  head.insertBefore(styleElem, head.firstChild);
1537
1538  // Set up the placeholders.
1539  var placeholder;
1540  var elem;
1541
1542  for ( var i = 0, len = inputs.length + textareas.length; i < len; i++ ) {
1543
1544    // Find the next element. If we've already done all the inputs we move on
1545    // to the textareas.
1546    elem = i < inputs.length ? inputs[ i ] : textareas[ i - inputs.length ];
1547
1548    // Get the value of the placeholder attribute, if any. IE10 emulating IE7
1549    // fails with getAttribute, hence the use of the attributes node.
1550    placeholder = elem.attributes.placeholder;
1551
1552    // If the element has a placeholder attribute we need to modify it.
1553    if ( placeholder ) {
1554
1555      // IE returns an empty object instead of undefined if the attribute is
1556      // not present.
1557      placeholder = placeholder.nodeValue;
1558
1559      // Only apply the polyfill if this element is of a type that supports
1560      // placeholders and has a placeholder attribute with a non-empty value.
1561      if ( placeholder && inArray(validTypes, elem.type) ) {
1562        newElement(elem);
1563      }
1564    }
1565  }
1566
1567  // If enabled, the polyfill will repeatedly check for changed/added elements
1568  // and apply to those as well.
1569  var timer = setInterval(function () {
1570    for ( var i = 0, len = inputs.length + textareas.length; i < len; i++ ) {
1571      elem = i < inputs.length ? inputs[ i ] : textareas[ i - inputs.length ];
1572
1573      // Only apply the polyfill if this element is of a type that supports
1574      // placeholders, and has a placeholder attribute with a non-empty value.
1575      placeholder = elem.attributes.placeholder;
1576
1577      if ( placeholder ) {
1578
1579        placeholder = placeholder.nodeValue;
1580
1581        if ( placeholder && inArray(validTypes, elem.type) ) {
1582
1583          // If the element hasn't had event handlers bound to it then add
1584          // them.
1585          if ( !elem.getAttribute(ATTR_EVENTS_BOUND) ) {
1586            newElement(elem);
1587          }
1588
1589          // If the placeholder value has changed or not been initialised yet
1590          // we need to update the display.
1591          if (
1592            placeholder !== elem.getAttribute(ATTR_CURRENT_VAL) ||
1593            ( elem.type === 'password' && !elem.getAttribute(ATTR_INPUT_TYPE) )
1594          ) {
1595
1596            // Attempt to change the type of password inputs (fails in IE < 9).
1597            if (
1598              elem.type === 'password' &&
1599              !elem.getAttribute(ATTR_INPUT_TYPE) &&
1600              changeType(elem, 'text')
1601            ) {
1602              elem.setAttribute(ATTR_INPUT_TYPE, 'password');
1603            }
1604
1605            // If the placeholder value has changed and the placeholder is
1606            // currently on display we need to change it.
1607            if ( elem.value === elem.getAttribute(ATTR_CURRENT_VAL) ) {
1608              elem.value = placeholder;
1609            }
1610
1611            // Keep a reference to the current placeholder value in case it
1612            // changes via another script.
1613            elem.setAttribute(ATTR_CURRENT_VAL, placeholder);
1614          }
1615        }
1616      } else if ( elem.getAttribute(ATTR_ACTIVE) ) {
1617        hidePlaceholder(elem);
1618        elem.removeAttribute(ATTR_CURRENT_VAL);
1619      }
1620    }
1621
1622    // If live updates are not enabled cancel the timer.
1623    if ( !liveUpdates ) {
1624      clearInterval(timer);
1625    }
1626  }, UPDATE_INTERVAL);
1627
1628  // Disabling placeholders before unloading the page prevents flash of
1629  // unstyled placeholders on load if the page was refreshed.
1630  addEventListener(global, 'beforeunload', function () {
1631    Placeholders.disable();
1632  });
1633
1634  //
1635  // Utility functions
1636  //
1637
1638  // No-op (used in place of public methods when native support is detected).
1639  function noop() {}
1640
1641  // Avoid IE9 activeElement of death when an iframe is used.
1642  //
1643  // More info:
1644  //  - http://bugs.jquery.com/ticket/13393
1645  //  - https://github.com/jquery/jquery/commit/85fc5878b3c6af73f42d61eedf73013e7faae408
1646  function safeActiveElement() {
1647    try {
1648      return document.activeElement;
1649    } catch ( err ) {}
1650  }
1651
1652  // Check whether an item is in an array. We don't use Array.prototype.indexOf
1653  // so we don't clobber any existing polyfills. This is a really simple
1654  // alternative.
1655  function inArray( arr, item ) {
1656    for ( var i = 0, len = arr.length; i < len; i++ ) {
1657      if ( arr[ i ] === item ) {
1658        return true;
1659      }
1660    }
1661    return false;
1662  }
1663
1664  // Cross-browser DOM event binding
1665  function addEventListener( elem, event, fn ) {
1666    if ( elem.addEventListener ) {
1667      return elem.addEventListener(event, fn, false);
1668    }
1669    if ( elem.attachEvent ) {
1670      return elem.attachEvent('on' + event, fn);
1671    }
1672  }
1673
1674  // Move the caret to the index position specified. Assumes that the element
1675  // has focus.
1676  function moveCaret( elem, index ) {
1677    var range;
1678    if ( elem.createTextRange ) {
1679      range = elem.createTextRange();
1680      range.move('character', index);
1681      range.select();
1682    } else if ( elem.selectionStart ) {
1683      elem.focus();
1684      elem.setSelectionRange(index, index);
1685    }
1686  }
1687
1688  // Attempt to change the type property of an input element.
1689  function changeType( elem, type ) {
1690    try {
1691      elem.type = type;
1692      return true;
1693    } catch ( e ) {
1694      // You can't change input type in IE8 and below.
1695      return false;
1696    }
1697  }
1698
1699  function handleElem( node, callback ) {
1700
1701    // Check if the passed in node is an input/textarea (in which case it can't
1702    // have any affected descendants).
1703    if ( node && node.getAttribute(ATTR_CURRENT_VAL) ) {
1704      callback(node);
1705    } else {
1706
1707      // If an element was passed in, get all affected descendants. Otherwise,
1708      // get all affected elements in document.
1709      var handleInputs = node ? node.getElementsByTagName('input') : input
1709s;
1710      var handleTextareas = node ? node.getElementsByTagName('textarea') : textareas;
1711
1712      var handleInputsLength = handleInputs ? handleInputs.length : 0;
1713      var handleTextareasLength = handleTextareas ? handleTextareas.length : 0;
1714
1715      // Run the callback for each element.
1716      var len = handleInputsLength + handleTextareasLength;
1717      var elem;
1718      for ( var i = 0; i < len; i++ ) {
1719
1720        elem = i < handleInputsLength ?
1721          handleInputs[ i ] :
1722          handleTextareas[ i - handleInputsLength ];
1723
1724        callback(elem);
1725      }
1726    }
1727  }
1728
1729  // Return all affected elements to their normal state (remove placeholder
1730  // value if present).
1731  function disablePlaceholders( node ) {
1732    handleElem(node, hidePlaceholder);
1733  }
1734
1735  // Show the placeholder value on all appropriate elements.
1736  function enablePlaceholders( node ) {
1737    handleElem(node, showPlaceholder);
1738  }
1739
1740  // Hide the placeholder value on a single element. Returns true if the
1741  // placeholder was hidden and false if it was not (because it wasn't visible
1742  // in the first place).
1743  function hidePlaceholder( elem, keydownValue ) {
1744
1745    var valueChanged = !!keydownValue && elem.value !== keydownValue;
1746    var isPlaceholderValue = elem.value === elem.getAttribute(ATTR_CURRENT_VAL);
1747
1748    if (
1749      ( valueChanged || isPlaceholderValue ) &&
1750      elem.getAttribute(ATTR_ACTIVE) === 'true'
1751    ) {
1752
1753      elem.removeAttribute(ATTR_ACTIVE);
1754      elem.value = elem.value.replace(elem.getAttribute(ATTR_CURRENT_VAL), '');
1755      elem.className = elem.className.replace(classNameRegExp, '');
1756
1757      // Restore the maxlength value. Old FF returns -1 if attribute not set.
1758      // See GH-56.
1759      var maxLength = elem.getAttribute(ATTR_MAXLENGTH);
1760      if ( parseInt(maxLength, 10) >= 0 ) {
1761        elem.setAttribute('maxLength', maxLength);
1762        elem.removeAttribute(ATTR_MAXLENGTH);
1763      }
1764
1765      // If the polyfill has changed the type of the element we need to change
1766      // it back.
1767      var type = elem.getAttribute(ATTR_INPUT_TYPE);
1768      if ( type ) {
1769        elem.type = type;
1770      }
1771
1772      return true;
1773    }
1774
1775    return false;
1776  }
1777
1778  // Show the placeholder value on a single element. Returns true if the
1779  // placeholder was shown and false if it was not (because it was already
1780  // visible).
1781  function showPlaceholder( elem ) {
1782
1783    var val = elem.getAttribute(ATTR_CURRENT_VAL);
1784
1785    if ( elem.value === '' && val ) {
1786
1787      elem.setAttribute(ATTR_ACTIVE, 'true');
1788      elem.value = val;
1789      elem.className += ' ' + placeholderClassName;
1790
1791      // Store and remove the maxlength value.
1792      var maxLength = elem.getAttribute(ATTR_MAXLENGTH);
1793      if ( !maxLength ) {
1794        elem.setAttribute(ATTR_MAXLENGTH, elem.maxLength);
1795        elem.removeAttribute('maxLength');
1796      }
1797
1798      // If the type of element needs to change, change it (e.g. password
1799      // inputs).
1800      var type = elem.getAttribute(ATTR_INPUT_TYPE);
1801      if ( type ) {
1802        elem.type = 'text';
1803      } else if ( elem.type === 'password' && changeType(elem, 'text') ) {
1804        elem.setAttribute(ATTR_INPUT_TYPE, 'password');
1805      }
1806
1807      return true;
1808    }
1809
1810    return false;
1811  }
1812
1813  // Returns a function that is used as a focus event handler.
1814  function makeFocusHandler( elem ) {
1815    return function () {
1816
1817      // Only hide the placeholder value if the (default) hide-on-focus
1818      // behaviour is enabled.
1819      if (
1820        hideOnInput &&
1821        elem.value === elem.getAttribute(ATTR_CURRENT_VAL) &&
1822        elem.getAttribute(ATTR_ACTIVE) === 'true'
1823      ) {
1824
1825        // Move the caret to the start of the input (this mimics the behaviour
1826        // of all browsers that do not hide the placeholder on focus).
1827        moveCaret(elem, 0);
1828      } else {
1829
1830        // Remove the placeholder.
1831        hidePlaceholder(elem);
1832      }
1833    };
1834  }
1835
1836  // Returns a function that is used as a blur event handler.
1837  function makeBlurHandler( elem ) {
1838    return function () {
1839      showPlaceholder(elem);
1840    };
1841  }
1842
1843  // Returns a function that is used as a submit event handler on form elements
1844  // that have children affected by this polyfill.
1845  function makeSubmitHandler( form ) {
1846    return function () {
1847
1848        // Turn off placeholders on all appropriate descendant elements.
1849        disablePlaceholders(form);
1850    };
1851  }
1852
1853  // Functions that are used as a event handlers when the hide-on-input
1854  // behaviour has been activated - very basic implementation of the 'input'
1855  // event.
1856  function makeKeydownHandler( elem ) {
1857    return function ( e ) {
1858      keydownVal = elem.value;
1859
1860      // Prevent the use of the arrow keys (try to keep the cursor before the
1861      // placeholder).
1862      if (
1863        elem.getAttribute(ATTR_ACTIVE) === 'true' &&
1864        keydownVal === elem.getAttribute(ATTR_CURRENT_VAL) &&
1865        inArray(badKeys, e.keyCode)
1866      ) {
1867        if ( e.preventDefault ) {
1868            e.preventDefault();
1869        }
1870        return false;
1871      }
1872    };
1873  }
1874
1875  function makeKeyupHandler(elem) {
1876    return function () {
1877      hidePlaceholder(elem, keydownVal);
1878
1879      // If the element is now empty we need to show the placeholder
1880      if ( elem.value === '' ) {
1881        elem.blur();
1882        moveCaret(elem, 0);
1883      }
1884    };
1885  }
1886
1887  function makeClickHandler(elem) {
1888    return function () {
1889      if (
1890        elem === safeActiveElement() &&
1891        elem.value === elem.getAttribute(ATTR_CURRENT_VAL) &&
1892        elem.getAttribute(ATTR_ACTIVE) === 'true'
1893      ) {
1894        moveCaret(elem, 0);
1895      }
1896    };
1897  }
1898
1899  // Bind event handlers to an element that we need to affect with the
1900  // polyfill.
1901  function newElement( elem ) {
1902
1903    // If the element is part of a form, make sure the placeholder string is
1904    // not submitted as a value.
1905    var form = elem.form;
1906    if ( form && typeof form === 'string' ) {
1907
1908      // Get the real form.
1909      form = document.getElementById(form);
1910
1911      // Set a flag on the form so we know it's been handled (forms can contain
1912      // multiple inputs).
1913      if ( !form.getAttribute(ATTR_FORM_HANDLED) ) {
1914        addEventListener(form, 'submit', makeSubmitHandler(form));
1915        form.setAttribute(ATTR_FORM_HANDLED, 'true');
1916      }
1917    }
1918
1919    // Bind event handlers to the element so we can hide/show the placeholder
1920    // as appropriate.
1921    addEventListener(elem, 'focus', makeFocusHandler(elem));
1922    addEventListener(elem, 'blur', makeBlurHandler(elem));
1923
1924    // If the placeholder should hide on input rather than on focus we need
1925    // additional event handlers
1926    if (hideOnInput) {
1927      addEventListener(elem, 'keydown', makeKeydownHandler(elem));
1928      addEventListener(elem, 'keyup', makeKeyupHandler(elem));
1929      addEventListener(elem, 'click', makeClickHandler(elem));
1930    }
1931
1932    // Remember that we've bound event handlers to this element.
1933    elem.setAttribute(ATTR_EVENTS_BOUND, 'true');
1934    elem.setAttribute(ATTR_CURRENT_VAL, placeholder);
1935
1936    // If the element doesn't have a value and is not focussed, set it to the
1937    // placeholder string.
1938    if ( hideOnInput || elem !== safeActiveElement() ) {
1939      showPlaceholder(elem);
1940    }
1941  }
1942
1943}(this) );
1944// IE spupport comes in IE10
1945(function rAFPolyfill() {
1946    var lastTime, vendors, x;
1947    lastTime = 0;
1948    vendors = ["webkit", "moz"];
1949    x = 0;
1950    while (x < vendors.length && !window.requestAnimationFrame) {
1951      window.requestAnimationFrame = window[vendors[x] + "RequestAnimationFrame"];
1952      window.cancelAnimationFrame = window[vendors[x] + "CancelAnimationFrame"] || window[vendors[x] + "CancelRequestAnimationFrame"];
1953      ++x;
1954    }
1955    if (!window.requestAnimationFrame) {
1956      window.requestAnimationFrame = function(callback, element) {
1957        var currTime, id, timeToCall;
1958        currTime = new Date().getTime();
1959        timeToCall = Math.max(0, 16 - (currTime - lastTime));
1960        id = window.setTimeout(function() {
1961          callback(currTime + timeToCall);
1962        }, timeToCall);
1963        lastTime = currTime + timeToCall;
1964        return id;
1965      };
1966    }
1967    if (!window.cancelAnimationFrame) {
1968      window.cancelAnimationFrame = function(id) {
1969        clearTimeout(id);
1970      };
1971    }
1972})();
1973
1974
1975
1976(function($) {
1977	'use strict';
1978
1979	var MK = window.MK || {};
1980
1981	/**
1982	 * MK.core holds most important methods that bootstraps whole application
1983	 * 
1984	 * @type {Object}
1985	 */
1986	MK.core = {};
1987
1988
1989
1990	/**
1991	 * State for referance of already loaded script files
1992	 * @type {Array}
1993	 */
1994	var _loadedDependencies = [];
1995
1996	/**
1997	 * State of queue represented as pairs of script ref => callback
1998	 * @type {Object}
1999	 */
2000	var _inQueue = {};
2001	
2002	/**
2003	 * Initializes all components in given scope (object or DOM reference) based on data attribute and 'pointer' css class '.js-el'.
2004	 * DOM work is reduced by single traversing for pointer class and later filtering through cached object. It expects init() method
2005	 * on every component. Component itself should be defined in MK.component namespace and assign to DOM element via data-mk-component.
2006	 * Use it once on DOM ready with document as a scope. For partial initialization after aja
2006x operations pass as a scope element
2007	 * where new DOM was inserted.
2008	 * 
2009	 * @param  {string|object}
2010	 */
2011	MK.core.initAll = function( scope ) {
2012		var $el = $( scope ).find( '.js-el' ), // single traversing
2013			$components = $el.filter( '[data-mk-component]' ),
2014			component = null;
2015
2016
2017		// initialize  component
2018		var init = function init(name, el) {
2019			var $el = $(el);
2020
2021			if ( $el.data('init-' + name) ) return; // do not initialize the same module twice
2022
2023			if ( typeof MK.component[ name ] !== 'function' ) console.log('Component init error: ', name);
2024			else {
2025				component = new MK.component[ name ]( el );
2026				component.init();
2027				$el.data('init-' + name, true); // mark as initialised
2028				// TODO add name
2029				MK.utils.eventManager.publish('component-inited');
2030			}
2031		};
2032
2033		$components.each( function() {
2034			var self = this,
2035				$this = $( this ),
2036				names = $this.data( 'mk-component' );
2037
2038			if( typeof names === 'string' ) {
2039				var name = names; // containes only single name. Keep it transparent.
2040				init(name, self);
2041			} else {
2042				names.forEach( function( name ) {
2043					init(name, self);
2044				});
2045			} 
2046		}); 
2047	};
2048
2049	/**
2050	 * Async loader for 3rd party plugins available from within theme or external CDNs / APIs.
2051	 * Take one argument as callback which is run when loading is finished. Also keeps track of already loaded scripts 
2052	 * and prevent duplication. Holds in queue multiple callbacks that where defined in different places but depend on the 
2053	 * same plugin.
2054	 *
2055	 * TODO: heavy test for multiple dependencies and crosssharing one dependency and different one dependency in queue, 
2056	 * bulletproof with single dependency
2057	 *
2058	 * @example MK.core.loadDependencies([MK.core.path.plugins + 'plugin.js'], function() {
2059	 *          	// do something when plugin is loaded
2060	 * 			})
2061	 * 
2062	 * @param  {array}
2063	 * @param  {function}
2064	 */
2065	MK.core.loadDependencies = function( dependencies, callback ) {
2066		var _callback = callback || function() {};
2067
2068        if( !dependencies ) {
2069        	// If no dependencies defined then run _callback imidietelly
2070        	_callback(); 
2071        	return;
2072        }
2073
2074		// Check for new dependencies
2075        var newDeps = dependencies.map( function( dep ) {
2076            if( _loadedDependencies.indexOf( dep ) === -1 ) {
2077            	 if( typeof _inQueue[ dep ] === 'undefined' ) {
2078        			// console.log( dep );
2079                	return dep;
2080                } else {
2081                	_inQueue[ dep ].push( _callback );
2082                	return true;
2083                }
2084            } else {
2085            	return false;
2086            }
2087        });
2088
2089        // The dependency is not new but it's not resolved yet
2090        // Callback is added to queue that will be run after the script is loaded
2091        // Don't run callback just yet.
2092        if( newDeps[0] === true ) {
2093        	// console.log('Waiting for ' + dependencies[0]);
2094        	return;
2095        }
2096
2097        // Dependency was loaded previously. We can run callback safely
2098        if( newDeps[0] === false ) {
2099        	_callback();
2100        	return;
2101        }
2102
2103        // Create queue and relationship script -> callback array to track
2104        // all callbacks that waits for ths script
2105        var queue = newDeps.map( function( script ) {
2106        	// console.log( script );
2107        	_inQueue[ script ] = [ _callback ];
2108            return $.getCachedScript( script );
2109        });
2110
2111        // Callbacks invoking
2112        var onLoad = function onLoad() {
2113        	var index;
2114        	newDeps.map( function( loaded ) {
2115        		_inQueue[ loaded ].forEach( function( callback ) {
2116        			callback();
2117        		});
2118        		delete _inQueue[ loaded ];
2119                _loadedDependencies.push( loaded );
2120        	});
2121        };
2122
2123        // Run callbacks when promise is resolved
2124        $.when.apply( null, queue ).done( onLoad );
2125	};
2126
2127	/**
2128	 * Single namespace for all paths recuired in application.
2129	 * @type {Object}
2130	 */
2131	MK.core.path = {
2132		theme   : mk_theme_dir,
2133		plugins : mk_theme_js_path + '/plugins/async/min/',
2134		ajaxUrl : window.PHP.ajax
2135	};
2136
2137
2138})(jQuery);
2139(function($) {
2140	'use strict';
2141
2142    var MK = window.MK || {};
2143	MK.utils = window.MK.utils || {};
2144
2145    /**
2146     * Enables to evaluate common methods through DOM JSON references by invoking from object with bracket notation MK.utils[var][var]
2147     * @type {Object}
2148     */
2149    MK.utils.actions = {};
2150
2151    MK.utils.actions.activate = function (el) {
2152        $(el).addClass('is-active');
2153    };
2154        
2155    MK.utils.actions.deactivate = function (el) {
2156        $(el).removeClass('is-active');
2157    };
2158
2159}(jQuery));
2160(function($) {
2161	'use strict';
2162
2163    var MK = window.MK || {};
2164	MK.utils = window.MK.utils || {};
2165
2166    /**
2167     * Gets user browser and its version
2168     * @return {Object} => {name, version}
2169     */
2170	MK.utils.browser = (function() {
2171        var dataBrowser = [
2172            {string: navigator.userAgent, subString: "Edge", identity: "Edge"},
2173            {string: navigator.userAgent, subString: "Chrome", identity: "Chrome"},
2174            {string: navigator.userAgent, subString: "MSIE", identity: "IE"},
2175            {string: navigator.userAgent, subString: "Trident", identity: "IE"},
2176            {string: navigator.userAgent, subString: "Firefox", identity: "Firefox"},
2177            {string: navigator.userAgent, subString: "Safari", identity: "Safari"},
2178            {string: navigator.userAgent, subString: "Opera", identity: "Opera"}
2179        ];
2180
2181		var versionSearchString = null;
2182        var searchString = function (data) {
2183            for (var i = 0; i < data.length; i++) {
2184                var dataString = data[i].string;
2185                versionSearchString = data[i].subString;
2186
2187                if (dataString.indexOf(data[i].subString) !== -1) {
2188                    return data[i].identity;
2189                }
2190            }
2191        };
2192        
2193        var searchVersion = function (dataString) {
2194            var index = dataString.indexOf(versionSearchString);
2195            if (index === -1) {
2196                return;
2197            }
2198
2199            var rv = dataString.indexOf("rv:");
2200            if (versionSearchString === "Trident" && rv !== -1) {
2201                return parseFloat(dataString.substring(rv + 3));
2202            } else {
2203                return parseFloat(dataString.substring(index + versionSearchString.length + 1));
2204            }
2205        };
2206
2207        var name = searchString(dataBrowser) || "Other";
2208        var version = searchVersion(navigator.userAgent) || searchVersion(navigator.appVersion) || "Unknown";
2209
2210        // Expose for css
2211        $('html').addClass(name).addClass(name + version);
2212
2213
2214        return {
2215        	name : name,
2216        	version : version
2217        };
2218        
2219	})();
2220
2221    /**
2222     * Gets user operating system
2223     * @return {String}
2224     */
2225	MK.utils.OS = (function() {
2226		if (navigator.appVersion.indexOf("Win")!=-1) return "Windows";
2227		if (navigator.appVersion.indexOf("Mac")!=-1) return "OSX";
2228		if (navigator.appVersion.indexOf("X11")!=-1) return "UNIX";
2229		if (navigator.appVersion.indexOf("Linux")!=-1) return "Linux";
2230	})();
2231	
2232    /**
2233     * Check if mobile device.
2234     * @return {Boolean}
2235     */
2236	MK.utils.isMobile = function() {
2237        // Problems with bigger tablets as users raport differences with behaviour. Switch to navigator sniffing
2238		// return ('ontouchstart' in document.documentElement) && matchMedia( '(max-width: 1024px)' ).matches;
2239     
2240        // http://www.abeautifulsite.net/detecting-mobile-devices-with-javascript/
2241        // if it still brings problem try to move to more sophisticated solution like
2242        // apachemobilefilter.org
2243        // detectright.com
2244        // web.wurfl.io
2245        // 
2246        // Seems as best solution here:
2247        // hgoebl.github.io/mobile-detect.js
2248
2249        function android() {
2250            return navigator.userAgent.match(/Android/i);
2251        }
2252
2253        function blackBerry() {
2254            return navigator.userAgent.match(/BlackBerry/i);
2255        }
2256
2257        function iOS() {
2258            return navigator.userAgent.match(/iPhone|iPad|iPod/i);
2259        }
2260
2261        function opera() {
2262            return navigator.userAgent.match(/Opera Mini/i);
2263        }
2264
2265        function windows() {
2266            return navigator.userAgent.match(/IEMobile/i);
2267        }
2268
2269        return (android() || blackBerry() || iOS() || opera() || windows() || matchMedia( '(max-width: 1024px)' ).matches); 
2270            
2271	};
2272
2273    /**
2274     * Check if menu is switched to responsive state based on user width settings
2275     * @return {Boolean} 
2276     */
2277    MK.utils.isResponsiveMenuState = function() {
2278        return window.matchMedia( '(max-width: '+ mk_responsive_nav_width +'px)').matches;
2279    };
2280
2281
2282
2283    MK.utils.getUrlParameter = function getUrlParameter(sParam) {
2284        var sPageURL = decodeURIComponent(window.location.search.substring(1)),
2285            sURLVariables = sPageURL.split('&'),
2286            sParameterName,
2287            i;
2288
2289        for (i = 0; i < sURLVariables.length; i++) {
2290            sParameterName = sURLVariables[i].split('=');
2291
2292            if (sParameterName[0] === sParam) {
2293                return sParameterName[1] === undefined ? true : sParameterName[1];
2294            }
2295        }
2296    };
2297
2298
2299    MK.utils.isSmoothScroll = (function() {
2300        var isUserChoice = (mk_smooth_scroll === 'true');
2301
2302        // We notify our app about smooth scroll option when user choose it from admin panel.
2303        return isUserChoice;
2304    }());
2305
2306    MK.utils.showBackgroundVideo = (function() {
2307        var isUserChoice = (mk_show_background_video === 'true');
2308
2309        return isUserChoice;
2310    }());
2311
2312}(jQuery));
2313
2314(function($) {
2315	'use strict';
2316
2317    var MK = window.MK || {};
2318	MK.utils = window.MK.utils || {};
2319
2320	/**
2321	 * Basic implementation of pub / sub pattern to avoid tight coupling with direct module communication
2322	 * @type {Object}
2323	 */
2324	MK.utils.eventManager = {};
2325
2326	/**
2327	 * Subscribe to custom event and run callbacks
2328	 * @param  {String}
2329	 * @param  {Function}
2330	 *
2331	 * @usage MK.utils.eventManager.subscribe('event', function(e, params) {} )
2332	 */
2333	MK.utils.eventManager.subscribe = function(evt, func) {
2334		$(this).on(evt, func);
2335	};
2336
2337	/**
2338	 * Unsubscribe from custom event
2339	 * @param  {String}
2340	 * @param  {Function}
2341	 */
2342	MK.utils.eventManager.unsubscribe = function(evt, func) {
2343		$(this).off(evt, func);
2344	};
2345
2346	/**
2347	 * Publish custom event to notify appliaction about state change
2348	 * @param  {String}
2349	 * 
2350	 * @usage MK.utils.eventManager.publish('event', {
2351	 *        	param: val
2352	 *        })
2353	 */
2354	MK.utils.eventManager.publish = function(evt, params) {
2355		$(this).trigger(evt, [params]);
2356	};
2357
2358}(jQuery));
2359(function($) {
2360	'use strict';
2361
2362    var MK = window.MK || {};
2363	MK.utils = window.MK.utils || {};
2364
2365	/**
2366	 * Control browser fullscreen mode
2367	 * @type {Object}
2368	 */
2369	MK.utils.fullscreen = {};
2370
2371	// TODO: move to namespace
2372	MK.utils.launchIntoFullscreen = function ( element ) {
2373	    if(element.requestFullscreen) {
2374	     	element.requestFullscreen();
2375	  	} else if(element.mozRequestFullScreen) {
2376	    	element.mozRequestFullScreen();
2377	  	} else if(element.webkitRequestFullscreen) {
2378	    	element.webkitRequestFullscreen();
2379	  	} else if(element.msRequestFullscreen) {
2380	    	element.msRequestFullscreen();
2381	  	}
2382	};
2383
2384	MK.utils.exitFullscreen = function () {
2385	  	if(document.exitFullscreen) {
2386	    	document.exitFullscreen();
2387	  	} else if(document.mozCancelFullScreen) {
2388	    	document.mozCancelFullScreen();
2389	  	} else if(document.webkitExitFullscreen) {
2390	    	document.webkitExitFullscreen();
2391	  	}
2392	};
2393
2394}(jQuery));
2395(function($) {
2396	'use strict';
2397
2398    var MK = window.MK || {};
2399	MK.utils = window.MK.utils || {};
2400
2401	MK.utils.misc = {};
2402	// TODO: move to namespace
2403
2404	/**
2405	 * Get all top offsets from jQuery collection
2406	 * 
2407	 * @param  {$Objects}
2408	 * @return {Aray}
2409	 */
2410	MK.utils.offsets = function( $els ) {
2411		return $.map( $els, function( el ) {
2412			return $( el ).offset().top;
2413		});
2414	};
2415
2416	/**
2417	 * Retrive from array of numbers first number that is higher than given parameter
2418	 * 
2419	 * @param  {Number}
2420	 * @param  {Array}
2421	 * @return {Number}
2422	 */
2423	MK.utils.nextHigherVal = function( val, arr ) {
2424		var i = 0,
2425			higher = null;
2426
2427		var check = function() {
2428			if( val > arr[ i ]) {
2429				i += 1;
2430				check();
2431			} else {
2432				higher = arr[ i ];
2433			}
2434		};
2435		check();
2436
2437		return higher;
2438	};
2439
2440
2441    MK.utils.throttle = function( delay, fn ) {
2442        var last;
2443        var deferTimer;
2444
2445        return function() {
2446            var context = this;
2447            var args = arguments;
2448            var now = +new Date;
2449            if( last && now < last + delay ) {
2450            	clearTimeout( deferTimer );
2451            	deferTimer = setTimeout( function() { 
2452            		last = now; fn.apply( context, args ); 
2453            	}, delay );
2454          	} else {
2455            	last = now;
2456            	fn.apply( context, args );
2457          	}
2458        };
2459    };
2460
2461    MK.utils.isElementInViewport = function( el ) {
2462        var elemTop = el.getBoundingClientRect().top;
2463	    var isVisible = (elemTop < window.innerHeight);
2464	    return isVisible;
2465    };
2466
2467})(jQuery); 
2468(function($) {
2469	'use strict';
2470
2471    var MK = window.MK || {};
2472	MK.utils = window.MK.utils || {};
2473
2474	/**
2475	 * Scrolls page to static pixel offset
2476	 * @param  {Number}
2477	 */
2478	MK.utils.scrollTo = function( offset ) {
2479		$('html, body').stop().animate({
2480			scrollTop: offset
2481			}, {
2482	  		duration: 1200,
2483	  		easing: "easeInOutExpo"
2484		});
2485	};
2486
2487	/**
2488	 * Scrolls to element passed in as object or DOM reference
2489	 * @param  {String|Object}
2490	 */
2491	MK.utils.scrollToAnchor = function( hash ) {
2492		// Escape meta-chars from hash name only.
2493		hash = hash.substring(1).replace(/[!"#$%&'()*+,./:;<=>?@[\]^`{|}~]/g, "\\$&");
2494		hash = "#" + hash;
2495		var $target = $( hash );
2496		// console.log( hash );
2497
2498		if( ! $target.length ) return;
2499
2500		var offset  = $target.offset().top;
2501		offset = offset - MK.val.offsetHeaderHeight( offset );
2502
2503		if( hash === '#top-of-page' ) window.history.replaceState( undefined, undefined, ' ' );
2504		else window.history.replaceState( undefined, undefined, hash );
2505
2506		MK.utils.scrollTo( offset );
2507	};
2508
2509	/**
2510	 * Controls native scroll behaviour
2511	 * @return {Object} => {disable, enable}
2512	 */
2513	MK.utils.scroll = (function() {
2514        // 37 - left arror, 38 - up arrow, 39 right arrow, 40 down arrow
2515	    var keys = [38, 40];
2516
2517        function preventDefault(e) {
2518          e = e || window.event;
2519          e.preventDefault();
2520          e.returnValue = false;  
2521        }
2522
2523        function wheel(e) {
2524          preventDefault(e);
2525        }
2526
2527        function keydown(e) {
2528            for (var i = keys.length; i--;) {
2529                if (e.keyCode === keys[i]) {
2530                    preventDefault(e);
2531                    return;
2532                }
2533            }
2534        }
2535
2536        function disableScroll() {
2537            if (window.addEventListener) {
2538                window.addEventListener('DOMMouseScroll', wheel, false);
2539            }
2540          	window.onmousewheel = document.onmousewheel = wheel;
2541          	document.onkeydown = keydown;
2542        }
2543
2544        function enableScroll() {            
2545          	if (window.removeEventListener) {
2546                window.removeEventListener('DOMMouseScroll', wheel, false);
2547            }
2548            window.onmousewheel = document.onmousewheel = document.onkeydown = null; 
2549        }	
2550
2551        return {
2552        	disable : disableScroll,
2553        	enable  : enableScroll
2554        };
2555
2556	})();
2557
2558	/**
2559	 * Checks if passed link element has anchor inside current page. Returns string like '#anchor' if so or false
2560	 * @param  {String|Object}
2561	 * @return {String|Boolean}
2562	 */
2563	MK.utils.detectAnchor = function( el ) {
2564		var $this = $( el ),
2565			loc = window.location,
2566			currentPage = loc.origin + loc.pathname,
2567			href = $this.attr( 'href' ),
2568			linkSplit = (href) ? href.split( '#' ) : '',
2569			hrefPage  = linkSplit[0] ? linkSplit[0] : '', 
2570			hrefHash  = linkSplit[1] ? linkSplit[1] : '';
2571
2572		if( typeof hrefHash !== 'undefined' && hrefHash !== '' ) {
2573			return '#' + hrefHash;
2574		} else {
2575			return false;
2576		}
2577	};
2578
2579	/**
2580	 * This should be invoked only on page load. 
2581	 * Scrolls to anchor from  address bar
2582	 */
2583	MK.utils.scrollToURLHash = function() {
2584		var loc = window.location,
2585			hash = loc.hash;
2586
2587		if ( hash.length && hash.substring(1).length ) {
2588			// !loading is added early after DOM is ready to prevent native jump to anchor
2589			hash = hash.replace( '!loading', '' );
2590
2591			// Wait for one second before animating 
2592			// Most of UI animations should be done by then and async operations complited
2593			setTimeout( function() {
2594				MK.utils.scrollToAnchor( hash );
2595			}, 1000 ); 
2596
2597			// Right after reset back address bar
2598			setTimeout( function() {
2599				window.history.replaceState(undefined, undefined, hash);
2600			}, 1001);
2601		}
2602	};
2603
2604	/**
2605	 * Scroll Spy implementation. Spy dynamic offsets of elements or static pixel offset
2606	 * @param  {Number|Element}
2607	 * @param  {Object} => callback object {before, active, after}
2608	 */
2609	MK.utils.scrollSpy = function( toSpy, config ) {
2610		var $window   = $( window ),
2611	        container = document.getElementById( 'mk-theme-container' ),
2612	        isObj     = ( typeof toSpy === 'object' ),
2613	        offset    = (isObj) ? MK.val.dynamicOffset( toSpy, config.position, config.threshold ) : function() { return toSpy; },
2614	        height    = (isObj) ? MK.val.dynamicHeight( toSpy ) : function() { return 0; },
2615	        cacheVals = {},
2616	        _p 		  = 'before'; // current position
2617
2618		var checkPosition = function() {
2619	    	var s = MK.val.scroll(), 
2620	    		o = offset(),
2621	    		h = height();
2622
2623	        if( s < o && _p !== 'before' ) {
2624	        	// console.log( toSpy, 'before' );
2625	        	if( config.before ) config.before();
2626	        	_p = 'before';
2627	        } 
2628	        else if( s >= o && s <= o + h && _p !== 'active' ) {
2629	        	// console.log( toSpy, 'active' );
2630	        	if( config.active ) config.active( o );
2631	        	_p = 'active';
2632	        }
2633	        else if( s > o + h && _p !== 'after' ) {
2634	        	// console.log( toSpy, 'after' );
2635	        	if( config.after) config.after( o + h );
2636	        	_p = 'after';
2637	        }
2638		};
2639
2640		var rAF = function() {
2641			window.requestAnimationFrame( checkPosition );
2642		};
2643
2644		var exportVals = function() {
2645			return cacheVals;    
2646		};
2647
2648		var updateCache = function() {
2649	    	var o = offset(),
2650	    		h = height();
2651	    		
2652	        cacheVals = {
2653	        	before : o - $window.height(),
2654	        	active : o,
2655	        	after : o + h
2656	        };
2657		};
2658
2659		if( config.cache ) {
2660			config.cache( exportVals );
2661		}
2662
2663	    checkPosition();
2664	    $window.on( 'load', checkPosition );
2665	    $window.on( 'resize', checkPosition );
2666	    $window.on( 'mouseup', checkPosition );
2667   		window.addResizeListener( container, checkPosition );
2668
2669	    $window.on( 'scroll', rAF ); 
2670
2671   		updateCache();
2672	    $window.on( 'load', updateCache );
2673	    $window.on( 'resize', updateCache );
2674   		window.addResizeListener( container, updateCache );
2675	};
2676
2677}(jQuery));
2678(function($) {
2679    'use strict';
2680
2681    // Create delagation event handler to behave as "live" listener. We may provide new elements with ajax etc later
2682    // Just add js-taphover class whatever element you'd like to immidietely bring hover on touch devices
2683    $("body").on("click touchend", '.js-taphover', function (e) {
2684        var $link = $(e.currentTarget); // grab target
2685        var $target = $(e.target);
2686
2687        // Rather than ":hover" state we operate on ".hover" class which gives us more control and chance to emulate it on click
2688        // yet it is easy to reason about in our CSS
2689        if ($link.hasClass('hover')) {
2690            return true;
2691        } else if ( MK.utils.isMobile() ) {
2692            if ( ($target.hasClass('hover-icon') || $target.closest('.hover-icon').length) && !$target.closest('.js-taphover').hasClass('hover') ) {
2693                e.preventDefault();
2694            }
2695            $link.addClass('hover');
2696            $('.js-taphover').not(e.currentTarget).removeClass('hover'); // remove it from previous element
2697            e.stopPropagation(); // do not leak to document root if expected element was touched
2698        }
2699    });
2700
2701    // Whenever click leaks to the root romve all hover classes
2702    $(document).on("click", function(e) {
2703        $('.js-taphover').removeClass('hover');
2704    });
2705
2706}(jQuery));
2707// (function() {
2708//     'use strict';
2709
2710//     // Make sure the video behaves like background-size: cover
2711//     window.videoCover = function( holderSelector, videoSelector ) {
2712//         var videos = document.querySelectorAll( videoSelector ),
2713//             holder = document.querySelectorAll( holderSelector )[0];
2714
2715//         [].forEach.call(videos, function(video) {
2716
2717//             var videoAspectRatio;
2718
2719//             resizeBackground(); 
2720
2721//             video.onloadedmetadata = function() {
2722//                 // get images aspect ratio
2723//                 videoAspectRatio = this.height / this.width;
2724//                 // attach resize event and fire it once
2725//                 window.onresize = resizeBackground;
2726//                 resizeBackground();
2727//             };
2728
2729//             function resizeBackground() {
2730//                 // get window size and aspect ratio
2731//                 var holderWidth = holder.innerWidth,
2732//                     holderHeight = holder.innerHeight,
2733//                     holderAspectRatio = holderHeight / holderWidth;
2734
2735//                 //compare holder ratio to image ratio so you know which way the image should fill
2736//                 if ( holderAspectRatio < videoAspectRatio ) {
2737//                     // we are fill width
2738//                     video.style.width = holderWidth + "px";
2739//                     // and applying the correct aspect to the height now
2740//                     video.style.height = (holderWidth * videoAspectRatio) + "px"; // this can be margin if your element is not positioned relatively, absolutely or fixed
2741//                     // make sure image is always centered
2742//                     video.style.left = "0px";
2743//                     video.style.top = (holderHeight - (holderWidth * videoAspectRatio)) / 2 + "px";
2744//                 } else { // same thing as above but filling height instead
2745//                     video.style.height = holderHeight + "px";
2746//                     video.style.width = (holderHeight / videoAspectRatio) + "px";
2747//                     video.style.left = (holderWidth - (holderHeight / videoAspectRatio)) / 2 + "px";
2748//                     video.style.top = "0px";
2749//                 }
2750//             }
2751
2752//         });
2753//     };
2754
2755// }());
2756// 
2757// 
2758// 
2759// TODO it is temp only. make it as a plugin
2760
2761(function($) {
2762    'use strict';
2763
2764    var $videoHolder = $('.mk-center-video'),
2765        $wrapper = $videoHolder.parent(),
2766        baseAspectRatio = 56.25;
2767
2768    var wrapperHeight,
2769        wrapperWidth,
2770        wrapperAspectRatio;
2771
2772    function calc() {
2773        wrapperHeight = $wrapper.height();
2774        wrapperWidth = $wrapper.width();
2775        wrapperAspectRatio = (wrapperHeight / wrapperWidth) * 100;
2776    } 
2777
2778    function apply() {        
2779        var width = (wrapperAspectRatio / baseAspectRatio) * 100,
2780            widthOverflow = (width - 100);
2781
2782        $videoHolder.css({
2783            'padding-top': wrapperAspectRatio + '%',
2784            'width': width + '%',
2785            'left': -(widthOverflow / 2) + '%'
2786        }); 
2787    }
2788
2789    function reset() {
2790        $videoHolder.css({
2791            'padding-top': baseAspectRatio + '%',
2792            'width': 100 + '%',
2793            'left': 0
2794        });
2795    }
2796
2797    function setCover() {
2798        reset();
2799        calc();
2800        if(wrapperAspectRatio > baseAspectRatio) apply();
2801    }
2802
2803    $(window).on('load', setCover);
2804    $(window).on('resize', setCover);
2805
2806
2807}(jQuery));
2808(function($) {
2809	'use strict';
2810
2811	var MK = window.MK || {};
2812
2813	/**
2814	* 	MK.val is collection of Lambdas responsible for returning up to date values of method type like scrollY or el offset.
2815	* 	The Lambda is responsible for keeping track of value of a particular property, usually takes as argument an object
2816	* 	(or DOM reference) and internally creates and updates data that is returned as primitive value - through variable reference.
2817	*
2818	*  Benefits of this approach:
2819	*  - reduced DOM reads
2820	*  - auto-updating values without need for additional logic where methods are called
2821	*  - updating values when needed to be updated not read
2822	*
2823	*  Downsides:
2824	*  - Memory overhead with closures and keeping state in memory ( still beter than read state from DOM, but use wisely -
2825	*    do not use it when you really need static value on runtime )
2826	*/
2827	MK.val = {};
2828
2829	/**
2830	* Current window offsetY position
2831	*
2832	* @uses   MK.val.scroll()
2833	* @return {number}
2834	*/
2835	MK.val.scroll = (function() {
2836		var offset = 0,
2837		$window = $(window),
2838		hasPageYOffset = (window.pageYOffset !== undefined),
2839		body = (document.documentElement || document.body.parentNode || document.body); // cross browser handling
2840
2841		var update = function() {
2842			offset = hasPageYOffset ? window.pageYOffset : body.scrollTop;
2843		};
2844
2845		var rAF = function() {
2846			window.requestAnimationFrame(update);
2847		};
2848
2849		update();
2850		$window.on('load', update);
2851		$window.on('resize', update);
2852		$window.on('scroll', rAF);
2853
2854		return function() {
2855			return offset;
2856		};
2857	})();
2858
2859
2860	/**
2861	* Changes number of percent to pixels based on viewport height
2862	*
2863	* @uses   MK.val.viewportPercentHeight({percent val})
2864	* @param  {number}
2865	* @return {number}
2866	*/
2867	MK.val.viewportPercentHeight = function(percent) {
2868		return $(window).height() * (percent / 100);
2869	};
2870
2871
2872	/**
2873	* Wordpress adminbar height based on wp media queries
2874	* @return {Number}
2875	*/
2876	MK.val.adminbarHeight = function() {
2877		if (php.hasAdminbar) {
2878			// apply WP native media-query and sizes
2879			return (window.matchMedia('( max-width: 782px )').matches) ? 46 : 32;
2880		} else {
2881			return 0;
2882		}
2883	};
2884
2885
2886	/**
2887	* Offset when header becomes sticky. Evaluates viewport % and header height to pixels for according options
2888	* @return {Number}
2889	*/
2890	MK.val.stickyOffset = (function() {
2891		var $header = $('.mk-header').not('.js-header-shortcode').first();
2892
2893		// We need to have returning function even when header is disabled
2894		if (!$header.length) {
2895			return function() {
2896				return 0;
2897			};
2898		}
2899
2900
2901
2902		var $toolbar = $header.find('.mk-header-toolbar'),
2903		config = $header.data(),
2904		hasToolbar = $toolbar.length,
2905		toolbarHeight = (hasToolbar) ? $toolbar.height() : 0,
2906		isVertical = (config.headerStyle === 4),
2907		headerHeight = (isVertical) ? 0 : config.height;
2908
2909		var type = ((typeof config.stickyOffset === 'number') ? 'number' : false) ||
2910		((config.stickyOffset === 'header') ? 'header' : false) ||
2911		'percent';
2912
2913		var stickyOffset = 0;
2914		var setOffset = function() {
2915
2916			//we calculate toolbar height for When the device is changed Size
2917			//Toolbar height in responsive state is 0
2918			toolbarHeight = (hasToolbar) ? $toolbar.height() : 0;
2919
2920			if (MK.utils.isResponsiveMenuState()) {
2921				headerHeight = config.responsiveHeight;
2922
2923				if (hasToolbar) {
2924					if ($toolbar.is(':hidden')) {
2925						toolbarHeight = 0;
2926					}
2927				}
2928			}
2929
2930			if (type === 'number') {
2931				stickyOffset = config.stickyOffset;
2932			} else if (type === 'header') {
2933
2934				stickyOffset = headerHeight + toolbarHeight + MK.val.adminbarHeight(); // add all header components here, make them 0 if needed
2935
2936			} else if (type === 'percent') {
2937				stickyOffset = MK.val.viewportPercentHeight(parseInt(config.stickyOffset));
2938			}
2939		};
2940
2941		setOffset();
2942		$(window).on('resize', setOffset);
2943
2944		return function() {
2945			return stickyOffset;
2946		};
2947	}());
2948
2949
2950
2951	/**
2952	* Gets header height on particular offsetY position. Use to determine logic for fullHeight, smooth scroll etc.
2953	* Takes one parameter which is offset position we're interested in.
2954	*
2955	* @uses   MK.val.offsetHeaderHeight({offset val})
2956	* @param  {number}
2957	* @return {number}
2958	*/
2959	MK.val.offsetHeaderHeight = (function() { // Closure avoids multiple DOM reads. We need to fetch header config only once.
2960		var $header = $('.mk-header').not('.js-header-shortcode').first();
2961
2962		// We need to have returning function even when header is disabled
2963		if (!$header.length) {
2964			return function() {
2965				return 0;
2966			};
2967		}
2968
2969		var $toolbar = $header.find('.mk-header-toolbar'),
2970		config = $header.data(),
2971		stickyHeight = config.stickyHeight,
2972		desktopHeight = config.height,
2973		mobileHeight = config.responsiveHeight,
2974		isTransparent = $header.hasClass('transparent-header'),
2975		isSticky = config.stickyStyle.length,
2976		isStickyLazy = config.stickyStyle === 'lazy',
2977		isVertical = config.headerStyle === 4,
2978		hasToolbar = $toolbar.length,
2979		toolbarHeight = hasToolbar ? $toolbar.height() : 0,
2980		bufor = 5;
2981
2982		/**
2983		 * The sticky section of header style 2 has fixed height.
2984		 * The stickey height option does not affect this header style.
2985		 */
2986		if ( config.headerStyle === 2 ) {
2987			stickyHeight = $header.find( '.mk-header-nav-container' ).outerHeight();
2988		}
2989
2990		// if header has border bottom we can calculate that (for responsive state)
2991		var $innerHeader = $header.find('.mk-header-inner');
2992		var hasInnerHeader = $innerHeader.length;
2993
2994		var headerHeight = function(offset) {
2995
2996			toolbarHeight = hasToolbar ? $toolbar.height() : 0
2997			var stickyOffset = MK.val.stickyOffset();
2998
2999
3000			if (MK.utils.isResponsiveMenuState()) { //  Header avaible only on top for mobile
3001
3002				if (hasToolbar && $toolbar.is(':hidden')) {
3003					toolbarHeight = 0;
3004				}
3005
3006				//in responsive state , .mk-header-holder position's changed to "relative"
3007				//and header's border affected to offset,so borders must be calculated
3008				var headerBorder = 0;
3009				headerBorder = parseInt($innerHeader.css('border-bottom-width'));
3010
3011				var totalHeight = mobileHeight + MK.val.adminbarHeight() + toolbarHeight + headerBorder;
3012
3013				if (offset <= totalHeight) return totalHeight;
3014				else return MK.val.adminbarHeight();
3015			} else {
3016				if (offset <= stickyOffset) {
3017					if (isVertical) {
3018						if (hasToolbar) {
3019							return toolbarHeight + MK.val.adminbarHeight();
3020						} else {
3021							return MK.val.adminbarHeight();
3022						}
3023					} else if (isTransparent) {
3024						return MK.val.adminbarHeight();
3025					} else {
3026						return desktopHeight + toolbarHeight + MK.val.adminbarHeight();
3027					} // For any other return regular desktop height
3028				} else if (offset > stickyOffset) {
3029					if (isVertical) {
3030						return MK.val.adminbarHeight();
3031					} else if (!isSticky) {
3032						return MK.val.adminbarHeight();
3033					} else if (isStickyLazy) {
3034						return MK.val.adminbarHeight();
3035					} else if (isSticky) {
3036						return stickyHeight + MK.val.adminbarHeight();
3037					}
3038				}
3039			}
3040			// default to 0 to prevent errors ( need to return number )
3041			// Anyway make sure all scenarios are covered in IFs
3042			return 0;
3043		};
3044
3045		return function(offset) {
3046			return headerHeight(offset - MK.val.adminbarHeight());
3047		};
3048	})();
3049
3050
3051	/**
3052	* Gets current offset of given element (passed as object or DOM reference) from top or bottom (default to top)
3053	* of screen  with possible threshold (default to 0)
3054	*
3055	* @uses   MK.val.dynamicOffset({obj reference}, {'top'|'bottom'}, {threshold val})
3056	* @param  {string|object}
3057	* @param  {string}
3058	* @param  {number}
3059	* @return {number}
3060	*/
3061	MK.val.dynamicOffset = function(el, position, threshold) {
3062		var $window = $(window),
3063		$el = $(el),
3064		pos = position || 'top',
3065		thr = threshold || 0,
3066		container = document.getElementById('mk-theme-container'),
3067		currentPos = 0;
3068
3069		var offset = 0,
3070		winH = 0,
3071		rect = 0,
3072		x = 0;
3073
3074		var update = function() {
3075			winH = $window.height();
3076			rect = $el[0].getBoundingClientRect();
3077			offset = (rect.top + MK.val.scroll());
3078			x = (pos === 'top') ? MK.val.offsetHeaderHeight(offset) : winH + (rect.height - thr);
3079			currentPos = offset - x - 1;
3080		};
3081
3082		update();
3083		$window.on('load', update);
3084		$window.on('resize', update);
3085		window.addResizeListener(container, update);
3086
3087		return function() {
3088			return currentPos;
3089		};
3090	};
3091
3092	/**
3093	* Gets current height of given element (passed as object or DOM reference)
3094	*
3095	* @uses   MK.val.dynamicHeight({obj reference})
3096	* @param  {string|object}
3097	* @return {number}
3098	*/
3099	MK.val.dynamicHeight = function(el) {
3100		var $window = $(window),
3101		$el = $(el),
3102		container = document.getElementById('mk-theme-container'),
3103		currentHeight = 0;
3104
3105		var update = function() {
3106			currentHeight = $el.outerHeight();
3107		};
3108
3109		update();
3110		$window.on('load', update);
3111		$window.on('resize', update);
3112		window.addResizeListener(container, update);
3113
3114		return function() {
3115			return currentHeight;
3116		};
3117	};
3118
3119})(jQuery);
3120
3121/*
3122 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
3123 *
3124 */
3125jQuery.easing["jswing"] = jQuery.easing["swing"];
3126jQuery.extend(jQuery.easing, {
3127        def: "easeOutQuad",
3128        swing: function (a, b, c, d, e) {
3129                return jQuery.easing[jQuery.easing.def](a, b, c, d, e)
3130        },
3131        easeInQuad: function (a, b, c, d, e) {
3132                return d * (b /= e) * b + c
3133        },
3134        easeOutQuad: function (a, b, c, d, e) {
3135                return -d * (b /= e) * (b - 2) + c
3136        },
3137        easeInOutQuad: function (a, b, c, d, e) {
3138                if ((b /= e / 2) < 1) return d / 2 * b * b + c;
3139                return -d / 2 * (--b * (b - 2) - 1) + c
3140        },
3141        easeInCubic: function (a, b, c, d, e) {
3142                return d * (b /= e) * b * b + c
3143        },
3144        easeOutCubic: function (a, b, c, d, e) {
3145                return d * ((b = b / e - 1) * b * b + 1) + c
3146        },
3147        easeInOutCubic: function (a, b, c, d, e) {
3148                if ((b /= e / 2) < 1) return d / 2 * b * b * b + c;
3149                return d / 2 * ((b -= 2) * b * b + 2) + c
3150        },
3151        easeInQuart: function (a, b, c, d, e) {
3152                return d * (b /= e) * b * b * b + c
3153        },
3154        easeOutQuart: function (a, b, c, d, e) {
3155                return -d * ((b = b / e - 1) * b * b * b - 1) + c
3156        },
3157        easeInOutQuart: function (a, b, c, d, e) {
3158                if ((b /= e / 2) < 1) return d / 2 * b * b * b * b + c;
3159                return -d / 2 * ((b -= 2) * b * b * b - 2) + c
3160        },
3161        easeInQuint: function (a, b, c, d, e) {
3162                return d * (b /= e) * b * b * b * b + c
3163        },
3164        easeOutQuint: function (a, b, c, d, e) {
3165                return d * ((b = b / e - 1) * b * b * b * b + 1) + c
3166        },
3167        easeInOutQuint: function (a, b, c, d, e) {
3168                if ((b /= e / 2) < 1) return d / 2 * b * b * b * b * b + c;
3169                return d / 2 * ((b -= 2) * b * b * b * b + 2) + c
3170        },
3171        easeInSine: function (a, b, c, d, e) {
vendor: 5,544 bytes, lines 3172-3311
3172                return -d * Math.cos(b / e * (Math.PI / 2)) + d + c
3173        },
3174        easeOutSine: function (a, b, c, d, e) {
3175                return d * Math.sin(b / e * (Math.PI / 2)) + c
3176        },
3177        easeInOutSine: function (a, b, c, d, e) {
3178                return -d / 2 * (Math.cos(Math.PI * b / e) - 1) + c
3179        },
3180        easeInExpo: function (a, b, c, d, e) {
3181                return b == 0 ? c : d * Math.pow(2, 10 * (b / e - 1)) + c
3182        },
3183        easeOutExpo: function (a, b, c, d, e) {
3184                return b == e ? c + d : d * (-Math.pow(2, -10 * b / e) + 1) + c
3185        },
3186        easeInOutExpo: function (a, b, c, d, e) {
3187                if (b == 0) return c;
3188                if (b == e) return c + d;
3189                if ((b /= e / 2) < 1) return d / 2 * Math.pow(2, 10 * (b - 1)) + c;
3190                return d / 2 * (-Math.pow(2, -10 * --b) + 2) + c
3191        },
3192        easeInCirc: function (a, b, c, d, e) {
3193                return -d * (Math.sqrt(1 - (b /= e) * b) - 1) + c
3194        },
3195        easeOutCirc: function (a, b, c, d, e) {
3196                return d * Math.sqrt(1 - (b = b / e - 1) * b) + c
3197        },
3198        easeInOutCirc: function (a, b, c, d, e) {
3199                if ((b /= e / 2) < 1) return -d / 2 * (Math.sqrt(1 - b * b) - 1) + c;
3200                return d / 2 * (Math.sqrt(1 - (b -= 2) * b) + 1) + c
3201        },
3202        easeInElastic: function (a, b, c, d, e) {
3203                var f = 1.70158;
3204                var g = 0;
3205                var h = d;
3206                if (b == 0) return c;
3207                if ((b /= e) == 1) return c + d;
3208                if (!g) g = e * .3;
3209                if (h < Math.abs(d)) {
3210                        h = d;
3211                        var f = g / 4
3212                } else var f = g / (2 * Math.PI) * Math.asin(d / h);
3213                return -(h * Math.pow(2, 10 * (b -= 1)) * Math.sin((b * e - f) * 2 * Math.PI / g)) + c
3214        },
3215        easeOutElastic: function (a, b, c, d, e) {
3216                var f = 1.70158;
3217                var g = 0;
3218                var h = d;
3219                if (b == 0) return c;
3220                if ((b /= e) == 1) return c + d;
3221                if (!g) g = e * .3;
3222                if (h < Math.abs(d)) {
3223                        h = d;
3224                        var f = g / 4
3225                } else var f = g / (2 * Math.PI) * Math.asin(d / h);
3226                return h * Math.pow(2, -10 * b) * Math.sin((b * e - f) * 2 * Math.PI / g) + d + c
3227        },
3228        easeInOutElastic: function (a, b, c, d, e) {
3229                var f = 1.70158;
3230                var g = 0;
3231                var h = d;
3232                if (b == 0) return c;
3233                if ((b /= e / 2) == 2) return c + d;
3234                if (!g) g = e * .3 * 1.5;
3235                if (h < Math.abs(d)) {
3236                        h = d;
3237                        var f = g / 4
3238                } else var f = g / (2 * Math.PI) * Math.asin(d / h);
3239                if (b < 1) return -.5 * h * Math.pow(2, 10 * (b -= 1)) * Math.sin((b * e - f) * 2 * Math.PI / g) + c;
3240                return h * Math.pow(2, -10 * (b -= 1)) * Math.sin((b * e - f) * 2 * Math.PI / g) * .5 + d + c
3241        },
3242        easeInBack: function (a, b, c, d, e, f) {
3243                if (f == undefined) f = 1.70158;
3244                return d * (b /= e) * b * ((f + 1) * b - f) + c
3245        },
3246        easeOutBack: function (a, b, c, d, e, f) {
3247                if (f == undefined) f = 1.70158;
3248                return d * ((b = b / e - 1) * b * ((f + 1) * b + f) + 1) + c
3249        },
3250        easeInOutBack: function (a, b, c, d, e, f) {
3251                if (f == undefined) f = 1.70158;
3252                if ((b /= e / 2) < 1) return d / 2 * b * b * (((f *= 1.525) + 1) * b - f) + c;
3253                return d / 2 * ((b -= 2) * b * (((f *= 1.525) + 1) * b + f) + 2) + c
3254        },
3255        easeInBounce: function (a, b, c, d, e) {
3256                return d - jQuery.easing.easeOutBounce(a, e - b, 0, d, e) + c
3257        },
3258        easeOutBounce: function (a, b, c, d, e) {
3259                if ((b /= e) < 1 / 2.75) {
3260                        return d * 7.5625 * b * b + c
3261                } else if (b < 2 / 2.75) {
3262                        return d * (7.5625 * (b -= 1.5 / 2.75) * b + .75) + c
3263                } else if (b < 2.5 / 2.75) {
3264                        return d * (7.5625 * (b -= 2.25 / 2.75) * b + .9375) + c
3265                } else {
3266                        return d * (7.5625 * (b -= 2.625 / 2.75) * b + .984375) + c
3267                }
3268        },
3269        easeInOutBounce: function (a, b, c, d, e) {
3270                if (b < e / 2) return jQuery.easing.easeInBounce(a, b * 2, 0, d, e) * .5 + c;
3271                return jQuery.easing.easeOutBounce(a, b * 2 - e, 0, d, e) * .5 + d * .5 + c
3272        }
3273});
3274// ==================================================
3275// fancyBox v3.5.7
3276//
3277// Licensed GPLv3 for open source use
3278// or fancyBox Commercial License for commercial use
3279//
3280// http://fancyapps.com/fancybox/
3281// Copyright 2019 fancyApps
3282//
3283// ==================================================
3284(function (window, document, $, undefined) {
3285	"use strict";
3286
3287	window.console = window.console || {
3288	  info: function (stuff) {}
3289	};
3290
3291	// If there's no jQuery, fancyBox can't work
3292	// =========================================
3293
3294	if (!$) {
3295	  return;
3296	}
3297
3298	// Check if fancyBox is already initialized
3299	// ========================================
3300
3301	if ($.fn.fancybox) {
3302	  console.info("fancyBox already initialized");
3303
3304	  return;
3305	}
3306
3307	// Private default settings
3308	// ========================
3309
3310	var defaults = {
3311	  // Close existing modals
vendor: 141,869 bytes, lines 3312-8848
3312	  // Set this to false if you do not need to stack multiple instances
3313	  closeExisting: false,
3314
3315	  // Enable infinite gallery navigation
3316	  loop: false,
3317
3318	  // Horizontal space between slides
3319	  gutter: 50,
3320
3321	  // Enable keyboard navigation
3322	  keyboard: true,
3323
3324	  // Should allow caption to overlap the content
3325	  preventCaptionOverlap: true,
3326
3327	  // Should display navigation arrows at the screen edges
3328	  arrows: true,
3329
3330	  // Should display counter at the top left corner
3331	  infobar: true,
3332
3333	  // Should display close button (using `btnTpl.smallBtn` template) over the content
3334	  // Can be true, false, "auto"
3335	  // If "auto" - will be automatically enabled for "html", "inline" or "ajax" items
3336	  smallBtn: "auto",
3337
3338	  // Should display toolbar (buttons at the top)
3339	  // Can be true, false, "auto"
3340	  // If "auto" - will be automatically hidden if "smallBtn" is enabled
3341	  toolbar: "auto",
3342
3343	  // What buttons should appear in the top right corner.
3344	  // Buttons will be created using templates from `btnTpl` option
3345	  // and they will be placed into toolbar (class="fancybox-toolbar"` element)
3346	  buttons: [
3347		"zoom",
3348		//"share",
3349		"slideShow",
3350		//"fullScreen",
3351		//"download",
3352		"thumbs",
3353		"close"
3354	  ],
3355
3356	  // Detect "idle" time in seconds
3357	  idleTime: 3,
3358
3359	  // Disable right-click and use simple image protection for images
3360	  protect: false,
3361
3362	  // Shortcut to make content "modal" - disable keyboard navigtion, hide buttons, etc
3363	  modal: false,
3364
3365	  image: {
3366		// Wait for images to load before displaying
3367		//   true  - wait for image to load and then display;
3368		//   false - display thumbnail and load the full-sized image over top,
3369		//           requires predefined image dimensions (`data-width` and `data-height` attributes)
3370		preload: false
3371	  },
3372
3373	  ajax: {
3374		// Object containing settings for ajax request
3375		settings: {
3376		  // This helps to indicate that request comes from the modal
3377		  // Feel free to change naming
3378		  data: {
3379			fancybox: true
3380		  }
3381		}
3382	  },
3383
3384	  iframe: {
3385		// Iframe template
3386		tpl: '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" allowfullscreen="allowfullscreen" allow="autoplay; fullscreen" src=""></iframe>',
3387
3388		// Preload iframe before displaying it
3389		// This allows to calculate iframe content width and height
3390		// (note: Due to "Same Origin Policy", you can't get cross domain data).
3391		preload: true,
3392
3393		// Custom CSS styling for iframe wrapping element
3394		// You can use this to set custom iframe dimensions
3395		css: {},
3396
3397		// Iframe tag attributes
3398		attr: {
3399		  scrolling: "auto"
3400		}
3401	  },
3402
3403	  // For HTML5 video only
3404	  video: {
3405		tpl: '<video class="fancybox-video" controls controlsList="nodownload" poster="{{poster}}">' +
3406		  '<source src="{{src}}" type="{{format}}" />' +
3407		  'Sorry, your browser doesn\'t support embedded videos, <a href="{{src}}">download</a> and watch with your favorite video player!' +
3408		  "</video>",
3409		format: "", // custom video format
3410		autoStart: true
3411	  },
3412
3413	  // Default content type if cannot be detected automatically
3414	  defaultType: "image",
3415
3416	  // Open/close animation type
3417	  // Possible values:
3418	  //   false            - disable
3419	  //   "zoom"           - zoom images from/to thumbnail
3420	  //   "fade"
3421	  //   "zoom-in-out"
3422	  //
3423	  animationEffect: "zoom",
3424
3425	  // Duration in ms for open/close animation
3426	  animationDuration: 366,
3427
3428	  // Should image change opacity while zooming
3429	  // If opacity is "auto", then opacity will be changed if image and thumbnail have different aspect ratios
3430	  zoomOpacity: "auto",
3431
3432	  // Transition effect between slides
3433	  //
3434	  // Possible values:
3435	  //   false            - disable
3436	  //   "fade'
3437	  //   "slide'
3438	  //   "circular'
3439	  //   "tube'
3440	  //   "zoom-in-out'
3441	  //   "rotate'
3442	  //
3443	  transitionEffect: "fade",
3444
3445	  // Duration in ms for transition animation
3446	  transitionDuration: 366,
3447
3448	  // Custom CSS class for slide element
3449	  slideClass: "",
3450
3451	  // Custom CSS class for layout
3452	  baseClass: "",
3453
3454	  // Base template for layout
3455	  baseTpl: '<div class="fancybox-container" role="dialog" tabindex="-1">' +
3456		'<div class="fancybox-bg"></div>' +
3457		'<div class="fancybox-inner">' +
3458		'<div class="fancybox-infobar"><span data-fancybox-index></span>&nbsp;/&nbsp;<span data-fancybox-count></span></div>' +
3459		'<div class="fancybox-toolbar">{{buttons}}</div>' +
3460		'<div class="fancybox-navigation">{{arrows}}</div>' +
3461		'<div class="fancybox-stage"></div>' +
3462		'<div class="fancybox-caption"><div class="fancybox-caption__body"></div></div>' +
3463		"</div>" +
3464		"</div>",
3465
3466	  // Loading indicator template
3467	  spinnerTpl: '<div class="fancybox-loading"></div>',
3468
3469	  // Error message template
3470	  errorTpl: '<div class="fancybox-error"><p>{{ERROR}}</p></div>',
3471
3472	  btnTpl: {
3473		download: '<a download data-fancybox-download class="fancybox-button fancybox-button--download" title="{{DOWNLOAD}}" href="javascript:;">' +
3474		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.62 17.09V19H5.38v-1.91zm-2.97-6.96L17 11.45l-5 4.87-5-4.87 1.36-1.32 2.68 2.64V5h1.92v7.77z"/></svg>' +
3475		  "</a>",
3476
3477		zoom: '<button data-fancybox-zoom class="fancybox-button fancybox-button--zoom" title="{{ZOOM}}">' +
3478		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.7 17.3l-3-3a5.9 5.9 0 0 0-.6-7.6 5.9 5.9 0 0 0-8.4 0 5.9 5.9 0 0 0 0 8.4 5.9 5.9 0 0 0 7.7.7l3 3a1 1 0 0 0 1.3 0c.4-.5.4-1 0-1.5zM8.1 13.8a4 4 0 0 1 0-5.7 4 4 0 0 1 5.7 0 4 4 0 0 1 0 5.7 4 4 0 0 1-5.7 0z"/></svg>' +
3479		  "</button>",
3480
3481		close: '<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}">' +
3482		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 10.6L6.6 5.2 5.2 6.6l5.4 5.4-5.4 5.4 1.4 1.4 5.4-5.4 5.4 5.4 1.4-1.4-5.4-5.4 5.4-5.4-1.4-1.4-5.4 5.4z"/></svg>' +
3483		  "</button>",
3484
3485		// Arrows
3486		arrowLeft: '<button data-fancybox-prev class="fancybox-button fancybox-button--arrow_left" title="{{PREV}}">' +
3487		  '<div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11.28 15.7l-1.34 1.37L5 12l4.94-5.07 1.34 1.38-2.68 2.72H19v1.94H8.6z"/></svg></div>' +
3488		  "</button>",
3489
3490		arrowRight: '<button data-fancybox-next class="fancybox-button fancybox-button--arrow_right" title="{{NEXT}}">' +
3491		  '<div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.4 12.97l-2.68 2.72 1.34 1.38L19 12l-4.94-5.07-1.34 1.38 2.68 2.72H5v1.94z"/></svg></div>' +
3492		  "</button>",
3493
3494		// This small close button will be appended to your html/inline/ajax content by default,
3495		// if "smallBtn" option is not set to false
3496		smallBtn: '<button type="button" data-fancybox-close class="fancybox-button fancybox-close-small" title="{{CLOSE}}">' +
3497		  '<svg xmlns="http://www.w3.org/2000/svg" version="1" viewBox="0 0 24 24"><path d="M13 12l5-5-1-1-5 5-5-5-1 1 5 5-5 5 1 1 5-5 5 5 1-1z"/></svg>' +
3498		  "</button>"
3499	  },
3500
3501	  // Container is injected into this element
3502	  parentEl: "body",
3503
3504	  // Hide browser vertical scrollbars; use at your own risk
3505	  hideScrollbar: true,
3506
3507	  // Focus handling
3508	  // ==============
3509
3510	  // Try to focus on the first focusable element after opening
3511	  autoFocus: true,
3512
3513	  // Put focus back to active element after closing
3514	  backFocus: true,
3515
3516	  // Do not let user to focus on element outside modal content
3517	  trapFocus: true,
3518
3519	  // Module specific options
3520	  // =======================
3521
3522	  fullScreen: {
3523		autoStart: false
3524	  },
3525
3526	  // Set `touch: false` to disable panning/swiping
3527	  touch: {
3528		vertical: true, // Allow to drag content vertically
3529		momentum: true // Continue movement after releasing mouse/touch when panning
3530	  },
3531
3532	  // Hash value when initializing manually,
3533	  // set `false` to disable hash change
3534	  hash: null,
3535
3536	  // Customize or add new media types
3537	  // Example:
3538	  /*
3539		media : {
3540		  youtube : {
3541			params : {
3542			  autoplay : 0
3543			}
3544		  }
3545		}
3546	  */
3547	  media: {},
3548
3549	  slideShow: {
3550		autoStart: false,
3551		speed: 3000
3552	  },
3553
3554	  thumbs: {
3555		autoStart: false, // Display thumbnails on opening
3556		hideOnClose: true, // Hide thumbnail grid when closing animation starts
3557		parentEl: ".fancybox-container", // Container is injected into this element
3558		axis: "y" // Vertical (y) or horizontal (x) scrolling
3559	  },
3560
3561	  // Use mousewheel to navigate gallery
3562	  // If 'auto' - enabled for images only
3563	  wheel: "auto",
3564
3565	  // Callbacks
3566	  //==========
3567
3568	  // See Documentation/API/Events for more information
3569	  // Example:
3570	  /*
3571		afterShow: function( instance, current ) {
3572		  console.info( 'Clicked element:' );
3573		  console.info( current.opts.$orig );
3574		}
3575	  */
3576
3577	  onInit: $.noop, // When instance has been initialized
3578
3579	  beforeLoad: $.noop, // Before the content of a slide is being loaded
3580	  afterLoad: $.noop, // When the content of a slide is done loading
3581
3582	  beforeShow: $.noop, // Before open animation starts
3583	  afterShow: $.noop, // When content is done loading and animating
3584
3585	  beforeClose: $.noop, // Before the instance attempts to close. Return false to cancel the close.
3586	  afterClose: $.noop, // After instance has been closed
3587
3588	  onActivate: $.noop, // When instance is brought to front
3589	  onDeactivate: $.noop, // When other instance has been activated
3590
3591	  // Interaction
3592	  // ===========
3593
3594	  // Use options below to customize taken action when user clicks or double clicks on the fancyBox area,
3595	  // each option can be string or method that returns value.
3596	  //
3597	  // Possible values:
3598	  //   "close"           - close instance
3599	  //   "next"            - move to next gallery item
3600	  //   "nextOrClose"     - move to next gallery item or close if gallery has only one item
3601	  //   "toggleControls"  - show/hide controls
3602	  //   "zoom"            - zoom image (if loaded)
3603	  //   false             - do nothing
3604
3605	  // Clicked on the content
3606	  clickContent: function (current, event) {
3607		return current.type === "image" ? "zoom" : false;
3608	  },
3609
3610	  // Clicked on the slide
3611	  clickSlide: "close",
3612
3613	  // Clicked on the background (backdrop) element;
3614	  // if you have not changed the layout, then most likely you need to use `clickSlide` option
3615	  clickOutside: "close",
3616
3617	  // Same as previous two, but for double click
3618	  dblclickContent: false,
3619	  dblclickSlide: false,
3620	  dblclickOutside: false,
3621
3622	  // Custom options when mobile device is detected
3623	  // =============================================
3624
3625	  mobile: {
3626		preventCaptionOverlap: false,
3627		idleTime: false,
3628		clickContent: function (current, event) {
3629		  return current.type === "image" ? "toggleControls" : false;
3630		},
3631		clickSlide: function (current, event) {
3632		  return current.type === "image" ? "toggleControls" : "close";
3633		},
3634		dblclickContent: function (current, event) {
3635		  return current.type === "image" ? "zoom" : false;
3636		},
3637		dblclickSlide: function (current, event) {
3638		  return current.type === "image" ? "zoom" : false;
3639		}
3640	  },
3641
3642	  // Internationalization
3643	  // ====================
3644
3645	  lang: "en",
3646	  i18n: {
3647		en: {
3648		  CLOSE: "Close",
3649		  NEXT: "Next",
3650		  PREV: "Previous",
3651		  ERROR: "The requested content cannot be loaded. <br/> Please try again later.",
3652		  PLAY_START: "Start slideshow",
3653		  PLAY_STOP: "Pause slideshow",
3654		  FULL_SCREEN: "Full screen",
3655		  THUMBS: "Thumbnails",
3656		  DOWNLOAD: "Download",
3657		  SHARE: "Share",
3658		  ZOOM: "Zoom"
3659		},
3660		de: {
3661		  CLOSE: "Schlie&szlig;en",
3662		  NEXT: "Weiter",
3663		  PREV: "Zur&uuml;ck",
3664		  ERROR: "Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es sp&auml;ter nochmal.",
3665		  PLAY_START: "Diaschau starten",
3666		  PLAY_STOP: "Diaschau beenden",
3667		  FULL_SCREEN: "Vollbild",
3668		  THUMBS: "Vorschaubilder",
3669		  DOWNLOAD: "Herunterladen",
3670		  SHARE: "Teilen",
3671		  ZOOM: "Vergr&ouml;&szlig;ern"
3672		}
3673	  }
3674	};
3675
3676	// Few useful variables and methods
3677	// ================================
3678
3679	var $W = $(window);
3680	var $D = $(document);
3681
3682	var called = 0;
3683
3684	// Check if an object is a jQuery object and not a native JavaScript object
3685	// ========================================================================
3686	var isQuery = function (obj) {
3687	  return obj && obj.hasOwnProperty && obj instanceof $;
3688	};
3689
3690	// Handle multiple browsers for "requestAnimationFrame" and "cancelAnimationFrame"
3691	// ===============================================================================
3692	var requestAFrame = (function () {
3693	  return (
3694		window.requestAnimationFrame ||
3695		window.webkitRequestAnimationFrame ||
3696		window.mozRequestAnimationFrame ||
3697		window.oRequestAnimationFrame ||
3698		// if all else fails, use setTimeout
3699		function (callback) {
3700		  return window.setTimeout(callback, 1000 / 60);
3701		}
3702	  );
3703	})();
3704
3705	var cancelAFrame = (function () {
3706	  return (
3707		window.cancelAnimationFrame ||
3708		window.webkitCancelAnimationFrame ||
3709		window.mozCancelAnimationFrame ||
3710		window.oCancelAnimationFrame ||
3711		function (id) {
3712		  window.clearTimeout(id);
3713		}
3714	  );
3715	})();
3716
3717	// Detect the supported transition-end event property name
3718	// =======================================================
3719	var transitionEnd = (function () {
3720	  var el = document.createElement("fakeelement"),
3721		t;
3722
3723	  var transitions = {
3724		transition: "transitionend",
3725		OTransition: "oTransitionEnd",
3726		MozTransition: "transitionend",
3727		WebkitTransition: "webkitTransitionEnd"
3728	  };
3729
3730	  for (t in transitions) {
3731		if (el.style[t] !== undefined) {
3732		  return transitions[t];
3733		}
3734	  }
3735
3736	  return "transitionend";
3737	})();
3738
3739	// Force redraw on an element.
3740	// This helps in cases where the browser doesn't redraw an updated element properly
3741	// ================================================================================
3742	var forceRedraw = function ($el) {
3743	  return $el && $el.length && $el[0].offsetHeight;
3744	};
3745
3746	// Exclude array (`buttons`) options from deep merging
3747	// ===================================================
3748	var mergeOpts = function (opts1, opts2) {
3749	  var rez = $.extend(true, {}, opts1, opts2);
3750
3751	  $.each(opts2, function (key, value) {
3752		if ($.isArray(value)) {
3753		  rez[key] = value;
3754		}
3755	  });
3756
3757	  return rez;
3758	};
3759
3760	// How much of an element is visible in viewport
3761	// =============================================
3762
3763	var inViewport = function (elem) {
3764	  var elemCenter, rez;
3765
3766	  if (!elem || elem.ownerDocument !== document) {
3767		return false;
3768	  }
3769
3770	  $(".fancybox-container").css("pointer-events", "none");
3771
3772	  elemCenter = {
3773		x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
3774		y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
3775	  };
3776
3777	  rez = document.elementFromPoint(elemCenter.x, elemCenter.y) === elem;
3778
3779	  $(".fancybox-container").css("pointer-events", "");
3780
3781	  return rez;
3782	};
3783
3784	// Class definition
3785	// ================
3786
3787	var FancyBox = function (content, opts, index) {
3788	  var self = this;
3789
3790	  self.opts = mergeOpts({
3791		index: index
3792	  }, $.fancybox.defaults);
3793
3794	  if ($.isPlainObject(opts)) {
3795		self.opts = mergeOpts(self.opts, opts);
3796	  }
3797
3798	  if ($.fancybox.isMobile) {
3799		self.opts = mergeOpts(self.opts, self.opts.mobile);
3800	  }
3801
3802	  self.id = self.opts.id || ++called;
3803
3804	  self.currIndex = parseInt(self.opts.index, 10) || 0;
3805	  self.prevIndex = null;
3806
3807	  self.prevPos = null;
3808	  self.currPos = 0;
3809
3810	  self.firstRun = true;
3811
3812	  // All group items
3813	  self.group = [];
3814
3815	  // Existing slides (for current, next and previous gallery items)
3816	  self.slides = {};
3817
3818	  // Create group elements
3819	  self.addContent(content);
3820
3821	  if (!self.group.length) {
3822		return;
3823	  }
3824
3825	  self.init();
3826	};
3827
3828	$.extend(FancyBox.prototype, {
3829	  // Create DOM structure
3830	  // ====================
3831
3832	  init: function () {
3833		var self = this,
3834		  firstItem = self.group[self.currIndex],
3835		  firstItemOpts = firstItem.opts,
3836		  $container,
3837		  buttonStr;
3838
3839		if (firstItemOpts.closeExisting) {
3840		  $.fancybox.close(true);
3841		}
3842
3843		// Hide scrollbars
3844		// ===============
3845
3846		$("body").addClass("fancybox-active");
3847
3848		if (
3849		  !$.fancybox.getInstance() &&
3850		  firstItemOpts.hideScrollbar !== false &&
3851		  !$.fancybox.isMobile &&
3852		  document.body.scrollHeight > window.innerHeight
3853		) {
3854		  $("head").append(
3855			'<style id="fancybox-style-noscroll" type="text/css">.compensate-for-scrollbar{margin-right:' +
3856			(window.innerWidth - document.documentElement.clientWidth) +
3857			"px;}</style>"
3858		  );
3859
3860		  $("body").addClass("compensate-for-scrollbar");
3861		}
3862
3863		// Build html markup and set references
3864		// ====================================
3865
3866		// Build html code for buttons and insert into main template
3867		buttonStr = "";
3868
3869		$.each(firstItemOpts.buttons, function (index, value) {
3870		  buttonStr += firstItemOpts.btnTpl[value] || "";
3871		});
3872
3873		// Create markup from base template, it will be initially hidden to
3874		// avoid unnecessary work like painting while initializing is not complete
3875		$container = $(
3876			self.translate(
3877			  self,
3878			  firstItemOpts.baseTpl
3879			  .replace("{{buttons}}", buttonStr)
3880			  .replace("{{arrows}}", firstItemOpts.btnTpl.arrowLeft + firstItemOpts.btnTpl.arrowRight)
3881			)
3882		  )
3883		  .attr("id", "fancybox-container-" + self.id)
3884		  .addClass(firstItemOpts.baseClass)
3885		  .data("FancyBox", self)
3886		  .appendTo(firstItemOpts.parentEl);
3887
3888		// Create object holding references to jQuery wrapped nodes
3889		self.$refs = {
3890		  container: $container
3891		};
3892
3893		["bg", "inner", "infobar", "toolbar", "stage", "caption", "navigation"].forEach(function (item) {
3894		  self.$refs[item] = $container.find(".fancybox-" + item);
3895		});
3896
3897		self.trigger("onInit");
3898
3899		// Enable events, deactive previous instances
3900		self.activate();
3901
3902		// Build slides, load and reveal content
3903		self.jumpTo(self.currIndex);
3904	  },
3905
3906	  // Simple i18n support - replaces object keys found in template
3907	  // with corresponding values
3908	  // ============================================================
3909
3910	  translate: function (obj, str) {
3911		var arr = obj.opts.i18n[obj.opts.lang] || obj.opts.i18n.en;
3912
3913		return str.replace(/\{\{(\w+)\}\}/g, function (match, n) {
3914		  return arr[n] === undefined ? match : arr[n];
3915		});
3916	  },
3917
3918	  // Populate current group with fresh content
3919	  // Check if each object has valid type and content
3920	  // ===============================================
3921
3922	  addContent: function (content) {
3923		var self = this,
3924		  items = $.makeArray(content),
3925		  thumbs;
3926
3927		$.each(items, function (i, item) {
3928		  var obj = {},
3929			opts = {},
3930			$item,
3931			type,
3932			found,
3933			src,
3934			srcParts;
3935
3936		  // Step 1 - Make sure we have an object
3937		  // ====================================
3938
3939		  if ($.isPlainObject(item)) {
3940			// We probably have manual usage here, something like
3941			// $.fancybox.open( [ { src : "image.jpg", type : "image" } ] )
3942
3943			obj = item;
3944			opts = item.opts || item;
3945		  } else if ($.type(item) === "object" && $(item).length) {
3946			// Here we probably have jQuery collection returned by some selector
3947			$item = $(item);
3948
3949			// Support attributes like `data-options='{"touch" : false}'` and `data-touch='false'`
3950			opts = $item.data() || {};
3951			opts = $.extend(true, {}, opts, opts.options);
3952
3953			// Here we store clicked element
3954			opts.$orig = $item;
3955
3956			obj.src = self.opts.src || opts.src || $item.attr("href");
3957
3958			// Assume that simple syntax is used, for example:
3959			//   `$.fancybox.open( $("#test"), {} );`
3960			if (!obj.type && !obj.src) {
3961			  obj.type = "inline";
3962			  obj.src = item;
3963			}
3964		  } else {
3965			// Assume we have a simple html code, for example:
3966			//   $.fancybox.open( '<div><h1>Hi!</h1></div>' );
3967			obj = {
3968			  type: "html",
3969			  src: item + ""
3970			};
3971		  }
3972
3973		  // Each gallery object has full collection of options
3974		  obj.opts = $.extend(true, {}, self.opts, opts);
3975
3976		  // Do not merge buttons array
3977		  if ($.isArray(opts.buttons)) {
3978			obj.opts.buttons = opts.buttons;
3979		  }
3980
3981		  if ($.fancybox.isMobile && obj.opts.mobile) {
3982			obj.opts = mergeOpts(obj.opts, obj.opts.mobile);
3983		  }
3984
3985		  // Step 2 - Make sure we have content type, if not - try to guess
3986		  // ==============================================================
3987
3988		  type = obj.type || obj.opts.type;
3989		  src = obj.src || "";
3990
3991		  if (!type && src) {
3992			if ((found = src.match(/\.(mp4|mov|ogv|webm)((\?|#).*)?$/i))) {
3993			  type = "video";
3994
3995			  if (!obj.opts.video.format) {
3996				obj.opts.video.format = "video/" + (found[1] === "ogv" ? "ogg" : found[1]);
3997			  }
3998			} else if (src.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i)) {
3999			  type = "image";
4000			} else if (src.match(/\.(pdf)((\?|#).*)?$/i)) {
4001			  type = "iframe";
4002			  obj = $.extend(true, obj, {
4003				contentType: "pdf",
4004				opts: {
4005				  iframe: {
4006					preload: false
4007				  }
4008				}
4009			  });
4010			} else if (src.charAt(0) === "#") {
4011			  type = "inline";
4012			}
4013		  }
4014
4015		  if (type) {
4016			obj.type = type;
4017		  } else {
4018			self.trigger("objectNeedsType", obj);
4019		  }
4020
4021		  if (!obj.contentType) {
4022			obj.contentType = $.inArray(obj.type, ["html", "inline", "ajax"]) > -1 ? "html" : obj.type;
4023		  }
4024
4025		  // Step 3 - Some adjustments
4026		  // =========================
4027
4028		  obj.index = self.group.length;
4029
4030		  if (obj.opts.smallBtn == "auto") {
4031			obj.opts.smallBtn = $.inArray(obj.type, ["html", "inline", "ajax"]) > -1;
4032		  }
4033
4034		  if (obj.opts.toolbar === "auto") {
4035			obj.opts.toolbar = !obj.opts.smallBtn;
4036		  }
4037
4038		  // Find thumbnail image, check if exists and if is in the viewport
4039		  obj.$thumb = obj.opts.$thumb || null;
4040
4041		  if (obj.opts.$trigger && obj.index === self.opts.index) {
4042			obj.$thumb = obj.opts.$trigger.find("img:first");
4043
4044			if (obj.$thumb.length) {
4045			  obj.opts.$orig = obj.opts.$trigger;
4046			}
4047		  }
4048
4049		  if (!(obj.$thumb && obj.$thumb.length) && obj.opts.$orig) {
4050			obj.$thumb = obj.opts.$orig.find("img:first");
4051		  }
4052
4053		  if (obj.$thumb && !obj.$thumb.length) {
4054			obj.$thumb = null;
4055		  }
4056
4057		  obj.thumb = obj.opts.thumb || (obj.$thumb ? obj.$thumb[0].src : null);
4058
4059		  // "caption" is a "special" option, it can be used to customize caption per gallery item
4060		  if ($.type(obj.opts.caption) === "function") {
4061			obj.opts.caption = obj.opts.caption.apply(item, [self, obj]);
4062		  }
4063
4064		  if ($.type(self.opts.caption) === "function") {
4065			obj.opts.caption = self.opts.caption.apply(item, [self, obj]);
4066		  }
4067
4068		  // Make sure we have caption as a string or jQuery object
4069		  if (!(obj.opts.caption instanceof $)) {
4070			obj.opts.caption = obj.opts.caption === undefined ? "" : obj.opts.caption + "";
4071		  }
4072
4073		  // Check if url contains "filter" used to filter the content
4074		  // Example: "ajax.html #something"
4075		  if (obj.type === "ajax") {
4076			srcParts = src.split(/\s+/, 2);
4077
4078			if (srcParts.length > 1) {
4079			  obj.src = srcParts.shift();
4080
4081			  obj.opts.filter = srcParts.shift();
4082			}
4083		  }
4084
4085		  // Hide all buttons and disable interactivity for modal items
4086		  if (obj.opts.modal) {
4087			obj.opts = $.extend(true, obj.opts, {
4088			  trapFocus: true,
4089			  // Remove buttons
4090			  infobar: 0,
4091			  toolbar: 0,
4092
4093			  smallBtn: 0,
4094
4095			  // Disable keyboard navigation
4096			  keyboard: 0,
4097
4098			  // Disable some modules
4099			  slideShow: 0,
4100			  fullScreen: 0,
4101			  thumbs: 0,
4102			  touch: 0,
4103
4104			  // Disable click event handlers
4105			  clickContent: false,
4106			  clickSlide: false,
4107			  clickOutside: false,
4108			  dblclickContent: false,
4109			  dblclickSlide: false,
4110			  dblclickOutside: false
4111			});
4112		  }
4113
4114		  // Step 4 - Add processed object to group
4115		  // ======================================
4116
4117		  self.group.push(obj);
4118		});
4119
4120		// Update controls if gallery is already opened
4121		if (Object.keys(self.slides).length) {
4122		  self.updateControls();
4123
4124		  // Update thumbnails, if needed
4125		  thumbs = self.Thumbs;
4126
4127		  if (thumbs && thumbs.isActive) {
4128			thumbs.create();
4129
4130			thumbs.focus();
4131		  }
4132		}
4133	  },
4134
4135	  // Attach an event handler functions for:
4136	  //   - navigation buttons
4137	  //   - browser scrolling, resizing;
4138	  //   - focusing
4139	  //   - keyboard
4140	  //   - detecting inactivity
4141	  // ======================================
4142
4143	  addEvents: function () {
4144		var self = this;
4145
4146		self.removeEvents();
4147
4148		// Make navigation elements clickable
4149		// ==================================
4150
4151		self.$refs.container
4152		  .on("click.fb-close", "[data-fancybox-close]", function (e) {
4153			e.stopPropagation();
4154			e.preventDefault();
4155
4156			self.close(e);
4157		  })
4158		  .on("touchstart.fb-prev click.fb-prev", "[data-fancybox-prev]", function (e) {
4159			e.stopPropagation();
4160			e.preventDefault();
4161
4162			self.previous();
4163		  })
4164		  .on("touchstart.fb-next click.fb-next", "[data-fancybox-next]", function (e) {
4165			e.stopPropagation();
4166			e.preventDefault();
4167
4168			self.next();
4169		  })
4170		  .on("click.fb", "[data-fancybox-zoom]", function (e) {
4171			// Click handler for zoom button
4172			self[self.isScaledDown() ? "scaleToActual" : "scaleToFit"]();
4173		  });
4174
4175		// Handle page scrolling and browser resizing
4176		// ==========================================
4177
4178		$W.on("orientationchange.fb resize.fb", function (e) {
4179		  if (e && e.originalEvent && e.originalEvent.type === "resize") {
4180			if (self.requestId) {
4181			  cancelAFrame(self.requestId);
4182			}
4183
4184			self.requestId = requestAFrame(function () {
4185			  self.update(e);
4186			});
4187		  } else {
4188			if (self.current && self.current.type === "iframe") {
4189			  self.$refs.stage.hide();
4190			}
4191
4192			setTimeout(
4193			  function () {
4194				self.$refs.stage.show();
4195
4196				self.update(e);
4197			  },
4198			  $.fancybox.isMobile ? 600 : 250
4199			);
4200		  }
4201		});
4202
4203		$D.on("keydown.fb", function (e) {
4204		  var instance = $.fancybox ? $.fancybox.getInstance() : null,
4205			current = instance.current,
4206			keycode = e.keyCode || e.which;
4207
4208		  // Trap keyboard focus inside of the modal
4209		  // =======================================
4210
4211		  if (keycode == 9) {
4212			if (current.opts.trapFocus) {
4213			  self.focus(e);
4214			}
4215
4216			return;
4217		  }
4218
4219		  // Enable keyboard navigation
4220		  // ==========================
4221
4222		  if (!current.opts.keyboard || e.ctrlKey || e.altKey || e.shiftKey || $(e.target).is("input,textarea,video,audio,select")) {
4223			return;
4224		  }
4225
4226		  // Backspace and Esc keys
4227		  if (keycode === 8 || keycode === 27) {
4228			e.preventDefault();
4229
4230			self.close(e);
4231
4232			return;
4233		  }
4234
4235		  // Left arrow and Up arrow
4236		  if (keycode === 37 || keycode === 38) {
4237			e.preventDefault();
4238
4239			self.previous();
4240
4241			return;
4242		  }
4243
4244		  // Righ arrow and Down arrow
4245		  if (keycode === 39 || keycode === 40) {
4246			e.preventDefault();
4247
4248			self.next();
4249
4250			return;
4251		  }
4252
4253		  self.trigger("afterKeydown", e, keycode);
4254		});
4255
4256		// Hide controls after some inactivity period
4257		if (self.group[self.currIndex].opts.idleTime) {
4258		  self.idleSecondsCounter = 0;
4259
4260		  $D.on(
4261			"mousemove.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle",
4262			function (e) {
4263			  self.idleSecondsCounter = 0;
4264
4265			  if (self.isIdle) {
4266				self.showControls();
4267			  }
4268
4269			  self.isIdle = false;
4270			}
4271		  );
4272
4273		  self.idleInterval = window.setInterval(function () {
4274			self.idleSecondsCounter++;
4275
4276			if (self.idleSecondsCounter >= self.group[self.currIndex].opts.idleTime && !self.isDragging) {
4277			  self.isIdle = true;
4278			  self.idleSecondsCounter = 0;
4279
4280			  self.hideControls();
4281			}
4282		  }, 1000);
4283		}
4284	  },
4285
4286	  // Remove events added by the core
4287	  // ===============================
4288
4289	  removeEvents: function () {
4290		var self = this;
4291
4292		$W.off("orientationchange.fb resize.fb");
4293		$D.off("keydown.fb .fb-idle");
4294
4295		this.$refs.container.off(".fb-close .fb-prev .fb-next");
4296
4297		if (self.idleInterval) {
4298		  window.clearInterval(self.idleInterval);
4299
4300		  self.idleInterval = null;
4301		}
4302	  },
4303
4304	  // Change to previous gallery item
4305	  // ===============================
4306
4307	  previous: function (duration) {
4308		return this.jumpTo(this.currPos - 1, duration);
4309	  },
4310
4311	  // Change to next gallery item
4312	  // ===========================
4313
4314	  next: function (duration) {
4315		return this.jumpTo(this.currPos + 1, duration);
4316	  },
4317
4318	  // Switch to selected gallery item
4319	  // ===============================
4320
4321	  jumpTo: function (pos, duration) {
4322		var self = this,
4323		  groupLen = self.group.length,
4324		  firstRun,
4325		  isMoved,
4326		  loop,
4327		  current,
4328		  previous,
4329		  slidePos,
4330		  stagePos,
4331		  prop,
4332		  diff;
4333
4334		if (self.isDragging || self.isClosing || (self.isAnimating && self.firstRun)) {
4335		  return;
4336		}
4337
4338		// Should loop?
4339		pos = parseInt(pos, 10);
4340		loop = self.current ? self.current.opts.loop : self.opts.loop;
4341
4342		if (!loop && (pos < 0 || pos >= groupLen)) {
4343		  return false;
4344		}
4345
4346		// Check if opening for the first time; this helps to speed things up
4347		firstRun = self.firstRun = !Object.keys(self.slides).length;
4348
4349		// Create slides
4350		previous = self.current;
4351
4352		self.prevIndex = self.currIndex;
4353		self.prevPos = self.currPos;
4354
4355		current = self.createSlide(pos);
4356
4357		if (groupLen > 1) {
4358		  if (loop || current.index < groupLen - 1) {
4359			self.createSlide(pos + 1);
4360		  }
4361
4362		  if (loop || current.index > 0) {
4363			self.createSlide(pos - 1);
4364		  }
4365		}
4366
4367		self.current = current;
4368		self.currIndex = current.index;
4369		self.currPos = current.pos;
4370
4371		self.trigger("beforeShow", firstRun);
4372
4373		self.updateControls();
4374
4375		// Validate duration length
4376		current.forcedDuration = undefined;
4377
4378		if ($.isNumeric(duration)) {
4379		  current.forcedDuration = duration;
4380		} else {
4381		  duration = current.opts[firstRun ? "animationDuration" : "transitionDuration"];
4382		}
4383
4384		duration = parseInt(duration, 10);
4385
4386		// Check if user has swiped the slides or if still animating
4387		isMoved = self.isMoved(current);
4388
4389		// Make sure current slide is visible
4390		current.$slide.addClass("fancybox-slide--current");
4391
4392		// Fresh start - reveal container, current slide and start loading content
4393		if (firstRun) {
4394		  if (current.opts.animationEffect && duration) {
4395			self.$refs.container.css("transition-duration", duration + "ms");
4396		  }
4397
4398		  self.$refs.container.addClass("fancybox-is-open").trigger("focus");
4399
4400		  // Attempt to load content into slide
4401		  // This will later call `afterLoad` -> `revealContent`
4402		  self.loadSlide(current);
4403
4404		  self.preload("image");
4405
4406		  return;
4407		}
4408
4409		// Get actual slide/stage positions (before cleaning up)
4410		slidePos = $.fancybox.getTranslate(previous.$slide);
4411		stagePos = $.fancybox.getTranslate(self.$refs.stage);
4412
4413		// Clean up all slides
4414		$.each(self.slides, function (index, slide) {
4415		  $.fancybox.stop(slide.$slide, true);
4416		});
4417
4418		if (previous.pos !== current.pos) {
4419		  previous.isComplete = false;
4420		}
4421
4422		previous.$slide.removeClass("fancybox-slide--complete fancybox-slide--current");
4423
4424		// If slides are out of place, then animate them to correct position
4425		if (isMoved) {
4426		  // Calculate horizontal swipe distance
4427		  diff = slidePos.left - (previous.pos * slidePos.width + previous.pos * previous.opts.gutter);
4428
4429		  $.each(self.slides, function (index, slide) {
4430			slide.$slide.removeClass("fancybox-animated").removeClass(function (index, className) {
4431			  return (className.match(/(^|\s)fancybox-fx-\S+/g) || []).join(" ");
4432			});
4433
4434			// Make sure that each slide is in equal distance
4435			// This is mostly needed for freshly added slides, because they are not yet positioned
4436			var leftPos = slide.pos * slidePos.width + slide.pos * slide.opts.gutter;
4437
4438			$.fancybox.setTranslate(slide.$slide, {
4439			  top: 0,
4440			  left: leftPos - stagePos.left + diff
4441			});
4442
4443			if (slide.pos !== current.pos) {
4444			  slide.$slide.addClass("fancybox-slide--" + (slide.pos > current.pos ? "next" : "previous"));
4445			}
4446
4447			// Redraw to make sure that transition will start
4448			forceRedraw(slide.$slide);
4449
4450			// Animate the slide
4451			$.fancybox.animate(
4452			  slide.$slide, {
4453				top: 0,
4454				left: (slide.pos - current.pos) * slidePos.width + (slide.pos - current.pos) * slide.opts.gutter
4455			  },
4456			  duration,
4457			  function () {
4458				slide.$slide
4459				  .css({
4460					transform: "",
4461					opacity: ""
4462				  })
4463				  .removeClass("fancybox-slide--next fancybox-slide--previous");
4464
4465				if (slide.pos === self.currPos) {
4466				  self.complete();
4467				}
4468			  }
4469			);
4470		  });
4471		} else if (duration && current.opts.transitionEffect) {
4472		  // Set transition effect for previously active slide
4473		  prop = "fancybox-animated fancybox-fx-" + current.opts.transitionEffect;
4474
4475		  previous.$slide.addClass("fancybox-slide--" + (previous.pos > current.pos ? "next" : "previous"));
4476
4477		  $.fancybox.animate(
4478			previous.$slide,
4479			prop,
4480			duration,
4481			function () {
4482			  previous.$slide.removeClass(prop).removeClass("fancybox-slide--next fancybox-slide--previous");
4483			},
4484			false
4485		  );
4486		}
4487
4488		if (current.isLoaded) {
4489		  self.revealContent(current);
4490		} else {
4491		  self.loadSlide(current);
4492		}
4493
4494		self.preload("image");
4495	  },
4496
4497	  // Create new "slide" element
4498	  // These are gallery items  that are actually added to DOM
4499	  // =======================================================
4500
4501	  createSlide: function (pos) {
4502		var self = this,
4503		  $slide,
4504		  index;
4505
4506		index = pos % self.group.length;
4507		index = index < 0 ? self.group.length + index : index;
4508
4509		if (!self.slides[pos] && self.group[index]) {
4510		  $slide = $('<div class="fancybox-slide"></div>').appendTo(self.$refs.stage);
4511
4512		  self.slides[pos] = $.extend(true, {}, self.group[index], {
4513			pos: pos,
4514			$slide: $slide,
4515			isLoaded: false
4516		  });
4517
4518		  self.updateSlide(self.slides[pos]);
4519		}
4520
4521		return self.slides[pos];
4522	  },
4523
4524	  // Scale image to the actual size of the image;
4525	  // x and y values should be relative to the slide
4526	  // ==============================================
4527
4528	  scaleToActual: function (x, y, duration) {
4529		var self = this,
4530		  current = self.current,
4531		  $content = current.$content,
4532		  canvasWidth = $.fancybox.getTranslate(current.$slide).width,
4533		  canvasHeight = $.fancybox.getTranslate(current.$slide).height,
4534		  newImgWidth = current.width,
4535		  newImgHeight = current.height,
4536		  imgPos,
4537		  posX,
4538		  posY,
4539		  scaleX,
4540		  scaleY;
4541
4542		if (self.isAnimating || self.isMoved() || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) {
4543		  return;
4544		}
4545
4546		self.isAnimating = true;
4547
4548		$.fancybox.stop($content);
4549
4550		x = x === undefined ? canvasWidth * 0.5 : x;
4551		y = y === undefined ? canvasHeight * 0.5 : y;
4552
4553		imgPos = $.fancybox.getTranslate($content);
4554
4555		imgPos.top -= $.fancybox.getTranslate(current.$slide).top;
4556		imgPos.left -= $.fancybox.getTranslate(current.$slide).left;
4557
4558		scaleX = newImgWidth / imgPos.width;
4559		scaleY = newImgHeight / imgPos.height;
4560
4561		// Get center position for original image
4562		posX = canvasWidth * 0.5 - newImgWidth * 0.5;
4563		posY = canvasHeight * 0.5 - newImgHeight * 0.5;
4564
4565		// Make sure image does not move away from edges
4566		if (newImgWidth > canvasWidth) {
4567		  posX = imgPos.left * scaleX - (x * scaleX - x);
4568
4569		  if (posX > 0) {
4570			posX = 0;
4571		  }
4572
4573		  if (posX < canvasWidth - newImgWidth) {
4574			posX = canvasWidth - newImgWidth;
4575		  }
4576		}
4577
4578		if (newImgHeight > canvasHeight) {
4579		  posY = imgPos.top * scaleY - (y * scaleY - y);
4580
4581		  if (posY > 0) {
4582			posY = 0;
4583		  }
4584
4585		  if (posY < canvasHeight - newImgHeight) {
4586			posY = canvasHeight - newImgHeight;
4587		  }
4588		}
4589
4590		self.updateCursor(newImgWidth, newImgHeight);
4591
4592		$.fancybox.animate(
4593		  $content, {
4594			top: posY,
4595			left: posX,
4596			scaleX: scaleX,
4597			scaleY: scaleY
4598		  },
4599		  duration || 366,
4600		  function () {
4601			self.isAnimating = false;
4602		  }
4603		);
4604
4605		// Stop slideshow
4606		if (self.SlideShow && self.SlideShow.isActive) {
4607		  self.SlideShow.stop();
4608		}
4609	  },
4610
4611	  // Scale image to fit inside parent element
4612	  // ========================================
4613
4614	  scaleToFit: function (duration) {
4615		var self = this,
4616		  current = self.current,
4617		  $content = current.$content,
4618		  end;
4619
4620		if (self.isAnimating || self.isMoved() || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) {
4621		  return;
4622		}
4623
4624		self.isAnimating = true;
4625
4626		$.fancybox.stop($content);
4627
4628		end = self.getFitPos(current);
4629
4630		self.updateCursor(end.width, end.height);
4631
4632		$.fancybox.animate(
4633		  $content, {
4634			top: end.top,
4635			left: end.left,
4636			scaleX: end.width / $content.width(),
4637			scaleY: end.height / $content.height()
4638		  },
4639		  duration || 366,
4640		  function () {
4641			self.isAnimating = false;
4642		  }
4643		);
4644	  },
4645
4646	  // Calculate image size to fit inside viewport
4647	  // ===========================================
4648
4649	  getFitPos: function (slide) {
4650		var self = this,
4651		  $content = slide.$content,
4652		  $slide = slide.$slide,
4653		  width = slide.width || slide.opts.width,
4654		  height = slide.height || slide.opts.height,
4655		  maxWidth,
4656		  maxHeight,
4657		  minRatio,
4658		  aspectRatio,
4659		  rez = {};
4660
4661		if (!slide.isLoaded || !$content || !$content.length) {
4662		  return false;
4663		}
4664
4665		maxWidth = $.fancybox.getTranslate(self.$refs.stage).width;
4666		maxHeight = $.fancybox.getTranslate(self.$refs.stage).height;
4667
4668		maxWidth -=
4669		  parseFloat($slide.css("paddingLeft")) +
4670		  parseFloat($slide.css("paddingRight")) +
4671		  parseFloat($content.css("marginLeft")) +
4672		  parseFloat($content.css("marginRight"));
4673
4674		maxHeight -=
4675		  parseFloat($slide.css("paddingTop")) +
4676		  parseFloat($slide.css("paddingBottom")) +
4677		  parseFloat($content.css("marginTop")) +
4678		  parseFloat($content.css("marginBottom"));
4679
4680		if (!width || !height) {
4681		  width = maxWidth;
4682		  height = maxHeight;
4683		}
4684
4685		minRatio = Math.min(1, maxWidth / width, maxHeight / height);
4686
4687		width = minRatio * width;
4688		height = minRatio * height;
4689
4690		// Adjust width/height to precisely fit into container
4691		if (width > maxWidth - 0.5) {
4692		  width = maxWidth;
4693		}
4694
4695		if (height > maxHeight - 0.5) {
4696		  height = maxHeight;
4697		}
4698
4699		if (slide.type === "image") {
4700		  rez.top = Math.floor((maxHeight - height) * 0.5) + parseFloat($slide.css("paddingTop"));
4701		  rez.left = Math.floor((maxWidth - width) * 0.5) + parseFloat($slide.css("paddingLeft"));
4702		} else if (slide.contentType === "video") {
4703		  // Force aspect ratio for the video
4704		  // "I say the whole world must learn of our peaceful ways… by force!"
4705		  aspectRatio = slide.opts.width && slide.opts.height ? width / height : slide.opts.ratio || 16 / 9;
4706
4707		  if (height > width / aspectRatio) {
4708			height = width / aspectRatio;
4709		  } else if (width > height * aspectRatio) {
4710			width = height * aspectRatio;
4711		  }
4712		}
4713
4714		rez.width = width;
4715		rez.height = height;
4716
4717		return rez;
4718	  },
4719
4720	  // Update content size and position for all slides
4721	  // ==============================================
4722
4723	  update: function (e) {
4724		var self = this;
4725
4726		$.each(self.slides, function (key, slide) {
4727		  self.updateSlide(slide, e);
4728		});
4729	  },
4730
4731	  // Update slide content position and size
4732	  // ======================================
4733
4734	  updateSlide: function (slide, e) {
4735		var self = this,
4736		  $content = slide && slide.$content,
4737		  width = slide.width || slide.opts.width,
4738		  height = slide.height || slide.opts.height,
4739		  $slide = slide.$slide;
4740
4741		// First, prevent caption overlap, if needed
4742		self.adjustCaption(slide);
4743
4744		// Then resize content to fit inside the slide
4745		if ($content && (width || height || slide.contentType === "video") && !slide.hasError) {
4746		  $.fancybox.stop($content);
4747
4748		  $.fancybox.setTranslate($content, self.getFitPos(slide));
4749
4750		  if (slide.pos === self.currPos) {
4751			self.isAnimating = false;
4752
4753			self.updateCursor();
4754		  }
4755		}
4756
4757		// Then some adjustments
4758		self.adjustLayout(slide);
4759
4760		if ($slide.length) {
4761		  $slide.trigger("refresh");
4762
4763		  if (slide.pos === self.currPos) {
4764			self.$refs.toolbar
4765			  .add(self.$refs.navigation.find(".fancybox-button--arrow_right"))
4766			  .toggleClass("compensate-for-scrollbar", $slide.get(0).scrollHeight > $slide.get(0).clientHeight);
4767		  }
4768		}
4769
4770		self.trigger("onUpdate", slide, e);
4771	  },
4772
4773	  // Horizontally center slide
4774	  // =========================
4775
4776	  centerSlide: function (duration) {
4777		var self = this,
4778		  current = self.current,
4779		  $slide = current.$slide;
4780
4781		if (self.isClosing || !current) {
4782		  return;
4783		}
4784
4785		$slide.siblings().css({
4786		  transform: "",
4787		  opacity: ""
4788		});
4789
4790		$slide
4791		  .parent()
4792		  .children()
4793		  .removeClass("fancybox-slide--previous fancybox-slide--next");
4794
4795		$.fancybox.animate(
4796		  $slide, {
4797			top: 0,
4798			left: 0,
4799			opacity: 1
4800		  },
4801		  duration === undefined ? 0 : duration,
4802		  function () {
4803			// Clean up
4804			$slide.css({
4805			  transform: "",
4806			  opacity: ""
4807			});
4808
4809			if (!current.isComplete) {
4810			  self.complete();
4811			}
4812		  },
4813		  false
4814		);
4815	  },
4816
4817	  // Check if current slide is moved (swiped)
4818	  // ========================================
4819
4820	  isMoved: function (slide) {
4821		var current = slide || this.current,
4822		  slidePos,
4823		  stagePos;
4824
4825		if (!current) {
4826		  return false;
4827		}
4828
4829		stagePos = $.fancybox.getTranslate(this.$refs.stage);
4830		slidePos = $.fancybox.getTranslate(current.$slide);
4831
4832		return (
4833		  !current.$slide.hasClass("fancybox-animated") &&
4834		  (Math.abs(slidePos.top - stagePos.top) > 0.5 || Math.abs(slidePos.left - stagePos.left) > 0.5)
4835		);
4836	  },
4837
4838	  // Update cursor style depending if content can be zoomed
4839	  // ======================================================
4840
4841	  updateCursor: function (nextWidth, nextHeight) {
4842		var self = this,
4843		  current = self.current,
4844		  $container = self.$refs.container,
4845		  canPan,
4846		  isZoomable;
4847
4848		if (!current || self.isClosing || !self.Guestures) {
4849		  return;
4850		}
4851
4852		$container.removeClass("fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-zoomOut fancybox-can-swipe fancybox-can-pan");
4853
4854		canPan = self.canPan(nextWidth, nextHeight);
4855
4856		isZoomable = canPan ? true : self.isZoomable();
4857
4858		$container.toggleClass("fancybox-is-zoomable", isZoomable);
4859
4860		$("[data-fancybox-zoom]").prop("disabled", !isZoomable);
4861
4862		if (canPan) {
4863		  $container.addClass("fancybox-can-pan");
4864		} else if (
4865		  isZoomable &&
4866		  (current.opts.clickContent === "zoom" || ($.isFunction(current.opts.clickContent) && current.opts.clickContent(current) == "zoom"))
4867		) {
4868		  $container.addClass("fancybox-can-zoomIn");
4869		} else if (current.opts.touch && (current.opts.touch.vertical || self.group.length > 1) && current.contentType !== "video") {
4870		  $container.addClass("fancybox-can-swipe");
4871		}
4872	  },
4873
4874	  // Check if current slide is zoomable
4875	  // ==================================
4876
4877	  isZoomable: function () {
4878		var self = this,
4879		  current = self.current,
4880		  fitPos;
4881
4882		// Assume that slide is zoomable if:
4883		//   - image is still loading
4884		//   - actual size of the image is smaller than available area
4885		if (current && !self.isClosing && current.type === "image" && !current.hasError) {
4886		  if (!current.isLoaded) {
4887			return true;
4888		  }
4889
4890		  fitPos = self.getFitPos(current);
4891
4892		  if (fitPos && (current.width > fitPos.width || current.height > fitPos.height)) {
4893			return true;
4894		  }
4895		}
4896
4897		return false;
4898	  },
4899
4900	  // Check if current image dimensions are smaller than actual
4901	  // =========================================================
4902
4903	  isScaledDown: function (nextWidth, nextHeight) {
4904		var self = this,
4905		  rez = false,
4906		  current = self.current,
4907		  $content = current.$content;
4908
4909		if (nextWidth !== undefined && nextHeight !== undefined) {
4910		  rez = nextWidth < current.width && nextHeight < current.height;
4911		} else if ($content) {
4912		  rez = $.fancybox.getTranslate($content);
4913		  rez = rez.width < current.width && rez.height < current.height;
4914		}
4915
4916		return rez;
4917	  },
4918
4919	  // Check if image dimensions exceed parent element
4920	  // ===============================================
4921
4922	  canPan: function (nextWidth, nextHeight) {
4923		var self = this,
4924		  current = self.current,
4925		  pos = null,
4926		  rez = false;
4927
4928		if (current.type === "image" && (current.isComplete || (nextWidth && nextHeight)) && !current.hasError) {
4929		  rez = self.getFitPos(current);
4930
4931		  if (nextWidth !== undefined && nextHeight !== undefined) {
4932			pos = {
4933			  width: nextWidth,
4934			  height: nextHeight
4935			};
4936		  } else if (current.isComplete) {
4937			pos = $.fancybox.getTranslate(current.$content);
4938		  }
4939
4940		  if (pos && rez) {
4941			rez = Math.abs(pos.width - rez.width) > 1.5 || Math.abs(pos.height - rez.height) > 1.5;
4942		  }
4943		}
4944
4945		return rez;
4946	  },
4947
4948	  // Load content into the slide
4949	  // ===========================
4950
4951	  loadSlide: function (slide) {
4952		var self = this,
4953		  type,
4954		  $slide,
4955		  ajaxLoad;
4956
4957		if (slide.isLoading || slide.isLoaded) {
4958		  return;
4959		}
4960
4961		slide.isLoading = true;
4962
4963		if (self.trigger("beforeLoad", slide) === false) {
4964		  slide.isLoading = false;
4965
4966		  return false;
4967		}
4968
4969		type = slide.type;
4970		$slide = slide.$slide;
4971
4972		$slide
4973		  .off("refresh")
4974		  .trigger("onReset")
4975		  .addClass(slide.opts.slideClass);
4976
4977		// Create content depending on the type
4978		switch (type) {
4979		  case "image":
4980			self.setImage(slide);
4981
4982			break;
4983
4984		  case "iframe":
4985			self.setIframe(slide);
4986
4987			break;
4988
4989		  case "html":
4990			self.setContent(slide, slide.src || slide.content);
4991
4992			break;
4993
4994		  case "video":
4995			self.setContent(
4996			  slide,
4997			  slide.opts.video.tpl
4998			  .replace(/\{\{src\}\}/gi, slide.src)
4999			  .replace("{{format}}", slide.opts.videoFormat || slide.opts.video.format || "")
5000			  .replace("{{poster}}", slide.thumb || "")
5001			);
5002
5003			break;
5004
5005		  case "inline":
5006			if ($(slide.src).length) {
5007			  self.setContent(slide, $(slide.src));
5008			} else {
5009			  self.setError(slide);
5010			}
5011
5012			break;
5013
5014		  case "ajax":
5015			self.showLoading(slide);
5016
5017			ajaxLoad = $.ajax(
5018			  $.extend({}, slide.opts.ajax.settings, {
5019				url: slide.src,
5020				success: function (data, textStatus) {
5021				  if (textStatus === "success") {
5022					self.setContent(slide, data);
5023				  }
5024				},
5025				error: function (jqXHR, textStatus) {
5026				  if (jqXHR && textStatus !== "abort") {
5027					self.setError(slide);
5028				  }
5029				}
5030			  })
5031			);
5032
5033			$slide.one("onReset", function () {
5034			  ajaxLoad.abort();
5035			});
5036
5037			break;
5038
5039		  default:
5040			self.setError(slide);
5041
5042			break;
5043		}
5044
5045		return true;
5046	  },
5047
5048	  // Use thumbnail image, if possible
5049	  // ================================
5050
5051	  setImage: function (slide) {
5052		var self = this,
5053		  ghost;
5054
5055		// Check if need to show loading icon
5056		setTimeout(function () {
5057		  var $img = slide.$image;
5058
5059		  if (!self.isClosing && slide.isLoading && (!$img || !$img.length || !$img[0].complete) && !slide.hasError) {
5060			self.showLoading(slide);
5061		  }
5062		}, 50);
5063
5064		//Check if image has srcset
5065		self.checkSrcset(slide);
5066
5067		// This will be wrapper containing both ghost and actual image
5068		slide.$content = $('<div class="fancybox-content"></div>')
5069		  .addClass("fancybox-is-hidden")
5070		  .appendTo(slide.$slide.addClass("fancybox-slide--image"));
5071
5072		// If we have a thumbnail, we can display it while actual image is loading
5073		// Users will not stare at black screen and actual image will appear gradually
5074		if (slide.opts.preload !== false && slide.opts.width && slide.opts.height && slide.thumb) {
5075		  slide.width = slide.opts.width;
5076		  slide.height = slide.opts.height;
5077
5078		  ghost = document.createElement("img");
5079
5080		  ghost.onerror = function () {
5081			$(this).remove();
5082
5083			slide.$ghost = null;
5084		  };
5085
5086		  ghost.onload = function () {
5087			self.afterLoad(slide);
5088		  };
5089
5090		  slide.$ghost = $(ghost)
5091			.addClass("fancybox-image")
5092			.appendTo(slide.$content)
5093			.attr("src", slide.thumb);
5094		}
5095
5096		// Start loading actual image
5097		self.setBigImage(slide);
5098	  },
5099
5100	  // Check if image has srcset and get the source
5101	  // ============================================
5102	  checkSrcset: function (slide) {
5103		var srcset = slide.opts.srcset || slide.opts.image.srcset,
5104		  found,
5105		  temp,
5106		  pxRatio,
5107		  windowWidth;
5108
5109		// If we have "srcset", then we need to find first matching "src" value.
5110		// This is necessary, because when you set an src attribute, the browser will preload the image
5111		// before any javascript or even CSS is applied.
5112		if (srcset) {
5113		  pxRatio = window.devicePixelRatio || 1;
5114		  windowWidth = window.innerWidth * pxRatio;
5115
5116		  temp = srcset.split(",").map(function (el) {
5117			var ret = {};
5118
5119			el.trim()
5120			  .split(/\s+/)
5121			  .forEach(function (el, i) {
5122				var value = parseInt(el.substring(0, el.length - 1), 10);
5123
5124				if (i === 0) {
5125				  return (ret.url = el);
5126				}
5127
5128				if (value) {
5129				  ret.value = value;
5130				  ret.postfix = el[el.length - 1];
5131				}
5132			  });
5133
5134			return ret;
5135		  });
5136
5137		  // Sort by value
5138		  temp.sort(function (a, b) {
5139			return a.value - b.value;
5140		  });
5141
5142		  // Ok, now we have an array of all srcset values
5143		  for (var j = 0; j < temp.length; j++) {
5144			var el = temp[j];
5145
5146			if ((el.postfix === "w" && el.value >= windowWidth) || (el.postfix === "x" && el.value >= pxRatio)) {
5147			  found = el;
5148			  break;
5149			}
5150		  }
5151
5152		  // If not found, take the last one
5153		  if (!found && temp.length) {
5154			found = temp[temp.length - 1];
5155		  }
5156
5157		  if (found) {
5158			slide.src = found.url;
5159
5160			// If we have default width/height values, we can calculate height for matching source
5161			if (slide.width && slide.height && found.postfix == "w") {
5162			  slide.height = (slide.width / slide.height) * found.value;
5163			  slide.width = found.value;
5164			}
5165
5166			slide.opts.srcset = srcset;
5167		  }
5168		}
5169	  },
5170
5171	  // Create full-size image
5172	  // ======================
5173
5174	  setBigImage: function (slide) {
5175		var self = this,
5176		  img = document.createElement("img"),
5177		  $img = $(img);
5178
5179		slide.$image = $img
5180		  .one("error", function () {
5181			self.setError(slide);
5182		  })
5183		  .one("load", function () {
5184			var sizes;
5185
5186			if (!slide.$ghost) {
5187			  self.resolveImageSlideSize(slide, this.naturalWidth, this.naturalHeight);
5188
5189			  self.afterLoad(slide);
5190			}
5191
5192			if (self.isClosing) {
5193			  return;
5194			}
5195
5196			if (slide.opts.srcset) {
5197			  sizes = slide.opts.sizes;
5198
5199			  if (!sizes || sizes === "auto") {
5200				sizes =
5201				  (slide.width / slide.height > 1 && $W.width() / $W.height() > 1 ? "100" : Math.round((slide.width / slide.height) * 100)) +
5202				  "vw";
5203			  }
5204
5205			  $img.attr("sizes", sizes).attr("srcset", slide.opts.srcset);
5206			}
5207
5208			// Hide temporary image after some delay
5209			if (slide.$ghost) {
5210			  setTimeout(function () {
5211				if (slide.$ghost && !self.isClosing) {
5212				  slide.$ghost.hide();
5213				}
5214			  }, Math.min(300, Math.max(1000, slide.height / 1600)));
5215			}
5216
5217			self.hideLoading(slide);
5218		  })
5219		  .addClass("fancybox-image")
5220		  .attr("src", slide.src)
5221		  .appendTo(slide.$content);
5222
5223		if ((img.complete || img.readyState == "complete") && $img.naturalWidth && $img.naturalHeight) {
5224		  $img.trigger("load");
5225		} else if (img.error) {
5226		  $img.trigger("error");
5227		}
5228	  },
5229
5230	  // Computes the slide size from image size and maxWidth/maxHeight
5231	  // ==============================================================
5232
5233	  resolveImageSlideSize: function (slide, imgWidth, imgHeight) {
5234		var maxWidth = parseInt(slide.opts.width, 10),
5235		  maxHeight = parseInt(slide.opts.height, 10);
5236
5237		// Sets the default values from the image
5238		slide.width = imgWidth;
5239		slide.height = imgHeight;
5240
5241		if (maxWidth > 0) {
5242		  slide.width = maxWidth;
5243		  slide.height = Math.floor((maxWidth * imgHeight) / imgWidth);
5244		}
5245
5246		if (maxHeight > 0) {
5247		  slide.width = Math.floor((maxHeight * imgWidth) / imgHeight);
5248		  slide.height = maxHeight;
5249		}
5250	  },
5251
5252	  // Create iframe wrapper, iframe and bindings
5253	  // ==========================================
5254
5255	  setIframe: function (slide) {
5256		var self = this,
5257		  opts = slide.opts.iframe,
5258		  $slide = slide.$slide,
5259		  $iframe;
5260
5261		slide.$content = $('<div class="fancybox-content' + (opts.preload ? " fancybox-is-hidden" : "") + '"></div>')
5262		  .css(opts.css)
5263		  .appendTo($slide);
5264
5265		$slide.addClass("fancybox-slide--" + slide.contentType);
5266
5267		slide.$iframe = $iframe = $(opts.tpl.replace(/\{rnd\}/g, new Date().getTime()))
5268		  .attr(opts.attr)
5269		  .appendTo(slide.$content);
5270
5271		if (opts.preload) {
5272		  self.showLoading(slide);
5273
5274		  // Unfortunately, it is not always possible to determine if iframe is successfully loaded
5275		  // (due to browser security policy)
5276
5277		  $iframe.on("load.fb error.fb", function (e) {
5278			this.isReady = 1;
5279
5280			slide.$slide.trigger("refresh");
5281
5282			self.afterLoad(slide);
5283		  });
5284
5285		  // Recalculate iframe content size
5286		  // ===============================
5287
5288		  $slide.on("refresh.fb", function () {
5289			var $content = slide.$content,
5290			  frameWidth = opts.css.width,
5291			  frameHeight = opts.css.height,
5292			  $contents,
5293			  $body;
5294
5295			if ($iframe[0].isReady !== 1) {
5296			  return;
5297			}
5298
5299			try {
5300			  $contents = $iframe.contents();
5301			  $body = $contents.find("body");
5302			} catch (ignore) {}
5303
5304			// Calculate content dimensions, if it is accessible
5305			if ($body && $body.length && $body.children().length) {
5306			  // Avoid scrolling to top (if multiple instances)
5307			  $slide.css("overflow", "visible");
5308
5309			  $content.css({
5310				width: "100%",
5311				"max-width": "100%",
5312				height: "9999px"
5313			  });
5314
5315			  if (frameWidth === undefined) {
5316				frameWidth = Math.ceil(Math.max($body[0].clientWidth, $body.outerWidth(true)));
5317			  }
5318
5319			  $content.css("width", frameWidth ? frameWidth : "").css("max-width", "");
5320
5321			  if (frameHeight === undefined) {
5322				frameHeight = Math.ceil(Math.max($body[0].clientHeight, $body.outerHeight(true)));
5323			  }
5324
5325			  $content.css("height", frameHeight ? frameHeight : "");
5326
5327			  $slide.css("overflow", "auto");
5328			}
5329
5330			$content.removeClass("fancybox-is-hidden");
5331		  });
5332		} else {
5333		  self.afterLoad(slide);
5334		}
5335
5336		$iframe.attr("src", slide.src);
5337
5338		// Remove iframe if closing or changing gallery item
5339		$slide.one("onReset", function () {
5340		  // This helps IE not to throw errors when closing
5341		  try {
5342			$(this)
5343			  .find("iframe")
5344			  .hide()
5345			  .unbind()
5346			  .attr("src", "//about:blank");
5347		  } catch (ignore) {}
5348
5349		  $(this)
5350			.off("refresh.fb")
5351			.empty();
5352
5353		  slide.isLoaded = false;
5354		  slide.isRevealed = false;
5355		});
5356	  },
5357
5358	  // Wrap and append content to the slide
5359	  // ======================================
5360
5361	  setContent: function (slide, content) {
5362		var self = this;
5363
5364		if (self.isClosing) {
5365		  return;
5366		}
5367
5368		self.hideLoading(slide);
5369
5370		if (slide.$content) {
5371		  $.fancybox.stop(slide.$content);
5372		}
5373
5374		slide.$slide.empty();
5375
5376		// If content is a jQuery object, then it will be moved to the slide.
5377		// The placeholder is created so we will know where to put it back.
5378		if (isQuery(content) && content.parent().length) {
5379		  // Make sure content is not already moved to fancyBox
5380		  if (content.hasClass("fancybox-content") || content.parent().hasClass("fancybox-content")) {
5381			content.parents(".fancybox-slide").trigger("onReset");
5382		  }
5383
5384		  // Create temporary element marking original place of the content
5385		  slide.$placeholder = $("<div>")
5386			.hide()
5387			.insertAfter(content);
5388
5389		  // Make sure content is visible
5390		  content.css("display", "inline-block");
5391		} else if (!slide.hasError) {
5392		  // If content is just a plain text, try to convert it to html
5393		  if ($.type(content) === "string") {
5394			content = $("<div>")
5395			  .append($.trim(content))
5396			  .contents();
5397		  }
5398
5399		  // If "filter" option is provided, then filter content
5400		  if (slide.opts.filter) {
5401			content = $("<div>")
5402			  .html(content)
5403			  .find(slide.opts.filter);
5404		  }
5405		}
5406
5407		slide.$slide.one("onReset", function () {
5408		  // Pause all html5 video/audio
5409		  $(this)
5410			.find("video,audio")
5411			.trigger("pause");
5412
5413		  // Put content back
5414		  if (slide.$placeholder) {
5415			slide.$placeholder.after(content.removeClass("fancybox-content").hide()).remove();
5416
5417			slide.$placeholder = null;
5418		  }
5419
5420		  // Remove custom close button
5421		  if (slide.$smallBtn) {
5422			slide.$smallBtn.remove();
5423
5424			slide.$smallBtn = null;
5425		  }
5426
5427		  // Remove content and mark slide as not loaded
5428		  if (!slide.hasError) {
5429			$(this).empty();
5430
5431			slide.isLoaded = false;
5432			slide.isRevealed = false;
5433		  }
5434		});
5435
5436		$(content).appendTo(slide.$slide);
5437
5438		if ($(content).is("video,audio")) {
5439		  $(content).addClass("fancybox-video");
5440
5441		  $(content).wrap("<div></div>");
5442
5443		  slide.contentType = "video";
5444
5445		  slide.opts.width = slide.opts.width || $(content).attr("width");
5446		  slide.opts.height = slide.opts.height || $(content).attr("height");
5447		}
5448
5449		slide.$content = slide.$slide
5450		  .children()
5451		  .filter("div,form,main,video,audio,article,.fancybox-content")
5452		  .first();
5453
5454		slide.$content.siblings().hide();
5455
5456		// Re-check if there is a valid content
5457		// (in some cases, ajax response can contain various elements or plain text)
5458		if (!slide.$content.length) {
5459		  slide.$content = slide.$slide
5460			.wrapInner("<div></div>")
5461			.children()
5462			.first();
5463		}
5464
5465		slide.$content.addClass("fancybox-content");
5466
5467		slide.$slide.addClass("fancybox-slide--" + slide.contentType);
5468
5469		self.afterLoad(slide);
5470	  },
5471
5472	  // Display error message
5473	  // =====================
5474
5475	  setError: function (slide) {
5476		slide.hasError = true;
5477
5478		slide.$slide
5479		  .trigger("onReset")
5480		  .removeClass("fancybox-slide--" + slide.contentType)
5481		  .addClass("fancybox-slide--error");
5482
5483		slide.contentType = "html";
5484
5485		this.setContent(slide, this.translate(slide, slide.opts.errorTpl));
5486
5487		if (slide.pos === this.currPos) {
5488		  this.isAnimating = false;
5489		}
5490	  },
5491
5492	  // Show loading icon inside the slide
5493	  // ==================================
5494
5495	  showLoading: function (slide) {
5496		var self = this;
5497
5498		slide = slide || self.current;
5499
5500		if (slide && !slide.$spinner) {
5501		  slide.$spinner = $(self.translate(self, self.opts.spinnerTpl))
5502			.appendTo(slide.$slide)
5503			.hide()
5504			.fadeIn("fast");
5505		}
5506	  },
5507
5508	  // Remove loading icon from the slide
5509	  // ==================================
5510
5511	  hideLoading: function (slide) {
5512		var self = this;
5513
5514		slide = slide || self.current;
5515
5516		if (slide && slide.$spinner) {
5517		  slide.$spinner.stop().remove();
5518
5519		  delete slide.$spinner;
5520		}
5521	  },
5522
5523	  // Adjustments after slide content has been loaded
5524	  // ===============================================
5525
5526	  afterLoad: function (slide) {
5527		var self = this;
5528
5529		if (self.isClosing) {
5530		  return;
5531		}
5532
5533		slide.isLoading = false;
5534		slide.isLoaded = true;
5535
5536		self.trigger("afterLoad", slide);
5537
5538		self.hideLoading(slide);
5539
5540		// Add small close button
5541		if (slide.opts.smallBtn && (!slide.$smallBtn || !slide.$smallBtn.length)) {
5542		  slide.$smallBtn = $(self.translate(slide, slide.opts.btnTpl.smallBtn)).appendTo(slide.$content);
5543		}
5544
5545		// Disable right click
5546		if (slide.opts.protect && slide.$content && !slide.hasError) {
5547		  slide.$content.on("contextmenu.fb", function (e) {
5548			if (e.button == 2) {
5549			  e.preventDefault();
5550			}
5551
5552			return true;
5553		  });
5554
5555		  // Add fake element on top of the image
5556		  // This makes a bit harder for user to select image
5557		  if (slide.type === "image") {
5558			$('<div class="fancybox-spaceball"></div>').appendTo(slide.$content);
5559		  }
5560		}
5561
5562		self.adjustCaption(slide);
5563
5564		self.adjustLayout(slide);
5565
5566		if (slide.pos === self.currPos) {
5567		  self.updateCursor();
5568		}
5569
5570		self.revealContent(slide);
5571	  },
5572
5573	  // Prevent caption overlap,
5574	  // fix css inconsistency across browsers
5575	  // =====================================
5576
5577	  adjustCaption: function (slide) {
5578		var self = this,
5579		  current = slide || self.current,
5580		  caption = current.opts.caption,
5581		  preventOverlap = current.opts.preventCaptionOverlap,
5582		  $caption = self.$refs.caption,
5583		  $clone,
5584		  captionH = false;
5585
5586		$caption.toggleClass("fancybox-caption--separate", preventOverlap);
5587
5588		if (preventOverlap && caption && caption.length) {
5589		  if (current.pos !== self.currPos) {
5590			$clone = $caption.clone().appendTo($caption.parent());
5591
5592			$clone
5593			  .children()
5594			  .eq(0)
5595			  .empty()
5596			  .html(caption);
5597
5598			captionH = $clone.outerHeight(true);
5599
5600			$clone.empty().remove();
5601		  } else if (self.$caption) {
5602			captionH = self.$caption.outerHeight(true);
5603		  }
5604
5605		  current.$slide.css("padding-bottom", captionH || "");
5606		}
5607	  },
5608
5609	  // Simple hack to fix inconsistency across browsers, described here (affects Edge, too):
5610	  // https://bugzilla.mozilla.org/show_bug.cgi?id=748518
5611	  // ====================================================================================
5612
5613	  adjustLayout: function (slide) {
5614		var self = this,
5615		  current = slide || self.current,
5616		  scrollHeight,
5617		  marginBottom,
5618		  inlinePadding,
5619		  actualPadding;
5620
5621		if (current.isLoaded && current.opts.disableLayoutFix !== true) {
5622		  current.$content.css("margin-bottom", "");
5623
5624		  // If we would always set margin-bottom for the content,
5625		  // then it would potentially break vertical align
5626		  if (current.$content.outerHeight() > current.$slide.height() + 0.5) {
5627			inlinePadding = current.$slide[0].style["padding-bottom"];
5628			actualPadding = current.$slide.css("padding-bottom");
5629
5630			if (parseFloat(actualPadding) > 0) {
5631			  scrollHeight = current.$slide[0].scrollHeight;
5632
5633			  current.$slide.css("padding-bottom", 0);
5634
5635			  if (Math.abs(scrollHeight - current.$slide[0].scrollHeight) < 1) {
5636				marginBottom = actualPadding;
5637			  }
5638
5639			  current.$slide.css("padding-bottom", inlinePadding);
5640			}
5641		  }
5642
5643		  current.$content.css("margin-bottom", marginBottom);
5644		}
5645	  },
5646
5647	  // Make content visible
5648	  // This method is called right after content has been loaded or
5649	  // user navigates gallery and transition should start
5650	  // ============================================================
5651
5652	  revealContent: function (slide) {
5653		var self = this,
5654		  $slide = slide.$slide,
5655		  end = false,
5656		  start = false,
5657		  isMoved = self.isMoved(slide),
5658		  isRevealed = slide.isRevealed,
5659		  effect,
5660		  effectClassName,
5661		  duration,
5662		  opacity;
5663
5664		slide.isRevealed = true;
5665
5666		effect = slide.opts[self.firstRun ? "animationEffect" : "transitionEffect"];
5667		duration = slide.opts[self.firstRun ? "animationDuration" : "transitionDuration"];
5668
5669		duration = parseInt(slide.forcedDuration === undefined ? duration : slide.forcedDuration, 10);
5670
5671		if (isMoved || slide.pos !== self.currPos || !duration) {
5672		  effect = false;
5673		}
5674
5675		// Check if can zoom
5676		if (effect === "zoom") {
5677		  if (slide.pos === self.currPos && duration && slide.type === "image" && !slide.hasError && (start = self.getThumbPos(slide))) {
5678			end = self.getFitPos(slide);
5679		  } else {
5680			effect = "fade";
5681		  }
5682		}
5683
5684		// Zoom animation
5685		// ==============
5686		if (effect === "zoom") {
5687		  self.isAnimating = true;
5688
5689		  end.scaleX = end.width / start.width;
5690		  end.scaleY = end.height / start.height;
5691
5692		  // Check if we need to animate opacity
5693		  opacity = slide.opts.zoomOpacity;
5694
5695		  if (opacity == "auto") {
5696			opacity = Math.abs(slide.width / slide.height - start.width / start.height) > 0.1;
5697		  }
5698
5699		  if (opacity) {
5700			start.opacity = 0.1;
5701			end.opacity = 1;
5702		  }
5703
5704		  // Draw image at start position
5705		  $.fancybox.setTranslate(slide.$content.removeClass("fancybox-is-hidden"), start);
5706
5707		  forceRedraw(slide.$content);
5708
5709		  // Start animation
5710		  $.fancybox.animate(slide.$content, end, duration, function () {
5711			self.isAnimating = false;
5712
5713			self.complete();
5714		  });
5715
5716		  return;
5717		}
5718
5719		self.updateSlide(slide);
5720
5721		// Simply show content if no effect
5722		// ================================
5723		if (!effect) {
5724		  slide.$content.removeClass("fancybox-is-hidden");
5725
5726		  if (!isRevealed && isMoved && slide.type === "image" && !slide.hasError) {
5727			slide.$content.hide().fadeIn("fast");
5728		  }
5729
5730		  if (slide.pos === self.currPos) {
5731			self.complete();
5732		  }
5733
5734		  return;
5735		}
5736
5737		// Prepare for CSS transiton
5738		// =========================
5739		$.fancybox.stop($slide);
5740
5741		//effectClassName = "fancybox-animated fancybox-slide--" + (slide.pos >= self.prevPos ? "next" : "previous") + " fancybox-fx-" + effect;
5742		effectClassName = "fancybox-slide--" + (slide.pos >= self.prevPos ? "next" : "previous") + " fancybox-animated fancybox-fx-" + effect;
5743
5744		$slide.addClass(effectClassName).removeClass("fancybox-slide--current"); //.addClass(effectClassName);
5745
5746		slide.$content.removeClass("fancybox-is-hidden");
5747
5748		// Force reflow
5749		forceRedraw($slide);
5750
5751		if (slide.type !== "image") {
5752		  slide.$content.hide().show(0);
5753		}
5754
5755		$.fancybox.animate(
5756		  $slide,
5757		  "fancybox-slide--current",
5758		  duration,
5759		  function () {
5760			$slide.removeClass(effectClassName).css({
5761			  transform: "",
5762			  opacity: ""
5763			});
5764
5765			if (slide.pos === self.currPos) {
5766			  self.complete();
5767			}
5768		  },
5769		  true
5770		);
5771	  },
5772
5773	  // Check if we can and have to zoom from thumbnail
5774	  //================================================
5775
5776	  getThumbPos: function (slide) {
5777		var rez = false,
5778		  $thumb = slide.$thumb,
5779		  thumbPos,
5780		  btw,
5781		  brw,
5782		  bbw,
5783		  blw;
5784
5785		if (!$thumb || !inViewport($thumb[0])) {
5786		  return false;
5787		}
5788
5789		thumbPos = $.fancybox.getTranslate($thumb);
5790
5791		btw = parseFloat($thumb.css("border-top-width") || 0);
5792		brw = parseFloat($thumb.css("border-right-width") || 0);
5793		bbw = parseFloat($thumb.css("border-bottom-width") || 0);
5794		blw = parseFloat($thumb.css("border-left-width") || 0);
5795
5796		rez = {
5797		  top: thumbPos.top + btw,
5798		  left: thumbPos.left + blw,
5799		  width: thumbPos.width - brw - blw,
5800		  height: thumbPos.height - btw - bbw,
5801		  scaleX: 1,
5802		  scaleY: 1
5803		};
5804
5805		return thumbPos.width > 0 && thumbPos.height > 0 ? rez : false;
5806	  },
5807
5808	  // Final adjustments after current gallery item is moved to position
5809	  // and it`s content is loaded
5810	  // ==================================================================
5811
5812	  complete: function () {
5813		var self = this,
5814		  current = self.current,
5815		  slides = {},
5816		  $el;
5817
5818		if (self.isMoved() || !current.isLoaded) {
5819		  return;
5820		}
5821
5822		if (!current.isComplete) {
5823		  current.isComplete = true;
5824
5825		  current.$slide.siblings().trigger("onReset");
5826
5827		  self.preload("inline");
5828
5829		  // Trigger any CSS transiton inside the slide
5830		  forceRedraw(current.$slide);
5831
5832		  current.$slide.addClass("fancybox-slide--complete");
5833
5834		  // Remove unnecessary slides
5835		  $.each(self.slides, function (key, slide) {
5836			if (slide.pos >= self.currPos - 1 && slide.pos <= self.currPos + 1) {
5837			  slides[slide.pos] = slide;
5838			} else if (slide) {
5839			  $.fancybox.stop(slide.$slide);
5840
5841			  slide.$slide.off().remove();
5842			}
5843		  });
5844
5845		  self.slides = slides;
5846		}
5847
5848		self.isAnimating = false;
5849
5850		self.updateCursor();
5851
5852		self.trigger("afterShow");
5853
5854		// Autoplay first html5 video/audio
5855		if (!!current.opts.video.autoStart) {
5856		  current.$slide
5857			.find("video,audio")
5858			.filter(":visible:first")
5859			.trigger("play")
5860			.one("ended", function () {
5861			  if (Document.exitFullscreen) {
5862				Document.exitFullscreen();
5863			  } else if (this.webkitExitFullscreen) {
5864				this.webkitExitFullscreen();
5865			  }
5866
5867			  self.next();
5868			});
5869		}
5870
5871		// Try to focus on the first focusable element
5872		if (current.opts.autoFocus && current.contentType === "html") {
5873		  // Look for the first input with autofocus attribute
5874		  $el = current.$content.find("input[autofocus]:enabled:visible:first");
5875
5876		  if ($el.length) {
5877			$el.trigger("focus");
5878		  } else {
5879			self.focus(null, true);
5880		  }
5881		}
5882
5883		// Avoid jumping
5884		current.$slide.scrollTop(0).scrollLeft(0);
5885	  },
5886
5887	  // Preload next and previous slides
5888	  // ================================
5889
5890	  preload: function (type) {
5891		var self = this,
5892		  prev,
5893		  next;
5894
5895		if (self.group.length < 2) {
5896		  return;
5897		}
5898
5899		next = self.slides[self.currPos + 1];
5900		prev = self.slides[self.currPos - 1];
5901
5902		if (prev && prev.type === type) {
5903		  self.loadSlide(prev);
5904		}
5905
5906		if (next && next.type === type) {
5907		  self.loadSlide(next);
5908		}
5909	  },
5910
5911	  // Try to find and focus on the first focusable element
5912	  // ====================================================
5913
5914	  focus: function (e, firstRun) {
5915		var self = this,
5916		  focusableStr = [
5917			"a[href]",
5918			"area[href]",
5919			'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',
5920			"select:not([disabled]):not([aria-hidden])",
5921			"textarea:not([disabled]):not([aria-hidden])",
5922			"button:not([disabled]):not([aria-hidden])",
5923			"iframe",
5924			"object",
5925			"embed",
5926			"video",
5927			"audio",
5928			"[contenteditable]",
5929			'[tabindex]:not([tabindex^="-"])'
5930		  ].join(","),
5931		  focusableItems,
5932		  focusedItemIndex;
5933
5934		if (self.isClosing) {
5935		  return;
5936		}
5937
5938		if (e || !self.current || !self.current.isComplete) {
5939		  // Focus on any element inside fancybox
5940		  focusableItems = self.$refs.container.find("*:visible");
5941		} else {
5942		  // Focus inside current slide
5943		  focusableItems = self.current.$slide.find("*:visible" + (firstRun ? ":not(.fancybox-close-small)" : ""));
5944		}
5945
5946		focusableItems = focusableItems.filter(focusableStr).filter(function () {
5947		  return $(this).css("visibility") !== "hidden" && !$(this).hasClass("disabled");
5948		});
5949
5950		if (focusableItems.length) {
5951		  focusedItemIndex = focusableItems.index(document.activeElement);
5952
5953		  if (e && e.shiftKey) {
5954			// Back tab
5955			if (focusedItemIndex < 0 || focusedItemIndex == 0) {
5956			  e.preventDefault();
5957
5958			  focusableItems.eq(focusableItems.length - 1).trigger("focus");
5959			}
5960		  } else {
5961			// Outside or Forward tab
5962			if (focusedItemIndex < 0 || focusedItemIndex == focusableItems.length - 1) {
5963			  if (e) {
5964				e.preventDefault();
5965			  }
5966
5967			  focusableItems.eq(0).trigger("focus");
5968			}
5969		  }
5970		} else {
5971		  self.$refs.container.trigger("focus");
5972		}
5973	  },
5974
5975	  // Activates current instance - brings container to the front and enables keyboard,
5976	  // notifies other instances about deactivating
5977	  // =================================================================================
5978
5979	  activate: function () {
5980		var self = this;
5981
5982		// Deactivate all instances
5983		$(".fancybox-container").each(function () {
5984		  var instance = $(this).data("FancyBox");
5985
5986		  // Skip self and closing instances
5987		  if (instance && instance.id !== self.id && !instance.isClosing) {
5988			instance.trigger("onDeactivate");
5989
5990			instance.removeEvents();
5991
5992			instance.isVisible = false;
5993		  }
5994		});
5995
5996		self.isVisible = true;
5997
5998		if (self.current || self.isIdle) {
5999		  self.update();
6000
6001		  self.updateControls();
6002		}
6003
6004		self.trigger("onActivate");
6005
6006		self.addEvents();
6007	  },
6008
6009	  // Start closing procedure
6010	  // This will start "zoom-out" animation if needed and clean everything up afterwards
6011	  // =================================================================================
6012
6013	  close: function (e, d) {
6014		var self = this,
6015		  current = self.current,
6016		  effect,
6017		  duration,
6018		  $content,
6019		  domRect,
6020		  opacity,
6021		  start,
6022		  end;
6023
6024		var done = function () {
6025		  self.cleanUp(e);
6026		};
6027
6028		if (self.isClosing) {
6029		  return false;
6030		}
6031
6032		self.isClosing = true;
6033
6034		// If beforeClose callback prevents closing, make sure content is centered
6035		if (self.trigger("beforeClose", e) === false) {
6036		  self.isClosing = false;
6037
6038		  requestAFrame(function () {
6039			self.update();
6040		  });
6041
6042		  return false;
6043		}
6044
6045		// Remove all events
6046		// If there are multiple instances, they will be set again by "activate" method
6047		self.removeEvents();
6048
6049		$content = current.$content;
6050		effect = current.opts.animationEffect;
6051		duration = $.isNumeric(d) ? d : effect ? current.opts.animationDuration : 0;
6052
6053		current.$slide.removeClass("fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated");
6054
6055		if (e !== true) {
6056		  $.fancybox.stop(current.$slide);
6057		} else {
6058		  effect = false;
6059		}
6060
6061		// Remove other slides
6062		current.$slide
6063		  .siblings()
6064		  .trigger("onReset")
6065		  .remove();
6066
6067		// Trigger animations
6068		if (duration) {
6069		  self.$refs.container
6070			.removeClass("fancybox-is-open")
6071			.addClass("fancybox-is-closing")
6072			.css("transition-duration", duration + "ms");
6073		}
6074
6075		// Clean up
6076		self.hideLoading(current);
6077
6078		self.hideControls(true);
6079
6080		self.updateCursor();
6081
6082		// Check if possible to zoom-out
6083		if (
6084		  effect === "zoom" &&
6085		  !($content && duration && current.type === "image" && !self.isMoved() && !current.hasError && (end = self.getThumbPos(current)))
6086		) {
6087		  effect = "fade";
6088		}
6089
6090		if (effect === "zoom") {
6091		  $.fancybox.stop($content);
6092
6093		  domRect = $.fancybox.getTranslate($content);
6094
6095		  start = {
6096			top: domRect.top,
6097			left: domRect.left,
6098			scaleX: domRect.width / end.width,
6099			scaleY: domRect.height / end.height,
6100			width: end.width,
6101			height: end.height
6102		  };
6103
6104		  // Check if we need to animate opacity
6105		  opacity = current.opts.zoomOpacity;
6106
6107		  if (opacity == "auto") {
6108			opacity = Math.abs(current.width / current.height - end.width / end.height) > 0.1;
6109		  }
6110
6111		  if (opacity) {
6112			end.opacity = 0;
6113		  }
6114
6115		  $.fancybox.setTranslate($content, start);
6116
6117		  forceRedraw($content);
6118
6119		  $.fancybox.animate($content, end, duration, done);
6120
6121		  return true;
6122		}
6123
6124		if (effect && duration) {
6125		  $.fancybox.animate(
6126			current.$slide.addClass("fancybox-slide--previous").removeClass("fancybox-slide--current"),
6127			"fancybox-animated fancybox-fx-" + effect,
6128			duration,
6129			done
6130		  );
6131		} else {
6132		  // If skip animation
6133		  if (e === true) {
6134			setTimeout(done, duration);
6135		  } else {
6136			done();
6137		  }
6138		}
6139
6140		return true;
6141	  },
6142
6143	  // Final adjustments after removing the instance
6144	  // =============================================
6145
6146	  cleanUp: function (e) {
6147		var self = this,
6148		  instance,
6149		  $focus = self.current.opts.$orig,
6150		  x,
6151		  y;
6152
6153		self.current.$slide.trigger("onReset");
6154
6155		self.$refs.container.empty().remove();
6156
6157		self.trigger("afterClose", e);
6158
6159		// Place back focus
6160		if (!!self.current.opts.backFocus) {
6161		  if (!$focus || !$focus.length || !$focus.is(":visible")) {
6162			$focus = self.$trigger;
6163		  }
6164
6165		  if ($focus && $focus.length) {
6166			x = window.scrollX;
6167			y = window.scrollY;
6168
6169			$focus.trigger("focus");
6170
6171			$("html, body")
6172			  .scrollTop(y)
6173			  .scrollLeft(x);
6174		  }
6175		}
6176
6177		self.current = null;
6178
6179		// Check if there are other instances
6180		instance = $.fancybox.getInstance();
6181
6182		if (instance) {
6183		  instance.activate();
6184		} else {
6185		  $("body").removeClass("fancybox-active compensate-for-scrollbar");
6186
6187		  $("#fancybox-style-noscroll").remove();
6188		}
6189	  },
6190
6191	  // Call callback and trigger an event
6192	  // ==================================
6193
6194	  trigger: function (name, slide) {
6195		var args = Array.prototype.slice.call(arguments, 1),
6196		  self = this,
6197		  obj = slide && slide.opts ? slide : self.current,
6198		  rez;
6199
6200		if (obj) {
6201		  args.unshift(obj);
6202		} else {
6203		  obj = self;
6204		}
6205
6206		args.unshift(self);
6207
6208		if ($.isFunction(obj.opts[name])) {
6209		  rez = obj.opts[name].apply(obj, args);
6210		}
6211
6212		if (rez === false) {
6213		  return rez;
6214		}
6215
6216		if (name === "afterClose" || !self.$refs) {
6217		  $D.trigger(name + ".fb", args);
6218		} else {
6219		  self.$refs.container.trigger(name + ".fb", args);
6220		}
6221	  },
6222
6223	  // Update infobar values, navigation button states and reveal caption
6224	  // ==================================================================
6225
6226	  updateControls: function () {
6227		var self = this,
6228		  current = self.current,
6229		  index = current.index,
6230		  $container = self.$refs.container,
6231		  $caption = self.$refs.caption,
6232		  caption = current.opts.caption;
6233
6234		// Recalculate content dimensions
6235		current.$slide.trigger("refresh");
6236
6237		// Set caption
6238		if (caption && caption.length) {
6239		  self.$caption = $caption;
6240
6241		  $caption
6242			.children()
6243			.eq(0)
6244			.html(caption);
6245		} else {
6246		  self.$caption = null;
6247		}
6248
6249		if (!self.hasHiddenControls && !self.isIdle) {
6250		  self.showControls();
6251		}
6252
6253		// Update info and navigation elements
6254		$container.find("[data-fancybox-count]").html(self.group.length);
6255		$container.find("[data-fancybox-index]").html(index + 1);
6256
6257		$container.find("[data-fancybox-prev]").prop("disabled", !current.opts.loop && index <= 0);
6258		$container.find("[data-fancybox-next]").prop("disabled", !current.opts.loop && index >= self.group.length - 1);
6259
6260		if (current.type === "image") {
6261		  // Re-enable buttons; update download button source
6262		  $container
6263			.find("[data-fancybox-zoom]")
6264			.show()
6265			.end()
6266			.find("[data-fancybox-download]")
6267			.attr("href", current.opts.image.src || current.src)
6268			.show();
6269		} else if (current.opts.toolbar) {
6270		  $container.find("[data-fancybox-download],[data-fancybox-zoom]").hide();
6271		}
6272
6273		// Make sure focus is not on disabled button/element
6274		if ($(document.activeElement).is(":hidden,[disabled]")) {
6275		  self.$refs.container.trigger("focus");
6276		}
6277	  },
6278
6279	  // Hide toolbar and caption
6280	  // ========================
6281
6282	  hideControls: function (andCaption) {
6283		var self = this,
6284		  arr = ["infobar", "toolbar", "nav"];
6285
6286		if (andCaption || !self.current.opts.preventCaptionOverlap) {
6287		  arr.push("caption");
6288		}
6289
6290		this.$refs.container.removeClass(
6291		  arr
6292		  .map(function (i) {
6293			return "fancybox-show-" + i;
6294		  })
6295		  .join(" ")
6296		);
6297
6298		this.hasHiddenControls = true;
6299	  },
6300
6301	  showControls: function () {
6302		var self = this,
6303		  opts = self.current ? self.current.opts : self.opts,
6304		  $container = self.$refs.container;
6305
6306		self.hasHiddenControls = false;
6307		self.idleSecondsCounter = 0;
6308
6309		$container
6310		  .toggleClass("fancybox-show-toolbar", !!(opts.toolbar && opts.buttons))
6311		  .toggleClass("fancybox-show-infobar", !!(opts.infobar && self.group.length > 1))
6312		  .toggleClass("fancybox-show-caption", !!self.$caption)
6313		  .toggleClass("fancybox-show-nav", !!(opts.arrows && self.group.length > 1))
6314		  .toggleClass("fancybox-is-modal", !!opts.modal);
6315	  },
6316
6317	  // Toggle toolbar and caption
6318	  // ==========================
6319
6320	  toggleControls: function () {
6321		if (this.hasHiddenControls) {
6322		  this.showControls();
6323		} else {
6324		  this.hideControls();
6325		}
6326	  }
6327	});
6328
6329	$.fancybox = {
6330	  version: "3.5.7",
6331	  defaults: defaults,
6332
6333	  // Get current instance and execute a command.
6334	  //
6335	  // Examples of usage:
6336	  //
6337	  //   $instance = $.fancybox.getInstance();
6338	  //   $.fancybox.getInstance().jumpTo( 1 );
6339	  //   $.fancybox.getInstance( 'jumpTo', 1 );
6340	  //   $.fancybox.getInstance( function() {
6341	  //       console.info( this.currIndex );
6342	  //   });
6343	  // ======================================================
6344
6345	  getInstance: function (command) {
6346		var instance = $('.fancybox-container:not(".fancybox-is-closing"):last').data("FancyBox"),
6347		  args = Array.prototype.slice.call(arguments, 1);
6348
6349		if (instance instanceof FancyBox) {
6350		  if ($.type(command) === "string") {
6351			instance[command].apply(instance, args);
6352		  } else if ($.type(command) === "function") {
6353			command.apply(instance, args);
6354		  }
6355
6356		  return instance;
6357		}
6358
6359		return false;
6360	  },
6361
6362	  // Create new instance
6363	  // ===================
6364
6365	  open: function (items, opts, index) {
6366		return new FancyBox(items, opts, index);
6367	  },
6368
6369	  // Close current or all instances
6370	  // ==============================
6371
6372	  close: function (all) {
6373		var instance = this.getInstance();
6374
6375		if (instance) {
6376		  instance.close();
6377
6378		  // Try to find and close next instance
6379		  if (all === true) {
6380			this.close(all);
6381		  }
6382		}
6383	  },
6384
6385	  // Close all instances and unbind all events
6386	  // =========================================
6387
6388	  destroy: function () {
6389		this.close(true);
6390
6391		$D.add("body").off("click.fb-start", "**");
6392	  },
6393
6394	  // Try to detect mobile devices
6395	  // ============================
6396
6397	  isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
6398
6399	  // Detect if 'translate3d' support is available
6400	  // ============================================
6401
6402	  use3d: (function () {
6403		var div = document.createElement("div");
6404
6405		return (
6406		  window.getComputedStyle &&
6407		  window.getComputedStyle(div) &&
6408		  window.getComputedStyle(div).getPropertyValue("transform") &&
6409		  !(document.documentMode && document.documentMode < 11)
6410		);
6411	  })(),
6412
6413	  // Helper function to get current visual state of an element
6414	  // returns array[ top, left, horizontal-scale, vertical-scale, opacity ]
6415	  // =====================================================================
6416
6417	  getTranslate: function ($el) {
6418		var domRect;
6419
6420		if (!$el || !$el.length) {
6421		  return false;
6422		}
6423
6424		domRect = $el[0].getBoundingClientRect();
6425
6426		return {
6427		  top: domRect.top || 0,
6428		  left: domRect.left || 0,
6429		  width: domRect.width,
6430		  height: domRect.height,
6431		  opacity: parseFloat($el.css("opacity"))
6432		};
6433	  },
6434
6435	  // Shortcut for setting "translate3d" properties for element
6436	  // Can set be used to set opacity, too
6437	  // ========================================================
6438
6439	  setTranslate: function ($el, props) {
6440		var str = "",
6441		  css = {};
6442
6443		if (!$el || !props) {
6444		  return;
6445		}
6446
6447		if (props.left !== undefined || props.top !== undefined) {
6448		  str =
6449			(props.left === undefined ? $el.position().left : props.left) +
6450			"px, " +
6451			(props.top === undefined ? $el.position().top : props.top) +
6452			"px";
6453
6454		  if (this.use3d) {
6455			str = "translate3d(" + str + ", 0px)";
6456		  } else {
6457			str = "translate(" + str + ")";
6458		  }
6459		}
6460
6461		if (props.scaleX !== undefined && props.scaleY !== undefined) {
6462		  str += " scale(" + props.scaleX + ", " + props.scaleY + ")";
6463		} else if (props.scaleX !== undefined) {
6464		  str += " scaleX(" + props.scaleX + ")";
6465		}
6466
6467		if (str.length) {
6468		  css.transform = str;
6469		}
6470
6471		if (props.opacity !== undefined) {
6472		  css.opacity = props.opacity;
6473		}
6474
6475		if (props.width !== undefined) {
6476		  css.width = props.width;
6477		}
6478
6479		if (props.height !== undefined) {
6480		  css.height = props.height;
6481		}
6482
6483		return $el.css(css);
6484	  },
6485
6486	  // Simple CSS transition handler
6487	  // =============================
6488
6489	  animate: function ($el, to, duration, callback, leaveAnimationName) {
6490		var self = this,
6491		  from;
6492
6493		if ($.isFunction(duration)) {
6494		  callback = duration;
6495		  duration = null;
6496		}
6497
6498		self.stop($el);
6499
6500		from = self.getTranslate($el);
6501
6502		$el.on(transitionEnd, function (e) {
6503		  // Skip events from child elements and z-index change
6504		  if (e && e.originalEvent && (!$el.is(e.originalEvent.target) || e.originalEvent.propertyName == "z-index")) {
6505			return;
6506		  }
6507
6508		  self.stop($el);
6509
6510		  if ($.isNumeric(duration)) {
6511			$el.css("transition-duration", "");
6512		  }
6513
6514		  if ($.isPlainObject(to)) {
6515			if (to.scaleX !== undefined && to.scaleY !== undefined) {
6516			  self.setTranslate($el, {
6517				top: to.top,
6518				left: to.left,
6519				width: from.width * to.scaleX,
6520				height: from.height * to.scaleY,
6521				scaleX: 1,
6522				scaleY: 1
6523			  });
6524			}
6525		  } else if (leaveAnimationName !== true) {
6526			$el.removeClass(to);
6527		  }
6528
6529		  if ($.isFunction(callback)) {
6530			callback(e);
6531		  }
6532		});
6533
6534		if ($.isNumeric(duration)) {
6535		  $el.css("transition-duration", duration + "ms");
6536		}
6537
6538		// Start animation by changing CSS properties or class name
6539		if ($.isPlainObject(to)) {
6540		  if (to.scaleX !== undefined && to.scaleY !== undefined) {
6541			delete to.width;
6542			delete to.height;
6543
6544			if ($el.parent().hasClass("fancybox-slide--image")) {
6545			  $el.parent().addClass("fancybox-is-scaling");
6546			}
6547		  }
6548
6549		  $.fancybox.setTranslate($el, to);
6550		} else {
6551		  $el.addClass(to);
6552		}
6553
6554		// Make sure that `transitionend` callback gets fired
6555		$el.data(
6556		  "timer",
6557		  setTimeout(function () {
6558			$el.trigger(transitionEnd);
6559		  }, duration + 33)
6560		);
6561	  },
6562
6563	  stop: function ($el, callCallback) {
6564		if ($el && $el.length) {
6565		  clearTimeout($el.data("timer"));
6566
6567		  if (callCallback) {
6568			$el.trigger(transitionEnd);
6569		  }
6570
6571		  $el.off(transitionEnd).css("transition-duration", "");
6572
6573		  $el.parent().removeClass("fancybox-is-scaling");
6574		}
6575	  }
6576	};
6577
6578	// Default click handler for "fancyboxed" links
6579	// ============================================
6580
6581	function _run(e, opts) {
6582	  var items = [],
6583		index = 0,
6584		$target,
6585		value,
6586		instance;
6587
6588	  // Avoid opening multiple times
6589	  if (e && e.isDefaultPrevented()) {
6590		return;
6591	  }
6592
6593	  e.preventDefault();
6594
6595	  opts = opts || {};
6596
6597	  if (e && e.data) {
6598		opts = mergeOpts(e.data.options, opts);
6599	  }
6600
6601	  $target = opts.$target || $(e.currentTarget).trigger("blur");
6602	  instance = $.fancybox.getInstance();
6603
6604	  if (instance && instance.$trigger && instance.$trigger.is($target)) {
6605		return;
6606	  }
6607
6608	  if (opts.selector) {
6609		items = $(opts.selector);
6610	  } else {
6611		// Get all related items and find index for clicked one
6612		value = $target.attr("data-fancybox") || "";
6613
6614		if (value) {
6615		  items = e.data ? e.data.items : [];
6616		  items = items.length ? items.filter('[data-fancybox="' + value + '"]') : $('[data-fancybox="' + value + '"]');
6617		} else {
6618		  items = [$target];
6619		}
6620	  }
6621
6622	  index = $(items).index($target);
6623
6624	  // Sometimes current item can not be found
6625	  if (index < 0) {
6626		index = 0;
6627	  }
6628
6629	  instance = $.fancybox.open(items, opts, index);
6630
6631	  // Save last active element
6632	  instance.$trigger = $target;
6633	}
6634
6635	// Create a jQuery plugin
6636	// ======================
6637
6638	$.fn.fancybox = function (options) {
6639	  var selector;
6640
6641	  options = options || {};
6642	  selector = options.selector || false;
6643
6644	  if (selector) {
6645		// Use body element instead of document so it executes first
6646		$("body")
6647		  .off("click.fb-start", selector)
6648		  .on("click.fb-start", selector, {
6649			options: options
6650		  }, _run);
6651	  } else {
6652		this.off("click.fb-start").on(
6653		  "click.fb-start", {
6654			items: this,
6655			options: options
6656		  },
6657		  _run
6658		);
6659	  }
6660
6661	  return this;
6662	};
6663
6664	// Self initializing plugin for all elements having `data-fancybox` attribute
6665	// ==========================================================================
6666
6667	$D.on("click.fb-start", "[data-fancybox]", _run);
6668
6669	// Enable "trigger elements"
6670	// =========================
6671
6672	$D.on("click.fb-start", "[data-fancybox-trigger]", function (e) {
6673	  $('[data-fancybox="' + $(this).attr("data-fancybox-trigger") + '"]')
6674		.eq($(this).attr("data-fancybox-index") || 0)
6675		.trigger("click.fb-start", {
6676		  $trigger: $(this)
6677		});
6678	});
6679
6680	// Track focus event for better accessibility styling
6681	// ==================================================
6682	(function () {
6683	  var buttonStr = ".fancybox-button",
6684		focusStr = "fancybox-focus",
6685		$pressed = null;
6686
6687	  $D.on("mousedown mouseup focus blur", buttonStr, function (e) {
6688		switch (e.type) {
6689		  case "mousedown":
6690			$pressed = $(this);
6691			break;
6692		  case "mouseup":
6693			$pressed = null;
6694			break;
6695		  case "focusin":
6696			$(buttonStr).removeClass(focusStr);
6697
6698			if (!$(this).is($pressed) && !$(this).is("[disabled]")) {
6699			  $(this).addClass(focusStr);
6700			}
6701			break;
6702		  case "focusout":
6703			$(buttonStr).removeClass(focusStr);
6704			break;
6705		}
6706	  });
6707	})();
6708  })(window, document, jQuery);
6709  // ==========================================================================
6710  //
6711  // Media
6712  // Adds additional media type support
6713  //
6714  // ==========================================================================
6715  (function ($) {
6716	"use strict";
6717
6718	// Object containing properties for each media type
6719	var defaults = {
6720	  youtube: {
6721		matcher: /(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,
6722		params: {
6723		  autoplay: 1,
6724		  autohide: 1,
6725		  fs: 1,
6726		  rel: 0,
6727		  hd: 1,
6728		  wmode: "transparent",
6729		  enablejsapi: 1,
6730		  html5: 1
6731		},
6732		paramPlace: 8,
6733		type: "iframe",
6734		url: "https://www.youtube-nocookie.com/embed/$4",
6735		thumb: "https://img.youtube.com/vi/$4/hqdefault.jpg"
6736	  },
6737
6738	  vimeo: {
6739		matcher: /^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,
6740		params: {
6741		  autoplay: 1,
6742		  hd: 1,
6743		  show_title: 1,
6744		  show_byline: 1,
6745		  show_portrait: 0,
6746		  fullscreen: 1
6747		},
6748		paramPlace: 3,
6749		type: "iframe",
6750		url: "//player.vimeo.com/video/$2"
6751	  },
6752
6753	  instagram: {
6754		matcher: /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
6755		type: "image",
6756		url: "//$1/p/$2/media/?size=l"
6757	  },
6758
6759	  // Examples:
6760	  // http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
6761	  // https://www.google.com/maps/@37.7852006,-122.4146355,14.65z
6762	  // https://www.google.com/maps/@52.2111123,2.9237542,6.61z?hl=en
6763	  // https://www.google.com/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572
6764	  gmap_place: {
6765		matcher: /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,
6766		type: "iframe",
6767		url: function (rez) {
6768		  return (
6769			"//maps.google." +
6770			rez[2] +
6771			"/?ll=" +
6772			(rez[9] ? rez[9] + "&z=" + Math.floor(rez[10]) + (rez[12] ? rez[12].replace(/^\//, "&") : "") : rez[12] + "").replace(/\?/, "&") +
6773			"&output=" +
6774			(rez[12] && rez[12].indexOf("layer=c") > 0 ? "svembed" : "embed")
6775		  );
6776		}
6777	  },
6778
6779	  // Examples:
6780	  // https://www.google.com/maps/search/Empire+State+Building/
6781	  // https://www.google.com/maps/search/?api=1&query=centurylink+field
6782	  // https://www.google.com/maps/search/?api=1&query=47.5951518,-122.3316393
6783	  gmap_search: {
6784		matcher: /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,
6785		type: "iframe",
6786		url: function (rez) {
6787		  return "//maps.google." + rez[2] + "/maps?q=" + rez[5].replace("query=", "q=").replace("api=1", "") + "&output=embed";
6788		}
6789	  }
6790	};
6791
6792	// Formats matching url to final form
6793	var format = function (url, rez, params) {
6794	  if (!url) {
6795		return;
6796	  }
6797
6798	  params = params || "";
6799
6800	  if ($.type(params) === "object") {
6801		params = $.param(params, true);
6802	  }
6803
6804	  $.each(rez, function (key, value) {
6805		url = url.replace("$" + key, value || "");
6806	  });
6807
6808	  if (params.length) {
6809		url += (url.indexOf("?") > 0 ? "&" : "?") + params;
6810	  }
6811
6812	  return url;
6813	};
6814
6815	$(document).on("objectNeedsType.fb", function (e, instance, item) {
6816	  var url = item.src || "",
6817		type = false,
6818		media,
6819		thumb,
6820		rez,
6821		params,
6822		urlParams,
6823		paramObj,
6824		provider;
6825
6826	  media = $.extend(true, {}, defaults, item.opts.media);
6827
6828	  // Look for any matching media type
6829	  $.each(media, function (providerName, providerOpts) {
6830		rez = url.match(providerOpts.matcher);
6831
6832		if (!rez) {
6833		  return;
6834		}
6835
6836		type = providerOpts.type;
6837		provider = providerName;
6838		paramObj = {};
6839
6840		if (providerOpts.paramPlace && rez[providerOpts.paramPlace]) {
6841		  urlParams = rez[providerOpts.paramPlace];
6842
6843		  if (urlParams[0] == "?") {
6844			urlParams = urlParams.substring(1);
6845		  }
6846
6847		  urlParams = urlParams.split("&");
6848
6849		  for (var m = 0; m < urlParams.length; ++m) {
6850			var p = urlParams[m].split("=", 2);
6851
6852			if (p.length == 2) {
6853			  paramObj[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
6854			}
6855		  }
6856		}
6857
6858		params = $.extend(true, {}, providerOpts.params, item.opts[providerName], paramObj);
6859
6860		url =
6861		  $.type(providerOpts.url) === "function" ? providerOpts.url.call(this, rez, params, item) : format(providerOpts.url, rez, params);
6862
6863		thumb =
6864		  $.type(providerOpts.thumb) === "function" ? providerOpts.thumb.call(this, rez, params, item) : format(providerOpts.thumb, rez);
6865
6866		if (providerName === "youtube") {
6867		  url = url.replace(/&t=((\d+)m)?(\d+)s/, function (match, p1, m, s) {
6868			return "&start=" + ((m ? parseInt(m, 10) * 60 : 0) + parseInt(s, 10));
6869		  });
6870		} else if (providerName === "vimeo") {
6871		  url = url.replace("&%23", "#");
6872		}
6873
6874		return false;
6875	  });
6876
6877	  // If it is found, then change content type and update the url
6878
6879	  if (type) {
6880		if (!item.opts.thumb && !(item.opts.$thumb && item.opts.$thumb.length)) {
6881		  item.opts.thumb = thumb;
6882		}
6883
6884		if (type === "iframe") {
6885		  item.opts = $.extend(true, item.opts, {
6886			iframe: {
6887			  preload: false,
6888			  attr: {
6889				scrolling: "no"
6890			  }
6891			}
6892		  });
6893		}
6894
6895		$.extend(item, {
6896		  type: type,
6897		  src: url,
6898		  origSrc: item.src,
6899		  contentSource: provider,
6900		  contentType: type === "image" ? "image" : provider == "gmap_place" || provider == "gmap_search" ? "map" : "video"
6901		});
6902	  } else if (url) {
6903		item.type = item.opts.defaultType;
6904	  }
6905	});
6906
6907	// Load YouTube/Video API on request to detect when video finished playing
6908	var VideoAPILoader = {
6909	  youtube: {
6910		src: "https://www.youtube.com/iframe_api",
6911		class: "YT",
6912		loading: false,
6913		loaded: false
6914	  },
6915
6916	  vimeo: {
6917		src: "https://player.vimeo.com/api/player.js",
6918		class: "Vimeo",
6919		loading: false,
6920		loaded: false
6921	  },
6922
6923	  load: function (vendor) {
6924		var _this = this,
6925		  script;
6926
6927		if (this[vendor].loaded) {
6928		  setTimeout(function () {
6929			_this.done(vendor);
6930		  });
6931		  return;
6932		}
6933
6934		if (this[vendor].loading) {
6935		  return;
6936		}
6937
6938		this[vendor].loading = true;
6939
6940		script = document.createElement("script");
6941		script.type = "text/javascript";
6942		script.src = this[vendor].src;
6943
6944		if (vendor === "youtube") {
6945		  window.onYouTubeIframeAPIReady = function () {
6946			_this[vendor].loaded = true;
6947			_this.done(vendor);
6948		  };
6949		} else {
6950		  script.onload = function () {
6951			_this[vendor].loaded = true;
6952			_this.done(vendor);
6953		  };
6954		}
6955
6956		document.body.appendChild(script);
6957	  },
6958	  done: function (vendor) {
6959		var instance, $el, player;
6960
6961		if (vendor === "youtube") {
6962		  delete window.onYouTubeIframeAPIReady;
6963		}
6964
6965		instance = $.fancybox.getInstance();
6966
6967		if (instance) {
6968		  $el = instance.current.$content.find("iframe");
6969
6970		  if (vendor === "youtube" && YT !== undefined && YT) {
6971			player = new YT.Player($el.attr("id"), {
6972			  events: {
6973				onStateChange: function (e) {
6974				  if (e.data == 0) {
6975					instance.next();
6976				  }
6977				}
6978			  }
6979			});
6980		  } else if (vendor === "vimeo" && Vimeo !== undefined && Vimeo) {
6981			player = new Vimeo.Player($el);
6982
6983			player.on("ended", function () {
6984			  instance.next();
6985			});
6986		  }
6987		}
6988	  }
6989	};
6990
6991	$(document).on({
6992	  "afterShow.fb": function (e, instance, current) {
6993		if (instance.group.length > 1 && (current.contentSource === "youtube" || current.contentSource === "vimeo")) {
6994		  VideoAPILoader.load(current.contentSource);
6995		}
6996	  }
6997	});
6998  })(jQuery);
6999  // ==========================================================================
7000  //
7001  // Guestures
7002  // Adds touch guestures, handles click and tap events
7003  //
7004  // ==========================================================================
7005  (function (window, document, $) {
7006	"use strict";
7007
7008	var requestAFrame = (function () {
7009	  return (
7010		window.requestAnimationFrame ||
7011		window.webkitRequestAnimationFrame ||
7012		window.mozRequestAnimationFrame ||
7013		window.oRequestAnimationFrame ||
7014		// if all else fails, use setTimeout
7015		function (callback) {
7016		  return window.setTimeout(callback, 1000 / 60);
7017		}
7018	  );
7019	})();
7020
7021	var cancelAFrame = (function () {
7022	  return (
7023		window.cancelAnimationFrame ||
7024		window.webkitCancelAnimationFrame ||
7025		window.mozCancelAnimationFrame ||
7026		window.oCancelAnimationFrame ||
7027		function (id) {
7028		  window.clearTimeout(id);
7029		}
7030	  );
7031	})();
7032
7033	var getPointerXY = function (e) {
7034	  var result = [];
7035
7036	  e = e.originalEvent || e || window.e;
7037	  e = e.touches && e.touches.length ? e.touches : e.changedTouches && e.changedTouches.length ? e.changedTouches : [e];
7038
7039	  for (var key in e) {
7040		if (e[key].pageX) {
7041		  result.push({
7042			x: e[key].pageX,
7043			y: e[key].pageY
7044		  });
7045		} else if (e[key].clientX) {
7046		  result.push({
7047			x: e[key].clientX,
7048			y: e[key].clientY
7049		  });
7050		}
7051	  }
7052
7053	  return result;
7054	};
7055
7056	var distance = function (point2, point1, what) {
7057	  if (!point1 || !point2) {
7058		return 0;
7059	  }
7060
7061	  if (what === "x") {
7062		return point2.x - point1.x;
7063	  } else if (what === "y") {
7064		return point2.y - point1.y;
7065	  }
7066
7067	  return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
7068	};
7069
7070	var isClickable = function ($el) {
7071	  if (
7072		$el.is('a,area,button,[role="button"],input,label,select,summary,textarea,video,audio,iframe') ||
7073		$.isFunction($el.get(0).onclick) ||
7074		$el.data("selectable")
7075	  ) {
7076		return true;
7077	  }
7078
7079	  // Check for attributes like data-fancybox-next or data-fancybox-close
7080	  for (var i = 0, atts = $el[0].attributes, n = atts.length; i < n; i++) {
7081		if (atts[i].nodeName.substr(0, 14) === "data-fancybox-") {
7082		  return true;
7083		}
7084	  }
7085
7086	  return false;
7087	};
7088
7089	var hasScrollbars = function (el) {
7090	  var overflowY = window.getComputedStyle(el)["overflow-y"],
7091		overflowX = window.getComputedStyle(el)["overflow-x"],
7092		vertical = (overflowY === "scroll" || overflowY === "auto") && el.scrollHeight > el.clientHeight,
7093		horizontal = (overflowX === "scroll" || overflowX === "auto") && el.scrollWidth > el.clientWidth;
7094
7095	  return vertical || horizontal;
7096	};
7097
7098	var isScrollable = function ($el) {
7099	  var rez = false;
7100
7101	  while (true) {
7102		rez = hasScrollbars($el.get(0));
7103
7104		if (rez) {
7105		  break;
7106		}
7107
7108		$el = $el.parent();
7109
7110		if (!$el.length || $el.hasClass("fancybox-stage") || $el.is("body")) {
7111		  break;
7112		}
7113	  }
7114
7115	  return rez;
7116	};
7117
7118	var Guestures = function (instance) {
7119	  var self = this;
7120
7121	  self.instance = instance;
7122
7123	  self.$bg = instance.$refs.bg;
7124	  self.$stage = instance.$refs.stage;
7125	  self.$container = instance.$refs.container;
7126
7127	  self.destroy();
7128
7129	  self.$container.on("touchstart.fb.touch mousedown.fb.touch", $.proxy(self, "ontouchstart"));
7130	};
7131
7132	Guestures.prototype.destroy = function () {
7133	  var self = this;
7134
7135	  self.$container.off(".fb.touch");
7136
7137	  $(document).off(".fb.touch");
7138
7139	  if (self.requestId) {
7140		cancelAFrame(self.requestId);
7141		self.requestId = null;
7142	  }
7143
7144	  if (self.tapped) {
7145		clearTimeout(self.tapped);
7146		self.tapped = null;
7147	  }
7148	};
7149
7150	Guestures.prototype.ontouchstart = function (e) {
7151	  var self = this,
7152		$target = $(e.target),
7153		instance = self.instance,
7154		current = instance.current,
7155		$slide = current.$slide,
7156		$content = current.$content,
7157		isTouchDevice = e.type == "touchstart";
7158
7159	  // Do not respond to both (touch and mouse) events
7160	  if (isTouchDevice) {
7161		self.$container.off("mousedown.fb.touch");
7162	  }
7163
7164	  // Ignore right click
7165	  if (e.originalEvent && e.originalEvent.button == 2) {
7166		return;
7167	  }
7168
7169	  // Ignore taping on links, buttons, input elements
7170	  if (!$slide.length || !$target.length || isClickable($target) || isClickable($target.parent())) {
7171		return;
7172	  }
7173	  // Ignore clicks on the scrollbar
7174	  if (!$target.is("img") && e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left) {
7175		return;
7176	  }
7177
7178	  // Ignore clicks while zooming or closing
7179	  if (!current || instance.isAnimating || current.$slide.hasClass("fancybox-animated")) {
7180		e.stopPropagation();
7181		e.preventDefault();
7182
7183		return;
7184	  }
7185
7186	  self.realPoints = self.startPoints = getPointerXY(e);
7187
7188	  if (!self.startPoints.length) {
7189		return;
7190	  }
7191
7192	  // Allow other scripts to catch touch event if "touch" is set to false
7193	  if (current.touch) {
7194		e.stopPropagation();
7195	  }
7196
7197	  self.startEvent = e;
7198
7199	  self.canTap = true;
7200	  self.$target = $target;
7201	  self.$content = $content;
7202	  self.opts = current.opts.touch;
7203
7204	  self.isPanning = false;
7205	  self.isSwiping = false;
7206	  self.isZooming = false;
7207	  self.isScrolling = false;
7208	  self.canPan = instance.canPan();
7209
7210	  self.startTime = new Date().getTime();
7211	  self.distanceX = self.distanceY = self.distance = 0;
7212
7213	  self.canvasWidth = Math.round($slide[0].clientWidth);
7214	  self.canvasHeight = Math.round($slide[0].clientHeight);
7215
7216	  self.contentLastPos = null;
7217	  self.contentStartPos = $.fancybox.getTranslate(self.$content) || {
7218		top: 0,
7219		left: 0
7220	  };
7221	  self.sliderStartPos = $.fancybox.getTranslate($slide);
7222
7223	  // Since position will be absolute, but we need to make it relative to the stage
7224	  self.stagePos = $.fancybox.getTranslate(instance.$refs.stage);
7225
7226	  self.sliderStartPos.top -= self.stagePos.top;
7227	  self.sliderStartPos.left -= self.stagePos.left;
7228
7229	  self.contentStartPos.top -= self.stagePos.top;
7230	  self.contentStartPos.left -= self.stagePos.left;
7231
7232	  $(document)
7233		.off(".fb.touch")
7234		.on(isTouchDevice ? "touchend.fb.touch touchcancel.fb.touch" : "mouseup.fb.touch mouseleave.fb.touch", $.proxy(self, "ontouchend"))
7235		.on(isTouchDevice ? "touchmove.fb.touch" : "mousemove.fb.touch", $.proxy(self, "ontouchmove"));
7236
7237	  if ($.fancybox.isMobile) {
7238		document.addEventListener("scroll", self.onscroll, true);
7239	  }
7240
7241	  // Skip if clicked outside the sliding area
7242	  if (!(self.opts || self.canPan) || !($target.is(self.$stage) || self.$stage.find($target).length)) {
7243		if ($target.is(".fancybox-image")) {
7244		  e.preventDefault();
7245		}
7246
7247		if (!($.fancybox.isMobile && $target.parents(".fancybox-caption").length)) {
7248		  return;
7249		}
7250	  }
7251
7252	  self.isScrollable = isScrollable($target) || isScrollable($target.parent());
7253
7254	  // Check if element is scrollable and try to prevent default behavior (scrolling)
7255	  if (!($.fancybox.isMobile && self.isScrollable)) {
7256		e.preventDefault();
7257	  }
7258
7259	  // One finger or mouse click - swipe or pan an image
7260	  if (self.startPoints.length === 1 || current.hasError) {
7261		if (self.canPan) {
7262		  $.fancybox.stop(self.$content);
7263
7264		  self.isPanning = true;
7265		} else {
7266		  self.isSwiping = true;
7267		}
7268
7269		self.$container.addClass("fancybox-is-grabbing");
7270	  }
7271
7272	  // Two fingers - zoom image
7273	  if (self.startPoints.length === 2 && current.type === "image" && (current.isLoaded || current.$ghost)) {
7274		self.canTap = false;
7275		self.isSwiping = false;
7276		self.isPanning = false;
7277
7278		self.isZooming = true;
7279
7280		$.fancybox.stop(self.$content);
7281
7282		self.centerPointStartX = (self.startPoints[0].x + self.startPoints[1].x) * 0.5 - $(window).scrollLeft();
7283		self.centerPointStartY = (self.startPoints[0].y + self.startPoints[1].y) * 0.5 - $(window).scrollTop();
7284
7285		self.percentageOfImageAtPinchPointX = (self.centerPointStartX - self.contentStartPos.left) / self.contentStartPos.width;
7286		self.percentageOfImageAtPinchPointY = (self.centerPointStartY - self.contentStartPos.top) / self.contentStartPos.height;
7287
7288		self.startDistanceBetweenFingers = distance(self.startPoints[0], self.startPoints[1]);
7289	  }
7290	};
7291
7292	Guestures.prototype.onscroll = function (e) {
7293	  var self = this;
7294
7295	  self.isScrolling = true;
7296
7297	  document.removeEventListener("scroll", self.onscroll, true);
7298	};
7299
7300	Guestures.prototype.ontouchmove = function (e) {
7301	  var self = this;
7302
7303	  // Make sure user has not released over iframe or disabled element
7304	  if (e.originalEvent.buttons !== undefined && e.originalEvent.buttons === 0) {
7305		self.ontouchend(e);
7306		return;
7307	  }
7308
7309	  if (self.isScrolling) {
7310		self.canTap = false;
7311		return;
7312	  }
7313
7314	  self.newPoints = getPointerXY(e);
7315
7316	  if (!(self.opts || self.canPan) || !self.newPoints.length || !self.newPoints.length) {
7317		return;
7318	  }
7319
7320	  if (!(self.isSwiping && self.isSwiping === true)) {
7321		e.preventDefault();
7322	  }
7323
7324	  self.distanceX = distance(self.newPoints[0], self.startPoints[0], "x");
7325	  self.distanceY = distance(self.newPoints[0], self.startPoints[0], "y");
7326
7327	  self.distance = distance(self.newPoints[0], self.startPoints[0]);
7328
7329	  // Skip false ontouchmove events (Chrome)
7330	  if (self.distance > 0) {
7331		if (self.isSwiping) {
7332		  self.onSwipe(e);
7333		} else if (self.isPanning) {
7334		  self.onPan();
7335		} else if (self.isZooming) {
7336		  self.onZoom();
7337		}
7338	  }
7339	};
7340
7341	Guestures.prototype.onSwipe = function (e) {
7342	  var self = this,
7343		instance = self.instance,
7344		swiping = self.isSwiping,
7345		left = self.sliderStartPos.left || 0,
7346		angle;
7347
7348	  // If direction is not yet determined
7349	  if (swiping === true) {
7350		// We need at least 10px distance to correctly calculate an angle
7351		if (Math.abs(self.distance) > 10) {
7352		  self.canTap = false;
7353
7354		  if (instance.group.length < 2 && self.opts.vertical) {
7355			self.isSwiping = "y";
7356		  } else if (instance.isDragging || self.opts.vertical === false || (self.opts.vertical === "auto" && $(window).width() > 800)) {
7357			self.isSwiping = "x";
7358		  } else {
7359			angle = Math.abs((Math.atan2(self.distanceY, self.distanceX) * 180) / Math.PI);
7360
7361			self.isSwiping = angle > 45 && angle < 135 ? "y" : "x";
7362		  }
7363
7364		  if (self.isSwiping === "y" && $.fancybox.isMobile && self.isScrollable) {
7365			self.isScrolling = true;
7366
7367			return;
7368		  }
7369
7370		  instance.isDragging = self.isSwiping;
7371
7372		  // Reset points to avoid jumping, because we dropped first swipes to calculate the angle
7373		  self.startPoints = self.newPoints;
7374
7375		  $.each(instance.slides, function (index, slide) {
7376			var slidePos, stagePos;
7377
7378			$.fancybox.stop(slide.$slide);
7379
7380			slidePos = $.fancybox.getTranslate(slide.$slide);
7381			stagePos = $.fancybox.getTranslate(instance.$refs.stage);
7382
7383			slide.$slide
7384			  .css({
7385				transform: "",
7386				opacity: "",
7387				"transition-duration": ""
7388			  })
7389			  .removeClass("fancybox-animated")
7390			  .removeClass(function (index, className) {
7391				return (className.match(/(^|\s)fancybox-fx-\S+/g) || []).join(" ");
7392			  });
7393
7394			if (slide.pos === instance.current.pos) {
7395			  self.sliderStartPos.top = slidePos.top - stagePos.top;
7396			  self.sliderStartPos.left = slidePos.left - stagePos.left;
7397			}
7398
7399			$.fancybox.setTranslate(slide.$slide, {
7400			  top: slidePos.top - stagePos.top,
7401			  left: slidePos.left - stagePos.left
7402			});
7403		  });
7404
7405		  // Stop slideshow
7406		  if (instance.SlideShow && instance.SlideShow.isActive) {
7407			instance.SlideShow.stop();
7408		  }
7409		}
7410
7411		return;
7412	  }
7413
7414	  // Sticky edges
7415	  if (swiping == "x") {
7416		if (
7417		  self.distanceX > 0 &&
7418		  (self.instance.group.length < 2 || (self.instance.current.index === 0 && !self.instance.current.opts.loop))
7419		) {
7420		  left = left + Math.pow(self.distanceX, 0.8);
7421		} else if (
7422		  self.distanceX < 0 &&
7423		  (self.instance.group.length < 2 ||
7424			(self.instance.current.index === self.instance.group.length - 1 && !self.instance.current.opts.loop))
7425		) {
7426		  left = left - Math.pow(-self.distanceX, 0.8);
7427		} else {
7428		  left = left + self.distanceX;
7429		}
7430	  }
7431
7432	  self.sliderLastPos = {
7433		top: swiping == "x" ? 0 : self.sliderStartPos.top + self.distanceY,
7434		left: left
7435	  };
7436
7437	  if (self.requestId) {
7438		cancelAFrame(self.requestId);
7439
7440		self.requestId = null;
7441	  }
7442
7443	  self.requestId = requestAFrame(function () {
7444		if (self.sliderLastPos) {
7445		  $.each(self.instance.slides, function (index, slide) {
7446			var pos = slide.pos - self.instance.currPos;
7447
7448			$.fancybox.setTranslate(slide.$slide, {
7449			  top: self.sliderLastPos.top,
7450			  left: self.sliderLastPos.left + pos * self.canvasWidth + pos * slide.opts.gutter
7451			});
7452		  });
7453
7454		  self.$container.addClass("fancybox-is-sliding");
7455		}
7456	  });
7457	};
7458
7459	Guestures.prototype.onPan = function () {
7460	  var self = this;
7461
7462	  // Prevent accidental movement (sometimes, when tapping casually, finger can move a bit)
7463	  if (distance(self.newPoints[0], self.realPoints[0]) < ($.fancybox.isMobile ? 10 : 5)) {
7464		self.startPoints = self.newPoints;
7465		return;
7466	  }
7467
7468	  self.canTap = false;
7469
7470	  self.contentLastPos = self.limitMovement();
7471
7472	  if (self.requestId) {
7473		cancelAFrame(self.requestId);
7474	  }
7475
7476	  self.requestId = requestAFrame(function () {
7477		$.fancybox.setTranslate(self.$content, self.contentLastPos);
7478	  });
7479	};
7480
7481	// Make panning sticky to the edges
7482	Guestures.prototype.limitMovement = function () {
7483	  var self = this;
7484
7485	  var canvasWidth = self.canvasWidth;
7486	  var canvasHeight = self.canvasHeight;
7487
7488	  var distanceX = self.distanceX;
7489	  var distanceY = self.distanceY;
7490
7491	  var contentStartPos = self.contentStartPos;
7492
7493	  var currentOffsetX = contentStartPos.left;
7494	  var currentOffsetY = contentStartPos.top;
7495
7496	  var currentWidth = contentStartPos.width;
7497	  var currentHeight = contentStartPos.height;
7498
7499	  var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY, newOffsetX, newOffsetY;
7500
7501	  if (currentWidth > canvasWidth) {
7502		newOffsetX = currentOffsetX + distanceX;
7503	  } else {
7504		newOffsetX = currentOffsetX;
7505	  }
7506
7507	  newOffsetY = currentOffsetY + distanceY;
7508
7509	  // Slow down proportionally to traveled distance
7510	  minTranslateX = Math.max(0, canvasWidth * 0.5 - currentWidth * 0.5);
7511	  minTranslateY = Math.max(0, canvasHeight * 0.5 - currentHeight * 0.5);
7512
7513	  maxTranslateX = Math.min(canvasWidth - currentWidth, canvasWidth * 0.5 - currentWidth * 0.5);
7514	  maxTranslateY = Math.min(canvasHeight - currentHeight, canvasHeight * 0.5 - currentHeight * 0.5);
7515
7516	  //   ->
7517	  if (distanceX > 0 && newOffsetX > minTranslateX) {
7518		newOffsetX = minTranslateX - 1 + Math.pow(-minTranslateX + currentOffsetX + distanceX, 0.8) || 0;
7519	  }
7520
7521	  //    <-
7522	  if (distanceX < 0 && newOffsetX < maxTranslateX) {
7523		newOffsetX = maxTranslateX + 1 - Math.pow(maxTranslateX - currentOffsetX - distanceX, 0.8) || 0;
7524	  }
7525
7526	  //   \/
7527	  if (distanceY > 0 && newOffsetY > minTranslateY) {
7528		newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8) || 0;
7529	  }
7530
7531	  //   /\
7532	  if (distanceY < 0 && newOffsetY < maxTranslateY) {
7533		newOffsetY = maxTranslateY + 1 - Math.pow(maxTranslateY - currentOffsetY - distanceY, 0.8) || 0;
7534	  }
7535
7536	  return {
7537		top: newOffsetY,
7538		left: newOffsetX
7539	  };
7540	};
7541
7542	Guestures.prototype.limitPosition = function (newOffsetX, newOffsetY, newWidth, newHeight) {
7543	  var self = this;
7544
7545	  var canvasWidth = self.canvasWidth;
7546	  var canvasHeight = self.canvasHeight;
7547
7548	  if (newWidth > canvasWidth) {
7549		newOffsetX = newOffsetX > 0 ? 0 : newOffsetX;
7550		newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX;
7551	  } else {
7552		// Center horizontally
7553		newOffsetX = Math.max(0, canvasWidth / 2 - newWidth / 2);
7554	  }
7555
7556	  if (newHeight > canvasHeight) {
7557		newOffsetY = newOffsetY > 0 ? 0 : newOffsetY;
7558		newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY;
7559	  } else {
7560		// Center vertically
7561		newOffsetY = Math.max(0, canvasHeight / 2 - newHeight / 2);
7562	  }
7563
7564	  return {
7565		top: newOffsetY,
7566		left: newOffsetX
7567	  };
7568	};
7569
7570	Guestures.prototype.onZoom = function () {
7571	  var self = this;
7572
7573	  // Calculate current distance between points to get pinch ratio and new width and height
7574	  var contentStartPos = self.contentStartPos;
7575
7576	  var currentWidth = contentStartPos.width;
7577	  var currentHeight = contentStartPos.height;
7578
7579	  var currentOffsetX = contentStartPos.left;
7580	  var currentOffsetY = contentStartPos.top;
7581
7582	  var endDistanceBetweenFingers = distance(self.newPoints[0], self.newPoints[1]);
7583
7584	  var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers;
7585
7586	  var newWidth = Math.floor(currentWidth * pinchRatio);
7587	  var newHeight = Math.floor(currentHeight * pinchRatio);
7588
7589	  // This is the translation due to pinch-zooming
7590	  var translateFromZoomingX = (currentWidth - newWidth) * self.percentageOfImageAtPinchPointX;
7591	  var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY;
7592
7593	  // Point between the two touches
7594	  var centerPointEndX = (self.newPoints[0].x + self.newPoints[1].x) / 2 - $(window).scrollLeft();
7595	  var centerPointEndY = (self.newPoints[0].y + self.newPoints[1].y) / 2 - $(window).scrollTop();
7596
7597	  // And this is the translation due to translation of the centerpoint
7598	  // between the two fingers
7599	  var translateFromTranslatingX = centerPointEndX - self.centerPointStartX;
7600	  var translateFromTranslatingY = centerPointEndY - self.centerPointStartY;
7601
7602	  // The new offset is the old/current one plus the total translation
7603	  var newOffsetX = currentOffsetX + (translateFromZoomingX + translateFromTranslatingX);
7604	  var newOffsetY = currentOffsetY + (translateFromZoomingY + translateFromTranslatingY);
7605
7606	  var newPos = {
7607		top: newOffsetY,
7608		left: newOffsetX,
7609		scaleX: pinchRatio,
7610		scaleY: pinchRatio
7611	  };
7612
7613	  self.canTap = false;
7614
7615	  self.newWidth = newWidth;
7616	  self.newHeight = newHeight;
7617
7618	  self.contentLastPos = newPos;
7619
7620	  if (self.requestId) {
7621		cancelAFrame(self.requestId);
7622	  }
7623
7624	  self.requestId = requestAFrame(function () {
7625		$.fancybox.setTranslate(self.$content, self.contentLastPos);
7626	  });
7627	};
7628
7629	Guestures.prototype.ontouchend = function (e) {
7630	  var self = this;
7631
7632	  var swiping = self.isSwiping;
7633	  var panning = self.isPanning;
7634	  var zooming = self.isZooming;
7635	  var scrolling = self.isScrolling;
7636
7637	  self.endPoints = getPointerXY(e);
7638	  self.dMs = Math.max(new Date().getTime() - self.startTime, 1);
7639
7640	  self.$container.removeClass("fancybox-is-grabbing");
7641
7642	  $(document).off(".fb.touch");
7643
7644	  document.removeEventListener("scroll", self.onscroll, true);
7645
7646	  if (self.requestId) {
7647		cancelAFrame(self.requestId);
7648
7649		self.requestId = null;
7650	  }
7651
7652	  self.isSwiping = false;
7653	  self.isPanning = false;
7654	  self.isZooming = false;
7655	  self.isScrolling = false;
7656
7657	  self.instance.isDragging = false;
7658
7659	  if (self.canTap) {
7660		return self.onTap(e);
7661	  }
7662
7663	  self.speed = 100;
7664
7665	  // Speed in px/ms
7666	  self.velocityX = (self.distanceX / self.dMs) * 0.5;
7667	  self.velocityY = (self.distanceY / self.dMs) * 0.5;
7668
7669	  if (panning) {
7670		self.endPanning();
7671	  } else if (zooming) {
7672		self.endZooming();
7673	  } else {
7674		self.endSwiping(swiping, scrolling);
7675	  }
7676
7677	  return;
7678	};
7679
7680	Guestures.prototype.endSwiping = function (swiping, scrolling) {
7681	  var self = this,
7682		ret = false,
7683		len = self.instance.group.length,
7684		distanceX = Math.abs(self.distanceX),
7685		canAdvance = swiping == "x" && len > 1 && ((self.dMs > 130 && distanceX > 10) || distanceX > 50),
7686		speedX = 300;
7687
7688	  self.sliderLastPos = null;
7689
7690	  // Close if swiped vertically / navigate if horizontally
7691	  if (swiping == "y" && !scrolling && Math.abs(self.distanceY) > 50) {
7692		// Continue vertical movement
7693		$.fancybox.animate(
7694		  self.instance.current.$slide, {
7695			top: self.sliderStartPos.top + self.distanceY + self.velocityY * 150,
7696			opacity: 0
7697		  },
7698		  200
7699		);
7700		ret = self.instance.close(true, 250);
7701	  } else if (canAdvance && self.distanceX > 0) {
7702		ret = self.instance.previous(speedX);
7703	  } else if (canAdvance && self.distanceX < 0) {
7704		ret = self.instance.next(speedX);
7705	  }
7706
7707	  if (ret === false && (swiping == "x" || swiping == "y")) {
7708		self.instance.centerSlide(200);
7709	  }
7710
7711	  self.$container.removeClass("fancybox-is-sliding");
7712	};
7713
7714	// Limit panning from edges
7715	// ========================
7716	Guestures.prototype.endPanning = function () {
7717	  var self = this,
7718		newOffsetX,
7719		newOffsetY,
7720		newPos;
7721
7722	  if (!self.contentLastPos) {
7723		return;
7724	  }
7725
7726	  if (self.opts.momentum === false || self.dMs > 350) {
7727		newOffsetX = self.contentLastPos.left;
7728		newOffsetY = self.contentLastPos.top;
7729	  } else {
7730		// Continue movement
7731		newOffsetX = self.contentLastPos.left + self.velocityX * 500;
7732		newOffsetY = self.contentLastPos.top + self.velocityY * 500;
7733	  }
7734
7735	  newPos = self.limitPosition(newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height);
7736
7737	  newPos.width = self.contentStartPos.width;
7738	  newPos.height = self.contentStartPos.height;
7739
7740	  $.fancybox.animate(self.$content, newPos, 366);
7741	};
7742
7743	Guestures.prototype.endZooming = function () {
7744	  var self = this;
7745
7746	  var current = self.instance.current;
7747
7748	  var newOffsetX, newOffsetY, newPos, reset;
7749
7750	  var newWidth = self.newWidth;
7751	  var newHeight = self.newHeight;
7752
7753	  if (!self.contentLastPos) {
7754		return;
7755	  }
7756
7757	  newOffsetX = self.contentLastPos.left;
7758	  newOffsetY = self.contentLastPos.top;
7759
7760	  reset = {
7761		top: newOffsetY,
7762		left: newOffsetX,
7763		width: newWidth,
7764		height: newHeight,
7765		scaleX: 1,
7766		scaleY: 1
7767	  };
7768
7769	  // Reset scalex/scaleY values; this helps for perfomance and does not break animation
7770	  $.fancybox.setTranslate(self.$content, reset);
7771
7772	  if (newWidth < self.canvasWidth && newHeight < self.canvasHeight) {
7773		self.instance.scaleToFit(150);
7774	  } else if (newWidth > current.width || newHeight > current.height) {
7775		self.instance.scaleToActual(self.centerPointStartX, self.centerPointStartY, 150);
7776	  } else {
7777		newPos = self.limitPosition(newOffsetX, newOffsetY, newWidth, newHeight);
7778
7779		$.fancybox.animate(self.$content, newPos, 150);
7780	  }
7781	};
7782
7783	Guestures.prototype.onTap = function (e) {
7784	  var self = this;
7785	  var $target = $(e.target);
7786
7787	  var instance = self.instance;
7788	  var current = instance.current;
7789
7790	  var endPoints = (e && getPointerXY(e)) || self.startPoints;
7791
7792	  var tapX = endPoints[0] ? endPoints[0].x - $(window).scrollLeft() - self.stagePos.left : 0;
7793	  var tapY = endPoints[0] ? endPoints[0].y - $(window).scrollTop() - self.stagePos.top : 0;
7794
7795	  var where;
7796
7797	  var process = function (prefix) {
7798		var action = current.opts[prefix];
7799
7800		if ($.isFunction(action)) {
7801		  action = action.apply(instance, [current, e]);
7802		}
7803
7804		if (!action) {
7805		  return;
7806		}
7807
7808		switch (action) {
7809		  case "close":
7810			instance.close(self.startEvent);
7811
7812			break;
7813
7814		  case "toggleControls":
7815			instance.toggleControls();
7816
7817			break;
7818
7819		  case "next":
7820			instance.next();
7821
7822			break;
7823
7824		  case "nextOrClose":
7825			if (instance.group.length > 1) {
7826			  instance.next();
7827			} else {
7828			  instance.close(self.startEvent);
7829			}
7830
7831			break;
7832
7833		  case "zoom":
7834			if (current.type == "image" && (current.isLoaded || current.$ghost)) {
7835			  if (instance.canPan()) {
7836				instance.scaleToFit();
7837			  } else if (instance.isScaledDown()) {
7838				instance.scaleToActual(tapX, tapY);
7839			  } else if (instance.group.length < 2) {
7840				instance.close(self.startEvent);
7841			  }
7842			}
7843
7844			break;
7845		}
7846	  };
7847
7848	  // Ignore right click
7849	  if (e.originalEvent && e.originalEvent.button == 2) {
7850		return;
7851	  }
7852
7853	  // Skip if clicked on the scrollbar
7854	  if (!$target.is("img") && tapX > $target[0].clientWidth + $target.offset().left) {
7855		return;
7856	  }
7857
7858	  // Check where is clicked
7859	  if ($target.is(".fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container")) {
7860		where = "Outside";
7861	  } else if ($target.is(".fancybox-slide")) {
7862		where = "Slide";
7863	  } else if (
7864		instance.current.$content &&
7865		instance.current.$content
7866		.find($target)
7867		.addBack()
7868		.filter($target).length
7869	  ) {
7870		where = "Content";
7871	  } else {
7872		return;
7873	  }
7874
7875	  // Check if this is a double tap
7876	  if (self.tapped) {
7877		// Stop previously created single tap
7878		clearTimeout(self.tapped);
7879		self.tapped = null;
7880
7881		// Skip if distance between taps is too big
7882		if (Math.abs(tapX - self.tapX) > 50 || Math.abs(tapY - self.tapY) > 50) {
7883		  return this;
7884		}
7885
7886		// OK, now we assume that this is a double-tap
7887		process("dblclick" + where);
7888	  } else {
7889		// Single tap will be processed if user has not clicked second time within 300ms
7890		// or there is no need to wait for double-tap
7891		self.tapX = tapX;
7892		self.tapY = tapY;
7893
7894		if (current.opts["dblclick" + where] && current.opts["dblclick" + where] !== current.opts["click" + where]) {
7895		  self.tapped = setTimeout(function () {
7896			self.tapped = null;
7897
7898			if (!instance.isAnimating) {
7899			  process("click" + where);
7900			}
7901		  }, 500);
7902		} else {
7903		  process("click" + where);
7904		}
7905	  }
7906
7907	  return this;
7908	};
7909
7910	$(document)
7911	  .on("onActivate.fb", function (e, instance) {
7912		if (instance && !instance.Guestures) {
7913		  instance.Guestures = new Guestures(instance);
7914		}
7915	  })
7916	  .on("beforeClose.fb", function (e, instance) {
7917		if (instance && instance.Guestures) {
7918		  instance.Guestures.destroy();
7919		}
7920	  });
7921  })(window, document, jQuery);
7922  // ==========================================================================
7923  //
7924  // SlideShow
7925  // Enables slideshow functionality
7926  //
7927  // Example of usage:
7928  // $.fancybox.getInstance().SlideShow.start()
7929  //
7930  // ==========================================================================
7931  (function (document, $) {
7932	"use strict";
7933
7934	$.extend(true, $.fancybox.defaults, {
7935	  btnTpl: {
7936		slideShow: '<button data-fancybox-play class="fancybox-button fancybox-button--play" title="{{PLAY_START}}">' +
7937		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.5 5.4v13.2l11-6.6z"/></svg>' +
7938		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.33 5.75h2.2v12.5h-2.2V5.75zm5.15 0h2.2v12.5h-2.2V5.75z"/></svg>' +
7939		  "</button>"
7940	  },
7941	  slideShow: {
7942		autoStart: false,
7943		speed: 3000,
7944		progress: true
7945	  }
7946	});
7947
7948	var SlideShow = function (instance) {
7949	  this.instance = instance;
7950	  this.init();
7951	};
7952
7953	$.extend(SlideShow.prototype, {
7954	  timer: null,
7955	  isActive: false,
7956	  $button: null,
7957
7958	  init: function () {
7959		var self = this,
7960		  instance = self.instance,
7961		  opts = instance.group[instance.currIndex].opts.slideShow;
7962
7963		self.$button = instance.$refs.toolbar.find("[data-fancybox-play]").on("click", function () {
7964		  self.toggle();
7965		});
7966
7967		if (instance.group.length < 2 || !opts) {
7968		  self.$button.hide();
7969		} else if (opts.progress) {
7970		  self.$progress = $('<div class="fancybox-progress"></div>').appendTo(instance.$refs.inner);
7971		}
7972	  },
7973
7974	  set: function (force) {
7975		var self = this,
7976		  instance = self.instance,
7977		  current = instance.current;
7978
7979		// Check if reached last element
7980		if (current && (force === true || current.opts.loop || instance.currIndex < instance.group.length - 1)) {
7981		  if (self.isActive && current.contentType !== "video") {
7982			if (self.$progress) {
7983			  $.fancybox.animate(self.$progress.show(), {
7984				scaleX: 1
7985			  }, current.opts.slideShow.speed);
7986			}
7987
7988			self.timer = setTimeout(function () {
7989			  if (!instance.current.opts.loop && instance.current.index == instance.group.length - 1) {
7990				instance.jumpTo(0);
7991			  } else {
7992				instance.next();
7993			  }
7994			}, current.opts.slideShow.speed);
7995		  }
7996		} else {
7997		  self.stop();
7998		  instance.idleSecondsCounter = 0;
7999		  instance.showControls();
8000		}
8001	  },
8002
8003	  clear: function () {
8004		var self = this;
8005
8006		clearTimeout(self.timer);
8007
8008		self.timer = null;
8009
8010		if (self.$progress) {
8011		  self.$progress.removeAttr("style").hide();
8012		}
8013	  },
8014
8015	  start: function () {
8016		var self = this,
8017		  current = self.instance.current;
8018
8019		if (current) {
8020		  self.$button
8021			.attr("title", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_STOP)
8022			.removeClass("fancybox-button--play")
8023			.addClass("fancybox-button--pause");
8024
8025		  self.isActive = true;
8026
8027		  if (current.isComplete) {
8028			self.set(true);
8029		  }
8030
8031		  self.instance.trigger("onSlideShowChange", true);
8032		}
8033	  },
8034
8035	  stop: function () {
8036		var self = this,
8037		  current = self.instance.current;
8038
8039		self.clear();
8040
8041		self.$button
8042		  .attr("title", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_START)
8043		  .removeClass("fancybox-button--pause")
8044		  .addClass("fancybox-button--play");
8045
8046		self.isActive = false;
8047
8048		self.instance.trigger("onSlideShowChange", false);
8049
8050		if (self.$progress) {
8051		  self.$progress.removeAttr("style").hide();
8052		}
8053	  },
8054
8055	  toggle: function () {
8056		var self = this;
8057
8058		if (self.isActive) {
8059		  self.stop();
8060		} else {
8061		  self.start();
8062		}
8063	  }
8064	});
8065
8066	$(document).on({
8067	  "onInit.fb": function (e, instance) {
8068		if (instance && !instance.SlideShow) {
8069		  instance.SlideShow = new SlideShow(instance);
8070		}
8071	  },
8072
8073	  "beforeShow.fb": function (e, instance, current, firstRun) {
8074		var SlideShow = instance && instance.SlideShow;
8075
8076		if (firstRun) {
8077		  if (SlideShow && current.opts.slideShow.autoStart) {
8078			SlideShow.start();
8079		  }
8080		} else if (SlideShow && SlideShow.isActive) {
8081		  SlideShow.clear();
8082		}
8083	  },
8084
8085	  "afterShow.fb": function (e, instance, current) {
8086		var SlideShow = instance && instance.SlideShow;
8087
8088		if (SlideShow && SlideShow.isActive) {
8089		  SlideShow.set();
8090		}
8091	  },
8092
8093	  "afterKeydown.fb": function (e, instance, current, keypress, keycode) {
8094		var SlideShow = instance && instance.SlideShow;
8095
8096		// "P" or Spacebar
8097		if (SlideShow && current.opts.slideShow && (keycode === 80 || keycode === 32) && !$(document.activeElement).is("button,a,input")) {
8098		  keypress.preventDefault();
8099
8100		  SlideShow.toggle();
8101		}
8102	  },
8103
8104	  "beforeClose.fb onDeactivate.fb": function (e, instance) {
8105		var SlideShow = instance && instance.SlideShow;
8106
8107		if (SlideShow) {
8108		  SlideShow.stop();
8109		}
8110	  }
8111	});
8112
8113	// Page Visibility API to pause slideshow when window is not active
8114	$(document).on("visibilitychange", function () {
8115	  if ( $.fancybox.version != '3.5.7' ) {
8116		  return;
8117	  }
8118
8119	  var instance = $.fancybox.getInstance(),
8120		SlideShow = instance && instance.SlideShow;
8121
8122	  if (SlideShow && SlideShow.isActive) {
8123		if (document.hidden) {
8124		  SlideShow.clear();
8125		} else {
8126		  SlideShow.set();
8127		}
8128	  }
8129	});
8130  })(document, jQuery);
8131  // ==========================================================================
8132  //
8133  // FullScreen
8134  // Adds fullscreen functionality
8135  //
8136  // ==========================================================================
8137  (function (document, $) {
8138	"use strict";
8139
8140	// Collection of methods supported by user browser
8141	var fn = (function () {
8142	  var fnMap = [
8143		["requestFullscreen", "exitFullscreen", "fullscreenElement", "fullscreenEnabled", "fullscreenchange", "fullscreenerror"],
8144		// new WebKit
8145		[
8146		  "webkitRequestFullscreen",
8147		  "webkitExitFullscreen",
8148		  "webkitFullscreenElement",
8149		  "webkitFullscreenEnabled",
8150		  "webkitfullscreenchange",
8151		  "webkitfullscreenerror"
8152		],
8153		// old WebKit (Safari 5.1)
8154		[
8155		  "webkitRequestFullScreen",
8156		  "webkitCancelFullScreen",
8157		  "webkitCurrentFullScreenElement",
8158		  "webkitCancelFullScreen",
8159		  "webkitfullscreenchange",
8160		  "webkitfullscreenerror"
8161		],
8162		[
8163		  "mozRequestFullScreen",
8164		  "mozCancelFullScreen",
8165		  "mozFullScreenElement",
8166		  "mozFullScreenEnabled",
8167		  "mozfullscreenchange",
8168		  "mozfullscreenerror"
8169		],
8170		["msRequestFullscreen", "msExitFullscreen", "msFullscreenElement", "msFullscreenEnabled", "MSFullscreenChange", "MSFullscreenError"]
8171	  ];
8172
8173	  var ret = {};
8174
8175	  for (var i = 0; i < fnMap.length; i++) {
8176		var val = fnMap[i];
8177
8178		if (val && val[1] in document) {
8179		  for (var j = 0; j < val.length; j++) {
8180			ret[fnMap[0][j]] = val[j];
8181		  }
8182
8183		  return ret;
8184		}
8185	  }
8186
8187	  return false;
8188	})();
8189
8190	if (fn) {
8191	  var FullScreen = {
8192		request: function (elem) {
8193		  elem = elem || document.documentElement;
8194
8195		  elem[fn.requestFullscreen](elem.ALLOW_KEYBOARD_INPUT);
8196		},
8197		exit: function () {
8198		  document[fn.exitFullscreen]();
8199		},
8200		toggle: function (elem) {
8201		  elem = elem || document.documentElement;
8202
8203		  if (this.isFullscreen()) {
8204			this.exit();
8205		  } else {
8206			this.request(elem);
8207		  }
8208		},
8209		isFullscreen: function () {
8210		  return Boolean(document[fn.fullscreenElement]);
8211		},
8212		enabled: function () {
8213		  return Boolean(document[fn.fullscreenEnabled]);
8214		}
8215	  };
8216
8217	  $.extend(true, $.fancybox.defaults, {
8218		btnTpl: {
8219		  fullScreen: '<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fsenter" title="{{FULL_SCREEN}}">' +
8220			'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>' +
8221			'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 16h3v3h2v-5H5zm3-8H5v2h5V5H8zm6 11h2v-3h3v-2h-5zm2-11V5h-2v5h5V8z"/></svg>' +
8222			"</button>"
8223		},
8224		fullScreen: {
8225		  autoStart: false
8226		}
8227	  });
8228
8229	  $(document).on(fn.fullscreenchange, function () {
8230		var isFullscreen = FullScreen.isFullscreen(),
8231		  instance = $.fancybox.getInstance();
8232
8233		if (instance) {
8234		  // If image is zooming, then force to stop and reposition properly
8235		  if (instance.current && instance.current.type === "image" && instance.isAnimating) {
8236			instance.isAnimating = false;
8237
8238			instance.update(true, true, 0);
8239
8240			if (!instance.isComplete) {
8241			  instance.complete();
8242			}
8243		  }
8244
8245		  instance.trigger("onFullscreenChange", isFullscreen);
8246
8247		  instance.$refs.container.toggleClass("fancybox-is-fullscreen", isFullscreen);
8248
8249		  instance.$refs.toolbar
8250			.find("[data-fancybox-fullscreen]")
8251			.toggleClass("fancybox-button--fsenter", !isFullscreen)
8252			.toggleClass("fancybox-button--fsexit", isFullscreen);
8253		}
8254	  });
8255	}
8256
8257	$(document).on({
8258	  "onInit.fb": function (e, instance) {
8259		var $container;
8260
8261		if (!fn) {
8262		  instance.$refs.toolbar.find("[data-fancybox-fullscreen]").remove();
8263
8264		  return;
8265		}
8266
8267		if (instance && instance.group[instance.currIndex].opts.fullScreen) {
8268		  $container = instance.$refs.container;
8269
8270		  $container.on("click.fb-fullscreen", "[data-fancybox-fullscreen]", function (e) {
8271			e.stopPropagation();
8272			e.preventDefault();
8273
8274			FullScreen.toggle();
8275		  });
8276
8277		  if (instance.opts.fullScreen && instance.opts.fullScreen.autoStart === true) {
8278			FullScreen.request();
8279		  }
8280
8281		  // Expose API
8282		  instance.FullScreen = FullScreen;
8283		} else if (instance) {
8284		  instance.$refs.toolbar.find("[data-fancybox-fullscreen]").hide();
8285		}
8286	  },
8287
8288	  "afterKeydown.fb": function (e, instance, current, keypress, keycode) {
8289		// "F"
8290		if (instance && instance.FullScreen && keycode === 70) {
8291		  keypress.preventDefault();
8292
8293		  instance.FullScreen.toggle();
8294		}
8295	  },
8296
8297	  "beforeClose.fb": function (e, instance) {
8298		if (instance && instance.FullScreen && instance.$refs.container.hasClass("fancybox-is-fullscreen")) {
8299		  FullScreen.exit();
8300		}
8301	  }
8302	});
8303  })(document, jQuery);
8304  // ==========================================================================
8305  //
8306  // Thumbs
8307  // Displays thumbnails in a grid
8308  //
8309  // ==========================================================================
8310  (function (document, $) {
8311	"use strict";
8312
8313	var CLASS = "fancybox-thumbs",
8314	  CLASS_ACTIVE = CLASS + "-active";
8315
8316	// Make sure there are default values
8317	$.fancybox.defaults = $.extend(
8318	  true, {
8319		btnTpl: {
8320		  thumbs: '<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="{{THUMBS}}">' +
8321			'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14.59 14.59h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76H5.65v-3.76zm8.94-4.47h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76H5.65v-3.76zm8.94-4.47h3.76v3.76h-3.76V5.65zm-4.47 0h3.76v3.76h-3.76V5.65zm-4.47 0h3.76v3.76H5.65V5.65z"/></svg>' +
8322			"</button>"
8323		},
8324		thumbs: {
8325		  autoStart: false, // Display thumbnails on opening
8326		  hideOnClose: true, // Hide thumbnail grid when closing animation starts
8327		  parentEl: ".fancybox-container", // Container is injected into this element
8328		  axis: "y" // Vertical (y) or horizontal (x) scrolling
8329		}
8330	  },
8331	  $.fancybox.defaults
8332	);
8333
8334	var FancyThumbs = function (instance) {
8335	  this.init(instance);
8336	};
8337
8338	$.extend(FancyThumbs.prototype, {
8339	  $button: null,
8340	  $grid: null,
8341	  $list: null,
8342	  isVisible: false,
8343	  isActive: false,
8344
8345	  init: function (instance) {
8346		var self = this,
8347		  group = instance.group,
8348		  enabled = 0;
8349
8350		self.instance = instance;
8351		self.opts = group[instance.currIndex].opts.thumbs;
8352
8353		instance.Thumbs = self;
8354
8355		self.$button = instance.$refs.toolbar.find("[data-fancybox-thumbs]");
8356
8357		// Enable thumbs if at least two group items have thumbnails
8358		for (var i = 0, len = group.length; i < len; i++) {
8359		  if (group[i].thumb) {
8360			enabled++;
8361		  }
8362
8363		  if (enabled > 1) {
8364			break;
8365		  }
8366		}
8367
8368		if (enabled > 1 && !!self.opts) {
8369		  self.$button.removeAttr("style").on("click", function () {
8370			self.toggle();
8371		  });
8372
8373		  self.isActive = true;
8374		} else {
8375		  self.$button.hide();
8376		}
8377	  },
8378
8379	  create: function () {
8380		var self = this,
8381		  instance = self.instance,
8382		  parentEl = self.opts.parentEl,
8383		  list = [],
8384		  src;
8385
8386		if (!self.$grid) {
8387		  // Create main element
8388		  self.$grid = $('<div class="' + CLASS + " " + CLASS + "-" + self.opts.axis + '"></div>').appendTo(
8389			instance.$refs.container
8390			.find(parentEl)
8391			.addBack()
8392			.filter(parentEl)
8393		  );
8394
8395		  // Add "click" event that performs gallery navigation
8396		  self.$grid.on("click", "a", function () {
8397			instance.jumpTo($(this).attr("data-index"));
8398		  });
8399		}
8400
8401		// Build the list
8402		if (!self.$list) {
8403		  self.$list = $('<div class="' + CLASS + '__list">').appendTo(self.$grid);
8404		}
8405
8406		$.each(instance.group, function (i, item) {
8407		  src = item.thumb;
8408
8409		  if (!src && item.type === "image") {
8410			src = item.src;
8411		  }
8412
8413		  list.push(
8414			'<a href="javascript:;" tabindex="0" data-index="' +
8415			i +
8416			'"' +
8417			(src && src.length ? ' style="background-image:url(' + src + ')"' : 'class="fancybox-thumbs-missing"') +
8418			"></a>"
8419		  );
8420		});
8421
8422		self.$list[0].innerHTML = list.join("");
8423
8424		if (self.opts.axis === "x") {
8425		  // Set fixed width for list element to enable horizontal scrolling
8426		  self.$list.width(
8427			parseInt(self.$grid.css("padding-right"), 10) +
8428			instance.group.length *
8429			self.$list
8430			.children()
8431			.eq(0)
8432			.outerWidth(true)
8433		  );
8434		}
8435	  },
8436
8437	  focus: function (duration) {
8438		var self = this,
8439		  $list = self.$list,
8440		  $grid = self.$grid,
8441		  thumb,
8442		  thumbPos;
8443
8444		if (!self.instance.current) {
8445		  return;
8446		}
8447
8448		thumb = $list
8449		  .children()
8450		  .removeClass(CLASS_ACTIVE)
8451		  .filter('[data-index="' + self.instance.current.index + '"]')
8452		  .addClass(CLASS_ACTIVE);
8453
8454		thumbPos = thumb.position();
8455
8456		// Check if need to scroll to make current thumb visible
8457		if (self.opts.axis === "y" && (thumbPos.top < 0 || thumbPos.top > $list.height() - thumb.outerHeight())) {
8458		  $list.stop().animate({
8459			  scrollTop: $list.scrollTop() + thumbPos.top
8460			},
8461			duration
8462		  );
8463		} else if (
8464		  self.opts.axis === "x" &&
8465		  (thumbPos.left < $grid.scrollLeft() || thumbPos.left > $grid.scrollLeft() + ($grid.width() - thumb.outerWidth()))
8466		) {
8467		  $list
8468			.parent()
8469			.stop()
8470			.animate({
8471				scrollLeft: thumbPos.left
8472			  },
8473			  duration
8474			);
8475		}
8476	  },
8477
8478	  update: function () {
8479		var that = this;
8480		that.instance.$refs.container.toggleClass("fancybox-show-thumbs", this.isVisible);
8481
8482		if (that.isVisible) {
8483		  if (!that.$grid) {
8484			that.create();
8485		  }
8486
8487		  that.instance.trigger("onThumbsShow");
8488
8489		  that.focus(0);
8490		} else if (that.$grid) {
8491		  that.instance.trigger("onThumbsHide");
8492		}
8493
8494		// Update content position
8495		that.instance.update();
8496	  },
8497
8498	  hide: function () {
8499		this.isVisible = false;
8500		this.update();
8501	  },
8502
8503	  show: function () {
8504		this.isVisible = true;
8505		this.update();
8506	  },
8507
8508	  toggle: function () {
8509		this.isVisible = !this.isVisible;
8510		this.update();
8511	  }
8512	});
8513
8514	$(document).on({
8515	  "onInit.fb": function (e, instance) {
8516		var Thumbs;
8517
8518		if (instance && !instance.Thumbs) {
8519		  Thumbs = new FancyThumbs(instance);
8520
8521		  if (Thumbs.isActive && Thumbs.opts.autoStart === true) {
8522			Thumbs.show();
8523		  }
8524		}
8525	  },
8526
8527	  "beforeShow.fb": function (e, instance, item, firstRun) {
8528		var Thumbs = instance && instance.Thumbs;
8529
8530		if (Thumbs && Thumbs.isVisible) {
8531		  Thumbs.focus(firstRun ? 0 : 250);
8532		}
8533	  },
8534
8535	  "afterKeydown.fb": function (e, instance, current, keypress, keycode) {
8536		var Thumbs = instance && instance.Thumbs;
8537
8538		// "G"
8539		if (Thumbs && Thumbs.isActive && keycode === 71) {
8540		  keypress.preventDefault();
8541
8542		  Thumbs.toggle();
8543		}
8544	  },
8545
8546	  "beforeClose.fb": function (e, instance) {
8547		var Thumbs = instance && instance.Thumbs;
8548
8549		if (Thumbs && Thumbs.isVisible && Thumbs.opts.hideOnClose !== false) {
8550		  Thumbs.$grid.hide();
8551		}
8552	  }
8553	});
8554  })(document, jQuery);
8555  //// ==========================================================================
8556  //
8557  // Share
8558  // Displays simple form for sharing current url
8559  //
8560  // ==========================================================================
8561  (function (document, $) {
8562	"use strict";
8563
8564	$.extend(true, $.fancybox.defaults, {
8565	  btnTpl: {
8566		share: '<button data-fancybox-share class="fancybox-button fancybox-button--share" title="{{SHARE}}">' +
8567		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M2.55 19c1.4-8.4 9.1-9.8 11.9-9.8V5l7 7-7 6.3v-3.5c-2.8 0-10.5 2.1-11.9 4.2z"/></svg>' +
8568		  "</button>"
8569	  },
8570	  share: {
8571		url: function (instance, item) {
8572		  return (
8573			(!instance.currentHash && !(item.type === "inline" || item.type === "html") ? item.origSrc || item.src : false) || window.location
8574		  );
8575		},
8576		tpl: '<div class="fancybox-share">' +
8577		  "<h1>{{SHARE}}</h1>" +
8578		  "<p>" +
8579		  '<a class="fancybox-share__button fancybox-share__button--fb" href="https://www.facebook.com/sharer/sharer.php?u={{url}}">' +
8580		  '<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m287 456v-299c0-21 6-35 35-35h38v-63c-7-1-29-3-55-3-54 0-91 33-91 94v306m143-254h-205v72h196" /></svg>' +
8581		  "<span>Facebook</span>" +
8582		  "</a>" +
8583		  '<a class="fancybox-share__button fancybox-share__button--tw" href="https://twitter.com/intent/tweet?url={{url}}&text={{descr}}">' +
8584		  '<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m456 133c-14 7-31 11-47 13 17-10 30-27 37-46-15 10-34 16-52 20-61-62-157-7-141 75-68-3-129-35-169-85-22 37-11 86 26 109-13 0-26-4-37-9 0 39 28 72 65 80-12 3-25 4-37 2 10 33 41 57 77 57-42 30-77 38-122 34 170 111 378-32 359-208 16-11 30-25 41-42z" /></svg>' +
8585		  "<span>Twitter</span>" +
8586		  "</a>" +
8587		  '<a class="fancybox-share__button fancybox-share__button--pt" href="https://www.pinterest.com/pin/create/button/?url={{url}}&description={{descr}}&media={{media}}">' +
8588		  '<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m265 56c-109 0-164 78-164 144 0 39 15 74 47 87 5 2 10 0 12-5l4-19c2-6 1-8-3-13-9-11-15-25-15-45 0-58 43-110 113-110 62 0 96 38 96 88 0 67-30 122-73 122-24 0-42-19-36-44 6-29 20-60 20-81 0-19-10-35-31-35-25 0-44 26-44 60 0 21 7 36 7 36l-30 125c-8 37-1 83 0 87 0 3 4 4 5 2 2-3 32-39 42-75l16-64c8 16 31 29 56 29 74 0 124-67 124-157 0-69-58-132-146-132z" fill="#fff"/></svg>' +
8589		  "<span>Pinterest</span>" +
8590		  "</a>" +
8591		  "</p>" +
8592		  '<p><input class="fancybox-share__input" type="text" value="{{url_raw}}" onclick="select()" /></p>' +
8593		  "</div>"
8594	  }
8595	});
8596
8597	function escapeHtml(string) {
8598	  var entityMap = {
8599		"&": "&amp;",
8600		"<": "&lt;",
8601		">": "&gt;",
8602		'"': "&quot;",
8603		"'": "&#39;",
8604		"/": "&#x2F;",
8605		"`": "&#x60;",
8606		"=": "&#x3D;"
8607	  };
8608
8609	  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
8610		return entityMap[s];
8611	  });
8612	}
8613
8614	$(document).on("click", "[data-fancybox-share]", function () {
8615	  var instance = $.fancybox.getInstance(),
8616		current = instance.current || null,
8617		url,
8618		tpl;
8619
8620	  if (!current) {
8621		return;
8622	  }
8623
8624	  if ($.type(current.opts.share.url) === "function") {
8625		url = current.opts.share.url.apply(current, [instance, current]);
8626	  }
8627
8628	  tpl = current.opts.share.tpl
8629		.replace(/\{\{media\}\}/g, current.type === "image" ? encodeURIComponent(current.src) : "")
8630		.replace(/\{\{url\}\}/g, encodeURIComponent(url))
8631		.replace(/\{\{url_raw\}\}/g, escapeHtml(url))
8632		.replace(/\{\{descr\}\}/g, instance.$caption ? encodeURIComponent(instance.$caption.text()) : "");
8633
8634	  $.fancybox.open({
8635		src: instance.translate(instance, tpl),
8636		type: "html",
8637		opts: {
8638		  touch: false,
8639		  animationEffect: false,
8640		  afterLoad: function (shareInstance, shareCurrent) {
8641			// Close self if parent instance is closing
8642			instance.$refs.container.one("beforeClose.fb", function () {
8643			  shareInstance.close(null, 0);
8644			});
8645
8646			// Opening links in a popup window
8647			shareCurrent.$content.find(".fancybox-share__button").on('click',function () {
8648			  window.open(this.href, "Share", "width=550, height=450");
8649			  return false;
8650			});
8651		  },
8652		  mobile: {
8653			autoFocus: false
8654		  }
8655		}
8656	  });
8657	});
8658  })(document, jQuery);
8659  // ==========================================================================
8660  //
8661  // Hash
8662  // Enables linking to each modal
8663  //
8664  // ==========================================================================
8665  (function (window, document, $) {
8666	"use strict";
8667
8668	// Simple $.escapeSelector polyfill (for jQuery prior v3)
8669	if (!$.escapeSelector) {
8670	  $.escapeSelector = function (sel) {
8671		var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
8672		var fcssescape = function (ch, asCodePoint) {
8673		  if (asCodePoint) {
8674			// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
8675			if (ch === "\0") {
8676			  return "\uFFFD";
8677			}
8678
8679			// Control characters and (dependent upon position) numbers get escaped as code points
8680			return ch.slice(0, -1) + "\\" + ch.charCodeAt(ch.length - 1).toString(16) + " ";
8681		  }
8682
8683		  // Other potentially-special ASCII characters get backslash-escaped
8684		  return "\\" + ch;
8685		};
8686
8687		return (sel + "").replace(rcssescape, fcssescape);
8688	  };
8689	}
8690
8691	// Get info about gallery name and current index from url
8692	function parseUrl() {
8693	  var hash = window.location.hash.substr(1),
8694		rez = hash.split("-"),
8695		index = rez.length > 1 && /^\+?\d+$/.test(rez[rez.length - 1]) ? parseInt(rez.pop(-1), 10) || 1 : 1,
8696		gallery = rez.join("-");
8697
8698	  return {
8699		hash: hash,
8700		/* Index is starting from 1 */
8701		index: index < 1 ? 1 : index,
8702		gallery: gallery
8703	  };
8704	}
8705
8706	// Trigger click evnt on links to open new fancyBox instance
8707	function triggerFromUrl(url) {
8708	  if (url.gallery !== "") {
8709		// If we can find element matching 'data-fancybox' atribute,
8710		// then triggering click event should start fancyBox
8711		$("[data-fancybox='" + $.escapeSelector(url.gallery) + "']")
8712		  .eq(url.index - 1)
8713		  .focus()
8714		  .trigger("click.fb-start");
8715	  }
8716	}
8717
8718	// Get gallery name from current instance
8719	function getGalleryID(instance) {
8720	  var opts, ret;
8721
8722	  if (!instance) {
8723		return false;
8724	  }
8725
8726	  opts = instance.current ? instance.current.opts : instance.opts;
8727	  ret = opts.hash || (opts.$orig ? opts.$orig.data("fancybox") || opts.$orig.data("fancybox-trigger") : "");
8728
8729	  return ret === "" ? false : ret;
8730	}
8731
8732	// Start when DOM becomes ready
8733	$(function () {
8734	  if ( $.fancybox.version != '3.5.7' ) {
8735		  return;
8736	  }
8737
8738	  // Check if user has disabled this module
8739	  if ($.fancybox.defaults.hash === false) {
8740		return;
8741	  }
8742
8743	  // Update hash when opening/closing fancyBox
8744	  $(document).on({
8745		"onInit.fb": function (e, instance) {
8746		  var url, gallery;
8747
8748		  if (instance.group[instance.currIndex].opts.hash === false) {
8749			return;
8750		  }
8751
8752		  url = parseUrl();
8753		  gallery = getGalleryID(instance);
8754
8755		  // Make sure gallery start index matches index from hash
8756		  if (gallery && url.gallery && gallery == url.gallery) {
8757			instance.currIndex = url.index - 1;
8758		  }
8759		},
8760
8761		"beforeShow.fb": function (e, instance, current, firstRun) {
8762		  var gallery;
8763
8764		  if (!current || current.opts.hash === false) {
8765			return;
8766		  }
8767
8768		  // Check if need to update window hash
8769		  gallery = getGalleryID(instance);
8770
8771		  if (!gallery) {
8772			return;
8773		  }
8774
8775		  // Variable containing last hash value set by fancyBox
8776		  // It will be used to determine if fancyBox needs to close after hash change is detected
8777		  instance.currentHash = gallery + (instance.group.length > 1 ? "-" + (current.index + 1) : "");
8778
8779		  // If current hash is the same (this instance most likely is opened by hashchange), then do nothing
8780		  if (window.location.hash === "#" + instance.currentHash) {
8781			return;
8782		  }
8783
8784		  if (firstRun && !instance.origHash) {
8785			instance.origHash = window.location.hash;
8786		  }
8787
8788		  if (instance.hashTimer) {
8789			clearTimeout(instance.hashTimer);
8790		  }
8791
8792		  // Update hash
8793		  instance.hashTimer = setTimeout(function () {
8794			if ("replaceState" in window.history) {
8795			  window.history[firstRun ? "pushState" : "replaceState"]({},
8796				document.title,
8797				window.location.pathname + window.location.search + "#" + instance.currentHash
8798			  );
8799
8800			  if (firstRun) {
8801				instance.hasCreatedHistory = true;
8802			  }
8803			} else {
8804			  window.location.hash = instance.currentHash;
8805			}
8806
8807			instance.hashTimer = null;
8808		  }, 300);
8809		},
8810
8811		"beforeClose.fb": function (e, instance, current) {
8812		  if (!current || current.opts.hash === false) {
8813			return;
8814		  }
8815
8816		  clearTimeout(instance.hashTimer);
8817
8818		  // Goto previous history entry
8819		  if (instance.currentHash && instance.hasCreatedHistory) {
8820			window.history.back();
8821		  } else if (instance.currentHash) {
8822			if ("replaceState" in window.history) {
8823			  window.history.replaceState({}, document.title, window.location.pathname + window.location.search + (instance.origHash || ""));
8824			} else {
8825			  window.location.hash = instance.origHash;
8826			}
8827		  }
8828
8829		  instance.currentHash = null;
8830		}
8831	  });
8832
8833	  // Check if need to start/close after url has changed
8834	  $(window).on("hashchange.fb", function () {
8835		var url = parseUrl(),
8836		  fb = null;
8837
8838		// Find last fancyBox instance that has "hash"
8839		$.each(
8840		  $(".fancybox-container")
8841		  .get()
8842		  .reverse(),
8843		  function (index, value) {
8844			var tmp = $(value).data("FancyBox");
8845
8846			if (tmp && tmp.currentHash) {
8847			  fb = tmp;
8848			  return false;
8849			}
8850		  }
8851		);
8852
8853		if (fb) {
8854		  // Now, compare hash values
8855		  if (fb.currentHash !== url.gallery + "-" + url.index && !(url.index === 1 && fb.currentHash == url.gallery)) {
8856			fb.currentHash = null;
8857
8858			fb.close();
8859		  }
8860		} else if (url.gallery !== "") {
8861		  triggerFromUrl(url);
8862		}
8863	  });
8864
8865	  // Check current hash and trigger click event on matching element to start fancyBox, if needed
8866	  setTimeout(function () {
8867		if ( $.fancybox.version != '3.5.7' ) {
8868			return;
8869		}
8870
8871		if (!$.fancybox.getInstance()) {
8872		  triggerFromUrl(parseUrl());
8873		}
8874	  }, 50);
8875	});
8876  })(window, document, jQuery);
8877  // ==========================================================================
8878  //
8879  // Wheel
8880  // Basic mouse weheel support for gallery navigation
8881  //
8882  // ==========================================================================
8883  (function (document, $) {
8884	"use strict";
8885
8886	var prevTime = new Date().getTime();
8887
8888	$(document).on({
8889	  "onInit.fb": function (e, instance, current) {
8890		instance.$refs.stage.on("mousewheel DOMMouseScroll wheel MozMousePixelScroll", function (e) {
8891		  var current = instance.current,
8892			currTime = new Date().getTime();
8893
8894		  if (instance.group.length < 2 || current.opts.wheel === false || (current.opts.wheel === "auto" && current.type !== "image")) {
8895			return;
8896		  }
8897
8898		  e.preventDefault();
8899		  e.stopPropagation();
8900
8901		  if (current.$slide.hasClass("fancybox-animated")) {
8902			return;
8903		  }
8904
8905		  e = e.originalEvent || e;
8906
8907		  if (currTime - prevTime < 250) {
8908			return;
8909		  }
8910
8911		  prevTime = currTime;
8912
8913		  instance[(-e.deltaY || -e.deltaX || e.wheelDelta || -e.detail) < 0 ? "next" : "previous"]();
8914		});
8915	  }
8916	});
8917  })(document, jQuery);
8918
8919;
8920(function ($, window, document, undefined) {
8921
8922  var pluginName = "MegaMenu",
8923    defaults = {
8924      propertyName: "value"
8925    };
8926
8927  // Set delay time for mouseout
8928  var delayOut = 400; // Default delay time is 200
8929
8930  // the list of menus
8931  var menus = [];
8932
8933  function CustomMenu(element, options) {
8934    this.element = element;
8935
8936    this.options = $.extend({}, defaults, options);
8937
8938    this._defaults = defaults;
8939    this._name = pluginName;
8940
8941    this.init();
8942  }
8943
8944  CustomMenu.prototype = {
8945    isOpen: false,
8946    timeout: null,
8947    init: function () {
8948
8949      var that = this;
8950
8951      $(this).each(function(index, menu) {
8952        that.node = menu.element;
8953        that.addListeners(menu.element);
8954
8955        var $menu = $(menu.element);
8956        $menu.addClass("dropdownJavascript");
8957        menus.push(menu.element);
8958
8959        $menu.find('ul > li').each(function(index, submenu) {
8960          if ($(submenu).find('ul').length > 0 ) {
8961            $(submenu).addClass('with-menu');
8962          }
8963        });
8964      });
8965    },
8966    addListeners: function(menu) {
8967      var that = this;
8968      $(menu).on('mouseover',function(e) {
8969        that.handleMouseOver.call(that, e);
8970      }).on('mouseout',function(e) {
8971          that.handleMouseOut.call(that, e);
8972        });
8973    },
8974    handleMouseOver: function (e) {
8975      var that = this;
8976      // clear the timeout
8977      this.clearTimeout();
8978
8979      // find the parent list item
8980      //var item = ('target' in e ? e.target : e.srcElement);
8981      var item = e.target || e.srcElement;
8982      while (item.nodeName != 'LI' && item != this.node) {
8983        item = item.parentNode;
8984      }
8985
8986      // if the target is within a list item, set the timeout
8987      if (item.nodeName == 'LI') {
8988        this.toOpen = item;
8989        this.timeout = setTimeout(function() {
8990          that.open.call(that);
8991        }, this.options.delay);
8992      }
8993
8994    },
8995    handleMouseOut: function () {
8996      var that = this;
8997      // clear the timeout
8998      this.clearTimeout();
8999
9000      // Check mouseout delay overriding
9001      var _delayOut = this.options.delay;
9002      if ( delayOut ) {
9003        _delayOut = delayOut;
9004      }
9005
9006      this.timeout = setTimeout(function() {
9007        that.close.call(that);
9008      }, _delayOut );
9009
9010    },
9011    clearTimeout: function () {
9012
9013      // clear the timeout
9014      if (this.timeout) {
9015        clearTimeout(this.timeout);
9016        this.timeout = null;
9017      }
9018
9019    },
9020    open: function () {
9021
9022      var that = this;
9023      // store that the menu is open
9024      this.isOpen = true;
9025
9026      // loop over the list items with the same parent
9027      var items = $(this.toOpen).parent().children('li');
9028      $(items).each(function(index, item) {
9029        $(item).find("ul").each(function(index, submenu) {
9030          if (item != that.toOpen) {
9031            // close the submenu
9032            $(item).removeClass("dropdownOpen");
9033            that.close(item);
9034
9035          } else if (!$(item).hasClass('dropdownOpen')) {
9036
9037            // open the submenu
9038            //if ( !$(item).parents('li').hasClass('has-mega-menu') ) {
9039              $(item).addClass("dropdownOpen");
9040            //}
9041
9042
9043            // determine the location of the edges of the submenu
9044            var left = 0;
9045            var node = submenu;
9046            while (node) {
9047              //abs is because when you make menus right to left
9048              //the offsetLeft would be negative
9049              left += Math.abs(node.offsetLeft);
9050              node = node.offsetParent;
9051            }
9052            var right = left + submenu.offsetWidth;
9053
9054
9055            //We should refactor this code to execute only when menu is vertical
9056            var menuHeight = $(submenu).outerHeight();
9057            var parentTop = $(submenu).offset().top - $(window).scrollTop();
9058            var totalHeight = menuHeight + parentTop;
9059            var windowHeight = window.innerHeight;
9060
9061           /* if (totalHeight > windowHeight) {
9062              var bestTop = (windowHeight - totalHeight) - 20;
9063              $(submenu).css('margin-top', bestTop + "px");
9064            }*/
9065
9066            //remove any previous classes
9067            $(item).removeClass('dropdownRightToLeft');
9068
9069            // move the submenu to the right of the item if appropriate
9070            if (left < 0) $(item).addClass('dropdownLeftToRight');
9071
9072            // move the submenu to the left of the item if appropriate
9073            if (right > document.body.clientWidth) {
9074              $(item).addClass('dropdownRightToLeft');
9075            }
9076
9077          }
9078        });
9079      });
9080
9081    },
9082
9083
9084    close: function (node) {
9085
9086      // if no node was specified, close all menus
9087      if (!node) {
9088        this.isOpen = false;
9089        node = this.node;
9090      }
9091
9092      // loop over the items, closing their submenus
9093      $(node).find('li').each(function(index, item) {
9094        $(item).removeClass('dropdownOpen');
9095      });
9096
9097    }
9098  };
9099
9100  $.fn[pluginName] = function (options) {
9101    return this.each(function () {
9102      if (!$.data(this, "plugin_" + pluginName)) {
9103        $.data(this, "plugin_" + pluginName,
9104          new CustomMenu(this, options));
9105      }
9106    });
9107  };
9108
9109})(jQuery, window, document);
9110
9111/*!
9112 * modernizr v3.3.1
9113 * Build https://modernizr.com/download?-cssanimations-csstransitions-touchevents-domprefixes-prefixed-prefixes-setclasses-shiv-testallprops-testprop-teststyles-dontmin
9114 *
9115 * Copyright (c)
9116 *  Faruk Ates
9117 *  Paul Irish
9118 *  Alex Sexton
9119 *  Ryan Seddon
9120 *  Patrick Kettner
9121 *  Stu Cox
9122 *  Richard Herrera
9123
9124 * MIT License
9125 */
9126
9127/*
9128 * Modernizr tests which native CSS3 and HTML5 features are available in the
9129 * current UA and makes the results available to you in two ways: as properties on
9130 * a global `Modernizr` object, and as classes on the `<html>` element. This
9131 * information allows you to progressively enhance your pages with a granular level
9132 * of control over the experience.
9133*/
9134
9135;(function(window, document, undefined){
9136  var classes = [];
9137  
9138
9139  var tests = [];
9140  
9141
9142  /**
9143   *
9144   * ModernizrProto is the constructor for Modernizr
9145   *
9146   * @class
9147   * @access public
9148   */
9149
9150  var ModernizrProto = {
9151    // The current version, dummy
9152    _version: '3.3.1',
9153
9154    // Any settings that don't work as separate modules
9155    // can go in here as configuration.
9156    _config: {
9157      'classPrefix': '',
9158      'enableClasses': true,
9159      'enableJSClass': true,
9160      'usePrefixes': true
9161    },
9162
9163    // Queue of tests
9164    _q: [],
9165
9166    // Stub these for people who are listening
9167    on: function(test, cb) {
9168      // I don't really think people should do this, but we can
9169      // safe guard it a bit.
9170      // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.
9171      // This is in case people listen to synchronous tests. I would leave it out,
9172      // but the code to *disallow* sync tests in the real version of this
9173      // function is actually larger than this.
9174      var self = this;
9175      setTimeout(function() {
9176        cb(self[test]);
9177      }, 0);
9178    },
9179
9180    addTest: function(name, fn, options) {
9181      tests.push({name: name, fn: fn, options: options});
9182    },
9183
9184    addAsyncTest: function(fn) {
9185      tests.push({name: null, fn: fn});
9186    }
9187  };
9188
9189  
9190
9191  // Fake some of Object.create so we can force non test results to be non "own" properties.
9192  var Modernizr = function() {};
9193  Modernizr.prototype = ModernizrProto;
9194
9195  // Leak modernizr globally when you `require` it rather than force it here.
9196  // Overwrite name so constructor name is nicer :D
9197  Modernizr = new Modernizr();
9198
9199  
9200
9201  /**
9202   * List of property values to set for css tests. See ticket #21
9203   * http://git.io/vUGl4
9204   *
9205   * @memberof Modernizr
9206   * @name Modernizr._prefixes
9207   * @optionName Modernizr._prefixes
9208   * @optionProp prefixes
9209   * @access public
9210   * @example
9211   *
9212   * Modernizr._prefixes is the internal list of prefixes that we test against
9213   * inside of things like [prefixed](#modernizr-prefixed) and [prefixedCSS](#-code-modernizr-prefixedcss). It is simply
9214   * an array of kebab-case vendor prefixes you can use within your code.
9215   *
9216   * Some common use cases include
9217   *
9218   * Generating all possible prefixed version of a CSS property
9219   * ```js
9220   * var rule = Modernizr._prefixes.join('transform: rotate(20deg); ');
9221   *
9222   * rule === 'transform: rotate(20deg); webkit-transform: rotate(20deg); moz-transform: rotate(20deg); o-transform: rotate(20deg); ms-transform: rotate(20deg);'
9223   * ```
9224   *
9225   * Generating all possible prefixed version of a CSS value
9226   * ```js
9227   * rule = 'display:' +  Modernizr._prefixes.join('flex; display:') + 'flex';
9228   *
9229   * rule === 'display:flex; display:-webkit-flex; display:-moz-flex; display:-o-flex; display:-ms-flex; display:flex'
9230   * ```
9231   */
9232
9233  // we use ['',''] rather than an empty array in order to allow a pattern of .`join()`ing prefixes to test
9234  // values in feature detects to continue to work
9235  var prefixes = (ModernizrProto._config.usePrefixes ? ' -webkit- -moz- -o- -ms- '.split(' ') : ['','']);
9236
9237  // expose these for the plugin API. Look in the source for how to join() them against your input
9238  ModernizrProto._prefixes = prefixes;
9239
9240  
9241
9242  /**
9243   * is returns a boolean if the typeof an obj is exactly type.
9244   *
9245   * @access private
9246   * @function is
9247   * @param {*} obj - A thing we want to check the type of
9248   * @param {string} type - A string to compare the typeof against
9249   * @returns {boolean}
9250   */
9251
9252  function is(obj, type) {
9253    return typeof obj === type;
9254  }
9255  ;
9256
9257  /**
9258   * Run through all tests and detect their support in the current UA.
9259   *
9260   * @access private
9261   */
9262
9263  function testRunner() {
9264    var featureNames;
9265    var feature;
9266    var aliasIdx;
9267    var result;
9268    var nameIdx;
9269    var featureName;
9270    var featureNameSplit;
9271
9272    for (var featureIdx in tests) {
9273      if (tests.hasOwnProperty(featureIdx)) {
9274        featureNames = [];
9275        feature = tests[featureIdx];
9276        // run the test, throw the return value into the Modernizr,
9277        // then based on that boolean, define an appropriate className
9278        // and push it into an array of classes we'll join later.
9279        //
9280        // If there is no name, it's an 'async' test that is run,
9281        // but not directly added to the object. That should
9282        // be done with a post-run addTest call.
9283        if (feature.name) {
9284          featureNames.push(feature.name.toLowerCase());
9285
9286          if (feature.options && feature.options.aliases && feature.options.aliases.length) {
9287            // Add all the aliases into the names list
9288            for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {
9289              featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());
9290            }
9291          }
9292        }
9293
9294        // Run the test, or use the raw value if it's not a function
9295        result = is(feature.fn, 'function') ? feature.fn() : feature.fn;
9296
9297
9298        // Set each of the names on the Modernizr object
9299        for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {
9300          featureName = featureNames[nameIdx];
9301          // Support dot properties as sub tests. We don't do checking to make sure
9302          // that the implied parent tests have been added. You must call them in
9303          // order (either in the test, or make the parent test a dependency).
9304          //
9305          // Cap it to TWO to make the logic simple and because who needs that kind of subtesting
9306          // hashtag famous last words
9307          featureNameSplit = featureName.split('.');
9308
9309          if (featureNameSplit.length === 1) {
9310            Modernizr[featureNameSplit[0]] = result;
9311          } else {
9312            // cast to a Boolean, if not one already
9313            /* jshint -W053 */
9314            if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
9315              Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
9316            }
9317
9318            Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;
9319          }
9320
9321          classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));
9322        }
9323      }
9324    }
9325  }
9326  ;
9327
9328  /**
9329   * docElement is a convenience wrapper to grab the root element of the document
9330   *
9331   * @access private
9332   * @returns {HTMLElement|SVGElement} The root element of the document
9333   */
9334
9335  var docElement = document.documentElement;
9336  
9337
9338  /**
9339   * A convenience helper to check if the document we are running in is an SVG document
9340   *
9341   * @access private
9342   * @returns {boolean}
9343   */
9344
9345  var isSVG = docElement.nodeName.toLowerCase() === 'svg';
9346  
9347
9348  /**
9349   * setClasses takes an array of class names and adds them to the root element
9350   *
9351   * @access private
9352   * @function setClasses
9353   * @param {string[]} classes - Array of class names
9354   */
9355
9356  // Pass in an and array of class names, e.g.:
9357  //  ['no-webp', 'borderradius', ...]
9358  function setClasses(classes) {
9359    var className = docElement.className;
9360    var classPrefix = Modernizr._config.classPrefix || '';
9361
9362    if (isSVG) {
9363      className = className.baseVal;
9364    }
9365
9366    // Change `no-js` to `js` (independently of the `enableClasses` option)
9367    // Handle classPrefix on this too
9368    if (Modernizr._config.enableJSClass) {
9369      var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)');
9370      className = className.replace(reJS, '$1' + classPrefix + 'js$2');
9371    }
9372
9373    if (Modernizr._config.enableClasses) {
9374      // Add the new classes
9375      className += ' ' + classPrefix + classes.join(' ' + classPrefix);
9376      isSVG ? docElement.className.baseVal = className : docElement.className = className;
9377    }
9378
9379  }
9380
9381  ;
9382
9383/**
9384  * @optionName html5shiv
9385  * @optionProp html5shiv
9386  */
9387
9388  // Take the html5 variable out of the html5shiv scope so we can return it.
9389  var html5;
9390  if (!isSVG) {
9391    /**
9392     * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
9393     */
9394    ;(function(window, document) {
9395      /*jshint evil:true */
9396      /** version */
9397      var version = '3.7.3';
9398
9399      /** Preset options */
9400      var options = window.html5 || {};
9401
9402      /** Used to skip problem elements */
9403      var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
9404
9405      /** Not all elements can be cloned in IE **/
9406      var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
9407
9408      /** Detect whether the browser supports default html5 styles */
9409      var supportsHtml5Styles;
9410
9411      /** Name of the expando, to work with multiple documents or to re-shiv one document */
9412      var expando = '_html5shiv';
9413
9414      /** The id for the the documents expando */
9415      var expanID = 0;
9416
9417      /** Cached data for each document */
9418      var expandoData = {};
9419
9420      /** Detect whether the browser supports unknown elements */
9421      var supportsUnknownElements;
9422
9423      (function() {
9424        try {
9425          var a = document.createElement('a');
9426          a.innerHTML = '<xyz></xyz>';
9427          //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
9428          supportsHtml5Styles = ('hidden' in a);
9429
9430          supportsUnknownElements = a.childNodes.length == 1 || (function() {
9431            // assign a false positive if unable to shiv
9432            (document.createElement)('a');
9433            var frag = document.createDocumentFragment();
9434            return (
9435              typeof frag.cloneNode == 'undefined' ||
9436                typeof frag.createDocumentFragment == 'undefined' ||
9437                typeof frag.createElement == 'undefined'
9438            );
9439          }());
9440        } catch(e) {
9441          // assign a false positive if detection fails => unable to shiv
9442          supportsHtml5Styles = true;
9443          supportsUnknownElements = true;
9444        }
9445
9446      }());
9447
9448      /*--------------------------------------------------------------------------*/
9449
9450      /**
9451       * Creates a style sheet with the given CSS text and adds it to the document.
9452       * @private
9453       * @param {Document} ownerDocument The document.
9454       * @param {String} cssText The CSS text.
9455       * @returns {StyleSheet} The style element.
9456       */
9457      function addStyleSheet(ownerDocument, cssText) {
9458        var p = ownerDocument.createElement('p'),
9459          parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
9460
9461        p.innerHTML = 'x<style>' + cssText + '</style>';
9462        return parent.insertBefore(p.lastChild, parent.firstChild);
9463      }
9464
9465      /**
9466       * Returns the value of `html5.elements` as an array.
9467       * @private
9468       * @returns {Array} An array of shived element node names.
9469       */
9470      function getElements() {
9471        var elements = html5.elements;
9472        return typeof elements == 'string' ? elements.split(' ') : elements;
9473      }
9474
9475      /**
9476       * Extends the built-in list of html5 elements
9477       * @memberOf html5
9478       * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
9479       * @param {Document} ownerDocument The context document.
9480       */
9481      function addElements(newElements, ownerDocument) {
9482        var elements = html5.elements;
9483        if(typeof elements != 'string'){
9484          elements = elements.join(' ');
9485        }
9486        if(typeof newElements != 'string'){
9487          newElements = newElements.join(' ');
9488        }
9489        html5.elements = elements +' '+ newElements;
9490        shivDocument(ownerDocument);
9491      }
9492
9493      /**
9494       * Returns the data associated to the given document
9495       * @private
9496       * @param {Document} ownerDocument The document.
9497       * @returns {Object} An object of data.
9498       */
9499      function getExpandoData(ownerDocument) {
9500        var data = expandoData[ownerDocument[expando]];
9501        if (!data) {
9502          data = {};
9503          expanID++;
9504          ownerDocument[expando] = expanID;
9505          expandoData[expanID] = data;
9506        }
9507        return data;
9508      }
9509
9510      /**
9511       * returns a shived element for the given nodeName and document
9512       * @memberOf html5
9513       * @param {String}
vendor: 4,418 bytes, lines 9513-9624
9513 nodeName name of the element
9514       * @param {Document|DocumentFragment} ownerDocument The context document.
9515       * @returns {Object} The shived element.
9516       */
9517      function createElement(nodeName, ownerDocument, data){
9518        if (!ownerDocument) {
9519          ownerDocument = document;
9520        }
9521        if(supportsUnknownElements){
9522          return ownerDocument.createElement(nodeName);
9523        }
9524        if (!data) {
9525          data = getExpandoData(ownerDocument);
9526        }
9527        var node;
9528
9529        if (data.cache[nodeName]) {
9530          node = data.cache[nodeName].cloneNode();
9531        } else if (saveClones.test(nodeName)) {
9532          node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
9533        } else {
9534          node = data.createElem(nodeName);
9535        }
9536
9537        // Avoid adding some elements to fragments in IE < 9 because
9538        // * Attributes like `name` or `type` cannot be set/changed once an element
9539        //   is inserted into a document/fragment
9540        // * Link elements with `src` attributes that are inaccessible, as with
9541        //   a 403 response, will cause the tab/window to crash
9542        // * Script elements appended to fragments will execute when their `src`
9543        //   or `text` property is set
9544        return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
9545      }
9546
9547      /**
9548       * returns a shived DocumentFragment for the given document
9549       * @memberOf html5
9550       * @param {Document} ownerDocument The context document.
9551       * @returns {Object} The shived DocumentFragment.
9552       */
9553      function createDocumentFragment(ownerDocument, data){
9554        if (!ownerDocument) {
9555          ownerDocument = document;
9556        }
9557        if(supportsUnknownElements){
9558          return ownerDocument.createDocumentFragment();
9559        }
9560        data = data || getExpandoData(ownerDocument);
9561        var clone = data.frag.cloneNode(),
9562          i = 0,
9563          elems = getElements(),
9564          l = elems.length;
9565        for(;i<l;i++){
9566          clone.createElement(elems[i]);
9567        }
9568        return clone;
9569      }
9570
9571      /**
9572       * Shivs the `createElement` and `createDocumentFragment` methods of the document.
9573       * @private
9574       * @param {Document|DocumentFragment} ownerDocument The document.
9575       * @param {Object} data of the document.
9576       */
9577      function shivMethods(ownerDocument, data) {
9578        if (!data.cache) {
9579          data.cache = {};
9580          data.createElem = ownerDocument.createElement;
9581          data.createFrag = ownerDocument.createDocumentFragment;
9582          data.frag = data.createFrag();
9583        }
9584
9585
9586        ownerDocument.createElement = function(nodeName) {
9587          //abort shiv
9588          if (!html5.shivMethods) {
9589            return data.createElem(nodeName);
9590          }
9591          return createElement(nodeName, ownerDocument, data);
9592        };
9593
9594        ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
9595                                                        'var n=f.cloneNode(),c=n.createElement;' +
9596                                                        'h.shivMethods&&(' +
9597                                                        // unroll the `createElement` calls
9598                                                        getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
9599          data.createElem(nodeName);
9600          data.frag.createElement(nodeName);
9601          return 'c("' + nodeName + '")';
9602        }) +
9603          ');return n}'
9604                                                       )(html5, data.frag);
9605      }
9606
9607      /*--------------------------------------------------------------------------*/
9608
9609      /**
9610       * Shivs the given document.
9611       * @memberOf html5
9612       * @param {Document} ownerDocument The document to shiv.
9613       * @returns {Document} The shived document.
9614       */
9615      function shivDocument(ownerDocument) {
9616        if (!ownerDocument) {
9617          ownerDocument = document;
9618        }
9619        var data = getExpandoData(ownerDocument);
9620
9621        if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
9622          data.hasCSS = !!addStyleSheet(ownerDocument,
9623                                        // corrects block display not defined in IE6/7/8/9
9624                                        'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{dis
9624play:block}' +
9625                                        // adds styling not present in IE6/7/8/9
9626                                        'mark{background:#FF0;color:#000}' +
9627                                        // hides non-rendered elements
9628                                        'template{display:none}'
9629                                       );
9630        }
9631        if (!supportsUnknownElements) {
9632          shivMethods(ownerDocument, data);
9633        }
9634        return ownerDocument;
9635      }
9636
9637      /*--------------------------------------------------------------------------*/
9638
9639      /**
9640       * The `html5` object is exposed so that more elements can be shived and
9641       * existing shiving can be detected on iframes.
9642       * @type Object
9643       * @example
9644       *
9645       * // options can be changed before the script is included
9646       * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
9647       */
9648      var html5 = {
9649
9650        /**
9651         * An array or space separated string of node names of the elements to shiv.
9652         * @memberOf html5
9653         * @type Array|String
9654         */
9655        'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
9656
9657        /**
9658         * current version of html5shiv
9659         */
9660        'version': version,
9661
9662        /**
9663         * A flag to indicate that the HTML5 style sheet should be inserted.
9664         * @memberOf html5
9665         * @type Boolean
9666         */
9667        'shivCSS': (options.shivCSS !== false),
9668
9669        /**
9670         * Is equal to true if a browser supports creating unknown/HTML5 elements
9671         * @memberOf html5
9672         * @type boolean
9673         */
9674        'supportsUnknownElements': supportsUnknownElements,
9675
9676        /**
9677         * A flag to indicate that the document's `createElement` and `createDocumentFragment`
9678         * methods should be overwritten.
9679         * @memberOf html5
9680         * @type Boolean
9681         */
9682        'shivMethods': (options.shivMethods !== false),
9683
9684        /**
9685         * A string to describe the type of `html5` object ("default" or "default print").
9686         * @memberOf html5
9687         * @type String
9688         */
9689        'type': 'default',
9690
9691        // shivs the document according to the specified `html5` object options
9692        'shivDocument': shivDocument,
9693
9694        //creates a shived element
9695        createElement: createElement,
9696
9697        //creates a shived documentFragment
9698        createDocumentFragment: createDocumentFragment,
9699
9700        //extends list of elements
9701        addElements: addElements
9702      };
9703
9704      /*--------------------------------------------------------------------------*/
9705
9706      // expose html5
9707      window.html5 = html5;
9708
9709      // shiv the document
9710      shivDocument(document);
9711
9712      if(typeof module == 'object' && module.exports){
9713        module.exports = html5;
9714      }
9715
9716    }(typeof window !== "undefined" ? window : this, document));
9717  }
9718;
9719
9720  /**
9721   * If the browsers follow the spec, then they would expose vendor-specific style as:
9722   *   elem.style.WebkitBorderRadius
9723   * instead of something like the following, which would be technically incorrect:
9724   *   elem.style.webkitBorderRadius
9725
9726   * Webkit ghosts their properties in lowercase but Opera & Moz do not.
9727   * Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
9728   *   erik.eae.net/archives/2008/03/10/21.48.10/
9729
9730   * More here: github.com/Modernizr/Modernizr/issues/issue/21
9731   *
9732   * @access private
9733   * @returns {string} The string representing the vendor-specific style properties
9734   */
9735
9736  var omPrefixes = 'Moz O ms Webkit';
9737  
9738
9739  /**
9740   * List of JavaScript DOM values used for tests
9741   *
9742   * @memberof Modernizr
9743   * @name Modernizr._domPrefixes
9744   * @optionName Modernizr._domPrefixes
9745   * @optionProp domPrefixes
9746   * @access public
9747   * @example
9748   *
9749   * Modernizr._domPrefixes is exactly the same as [_prefixes](#modernizr-_prefixes), but rather
9750   * than kebab-case properties, all properties are their Capitalized variant
9751   *
9752   * ```js
9753   * Modernizr._domPrefixes === [ "Moz", "O", "ms", "Webkit" ];
9754   * ```
9755   */
9756
9757  var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []);
9758  ModernizrProto._domPrefixes = domPrefixes;
9759  
9760
9761  /**
9762   * cssToDOM takes a kebab-case string and converts it to camelCase
9763   * e.g. box-sizing -> boxSizing
9764   *
9765   * @access private
9766   * @function cssToDOM
9767   * @param {string} name - String name of kebab-case prop we want to convert
9768   * @returns {string} The camelCase version of the supplied name
9769   */
9770
9771  function cssToDOM(name) {
9772    return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {
9773      return m1 + m2.toUpperCase();
9774    }).replace(/^-/, '');
9775  }
9776  ;
9777
9778  var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []);
9779  ModernizrProto._cssomPrefixes = cssomPrefixes;
9780  
9781
9782  /**
9783   * atRule returns a given CSS property at-rule (eg @keyframes), possibly in
9784   * some prefixed form, or false, in the case of an unsupported rule
9785   *
9786   * @memberof Modernizr
9787   * @name Modernizr.atRule
9788   * @optionName Modernizr.atRule()
9789   * @optionProp atRule
9790   * @access public
9791   * @function atRule
9792   * @param {string} prop - String name of the @-rule to test for
9793   * @returns {string|boolean} The string representing the (possibly prefixed)
9794   * valid version of the @-rule, or `false` when it is unsupported.
9795   * @example
9796   * ```js
9797   *  var keyframes = Modernizr.atRule('@keyframes');
9798   *
9799   *  if (keyframes) {
9800   *    // keyframes are supported
9801   *    // could be `@-webkit-keyframes` or `@keyframes`
9802   *  } else {
9803   *    // keyframes === `false`
9804   *  }
9805   * ```
9806   *
9807   */
9808
9809  var atRule = function(prop) {
9810    var length = prefixes.length;
9811    var cssrule = window.CSSRule;
9812    var rule;
9813
9814    if (typeof cssrule === 'undefined') {
9815      return undefined;
9816    }
9817
9818    if (!prop) {
9819      return false;
9820    }
9821
9822    // remove literal @ from beginning of provided property
9823    prop = prop.replace(/^@/, '');
9824
9825    // CSSRules use underscores instead of dashes
9826    rule = prop.replace(/-/g, '_').toUpperCase() + '_RULE';
9827
9828    if (rule in cssrule) {
9829      return '@' + prop;
9830    }
9831
9832    for (var i = 0; i < length; i++) {
9833      // prefixes gives us something like -o-, and we want O_
9834      var prefix = prefixes[i];
9835      var thisRule = prefix.toUpperCase() + '_' + rule;
9836
9837      if (thisRule in cssrule) {
9838        return '@-' + prefix.toLowerCase() + '-' + prop;
9839      }
9840    }
9841
9842    return false;
9843  };
9844
9845  ModernizrProto.atRule = atRule;
9846
9847  
9848
9849
9850  /**
9851   * contains checks to see if a string contains another string
9852   *
9853   * @access private
9854   * @function contains
9855   * @param {string} str - The string we want to check for substrings
9856   * @param {string} substr - The substring we want to search the first string for
9857   * @returns {boolean}
9858   */
9859
9860  function contains(str, substr) {
9861    return !!~('' + str).indexOf(substr);
9862  }
9863
9864  ;
9865
9866  /**
9867   * createElement is a convenience wrapper around document.createElement. Since we
9868   * use createElement all over the place, this allows for (slightly) smaller code
9869   * as well as abstracting away issues with creating elements in contexts other than
9870   * HTML documents (e.g. SVG documents).
9871   *
9872   * @access private
9873   * @function createElement
9874   * @returns {HTMLElement|SVGElement} An HTML or SVG element
9875   */
9876
9877  function createElement() {
9878    if (typeof document.createElement !== 'function') {
9879      // This is the case in IE7, where the type of createElement is "object".
9880      // For this reason, we cannot call apply() as Object is not a Function.
9881      return document.createElement(arguments[0]);
9882    } else if (isSVG) {
9883      return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);
9884    } else {
9885      return document.createElement.apply(document, arguments);
9886    }
9887  }
9888
9889  ;
9890
9891  /**
9892   * getBody returns the body of a document, or an element that can stand in for
9893   * the body if a real body does not exist
9894   *
9895   * @access private
9896   * @function getBody
9897   * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an
9898   * artificially created element that stands in for the body
9899   */
9900
9901  function getBody() {
9902    // After page load injecting a fake body doesn't work so check if body exists
9903    var body = document.body;
9904
9905    if (!body) {
9906      // Can't use the real body create a fake one.
9907      body = createElement(isSVG ? 'svg' : 'body');
9908      body.fake = true;
9909    }
9910
9911    return body;
9912  }
9913
9914  ;
9915
9916  /**
9917   * injectElementWithStyles injects an element with style element and some CSS rules
9918   *
9919   * @access private
9920   * @function injectElementWithStyles
9921   * @param {string} rule - String representing a css rule
9922   * @param {function} callback - A function that is used to test the injected element
9923   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
9924   * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes
9925   * @returns {boolean}
9926   */
9927
9928  function injectElementWithStyles(rule, callback, nodes, testnames) {
9929    var mod = 'modernizr';
9930    var style;
9931    var ret;
9932    var node;
9933    var docOverflow;
9934    var div = createElement('div');
9935    var body = getBody();
9936
9937    if (parseInt(nodes, 10)) {
9938      // In order not to give false positives we create a node for each test
9939      // This also allows the method to scale for unspecified uses
9940      while (nodes--) {
9941        node = createElement('div');
9942        node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
9943        div.appendChild(node);
9944      }
9945    }
9946
9947    style = createElement('style');
9948    style.type = 'text/css';
9949    style.id = 's' + mod;
9950
9951    // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.
9952    // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
9953    (!body.fake ? div : body).appendChild(style);
9954    body.appendChild(div);
9955
9956    if (style.styleSheet) {
9957      style.styleSheet.cssText = rule;
9958    } else {
9959      style.appendChild(document.createTextNode(rule));
9960    }
9961    div.id = mod;
9962
9963    if (body.fake) {
9964      //avoid crashing IE8, if background image is used
9965      body.style.background = '';
9966      //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
9967      body.style.overflow = 'hidden';
9968      docOverflow = docElement.style.overflow;
9969      docElement.style.overflow = 'hidden';
9970      docElement.appendChild(body);
9971    }
9972
9973    ret = callback(div, rule);
9974    // If this is done after page load we don't want to remove the body so check if body exists
9975    if (body.fake) {
9976      body.parentNode.removeChild(body);
9977      docElement.style.overflow = docOverflow;
9978      // Trigger layout so kinetic scrolling isn't disabled in iOS6+
9979      docElement.offsetHeight;
9980    } else {
9981      div.parentNode.removeChild(div);
9982    }
9983
9984    return !!ret;
9985
9986  }
9987
9988  ;
9989
9990  /**
9991   * testStyles injects an element with style element and some CSS rules
9992   *
9993   * @memberof Modernizr
9994   * @name Modernizr.testStyles
9995   * @optionName Modernizr.testStyles()
9996   * @optionProp testStyles
9997   * @access public
9998   * @function testStyles
9999   * @param {string} rule - String representing a css rule
10000   * @param {function} callback - A function that is used to test the injected element
10001   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
10002   * @param {string[]}
10002 [testnames] - An array of strings that are used as ids for the additional nodes
10003   * @returns {boolean}
10004   * @example
10005   *
10006   * `Modernizr.testStyles` takes a CSS rule and injects it onto the current page
10007   * along with (possibly multiple) DOM elements. This lets you check for features
10008   * that can not be detected by simply checking the [IDL](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Interface_development_guide/IDL_interface_rules).
10009   *
10010   * ```js
10011   * Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) {
10012   *   // elem is the first DOM node in the page (by default #modernizr)
10013   *   // rule is the first argument you supplied - the CSS rule in string form
10014   *
10015   *   addTest('widthworks', elem.style.width === '9px')
10016   * });
10017   * ```
10018   *
10019   * If your test requires multiple nodes, you can include a third argument
10020   * indicating how many additional div elements to include on the page. The
10021   * additional nodes are injected as children of the `elem` that is returned as
10022   * the first argument to the callback.
10023   *
10024   * ```js
10025   * Modernizr.testStyles('#modernizr {width: 1px}; #modernizr2 {width: 2px}', function(elem) {
10026   *   document.getElementById('modernizr').style.width === '1px'; // true
10027   *   document.getElementById('modernizr2').style.width === '2px'; // true
10028   *   elem.firstChild === document.getElementById('modernizr2'); // true
10029   * }, 1);
10030   * ```
10031   *
10032   * By default, all of the additional elements have an ID of `modernizr[n]`, where
10033   * `n` is its index (e.g. the first additional, second overall is `#modernizr2`,
10034   * the second additional is `#modernizr3`, etc.).
10035   * If you want to have more meaningful IDs for your function, you can provide
10036   * them as the fourth argument, as an array of strings
10037   *
10038   * ```js
10039   * Modernizr.testStyles('#foo {width: 10px}; #bar {height: 20px}', function(elem) {
10040   *   elem.firstChild === document.getElementById('foo'); // true
10041   *   elem.lastChild === document.getElementById('bar'); // true
10042   * }, 2, ['foo', 'bar']);
10043   * ```
10044   *
10045   */
10046
10047  var testStyles = ModernizrProto.testStyles = injectElementWithStyles;
10048  
10049
10050  /**
10051   * fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill.
10052   *
10053   * @access private
10054   * @function fnBind
10055   * @param {function} fn - a function you want to change `this` reference to
10056   * @param {object} that - the `this` you want to call the function with
10057   * @returns {function} The wrapped version of the supplied function
10058   */
10059
10060  function fnBind(fn, that) {
10061    return function() {
10062      return fn.apply(that, arguments);
10063    };
10064  }
10065
10066  ;
10067
10068  /**
10069   * testDOMProps is a generic DOM property test; if a browser supports
10070   *   a certain property, it won't return undefined for it.
10071   *
10072   * @access private
10073   * @function testDOMProps
10074   * @param {array.<string>} props - An array of properties to test for
10075   * @param {object} obj - An object or Element you want to use to test the parameters again
10076   * @param {boolean|object} elem - An Element to bind the property lookup again. Use `false` to prevent the check
10077   */
10078  function testDOMProps(props, obj, elem) {
10079    var item;
10080
10081    for (var i in props) {
10082      if (props[i] in obj) {
10083
10084        // return the property name as a string
10085        if (elem === false) {
10086          return props[i];
10087        }
10088
10089        item = obj[props[i]];
10090
10091        // let's bind a function
10092        if (is(item, 'function')) {
10093          // bind to obj unless overriden
10094          return fnBind(item, elem || obj);
10095        }
10096
10097        // return the unbound function or obj or value
10098        return item;
10099      }
10100    }
10101    return false;
10102  }
10103
10104  ;
10105
10106  /**
10107   * Create our "modernizr" element that we do most feature tests on.
10108   *
10109   * @access private
10110   */
10111
10112  var modElem = {
10113    elem: createElement('modernizr')
10114  };
10115
10116  // Clean up this element
10117  Modernizr._q.push(function() {
10118    delete modElem.elem;
10119  });
10120
10121  
10122
10123  var mStyle = {
10124    style: modElem.elem.style
10125  };
10126
10127  // kill ref for gc, must happen before mod.elem is removed, so we unshift on to
10128  // the front of the queue.
10129  Modernizr._q.unshift(function() {
10130    delete mStyle.style;
10131  });
10132
10133  
10134
10135  /**
10136   * domToCSS takes a camelCase string and converts it to kebab-case
10137   * e.g. boxSizing -> box-sizing
10138   *
10139   * @access private
10140   * @function domToCSS
10141   * @param {string} name - String name of camelCase prop we want to convert
10142   * @returns {string} The kebab-case version of the supplied name
10143   */
10144
10145  function domToCSS(name) {
10146    return name.replace(/([A-Z])/g, function(str, m1) {
10147      return '-' + m1.toLowerCase();
10148    }).replace(/^ms-/, '-ms-');
10149  }
10150  ;
10151
10152  /**
10153   * nativeTestProps allows for us to use native feature detection functionality if available.
10154   * some prefixed form, or false, in the case of an unsupported rule
10155   *
10156   * @access private
10157   * @function nativeTestProps
10158   * @param {array} props - An array of property names
10159   * @param {string} value - A string representing the value we want to check via @supports
10160   * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise
10161   */
10162
10163  // Accepts a list of property names and a single value
10164  // Returns `undefined` if native detection not available
10165  function nativeTestProps(props, value) {
10166    var i = props.length;
10167    // Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface
10168    if ('CSS' in window && 'supports' in window.CSS) {
10169      // Try every prefixed variant of the property
10170      while (i--) {
10171        if (window.CSS.supports(domToCSS(props[i]), value)) {
10172          return true;
10173        }
10174      }
10175      return false;
10176    }
10177    // Otherwise fall back to at-rule (for Opera 12.x)
10178    else if ('CSSSupportsRule' in window) {
10179      // Build a condition string for every prefixed variant
10180      var conditionText = [];
10181      while (i--) {
10182        conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');
10183      }
10184      conditionText = conditionText.join(' or ');
10185      return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {
10186        return getComputedStyle(node, null).position == 'absolute';
10187      });
10188    }
10189    return undefined;
10190  }
10191  ;
10192
10193  // testProps is a generic CSS / DOM property test.
10194
10195  // In testing support for a given CSS property, it's legit to test:
10196  //    `elem.style[styleName] !== undefined`
10197  // If the property is supported it will return an empty string,
10198  // if unsupported it will return undefined.
10199
10200  // We'll take advantage of this quick test and skip setting a style
10201  // on our modernizr element, but instead just testing undefined vs
10202  // empty string.
10203
10204  // Property names can be provided in either camelCase or kebab-case.
10205
10206  function testProps(props, prefixed, value, skipValueTest) {
10207    skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;
10208
10209    // Try native detect first
10210    if (!is(value, 'undefined')) {
10211      var result = nativeTestProps(props, value);
10212      if (!is(result, 'undefined')) {
10213        return result;
10214      }
10215    }
10216
10217    // Otherwise do it properly
10218    var afterInit, i, propsLength, prop, before;
10219
10220    // If we don't have a style element, that means we're running async or after
10221    // the core tests, so we'll need to create our own elements to use
10222
10223    // inside of an SVG element, in certain browsers, the `style` element is only
10224    // defined for valid tags. Therefore, if `modernizr` does not have one, we
10225    // fall back to a less used element and hope for the best.
10226    // for strict XHTML browsers the hardly used samp element is used
10227    var elems = ['modernizr', 'tspan', 'samp'];
10228    while (!mStyle.style && elems.length) {
10229      afterInit = true;
10230      mStyle.modElem = createElement(elems.shift());
10231      mStyle.style = mStyle.modElem.style;
10232    }
10233
10234    // Delete the objects if we created them.
10235    function cleanElems() {
10236      if (afterInit) {
10237        delete mStyle.style;
10238        delete mStyle.modElem;
10239      }
10240    }
10241
10242    propsLength = props.length;
10243    for (i = 0; i < propsLength; i++) {
10244      prop = props[i];
10245      before = mStyle.style[prop];
10246
10247      if (contains(prop, '-')) {
10248        prop = cssToDOM(prop);
10249      }
10250
10251      if (mStyle.style[prop] !== undefined) {
10252
10253        // If value to test has been passed in, do a set-and-check test.
10254        // 0 (integer) is a valid property value, so check that `value` isn't
10255        // undefined, rather than just checking it's truthy.
10256        if (!skipValueTest && !is(value, 'undefined')) {
10257
10258          // Needs a try catch block because of old IE. This is slow, but will
10259          // be avoided in most cases because `skipValueTest` will be used.
10260          try {
10261            mStyle.style[prop] = value;
10262          } catch (e) {}
10263
10264          // If the property value has changed, we assume the value used is
10265          // supported. If `value` is empty string, it'll fail here (because
10266          // it hasn't changed), which matches how browsers have implemented
10267          // CSS.supports()
10268          if (mStyle.style[prop] != before) {
10269            cleanElems();
10270            return prefixed == 'pfx' ? prop : true;
10271          }
10272        }
10273        // Otherwise just return true, or the property name if this is a
10274        // `prefixed()` call
10275        else {
10276          cleanElems();
10277          return prefixed == 'pfx' ? prop : true;
10278        }
10279      }
10280    }
10281    cleanElems();
10282    return false;
10283  }
10284
10285  ;
10286
10287  /**
10288   * testProp() investigates whether a given style property is recognized
10289   * Property names can be provided in either camelCase or kebab-case.
10290   *
10291   * @memberof Modernizr
10292   * @name Modernizr.testProp
10293   * @access public
10294   * @optionName Modernizr.testProp()
10295   * @optionProp testProp
10296   * @function testProp
10297   * @param {string} prop - Name of the CSS property to check
10298   * @param {string} [value] - Name of the CSS value to check
10299   * @param {boolean} [useValue] - Whether or not to check the value if @supports isn't supported
10300   * @returns {boolean}
10301   * @example
10302   *
10303   * Just like [testAllProps](#modernizr-testallprops), only it does not check any vendor prefixed
10304   * version of the string.
10305   *
10306   * Note that the property name must be provided in camelCase (e.g. boxSizing not box-sizing)
10307   *
10308   * ```js
10309   * Modernizr.testProp('pointerEvents')  // true
10310   * ```
10311   *
10312   * You can also provide a value as an optional second argument to check if a
10313   * specific value is supported
10314   *
10315   * ```js
10316   * Modernizr.testProp('pointerEvents', 'none') // true
10317   * Modernizr.testProp('pointerEvents', 'penguin') // false
10318   * ```
10319   */
10320
10321  var testProp = ModernizrProto.testProp = function(prop, value, useValue) {
10322    return testProps([prop], undefined, value, useValue);
10323  };
10324  
10325
10326  /**
10327   * testPropsAll tests a list of DOM properties we want to check against.
10328   * We specify literally ALL possible (known and/or likely) properties on
10329   * the element including the non-vendor prefixed one, for forward-
10330   * compatibility.
10331   *
10332   * @access private
10333   * @function testPropsAll
10334   * @param {string} prop - A string of the property to test for
10335   * @param {string|object} [prefixed] - An object to check the prefixed properties on. Use a string to skip
10336   * @param {HTMLElement|SVGElement} [elem] - An element used to test the property and value against
10337   * @param {string} [value] - A string of a css value
10338   * @param {boolean} [skipValueTest] - An boolean representing if you want to test if value sticks when set
10339   */
10340  function testPropsAll(prop, prefixed, elem, value, skipValueTest) {
10341
10342    var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
10343    props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
10344
10345    // did they call .prefixed('boxSizing') or are we just testing a prop?
10346    if (is(prefixed, 'string') || is(prefixed, 'undefined')) {
10347      return testProps(props, prefixed, value, skipValueTest);
10348
10349      // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
10350    } else {
10351      props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
10352      return testDOMProps(props, prefixed, elem);
10353    }
10354  }
10355
10356  // Modernizr.testAllProps() investigates whether a given style property,
10357  // or any of its vendor-prefixed variants, is recognized
10358  //
10359  // Note that the property names must be provided in the camelCase variant.
10360  // Modernizr.testAllProps('boxSizing')
10361  ModernizrProto.testAllProps = testPropsAll;
10362
10363  
10364
10365  /**
10366   * prefixed returns the prefixed or nonprefixed property name variant of your input
10367   *
10368   * @memberof Modernizr
10369   * @name Modernizr.prefixed
10370   * @optionName Modernizr.prefixed()
10371   * @optionProp prefixed
10372   * @access public
10373   * @function prefixed
10374   * @param {string} prop - String name of the property to test for
10375   * @param {object} [obj] - An object to test for the prefixed properties on
10376   * @param {HTMLElement} [elem] - An element used to test specific properties against
10377   * @returns {string|false} The string representing the (possibly prefixed) valid
10378   * version of the property, or `false` when it is unsupported.
10379   * @example
10380   *
10381   * Modernizr.prefixed takes a string css value in the DOM style camelCase (as
10382   * opposed to the css style kebab-case) form and returns the (possibly prefixed)
10383   * version of that property that the browser actually supports.
10384   *
10385   * For example, in older Firefox...
10386   * ```js
10387   * prefixed('boxSizing')
10388   * ```
10389   * returns 'MozBoxSizing'
10390   *
10391   * In newer Firefox, as well as any other browser that support the unprefixed
10392   * version would simply return `boxSizing`. Any browser that does not support
10393   * the property at all, it will return `false`.
10394   *
10395   * By default, prefixed is checked against a DOM element. If you want to check
10396   * for a property on another object, just pass it as a second argument
10397   *
10398   * ```js
10399   * var rAF = prefixed('requestAnimationFrame', window);
10400   *
10401   * raf(function() {
10402   *  renderFunction();
10403   * })
10404   * ```
10405   *
10406   * Note that this will return _the actual function_ - not the name of the function.
10407   * If you need the actual name of the property, pass in `false` as a third argument
10408   *
10409   * ```js
10410   * var rAFProp = prefixed('requestAnimationFrame', window, false);
10411   *
10412   * rafProp === 'WebkitRequestAnimationFrame' // in older webkit
10413   * ```
10414   *
10415   * One common use case for prefixed is if you're trying to determine which transition
10416   * end event to bind to, you might do something like...
10417   * ```js
10418   * var transEndEventNames = {
10419   *     'WebkitTransition' : 'webkitTransitionEnd', * Saf 6, Android Browser
10420   *     'MozTransition'    : 'transitionend',       * only for FF < 15
10421   *     'transition'       : 'transitionend'        * IE10, Opera, Chrome, FF 15+, Saf 7+
10422   * };
10423   *
10424   * var transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
10425   * ```
10426   *
10427   * If you want a similar lookup, but in kebab-case, you can use [prefixedCSS](#modernizr-prefixedcss).
10428   */
10429
10430  var prefixed = ModernizrProto.prefixed = function(prop, obj, elem) {
10431    if (prop.indexOf('@') === 0) {
10432      return atRule(prop);
10433    }
10434
10435    if (prop.indexOf('-') != -1) {
10436      // Convert kebab-case to camelCase
10437      prop = cssToDOM(prop);
10438    }
10439    if (!obj) {
10440      return testPropsAll(prop, 'pfx');
10441    } else {
10442      // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
10443      return testPropsAll(prop, obj, elem);
10444    }
10445  };
10446
10447  
10448
10449  /**
10450   * testAllProps determines whether a given CSS property is supported in the browser
10451   *
10452   * @memberof Modernizr
10453   * @name Modernizr.testAllProps
10454   * @optionName Modernizr.testAllProps()
10455   * @optionProp testAllProps
10456   * @access public
10457   * @function testAllProps
10458   * @param {string} prop - String naming the property to test (either camelCase or kebab-case)
10459   * @param {string} [value] - String of the value to test
10460   * @param {boolean} [skipValueTest=false] - Whether to skip testing that the value is supported when using non-native detection
10461   * @example
10462   *
10463   * testAllProps determines whether a given CSS property, in some prefixed form,
10464   * is supported by the browser.
10465   *
10466   * ```js
10467   * testAllProps('boxSizing')  // true
10468   * ```
10469   *
10470   * It can optionally be given a CSS value in string form to test if a property
10471   * value is valid
10472   *
10473   * ```js
10474   * testAllProps('display', 'block') // true
10475   * testAllProps('display', 'penguin') // false
10476   * ```
10477   *
10478   * A boolean can be passed as a third parameter to skip the value check when
10479   * native detection (@supports) isn't available.
10480   *
10481   * ```js
10482   * testAllProps('shapeOutside', 'content-box', true);
10483   * ```
10484   */
10485
10486  function testAllProps(prop, value, skipValueTest) {
10487    return testPropsAll(prop, undefined, undefined, value, skipValueTest);
10488  }
10489  ModernizrProto.testAllProps = testAllProps;
10490  
10491/*!
10492{
10493  "name": "CSS Animations",
10494  "property": "cssanimations",
10495  "caniuse": "css-animation",
10496  "polyfills": ["transformie", "csssandpaper"],
10497  "tags": ["css"],
10498  "warnings": ["Android < 4 will pass this test, but can only animate a single property at a time"],
10499  "notes": [{
10500    "name" : "Article: 'Dispelling the Android CSS animation myths'",
10501    "href": "https://goo.gl/OGw5Gm"
10502  }]
10503}
10504!*/
10505/* DOC
10506Detects whether or not elements can be animated using CSS
10507*/
10508
10509  Modernizr.addTest('cssanimations', testAllProps('animationName', 'a', true));
10510
10511/*!
10512{
10513  "name": "CSS Transitions",
10514  "property": "csstransitions",
10515  "caniuse": "css-transitions",
10516  "tags": ["css"]
10517}
10518!*/
10519
10520  Modernizr.addTest('csstransitions', testAllProps('transition', 'all', true));
10521
10522/*!
10523{
10524  "name": "Touch Events",
10525  "property": "touchevents",
10526  "caniuse" : "touch",
10527  "tags": ["media", "attribute"],
10528  "notes": [{
10529    "name": "Touch Events spec",
10530    "href": "https://www.w3.org/TR/2013/WD-touch-events-20130124/"
10531  }],
10532  "warnings": [
10533    "Indicates if the browser supports the Touch Events spec, and does not necessarily reflect a touchscreen device"
10534  ],
10535  "knownBugs": [
10536    "False-positive on some configurations of Nokia N900",
10537    "False-positive on some BlackBerry 6.0 builds – https://github.com/Modernizr/Modernizr/issues/372#issuecomment-3112695"
10538  ]
10539}
10540!*/
10541/* DOC
10542Indicates if the browser supports the W3C Touch Events API.
10543
10544This *does not* necessarily reflect a touchscreen device:
10545
10546* Older touchscreen devices only emulate mouse events
10547* Modern IE touch devices implement the Pointer Events API instead: use `Modernizr.pointerevents` to detect support for that
10548* Some browsers & OS setups may enable touch APIs when no touchscreen is connected
10549* Future browsers may implement other event models for touch interactions
10550
10551See this article: [You Can't Detect A Touchscreen](http://www.stucox.com/blog/you-cant-detect-a-touchscreen/).
10552
10553It's recommended to bind both mouse and touch/pointer events simultaneously – see [this HTML5 Rocks tutorial](http://www.html5rocks.com/en/mobile/touchandmouse/).
10554
10555This test will also return `true` for Firefox 4 Multitouch support.
10556*/
10557
10558  // Chrome (desktop) used to lie about its support on this, but that has since been rectified: http://crbug.com/36415
10559  Modernizr.addTest('touchevents', function() {
10560    var bool;
10561    if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
10562      bool = true;
10563    } else {
10564      // include the 'heartz' as a way to have a non matching MQ to help terminate the join
10565      // https://git.io/vznFH
10566      var query = ['@media (', prefixes.join('touch-enabled),('), 'heartz', ')', '{#modernizr{top:9px;position:absolute}}'].join('');
10567      testStyles(query, function(node) {
10568        bool = node.offsetTop === 9;
10569      });
10570    }
10571    return bool;
10572  });
10573
10574
10575  // Run each test
10576  testRunner();
10577
10578  // Remove the "no-js" class if it exists
10579  setClasses(classes);
10580
10581  delete ModernizrProto.addTest;
10582  delete ModernizrProto.addAsyncTest;
10583
10584  // Run the things that are supposed to run after the tests
10585  for (var i = 0; i < Modernizr._q.length; i++) {
10586    Modernizr._q[i]();
10587  }
10588
10589  // Leak Modernizr namespace
10590  window.Modernizr = Modernizr;
10591
10592
10593;
10594
10595})(window, document);
10596$(function() {
10597    ParallaxScroll.init();
10598});
10599
10600// Credit: https://github.com/alumbo/jquery.parallax-scroll
10601var ParallaxScroll = {
10602    /* PUBLIC VARIABLES */
10603    showLogs: false,
10604    round: 1000,
10605
10606    /* PUBLIC FUNCTIONS */
10607    init: function() {
10608        this._log("init");
10609        if (this._inited) {
10610            this._log("Already Inited");
10611            this._inited = true;
10612            return;
10613        }
10614        this._requestAnimationFrame = (function(){
10615          return  window.requestAnimationFrame       || 
10616                  window.webkitRequestAnimationFrame || 
10617                  window.mozRequestAnimationFrame    || 
10618                  window.oRequestAnimationFrame      || 
10619                  window.msRequestAnimationFrame     || 
10620                  function(/* function */ callback, /* DOMElement */ element){
10621                      window.setTimeout(callback, 1000 / 60);
10622                  };
10623        })();
10624        this._onScroll(true);
10625    },
10626
10627    /* PRIVATE VARIABLES */
10628    _inited: false,
10629    _properties: ['x', 'y', 'z', 'rotateX', 'rotateY', 'rotateZ', 'scaleX', 'scaleY', 'scaleZ', 'scale'],
10630    _requestAnimationFrame:null,
10631
10632    /* PRIVATE FUNCTIONS */
10633    _log: function(message) {
10634        if (this.showLogs) console.log("Parallax Scroll / " + message);
10635    },
10636    _onScroll: function(noSmooth) {
10637        var scroll = $(document).scrollTop();
10638        var windowHeight = $(window).height();
10639        this._log("onScroll " + scroll);
10640        $("[data-parallax]").each($.proxy(function(index, el) {
10641            var $el = $(el);
10642            var properties = [];
10643            var applyProperties = false;
10644            var style = $el.data("style");
10645            if (style == undefined) {
10646                style = $el.attr("style") || "";
10647                $el.data("style", style);
10648            }
10649            var datas = [$el.data("parallax")];
10650            var iData;
10651            for(iData = 2; ; iData++) {
10652                if($el.data("parallax"+iData)) {
10653                    datas.push($el.data("parallax-"+iData));
10654                }
10655                else {
10656                    break;
10657                }
10658            }
10659            var datasLength = datas.length;
10660            for(iData = 0; iData < datasLength; iData ++) {
10661                var data = datas[iData];
10662                var scrollFrom = data["from-scroll"];
10663                if (scrollFrom == undefined) scrollFrom = Math.max(0, $(el).offset().top - windowHeight);
10664                scrollFrom = scrollFrom | 0;
10665                var scrollDistance = data["distance"];
10666                var scrollTo = data["to-scroll"];
10667                if (scrollDistance == undefined && scrollTo == undefined) scrollDistance = windowHeight;
10668                scrollDistance = Math.max(scrollDistance | 0, 1);
10669                var easing = data["easing"];
10670                var easingReturn = data["easing-return"];
10671                if (easing == undefined || !$.easing|| !$.easing[easing]) easing = null;
10672                if (easingReturn == undefined || !$.easing|| !$.easing[easingReturn]) easingReturn = easing;
10673                if (easing) {
10674                    var totalTime = data["duration"];
10675                    if (totalTime == undefined) totalTime = scrollDistance;
10676                    totalTime = Math.max(totalTime | 0, 1);
10677                    var totalTimeReturn = data["duration-return"];
10678                    if (totalTimeReturn == undefined) totalTimeReturn = totalTime;
10679                    scrollDistance = 1;
10680                    var currentTime = $el.data("current-time");
10681                    if(currentTime == undefined) currentTime = 0;
10682                }
10683                if (scrollTo == undefined) scrollTo = scrollFrom + scrollDistance;
10684                scrollTo = scrollTo | 0;
10685                var smoothness = data["smoothness"];
10686                if (smoothness == undefined) smoothness = 30;
10687                smoothness = smoothness | 0;
10688                if (noSmooth || smoothness == 0) smoothness = 1;
10689                smoothness = smoothness | 0;
10690                var scrollCurrent = scroll;
10691                scrollCurrent = Math.max(scrollCurrent, scrollFrom);
10692                scrollCurrent = Math.min(scrollCurrent, scrollTo);
10693                if(easing) {
10694                    if($el.data("sens") == undefined) $el.data("sens", "back");
10695                    if(scrollCurrent>scrollFrom) {
10696                        if($el.data("sens") == "back") {
10697                            currentTime = 1;
10698                            $el.data("sens", "go");
10699                        }
10700                        else {
10701                            currentTime++;
10702                        }
10703                    }
10704                    if(scrollCurrent<scrollTo) {
10705                        if($el.data("sens") == "go") {
10706                            currentTime = 1;
10707                            $el.data("sens", "back");
10708                        }
10709                        else {
10710                            currentTime++;
10711                        }
10712                    }
10713                    if(noSmooth) currentTime = totalTime;
10714                    $el.data("current-time", currentTime);
10715                }
10716                this._properties.map($.proxy(function(prop) {
10717                    var defaultProp = 0;
10718                    var to = data[prop];
10719                    if (to == undefined) return;
10720                    if(prop=="scale" || prop=="scaleX" || prop=="scaleY" || prop=="scaleZ" ) {
10721                        defaultProp = 1;
10722                    }
10723                    else {
10724                        to = to | 0;
10725                    }
10726                    var prev = $el.data("_" + prop);
10727                    if (prev == undefined) prev = defaultProp;
10728                    var next = ((to-defaultProp) * ((scrollCurrent - scrollFrom) / (scrollTo - scrollFrom))) + defaultProp;
10729                    var val = prev + (next - prev) / smoothness;
10730                    if(easing && currentTime>0 && currentTime<=totalTime) {
10731                        var from = defaultProp;
10732                        if($el.data("sens") == "back") {
10733                            from = to;
10734                            to = -to;
10735                            easing = easingReturn;
10736                            totalTime = totalTimeReturn;
10737                        }
10738                        val = $.easing[easing](null, currentTime, from, to, totalTime);
10739                    }
10740                    val = Math.ceil(val * this.round) / this.round;
10741                    if(val==prev&&next==to) val = to;
10742                    if(!properties[prop]) properties[prop] = 0;
10743                    properties[prop] += val;
10744                    if (prev != properties[prop]) {
10745                        $el.data("_" + prop, properties[prop]);
10746                        applyProperties = true;
10747                    }
10748                }, this));
10749            }
10750            if (applyProperties) {
10751                if (properties["z"] != undefined) {
10752                    var perspective = data["perspective"];
10753                    if (perspective == undefined) perspective = 800;
10754                    var $parent = $el.parent();
10755                    if(!$parent.data("style")) $parent.data("style", $parent.attr("style") || "");
10756                    $parent.attr("style", "perspective:" + perspective + "px; -webkit-perspective:" + perspective + "px; "+ $parent.data("style"));
10757                }
10758                if(properties["scaleX"] == undefined) properties["scaleX"] = 1;
10759                if(properties["scaleY"] == undefined) properties["scaleY"] = 1;
10760                if(properties["scaleZ"] == undefined) properties["scaleZ"] = 1;
10761                if (properties["scale"] != undefined) {
10762                    properties["scaleX"] *= properties["scale"];
10763                    properties["scaleY"] *= properties["scale"];
10764                    properties["scaleZ"] *= properties["scale"];
10765                }
10766                var translate3d = "translate3d(" + (properties["x"] ? properties["x"] : 0) + "px, " + (properties["y"] ? properties["y"] : 0) + "px, " + (properties["z"] ? properties["z"] : 0) + "px)";
10767                var rotate3d = "rotateX(" + (properties["rotateX"] ? properties["rotateX"] : 0) + "deg) rotateY(" + (properties["rotateY"] ? properties["rotateY"] : 0) + "deg) rotateZ(" + (properties["rotateZ"] ? properties["rotateZ"] : 0) + "deg)";
10768                var scale3d = "scaleX(" + properties["scaleX"] + ") scaleY(" + properties["scaleY"] + ") scaleZ(" + properties["scaleZ"] + ")";
10769                var cssTransform = translate3d + " " + rotate3d + " " + scale3d + ";";
10770                this._log(cssTransform);
10771                $el.attr("style", "transform:" + cssTransform + " -webkit-transform:" + cssTransform + " " + style);
10772            }
10773        }, this));
10774        if(window.requestAnimationFrame) {
10775            window.requestAnimationFrame($.proxy(this._onScroll, this, false));
10776        }
10777        else {
10778            this._requestAnimationFrame($.proxy(this._onScroll, this, false));
10779        }
10780    }
10781};
10782;
10783(function($, window, undefined) {
10784
10785	'use strict';
10786
10787	// global
10788	var Modernizr = window.Modernizr,
10789		$body = $('body');
10790
10791	$.DLMenu = function(options, element) {
10792		this.$el = $(element);
10793		this._init(options);
10794	};
10795
10796	$.DLMenu.defaults = {
10797		animationClasses: {
10798			classin: 'mk-vm-animate-in-' + mk_vertical_header_anim,
10799			classout: 'mk-vm-animate-out-' + mk_vertical_header_anim
10800		},
10801		onLevelClick: function(el, name) {
10802			return false;
10803		},
10804		onLinkClick: function(el, ev) {
10805			return false;
10806		}
10807	};
10808
10809	$.DLMenu.prototype = {
10810		_init: function(options) {
10811
10812			this.options = $.extend(true, {}, $.DLMenu.defaults, options);
10813			this._config();
10814
10815			var animEndEventNames = {
10816					'WebkitAnimation': 'webkitAnimationEnd',
10817					'OAnimation': 'oAnimationEnd',
10818					'msAnimation': 'MSAnimationEnd',
10819					'animation': 'animationend'
10820				},
10821				transEndEventNames = {
10822					'WebkitTransition': 'webkitTransitionEnd',
10823					'MozTransition': 'transitionend',
10824					'OTransition': 'oTransitionEnd',
10825					'msTransition': 'MSTransitionEnd',
10826					'transition': 'transitionend'
10827				};
10828
10829			this.animEndEventName = animEndEventNames[Modernizr.prefixed('animation')] + '.dlmenu';
10830			this.transEndEventName = transEndEventNames[Modernizr.prefixed('transition')] + '.dlmenu';
10831
10832			this.animEndEventNameUnsufixed = animEndEventNames[Modernizr.prefixed('animation')];
10833			this.transEndEventNameUnsufixed = transEndEventNames[Modernizr.prefixed('transition')];
10834
10835			this.supportAnimations = Modernizr.cssanimations;
10836			this.supportTransitions = Modernizr.csstransitions;
10837
10838			this._initEvents();
10839
10840		},
10841		_config: function() {
10842			this.open = false;
10843			this.$trigger = this.$el.children('.mk-vm-trigger');
10844			this.$menu = this.$el.children('ul.mk-vm-menu');
10845			this.$menuitems = this.$menu.find('li:not(.mk-vm-back)');
10846			this.$back = this.$menu.find('li.mk-vm-back');
10847		},
10848		_initEvents: function() {
10849
10850			var self = this;
10851			
10852			$('.mk-vm-menuwrapper a').on('transitionend', function(event) {
10853				event.stopPropagation();
10854			});
10855
10856			this.$menuitems.on('click.dlmenu', 'a', function(event) {
10857
10858				// Breaks smooth scroll in vertical menu
10859				// event.stopPropagation();
10860
10861				var $item = $(event.delegateTarget),
10862					$submenu = $(event.currentTarget).siblings('ul.sub-menu');
10863
10864				if ($submenu.length > 0) {
10865					var $flyin = $submenu.clone().css('opacity', 0).insertAfter(self.$menu);
10866					var onAnimationEndFn = function() {
10867						var $parent = $item.parents('.mk-vm-subviewopen:first');
10868						self.$menu.off(self.animEndEventName).removeClass(self.options.animationClasses.classout).addClass('mk-vm-subview');
10869						$item.addClass('mk-vm-subviewopen')
10870						$parent.removeClass('mk-vm-subviewopen').addClass('mk-vm-subview');
10871						$flyin.remove();
10872
10873						// Redraw for firefox issues
10874						var $txt = $item.find('.meni-item-text');
10875						$txt.css('opacity', 0.99);
10876						setTimeout(function() { $txt.css('opacity', 1) }, 0);
10877					};
10878
10879					setTimeout(function() {
10880						$flyin.addClass(self.options.animationClasses.classin);
10881						self.$menu.addClass(self.options.animationClasses.classout);
10882						if (self.supportAnimations) {
10883							self.$menu.on(self.animEndEventName, onAnimationEndFn);
10884						} else {
10885							onAnimationEndFn.call();
10886						}
10887
10888						self.options.onLevelClick($item, $item.children('a:first').text());
10889					});
10890
10891
10892					// This caused firefox issue. Test properly if need to bring it back
10893					// if (self.open) {
10894					// 	self._closeMenu();
10895					// } else {
10896					// 	self._openMenu();
10897					// }
10898
10899					return false;
10900
10901				} else {
10902					self.options.onLinkClick($item, event);
10903				}
10904
10905			});
10906
10907
10908			// this.$trigger.on('click.dlmenu', function() {
10909
10910			// 	if (self.open) {
10911			// 		self._closeMenu();
10912			// 	} else {
10913			// 		// if( ! $(this).hasClass('menu-item-has-children') ) return false;
10914			// 		self._openMenu();
10915			// 	}
10916			// 	return false;
10917
10918			// });
10919
10920			this.$back.on('click.dlmenu', function(event) {
10921
10922				var $this = $(this),
10923					$submenu = $this.parents('ul.sub-menu:first'),
10924					$item = $submenu.parent(),
10925
10926					$flyin = $submenu.clone().insertAfter(self.$menu);
10927
10928				var onAnimationEndFn = function() {
10929					self.$menu.off(self.animEndEventName).removeClass(self.options.animationClasses.classin);
10930					$flyin.remove();
10931				};
10932
10933				setTimeout(function() {
10934					$flyin.addClass(self.options.animationClasses.classout);
10935					self.$menu.addClass(self.options.animationClasses.classin);
10936					if (self.supportAnimations) {
10937						self.$menu.on(self.animEndEventName, onAnimationEndFn);
10938					} else {
10939						onAnimationEndFn.call();
10940					}
10941
10942					$item.removeClass('mk-vm-subviewopen');
10943
10944					var $subview = $this.parents('.mk-vm-subview:first');
10945					if ($subview.is('li')) {
10946						$subview.addClass('mk-vm-subviewopen');
10947					}
10948					$subview.removeClass('mk-vm-subview');
10949				});
10950
10951				return false;
10952
10953			});
10954
10955		},
10956		closeMenu: function() {
10957			if (this.open) {
10958				this._closeMenu();
10959			}
10960		},
10961		_closeMenu: function() {
10962			var self = this,
10963				onTransitionEndFn = function() {
10964					self.$menu.off(self.transEndEventName);
10965					self._resetMenu();
10966				};
10967
10968			this.$menu.removeClass('mk-vm-menuopen');
10969			this.$menu.addClass('mk-vm-menu-toggle');
10970			this.$trigger.removeClass('mk-vm-active');
10971
10972			if (this.supportTransitions) {
10973				this.$menu.on(this.transEndEventName, onTransitionEndFn);
10974			} else {
10975				onTransitionEndFn.call();
10976			}
10977
10978			this.open = false;
10979		},
10980		openMenu: function() {
10981			if (!this.open) {
10982				this._openMenu();
10983			}
10984		},
10985		_openMenu: function() {
10986			var self = this;
10987			$body.off('click').on('click.dlmenu', function() {
10988				self._closeMenu();
10989			});
10990			this.$menu.addClass('mk-vm-menuopen mk-vm-menu-toggle').on(this.transEndEventName, function() {
10991				$(this).removeClass('mk-vm-menu-toggle');
10992			});
10993			this.$trigger.addClass('mk-vm-active');
10994			this.open = true;
10995		},
10996		_resetMenu: function() {
10997			this.$menu.removeClass('mk-vm-subview');
10998			this.$menuitems.removeClass('mk-vm-subview mk-vm-subviewopen');
10999		}
11000	};
11001
11002	var logError = function(message) {
11003		if (window.console) {
11004			window.console.error(message);
11005		}
11006	};
11007
11008	$.fn.dlmenu = function(options) {
11009		if (typeof options === 'string') {
11010			var args = Array.prototype.slice.call(arguments, 1);
11011			this.each(function() {
11012				var instance = $.data(this, 'dlmenu');
11013				if (!instance) {
11014					logError("cannot call methods on dlmenu prior to initialization; " +
11015						"attempted to call method '" + options + "'");
11016					return;
11017				}
11018				if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
11019					logError("no such method '" + options + "' for dlmenu instance");
11020					return;
11021				}
11022				instance[options].apply(instance, args);
11023			});
11024		} else {
11025			this.each(function() {
11026				var instance = $.data(this, 'dlmenu');
11027				if (instance) {
11028					instance._init();
11029				} else {
11030					instance = $.data(this, 'dlmenu', new $.DLMenu(options, this));
11031				}
11032			});
11033		}
11034		return this;
11035	};
11036
11037})(jQuery, window);
11038( function($) {
11039    'use strict';
11040
11041	/* 
11042	 * Define popup / hover states manually to prevent click for IE on touchdevices
11043	 */
11044
11045	$('.mk-main-navigation .menu-item-has-children').children('a').attr('aria-haspopup', 'true'); 
11046	$('.animated-column-item').attr('aria-haspopup', 'true');
11047
11048})( jQuery );
11049(function($) {
11050    'use strict';
11051
11052    var Accordion = function(el) { 
11053        // Private
11054        var that = this,
11055            $el = $(el),
11056            initial = $el.data('initialindex'),
11057            timeout;
11058
11059        // Public
11060        this.$el = $el;
11061        this.$single = $('.' + this.dom.single, $el);
11062        this.isExpendable = ($el.data('style') === 'toggle-action');
11063
11064        // Init 
11065        this.bindClicks();
11066        // Reveal initial tab on load event (wait for possible images inside)
11067        $(window).on('load', function() {
11068            if( initial !== -1 ) that.show(that.$single.eq(initial), true)
11069        });
11070        $(window).on('resize', function() {
11071            clearTimeout(timeout);
11072            timeout = setTimeout(that.bindClicks.bind(that), 500);
11073        }); 
11074    }
11075
11076    Accordion.prototype.dom = {
11077        // only class names please!
11078        single        : 'mk-accordion-single',
11079        tab           : 'mk-accordion-tab',
11080        pane          : 'mk-accordion-pane',
11081        current       : 'current',
11082        mobileToggle  : 'mobile-false',
11083        mobileBreakPoint : 767
11084    }
11085
11086    Accordion.prototype.bindClicks = function() {
11087        // Prevent multiple events binding
11088        this.$single.off('click', '.' + this.dom.tab);
11089
11090        if( !(window.matchMedia('(max-width: ' + this.dom.mobileBreakPoint +'px)').matches 
11091          && this.$el.hasClass(this.dom.mobileToggle)) ) {
11092
11093            this.$single.on('click', '.' + this.dom.tab, this.handleEvent.bind(this));
11094            // When website is loaded in mobile view and resized to desktop 'current' will 
11095            // inherit display: none from css. Repair it by calling show() on this element
11096            var $current = $('.' + this.dom.current, this.$el);
11097            if($('.' + this.dom.pane, $current).css('display') === 'none') this.show($current);
11098        }
11099    }
11100
11101    Accordion.prototype.handleEvent = function(e) {
11102        e.preventDefault();
11103        e.stopPropagation();
11104
11105        var $single = $(e.delegateTarget);
11106
11107        if(!$single.hasClass(this.dom.current)) {
11108            this.show($single);
11109        }
11110        else {
11111            if(this.isExpendable) this.hide($single);
11112        }
11113    }
11114
11115    Accordion.prototype.hide = function($single) {
11116        $single.removeClass(this.dom.current);
11117        $('.' + this.dom.pane, $single).slideUp();
11118    }
11119
11120    Accordion.prototype.show = function($single, initial) {
11121        // hide currently opened tab
11122        if(!this.isExpendable) {
11123            var that = this;
11124            this.hide($('.' + this.dom.current, that.$el));
11125        }
11126
11127        $single.addClass(this.dom.current);
11128        $('.' + this.dom.pane, $single).slideDown('', function() {
11129            if ( initial || ! $(this).parents('.mk-accordion').hasClass('scroll-click') ) {
11130                return;
11131            }
11132
11133            if (typeof $single.prev() === 'undefined') {
11134                $single = $single.prev()
11135            }
11136
11137            window.scrollTo({ top: $single.offset().top - 100, left: 0, behavior: 'smooth' });
11138        });
11139    }
11140
11141
11142
11143    // ///////////////////////////////////////
11144    //
11145    // Apply to:
11146    //
11147    // ///////////////////////////////////////
11148
11149	function init() {
11150		$('.mk-accordion').each(function() {
11151			new Accordion(this);
11152		});
11153	}
11154
11155	init();
11156	$(window).on('vc_reload', init);
11157
11158})(jQuery);
11159
11160(function($) {
11161
11162    'use strict';
11163
11164    var SkillDiagram = function( el ) {
11165        this.el = el;
11166    }
11167
11168    SkillDiagram.prototype = {
11169        init : function() {
11170            this.cacheElements();
11171            this.createDiagram();
11172            this.$skills.each( this.createSkill.bind( this ) );
11173        },
11174
11175        cacheElements : function() {
11176            this.$el = $( this.el );
11177            this.$skills = this.$el.find( '.mk-meter-arch');
11178            this.config  = this.$el.data();
11179            this.config.radius = this.config.dimension / 2;
11180        },
11181
11182        random : function( l, u ) {
11183            return Math.floor( ( Math.random() * ( u - l + 1 ) ) + l );
11184        },
11185
11186        createDiagram : function() {
11187            var self = this;
11188            $(this.el).find('svg').remove();
11189
11190            this.diagram = Raphael( this.el, this.config.dimension, this.config.dimension );
11191
11192            // Make svg scalable in different screen sizes
11193            this.diagram.setViewBox(0,0,this.config.dimension,this.config.dimension,true);
11194            this.diagram.setSize('90%', '90%');
11195
11196            this.diagram.circle( this.config.radius, this.config.radius, 80 ).attr({
11197                stroke: 'none',
11198                fill: this.config.circleColor
11199            });
11200
11201            // Export title
11202            this.title = this.diagram.text( this.config.radius, this.config.radius, this.config.defaultText ).attr({
11203                font: "22px helvetica",
11204                fill: this.config.defaultTextColor
11205            }).toFront();
11206
11207            this.diagram.customAttributes.arc = function(value, color, rad){
11208                var v = 3.6 * value,
11209                    alpha = v == 360 ? 359.99 : v,
11210                    r  = self.random( 91, 240 ),
11211                    a  = (r - alpha) * Math.PI/180,
11212                    b  = r * Math.PI/180,
11213                    sx = self.config.radius + rad * Math.cos(b),
11214                    sy = self.config.radius - rad * Math.sin(b),
11215                    x  = self.config.radius + rad * Math.cos(a),
11216                    y  = self.config.radius - rad * Math.sin(a),
11217                    path = [['M', sx, sy], ['A', rad, rad, 0, +(alpha > 180), 1, x, y]];
11218
11219                return {
11220                    path: path,
11221                    stroke: color
11222                }
11223            }
11224        },
11225
11226        createSkill : function( id, el ) {
11227            var self   = this,
11228                $this  = $( el ),
11229                config = $this.data(),
11230                radMin = 72,
11231                radVal = 27,
11232                newRad = radMin + ( radVal * (id + 1) );
11233
11234            var $path = this.diagram.path().attr({
11235                'stroke-width': 28,
11236                arc: [config.percent, config.color, newRad]
11237            });
11238
11239            $path.mouseover( function() {
11240                self.showSkill( this, config.name, config.percent );
11241            }).mouseout( function() {
11242                self.hideSkill( this )
11243            });
11244        },
11245
11246        showSkill : function( self, name, percent ) {
11247            var $this = self,
11248                time = 250;
11249
11250            //solves IE problem
11251            if(Raphael.type != 'VML') $this.toFront();
11252
11253            $this.animate({
11254                'stroke-width': 50,
11255                'opacity': 0.9,
11256            }, 800, 'elastic' );
11257
11258            this.title.stop()
11259                .animate({ opacity: 0 }, time, '>', function(){
11260                    this.attr({ text: name + '\n' + percent + '%' }).animate({ opacity: 1 }, time, '<');
11261                }).toFront();
11262        },
11263
11264        hideSkill : function( self ) {
11265            var $this = self,
11266                self = this,
11267                time = 250;
11268
11269            $this.stop().animate({
11270                'stroke-width': 28,
11271                opacity: 1
11272            }, time * 4, 'elastic' );
11273
11274            self.title.stop()
11275                .animate({ opacity: 0 }, time, '>', function(){
11276                    self.title.attr({ text: self.config.defaultText })
11277                    .animate({ opacity: 1 }, time, '<');
11278                });
11279        }
11280    }
11281
11282    var init = function init() {
11283        if( typeof Raphael === 'undefined' ) return;
11284        $( '.mk-skill-diagram' ).each( function() {
11285            var diagram = new SkillDiagram( this );
11286                diagram.init();
11287        });
11288    }
11289
11290    init();
11291    $(window).on('vc_reload', init);
11292
11293})(jQuery);
11294
11295/*
11296 * Tab delegation 
11297 * Action for modules when we don't have access to chidren DOM on processing templates
11298 * yet we want ass option of opening link in new tab. 
11299 * Helpful for use with external widgets like flickr
11300 */
11301
11302(function($) {
11303
11304	'use strict';
11305
11306	$( '[data-js="tab-delegation"]' ).each( tabDelegation );
11307
11308	function tabDelegation() {
11309		var $this = $( this ),
11310			data  = $this.data();
11311
11312		// Create delegation on parent element to affect async loaded children
11313		if( data.tab ) $this.on( 'click', 'a', openInTab );
11314	}
11315
11316	function openInTab( e ) {
11317		e.preventDefault(); 
11318
11319		var $this = $( this ),
11320			url = $this.attr( 'href' );
11321
11322		window.open( url, '_blank' );
11323	}
11324
11325})(jQuery);
11326(function($) {
11327    'use strict';
11328
11329    var init = function init() {
11330        var Toggle = function(el) {
11331        var that = this,
11332            $el = $(el);
11333
11334            this.$el = $el;
11335            $el.on('click', function() {
11336                $el.hasClass('active-toggle') ? that.close() : that.open()
11337            });
11338        };
11339
11340        Toggle.prototype.dom = {
11341            pane   : 'mk-toggle-pane',
11342            active : 'active-toggle'
11343        };
11344
11345        Toggle.prototype.open = function() {
11346            var $this = this.$el;
11347            $this.addClass(this.dom.active);
11348            $this.siblings('.' + this.dom.pane).slideDown(200);
11349        };
11350
11351        Toggle.prototype.close = function() {
11352            var $this = this.$el;
11353            $this.removeClass(this.dom.active);
11354            $this.siblings('.' + this.dom.pane).slideUp(200);
11355        };
11356
11357        // Apply to.
11358        var $toggle = $('.mk-toggle-title');
11359
11360        if(!$toggle.length) return;
11361
11362        $toggle.each(function() {
11363            new Toggle(this);
11364        });
11365    }
11366    $(window).on('load vc_reload', init);
11367
11368})(jQuery);
11369
11370//////////////////////////////////////////////////////////////////////////
11371//
11372//   Init all scripts
11373//
11374//////////////////////////////////////////////////////////////////////////
11375
11376// This is bad but we don't have other access to this scope.
11377// Ajax Portfolio  is defined as plugin and on success needs these to be reinited
11378// We'll refactor all of this.
11379window.ajaxInit = function() {
11380    mk_lightbox_init();
11381    mk_click_events();
11382    mk_social_share_global();
11383   // mk_social_share();
11384    mk_gallery();
11385    loop_audio_init();
11386};
11387
11388window.ajaxDelayedInit = function() {
11389    mk_flexslider_init();
11390    // mk_portfolio_ajax();
11391};
11392
11393$(document).ready(function() {
11394    mk_lightbox_init();
11395    mk_login_form();
11396    mk_backgrounds_parallax();
11397    mk_flexslider_init();
11398    mk_event_countdown();
11399    mk_skill_meter();
11400    mk_milestone();
11401    mk_ajax_search();
11402    mk_hover_events();
11403    mk_portfolio_ajax();
11404    product_loop_add_cart();
11405  //  mk_social_share();
11406    loop_audio_init();
11407    mk_portfolio_widget();
11408    mk_contact_form();
11409    mk_blog_carousel();
11410    mk_header_searchform();
11411    mk_click_events();
11412    mk_text_typer();
11413    mk_tab_slider_func();
11414    mkPositionSidebar();
11415
11416    $(window).on('load', function() {
11417        mk_unfold_footer();
11418        mk_tabs();
11419        mk_accordion_toggles_tooltip();
11420        mk_gallery();
11421        mk_theatre_responsive_calculator();
11422        mk_tabs_responsive();
11423        mk_start_tour_resize();
11424        mk_header_social_resize();
11425        mk_page_section_social_video_bg();
11426        mk_one_page_scroller();
11427
11428        setTimeout(function() {
11429            /*
11430                Somehow the values are not correctly updated for the screens
11431                and we need to put setTimeout to fix the issue
11432            */
11433            mk_mobile_tablet_responsive_calculator();
11434        }, 300);
11435
11436        console.log("ready for rock");
11437    });
11438
11439
11440    var onDebouncedResize = function() {
11441        mk_theatre_responsive_calculator();
11442        mk_mobile_tablet_responsive_calculator();
11443        mk_tabs_responsive();
11444        mk_accordion_toggles_tooltip();
11445        mk_start_tour_resize();
11446        mk_header_social_resize();
11447
11448        setTimeout(function() {
11449            mk_unfold_footer();
11450        }, 300);
11451    };
11452
11453    var debounceResize = null;
11454    $(window).on("resize", function() {
11455        if( debounceResize !== null ) { clearTimeout( debounceResize ); }
11456        debounceResize = setTimeout( onDebouncedResize, 300 );
11457    });
11458
11459    var onDebouncedScroll = function() {
11460        mk_skill_meter();
11461        //TODO: Ask to Bart how we can call javascript component
11462        //mk_charts();
11463        mk_milestone();
11464    };
11465
11466    var debounceScroll = null;
11467    $(window).on("scroll", function() {
11468        if( debounceScroll !== null ) { clearTimeout( debounceScroll ); }
11469        debounceScroll = setTimeout( onDebouncedScroll, 100 );
11470    });
11471
11472    if (MK.utils.isMobile()) {
11473        $('body').addClass('no-transform');
11474    }
11475
11476});
11477
11478/* VC frontend editor  */
11479/* -------------------------------------------------------------------- */
11480$(window).on("vc_reload",function () {
11481    mk_flexslider_init();
11482    loop_audio_init();
11483    mk_tab_slider_func();
11484    mk_event_countdown();
11485    videoLoadState();
11486    mk_page_section_social_video_bg();
11487    mk_hover_events();
11488
11489    setTimeout(function() {
11490        mkPositionSidebar();
11491    }, 200);
11492});
11493
11494// Replace this if new event for remove found.
11495$( document ).on( 'click', '.vc_control-btn-delete', function() {
11496    $( window ).trigger( 'vc_reload' );
11497} );
11498
11499$( document ).on( 'sortupdate', '.ui-sortable', function() {
11500    $( window ).trigger( 'vc_reload' );
11501} );
11502
11503/* Typer */
11504/* -------------------------------------------------------------------- */
11505function mk_text_typer() {
11506
11507    "use strict";
11508
11509    $('[data-typer-targets]').each(function() {
11510        var that = this;
11511        MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.typed.js' ], function() {
11512            var $this = $(that),
11513                $first_string = [$this.text()],
11514                $rest_strings = $this.attr('data-typer-targets').split(','),
11515                $strings = $first_string.concat($rest_strings);
11516
11517            $this.text('');
11518
11519            $this.typed({
11520                strings: $strings,
11521                typeSpeed: 30, // typing speed
11522                backDelay: 1200, // pause before backspacing
11523                loop: true, // loop on or off (true or false)
11524                loopCount: false, // number of loops, false = infinite
11525            });
11526        });
11527    });
11528}
11529
11530
11531
11532/* Tab Slider */
11533/* -------------------------------------------------------------------- */
11534
11535function mk_tab_slider_func() {
11536
11537    "use strict";
11538
11539    $('.mk-tab-slider').each(function() {
11540        var that = this;
11541
11542        MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.swiper.js' ], function() {
11543            var $this = $(that),
11544                id = $this.data('id'),
11545                $autoplayTime = $this.data('autoplay'),
11546                $content = $('.mk-slider-content');
11547
11548            var mk_tab_slider = $this.swiper({
11549                wrapperClass: 'mk-tab-slider-wrapper',
11550                slideClass: 'mk-tab-slider-item',
11551                calculateHeight: true,
11552                speed: 500,
11553                autoplay: isTest ? false : $autoplayTime,
11554                onSlideChangeStart: function() {
11555                    $('.mk-tab-slider-nav[data-id="' + id + '"]').find(".active").removeClass('active')
11556                    $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").eq(mk_tab_slider.activeIndex).addClass('active')
11557                }
11558            });
11559
11560            // Simple repaint for firefox issue (can't handle 100% height after plugin init)
11561            function repaintFirefox() {
11562                $content.css('display','block');
11563                setTimeout(function() {
11564                    mk_tab_slider.reInit();
11565                    $content.css('display','table');
11566                },100);
11567            }
11568
11569            $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").first().addClass('active');
11570
11571            $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").on('touchstart mousedown', function(e) {
11572                e.preventDefault()
11573                $('.mk-tab-slider-nav[data-id="' + id + '"]').find(".active").removeClass('active')
11574                $(this).addClass('active')
11575                mk_tab_slider.swipeTo($(this).index())
11576            });
11577
11578            $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").on('click',function(e) {
11579                e.preventDefault();
11580            });
11581
11582            repaintFirefox();
11583            $(window).on('resize', repaintFirefox);
11584        });
11585
11586    });
11587
11588}
11589
11590
11591
11592/* Edge One Pager */
11593/* -------------------------------------------------------------------- */
11594function mk_one_page_scroller() {
11595
11596    "use strict";
11597
11598    $('.mk-edge-one-pager').each(function() {
11599        var self = this;
11600
11601        MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.fullpage.js' ], function() {
11602
11603            var $this = $(self),
11604                anchorArr = [];
11605
11606            $this.find('.section').each(function() {
11607                anchorArr.push($(this).attr('data-title'));
11608            });
11609
11610            var scrollable = true;
11611            $this.find('.section').each(function() {
11612                var $section = $(this),
11613                    $content = $section.find('.edge-slide-content'),
11614                    sectionHeight = $section.height(),
11615                    contentHeight = $content.innerHeight();
11616
11617                if((contentHeight + 30) > $(window).height()) {
11618                    scrollable = false;
11619                }
11620            });
11621
11622            if(!scrollable){
11623                $this.find('.section').each(function() {
11624                    var $section = $(this);
11625                    $section.addClass('active').css({
11626                        'padding-bottom': '50px'
11627                    });
11628                });
11629            }
11630
11631            if(scrollable) {
11632                $this.fullpage({
11633                    verticalCentered: false,
11634                    resize: true,
11635                    slidesColor: ['#ccc', '#fff'],
11636                    anchors: anchorArr,
11637                    scrollingSpeed: 600,
11638                    easing: 'easeInQuart',
11639                    menu: false,
11640                    navigation: true,
11641                    navigationPosition: 'right',
11642                    navigationTooltips: false,
11643                    slidesNavigation: true,
11644                    slidesNavPosition: 'bottom',
11645                    loopBottom: false,
11646                    loopTop: false,
11647                    loopHorizontal: true,
11648                    autoScrolling: true,
11649                    scrollOverflow: false,
11650                    css3: true,
11651                    paddingTop: 0,
11652                    paddingBottom: 0,
11653                    normalScrollElements: '.mk-header, .mk-responsive-wrap',
11654                    normalScrollElementTouchThreshold: 5,
11655                    keyboardScrolling: true,
11656                    touchSensitivity: 15,
11657                    continuousVertical: false,
11658                    animateAnchor: true,
11659
11660                    onLeave: function(index, nextIndex, direction) {
11661                        var currentSkin = $this.find('.one-pager-slide').eq(nextIndex - 1).attr('data-header-skin');
11662                        MK.utils.eventManager.publish( 'firstElSkinChange', currentSkin );
11663                        $('#fullPage-nav').removeClass('light-skin dark-skin').addClass(currentSkin + '-skin');
11664
11665                    },
11666                    afterRender: function() {
11667
11668                        var $nav = $('#fullPage-nav');
11669
11670                        setTimeout(function() {
11671                            var currentSkin = $this.find('.one-pager-slide').eq(0).attr('data-header-skin');
11672                            MK.utils.eventManager.publish( 'firstElSkinChange', currentSkin );
11673                            if($nav.length) $nav.removeClass('light-skin dark-skin').addClass(currentSkin + '-skin');
11674                        }, 300);
11675
11676                        var $slide = $this.find('.section'),
11677                            headerHeight = MK.val.offsetHeaderHeight(0),
11678                            windowHeight = $(window).height();
11679
11680                        $slide.height(windowHeight - headerHeight);
11681
11682                        if($nav.length) {
11683                            $nav.css({
11684                                'top': 'calc(50% + ' + (headerHeight/2) + 'px)',
11685                                'marginTop': 0
11686                            });
11687
11688                            var style = $this.attr('data-pagination');
11689                            $nav.addClass('pagination-' + style);
11690                        }
11691
11692                        setTimeout(mk_one_pager_resposnive, 1000);
11693                    },
11694                    afterResize: function() {
11695                        var $slide = $this.find('.section'),
11696                            headerHeight = MK.val.offsetHeaderHeight(0),
11697                            windowHeight = $(window).height();
11698
11699                        $slide.height(windowHeight - headerHeight);
11700
11701                        $('#fullPage-nav').css({
11702                            'top': 'calc(50% + ' + (headerHeight/2) + 'px)',
11703                            'marginTop': 0
11704                        });
11705
11706                        setTimeout(mk_one_pager_resposnive, 1000);
11707                        console.log('Reposition pager content.');
11708                    },
11709                });
11710            }
11711
11712            // Linking to slides available for desktop and mobile scenarios
11713            function swipeTo(href, e) {
11714                href = '_' + href; // ensure a char before #
11715                if (!~href.indexOf('#')) return;
11716                var section = href.split('#')[1];
11717                if (~anchorArr.indexOf(section)) {
11718                    if (typeof e !== 'undefined') e.preventDefault();
11719                    if (scrollable) $.fn.fullpage.moveTo(section);
11720                    else MK.utils.scrollToAnchor('[data-title="'+section+'"]');
11721                }
11722            }
11723
11724            // onload
11725            var loc = window.location;
11726            if(loc.hash) swipeTo(loc.hash);
11727
11728            $(document).on('click', 'a', function(e) {
11729                var $link = $(e.currentTarget);
11730                swipeTo($link.attr('href'), e);
11731            });
11732        });
11733    });
11734
11735
11736
11737}
11738
11739
11740function mk_one_pager_resposnive() {
11741    "use strict";
11742
11743    $('.mk-edge-one-pager').each(function() {
11744        var $pager = $(this),
11745            headerHeight = MK.val.offsetHeaderHeight(0),
11746            windowHeight = $(window).height() - headerHeight;
11747
11748        $pager.find('.one-pager-slide').each(function() {
11749            var $slide = $(this),
11750                $content = $slide.find('.edge-slide-content');
11751
11752            if ($slide.hasClass('left_center') || $slide.hasClass('center_center') || $slide.hasClass('right_center')) {
11753                var contentHeight  = $content.height(),
11754                    distanceFromTop = (windowHeight - contentHeight) / 2;
11755
11756                distanceFromTop  = (distanceFromTop < 50) ? 50 + headerHeight : distanceFromTop;
11757
11758                $content.css('marginTop', distanceFromTop);
11759            }
11760
11761            if ($slide.hasClass('left_bottom') || $slide.hasClass('center_bottom') || $slide.hasClass('right_bottom')) {
11762                var distanceFromTop = windowHeight - $content.height() - 90;
11763                $content.css('marginTop', (distanceFromTop));
11764            }
11765        });
11766
11767        /**
11768         * Fix AM-2853
11769         *
11770         * @since 6.0.3
11771         *
11772         * At the init of Edge One Pager (EOP), EOP will render all image
11773         * background of each sections from top to bottom. In this case,
11774         * the page height will be more than screen height and the scroll
11775         * bar will appear. At the same time, the full width row will set
11776         * the container width into 100%. But, after all Slides are set up,
11777         * EOP height will be 100% of the screen height, so the scroll bar
11778         * will be disappeared. It's caused spacing issues on the left and
11779         * right side of the EOP container. To fix this, the row width
11780         * should be resized and row position should be readjusted.
11781         */
11782        var $row = $pager.parents( '.vc_row.vc_row-fluid.mk-fullwidth-true' );
11783
11784        // Run only if the Edge One Pager is wrapped inside full width row.
11785        if ( $row.length > 0 ) {
11786            // Set the wrapper and row width.
11787            var $wrapper = $( '.mk-main-wrapper-holder' );
11788            var $grid = $row.children( '.mk-grid' );
11789            var rowWidth = $row.width();         // Original width.
11790            var wrapperWidth = $wrapper.width(); // The new width.
11791
11792            // Run only if original width is smaller than the new width.
11793            if ( rowWidth >= wrapperWidth || $grid.length > 0 ) {
11794                return;
11795            }
11796
11797            // Get the content left offset.
11798            var $content = $wrapper.find( '.theme-content' );
11799            var oriPos = $content.position();
11800            var oriPadLeft = $content.css( 'padding-left' );
11801            var oriLeft = parseInt( oriPos.left ) + parseInt( oriPadLeft );
11802
11803            // Ensure the new width and left position is more than 0.
11804            if ( wrapperWidth <= 0 || oriLeft <= 0 ) {
11805                return;
11806            }
11807
11808            // Resize the width and left position of row full width.
11809            $row.css({
11810                'width': wrapperWidth,
11811                'left': oriLeft * -1,
11812            });
11813        }
11814    });
11815}
11816
11817/* Image Gallery */
11818/* -------------------------------------------------------------------- */
11819
11820function mk_gallery() {
11821
11822    "use strict";
11823
11824    $('.mk-gallery .mk-gallery-item.hover-overlay_layer .item-holder').each(function() {
11825        var itemHolder = $(this),
11826            galleryDesc = itemHolder.find('.gallery-desc');
11827
11828        function updatePosition() {
11829            var parentHeight = itemHolder.outerHeight(),
11830                contentHeight = galleryDesc.innerHeight();
11831
11832            var paddingVal = (parentHeight - contentHeight) / 2;
11833            galleryDesc.css({
11834                'top': paddingVal,
11835                // 'padding-bottom': paddingVal
11836            });
11837
11838            // console.log(parentHeight);
11839            // console.log(contentHeight);
11840
11841
11842        }
11843        updatePosition();
11844
11845        $(window).on('resize', function() {
11846            setTimeout(function() {
11847                updatePosition();
11848            }, 1000);
11849        });
11850    });
11851    // Execute hover state for mk gallery item
11852    if ($(window).width() <= 1024) {
11853        $('.mk-gallery .mk-gallery-item').on('click', function (e) {
11854            var clicks = $(this).data('clicks');
11855            if (clicks) {
11856                // First click
11857                $(this).toggleClass('hover-state');
11858            } else {
11859                // Second click
11860                $(this).toggleClass('hover-state');
11861            }
11862            $(this).data("clicks", !clicks);
11863        });
11864    }
11865}
11866
11867/* Theatre Slider Responsive Calculator */
11868/* -------------------------------------------------------------------- */
11869
11870function mk_theatre_responsive_calculator() {
11871    var $laptopContainer = $(".laptop-theatre-slider");
11872    var $computerContainer = $(".desktop-theatre-slider");
11873    $laptopContainer.each(function() {
11874        var $this = $(this),
11875            $window = $(window),
11876            $windowWidth = $window.outerWidth(),
11877            $windowHeight = $window.outerHeight(),
11878            $width = $this.outerWidth(),
11879            $height = $this.outerHeight(),
11880            $paddingTop = 38,
11881            $paddingRight = 143,
11882            $paddingBottom = 78,
11883            $paddingLeft = 143;
11884
11885        var $player = $this.find('.player-container');
11886
11887        if ($windowWidth > $width) {
11888            $player.css({
11889                'padding-left': parseInt(($width * $paddingLeft) / 1200),
11890                'padding-right': parseInt(($width * $paddingRight) / 1200),
11891                'padding-top': parseInt(($height * $paddingTop) / 690),
11892                'padding-bottom': parseInt(($height * $paddingBottom) / 690),
11893            });
11894        }
11895
11896    });
11897
11898    $computerContainer.each(function() {
11899        var $this = $(this),
11900            $window = $(window),
11901            $windowWidth = $window.outerWidth(),
11902            $windowHeight = $window.outerHeight(),
11903            $width = $this.outerWidth(),
11904            $height = $this.outerHeight(),
11905            $paddingTop = 60,
11906            $paddingRight = 52,
11907            $paddingBottom = 290,
11908            $paddingLeft = 49;
11909
11910        var $player = $this.find('.player-container');
11911
11912        if ($windowWidth > $width) {
11913            $player.css({
11914                'padding-left': parseInt(($width * $paddingLeft) / 1200),
11915                'padding-right': parseInt(($width * $paddingRight) / 1200),
11916                'padding-top': parseInt(($height * $paddingTop) / 969),
11917                'padding-bottom': parseInt(($height * $paddingBottom) / 969),
11918            });
11919        }
11920
11921    });
11922
11923}
11924
11925/* Mobile and Tablet Slideshow Responsive Calculator */
11926/* -------------------------------------------------------------------- */
11927function mk_mobile_tablet_responsive_calculator() {
11928    var $laptopSlideshow = $(".mk-laptop-slideshow-shortcode");
11929    var $lcdSlideshow = $(".mk-lcd-slideshow");
11930
11931    if ($.exists(".mk-laptop-slideshow-shortcode")) {
11932        $laptopSlideshow.each(function() {
11933            var $this = $(this),
11934                $window = $(window),
11935                $windowWidth = $window.outerWidth(),
11936                $windowHeight = $window.outerHeight(),
11937                $width = $this.outerWidth(),
11938                $height = $this.outerHeight(),
11939                $paddingTop = 28,
11940                $paddingRight = 102,
11941                $paddingBottom = 52,
11942                $paddingLeft = 102;
11943
11944            var $player = $this.find(".slideshow-container");
11945
11946            $player.css({
11947                "padding-left": parseInt(($width * $paddingLeft) / 836),
11948                "padding-right": parseInt(($width * $paddingRight) / 836),
11949                "padding-top": parseInt(($height * $paddingTop) / 481),
11950                "padding-bottom": parseInt(($height * $paddingBottom) / 481),
11951            });
11952
11953        });
11954    }
11955
11956    if ($.exists(".mk-lcd-slideshow")) {
11957        $lcdSlideshow.each(function() {
11958            var $this = $(this),
11959                $window = $(window),
11960                $windowWidth = $window.outerWidth(),
11961                $windowHeight = $window.outerHeight(),
11962                $width = $this.outerWidth(),
11963                $height = $this.outerHeight(),
11964                $paddingTop = 35,
11965                $paddingRight = 39,
11966                $paddingBottom = 213,
11967                $paddingLeft = 36;
11968
11969            var $player = $this.find(".slideshow-container");
11970            $player.css({
11971                "padding-left": parseInt(($width * $paddingLeft) / 886),
11972                "padding-right": parseInt(($width * $paddingRight) / 886),
11973                "padding-top": parseInt(($height * $paddingTop) / 713),
11974                "padding-bottom": parseInt(($height * $paddingBottom) / 713),
11975            });
11976        });
11977    }
11978}
11979
11980
11981/* Start a tour resize function */
11982/* -------------------------------------------------------------------- */
11983function mk_start_tour_resize() {
11984
11985    $('.mk-header-start-tour').each(function() {
11986
11987        var $windowWidth = $(document).width(),
11988            $this = $(this),
11989            $linkWidth = $this.width() + 15,
11990            $padding = ($windowWidth - mk_responsive_nav_width) / 2;
11991
11992
11993
11994        function updateStartTour(){
11995            if($windowWidth < mk_responsive_nav_width){
11996                $this.removeClass('hidden');
11997                $this.addClass('show');
11998            }else{
11999                if($padding < $linkWidth){
12000                    $this.removeClass('show');
12001                    $this.addClass('hidden');
12002                }else{
12003                    $this.removeClass('hidden');
12004                    $this.addClass('show');
12005                }
12006            }
12007        }
12008
12009        setTimeout(function() {
12010            updateStartTour();
12011        }, 300);
12012    });
12013}
12014
12015/* Header social resize function */
12016/* -------------------------------------------------------------------- */
12017function mk_header_social_resize() {
12018
12019    $('.mk-header-social.header-section').each(function() {
12020
12021        var $windowWidth = $(document).width(),
12022            $this = $(this),
12023            $linkWidth = $this.width() + 15,
12024            $padding = ($windowWidth - mk_responsive_nav_width) / 2;
12025
12026
12027
12028        function updateStartTour(){
12029            if($windowWidth < mk_responsive_nav_width){
12030                $this.removeClass('hidden');
12031                $this.addClass('show');
12032            }else{
12033                if($padding < $linkWidth){
12034                    $this.removeClass('show');
12035                    $this.addClass('hidden');
12036                }else{
12037                    $this.removeClass('hidden');
12038                    $this.addClass('show');
12039                }
12040            }
12041        }
12042
12043        setTimeout(function() {
12044            updateStartTour();
12045        }, 300);
12046    });
12047}
12048
12049/* Page Section Socail Video Player Controls */
12050/* -------------------------------------------------------------------- */
12051
12052function mk_page_section_social_video_bg() {
12053    $(".mk-page-section.social-hosted").each(function() {
12054        var $container = $(this),
12055            $sound = $container.data('sound'),
12056            $source = $container.data('source'),
12057            player,
12058            timer = 1000;
12059
12060        if ( $( 'body' ).hasClass( '.compose-mode' ) ) {
12061            timer = 2000;
12062        }
12063
12064        if ($source == 'youtube') {
12065            var youtube = $container.find('iframe')[0];
12066            try {
12067                player = new YT.Player(youtube, {
12068                    events: {
12069                        'onReady': function () {
12070                           player.playVideo();
12071                           if($sound == false) {
12072                               player.mute();
12073                           }
12074                       }
12075                    }
12076                });
12077
12078
12079            } catch (e) {
12080            	console.log( e );
12081            }
12082        }
12083        if ($source == 'vimeo') {
12084            var vimeo = $container.find('iframe')[0];
12085            player = $f(vimeo);
12086            setTimeout(function() {
12087                player.api('play');
12088                if($sound === false) {
12089                    player.api('setVolume', 0);
12090                }
12091            }, timer);
12092        }
12093
12094    });
12095}
12096
12097// Pre RequireJS hot bug fixing
12098
12099function videoLoadState() {
12100    $('.mk-section-video video').each(function() {
12101        var mkVideo = this;
12102
12103        mkVideo.play();
12104        this.onload = fire();
12105
12106        function fire() {
12107            setTimeout(function() {
12108                $(mkVideo).animate({
12109                    'opacity': 1
12110                }, 300);
12111            }, 1000);
12112        }
12113    });
12114}
12115videoLoadState();
12116
12117
12118// Gmap Widget
12119(function($) {
12120
12121    $(window).on('load vc_reload', initialize);
12122
12123    function initialize() {
12124        var $gmap = $('.gmap_widget');
12125        if($gmap.length && typeof google !== 'undefined') $gmap.each(run);
12126    }
12127
12128    function run() {
12129        var $mapHolder = $(this);
12130        var myLatlng = new google.maps.LatLng($mapHolder.data('latitude'), $mapHolder.data('longitude'));
12131        var mapOptions = $mapHolder.data('options');
12132            mapOptions.mapTypeId = google.maps.MapTypeId.ROADMAP;
12133            mapOptions.center = myLatlng;
12134        var map = new google.maps.Map(this, mapOptions);
12135
12136        new google.maps.Marker({
12137            position: myLatlng,
12138            map: map
12139        });
12140    }
12141
12142}(jQuery));
12143
12144// Instagram Widget
12145(function($) {
12146
12147    $(window).on('load', function() {
12148        var $feeds = $('.mk-instagram-feeds');
12149        if($feeds.length) $feeds.each(run);
12150    });
12151
12152    function run() {
12153        var options = $(this).data('options');
12154            options.template = '<a class="featured-image '+options.tmp_col+'-columns" href="{{link}}" target="_'+options.tmp_target+'"><div class="item-holder"><img src="{{image}}" /><div class="image-hover-overlay"></div></div></a>';
12155        var feed = new Instafeed(options);
12156        feed.run();
12157    }
12158}(jQuery));
12159
12160
12161// Flipbox backface visibility fix for chrome
12162(function($) {
12163     $(window).on('load', function() {
12164         setTimeout( function() {
12165            $('.chrome-flipbox-backface-fix').removeClass('chrome-flipbox-backface-fix');
12166         }, 300);
12167     });
12168}(jQuery));
12169
12170
12171/* Product in VC Tab Bug Fix
12172/* -------------------------------------------------------------------- */
12173(function($) {
12174    $(window).on('load', function() {
12175        $('.vc_tta-tab a').on('click', function() {
12176            setTimeout( function() {
12177                $(window).trigger('resize');
12178            }, 100);
12179        });
12180    });
12181}(jQuery));
12182
12183
12184/* Vertical menu fix when childrens exceed screen height
12185/* -------------------------------------------------------------------- */
12186(function($) {
12187    $(window).on('load', function() {
12188        $('#mk-vm-menu .menu-item-has-children, #mk-vm-menu .mk-vm-back').on('mouseenter', function() {
12189            var $header_inner = $(this).closest('.mk-header-inner'),
12190                $header_inner_height = $header_inner.outerHeight(),
12191                $header_bg = $header_inner.find('.mk-header-bg'),
12192                total_height = 0;
12193            $header_bg.css('height', '100%');
12194            setTimeout( function() {
12195                $header_inner.children(':visible').each(function() {
12196                    total_height += $(this).outerHeight(true);
12197                });
12198                total_height -= $header_bg.height();
12199                if ( total_height < $header_inner_height ) {
12200                    $header_bg.css('height', '100%');
12201                } else {
12202                    $header_bg.css('height', total_height + 'px');
12203                }
12204            }, 600);
12205        });
12206    });
12207}(jQuery));
12208
12209
12210/* Woocommerce varitions lightbox fix
12211/* -------------------------------------------------------------------- */
12212(function($) {
12213    $(window).on('load', function() {
12214
12215        if ( $('.woo-variation-gallery-thumbnail-wrapper').length > 0 ) {
12216            return;
12217        }
12218
12219        var $variations_form = $('.variations_form');
12220
12221        if ( $variations_form.length ) {
12222
12223            var $varitions_selects = $variations_form.find('.variations').find('.value').find('select');
12224            $varitions_selects.on('change', function() {
12225
12226                // Woocommerce variations lightbox with galleries
12227                var $all_img_container = $('.mk-product-image .mk-woocommerce-main-image');
12228                if ( $all_img_container.length ) {
12229                    $( $all_img_container ).each( set_lightbox_href );
12230                }
12231
12232            });
12233            $varitions_selects.trigger('change');
12234
12235        }
12236
12237    });
12238
12239    function set_lightbox_href() {
12240
12241        var $product_img = $( this ).find( 'img' ),
12242            $lightbox    = $( this ).find( '.mk-lightbox' );
12243
12244        setTimeout( function() {
12245            var image_url    = $product_img.attr( 'src' ),
12246                image_suffix = image_url.substr( image_url.lastIndexOf('.') - image_url.length ), // Get image suffix
12247                image_url    = image_url.slice( 0 , image_url.lastIndexOf('-') ); // Remove image size
12248            $lightbox.attr('href', image_url + image_suffix );
12249        }, 300);
12250    }
12251
12252}(jQuery));
12253
12254
12255/* Remove video section when on mobile */
12256/* -------------------------------------------------------------------- */
12257if( ! MK.utils.showBackgroundVideo ) {
12258	(function($) {
12259		if ( MK.utils.isMobile() ) {
12260		  $('.mk-section-video video').remove();
12261		  $('.mk-section-video').addClass('mk-section-video-disable');
12262		}
12263	}(jQuery));
12264}
12265
12266
12267/* Yith AJAX Product Filter & Yith Infinite Scrolling Plugin Fix
12268/* -------------------------------------------------------------------- */
12269(function($) {
12270    $(window).on('load', function() {
12271
12272        $(document).on( 'yith-wcan-ajax-filtered yith_infs_added_elem yith-wcan-ajax-reset-filtered', function(){
12273            setTimeout( function() {
12274                MK.utils.eventManager.publish('ajaxLoaded');
12275                MK.core.initAll( document );
12276            }, 1000 );
12277        });
12278
12279        // Fixed YITH Filter plugin causes issue for dropdown sort
12280        $(document).on( 'yith-wcan-ajax-filtered yith-wcan-ajax-reset-filtered', function(){
12281            setTimeout( function() {
12282                $( '.woocommerce-ordering' ).on( 'change', 'select.orderby', function() {
12283                    $( this ).closest( 'form' ).submit();
12284                });
12285            }, 1000 );
12286        });
12287
12288    });
12289}(jQuery));
12290
12291
12292/* Toggle loading state in URL for anchor links.
12293 * - Add a filter to escape meta-chars from hash string.
12294/* -------------------------------------------------------------------- */
12295!function(e){var a=window.location,n=a.hash;if(n.length&&n.substring(1).length){var hSuf = n.substring(1).replace(/[!"#$%&'()*+,./:;<=>?@[\]^`{|}~]/g, "\\$&");var r=e(".vc_row, .mk-main-wrapper-holder, .mk-page-section, #comments"),t=r.filter("#"+hSuf);if(!t.length)return;n=n.replace("!loading","");var i=n+"!loading";a.hash=i}}(jQuery);
12296
12297
12298/* Determine the top spacing of sidebar for full-width page section & row.
12299/* -------------------------------------------------------------------- */
12300function mkPositionSidebar() {
12301
12302	var themeContent = $( '.theme-content' ),
12303		lastFullWidthChild = themeContent.find( '.vc_row-full-width' ).last(),
12304		top,
12305		sidebar = $( '#theme-page > .mk-main-wrapper-holder > .theme-page-wrapper > #mk-sidebar' );
12306
12307	if ( ! lastFullWidthChild.length ) {
12308		sidebar.removeAttr( 'style' );
12309		return;
12310	}
12311
12312	top = lastFullWidthChild.offset().top - themeContent.offset().top;
12313	sidebar.css( 'padding-top', top );
12314}
12315
12316function mk_accordion_toggles_tooltip() {
12317
12318  "use strict";
12319
12320
12321  /* Message Boxes */
12322  /* -------------------------------------------------------------------- */
12323
12324  $('.box-close-btn').on('click', function() {
12325    $(this).parent().fadeOut(300);
12326    return false;
12327
12328  });
12329
12330}
12331
12332function mk_portfolio_ajax() {
12333  "use strict";
12334
12335  var headerHeight = 0;
12336  if ($.exists("#wpadminbar")) {
12337    headerHeight += $("#wpadminbar").height();
12338  }
12339  if (!$.exists('.mk-vm-menuwrapper')) {
12340    headerHeight += parseInt($('.mk-header').attr('data-sticky-height'));
12341  }
12342
12343  function init() {
12344    var $portfolio = $('.portfolio-grid.portfolio-ajax-enabled');
12345    if (!$portfolio.length) return; // quit if no portfolio wrappers
12346    MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.ajax.portfolio.js' ], function() {
12347      // wait for ajax response propagation and insertion
12348      setTimeout(function() {
12349        $portfolio.each( function() {
12350          $(this).ajaxPortfolio({ extraOffset: headerHeight });
12351        });
12352      }, 100);
12353    });
12354  }
12355
12356  init();
12357
12358  // Reinit when ajax loaded stuff
12359  // We have global reinit on Components. so move the ajaxPortfolio to component namespace as a standalone module to get it right.
12360  MK.utils.eventManager.subscribe('ajaxLoaded', init);
12361}
12362
12363/**
12364 * Ajax Search on header nav.
12365 */
12366function mk_ajax_search() {
12367    "use strict";
12368
12369    // Check if ajax search box enabled.
12370    if (mk_ajax_search_option !== "beside_nav") {
12371        return;
12372    }
12373
12374    // Set minimum length of text to get ajax result.
12375    var minimumLengthToSearch = 3;
12376    var $mkAjaxSearchInput = $('#mk-ajax-search-input');
12377    var security = $mkAjaxSearchInput.siblings('input[name="security"]').val();
12378    var wpHttpReferer = $mkAjaxSearchInput.siblings('input[name="_wp_http_referer"]').val();
12379    var querySpliter = (ajaxurl.indexOf('?') > -1) ? '&' : '?';
12380    var ul = document.getElementById('mk-nav-search-result');
12381    var searchTerm; // Search term
12382    var requestCounter = 0;
12383    var responseCounter = 0;
12384
12385    // Add listener for getting result quickly while user entering text, past text and etc.
12386    $mkAjaxSearchInput.on('paste input propertychange', onSearchBoxInput);
12387
12388    /**
12389     * Callback function for entering search term listener (e.g. keyup).
12390     * It will generate AJAX request to get data.
12391     *
12392     * @param e
12393     */
12394    function onSearchBoxInput(e) {
12395        var target = e.target || e.srcElement;
12396        var newValue = target.value;
12397
12398        // Check if user change the value of text box
12399        if (searchTerm !== newValue) {
12400            searchTerm = newValue;
12401            ul.innerHTML = '';
12402            if (searchTerm.length >= minimumLengthToSearch) {
12403                // Show loading icon
12404                $mkAjaxSearchInput.addClass('ajax-searching');
12405                requestCounter++;
12406                $.getJSON(ajaxurl + querySpliter + 'callback=?&action=mk_ajax_search&security=' + security + '&_wp_http_referer=' + wpHttpReferer + '&term=' + searchTerm)
12407                    .done(showSearchResult)
12408                    .fail(showErrorMessage);
12409            }
12410        }
12411    }
12412
12413    /**
12414     * Callback function for the response of the search request.
12415     *
12416     * @param data
12417     */
12418    function showSearchResult(data) {
12419        responseCounter++;
12420
12421        // Only show response of latest request.
12422        if (isCorrectResponse()) {
12423            if (data.length > 0) {
12424                // Append result to result container
12425                for (var i = 0; i < data.length; i++) {
12426                    var item = data[i];
12427                    $('<li>').append('<a href="' + item.link + '">' + item.image + '<span class="search-title">' + item.label + '</span><span class="search-date">' + item.date + '</span></a>').appendTo(ul);
12428                }
12429            } else {
12430                // Show no result message
12431                ul.innerHTML = '<li class="mk-nav-search-result-zero">No Result.</li>';
12432            }
12433
12434            // Hide loading icon
12435            $mkAjaxSearchInput.parent('form').removeClass('ajax-searching').addClass('ajax-search-complete');
12436        }
12437    }
12438
12439    /**
12440     * If any errors, we need a handler to show error message.
12441     */
12442    function showErrorMessage() {
12443        responseCounter++;
12444
12445        if (isCorrectResponse()) {
12446            ul.innerHTML = '<li class="mk-nav-search-error-message">Can not search! Please try again.</li>';
12447        }
12448    }
12449
12450    /**
12451     * Check if the response is right for the request. we show latest response only.
12452     *
12453     * @returns {boolean}
12454     */
12455    function isCorrectResponse() {
12456        return requestCounter === responseCounter;
12457    }
12458}
12459/* Background Parallax Effects */
12460/* -------------------------------------------------------------------- */
12461
12462function mk_backgrounds_parallax() {
12463
12464  "use strict";
12465
12466  if (mk_header_parallax == true) {
12467    $('.mk-header-bg').addClass('mk-parallax-enabled');
12468  }
12469  if (mk_body_parallax == true) {
12470    $('body').addClass('mk-parallax-enabled');
12471  }
12472  if (mk_banner_parallax == true) {
12473    $('.mk-header').addClass('mk-parallax-enabled');
12474  }
12475  if (mk_footer_parallax == true) {
12476    $('#mk-footer').addClass('mk-parallax-enabled');
12477  }
12478
12479  $('.mk-parallax-enabled').each(function () {
12480    var $this = $( this );
12481    if (!MK.utils.isMobile()) {
12482      MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.parallax.js' ], function() {
12483        $this.parallax("49%", 0.3);
12484      });
12485    }
12486  });
12487
12488  $('.mk-fullwidth-slideshow.parallax-slideshow').each(function () {
12489    var $this = $( this );
12490    if (!MK.utils.isMobile()) {
12491      MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.parallax.js' ], function() {
12492        var speed_factor = $this.attr('data-speedFactor');
12493        $this.parallax("49%", speed_factor);
12494      });
12495    }
12496  });
12497
12498}
12499/* Blog, Portfolio Audio */
12500/* -------------------------------------------------------------------- */
12501
12502function loop_audio_init() {
12503  if (!$.exists('.jp-jplayer')) {
12504    return;
12505  }
12506
12507  $('.jp-jplayer.mk-blog-audio').each(function () {
12508    var $this = $(this);
12509    var $thisControls = $this.next('.jp-audio');
12510    var audio = $this.find( '.mk-audio' )[0];
12511
12512    // Set initial values.
12513    $thisControls.find('.jp-current-time').text('0:0');
12514    $thisControls.find('.jp-volume-bar-value').css('width', 25);
12515
12516    /*
12517     * When audio data is loaded.
12518     */
12519    audio.addEventListener('loadeddata', jsPlayerloaded(audio, $thisControls), false);
12520
12521    audio.addEventListener('loadedmetadata', function() {
12522      var minutes = Math.floor(audio.duration / 60);
12523      var seconds = Math.floor(audio.duration % 60);
12524
12525      // Update the duration time.
12526      if (!isNaN(minutes)) {
12527        $thisControls.find('.jp-duration').text(minutes + ':' + seconds);
12528      }
12529
12530      // Show play button when audio is loaded.
12531      $thisControls.removeClass('jp-audio-loading').addClass('jp-audio-loaded');
12532    });
12533
12534    /*
12535     * When audio is playing.
12536     */
12537    audio.addEventListener('timeupdate', function() {
12538      var minutes = Math.floor(audio.currentTime / 60);
12539      var seconds = Math.floor(audio.currentTime % 60);
12540
12541      // Update curren time.
12542      $thisControls.find('.jp-current-time').text(minutes + ':' + seconds);
12543
12544      // Convert length of audio to 0 - 100 while keeping ratio.
12545      var position = ((audio.currentTime - 0) / (audio.duration - 0)) * (100 - 0) + 0;
12546
12547      // Update position of progress bar.
12548      $thisControls.find('.jp-play-bar').css('width', position + '%');
12549    });
12550
12551    /*
12552     * When audio is ended.
12553     */
12554    audio.addEventListener('ended', function() {
12555      // Show play button.
12556      $thisControls.removeClass('jp-audio-playing');
12557
12558      // Reset the position of progress bar.
12559      $thisControls.find('.jp-play-bar').css('width', 0);
12560
12561      // Reset the current time.
12562      $thisControls.find('.jp-current-time').text('0:0');
12563    });
12564
12565    /*
12566     * Play the audio.
12567     */
12568    $thisControls.find('.jp-play').on('click', function() {
12569      audio.play();
12570
12571      // Show pause button.
12572      $thisControls.addClass('jp-audio-playing').removeClass('jp-audio-paused');
12573    });
12574
12575    /*
12576     * Pause the audio..
12577     */
12578    $thisControls.find('.jp-pause').on('click', function() {
12579      audio.pause();
12580
12581      // Show play button.
12582      $thisControls.addClass('jp-audio-paused').removeClass('jp-audio-playing');
12583    });
12584
12585    /*
12586     * Mute the audio.
12587     */
12588    $thisControls.find('.jp-volume-bar svg').on('click', function() {
12589      audio.muted = !audio.muted;
12590
12591      $(this).parent().toggleClass('jp-muted');
12592    });
12593
12594    /*
12595     * Adjust the volume.
12596     */
12597    $thisControls.find('.inner-value-adjust').on('click', function(e) {
12598      // Get the posiiton of mouse click, between 0 to 25.
12599      var position = e.pageX - $(this).offset().left;
12600
12601      // Scale the number from 0 - 25 to 0 - 1 while keeping ratio.
12602      var volume = ((position - 0) / (25 - 0)) * (1 - 0) + 0;
12603
12604      // Set volume.
12605      audio.volume = volume;
12606
12607      // Update the position of volume bar.
12608      $(this).find('.jp-volume-bar-value').css('width', position);
12609    });
12610
12611    /*
12612     * Adjust current time from progress bar.
12613     */
12614    $thisControls.find('.jp-seek-bar').on('click', function(e) {
12615      // Get the position of mouse click.
12616      var position = e.pageX - $(this).offset().left;
12617
12618      // Scale the number from 0 - currentTime to 0 - 100 while keeping ratio.
12619      var currnetTime = ((position - 0) / ($(this).width() - 0)) * (audio.duration - 0) + 0;
12620
12621      // Set current time.
12622      audio.currentTime = currnetTime;
12623
12624      // Update the position of progress bar.
12625      $thisControls.find('.jp-play-bar').css('width', currnetTime + '%');
12626    });
12627  });
12628
12629  function jsPlayerloaded(audio, $thisControls) {
12630    var minutes = Math.floor(audio.duration / 60);
12631    var seconds = Math.floor(audio.duration % 60);
12632
12633    // Update the duration time.
12634    if (!isNaN(minutes)) {
12635      $thisControls.find('.jp-duration').text(minutes + ':' + seconds);
12636    }
12637
12638    // Show play button when audio is loaded.
12639    $thisControls.removeClass('jp-audio-loading').addClass('jp-audio-loaded');
12640  }
12641}
12642
12643/* Blog Loop Carousel Shortcode */
12644/* -------------------------------------------------------------------- */
12645
12646
12647function mk_blog_carousel() {
12648
12649  "use strict";
12650
12651  if (!$.exists('.mk-blog-showcase')) {
12652    return;
12653  }
12654  $('.mk-blog-showcase ul li').each(function () {
12655
12656    $(this).mouseenter( function () {
12657
12658      $(this).siblings('li').removeClass('mk-blog-first-el').end().addClass('mk-blog-first-el');
12659
12660    });
12661
12662  });
12663
12664
12665}
12666
12667
12668
12669
12670/**
12671 * Contact Form
12672 *
12673 * Mostly implemented in Vanilla JS instead of jQuery.
12674 */
12675function mk_contact_form() {
12676    "use strict";
12677    var mkContactForms = document.getElementsByClassName('mk-contact-form');
12678    if (mkContactForms.length === 0) {
12679        return;
12680    }
12681    var captchaImageHolder = $('.captcha-image-holder');
12682    var activeClassName = 'is-active';
12683    var invalidClassName = 'mk-invalid';
12684    for (var i = 0; i < mkContactForms.length; i++) {
12685        initializeForm(mkContactForms[i], activeClassName, invalidClassName);
12686    }
12687    if (captchaImageHolder.length > 0) {
12688        $(window).on('load', initializeCaptchas);
12689    }
12690    /**
12691     * Initialize mk forms. e.g add activeClassName for inputs.
12692     *
12693     * @param form
12694     * @param activeClassName
12695     * @param invalidClassName
12696     */
12697    function initializeForm(form, activeClassName, invalidClassName) {
12698        var inputs = getFormInputs(form);
12699        for (var i = 0; i < inputs.length; i++) {
12700            markActiveClass(inputs[i]);
12701        }
12702        form.addEventListener('submit', function(e) {
12703            validateForm(e, invalidClassName);
12704        });
12705        /**
12706         * Set activeClassName for the parent node of the inout
12707         */
12708        function setActiveClass() {
12709            addClass(this.parentNode, activeClassName);
12710        }
12711        /**
12712         * Unset activeClassName from the parent node of the input.
12713         * We need to unset activeClassName only if the data was empty.
12714         * e.g. in the line style of the mk-contact-form, we set labels position based on activeClassName.
12715         */
12716        function unsetActiveClass() {
12717            if (this.value === '') {
12718                removeClass(this.parentNode, activeClassName);
12719            }
12720        }
12721        /**
12722         * Add event listeners (focus,blur) for input to set and unset activeClassName.
12723         *
12724         * @param input
12725         */
12726        function markActiveClass(input) {
12727            input.addEventListener('focus', setActiveClass);
12728            input.addEventListener('blur', unsetActiveClass);
12729        }
12730    }
12731    /**
12732     * Validate form when it's submitted. If everything was valid, we with post form in ajax request.
12733     *
12734     * @param e
12735     * @param invalidClassName
12736     */
12737    function validateForm(e, invalidClassName) {
12738        e.preventDefault();
12739        var form = e.target || e.srcElement;
12740        var inputs = getFormInputs(form);
12741        var isValidForm = true;
12742        var hasCaptchaField = false;
12743        for (var i = 0; i < inputs.length; i++) {
12744            var input = inputs[i];
12745            input.value = String(input.value).trim();
12746            switch (input.type) {
12747                case 'hidden':
12748                    break;
12749                case 'checkbox':
12750                    isValidForm = validateCheckBox(input, invalidClassName) && isValidForm;
12751                    break;
12752                case 'email':
12753                    isValidForm = validateEmail(input, invalidClassName) && isValidForm;
12754                    break;
12755                case 'textarea':
12756                    isValidForm = validateText(input, invalidClassName) && isValidForm;
12757                    break;
12758                case 'text':
12759                    /**
12760                     * Some old browsers such as IE 8 and 9 detect email type as text.
12761                     * So, we need to extra check for data-type attribute
12762                     */
12763                    if (input.dataset.type === 'captcha') {
12764                        isValidForm = validateText(input, invalidClassName) && isValidForm;
12765                        hasCaptchaField = true;
12766                    } else if (input.dataset.type === 'email') {
12767                        isValidForm = validateEmail(input, invalidClassName) && isValidForm;
12768                    } else {
12769                        isValidForm = validateText(input, invalidClassName) && isValidForm;
12770                    }
12771                    break;
12772                default:
12773                    /**
12774                     * e.g. validating for radiobox, selectbox and etc.
12775                     */
12776                    console.warn('Implement validation for ' + input.name + ':' + input.type);
12777                    break;
12778            }
12779        }
12780        if (isValidForm) {
12781            if (hasCaptchaField) {
12782                validateCaptcha(form, invalidClassName, sendForm);
12783            } else {
12784                sendForm(form);
12785            }
12786        }
12787    }
12788    /**
12789     * Validate captcha of form. If everything was, we will execute captchaIsValidCallback which as sendForm().
12790     *
12791     * @param form
12792     * @param invalidClassName
12793     * @param captchaIsValidCallback
12794     * @returns boolean
12795     */
12796    function validateCaptcha(form, invalidClassName, captchaIsValidCallback) {
12797        var input = form.querySelectorAll('[data-type="captcha"]')[0];
12798        if (input.value.length === 0) {
12799            addClass(input, invalidClassName);
12800            return false;
12801        } else {
12802            window.get.captcha(input.value).done(function(data) {
12803                loadCaptcha();
12804                input.value = '';
12805                if (data !== 'ok') {
12806                    addClass(input, invalidClassName);
12807                    addClass(input, 'contact-captcha-invalid');
12808                    removeClass(input, 'contact-captcha-valid');
12809                    input.placeholder = mk_captcha_invalid_txt;
12810                } else {
12811                    removeClass(input, invalidClassName);
12812                    removeClass(input, 'contact-captcha-invalid');
12813                    addClass(input, 'contact-captcha-valid');
12814                    input.placeholder = mk_captcha_correct_txt;
12815                    captchaIsValidCallback(form);
12816                }
12817            });
12818        }
12819    }
12820    /**
12821     * Send submitted form.
12822     *
12823     * @param form
12824     */
12825    function sendForm(form) {
12826        var $form = $(form);
12827        var data = getFormData(form);
12828        progressButton.loader($form);
12829        $.post(ajaxurl, data, function(response) {
12830            var res = JSON.parse(response);
12831            if (res.action_Status) {
12832                progressButton.success($form);
12833                $form.find('.text-input').val('');
12834                $form.find('textarea').val('');
12835                $form.find('input[type=checkbox]').attr("checked", false);
12836                $form.find('.contact-form-message').slideDown().addClass('state-success').html(res.message);
12837                setTimeout(function() {
12838                   $form.find('.contact-form-message').slideUp();  
12839                }, 5000);
12840            } else {
12841                progressButton.error($form);
12842                $form.find('.contact-form-message').removeClass('state-success').html(res.message);
12843            }
12844        });
12845    }
12846    /**
12847     * Initialize all captcha images for first time. All captcha images is always same. e.g. if we have multiple form,
12848     * all of them will have the same image.
12849     * It will also add event listener for '.captcha-change-image' objects to reload the captcha.
12850     */
12851    function initializeCaptchas() {
12852        var captchaChangeImageButtons = document.getElementsByClassName('captcha-change-image');
12853        for (var i = 0; i < captchaChangeImageButtons.length; i++) {
12854            captchaChangeImageButtons[i].addEventListener('click', loadCaptcha);
12855        }
12856    }
12857    /**
12858     * Load captcha text and append the image to captcha container.
12859     * If it used as a callback, it will prevent default behave of the event.
12860     * e.g. loading new captcha by click on <a> without changing url.
12861     */
12862    function loadCaptcha(e) {
12863        if (e) {
12864            e.preventDefault();
12865        }
12866        $.post(ajaxurl, {
12867            action: 'mk_create_captcha_image'
12868        }, appendImage);
12869        /**
12870         * The callback function for append or change old image src based on response. T
12871         * The captchaImageURL is the url of the captcha which is provided in ajax response of mk_create_captcha_image.
12872         * @param captchaImageURL
12873         */
12874        function appendImage(captchaImageURL) {
12875            if (captchaImageHolder.find('.captcha-image').length === 0) {
12876                captchaImageHolder.html('<img src="' + captchaImageURL + '" class="captcha-image" alt="captcha txt">');
12877            } else {
12878                captchaImageHolder.find('.captcha-image').attr("src", captchaImageURL + '?' + new Date().getTime());
12879            }
12880        }
12881    }
12882    /**
12883     * Get form inputs using querySelectorAll().
12884     * It returns <input> and <textarea> tags. If you need any other tags such as <select>, please update this function.
12885     *
12886     * @param form
12887     * @returns {NodeList}
12888     */
12889    function getFormInputs(form) {
12890        return form.querySelectorAll('input,textarea');
12891    }
12892    /**
12893     * Get data of the form inputs and textareas as a object.
12894     *
12895     * @param form
12896     * @returns {{action: string}}
12897     */
12898    function getFormData(form) {
12899        var data = {
12900            action: 'mk_contact_form'
12901        };
12902        var inputs = getFormInputs(form);
12903        for (var i = 0; i < inputs.length; i++) {
12904            data[inputs[i].name] = inputs[i].value;
12905        }
12906        return data;
12907    }
12908}
12909/* Ajax Login Form */
12910/* -------------------------------------------------------------------- */
12911function mk_login_form() {
12912    $('form.mk-login-form').each(function() {
12913        var $this = $(this);
12914        $this.on('submit', function(e) {
12915            $('p.mk-login-status', $this).show().text(ajax_login_object.loadingmessage);
12916            $.ajax({
12917                type: 'POST',
12918                dataType: 'json',
12919                url: ajax_login_object.ajaxurl,
12920                data: {
12921                    'action': 'ajaxlogin',
12922                    'username': $('#username', $this).val(),
12923                    'password': $('#password', $this).val(),
12924                    'security': $('#security', $this).val()
12925                },
12926                success: function(data) {
12927                    $('p.mk-login-status', $this).text(data.message);
12928                    if (data.loggedin === true) {
12929                        document.location.href = ajax_login_object.redirecturl;
12930                    }
12931                }
12932            });
12933            e.preventDefault();
12934        });
12935    });
12936}
12937/* Progress Button */
12938/* -------------------------------------------------------------------- */
12939var progressButton = {
12940    loader: function(form) {
12941        MK.core.loadDependencies([MK.core.path.plugins + 'tweenmax.js'], function() {
12942            var $form = form,
12943                progressBar = $form.find(".mk-progress-button .mk-progress-inner"),
12944                buttonText = $form.find(".mk-progress-button .mk-progress-button-content"),
12945                progressButton = new TimelineLite();
12946            progressButton.to(progressBar, 0, {
12947                width: "100%",
12948                scaleX: 0,
12949                scaleY: 1
12950            }).to(buttonText, .3, {
12951                y: -5
12952            }).to(progressBar, 1.5, {
12953                scaleX: 1,
12954                ease: Power2.easeInOut
12955            }, "-=.1").to(buttonText, .3, {
12956                y: 0
12957            }).to(progressBar, .3, {
12958                scaleY: 0
12959            });
12960        });
12961    },
12962    success: function(form) {
12963        MK.core.loadDependencies([MK.core.path.plugins + 'tweenmax.js'], function() {
12964            var $form = form,
12965                buttonText = $form.find(".mk-button .mk-progress-button-content, .mk-contact-button .mk-progress-button-content"),
12966                successIcon = $form.find(".mk-progress-button .state-success"),
12967                progressButtonSuccess = new TimelineLite({
12968                    onComplete: hideSuccessMessage
12969                });
12970            progressButtonSuccess.to(buttonText, .3, {
12971                paddingRight: 20,
12972                ease: Power2.easeInOut
12973            }, "+=1").to(successIcon, .3, {
12974                opacity: 1
12975            }).to(successIcon, 2, {
12976                opacity: 1
12977            });
12978
12979            function hideSuccessMessage() {
12980                progressButtonSuccess.reverse()
12981            }
12982        });
12983    },
12984    error: function(form) {
12985        MK.core.loadDependencies([MK.core.path.plugins + 'tweenmax.js'], function() {
12986            var $form = form,
12987                buttonText = $form.find(".mk-button .mk-progress-button-content, .mk-contact-button .mk-progress-button-content"),
12988                errorIcon = $form.find(".mk-progress-button .state-error"),
12989                progressButtonError = new TimelineLite({
12990                    onComplete: hideErrorMessage
12991                });
12992            progressButtonError.to(buttonText, .3, {
12993                paddingRight: 20
12994            }, "+=1").to(errorIcon, .3, {
12995                opacity: 1
12996            }).to(errorIcon, 2, {
12997                opacity: 1
12998            });
12999
13000            function hideErrorMessage() {
13001                progressButtonError.reverse()
13002            }
13003        });
13004    }
13005};
13006function mk_click_events() {
13007  "use strict";
13008
13009  var eventtype = 'click'; 
13010
13011  $(".mk-header-login, .mk-header-signup, .mk-side-dashboard, .mk-quick-contact-wrapper, .mk-dashboard-trigger, .blog-share-container, .news-share-buttons, .main-nav-side-search, #mk-fullscreen-search-wrapper, #fullscreen-navigation").on(eventtype, function(event) {
13012    if (event.stopPropagation) {
13013      event.stopPropagation();
13014    } else if (window.event) {
13015      window.event.cancelBubble = true;
13016    }
13017  });
13018  $("html").on(eventtype, function() {
13019    $(".mk-login-register, .mk-header-subscribe, #mk-quick-contact, .single-share-buttons, .single-share-box, .blog-social-share, .news-share-buttons, #mk-nav-search-wrapper").fadeOut(300);
13020    $('.mk-quick-contact-link').removeClass('quick-contact-active');
13021    // Removed By Maki for repairing fullnav scroll issue. Hope it odesnt break anything
13022    // $('body').css('overflow', 'visible');
13023  });
13024
13025  $('.mk-fullscreen-search-overlay').on(eventtype,function(){
13026    $(this).removeClass('mk-fullscreen-search-overlay-show');
13027  });
13028
13029  $('.mk-forget-password').on(eventtype, function() {
13030    $('.mk-forget-panel').siblings().hide().end().show();
13031  });
13032
13033  $('.mk-create-account').on(eventtype, function() {
13034    $('#mk-register-panel').siblings().hide().end().show();
13035  });
13036
13037  $('.mk-return-login').on(eventtype, function() {
13038    $('#mk-login-panel').siblings().hide().end().show();
13039  });
13040
13041
13042  $('.mk-quick-contact-link').on(eventtype, function() {
13043    var $this = $(this),
13044        $quickContact = $('#mk-quick-contact');
13045    if (!$this.hasClass('quick-contact-active')) {
13046      $quickContact.addClass('quick-contact-anim').fadeIn(250);
13047      $this.addClass('quick-contact-active');
13048    } else {
13049      $quickContact.removeClass('quick-contact-anim').fadeOut(100);
13050      $this.removeClass('quick-contact-active');
13051    }
13052    return false;
13053  });
13054
13055}
13056
13057function mk_social_share_global() {
13058
13059  "use strict";
13060
13061  var eventtype = 'click';
13062
13063  $('.twitter-share').on(eventtype, function() {
13064    var $this = $(this),
13065        $url = $this.attr('data-url'),
13066        $title = $this.attr('data-title');
13067
13068    window.open('http://twitter.com/intent/tweet?text=' + $title + ' ' + $url, "twitterWindow", "height=380,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
13069    return false;
13070  });
13071
13072  $('.pinterest-share').on(eventtype, function() {
13073    var $this = $(this),
13074        $url = $this.attr('data-url'),
13075        $title = $this.attr('data-title'),
13076        $image = $this.attr('data-image');
13077    window.open('http://pinterest.com/pin/create/button/?url=' + $url + '&media=' + $image + '&description=' + $title, "twitterWindow", "height=320,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
13078    return false;
13079  });
13080
13081  $('.facebook-share').on(eventtype, function() {
13082    var $url = $(this).attr('data-url');
13083    window.open('https://www.facebook.com/sharer/sharer.php?u=' + $url, "facebookWindow", "height=380,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
13084    return false;
13085  });
13086
13087  $('.googleplus-share').on(eventtype, function() {
13088    var $url = $(this).attr('data-url');
13089    window.open('https://plus.google.com/share?url=' + $url, "googlePlusWindow", "height=380,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
13090    return false;
13091  });
13092
13093  $('.linkedin-share').on(eventtype, function() {
13094    var $this = $(this),
13095        $url = $this.attr('data-url'),
13096        $title = $this.attr('data-title'),
13097        $desc = $this.attr('data-desc');
13098    window.open('http://www.linkedin.com/shareArticle?mini=true&url=' + $url + '&title=' + $title + '&summary=' + $desc, "linkedInWindow", "height=380,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
13099    return false;
13100  });
13101}
13102
13103
13104/* Event Count Down */
13105/* -------------------------------------------------------------------- */
13106
13107function mk_event_countdown() {
13108  if ($.exists('.mk-event-countdown')) {
13109
13110    MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.countdown.js' ], function() {
13111
13112      $('.mk-event-countdown').each(function () {
13113        if (isTest) return;
13114        var $this = $(this),
13115          $date = $this.attr('data-date'),
13116          $offset = $this.attr('data-offset');
13117
13118        $this.downCount({
13119          date: $date,
13120          offset: $offset
13121        });
13122      });
13123      
13124    });
13125  }
13126}
13127/* Flexslider init */
13128/* -------------------------------------------------------------------- */
13129
13130function mk_flexslider_init() {
13131
13132  var $lcd = $('.mk-lcd-slideshow'),
13133      $laptop = $('.mk-laptop-slideshow-shortcode');
13134
13135  if($lcd.length) $lcd.find('.mk-lcd-image').fadeIn();
13136  if($laptop.length) $laptop.find(".mk-laptop-image").fadeIn();
13137
13138  $('.js-flexslider').each(function () {
13139
13140    if ($(this).parents('.mk-tabs').length || $(this).parents('.mk-accordion').length) {
13141      $(this).removeData("flexslider");
13142    }
13143
13144    var $this = $(this),
13145      $selector = $this.attr('data-selector'),
13146      $animation = $this.attr('data-animation'),
13147      $easing = $this.attr('data-easing'),
13148      $direction = $this.attr('data-direction'),
13149      $smoothHeight = $this.attr('data-smoothHeight') == "true" ? true : false,
13150      $slideshowSpeed = $this.attr('data-slideshowSpeed'),
13151      $animationSpeed = $this.attr('data-animationSpeed'),
13152      $controlNav = $this.attr('data-controlNav') == "true" ? true : false,
13153      $directionNav = $this.attr('data-directionNav') == "true" ? true : false,
13154      $pauseOnHover = $this.attr('data-pauseOnHover') == "true" ? true : false,
13155      $isCarousel = $this.attr('data-isCarousel') == "true" ? true : false;
13156
13157
13158    if ($selector !== undefined) {
13159      var $selector_class = $selector;
13160    } else {
13161      var $selector_class = ".mk-flex-slides > li";
13162    }
13163
13164    if ($isCarousel === true) {
13165      var $itemWidth = parseInt($this.attr('data-itemWidth')),
13166        $itemMargin = parseInt($this.attr('data-itemMargin')),
13167        $minItems = parseInt($this.attr('data-minItems')),
13168        $maxItems = parseInt($this.attr('data-maxItems')),
13169        $move = parseInt($this.attr('data-move'));
13170    } else {
13171      var $itemWidth = $itemMargin = $minItems = $maxItems = $move = 0;
13172    }
13173
13174    MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.flexslider.js' ], function() {
13175      $this.flexslider({
13176        selector: $selector_class,
13177        animation: $animation,
13178        easing: $easing,
13179        direction: $direction,
13180        smoothHeight: $smoothHeight,
13181        slideshow: !isTest, // autoplay
13182        slideshowSpeed: $slideshowSpeed,
13183        animationSpeed: $animationSpeed,
13184        controlNav: $controlNav,
13185        directionNav: $directionNav,
13186        pauseOnHover: $pauseOnHover,
13187        prevText: "",
13188        nextText: "",
13189        itemWidth: $itemWidth,
13190        itemMargin: $itemMargin,
13191        minItems: $minItems,
13192        maxItems: $maxItems,
13193        move: $move
13194      });
13195    });
13196
13197  });
13198
13199}
13200
13201/* Header Search Form */
13202/* -------------------------------------------------------------------- */
13203
13204function mk_header_searchform() {
13205
13206  $('.mk-search-trigger').on('click',function(){
13207    setTimeout(function() {
13208        $('#mk-ajax-search-input').focus();
13209    },500);
13210  });
13211
13212  "use strict";
13213
13214  $('.mk-header-toolbar .mk-header-searchform .text-input').on('focus', function () {
13215
13216    if ($('.mk-header-toolbar .mk-header-searchform .text-input').hasClass('on-close-state')) {
13217      $('.mk-header-toolbar .mk-header-searchform .text-input').removeClass('on-close-state').animate({
13218        'width': '200px'
13219      }, 200);
13220      return false;
13221    }
13222  });
13223
13224  $(".mk-header-toolbar .mk-header-searchform").on('click',function (event) {
13225    if (event.stopPropagation) {
13226      event.stopPropagation();
13227    } else if (window.event) {
13228      window.event.cancelBubble = true;
13229    }
13230  });
13231
13232
13233  $("html").on('click',function () {
13234    $(this).find(".mk-header-toolbar .mk-header-searchform .text-input").addClass('on-close-state').animate({
13235      'width': 90
13236    }, 300);
13237  });
13238
13239  // Fix search for edge browser
13240  if(MK.utils.browser.name === 'Edge') {
13241    $('#mk-fullscreen-search-input').on('keydown', function(e) {
13242      if (e.which == 13) {
13243        e.preventDefault();
13244        $('#mk-fullscreen-searchform').submit();
13245      }
13246    });
13247  }
13248
13249}
13250
13251
13252
13253
13254/* Hover Events */
13255/* -------------------------------------------------------------------- */
13256
13257function mk_hover_events() {
13258
13259  "use strict";
13260
13261  $('.shopping-cart-header').hover(
13262    function() {
13263      $(this).find('.mk-shopping-cart-box').stop(true, true).fadeIn(250);
13264    },
13265    function() {
13266      $(this).find('.mk-shopping-cart-box').stop(true, true).delay(500).fadeOut(250);
13267    }
13268  );
13269
13270
13271  $('.widget-sub-navigation > ul > li, .widget_nav_menu ul.menu > li, .widget_product_categories ul > .cat-item').each(function() {
13272
13273    var $this = $(this),
13274        $subLevel = $this.find('ul').first();
13275
13276    if ($this.hasClass('page_item_has_children') || $this.hasClass('menu-item-has-children') || $this.hasClass('cat-parent')) {
13277      $this.on('click', function() {
13278        if($this.hasClass('toggle-active')) {
13279            $subLevel.stop(true, true).slideUp(700);
13280            $this.removeClass('toggle-active');
13281        } else {
13282            $subLevel.stop(true, true).slideDown(700);
13283            $this.addClass('toggle-active');
13284        }
13285      });
13286
13287      $subLevel.on('click', function(e){
13288        e.stopPropagation();
13289      });
13290    }
13291
13292  });
13293
13294  // var eventtype = mobilecheck() ? 'touchstart' : 'click';
13295  var eventtype = 'click';
13296
13297  $('.mk-fullscreen-trigger').on(eventtype, function(e) {
13298    $('.mk-fullscreen-search-overlay').addClass('mk-fullscreen-search-overlay-show');
13299    setTimeout(function(){
13300      $("#mk-fullscreen-search-input").focus();
13301    }, 300);
13302    e.preventDefault();
13303  });
13304
13305  $('.mk-fullscreen-close').on(eventtype, function(e) {
13306    $('.mk-fullscreen-search-overlay').removeClass('mk-fullscreen-search-overlay-show');
13307    e.preventDefault();
13308  });
13309
13310}
13311
13312function mk_unfold_footer() {
13313  var $this = $('#mk-footer'),
13314      $spacer = $('#mk-footer-unfold-spacer'),
13315      $footerHeight = $this.outerHeight();
13316
13317  // Stick with CSS media query breakpoint to target exact screen width
13318  if( !window.matchMedia("(max-width: 767px)").matches ) {
13319      if ($this.hasClass('mk-footer-unfold')) {
13320        $spacer.css('height', $footerHeight);
13321      }
13322  } else {
13323     $spacer.css('height', 0);
13324  }
13325}
13326
13327/* jQuery fancybox lightbox */
13328/* -------------------------------------------------------------------- */
13329function mk_lightbox_init() {
13330
13331	$(".mk-lightbox").fancybox({
13332		loop: true,
13333	});
13334
13335	$.fancybox.defaults.hash = false;
13336
13337}
13338
13339
13340/* Milestone Number Shortcode */
13341/* -------------------------------------------------------------------- */
13342
13343function mk_milestone() {
13344
13345  "use strict";
13346
13347  if( isTest || !$.exists('.mk-milestone') ) return;
13348
13349  $('.mk-milestone').each(function () {
13350    var $this = $(this),
13351      stop_number = $this.find('.milestone-number').attr('data-stop'),
13352      animation_speed = parseInt($this.find('.milestone-number').attr('data-speed'));
13353
13354    var build = function() {
13355      if (!$this.hasClass('scroll-animated')) {
13356        $this.addClass('scroll-animated');
13357
13358        $({
13359          countNum: $this.find('.milestone-number').text()
13360        }).animate({
13361          countNum: stop_number
13362        }, {
13363          duration: animation_speed,
13364          easing: 'linear',
13365          step: function () {
13366            $this.find('.milestone-number').text(Math.floor(this.countNum));
13367          },
13368          complete: function () {
13369            $this.find('.milestone-number').text(this.countNum);
13370          }
13371        });
13372      }
13373    };
13374
13375    if ( !MK.utils.isMobile() ) {
13376      // refactored only :in-viewport logic. rest is to-do
13377      MK.utils.scrollSpy( this, {
13378          position: 'bottom',
13379          after: build
13380      });
13381    } else {
13382      build();
13383    }
13384
13385  });
13386
13387}
13388
13389
13390
13391
13392/* Recent Works Widget */
13393/* -------------------------------------------------------------------- */
13394
13395function mk_portfolio_widget() {
13396
13397  "use strict";
13398
13399  $('.widget_recent_portfolio li').each(function () {
13400
13401    $(this).find('.portfolio-widget-thumb').on('hover',function () {
13402
13403      $(this).siblings('.portfolio-widget-info').animate({
13404        'opacity': 1
13405      }, 200);
13406    }, function () {
13407
13408      $(this).siblings('.portfolio-widget-info').animate({
13409        'opacity': 0
13410      }, 200);
13411    });
13412
13413  });
13414}
13415
13416
13417
13418/* Skill Meter and Charts */
13419/* -------------------------------------------------------------------- */
13420function mk_skill_meter() {
13421    "use strict";
13422    if ($.exists('.mk-skill-meter')) {
13423        if (!MK.utils.isMobile()) {
13424            $(".mk-skill-meter .progress-outer").each(function() {
13425                var $this = $(this);
13426
13427                var build = function() {
13428                    if (!$this.hasClass('scroll-animated')) {
13429                        $this.addClass('scroll-animated');
13430                        $this.animate({
13431                            width: $this.attr("data-width") + '%'
13432                        }, 2000);
13433                    }
13434                };
13435
13436                MK.utils.scrollSpy( this, {
13437                    position: 'bottom',
13438                    after: build
13439                });
13440            });
13441        } else {
13442            $(".mk-skill-meter .progress-outer").each(function() {
13443                var $this = $(this);
13444                if (!$this.hasClass('scroll-animated')) {
13445                    $this.addClass('scroll-animated');
13446                    $this.css({
13447                        width: $(this).attr("data-width") + '%'
13448                    });
13449                }
13450            });
13451        }
13452    }
13453}
13454
13455// function mk_charts() {
13456//     "use strict";
13457
13458//     if( !$.exists('.mk-chart') ) return;
13459
13460//     MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.easyPieChart.js' ], function() {
13461
13462//         $('.mk-chart').each(function() {
13463
13464//             var $this = $(this),
13465//                 $parent_width = $(this).parent().width(),
13466//                 $chart_size = parseInt($this.attr('data-barSize'));
13467
13468//             if ($parent_width < $chart_size) {
13469//                 $chart_size = $parent_width;
13470//                 $this.css('line-height', $chart_size);
13471//                 $this.find('i').css({
13472//                     'line-height': $chart_size + 'px'
13473//                 });
13474//                 $this.css({
13475//                     'line-height': $chart_size + 'px'
13476//                 });
13477//             }
13478
13479//             var build = function() {
13480//                 $this.easyPieChart({
13481//                     animate: 1300,
13482//                     lineCap: 'butt',
13483//                     lineWidth: $this.attr('data-lineWidth'),
13484//                     size: $chart_size,
13485//                     barColor: $this.attr('data-barColor'),
13486//                     trackColor: $this.attr('data-trackColor'),
13487//                     scaleColor: 'transparent',
13488//                     onStep: function(value) {
13489//                         this.$el.find('.chart-percent span').text(Math.ceil(value));
13490//                     }
13491//                 });
13492//             };
13493
13494//             // refactored only :in-viewport logic. rest is to-do
13495//             MK.utils.scrollSpy( this, {
13496//                 position: 'bottom',
13497//                 after: build
13498//             });
13499
13500
13501//         });
13502//     });
13503// }
13504/* Toolbar subscribe form */
13505/* -------------------------------------------------------------------- */
13506
13507$( "#mc-embedded-subscribe-form" ).on('submit',function( e ){
13508    var $this = $(this);
13509
13510    e.preventDefault();
13511    $.ajax({
13512        url: MK.core.path.ajaxUrl,
13513        type: "POST",
13514        data: {
13515            action: "mk_ajax_subscribe",
13516            email: $this.find( ".mk-subscribe--email" ).val(),
13517            list_id: $this.find( ".mk-subscribe--list-id" ).val(),
13518            optin: $this.find( ".mk-subscribe--optin" ).val()
13519        },
13520        success: function ( res ) {
13521            $this.parent().find( ".mk-subscribe--message" ).html( $.parseJSON( res ).message );
13522        }
13523    });
13524});
13525
13526/**
13527 * Add class to tag. It's vanilla js instead of jQuery.
13528 * @param tag
13529 * @param className
13530 */
13531function addClass(tag, className) {
13532    tag.className += ' ' + className;
13533}
13534
13535/**
13536 * Remove class from tag. It's vanilla js instead of jQuery.
13537 * Replacing should be with g for replacing all occurrence.
13538 *
13539 * @param tag
13540 * @param className
13541 */
13542function removeClass(tag, className) {
13543    tag.className = tag.className.replace(new RegExp(className, 'g'), '');
13544}
13545
13546
13547/**
13548 * If we're running under Node for testing purpose.
13549 */
13550if(typeof exports !== 'undefined') {
13551    exports.addClass = addClass;
13552    exports.removeClass = removeClass;
13553}
13554
13555/*!
13556*  javascript-debounce 1.0.0
13557*
13558*  A lightweight, dependency-free JavaScript module for debouncing functions based on David Walsh's debounce function.
13559*
13560*  Source code available at: https://github.com/jgarber623/javascript-debounce
13561*
13562*  (c) 2015-present Jason Garber (http://sixtwothree.org)
13563*
13564*  javascript-debounce may be freely distributed under the MIT license.
13565*/
13566
13567(function(root, factory) {
13568	if (typeof define === "function" && define.amd) {
13569		define([], factory);
13570	} else if (typeof exports === "object") {
13571		module.exports = factory();
13572	} else {
13573		root.debounce = factory();
13574	}
13575})(this, function() {
13576	"use strict";
13577	return function(callback, delay) {
13578		var timeout;
13579		return function() {
13580			var context = this, args = arguments;
13581			clearTimeout(timeout);
13582			timeout = setTimeout(function() {
13583				callback.apply(context, args);
13584			}, delay);
13585		};
13586	};
13587});
13588
13589/**
13590 * Validate email address.
13591 *
13592 * @param input
13593 * @param invalidClassName
13594 * @returns boolean
13595 */
13596function validateEmail(input, invalidClassName) {
13597    var value = input.value.trim();
13598    if ((input.required || value.length > 0) && !/^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,63})$/i.test(value)) {
13599        if (invalidClassName) {
13600            addClass(input, invalidClassName);
13601        }
13602        return false;
13603    } else {
13604        if (invalidClassName) {
13605            removeClass(input, invalidClassName);
13606        }
13607        return true;
13608    }
13609}
13610/**
13611 * Validate text entry.
13612 *
13613 * @param input
13614 * @param invalidClassName
13615 * @returns boolean
13616 */
13617function validateText(input, invalidClassName) {
13618    var value = input.value.trim();
13619    if (input.required && value.length === 0) {
13620        if (invalidClassName) {
13621            addClass(input, invalidClassName);
13622        }
13623        return false;
13624    } else {
13625        if (invalidClassName) {
13626            removeClass(input, invalidClassName);
13627        }
13628        return true;
13629    }
13630}
13631/**
13632 * Validate Checkbox.
13633 *
13634 * @param input
13635 * @param invalidClassName
13636 * @returns boolean
13637 */
13638function validateCheckBox(input, invalidClassName) {
13639    if (input.required && input.checked == false) {
13640        if (invalidClassName) {
13641            addClass(input, invalidClassName);
13642        }
13643        return false;
13644    } else {
13645        if (invalidClassName) {
13646            removeClass(input, invalidClassName);
13647        }
13648        return true;
13649    }
13650}
13651/**
13652 * If we're running under Node for testing purpose.
13653 */
13654if (typeof exports !== 'undefined') {
13655    exports.validateEmail = validateEmail;
13656    exports.validateText = validateText;
13657}
13658(function( $ ) {
13659	'use strict';
13660
13661    var $wrapper = $('.js-bottom-corner-btns');
13662    var $contactBtn = $wrapper.find('.js-bottom-corner-btn--contact');
13663    var $backBtn = $wrapper.find('.js-bottom-corner-btn--back');
13664    var hasContactBtn = $contactBtn.length;
13665    var hasBackBtn = $backBtn.length;
13666
13667    if(!hasBackBtn) return;
13668
13669    function deactivate() {
13670        $contactBtn.removeClass('is-active');
13671        $backBtn.removeClass('is-active');
13672    }
13673
13674    function activate() { 
13675        $contactBtn.addClass('is-active');
13676        $backBtn.addClass('is-active');
13677    }
13678
13679    MK.utils.scrollSpy( 400, {
13680        before: deactivate,
13681        after: activate
13682    });
13683
13684})( jQuery );
13685(function($) {
13686	'use strict';
13687	
13688	$('.mk-fullscreen-nav-close, .mk-fullscreen-nav-wrapper, #fullscreen-navigation a').on('click', function(e) {
13689		
13690		// Close nav with removing classes
13691		$('.mk-fullscreen-nav').removeClass('opened');
13692		$('.mk-dashboard-trigger').removeClass('fullscreen-active');
13693		$('body').removeClass('fullscreen-nav-opened'); 
13694		
13695		var anchor = MK.utils.detectAnchor( this ),
13696		$this = $( this );
13697		
13698		// Scroll to anchor if exists
13699		if( anchor.length ) {
13700			// Moved 4 these lines after anchor check because console error. If anchor
13701			// return false, split part will throw an error because $this is not a link.
13702			// Fix AM-2027
13703			var href = $this.attr( 'href' ).split( '#' )[0];
13704			var url = window.location.href;
13705			var isSamePage = url.indexOf( href ) !== -1;
13706
13707			if ( isSamePage ) {
13708				e.preventDefault();
13709			}
13710			MK.utils.scrollToAnchor( anchor );
13711			
13712		// Or do nothing if pointless # as href
13713		// BAD  PRACTICE: it is very popular to use "#" for click elements that we listen to with js.
13714		// GOOD PRACTICE: prefer "javascript:;" as easier to handle and more readable version
13715		} else if( $this.attr( 'href' ) === '#' ) {
13716			e.preventDefault();
13717		}
13718	});
13719	
13720	$('.fullscreen-navigation-ul .menu-sub-level-arrow').on('click', function(){
13721		$(this).siblings('.sub-menu').slideToggle();
13722	});
13723	
13724}(jQuery));
13725(function($) {
13726	'use strict';
13727
13728	/**
13729     * Mega menu
13730     */
13731    var $navList = $(".main-navigation-ul");
13732    var megaMenu = function megaMenu() {
13733
13734        $navList.MegaMenu({
13735            type: "vertical",
13736            delay: 200
13737        });
13738    };
13739
13740    $(window).on('load', megaMenu);
13741
13742}(jQuery));
13743(function($) {
13744	'use strict';
13745
13746	/**
13747     * One pager menu hash update. 
13748     * Smooth scroll is appended globally whenever the click element has corresponding #el
13749     */    
13750    var onePageNavItem = function onePageNavItem() {
13751        var $this = $( this ),
13752            link = $this.find( 'a' ),
13753            anchor = MK.utils.detectAnchor( link ); // anchor on current page
13754
13755        if( !anchor.length ) return;
13756
13757        $this.removeClass( 'current-menu-item current-menu-ancestor current-menu-parent' );
13758
13759        var activeNav = function( state ) {
13760            return function() {
13761                $this[ state ? 'addClass' : 'removeClass' ]( 'current-menu-item' );
13762                window.history.replaceState( undefined, undefined, [ state ? anchor : ' ' ] );
13763            };
13764        };
13765
13766        MK.utils.scrollSpy( $( anchor )[0], {
13767            before : activeNav( false ),
13768            active : activeNav( true ),
13769            after  : activeNav( false ),
13770        });
13771    };
13772
13773    var $navItems = $('.js-main-nav').find( 'li' );
13774    
13775    $(window).on('load', function() {
13776        // Wait with spying anchors so we do not assign anchor that is browser scroll to after page load
13777        // Especially when there are anchors on top - refreshing page can cause grabbing one of them into url
13778        // and force unwanted scroll
13779        setTimeout(function() {
13780            $navItems.each( onePageNavItem );
13781        }, 1000);
13782    });
13783	
13784}(jQuery));
13785(function($) {
13786    'use strict';
13787
13788    var $window = $(window);
13789    var $body = $('body');
13790    var $resMenuWrap = $('.mk-responsive-wrap');
13791    var $post_nav = $('.mk-post-nav');
13792    var $toolbar = $('.mk-header-toolbar');
13793    var $resMenuLink = $('.mk-nav-responsive-link');
13794
13795    // Flags
13796    var hasResMenu = ($resMenuWrap.length > 0);
13797
13798    //initial window and screen height
13799    var windowHeight = $window.height();
13800    var screenHeight = screen.height;
13801
13802    // We keep this handler above hasResMenu flag.
13803    // Even if our header doesn't contain droppable responsive menu (in favor of fullscreen or side menu) 
13804    // we still transform tollbar into collapsible menu part in responsive state
13805    $('.mk-toolbar-resposnive-icon').on('click', function(e) {
13806        e.preventDefault();
13807        console.log('clicked');
13808        if ($body.hasClass('toolbar-opened')) {
13809            $body.removeClass('toolbar-opened').addClass('toolbar-closed');
13810            $toolbar.hide();
13811        } else {
13812            $body.removeClass('toolbar-closed').addClass('toolbar-opened');
13813            $toolbar.show();
13814        }
13815    });
13816
13817
13818    if ( ! hasResMenu && ! $('.vc_mk_header') ) return;
13819
13820    function toggleResMenu(e) {
13821        e.preventDefault();
13822        var $this = $(this);
13823        var $headerInner = $this.parents('header');
13824        var $resMenu = $headerInner.find('.mk-responsive-wrap');
13825        var searchBox = $('.responsive-searchform .text-input');
13826        var adminBarHeight = $('#wpadminbar').height(); /* Fix AM-1918 */
13827
13828        if ($body.hasClass('mk-opened-nav')) {
13829            $this.removeClass('is-active');
13830            $body.removeClass('mk-opened-nav').addClass('mk-closed-nav').trigger('mk-closed-nav');
13831            $resMenu.hide();
13832            $post_nav.removeClass('post-nav-backward');
13833        } else {
13834            $this.addClass('is-active');
13835            $body.removeClass('mk-closed-nav').addClass('mk-opened-nav').trigger('mk-opened-nav');
13836            $resMenu.show();
13837            $post_nav.addClass('post-nav-backward');
13838
13839        }
13840
13841        //for iPhone 5 focus bug , remove search box focused class
13842        if(searchBox.hasClass('input-focused')){
13843            searchBox.removeClass('input-focused');
13844        }
13845        
13846    }
13847
13848    $resMenuLink.each(function() {
13849        $(this).on('click', toggleResMenu);
13850    });
13851
13852    $( window ).on( 'vc_reload', function () {
13853        $('.vc_mk_header .mk-nav-responsive-link').each(function() {
13854            $(this).on('click', toggleResMenu);
13855        });
13856    } )
13857
13858    var setResMenuHeight = function() {
13859        var height = $window.height() - MK.val.offsetHeaderHeight(0);
13860        $resMenuWrap.css('max-height', height);
13861    };
13862
13863    // check if device virtual keyboard is active 
13864    var isVirtualKeyboard = function() {
13865        var currentWindowHeight = $window.height();
13866        var currentScreenHeight = screen.height;
13867        var searchBox = $('.responsive-searchform .text-input');
13868        var searchBoxIsFocused = false; 
13869
13870        //for iPhone 5 focus bug , add class for detect focus state
13871        searchBox.on('touchstart touchend', function(e) {
13872            searchBox.addClass('input-focused');
13873        });
13874
13875        searchBoxIsFocused = (searchBox.is(':focus') || searchBox.hasClass("input-focused"));
13876
13877        if ($body.hasClass('mk-opened-nav') && searchBoxIsFocused && currentScreenHeight == screenHeight && currentWindowHeight != windowHeight) {
13878            return true;
13879        } else {
13880            return false;
13881        }
13882    };
13883
13884    var hideResMenu = function hideResMenu() {
13885        if (MK.utils.isResponsiveMenuState()) {
13886
13887            //when search box in responsive menu is focused , window resize fired but at this time responsive menu should be open
13888            if (!isVirtualKeyboard()) {
13889                // hide toggled menu and its states
13890                if ($body.hasClass('mk-opened-nav')) {
13891                    $resMenuLink.filter('.is-active').trigger('click');
13892                }
13893                // hide menu wrapper
13894                $resMenuWrap.hide();
13895
13896            }
13897        }
13898    };
13899
13900    $resMenuWrap.on('click', 'a', hideResMenu);
13901
13902}(jQuery));
13903
13904(function($) {
13905    'use strict';
13906
13907    var $header = $('.mk-header');    
13908    var hasHeader = ($header.length > 0);
13909
13910    if(!hasHeader && ! $('.vc_mk_header') ) return;
13911    
13912    var $sticky_style = $header.attr('data-header-style');
13913
13914    //if ($sticky_style !== 3) return;
13915
13916    $('.sidedash-navigation-ul > li').each(function() {
13917        var $this = $(this);
13918
13919        $this.children('ul').siblings('a').after('<span class="mk-nav-arrow mk-nav-sub-closed"><svg class="mk-svg-icon" data-name="mk-moon-arrow-down" data-cacheid="2" style=" height:14px; width: 14px; " xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M512 192l-96-96-160 160-160-160-96 96 256 255.999z"></path></svg></span>');
13920    });
13921
13922    function toggleSubMenu(e) {
13923        e.preventDefault();
13924        var $this = $(this);
13925        
13926        if ($this.hasClass('mk-nav-sub-closed')) {
13927            $this.siblings('ul').slideDown(450).end().removeClass('mk-nav-sub-closed').addClass('mk-nav-sub-opened');
13928        } else {
13929            $this.siblings('ul').slideUp(450).end().removeClass('mk-nav-sub-opened').addClass('mk-nav-sub-closed');
13930        }
13931    };
13932
13933    function toggleFullMenu(e) {
13934        e.preventDefault();
13935        var $this = $(this),
13936            $body = $('body'),
13937            $fullscreen_box = $('.mk-fullscreen-nav');
13938
13939        if ($this.hasClass('dashboard-style')){
13940          if (!$this.hasClass('dashboard-active')) {
13941            $this.addClass('dashboard-active');
13942            $body.addClass('dashboard-opened');
13943          } else {
13944            $this.removeClass('dashboard-active'); 
13945            $body.removeClass('dashboard-opened');
13946          }
13947        }else if($this.hasClass('fullscreen-style')){
13948          if (!$this.hasClass('fullscreen-active')) {
13949            $this.addClass('fullscreen-active');
13950            $body.addClass('fullscreen-nav-opened');
13951            $fullscreen_box.addClass('opened');
13952            // MK.utils.scroll.disable();
13953          } else {
13954            $this.removeClass('fullscreen-active');
13955            $body.removeClass('fullscreen-nav-opened');
13956            $fullscreen_box.removeClass('opened');
13957          }
13958        }
13959    }
13960
13961    $('.mk-nav-arrow').each(function() {
13962        $(this).stop(true).on('click', toggleSubMenu);
13963    });
13964
13965    $('.mk-dashboard-trigger').each(function() {
13966        $(this).on('click', toggleFullMenu);
13967    });
13968
13969    $( window ).on( 'vc_reload', function () {
13970        $('.vc_mk_header .mk-dashboard-trigger').each(function() {
13971            $(this).on('click', toggleFullMenu);
13972        });
13973
13974        $('.vc_mk_header .mk-nav-arrow').each(function() {
13975            $(this).stop(true).on('click', toggleSubMenu);
13976       });
13977    } );
13978
13979    $('html').on('click', function() {
13980        $('body').removeClass('dashboard-opened');
13981        $('.mk-dashboard-trigger').removeClass('dashboard-active');
13982    });
13983
13984}(jQuery));
13985
13986(function($) {
13987	'use strict';
13988
13989    /**
13990     * Vertical menu
13991     */
13992    var $verticalMenu = $('#mk-vm-menu');
13993    var verticalMenu = function verticalMenu() {
13994        if(!$verticalMenu.data('vertical-menu') && !MK.utils.isResponsiveMenuState()) {
13995            $verticalMenu.dlmenu();
13996            $verticalMenu.data('vertical-menu', true);
13997        }
13998    };
13999
14000    verticalMenu();
14001    $(window).on('resize', verticalMenu);
14002	
14003}(jQuery));
14004(function($) {
14005    'use strict';
14006
14007    // WPML
14008    var $lang_item = $('.mk-main-navigation > .main-navigation-ul > .menu-item-language');
14009    $lang_item.addClass('no-mega-menu').css('visibility', 'visible');
14010    $('.mk-main-navigation .menu-item-language > a').addClass('menu-item-link');
14011
14012})(jQuery);
14013(function($) {
14014	'use strict';
14015
14016    var $header = $( '.mk-header' ).first(); // Theme header is always first, do not apply to shortcode headers.
14017    var hasHeader = ($header.length > 0);
14018
14019    if(!hasHeader) return;
14020
14021    var $window = $( window );
14022    var $document = $( document );
14023    var $headerHolder = $header.find( '.mk-header-holder' );
14024    var $paddingWrapper = $header.find('.mk-header-padding-wrapper');
14025    var config = $header.data();
14026
14027    /**
14028     * Flags
14029     * @type {Boolean}
14030     */
14031    var isStickyLazy = (config.stickyStyle === 'lazy');
14032    var isStickyFixed = (config.stickyStyle === 'fixed');
14033    var isStickySlide = (config.stickyStyle === 'slide');
14034
14035    function isSticky() { // Check for sticky compatibility
14036        //return config.headerStyle !== 4; header style 4 needs sticky state for transparent header.
14037        return true;
14038    }
14039
14040    function isColorable() { // Check for coloring compatibility
14041        // TODO make it explicit in DOM that header is transparent as this is only scenario for colorable header
14042        // Monkey patch - exclude header styles that don't fit colorable
14043        return config.headerStyle !== 4;
14044    }
14045
14046
14047    /**
14048     * Change header skin
14049     */
14050	function changeSkin( e, skin ) {
14051		$header.attr( 'data-transparent-skin', skin );
14052        // Fix for class based skining
14053        var contrast = skin === 'light' ? 'dark' : 'light';
14054        $header.addClass(skin + '-skin');
14055        $header.removeClass(contrast + '-skin');
14056	}
14057
14058    if(isColorable()) MK.utils.eventManager.subscribe( 'firstElSkinChange', changeSkin );
14059
14060
14061    // Assign sticky scenarions
14062    if (isSticky() && isStickyLazy) {
14063      if(config.headerStyle !== 2) {
14064        lazySticky();
14065      }
14066    }
14067    else if (isSticky() && isStickyFixed) fixedSticky();
14068    else if (isSticky() && isStickySlide) slideSticky();
14069
14070    /**
14071     * Sticky header behavior: Lazy
14072     */
14073    function lazySticky() {
14074        var elClassHidden = 'header--hidden';
14075        var elClassSticky = 'a-sticky';
14076        var wScrollCurrent = 0;
14077        var wScrollBefore = 0;
14078        var wScrollDiff = 0;
14079        var wHeight = 0;
14080        var dHeight = 0;
14081
14082        var setSizes = function setSizes() {
14083            dHeight = $document.height();
14084            wHeight = $window.height();
14085        };
14086
14087        var onScroll = function onScroll() {
14088            wScrollCurrent = MK.val.scroll();
14089            wScrollDiff = wScrollBefore - wScrollCurrent;
14090
14091            if( wScrollCurrent <= 0 ) { // scrolled to the very top; element sticks to the top
14092                $headerHolder.removeClass( elClassHidden );
14093                $header.removeClass( elClassSticky );
14094                $('body').trigger('mk:header-unsticky');
14095
14096            } else if( wScrollDiff > 0 && $headerHolder.hasClass( elClassHidden ) ) { // scrolled up; element slides in
14097                $headerHolder.removeClass( elClassHidden );
14098                $header.addClass( elClassSticky );
14099                $('body').trigger('mk:header-sticky');
14100
14101            } else if( wScrollDiff < 0 ) { // scrolled down
14102
14103                if( wScrollCurrent + wHeight >= dHeight && $headerHolder.hasClass( elClassHidden ) ) { // scrolled to the very bottom; element slides in
14104                    $headerHolder.removeClass( elClassHidden );
14105                    $header.addClass( elClassSticky );
14106                    $('body').trigger('mk:header-sticky');
14107                } else { // scrolled down; element slides out
14108                    $headerHolder.addClass( elClassHidden );
14109                    $header.removeClass( elClassSticky );
14110                    $('body').trigger('mk:header-unsticky');
14111                }
14112            }
14113
14114            wScrollBefore = wScrollCurrent;
14115        };
14116
14117        setSizes();
14118        onScroll();
14119        $window.on( 'resize', MK.utils.throttle( 100, setSizes ) );
14120        $window.on( 'scroll', MK.utils.throttle( 500, onScroll ) );
14121    }
14122
14123
14124    /**
14125     * Sticky header behavior: Fixed
14126     */
14127    function fixedSticky() {
14128        var sticked = false;
14129        var scrollPos;
14130
14131        var toggleState = function toggleState() {
14132            scrollPos = MK.val.scroll() + MK.val.adminbarHeight();
14133
14134            if( (scrollPos > MK.val.stickyOffset() ) && ! MK.utils.isResponsiveMenuState() ) {
14135                if(sticked) return; // stop if already sticked
14136                $header.addClass('a-sticky');
14137                sticked = true;
14138                $('body').trigger('mk:header-sticky');
14139            } else {
14140                if(!sticked) return; // stop if already unsticked
14141                $header.removeClass('a-sticky');
14142                sticked = false;
14143                $('body').trigger('mk:header-unsticky');
14144            }
14145        };
14146
14147        toggleState();
14148        $window.on( 'scroll', MK.utils.throttle( 100, toggleState) );
14149        $window.on( 'resize', MK.utils.throttle( 100, toggleState) );
14150    }
14151
14152
14153    /**
14154     * Sticky header behavior: Slide
14155     */
14156    function slideSticky() {
14157        var sticked = false;
14158        var onScroll = function onScroll() {
14159            if (MK.val.scroll() > MK.val.stickyOffset()) {
14160                if(sticked) return; // stop if already sticked
14161                $header.addClass('pre-sticky');
14162                $paddingWrapper.addClass('enable-padding');
14163                setTimeout(function() {
14164                    $header.addClass('a-sticky');
14165                    $('body').trigger('mk:header-sticky');
14166                }, 1);
14167                sticked = true;
14168            } else {
14169                if(!sticked) return; // stop if already unsticked
14170                $header.removeClass('a-sticky');
14171                $header.removeClass('pre-sticky');
14172                $paddingWrapper.removeClass('enable-padding');
14173                sticked = false;
14174                $('body').trigger('mk:header-unsticky');
14175            }
14176        };
14177
14178        onScroll();
14179        $window.on( 'scroll', MK.utils.throttle( 100, onScroll) );
14180    }
14181
14182    // TODO
14183    // var pageIntro = $('body').data('intro'); // block scrolling on page intro
14184
14185
14186})( jQuery );
14187
14188(function($){
14189	'use strict';
14190
14191	// Do not assign at all if no touch events
14192	var hasTouchscreen = ('ontouchstart' in document.documentElement);
14193	if(!hasTouchscreen) return;
14194
14195	$('.mk-main-navigation .menu-item-has-children').each( normalizeClick );
14196
14197	function normalizeClick() {
14198		$(this).on('click', handleClick);
14199	}
14200
14201	// Most reasonable way to normalize click and let hover state on first touch yet don't break experience on multiple input devices is to actually check against desired effect.
14202	// Better way would be to check against expected state but JS doesn't detect :hover so it would be nice to have it normalized globally like expecting .hover class in css
14203	function handleClick(e) {
14204		var $this = $(e.currentTarget);
14205		var $child = $this.find('> ul');
14206		var isVisible = $child.css('display') !== 'none';
14207
14208		if(!isVisible) {
14209			e.preventDefault();
14210			e.stopPropagation();
14211		}
14212	}
14213
14214}(jQuery));
14215(function( $ ) {
14216	'use strict';
14217
14218	MK.ui.preloader = {
14219		dom : {
14220			overlay: '.mk-body-loader-overlay'
14221		},
14222
14223		hide : function hide() {
14224			$( this.dom.overlay ).fadeOut(600, "easeInOutExpo", function() {
14225				$('body').removeClass('loading');
14226            //$( this ).remove();
14227         });
14228		}
14229	};  
14230
14231})( jQuery ); 
14232(function($) {
14233	'use strict';
14234
14235    var _ajaxUrl = MK.core.path.ajaxUrl;
14236    var _instances = {};
14237
14238	MK.utils.ajaxLoader = function ajaxLoader(el) {
14239		// retrun a cached instance to have control over state from within multiple places
14240		// we may need for example to reset pageId when do filtering. It is really one instance that controls both filtering and pagination / load more
14241		var id = '#' + ($(el).attr('id'));
14242		if(typeof _instances[id] !== 'undefined') return _instances[id];
14243
14244		// else lets start new instance
14245		this.id = id;
14246		this.el = el;
14247		this.isLoading = false;
14248		this.xhrCounter = 0;
14249	};
14250
14251	MK.utils.ajaxLoader.prototype = { 
14252		init: function init() {
14253			// prevent double initialization of we return an instance
14254			if ( this.initialized && typeof window.vc_iframe === 'undefined' ) {
14255				return;
14256			}
14257
14258			this.createInstance();
14259			this.cacheElements();
14260
14261			this.initialized = true;
14262		},
14263
14264		cacheElements: function cacheElements() {
14265			this.$container = $(this.el);
14266			this.id = '#' + (this.$container.attr('id'));
14267	        this.categories = this.$container.data('loop-categories');
14268
14269			this.data = {};
14270			this.data.action = 'mk_load_more';
14271	        this.data.query = this.$container.data('query');
14272	        this.data.atts = this.$container.data('loop-atts');
14273	        this.data.loop_iterator = this.$container.data('loop-iterator');
14274	        this.data.author = this.$container.data('loop-author');
14275	        this.data.posts = this.$container.data('loop-posts');
14276	        this.data.safe_load_more = this.$container.siblings('#safe_load_more').val();
14277	        this.data._wp_http_referer = this.$container.siblings('input[name="_wp_http_referer"]').val();
14278	        this.data.paged = 1;
14279	        this.data.maxPages = this.$container.data('max-pages');
14280	        this.data.term = this.categories;
14281		},
14282
14283		createInstance: function() {
14284			_instances[this.id] = this;
14285		},
14286
14287		load: function load(unique) {
14288			var self = this;
14289			var seq = ++this.xhrCounter;
14290            this.isLoading = true;
14291			
14292			// If mk-ajax-loaded-posts span exists, get the post ids
14293			if ( this.$container.siblings('.mk-ajax-loaded-posts').length ) {
14294				var loaded_posts = this.$container.siblings('.mk-ajax-loaded-posts').attr('data-loop-loaded-posts');
14295				
14296				// Do not send looaded posts for Classic Pagination Navigation
14297				if ( this.$container.attr('data-pagination-style') != 1 ) {
14298					self.data.loaded_posts = loaded_posts.split(',');
14299				}
14300			}
14301
14302            return $.when(
14303	            $.ajax({
14304	                url 	: _ajaxUrl,
14305	                type 	: "POST",
14306	                data 	: self.data
14307	            })
14308	        ).done(function(response) {
14309	        	self.onDone(response, unique, seq);
14310	        });
14311		},
14312
14313		onDone: function(response, unique, seq) {
14314			if(seq === this.xhrCounter) {
14315				var self = this;
14316
14317				response = $.parseJSON(response);
14318				response.unique = unique;
14319				response.id = this.id;
14320				
14321				// If mk-ajax-loaded-posts span exists, update current post ids 
14322				// with new post ids from server's response
14323				if ( this.$container.siblings('.mk-ajax-loaded-posts').length ) {
14324					this.$container.siblings('.mk-ajax-loaded-posts').attr('data-loop-loaded-posts', response.loaded_posts);
14325				}
14326
14327	            this.setData({
14328	                maxPages: response.maxPages,
14329	                found_posts: response.found_posts,
14330	                loop_iterator: response.i
14331	            });
14332
14333				// Preload images first by creating object from returned content.
14334				// mk_imagesLoaded() method will create a promise that gets resolved when all images inside are loaded.
14335				// Our ajaxLoad is somehow more similar to window.onload event now.
14336				$(response.content).mk_imagesLoaded().then(function() {
14337					MK.utils.eventManager.publish('ajaxLoaded', response);
14338		        	self.isLoading = false;
14339		        	self.initNewComponents();
14340				});
14341
14342	        } else console.log('XHR request nr '+ seq +' aborted');
14343
14344        },
14345
14346		setData: function setData(atts) {
14347			for(var att in atts) {
14348				if(att === 'term' && atts[att] === '*') this.data.term = '';
14349				else this.data[att] = atts[att];
14350			}
14351		},
14352
14353		getData: function getData(att) {
14354			return this.data[att];
14355		},
14356
14357		initNewComponents: function initNewComponents() {
14358            // Legacy scripts reinit
14359            window.ajaxInit();
14360            setTimeout(window.ajaxDelayedInit, 1000);
14361            // New way to init apended things
14362            MK.core.initAll(this.el);
14363        }
14364	};
14365
14366}(jQuery));
14367MK.component.BackgroundImageSetter = (function ($) {
14368
14369	'use strict';
14370
14371	var module = {};
14372
14373
14374	/*---------------------------------------------------------------------------------*/
14375	/* Private Variables
14376	/*---------------------------------------------------------------------------------*/
14377
14378	/**
14379	 *	Take all elements with data-mk-img-set attribute and evaluate best image according to given device orientation and resolution,
14380	 *	sets style for backround-image on the same node element.	 *
14381	 */
14382
14383	var $win = $(window),
14384		// $layers = $('[data-mk-img-set]'),
14385		screen = getScreenSize(),
14386		orientation = getOrientation(),
14387		device = getDevice(),
14388		lastOrientation = orientation,
14389		lastDevice = device;
14390
14391
14392	/*---------------------------------------------------------------------------------*/
14393	/* Private Methods
14394	/*---------------------------------------------------------------------------------*/
14395
14396	function run($layers) {
14397		$layers.filter( function() {
14398			return !this.hasAttribute("mk-img-loaded");
14399		}).each(applyBg);
14400	}
14401
14402	// Keep our main side effect out of calculations so they can be run once before loop of applying bg as a result
14403	function applyBg() {
14404		var $this = $(this),
14405			imgs = $this.data('mk-img-set');
14406
14407		$this.css('background-image', 'url('+ module.getImage(imgs) +')');
14408		$this.find('.mk-adaptive-image').attr('src', module.getImage(imgs));
14409	}
14410
14411	// Keep track of current screen size while resizing but update device reference
14412	// and reapply backgrounds only when we discover switch point
14413	function handleResize($layers) {
14414		updateScreenSize();
14415		if(hasSwitched()) {
14416			updateDevice();
14417			run($layers);
14418		}
14419	}
14420
14421	function getScreenSize() {
14422		return {
14423			w: $win.width(),
14424			h: $win.height()
14425		};
14426	}
14427
14428	// Name our device classes and add them id which simply means which one is wider
14429	function getDevice() {
14430		if     (screen.w > 1024) 	return {class: 'desktop', id: 2};
14431		else if(screen.w > 736) 	return {class: 'tablet',  id: 1};
14432		else 					 	return {class: 'mobile',  id: 0};
14433	}
14434
14435	function getOrientation() {
14436		if(screen.w > screen.h) 	return 'landscape';
14437		else 						return 'portrait';
14438	}
14439
14440	function updateScreenSize() {
14441		screen = getScreenSize();
14442	}
14443
14444	function updateDevice() {
14445		if(lastOrientation !== orientation) orientation = lastOrientation;
14446		// Switch device only if going from smaller size to bigger.
14447		// Bigger to smaller is perfectly handled by browsers and doesn't require change and reupload
14448		if(lastDevice.id > device.id) device = lastDevice;
14449	}
14450
14451	function hasSwitched() {
14452		lastOrientation = getOrientation();
14453		lastDevice = getDevice();
14454
14455		if(lastOrientation !== orientation || lastDevice.class !== device.class) return true;
14456		else return false;
14457	}
14458
14459
14460	/*---------------------------------------------------------------------------------*/
14461	/* Public Methods
14462	/*---------------------------------------------------------------------------------*/
14463
14464	// As desired image might be not available we have to evaluate the best match.
14465	module.getImage = function (imgs) {
14466		if (imgs['responsive'] === 'false') {
14467			return (imgs['landscape']['desktop']) ? imgs['landscape']['desktop'] : (imgs['landscape']['external'] ? imgs['landscape']['external'] : '');
14468
14469		}
14470		var hasOrientation = !!imgs[orientation];
14471		// there are only two orientations now and we may get them by string name if both are there
14472		// or by index of 0 if only one is available. Note Objects has no lexical order so we need to grab key name by its index.
14473		// Also we may have external file for each orientation which we don't scale internaly so we grab it as it is. If nothing found return an empty string
14474		var imgOriented = imgs[ (hasOrientation ? orientation : Object.keys(imgs)[0]) ],
14475			imgExact    = (imgOriented[device.class]) ? imgOriented[device.class] : (imgOriented['external'] ? imgOriented['external'] : '');
14476		return imgExact;
14477	}
14478
14479	module.init = function ($layers) {
14480
14481		// Run and bind
14482		run($layers);
14483		$layers.attr('mk-img-loaded', '');
14484	};
14485
14486	module.onResize = function ($layers) {
14487		$win.on('resize', MK.utils.throttle( 500, function() {
14488			handleResize($layers);
14489		}));
14490	};
14491
14492	return module;
14493
14494}(jQuery));
14495
14496
14497jQuery(function($) {
14498
14499	var init = function init() {
14500		// Get All Layers, Excluding Edge Slider and Page Section
14501		$allLayers = $('[data-mk-img-set]').filter(function(index) {
14502			return !$(this).hasClass('mk-section-image') && !$(this).hasClass('background-layer') && !$(this).hasClass('mk-video-section-touch');
14503		});;
14504
14505		// Handle the resize
14506		MK.component.BackgroundImageSetter.onResize($allLayers);
14507
14508		// Set all the BG Layers
14509		MK.component.BackgroundImageSetter.init($allLayers);
14510	}
14511	init();
14512
14513	$(window).on('vc_reload', init);
14514
14515});
14516
14517(function( $ ) {
14518	'use strict';
14519
14520	var val = MK.val;
14521
14522	MK.component.FullHeight = function( el ) {
14523		var $window = $( window ),
14524			$this = $( el ),
14525			config = $this.data( 'fullheight-config' ),
14526			container = document.getElementById( 'mk-theme-container' ),
14527			minH = (config && config.min) ? config.min : 0,
14528			winH = null,
14529			height = null,
14530			update_count = 0,
14531			testing = MK.utils.getUrlParameter('testing'),
14532			offset = null;
14533
14534		// We need to provide height on the same specificity level for workaround to IE bug
14535		// connect.microsoft.com/IE/feedback/details/802625/min-height-and-flexbox-flex-direction-column-dont-work-together-in-ie-10-11-preview
14536		// stackoverflow.com/questions/19371626/flexbox-not-centering-vertically-in-ie
14537		if(MK.utils.browser.name === ('IE' || 'Edge')) $this.css( 'height', '1px' );
14538
14539		var update = function() {
14540
14541			if(update_count === 0) {
14542				winH = $window.height();
14543				// for correct calculate
14544				offset = $this.offset().top - 1;
14545				height = Math.max(minH, winH - val.offsetHeaderHeight( offset ));
14546				$this.css( 'min-height', height );
14547				if(testing !== undefined )
14548				update_count++;
14549			}
14550
14551		};
14552
14553		// TODO remove scroll listener by dynamic offset reader
14554		var init = function() {
14555			update();
14556			$window.on( 'resize', update );
14557			$window.on( 'scroll', update );
14558			window.addResizeListener( container, update );
14559		};
14560
14561		return {
14562			init : init
14563		};
14564	};
14565
14566})( jQuery );
14567
14568
14569(function( $ ) {
14570	'use strict';
14571
14572	var core  = MK.core,
14573		utils = MK.utils,
14574		path  = MK.core.path;
14575
14576
14577	MK.ui.FullScreenGallery = function( element, settings ) {
14578		this.element = element;
14579		this.config = settings;
14580
14581		this.isFullScreen = false;
14582	};
14583
14584
14585	// preload slick PLUGIN TO USE THIS
14586	MK.ui.FullScreenGallery.prototype = {
14587		dom : {
14588			fullScrBtn 		: '.slick-full-screen',
14589			exitFullScrBtn 	: '.slick-minimize',
14590			playBtn 		: '.slick-play',
14591			pauseBtn 		: '.slick-pause',
14592			shareBtn 		: '.slick-share',
14593			socialShare 	: '.slick-social-share',
14594		    wrapper 		: '.slick-slider-wrapper',
14595			slider 			: '.slick-slides',
14596			slides 			: '.slick-slide',
14597			dots 			: '.slick-dot',
14598			active 			: '.slick-active',
14599			hiddenClass 	: 'is-hidden',
14600			dataId 			: 'slick-index'
14601		},
14602
14603		tpl: {
14604			dot  : '<div class="slick-dot"></div>',
14605			next : '<a href="javascript:;" class="slick-next"> <svg width="33px" height="65px"> <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points=" 0.5,0.5 32.5,32.5 0.5,64.5"/> </svg> </a>',
14606			prev : '<a href="javascript:;" class="slick-prev"> <svg  width="33px" height="65px"> <polyline fill="none" stroke="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points=" 32.5,64.5 0.5,32.5 32.5,0.5"/> </svg> </a>'
14607		},
14608
14609		init : function() { 
14610			var self = this;
14611
14612			// core.loadDependencies([ path.plugins + 'slick.js' ], function() {
14613				self.cacheElements();
14614				self.getViewportSizes();
14615				self.updateSizes( 'window' );
14616				self.create();
14617				// update cache with elements propagated by plugin
14618				self.updateCacheElements();
14619				self.createPagination();
14620				self.bindEvents();
14621			// });
14622		},
14623
14624		create : function() {
14625			var self = this;
14626
14627			this.slick = this.$gallery.slick({
14628		        dots: true,
14629		        arrows: true,
14630				infinite: true,
14631				speed: 300,
14632				slidesToShow: 1,
14633				centerMode: true,
14634				centerPadding: '0px',
14635				variableWidth: true,
14636				autoplay: false,
14637				autoplaySpeed: 3000,
14638        		useTransform: true,
14639                prevArrow: self.tpl.prev,
14640                nextArrow: self.tpl.next,
14641                customPaging: function(slider, i) {
14642                    return self.tpl.dot;
14643                },
14644			});
14645		},
14646
14647		cacheElements : function() {
14648			this.$window = $( window );
14649			this.$gallery = $( this.element );
14650
14651			this.$fullScrBtn = $( this.dom.fullScrBtn );
14652			this.$exitFullScrBtn = $( this.dom.exitFullScrBtn );
14653			this.$playBtn = $( this.dom.playBtn );
14654			this.$pauseBtn = $( this.dom.pauseBtn );
14655			this.$shareBtn = $( this.dom.shareBtn );
14656			this.$socialShare = $( this.dom.socialShare );
14657
14658		    this.$wrapper = $( this.dom.wrapper );
14659			this.$slider = $( this.dom.slider );
14660			this.$slides = $( this.dom.slides );
14661			this.$imgs = this.$slides.find( 'img' );
14662			// store reference to initial images without slides appended by pugin
14663			// - needed for creating of pagination
14664			this.$originalImgs = this.$imgs;
14665		},
14666
14667		updateCacheElements : function() {
14668			this.$slides = $( this.dom.slides );
14669			this.$imgs = this.$slides.find( 'img' );
14670			this.$dots = $( this.dom.dots );
14671		},
14672
14673		bindEvents : function() {
14674			var self = this;
14675			this.$fullScrBtn.on( 'click', this.toFullScreen.bind( this ) );
14676			this.$exitFullScrBtn.on( 'click', this.exitFullScreen.bind( this ) );
14677			this.$playBtn.on( 'click', this.play.bind( this ) );
14678			this.$pauseBtn.on( 'click', this.pause.bind( this ) );
14679			this.$shareBtn.on( 'click', this.toggleShare.bind( this ) );
14680			this.$socialShare.on( 'click', 'a', this.socialShare.bind( this ) );
14681			this.$window.on( 'resize', this.onResize.bind( this ) );
14682			this.$window.on( 'keydown', function(e) {
14683				if(e.keyCode === 39) self.$gallery.slick('slickNext');
14684				if(e.keyCode === 37) self.$gallery.slick('slickPrev');
14685			});
14686			$( document ).on( 'fullscreenchange mozfullscreenchange webkitfullscreenchange msfullcreenchange', this.exitFullScreen.bind( this ) );
14687		},
14688
14689		getViewportSizes : function() {
14690			this.screen = {
14691				w: screen.width,
14692				h: screen.height
14693			};
14694			this.window = {
14695				w: this.$window.width(),
14696				h: this.$window.height()
14697			};
14698		},
14699
14700		updateSizes : function( viewport ) {
14701			this.$wrapper.width( this[ viewport ].w );
14702			this.$wrapper.height( '100%' );
14703			this.$imgs.height( '100%');
14704		},
14705
14706		createPagination : function() {
14707			var self = this;
14708			this.$dots.each( function( i ) {
14709				var img = self.$originalImgs.eq( i ).attr( 'src' );
14710
14711				$( this ).css({
14712					'background-image': 'url('+ img +')'
14713				});
14714			});	
14715		},
14716
14717		play : function(e) {
14718			e.preventDefault();
14719			this.$playBtn.addClass( this.dom.hiddenClass );
14720			this.$pauseBtn.removeClass( this.dom.hiddenClass );
14721			$( this.element ).slick( 'slickPlay' );
14722		},
14723
14724		pause : function(e) {
14725			e.preventDefault();
14726			this.$pauseBtn.addClass( this.dom.hiddenClass );
14727			this.$playBtn.removeClass( this.dom.hiddenClass );
14728			$( this.element ).slick( 'slickPause' );
14729		},
14730
14731		toggleShare : function(e) {
14732			e.preventDefault();
14733			this.$socialShare.toggleClass( this.dom.hiddenClass );
14734		},
14735
14736		getCurentId : function() {
14737			return this.$slides.filter( this.dom.active ).data( this.dom.dataId );
14738		},
14739
14740		toFullScreen : function() {
14741			var self = this;
14742
14743			this.$fullScrBtn.addClass( this.dom.hiddenClass );
14744			this.$exitFullScrBtn.removeClass( this.dom.hiddenClass );
14745
14746			this.$slider.hide().fadeIn( 500 );
14747			utils.launchIntoFullscreen( document.documentElement );
14748			this.updateSizes( 'screen' );
14749			$( this.element ).slick( 'slickGoTo', this.getCurentId(), true );
14750
14751			// Update state with delay so we avoid triggering exitFullScreen fn from 
14752			// fullscreenchange event
14753			setTimeout( function() {
14754				self.isFullScreen = true;
14755			}, 1000);					
14756		},
14757
14758		exitFullScreen : function() {
14759			if( this.isFullScreen ) { 
14760				this.$exitFullScrBtn.addClass( this.dom.hiddenClass );
14761				this.$fullScrBtn.removeClass( this.dom.hiddenClass );
14762
14763				utils.exitFullscreen();
14764				this.updateSizes( 'window' );
14765				$( this.element ).slick( 'slickGoTo', this.getCurentId(), true );
14766
14767				this.isFullScreen = false;
14768			}
14769
14770		},
14771
14772		onResize : function() {
14773			this.getViewportSizes();
14774			this.updateSizes( this.isFullScreen ? 'screen' : 'window' );
14775			$( this.element ).slick( 'refresh' );  
14776			$( this.element ).slick( 'slickGoTo', this.getCurentId(), true );
14777			this.updateCacheElements();
14778			this.createPagination();
14779		},
14780
14781		socialShare : function( e ) {
14782			e.preventDefault();
14783			var $this = $( e.currentTarget ),
14784				network = $this.data( 'network' ),
14785				id = this.config.id,
14786				url = this.config.url,
14787				title = this.$wrapper.find( '.slick-title' ).text(),
14788				name;
14789				var picture = this.$slides.filter( this.dom.active ).children().first().attr( 'src' );
14790			switch( network ) {
14791				case 'facebook': 
14792					url = 'https://www.facebook.com/sharer/sharer.php?picture=' + picture+'&u=' + url + '#id=' + id;
14793					name = 'Facebook Share';
14794					break;
14795				case 'twitter':
14796					url = 'http://twitter.com/intent/tweet?text=' + url + '#id=' + id;
14797					name = 'Twitter Share';
14798					break;
14799				case 'pinterest':
14800					url = 'http://pinterest.com/pin/create/bookmarklet/?media=' + picture + '&url=' + url + '&is_video=false&description=' + title;
14801					// other available link paranmeters: media, description
14802					name = 'Pinterest Share';
14803					break;
14804
14805			}
14806
14807       		window.open( url, name, "height=380 ,width=660, resizable=0, toolbar=0, menubar=0, status=0, location=0, scrollbars=0" );
14808		}
14809	};
14810
14811})( jQuery );
14812(function($) {
14813    'use strict';
14814
14815    MK.component.Grid = function( el ) {
14816    	var $container = $(el);
14817    	var config = $container.data( 'grid-config' );
14818        var isSlideshow = $container.closest('[data-mk-component="SwipeSlideshow"]').length;
14819        var miniGridConfig = {
14820            container: el,
14821            item: config.item + ':not(.is-hidden)',
14822            gutter: 0 
14823        };
14824
14825        var init = function init(){
14826            // Flags for cancelling usage goes first :
14827            // Quit early if we discover that Grid is used inside SwipeSlideshow as it brings bug with crossoverriding positioning 
14828            // + grid is not really needed as we have single row all handled by slider.
14829            // It happens only in woocommerce carousel as of hardcoded Grid in loop-start.php
14830            if(isSlideshow) return; 
14831	        MK.core.loadDependencies([ MK.core.path.plugins + 'minigrid.js' ], create);
14832        };
14833
14834        // Remove el hidden without adding proper class
14835        var prepareForGrid = function prepareForGrid() {
14836            var $item = $(this);
14837            var isHidden = ($item.css('display') === 'none');
14838            if(isHidden) $item.addClass('is-hidden');
14839            else $item.removeClass('is-hidden');
14840        };
14841
14842        var create = function create() {
14843            var timer = null;
14844
14845	        function draw() { 
14846                // Prevent plugin breaking when feeding it with hidden elements
14847                $container.find(config.item).each( prepareForGrid );
14848	            minigrid(miniGridConfig);
14849	        }
14850
14851            function redraw() {
14852                if (timer) clearTimeout(timer);
14853                timer = setTimeout(draw, 100);
14854            }
14855
14856            // init
14857	        draw(); 
14858            // If reinitializing drop existing event handler
14859            $(window).off('resize', redraw);
14860            $(window).on('resize', redraw);
14861            MK.utils.eventManager.subscribe('item-expanded', redraw);
14862            MK.utils.eventManager.subscribe('ajaxLoaded', redraw);
14863            MK.utils.eventManager.subscribe('staticFilter', redraw);
14864        };
14865
14866        return {
14867         	init : init
14868        };
14869    };
14870
14871})(jQuery);
14872
14873
14874
14875
14876
14877
14878
14879
14880/**
14881 * ICON FACTORY @ Maki
14882 * 
14883 * Javascript part that translates css styles into link to server side manufacturer.
14884 * By passing extra args we generate icons as needed on server and send them back with ajax and attch them to DOM here.
14885 *
14886 * This is temporary solution that helps us switching from font icons to singular svgs without too match overhead. The finalized solution shoulnd be 99% server side.
14887 * Our main templating is happening there. We should have an icon_factory(name, properties) function that we can call directly in templates to serve us icons. 
14888 * Post load, js soluition should target only elements that we have no direct access to. We set it as TODO for future as part of progressive development. 
14889 * When correct factory is done we should be able to use it here and there to progressively kill overhead generated by current solution until we could totally switch it.
14890 * 
14891 * Prons:
14892 * - automated process where we can mimic old behaviour
14893 * - possible bugs are easy to patch 
14894 * - far samller download size for assets needed by theme (no font families css and fonts itself to download, which are currently blocking page load time)
14895 * - icon generation moved to server side where our main templating is already happening
14896 * - we can easily switch how our Icon should be outputed - inline, img, object, iframe. Whatever our situation requires (img for responsive icons for example)
14897 *
14898 * Cons:
14899 * - possible bugs based on different nature of svgs / fonts. Need to be manually fixed
14900 * - some manual work to straighten things - litle css refactors here and there
14901 * - as the mapping the icons happens in server side, it may cause CPU bottlenecks and should be cashed in DB for repetitve usage.
14902 *
14903 *
14904 * TODO Refactor to config obj as parameter for easier passing it. Also decouple more - especially loops
14905 */
14906(function ($) {
14907	'use strict';
14908
14909	// As long as we can manage this manually it is better like so. We avoid delay based on waiting for ajax to finish
14910 	// $.get( MK.core.path.theme + '/assets/icons/icon-families.json', createAll);
14911 	var families = [
14912		['awesome-icons' , 'mk-icon-'], // [family, prefix]
14913		['icomoon' 		 , 'mk-moon-'],
14914		['pe-line-icons' , 'mk-li-'],
14915		['theme-icons' 	 , 'mk-jupiter-icon-'] 
14916	];
14917
14918	// Our css contains this extends for particular families of fonts. For now we automate the process and extend it here as well
14919	var extend = {
14920		'awesome-icons' : [], 
14921		'icomoon' : [],
14922		'pe-line-icons' : [],
14923		'theme-icons' : []
14924	};	
14925 	
14926 	// Cache holder for quick access to repeating icons. config / svg
14927	var _cache = {};
14928	var _cacheId = 0;
14929	// Merge configs to call it with single ajax
14930	var _config = [];
14931	// Counter for all families. We merge all our families for single ajax request and countdown when to trigger the download.
14932	var _roundCount = 0;
14933	// Mapper for icons - config / array with nodes
14934	var _iconMap = {};
14935
14936
14937	// Closure to merge $icons together and to run the download when we counted down icon families to 0
14938 	var getIconsSprite = (function() {
14939 		var $icons = null;
14940 		var iterator = 0;
14941
14942 		function run(callback) {
14943	 		var config = encodeURIComponent(JSON.stringify(_config));
14944
14945			$.ajax({
14946				url : MK.core.path.ajaxUrl,
14947				// dataType: 'xml',
14948				method: 'POST',
14949				data: {action : 'mk_get_icon', iterator: iterator++, config: config},
14950				success: function(sprite) { 
14951					callback(sprite, $icons);
14952					_config = [];
14953					_iconMap = {};
14954					$icons = null;
14955				},
14956				error: function(err) { 
14957					console.log('Icon load problem');
14958				}
14959			});
14960		}
14961
14962		return function(callback, $els, count) {
14963			if(!$icons) $icons = $els;
14964			else $icons.add($els);
14965			// console.log(count);
14966			if(!count) run(callback);
14967		};
14968 	}());
14969
14970 	// Wait for DOM manipulations and run where really needed
14971 	$(window).on('load', function() { 
14972 		setTimeout(function() {
14973 			createAll(document);
14974 			if($('.mk-header').length) createAll('.mk-header');
14975 			if($('.js-flexslider, .mk-flexslider').length) createAll('.js-flexslider, .mk-flexslider');
14976 			if($('.mk-accordion').length) createAll('.mk-accordion'); 
14977 		}, 1000); 
14978 	});
14979
14980 	MK.utils.eventManager.subscribe('ajaxLoaded', function() {
14981 		// Wait for actuall DOM insertion
14982 		setTimeout(createAll, 100, '.js-loop');
14983 	});
14984
14985	MK.utils.eventManager.subscribe('ajax-preview', function() {
14986 		setTimeout(createAll, 100, '.ajax-container');
14987	});
14988
14989	MK.utils.eventManager.subscribe('photoAlbum-open', function() {
14990 		setTimeout(createAll, 100, '.gallery-share');
14991	});
14992
14993	MK.utils.eventManager.subscribe('quickViewOpen', function() {
14994 		setTimeout(createAll, 300, '.mk-modal-content');
14995	});
14996
14997 	// Our main runner that creates all icons in given scope
14998 	function createAll(scope) {
14999		// iterate through families
15000 		for(var i = 0, l = families.length; i < l; i++) {
15001 			var family = families[i][0];
15002 			var prefix = families[i][1];
15003 			var $icons = getIcons(family, prefix, scope);
15004 			if($icons.length) {
15005 				_roundCount++;
15006 				// apply arguments from current loop iteration but send createIcons to event loop so it will get trigerred in the same order as this loop finish.
15007 				// We need it to pass all $icons first so we can merge all families before ajax request.
15008 				setTimeout(createIcons, 0, $icons, family, prefix);
15009 			}
15010 		}
15011 	}
15012
15013 	// Grab all els in given scope that contains our prefix, anywhere in class attribute. Extend if needed
15014 	function getIcons(family, prefix, scope) {
15015 		var $scope = $(scope);
15016 		var $icons = $scope.find('[class*='+ prefix +']');
15017 		var extraClassNames = extend[family];
15018 		// if nothing to extend just return what we have till now
15019 		if(!extraClassNames) return $icons; 
15020 		// Extend it with our css garbish
15021 		extraClassNames.forEach(function(className) {
15022 			var $icon = $scope.find(className);
15023 			$icons = $icons.add($icon);
15024 		});
15025 		// serve all
15026 		return $icons;
15027 	}
15028
15029
15030 	function createIcons($icons, family, prefix, i, unicode) {
15031 		var id   = i || 0;
15032		var icon = $icons[id];
15033
15034		// quick check point, if no more icons break recursion
15035		if(!icon) {
15036			_roundCount--;
15037			getIconsSprite(insertIcons, $icons, _roundCount, _config);
15038			return;
15039		}
15040
15041		var css       = getComputedStyle( icon, ':before');
15042		var classAttr = icon.getAttribute('class');
15043		var name      = (classAttr) ? matchClass(classAttr.split(' '), prefix) : false;
15044		var h         = getComputedStyle(icon).fontSize;
15045		var config    = createConfig(css, name, family, unicode, h);
15046		var cache 	  = JSON.stringify(config);
15047
15048		if(!config) {
15049			// Yep, we have a mess so sometimes we try to call for an icon where it should not exist (no class match or unicode found)
15050			// As we expect empty response from server, we just skip to next icon
15051
15052		} else if(_cache[cache]) {
15053			// Use cached icon when possible
15054			// 
15055			if(typeof _iconMap[cache] === 'undefined') _iconMap[cache] = [$icons.eq(id)];
15056			else _iconMap[cache].push($icons.eq(id));
15057
15058		} else {
15059			if(typeof _iconMap[cache] === 'undefined') _iconMap[cache] = [$icons.eq(id)];
15060			else _iconMap[cache].push($icons.eq(id));
15061
15062			_cache[cache] = _cacheId.toString(); // number as string so we could do [var] key lookup after reversal
15063			config.id = _cacheId; // extend config for server only
15064			_config.push(config);
15065
15066			_cacheId++; // increment after caching
15067		}
15068
15069		createIcons($icons, family, prefix, ++id);
15070 	}
15071
15072 	function insertIcons(sprite, $icons) {
15073 		var $sprite = $(sprite);
15074 		var $svgs   = $sprite.find('svg');
15075 		var idMap   = invert(_cache);
15076
15077 		$sprite.each(function() {
15078 			var $svg = $(this);
15079 			var id   = $svg.attr('data-cacheid'); // read as string
15080 			var configKey = idMap[id];
15081
15082 			_cache[configKey] = this;
15083 			// console.log(id, this)
15084 		});
15085
15086 		// console.log('sprite',sprite)
15087 		// 
15088
15089 		Object.keys(_iconMap).forEach(function (cacheKey) {
15090		   	_iconMap[cacheKey].forEach(function($icons) {
15091		   		$icons.each(function() {
15092		   			var $svg = $(_cache[cacheKey]).clone();
15093		   			var $icon = $(this);
15094
15095		   			// console.log($icon[0], _cache[cacheKey]);  
15096		   			
15097		   			function remove() {
15098		   				// exclude problematic stuff
15099		   				if($icon.parents('.pricing-features')) return;
15100			   			$icon.not('.mk-jupiter-icon-xing') 
15101			   				 .not('.mk-jupiter-icon-square-xing')
15102			   				 .not('.mk-jupiter-icon-simple-xing')
15103			   				 .find('.mk-svg-icon') 
15104			   				 .not('[data-name="mk-moon-zoom-in"]')
15105			   				 .remove(); // and remove else to reapply styles with new loaded svg
15106		   			}
15107
15108		   			if($svg.length ) remove();
15109
15110		   			if(!$icon.find('svg').length) {
15111		   				if($icon.parents('.widget ul').length) $icon.prepend($svg);
15112		   				else $icon.append($svg);
15113					}
15114		   		});
15115		   	});
15116		});
15117
15118 		// Notify rest of app
15119		MK.utils.eventManager.publish('iconsInsert');
15120 	}
15121
15122 	// Prepare configuration for server side. We need to grab icons and manipulate them a little there
15123 	function createConfig(css, name, family, unicode, height) {
15124 		var hasGradient  = checkGradient(css);
15125 		var hasDirection = extractGradient('direction', css.background);
15126
15127 		var config = {
15128 			family: family, 
15129 			// this is mostly for Extends. Because we've been customizing singular elements and assigning content unicode manually, 
15130 			// now we don't have any proper anchor for usage with our json map
15131 			unicode: (unicode) ? unicode : decodeUnicode(css.content), 
15132 			name: name,
15133 			// fill: css.color,
15134 			gradient_type:  hasGradient ? extractGradient('type' , css.background) : false,
15135 			gradient_start: hasGradient ? extractGradient('start', css.background) : false,
15136 			gradient_stop:  hasGradient ? extractGradient('stop' , css.background) : false,
15137 			gradient_direction: hasDirection ? extractGradient('direction', css.background).replace(' ', '-') : false,
15138 			height: height
15139 		};
15140
15141 		// If there is no name or unicode the whole config is invalid
15142 		if(!config.name && !config.unicode) return false;
15143 		else return config;
15144 	}
15145
15146 	// Extract class name that represents the icon that we try to generate
15147 	function matchClass(classes, prefix) {
15148 		// var missing = '';
15149 		for(var i = 0, l = classes.length; i < l; i++) {
15150 			if(classes[i].indexOf(prefix) !== -1) return classes[i]; // return first matched class name
15151 			// else missing += ' .' + classes[i]; // collect not matching classes
15152 		}
15153 		// if we didn't returned anything within loop we output notification here. Keep it for testing only
15154 		// console.log('Possibility of missing icons for element with classes:' + missing);
15155 	}
15156
15157 	// Check if background conatains gradient declaration and return bg string if so or false 
15158 	function checkGradient(css) {
15159 		var bg = css.background;
15160 		if(bg.indexOf('radial') !== -1 || bg.indexOf('linear') !== -1) return bg;
15161 		else return false;
15162 	}
15163
15164 	// Extract background attribiutes from bg string.
15165 	// Multipurpose function which returns part we ask for
15166 	function extractGradient(attr, grad) {
15167 		// quit if gradient is falsy
15168 		// console.log(grad);
15169 		if(!grad) return false;
15170
15171 		var isRadial = grad.indexOf('radial')  !== -1;
15172 		var isLinear = grad.indexOf('linear')  !== -1;
15173 		var hasDirection = grad.indexOf('(to') !== -1;
15174 		var f, t; // from, to
15175
15176 		if(attr === 'type') {
15177 			if(isRadial) return 'radial';
15178 			if(isLinear) return 'linear';
15179
15180 		} else if(attr === 'start') {
15181 			f = getStrPosition(grad, 'rgb(', 1);
15182 			t = getStrPosition(grad, '0%'  , 1);
15183
15184 		} else if(attr === 'stop') {
15185 			f = getStrPosition(grad, 'rgb(', 2);
15186 			t = getStrPosition(grad, '100%', 1);
15187
15188 		} else if(attr === 'direction') {
15189 			if(!hasDirection) return false;
15190 			f = getStrPosition(grad, '(to', 1) + 4;
15191 			t = getStrPosition(grad, ', rgb(', 1);
15192
15193 		} else {
15194 			return false;
15195 		}
15196 		
15197 		return grad.slice(f, t);
15198 	}
15199
15200 	// Helper for getting indexOf but with lookup for instance of the string
15201 	// str - string to search
15202 	// m - what we're looking for
15203 	// i - instance, starting at 1
15204 	function getStrPosition(str, m, i) {
15205	   return str.split(m, i).join(m).length;
15206	}
15207
15208	// JS outputs unicode results rather than code representation. This helper function does the job
15209	function decodeUnicode(content) {
15210		// escape() kills \ escape signature and outputs it as %u
15211		// str replace to drop special chars
15212		// and we bring it all to lowercase to match filenames we keep on server
15213		if(content && content !== 'none') return escape(content).replace(/%22/g, '').replace('%u', '').toLowerCase();
15214		else return false; // just in case we haven't provided content to work with
15215	}
15216
15217	function invert(obj) {
15218	  	var new_obj = {};
15219	  	for (var prop in obj) {
15220	    	if(obj.hasOwnProperty(prop)) {
15221	      		new_obj[obj[prop]] = prop;
15222	    	}
15223	  	}
15224	  	return new_obj;
15225	}
15226
15227}(jQuery));
15228/*!
15229 * imagesLoaded PACKAGED v4.1.1
15230 * JavaScript is all like "You images are done yet or what?"
15231 * MIT License
15232 */
15233
15234!function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}("undefined"!=typeof window?window:this,function(){function t(){}var e=t.prototype;return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[];return-1==n.indexOf(e)&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e);var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||{};return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=i.indexOf(e);return-1!=n&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=0,o=i[n];e=e||[];for(var r=this._onceEvents&&this._onceEvents[t];o;){var s=r&&r[o];s&&(this.off(t,o),delete r[o]),o.apply(this,e),n+=s?0:1,o=i[n]}return this}},t}),function(t,e){"use strict";"function"==typeof define&&define.amd?define(["ev-emitter/ev-emitter"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}(window,function(t,e){function i(t,e){for(var i in e)t[i]=e[i];return t}function n(t){var e=[];if(Array.isArray(t))e=t;else if("number"==typeof t.length)for(var i=0;i<t.length;i++)e.push(t[i]);else e.push(t);return e}function o(t,e,r){return this instanceof o?("string"==typeof t&&(t=document.querySelectorAll(t)),this.elements=n(t),this.options=i({},this.options),"function"==typeof e?r=e:i(this.options,e),r&&this.on("always",r),this.getImages(),h&&(this.jqDeferred=new h.Deferred),void setTimeout(function(){this.check()}.bind(this))):new o(t,e,r)}function r(t){this.img=t}function s(t,e){this.url=t,this.element=e,this.img=new Image}var h=t.jQuery,a=t.console;o.prototype=Object.create(e.prototype),o.prototype.options={},o.prototype.getImages=function(){this.images=[],this.elements.forEac
15234h(this.addElementImages,this)},o.prototype.addElementImages=function(t){"IMG"==t.nodeName&&this.addImage(t),this.options.background===!0&&this.addElementBackgroundImages(t);var e=t.nodeType;if(e&&d[e]){for(var i=t.querySelectorAll("img"),n=0;n<i.length;n++){var o=i[n];this.addImage(o)}if("string"==typeof this.options.background){var r=t.querySelectorAll(this.options.background);for(n=0;n<r.length;n++){var s=r[n];this.addElementBackgroundImages(s)}}}};var d={1:!0,9:!0,11:!0};return o.prototype.addElementBackgroundImages=function(t){var e=getComputedStyle(t);if(e)for(var i=/url\((['"])?(.*?)\1\)/gi,n=i.exec(e.backgroundImage);null!==n;){var o=n&&n[2];o&&this.addBackground(o,t),n=i.exec(e.backgroundImage)}},o.prototype.addImage=function(t){var e=new r(t);this.images.push(e)},o.prototype.addBackground=function(t,e){var i=new s(t,e);this.images.push(i)},o.prototype.check=function(){function t(t,i,n){setTimeout(function(){e.progress(t,i,n)})}var e=this;return this.progressedCount=0,this.hasAnyBroken=!1,this.images.length?void this.images.forEach(function(e){e.once("progress",t),e.check()}):void this.complete()},o.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent("progress",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount==this.images.length&&this.complete(),this.options.debug&&a&&a.log("progress: "+i,t,e)},o.prototype.complete=function(){var t=this.hasAnyBroken?"fail":"done";if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent("always",[this]),this.jqDeferred){var e=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[e](this)}},r.prototype=Object.create(e.prototype),r.prototype.check=function(){var t=this.getIsImageComplete();return t?void this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),void(this.proxyImage.src=this.img.src))},r.prototype.getIsImageComplete=function(){return this.img.complete&&void 0!==this.img.naturalWidth},r.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.img,e])},r.prototype.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t)},r.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},r.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},r.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},s.prototype=Object.create(r.prototype),s.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url;var t=this.getIsImageComplete();t&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},s.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},s.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.element,e])},o.makeJQueryPlugin=function(e){e=e||t.jQuery,e&&(h=e,h.fn.imagesLoaded=function(t,e){var i=new o(this,t,e);return i.jqDeferred.promise(h(this))})},o.makeJQueryPlugin(),o});
15235
15236(function($, window){
15237    'use strict';
15238
15239    var scrollY = MK.val.scroll; 
15240    var dynamicHeight = MK.val.dynamicHeight;
15241
15242    var $window = $(window);
15243    var $containers = $('.js-loop');
15244
15245    $containers.each( pagination );
15246
15247	$window.on( 'vc_reload', function() {
15248		$('.js-loop').each( pagination );
15249	} );
15250
15251    function pagination() {
15252        var unique = Date.now();
15253        var $container = $(this);
15254        var $superContainer = $container.parent(); // should contain clearing so it stretches with floating children
15255        var $loadBtn = $container.siblings('.js-loadmore-holder').find('.js-loadmore-button');
15256        var $loadScroll = $('.js-load-more-scroll');
15257        var style = $container.data('pagination-style');
15258        var maxPages = $container.data('max-pages');
15259        var id = '#' + ($container.attr('id'));
15260        var ajaxLoader = new MK.utils.ajaxLoader(id);
15261        var isLoadBtn = (style === 2);
15262        var isInfiniteScroll = (style === 3); // add flag for last container
15263        var scrollCheckPoint = null;
15264        var isHandlerBinded = false;
15265
15266        ajaxLoader.init();
15267
15268        init();
15269
15270        function init() {
15271            MK.utils.eventManager.subscribe('ajaxLoaded', onLoad);
15272            bindHandlers();
15273            if( isInfiniteScroll ) scrollCheckPoint = spyScrollCheckPoint();
15274
15275			$window.on( 'vc_reload', function() {
15276				$window.off('scroll', handleScroll);
15277			} );
15278        }
15279
15280        function bindHandlers() {
15281            if( isLoadBtn ) $loadBtn.on('click', handleClick);
15282            if( isInfiniteScroll ) $window.on('scroll', handleScroll); 
15283            isHandlerBinded = true;
15284        }
15285
15286        function unbindHandlers() {
15287            if( isLoadBtn ) $loadBtn.off('click', handleClick);
15288            if( isInfiniteScroll ) $window.off('scroll', handleScroll);
15289            isHandlerBinded = false;
15290        }
15291
15292        function handleClick(e) {
15293            e.preventDefault();
15294            if(!ajaxLoader.isLoading) loadMore();
15295        }
15296
15297        function handleScroll() {
15298            if((scrollY() > scrollCheckPoint()) && !ajaxLoader.isLoading) loadMore();
15299        }
15300
15301        function loadMore() {
15302            loadingIndicatorStart();
15303            var page = ajaxLoader.getData('paged');
15304            ajaxLoader.setData({paged: ++page});
15305            ajaxLoader.load(unique);
15306        }
15307
15308        function onLoad(e, response) {
15309            if( typeof response !== 'undefined' && response.id === id) {
15310                // Checking found posts helps to fix all pagination styles 
15311                if( ajaxLoader.getData('found_posts') <= 0 && ajaxLoader.getData('paged') >= ajaxLoader.getData('maxPages')) loadingIndicatorHide();
15312                else loadingIndicatorShow();
15313                if(response.unique === unique) $container.append(response.content);
15314                loadingIndicatorStop();
15315            }
15316        }
15317
15318        function loadingIndicatorStart() {
15319            if(isLoadBtn) $loadBtn.addClass('is-active');
15320            else if(isInfiniteScroll) MK.ui.loader.add('.js-load-more-scroll');
15321
15322        }
15323
15324        function loadingIndicatorStop() {
15325            if(isLoadBtn) $loadBtn.removeClass('is-active');
15326            else if(isInfiniteScroll) MK.ui.loader.remove('.js-load-more-scroll');
15327        }
15328
15329        function loadingIndicatorShow() {
15330            if(isHandlerBinded) return;
15331            if(isLoadBtn) $loadBtn.show();
15332            else if(isInfiniteScroll) $loadScroll.show();
15333            bindHandlers();
15334        }
15335
15336        function loadingIndicatorHide() {
15337            if(!isHandlerBinded) return;
15338            if(isLoadBtn) $loadBtn.hide();
15339            else if(isInfiniteScroll) $loadScroll.hide();
15340            unbindHandlers();
15341        }
15342
15343
15344        function spyScrollCheckPoint() {
15345            var containerO = 0;
15346            var containerH = dynamicHeight( $superContainer );
15347            var winH = dynamicHeight( window );
15348 
15349            var setVals = function() {
15350                containerO = $superContainer.offset().top;
15351            };
15352
15353            setVals();
15354            $window.on('resize', function() { requestAnimationFrame(setVals); });
15355
15356            return function() {
15357                return (containerH() + containerO) - (winH() * 2);
15358            };
15359        }
15360    }
15361
15362})(jQuery, window);
15363(function($) {
15364	'use strict';
15365
15366	// Check if it's inside hidden parent
15367	// Cannot be position: fixed
15368	function isHidden(el) {
15369	    return (el.offsetParent === null);
15370	}
15371
15372	MK.component.Masonry = function(el) {
15373		var $window = $(window);
15374		var $container = $(el);
15375		var config = $container.data( 'masonry-config' );
15376		var $masonryItems = $container.find(config.item);
15377		var cols = config.cols || 8;
15378		var $filterItems = null; // assign only when apply filter
15379		var wall = null;
15380		
15381        var init = function init() {
15382        	MK.core.loadDependencies([ MK.core.path.plugins + 'freewall.js' ], onDepLoad);
15383        };
15384
15385        var onDepLoad = function onDepLoad() {
15386        	masonry();
15387
15388        	// Events
15389	        $window.on('resize', onResize);
15390            MK.utils.eventManager.subscribe('ajaxLoaded', onPostAddition);
15391			MK.utils.eventManager.subscribe('staticFilter', resize);
15392        };
15393
15394	    var masonry = function masonry() {
15395	    	// Quit for hidden elements for now.
15396	    	if(isHidden(el)) return;
15397
15398	    	var newCols;
15399	    	if(window.matchMedia( '(max-width:600px)' ).matches) newCols = 2;
15400	    	else if(window.matchMedia( '(max-width:850px)' ).matches) newCols = 4;
15401	    	else newCols = cols;
15402
15403	    	var colW = $container.width() / newCols;
15404
15405	        wall = new Freewall( config.container );
15406
15407	        // We need to pass settings to a plugin via reset method. Strange but works fine.
15408			wall.reset({
15409				selector: config.item + ':not(.is-hidden)',
15410				gutterX: 0, // set default gutter to 0 and again - apply margins to item holders in css
15411				gutterY: 0,
15412				cellW: colW,
15413				cellH: colW
15414			});
15415
15416	        wall.fillHoles();
15417	        wall.fitWidth();
15418
15419	        $masonryItems.each(function() {
15420	        	$(this).data('loaded', true);
15421	        });
15422        };
15423
15424
15425		// Clear attributes after the plugin. It's API method dosn't handle it properly
15426		var destroyContainer = function destroyContainer() {
15427			$container.removeAttr('style')
15428				 .removeData('wall-height')
15429				 .removeData('wall-width')
15430				 .removeData('min-width')
15431				 .removeData('total-col')
15432				 .removeData('total-row')
15433				 .removeAttr('data-wall-height')
15434				 .removeAttr('data-wall-width')
15435				 .removeAttr('data-min-width')
15436				 .removeAttr('data-total-col')
15437				 .removeAttr('data-total-row');
15438		};
15439
15440		var destroyItem = function destroyItem() {
15441			var $item = $(this);
15442			$item.removeAttr('style')
15443				 .removeData('delay')
15444				 .removeData('height')
15445				 .removeData('width')
15446				 .removeData('state')
15447				 .removeAttr('data-delay')
15448				 .removeAttr('data-height')
15449				 .removeAttr('data-width')
15450				 .removeAttr('data-state'); 
15451		};
15452
15453		var destroyAll = function destroyAll() {
15454	    	if( !wall ) return;
15455    		wall.destroy(); // API destroy
15456    		destroyContainer();
15457    		$masonryItems.each( destroyItem ); // run our deeper destroy
15458		};
15459
15460		var onResize = function onResize() {
15461			requestAnimationFrame(resize);
15462		};
15463
15464        var refresh = function refresh() {
15465	    	if( !wall ) return; 
15466	    	setTimeout(wall.fitWidth.bind(wall), 5);
15467        };
15468
15469        var resize = function resize() {
15470        	destroyAll();
15471	    	masonry();
15472        };
15473
15474        var onPostAddition = function onPostAddition() {
15475        	$masonryItems = $container.find(config.item);
15476
15477        	$masonryItems.each(function() {
15478        		var $item = $(this),
15479        			isLoaded = $item.data('loaded');
15480
15481        		if(!isLoaded) $item.css('visibility', 'hidden');
15482        	});
15483
15484        	
15485        	$container.mk_imagesLoaded().then(function() {
15486        		destroyAll();
15487        		masonry();
15488        	});
15489        };
15490
15491        return {
15492         	init : init
15493        };
15494	};
15495
15496}(jQuery));
15497(function($) {
15498	'use strict';
15499
15500	MK.component.Pagination = function(el) {
15501		this.el = el;
15502	};
15503
15504	MK.component.Pagination.prototype = {
15505		init: function init() {
15506			this.cacheElements(); 
15507			this.bindEvents();
15508			this.onInitLoad();
15509		},
15510
15511		cacheElements: function cacheElements() {
15512			this.lastId = 1;
15513			this.unique = Date.now();
15514			this.$pagination = $(this.el);
15515			this.$container = this.$pagination.prev('.js-loop');
15516			this.$pageLinks = this.$pagination.find('.js-pagination-page');
15517			this.$nextLink = this.$pagination.find('.js-pagination-next');
15518			this.$prevLink = this.$pagination.find('.js-pagination-prev');
15519			this.$current = this.$pagination.find('.js-current-page');
15520			this.$maxPages = this.$pagination.find('.pagination-max-pages'); // TODO change in DOM and here to js class
15521			this.containerId = '#' + this.$container.attr('id');
15522			this.pagePathname = window.location.pathname;
15523			this.pageSearch = window.location.search;
15524			this.popState = false;
15525			this.ajaxLoader = new MK.utils.ajaxLoader('#' + this.$container.attr('id'));
15526			this.ajaxLoader.init();
15527		},
15528
15529		bindEvents: function bindEvents() {
15530			this.$pageLinks.on('click', this.pageClick.bind(this));
15531			this.$nextLink.on('click', this.nextClick.bind(this));
15532			this.$prevLink.on('click', this.prevClick.bind(this)); 
15533			MK.utils.eventManager.subscribe('ajaxLoaded', this.onLoad.bind(this));
15534		},
15535
15536		pageClick: function pageClick(e) {
15537			e.preventDefault(); 
15538			var $this = $(e.currentTarget);
15539			var id = parseFloat($this.attr('data-page-id'));
15540
15541			if(id > this.ajaxLoader.getData('maxPages') || id < 1) return;
15542			this.load(id, $this);
15543			this.updatePagedNumUrl( id );
15544		},
15545
15546		nextClick: function nextClick(e) {
15547			e.preventDefault(); 
15548			if(this.ajaxLoader.getData('paged') === this.ajaxLoader.getData('maxPages')) return;
15549			this.load(++this.lastId, $(e.currentTarget));
15550			this.updatePagedNumUrl( this.lastId );
15551		},
15552
15553		prevClick: function prevClick(e) {
15554			e.preventDefault(); 
15555			if(this.ajaxLoader.getData('paged') === 1) return;
15556			this.load(--this.lastId, $(e.currentTarget));
15557			this.updatePagedNumUrl( this.lastId );
15558		},
15559
15560		load: function load(id, $el) {
15561			this.lastId = id;
15562			this.ajaxLoader.setData({paged: id});
15563			this.ajaxLoader.load(this.unique);
15564			this.removeIndicator();
15565			MK.ui.loader.add($el);
15566		},
15567
15568		onLoad: function success(e, response) {
15569			if( typeof response !== 'undefined' && response.id === this.containerId) {
15570				this.updatePagination();
15571				this.lastId = this.ajaxLoader.getData('paged');
15572
15573				if(response.unique === this.unique) {
15574					this.removeIndicator();
15575					this.scrollPage();
15576			        this.$container.html(response.content);  
15577				}   
15578			}         
15579        },
15580
15581        updatePagination: function updatePagination() {
15582        	var self = this;
15583
15584        	// Hide / show arrows
15585        	var isFirst = (this.ajaxLoader.getData('paged') === 1);
15586        	var isLast = (this.ajaxLoader.getData('paged') === this.ajaxLoader.getData('maxPages'));
15587
15588        	if(isFirst) this.$prevLink.addClass('is-vis-hidden');
15589        	else this.$prevLink.removeClass('is-vis-hidden');
15590
15591        	if(isLast) this.$nextLink.addClass('is-vis-hidden');
15592        	else this.$nextLink.removeClass('is-vis-hidden');
15593
15594			// X of Y
15595			this.$current.html(this.ajaxLoader.getData('paged'));
15596			this.$maxPages.html(this.ajaxLoader.getData('maxPages'));
15597
15598			// Move overfloating items
15599			var displayItems = 10;
15600			var centerAt = displayItems / 2;
15601
15602			if(this.ajaxLoader.getData('maxPages') > displayItems) {
15603				this.$pageLinks.each(function(i) {
15604
15605					var id = self.lastId - centerAt;
15606						id = Math.max(id, 1);
15607						id = Math.min(id, self.ajaxLoader.getData('maxPages') - displayItems + 1);
15608						id = id + i;
15609
15610					$(this).html( id ).attr('data-page-id', id).show();
15611
15612					if(i === 0 && id > 1) $(this).html('...');
15613					if(i === displayItems - 1 && id < self.ajaxLoader.getData('maxPages')) $(this).html('...');
15614				});
15615			} else {
15616				this.$pageLinks.each(function(i) {
15617					var $link = $(this);
15618					var id = i + 1;
15619
15620					$link.html(id).attr('data-page-id', id);
15621
15622					if( self.ajaxLoader.getData('maxPages') === 1) {
15623						self.$pageLinks.hide();
15624					} else {
15625						if(i > self.ajaxLoader.getData('maxPages') - 1) $link.hide();
15626						else $link.show();						
15627					}
15628
15629				});
15630			}
15631
15632        	// Highlight current only
15633			this.$pageLinks.filter('[data-page-id="' + this.ajaxLoader.getData('paged') + '"]' ).addClass('current-page')
15634				 .siblings().removeClass('current-page');
15635
15636        },
15637
15638        scrollPage: function scrollPage() {
15639            var containerOffset = this.$container.offset().top;
15640            var offset = containerOffset - MK.val.offsetHeaderHeight( containerOffset ) - 20; 
15641
15642            this.$container.find('a:first').focus()
15643            MK.utils.scrollTo( offset ); 
15644        },
15645
15646        removeIndicator: function removeIndicator() {
15647        	MK.ui.loader.remove('.js-pagination-page, .js-pagination-next, .js-pagination-prev');
15648        },
15649
15650		/**
15651		 * Set some actions when archive/category page is loaded. Actions list:
15652		 * - Select the correct paged ID on pagination list.
15653		 * - Set current paged ID on the label.
15654		 * - Add event listener onpopstate for handling prev/next button of Browser URL.
15655		 * - Set info for updatePagedNumUrl() about request comes from popstate.
15656		 *
15657		 * @since 5.9.8
15658		 */
15659		onInitLoad: function onInitLoad() {
15660			var initPagedID = this.$pagination.data( 'init-pagination' );
15661			if ( initPagedID && initPagedID > 1 ) {
15662				this.$current.html( initPagedID );
15663				this.$pageLinks.filter( '[data-page-id="' + initPagedID + '"]' ).addClass( 'current-page' ).siblings().removeClass( 'current-page' );
15664			}
15665
15666			// Run popstate only if it's supported by the browser.
15667			if ( 'onpopstate' in window ) {
15668				var thisPop = this;
15669				window.onpopstate = function( event ) {
15670					var id = 1;
15671
15672					// At start, state is always null. So, we should check it before processing.
15673					if ( typeof event.state === 'object' && event.state ) {
15674						var state = event.state;
15675
15676						// Set paged ID for updating page.
15677						if ( state.hasOwnProperty( 'MkPagination' ) ) {
15678							var currentState = state.MkPagination;
15679							if ( currentState.hasOwnProperty( 'paged' ) ) {
15680								id = parseFloat( currentState.paged );
15681							}
15682						}
15683					} else {
15684						id = parseFloat( thisPop.getURLPagedID() );
15685					}
15686
15687					// Tell updatePagedNumUrl() if request come from popstate.
15688					thisPop.popState = true;
15689					thisPop.$pageLinks.filter( '[data-page-id="' + id + '"]' ).trigger( 'click' );
15690				}
15691			}
15692		},
15693
15694		/**
15695		 * Update current pagination browser URL by adding/changing paged number. Only run if
15696		 * the browser support pushState and the request not coming from popstate.
15697		 *
15698		 * WordPress has some ways to set paged number:
15699		 * 1. page/[number], paged=[number] will be directed here.
15700		 * 2. page=[number]
15701		 * So, we should check which one the request is used here.
15702		 *
15703		 * @since 5.9.8
15704		 */
15705		updatePagedNumUrl: function updatePagedNumUrl( id ) {
15706			// Check pushState browser support and ignore if request come from popstate.
15707			if ( 'history' in window && 'pushState' in history && id && ! this.popState ) {
15708				var fullPage = this.pagePathname + this.pageSearch;
15709				var isQueryPage = false;
15710
15711				// Style 1 - /page/[number], as default value.
15712				var newPage = 'page/' + id + '/';
15713				var expPage = /page\/\d+\/?/;
15714				var result = this.pagePathname.match( /\/page\/\d+/ );
15715				var isPagedExist = ( result ) ? true : false;
15716
15717				// Style 2 - ?page=[number], only run if /page/ is not exist and URL query var exist.
15718				if ( ! isPagedExist && this.pageSearch ) {
15719					isQueryPage = this.pageSearch.match( /page\=\d+/ );
15720					if ( isQueryPage ) {
15721						newPage = 'page=' + id;
15722						expPage = /page\=\d+/;
15723					}
15724				}
15725
15726				// If page number is 1, remove paged number from URL.
15727				if ( id === 1 ) {
15728					newPage = '';
15729					if ( isQueryPage ) {
15730						expPage = ( this.pageSearch.match( /\&+/ ) ) ? /page\=\d+\&?/ : /\?page\=\d+\&?/;
15731					}
15732				}
15733
15734				// Set new pathname. Do replacement only if the new pathname contains paged number.
15735				var newURL = this.pagePathname + newPage + this.pageSearch;
15736				if ( fullPage.match( expPage ) ) {
15737					newURL = fullPage.replace( expPage, newPage );
15738				}
15739
15740				// Set history state and return popstate back to fal
15740se.
15741				var historyState = {
15742					MkPagination: {
15743						url: newURL,
15744						paged: id
15745					}
15746				}
15747				this.popState = false;
15748
15749				// Push new pathname to display/hide the paged number.
15750				window.history.pushState( historyState, null, newURL );
15751			}
15752			this.popState = false;
15753		},
15754
15755		/**
15756		 * Get current URL page ID. Notes:
15757		 * 1. page/[number], paged=[number] will be directed here.
15758		 * 2. page=[number]
15759		 *
15760		 * @return {integer} Current paged ID. Default 1.
15761		 */
15762		getURLPagedID: function getURLPagedID() {
15763			var pathname = window.location.pathname;
15764			var search = window.location.search;
15765			var pagedId = 1;
15766			var result = '';
15767			var isPagedExist = false;
15768
15769			// Search based on style 1.
15770			result = pathname.match( /\/page\/(\d+)/ );
15771			if ( result ) {
15772				isPagedExist = true;
15773				pagedId = ( result.hasOwnProperty( 1 ) ) ? result[1] : 1;
15774			}
15775
15776			// Search based on style 2.
15777			if ( ! isPagedExist && search ) {
15778				result = search.match( /page\=(\d+)/ );
15779				if ( result ) {
15780					isPagedExist = true;
15781					pagedId = ( result.hasOwnProperty( 1 ) ) ? result[1] : 1;
15782				}
15783			}
15784
15785			return pagedId;
15786		}
15787	};
15788
15789}(jQuery));
15790(function( $ ) {
15791	'use strict';
15792
15793	var val = MK.val,
15794		utils = MK.utils;
15795
15796	MK.component.Parallax = function( el ) {
15797		var self = this,
15798			$this = $( el ),
15799        	obj = $this[0],
15800			$window = $( window ),
15801		    container = document.getElementById( 'mk-theme-container' ),
15802			config = $this.data( 'parallax-config' ),
15803			$holder = $( config.holder ),
15804			headerHeight = null,
15805			offset = null,
15806			elHeight = null,
15807			ticking = false,
15808			isMobile = null;
15809
15810
15811		var clientRect = null;
15812
15813		var update = function() {
15814			// Clear styles to check for natural styles
15815			// then apply position and size
15816			obj.style.transform = null;
15817			obj.style.top = null;
15818			obj.style.bottom = null;
15819
15820			isMobile = MK.utils.isMobile();
15821
15822			if( isMobile ) {
15823        		$this.css( 'height', '' );
15824				return;
15825			}
15826
15827			clientRect = $this[ 0 ].getBoundingClientRect();
15828			offset = clientRect.top;
15829			elHeight = clientRect.height;
15830			headerHeight = val.offsetHeaderHeight( offset );
15831			offset = offset - headerHeight + val.scroll(); 
15832
15833			setPosition(); 
15834			setSize( ); 
15835		};
15836
15837
15838        var h = 0,
15839        	winH = 0,
15840        	proportion = 0,
15841        	height = 0;
15842
15843        // Position and background attachement should me moved to CSS but we repair it high specificity here as styles are not reliable currently
15844        var setSize = function() {
15845        	$this.css( 'height', '' );
15846        	winH = $window.height() - headerHeight;
15847        	h = obj.getBoundingClientRect().height; 
15848
15849        	if( config.speed <= 1 && config.speed > 0 ) {
15850        		if( offset === 0 ) {
15851	        		$this.css({
15852	        			backgroundAttachment: 'scroll',
15853	        			'will-change': 'transform'
15854	        		});
15855        		} else {
15856	        		$this.css({
15857						height : h + ( (winH - h) * config.speed ),
15858	        			backgroundAttachment: 'scroll',
15859	        			'will-change': 'transform' 
15860	        		}); 
15861	        	}
15862
15863        	} else if ( config.speed > 1 && h <= winH ) {
15864        		$this.css({
15865        			// good for full heights - 2 because it's viewable by 2 screen heights
15866        			height: ( winH  +  ( ( winH * config.speed ) - winH ) * 2 ),  
15867        			top: -( ( winH * config.speed ) - winH ),
15868        			backgroundAttachment: 'scroll',
15869        			'will-change': 'transform'
15870        		}); 
15871
15872        	} else if ( config.speed > 1 && h > winH ) {
15873        		proportion = h / winH;
15874        		height = ( winH  +  ( ( winH * config.speed ) - winH ) * (1 + proportion) );
15875 
15876        		$this.css({
15877        			height: height,
15878        			top: -( height - (winH * config.speed) ),
15879        			backgroundAttachment: 'scroll',
15880        			'will-change': 'transform'
15881        		}); 
15882
15883        	} else if ( config.speed < 0 && h >= winH ) {
15884        		height = h * (1  - config.speed);
15885        		$this.css({
15886					height: height + (height - h),
15887        			top: h - height,
15888        			backgroundAttachment: 'scroll',
15889        			'will-change': 'transform'
15890        		});   
15891
15892        	} else if ( config.speed < 0 && h < winH ) {
15893        		// candidate to change
15894        		var display = (winH + h) / winH;
15895        		height = h * -config.speed * display;
15896        		$this.css({
15897					height: h + (height * 2),
15898        			top: -height,
15899        			backgroundAttachment: 'scroll',
15900        			'will-change': 'transform'
15901        		});         		
15902        	}
15903        };
15904
15905
15906		var currentPoint = null,
15907			progressVal = null,
15908			startPoint = null,
15909			endPoint = null,
15910			$opacityLayer = config.opacity ? $this.find( config.opacity ) : null,
15911			scrollY = null;
15912
15913		var setPosition = function() {
15914			startPoint = offset - winH;
15915			endPoint = offset + elHeight + winH - headerHeight;
15916			scrollY = val.scroll();
15917
15918			if( scrollY < startPoint || scrollY > endPoint ) { 
15919				ticking = false;
15920				return; 
15921			}
15922
15923			currentPoint = (( -offset + scrollY ) * config.speed);
15924
15925            $this.css({
15926              	'-webkit-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
15927              	'-moz-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
15928              	'-ms-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
15929              	'-o-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
15930              	'transform': 'translateY(' + currentPoint + 'px) translateZ(0)'
15931            });  
15932
15933			ticking = false;
15934		};
15935
15936 
15937		var requestTick = function() {
15938			if( !ticking && !isMobile ) {
15939				ticking = true;
15940				window.requestAnimationFrame( setPosition );
15941			}
15942		};
15943
15944
15945		var init = function() { 
15946			// Disable scroll effects when smooth scroll is disabled
15947			if( !MK.utils.isSmoothScroll ) { return; }
15948
15949			update();
15950			setTimeout(update, 100);
15951			$window.on( 'load', update );
15952			$window.on( 'resize', update );
15953	        window.addResizeListener( container, update );
15954	        
15955			$window.on( 'scroll', requestTick );
15956		};
15957		
15958 
15959		return {
15960			init : init
15961		};
15962	};
15963
15964})( jQuery );
15965(function($) {
15966	'use strict';
15967
15968	MK.component.Preloader = function(el) {
15969		this.el = el;
15970	};
15971
15972	MK.component.Preloader.prototype = {
15973		init: function init() {
15974			this.cacheElements();
15975			this.bindEvents();
15976		},
15977
15978		cacheElements: function cacheElements() {
15979			this.$preloader = $(this.el);
15980		},
15981
15982		bindEvents: function bindEvents() {
15983			this.onLoad(); // all components inited on page load
15984		},
15985
15986		onLoad: function onLoad() {
15987			setTimeout(this.hidePreloader.bind(this), 300);
15988		},
15989
15990		hidePreloader: function hidePreloader() {
15991			this.$preloader.hide();
15992		}
15993	};
15994
15995}(jQuery));
15996
15997(function($) {
15998	'use strict';
15999
16000	// Image added for proportional scaling
16001	MK.ui.loader = {
16002		tpl : function() {
16003			return '<div class="mk-loading-indicator">' + 
16004						'<div class="mk-loading-indicator__inner">' +
16005							'<div class="mk-loading-indicator__icon"></div>' +
16006							'<img style="height:100%; width:auto;" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">' +
16007						'</div>' +
16008					'</div>';
16009		},
16010
16011		add : function(item) {
16012			$(item).append(this.tpl);
16013		},
16014
16015		remove : function(item) {
16016			if(item) $(item).find('.mk-loading-indicator').remove();
16017			else $('.mk-loading-indicator').remove();
16018		}
16019	};
16020
16021}(jQuery));
16022(function( $ ) {
16023	// IE / Edge fix for fixed positioned elements
16024	// MS clip path doesnt redraw properly so we expirience similar bug like with background attachement fixed on Chrome
16025	if (MK.utils.browser.name === 'Edge' || MK.utils.browser.name === 'IE') {
16026	 	var val = 1;
16027	 	var $edgeClipper = $('.mk-slider-slide'); // edge slider
16028	 	var $sectionClipper = $('.clipper-true'); // edge slider
16029	 	var $bgLayer = $('.background-layer'); // page section
16030
16031    	var onScroll = function onScroll() {
16032	    	val *= -1;
16033	    	if( $edgeClipper.length ) $edgeClipper.each( redraw );
16034	    	if( $sectionClipper.length ) $sectionClipper.each( redraw );
16035	    	if( $bgLayer.length ) $bgLayer.each( redraw );
16036    	};
16037
16038	 	var redraw = function redraw() {
16039	    	$(this).css('margin-top', val / 100);
16040	    };
16041
16042	    $(window).on("scroll", function () {	    	
16043	    	window.requestAnimationFrame(onScroll);
16044	    });
16045	 }
16046}(jQuery));
16047MK.component.ResponsiveImageSetter = (function ($) {
16048
16049	'use strict';
16050
16051	var module = {};
16052
16053
16054	/*---------------------------------------------------------------------------------*/
16055	/* Private Variables
16056	/*---------------------------------------------------------------------------------*/
16057
16058	var viewportClass = getViewportClass();
16059	var isRetina = window.devicePixelRatio >= 2;
16060
16061
16062	/*---------------------------------------------------------------------------------*/
16063	/* Private Methods
16064	/*---------------------------------------------------------------------------------*/
16065
16066	function run($imgs) {
16067		$imgs.filter( function() {
16068			return !this.hasAttribute("mk-img-src-setted");
16069		}).each(setSrcAttr);
16070	}
16071
16072	function setSrcAttr() {
16073		var $img = $(this);
16074		var set = $img.data('mk-image-src-set');
16075		// Set src attribute to img link suitable for our logic. It will load the image.
16076		if(set['responsive'] === 'false' && isRetina && set['2x']) $img.attr('src', set['2x']);
16077		else if(set['responsive'] === 'false') $img.attr('src', set.default);
16078		else if(viewportClass === 1 && isRetina && set['2x']) $img.attr('src', set['2x']); // default x2 for retina
16079		else if(viewportClass === 0 && set.mobile) $img.attr('src', set.mobile);
16080		else $img.attr('src', set.default);
16081
16082		$img.load(function() {
16083			$(window).trigger('mk-image-loaded')
16084		})
16085	}
16086
16087	function getViewportClass() {
16088		if(window.matchMedia('(max-width: 736px)').matches) return 0;
16089		else return 1;
16090	}
16091
16092	function handleResize($imgs) {
16093		if(!$imgs.length) return;
16093 // Do not run if empty collection
16094		var currentViewportClass = getViewportClass();
16095		// We don't need to reload bigger images when screen size is decreasing as browser already performs resize operation.
16096		// Run update on for increasing screen size
16097		if( currentViewportClass > viewportClass) {
16098			viewportClass = currentViewportClass; // update for further reference
16099			run($imgs);
16100		}
16101	}
16102
16103
16104	/*---------------------------------------------------------------------------------*/
16105	/* Public Methods
16106	/*---------------------------------------------------------------------------------*/
16107
16108	module.init = function ($imgs) {
16109
16110		// Do not run if empty collection
16111		if(!$imgs.length) return;
16112
16113		// Run and bind to events
16114		run($imgs);
16115		$imgs.attr('mk-img-src-setted', '');
16116
16117	};
16118
16119	module.onResize = function ($imgs) {
16120
16121		$(window).on( 'resize', MK.utils.throttle( 500, function() {
16122			handleResize($imgs);
16123		}));
16124
16125
16126	};
16127
16128
16129	module.handleAjax = function () {
16130    	setTimeout(function ajaxDelayedCallback() { // give it a chance to insert content first
16131	    	var $newImgs = $('img[data-mk-image-src-set]').filter( function() {
16132				return !this.hasAttribute("mk-lazyload");
16133			});
16134			if(!$newImgs.length) return;
16135	    	run($newImgs);
16136    	}, 100);
16137    }
16138
16139
16140	return module;
16141
16142}(jQuery));
16143
16144
16145jQuery(function($) {
16146
16147	var init = function init() {
16148		// Get All Responsive Images
16149		$allImages = $('img[data-mk-image-src-set]').filter(function(index) {
16150			var isNotPortfolioImage = !$(this).hasClass('portfolio-image'),
16151				isNotBlogImage = $(this).closest('.mk-blog-container').length == 0,
16152				isNotSwiperImage = !$(this).hasClass('swiper-slide-image'),
16153				isNotGalleryImage = !$(this).hasClass('mk-gallery-image');
16154			return isNotPortfolioImage && isNotBlogImage && isNotSwiperImage && isNotGalleryImage;
16155		});;
16156
16157		// Handle the resize
16158		MK.component.ResponsiveImageSetter.onResize($allImages);
16159
16160		MK.component.ResponsiveImageSetter.init($allImages);
16161
16162		MK.utils.eventManager.subscribe('ajaxLoaded', MK.component.ResponsiveImageSetter.handleAjax ); // ajax loops
16163		MK.utils.eventManager.subscribe('ajax-preview', MK.component.ResponsiveImageSetter.handleAjax ); // ajax portfolio
16164		MK.utils.eventManager.subscribe('quickViewOpen', MK.component.ResponsiveImageSetter.handleAjax );
16165	}
16166	init();
16167	$(window).on('vc_reload', init);
16168
16169});
16170
16171
16172
16173(function( $ ) {
16174	'use strict';
16175
16176	var utils = MK.utils;
16177	var val   = MK.val;
16178
16179	/**
16180	 * Keep track of top Level sections so we can easly skip to next one.
16181	 * We must be explicit about DOM level to nested sections.
16182	 * The list of sections is static. If you'd need to refreh it on ajax etc do it with pub/sub (not really needed now).
16183	 * We keep track for the same sections in Footer for mutating window location with '!loading' to prevent native anchor behaviour.
16184	 */
16185	var $topLevelSections = $('#theme-page > .vc_row, #theme-page > .mk-main-wrapper-holder, #theme-page > .mk-page-section');
16186
16187	$( document ).on( 'click', '.mk-skip-to-next', function() {
16188		var $this = $( this ),
16189			/**
16190			 * Static height of button + the space to the bottom of the container.
16191			 *
16192			 * @TODO Possible to calculate dynamically.
16193			 */
16194			btnHeight = $this.hasClass( 'edge-skip-slider' ) ? 150 : 76,
16195			offset = $this.offset().top + btnHeight,
16196			nextOffset = utils.nextHigherVal( utils.offsets( $topLevelSections ), [offset] );
16197
16198		utils.scrollTo( nextOffset - val.offsetHeaderHeight( nextOffset ) );
16199	});
16200
16201})( jQuery );
16202
16203(function( $ ) {
16204	'use strict';
16205
16206	/**
16207	 * A fork from original VC function.
16208	 * The original one is adding some padding which causes extra padding
16209	 * on our templates so we customized the codes.
16210	 *
16211	 * @since 5.9.8
16212	 * @since 6.0.1 Improve logic to handle LTR responsive state.
16213	 * @since 6.0.1 Fix missing padding-left if row has its own padding-left when
16214	 *              Vertical Header is active.
16215	 */
16216	function MkfullWidthRow() {
16217		var $windowWidth = $(document).width();
16218		var $elements = $('[data-mk-full-width="true"]');
16219		var direction = $('body.rtl').length ? 'right' : 'left';
16220		var verticalHeader = $('body.vertical-header-enabled').length ? true : false;
16221		var verticalHeaderWidth = ( $( '.header-style-4 .mk-header-inner' ).outerWidth() > 270 ) ? 0 : 270;
16222		var verticalHeaderRtl = $('body.rtl').length ? -1 : 1;
16223		var verticalHeaderRtlWidth = $('body.rtl.vertical-header-enabled').length ? verticalHeaderWidth : 0;
16224		var verticalHeaderRight = $('body.vertical-header-right').length ? -1 : 1;
16225		var verticalHeaderWidthBoxed = 0;
16226		var boxed = $('body.mk-boxed-enabled').length;
16227		var boxedOffset = ( boxed ) ? ( $(window).width() - $('#theme-page').outerWidth() ) / 2 : 0;
16228		var boxedMaxWidth = ( boxed ) ? $('#theme-page').outerWidth() : 'auto';
16229
16230		if ( verticalHeader && boxed ) {
16231			verticalHeaderWidthBoxed = ( $( '.header-style-4 .mk-header-inner' ).outerWidth() > 270 ) ? 0 : verticalHeaderRtl * verticalHeaderRight * 135;
16232		}
16233
16234		var transparentHeader = $('.transparent-header').length;
16235		if ( transparentHeader > 0 ) {
16236			verticalHeaderWidthBoxed = 0;
16237		}
16238
16239		$.each($elements, function(key, item) {
16240			var $el = $(this);
16241			var css;
16242			$el.addClass("vc_hidden");
16243			var $el_full = $el.next(".vc_row-full-width");
16244			if ($el_full.length || ($el_full = $el.parent().next(".vc_row-full-width")), $el_full.length) {
16245				var el_margin_left = parseInt($el.css("margin-left"), 10),
16246				el_margin_right = parseInt($el.css("margin-right"), 10),
16247				offset = 0 - $el_full.offset().left - el_margin_left,
16248				width = $(window).width();
16249				if (css = {
16250					position: "relative",
16251					"box-sizing": "border-box",
16252					width: $(window).width(),
16253					maxWidth: boxedMaxWidth
16254				},
16255				css[direction] = offset + boxedOffset + verticalHeaderWidthBoxed + ( verticalHeaderRight * verticalHeaderRtlWidth ),
16256				$el.css(css), !$el.data("mkStretchContent")) {
16257					var padding = -1 * offset;
16258					0 > padding && (padding = 0);
16259					var paddingRight = width - padding - $el_full.width() + el_margin_left + el_margin_right;
16260					padding = padding - paddingRight;
16261					if ( 0 > paddingRight && (paddingRight = 0) ) {
16262						css = {};
16263						if ( 'right' === direction ) {
16264							css["padding-left"] = padding + "px";
16265							css["padding-right"] = 0;
16266						} else {
16267							css["padding-right"] = padding + "px";
16268							css["padding-left"] = 0;
16269						}
16270
16271						$el.css(css)
16272					}
16273				}
16274
16275				/**
16276				 * Fix AM-2974
16277				 *
16278				 * When user set padding-left or padding-right in the row, both of them
16279				 * will be prioritized as important styles. It breaks padding-left set
16280				 * by Vertical Header to make the row content fit with the content
16281				 * container. We need to repopulate the padding-{side - based on Vertical
16282				 * Header position} value.
16283				 *
16284				 * Works when:
16285				 * - Vertical Header is active
16286				 * - Main layout is not boxed
16287				 * - Page Section is full layout
16288				 * - Row is full width layout and content
16289				 * - Row has its own padding-left and padding-right
16290				 * - There is no additional padding added
16291				 *
16292				 * How it works:
16293				 * Get current row padding-left and vertical header width. If both of them
16294				 * are equal, it means row position is correct related to Vertical Header.
16295				 * If not, we should sum both of them, then declare new padding-{side}
16296				 * style attribute.
16297				 *
16298				 * Tested with:
16299				 * - Main Layout: Full & Boxed Layout
16300				 * - Page Section: Full Layout and Non Full Layout
16301				 * - Row: Full Width, Full Width Content, and Non Full Width
16302				 * - Header: Non vertical headers
16303				 * - Transparent Header
16304				 * - RTL and LTR
16305				 */
16306				if ( verticalHeader && ! boxed && ! transparentHeader && ! css.hasOwnProperty( 'padding-left' ) && ! css.hasOwnProperty( 'padding-right' )) {
16307					// Get row padding-{side} and Vertical Header width.
16308					var side = 'left';
16309					if ( verticalHeaderRight === -1 ) {
16310						side = 'right';
16311					}
16312					var el_padding_dir = parseInt( $el.css( 'padding-' + side ), 10 );
16313					var header_padding_dir = $( '.header-style-4 .mk-header-inner' ).outerWidth();
16314					// Compare both of row and vertical header padding-{side}.
16315					if ( el_padding_dir != header_padding_dir) {
16316						if($windowWidth > mk_responsive_nav_width) {
16317							$el[0].style.setProperty( 'padding-' + side, header_padding_dir + 'px', 'important' );	
16318						} else {
16319							$el[0].style.removeProperty( 'padding-' + side);	
16320						}
16321						
16322
16323						// Reset padding-{side} for page section.
16324						var $el_page_section = $el.find( '.mk-page-section.full_layout' );
16325						if ( $el_page_section.length > 0 ) {
16326							$el_page_section[0].style.setProperty( 'padding-' + side, 'unset', 'important' );
16327						}
16328					}
16329				}
16330
16331				$el.attr("data-mk-full-width-init", "true"), $el.removeClass("vc_hidden"), $(document).trigger("vc-full-width-row-single", {
16332					el: $el,
16333					offset: offset,
16334					marginLeft: el_margin_left,
16335					marginRight: el_margin_right,
16336					elFull: $el_full,
16337					width: width
16338				})
16339			}
16340		}
16340), $(document).trigger("mk-full-width-row", $elements);
16341	}
16342
16343	MkfullWidthRow();
16344	var debounceResize = null;
16345	$(window).on("resize", function() {
16346		if( debounceResize !== null ) { clearTimeout( debounceResize ); }
16347		debounceResize = setTimeout( MkfullWidthRow, 100 );
16348	});
16349
16350})( jQuery );
16351
16352(function($) {
16353	'use strict';
16354
16355	// 
16356	// Constructor
16357	// 
16358	// /////////////////////////////////////////////////////////
16359
16360	MK.ui.Slider = function( container, config ) { 
16361
16362		var defaults = {
16363				slide 				: '.mk-slider-slide',
16364	            nav 	     		: '.mk-slider-nav',
16365                effect              : 'roulete',
16366                ease 				: 'easeOutQuart', // should not be changed, remove
16367                slidesPerView       : 1,
16368                slidesToView        : 1,
16369                transitionTime      : 700,
16370                displayTime         : 3000,
16371                autoplay            : true,
16372                hasNav              : true,
16373                hasPagination       : true,
16374                paginationTpl 		: '<span></span>',
16375                paginationEl 		: '#pagination',
16376                draggable           : true,
16377                fluidHeight 		: false,
16378                pauseOnHover		: false,
16379                lazyload			: false,
16380                activeClass 		: 'is-active',
16381                edgeSlider	 		: false,
16382                spinnerTpl 			: '<div class="mk-slider-spinner-wrap"><div class="mk-slider-spinner-fallback"></div><svg class="mk-slider-spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg"><circle class="mk-slider-spinner-path" fill="none" stroke-width="4" stroke-linecap="round" cx="33" cy="33" r="30"></circle></svg></div>',
16383                onInitialize 		: function() {},
16384                onAfterSlide 		: function( id ) {},
16385                onBeforeSlide 		: function( id ) {}
16386		};
16387
16388		this.state = {
16389			id 						: 0,
16390			moveForward 			: true,
16391			running   				: false,
16392            zIFlow					: null,
16393            stop 					: false,
16394		};
16395
16396		this.config = $.extend( defaults, config );
16397		this.container = container;
16398
16399		this.initPerView = this.config.slidesPerView;
16400
16401		// Timer holder
16402		this.activeTimer = null;
16403		this.autoplay = null;
16404		this.timer = null;
16405		this.timerRemaining = parseInt(this.config.displayTime);
16406
16407		// Boolean 'Em All, Making sure it's not string
16408		this.config.lazyload = JSON.parse(this.config.lazyload);
16409		this.config.edgeSlider = JSON.parse(this.config.edgeSlider);
16410
16411		// Image Loader Instance
16412		this.imageLoader = null;
16413
16414		// Add abort command to imagesLoaded, Placing it inside script makes it to work with different versions
16415		// of imagesLoaded if loaded by other Plugins
16416		imagesLoaded.prototype.abort = function() {
16417			this.progress = this.complete = function() { };
16418		};
16419	};
16420
16421	
16422
16423	// 
16424	// Shared methods
16425	// 
16426	// /////////////////////////////////////////////////////////
16427
16428	MK.ui.Slider.prototype = {
16429
16430		init : function() {
16431			this.setPerViewItems();
16432			this.cacheElements();
16433			this.getSlideSize();
16434			this.bindEvents();
16435            this.setSize();
16436			this.setPos();
16437
16438			// Hack for preparing 'prev' on first click if needed
16439			this.updateId( -1 );
16440			this.updateId( 1 );
16441
16442			this.val = this.dynamicVal();
16443			this.timeline = this.prepareTimeline( this.config.transitionTime );
16444
16445			this.timeline.build();
16446
16447			if( this.config.hasPagination ) { this.buildPagination(); }
16448			
16449			if( this.config.autoplay && document.hasFocus() ) { this.setTimer(); }
16450
16451			if( typeof this.config.onInitialize === 'function' ) {
16452				this.config.onInitialize( this.slides );
16453			}
16454
16455			if( this.config.fluidHeight === true ) {
16456				$( this.slides ).height( 'auto' );
16457				$( this.container ).css( 'transition', 'height ' + 200 + 'ms ease-out' );
16458				this.setHeight( 0 );
16459			}
16460
16461
16462			if( this.config.fluidHeight === 'toHighest' ) {
16463				this.setHeightToHighest();
16464			}
16465
16466			// Create timer per slide if required
16467			$(this.slides).each(this.createTimer);
16468
16469			// If it's Edge Slider and Lazy Load is enabled 
16470			if ( this.config.lazyload && this.config.edgeSlider ) {
16471
16472				// If It's not a Video Slide
16473				if ( $(this.slides[this.state.id]).find('video').length === 0 ) {
16474					// Set the first slide's BG image
16475					var $slideImg = $(this.slides[this.state.id]).children('[data-mk-img-set]');
16476					MK.component.BackgroundImageSetter.init( $slideImg );
16477				}
16478				$(this.config.spinnerTpl).prependTo( this.$slides );
16479
16480			} else {
16481
16482				// Set all slides's BG images
16483				MK.component.BackgroundImageSetter.init( $(this.slides).children('[data-mk-img-set]') );
16484
16485			}
16486			
16487
16488
16489		},
16490
16491
16492		cacheElements : function () {
16493			this.container = this.isNode( this.container ) ? this.container 
16494				: document.querySelectorAll( this.container )[0];
16495			this.slides = this.container.querySelectorAll( this.config.slide );
16496			this.$slides = $(this.slides);
16497
16498			if( this.config.hasNav ) { this.$nav = $( this.config.nav ); }
16499			if( this.config.hasPagination ) { this.$pagination = $( this.config.paginationEl ); }
16500		},
16501
16502
16503		bindEvents : function() {
16504			var $window = $( window );
16505
16506			if( this.config.slidesPerView > 1 ) { $window.on( 'resize', this.setPerViewItems.bind( this ) ); }
16507			if( this.config.hasNav ) { this.eventsNav(); }
16508			if( this.config.hasPagination ) { this.eventsPag(); }
16509			if( this.config.draggable ) { this.dragHandler(); }
16510			if( this.config.autoplay ) {
16511				$window.on( 'focus', this.windowActive.bind( this ) );
16512				$window.on( 'blur', this.windowInactive.bind( this ) );
16513			}
16514			if( this.config.pauseOnHover ) {
16515				$(this.container).on( 'mouseleave', this.setTimer.bind( this ) );
16516				$(this.container).on( 'mouseenter', this.unsetTimer.bind( this ) );
16517			}
16518			if( this.config.fluidHeight === 'toHighest' ) {
16519				$window.on( 'resize', this.setHeightToHighest.bind( this ) );
16520			}
16521		},
16522
16523
16524		setPerViewItems: function() {
16525			if(window.matchMedia( '(max-width: 500px)' ).matches) { this.config.slidesPerView = 1; }
16526			else if(window.matchMedia( '(max-width: 767px)' ).matches && this.initPerView >= 2 ) { this.config.slidesPerView = 2; }
16527			else if(window.matchMedia( '(max-width: 1024px)' ).matches && this.initPerView >= 3 ) { this.config.slidesPerView = 3; }
16528			else { this.config.slidesPerView = this.initPerView; }
16529			
16530        	if( typeof this.slides === 'undefined' ) return; 
16531			this.getSlideSize();
16532			this.setSize();
16533			this.setPos();
16534			this.timeline = this.prepareTimeline( this.config.transitionTime );
16535			this.timeline.build();
16536		},
16537
16538
16539		eventsNav : function() {
16540			this.$nav.on( 'click', 'a', this.handleNav.bind( this ) );
16541		},
16542
16543
16544		eventsPag : function() {
16545			this.$pagination.on( 'click', 'a', this.handlePagination.bind( this ) );
16546		},
16547
16548
16549		handleNav : function( e ) {
16550			e.preventDefault();
16551
16552			if( this.state.running ) { return; }
16553			this.state.running = true;
16554
16555			var $this = $( e.currentTarget ),
16556				moveForward = $this.data( 'direction' ) === 'next';
16557
16558
16559			if( this.config.autoplay ) { 
16560				this.unsetTimer();
16561				setTimeout( this.setTimer.bind( this ), this.config.transitionTime );
16562			}
16563
16564			this.state.moveForward = moveForward;
16565			this.timeline.build();
16566			this.timeline.play();
16567
16568			this.setActive( this.nextId( moveForward ? 1 : -1 ) );
16569			if( this.config.fluidHeight ) { this.setHeight( this.nextId( moveForward ? 1 : -1 ) ); }
16570		},
16571
16572
16573		handlePagination : function( e ) {
16574			e.preventDefault();
16575
16576			var $this = $( e.currentTarget ),
16577				id = $this.index();
16578
16579			this.goTo( id );
16580		},
16581
16582
16583		reset: function() {
16584			this.state.stop = true;
16585			this.state.id = 0;
16586			this.setPos();
16587			this.unsetTimer();
16588			this.setTimer();
16589		},
16590
16591
16592		goTo : function(id) {
16593			if( this.state.running ) { return; }
16594			this.state.running = true;
16595
16596			var lastId = this.state.id;
16597
16598			if( lastId === id ) {
16599				return;
16600			} else if( lastId < id ) {
16601				this.state.moveForward = true;
16602			} else {
16603				this.state.moveForward = false;
16604			}
16605
16606			if( this.config.autoplay ) { 
16607				this.unsetTimer();
16608				setTimeout( this.setTimer.bind( this ), this.config.transitionTime );
16609			}
16610
16611			this.timeline.build( Math.abs( lastId - id ) );
16612			this.timeline.play();
16613
16614			this.setActive( id );
16615			if( this.config.fluidHeight ) { this.setHeight( id ); } 
16616		},
16617
16618
16619		windowActive : function() {
16620			this.setTimer(false, true);
16621			$(this.container).removeClass('is-paused'); 
16622		},
16623
16624
16625		windowInactive : function() {
16626			this.unsetTimer();
16627			$(this.container).addClass('is-paused');
16628		},
16629
16630
16631		updateId : function( val ) {
16632			this.state.id = this.nextId(val);
16633		},
16634
16635		nextId : function( val ) {
16636			var len = this.slides.length,
16637				insertVal = this.state.id + val;
16638				insertVal = ( insertVal >= 0 ) ? insertVal : len + val;
16639				insertVal = ( insertVal >= len ) ? 0 : insertVal;
16640
16641			return insertVal;
16642		},
16643
16644
16645		setStyle : function( obj, style ) {
16646            var hasT = style.transform,
16647            	t = {
16648	                x       : ( hasT ) ? style.transform.translateX : null,
16649	                y       : ( hasT ) ? style.transform.translateY : null,
16650	                scale   : ( hasT ) ? style.transform.scale 		: null,
16651	                rotate  : ( hasT ) ? style.transform.rotate 	: null,
16652	                rotateX : ( hasT ) ? style.transform.rotateX 	: null,
16653	                rotateY : ( hasT ) ? style.transform.rotateY 	: null
16654           		},
16655				z  = 'translateZ(0)',
16656            	x  = (t.x) ?  'translateX(' + t.x + '%)' 		: 'translateX(0)',
16657                y  = (t.y) ?  'translateY(' + t.y + '%)' 		: 'translateY(0)',
16658                s  = (t.scale)  ?  'scale(' + t.scale + ')' 	: 'scale(1)',
16659                r  = (t.rotate) ? 'rotate(' + t.rotate + 'deg)' : 'rotate(0)',
16660                rX = (t.rotateX) ? 'rotateX(' + t.rotateX + 'deg)' : '',
16661                rY = (t.rotateY) ? 'rotateY(' + t.rotateY + 'deg)' : '',
16662
16663           		o = style.opacity,
16664           		h = style.height,
16665           		w = style.width;
16666
16667            var c = z + x + y  + s + r + rX + rY;
16668
16669            if( c.length ) {
16670	            obj.style.webkitTransform 	= c;
16671	            obj.style.msTransform 		= c;
16672	            obj.style.transform 		= c;
16673	        }
16674
16675            if( typeof o === 'number' ) { obj.style.opacity = o; }
16676            if( h ) { obj.style.height  = h + '%'; }
16677            if( w ) { obj.style.width   = w + '%'; }
16678		},
16679
16680
16681		setPos : function() {
16682        	if( typeof this.slides === 'undefined' ) return; 
16683		    var id 			= this.state.id,
16684		    	i 			= 0,
16685		    	len 		= this.slides.length,
16686		    	animation 	= this.animation[ this.config.effect ],
16687		    	axis 		= animation.axis,
16688				animNext	= animation.next,
16689				animActi 	= animation.active,
16690				animPrev 	= animation.prev,
16691                perView 	= this.config.slidesPerView,
16692                slideId 	= null,
16693                zIFlow 		= null,
16694                style 		= {};
16695
16696            style.transform = {};
16697
16698
16699            for( ; i < len; i += 1 ) {
16700                if(i < perView) {
16701                	// Position for visible slides. Apply active styles
16702                	style = animActi;
16703                    style.transform[ 'translate' + axis ] = i * 100;
16704                } else {
16705                	// Rest slides move after edge based on axis and moveForward. Apply Next / Prev styles
16706                	style = this.state.moveForward ? animNext : animPrev;
16707                    style.transform[ 'translate' + axis ] =  this.state.moveForward ? perView * 100 : -100;
16708                }
16709
16710                this.slides[ i ].style.zIndex = 0;
16711
16712                slideId = ( i + id ) % len;
16713                this.setStyle( this.slides[ slideId ], style );
16714            }
16715		},
16716
16717
16718        // When we're setting animation along Y axis we're going to set up height
16719        // otherwise width. It is shared amongst all slides
16720        setSize : function() {
16721        	if( typeof this.slides === 'undefined' ) return; 
16722        	var i = 0,
16723		    	len = this.slides.length,
16724		    	axis = this.animation[ this.config.effect ].axis,
16725                slideSize = this.slideSize,
16726        		style = {};
16727
16728            if( axis === 'Y' ) {
16729                style.height = slideSize[ axis ];
16730            } else {
16731                style.width = slideSize[ axis ];
16732            }
16733
16734            for( ; i < len; i += 1 ) {
16735                this.setStyle( this.slides[ i ], style );
16736            }
16737        },
16738
16739
16740        setHeight : function( id ) {
16741			var $slides = $( this.slides ),
16742				$activeSlide = $slides.eq( id );
16743
16744        	var currentHeight = $activeSlide.height();
16745        	$( this.container ).height( currentHeight ); 
16746        },
16747
16748
16749        setHeightToHighest : function() {
16750        	// this is becouse of alliginig woocommrece carousel. Too much DOM
16751        	// Refactor someday
16752			var $slides = $( this.slides ),
16753				height = 0;
16754
16755        	$slides.each(function() {
16756        		height = Math.max(height, $(this).find('> div').outerHeight());
16757        	});
16758
16759        	$( this.container ).height( height ); 
16760        },
16761
16762
16763        // Little utility inspired by GreenSock.
16764        // We export this to this.timeline on init. 
16765        prepareTimeline : function( time ) {
16766			var self 		= this,
16767				iteration 	= 0,
16768            	totalIter 	= time / (1000 / 60),
16769            	animLoop 	= [],
16770            	aL 			= 0, // animation length
16771            	loops 		= 1,
16772				ease 		= this.config.ease, 
16773				currentStyle, timeProg, 
16774				build, move, add, play, reverse, progress, kill;
16775
16776
16777			// Build constants, run them only once
16778			// take out possibly
16779			var len 		= this.slides.length,
16780				perView   	= this.config.slidesPerView,
16781				animation 	= this.animation[ this.config.effect ],
16782				animAxis 	= animation.axis,
16783				animNext	= animation.next,
16784				animActi 	= animation.active,
16785				animPrev 	= animation.prev,
16786				style 		= {},
16787				slideId 	= null,
16788				zIFlow 		= null;
16789
16790				style.transform = {};
16791
16792
16793			build = function( repeats ) {
16794				var currentEase = ease;
16795				loops = repeats || loops;
16796
16797				// console.log('build', loops);
16798
16799				if( !loops ) { return; }
16800				if( loops > 1 ) {
16801					currentEase = 'linearEase';
16802				}
16803
16804				// clean before running new build
16805				kill();
16806				// set new positions
16807				self.setPos();
16808
16809				var id = self.state.id,
16810					moveForward = self.state.moveForward,
16811					i = 0,
16812					axisMove = (moveForward) ? -100 : 100;
16813
16814				for( ; i <= perView; i += 1 ) {
16815					slideId = ( (moveForward) ? i + id : i + id - 1 ) % len;
16816					slideId = ( slideId < 0 ) ? len + slideId : slideId;
16817
16818					if( i === 0 ) {
16819						style = moveForward ? animPrev : animActi;
16820					} else if( i === perView ) {
16821						style = moveForward ? animActi : animNext;
16822					} else {
16823						style = animActi;
16824	            	}
16825
16826               	 	zIFlow = (self.state.moveForward) ? animNext.zIndex : animPrev.zIndex; 
16827	                if( zIFlow ) { 
16828	                	// console.log( zIFlow );
16829	                	self.slides[ slideId ].style.zIndex = (zIFlow === '+') ? i + 1 : len - i;
16830	                }
16831
16832					style.transform[ 'translate' + animAxis ] = axisMove;
16833	            	add( self.slides[ slideId ], style, currentEase );
16834				}
16835			};
16836
16837			add = function( slide, toStyles, ease ) {
16838				if( typeof slide === 'undefined' ) {
16839					throw 'Add at least one slide';
16840				}
16841
16842	            var fromStyles = slide.style,
16843					style = self.refStyle( toStyles, fromStyles );
16844
16845				animLoop.push( [slide, style, ease] );
16846				aL += 1;
16847			};
16848
16849			move = function( startProg, mode ) {
16850				if (isTest) return;
16851				var currentTotalIter = totalIter;
16852
16853				if( loops > 1 ) {
16854				 	currentTotalIter = totalIter / 5;
16855				}
16856
16857				if( !self.state.running ) { self.state.running = true; }
16858
16859				if( startProg ) {
16860					// update iteration val to cached outside var
16861					// ceil to handle properly play after mouse up / touch end
16862					iteration = Math.ceil(startProg * currentTotalIter);
16863				}
16864				
16865				timeProg = iteration / currentTotalIter;
16866				progress( timeProg );
16867
16868				// Break loop
16869				if( iteration >= currentTotalIter && mode === 'play' || 
16870					iteration <= 0 && mode === 'reverse' ) { 
16871
16872					self.state.running = false;
16873					iteration = 0;
16874					kill();
16875	            	self.updateId( self.state.moveForward ? 1 : -1 );
16876					// If we're creating multiple animation loop we trigger outside only first pass to start all game.
16877					// the rest are triggered as callback
16878					loops -= 1;
16879					if( loops > 0 ) {
16880						build();
16881						play();
16882					}
16883
16884					// if we run all loops reset back the default value
16885					if( !loops ) {
16886						loops = 1;
16887						self.timerRemaining = parseInt(self.config.displayTime);
16888						self.config.onAfterSlide( self.state.id );
16889					}
16890
16891					return; 
16892				}
16893
16894				// Run in given mode
16895				if( mode === 'play') {
16896					iteration += 1;
16897				} else {
16898					iteration -= 1;
16899				}
16900
16901				requestAnimationFrame( function() {
16902					if(self.state.stop) return;
16903					move( 0, mode );
16904				});
16905			};
16906
16907			play = function( startProg ) {
16908
16909				var $nextSlide = $(self.slides[ self.nextId(self.state.moveForward ? 1 : -1) ] );
16910
16911				// If it's Edge Slider and Lazy Load is enabled and It's not a Video Slide
16912				if ( self.config.lazyload && self.config.edgeSlider ) {
16913
16914					// Set the next slide's BG Image
16915					var $slideImg = $nextSlide.find('[data-mk-img-set]');
16916					if ( $slideImg.length ) {
16917						MK.component.BackgroundImageSetter.init( $slideImg );
16918					}
16919
16920				}
16921
16922				self.config.onBeforeSlide( self.nextId(self.state.moveForward ? 1 : -1) );
16923				var start = startProg || 0;
16924				iteration = 0;
16925				self.state.stop = false;
16926				move( start, 'play' );
16927
16928			};
16929
16930			reverse = function( startProg ) {
16931				var start = startProg || 1;
16932				move( start, 'reverse' );
16933			};
16934
16935			progress = function( progVal ) {
16936            	var aI = 0, 
16937            		currentStyle;
16938
16939				for( aI; aI < aL; aI++ ) {
16940					if( progVal !== 1 && progVal !== 0 ) {
16941						currentStyle = self.currentStyle( progVal, animLoop[ aI ][ 1 ], animLoop[ aI ][ 2 ] );
16942					} else if( progVal === 1) {
16943						currentStyle = self.currentStyle( progVal, animLoop[ aI ][ 1 ], 'linearEase' );
16944					} else if ( progVal === 0 ) {
16945						currentStyle = self.currentStyle( progVal, animLoop[ aI ][ 1 ], 'linearEase' );
16946					} 
16947					self.setStyle( animLoop[ aI ][ 0 ], currentStyle );
16948				}
16949			};
16950
16951			// Clear previous loop
16952			kill = function() {
16953				animLoop = [];
16954            	aL = 0;
16955			};
16956
16957
16958			return {
16959				build 		: build,
16960				add 		: add,
16961				play 		: play,
16962				reverse 	: reverse,
16963				progress 	: progress
16964			};
16965		},
16966
16967
16968		// Build reference styles.
16969		// Return object with array containig initial style and change of its value
16970		// as required for easing functions
16971		refStyle : function( toStyles, fromStyles ) {
16972			var axis = this.animation[ this.config.effect ].axis,
16973            	style = {},
16974				initVal, changeVal, endVal, dynamicEnd, styleProp, transProp, transform;
16975
16976			for( styleProp in toStyles ) {
16977
16978				if( styleProp === 'transform' ) {
16979					transform = this.getTransforms( fromStyles );
16980					style.transform = {};
16981
16982					for( transProp in toStyles.transform ) {
16983						// don't care about z
16984						if( transProp === 'translateZ' ) { continue; }
16985
16986						initVal = transform[ transProp ] || 0; // if it is undefined it means it's 0
16987						dynamicEnd = ( transProp === 'translate' + axis ) ? initVal : 0;
16988						endVal  = toStyles.transform[ transProp ] + dynamicEnd; // it is dynamic, based on slide position in current set
16989						changeVal = endVal - initVal;
16990						style.transform[ transProp ] = [ initVal, changeVal ];
16991					}
16992				} else if( styleProp === 'zIndex' ) {
16993					// console.log( 'z' );
16994					continue;
16995				} else {
16996					initVal = parseFloat( fromStyles[ styleProp ] ) || 0; // if it is undefined it means it's 0
16997					endVal  = toStyles[ styleProp ];
16998					changeVal = endVal - initVal;
16999					style[ styleProp ] =  [ initVal, changeVal ];
17000				}
17001			}
17002
17003			return style;
17004		},
17005
17006
17007		currentStyle : function( progress, style, ease ) {
17008			var self = this,
17009				currentStyle = {},
17010            	currentVals, styleProp, transProp, prog;
17011
17012			// Redo same loop but construct currentStyle object out of cached values
17013			for( styleProp in style ) {
17014
17015				if( styleProp === 'transform' ) {
17016					currentStyle.transform = {};
17017
17018					for( transProp in style.transform ) {
17019						// remove this line. double check first if needed by logging
17020						if( transProp === 'translateZ' ) { continue; }
17021
17022						currentVals = style.transform[ transProp ];
17023						currentStyle.transform[ transProp ] = 
17024							// (currentIteration, startValue, changeInValue, totalIterations)
17025								self.ease[ ease ]( progress, currentVals[ 0 ], currentVals[ 1 ], 1 );
17026					}
17027				} else {
17028					currentVals = style[ styleProp ];
17029					currentStyle[ styleProp ] = 
17030						self.ease[ ease ]( progress, currentVals[ 0 ], currentVals[ 1 ], 1 );
17031				}
17032			}
17033
17034			return currentStyle;
17035		},
17036
17037
17038		setActive : function( id ) {
17039			var $slides = $( this.slides ),
17040				className = this.config.activeClass;
17041
17042			$slides.removeClass( className );
17043
17044			if( this.config.hasPagination ) {
17045				var $pagination = this.$pagination.find( 'a' );
17046				$pagination.removeClass( className );
17047				$pagination.eq( id ).addClass( className );
17048			}
17049
17050			if( this.activeTimer ) {
17051				clearTimeout( this.activeTimer );
17052				if ( this.imageLoader ) {
17053					this.imageLoader.abort();
17054				}
17055			} 
17056			
17057
17058			var self = this;
17059
17060			this.activeTimer = setTimeout( function() {
17061
17062				var $currentSlide = $slides.eq( id );
17063
17064				if ( self.config.lazyload && self.config.edgeSlider ) {  // If it's Edge Slider and Lazy Load is enabled
17065
17066					if ( $currentSlide.find('.mk-section-video').length && $currentSlide.children('.mk-video-section-touch').length ) {  // If it's a Video Slide and has a Preview image
17067						
17068						var imgSet = $currentSlide.children('.mk-video-section-touch').data('mk-img-set');
17069						var exactImg = MK.component.BackgroundImageSetter.getImage( imgSet );
17070						var $bgImage = $('<img>').attr('src', exactImg );
17071
17072						self.imageLoader = imagesLoaded( $bgImage[0], function( instance ) {
17073							$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
17074							setTimeout( function() {
17075						 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
17076						 	}, 200);
17077							$currentSlide.addClass( className );
17078					 	});
17079
17080					} else if ( $currentSlide.find('.mk-section-video').length && $currentSlide.children('.mk-video-section-touch').length === 0 ) { // If it's a Video Slide and has NOT a Preview image
17081
17082						$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
17083						setTimeout( function() {
17084					 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
17085					 	}, 200);
17086						$currentSlide.addClass( className );
17087						
17088					} else {  // If it's a Image Slide
17089
17090						if ( $currentSlide.children('[data-mk-img-set]').length ) {
17091							// Get the matching Image URL to start lazy loading
17092							var imgSet = $currentSlide.children('[data-mk-img-set]').data('mk-img-set');
17093							var exactImg = MK.component.BackgroundImageSetter.getImage( imgSet );
17094							var $bgImage = $('<img>').attr('src', exactImg );
17095
17096							// Prevent counting time on slide until the image loads
17097							self.unsetTimer();
17098							self.imageLoader = imagesLoaded( $bgImage[0], function( instance ) {
17099								// Hide spinner, Continue counting time on slide and show the content
17100							 	$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
17101							 	setTimeout( function() {
17102							 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
17103							 	}, 200);
17104								self.setTimer(false, false, $currentSlide.data('timer') || Number(self.config.displayTime) );
17105								$currentSlide.addClass( className );
17106							});
17107						} else {
17108							$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
17109						 	setTimeout( function() {
17110						 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
17111						 	}, 200);
17112							self.setTimer(false, false, $currentSlide.data('timer') || Number(self.config.displayTime) );
17113							$currentSlide.addClass( className );
17114						}
17115
17116					}
17117
17118				} else {
17119
17120					$currentSlide.addClass( className );
17121
17122				}
17123				
17124				
17125			}, this.config.transitionTime );
17126		},
17127
17128		createTimer : function() {
17129
17130			var $slide = $(this),
17131				video = $slide.find('video').get(0);
17132
17133			if(video) {
17134				// A hacky but reliable way to ge the video duration
17135				var interval = setInterval( function() {
17136					// If the metadata is ready
17137					if ( video.readyState > 0 ) {
17138						$slide.data('timer', (video.duration * 1000));
17139						$slide.attr('data-timer', (video.duration * 1000));
17140						clearInterval(interval);
17141					}
17142				}, 100);
17143			}
17144
17145		},
17146		
17147		setTimer : function( isFirst, isPaused, fixed_time ) {
17148			// check for custom timer
17149			var customTimer = this.$slides.eq(this.nextId(this.state.moveForward ? 1 : -1)).data('timer'),
17150				trans = parseInt( this.config.transitionTime ),
17151				interval = customTimer ? customTimer : parseInt( this.config.displayTime ),
17152				timer = interval + trans;
17153
17154			var self  = this,
17155				first = isFirst || true,
17156				fixed_time = fixed_time || 0,
17157				create, run;
17158
17159			this.timer = true;
17160			this.lastSetTimer = Date.now();
17161
17162			create = function() {	
17163
17164				if( self.autoplay ) { clearTimeout( self.autoplay ); }
17165				if( !self.timer ) {
17166					return;
17167				}
17168				self.state.moveForward = true;
17169				self.timeline.build();
17170				self.timeline.play();
17171				self.setActive( self.nextId( 1 ) );
17172				if( self.config.fluidHeight ) { self.setHeight( self.nextId( 1 ) ); }
17173				first = false;
17174				self.lastSetTimer = Date.now();
17175
17176				run();
17177			};
17178
17179			run = function(newInterval) {
17180				// check for custom timer
17181				customTimer = self.$slides.eq(self.nextId(self.state.moveForward ? 1 : -1)).data('timer');
17182				interval = customTimer ? customTimer : parseInt( self.config.displayTime );
17183				timer = interval + trans; // update timer with current val
17184
17185				var time = newInterval || timer;
17186				self.autoplay = setTimeout( create, time );
17187			};
17188
17189			if ( fixed_time ) {
17190				run( fixed_time );
17191			} else if (isPaused) {
17192				run( this.timerRemaining );
17193			} else {
17194				run();
17195			}
17196		},
17197
17198
17199		unsetTimer : function() {
17200			this.timer = false;
17201			this.lastUnsetTimer = Date.now();
17202			this.timerRemaining -= this.lastUnsetTimer - this.lastSetTimer;
17203			if( this.autoplay ) { clearTimeout( this.autoplay ); }
17204		},
17205
17206
17207		buildPagination : function() {
17208			var i   = 0,
17209				len = this.slides.length,
17210				tpl = '';
17211
17212			for( ; i < len; i += 1 ) {
17213				tpl += '<a href="javascript:;">' + this.config.paginationTpl + '</a>';
17214			}
17215
17216			this.$pagination.html( tpl );
17217			this.setActive( 0 );
17218		},
17219
17220
17221		getSlideSize : function() {
17222			this.slideSize = {
17223                X: 100 / this.config.slidesPerView,
17224                Y: 100 / this.config.slidesPerView
17225            };
17226		},
17227
17228
17229		getTransforms : function( style ) {
17230			// console.log( style );
17231		    var transform = style.transform || style.webkitTransform || style.mozTransform,
17232		    	regex = /(\w+)\(([^)]*)\)/g,
17233				match,
17234				T = {};
17235
17236			if( typeof transform !== 'string' ) {
17237				throw 'Transform prop is not a string.';
17238			}
17239
17240		    if( !transform ) { return; }
17241	
17242			// Run regex assignment
17243			while( match = regex.exec( transform ) ) {
17244				T[ match[ 1 ] ] = parseFloat( match[ 2 ] );
17245			}
17246
17247		    return T;
17248		},
17249
17250		isNode : function( o ) {
17251			return (
17252		    	typeof Node === "object" ? o instanceof Node : 
17253		   			o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string"
17254		  	);
17255		},
17256
17257
17258		dragHandler : function() {
17259			var self = this,
17260				$container = $( this.container ),
17261				prevBuild = false, 
17262				nextBuild = false,
17263				dragging = false,
17264				buffor = 5, // helpful for decoupling with click events
17265				dragStart, dragMove, dragEnd, progress;
17266
17267			progress = function( moveX ) {
17268				return moveX / self.val.viewportW();
17269			};
17270
17271			dragStart = function( moveX, startX ) {
17272				// console.log( 'start', moveX, startX );
17273			};
17274
17275			dragMove = function( moveX ) {
17276				// console.log('move');
17277				if( self.state.running ) return;
17278
17279				// Don't need to check for existance here
17280
17281				if( moveX < -buffor ) {
17282
17283					if( !nextBuild ) {
17284						self.state.moveForward = true;
17285						self.timeline.build();
17286						nextBuild = true;
17287						prevBuild = false;
17288						self.unsetTimer();
17289					} else {
17290						// turn progress into positive val
17291						self.timeline.progress( -progress( moveX ) );
17292					}
17293					dragging = true;
17294				} else if( moveX > buffor ) {
17295
17296					if( !prevBuild ) {
17297						self.state.moveForward = false;
17298						self.timeline.build();
17299						prevBuild = true;
17300						nextBuild = false;
17301						self.unsetTimer();
17302					} else {
17303						self.timeline.progress( progress( moveX ) );
17304					}
17305					dragging = true;
17306				}
17307			};
17308
17309			dragEnd = function( moveX ) {
17310				if( dragging ) {
17311					var prog = progress( moveX ),
17312						absProg = prog < 0 ? -prog : prog;
17313
17314					if( absProg > 0.1 ) {
17315						self.timeline.play( absProg );
17316						self.setActive( self.nextId( prog < 0 ? 1 : -1 ) );
17317						if( self.config.fluidHeight ) { self.setHeight( self.nextId( prog < 0 ? 1 : -1 ) ); }
17318					} else {
17319						self.timeline.reverse( absProg );
17320						// eventually move this to reverse callbacks	
17321						if(prog < 0) {
17322							self.updateId( -1 );
17323						} else {
17324							self.updateId( 1 );
17325						}
17326					}
17327
17328					prevBuild = false;
17329					nextBuild = false;
17330					dragging = false;
17331					if( self.config.autoplay ) { self.setTimer( false ); }
17332				}
17333			};
17334
17335			this.drag( $container, dragStart, dragMove, dragEnd );
17336		},
17337
17338
17339		drag : function( $el, startFn, moveFn, stopFn ) {
17340
17341		    var touchX, touchY, movX, movY, go, evt,
17342		   		prevent, start, move, stop;
17343
17344		    prevent = function( e ) {
17345		        e.preventDefault();
17346		    };
17347
17348		    start = function( e ) {
17349		        // $el.on("touchmove", prevent);
17350		        $el.on("mousemove", prevent);
17351		        $el.on("touchmove", move);
17352		        $el.on("mousemove", move);
17353
17354		        evt = (e.type === 'touchstart') ? e.originalEvent.touches[0] : e;
17355		        touchX = evt.pageX;
17356
17357		        if(typeof startFn === 'function') {
17358		        	startFn(movX, touchX);
17359		        }
17360		    };
17361
17362		    move = function( e ) {
17363		        evt = (e.type === 'touchmove') ? e.originalEvent.touches[0] : e;
17364		        movX = evt.pageX - touchX;
17365
17366	        	if(typeof moveFn === 'function') {
17367		        	moveFn(movX);
17368		        }
17369		    };
17370
17371		    stop = function( e ) {
17372		        // $el.off("touchmove", prevent);
17373		        $el.off("mousemove", prevent);
17374		        $el.off("touchmove", move);
17375		        $el.off("mousemove", move);
17376
17377		    	if(typeof stopFn === 'function') {
17378		        	stopFn(movX);
17379		        }
17380		    };
17381
17382		    $el.on("touchstart", start);
17383		    $el.on("mousedown", start);
17384		    $el.on("touchend", stop);
17385		    $el.on("touchleave", stop);
17386		    $el.on("touchcancel", stop);
17387		    $el.on("mouseup", stop);
17388		    $el.on("mouseleave", stop);
17389		},
17390
17391
17392		dynamicVal : function() {
17393			var $window = $( window ),
17394				update, 
17395				getViewportW, viewportW;
17396
17397			update = function() {
17398 				viewportW = $window.width();
17399			};
17400
17401			getViewportW = function() {
17402				return viewportW;
17403			};
17404
17405			update();
17406			$window.on( 'load', update );
17407			$window.on( 'resize', update );
17408
17409			return {
17410				viewportW : getViewportW
17411			};
17412		}
17413	};
17414
17415
17416
17417	// 
17418	// Set of default animations
17419	// 
17420	// /////////////////////////////////////////////////////////
17421
17422	MK.ui.Slider.prototype.animation = {
17423
17424        slide : {
17425        	axis : 'X', 
17426            next : { transform: {} },
17427            active : { transform: {} },
17428            prev : { transform: {} }
17429        },
17430
17431        vertical_slide : {
17432        	axis : 'Y',
17433            next : { transform: {} },
17434            active : { transform: {} },
17435            prev : { transform: {} }
17436        },
17437
17438        perspective_flip : {
17439        	axis : 'Y',
17440            next : { 
17441            	transform: {
17442            		rotateX : 80
17443            	} 
17444            },
17445            active : { 
17446            	transform: {
17447            		rotateX : 0
17448            	} 
17449            },
17450            prev : { 
17451            	transform: {
17452            		rotateX : 0
17453            	} 
17454            }
17455        },
17456
17457        zoom : {
17458			axis : 'Z',
17459            next: {
17460                opacity	: 0,
17461                transform : {
17462	                scale : 0.9
17463	            }
17464            },
17465            active: {
17466                opacity	: 1,
17467                transform : {
17468	                scale : 1
17469	            }
17470            },
17471            prev: {
17472                opacity	: 0,
17473                transform : {
17474	                scale : 1.1
17475	            }
17476            }
17477        },
17478
17479        fade : {
17480			axis : 'Z',
17481            next: {
17482                opacity	: 0,
17483                transform : {}
17484            },
17485            active: {
17486                opacity	: 1,
17487                transform : {}
17488            },
17489            prev: {
17490                opacity	: 0,
17491                transform : {}
17492            }
17493        },
17494
17495        kenburned : {
17496			axis : 'Z',
17497            next: {
17498                opacity	: 0,
17499                transform : {}
17500            },
17501            active: {
17502                opacity	: 1,
17503                transform : {}
17504            },
17505            prev: {
17506                opacity	: 0,
17507                transform : {}
17508            }
17509        },
17510
17511        zoom_out : {
17512			axis : 'Z',
17513            next: {
17514				zIndex : '+',
17515                opacity	: 1,
17516                transform : {
17517	                translateY : 100,
17518	                scale : 1
17519	            }
17520            },
17521            active: {
17522                opacity	: 1,
17523                transform : {
17524	                translateY : 0,
17525	                scale : 1
17526	            }
17527            },
17528            prev: {
17529				zIndex : '+',
17530                opacity	: 0,
17531                transform : {
17532	                translateY : 0,
17533	                scale : 0.5
17534	            }
17535            }
17536        },
17537
17538        // Problem with Z-Flow
17539        horizontal_curtain : {
17540			axis : 'Z',
17541            next: {
17542				zIndex : '+',
17543                transform : {
17544	                translateX : 100,
17545	            }
17546            },
17547            active: {
17548                transform : {
17549	                translateX : 0,
17550	            }
17551            },
17552            prev: {
17553				zIndex : '+',
17554                transform : {
17555	                translateX : -70,
17556	            }
17557            }
17558        },
17559
17560		roulete : {
17561			axis : 'X',
17562            next: {
17563                opacity	: 0.5,
17564                transform : {
17565	                scale : 0.5,
17566	                rotate : 10,
17567	                translateY : 20
17568	            }
17569            },
17570            active: {
17571                opacity	: 1,
17572                transform : {
17573	                scale : 1,
17574	                rotate : 0,
17575	                translateY : 0
17576	            }
17577            },
17578            prev: {
17579                opacity	: 0.3,
17580                transform : {
17581	                scale : 0.5,
17582	                rotate : -10,
17583	                translateY : 20
17584	            }
17585            }
17586		}
17587	};
17588
17589
17590
17591	// 
17592	// Penner's easing library
17593	// 
17594	// /////////////////////////////////////////////////////////
17595
17596	MK.ui.Slider.prototype.ease = {
17597		/*
17598		 *
17599		 * TERMS OF USE - EASING EQUATIONS
17600		 * 
17601		 * Open source under the BSD License. 
17602		 * 
17603		 * Copyright © 2001 Robert Penner
17604		 * All rights reserved.
17605		 * 
17606		 * Redistribution and use in source and binary forms, with or without modification, 
17607		 * are permitted provided that the following conditions are met:
17608		 * 
17609		 * Redistributions of source code must retain the above copyright notice, this list of 
17610		 * conditions and the following disclaimer.
17611		 * Redistributions in binary form must reproduce the above copyright notice, this list 
17612		 * of conditions and the following disclaimer in the documentation and/or other materials 
17613		 * provided with the distribution.
17614		 * 
17615		 * Neither the name of the author nor the names of contributors may be used to endorse 
17616		 * or promote products derived from this software without specific prior written permission.
17617		 * 
17618		 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
17619		 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17620		 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
17621		 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
17622		 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
17623		 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
17624		 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
17625		 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
17626		 * OF THE POSSIBILITY OF SUCH DAMAGE. 
17627		 *
17628		 */
17629		linearEase : function(currentIteration, startValue, changeInValue, totalIterations) {
17630			return changeInValue * currentIteration / totalIterations + startValue;
17631		},
17632
17633		easeInQuad : function(currentIteration, startValue, changeInValue, totalIterations) {
17634			return changeInValue * (currentIteration /= totalIterations) * currentIteration + startValue;
17635		},
17636
17637		easeOutQuad : function(currentIteration, startValue, changeInValue, totalIterations) {
17638			return -changeInValue * (currentIteration /= totalIterations) * (currentIteration - 2) + startValue;
17639		},
17640
17641		easeInOutQuad : function(currentIteration, startValue, changeInValue, totalIterations) {
17642			if ((currentIteration /= totalIterations / 2) < 1) {
17643				return changeInValue / 2 * currentIteration * currentIteration + startValue;
17644			}
17645			return -changeInValue / 2 * ((--currentIteration) * (currentIteration - 2) - 1) + startValue;
17646		},
17647
17648		easeInCubic : function(currentIteration, startValue, changeInValue, totalIterations) {
17649			return changeInValue * Math.pow(currentIteration / totalIterations, 3) + startValue;
17650		},
17651
17652		easeOutCubic : function(currentIteration, startValue, changeInValue, totalIterations) {
17653			return changeInValue * (Math.pow(currentIteration / totalIterations - 1, 3) + 1) + startValue;
17654		},
17655
17656		easeInOutCubic : function(currentIteration, startValue, changeInValue, totalIterations) {
17657			if ((currentIteration /= totalIterations / 2) < 1) {
17658				return changeInValue / 2 * Math.pow(currentIteration, 3) + startValue;
17659			}
17660			return changeInValue / 2 * (Math.pow(currentIteration - 2, 3) + 2) + startValue;
17661		},
17662
17663		easeInQuart : function(currentIteration, startValue, changeInValue, totalIterations) {
17664			return changeInValue * Math.pow (currentIteration / totalIterations, 4) + startValue;
17665		},
17666
17667		easeOutQuart : function(currentIteration, startValue, changeInValue, totalIterations) {
17668			return -changeInValue * (Math.pow(currentIteration / totalIterations - 1, 4) - 1) + startValue;
17669		},
17670
17671		easeInOutQuart : function(currentIteration, startValue, changeInValue, totalIterations) {
17672			if ((currentIteration /= totalIterations / 2) < 1) {
17673				return changeInValue / 2 * Math.pow(currentIteration, 4) + startValue;
17674			}
17675			return -changeInValue/2 * (Math.pow(currentIteration - 2, 4) - 2) + startValue;
17676		},
17677
17678		easeInQuint : function(currentIteration, startValue, changeInValue, totalIterations) {
17679			return changeInValue * Math.pow (currentIteration / totalIterations, 5) + startValue;
17680		},
17681
17682		easeOutQuint : function(currentIteration, startValue, changeInValue, totalIterations) {
17683			return changeInValue * (Math.pow(currentIteration / totalIterations - 1, 5) + 1) + startValue;
17684		},
17685
17686		easeInOutQuint : function(currentIteration, startValue, changeInValue, totalIterations) {
17687			if ((currentIteration /= totalIterations / 2) < 1) {
17688				return changeInValue / 2 * Math.pow(currentIteration, 5) + startValue;
17689			}
17690			return changeInValue / 2 * (Math.pow(currentIteration - 2, 5) + 2) + startValue;
17691		},
17692
17693		easeInSine : function(currentIteration, startValue, changeInValue, totalIterations) {
17694			return changeInValue * (1 - Math.cos(currentIteration / totalIterations * (Math.PI / 2))) + startValue;
17695		},
17696
17697		easeOutSine : function(currentIteration, startValue, changeInValue, totalIterations) {
17698			return changeInValue * Math.sin(currentIteration / totalIterations * (Math.PI / 2)) + startValue;
17699		},
17700
17701		easeInOutSine : function(currentIteration, startValue, changeInValue, totalIterations) {
17702			return changeInValue / 2 * (1 - Math.cos(Math.PI * currentIteration / totalIterations)) + startValue;
17703		},
17704
17705		easeInExpo : function(currentIteration, startValue, changeInValue, totalIterations) {
17706			return changeInValue * Math.pow(2, 10 * (currentIteration / totalIterations - 1)) + startValue;
17707		},
17708
17709		easeOutExpo : function(currentIteration, startValue, changeInValue, totalIterations) {
17710			return changeInValue * (-Math.pow(2, -10 * currentIteration / totalIterations) + 1) + startValue;
17711		},
17712
17713		easeInOutExpo : function(currentIteration, startValue, changeInValue, totalIterations) {
17714			if ((currentIteration /= totalIterations / 2) < 1) {
17715				return changeInValue / 2 * Math.pow(2, 10 * (currentIteration - 1)) + startValue;
17716			}
17717			return changeInValue / 2 * (-Math.pow(2, -10 * --currentIteration) + 2) + startValue;
17718		},
17719
17720		easeInCirc : function(currentIteration, startValue, changeInValue, totalIterations) {
17721			return changeInValue * (1 - Math.sqrt(1 - (currentIteration /= totalIterations) * currentIteration)) + startValue;
17722		},
17723
17724		easeOutCirc : function(currentIteration, startValue, changeInValue, totalIterations) {
17725			return changeInValue * Math.sqrt(1 - (currentIteration = currentIteration / totalIterations - 1) * currentIteration) + startValue;
17726		},
17727
17728		easeInOutCirc : function(currentIteration, startValue, changeInValue, totalIterations) {
17729			if ((currentIteration /= totalIterations / 2) < 1) {
17730				return changeInValue / 2 * (1 - Math.sqrt(1 - currentIteration * currentIteration)) + startValue;
17731			}
17732			return changeInValue / 2 * (Math.sqrt(1 - (currentIteration -= 2) * currentIteration) + 1) + startValue;
17733		}
17734	};
17735
17736})(jQuery);
17737/* Social Share */
17738/* -------------------------------------------------------------------- */
17739(function($) {
17740    'use strict';
17741
17742    MK.component.SocialShare = function( el ) {
17743        var networks = {
17744			twitter : 'http://twitter.com/intent/tweet?text={title}&url={url}',
17745			pinterest : 'http://pinterest.com/pin/create/button/?url={url}&media={image}&description={title}',
17746			facebook : 'https://www.facebook.com/sharer/sharer.php?u={url}',
17747			googleplus : 'https://plus.google.com/share?url={url}',
17748			linkedin : 'http://www.linkedin.com/shareArticle?mini=true&url={url}&title={title}&summary={desc}',
17749			digg : 'http://digg.com/submit?url={url}&title={title}',
17750			reddit : 'http://reddit.com/submit?url={url}&title={title}',
17751        };
17752
17753        this.networks = networks;
17754        this.el = el;
17755    };
17756
17757
17758	MK.component.SocialShare.prototype = {
17759
17760        init : function() {
17761            this.cacheElements();
17762            this.bindEvents();
17763        },
17764
17765        cacheElements : function() {
17766            this.$this  = $( this.el );
17767
17768
17769        },
17770
17771        bindEvents : function() {
17772			var thisObject = this;
17773			var tempClass = "";
17774			$.each(this.networks, function( key, value ) {
17775				  thisObject.$tempClass = $('.' + key + '-share');
17776				  thisObject.$tempClass.click(thisObject.openSharingDialog.bind(self, this, key));
17777
17778			});
17779        },
17780
17781        openSharingDialog : function(url, site, args) {
17782			var urlWrapper = url;
17783			var rx = new RegExp('\{[a-z]*\}','g'), res;
17784			var match = rx.exec(url);
17785			while (match != null) {
17786				var pureAttr = match[0].replace("{", "").replace("}" , "");
17787				var attValue = $(args.currentTarget).attr('data-' + pureAttr);
17788				if (attValue === undefined || attValue === null) {
17789					attValue = "";
17790				}
17791				attValue = attValue.replace('#', '%23'); // fix for twitter description
17792				urlWrapper = urlWrapper.replace(match, attValue);
17793				match = rx.exec(url);
17794			}
17795
17796			window.open(urlWrapper, site + "Window", "height=320,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
17797
17798        },
17799
17800
17801    };
17802
17803
17804	//////////////////////////////////////////
17805    //
17806    // Apply to:
17807    //
17808    // ///////////////////////////////////////
17809
17810    var $body = $('body');
17811
17812    if(!$body.length) return;
17813
17814    $body.each(function() {
17815        var socialShare = new MK.component.SocialShare(this);
17816			socialShare.init();
17817    });
17818
17819})(jQuery);
17820
17821
17822
17823//function mk_social_share() {
17824//
17825//  "use strict";
17826//
17827//  $('.twitter-share').on('click', function () {
17828//    var $url = $(this).attr('data-url'),
17829//      $title = $(this).attr('data-title');
17830//
17831//    window.open('http://twitter.com/intent/tweet?text=' + $title + ' ' + $url, "twitterWindow", "height=380,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
17832//    return false;
17833//  });
17834//
17835//  $('.pinterest-share').on('click', function () {
17836//    var $url = $(this).attr('data-url'),
17837//      $title = $(this).attr('data-title'),
17838//      $image = $(this).attr('data-image');
17839//    window.open('http://pinterest.com/pin/create/button/?url=' + $url + '&media=' + $image + '&description=' + $title, "twitterWindow", "height=320,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
17840//    return false;
17841//  });
17842//
17843//  $('.facebook-share').on('click', function () {
17844//    var $url = $(this).attr('data-url');
17845//    window.open('https://www.facebook.com/sharer/sharer.php?u=' + $url, "facebookWindow", "height=380,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
17846//    return false;
17847//  });
17848//
17849//  $('.googleplus-share').on('click', function () {
17850//    var $url = $(this).attr('data-url');
17851//    window.open('https://plus.google.com/share?url=' + $url, "googlePlusWindow", "height=380,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
17852//    return false;
17853//  });
17854//
17855//  $('.linkedin-share').on('click', function () {
17856//    var $url = $(this).attr('data-url'),
17857//      $title = $(this).attr('data-title'),
17858//      $desc = $(this).attr('data-desc');
17859//    window.open('http://www.linkedin.com/shareArticle?mini=true&url=' + $url + '&title=' + $title + '&summary=' + $desc, "linkedInWindow", "height=380,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
17860//    return false;
17861//  });
17862//}
17863
17864
17865
17866
17867(function($) {
17868	'use strict';
17869
17870	MK.component.Sortable = function(el) {
17871		this.el = el; 
17872	};
17873
17874	MK.component.Sortable.prototype = {
17875		init: function init() {
17876			this.cacheElements();
17877			this.bindEvents();
17878		},
17879
17880		cacheElements: function cacheElements() {
17881			this.unique = Date.now();
17882			this.$filter = $(this.el);
17883			this.config = this.$filter.data('sortable-config');
17884
17885			this.ajaxLoader = new MK.utils.ajaxLoader(this.config.container);
17886			this.ajaxLoader.init();
17887
17888			this.$container = $( this.config.container );
17889			this.$navItems = this.$filter.find('a');
17890			this.$filterItems = this.$container.find(this.config.item);
17891		},
17892
17893		bindEvents: function bindEvents() {
17894			this.$navItems.on('click', this.handleClick.bind(this));
17895			MK.utils.eventManager.subscribe('ajaxLoaded', this.onLoad.bind(this));
17896		},
17897
17898		handleClick: function handleClick(e) {
17899			e.preventDefault();
17900
17901			var $item = $(e.currentTarget);
17902			var term = $item.data('filter');
17903
17904			this.$navItems.removeClass('current');
17905			$item.addClass('current');
17906
17907			if(this.config.mode === 'ajax') this.inDB(term, $item);
17908	        else this.inPage(term);
17909		},
17910
17911		inDB: function inDB(term, $item) { 
17912			// Add load indicator only for long requests
17913			MK.ui.loader.remove(this.$filter);
17914			MK.ui.loader.add($item);
17915			
17916			// If mk-ajax-loaded-posts span exists and one of the filter is clicked,
17917			// clear post ids
17918			if ( this.$container.siblings('.mk-ajax-loaded-posts').length ) {		
17919				this.$container.siblings('.mk-ajax-loaded-posts').attr('data-loop-loaded-posts', '');
17920			}
17921
17922			this.ajaxLoader.setData({
17923				paged: 1,
17924				term: term
17925			});
17926            this.ajaxLoader.load(this.unique);
17927		},
17928
17929		inPage: function inPage(term) {
17930			var $filterItems = this.$container.find(this.config.item);
17931			$filterItems.removeClass('is-hidden'); // show all first
17932			// Replace all ', ' with ', .'. It's used to add '.' as class selector of each category.
17933			var className = term.replace( /, /g, ", ." );
17934			if(term !== '*') $filterItems.not( '.' + className ).addClass('is-hidden'); // hide filtered
17935			MK.utils.eventManager.publish('staticFilter');
17936		},
17937
17938		onLoad: function onLoad(e, response) {
17939			if(this.config.mode === 'static') {
17940				this.$navItems.removeClass('current').first().addClass('current');
17941			}
17942			if( typeof response !== 'undefined' &&  response.id === this.config.container) {
17943				MK.ui.loader.remove(this.$filter);
17944				if(response.unique === this.unique) {
17945		            this.$container.html(response.content);
17946					this.ajaxLoader.setData({paged: 1});
17947				}
17948			}
17949		}
17950	};
17951
17952})(jQuery);
17953(function($) {
17954	'use strict';
17955
17956	var $iframes = $('iframe');
17957
17958	$iframes.each(function() {
17959		var $iframe = $(this);
17960		var parent = $iframe.parent().get(0);
17961		var tagName = parent.tagName;
17962
17963		if(tagName === 'P') $iframe.wrap('<div class="mk-video-container"></div>');
17964	});
17965
17966}(jQuery));
17967(function($) {
17968  'use strict';
17969
17970  $(document).on('click', function(e) {
17971    $('.mk-toggle-trigger').removeClass('mk-toggle-active');
17972  });
17973
17974  function toggle(e) {
17975      e.preventDefault();
17976      e.stopPropagation();
17977      var $this = $(e.currentTarget);
17978
17979      if (!$this.hasClass('mk-toggle-active')) {
17980
17981        $('.mk-box-to-trigger').fadeOut(200);
17982        $this.parent().find('.mk-box-to-trigger').fadeIn(250);
17983        $('.mk-toggle-trigger').removeClass('mk-toggle-active');
17984        $this.addClass('mk-toggle-active');
17985
17986      } else {
17987
17988        $('.mk-box-to-trigger').fadeOut(200);
17989        $this.removeClass('mk-toggle-active');
17990
17991      }
17992  }
17993
17994  function assignToggle() {
17995    // wait for ajax response propagation and insertion
17996    setTimeout(function() {
17997      $('.mk-toggle-trigger').off('click', toggle);
17998      $('.mk-toggle-trigger').on('click', toggle);
17999    }, 100);
18000  }
18001
18002  assignToggle();
18003  MK.utils.eventManager.subscribe('ajaxLoaded', assignToggle);
18004  MK.utils.eventManager.subscribe('ajax-preview', assignToggle);
18005
18006  $(window).on('vc_reload', function(){
18007    assignToggle();
18008    MK.utils.eventManager.subscribe('ajaxLoaded', assignToggle);
18009    MK.utils.eventManager.subscribe('ajax-preview', assignToggle);
18010  });
18011
18012}(jQuery));
18013(function( $ ) {
18014    'use strict';
18015    if( MK.utils.isMobile() ) {
18016        $('.mk-animate-element').removeClass('mk-animate-element');
18017        return;
18018    }
18019    var init = function init() {
18020        var $rootLevelEls = $('.js-master-row, .widget');
18021        $rootLevelEls.each( spyViewport );
18022        $rootLevelEls.each( function rootLevelEl() {
18023            var $animateEl = $(this).find( '.mk-animate-element' );
18024            $animateEl.each( spyViewport );
18025            /**
18026             * Firefox has known issue where horizontal scrollbar will appear if an
18027             * element uses animation CSS. The solution should be set the element
18028             * position as fixed or overflow-x as hidden. Position fixed is not possible
18029             * to use because it's only cause other big problems. The best way is
18030             * set overflow-x as hidden in the page content container #theme-page.
18031             *
18032             * NOTE: The problem is spotted on Right To Left viewport only. So, it's
18033             *       limited to '.right-to-left' selector only for now to avoid other
18034             *       problems. Please extend the functionallity if it's happen in
18035             *       other viewport animation effect.
18036             */
18037            var browserName  = MK.utils.browser.name;
18038            if ( browserName === 'Firefox' ) {
18039                var $rightToLeft = $( this ).find( '.right-to-left' );
18040                if ( $rightToLeft.length > 0 ) {
18041                    $( '#theme-page' ).css( 'overflow-x', 'hidden' );
18042                }
18043            }
18044        });
18045    };
18046    var spyViewport = function spyViewport(i) {
18047        var self = this;
18048        MK.utils.scrollSpy( this, {
18049            position  : 'bottom',
18050            threshold : 200,
18051            after     : function() {
18052                animate.call(self, i);
18053            }
18054        });
18055    };
18056    var animate = function animate(i) {
18057        var $this = $(this);
18058        setTimeout(function() {
18059            $this.addClass( 'mk-in-viewport' );
18060        }, 100 * i);
18061    };
18062    $(window).on('load vc_reload', init);
18063}(jQuery));
18064
18065function product_loop_add_cart() {
18066    var $body = $('body');
18067    $body.on('click', '.add_to_cart_button', function() {
18068        var icon = '<svg class="mk-svg-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M437.011 74.99c-46.326-46.328-110.318-74.99-181.011-74.99-109.744 0-203.345 69.064-239.749 166.094l59.938 22.477c27.302-72.773 97.503-124.571 179.811-124.571 53.02 0 101.01 21.5 135.753 56.247l-71.753 71.753h192v-192l-74.989 74.99zm-181.011 373.01c-53.02 0-101.013-21.496-135.756-56.244l71.756-71.756h-192v192l74.997-74.997c46.323 46.331 110.309 74.997 181.003 74.997 109.745 0 203.346-69.064 239.75-166.094l-59.938-22.477c-27.302 72.773-97.503 124.571-179.812 124.571z"/></svg>';
18069        var $holder = $(this).parents('.product:eq(0)');
18070        var $i = $holder.find('.product-loading-icon');
18071        $holder.addClass('adding-to-cart').removeClass('added-to-cart');
18072        $i.html(icon);
18073    });
18074    $body.bind('added_to_cart', function() {
18075        var icon = '<svg class="mk-svg-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M432 64l-240 240-112-112-80 80 192 192 320-320z"/></svg>';
18076        var $holder = $('.adding-to-cart');
18077        var $i = $holder.find('.product-loading-icon');
18078        $holder.removeClass('adding-to-cart').addClass('added-to-cart');
18079        $i.html(icon);
18080    });
18081}
18082(function($) {
18083    'use strict';
18084
18085    MK.component.Tabs = function( el ) {
18086        var defaults = {
18087            activeClass : 'is-active'
18088        };
18089
18090        this.config = defaults;
18091        this.el = el;
18092    };
18093
18094    MK.component.Tabs.prototype = {
18095
18096        init : function() {
18097            this.cacheElements();
18098            this.bindEvents();
18099        },
18100
18101        cacheElements : function() {
18102            this.$this  = $( this.el );
18103            this.$tabs  = this.$this.find( '.mk-tabs-tab' );
18104            this.$panes = this.$this.find( '.mk-tabs-pane' );
18105            this.currentId = 0;
18106        },
18107
18108        bindEvents : function() {
18109            var self = this;
18110
18111            this.$tabs.on( 'click', this.switchPane.bind( this ) );
18112        },
18113
18114        switchPane : function( evt ) {
18115            evt.preventDefault();
18116
18117            var clickedId = $( evt.currentTarget ).index();
18118
18119            this.hide( this.currentId );
18120            this.show( clickedId );
18121
18122            // Update current id
18123            this.currentId = clickedId;
18124
18125            // Notify rest of the app
18126            MK.utils.eventManager.publish('item-expanded');            
18127        },
18128
18129        show : function( id ) {
18130            this.$tabs.eq( id ).addClass( this.config.activeClass );
18131            this.$panes.eq( id ).addClass( this.config.activeClass );
18132        },
18133
18134        hide : function( id ) {
18135            this.$tabs.eq( id ).removeClass( this.config.activeClass );
18136            this.$panes.eq( id ).removeClass( this.config.activeClass );
18137        }
18138    };
18139
18140})(jQuery);
18141
18142
18143/* Tabs */
18144/* -------------------------------------------------------------------- */
18145
18146function mk_tabs() {
18147
18148  // "use strict";
18149
18150  // if ($.exists('.mk-tabs, .mk-news-tab, .mk-woo-tabs')) {
18151  //   $(".mk-tabs, .mk-news-tab, .mk-woo-tabs").tabs();
18152
18153  //    $('.mk-tabs').on('click', function () {
18154  //      $('.mk-theme-loop').isotope('layout');
18155  //    });
18156
18157  //   $('.mk-tabs.vertical-style').each(function () {
18158  //     $(this).find('.mk-tabs-pane').css('minHeight', $(this).find('.mk-tabs-tabs').height() - 1);
18159  //   });
18160
18161  // }
18162}
18163
18164function mk_tabs_responsive(){
18165  // $('.mk-tabs, .mk-news-tab').each(function () {
18166  //   $this = $(this);
18167  //   if ($this.hasClass('mobile-true')) {
18168  //     if (window.matchMedia('(max-width: 767px)').matches)
18169  //     {
18170  //         $this.tabs("destroy");
18171  //     } else {
18172  //       $this.tabs();
18173  //     }
18174  //   }
18175  // });
18176  
18177}
18178
18179
18180(function($) {
18181    'use strict';
18182
18183    /**
18184     * Entry point of application. Runs all components
18185     */
18186    $( window ).on( 'load', function() {
18187        MK.core.initAll( document );
18188        MK.utils.scrollToURLHash();
18189        // TODO move preloader to components and manage it state from within
18190        setTimeout( function() { 
18191            MK.ui.preloader.hide(); // site wide 
18192            $('.mk-preloader').hide(); // components
18193            $('body').removeClass('loading');
18194        }, 150 ); 
18195    });
18196
18197    /**
18198     * VC frontend editor. Init all components.
18199     */
18200    $( window ).on( 'vc_reload', function() {
18201        setTimeout(function(){ 
18202            MK.core.initAll( document ); 
18203        }, 100);
18204    });
18205
18206    /**
18207     * Assign global click handlers
18208     */
18209    $( document ).on( 'click', '.js-smooth-scroll, .js-main-nav a', smoothScrollToAnchor);
18210    $( '.side_dashboard_menu a' ).on( 'click', smoothScrollToAnchor);
18211
18212    function smoothScrollToAnchor( evt ) {
18213        var anchor = MK.utils.detectAnchor( this );
18214        var $this = $(evt.currentTarget);
18215        var loc = window.location;
18216        var currentPage = loc.origin + loc.pathname;
18217        var href = $this.attr( 'href' );
18218        var linkSplit = (href) ? href.split( '#' ) : '';
18219        var hrefPage  = linkSplit[0] ? linkSplit[0] : ''; 
18220        var hrefHash  = linkSplit[1] ? linkSplit[1] : '';
18221
18222        if( anchor.length ) {
18223            if(hrefPage === currentPage || hrefPage === '') evt.preventDefault();
18224            MK.utils.scrollToAnchor( anchor );
18225
18226        } else if( $this.attr( 'href' ) === '#' ) {
18227            evt.preventDefault();
18228        }
18229    }
18230    
18231}(jQuery));})(jQuery);

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