PageSourceSearch

https://brownslinedental.com/wp-content/themes/jupiter/assets/js/core-scripts.6.10.0.js?ver=1635947841

js brownslinedental.com collected 2026-10-06 13:14:58 UTC 550,890 bytes, 18,106 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}(jQuery));
2307(function($) {
2308	'use strict';
2309
2310    var MK = window.MK || {};
2311	MK.utils = window.MK.utils || {};
2312
2313	/**
2314	 * Basic implementation of pub / sub pattern to avoid tight coupling with direct module communication
2315	 * @type {Object}
2316	 */
2317	MK.utils.eventManager = {};
2318
2319	/**
2320	 * Subscribe to custom event and run callbacks
2321	 * @param  {String}
2322	 * @param  {Function}
2323	 *
2324	 * @usage MK.utils.eventManager.subscribe('event', function(e, params) {} )
2325	 */
2326	MK.utils.eventManager.subscribe = function(evt, func) {
2327		$(this).on(evt, func);
2328	};
2329
2330	/**
2331	 * Unsubscribe from custom event
2332	 * @param  {String}
2333	 * @param  {Function}
2334	 */
2335	MK.utils.eventManager.unsubscribe = function(evt, func) {
2336		$(this).off(evt, func);
2337	};
2338
2339	/**
2340	 * Publish custom event to notify appliaction about state change
2341	 * @param  {String}
2342	 * 
2343	 * @usage MK.utils.eventManager.publish('event', {
2344	 *        	param: val
2345	 *        })
2346	 */
2347	MK.utils.eventManager.publish = function(evt, params) {
2348		$(this).trigger(evt, [params]);
2349	};
2350
2351}(jQuery));
2352(function($) {
2353	'use strict';
2354
2355    var MK = window.MK || {};
2356	MK.utils = window.MK.utils || {};
2357
2358	/**
2359	 * Control browser fullscreen mode
2360	 * @type {Object}
2361	 */
2362	MK.utils.fullscreen = {};
2363
2364	// TODO: move to namespace
2365	MK.utils.launchIntoFullscreen = function ( element ) {
2366	    if(element.requestFullscreen) {
2367	     	element.requestFullscreen();
2368	  	} else if(element.mozRequestFullScreen) {
2369	    	element.mozRequestFullScreen();
2370	  	} else if(element.webkitRequestFullscreen) {
2371	    	element.webkitRequestFullscreen();
2372	  	} else if(element.msRequestFullscreen) {
2373	    	element.msRequestFullscreen();
2374	  	}
2375	};
2376
2377	MK.utils.exitFullscreen = function () {
2378	  	if(document.exitFullscreen) {
2379	    	document.exitFullscreen();
2380	  	} else if(document.mozCancelFullScreen) {
2381	    	document.mozCancelFullScreen();
2382	  	} else if(document.webkitExitFullscreen) {
2383	    	document.webkitExitFullscreen();
2384	  	}
2385	};
2386
2387}(jQuery));
2388(function($) {
2389	'use strict';
2390
2391    var MK = window.MK || {};
2392	MK.utils = window.MK.utils || {};
2393
2394	MK.utils.misc = {};
2395	// TODO: move to namespace
2396
2397	/**
2398	 * Get all top offsets from jQuery collection
2399	 * 
2400	 * @param  {$Objects}
2401	 * @return {Aray}
2402	 */
2403	MK.utils.offsets = function( $els ) {
2404		return $.map( $els, function( el ) {
2405			return $( el ).offset().top;
2406		});
2407	};
2408
2409	/**
2410	 * Retrive from array of numbers first number that is higher than given parameter
2411	 * 
2412	 * @param  {Number}
2413	 * @param  {Array}
2414	 * @return {Number}
2415	 */
2416	MK.utils.nextHigherVal = function( val, arr ) {
2417		var i = 0,
2418			higher = null;
2419
2420		var check = function() {
2421			if( val > arr[ i ]) {
2422				i += 1;
2423				check();
2424			} else {
2425				higher = arr[ i ];
2426			}
2427		};
2428		check();
2429
2430		return higher;
2431	};
2432
2433
2434    MK.utils.throttle = function( delay, fn ) {
2435        var last;
2436        var deferTimer;
2437
2438        return function() {
2439            var context = this;
2440            var args = arguments;
2441            var now = +new Date;
2442            if( last && now < last + delay ) {
2443            	clearTimeout( deferTimer );
2444            	deferTimer = setTimeout( function() { 
2445            		last = now; fn.apply( context, args ); 
2446            	}, delay );
2447          	} else {
2448            	last = now;
2449            	fn.apply( context, args );
2450          	}
2451        };
2452    };
2453
2454    MK.utils.isElementInViewport = function( el ) {
2455        var elemTop = el.getBoundingClientRect().top;
2456	    var isVisible = (elemTop < window.innerHeight);
2457	    return isVisible;
2458    };
2459
2460})(jQuery); 
2461(function($) {
2462	'use strict';
2463
2464    var MK = window.MK || {};
2465	MK.utils = window.MK.utils || {};
2466
2467	/**
2468	 * Scrolls page to static pixel offset
2469	 * @param  {Number}
2470	 */
2471	MK.utils.scrollTo = function( offset ) {
2472		$('html, body').stop().animate({
2473			scrollTop: offset
2474			}, {
2475	  		duration: 1200,
2476	  		easing: "easeInOutExpo"
2477		});
2478	};
2479
2480	/**
2481	 * Scrolls to element passed in as object or DOM reference
2482	 * @param  {String|Object}
2483	 */
2484	MK.utils.scrollToAnchor = function( hash ) {
2485		// Escape meta-chars from hash name only.
2486		hash = hash.substring(1).replace(/[!"#$%&'()*+,./:;<=>?@[\]^`{|}~]/g, "\\$&");
2487		hash = "#" + hash;
2488		var $target = $( hash );
2489		// console.log( hash );
2490
2491		if( ! $target.length ) return;
2492
2493		var offset  = $target.offset().top;
2494		offset = offset - MK.val.offsetHeaderHeight( offset );
2495
2496		if( hash === '#top-of-page' ) window.history.replaceState( undefined, undefined, ' ' );
2497		else window.history.replaceState( undefined, undefined, hash );
2498
2499		MK.utils.scrollTo( offset );
2500	};
2501
2502	/**
2503	 * Controls native scroll behaviour
2504	 * @return {Object} => {disable, enable}
2505	 */
2506	MK.utils.scroll = (function() {
2507        // 37 - left arror, 38 - up arrow, 39 right arrow, 40 down arrow
2508	    var keys = [38, 40];
2509
2510        function preventDefault(e) {
2511          e = e || window.event;
2512          e.preventDefault();
2513          e.returnValue = false;  
2514        }
2515
2516        function wheel(e) {
2517          preventDefault(e);
2518        }
2519
2520        function keydown(e) {
2521            for (var i = keys.length; i--;) {
2522                if (e.keyCode === keys[i]) {
2523                    preventDefault(e);
2524                    return;
2525                }
2526            }
2527        }
2528
2529        function disableScroll() {
2530            if (window.addEventListener) {
2531                window.addEventListener('DOMMouseScroll', wheel, false);
2532            }
2533          	window.onmousewheel = document.onmousewheel = wheel;
2534          	document.onkeydown = keydown;
2535        }
2536
2537        function enableScroll() {            
2538          	if (window.removeEventListener) {
2539                window.removeEventListener('DOMMouseScroll', wheel, false);
2540            }
2541            window.onmousewheel = document.onmousewheel = document.onkeydown = null; 
2542        }	
2543
2544        return {
2545        	disable : disableScroll,
2546        	enable  : enableScroll
2547        };
2548
2549	})();
2550
2551	/**
2552	 * Checks if passed link element has anchor inside current page. Returns string like '#anchor' if so or false
2553	 * @param  {String|Object}
2554	 * @return {String|Boolean}
2555	 */
2556	MK.utils.detectAnchor = function( el ) {
2557		var $this = $( el ),
2558			loc = window.location,
2559			currentPage = loc.origin + loc.pathname,
2560			href = $this.attr( 'href' ),
2561			linkSplit = (href) ? href.split( '#' ) : '',
2562			hrefPage  = linkSplit[0] ? linkSplit[0] : '', 
2563			hrefHash  = linkSplit[1] ? linkSplit[1] : '';
2564
2565		if( typeof hrefHash !== 'undefined' && hrefHash !== '' ) {
2566			return '#' + hrefHash;
2567		} else {
2568			return false;
2569		}
2570	};
2571
2572	/**
2573	 * This should be invoked only on page load. 
2574	 * Scrolls to anchor from  address bar
2575	 */
2576	MK.utils.scrollToURLHash = function() {
2577		var loc = window.location,
2578			hash = loc.hash;
2579
2580		if ( hash.length && hash.substring(1).length ) {
2581			// !loading is added early after DOM is ready to prevent native jump to anchor
2582			hash = hash.replace( '!loading', '' );
2583
2584			// Wait for one second before animating 
2585			// Most of UI animations should be done by then and async operations complited
2586			setTimeout( function() {
2587				MK.utils.scrollToAnchor( hash );
2588			}, 1000 ); 
2589
2590			// Right after reset back address bar
2591			setTimeout( function() {
2592				window.history.replaceState(undefined, undefined, hash);
2593			}, 1001);
2594		}
2595	};
2596
2597	/**
2598	 * Scroll Spy implementation. Spy dynamic offsets of elements or static pixel offset
2599	 * @param  {Number|Element}
2600	 * @param  {Object} => callback object {before, active, after}
2601	 */
2602	MK.utils.scrollSpy = function( toSpy, config ) {
2603		var $window   = $( window ),
2604	        container = document.getElementById( 'mk-theme-container' ),
2605	        isObj     = ( typeof toSpy === 'object' ),
2606	        offset    = (isObj) ? MK.val.dynamicOffset( toSpy, config.position, config.threshold ) : function() { return toSpy; },
2607	        height    = (isObj) ? MK.val.dynamicHeight( toSpy ) : function() { return 0; },
2608	        cacheVals = {},
2609	        _p 		  = 'before'; // current position
2610
2611		var checkPosition = function() {
2612	    	var s = MK.val.scroll(), 
2613	    		o = offset(),
2614	    		h = height();
2615
2616	        if( s < o && _p !== 'before' ) {
2617	        	// console.log( toSpy, 'before' );
2618	        	if( config.before ) config.before();
2619	        	_p = 'before';
2620	        } 
2621	        else if( s >= o && s <= o + h && _p !== 'active' ) {
2622	        	// console.log( toSpy, 'active' );
2623	        	if( config.active ) config.active( o );
2624	        	_p = 'active';
2625	        }
2626	        else if( s > o + h && _p !== 'after' ) {
2627	        	// console.log( toSpy, 'after' );
2628	        	if( config.after) config.after( o + h );
2629	        	_p = 'after';
2630	        }
2631		};
2632
2633		var rAF = function() {
2634			window.requestAnimationFrame( checkPosition );
2635		};
2636
2637		var exportVals = function() {
2638			return cacheVals;    
2639		};
2640
2641		var updateCache = function() {
2642	    	var o = offset(),
2643	    		h = height();
2644	    		
2645	        cacheVals = {
2646	        	before : o - $window.height(),
2647	        	active : o,
2648	        	after : o + h
2649	        };
2650		};
2651
2652		if( config.cache ) {
2653			config.cache( exportVals );
2654		}
2655
2656	    checkPosition();
2657	    $window.on( 'load', checkPosition );
2658	    $window.on( 'resize', checkPosition );
2659	    $window.on( 'mouseup', checkPosition );
2660   		window.addResizeListener( container, checkPosition );
2661
2662	    $window.on( 'scroll', rAF ); 
2663
2664   		updateCache();
2665	    $window.on( 'load', updateCache );
2666	    $window.on( 'resize', updateCache );
2667   		window.addResizeListener( container, updateCache );
2668	};
2669
2670}(jQuery));
2671(function($) {
2672    'use strict';
2673
2674    // Create delagation event handler to behave as "live" listener. We may provide new elements with ajax etc later
2675    // Just add js-taphover class whatever element you'd like to immidietely bring hover on touch devices
2676    $("body").on("click touchend", '.js-taphover', function (e) {
2677        var $link = $(e.currentTarget); // grab target
2678        var $target = $(e.target);
2679
2680        // Rather than ":hover" state we operate on ".hover" class which gives us more control and chance to emulate it on click
2681        // yet it is easy to reason about in our CSS
2682        if ($link.hasClass('hover')) {
2683            return true;
2684        } else if ( MK.utils.isMobile() ) {
2685            if ( ($target.hasClass('hover-icon') || $target.closest('.hover-icon').length) && !$target.closest('.js-taphover').hasClass('hover') ) {
2686                e.preventDefault();
2687            }
2688            $link.addClass('hover');
2689            $('.js-taphover').not(e.currentTarget).removeClass('hover'); // remove it from previous element
2690            e.stopPropagation(); // do not leak to document root if expected element was touched
2691        }
2692    });
2693
2694    // Whenever click leaks to the root romve all hover classes
2695    $(document).on("click", function(e) {
2696        $('.js-taphover').removeClass('hover');
2697    });
2698
2699}(jQuery));
2700// (function() {
2701//     'use strict';
2702
2703//     // Make sure the video behaves like background-size: cover
2704//     window.videoCover = function( holderSelector, videoSelector ) {
2705//         var videos = document.querySelectorAll( videoSelector ),
2706//             holder = document.querySelectorAll( holderSelector )[0];
2707
2708//         [].forEach.call(videos, function(video) {
2709
2710//             var videoAspectRatio;
2711
2712//             resizeBackground(); 
2713
2714//             video.onloadedmetadata = function() {
2715//                 // get images aspect ratio
2716//                 videoAspectRatio = this.height / this.width;
2717//                 // attach resize event and fire it once
2718//                 window.onresize = resizeBackground;
2719//                 resizeBackground();
2720//             };
2721
2722//             function resizeBackground() {
2723//                 // get window size and aspect ratio
2724//                 var holderWidth = holder.innerWidth,
2725//                     holderHeight = holder.innerHeight,
2726//                     holderAspectRatio = holderHeight / holderWidth;
2727
2728//                 //compare holder ratio to image ratio so you know which way the image should fill
2729//                 if ( holderAspectRatio < videoAspectRatio ) {
2730//                     // we are fill width
2731//                     video.style.width = holderWidth + "px";
2732//                     // and applying the correct aspect to the height now
2733//                     video.style.height = (holderWidth * videoAspectRatio) + "px"; // this can be margin if your element is not positioned relatively, absolutely or fixed
2734//                     // make sure image is always centered
2735//                     video.style.left = "0px";
2736//                     video.style.top = (holderHeight - (holderWidth * videoAspectRatio)) / 2 + "px";
2737//                 } else { // same thing as above but filling height instead
2738//                     video.style.height = holderHeight + "px";
2739//                     video.style.width = (holderHeight / videoAspectRatio) + "px";
2740//                     video.style.left = (holderWidth - (holderHeight / videoAspectRatio)) / 2 + "px";
2741//                     video.style.top = "0px";
2742//                 }
2743//             }
2744
2745//         });
2746//     };
2747
2748// }());
2749// 
2750// 
2751// 
2752// TODO it is temp only. make it as a plugin
2753
2754(function($) {
2755    'use strict';
2756
2757    var $videoHolder = $('.mk-center-video'),
2758        $wrapper = $videoHolder.parent(),
2759        baseAspectRatio = 56.25;
2760
2761    var wrapperHeight,
2762        wrapperWidth,
2763        wrapperAspectRatio;
2764
2765    function calc() {
2766        wrapperHeight = $wrapper.height();
2767        wrapperWidth = $wrapper.width();
2768        wrapperAspectRatio = (wrapperHeight / wrapperWidth) * 100;
2769    } 
2770
2771    function apply() {        
2772        var width = (wrapperAspectRatio / baseAspectRatio) * 100,
2773            widthOverflow = (width - 100);
2774
2775        $videoHolder.css({
2776            'padding-top': wrapperAspectRatio + '%',
2777            'width': width + '%',
2778            'left': -(widthOverflow / 2) + '%'
2779        }); 
2780    }
2781
2782    function reset() {
2783        $videoHolder.css({
2784            'padding-top': baseAspectRatio + '%',
2785            'width': 100 + '%',
2786            'left': 0
2787        });
2788    }
2789
2790    function setCover() {
2791        reset();
2792        calc();
2793        if(wrapperAspectRatio > baseAspectRatio) apply();
2794    }
2795
2796    $(window).on('load', setCover);
2797    $(window).on('resize', setCover);
2798
2799
2800}(jQuery));
2801(function($) {
2802	'use strict';
2803
2804	var MK = window.MK || {};
2805
2806	/**
2807	* 	MK.val is collection of Lambdas responsible for returning up to date values of method type like scrollY or el offset.
2808	* 	The Lambda is responsible for keeping track of value of a particular property, usually takes as argument an object
2809	* 	(or DOM reference) and internally creates and updates data that is returned as primitive value - through variable reference.
2810	*
2811	*  Benefits of this approach:
2812	*  - reduced DOM reads
2813	*  - auto-updating values without need for additional logic where methods are called
2814	*  - updating values when needed to be updated not read
2815	*
2816	*  Downsides:
2817	*  - Memory overhead with closures and keeping state in memory ( still beter than read state from DOM, but use wisely -
2818	*    do not use it when you really need static value on runtime )
2819	*/
2820	MK.val = {};
2821
2822	/**
2823	* Current window offsetY position
2824	*
2825	* @uses   MK.val.scroll()
2826	* @return {number}
2827	*/
2828	MK.val.scroll = (function() {
2829		var offset = 0,
2830		$window = $(window),
2831		hasPageYOffset = (window.pageYOffset !== undefined),
2832		body = (document.documentElement || document.body.parentNode || document.body); // cross browser handling
2833
2834		var update = function() {
2835			offset = hasPageYOffset ? window.pageYOffset : body.scrollTop;
2836		};
2837
2838		var rAF = function() {
2839			window.requestAnimationFrame(update);
2840		};
2841
2842		update();
2843		$window.on('load', update);
2844		$window.on('resize', update);
2845		$window.on('scroll', rAF);
2846
2847		return function() {
2848			return offset;
2849		};
2850	})();
2851
2852
2853	/**
2854	* Changes number of percent to pixels based on viewport height
2855	*
2856	* @uses   MK.val.viewportPercentHeight({percent val})
2857	* @param  {number}
2858	* @return {number}
2859	*/
2860	MK.val.viewportPercentHeight = function(percent) {
2861		return $(window).height() * (percent / 100);
2862	};
2863
2864
2865	/**
2866	* Wordpress adminbar height based on wp media queries
2867	* @return {Number}
2868	*/
2869	MK.val.adminbarHeight = function() {
2870		if (php.hasAdminbar) {
2871			// apply WP native media-query and sizes
2872			return (window.matchMedia('( max-width: 782px )').matches) ? 46 : 32;
2873		} else {
2874			return 0;
2875		}
2876	};
2877
2878
2879	/**
2880	* Offset when header becomes sticky. Evaluates viewport % and header height to pixels for according options
2881	* @return {Number}
2882	*/
2883	MK.val.stickyOffset = (function() {
2884		var $header = $('.mk-header').not('.js-header-shortcode').first();
2885
2886		// We need to have returning function even when header is disabled
2887		if (!$header.length) {
2888			return function() {
2889				return 0;
2890			};
2891		}
2892
2893
2894
2895		var $toolbar = $header.find('.mk-header-toolbar'),
2896		config = $header.data(),
2897		hasToolbar = $toolbar.length,
2898		toolbarHeight = (hasToolbar) ? $toolbar.height() : 0,
2899		isVertical = (config.headerStyle === 4),
2900		headerHeight = (isVertical) ? 0 : config.height;
2901
2902		var type = ((typeof config.stickyOffset === 'number') ? 'number' : false) ||
2903		((config.stickyOffset === 'header') ? 'header' : false) ||
2904		'percent';
2905
2906		var stickyOffset = 0;
2907		var setOffset = function() {
2908
2909			//we calculate toolbar height for When the device is changed Size
2910			//Toolbar height in responsive state is 0
2911			toolbarHeight = (hasToolbar) ? $toolbar.height() : 0;
2912
2913			if (MK.utils.isResponsiveMenuState()) {
2914				headerHeight = config.responsiveHeight;
2915
2916				if (hasToolbar) {
2917					if ($toolbar.is(':hidden')) {
2918						toolbarHeight = 0;
2919					}
2920				}
2921			}
2922
2923			if (type === 'number') {
2924				stickyOffset = config.stickyOffset;
2925			} else if (type === 'header') {
2926
2927				stickyOffset = headerHeight + toolbarHeight + MK.val.adminbarHeight(); // add all header components here, make them 0 if needed
2928
2929			} else if (type === 'percent') {
2930				stickyOffset = MK.val.viewportPercentHeight(parseInt(config.stickyOffset));
2931			}
2932		};
2933
2934		setOffset();
2935		$(window).on('resize', setOffset);
2936
2937		return function() {
2938			return stickyOffset;
2939		};
2940	}());
2941
2942
2943
2944	/**
2945	* Gets header height on particular offsetY position. Use to determine logic for fullHeight, smooth scroll etc.
2946	* Takes one parameter which is offset position we're interested in.
2947	*
2948	* @uses   MK.val.offsetHeaderHeight({offset val})
2949	* @param  {number}
2950	* @return {number}
2951	*/
2952	MK.val.offsetHeaderHeight = (function() { // Closure avoids multiple DOM reads. We need to fetch header config only once.
2953		var $header = $('.mk-header').not('.js-header-shortcode').first();
2954
2955		// We need to have returning function even when header is disabled
2956		if (!$header.length) {
2957			return function() {
2958				return 0;
2959			};
2960		}
2961
2962		var $toolbar = $header.find('.mk-header-toolbar'),
2963		config = $header.data(),
2964		stickyHeight = config.stickyHeight,
2965		desktopHeight = config.height,
2966		mobileHeight = config.responsiveHeight,
2967		isTransparent = $header.hasClass('transparent-header'),
2968		isSticky = config.stickyStyle.length,
2969		isStickyLazy = config.stickyStyle === 'lazy',
2970		isVertical = config.headerStyle === 4,
2971		hasToolbar = $toolbar.length,
2972		toolbarHeight = hasToolbar ? $toolbar.height() : 0,
2973		bufor = 5;
2974
2975		/**
2976		 * The sticky section of header style 2 has fixed height.
2977		 * The stickey height option does not affect this header style.
2978		 */
2979		if ( config.headerStyle === 2 ) {
2980			stickyHeight = $header.find( '.mk-header-nav-container' ).outerHeight();
2981		}
2982
2983		// if header has border bottom we can calculate that (for responsive state)
2984		var $innerHeader = $header.find('.mk-header-inner');
2985		var hasInnerHeader = $innerHeader.length;
2986
2987		var headerHeight = function(offset) {
2988
2989			toolbarHeight = hasToolbar ? $toolbar.height() : 0
2990			var stickyOffset = MK.val.stickyOffset();
2991
2992
2993			if (MK.utils.isResponsiveMenuState()) { //  Header avaible only on top for mobile
2994
2995				if (hasToolbar && $toolbar.is(':hidden')) {
2996					toolbarHeight = 0;
2997				}
2998
2999				//in responsive state , .mk-header-holder position's changed to "relative"
3000				//and header's border affected to offset,so borders must be calculated
3001				var headerBorder = 0;
3002				headerBorder = parseInt($innerHeader.css('border-bottom-width'));
3003
3004				var totalHeight = mobileHeight + MK.val.adminbarHeight() + toolbarHeight + headerBorder;
3005
3006				if (offset <= totalHeight) return totalHeight;
3007				else return MK.val.adminbarHeight();
3008			} else {
3009				if (offset <= stickyOffset) {
3010					if (isVertical) {
3011						if (hasToolbar) {
3012							return toolbarHeight + MK.val.adminbarHeight();
3013						} else {
3014							return MK.val.adminbarHeight();
3015						}
3016					} else if (isTransparent) {
3017						return MK.val.adminbarHeight();
3018					} else {
3019						return desktopHeight + toolbarHeight + MK.val.adminbarHeight();
3020					} // For any other return regular desktop height
3021				} else if (offset > stickyOffset) {
3022					if (isVertical) {
3023						return MK.val.adminbarHeight();
3024					} else if (!isSticky) {
3025						return MK.val.adminbarHeight();
3026					} else if (isStickyLazy) {
3027						return MK.val.adminbarHeight();
3028					} else if (isSticky) {
3029						return stickyHeight + MK.val.adminbarHeight();
3030					}
3031				}
3032			}
3033			// default to 0 to prevent errors ( need to return number )
3034			// Anyway make sure all scenarios are covered in IFs
3035			return 0;
3036		};
3037
3038		return function(offset) {
3039			return headerHeight(offset - MK.val.adminbarHeight());
3040		};
3041	})();
3042
3043
3044	/**
3045	* Gets current offset of given element (passed as object or DOM reference) from top or bottom (default to top)
3046	* of screen  with possible threshold (default to 0)
3047	*
3048	* @uses   MK.val.dynamicOffset({obj reference}, {'top'|'bottom'}, {threshold val})
3049	* @param  {string|object}
3050	* @param  {string}
3051	* @param  {number}
3052	* @return {number}
3053	*/
3054	MK.val.dynamicOffset = function(el, position, threshold) {
3055		var $window = $(window),
3056		$el = $(el),
3057		pos = position || 'top',
3058		thr = threshold || 0,
3059		container = document.getElementById('mk-theme-container'),
3060		currentPos = 0;
3061
3062		var offset = 0,
3063		winH = 0,
3064		rect = 0,
3065		x = 0;
3066
3067		var update = function() {
3068			winH = $window.height();
3069			rect = $el[0].getBoundingClientRect();
3070			offset = (rect.top + MK.val.scroll());
3071			x = (pos === 'top') ? MK.val.offsetHeaderHeight(offset) : winH + (rect.height - thr);
3072			currentPos = offset - x - 1;
3073		};
3074
3075		update();
3076		$window.on('load', update);
3077		$window.on('resize', update);
3078		window.addResizeListener(container, update);
3079
3080		return function() {
3081			return currentPos;
3082		};
3083	};
3084
3085	/**
3086	* Gets current height of given element (passed as object or DOM reference)
3087	*
3088	* @uses   MK.val.dynamicHeight({obj reference})
3089	* @param  {string|object}
3090	* @return {number}
3091	*/
3092	MK.val.dynamicHeight = function(el) {
3093		var $window = $(window),
3094		$el = $(el),
3095		container = document.getElementById('mk-theme-container'),
3096		currentHeight = 0;
3097
3098		var update = function() {
3099			currentHeight = $el.outerHeight();
3100		};
3101
3102		update();
3103		$window.on('load', update);
3104		$window.on('resize', update);
3105		window.addResizeListener(container, update);
3106
3107		return function() {
3108			return currentHeight;
3109		};
3110	};
3111
3112})(jQuery);
3113
3114/*
3115 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
3116 *
3117 */
3118jQuery.easing["jswing"] = jQuery.easing["swing"];
3119jQuery.extend(jQuery.easing, {
3120        def: "easeOutQuad",
3121        swing: function (a, b, c, d, e) {
3122                return jQuery.easing[jQuery.easing.def](a, b, c, d, e)
3123        },
3124        easeInQuad: function (a, b, c, d, e) {
3125                return d * (b /= e) * b + c
3126        },
3127        easeOutQuad: function (a, b, c, d, e) {
3128                return -d * (b /= e) * (b - 2) + c
3129        },
3130        easeInOutQuad: function (a, b, c, d, e) {
3131                if ((b /= e / 2) < 1) return d / 2 * b * b + c;
3132                return -d / 2 * (--b * (b - 2) - 1) + c
3133        },
3134        easeInCubic: function (a, b, c, d, e) {
3135                return d * (b /= e) * b * b + c
3136        },
3137        easeOutCubic: function (a, b, c, d, e) {
3138                return d * ((b = b / e - 1) * b * b + 1) + c
3139        },
3140        easeInOutCubic: function (a, b, c, d, e) {
3141                if ((b /= e / 2) < 1) return d / 2 * b * b * b + c;
3142                return d / 2 * ((b -= 2) * b * b + 2) + c
3143        },
3144        easeInQuart: function (a, b, c, d, e) {
3145                return d * (b /= e) * b * b * b + c
3146        },
3147        easeOutQuart: function (a, b, c, d, e) {
3148                return -d * ((b = b / e - 1) * b * b * b - 1) + c
3149        },
3150        easeInOutQuart: function (a, b, c, d, e) {
3151                if ((b /= e / 2) < 1) return d / 2 * b * b * b * b + c;
3152                return -d / 2 * ((b -= 2) * b * b * b - 2) + c
3153        },
3154        easeInQuint: function (a, b, c, d, e) {
3155                return d * (b /= e) * b * b * b * b + c
3156        },
3157        easeOutQuint: function (a, b, c, d, e) {
3158                return d * ((b = b / e - 1) * b * b * b * b + 1) + c
3159        },
3160        easeInOutQuint: function (a, b, c, d, e) {
3161                if ((b /= e / 2) < 1) return d / 2 * b * b * b * b * b + c;
3162                return d / 2 * ((b -= 2) * b * b * b * b + 2) + c
3163        },
3164        easeInSine: function (a, b, c, d, e) {
vendor: 5,544 bytes, lines 3165-3304
3165                return -d * Math.cos(b / e * (Math.PI / 2)) + d + c
3166        },
3167        easeOutSine: function (a, b, c, d, e) {
3168                return d * Math.sin(b / e * (Math.PI / 2)) + c
3169        },
3170        easeInOutSine: function (a, b, c, d, e) {
3171                return -d / 2 * (Math.cos(Math.PI * b / e) - 1) + c
3172        },
3173        easeInExpo: function (a, b, c, d, e) {
3174                return b == 0 ? c : d * Math.pow(2, 10 * (b / e - 1)) + c
3175        },
3176        easeOutExpo: function (a, b, c, d, e) {
3177                return b == e ? c + d : d * (-Math.pow(2, -10 * b / e) + 1) + c
3178        },
3179        easeInOutExpo: function (a, b, c, d, e) {
3180                if (b == 0) return c;
3181                if (b == e) return c + d;
3182                if ((b /= e / 2) < 1) return d / 2 * Math.pow(2, 10 * (b - 1)) + c;
3183                return d / 2 * (-Math.pow(2, -10 * --b) + 2) + c
3184        },
3185        easeInCirc: function (a, b, c, d, e) {
3186                return -d * (Math.sqrt(1 - (b /= e) * b) - 1) + c
3187        },
3188        easeOutCirc: function (a, b, c, d, e) {
3189                return d * Math.sqrt(1 - (b = b / e - 1) * b) + c
3190        },
3191        easeInOutCirc: function (a, b, c, d, e) {
3192                if ((b /= e / 2) < 1) return -d / 2 * (Math.sqrt(1 - b * b) - 1) + c;
3193                return d / 2 * (Math.sqrt(1 - (b -= 2) * b) + 1) + c
3194        },
3195        easeInElastic: function (a, b, c, d, e) {
3196                var f = 1.70158;
3197                var g = 0;
3198                var h = d;
3199                if (b == 0) return c;
3200                if ((b /= e) == 1) return c + d;
3201                if (!g) g = e * .3;
3202                if (h < Math.abs(d)) {
3203                        h = d;
3204                        var f = g / 4
3205                } else var f = g / (2 * Math.PI) * Math.asin(d / h);
3206                return -(h * Math.pow(2, 10 * (b -= 1)) * Math.sin((b * e - f) * 2 * Math.PI / g)) + c
3207        },
3208        easeOutElastic: function (a, b, c, d, e) {
3209                var f = 1.70158;
3210                var g = 0;
3211                var h = d;
3212                if (b == 0) return c;
3213                if ((b /= e) == 1) return c + d;
3214                if (!g) g = e * .3;
3215                if (h < Math.abs(d)) {
3216                        h = d;
3217                        var f = g / 4
3218                } else var f = g / (2 * Math.PI) * Math.asin(d / h);
3219                return h * Math.pow(2, -10 * b) * Math.sin((b * e - f) * 2 * Math.PI / g) + d + c
3220        },
3221        easeInOutElastic: function (a, b, c, d, e) {
3222                var f = 1.70158;
3223                var g = 0;
3224                var h = d;
3225                if (b == 0) return c;
3226                if ((b /= e / 2) == 2) return c + d;
3227                if (!g) g = e * .3 * 1.5;
3228                if (h < Math.abs(d)) {
3229                        h = d;
3230                        var f = g / 4
3231                } else var f = g / (2 * Math.PI) * Math.asin(d / h);
3232                if (b < 1) return -.5 * h * Math.pow(2, 10 * (b -= 1)) * Math.sin((b * e - f) * 2 * Math.PI / g) + c;
3233                return h * Math.pow(2, -10 * (b -= 1)) * Math.sin((b * e - f) * 2 * Math.PI / g) * .5 + d + c
3234        },
3235        easeInBack: function (a, b, c, d, e, f) {
3236                if (f == undefined) f = 1.70158;
3237                return d * (b /= e) * b * ((f + 1) * b - f) + c
3238        },
3239        easeOutBack: function (a, b, c, d, e, f) {
3240                if (f == undefined) f = 1.70158;
3241                return d * ((b = b / e - 1) * b * ((f + 1) * b + f) + 1) + c
3242        },
3243        easeInOutBack: function (a, b, c, d, e, f) {
3244                if (f == undefined) f = 1.70158;
3245                if ((b /= e / 2) < 1) return d / 2 * b * b * (((f *= 1.525) + 1) * b - f) + c;
3246                return d / 2 * ((b -= 2) * b * (((f *= 1.525) + 1) * b + f) + 2) + c
3247        },
3248        easeInBounce: function (a, b, c, d, e) {
3249                return d - jQuery.easing.easeOutBounce(a, e - b, 0, d, e) + c
3250        },
3251        easeOutBounce: function (a, b, c, d, e) {
3252                if ((b /= e) < 1 / 2.75) {
3253                        return d * 7.5625 * b * b + c
3254                } else if (b < 2 / 2.75) {
3255                        return d * (7.5625 * (b -= 1.5 / 2.75) * b + .75) + c
3256                } else if (b < 2.5 / 2.75) {
3257                        return d * (7.5625 * (b -= 2.25 / 2.75) * b + .9375) + c
3258                } else {
3259                        return d * (7.5625 * (b -= 2.625 / 2.75) * b + .984375) + c
3260                }
3261        },
3262        easeInOutBounce: function (a, b, c, d, e) {
3263                if (b < e / 2) return jQuery.easing.easeInBounce(a, b * 2, 0, d, e) * .5 + c;
3264                return jQuery.easing.easeOutBounce(a, b * 2 - e, 0, d, e) * .5 + d * .5 + c
3265        }
3266});
3267// ==================================================
3268// fancyBox v3.5.7
3269//
3270// Licensed GPLv3 for open source use
3271// or fancyBox Commercial License for commercial use
3272//
3273// http://fancyapps.com/fancybox/
3274// Copyright 2019 fancyApps
3275//
3276// ==================================================
3277(function (window, document, $, undefined) {
3278	"use strict";
3279
3280	window.console = window.console || {
3281	  info: function (stuff) {}
3282	};
3283
3284	// If there's no jQuery, fancyBox can't work
3285	// =========================================
3286
3287	if (!$) {
3288	  return;
3289	}
3290
3291	// Check if fancyBox is already initialized
3292	// ========================================
3293
3294	if ($.fn.fancybox) {
3295	  console.info("fancyBox already initialized");
3296
3297	  return;
3298	}
3299
3300	// Private default settings
3301	// ========================
3302
3303	var defaults = {
3304	  // Close existing modals
vendor: 141,869 bytes, lines 3305-8841
3305	  // Set this to false if you do not need to stack multiple instances
3306	  closeExisting: false,
3307
3308	  // Enable infinite gallery navigation
3309	  loop: false,
3310
3311	  // Horizontal space between slides
3312	  gutter: 50,
3313
3314	  // Enable keyboard navigation
3315	  keyboard: true,
3316
3317	  // Should allow caption to overlap the content
3318	  preventCaptionOverlap: true,
3319
3320	  // Should display navigation arrows at the screen edges
3321	  arrows: true,
3322
3323	  // Should display counter at the top left corner
3324	  infobar: true,
3325
3326	  // Should display close button (using `btnTpl.smallBtn` template) over the content
3327	  // Can be true, false, "auto"
3328	  // If "auto" - will be automatically enabled for "html", "inline" or "ajax" items
3329	  smallBtn: "auto",
3330
3331	  // Should display toolbar (buttons at the top)
3332	  // Can be true, false, "auto"
3333	  // If "auto" - will be automatically hidden if "smallBtn" is enabled
3334	  toolbar: "auto",
3335
3336	  // What buttons should appear in the top right corner.
3337	  // Buttons will be created using templates from `btnTpl` option
3338	  // and they will be placed into toolbar (class="fancybox-toolbar"` element)
3339	  buttons: [
3340		"zoom",
3341		//"share",
3342		"slideShow",
3343		//"fullScreen",
3344		//"download",
3345		"thumbs",
3346		"close"
3347	  ],
3348
3349	  // Detect "idle" time in seconds
3350	  idleTime: 3,
3351
3352	  // Disable right-click and use simple image protection for images
3353	  protect: false,
3354
3355	  // Shortcut to make content "modal" - disable keyboard navigtion, hide buttons, etc
3356	  modal: false,
3357
3358	  image: {
3359		// Wait for images to load before displaying
3360		//   true  - wait for image to load and then display;
3361		//   false - display thumbnail and load the full-sized image over top,
3362		//           requires predefined image dimensions (`data-width` and `data-height` attributes)
3363		preload: false
3364	  },
3365
3366	  ajax: {
3367		// Object containing settings for ajax request
3368		settings: {
3369		  // This helps to indicate that request comes from the modal
3370		  // Feel free to change naming
3371		  data: {
3372			fancybox: true
3373		  }
3374		}
3375	  },
3376
3377	  iframe: {
3378		// Iframe template
3379		tpl: '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" allowfullscreen="allowfullscreen" allow="autoplay; fullscreen" src=""></iframe>',
3380
3381		// Preload iframe before displaying it
3382		// This allows to calculate iframe content width and height
3383		// (note: Due to "Same Origin Policy", you can't get cross domain data).
3384		preload: true,
3385
3386		// Custom CSS styling for iframe wrapping element
3387		// You can use this to set custom iframe dimensions
3388		css: {},
3389
3390		// Iframe tag attributes
3391		attr: {
3392		  scrolling: "auto"
3393		}
3394	  },
3395
3396	  // For HTML5 video only
3397	  video: {
3398		tpl: '<video class="fancybox-video" controls controlsList="nodownload" poster="{{poster}}">' +
3399		  '<source src="{{src}}" type="{{format}}" />' +
3400		  'Sorry, your browser doesn\'t support embedded videos, <a href="{{src}}">download</a> and watch with your favorite video player!' +
3401		  "</video>",
3402		format: "", // custom video format
3403		autoStart: true
3404	  },
3405
3406	  // Default content type if cannot be detected automatically
3407	  defaultType: "image",
3408
3409	  // Open/close animation type
3410	  // Possible values:
3411	  //   false            - disable
3412	  //   "zoom"           - zoom images from/to thumbnail
3413	  //   "fade"
3414	  //   "zoom-in-out"
3415	  //
3416	  animationEffect: "zoom",
3417
3418	  // Duration in ms for open/close animation
3419	  animationDuration: 366,
3420
3421	  // Should image change opacity while zooming
3422	  // If opacity is "auto", then opacity will be changed if image and thumbnail have different aspect ratios
3423	  zoomOpacity: "auto",
3424
3425	  // Transition effect between slides
3426	  //
3427	  // Possible values:
3428	  //   false            - disable
3429	  //   "fade'
3430	  //   "slide'
3431	  //   "circular'
3432	  //   "tube'
3433	  //   "zoom-in-out'
3434	  //   "rotate'
3435	  //
3436	  transitionEffect: "fade",
3437
3438	  // Duration in ms for transition animation
3439	  transitionDuration: 366,
3440
3441	  // Custom CSS class for slide element
3442	  slideClass: "",
3443
3444	  // Custom CSS class for layout
3445	  baseClass: "",
3446
3447	  // Base template for layout
3448	  baseTpl: '<div class="fancybox-container" role="dialog" tabindex="-1">' +
3449		'<div class="fancybox-bg"></div>' +
3450		'<div class="fancybox-inner">' +
3451		'<div class="fancybox-infobar"><span data-fancybox-index></span>&nbsp;/&nbsp;<span data-fancybox-count></span></div>' +
3452		'<div class="fancybox-toolbar">{{buttons}}</div>' +
3453		'<div class="fancybox-navigation">{{arrows}}</div>' +
3454		'<div class="fancybox-stage"></div>' +
3455		'<div class="fancybox-caption"><div class="fancybox-caption__body"></div></div>' +
3456		"</div>" +
3457		"</div>",
3458
3459	  // Loading indicator template
3460	  spinnerTpl: '<div class="fancybox-loading"></div>',
3461
3462	  // Error message template
3463	  errorTpl: '<div class="fancybox-error"><p>{{ERROR}}</p></div>',
3464
3465	  btnTpl: {
3466		download: '<a download data-fancybox-download class="fancybox-button fancybox-button--download" title="{{DOWNLOAD}}" href="javascript:;">' +
3467		  '<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>' +
3468		  "</a>",
3469
3470		zoom: '<button data-fancybox-zoom class="fancybox-button fancybox-button--zoom" title="{{ZOOM}}">' +
3471		  '<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>' +
3472		  "</button>",
3473
3474		close: '<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}">' +
3475		  '<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>' +
3476		  "</button>",
3477
3478		// Arrows
3479		arrowLeft: '<button data-fancybox-prev class="fancybox-button fancybox-button--arrow_left" title="{{PREV}}">' +
3480		  '<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>' +
3481		  "</button>",
3482
3483		arrowRight: '<button data-fancybox-next class="fancybox-button fancybox-button--arrow_right" title="{{NEXT}}">' +
3484		  '<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>' +
3485		  "</button>",
3486
3487		// This small close button will be appended to your html/inline/ajax content by default,
3488		// if "smallBtn" option is not set to false
3489		smallBtn: '<button type="button" data-fancybox-close class="fancybox-button fancybox-close-small" title="{{CLOSE}}">' +
3490		  '<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>' +
3491		  "</button>"
3492	  },
3493
3494	  // Container is injected into this element
3495	  parentEl: "body",
3496
3497	  // Hide browser vertical scrollbars; use at your own risk
3498	  hideScrollbar: true,
3499
3500	  // Focus handling
3501	  // ==============
3502
3503	  // Try to focus on the first focusable element after opening
3504	  autoFocus: true,
3505
3506	  // Put focus back to active element after closing
3507	  backFocus: true,
3508
3509	  // Do not let user to focus on element outside modal content
3510	  trapFocus: true,
3511
3512	  // Module specific options
3513	  // =======================
3514
3515	  fullScreen: {
3516		autoStart: false
3517	  },
3518
3519	  // Set `touch: false` to disable panning/swiping
3520	  touch: {
3521		vertical: true, // Allow to drag content vertically
3522		momentum: true // Continue movement after releasing mouse/touch when panning
3523	  },
3524
3525	  // Hash value when initializing manually,
3526	  // set `false` to disable hash change
3527	  hash: null,
3528
3529	  // Customize or add new media types
3530	  // Example:
3531	  /*
3532		media : {
3533		  youtube : {
3534			params : {
3535			  autoplay : 0
3536			}
3537		  }
3538		}
3539	  */
3540	  media: {},
3541
3542	  slideShow: {
3543		autoStart: false,
3544		speed: 3000
3545	  },
3546
3547	  thumbs: {
3548		autoStart: false, // Display thumbnails on opening
3549		hideOnClose: true, // Hide thumbnail grid when closing animation starts
3550		parentEl: ".fancybox-container", // Container is injected into this element
3551		axis: "y" // Vertical (y) or horizontal (x) scrolling
3552	  },
3553
3554	  // Use mousewheel to navigate gallery
3555	  // If 'auto' - enabled for images only
3556	  wheel: "auto",
3557
3558	  // Callbacks
3559	  //==========
3560
3561	  // See Documentation/API/Events for more information
3562	  // Example:
3563	  /*
3564		afterShow: function( instance, current ) {
3565		  console.info( 'Clicked element:' );
3566		  console.info( current.opts.$orig );
3567		}
3568	  */
3569
3570	  onInit: $.noop, // When instance has been initialized
3571
3572	  beforeLoad: $.noop, // Before the content of a slide is being loaded
3573	  afterLoad: $.noop, // When the content of a slide is done loading
3574
3575	  beforeShow: $.noop, // Before open animation starts
3576	  afterShow: $.noop, // When content is done loading and animating
3577
3578	  beforeClose: $.noop, // Before the instance attempts to close. Return false to cancel the close.
3579	  afterClose: $.noop, // After instance has been closed
3580
3581	  onActivate: $.noop, // When instance is brought to front
3582	  onDeactivate: $.noop, // When other instance has been activated
3583
3584	  // Interaction
3585	  // ===========
3586
3587	  // Use options below to customize taken action when user clicks or double clicks on the fancyBox area,
3588	  // each option can be string or method that returns value.
3589	  //
3590	  // Possible values:
3591	  //   "close"           - close instance
3592	  //   "next"            - move to next gallery item
3593	  //   "nextOrClose"     - move to next gallery item or close if gallery has only one item
3594	  //   "toggleControls"  - show/hide controls
3595	  //   "zoom"            - zoom image (if loaded)
3596	  //   false             - do nothing
3597
3598	  // Clicked on the content
3599	  clickContent: function (current, event) {
3600		return current.type === "image" ? "zoom" : false;
3601	  },
3602
3603	  // Clicked on the slide
3604	  clickSlide: "close",
3605
3606	  // Clicked on the background (backdrop) element;
3607	  // if you have not changed the layout, then most likely you need to use `clickSlide` option
3608	  clickOutside: "close",
3609
3610	  // Same as previous two, but for double click
3611	  dblclickContent: false,
3612	  dblclickSlide: false,
3613	  dblclickOutside: false,
3614
3615	  // Custom options when mobile device is detected
3616	  // =============================================
3617
3618	  mobile: {
3619		preventCaptionOverlap: false,
3620		idleTime: false,
3621		clickContent: function (current, event) {
3622		  return current.type === "image" ? "toggleControls" : false;
3623		},
3624		clickSlide: function (current, event) {
3625		  return current.type === "image" ? "toggleControls" : "close";
3626		},
3627		dblclickContent: function (current, event) {
3628		  return current.type === "image" ? "zoom" : false;
3629		},
3630		dblclickSlide: function (current, event) {
3631		  return current.type === "image" ? "zoom" : false;
3632		}
3633	  },
3634
3635	  // Internationalization
3636	  // ====================
3637
3638	  lang: "en",
3639	  i18n: {
3640		en: {
3641		  CLOSE: "Close",
3642		  NEXT: "Next",
3643		  PREV: "Previous",
3644		  ERROR: "The requested content cannot be loaded. <br/> Please try again later.",
3645		  PLAY_START: "Start slideshow",
3646		  PLAY_STOP: "Pause slideshow",
3647		  FULL_SCREEN: "Full screen",
3648		  THUMBS: "Thumbnails",
3649		  DOWNLOAD: "Download",
3650		  SHARE: "Share",
3651		  ZOOM: "Zoom"
3652		},
3653		de: {
3654		  CLOSE: "Schlie&szlig;en",
3655		  NEXT: "Weiter",
3656		  PREV: "Zur&uuml;ck",
3657		  ERROR: "Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es sp&auml;ter nochmal.",
3658		  PLAY_START: "Diaschau starten",
3659		  PLAY_STOP: "Diaschau beenden",
3660		  FULL_SCREEN: "Vollbild",
3661		  THUMBS: "Vorschaubilder",
3662		  DOWNLOAD: "Herunterladen",
3663		  SHARE: "Teilen",
3664		  ZOOM: "Vergr&ouml;&szlig;ern"
3665		}
3666	  }
3667	};
3668
3669	// Few useful variables and methods
3670	// ================================
3671
3672	var $W = $(window);
3673	var $D = $(document);
3674
3675	var called = 0;
3676
3677	// Check if an object is a jQuery object and not a native JavaScript object
3678	// ========================================================================
3679	var isQuery = function (obj) {
3680	  return obj && obj.hasOwnProperty && obj instanceof $;
3681	};
3682
3683	// Handle multiple browsers for "requestAnimationFrame" and "cancelAnimationFrame"
3684	// ===============================================================================
3685	var requestAFrame = (function () {
3686	  return (
3687		window.requestAnimationFrame ||
3688		window.webkitRequestAnimationFrame ||
3689		window.mozRequestAnimationFrame ||
3690		window.oRequestAnimationFrame ||
3691		// if all else fails, use setTimeout
3692		function (callback) {
3693		  return window.setTimeout(callback, 1000 / 60);
3694		}
3695	  );
3696	})();
3697
3698	var cancelAFrame = (function () {
3699	  return (
3700		window.cancelAnimationFrame ||
3701		window.webkitCancelAnimationFrame ||
3702		window.mozCancelAnimationFrame ||
3703		window.oCancelAnimationFrame ||
3704		function (id) {
3705		  window.clearTimeout(id);
3706		}
3707	  );
3708	})();
3709
3710	// Detect the supported transition-end event property name
3711	// =======================================================
3712	var transitionEnd = (function () {
3713	  var el = document.createElement("fakeelement"),
3714		t;
3715
3716	  var transitions = {
3717		transition: "transitionend",
3718		OTransition: "oTransitionEnd",
3719		MozTransition: "transitionend",
3720		WebkitTransition: "webkitTransitionEnd"
3721	  };
3722
3723	  for (t in transitions) {
3724		if (el.style[t] !== undefined) {
3725		  return transitions[t];
3726		}
3727	  }
3728
3729	  return "transitionend";
3730	})();
3731
3732	// Force redraw on an element.
3733	// This helps in cases where the browser doesn't redraw an updated element properly
3734	// ================================================================================
3735	var forceRedraw = function ($el) {
3736	  return $el && $el.length && $el[0].offsetHeight;
3737	};
3738
3739	// Exclude array (`buttons`) options from deep merging
3740	// ===================================================
3741	var mergeOpts = function (opts1, opts2) {
3742	  var rez = $.extend(true, {}, opts1, opts2);
3743
3744	  $.each(opts2, function (key, value) {
3745		if ($.isArray(value)) {
3746		  rez[key] = value;
3747		}
3748	  });
3749
3750	  return rez;
3751	};
3752
3753	// How much of an element is visible in viewport
3754	// =============================================
3755
3756	var inViewport = function (elem) {
3757	  var elemCenter, rez;
3758
3759	  if (!elem || elem.ownerDocument !== document) {
3760		return false;
3761	  }
3762
3763	  $(".fancybox-container").css("pointer-events", "none");
3764
3765	  elemCenter = {
3766		x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
3767		y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
3768	  };
3769
3770	  rez = document.elementFromPoint(elemCenter.x, elemCenter.y) === elem;
3771
3772	  $(".fancybox-container").css("pointer-events", "");
3773
3774	  return rez;
3775	};
3776
3777	// Class definition
3778	// ================
3779
3780	var FancyBox = function (content, opts, index) {
3781	  var self = this;
3782
3783	  self.opts = mergeOpts({
3784		index: index
3785	  }, $.fancybox.defaults);
3786
3787	  if ($.isPlainObject(opts)) {
3788		self.opts = mergeOpts(self.opts, opts);
3789	  }
3790
3791	  if ($.fancybox.isMobile) {
3792		self.opts = mergeOpts(self.opts, self.opts.mobile);
3793	  }
3794
3795	  self.id = self.opts.id || ++called;
3796
3797	  self.currIndex = parseInt(self.opts.index, 10) || 0;
3798	  self.prevIndex = null;
3799
3800	  self.prevPos = null;
3801	  self.currPos = 0;
3802
3803	  self.firstRun = true;
3804
3805	  // All group items
3806	  self.group = [];
3807
3808	  // Existing slides (for current, next and previous gallery items)
3809	  self.slides = {};
3810
3811	  // Create group elements
3812	  self.addContent(content);
3813
3814	  if (!self.group.length) {
3815		return;
3816	  }
3817
3818	  self.init();
3819	};
3820
3821	$.extend(FancyBox.prototype, {
3822	  // Create DOM structure
3823	  // ====================
3824
3825	  init: function () {
3826		var self = this,
3827		  firstItem = self.group[self.currIndex],
3828		  firstItemOpts = firstItem.opts,
3829		  $container,
3830		  buttonStr;
3831
3832		if (firstItemOpts.closeExisting) {
3833		  $.fancybox.close(true);
3834		}
3835
3836		// Hide scrollbars
3837		// ===============
3838
3839		$("body").addClass("fancybox-active");
3840
3841		if (
3842		  !$.fancybox.getInstance() &&
3843		  firstItemOpts.hideScrollbar !== false &&
3844		  !$.fancybox.isMobile &&
3845		  document.body.scrollHeight > window.innerHeight
3846		) {
3847		  $("head").append(
3848			'<style id="fancybox-style-noscroll" type="text/css">.compensate-for-scrollbar{margin-right:' +
3849			(window.innerWidth - document.documentElement.clientWidth) +
3850			"px;}</style>"
3851		  );
3852
3853		  $("body").addClass("compensate-for-scrollbar");
3854		}
3855
3856		// Build html markup and set references
3857		// ====================================
3858
3859		// Build html code for buttons and insert into main template
3860		buttonStr = "";
3861
3862		$.each(firstItemOpts.buttons, function (index, value) {
3863		  buttonStr += firstItemOpts.btnTpl[value] || "";
3864		});
3865
3866		// Create markup from base template, it will be initially hidden to
3867		// avoid unnecessary work like painting while initializing is not complete
3868		$container = $(
3869			self.translate(
3870			  self,
3871			  firstItemOpts.baseTpl
3872			  .replace("{{buttons}}", buttonStr)
3873			  .replace("{{arrows}}", firstItemOpts.btnTpl.arrowLeft + firstItemOpts.btnTpl.arrowRight)
3874			)
3875		  )
3876		  .attr("id", "fancybox-container-" + self.id)
3877		  .addClass(firstItemOpts.baseClass)
3878		  .data("FancyBox", self)
3879		  .appendTo(firstItemOpts.parentEl);
3880
3881		// Create object holding references to jQuery wrapped nodes
3882		self.$refs = {
3883		  container: $container
3884		};
3885
3886		["bg", "inner", "infobar", "toolbar", "stage", "caption", "navigation"].forEach(function (item) {
3887		  self.$refs[item] = $container.find(".fancybox-" + item);
3888		});
3889
3890		self.trigger("onInit");
3891
3892		// Enable events, deactive previous instances
3893		self.activate();
3894
3895		// Build slides, load and reveal content
3896		self.jumpTo(self.currIndex);
3897	  },
3898
3899	  // Simple i18n support - replaces object keys found in template
3900	  // with corresponding values
3901	  // ============================================================
3902
3903	  translate: function (obj, str) {
3904		var arr = obj.opts.i18n[obj.opts.lang] || obj.opts.i18n.en;
3905
3906		return str.replace(/\{\{(\w+)\}\}/g, function (match, n) {
3907		  return arr[n] === undefined ? match : arr[n];
3908		});
3909	  },
3910
3911	  // Populate current group with fresh content
3912	  // Check if each object has valid type and content
3913	  // ===============================================
3914
3915	  addContent: function (content) {
3916		var self = this,
3917		  items = $.makeArray(content),
3918		  thumbs;
3919
3920		$.each(items, function (i, item) {
3921		  var obj = {},
3922			opts = {},
3923			$item,
3924			type,
3925			found,
3926			src,
3927			srcParts;
3928
3929		  // Step 1 - Make sure we have an object
3930		  // ====================================
3931
3932		  if ($.isPlainObject(item)) {
3933			// We probably have manual usage here, something like
3934			// $.fancybox.open( [ { src : "image.jpg", type : "image" } ] )
3935
3936			obj = item;
3937			opts = item.opts || item;
3938		  } else if ($.type(item) === "object" && $(item).length) {
3939			// Here we probably have jQuery collection returned by some selector
3940			$item = $(item);
3941
3942			// Support attributes like `data-options='{"touch" : false}'` and `data-touch='false'`
3943			opts = $item.data() || {};
3944			opts = $.extend(true, {}, opts, opts.options);
3945
3946			// Here we store clicked element
3947			opts.$orig = $item;
3948
3949			obj.src = self.opts.src || opts.src || $item.attr("href");
3950
3951			// Assume that simple syntax is used, for example:
3952			//   `$.fancybox.open( $("#test"), {} );`
3953			if (!obj.type && !obj.src) {
3954			  obj.type = "inline";
3955			  obj.src = item;
3956			}
3957		  } else {
3958			// Assume we have a simple html code, for example:
3959			//   $.fancybox.open( '<div><h1>Hi!</h1></div>' );
3960			obj = {
3961			  type: "html",
3962			  src: item + ""
3963			};
3964		  }
3965
3966		  // Each gallery object has full collection of options
3967		  obj.opts = $.extend(true, {}, self.opts, opts);
3968
3969		  // Do not merge buttons array
3970		  if ($.isArray(opts.buttons)) {
3971			obj.opts.buttons = opts.buttons;
3972		  }
3973
3974		  if ($.fancybox.isMobile && obj.opts.mobile) {
3975			obj.opts = mergeOpts(obj.opts, obj.opts.mobile);
3976		  }
3977
3978		  // Step 2 - Make sure we have content type, if not - try to guess
3979		  // ==============================================================
3980
3981		  type = obj.type || obj.opts.type;
3982		  src = obj.src || "";
3983
3984		  if (!type && src) {
3985			if ((found = src.match(/\.(mp4|mov|ogv|webm)((\?|#).*)?$/i))) {
3986			  type = "video";
3987
3988			  if (!obj.opts.video.format) {
3989				obj.opts.video.format = "video/" + (found[1] === "ogv" ? "ogg" : found[1]);
3990			  }
3991			} else if (src.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i)) {
3992			  type = "image";
3993			} else if (src.match(/\.(pdf)((\?|#).*)?$/i)) {
3994			  type = "iframe";
3995			  obj = $.extend(true, obj, {
3996				contentType: "pdf",
3997				opts: {
3998				  iframe: {
3999					preload: false
4000				  }
4001				}
4002			  });
4003			} else if (src.charAt(0) === "#") {
4004			  type = "inline";
4005			}
4006		  }
4007
4008		  if (type) {
4009			obj.type = type;
4010		  } else {
4011			self.trigger("objectNeedsType", obj);
4012		  }
4013
4014		  if (!obj.contentType) {
4015			obj.contentType = $.inArray(obj.type, ["html", "inline", "ajax"]) > -1 ? "html" : obj.type;
4016		  }
4017
4018		  // Step 3 - Some adjustments
4019		  // =========================
4020
4021		  obj.index = self.group.length;
4022
4023		  if (obj.opts.smallBtn == "auto") {
4024			obj.opts.smallBtn = $.inArray(obj.type, ["html", "inline", "ajax"]) > -1;
4025		  }
4026
4027		  if (obj.opts.toolbar === "auto") {
4028			obj.opts.toolbar = !obj.opts.smallBtn;
4029		  }
4030
4031		  // Find thumbnail image, check if exists and if is in the viewport
4032		  obj.$thumb = obj.opts.$thumb || null;
4033
4034		  if (obj.opts.$trigger && obj.index === self.opts.index) {
4035			obj.$thumb = obj.opts.$trigger.find("img:first");
4036
4037			if (obj.$thumb.length) {
4038			  obj.opts.$orig = obj.opts.$trigger;
4039			}
4040		  }
4041
4042		  if (!(obj.$thumb && obj.$thumb.length) && obj.opts.$orig) {
4043			obj.$thumb = obj.opts.$orig.find("img:first");
4044		  }
4045
4046		  if (obj.$thumb && !obj.$thumb.length) {
4047			obj.$thumb = null;
4048		  }
4049
4050		  obj.thumb = obj.opts.thumb || (obj.$thumb ? obj.$thumb[0].src : null);
4051
4052		  // "caption" is a "special" option, it can be used to customize caption per gallery item
4053		  if ($.type(obj.opts.caption) === "function") {
4054			obj.opts.caption = obj.opts.caption.apply(item, [self, obj]);
4055		  }
4056
4057		  if ($.type(self.opts.caption) === "function") {
4058			obj.opts.caption = self.opts.caption.apply(item, [self, obj]);
4059		  }
4060
4061		  // Make sure we have caption as a string or jQuery object
4062		  if (!(obj.opts.caption instanceof $)) {
4063			obj.opts.caption = obj.opts.caption === undefined ? "" : obj.opts.caption + "";
4064		  }
4065
4066		  // Check if url contains "filter" used to filter the content
4067		  // Example: "ajax.html #something"
4068		  if (obj.type === "ajax") {
4069			srcParts = src.split(/\s+/, 2);
4070
4071			if (srcParts.length > 1) {
4072			  obj.src = srcParts.shift();
4073
4074			  obj.opts.filter = srcParts.shift();
4075			}
4076		  }
4077
4078		  // Hide all buttons and disable interactivity for modal items
4079		  if (obj.opts.modal) {
4080			obj.opts = $.extend(true, obj.opts, {
4081			  trapFocus: true,
4082			  // Remove buttons
4083			  infobar: 0,
4084			  toolbar: 0,
4085
4086			  smallBtn: 0,
4087
4088			  // Disable keyboard navigation
4089			  keyboard: 0,
4090
4091			  // Disable some modules
4092			  slideShow: 0,
4093			  fullScreen: 0,
4094			  thumbs: 0,
4095			  touch: 0,
4096
4097			  // Disable click event handlers
4098			  clickContent: false,
4099			  clickSlide: false,
4100			  clickOutside: false,
4101			  dblclickContent: false,
4102			  dblclickSlide: false,
4103			  dblclickOutside: false
4104			});
4105		  }
4106
4107		  // Step 4 - Add processed object to group
4108		  // ======================================
4109
4110		  self.group.push(obj);
4111		});
4112
4113		// Update controls if gallery is already opened
4114		if (Object.keys(self.slides).length) {
4115		  self.updateControls();
4116
4117		  // Update thumbnails, if needed
4118		  thumbs = self.Thumbs;
4119
4120		  if (thumbs && thumbs.isActive) {
4121			thumbs.create();
4122
4123			thumbs.focus();
4124		  }
4125		}
4126	  },
4127
4128	  // Attach an event handler functions for:
4129	  //   - navigation buttons
4130	  //   - browser scrolling, resizing;
4131	  //   - focusing
4132	  //   - keyboard
4133	  //   - detecting inactivity
4134	  // ======================================
4135
4136	  addEvents: function () {
4137		var self = this;
4138
4139		self.removeEvents();
4140
4141		// Make navigation elements clickable
4142		// ==================================
4143
4144		self.$refs.container
4145		  .on("click.fb-close", "[data-fancybox-close]", function (e) {
4146			e.stopPropagation();
4147			e.preventDefault();
4148
4149			self.close(e);
4150		  })
4151		  .on("touchstart.fb-prev click.fb-prev", "[data-fancybox-prev]", function (e) {
4152			e.stopPropagation();
4153			e.preventDefault();
4154
4155			self.previous();
4156		  })
4157		  .on("touchstart.fb-next click.fb-next", "[data-fancybox-next]", function (e) {
4158			e.stopPropagation();
4159			e.preventDefault();
4160
4161			self.next();
4162		  })
4163		  .on("click.fb", "[data-fancybox-zoom]", function (e) {
4164			// Click handler for zoom button
4165			self[self.isScaledDown() ? "scaleToActual" : "scaleToFit"]();
4166		  });
4167
4168		// Handle page scrolling and browser resizing
4169		// ==========================================
4170
4171		$W.on("orientationchange.fb resize.fb", function (e) {
4172		  if (e && e.originalEvent && e.originalEvent.type === "resize") {
4173			if (self.requestId) {
4174			  cancelAFrame(self.requestId);
4175			}
4176
4177			self.requestId = requestAFrame(function () {
4178			  self.update(e);
4179			});
4180		  } else {
4181			if (self.current && self.current.type === "iframe") {
4182			  self.$refs.stage.hide();
4183			}
4184
4185			setTimeout(
4186			  function () {
4187				self.$refs.stage.show();
4188
4189				self.update(e);
4190			  },
4191			  $.fancybox.isMobile ? 600 : 250
4192			);
4193		  }
4194		});
4195
4196		$D.on("keydown.fb", function (e) {
4197		  var instance = $.fancybox ? $.fancybox.getInstance() : null,
4198			current = instance.current,
4199			keycode = e.keyCode || e.which;
4200
4201		  // Trap keyboard focus inside of the modal
4202		  // =======================================
4203
4204		  if (keycode == 9) {
4205			if (current.opts.trapFocus) {
4206			  self.focus(e);
4207			}
4208
4209			return;
4210		  }
4211
4212		  // Enable keyboard navigation
4213		  // ==========================
4214
4215		  if (!current.opts.keyboard || e.ctrlKey || e.altKey || e.shiftKey || $(e.target).is("input,textarea,video,audio,select")) {
4216			return;
4217		  }
4218
4219		  // Backspace and Esc keys
4220		  if (keycode === 8 || keycode === 27) {
4221			e.preventDefault();
4222
4223			self.close(e);
4224
4225			return;
4226		  }
4227
4228		  // Left arrow and Up arrow
4229		  if (keycode === 37 || keycode === 38) {
4230			e.preventDefault();
4231
4232			self.previous();
4233
4234			return;
4235		  }
4236
4237		  // Righ arrow and Down arrow
4238		  if (keycode === 39 || keycode === 40) {
4239			e.preventDefault();
4240
4241			self.next();
4242
4243			return;
4244		  }
4245
4246		  self.trigger("afterKeydown", e, keycode);
4247		});
4248
4249		// Hide controls after some inactivity period
4250		if (self.group[self.currIndex].opts.idleTime) {
4251		  self.idleSecondsCounter = 0;
4252
4253		  $D.on(
4254			"mousemove.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle",
4255			function (e) {
4256			  self.idleSecondsCounter = 0;
4257
4258			  if (self.isIdle) {
4259				self.showControls();
4260			  }
4261
4262			  self.isIdle = false;
4263			}
4264		  );
4265
4266		  self.idleInterval = window.setInterval(function () {
4267			self.idleSecondsCounter++;
4268
4269			if (self.idleSecondsCounter >= self.group[self.currIndex].opts.idleTime && !self.isDragging) {
4270			  self.isIdle = true;
4271			  self.idleSecondsCounter = 0;
4272
4273			  self.hideControls();
4274			}
4275		  }, 1000);
4276		}
4277	  },
4278
4279	  // Remove events added by the core
4280	  // ===============================
4281
4282	  removeEvents: function () {
4283		var self = this;
4284
4285		$W.off("orientationchange.fb resize.fb");
4286		$D.off("keydown.fb .fb-idle");
4287
4288		this.$refs.container.off(".fb-close .fb-prev .fb-next");
4289
4290		if (self.idleInterval) {
4291		  window.clearInterval(self.idleInterval);
4292
4293		  self.idleInterval = null;
4294		}
4295	  },
4296
4297	  // Change to previous gallery item
4298	  // ===============================
4299
4300	  previous: function (duration) {
4301		return this.jumpTo(this.currPos - 1, duration);
4302	  },
4303
4304	  // Change to next gallery item
4305	  // ===========================
4306
4307	  next: function (duration) {
4308		return this.jumpTo(this.currPos + 1, duration);
4309	  },
4310
4311	  // Switch to selected gallery item
4312	  // ===============================
4313
4314	  jumpTo: function (pos, duration) {
4315		var self = this,
4316		  groupLen = self.group.length,
4317		  firstRun,
4318		  isMoved,
4319		  loop,
4320		  current,
4321		  previous,
4322		  slidePos,
4323		  stagePos,
4324		  prop,
4325		  diff;
4326
4327		if (self.isDragging || self.isClosing || (self.isAnimating && self.firstRun)) {
4328		  return;
4329		}
4330
4331		// Should loop?
4332		pos = parseInt(pos, 10);
4333		loop = self.current ? self.current.opts.loop : self.opts.loop;
4334
4335		if (!loop && (pos < 0 || pos >= groupLen)) {
4336		  return false;
4337		}
4338
4339		// Check if opening for the first time; this helps to speed things up
4340		firstRun = self.firstRun = !Object.keys(self.slides).length;
4341
4342		// Create slides
4343		previous = self.current;
4344
4345		self.prevIndex = self.currIndex;
4346		self.prevPos = self.currPos;
4347
4348		current = self.createSlide(pos);
4349
4350		if (groupLen > 1) {
4351		  if (loop || current.index < groupLen - 1) {
4352			self.createSlide(pos + 1);
4353		  }
4354
4355		  if (loop || current.index > 0) {
4356			self.createSlide(pos - 1);
4357		  }
4358		}
4359
4360		self.current = current;
4361		self.currIndex = current.index;
4362		self.currPos = current.pos;
4363
4364		self.trigger("beforeShow", firstRun);
4365
4366		self.updateControls();
4367
4368		// Validate duration length
4369		current.forcedDuration = undefined;
4370
4371		if ($.isNumeric(duration)) {
4372		  current.forcedDuration = duration;
4373		} else {
4374		  duration = current.opts[firstRun ? "animationDuration" : "transitionDuration"];
4375		}
4376
4377		duration = parseInt(duration, 10);
4378
4379		// Check if user has swiped the slides or if still animating
4380		isMoved = self.isMoved(current);
4381
4382		// Make sure current slide is visible
4383		current.$slide.addClass("fancybox-slide--current");
4384
4385		// Fresh start - reveal container, current slide and start loading content
4386		if (firstRun) {
4387		  if (current.opts.animationEffect && duration) {
4388			self.$refs.container.css("transition-duration", duration + "ms");
4389		  }
4390
4391		  self.$refs.container.addClass("fancybox-is-open").trigger("focus");
4392
4393		  // Attempt to load content into slide
4394		  // This will later call `afterLoad` -> `revealContent`
4395		  self.loadSlide(current);
4396
4397		  self.preload("image");
4398
4399		  return;
4400		}
4401
4402		// Get actual slide/stage positions (before cleaning up)
4403		slidePos = $.fancybox.getTranslate(previous.$slide);
4404		stagePos = $.fancybox.getTranslate(self.$refs.stage);
4405
4406		// Clean up all slides
4407		$.each(self.slides, function (index, slide) {
4408		  $.fancybox.stop(slide.$slide, true);
4409		});
4410
4411		if (previous.pos !== current.pos) {
4412		  previous.isComplete = false;
4413		}
4414
4415		previous.$slide.removeClass("fancybox-slide--complete fancybox-slide--current");
4416
4417		// If slides are out of place, then animate them to correct position
4418		if (isMoved) {
4419		  // Calculate horizontal swipe distance
4420		  diff = slidePos.left - (previous.pos * slidePos.width + previous.pos * previous.opts.gutter);
4421
4422		  $.each(self.slides, function (index, slide) {
4423			slide.$slide.removeClass("fancybox-animated").removeClass(function (index, className) {
4424			  return (className.match(/(^|\s)fancybox-fx-\S+/g) || []).join(" ");
4425			});
4426
4427			// Make sure that each slide is in equal distance
4428			// This is mostly needed for freshly added slides, because they are not yet positioned
4429			var leftPos = slide.pos * slidePos.width + slide.pos * slide.opts.gutter;
4430
4431			$.fancybox.setTranslate(slide.$slide, {
4432			  top: 0,
4433			  left: leftPos - stagePos.left + diff
4434			});
4435
4436			if (slide.pos !== current.pos) {
4437			  slide.$slide.addClass("fancybox-slide--" + (slide.pos > current.pos ? "next" : "previous"));
4438			}
4439
4440			// Redraw to make sure that transition will start
4441			forceRedraw(slide.$slide);
4442
4443			// Animate the slide
4444			$.fancybox.animate(
4445			  slide.$slide, {
4446				top: 0,
4447				left: (slide.pos - current.pos) * slidePos.width + (slide.pos - current.pos) * slide.opts.gutter
4448			  },
4449			  duration,
4450			  function () {
4451				slide.$slide
4452				  .css({
4453					transform: "",
4454					opacity: ""
4455				  })
4456				  .removeClass("fancybox-slide--next fancybox-slide--previous");
4457
4458				if (slide.pos === self.currPos) {
4459				  self.complete();
4460				}
4461			  }
4462			);
4463		  });
4464		} else if (duration && current.opts.transitionEffect) {
4465		  // Set transition effect for previously active slide
4466		  prop = "fancybox-animated fancybox-fx-" + current.opts.transitionEffect;
4467
4468		  previous.$slide.addClass("fancybox-slide--" + (previous.pos > current.pos ? "next" : "previous"));
4469
4470		  $.fancybox.animate(
4471			previous.$slide,
4472			prop,
4473			duration,
4474			function () {
4475			  previous.$slide.removeClass(prop).removeClass("fancybox-slide--next fancybox-slide--previous");
4476			},
4477			false
4478		  );
4479		}
4480
4481		if (current.isLoaded) {
4482		  self.revealContent(current);
4483		} else {
4484		  self.loadSlide(current);
4485		}
4486
4487		self.preload("image");
4488	  },
4489
4490	  // Create new "slide" element
4491	  // These are gallery items  that are actually added to DOM
4492	  // =======================================================
4493
4494	  createSlide: function (pos) {
4495		var self = this,
4496		  $slide,
4497		  index;
4498
4499		index = pos % self.group.length;
4500		index = index < 0 ? self.group.length + index : index;
4501
4502		if (!self.slides[pos] && self.group[index]) {
4503		  $slide = $('<div class="fancybox-slide"></div>').appendTo(self.$refs.stage);
4504
4505		  self.slides[pos] = $.extend(true, {}, self.group[index], {
4506			pos: pos,
4507			$slide: $slide,
4508			isLoaded: false
4509		  });
4510
4511		  self.updateSlide(self.slides[pos]);
4512		}
4513
4514		return self.slides[pos];
4515	  },
4516
4517	  // Scale image to the actual size of the image;
4518	  // x and y values should be relative to the slide
4519	  // ==============================================
4520
4521	  scaleToActual: function (x, y, duration) {
4522		var self = this,
4523		  current = self.current,
4524		  $content = current.$content,
4525		  canvasWidth = $.fancybox.getTranslate(current.$slide).width,
4526		  canvasHeight = $.fancybox.getTranslate(current.$slide).height,
4527		  newImgWidth = current.width,
4528		  newImgHeight = current.height,
4529		  imgPos,
4530		  posX,
4531		  posY,
4532		  scaleX,
4533		  scaleY;
4534
4535		if (self.isAnimating || self.isMoved() || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) {
4536		  return;
4537		}
4538
4539		self.isAnimating = true;
4540
4541		$.fancybox.stop($content);
4542
4543		x = x === undefined ? canvasWidth * 0.5 : x;
4544		y = y === undefined ? canvasHeight * 0.5 : y;
4545
4546		imgPos = $.fancybox.getTranslate($content);
4547
4548		imgPos.top -= $.fancybox.getTranslate(current.$slide).top;
4549		imgPos.left -= $.fancybox.getTranslate(current.$slide).left;
4550
4551		scaleX = newImgWidth / imgPos.width;
4552		scaleY = newImgHeight / imgPos.height;
4553
4554		// Get center position for original image
4555		posX = canvasWidth * 0.5 - newImgWidth * 0.5;
4556		posY = canvasHeight * 0.5 - newImgHeight * 0.5;
4557
4558		// Make sure image does not move away from edges
4559		if (newImgWidth > canvasWidth) {
4560		  posX = imgPos.left * scaleX - (x * scaleX - x);
4561
4562		  if (posX > 0) {
4563			posX = 0;
4564		  }
4565
4566		  if (posX < canvasWidth - newImgWidth) {
4567			posX = canvasWidth - newImgWidth;
4568		  }
4569		}
4570
4571		if (newImgHeight > canvasHeight) {
4572		  posY = imgPos.top * scaleY - (y * scaleY - y);
4573
4574		  if (posY > 0) {
4575			posY = 0;
4576		  }
4577
4578		  if (posY < canvasHeight - newImgHeight) {
4579			posY = canvasHeight - newImgHeight;
4580		  }
4581		}
4582
4583		self.updateCursor(newImgWidth, newImgHeight);
4584
4585		$.fancybox.animate(
4586		  $content, {
4587			top: posY,
4588			left: posX,
4589			scaleX: scaleX,
4590			scaleY: scaleY
4591		  },
4592		  duration || 366,
4593		  function () {
4594			self.isAnimating = false;
4595		  }
4596		);
4597
4598		// Stop slideshow
4599		if (self.SlideShow && self.SlideShow.isActive) {
4600		  self.SlideShow.stop();
4601		}
4602	  },
4603
4604	  // Scale image to fit inside parent element
4605	  // ========================================
4606
4607	  scaleToFit: function (duration) {
4608		var self = this,
4609		  current = self.current,
4610		  $content = current.$content,
4611		  end;
4612
4613		if (self.isAnimating || self.isMoved() || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) {
4614		  return;
4615		}
4616
4617		self.isAnimating = true;
4618
4619		$.fancybox.stop($content);
4620
4621		end = self.getFitPos(current);
4622
4623		self.updateCursor(end.width, end.height);
4624
4625		$.fancybox.animate(
4626		  $content, {
4627			top: end.top,
4628			left: end.left,
4629			scaleX: end.width / $content.width(),
4630			scaleY: end.height / $content.height()
4631		  },
4632		  duration || 366,
4633		  function () {
4634			self.isAnimating = false;
4635		  }
4636		);
4637	  },
4638
4639	  // Calculate image size to fit inside viewport
4640	  // ===========================================
4641
4642	  getFitPos: function (slide) {
4643		var self = this,
4644		  $content = slide.$content,
4645		  $slide = slide.$slide,
4646		  width = slide.width || slide.opts.width,
4647		  height = slide.height || slide.opts.height,
4648		  maxWidth,
4649		  maxHeight,
4650		  minRatio,
4651		  aspectRatio,
4652		  rez = {};
4653
4654		if (!slide.isLoaded || !$content || !$content.length) {
4655		  return false;
4656		}
4657
4658		maxWidth = $.fancybox.getTranslate(self.$refs.stage).width;
4659		maxHeight = $.fancybox.getTranslate(self.$refs.stage).height;
4660
4661		maxWidth -=
4662		  parseFloat($slide.css("paddingLeft")) +
4663		  parseFloat($slide.css("paddingRight")) +
4664		  parseFloat($content.css("marginLeft")) +
4665		  parseFloat($content.css("marginRight"));
4666
4667		maxHeight -=
4668		  parseFloat($slide.css("paddingTop")) +
4669		  parseFloat($slide.css("paddingBottom")) +
4670		  parseFloat($content.css("marginTop")) +
4671		  parseFloat($content.css("marginBottom"));
4672
4673		if (!width || !height) {
4674		  width = maxWidth;
4675		  height = maxHeight;
4676		}
4677
4678		minRatio = Math.min(1, maxWidth / width, maxHeight / height);
4679
4680		width = minRatio * width;
4681		height = minRatio * height;
4682
4683		// Adjust width/height to precisely fit into container
4684		if (width > maxWidth - 0.5) {
4685		  width = maxWidth;
4686		}
4687
4688		if (height > maxHeight - 0.5) {
4689		  height = maxHeight;
4690		}
4691
4692		if (slide.type === "image") {
4693		  rez.top = Math.floor((maxHeight - height) * 0.5) + parseFloat($slide.css("paddingTop"));
4694		  rez.left = Math.floor((maxWidth - width) * 0.5) + parseFloat($slide.css("paddingLeft"));
4695		} else if (slide.contentType === "video") {
4696		  // Force aspect ratio for the video
4697		  // "I say the whole world must learn of our peaceful ways… by force!"
4698		  aspectRatio = slide.opts.width && slide.opts.height ? width / height : slide.opts.ratio || 16 / 9;
4699
4700		  if (height > width / aspectRatio) {
4701			height = width / aspectRatio;
4702		  } else if (width > height * aspectRatio) {
4703			width = height * aspectRatio;
4704		  }
4705		}
4706
4707		rez.width = width;
4708		rez.height = height;
4709
4710		return rez;
4711	  },
4712
4713	  // Update content size and position for all slides
4714	  // ==============================================
4715
4716	  update: function (e) {
4717		var self = this;
4718
4719		$.each(self.slides, function (key, slide) {
4720		  self.updateSlide(slide, e);
4721		});
4722	  },
4723
4724	  // Update slide content position and size
4725	  // ======================================
4726
4727	  updateSlide: function (slide, e) {
4728		var self = this,
4729		  $content = slide && slide.$content,
4730		  width = slide.width || slide.opts.width,
4731		  height = slide.height || slide.opts.height,
4732		  $slide = slide.$slide;
4733
4734		// First, prevent caption overlap, if needed
4735		self.adjustCaption(slide);
4736
4737		// Then resize content to fit inside the slide
4738		if ($content && (width || height || slide.contentType === "video") && !slide.hasError) {
4739		  $.fancybox.stop($content);
4740
4741		  $.fancybox.setTranslate($content, self.getFitPos(slide));
4742
4743		  if (slide.pos === self.currPos) {
4744			self.isAnimating = false;
4745
4746			self.updateCursor();
4747		  }
4748		}
4749
4750		// Then some adjustments
4751		self.adjustLayout(slide);
4752
4753		if ($slide.length) {
4754		  $slide.trigger("refresh");
4755
4756		  if (slide.pos === self.currPos) {
4757			self.$refs.toolbar
4758			  .add(self.$refs.navigation.find(".fancybox-button--arrow_right"))
4759			  .toggleClass("compensate-for-scrollbar", $slide.get(0).scrollHeight > $slide.get(0).clientHeight);
4760		  }
4761		}
4762
4763		self.trigger("onUpdate", slide, e);
4764	  },
4765
4766	  // Horizontally center slide
4767	  // =========================
4768
4769	  centerSlide: function (duration) {
4770		var self = this,
4771		  current = self.current,
4772		  $slide = current.$slide;
4773
4774		if (self.isClosing || !current) {
4775		  return;
4776		}
4777
4778		$slide.siblings().css({
4779		  transform: "",
4780		  opacity: ""
4781		});
4782
4783		$slide
4784		  .parent()
4785		  .children()
4786		  .removeClass("fancybox-slide--previous fancybox-slide--next");
4787
4788		$.fancybox.animate(
4789		  $slide, {
4790			top: 0,
4791			left: 0,
4792			opacity: 1
4793		  },
4794		  duration === undefined ? 0 : duration,
4795		  function () {
4796			// Clean up
4797			$slide.css({
4798			  transform: "",
4799			  opacity: ""
4800			});
4801
4802			if (!current.isComplete) {
4803			  self.complete();
4804			}
4805		  },
4806		  false
4807		);
4808	  },
4809
4810	  // Check if current slide is moved (swiped)
4811	  // ========================================
4812
4813	  isMoved: function (slide) {
4814		var current = slide || this.current,
4815		  slidePos,
4816		  stagePos;
4817
4818		if (!current) {
4819		  return false;
4820		}
4821
4822		stagePos = $.fancybox.getTranslate(this.$refs.stage);
4823		slidePos = $.fancybox.getTranslate(current.$slide);
4824
4825		return (
4826		  !current.$slide.hasClass("fancybox-animated") &&
4827		  (Math.abs(slidePos.top - stagePos.top) > 0.5 || Math.abs(slidePos.left - stagePos.left) > 0.5)
4828		);
4829	  },
4830
4831	  // Update cursor style depending if content can be zoomed
4832	  // ======================================================
4833
4834	  updateCursor: function (nextWidth, nextHeight) {
4835		var self = this,
4836		  current = self.current,
4837		  $container = self.$refs.container,
4838		  canPan,
4839		  isZoomable;
4840
4841		if (!current || self.isClosing || !self.Guestures) {
4842		  return;
4843		}
4844
4845		$container.removeClass("fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-zoomOut fancybox-can-swipe fancybox-can-pan");
4846
4847		canPan = self.canPan(nextWidth, nextHeight);
4848
4849		isZoomable = canPan ? true : self.isZoomable();
4850
4851		$container.toggleClass("fancybox-is-zoomable", isZoomable);
4852
4853		$("[data-fancybox-zoom]").prop("disabled", !isZoomable);
4854
4855		if (canPan) {
4856		  $container.addClass("fancybox-can-pan");
4857		} else if (
4858		  isZoomable &&
4859		  (current.opts.clickContent === "zoom" || ($.isFunction(current.opts.clickContent) && current.opts.clickContent(current) == "zoom"))
4860		) {
4861		  $container.addClass("fancybox-can-zoomIn");
4862		} else if (current.opts.touch && (current.opts.touch.vertical || self.group.length > 1) && current.contentType !== "video") {
4863		  $container.addClass("fancybox-can-swipe");
4864		}
4865	  },
4866
4867	  // Check if current slide is zoomable
4868	  // ==================================
4869
4870	  isZoomable: function () {
4871		var self = this,
4872		  current = self.current,
4873		  fitPos;
4874
4875		// Assume that slide is zoomable if:
4876		//   - image is still loading
4877		//   - actual size of the image is smaller than available area
4878		if (current && !self.isClosing && current.type === "image" && !current.hasError) {
4879		  if (!current.isLoaded) {
4880			return true;
4881		  }
4882
4883		  fitPos = self.getFitPos(current);
4884
4885		  if (fitPos && (current.width > fitPos.width || current.height > fitPos.height)) {
4886			return true;
4887		  }
4888		}
4889
4890		return false;
4891	  },
4892
4893	  // Check if current image dimensions are smaller than actual
4894	  // =========================================================
4895
4896	  isScaledDown: function (nextWidth, nextHeight) {
4897		var self = this,
4898		  rez = false,
4899		  current = self.current,
4900		  $content = current.$content;
4901
4902		if (nextWidth !== undefined && nextHeight !== undefined) {
4903		  rez = nextWidth < current.width && nextHeight < current.height;
4904		} else if ($content) {
4905		  rez = $.fancybox.getTranslate($content);
4906		  rez = rez.width < current.width && rez.height < current.height;
4907		}
4908
4909		return rez;
4910	  },
4911
4912	  // Check if image dimensions exceed parent element
4913	  // ===============================================
4914
4915	  canPan: function (nextWidth, nextHeight) {
4916		var self = this,
4917		  current = self.current,
4918		  pos = null,
4919		  rez = false;
4920
4921		if (current.type === "image" && (current.isComplete || (nextWidth && nextHeight)) && !current.hasError) {
4922		  rez = self.getFitPos(current);
4923
4924		  if (nextWidth !== undefined && nextHeight !== undefined) {
4925			pos = {
4926			  width: nextWidth,
4927			  height: nextHeight
4928			};
4929		  } else if (current.isComplete) {
4930			pos = $.fancybox.getTranslate(current.$content);
4931		  }
4932
4933		  if (pos && rez) {
4934			rez = Math.abs(pos.width - rez.width) > 1.5 || Math.abs(pos.height - rez.height) > 1.5;
4935		  }
4936		}
4937
4938		return rez;
4939	  },
4940
4941	  // Load content into the slide
4942	  // ===========================
4943
4944	  loadSlide: function (slide) {
4945		var self = this,
4946		  type,
4947		  $slide,
4948		  ajaxLoad;
4949
4950		if (slide.isLoading || slide.isLoaded) {
4951		  return;
4952		}
4953
4954		slide.isLoading = true;
4955
4956		if (self.trigger("beforeLoad", slide) === false) {
4957		  slide.isLoading = false;
4958
4959		  return false;
4960		}
4961
4962		type = slide.type;
4963		$slide = slide.$slide;
4964
4965		$slide
4966		  .off("refresh")
4967		  .trigger("onReset")
4968		  .addClass(slide.opts.slideClass);
4969
4970		// Create content depending on the type
4971		switch (type) {
4972		  case "image":
4973			self.setImage(slide);
4974
4975			break;
4976
4977		  case "iframe":
4978			self.setIframe(slide);
4979
4980			break;
4981
4982		  case "html":
4983			self.setContent(slide, slide.src || slide.content);
4984
4985			break;
4986
4987		  case "video":
4988			self.setContent(
4989			  slide,
4990			  slide.opts.video.tpl
4991			  .replace(/\{\{src\}\}/gi, slide.src)
4992			  .replace("{{format}}", slide.opts.videoFormat || slide.opts.video.format || "")
4993			  .replace("{{poster}}", slide.thumb || "")
4994			);
4995
4996			break;
4997
4998		  case "inline":
4999			if ($(slide.src).length) {
5000			  self.setContent(slide, $(slide.src));
5001			} else {
5002			  self.setError(slide);
5003			}
5004
5005			break;
5006
5007		  case "ajax":
5008			self.showLoading(slide);
5009
5010			ajaxLoad = $.ajax(
5011			  $.extend({}, slide.opts.ajax.settings, {
5012				url: slide.src,
5013				success: function (data, textStatus) {
5014				  if (textStatus === "success") {
5015					self.setContent(slide, data);
5016				  }
5017				},
5018				error: function (jqXHR, textStatus) {
5019				  if (jqXHR && textStatus !== "abort") {
5020					self.setError(slide);
5021				  }
5022				}
5023			  })
5024			);
5025
5026			$slide.one("onReset", function () {
5027			  ajaxLoad.abort();
5028			});
5029
5030			break;
5031
5032		  default:
5033			self.setError(slide);
5034
5035			break;
5036		}
5037
5038		return true;
5039	  },
5040
5041	  // Use thumbnail image, if possible
5042	  // ================================
5043
5044	  setImage: function (slide) {
5045		var self = this,
5046		  ghost;
5047
5048		// Check if need to show loading icon
5049		setTimeout(function () {
5050		  var $img = slide.$image;
5051
5052		  if (!self.isClosing && slide.isLoading && (!$img || !$img.length || !$img[0].complete) && !slide.hasError) {
5053			self.showLoading(slide);
5054		  }
5055		}, 50);
5056
5057		//Check if image has srcset
5058		self.checkSrcset(slide);
5059
5060		// This will be wrapper containing both ghost and actual image
5061		slide.$content = $('<div class="fancybox-content"></div>')
5062		  .addClass("fancybox-is-hidden")
5063		  .appendTo(slide.$slide.addClass("fancybox-slide--image"));
5064
5065		// If we have a thumbnail, we can display it while actual image is loading
5066		// Users will not stare at black screen and actual image will appear gradually
5067		if (slide.opts.preload !== false && slide.opts.width && slide.opts.height && slide.thumb) {
5068		  slide.width = slide.opts.width;
5069		  slide.height = slide.opts.height;
5070
5071		  ghost = document.createElement("img");
5072
5073		  ghost.onerror = function () {
5074			$(this).remove();
5075
5076			slide.$ghost = null;
5077		  };
5078
5079		  ghost.onload = function () {
5080			self.afterLoad(slide);
5081		  };
5082
5083		  slide.$ghost = $(ghost)
5084			.addClass("fancybox-image")
5085			.appendTo(slide.$content)
5086			.attr("src", slide.thumb);
5087		}
5088
5089		// Start loading actual image
5090		self.setBigImage(slide);
5091	  },
5092
5093	  // Check if image has srcset and get the source
5094	  // ============================================
5095	  checkSrcset: function (slide) {
5096		var srcset = slide.opts.srcset || slide.opts.image.srcset,
5097		  found,
5098		  temp,
5099		  pxRatio,
5100		  windowWidth;
5101
5102		// If we have "srcset", then we need to find first matching "src" value.
5103		// This is necessary, because when you set an src attribute, the browser will preload the image
5104		// before any javascript or even CSS is applied.
5105		if (srcset) {
5106		  pxRatio = window.devicePixelRatio || 1;
5107		  windowWidth = window.innerWidth * pxRatio;
5108
5109		  temp = srcset.split(",").map(function (el) {
5110			var ret = {};
5111
5112			el.trim()
5113			  .split(/\s+/)
5114			  .forEach(function (el, i) {
5115				var value = parseInt(el.substring(0, el.length - 1), 10);
5116
5117				if (i === 0) {
5118				  return (ret.url = el);
5119				}
5120
5121				if (value) {
5122				  ret.value = value;
5123				  ret.postfix = el[el.length - 1];
5124				}
5125			  });
5126
5127			return ret;
5128		  });
5129
5130		  // Sort by value
5131		  temp.sort(function (a, b) {
5132			return a.value - b.value;
5133		  });
5134
5135		  // Ok, now we have an array of all srcset values
5136		  for (var j = 0; j < temp.length; j++) {
5137			var el = temp[j];
5138
5139			if ((el.postfix === "w" && el.value >= windowWidth) || (el.postfix === "x" && el.value >= pxRatio)) {
5140			  found = el;
5141			  break;
5142			}
5143		  }
5144
5145		  // If not found, take the last one
5146		  if (!found && temp.length) {
5147			found = temp[temp.length - 1];
5148		  }
5149
5150		  if (found) {
5151			slide.src = found.url;
5152
5153			// If we have default width/height values, we can calculate height for matching source
5154			if (slide.width && slide.height && found.postfix == "w") {
5155			  slide.height = (slide.width / slide.height) * found.value;
5156			  slide.width = found.value;
5157			}
5158
5159			slide.opts.srcset = srcset;
5160		  }
5161		}
5162	  },
5163
5164	  // Create full-size image
5165	  // ======================
5166
5167	  setBigImage: function (slide) {
5168		var self = this,
5169		  img = document.createElement("img"),
5170		  $img = $(img);
5171
5172		slide.$image = $img
5173		  .one("error", function () {
5174			self.setError(slide);
5175		  })
5176		  .one("load", function () {
5177			var sizes;
5178
5179			if (!slide.$ghost) {
5180			  self.resolveImageSlideSize(slide, this.naturalWidth, this.naturalHeight);
5181
5182			  self.afterLoad(slide);
5183			}
5184
5185			if (self.isClosing) {
5186			  return;
5187			}
5188
5189			if (slide.opts.srcset) {
5190			  sizes = slide.opts.sizes;
5191
5192			  if (!sizes || sizes === "auto") {
5193				sizes =
5194				  (slide.width / slide.height > 1 && $W.width() / $W.height() > 1 ? "100" : Math.round((slide.width / slide.height) * 100)) +
5195				  "vw";
5196			  }
5197
5198			  $img.attr("sizes", sizes).attr("srcset", slide.opts.srcset);
5199			}
5200
5201			// Hide temporary image after some delay
5202			if (slide.$ghost) {
5203			  setTimeout(function () {
5204				if (slide.$ghost && !self.isClosing) {
5205				  slide.$ghost.hide();
5206				}
5207			  }, Math.min(300, Math.max(1000, slide.height / 1600)));
5208			}
5209
5210			self.hideLoading(slide);
5211		  })
5212		  .addClass("fancybox-image")
5213		  .attr("src", slide.src)
5214		  .appendTo(slide.$content);
5215
5216		if ((img.complete || img.readyState == "complete") && $img.naturalWidth && $img.naturalHeight) {
5217		  $img.trigger("load");
5218		} else if (img.error) {
5219		  $img.trigger("error");
5220		}
5221	  },
5222
5223	  // Computes the slide size from image size and maxWidth/maxHeight
5224	  // ==============================================================
5225
5226	  resolveImageSlideSize: function (slide, imgWidth, imgHeight) {
5227		var maxWidth = parseInt(slide.opts.width, 10),
5228		  maxHeight = parseInt(slide.opts.height, 10);
5229
5230		// Sets the default values from the image
5231		slide.width = imgWidth;
5232		slide.height = imgHeight;
5233
5234		if (maxWidth > 0) {
5235		  slide.width = maxWidth;
5236		  slide.height = Math.floor((maxWidth * imgHeight) / imgWidth);
5237		}
5238
5239		if (maxHeight > 0) {
5240		  slide.width = Math.floor((maxHeight * imgWidth) / imgHeight);
5241		  slide.height = maxHeight;
5242		}
5243	  },
5244
5245	  // Create iframe wrapper, iframe and bindings
5246	  // ==========================================
5247
5248	  setIframe: function (slide) {
5249		var self = this,
5250		  opts = slide.opts.iframe,
5251		  $slide = slide.$slide,
5252		  $iframe;
5253
5254		slide.$content = $('<div class="fancybox-content' + (opts.preload ? " fancybox-is-hidden" : "") + '"></div>')
5255		  .css(opts.css)
5256		  .appendTo($slide);
5257
5258		$slide.addClass("fancybox-slide--" + slide.contentType);
5259
5260		slide.$iframe = $iframe = $(opts.tpl.replace(/\{rnd\}/g, new Date().getTime()))
5261		  .attr(opts.attr)
5262		  .appendTo(slide.$content);
5263
5264		if (opts.preload) {
5265		  self.showLoading(slide);
5266
5267		  // Unfortunately, it is not always possible to determine if iframe is successfully loaded
5268		  // (due to browser security policy)
5269
5270		  $iframe.on("load.fb error.fb", function (e) {
5271			this.isReady = 1;
5272
5273			slide.$slide.trigger("refresh");
5274
5275			self.afterLoad(slide);
5276		  });
5277
5278		  // Recalculate iframe content size
5279		  // ===============================
5280
5281		  $slide.on("refresh.fb", function () {
5282			var $content = slide.$content,
5283			  frameWidth = opts.css.width,
5284			  frameHeight = opts.css.height,
5285			  $contents,
5286			  $body;
5287
5288			if ($iframe[0].isReady !== 1) {
5289			  return;
5290			}
5291
5292			try {
5293			  $contents = $iframe.contents();
5294			  $body = $contents.find("body");
5295			} catch (ignore) {}
5296
5297			// Calculate content dimensions, if it is accessible
5298			if ($body && $body.length && $body.children().length) {
5299			  // Avoid scrolling to top (if multiple instances)
5300			  $slide.css("overflow", "visible");
5301
5302			  $content.css({
5303				width: "100%",
5304				"max-width": "100%",
5305				height: "9999px"
5306			  });
5307
5308			  if (frameWidth === undefined) {
5309				frameWidth = Math.ceil(Math.max($body[0].clientWidth, $body.outerWidth(true)));
5310			  }
5311
5312			  $content.css("width", frameWidth ? frameWidth : "").css("max-width", "");
5313
5314			  if (frameHeight === undefined) {
5315				frameHeight = Math.ceil(Math.max($body[0].clientHeight, $body.outerHeight(true)));
5316			  }
5317
5318			  $content.css("height", frameHeight ? frameHeight : "");
5319
5320			  $slide.css("overflow", "auto");
5321			}
5322
5323			$content.removeClass("fancybox-is-hidden");
5324		  });
5325		} else {
5326		  self.afterLoad(slide);
5327		}
5328
5329		$iframe.attr("src", slide.src);
5330
5331		// Remove iframe if closing or changing gallery item
5332		$slide.one("onReset", function () {
5333		  // This helps IE not to throw errors when closing
5334		  try {
5335			$(this)
5336			  .find("iframe")
5337			  .hide()
5338			  .unbind()
5339			  .attr("src", "//about:blank");
5340		  } catch (ignore) {}
5341
5342		  $(this)
5343			.off("refresh.fb")
5344			.empty();
5345
5346		  slide.isLoaded = false;
5347		  slide.isRevealed = false;
5348		});
5349	  },
5350
5351	  // Wrap and append content to the slide
5352	  // ======================================
5353
5354	  setContent: function (slide, content) {
5355		var self = this;
5356
5357		if (self.isClosing) {
5358		  return;
5359		}
5360
5361		self.hideLoading(slide);
5362
5363		if (slide.$content) {
5364		  $.fancybox.stop(slide.$content);
5365		}
5366
5367		slide.$slide.empty();
5368
5369		// If content is a jQuery object, then it will be moved to the slide.
5370		// The placeholder is created so we will know where to put it back.
5371		if (isQuery(content) && content.parent().length) {
5372		  // Make sure content is not already moved to fancyBox
5373		  if (content.hasClass("fancybox-content") || content.parent().hasClass("fancybox-content")) {
5374			content.parents(".fancybox-slide").trigger("onReset");
5375		  }
5376
5377		  // Create temporary element marking original place of the content
5378		  slide.$placeholder = $("<div>")
5379			.hide()
5380			.insertAfter(content);
5381
5382		  // Make sure content is visible
5383		  content.css("display", "inline-block");
5384		} else if (!slide.hasError) {
5385		  // If content is just a plain text, try to convert it to html
5386		  if ($.type(content) === "string") {
5387			content = $("<div>")
5388			  .append($.trim(content))
5389			  .contents();
5390		  }
5391
5392		  // If "filter" option is provided, then filter content
5393		  if (slide.opts.filter) {
5394			content = $("<div>")
5395			  .html(content)
5396			  .find(slide.opts.filter);
5397		  }
5398		}
5399
5400		slide.$slide.one("onReset", function () {
5401		  // Pause all html5 video/audio
5402		  $(this)
5403			.find("video,audio")
5404			.trigger("pause");
5405
5406		  // Put content back
5407		  if (slide.$placeholder) {
5408			slide.$placeholder.after(content.removeClass("fancybox-content").hide()).remove();
5409
5410			slide.$placeholder = null;
5411		  }
5412
5413		  // Remove custom close button
5414		  if (slide.$smallBtn) {
5415			slide.$smallBtn.remove();
5416
5417			slide.$smallBtn = null;
5418		  }
5419
5420		  // Remove content and mark slide as not loaded
5421		  if (!slide.hasError) {
5422			$(this).empty();
5423
5424			slide.isLoaded = false;
5425			slide.isRevealed = false;
5426		  }
5427		});
5428
5429		$(content).appendTo(slide.$slide);
5430
5431		if ($(content).is("video,audio")) {
5432		  $(content).addClass("fancybox-video");
5433
5434		  $(content).wrap("<div></div>");
5435
5436		  slide.contentType = "video";
5437
5438		  slide.opts.width = slide.opts.width || $(content).attr("width");
5439		  slide.opts.height = slide.opts.height || $(content).attr("height");
5440		}
5441
5442		slide.$content = slide.$slide
5443		  .children()
5444		  .filter("div,form,main,video,audio,article,.fancybox-content")
5445		  .first();
5446
5447		slide.$content.siblings().hide();
5448
5449		// Re-check if there is a valid content
5450		// (in some cases, ajax response can contain various elements or plain text)
5451		if (!slide.$content.length) {
5452		  slide.$content = slide.$slide
5453			.wrapInner("<div></div>")
5454			.children()
5455			.first();
5456		}
5457
5458		slide.$content.addClass("fancybox-content");
5459
5460		slide.$slide.addClass("fancybox-slide--" + slide.contentType);
5461
5462		self.afterLoad(slide);
5463	  },
5464
5465	  // Display error message
5466	  // =====================
5467
5468	  setError: function (slide) {
5469		slide.hasError = true;
5470
5471		slide.$slide
5472		  .trigger("onReset")
5473		  .removeClass("fancybox-slide--" + slide.contentType)
5474		  .addClass("fancybox-slide--error");
5475
5476		slide.contentType = "html";
5477
5478		this.setContent(slide, this.translate(slide, slide.opts.errorTpl));
5479
5480		if (slide.pos === this.currPos) {
5481		  this.isAnimating = false;
5482		}
5483	  },
5484
5485	  // Show loading icon inside the slide
5486	  // ==================================
5487
5488	  showLoading: function (slide) {
5489		var self = this;
5490
5491		slide = slide || self.current;
5492
5493		if (slide && !slide.$spinner) {
5494		  slide.$spinner = $(self.translate(self, self.opts.spinnerTpl))
5495			.appendTo(slide.$slide)
5496			.hide()
5497			.fadeIn("fast");
5498		}
5499	  },
5500
5501	  // Remove loading icon from the slide
5502	  // ==================================
5503
5504	  hideLoading: function (slide) {
5505		var self = this;
5506
5507		slide = slide || self.current;
5508
5509		if (slide && slide.$spinner) {
5510		  slide.$spinner.stop().remove();
5511
5512		  delete slide.$spinner;
5513		}
5514	  },
5515
5516	  // Adjustments after slide content has been loaded
5517	  // ===============================================
5518
5519	  afterLoad: function (slide) {
5520		var self = this;
5521
5522		if (self.isClosing) {
5523		  return;
5524		}
5525
5526		slide.isLoading = false;
5527		slide.isLoaded = true;
5528
5529		self.trigger("afterLoad", slide);
5530
5531		self.hideLoading(slide);
5532
5533		// Add small close button
5534		if (slide.opts.smallBtn && (!slide.$smallBtn || !slide.$smallBtn.length)) {
5535		  slide.$smallBtn = $(self.translate(slide, slide.opts.btnTpl.smallBtn)).appendTo(slide.$content);
5536		}
5537
5538		// Disable right click
5539		if (slide.opts.protect && slide.$content && !slide.hasError) {
5540		  slide.$content.on("contextmenu.fb", function (e) {
5541			if (e.button == 2) {
5542			  e.preventDefault();
5543			}
5544
5545			return true;
5546		  });
5547
5548		  // Add fake element on top of the image
5549		  // This makes a bit harder for user to select image
5550		  if (slide.type === "image") {
5551			$('<div class="fancybox-spaceball"></div>').appendTo(slide.$content);
5552		  }
5553		}
5554
5555		self.adjustCaption(slide);
5556
5557		self.adjustLayout(slide);
5558
5559		if (slide.pos === self.currPos) {
5560		  self.updateCursor();
5561		}
5562
5563		self.revealContent(slide);
5564	  },
5565
5566	  // Prevent caption overlap,
5567	  // fix css inconsistency across browsers
5568	  // =====================================
5569
5570	  adjustCaption: function (slide) {
5571		var self = this,
5572		  current = slide || self.current,
5573		  caption = current.opts.caption,
5574		  preventOverlap = current.opts.preventCaptionOverlap,
5575		  $caption = self.$refs.caption,
5576		  $clone,
5577		  captionH = false;
5578
5579		$caption.toggleClass("fancybox-caption--separate", preventOverlap);
5580
5581		if (preventOverlap && caption && caption.length) {
5582		  if (current.pos !== self.currPos) {
5583			$clone = $caption.clone().appendTo($caption.parent());
5584
5585			$clone
5586			  .children()
5587			  .eq(0)
5588			  .empty()
5589			  .html(caption);
5590
5591			captionH = $clone.outerHeight(true);
5592
5593			$clone.empty().remove();
5594		  } else if (self.$caption) {
5595			captionH = self.$caption.outerHeight(true);
5596		  }
5597
5598		  current.$slide.css("padding-bottom", captionH || "");
5599		}
5600	  },
5601
5602	  // Simple hack to fix inconsistency across browsers, described here (affects Edge, too):
5603	  // https://bugzilla.mozilla.org/show_bug.cgi?id=748518
5604	  // ====================================================================================
5605
5606	  adjustLayout: function (slide) {
5607		var self = this,
5608		  current = slide || self.current,
5609		  scrollHeight,
5610		  marginBottom,
5611		  inlinePadding,
5612		  actualPadding;
5613
5614		if (current.isLoaded && current.opts.disableLayoutFix !== true) {
5615		  current.$content.css("margin-bottom", "");
5616
5617		  // If we would always set margin-bottom for the content,
5618		  // then it would potentially break vertical align
5619		  if (current.$content.outerHeight() > current.$slide.height() + 0.5) {
5620			inlinePadding = current.$slide[0].style["padding-bottom"];
5621			actualPadding = current.$slide.css("padding-bottom");
5622
5623			if (parseFloat(actualPadding) > 0) {
5624			  scrollHeight = current.$slide[0].scrollHeight;
5625
5626			  current.$slide.css("padding-bottom", 0);
5627
5628			  if (Math.abs(scrollHeight - current.$slide[0].scrollHeight) < 1) {
5629				marginBottom = actualPadding;
5630			  }
5631
5632			  current.$slide.css("padding-bottom", inlinePadding);
5633			}
5634		  }
5635
5636		  current.$content.css("margin-bottom", marginBottom);
5637		}
5638	  },
5639
5640	  // Make content visible
5641	  // This method is called right after content has been loaded or
5642	  // user navigates gallery and transition should start
5643	  // ============================================================
5644
5645	  revealContent: function (slide) {
5646		var self = this,
5647		  $slide = slide.$slide,
5648		  end = false,
5649		  start = false,
5650		  isMoved = self.isMoved(slide),
5651		  isRevealed = slide.isRevealed,
5652		  effect,
5653		  effectClassName,
5654		  duration,
5655		  opacity;
5656
5657		slide.isRevealed = true;
5658
5659		effect = slide.opts[self.firstRun ? "animationEffect" : "transitionEffect"];
5660		duration = slide.opts[self.firstRun ? "animationDuration" : "transitionDuration"];
5661
5662		duration = parseInt(slide.forcedDuration === undefined ? duration : slide.forcedDuration, 10);
5663
5664		if (isMoved || slide.pos !== self.currPos || !duration) {
5665		  effect = false;
5666		}
5667
5668		// Check if can zoom
5669		if (effect === "zoom") {
5670		  if (slide.pos === self.currPos && duration && slide.type === "image" && !slide.hasError && (start = self.getThumbPos(slide))) {
5671			end = self.getFitPos(slide);
5672		  } else {
5673			effect = "fade";
5674		  }
5675		}
5676
5677		// Zoom animation
5678		// ==============
5679		if (effect === "zoom") {
5680		  self.isAnimating = true;
5681
5682		  end.scaleX = end.width / start.width;
5683		  end.scaleY = end.height / start.height;
5684
5685		  // Check if we need to animate opacity
5686		  opacity = slide.opts.zoomOpacity;
5687
5688		  if (opacity == "auto") {
5689			opacity = Math.abs(slide.width / slide.height - start.width / start.height) > 0.1;
5690		  }
5691
5692		  if (opacity) {
5693			start.opacity = 0.1;
5694			end.opacity = 1;
5695		  }
5696
5697		  // Draw image at start position
5698		  $.fancybox.setTranslate(slide.$content.removeClass("fancybox-is-hidden"), start);
5699
5700		  forceRedraw(slide.$content);
5701
5702		  // Start animation
5703		  $.fancybox.animate(slide.$content, end, duration, function () {
5704			self.isAnimating = false;
5705
5706			self.complete();
5707		  });
5708
5709		  return;
5710		}
5711
5712		self.updateSlide(slide);
5713
5714		// Simply show content if no effect
5715		// ================================
5716		if (!effect) {
5717		  slide.$content.removeClass("fancybox-is-hidden");
5718
5719		  if (!isRevealed && isMoved && slide.type === "image" && !slide.hasError) {
5720			slide.$content.hide().fadeIn("fast");
5721		  }
5722
5723		  if (slide.pos === self.currPos) {
5724			self.complete();
5725		  }
5726
5727		  return;
5728		}
5729
5730		// Prepare for CSS transiton
5731		// =========================
5732		$.fancybox.stop($slide);
5733
5734		//effectClassName = "fancybox-animated fancybox-slide--" + (slide.pos >= self.prevPos ? "next" : "previous") + " fancybox-fx-" + effect;
5735		effectClassName = "fancybox-slide--" + (slide.pos >= self.prevPos ? "next" : "previous") + " fancybox-animated fancybox-fx-" + effect;
5736
5737		$slide.addClass(effectClassName).removeClass("fancybox-slide--current"); //.addClass(effectClassName);
5738
5739		slide.$content.removeClass("fancybox-is-hidden");
5740
5741		// Force reflow
5742		forceRedraw($slide);
5743
5744		if (slide.type !== "image") {
5745		  slide.$content.hide().show(0);
5746		}
5747
5748		$.fancybox.animate(
5749		  $slide,
5750		  "fancybox-slide--current",
5751		  duration,
5752		  function () {
5753			$slide.removeClass(effectClassName).css({
5754			  transform: "",
5755			  opacity: ""
5756			});
5757
5758			if (slide.pos === self.currPos) {
5759			  self.complete();
5760			}
5761		  },
5762		  true
5763		);
5764	  },
5765
5766	  // Check if we can and have to zoom from thumbnail
5767	  //================================================
5768
5769	  getThumbPos: function (slide) {
5770		var rez = false,
5771		  $thumb = slide.$thumb,
5772		  thumbPos,
5773		  btw,
5774		  brw,
5775		  bbw,
5776		  blw;
5777
5778		if (!$thumb || !inViewport($thumb[0])) {
5779		  return false;
5780		}
5781
5782		thumbPos = $.fancybox.getTranslate($thumb);
5783
5784		btw = parseFloat($thumb.css("border-top-width") || 0);
5785		brw = parseFloat($thumb.css("border-right-width") || 0);
5786		bbw = parseFloat($thumb.css("border-bottom-width") || 0);
5787		blw = parseFloat($thumb.css("border-left-width") || 0);
5788
5789		rez = {
5790		  top: thumbPos.top + btw,
5791		  left: thumbPos.left + blw,
5792		  width: thumbPos.width - brw - blw,
5793		  height: thumbPos.height - btw - bbw,
5794		  scaleX: 1,
5795		  scaleY: 1
5796		};
5797
5798		return thumbPos.width > 0 && thumbPos.height > 0 ? rez : false;
5799	  },
5800
5801	  // Final adjustments after current gallery item is moved to position
5802	  // and it`s content is loaded
5803	  // ==================================================================
5804
5805	  complete: function () {
5806		var self = this,
5807		  current = self.current,
5808		  slides = {},
5809		  $el;
5810
5811		if (self.isMoved() || !current.isLoaded) {
5812		  return;
5813		}
5814
5815		if (!current.isComplete) {
5816		  current.isComplete = true;
5817
5818		  current.$slide.siblings().trigger("onReset");
5819
5820		  self.preload("inline");
5821
5822		  // Trigger any CSS transiton inside the slide
5823		  forceRedraw(current.$slide);
5824
5825		  current.$slide.addClass("fancybox-slide--complete");
5826
5827		  // Remove unnecessary slides
5828		  $.each(self.slides, function (key, slide) {
5829			if (slide.pos >= self.currPos - 1 && slide.pos <= self.currPos + 1) {
5830			  slides[slide.pos] = slide;
5831			} else if (slide) {
5832			  $.fancybox.stop(slide.$slide);
5833
5834			  slide.$slide.off().remove();
5835			}
5836		  });
5837
5838		  self.slides = slides;
5839		}
5840
5841		self.isAnimating = false;
5842
5843		self.updateCursor();
5844
5845		self.trigger("afterShow");
5846
5847		// Autoplay first html5 video/audio
5848		if (!!current.opts.video.autoStart) {
5849		  current.$slide
5850			.find("video,audio")
5851			.filter(":visible:first")
5852			.trigger("play")
5853			.one("ended", function () {
5854			  if (Document.exitFullscreen) {
5855				Document.exitFullscreen();
5856			  } else if (this.webkitExitFullscreen) {
5857				this.webkitExitFullscreen();
5858			  }
5859
5860			  self.next();
5861			});
5862		}
5863
5864		// Try to focus on the first focusable element
5865		if (current.opts.autoFocus && current.contentType === "html") {
5866		  // Look for the first input with autofocus attribute
5867		  $el = current.$content.find("input[autofocus]:enabled:visible:first");
5868
5869		  if ($el.length) {
5870			$el.trigger("focus");
5871		  } else {
5872			self.focus(null, true);
5873		  }
5874		}
5875
5876		// Avoid jumping
5877		current.$slide.scrollTop(0).scrollLeft(0);
5878	  },
5879
5880	  // Preload next and previous slides
5881	  // ================================
5882
5883	  preload: function (type) {
5884		var self = this,
5885		  prev,
5886		  next;
5887
5888		if (self.group.length < 2) {
5889		  return;
5890		}
5891
5892		next = self.slides[self.currPos + 1];
5893		prev = self.slides[self.currPos - 1];
5894
5895		if (prev && prev.type === type) {
5896		  self.loadSlide(prev);
5897		}
5898
5899		if (next && next.type === type) {
5900		  self.loadSlide(next);
5901		}
5902	  },
5903
5904	  // Try to find and focus on the first focusable element
5905	  // ====================================================
5906
5907	  focus: function (e, firstRun) {
5908		var self = this,
5909		  focusableStr = [
5910			"a[href]",
5911			"area[href]",
5912			'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',
5913			"select:not([disabled]):not([aria-hidden])",
5914			"textarea:not([disabled]):not([aria-hidden])",
5915			"button:not([disabled]):not([aria-hidden])",
5916			"iframe",
5917			"object",
5918			"embed",
5919			"video",
5920			"audio",
5921			"[contenteditable]",
5922			'[tabindex]:not([tabindex^="-"])'
5923		  ].join(","),
5924		  focusableItems,
5925		  focusedItemIndex;
5926
5927		if (self.isClosing) {
5928		  return;
5929		}
5930
5931		if (e || !self.current || !self.current.isComplete) {
5932		  // Focus on any element inside fancybox
5933		  focusableItems = self.$refs.container.find("*:visible");
5934		} else {
5935		  // Focus inside current slide
5936		  focusableItems = self.current.$slide.find("*:visible" + (firstRun ? ":not(.fancybox-close-small)" : ""));
5937		}
5938
5939		focusableItems = focusableItems.filter(focusableStr).filter(function () {
5940		  return $(this).css("visibility") !== "hidden" && !$(this).hasClass("disabled");
5941		});
5942
5943		if (focusableItems.length) {
5944		  focusedItemIndex = focusableItems.index(document.activeElement);
5945
5946		  if (e && e.shiftKey) {
5947			// Back tab
5948			if (focusedItemIndex < 0 || focusedItemIndex == 0) {
5949			  e.preventDefault();
5950
5951			  focusableItems.eq(focusableItems.length - 1).trigger("focus");
5952			}
5953		  } else {
5954			// Outside or Forward tab
5955			if (focusedItemIndex < 0 || focusedItemIndex == focusableItems.length - 1) {
5956			  if (e) {
5957				e.preventDefault();
5958			  }
5959
5960			  focusableItems.eq(0).trigger("focus");
5961			}
5962		  }
5963		} else {
5964		  self.$refs.container.trigger("focus");
5965		}
5966	  },
5967
5968	  // Activates current instance - brings container to the front and enables keyboard,
5969	  // notifies other instances about deactivating
5970	  // =================================================================================
5971
5972	  activate: function () {
5973		var self = this;
5974
5975		// Deactivate all instances
5976		$(".fancybox-container").each(function () {
5977		  var instance = $(this).data("FancyBox");
5978
5979		  // Skip self and closing instances
5980		  if (instance && instance.id !== self.id && !instance.isClosing) {
5981			instance.trigger("onDeactivate");
5982
5983			instance.removeEvents();
5984
5985			instance.isVisible = false;
5986		  }
5987		});
5988
5989		self.isVisible = true;
5990
5991		if (self.current || self.isIdle) {
5992		  self.update();
5993
5994		  self.updateControls();
5995		}
5996
5997		self.trigger("onActivate");
5998
5999		self.addEvents();
6000	  },
6001
6002	  // Start closing procedure
6003	  // This will start "zoom-out" animation if needed and clean everything up afterwards
6004	  // =================================================================================
6005
6006	  close: function (e, d) {
6007		var self = this,
6008		  current = self.current,
6009		  effect,
6010		  duration,
6011		  $content,
6012		  domRect,
6013		  opacity,
6014		  start,
6015		  end;
6016
6017		var done = function () {
6018		  self.cleanUp(e);
6019		};
6020
6021		if (self.isClosing) {
6022		  return false;
6023		}
6024
6025		self.isClosing = true;
6026
6027		// If beforeClose callback prevents closing, make sure content is centered
6028		if (self.trigger("beforeClose", e) === false) {
6029		  self.isClosing = false;
6030
6031		  requestAFrame(function () {
6032			self.update();
6033		  });
6034
6035		  return false;
6036		}
6037
6038		// Remove all events
6039		// If there are multiple instances, they will be set again by "activate" method
6040		self.removeEvents();
6041
6042		$content = current.$content;
6043		effect = current.opts.animationEffect;
6044		duration = $.isNumeric(d) ? d : effect ? current.opts.animationDuration : 0;
6045
6046		current.$slide.removeClass("fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated");
6047
6048		if (e !== true) {
6049		  $.fancybox.stop(current.$slide);
6050		} else {
6051		  effect = false;
6052		}
6053
6054		// Remove other slides
6055		current.$slide
6056		  .siblings()
6057		  .trigger("onReset")
6058		  .remove();
6059
6060		// Trigger animations
6061		if (duration) {
6062		  self.$refs.container
6063			.removeClass("fancybox-is-open")
6064			.addClass("fancybox-is-closing")
6065			.css("transition-duration", duration + "ms");
6066		}
6067
6068		// Clean up
6069		self.hideLoading(current);
6070
6071		self.hideControls(true);
6072
6073		self.updateCursor();
6074
6075		// Check if possible to zoom-out
6076		if (
6077		  effect === "zoom" &&
6078		  !($content && duration && current.type === "image" && !self.isMoved() && !current.hasError && (end = self.getThumbPos(current)))
6079		) {
6080		  effect = "fade";
6081		}
6082
6083		if (effect === "zoom") {
6084		  $.fancybox.stop($content);
6085
6086		  domRect = $.fancybox.getTranslate($content);
6087
6088		  start = {
6089			top: domRect.top,
6090			left: domRect.left,
6091			scaleX: domRect.width / end.width,
6092			scaleY: domRect.height / end.height,
6093			width: end.width,
6094			height: end.height
6095		  };
6096
6097		  // Check if we need to animate opacity
6098		  opacity = current.opts.zoomOpacity;
6099
6100		  if (opacity == "auto") {
6101			opacity = Math.abs(current.width / current.height - end.width / end.height) > 0.1;
6102		  }
6103
6104		  if (opacity) {
6105			end.opacity = 0;
6106		  }
6107
6108		  $.fancybox.setTranslate($content, start);
6109
6110		  forceRedraw($content);
6111
6112		  $.fancybox.animate($content, end, duration, done);
6113
6114		  return true;
6115		}
6116
6117		if (effect && duration) {
6118		  $.fancybox.animate(
6119			current.$slide.addClass("fancybox-slide--previous").removeClass("fancybox-slide--current"),
6120			"fancybox-animated fancybox-fx-" + effect,
6121			duration,
6122			done
6123		  );
6124		} else {
6125		  // If skip animation
6126		  if (e === true) {
6127			setTimeout(done, duration);
6128		  } else {
6129			done();
6130		  }
6131		}
6132
6133		return true;
6134	  },
6135
6136	  // Final adjustments after removing the instance
6137	  // =============================================
6138
6139	  cleanUp: function (e) {
6140		var self = this,
6141		  instance,
6142		  $focus = self.current.opts.$orig,
6143		  x,
6144		  y;
6145
6146		self.current.$slide.trigger("onReset");
6147
6148		self.$refs.container.empty().remove();
6149
6150		self.trigger("afterClose", e);
6151
6152		// Place back focus
6153		if (!!self.current.opts.backFocus) {
6154		  if (!$focus || !$focus.length || !$focus.is(":visible")) {
6155			$focus = self.$trigger;
6156		  }
6157
6158		  if ($focus && $focus.length) {
6159			x = window.scrollX;
6160			y = window.scrollY;
6161
6162			$focus.trigger("focus");
6163
6164			$("html, body")
6165			  .scrollTop(y)
6166			  .scrollLeft(x);
6167		  }
6168		}
6169
6170		self.current = null;
6171
6172		// Check if there are other instances
6173		instance = $.fancybox.getInstance();
6174
6175		if (instance) {
6176		  instance.activate();
6177		} else {
6178		  $("body").removeClass("fancybox-active compensate-for-scrollbar");
6179
6180		  $("#fancybox-style-noscroll").remove();
6181		}
6182	  },
6183
6184	  // Call callback and trigger an event
6185	  // ==================================
6186
6187	  trigger: function (name, slide) {
6188		var args = Array.prototype.slice.call(arguments, 1),
6189		  self = this,
6190		  obj = slide && slide.opts ? slide : self.current,
6191		  rez;
6192
6193		if (obj) {
6194		  args.unshift(obj);
6195		} else {
6196		  obj = self;
6197		}
6198
6199		args.unshift(self);
6200
6201		if ($.isFunction(obj.opts[name])) {
6202		  rez = obj.opts[name].apply(obj, args);
6203		}
6204
6205		if (rez === false) {
6206		  return rez;
6207		}
6208
6209		if (name === "afterClose" || !self.$refs) {
6210		  $D.trigger(name + ".fb", args);
6211		} else {
6212		  self.$refs.container.trigger(name + ".fb", args);
6213		}
6214	  },
6215
6216	  // Update infobar values, navigation button states and reveal caption
6217	  // ==================================================================
6218
6219	  updateControls: function () {
6220		var self = this,
6221		  current = self.current,
6222		  index = current.index,
6223		  $container = self.$refs.container,
6224		  $caption = self.$refs.caption,
6225		  caption = current.opts.caption;
6226
6227		// Recalculate content dimensions
6228		current.$slide.trigger("refresh");
6229
6230		// Set caption
6231		if (caption && caption.length) {
6232		  self.$caption = $caption;
6233
6234		  $caption
6235			.children()
6236			.eq(0)
6237			.html(caption);
6238		} else {
6239		  self.$caption = null;
6240		}
6241
6242		if (!self.hasHiddenControls && !self.isIdle) {
6243		  self.showControls();
6244		}
6245
6246		// Update info and navigation elements
6247		$container.find("[data-fancybox-count]").html(self.group.length);
6248		$container.find("[data-fancybox-index]").html(index + 1);
6249
6250		$container.find("[data-fancybox-prev]").prop("disabled", !current.opts.loop && index <= 0);
6251		$container.find("[data-fancybox-next]").prop("disabled", !current.opts.loop && index >= self.group.length - 1);
6252
6253		if (current.type === "image") {
6254		  // Re-enable buttons; update download button source
6255		  $container
6256			.find("[data-fancybox-zoom]")
6257			.show()
6258			.end()
6259			.find("[data-fancybox-download]")
6260			.attr("href", current.opts.image.src || current.src)
6261			.show();
6262		} else if (current.opts.toolbar) {
6263		  $container.find("[data-fancybox-download],[data-fancybox-zoom]").hide();
6264		}
6265
6266		// Make sure focus is not on disabled button/element
6267		if ($(document.activeElement).is(":hidden,[disabled]")) {
6268		  self.$refs.container.trigger("focus");
6269		}
6270	  },
6271
6272	  // Hide toolbar and caption
6273	  // ========================
6274
6275	  hideControls: function (andCaption) {
6276		var self = this,
6277		  arr = ["infobar", "toolbar", "nav"];
6278
6279		if (andCaption || !self.current.opts.preventCaptionOverlap) {
6280		  arr.push("caption");
6281		}
6282
6283		this.$refs.container.removeClass(
6284		  arr
6285		  .map(function (i) {
6286			return "fancybox-show-" + i;
6287		  })
6288		  .join(" ")
6289		);
6290
6291		this.hasHiddenControls = true;
6292	  },
6293
6294	  showControls: function () {
6295		var self = this,
6296		  opts = self.current ? self.current.opts : self.opts,
6297		  $container = self.$refs.container;
6298
6299		self.hasHiddenControls = false;
6300		self.idleSecondsCounter = 0;
6301
6302		$container
6303		  .toggleClass("fancybox-show-toolbar", !!(opts.toolbar && opts.buttons))
6304		  .toggleClass("fancybox-show-infobar", !!(opts.infobar && self.group.length > 1))
6305		  .toggleClass("fancybox-show-caption", !!self.$caption)
6306		  .toggleClass("fancybox-show-nav", !!(opts.arrows && self.group.length > 1))
6307		  .toggleClass("fancybox-is-modal", !!opts.modal);
6308	  },
6309
6310	  // Toggle toolbar and caption
6311	  // ==========================
6312
6313	  toggleControls: function () {
6314		if (this.hasHiddenControls) {
6315		  this.showControls();
6316		} else {
6317		  this.hideControls();
6318		}
6319	  }
6320	});
6321
6322	$.fancybox = {
6323	  version: "3.5.7",
6324	  defaults: defaults,
6325
6326	  // Get current instance and execute a command.
6327	  //
6328	  // Examples of usage:
6329	  //
6330	  //   $instance = $.fancybox.getInstance();
6331	  //   $.fancybox.getInstance().jumpTo( 1 );
6332	  //   $.fancybox.getInstance( 'jumpTo', 1 );
6333	  //   $.fancybox.getInstance( function() {
6334	  //       console.info( this.currIndex );
6335	  //   });
6336	  // ======================================================
6337
6338	  getInstance: function (command) {
6339		var instance = $('.fancybox-container:not(".fancybox-is-closing"):last').data("FancyBox"),
6340		  args = Array.prototype.slice.call(arguments, 1);
6341
6342		if (instance instanceof FancyBox) {
6343		  if ($.type(command) === "string") {
6344			instance[command].apply(instance, args);
6345		  } else if ($.type(command) === "function") {
6346			command.apply(instance, args);
6347		  }
6348
6349		  return instance;
6350		}
6351
6352		return false;
6353	  },
6354
6355	  // Create new instance
6356	  // ===================
6357
6358	  open: function (items, opts, index) {
6359		return new FancyBox(items, opts, index);
6360	  },
6361
6362	  // Close current or all instances
6363	  // ==============================
6364
6365	  close: function (all) {
6366		var instance = this.getInstance();
6367
6368		if (instance) {
6369		  instance.close();
6370
6371		  // Try to find and close next instance
6372		  if (all === true) {
6373			this.close(all);
6374		  }
6375		}
6376	  },
6377
6378	  // Close all instances and unbind all events
6379	  // =========================================
6380
6381	  destroy: function () {
6382		this.close(true);
6383
6384		$D.add("body").off("click.fb-start", "**");
6385	  },
6386
6387	  // Try to detect mobile devices
6388	  // ============================
6389
6390	  isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
6391
6392	  // Detect if 'translate3d' support is available
6393	  // ============================================
6394
6395	  use3d: (function () {
6396		var div = document.createElement("div");
6397
6398		return (
6399		  window.getComputedStyle &&
6400		  window.getComputedStyle(div) &&
6401		  window.getComputedStyle(div).getPropertyValue("transform") &&
6402		  !(document.documentMode && document.documentMode < 11)
6403		);
6404	  })(),
6405
6406	  // Helper function to get current visual state of an element
6407	  // returns array[ top, left, horizontal-scale, vertical-scale, opacity ]
6408	  // =====================================================================
6409
6410	  getTranslate: function ($el) {
6411		var domRect;
6412
6413		if (!$el || !$el.length) {
6414		  return false;
6415		}
6416
6417		domRect = $el[0].getBoundingClientRect();
6418
6419		return {
6420		  top: domRect.top || 0,
6421		  left: domRect.left || 0,
6422		  width: domRect.width,
6423		  height: domRect.height,
6424		  opacity: parseFloat($el.css("opacity"))
6425		};
6426	  },
6427
6428	  // Shortcut for setting "translate3d" properties for element
6429	  // Can set be used to set opacity, too
6430	  // ========================================================
6431
6432	  setTranslate: function ($el, props) {
6433		var str = "",
6434		  css = {};
6435
6436		if (!$el || !props) {
6437		  return;
6438		}
6439
6440		if (props.left !== undefined || props.top !== undefined) {
6441		  str =
6442			(props.left === undefined ? $el.position().left : props.left) +
6443			"px, " +
6444			(props.top === undefined ? $el.position().top : props.top) +
6445			"px";
6446
6447		  if (this.use3d) {
6448			str = "translate3d(" + str + ", 0px)";
6449		  } else {
6450			str = "translate(" + str + ")";
6451		  }
6452		}
6453
6454		if (props.scaleX !== undefined && props.scaleY !== undefined) {
6455		  str += " scale(" + props.scaleX + ", " + props.scaleY + ")";
6456		} else if (props.scaleX !== undefined) {
6457		  str += " scaleX(" + props.scaleX + ")";
6458		}
6459
6460		if (str.length) {
6461		  css.transform = str;
6462		}
6463
6464		if (props.opacity !== undefined) {
6465		  css.opacity = props.opacity;
6466		}
6467
6468		if (props.width !== undefined) {
6469		  css.width = props.width;
6470		}
6471
6472		if (props.height !== undefined) {
6473		  css.height = props.height;
6474		}
6475
6476		return $el.css(css);
6477	  },
6478
6479	  // Simple CSS transition handler
6480	  // =============================
6481
6482	  animate: function ($el, to, duration, callback, leaveAnimationName) {
6483		var self = this,
6484		  from;
6485
6486		if ($.isFunction(duration)) {
6487		  callback = duration;
6488		  duration = null;
6489		}
6490
6491		self.stop($el);
6492
6493		from = self.getTranslate($el);
6494
6495		$el.on(transitionEnd, function (e) {
6496		  // Skip events from child elements and z-index change
6497		  if (e && e.originalEvent && (!$el.is(e.originalEvent.target) || e.originalEvent.propertyName == "z-index")) {
6498			return;
6499		  }
6500
6501		  self.stop($el);
6502
6503		  if ($.isNumeric(duration)) {
6504			$el.css("transition-duration", "");
6505		  }
6506
6507		  if ($.isPlainObject(to)) {
6508			if (to.scaleX !== undefined && to.scaleY !== undefined) {
6509			  self.setTranslate($el, {
6510				top: to.top,
6511				left: to.left,
6512				width: from.width * to.scaleX,
6513				height: from.height * to.scaleY,
6514				scaleX: 1,
6515				scaleY: 1
6516			  });
6517			}
6518		  } else if (leaveAnimationName !== true) {
6519			$el.removeClass(to);
6520		  }
6521
6522		  if ($.isFunction(callback)) {
6523			callback(e);
6524		  }
6525		});
6526
6527		if ($.isNumeric(duration)) {
6528		  $el.css("transition-duration", duration + "ms");
6529		}
6530
6531		// Start animation by changing CSS properties or class name
6532		if ($.isPlainObject(to)) {
6533		  if (to.scaleX !== undefined && to.scaleY !== undefined) {
6534			delete to.width;
6535			delete to.height;
6536
6537			if ($el.parent().hasClass("fancybox-slide--image")) {
6538			  $el.parent().addClass("fancybox-is-scaling");
6539			}
6540		  }
6541
6542		  $.fancybox.setTranslate($el, to);
6543		} else {
6544		  $el.addClass(to);
6545		}
6546
6547		// Make sure that `transitionend` callback gets fired
6548		$el.data(
6549		  "timer",
6550		  setTimeout(function () {
6551			$el.trigger(transitionEnd);
6552		  }, duration + 33)
6553		);
6554	  },
6555
6556	  stop: function ($el, callCallback) {
6557		if ($el && $el.length) {
6558		  clearTimeout($el.data("timer"));
6559
6560		  if (callCallback) {
6561			$el.trigger(transitionEnd);
6562		  }
6563
6564		  $el.off(transitionEnd).css("transition-duration", "");
6565
6566		  $el.parent().removeClass("fancybox-is-scaling");
6567		}
6568	  }
6569	};
6570
6571	// Default click handler for "fancyboxed" links
6572	// ============================================
6573
6574	function _run(e, opts) {
6575	  var items = [],
6576		index = 0,
6577		$target,
6578		value,
6579		instance;
6580
6581	  // Avoid opening multiple times
6582	  if (e && e.isDefaultPrevented()) {
6583		return;
6584	  }
6585
6586	  e.preventDefault();
6587
6588	  opts = opts || {};
6589
6590	  if (e && e.data) {
6591		opts = mergeOpts(e.data.options, opts);
6592	  }
6593
6594	  $target = opts.$target || $(e.currentTarget).trigger("blur");
6595	  instance = $.fancybox.getInstance();
6596
6597	  if (instance && instance.$trigger && instance.$trigger.is($target)) {
6598		return;
6599	  }
6600
6601	  if (opts.selector) {
6602		items = $(opts.selector);
6603	  } else {
6604		// Get all related items and find index for clicked one
6605		value = $target.attr("data-fancybox") || "";
6606
6607		if (value) {
6608		  items = e.data ? e.data.items : [];
6609		  items = items.length ? items.filter('[data-fancybox="' + value + '"]') : $('[data-fancybox="' + value + '"]');
6610		} else {
6611		  items = [$target];
6612		}
6613	  }
6614
6615	  index = $(items).index($target);
6616
6617	  // Sometimes current item can not be found
6618	  if (index < 0) {
6619		index = 0;
6620	  }
6621
6622	  instance = $.fancybox.open(items, opts, index);
6623
6624	  // Save last active element
6625	  instance.$trigger = $target;
6626	}
6627
6628	// Create a jQuery plugin
6629	// ======================
6630
6631	$.fn.fancybox = function (options) {
6632	  var selector;
6633
6634	  options = options || {};
6635	  selector = options.selector || false;
6636
6637	  if (selector) {
6638		// Use body element instead of document so it executes first
6639		$("body")
6640		  .off("click.fb-start", selector)
6641		  .on("click.fb-start", selector, {
6642			options: options
6643		  }, _run);
6644	  } else {
6645		this.off("click.fb-start").on(
6646		  "click.fb-start", {
6647			items: this,
6648			options: options
6649		  },
6650		  _run
6651		);
6652	  }
6653
6654	  return this;
6655	};
6656
6657	// Self initializing plugin for all elements having `data-fancybox` attribute
6658	// ==========================================================================
6659
6660	$D.on("click.fb-start", "[data-fancybox]", _run);
6661
6662	// Enable "trigger elements"
6663	// =========================
6664
6665	$D.on("click.fb-start", "[data-fancybox-trigger]", function (e) {
6666	  $('[data-fancybox="' + $(this).attr("data-fancybox-trigger") + '"]')
6667		.eq($(this).attr("data-fancybox-index") || 0)
6668		.trigger("click.fb-start", {
6669		  $trigger: $(this)
6670		});
6671	});
6672
6673	// Track focus event for better accessibility styling
6674	// ==================================================
6675	(function () {
6676	  var buttonStr = ".fancybox-button",
6677		focusStr = "fancybox-focus",
6678		$pressed = null;
6679
6680	  $D.on("mousedown mouseup focus blur", buttonStr, function (e) {
6681		switch (e.type) {
6682		  case "mousedown":
6683			$pressed = $(this);
6684			break;
6685		  case "mouseup":
6686			$pressed = null;
6687			break;
6688		  case "focusin":
6689			$(buttonStr).removeClass(focusStr);
6690
6691			if (!$(this).is($pressed) && !$(this).is("[disabled]")) {
6692			  $(this).addClass(focusStr);
6693			}
6694			break;
6695		  case "focusout":
6696			$(buttonStr).removeClass(focusStr);
6697			break;
6698		}
6699	  });
6700	})();
6701  })(window, document, jQuery);
6702  // ==========================================================================
6703  //
6704  // Media
6705  // Adds additional media type support
6706  //
6707  // ==========================================================================
6708  (function ($) {
6709	"use strict";
6710
6711	// Object containing properties for each media type
6712	var defaults = {
6713	  youtube: {
6714		matcher: /(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,
6715		params: {
6716		  autoplay: 1,
6717		  autohide: 1,
6718		  fs: 1,
6719		  rel: 0,
6720		  hd: 1,
6721		  wmode: "transparent",
6722		  enablejsapi: 1,
6723		  html5: 1
6724		},
6725		paramPlace: 8,
6726		type: "iframe",
6727		url: "https://www.youtube-nocookie.com/embed/$4",
6728		thumb: "https://img.youtube.com/vi/$4/hqdefault.jpg"
6729	  },
6730
6731	  vimeo: {
6732		matcher: /^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,
6733		params: {
6734		  autoplay: 1,
6735		  hd: 1,
6736		  show_title: 1,
6737		  show_byline: 1,
6738		  show_portrait: 0,
6739		  fullscreen: 1
6740		},
6741		paramPlace: 3,
6742		type: "iframe",
6743		url: "//player.vimeo.com/video/$2"
6744	  },
6745
6746	  instagram: {
6747		matcher: /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
6748		type: "image",
6749		url: "//$1/p/$2/media/?size=l"
6750	  },
6751
6752	  // Examples:
6753	  // http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
6754	  // https://www.google.com/maps/@37.7852006,-122.4146355,14.65z
6755	  // https://www.google.com/maps/@52.2111123,2.9237542,6.61z?hl=en
6756	  // https://www.google.com/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572
6757	  gmap_place: {
6758		matcher: /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,
6759		type: "iframe",
6760		url: function (rez) {
6761		  return (
6762			"//maps.google." +
6763			rez[2] +
6764			"/?ll=" +
6765			(rez[9] ? rez[9] + "&z=" + Math.floor(rez[10]) + (rez[12] ? rez[12].replace(/^\//, "&") : "") : rez[12] + "").replace(/\?/, "&") +
6766			"&output=" +
6767			(rez[12] && rez[12].indexOf("layer=c") > 0 ? "svembed" : "embed")
6768		  );
6769		}
6770	  },
6771
6772	  // Examples:
6773	  // https://www.google.com/maps/search/Empire+State+Building/
6774	  // https://www.google.com/maps/search/?api=1&query=centurylink+field
6775	  // https://www.google.com/maps/search/?api=1&query=47.5951518,-122.3316393
6776	  gmap_search: {
6777		matcher: /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,
6778		type: "iframe",
6779		url: function (rez) {
6780		  return "//maps.google." + rez[2] + "/maps?q=" + rez[5].replace("query=", "q=").replace("api=1", "") + "&output=embed";
6781		}
6782	  }
6783	};
6784
6785	// Formats matching url to final form
6786	var format = function (url, rez, params) {
6787	  if (!url) {
6788		return;
6789	  }
6790
6791	  params = params || "";
6792
6793	  if ($.type(params) === "object") {
6794		params = $.param(params, true);
6795	  }
6796
6797	  $.each(rez, function (key, value) {
6798		url = url.replace("$" + key, value || "");
6799	  });
6800
6801	  if (params.length) {
6802		url += (url.indexOf("?") > 0 ? "&" : "?") + params;
6803	  }
6804
6805	  return url;
6806	};
6807
6808	$(document).on("objectNeedsType.fb", function (e, instance, item) {
6809	  var url = item.src || "",
6810		type = false,
6811		media,
6812		thumb,
6813		rez,
6814		params,
6815		urlParams,
6816		paramObj,
6817		provider;
6818
6819	  media = $.extend(true, {}, defaults, item.opts.media);
6820
6821	  // Look for any matching media type
6822	  $.each(media, function (providerName, providerOpts) {
6823		rez = url.match(providerOpts.matcher);
6824
6825		if (!rez) {
6826		  return;
6827		}
6828
6829		type = providerOpts.type;
6830		provider = providerName;
6831		paramObj = {};
6832
6833		if (providerOpts.paramPlace && rez[providerOpts.paramPlace]) {
6834		  urlParams = rez[providerOpts.paramPlace];
6835
6836		  if (urlParams[0] == "?") {
6837			urlParams = urlParams.substring(1);
6838		  }
6839
6840		  urlParams = urlParams.split("&");
6841
6842		  for (var m = 0; m < urlParams.length; ++m) {
6843			var p = urlParams[m].split("=", 2);
6844
6845			if (p.length == 2) {
6846			  paramObj[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
6847			}
6848		  }
6849		}
6850
6851		params = $.extend(true, {}, providerOpts.params, item.opts[providerName], paramObj);
6852
6853		url =
6854		  $.type(providerOpts.url) === "function" ? providerOpts.url.call(this, rez, params, item) : format(providerOpts.url, rez, params);
6855
6856		thumb =
6857		  $.type(providerOpts.thumb) === "function" ? providerOpts.thumb.call(this, rez, params, item) : format(providerOpts.thumb, rez);
6858
6859		if (providerName === "youtube") {
6860		  url = url.replace(/&t=((\d+)m)?(\d+)s/, function (match, p1, m, s) {
6861			return "&start=" + ((m ? parseInt(m, 10) * 60 : 0) + parseInt(s, 10));
6862		  });
6863		} else if (providerName === "vimeo") {
6864		  url = url.replace("&%23", "#");
6865		}
6866
6867		return false;
6868	  });
6869
6870	  // If it is found, then change content type and update the url
6871
6872	  if (type) {
6873		if (!item.opts.thumb && !(item.opts.$thumb && item.opts.$thumb.length)) {
6874		  item.opts.thumb = thumb;
6875		}
6876
6877		if (type === "iframe") {
6878		  item.opts = $.extend(true, item.opts, {
6879			iframe: {
6880			  preload: false,
6881			  attr: {
6882				scrolling: "no"
6883			  }
6884			}
6885		  });
6886		}
6887
6888		$.extend(item, {
6889		  type: type,
6890		  src: url,
6891		  origSrc: item.src,
6892		  contentSource: provider,
6893		  contentType: type === "image" ? "image" : provider == "gmap_place" || provider == "gmap_search" ? "map" : "video"
6894		});
6895	  } else if (url) {
6896		item.type = item.opts.defaultType;
6897	  }
6898	});
6899
6900	// Load YouTube/Video API on request to detect when video finished playing
6901	var VideoAPILoader = {
6902	  youtube: {
6903		src: "https://www.youtube.com/iframe_api",
6904		class: "YT",
6905		loading: false,
6906		loaded: false
6907	  },
6908
6909	  vimeo: {
6910		src: "https://player.vimeo.com/api/player.js",
6911		class: "Vimeo",
6912		loading: false,
6913		loaded: false
6914	  },
6915
6916	  load: function (vendor) {
6917		var _this = this,
6918		  script;
6919
6920		if (this[vendor].loaded) {
6921		  setTimeout(function () {
6922			_this.done(vendor);
6923		  });
6924		  return;
6925		}
6926
6927		if (this[vendor].loading) {
6928		  return;
6929		}
6930
6931		this[vendor].loading = true;
6932
6933		script = document.createElement("script");
6934		script.type = "text/javascript";
6935		script.src = this[vendor].src;
6936
6937		if (vendor === "youtube") {
6938		  window.onYouTubeIframeAPIReady = function () {
6939			_this[vendor].loaded = true;
6940			_this.done(vendor);
6941		  };
6942		} else {
6943		  script.onload = function () {
6944			_this[vendor].loaded = true;
6945			_this.done(vendor);
6946		  };
6947		}
6948
6949		document.body.appendChild(script);
6950	  },
6951	  done: function (vendor) {
6952		var instance, $el, player;
6953
6954		if (vendor === "youtube") {
6955		  delete window.onYouTubeIframeAPIReady;
6956		}
6957
6958		instance = $.fancybox.getInstance();
6959
6960		if (instance) {
6961		  $el = instance.current.$content.find("iframe");
6962
6963		  if (vendor === "youtube" && YT !== undefined && YT) {
6964			player = new YT.Player($el.attr("id"), {
6965			  events: {
6966				onStateChange: function (e) {
6967				  if (e.data == 0) {
6968					instance.next();
6969				  }
6970				}
6971			  }
6972			});
6973		  } else if (vendor === "vimeo" && Vimeo !== undefined && Vimeo) {
6974			player = new Vimeo.Player($el);
6975
6976			player.on("ended", function () {
6977			  instance.next();
6978			});
6979		  }
6980		}
6981	  }
6982	};
6983
6984	$(document).on({
6985	  "afterShow.fb": function (e, instance, current) {
6986		if (instance.group.length > 1 && (current.contentSource === "youtube" || current.contentSource === "vimeo")) {
6987		  VideoAPILoader.load(current.contentSource);
6988		}
6989	  }
6990	});
6991  })(jQuery);
6992  // ==========================================================================
6993  //
6994  // Guestures
6995  // Adds touch guestures, handles click and tap events
6996  //
6997  // ==========================================================================
6998  (function (window, document, $) {
6999	"use strict";
7000
7001	var requestAFrame = (function () {
7002	  return (
7003		window.requestAnimationFrame ||
7004		window.webkitRequestAnimationFrame ||
7005		window.mozRequestAnimationFrame ||
7006		window.oRequestAnimationFrame ||
7007		// if all else fails, use setTimeout
7008		function (callback) {
7009		  return window.setTimeout(callback, 1000 / 60);
7010		}
7011	  );
7012	})();
7013
7014	var cancelAFrame = (function () {
7015	  return (
7016		window.cancelAnimationFrame ||
7017		window.webkitCancelAnimationFrame ||
7018		window.mozCancelAnimationFrame ||
7019		window.oCancelAnimationFrame ||
7020		function (id) {
7021		  window.clearTimeout(id);
7022		}
7023	  );
7024	})();
7025
7026	var getPointerXY = function (e) {
7027	  var result = [];
7028
7029	  e = e.originalEvent || e || window.e;
7030	  e = e.touches && e.touches.length ? e.touches : e.changedTouches && e.changedTouches.length ? e.changedTouches : [e];
7031
7032	  for (var key in e) {
7033		if (e[key].pageX) {
7034		  result.push({
7035			x: e[key].pageX,
7036			y: e[key].pageY
7037		  });
7038		} else if (e[key].clientX) {
7039		  result.push({
7040			x: e[key].clientX,
7041			y: e[key].clientY
7042		  });
7043		}
7044	  }
7045
7046	  return result;
7047	};
7048
7049	var distance = function (point2, point1, what) {
7050	  if (!point1 || !point2) {
7051		return 0;
7052	  }
7053
7054	  if (what === "x") {
7055		return point2.x - point1.x;
7056	  } else if (what === "y") {
7057		return point2.y - point1.y;
7058	  }
7059
7060	  return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
7061	};
7062
7063	var isClickable = function ($el) {
7064	  if (
7065		$el.is('a,area,button,[role="button"],input,label,select,summary,textarea,video,audio,iframe') ||
7066		$.isFunction($el.get(0).onclick) ||
7067		$el.data("selectable")
7068	  ) {
7069		return true;
7070	  }
7071
7072	  // Check for attributes like data-fancybox-next or data-fancybox-close
7073	  for (var i = 0, atts = $el[0].attributes, n = atts.length; i < n; i++) {
7074		if (atts[i].nodeName.substr(0, 14) === "data-fancybox-") {
7075		  return true;
7076		}
7077	  }
7078
7079	  return false;
7080	};
7081
7082	var hasScrollbars = function (el) {
7083	  var overflowY = window.getComputedStyle(el)["overflow-y"],
7084		overflowX = window.getComputedStyle(el)["overflow-x"],
7085		vertical = (overflowY === "scroll" || overflowY === "auto") && el.scrollHeight > el.clientHeight,
7086		horizontal = (overflowX === "scroll" || overflowX === "auto") && el.scrollWidth > el.clientWidth;
7087
7088	  return vertical || horizontal;
7089	};
7090
7091	var isScrollable = function ($el) {
7092	  var rez = false;
7093
7094	  while (true) {
7095		rez = hasScrollbars($el.get(0));
7096
7097		if (rez) {
7098		  break;
7099		}
7100
7101		$el = $el.parent();
7102
7103		if (!$el.length || $el.hasClass("fancybox-stage") || $el.is("body")) {
7104		  break;
7105		}
7106	  }
7107
7108	  return rez;
7109	};
7110
7111	var Guestures = function (instance) {
7112	  var self = this;
7113
7114	  self.instance = instance;
7115
7116	  self.$bg = instance.$refs.bg;
7117	  self.$stage = instance.$refs.stage;
7118	  self.$container = instance.$refs.container;
7119
7120	  self.destroy();
7121
7122	  self.$container.on("touchstart.fb.touch mousedown.fb.touch", $.proxy(self, "ontouchstart"));
7123	};
7124
7125	Guestures.prototype.destroy = function () {
7126	  var self = this;
7127
7128	  self.$container.off(".fb.touch");
7129
7130	  $(document).off(".fb.touch");
7131
7132	  if (self.requestId) {
7133		cancelAFrame(self.requestId);
7134		self.requestId = null;
7135	  }
7136
7137	  if (self.tapped) {
7138		clearTimeout(self.tapped);
7139		self.tapped = null;
7140	  }
7141	};
7142
7143	Guestures.prototype.ontouchstart = function (e) {
7144	  var self = this,
7145		$target = $(e.target),
7146		instance = self.instance,
7147		current = instance.current,
7148		$slide = current.$slide,
7149		$content = current.$content,
7150		isTouchDevice = e.type == "touchstart";
7151
7152	  // Do not respond to both (touch and mouse) events
7153	  if (isTouchDevice) {
7154		self.$container.off("mousedown.fb.touch");
7155	  }
7156
7157	  // Ignore right click
7158	  if (e.originalEvent && e.originalEvent.button == 2) {
7159		return;
7160	  }
7161
7162	  // Ignore taping on links, buttons, input elements
7163	  if (!$slide.length || !$target.length || isClickable($target) || isClickable($target.parent())) {
7164		return;
7165	  }
7166	  // Ignore clicks on the scrollbar
7167	  if (!$target.is("img") && e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left) {
7168		return;
7169	  }
7170
7171	  // Ignore clicks while zooming or closing
7172	  if (!current || instance.isAnimating || current.$slide.hasClass("fancybox-animated")) {
7173		e.stopPropagation();
7174		e.preventDefault();
7175
7176		return;
7177	  }
7178
7179	  self.realPoints = self.startPoints = getPointerXY(e);
7180
7181	  if (!self.startPoints.length) {
7182		return;
7183	  }
7184
7185	  // Allow other scripts to catch touch event if "touch" is set to false
7186	  if (current.touch) {
7187		e.stopPropagation();
7188	  }
7189
7190	  self.startEvent = e;
7191
7192	  self.canTap = true;
7193	  self.$target = $target;
7194	  self.$content = $content;
7195	  self.opts = current.opts.touch;
7196
7197	  self.isPanning = false;
7198	  self.isSwiping = false;
7199	  self.isZooming = false;
7200	  self.isScrolling = false;
7201	  self.canPan = instance.canPan();
7202
7203	  self.startTime = new Date().getTime();
7204	  self.distanceX = self.distanceY = self.distance = 0;
7205
7206	  self.canvasWidth = Math.round($slide[0].clientWidth);
7207	  self.canvasHeight = Math.round($slide[0].clientHeight);
7208
7209	  self.contentLastPos = null;
7210	  self.contentStartPos = $.fancybox.getTranslate(self.$content) || {
7211		top: 0,
7212		left: 0
7213	  };
7214	  self.sliderStartPos = $.fancybox.getTranslate($slide);
7215
7216	  // Since position will be absolute, but we need to make it relative to the stage
7217	  self.stagePos = $.fancybox.getTranslate(instance.$refs.stage);
7218
7219	  self.sliderStartPos.top -= self.stagePos.top;
7220	  self.sliderStartPos.left -= self.stagePos.left;
7221
7222	  self.contentStartPos.top -= self.stagePos.top;
7223	  self.contentStartPos.left -= self.stagePos.left;
7224
7225	  $(document)
7226		.off(".fb.touch")
7227		.on(isTouchDevice ? "touchend.fb.touch touchcancel.fb.touch" : "mouseup.fb.touch mouseleave.fb.touch", $.proxy(self, "ontouchend"))
7228		.on(isTouchDevice ? "touchmove.fb.touch" : "mousemove.fb.touch", $.proxy(self, "ontouchmove"));
7229
7230	  if ($.fancybox.isMobile) {
7231		document.addEventListener("scroll", self.onscroll, true);
7232	  }
7233
7234	  // Skip if clicked outside the sliding area
7235	  if (!(self.opts || self.canPan) || !($target.is(self.$stage) || self.$stage.find($target).length)) {
7236		if ($target.is(".fancybox-image")) {
7237		  e.preventDefault();
7238		}
7239
7240		if (!($.fancybox.isMobile && $target.parents(".fancybox-caption").length)) {
7241		  return;
7242		}
7243	  }
7244
7245	  self.isScrollable = isScrollable($target) || isScrollable($target.parent());
7246
7247	  // Check if element is scrollable and try to prevent default behavior (scrolling)
7248	  if (!($.fancybox.isMobile && self.isScrollable)) {
7249		e.preventDefault();
7250	  }
7251
7252	  // One finger or mouse click - swipe or pan an image
7253	  if (self.startPoints.length === 1 || current.hasError) {
7254		if (self.canPan) {
7255		  $.fancybox.stop(self.$content);
7256
7257		  self.isPanning = true;
7258		} else {
7259		  self.isSwiping = true;
7260		}
7261
7262		self.$container.addClass("fancybox-is-grabbing");
7263	  }
7264
7265	  // Two fingers - zoom image
7266	  if (self.startPoints.length === 2 && current.type === "image" && (current.isLoaded || current.$ghost)) {
7267		self.canTap = false;
7268		self.isSwiping = false;
7269		self.isPanning = false;
7270
7271		self.isZooming = true;
7272
7273		$.fancybox.stop(self.$content);
7274
7275		self.centerPointStartX = (self.startPoints[0].x + self.startPoints[1].x) * 0.5 - $(window).scrollLeft();
7276		self.centerPointStartY = (self.startPoints[0].y + self.startPoints[1].y) * 0.5 - $(window).scrollTop();
7277
7278		self.percentageOfImageAtPinchPointX = (self.centerPointStartX - self.contentStartPos.left) / self.contentStartPos.width;
7279		self.percentageOfImageAtPinchPointY = (self.centerPointStartY - self.contentStartPos.top) / self.contentStartPos.height;
7280
7281		self.startDistanceBetweenFingers = distance(self.startPoints[0], self.startPoints[1]);
7282	  }
7283	};
7284
7285	Guestures.prototype.onscroll = function (e) {
7286	  var self = this;
7287
7288	  self.isScrolling = true;
7289
7290	  document.removeEventListener("scroll", self.onscroll, true);
7291	};
7292
7293	Guestures.prototype.ontouchmove = function (e) {
7294	  var self = this;
7295
7296	  // Make sure user has not released over iframe or disabled element
7297	  if (e.originalEvent.buttons !== undefined && e.originalEvent.buttons === 0) {
7298		self.ontouchend(e);
7299		return;
7300	  }
7301
7302	  if (self.isScrolling) {
7303		self.canTap = false;
7304		return;
7305	  }
7306
7307	  self.newPoints = getPointerXY(e);
7308
7309	  if (!(self.opts || self.canPan) || !self.newPoints.length || !self.newPoints.length) {
7310		return;
7311	  }
7312
7313	  if (!(self.isSwiping && self.isSwiping === true)) {
7314		e.preventDefault();
7315	  }
7316
7317	  self.distanceX = distance(self.newPoints[0], self.startPoints[0], "x");
7318	  self.distanceY = distance(self.newPoints[0], self.startPoints[0], "y");
7319
7320	  self.distance = distance(self.newPoints[0], self.startPoints[0]);
7321
7322	  // Skip false ontouchmove events (Chrome)
7323	  if (self.distance > 0) {
7324		if (self.isSwiping) {
7325		  self.onSwipe(e);
7326		} else if (self.isPanning) {
7327		  self.onPan();
7328		} else if (self.isZooming) {
7329		  self.onZoom();
7330		}
7331	  }
7332	};
7333
7334	Guestures.prototype.onSwipe = function (e) {
7335	  var self = this,
7336		instance = self.instance,
7337		swiping = self.isSwiping,
7338		left = self.sliderStartPos.left || 0,
7339		angle;
7340
7341	  // If direction is not yet determined
7342	  if (swiping === true) {
7343		// We need at least 10px distance to correctly calculate an angle
7344		if (Math.abs(self.distance) > 10) {
7345		  self.canTap = false;
7346
7347		  if (instance.group.length < 2 && self.opts.vertical) {
7348			self.isSwiping = "y";
7349		  } else if (instance.isDragging || self.opts.vertical === false || (self.opts.vertical === "auto" && $(window).width() > 800)) {
7350			self.isSwiping = "x";
7351		  } else {
7352			angle = Math.abs((Math.atan2(self.distanceY, self.distanceX) * 180) / Math.PI);
7353
7354			self.isSwiping = angle > 45 && angle < 135 ? "y" : "x";
7355		  }
7356
7357		  if (self.isSwiping === "y" && $.fancybox.isMobile && self.isScrollable) {
7358			self.isScrolling = true;
7359
7360			return;
7361		  }
7362
7363		  instance.isDragging = self.isSwiping;
7364
7365		  // Reset points to avoid jumping, because we dropped first swipes to calculate the angle
7366		  self.startPoints = self.newPoints;
7367
7368		  $.each(instance.slides, function (index, slide) {
7369			var slidePos, stagePos;
7370
7371			$.fancybox.stop(slide.$slide);
7372
7373			slidePos = $.fancybox.getTranslate(slide.$slide);
7374			stagePos = $.fancybox.getTranslate(instance.$refs.stage);
7375
7376			slide.$slide
7377			  .css({
7378				transform: "",
7379				opacity: "",
7380				"transition-duration": ""
7381			  })
7382			  .removeClass("fancybox-animated")
7383			  .removeClass(function (index, className) {
7384				return (className.match(/(^|\s)fancybox-fx-\S+/g) || []).join(" ");
7385			  });
7386
7387			if (slide.pos === instance.current.pos) {
7388			  self.sliderStartPos.top = slidePos.top - stagePos.top;
7389			  self.sliderStartPos.left = slidePos.left - stagePos.left;
7390			}
7391
7392			$.fancybox.setTranslate(slide.$slide, {
7393			  top: slidePos.top - stagePos.top,
7394			  left: slidePos.left - stagePos.left
7395			});
7396		  });
7397
7398		  // Stop slideshow
7399		  if (instance.SlideShow && instance.SlideShow.isActive) {
7400			instance.SlideShow.stop();
7401		  }
7402		}
7403
7404		return;
7405	  }
7406
7407	  // Sticky edges
7408	  if (swiping == "x") {
7409		if (
7410		  self.distanceX > 0 &&
7411		  (self.instance.group.length < 2 || (self.instance.current.index === 0 && !self.instance.current.opts.loop))
7412		) {
7413		  left = left + Math.pow(self.distanceX, 0.8);
7414		} else if (
7415		  self.distanceX < 0 &&
7416		  (self.instance.group.length < 2 ||
7417			(self.instance.current.index === self.instance.group.length - 1 && !self.instance.current.opts.loop))
7418		) {
7419		  left = left - Math.pow(-self.distanceX, 0.8);
7420		} else {
7421		  left = left + self.distanceX;
7422		}
7423	  }
7424
7425	  self.sliderLastPos = {
7426		top: swiping == "x" ? 0 : self.sliderStartPos.top + self.distanceY,
7427		left: left
7428	  };
7429
7430	  if (self.requestId) {
7431		cancelAFrame(self.requestId);
7432
7433		self.requestId = null;
7434	  }
7435
7436	  self.requestId = requestAFrame(function () {
7437		if (self.sliderLastPos) {
7438		  $.each(self.instance.slides, function (index, slide) {
7439			var pos = slide.pos - self.instance.currPos;
7440
7441			$.fancybox.setTranslate(slide.$slide, {
7442			  top: self.sliderLastPos.top,
7443			  left: self.sliderLastPos.left + pos * self.canvasWidth + pos * slide.opts.gutter
7444			});
7445		  });
7446
7447		  self.$container.addClass("fancybox-is-sliding");
7448		}
7449	  });
7450	};
7451
7452	Guestures.prototype.onPan = function () {
7453	  var self = this;
7454
7455	  // Prevent accidental movement (sometimes, when tapping casually, finger can move a bit)
7456	  if (distance(self.newPoints[0], self.realPoints[0]) < ($.fancybox.isMobile ? 10 : 5)) {
7457		self.startPoints = self.newPoints;
7458		return;
7459	  }
7460
7461	  self.canTap = false;
7462
7463	  self.contentLastPos = self.limitMovement();
7464
7465	  if (self.requestId) {
7466		cancelAFrame(self.requestId);
7467	  }
7468
7469	  self.requestId = requestAFrame(function () {
7470		$.fancybox.setTranslate(self.$content, self.contentLastPos);
7471	  });
7472	};
7473
7474	// Make panning sticky to the edges
7475	Guestures.prototype.limitMovement = function () {
7476	  var self = this;
7477
7478	  var canvasWidth = self.canvasWidth;
7479	  var canvasHeight = self.canvasHeight;
7480
7481	  var distanceX = self.distanceX;
7482	  var distanceY = self.distanceY;
7483
7484	  var contentStartPos = self.contentStartPos;
7485
7486	  var currentOffsetX = contentStartPos.left;
7487	  var currentOffsetY = contentStartPos.top;
7488
7489	  var currentWidth = contentStartPos.width;
7490	  var currentHeight = contentStartPos.height;
7491
7492	  var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY, newOffsetX, newOffsetY;
7493
7494	  if (currentWidth > canvasWidth) {
7495		newOffsetX = currentOffsetX + distanceX;
7496	  } else {
7497		newOffsetX = currentOffsetX;
7498	  }
7499
7500	  newOffsetY = currentOffsetY + distanceY;
7501
7502	  // Slow down proportionally to traveled distance
7503	  minTranslateX = Math.max(0, canvasWidth * 0.5 - currentWidth * 0.5);
7504	  minTranslateY = Math.max(0, canvasHeight * 0.5 - currentHeight * 0.5);
7505
7506	  maxTranslateX = Math.min(canvasWidth - currentWidth, canvasWidth * 0.5 - currentWidth * 0.5);
7507	  maxTranslateY = Math.min(canvasHeight - currentHeight, canvasHeight * 0.5 - currentHeight * 0.5);
7508
7509	  //   ->
7510	  if (distanceX > 0 && newOffsetX > minTranslateX) {
7511		newOffsetX = minTranslateX - 1 + Math.pow(-minTranslateX + currentOffsetX + distanceX, 0.8) || 0;
7512	  }
7513
7514	  //    <-
7515	  if (distanceX < 0 && newOffsetX < maxTranslateX) {
7516		newOffsetX = maxTranslateX + 1 - Math.pow(maxTranslateX - currentOffsetX - distanceX, 0.8) || 0;
7517	  }
7518
7519	  //   \/
7520	  if (distanceY > 0 && newOffsetY > minTranslateY) {
7521		newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8) || 0;
7522	  }
7523
7524	  //   /\
7525	  if (distanceY < 0 && newOffsetY < maxTranslateY) {
7526		newOffsetY = maxTranslateY + 1 - Math.pow(maxTranslateY - currentOffsetY - distanceY, 0.8) || 0;
7527	  }
7528
7529	  return {
7530		top: newOffsetY,
7531		left: newOffsetX
7532	  };
7533	};
7534
7535	Guestures.prototype.limitPosition = function (newOffsetX, newOffsetY, newWidth, newHeight) {
7536	  var self = this;
7537
7538	  var canvasWidth = self.canvasWidth;
7539	  var canvasHeight = self.canvasHeight;
7540
7541	  if (newWidth > canvasWidth) {
7542		newOffsetX = newOffsetX > 0 ? 0 : newOffsetX;
7543		newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX;
7544	  } else {
7545		// Center horizontally
7546		newOffsetX = Math.max(0, canvasWidth / 2 - newWidth / 2);
7547	  }
7548
7549	  if (newHeight > canvasHeight) {
7550		newOffsetY = newOffsetY > 0 ? 0 : newOffsetY;
7551		newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY;
7552	  } else {
7553		// Center vertically
7554		newOffsetY = Math.max(0, canvasHeight / 2 - newHeight / 2);
7555	  }
7556
7557	  return {
7558		top: newOffsetY,
7559		left: newOffsetX
7560	  };
7561	};
7562
7563	Guestures.prototype.onZoom = function () {
7564	  var self = this;
7565
7566	  // Calculate current distance between points to get pinch ratio and new width and height
7567	  var contentStartPos = self.contentStartPos;
7568
7569	  var currentWidth = contentStartPos.width;
7570	  var currentHeight = contentStartPos.height;
7571
7572	  var currentOffsetX = contentStartPos.left;
7573	  var currentOffsetY = contentStartPos.top;
7574
7575	  var endDistanceBetweenFingers = distance(self.newPoints[0], self.newPoints[1]);
7576
7577	  var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers;
7578
7579	  var newWidth = Math.floor(currentWidth * pinchRatio);
7580	  var newHeight = Math.floor(currentHeight * pinchRatio);
7581
7582	  // This is the translation due to pinch-zooming
7583	  var translateFromZoomingX = (currentWidth - newWidth) * self.percentageOfImageAtPinchPointX;
7584	  var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY;
7585
7586	  // Point between the two touches
7587	  var centerPointEndX = (self.newPoints[0].x + self.newPoints[1].x) / 2 - $(window).scrollLeft();
7588	  var centerPointEndY = (self.newPoints[0].y + self.newPoints[1].y) / 2 - $(window).scrollTop();
7589
7590	  // And this is the translation due to translation of the centerpoint
7591	  // between the two fingers
7592	  var translateFromTranslatingX = centerPointEndX - self.centerPointStartX;
7593	  var translateFromTranslatingY = centerPointEndY - self.centerPointStartY;
7594
7595	  // The new offset is the old/current one plus the total translation
7596	  var newOffsetX = currentOffsetX + (translateFromZoomingX + translateFromTranslatingX);
7597	  var newOffsetY = currentOffsetY + (translateFromZoomingY + translateFromTranslatingY);
7598
7599	  var newPos = {
7600		top: newOffsetY,
7601		left: newOffsetX,
7602		scaleX: pinchRatio,
7603		scaleY: pinchRatio
7604	  };
7605
7606	  self.canTap = false;
7607
7608	  self.newWidth = newWidth;
7609	  self.newHeight = newHeight;
7610
7611	  self.contentLastPos = newPos;
7612
7613	  if (self.requestId) {
7614		cancelAFrame(self.requestId);
7615	  }
7616
7617	  self.requestId = requestAFrame(function () {
7618		$.fancybox.setTranslate(self.$content, self.contentLastPos);
7619	  });
7620	};
7621
7622	Guestures.prototype.ontouchend = function (e) {
7623	  var self = this;
7624
7625	  var swiping = self.isSwiping;
7626	  var panning = self.isPanning;
7627	  var zooming = self.isZooming;
7628	  var scrolling = self.isScrolling;
7629
7630	  self.endPoints = getPointerXY(e);
7631	  self.dMs = Math.max(new Date().getTime() - self.startTime, 1);
7632
7633	  self.$container.removeClass("fancybox-is-grabbing");
7634
7635	  $(document).off(".fb.touch");
7636
7637	  document.removeEventListener("scroll", self.onscroll, true);
7638
7639	  if (self.requestId) {
7640		cancelAFrame(self.requestId);
7641
7642		self.requestId = null;
7643	  }
7644
7645	  self.isSwiping = false;
7646	  self.isPanning = false;
7647	  self.isZooming = false;
7648	  self.isScrolling = false;
7649
7650	  self.instance.isDragging = false;
7651
7652	  if (self.canTap) {
7653		return self.onTap(e);
7654	  }
7655
7656	  self.speed = 100;
7657
7658	  // Speed in px/ms
7659	  self.velocityX = (self.distanceX / self.dMs) * 0.5;
7660	  self.velocityY = (self.distanceY / self.dMs) * 0.5;
7661
7662	  if (panning) {
7663		self.endPanning();
7664	  } else if (zooming) {
7665		self.endZooming();
7666	  } else {
7667		self.endSwiping(swiping, scrolling);
7668	  }
7669
7670	  return;
7671	};
7672
7673	Guestures.prototype.endSwiping = function (swiping, scrolling) {
7674	  var self = this,
7675		ret = false,
7676		len = self.instance.group.length,
7677		distanceX = Math.abs(self.distanceX),
7678		canAdvance = swiping == "x" && len > 1 && ((self.dMs > 130 && distanceX > 10) || distanceX > 50),
7679		speedX = 300;
7680
7681	  self.sliderLastPos = null;
7682
7683	  // Close if swiped vertically / navigate if horizontally
7684	  if (swiping == "y" && !scrolling && Math.abs(self.distanceY) > 50) {
7685		// Continue vertical movement
7686		$.fancybox.animate(
7687		  self.instance.current.$slide, {
7688			top: self.sliderStartPos.top + self.distanceY + self.velocityY * 150,
7689			opacity: 0
7690		  },
7691		  200
7692		);
7693		ret = self.instance.close(true, 250);
7694	  } else if (canAdvance && self.distanceX > 0) {
7695		ret = self.instance.previous(speedX);
7696	  } else if (canAdvance && self.distanceX < 0) {
7697		ret = self.instance.next(speedX);
7698	  }
7699
7700	  if (ret === false && (swiping == "x" || swiping == "y")) {
7701		self.instance.centerSlide(200);
7702	  }
7703
7704	  self.$container.removeClass("fancybox-is-sliding");
7705	};
7706
7707	// Limit panning from edges
7708	// ========================
7709	Guestures.prototype.endPanning = function () {
7710	  var self = this,
7711		newOffsetX,
7712		newOffsetY,
7713		newPos;
7714
7715	  if (!self.contentLastPos) {
7716		return;
7717	  }
7718
7719	  if (self.opts.momentum === false || self.dMs > 350) {
7720		newOffsetX = self.contentLastPos.left;
7721		newOffsetY = self.contentLastPos.top;
7722	  } else {
7723		// Continue movement
7724		newOffsetX = self.contentLastPos.left + self.velocityX * 500;
7725		newOffsetY = self.contentLastPos.top + self.velocityY * 500;
7726	  }
7727
7728	  newPos = self.limitPosition(newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height);
7729
7730	  newPos.width = self.contentStartPos.width;
7731	  newPos.height = self.contentStartPos.height;
7732
7733	  $.fancybox.animate(self.$content, newPos, 366);
7734	};
7735
7736	Guestures.prototype.endZooming = function () {
7737	  var self = this;
7738
7739	  var current = self.instance.current;
7740
7741	  var newOffsetX, newOffsetY, newPos, reset;
7742
7743	  var newWidth = self.newWidth;
7744	  var newHeight = self.newHeight;
7745
7746	  if (!self.contentLastPos) {
7747		return;
7748	  }
7749
7750	  newOffsetX = self.contentLastPos.left;
7751	  newOffsetY = self.contentLastPos.top;
7752
7753	  reset = {
7754		top: newOffsetY,
7755		left: newOffsetX,
7756		width: newWidth,
7757		height: newHeight,
7758		scaleX: 1,
7759		scaleY: 1
7760	  };
7761
7762	  // Reset scalex/scaleY values; this helps for perfomance and does not break animation
7763	  $.fancybox.setTranslate(self.$content, reset);
7764
7765	  if (newWidth < self.canvasWidth && newHeight < self.canvasHeight) {
7766		self.instance.scaleToFit(150);
7767	  } else if (newWidth > current.width || newHeight > current.height) {
7768		self.instance.scaleToActual(self.centerPointStartX, self.centerPointStartY, 150);
7769	  } else {
7770		newPos = self.limitPosition(newOffsetX, newOffsetY, newWidth, newHeight);
7771
7772		$.fancybox.animate(self.$content, newPos, 150);
7773	  }
7774	};
7775
7776	Guestures.prototype.onTap = function (e) {
7777	  var self = this;
7778	  var $target = $(e.target);
7779
7780	  var instance = self.instance;
7781	  var current = instance.current;
7782
7783	  var endPoints = (e && getPointerXY(e)) || self.startPoints;
7784
7785	  var tapX = endPoints[0] ? endPoints[0].x - $(window).scrollLeft() - self.stagePos.left : 0;
7786	  var tapY = endPoints[0] ? endPoints[0].y - $(window).scrollTop() - self.stagePos.top : 0;
7787
7788	  var where;
7789
7790	  var process = function (prefix) {
7791		var action = current.opts[prefix];
7792
7793		if ($.isFunction(action)) {
7794		  action = action.apply(instance, [current, e]);
7795		}
7796
7797		if (!action) {
7798		  return;
7799		}
7800
7801		switch (action) {
7802		  case "close":
7803			instance.close(self.startEvent);
7804
7805			break;
7806
7807		  case "toggleControls":
7808			instance.toggleControls();
7809
7810			break;
7811
7812		  case "next":
7813			instance.next();
7814
7815			break;
7816
7817		  case "nextOrClose":
7818			if (instance.group.length > 1) {
7819			  instance.next();
7820			} else {
7821			  instance.close(self.startEvent);
7822			}
7823
7824			break;
7825
7826		  case "zoom":
7827			if (current.type == "image" && (current.isLoaded || current.$ghost)) {
7828			  if (instance.canPan()) {
7829				instance.scaleToFit();
7830			  } else if (instance.isScaledDown()) {
7831				instance.scaleToActual(tapX, tapY);
7832			  } else if (instance.group.length < 2) {
7833				instance.close(self.startEvent);
7834			  }
7835			}
7836
7837			break;
7838		}
7839	  };
7840
7841	  // Ignore right click
7842	  if (e.originalEvent && e.originalEvent.button == 2) {
7843		return;
7844	  }
7845
7846	  // Skip if clicked on the scrollbar
7847	  if (!$target.is("img") && tapX > $target[0].clientWidth + $target.offset().left) {
7848		return;
7849	  }
7850
7851	  // Check where is clicked
7852	  if ($target.is(".fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container")) {
7853		where = "Outside";
7854	  } else if ($target.is(".fancybox-slide")) {
7855		where = "Slide";
7856	  } else if (
7857		instance.current.$content &&
7858		instance.current.$content
7859		.find($target)
7860		.addBack()
7861		.filter($target).length
7862	  ) {
7863		where = "Content";
7864	  } else {
7865		return;
7866	  }
7867
7868	  // Check if this is a double tap
7869	  if (self.tapped) {
7870		// Stop previously created single tap
7871		clearTimeout(self.tapped);
7872		self.tapped = null;
7873
7874		// Skip if distance between taps is too big
7875		if (Math.abs(tapX - self.tapX) > 50 || Math.abs(tapY - self.tapY) > 50) {
7876		  return this;
7877		}
7878
7879		// OK, now we assume that this is a double-tap
7880		process("dblclick" + where);
7881	  } else {
7882		// Single tap will be processed if user has not clicked second time within 300ms
7883		// or there is no need to wait for double-tap
7884		self.tapX = tapX;
7885		self.tapY = tapY;
7886
7887		if (current.opts["dblclick" + where] && current.opts["dblclick" + where] !== current.opts["click" + where]) {
7888		  self.tapped = setTimeout(function () {
7889			self.tapped = null;
7890
7891			if (!instance.isAnimating) {
7892			  process("click" + where);
7893			}
7894		  }, 500);
7895		} else {
7896		  process("click" + where);
7897		}
7898	  }
7899
7900	  return this;
7901	};
7902
7903	$(document)
7904	  .on("onActivate.fb", function (e, instance) {
7905		if (instance && !instance.Guestures) {
7906		  instance.Guestures = new Guestures(instance);
7907		}
7908	  })
7909	  .on("beforeClose.fb", function (e, instance) {
7910		if (instance && instance.Guestures) {
7911		  instance.Guestures.destroy();
7912		}
7913	  });
7914  })(window, document, jQuery);
7915  // ==========================================================================
7916  //
7917  // SlideShow
7918  // Enables slideshow functionality
7919  //
7920  // Example of usage:
7921  // $.fancybox.getInstance().SlideShow.start()
7922  //
7923  // ==========================================================================
7924  (function (document, $) {
7925	"use strict";
7926
7927	$.extend(true, $.fancybox.defaults, {
7928	  btnTpl: {
7929		slideShow: '<button data-fancybox-play class="fancybox-button fancybox-button--play" title="{{PLAY_START}}">' +
7930		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.5 5.4v13.2l11-6.6z"/></svg>' +
7931		  '<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>' +
7932		  "</button>"
7933	  },
7934	  slideShow: {
7935		autoStart: false,
7936		speed: 3000,
7937		progress: true
7938	  }
7939	});
7940
7941	var SlideShow = function (instance) {
7942	  this.instance = instance;
7943	  this.init();
7944	};
7945
7946	$.extend(SlideShow.prototype, {
7947	  timer: null,
7948	  isActive: false,
7949	  $button: null,
7950
7951	  init: function () {
7952		var self = this,
7953		  instance = self.instance,
7954		  opts = instance.group[instance.currIndex].opts.slideShow;
7955
7956		self.$button = instance.$refs.toolbar.find("[data-fancybox-play]").on("click", function () {
7957		  self.toggle();
7958		});
7959
7960		if (instance.group.length < 2 || !opts) {
7961		  self.$button.hide();
7962		} else if (opts.progress) {
7963		  self.$progress = $('<div class="fancybox-progress"></div>').appendTo(instance.$refs.inner);
7964		}
7965	  },
7966
7967	  set: function (force) {
7968		var self = this,
7969		  instance = self.instance,
7970		  current = instance.current;
7971
7972		// Check if reached last element
7973		if (current && (force === true || current.opts.loop || instance.currIndex < instance.group.length - 1)) {
7974		  if (self.isActive && current.contentType !== "video") {
7975			if (self.$progress) {
7976			  $.fancybox.animate(self.$progress.show(), {
7977				scaleX: 1
7978			  }, current.opts.slideShow.speed);
7979			}
7980
7981			self.timer = setTimeout(function () {
7982			  if (!instance.current.opts.loop && instance.current.index == instance.group.length - 1) {
7983				instance.jumpTo(0);
7984			  } else {
7985				instance.next();
7986			  }
7987			}, current.opts.slideShow.speed);
7988		  }
7989		} else {
7990		  self.stop();
7991		  instance.idleSecondsCounter = 0;
7992		  instance.showControls();
7993		}
7994	  },
7995
7996	  clear: function () {
7997		var self = this;
7998
7999		clearTimeout(self.timer);
8000
8001		self.timer = null;
8002
8003		if (self.$progress) {
8004		  self.$progress.removeAttr("style").hide();
8005		}
8006	  },
8007
8008	  start: function () {
8009		var self = this,
8010		  current = self.instance.current;
8011
8012		if (current) {
8013		  self.$button
8014			.attr("title", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_STOP)
8015			.removeClass("fancybox-button--play")
8016			.addClass("fancybox-button--pause");
8017
8018		  self.isActive = true;
8019
8020		  if (current.isComplete) {
8021			self.set(true);
8022		  }
8023
8024		  self.instance.trigger("onSlideShowChange", true);
8025		}
8026	  },
8027
8028	  stop: function () {
8029		var self = this,
8030		  current = self.instance.current;
8031
8032		self.clear();
8033
8034		self.$button
8035		  .attr("title", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_START)
8036		  .removeClass("fancybox-button--pause")
8037		  .addClass("fancybox-button--play");
8038
8039		self.isActive = false;
8040
8041		self.instance.trigger("onSlideShowChange", false);
8042
8043		if (self.$progress) {
8044		  self.$progress.removeAttr("style").hide();
8045		}
8046	  },
8047
8048	  toggle: function () {
8049		var self = this;
8050
8051		if (self.isActive) {
8052		  self.stop();
8053		} else {
8054		  self.start();
8055		}
8056	  }
8057	});
8058
8059	$(document).on({
8060	  "onInit.fb": function (e, instance) {
8061		if (instance && !instance.SlideShow) {
8062		  instance.SlideShow = new SlideShow(instance);
8063		}
8064	  },
8065
8066	  "beforeShow.fb": function (e, instance, current, firstRun) {
8067		var SlideShow = instance && instance.SlideShow;
8068
8069		if (firstRun) {
8070		  if (SlideShow && current.opts.slideShow.autoStart) {
8071			SlideShow.start();
8072		  }
8073		} else if (SlideShow && SlideShow.isActive) {
8074		  SlideShow.clear();
8075		}
8076	  },
8077
8078	  "afterShow.fb": function (e, instance, current) {
8079		var SlideShow = instance && instance.SlideShow;
8080
8081		if (SlideShow && SlideShow.isActive) {
8082		  SlideShow.set();
8083		}
8084	  },
8085
8086	  "afterKeydown.fb": function (e, instance, current, keypress, keycode) {
8087		var SlideShow = instance && instance.SlideShow;
8088
8089		// "P" or Spacebar
8090		if (SlideShow && current.opts.slideShow && (keycode === 80 || keycode === 32) && !$(document.activeElement).is("button,a,input")) {
8091		  keypress.preventDefault();
8092
8093		  SlideShow.toggle();
8094		}
8095	  },
8096
8097	  "beforeClose.fb onDeactivate.fb": function (e, instance) {
8098		var SlideShow = instance && instance.SlideShow;
8099
8100		if (SlideShow) {
8101		  SlideShow.stop();
8102		}
8103	  }
8104	});
8105
8106	// Page Visibility API to pause slideshow when window is not active
8107	$(document).on("visibilitychange", function () {
8108	  if ( $.fancybox.version != '3.5.7' ) {
8109		  return;
8110	  }
8111
8112	  var instance = $.fancybox.getInstance(),
8113		SlideShow = instance && instance.SlideShow;
8114
8115	  if (SlideShow && SlideShow.isActive) {
8116		if (document.hidden) {
8117		  SlideShow.clear();
8118		} else {
8119		  SlideShow.set();
8120		}
8121	  }
8122	});
8123  })(document, jQuery);
8124  // ==========================================================================
8125  //
8126  // FullScreen
8127  // Adds fullscreen functionality
8128  //
8129  // ==========================================================================
8130  (function (document, $) {
8131	"use strict";
8132
8133	// Collection of methods supported by user browser
8134	var fn = (function () {
8135	  var fnMap = [
8136		["requestFullscreen", "exitFullscreen", "fullscreenElement", "fullscreenEnabled", "fullscreenchange", "fullscreenerror"],
8137		// new WebKit
8138		[
8139		  "webkitRequestFullscreen",
8140		  "webkitExitFullscreen",
8141		  "webkitFullscreenElement",
8142		  "webkitFullscreenEnabled",
8143		  "webkitfullscreenchange",
8144		  "webkitfullscreenerror"
8145		],
8146		// old WebKit (Safari 5.1)
8147		[
8148		  "webkitRequestFullScreen",
8149		  "webkitCancelFullScreen",
8150		  "webkitCurrentFullScreenElement",
8151		  "webkitCancelFullScreen",
8152		  "webkitfullscreenchange",
8153		  "webkitfullscreenerror"
8154		],
8155		[
8156		  "mozRequestFullScreen",
8157		  "mozCancelFullScreen",
8158		  "mozFullScreenElement",
8159		  "mozFullScreenEnabled",
8160		  "mozfullscreenchange",
8161		  "mozfullscreenerror"
8162		],
8163		["msRequestFullscreen", "msExitFullscreen", "msFullscreenElement", "msFullscreenEnabled", "MSFullscreenChange", "MSFullscreenError"]
8164	  ];
8165
8166	  var ret = {};
8167
8168	  for (var i = 0; i < fnMap.length; i++) {
8169		var val = fnMap[i];
8170
8171		if (val && val[1] in document) {
8172		  for (var j = 0; j < val.length; j++) {
8173			ret[fnMap[0][j]] = val[j];
8174		  }
8175
8176		  return ret;
8177		}
8178	  }
8179
8180	  return false;
8181	})();
8182
8183	if (fn) {
8184	  var FullScreen = {
8185		request: function (elem) {
8186		  elem = elem || document.documentElement;
8187
8188		  elem[fn.requestFullscreen](elem.ALLOW_KEYBOARD_INPUT);
8189		},
8190		exit: function () {
8191		  document[fn.exitFullscreen]();
8192		},
8193		toggle: function (elem) {
8194		  elem = elem || document.documentElement;
8195
8196		  if (this.isFullscreen()) {
8197			this.exit();
8198		  } else {
8199			this.request(elem);
8200		  }
8201		},
8202		isFullscreen: function () {
8203		  return Boolean(document[fn.fullscreenElement]);
8204		},
8205		enabled: function () {
8206		  return Boolean(document[fn.fullscreenEnabled]);
8207		}
8208	  };
8209
8210	  $.extend(true, $.fancybox.defaults, {
8211		btnTpl: {
8212		  fullScreen: '<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fsenter" title="{{FULL_SCREEN}}">' +
8213			'<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>' +
8214			'<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>' +
8215			"</button>"
8216		},
8217		fullScreen: {
8218		  autoStart: false
8219		}
8220	  });
8221
8222	  $(document).on(fn.fullscreenchange, function () {
8223		var isFullscreen = FullScreen.isFullscreen(),
8224		  instance = $.fancybox.getInstance();
8225
8226		if (instance) {
8227		  // If image is zooming, then force to stop and reposition properly
8228		  if (instance.current && instance.current.type === "image" && instance.isAnimating) {
8229			instance.isAnimating = false;
8230
8231			instance.update(true, true, 0);
8232
8233			if (!instance.isComplete) {
8234			  instance.complete();
8235			}
8236		  }
8237
8238		  instance.trigger("onFullscreenChange", isFullscreen);
8239
8240		  instance.$refs.container.toggleClass("fancybox-is-fullscreen", isFullscreen);
8241
8242		  instance.$refs.toolbar
8243			.find("[data-fancybox-fullscreen]")
8244			.toggleClass("fancybox-button--fsenter", !isFullscreen)
8245			.toggleClass("fancybox-button--fsexit", isFullscreen);
8246		}
8247	  });
8248	}
8249
8250	$(document).on({
8251	  "onInit.fb": function (e, instance) {
8252		var $container;
8253
8254		if (!fn) {
8255		  instance.$refs.toolbar.find("[data-fancybox-fullscreen]").remove();
8256
8257		  return;
8258		}
8259
8260		if (instance && instance.group[instance.currIndex].opts.fullScreen) {
8261		  $container = instance.$refs.container;
8262
8263		  $container.on("click.fb-fullscreen", "[data-fancybox-fullscreen]", function (e) {
8264			e.stopPropagation();
8265			e.preventDefault();
8266
8267			FullScreen.toggle();
8268		  });
8269
8270		  if (instance.opts.fullScreen && instance.opts.fullScreen.autoStart === true) {
8271			FullScreen.request();
8272		  }
8273
8274		  // Expose API
8275		  instance.FullScreen = FullScreen;
8276		} else if (instance) {
8277		  instance.$refs.toolbar.find("[data-fancybox-fullscreen]").hide();
8278		}
8279	  },
8280
8281	  "afterKeydown.fb": function (e, instance, current, keypress, keycode) {
8282		// "F"
8283		if (instance && instance.FullScreen && keycode === 70) {
8284		  keypress.preventDefault();
8285
8286		  instance.FullScreen.toggle();
8287		}
8288	  },
8289
8290	  "beforeClose.fb": function (e, instance) {
8291		if (instance && instance.FullScreen && instance.$refs.container.hasClass("fancybox-is-fullscreen")) {
8292		  FullScreen.exit();
8293		}
8294	  }
8295	});
8296  })(document, jQuery);
8297  // ==========================================================================
8298  //
8299  // Thumbs
8300  // Displays thumbnails in a grid
8301  //
8302  // ==========================================================================
8303  (function (document, $) {
8304	"use strict";
8305
8306	var CLASS = "fancybox-thumbs",
8307	  CLASS_ACTIVE = CLASS + "-active";
8308
8309	// Make sure there are default values
8310	$.fancybox.defaults = $.extend(
8311	  true, {
8312		btnTpl: {
8313		  thumbs: '<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="{{THUMBS}}">' +
8314			'<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>' +
8315			"</button>"
8316		},
8317		thumbs: {
8318		  autoStart: false, // Display thumbnails on opening
8319		  hideOnClose: true, // Hide thumbnail grid when closing animation starts
8320		  parentEl: ".fancybox-container", // Container is injected into this element
8321		  axis: "y" // Vertical (y) or horizontal (x) scrolling
8322		}
8323	  },
8324	  $.fancybox.defaults
8325	);
8326
8327	var FancyThumbs = function (instance) {
8328	  this.init(instance);
8329	};
8330
8331	$.extend(FancyThumbs.prototype, {
8332	  $button: null,
8333	  $grid: null,
8334	  $list: null,
8335	  isVisible: false,
8336	  isActive: false,
8337
8338	  init: function (instance) {
8339		var self = this,
8340		  group = instance.group,
8341		  enabled = 0;
8342
8343		self.instance = instance;
8344		self.opts = group[instance.currIndex].opts.thumbs;
8345
8346		instance.Thumbs = self;
8347
8348		self.$button = instance.$refs.toolbar.find("[data-fancybox-thumbs]");
8349
8350		// Enable thumbs if at least two group items have thumbnails
8351		for (var i = 0, len = group.length; i < len; i++) {
8352		  if (group[i].thumb) {
8353			enabled++;
8354		  }
8355
8356		  if (enabled > 1) {
8357			break;
8358		  }
8359		}
8360
8361		if (enabled > 1 && !!self.opts) {
8362		  self.$button.removeAttr("style").on("click", function () {
8363			self.toggle();
8364		  });
8365
8366		  self.isActive = true;
8367		} else {
8368		  self.$button.hide();
8369		}
8370	  },
8371
8372	  create: function () {
8373		var self = this,
8374		  instance = self.instance,
8375		  parentEl = self.opts.parentEl,
8376		  list = [],
8377		  src;
8378
8379		if (!self.$grid) {
8380		  // Create main element
8381		  self.$grid = $('<div class="' + CLASS + " " + CLASS + "-" + self.opts.axis + '"></div>').appendTo(
8382			instance.$refs.container
8383			.find(parentEl)
8384			.addBack()
8385			.filter(parentEl)
8386		  );
8387
8388		  // Add "click" event that performs gallery navigation
8389		  self.$grid.on("click", "a", function () {
8390			instance.jumpTo($(this).attr("data-index"));
8391		  });
8392		}
8393
8394		// Build the list
8395		if (!self.$list) {
8396		  self.$list = $('<div class="' + CLASS + '__list">').appendTo(self.$grid);
8397		}
8398
8399		$.each(instance.group, function (i, item) {
8400		  src = item.thumb;
8401
8402		  if (!src && item.type === "image") {
8403			src = item.src;
8404		  }
8405
8406		  list.push(
8407			'<a href="javascript:;" tabindex="0" data-index="' +
8408			i +
8409			'"' +
8410			(src && src.length ? ' style="background-image:url(' + src + ')"' : 'class="fancybox-thumbs-missing"') +
8411			"></a>"
8412		  );
8413		});
8414
8415		self.$list[0].innerHTML = list.join("");
8416
8417		if (self.opts.axis === "x") {
8418		  // Set fixed width for list element to enable horizontal scrolling
8419		  self.$list.width(
8420			parseInt(self.$grid.css("padding-right"), 10) +
8421			instance.group.length *
8422			self.$list
8423			.children()
8424			.eq(0)
8425			.outerWidth(true)
8426		  );
8427		}
8428	  },
8429
8430	  focus: function (duration) {
8431		var self = this,
8432		  $list = self.$list,
8433		  $grid = self.$grid,
8434		  thumb,
8435		  thumbPos;
8436
8437		if (!self.instance.current) {
8438		  return;
8439		}
8440
8441		thumb = $list
8442		  .children()
8443		  .removeClass(CLASS_ACTIVE)
8444		  .filter('[data-index="' + self.instance.current.index + '"]')
8445		  .addClass(CLASS_ACTIVE);
8446
8447		thumbPos = thumb.position();
8448
8449		// Check if need to scroll to make current thumb visible
8450		if (self.opts.axis === "y" && (thumbPos.top < 0 || thumbPos.top > $list.height() - thumb.outerHeight())) {
8451		  $list.stop().animate({
8452			  scrollTop: $list.scrollTop() + thumbPos.top
8453			},
8454			duration
8455		  );
8456		} else if (
8457		  self.opts.axis === "x" &&
8458		  (thumbPos.left < $grid.scrollLeft() || thumbPos.left > $grid.scrollLeft() + ($grid.width() - thumb.outerWidth()))
8459		) {
8460		  $list
8461			.parent()
8462			.stop()
8463			.animate({
8464				scrollLeft: thumbPos.left
8465			  },
8466			  duration
8467			);
8468		}
8469	  },
8470
8471	  update: function () {
8472		var that = this;
8473		that.instance.$refs.container.toggleClass("fancybox-show-thumbs", this.isVisible);
8474
8475		if (that.isVisible) {
8476		  if (!that.$grid) {
8477			that.create();
8478		  }
8479
8480		  that.instance.trigger("onThumbsShow");
8481
8482		  that.focus(0);
8483		} else if (that.$grid) {
8484		  that.instance.trigger("onThumbsHide");
8485		}
8486
8487		// Update content position
8488		that.instance.update();
8489	  },
8490
8491	  hide: function () {
8492		this.isVisible = false;
8493		this.update();
8494	  },
8495
8496	  show: function () {
8497		this.isVisible = true;
8498		this.update();
8499	  },
8500
8501	  toggle: function () {
8502		this.isVisible = !this.isVisible;
8503		this.update();
8504	  }
8505	});
8506
8507	$(document).on({
8508	  "onInit.fb": function (e, instance) {
8509		var Thumbs;
8510
8511		if (instance && !instance.Thumbs) {
8512		  Thumbs = new FancyThumbs(instance);
8513
8514		  if (Thumbs.isActive && Thumbs.opts.autoStart === true) {
8515			Thumbs.show();
8516		  }
8517		}
8518	  },
8519
8520	  "beforeShow.fb": function (e, instance, item, firstRun) {
8521		var Thumbs = instance && instance.Thumbs;
8522
8523		if (Thumbs && Thumbs.isVisible) {
8524		  Thumbs.focus(firstRun ? 0 : 250);
8525		}
8526	  },
8527
8528	  "afterKeydown.fb": function (e, instance, current, keypress, keycode) {
8529		var Thumbs = instance && instance.Thumbs;
8530
8531		// "G"
8532		if (Thumbs && Thumbs.isActive && keycode === 71) {
8533		  keypress.preventDefault();
8534
8535		  Thumbs.toggle();
8536		}
8537	  },
8538
8539	  "beforeClose.fb": function (e, instance) {
8540		var Thumbs = instance && instance.Thumbs;
8541
8542		if (Thumbs && Thumbs.isVisible && Thumbs.opts.hideOnClose !== false) {
8543		  Thumbs.$grid.hide();
8544		}
8545	  }
8546	});
8547  })(document, jQuery);
8548  //// ==========================================================================
8549  //
8550  // Share
8551  // Displays simple form for sharing current url
8552  //
8553  // ==========================================================================
8554  (function (document, $) {
8555	"use strict";
8556
8557	$.extend(true, $.fancybox.defaults, {
8558	  btnTpl: {
8559		share: '<button data-fancybox-share class="fancybox-button fancybox-button--share" title="{{SHARE}}">' +
8560		  '<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>' +
8561		  "</button>"
8562	  },
8563	  share: {
8564		url: function (instance, item) {
8565		  return (
8566			(!instance.currentHash && !(item.type === "inline" || item.type === "html") ? item.origSrc || item.src : false) || window.location
8567		  );
8568		},
8569		tpl: '<div class="fancybox-share">' +
8570		  "<h1>{{SHARE}}</h1>" +
8571		  "<p>" +
8572		  '<a class="fancybox-share__button fancybox-share__button--fb" href="https://www.facebook.com/sharer/sharer.php?u={{url}}">' +
8573		  '<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>' +
8574		  "<span>Facebook</span>" +
8575		  "</a>" +
8576		  '<a class="fancybox-share__button fancybox-share__button--tw" href="https://twitter.com/intent/tweet?url={{url}}&text={{descr}}">' +
8577		  '<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>' +
8578		  "<span>Twitter</span>" +
8579		  "</a>" +
8580		  '<a class="fancybox-share__button fancybox-share__button--pt" href="https://www.pinterest.com/pin/create/button/?url={{url}}&description={{descr}}&media={{media}}">' +
8581		  '<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>' +
8582		  "<span>Pinterest</span>" +
8583		  "</a>" +
8584		  "</p>" +
8585		  '<p><input class="fancybox-share__input" type="text" value="{{url_raw}}" onclick="select()" /></p>' +
8586		  "</div>"
8587	  }
8588	});
8589
8590	function escapeHtml(string) {
8591	  var entityMap = {
8592		"&": "&amp;",
8593		"<": "&lt;",
8594		">": "&gt;",
8595		'"': "&quot;",
8596		"'": "&#39;",
8597		"/": "&#x2F;",
8598		"`": "&#x60;",
8599		"=": "&#x3D;"
8600	  };
8601
8602	  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
8603		return entityMap[s];
8604	  });
8605	}
8606
8607	$(document).on("click", "[data-fancybox-share]", function () {
8608	  var instance = $.fancybox.getInstance(),
8609		current = instance.current || null,
8610		url,
8611		tpl;
8612
8613	  if (!current) {
8614		return;
8615	  }
8616
8617	  if ($.type(current.opts.share.url) === "function") {
8618		url = current.opts.share.url.apply(current, [instance, current]);
8619	  }
8620
8621	  tpl = current.opts.share.tpl
8622		.replace(/\{\{media\}\}/g, current.type === "image" ? encodeURIComponent(current.src) : "")
8623		.replace(/\{\{url\}\}/g, encodeURIComponent(url))
8624		.replace(/\{\{url_raw\}\}/g, escapeHtml(url))
8625		.replace(/\{\{descr\}\}/g, instance.$caption ? encodeURIComponent(instance.$caption.text()) : "");
8626
8627	  $.fancybox.open({
8628		src: instance.translate(instance, tpl),
8629		type: "html",
8630		opts: {
8631		  touch: false,
8632		  animationEffect: false,
8633		  afterLoad: function (shareInstance, shareCurrent) {
8634			// Close self if parent instance is closing
8635			instance.$refs.container.one("beforeClose.fb", function () {
8636			  shareInstance.close(null, 0);
8637			});
8638
8639			// Opening links in a popup window
8640			shareCurrent.$content.find(".fancybox-share__button").on('click',function () {
8641			  window.open(this.href, "Share", "width=550, height=450");
8642			  return false;
8643			});
8644		  },
8645		  mobile: {
8646			autoFocus: false
8647		  }
8648		}
8649	  });
8650	});
8651  })(document, jQuery);
8652  // ==========================================================================
8653  //
8654  // Hash
8655  // Enables linking to each modal
8656  //
8657  // ==========================================================================
8658  (function (window, document, $) {
8659	"use strict";
8660
8661	// Simple $.escapeSelector polyfill (for jQuery prior v3)
8662	if (!$.escapeSelector) {
8663	  $.escapeSelector = function (sel) {
8664		var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
8665		var fcssescape = function (ch, asCodePoint) {
8666		  if (asCodePoint) {
8667			// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
8668			if (ch === "\0") {
8669			  return "\uFFFD";
8670			}
8671
8672			// Control characters and (dependent upon position) numbers get escaped as code points
8673			return ch.slice(0, -1) + "\\" + ch.charCodeAt(ch.length - 1).toString(16) + " ";
8674		  }
8675
8676		  // Other potentially-special ASCII characters get backslash-escaped
8677		  return "\\" + ch;
8678		};
8679
8680		return (sel + "").replace(rcssescape, fcssescape);
8681	  };
8682	}
8683
8684	// Get info about gallery name and current index from url
8685	function parseUrl() {
8686	  var hash = window.location.hash.substr(1),
8687		rez = hash.split("-"),
8688		index = rez.length > 1 && /^\+?\d+$/.test(rez[rez.length - 1]) ? parseInt(rez.pop(-1), 10) || 1 : 1,
8689		gallery = rez.join("-");
8690
8691	  return {
8692		hash: hash,
8693		/* Index is starting from 1 */
8694		index: index < 1 ? 1 : index,
8695		gallery: gallery
8696	  };
8697	}
8698
8699	// Trigger click evnt on links to open new fancyBox instance
8700	function triggerFromUrl(url) {
8701	  if (url.gallery !== "") {
8702		// If we can find element matching 'data-fancybox' atribute,
8703		// then triggering click event should start fancyBox
8704		$("[data-fancybox='" + $.escapeSelector(url.gallery) + "']")
8705		  .eq(url.index - 1)
8706		  .focus()
8707		  .trigger("click.fb-start");
8708	  }
8709	}
8710
8711	// Get gallery name from current instance
8712	function getGalleryID(instance) {
8713	  var opts, ret;
8714
8715	  if (!instance) {
8716		return false;
8717	  }
8718
8719	  opts = instance.current ? instance.current.opts : instance.opts;
8720	  ret = opts.hash || (opts.$orig ? opts.$orig.data("fancybox") || opts.$orig.data("fancybox-trigger") : "");
8721
8722	  return ret === "" ? false : ret;
8723	}
8724
8725	// Start when DOM becomes ready
8726	$(function () {
8727	  if ( $.fancybox.version != '3.5.7' ) {
8728		  return;
8729	  }
8730
8731	  // Check if user has disabled this module
8732	  if ($.fancybox.defaults.hash === false) {
8733		return;
8734	  }
8735
8736	  // Update hash when opening/closing fancyBox
8737	  $(document).on({
8738		"onInit.fb": function (e, instance) {
8739		  var url, gallery;
8740
8741		  if (instance.group[instance.currIndex].opts.hash === false) {
8742			return;
8743		  }
8744
8745		  url = parseUrl();
8746		  gallery = getGalleryID(instance);
8747
8748		  // Make sure gallery start index matches index from hash
8749		  if (gallery && url.gallery && gallery == url.gallery) {
8750			instance.currIndex = url.index - 1;
8751		  }
8752		},
8753
8754		"beforeShow.fb": function (e, instance, current, firstRun) {
8755		  var gallery;
8756
8757		  if (!current || current.opts.hash === false) {
8758			return;
8759		  }
8760
8761		  // Check if need to update window hash
8762		  gallery = getGalleryID(instance);
8763
8764		  if (!gallery) {
8765			return;
8766		  }
8767
8768		  // Variable containing last hash value set by fancyBox
8769		  // It will be used to determine if fancyBox needs to close after hash change is detected
8770		  instance.currentHash = gallery + (instance.group.length > 1 ? "-" + (current.index + 1) : "");
8771
8772		  // If current hash is the same (this instance most likely is opened by hashchange), then do nothing
8773		  if (window.location.hash === "#" + instance.currentHash) {
8774			return;
8775		  }
8776
8777		  if (firstRun && !instance.origHash) {
8778			instance.origHash = window.location.hash;
8779		  }
8780
8781		  if (instance.hashTimer) {
8782			clearTimeout(instance.hashTimer);
8783		  }
8784
8785		  // Update hash
8786		  instance.hashTimer = setTimeout(function () {
8787			if ("replaceState" in window.history) {
8788			  window.history[firstRun ? "pushState" : "replaceState"]({},
8789				document.title,
8790				window.location.pathname + window.location.search + "#" + instance.currentHash
8791			  );
8792
8793			  if (firstRun) {
8794				instance.hasCreatedHistory = true;
8795			  }
8796			} else {
8797			  window.location.hash = instance.currentHash;
8798			}
8799
8800			instance.hashTimer = null;
8801		  }, 300);
8802		},
8803
8804		"beforeClose.fb": function (e, instance, current) {
8805		  if (!current || current.opts.hash === false) {
8806			return;
8807		  }
8808
8809		  clearTimeout(instance.hashTimer);
8810
8811		  // Goto previous history entry
8812		  if (instance.currentHash && instance.hasCreatedHistory) {
8813			window.history.back();
8814		  } else if (instance.currentHash) {
8815			if ("replaceState" in window.history) {
8816			  window.history.replaceState({}, document.title, window.location.pathname + window.location.search + (instance.origHash || ""));
8817			} else {
8818			  window.location.hash = instance.origHash;
8819			}
8820		  }
8821
8822		  instance.currentHash = null;
8823		}
8824	  });
8825
8826	  // Check if need to start/close after url has changed
8827	  $(window).on("hashchange.fb", function () {
8828		var url = parseUrl(),
8829		  fb = null;
8830
8831		// Find last fancyBox instance that has "hash"
8832		$.each(
8833		  $(".fancybox-container")
8834		  .get()
8835		  .reverse(),
8836		  function (index, value) {
8837			var tmp = $(value).data("FancyBox");
8838
8839			if (tmp && tmp.currentHash) {
8840			  fb = tmp;
8841			  return false;
8842			}
8843		  }
8844		);
8845
8846		if (fb) {
8847		  // Now, compare hash values
8848		  if (fb.currentHash !== url.gallery + "-" + url.index && !(url.index === 1 && fb.currentHash == url.gallery)) {
8849			fb.currentHash = null;
8850
8851			fb.close();
8852		  }
8853		} else if (url.gallery !== "") {
8854		  triggerFromUrl(url);
8855		}
8856	  });
8857
8858	  // Check current hash and trigger click event on matching element to start fancyBox, if needed
8859	  setTimeout(function () {
8860		if ( $.fancybox.version != '3.5.7' ) {
8861			return;
8862		}
8863
8864		if (!$.fancybox.getInstance()) {
8865		  triggerFromUrl(parseUrl());
8866		}
8867	  }, 50);
8868	});
8869  })(window, document, jQuery);
8870  // ==========================================================================
8871  //
8872  // Wheel
8873  // Basic mouse weheel support for gallery navigation
8874  //
8875  // ==========================================================================
8876  (function (document, $) {
8877	"use strict";
8878
8879	var prevTime = new Date().getTime();
8880
8881	$(document).on({
8882	  "onInit.fb": function (e, instance, current) {
8883		instance.$refs.stage.on("mousewheel DOMMouseScroll wheel MozMousePixelScroll", function (e) {
8884		  var current = instance.current,
8885			currTime = new Date().getTime();
8886
8887		  if (instance.group.length < 2 || current.opts.wheel === false || (current.opts.wheel === "auto" && current.type !== "image")) {
8888			return;
8889		  }
8890
8891		  e.preventDefault();
8892		  e.stopPropagation();
8893
8894		  if (current.$slide.hasClass("fancybox-animated")) {
8895			return;
8896		  }
8897
8898		  e = e.originalEvent || e;
8899
8900		  if (currTime - prevTime < 250) {
8901			return;
8902		  }
8903
8904		  prevTime = currTime;
8905
8906		  instance[(-e.deltaY || -e.deltaX || e.wheelDelta || -e.detail) < 0 ? "next" : "previous"]();
8907		});
8908	  }
8909	});
8910  })(document, jQuery);
8911
8912;
8913(function ($, window, document, undefined) {
8914
8915  var pluginName = "MegaMenu",
8916    defaults = {
8917      propertyName: "value"
8918    };
8919
8920  // Set delay time for mouseout
8921  var delayOut = 400; // Default delay time is 200
8922
8923  // the list of menus
8924  var menus = [];
8925
8926  function CustomMenu(element, options) {
8927    this.element = element;
8928
8929    this.options = $.extend({}, defaults, options);
8930
8931    this._defaults = defaults;
8932    this._name = pluginName;
8933
8934    this.init();
8935  }
8936
8937  CustomMenu.prototype = {
8938    isOpen: false,
8939    timeout: null,
8940    init: function () {
8941
8942      var that = this;
8943
8944      $(this).each(function(index, menu) {
8945        that.node = menu.element;
8946        that.addListeners(menu.element);
8947
8948        var $menu = $(menu.element);
8949        $menu.addClass("dropdownJavascript");
8950        menus.push(menu.element);
8951
8952        $menu.find('ul > li').each(function(index, submenu) {
8953          if ($(submenu).find('ul').length > 0 ) {
8954            $(submenu).addClass('with-menu');
8955          }
8956        });
8957      });
8958    },
8959    addListeners: function(menu) {
8960      var that = this;
8961      $(menu).on('mouseover',function(e) {
8962        that.handleMouseOver.call(that, e);
8963      }).on('mouseout',function(e) {
8964          that.handleMouseOut.call(that, e);
8965        });
8966    },
8967    handleMouseOver: function (e) {
8968      var that = this;
8969      // clear the timeout
8970      this.clearTimeout();
8971
8972      // find the parent list item
8973      //var item = ('target' in e ? e.target : e.srcElement);
8974      var item = e.target || e.srcElement;
8975      while (item.nodeName != 'LI' && item != this.node) {
8976        item = item.parentNode;
8977      }
8978
8979      // if the target is within a list item, set the timeout
8980      if (item.nodeName == 'LI') {
8981        this.toOpen = item;
8982        this.timeout = setTimeout(function() {
8983          that.open.call(that);
8984        }, this.options.delay);
8985      }
8986
8987    },
8988    handleMouseOut: function () {
8989      var that = this;
8990      // clear the timeout
8991      this.clearTimeout();
8992
8993      // Check mouseout delay overriding
8994      var _delayOut = this.options.delay;
8995      if ( delayOut ) {
8996        _delayOut = delayOut;
8997      }
8998
8999      this.timeout = setTimeout(function() {
9000        that.close.call(that);
9001      }, _delayOut );
9002
9003    },
9004    clearTimeout: function () {
9005
9006      // clear the timeout
9007      if (this.timeout) {
9008        clearTimeout(this.timeout);
9009        this.timeout = null;
9010      }
9011
9012    },
9013    open: function () {
9014
9015      var that = this;
9016      // store that the menu is open
9017      this.isOpen = true;
9018
9019      // loop over the list items with the same parent
9020      var items = $(this.toOpen).parent().children('li');
9021      $(items).each(function(index, item) {
9022        $(item).find("ul").each(function(index, submenu) {
9023          if (item != that.toOpen) {
9024            // close the submenu
9025            $(item).removeClass("dropdownOpen");
9026            that.close(item);
9027
9028          } else if (!$(item).hasClass('dropdownOpen')) {
9029
9030            // open the submenu
9031            //if ( !$(item).parents('li').hasClass('has-mega-menu') ) {
9032              $(item).addClass("dropdownOpen");
9033            //}
9034
9035
9036            // determine the location of the edges of the submenu
9037            var left = 0;
9038            var node = submenu;
9039            while (node) {
9040              //abs is because when you make menus right to left
9041              //the offsetLeft would be negative
9042              left += Math.abs(node.offsetLeft);
9043              node = node.offsetParent;
9044            }
9045            var right = left + submenu.offsetWidth;
9046
9047
9048            //We should refactor this code to execute only when menu is vertical
9049            var menuHeight = $(submenu).outerHeight();
9050            var parentTop = $(submenu).offset().top - $(window).scrollTop();
9051            var totalHeight = menuHeight + parentTop;
9052            var windowHeight = window.innerHeight;
9053
9054           /* if (totalHeight > windowHeight) {
9055              var bestTop = (windowHeight - totalHeight) - 20;
9056              $(submenu).css('margin-top', bestTop + "px");
9057            }*/
9058
9059            //remove any previous classes
9060            $(item).removeClass('dropdownRightToLeft');
9061
9062            // move the submenu to the right of the item if appropriate
9063            if (left < 0) $(item).addClass('dropdownLeftToRight');
9064
9065            // move the submenu to the left of the item if appropriate
9066            if (right > document.body.clientWidth) {
9067              $(item).addClass('dropdownRightToLeft');
9068            }
9069
9070          }
9071        });
9072      });
9073
9074    },
9075
9076
9077    close: function (node) {
9078
9079      // if no node was specified, close all menus
9080      if (!node) {
9081        this.isOpen = false;
9082        node = this.node;
9083      }
9084
9085      // loop over the items, closing their submenus
9086      $(node).find('li').each(function(index, item) {
9087        $(item).removeClass('dropdownOpen');
9088      });
9089
9090    }
9091  };
9092
9093  $.fn[pluginName] = function (options) {
9094    return this.each(function () {
9095      if (!$.data(this, "plugin_" + pluginName)) {
9096        $.data(this, "plugin_" + pluginName,
9097          new CustomMenu(this, options));
9098      }
9099    });
9100  };
9101
9102})(jQuery, window, document);
9103
9104/*!
9105 * modernizr v3.3.1
9106 * Build https://modernizr.com/download?-cssanimations-csstransitions-touchevents-domprefixes-prefixed-prefixes-setclasses-shiv-testallprops-testprop-teststyles-dontmin
9107 *
9108 * Copyright (c)
9109 *  Faruk Ates
9110 *  Paul Irish
9111 *  Alex Sexton
9112 *  Ryan Seddon
9113 *  Patrick Kettner
9114 *  Stu Cox
9115 *  Richard Herrera
9116
9117 * MIT License
9118 */
9119
9120/*
9121 * Modernizr tests which native CSS3 and HTML5 features are available in the
9122 * current UA and makes the results available to you in two ways: as properties on
9123 * a global `Modernizr` object, and as classes on the `<html>` element. This
9124 * information allows you to progressively enhance your pages with a granular level
9125 * of control over the experience.
9126*/
9127
9128;(function(window, document, undefined){
9129  var classes = [];
9130  
9131
9132  var tests = [];
9133  
9134
9135  /**
9136   *
9137   * ModernizrProto is the constructor for Modernizr
9138   *
9139   * @class
9140   * @access public
9141   */
9142
9143  var ModernizrProto = {
9144    // The current version, dummy
9145    _version: '3.3.1',
9146
9147    // Any settings that don't work as separate modules
9148    // can go in here as configuration.
9149    _config: {
9150      'classPrefix': '',
9151      'enableClasses': true,
9152      'enableJSClass': true,
9153      'usePrefixes': true
9154    },
9155
9156    // Queue of tests
9157    _q: [],
9158
9159    // Stub these for people who are listening
9160    on: function(test, cb) {
9161      // I don't really think people should do this, but we can
9162      // safe guard it a bit.
9163      // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.
9164      // This is in case people listen to synchronous tests. I would leave it out,
9165      // but the code to *disallow* sync tests in the real version of this
9166      // function is actually larger than this.
9167      var self = this;
9168      setTimeout(function() {
9169        cb(self[test]);
9170      }, 0);
9171    },
9172
9173    addTest: function(name, fn, options) {
9174      tests.push({name: name, fn: fn, options: options});
9175    },
9176
9177    addAsyncTest: function(fn) {
9178      tests.push({name: null, fn: fn});
9179    }
9180  };
9181
9182  
9183
9184  // Fake some of Object.create so we can force non test results to be non "own" properties.
9185  var Modernizr = function() {};
9186  Modernizr.prototype = ModernizrProto;
9187
9188  // Leak modernizr globally when you `require` it rather than force it here.
9189  // Overwrite name so constructor name is nicer :D
9190  Modernizr = new Modernizr();
9191
9192  
9193
9194  /**
9195   * List of property values to set for css tests. See ticket #21
9196   * http://git.io/vUGl4
9197   *
9198   * @memberof Modernizr
9199   * @name Modernizr._prefixes
9200   * @optionName Modernizr._prefixes
9201   * @optionProp prefixes
9202   * @access public
9203   * @example
9204   *
9205   * Modernizr._prefixes is the internal list of prefixes that we test against
9206   * inside of things like [prefixed](#modernizr-prefixed) and [prefixedCSS](#-code-modernizr-prefixedcss). It is simply
9207   * an array of kebab-case vendor prefixes you can use within your code.
9208   *
9209   * Some common use cases include
9210   *
9211   * Generating all possible prefixed version of a CSS property
9212   * ```js
9213   * var rule = Modernizr._prefixes.join('transform: rotate(20deg); ');
9214   *
9215   * rule === 'transform: rotate(20deg); webkit-transform: rotate(20deg); moz-transform: rotate(20deg); o-transform: rotate(20deg); ms-transform: rotate(20deg);'
9216   * ```
9217   *
9218   * Generating all possible prefixed version of a CSS value
9219   * ```js
9220   * rule = 'display:' +  Modernizr._prefixes.join('flex; display:') + 'flex';
9221   *
9222   * rule === 'display:flex; display:-webkit-flex; display:-moz-flex; display:-o-flex; display:-ms-flex; display:flex'
9223   * ```
9224   */
9225
9226  // we use ['',''] rather than an empty array in order to allow a pattern of .`join()`ing prefixes to test
9227  // values in feature detects to continue to work
9228  var prefixes = (ModernizrProto._config.usePrefixes ? ' -webkit- -moz- -o- -ms- '.split(' ') : ['','']);
9229
9230  // expose these for the plugin API. Look in the source for how to join() them against your input
9231  ModernizrProto._prefixes = prefixes;
9232
9233  
9234
9235  /**
9236   * is returns a boolean if the typeof an obj is exactly type.
9237   *
9238   * @access private
9239   * @function is
9240   * @param {*} obj - A thing we want to check the type of
9241   * @param {string} type - A string to compare the typeof against
9242   * @returns {boolean}
9243   */
9244
9245  function is(obj, type) {
9246    return typeof obj === type;
9247  }
9248  ;
9249
9250  /**
9251   * Run through all tests and detect their support in the current UA.
9252   *
9253   * @access private
9254   */
9255
9256  function testRunner() {
9257    var featureNames;
9258    var feature;
9259    var aliasIdx;
9260    var result;
9261    var nameIdx;
9262    var featureName;
9263    var featureNameSplit;
9264
9265    for (var featureIdx in tests) {
9266      if (tests.hasOwnProperty(featureIdx)) {
9267        featureNames = [];
9268        feature = tests[featureIdx];
9269        // run the test, throw the return value into the Modernizr,
9270        // then based on that boolean, define an appropriate className
9271        // and push it into an array of classes we'll join later.
9272        //
9273        // If there is no name, it's an 'async' test that is run,
9274        // but not directly added to the object. That should
9275        // be done with a post-run addTest call.
9276        if (feature.name) {
9277          featureNames.push(feature.name.toLowerCase());
9278
9279          if (feature.options && feature.options.aliases && feature.options.aliases.length) {
9280            // Add all the aliases into the names list
9281            for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {
9282              featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());
9283            }
9284          }
9285        }
9286
9287        // Run the test, or use the raw value if it's not a function
9288        result = is(feature.fn, 'function') ? feature.fn() : feature.fn;
9289
9290
9291        // Set each of the names on the Modernizr object
9292        for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {
9293          featureName = featureNames[nameIdx];
9294          // Support dot properties as sub tests. We don't do checking to make sure
9295          // that the implied parent tests have been added. You must call them in
9296          // order (either in the test, or make the parent test a dependency).
9297          //
9298          // Cap it to TWO to make the logic simple and because who needs that kind of subtesting
9299          // hashtag famous last words
9300          featureNameSplit = featureName.split('.');
9301
9302          if (featureNameSplit.length === 1) {
9303            Modernizr[featureNameSplit[0]] = result;
9304          } else {
9305            // cast to a Boolean, if not one already
9306            /* jshint -W053 */
9307            if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
9308              Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
9309            }
9310
9311            Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;
9312          }
9313
9314          classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));
9315        }
9316      }
9317    }
9318  }
9319  ;
9320
9321  /**
9322   * docElement is a convenience wrapper to grab the root element of the document
9323   *
9324   * @access private
9325   * @returns {HTMLElement|SVGElement} The root element of the document
9326   */
9327
9328  var docElement = document.documentElement;
9329  
9330
9331  /**
9332   * A convenience helper to check if the document we are running in is an SVG document
9333   *
9334   * @access private
9335   * @returns {boolean}
9336   */
9337
9338  var isSVG = docElement.nodeName.toLowerCase() === 'svg';
9339  
9340
9341  /**
9342   * setClasses takes an array of class names and adds them to the root element
9343   *
9344   * @access private
9345   * @function setClasses
9346   * @param {string[]} classes - Array of class names
9347   */
9348
9349  // Pass in an and array of class names, e.g.:
9350  //  ['no-webp', 'borderradius', ...]
9351  function setClasses(classes) {
9352    var className = docElement.className;
9353    var classPrefix = Modernizr._config.classPrefix || '';
9354
9355    if (isSVG) {
9356      className = className.baseVal;
9357    }
9358
9359    // Change `no-js` to `js` (independently of the `enableClasses` option)
9360    // Handle classPrefix on this too
9361    if (Modernizr._config.enableJSClass) {
9362      var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)');
9363      className = className.replace(reJS, '$1' + classPrefix + 'js$2');
9364    }
9365
9366    if (Modernizr._config.enableClasses) {
9367      // Add the new classes
9368      className += ' ' + classPrefix + classes.join(' ' + classPrefix);
9369      isSVG ? docElement.className.baseVal = className : docElement.className = className;
9370    }
9371
9372  }
9373
9374  ;
9375
9376/**
9377  * @optionName html5shiv
9378  * @optionProp html5shiv
9379  */
9380
9381  // Take the html5 variable out of the html5shiv scope so we can return it.
9382  var html5;
9383  if (!isSVG) {
9384    /**
9385     * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
9386     */
9387    ;(function(window, document) {
9388      /*jshint evil:true */
9389      /** version */
9390      var version = '3.7.3';
9391
9392      /** Preset options */
9393      var options = window.html5 || {};
9394
9395      /** Used to skip problem elements */
9396      var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
9397
9398      /** Not all elements can be cloned in IE **/
9399      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;
9400
9401      /** Detect whether the browser supports default html5 styles */
9402      var supportsHtml5Styles;
9403
9404      /** Name of the expando, to work with multiple documents or to re-shiv one document */
9405      var expando = '_html5shiv';
9406
9407      /** The id for the the documents expando */
9408      var expanID = 0;
9409
9410      /** Cached data for each document */
9411      var expandoData = {};
9412
9413      /** Detect whether the browser supports unknown elements */
9414      var supportsUnknownElements;
9415
9416      (function() {
9417        try {
9418          var a = document.createElement('a');
9419          a.innerHTML = '<xyz></xyz>';
9420          //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
9421          supportsHtml5Styles = ('hidden' in a);
9422
9423          supportsUnknownElements = a.childNodes.length == 1 || (function() {
9424            // assign a false positive if unable to shiv
9425            (document.createElement)('a');
9426            var frag = document.createDocumentFragment();
9427            return (
9428              typeof frag.cloneNode == 'undefined' ||
9429                typeof frag.createDocumentFragment == 'undefined' ||
9430                typeof frag.createElement == 'undefined'
9431            );
9432          }());
9433        } catch(e) {
9434          // assign a false positive if detection fails => unable to shiv
9435          supportsHtml5Styles = true;
9436          supportsUnknownElements = true;
9437        }
9438
9439      }());
9440
9441      /*--------------------------------------------------------------------------*/
9442
9443      /**
9444       * Creates a style sheet with the given CSS text and adds it to the document.
9445       * @private
9446       * @param {Document} ownerDocument The document.
9447       * @param {String} cssText The CSS text.
9448       * @returns {StyleSheet} The style element.
9449       */
9450      function addStyleSheet(ownerDocument, cssText) {
9451        var p = ownerDocument.createElement('p'),
9452          parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
9453
9454        p.innerHTML = 'x<style>' + cssText + '</style>';
9455        return parent.insertBefore(p.lastChild, parent.firstChild);
9456      }
9457
9458      /**
9459       * Returns the value of `html5.elements` as an array.
9460       * @private
9461       * @returns {Array} An array of shived element node names.
9462       */
9463      function getElements() {
9464        var elements = html5.elements;
9465        return typeof elements == 'string' ? elements.split(' ') : elements;
9466      }
9467
9468      /**
9469       * Extends the built-in list of html5 elements
9470       * @memberOf html5
9471       * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
9472       * @param {Document} ownerDocument The context document.
9473       */
9474      function addElements(newElements, ownerDocument) {
9475        var elements = html5.elements;
9476        if(typeof elements != 'string'){
9477          elements = elements.join(' ');
9478        }
9479        if(typeof newElements != 'string'){
9480          newElements = newElements.join(' ');
9481        }
9482        html5.elements = elements +' '+ newElements;
9483        shivDocument(ownerDocument);
9484      }
9485
9486      /**
9487       * Returns the data associated to the given document
9488       * @private
9489       * @param {Document} ownerDocument The document.
9490       * @returns {Object} An object of data.
9491       */
9492      function getExpandoData(ownerDocument) {
9493        var data = expandoData[ownerDocument[expando]];
9494        if (!data) {
9495          data = {};
9496          expanID++;
9497          ownerDocument[expando] = expanID;
9498          expandoData[expanID] = data;
9499        }
9500        return data;
9501      }
9502
9503      /**
9504       * returns a shived element for the given nodeName and document
9505       * @memberOf html5
9506       * @param {String}
vendor: 4,418 bytes, lines 9506-9617
9506 nodeName name of the element
9507       * @param {Document|DocumentFragment} ownerDocument The context document.
9508       * @returns {Object} The shived element.
9509       */
9510      function createElement(nodeName, ownerDocument, data){
9511        if (!ownerDocument) {
9512          ownerDocument = document;
9513        }
9514        if(supportsUnknownElements){
9515          return ownerDocument.createElement(nodeName);
9516        }
9517        if (!data) {
9518          data = getExpandoData(ownerDocument);
9519        }
9520        var node;
9521
9522        if (data.cache[nodeName]) {
9523          node = data.cache[nodeName].cloneNode();
9524        } else if (saveClones.test(nodeName)) {
9525          node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
9526        } else {
9527          node = data.createElem(nodeName);
9528        }
9529
9530        // Avoid adding some elements to fragments in IE < 9 because
9531        // * Attributes like `name` or `type` cannot be set/changed once an element
9532        //   is inserted into a document/fragment
9533        // * Link elements with `src` attributes that are inaccessible, as with
9534        //   a 403 response, will cause the tab/window to crash
9535        // * Script elements appended to fragments will execute when their `src`
9536        //   or `text` property is set
9537        return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
9538      }
9539
9540      /**
9541       * returns a shived DocumentFragment for the given document
9542       * @memberOf html5
9543       * @param {Document} ownerDocument The context document.
9544       * @returns {Object} The shived DocumentFragment.
9545       */
9546      function createDocumentFragment(ownerDocument, data){
9547        if (!ownerDocument) {
9548          ownerDocument = document;
9549        }
9550        if(supportsUnknownElements){
9551          return ownerDocument.createDocumentFragment();
9552        }
9553        data = data || getExpandoData(ownerDocument);
9554        var clone = data.frag.cloneNode(),
9555          i = 0,
9556          elems = getElements(),
9557          l = elems.length;
9558        for(;i<l;i++){
9559          clone.createElement(elems[i]);
9560        }
9561        return clone;
9562      }
9563
9564      /**
9565       * Shivs the `createElement` and `createDocumentFragment` methods of the document.
9566       * @private
9567       * @param {Document|DocumentFragment} ownerDocument The document.
9568       * @param {Object} data of the document.
9569       */
9570      function shivMethods(ownerDocument, data) {
9571        if (!data.cache) {
9572          data.cache = {};
9573          data.createElem = ownerDocument.createElement;
9574          data.createFrag = ownerDocument.createDocumentFragment;
9575          data.frag = data.createFrag();
9576        }
9577
9578
9579        ownerDocument.createElement = function(nodeName) {
9580          //abort shiv
9581          if (!html5.shivMethods) {
9582            return data.createElem(nodeName);
9583          }
9584          return createElement(nodeName, ownerDocument, data);
9585        };
9586
9587        ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
9588                                                        'var n=f.cloneNode(),c=n.createElement;' +
9589                                                        'h.shivMethods&&(' +
9590                                                        // unroll the `createElement` calls
9591                                                        getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
9592          data.createElem(nodeName);
9593          data.frag.createElement(nodeName);
9594          return 'c("' + nodeName + '")';
9595        }) +
9596          ');return n}'
9597                                                       )(html5, data.frag);
9598      }
9599
9600      /*--------------------------------------------------------------------------*/
9601
9602      /**
9603       * Shivs the given document.
9604       * @memberOf html5
9605       * @param {Document} ownerDocument The document to shiv.
9606       * @returns {Document} The shived document.
9607       */
9608      function shivDocument(ownerDocument) {
9609        if (!ownerDocument) {
9610          ownerDocument = document;
9611        }
9612        var data = getExpandoData(ownerDocument);
9613
9614        if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
9615          data.hasCSS = !!addStyleSheet(ownerDocument,
9616                                        // corrects block display not defined in IE6/7/8/9
9617                                        'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{dis
9617play:block}' +
9618                                        // adds styling not present in IE6/7/8/9
9619                                        'mark{background:#FF0;color:#000}' +
9620                                        // hides non-rendered elements
9621                                        'template{display:none}'
9622                                       );
9623        }
9624        if (!supportsUnknownElements) {
9625          shivMethods(ownerDocument, data);
9626        }
9627        return ownerDocument;
9628      }
9629
9630      /*--------------------------------------------------------------------------*/
9631
9632      /**
9633       * The `html5` object is exposed so that more elements can be shived and
9634       * existing shiving can be detected on iframes.
9635       * @type Object
9636       * @example
9637       *
9638       * // options can be changed before the script is included
9639       * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
9640       */
9641      var html5 = {
9642
9643        /**
9644         * An array or space separated string of node names of the elements to shiv.
9645         * @memberOf html5
9646         * @type Array|String
9647         */
9648        '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',
9649
9650        /**
9651         * current version of html5shiv
9652         */
9653        'version': version,
9654
9655        /**
9656         * A flag to indicate that the HTML5 style sheet should be inserted.
9657         * @memberOf html5
9658         * @type Boolean
9659         */
9660        'shivCSS': (options.shivCSS !== false),
9661
9662        /**
9663         * Is equal to true if a browser supports creating unknown/HTML5 elements
9664         * @memberOf html5
9665         * @type boolean
9666         */
9667        'supportsUnknownElements': supportsUnknownElements,
9668
9669        /**
9670         * A flag to indicate that the document's `createElement` and `createDocumentFragment`
9671         * methods should be overwritten.
9672         * @memberOf html5
9673         * @type Boolean
9674         */
9675        'shivMethods': (options.shivMethods !== false),
9676
9677        /**
9678         * A string to describe the type of `html5` object ("default" or "default print").
9679         * @memberOf html5
9680         * @type String
9681         */
9682        'type': 'default',
9683
9684        // shivs the document according to the specified `html5` object options
9685        'shivDocument': shivDocument,
9686
9687        //creates a shived element
9688        createElement: createElement,
9689
9690        //creates a shived documentFragment
9691        createDocumentFragment: createDocumentFragment,
9692
9693        //extends list of elements
9694        addElements: addElements
9695      };
9696
9697      /*--------------------------------------------------------------------------*/
9698
9699      // expose html5
9700      window.html5 = html5;
9701
9702      // shiv the document
9703      shivDocument(document);
9704
9705      if(typeof module == 'object' && module.exports){
9706        module.exports = html5;
9707      }
9708
9709    }(typeof window !== "undefined" ? window : this, document));
9710  }
9711;
9712
9713  /**
9714   * If the browsers follow the spec, then they would expose vendor-specific style as:
9715   *   elem.style.WebkitBorderRadius
9716   * instead of something like the following, which would be technically incorrect:
9717   *   elem.style.webkitBorderRadius
9718
9719   * Webkit ghosts their properties in lowercase but Opera & Moz do not.
9720   * Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
9721   *   erik.eae.net/archives/2008/03/10/21.48.10/
9722
9723   * More here: github.com/Modernizr/Modernizr/issues/issue/21
9724   *
9725   * @access private
9726   * @returns {string} The string representing the vendor-specific style properties
9727   */
9728
9729  var omPrefixes = 'Moz O ms Webkit';
9730  
9731
9732  /**
9733   * List of JavaScript DOM values used for tests
9734   *
9735   * @memberof Modernizr
9736   * @name Modernizr._domPrefixes
9737   * @optionName Modernizr._domPrefixes
9738   * @optionProp domPrefixes
9739   * @access public
9740   * @example
9741   *
9742   * Modernizr._domPrefixes is exactly the same as [_prefixes](#modernizr-_prefixes), but rather
9743   * than kebab-case properties, all properties are their Capitalized variant
9744   *
9745   * ```js
9746   * Modernizr._domPrefixes === [ "Moz", "O", "ms", "Webkit" ];
9747   * ```
9748   */
9749
9750  var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []);
9751  ModernizrProto._domPrefixes = domPrefixes;
9752  
9753
9754  /**
9755   * cssToDOM takes a kebab-case string and converts it to camelCase
9756   * e.g. box-sizing -> boxSizing
9757   *
9758   * @access private
9759   * @function cssToDOM
9760   * @param {string} name - String name of kebab-case prop we want to convert
9761   * @returns {string} The camelCase version of the supplied name
9762   */
9763
9764  function cssToDOM(name) {
9765    return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {
9766      return m1 + m2.toUpperCase();
9767    }).replace(/^-/, '');
9768  }
9769  ;
9770
9771  var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []);
9772  ModernizrProto._cssomPrefixes = cssomPrefixes;
9773  
9774
9775  /**
9776   * atRule returns a given CSS property at-rule (eg @keyframes), possibly in
9777   * some prefixed form, or false, in the case of an unsupported rule
9778   *
9779   * @memberof Modernizr
9780   * @name Modernizr.atRule
9781   * @optionName Modernizr.atRule()
9782   * @optionProp atRule
9783   * @access public
9784   * @function atRule
9785   * @param {string} prop - String name of the @-rule to test for
9786   * @returns {string|boolean} The string representing the (possibly prefixed)
9787   * valid version of the @-rule, or `false` when it is unsupported.
9788   * @example
9789   * ```js
9790   *  var keyframes = Modernizr.atRule('@keyframes');
9791   *
9792   *  if (keyframes) {
9793   *    // keyframes are supported
9794   *    // could be `@-webkit-keyframes` or `@keyframes`
9795   *  } else {
9796   *    // keyframes === `false`
9797   *  }
9798   * ```
9799   *
9800   */
9801
9802  var atRule = function(prop) {
9803    var length = prefixes.length;
9804    var cssrule = window.CSSRule;
9805    var rule;
9806
9807    if (typeof cssrule === 'undefined') {
9808      return undefined;
9809    }
9810
9811    if (!prop) {
9812      return false;
9813    }
9814
9815    // remove literal @ from beginning of provided property
9816    prop = prop.replace(/^@/, '');
9817
9818    // CSSRules use underscores instead of dashes
9819    rule = prop.replace(/-/g, '_').toUpperCase() + '_RULE';
9820
9821    if (rule in cssrule) {
9822      return '@' + prop;
9823    }
9824
9825    for (var i = 0; i < length; i++) {
9826      // prefixes gives us something like -o-, and we want O_
9827      var prefix = prefixes[i];
9828      var thisRule = prefix.toUpperCase() + '_' + rule;
9829
9830      if (thisRule in cssrule) {
9831        return '@-' + prefix.toLowerCase() + '-' + prop;
9832      }
9833    }
9834
9835    return false;
9836  };
9837
9838  ModernizrProto.atRule = atRule;
9839
9840  
9841
9842
9843  /**
9844   * contains checks to see if a string contains another string
9845   *
9846   * @access private
9847   * @function contains
9848   * @param {string} str - The string we want to check for substrings
9849   * @param {string} substr - The substring we want to search the first string for
9850   * @returns {boolean}
9851   */
9852
9853  function contains(str, substr) {
9854    return !!~('' + str).indexOf(substr);
9855  }
9856
9857  ;
9858
9859  /**
9860   * createElement is a convenience wrapper around document.createElement. Since we
9861   * use createElement all over the place, this allows for (slightly) smaller code
9862   * as well as abstracting away issues with creating elements in contexts other than
9863   * HTML documents (e.g. SVG documents).
9864   *
9865   * @access private
9866   * @function createElement
9867   * @returns {HTMLElement|SVGElement} An HTML or SVG element
9868   */
9869
9870  function createElement() {
9871    if (typeof document.createElement !== 'function') {
9872      // This is the case in IE7, where the type of createElement is "object".
9873      // For this reason, we cannot call apply() as Object is not a Function.
9874      return document.createElement(arguments[0]);
9875    } else if (isSVG) {
9876      return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);
9877    } else {
9878      return document.createElement.apply(document, arguments);
9879    }
9880  }
9881
9882  ;
9883
9884  /**
9885   * getBody returns the body of a document, or an element that can stand in for
9886   * the body if a real body does not exist
9887   *
9888   * @access private
9889   * @function getBody
9890   * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an
9891   * artificially created element that stands in for the body
9892   */
9893
9894  function getBody() {
9895    // After page load injecting a fake body doesn't work so check if body exists
9896    var body = document.body;
9897
9898    if (!body) {
9899      // Can't use the real body create a fake one.
9900      body = createElement(isSVG ? 'svg' : 'body');
9901      body.fake = true;
9902    }
9903
9904    return body;
9905  }
9906
9907  ;
9908
9909  /**
9910   * injectElementWithStyles injects an element with style element and some CSS rules
9911   *
9912   * @access private
9913   * @function injectElementWithStyles
9914   * @param {string} rule - String representing a css rule
9915   * @param {function} callback - A function that is used to test the injected element
9916   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
9917   * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes
9918   * @returns {boolean}
9919   */
9920
9921  function injectElementWithStyles(rule, callback, nodes, testnames) {
9922    var mod = 'modernizr';
9923    var style;
9924    var ret;
9925    var node;
9926    var docOverflow;
9927    var div = createElement('div');
9928    var body = getBody();
9929
9930    if (parseInt(nodes, 10)) {
9931      // In order not to give false positives we create a node for each test
9932      // This also allows the method to scale for unspecified uses
9933      while (nodes--) {
9934        node = createElement('div');
9935        node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
9936        div.appendChild(node);
9937      }
9938    }
9939
9940    style = createElement('style');
9941    style.type = 'text/css';
9942    style.id = 's' + mod;
9943
9944    // 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.
9945    // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
9946    (!body.fake ? div : body).appendChild(style);
9947    body.appendChild(div);
9948
9949    if (style.styleSheet) {
9950      style.styleSheet.cssText = rule;
9951    } else {
9952      style.appendChild(document.createTextNode(rule));
9953    }
9954    div.id = mod;
9955
9956    if (body.fake) {
9957      //avoid crashing IE8, if background image is used
9958      body.style.background = '';
9959      //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
9960      body.style.overflow = 'hidden';
9961      docOverflow = docElement.style.overflow;
9962      docElement.style.overflow = 'hidden';
9963      docElement.appendChild(body);
9964    }
9965
9966    ret = callback(div, rule);
9967    // If this is done after page load we don't want to remove the body so check if body exists
9968    if (body.fake) {
9969      body.parentNode.removeChild(body);
9970      docElement.style.overflow = docOverflow;
9971      // Trigger layout so kinetic scrolling isn't disabled in iOS6+
9972      docElement.offsetHeight;
9973    } else {
9974      div.parentNode.removeChild(div);
9975    }
9976
9977    return !!ret;
9978
9979  }
9980
9981  ;
9982
9983  /**
9984   * testStyles injects an element with style element and some CSS rules
9985   *
9986   * @memberof Modernizr
9987   * @name Modernizr.testStyles
9988   * @optionName Modernizr.testStyles()
9989   * @optionProp testStyles
9990   * @access public
9991   * @function testStyles
9992   * @param {string} rule - String representing a css rule
9993   * @param {function} callback - A function that is used to test the injected element
9994   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
9995   * @param {string[]}
9995 [testnames] - An array of strings that are used as ids for the additional nodes
9996   * @returns {boolean}
9997   * @example
9998   *
9999   * `Modernizr.testStyles` takes a CSS rule and injects it onto the current page
10000   * along with (possibly multiple) DOM elements. This lets you check for features
10001   * 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).
10002   *
10003   * ```js
10004   * Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) {
10005   *   // elem is the first DOM node in the page (by default #modernizr)
10006   *   // rule is the first argument you supplied - the CSS rule in string form
10007   *
10008   *   addTest('widthworks', elem.style.width === '9px')
10009   * });
10010   * ```
10011   *
10012   * If your test requires multiple nodes, you can include a third argument
10013   * indicating how many additional div elements to include on the page. The
10014   * additional nodes are injected as children of the `elem` that is returned as
10015   * the first argument to the callback.
10016   *
10017   * ```js
10018   * Modernizr.testStyles('#modernizr {width: 1px}; #modernizr2 {width: 2px}', function(elem) {
10019   *   document.getElementById('modernizr').style.width === '1px'; // true
10020   *   document.getElementById('modernizr2').style.width === '2px'; // true
10021   *   elem.firstChild === document.getElementById('modernizr2'); // true
10022   * }, 1);
10023   * ```
10024   *
10025   * By default, all of the additional elements have an ID of `modernizr[n]`, where
10026   * `n` is its index (e.g. the first additional, second overall is `#modernizr2`,
10027   * the second additional is `#modernizr3`, etc.).
10028   * If you want to have more meaningful IDs for your function, you can provide
10029   * them as the fourth argument, as an array of strings
10030   *
10031   * ```js
10032   * Modernizr.testStyles('#foo {width: 10px}; #bar {height: 20px}', function(elem) {
10033   *   elem.firstChild === document.getElementById('foo'); // true
10034   *   elem.lastChild === document.getElementById('bar'); // true
10035   * }, 2, ['foo', 'bar']);
10036   * ```
10037   *
10038   */
10039
10040  var testStyles = ModernizrProto.testStyles = injectElementWithStyles;
10041  
10042
10043  /**
10044   * fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill.
10045   *
10046   * @access private
10047   * @function fnBind
10048   * @param {function} fn - a function you want to change `this` reference to
10049   * @param {object} that - the `this` you want to call the function with
10050   * @returns {function} The wrapped version of the supplied function
10051   */
10052
10053  function fnBind(fn, that) {
10054    return function() {
10055      return fn.apply(that, arguments);
10056    };
10057  }
10058
10059  ;
10060
10061  /**
10062   * testDOMProps is a generic DOM property test; if a browser supports
10063   *   a certain property, it won't return undefined for it.
10064   *
10065   * @access private
10066   * @function testDOMProps
10067   * @param {array.<string>} props - An array of properties to test for
10068   * @param {object} obj - An object or Element you want to use to test the parameters again
10069   * @param {boolean|object} elem - An Element to bind the property lookup again. Use `false` to prevent the check
10070   */
10071  function testDOMProps(props, obj, elem) {
10072    var item;
10073
10074    for (var i in props) {
10075      if (props[i] in obj) {
10076
10077        // return the property name as a string
10078        if (elem === false) {
10079          return props[i];
10080        }
10081
10082        item = obj[props[i]];
10083
10084        // let's bind a function
10085        if (is(item, 'function')) {
10086          // bind to obj unless overriden
10087          return fnBind(item, elem || obj);
10088        }
10089
10090        // return the unbound function or obj or value
10091        return item;
10092      }
10093    }
10094    return false;
10095  }
10096
10097  ;
10098
10099  /**
10100   * Create our "modernizr" element that we do most feature tests on.
10101   *
10102   * @access private
10103   */
10104
10105  var modElem = {
10106    elem: createElement('modernizr')
10107  };
10108
10109  // Clean up this element
10110  Modernizr._q.push(function() {
10111    delete modElem.elem;
10112  });
10113
10114  
10115
10116  var mStyle = {
10117    style: modElem.elem.style
10118  };
10119
10120  // kill ref for gc, must happen before mod.elem is removed, so we unshift on to
10121  // the front of the queue.
10122  Modernizr._q.unshift(function() {
10123    delete mStyle.style;
10124  });
10125
10126  
10127
10128  /**
10129   * domToCSS takes a camelCase string and converts it to kebab-case
10130   * e.g. boxSizing -> box-sizing
10131   *
10132   * @access private
10133   * @function domToCSS
10134   * @param {string} name - String name of camelCase prop we want to convert
10135   * @returns {string} The kebab-case version of the supplied name
10136   */
10137
10138  function domToCSS(name) {
10139    return name.replace(/([A-Z])/g, function(str, m1) {
10140      return '-' + m1.toLowerCase();
10141    }).replace(/^ms-/, '-ms-');
10142  }
10143  ;
10144
10145  /**
10146   * nativeTestProps allows for us to use native feature detection functionality if available.
10147   * some prefixed form, or false, in the case of an unsupported rule
10148   *
10149   * @access private
10150   * @function nativeTestProps
10151   * @param {array} props - An array of property names
10152   * @param {string} value - A string representing the value we want to check via @supports
10153   * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise
10154   */
10155
10156  // Accepts a list of property names and a single value
10157  // Returns `undefined` if native detection not available
10158  function nativeTestProps(props, value) {
10159    var i = props.length;
10160    // Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface
10161    if ('CSS' in window && 'supports' in window.CSS) {
10162      // Try every prefixed variant of the property
10163      while (i--) {
10164        if (window.CSS.supports(domToCSS(props[i]), value)) {
10165          return true;
10166        }
10167      }
10168      return false;
10169    }
10170    // Otherwise fall back to at-rule (for Opera 12.x)
10171    else if ('CSSSupportsRule' in window) {
10172      // Build a condition string for every prefixed variant
10173      var conditionText = [];
10174      while (i--) {
10175        conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');
10176      }
10177      conditionText = conditionText.join(' or ');
10178      return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {
10179        return getComputedStyle(node, null).position == 'absolute';
10180      });
10181    }
10182    return undefined;
10183  }
10184  ;
10185
10186  // testProps is a generic CSS / DOM property test.
10187
10188  // In testing support for a given CSS property, it's legit to test:
10189  //    `elem.style[styleName] !== undefined`
10190  // If the property is supported it will return an empty string,
10191  // if unsupported it will return undefined.
10192
10193  // We'll take advantage of this quick test and skip setting a style
10194  // on our modernizr element, but instead just testing undefined vs
10195  // empty string.
10196
10197  // Property names can be provided in either camelCase or kebab-case.
10198
10199  function testProps(props, prefixed, value, skipValueTest) {
10200    skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;
10201
10202    // Try native detect first
10203    if (!is(value, 'undefined')) {
10204      var result = nativeTestProps(props, value);
10205      if (!is(result, 'undefined')) {
10206        return result;
10207      }
10208    }
10209
10210    // Otherwise do it properly
10211    var afterInit, i, propsLength, prop, before;
10212
10213    // If we don't have a style element, that means we're running async or after
10214    // the core tests, so we'll need to create our own elements to use
10215
10216    // inside of an SVG element, in certain browsers, the `style` element is only
10217    // defined for valid tags. Therefore, if `modernizr` does not have one, we
10218    // fall back to a less used element and hope for the best.
10219    // for strict XHTML browsers the hardly used samp element is used
10220    var elems = ['modernizr', 'tspan', 'samp'];
10221    while (!mStyle.style && elems.length) {
10222      afterInit = true;
10223      mStyle.modElem = createElement(elems.shift());
10224      mStyle.style = mStyle.modElem.style;
10225    }
10226
10227    // Delete the objects if we created them.
10228    function cleanElems() {
10229      if (afterInit) {
10230        delete mStyle.style;
10231        delete mStyle.modElem;
10232      }
10233    }
10234
10235    propsLength = props.length;
10236    for (i = 0; i < propsLength; i++) {
10237      prop = props[i];
10238      before = mStyle.style[prop];
10239
10240      if (contains(prop, '-')) {
10241        prop = cssToDOM(prop);
10242      }
10243
10244      if (mStyle.style[prop] !== undefined) {
10245
10246        // If value to test has been passed in, do a set-and-check test.
10247        // 0 (integer) is a valid property value, so check that `value` isn't
10248        // undefined, rather than just checking it's truthy.
10249        if (!skipValueTest && !is(value, 'undefined')) {
10250
10251          // Needs a try catch block because of old IE. This is slow, but will
10252          // be avoided in most cases because `skipValueTest` will be used.
10253          try {
10254            mStyle.style[prop] = value;
10255          } catch (e) {}
10256
10257          // If the property value has changed, we assume the value used is
10258          // supported. If `value` is empty string, it'll fail here (because
10259          // it hasn't changed), which matches how browsers have implemented
10260          // CSS.supports()
10261          if (mStyle.style[prop] != before) {
10262            cleanElems();
10263            return prefixed == 'pfx' ? prop : true;
10264          }
10265        }
10266        // Otherwise just return true, or the property name if this is a
10267        // `prefixed()` call
10268        else {
10269          cleanElems();
10270          return prefixed == 'pfx' ? prop : true;
10271        }
10272      }
10273    }
10274    cleanElems();
10275    return false;
10276  }
10277
10278  ;
10279
10280  /**
10281   * testProp() investigates whether a given style property is recognized
10282   * Property names can be provided in either camelCase or kebab-case.
10283   *
10284   * @memberof Modernizr
10285   * @name Modernizr.testProp
10286   * @access public
10287   * @optionName Modernizr.testProp()
10288   * @optionProp testProp
10289   * @function testProp
10290   * @param {string} prop - Name of the CSS property to check
10291   * @param {string} [value] - Name of the CSS value to check
10292   * @param {boolean} [useValue] - Whether or not to check the value if @supports isn't supported
10293   * @returns {boolean}
10294   * @example
10295   *
10296   * Just like [testAllProps](#modernizr-testallprops), only it does not check any vendor prefixed
10297   * version of the string.
10298   *
10299   * Note that the property name must be provided in camelCase (e.g. boxSizing not box-sizing)
10300   *
10301   * ```js
10302   * Modernizr.testProp('pointerEvents')  // true
10303   * ```
10304   *
10305   * You can also provide a value as an optional second argument to check if a
10306   * specific value is supported
10307   *
10308   * ```js
10309   * Modernizr.testProp('pointerEvents', 'none') // true
10310   * Modernizr.testProp('pointerEvents', 'penguin') // false
10311   * ```
10312   */
10313
10314  var testProp = ModernizrProto.testProp = function(prop, value, useValue) {
10315    return testProps([prop], undefined, value, useValue);
10316  };
10317  
10318
10319  /**
10320   * testPropsAll tests a list of DOM properties we want to check against.
10321   * We specify literally ALL possible (known and/or likely) properties on
10322   * the element including the non-vendor prefixed one, for forward-
10323   * compatibility.
10324   *
10325   * @access private
10326   * @function testPropsAll
10327   * @param {string} prop - A string of the property to test for
10328   * @param {string|object} [prefixed] - An object to check the prefixed properties on. Use a string to skip
10329   * @param {HTMLElement|SVGElement} [elem] - An element used to test the property and value against
10330   * @param {string} [value] - A string of a css value
10331   * @param {boolean} [skipValueTest] - An boolean representing if you want to test if value sticks when set
10332   */
10333  function testPropsAll(prop, prefixed, elem, value, skipValueTest) {
10334
10335    var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
10336    props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
10337
10338    // did they call .prefixed('boxSizing') or are we just testing a prop?
10339    if (is(prefixed, 'string') || is(prefixed, 'undefined')) {
10340      return testProps(props, prefixed, value, skipValueTest);
10341
10342      // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
10343    } else {
10344      props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
10345      return testDOMProps(props, prefixed, elem);
10346    }
10347  }
10348
10349  // Modernizr.testAllProps() investigates whether a given style property,
10350  // or any of its vendor-prefixed variants, is recognized
10351  //
10352  // Note that the property names must be provided in the camelCase variant.
10353  // Modernizr.testAllProps('boxSizing')
10354  ModernizrProto.testAllProps = testPropsAll;
10355
10356  
10357
10358  /**
10359   * prefixed returns the prefixed or nonprefixed property name variant of your input
10360   *
10361   * @memberof Modernizr
10362   * @name Modernizr.prefixed
10363   * @optionName Modernizr.prefixed()
10364   * @optionProp prefixed
10365   * @access public
10366   * @function prefixed
10367   * @param {string} prop - String name of the property to test for
10368   * @param {object} [obj] - An object to test for the prefixed properties on
10369   * @param {HTMLElement} [elem] - An element used to test specific properties against
10370   * @returns {string|false} The string representing the (possibly prefixed) valid
10371   * version of the property, or `false` when it is unsupported.
10372   * @example
10373   *
10374   * Modernizr.prefixed takes a string css value in the DOM style camelCase (as
10375   * opposed to the css style kebab-case) form and returns the (possibly prefixed)
10376   * version of that property that the browser actually supports.
10377   *
10378   * For example, in older Firefox...
10379   * ```js
10380   * prefixed('boxSizing')
10381   * ```
10382   * returns 'MozBoxSizing'
10383   *
10384   * In newer Firefox, as well as any other browser that support the unprefixed
10385   * version would simply return `boxSizing`. Any browser that does not support
10386   * the property at all, it will return `false`.
10387   *
10388   * By default, prefixed is checked against a DOM element. If you want to check
10389   * for a property on another object, just pass it as a second argument
10390   *
10391   * ```js
10392   * var rAF = prefixed('requestAnimationFrame', window);
10393   *
10394   * raf(function() {
10395   *  renderFunction();
10396   * })
10397   * ```
10398   *
10399   * Note that this will return _the actual function_ - not the name of the function.
10400   * If you need the actual name of the property, pass in `false` as a third argument
10401   *
10402   * ```js
10403   * var rAFProp = prefixed('requestAnimationFrame', window, false);
10404   *
10405   * rafProp === 'WebkitRequestAnimationFrame' // in older webkit
10406   * ```
10407   *
10408   * One common use case for prefixed is if you're trying to determine which transition
10409   * end event to bind to, you might do something like...
10410   * ```js
10411   * var transEndEventNames = {
10412   *     'WebkitTransition' : 'webkitTransitionEnd', * Saf 6, Android Browser
10413   *     'MozTransition'    : 'transitionend',       * only for FF < 15
10414   *     'transition'       : 'transitionend'        * IE10, Opera, Chrome, FF 15+, Saf 7+
10415   * };
10416   *
10417   * var transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
10418   * ```
10419   *
10420   * If you want a similar lookup, but in kebab-case, you can use [prefixedCSS](#modernizr-prefixedcss).
10421   */
10422
10423  var prefixed = ModernizrProto.prefixed = function(prop, obj, elem) {
10424    if (prop.indexOf('@') === 0) {
10425      return atRule(prop);
10426    }
10427
10428    if (prop.indexOf('-') != -1) {
10429      // Convert kebab-case to camelCase
10430      prop = cssToDOM(prop);
10431    }
10432    if (!obj) {
10433      return testPropsAll(prop, 'pfx');
10434    } else {
10435      // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
10436      return testPropsAll(prop, obj, elem);
10437    }
10438  };
10439
10440  
10441
10442  /**
10443   * testAllProps determines whether a given CSS property is supported in the browser
10444   *
10445   * @memberof Modernizr
10446   * @name Modernizr.testAllProps
10447   * @optionName Modernizr.testAllProps()
10448   * @optionProp testAllProps
10449   * @access public
10450   * @function testAllProps
10451   * @param {string} prop - String naming the property to test (either camelCase or kebab-case)
10452   * @param {string} [value] - String of the value to test
10453   * @param {boolean} [skipValueTest=false] - Whether to skip testing that the value is supported when using non-native detection
10454   * @example
10455   *
10456   * testAllProps determines whether a given CSS property, in some prefixed form,
10457   * is supported by the browser.
10458   *
10459   * ```js
10460   * testAllProps('boxSizing')  // true
10461   * ```
10462   *
10463   * It can optionally be given a CSS value in string form to test if a property
10464   * value is valid
10465   *
10466   * ```js
10467   * testAllProps('display', 'block') // true
10468   * testAllProps('display', 'penguin') // false
10469   * ```
10470   *
10471   * A boolean can be passed as a third parameter to skip the value check when
10472   * native detection (@supports) isn't available.
10473   *
10474   * ```js
10475   * testAllProps('shapeOutside', 'content-box', true);
10476   * ```
10477   */
10478
10479  function testAllProps(prop, value, skipValueTest) {
10480    return testPropsAll(prop, undefined, undefined, value, skipValueTest);
10481  }
10482  ModernizrProto.testAllProps = testAllProps;
10483  
10484/*!
10485{
10486  "name": "CSS Animations",
10487  "property": "cssanimations",
10488  "caniuse": "css-animation",
10489  "polyfills": ["transformie", "csssandpaper"],
10490  "tags": ["css"],
10491  "warnings": ["Android < 4 will pass this test, but can only animate a single property at a time"],
10492  "notes": [{
10493    "name" : "Article: 'Dispelling the Android CSS animation myths'",
10494    "href": "https://goo.gl/OGw5Gm"
10495  }]
10496}
10497!*/
10498/* DOC
10499Detects whether or not elements can be animated using CSS
10500*/
10501
10502  Modernizr.addTest('cssanimations', testAllProps('animationName', 'a', true));
10503
10504/*!
10505{
10506  "name": "CSS Transitions",
10507  "property": "csstransitions",
10508  "caniuse": "css-transitions",
10509  "tags": ["css"]
10510}
10511!*/
10512
10513  Modernizr.addTest('csstransitions', testAllProps('transition', 'all', true));
10514
10515/*!
10516{
10517  "name": "Touch Events",
10518  "property": "touchevents",
10519  "caniuse" : "touch",
10520  "tags": ["media", "attribute"],
10521  "notes": [{
10522    "name": "Touch Events spec",
10523    "href": "https://www.w3.org/TR/2013/WD-touch-events-20130124/"
10524  }],
10525  "warnings": [
10526    "Indicates if the browser supports the Touch Events spec, and does not necessarily reflect a touchscreen device"
10527  ],
10528  "knownBugs": [
10529    "False-positive on some configurations of Nokia N900",
10530    "False-positive on some BlackBerry 6.0 builds – https://github.com/Modernizr/Modernizr/issues/372#issuecomment-3112695"
10531  ]
10532}
10533!*/
10534/* DOC
10535Indicates if the browser supports the W3C Touch Events API.
10536
10537This *does not* necessarily reflect a touchscreen device:
10538
10539* Older touchscreen devices only emulate mouse events
10540* Modern IE touch devices implement the Pointer Events API instead: use `Modernizr.pointerevents` to detect support for that
10541* Some browsers & OS setups may enable touch APIs when no touchscreen is connected
10542* Future browsers may implement other event models for touch interactions
10543
10544See this article: [You Can't Detect A Touchscreen](http://www.stucox.com/blog/you-cant-detect-a-touchscreen/).
10545
10546It's recommended to bind both mouse and touch/pointer events simultaneously – see [this HTML5 Rocks tutorial](http://www.html5rocks.com/en/mobile/touchandmouse/).
10547
10548This test will also return `true` for Firefox 4 Multitouch support.
10549*/
10550
10551  // Chrome (desktop) used to lie about its support on this, but that has since been rectified: http://crbug.com/36415
10552  Modernizr.addTest('touchevents', function() {
10553    var bool;
10554    if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
10555      bool = true;
10556    } else {
10557      // include the 'heartz' as a way to have a non matching MQ to help terminate the join
10558      // https://git.io/vznFH
10559      var query = ['@media (', prefixes.join('touch-enabled),('), 'heartz', ')', '{#modernizr{top:9px;position:absolute}}'].join('');
10560      testStyles(query, function(node) {
10561        bool = node.offsetTop === 9;
10562      });
10563    }
10564    return bool;
10565  });
10566
10567
10568  // Run each test
10569  testRunner();
10570
10571  // Remove the "no-js" class if it exists
10572  setClasses(classes);
10573
10574  delete ModernizrProto.addTest;
10575  delete ModernizrProto.addAsyncTest;
10576
10577  // Run the things that are supposed to run after the tests
10578  for (var i = 0; i < Modernizr._q.length; i++) {
10579    Modernizr._q[i]();
10580  }
10581
10582  // Leak Modernizr namespace
10583  window.Modernizr = Modernizr;
10584
10585
10586;
10587
10588})(window, document);
10589$(function() {
10590    ParallaxScroll.init();
10591});
10592
10593// Credit: https://github.com/alumbo/jquery.parallax-scroll
10594var ParallaxScroll = {
10595    /* PUBLIC VARIABLES */
10596    showLogs: false,
10597    round: 1000,
10598
10599    /* PUBLIC FUNCTIONS */
10600    init: function() {
10601        this._log("init");
10602        if (this._inited) {
10603            this._log("Already Inited");
10604            this._inited = true;
10605            return;
10606        }
10607        this._requestAnimationFrame = (function(){
10608          return  window.requestAnimationFrame       || 
10609                  window.webkitRequestAnimationFrame || 
10610                  window.mozRequestAnimationFrame    || 
10611                  window.oRequestAnimationFrame      || 
10612                  window.msRequestAnimationFrame     || 
10613                  function(/* function */ callback, /* DOMElement */ element){
10614                      window.setTimeout(callback, 1000 / 60);
10615                  };
10616        })();
10617        this._onScroll(true);
10618    },
10619
10620    /* PRIVATE VARIABLES */
10621    _inited: false,
10622    _properties: ['x', 'y', 'z', 'rotateX', 'rotateY', 'rotateZ', 'scaleX', 'scaleY', 'scaleZ', 'scale'],
10623    _requestAnimationFrame:null,
10624
10625    /* PRIVATE FUNCTIONS */
10626    _log: function(message) {
10627        if (this.showLogs) console.log("Parallax Scroll / " + message);
10628    },
10629    _onScroll: function(noSmooth) {
10630        var scroll = $(document).scrollTop();
10631        var windowHeight = $(window).height();
10632        this._log("onScroll " + scroll);
10633        $("[data-parallax]").each($.proxy(function(index, el) {
10634            var $el = $(el);
10635            var properties = [];
10636            var applyProperties = false;
10637            var style = $el.data("style");
10638            if (style == undefined) {
10639                style = $el.attr("style") || "";
10640                $el.data("style", style);
10641            }
10642            var datas = [$el.data("parallax")];
10643            var iData;
10644            for(iData = 2; ; iData++) {
10645                if($el.data("parallax"+iData)) {
10646                    datas.push($el.data("parallax-"+iData));
10647                }
10648                else {
10649                    break;
10650                }
10651            }
10652            var datasLength = datas.length;
10653            for(iData = 0; iData < datasLength; iData ++) {
10654                var data = datas[iData];
10655                var scrollFrom = data["from-scroll"];
10656                if (scrollFrom == undefined) scrollFrom = Math.max(0, $(el).offset().top - windowHeight);
10657                scrollFrom = scrollFrom | 0;
10658                var scrollDistance = data["distance"];
10659                var scrollTo = data["to-scroll"];
10660                if (scrollDistance == undefined && scrollTo == undefined) scrollDistance = windowHeight;
10661                scrollDistance = Math.max(scrollDistance | 0, 1);
10662                var easing = data["easing"];
10663                var easingReturn = data["easing-return"];
10664                if (easing == undefined || !$.easing|| !$.easing[easing]) easing = null;
10665                if (easingReturn == undefined || !$.easing|| !$.easing[easingReturn]) easingReturn = easing;
10666                if (easing) {
10667                    var totalTime = data["duration"];
10668                    if (totalTime == undefined) totalTime = scrollDistance;
10669                    totalTime = Math.max(totalTime | 0, 1);
10670                    var totalTimeReturn = data["duration-return"];
10671                    if (totalTimeReturn == undefined) totalTimeReturn = totalTime;
10672                    scrollDistance = 1;
10673                    var currentTime = $el.data("current-time");
10674                    if(currentTime == undefined) currentTime = 0;
10675                }
10676                if (scrollTo == undefined) scrollTo = scrollFrom + scrollDistance;
10677                scrollTo = scrollTo | 0;
10678                var smoothness = data["smoothness"];
10679                if (smoothness == undefined) smoothness = 30;
10680                smoothness = smoothness | 0;
10681                if (noSmooth || smoothness == 0) smoothness = 1;
10682                smoothness = smoothness | 0;
10683                var scrollCurrent = scroll;
10684                scrollCurrent = Math.max(scrollCurrent, scrollFrom);
10685                scrollCurrent = Math.min(scrollCurrent, scrollTo);
10686                if(easing) {
10687                    if($el.data("sens") == undefined) $el.data("sens", "back");
10688                    if(scrollCurrent>scrollFrom) {
10689                        if($el.data("sens") == "back") {
10690                            currentTime = 1;
10691                            $el.data("sens", "go");
10692                        }
10693                        else {
10694                            currentTime++;
10695                        }
10696                    }
10697                    if(scrollCurrent<scrollTo) {
10698                        if($el.data("sens") == "go") {
10699                            currentTime = 1;
10700                            $el.data("sens", "back");
10701                        }
10702                        else {
10703                            currentTime++;
10704                        }
10705                    }
10706                    if(noSmooth) currentTime = totalTime;
10707                    $el.data("current-time", currentTime);
10708                }
10709                this._properties.map($.proxy(function(prop) {
10710                    var defaultProp = 0;
10711                    var to = data[prop];
10712                    if (to == undefined) return;
10713                    if(prop=="scale" || prop=="scaleX" || prop=="scaleY" || prop=="scaleZ" ) {
10714                        defaultProp = 1;
10715                    }
10716                    else {
10717                        to = to | 0;
10718                    }
10719                    var prev = $el.data("_" + prop);
10720                    if (prev == undefined) prev = defaultProp;
10721                    var next = ((to-defaultProp) * ((scrollCurrent - scrollFrom) / (scrollTo - scrollFrom))) + defaultProp;
10722                    var val = prev + (next - prev) / smoothness;
10723                    if(easing && currentTime>0 && currentTime<=totalTime) {
10724                        var from = defaultProp;
10725                        if($el.data("sens") == "back") {
10726                            from = to;
10727                            to = -to;
10728                            easing = easingReturn;
10729                            totalTime = totalTimeReturn;
10730                        }
10731                        val = $.easing[easing](null, currentTime, from, to, totalTime);
10732                    }
10733                    val = Math.ceil(val * this.round) / this.round;
10734                    if(val==prev&&next==to) val = to;
10735                    if(!properties[prop]) properties[prop] = 0;
10736                    properties[prop] += val;
10737                    if (prev != properties[prop]) {
10738                        $el.data("_" + prop, properties[prop]);
10739                        applyProperties = true;
10740                    }
10741                }, this));
10742            }
10743            if (applyProperties) {
10744                if (properties["z"] != undefined) {
10745                    var perspective = data["perspective"];
10746                    if (perspective == undefined) perspective = 800;
10747                    var $parent = $el.parent();
10748                    if(!$parent.data("style")) $parent.data("style", $parent.attr("style") || "");
10749                    $parent.attr("style", "perspective:" + perspective + "px; -webkit-perspective:" + perspective + "px; "+ $parent.data("style"));
10750                }
10751                if(properties["scaleX"] == undefined) properties["scaleX"] = 1;
10752                if(properties["scaleY"] == undefined) properties["scaleY"] = 1;
10753                if(properties["scaleZ"] == undefined) properties["scaleZ"] = 1;
10754                if (properties["scale"] != undefined) {
10755                    properties["scaleX"] *= properties["scale"];
10756                    properties["scaleY"] *= properties["scale"];
10757                    properties["scaleZ"] *= properties["scale"];
10758                }
10759                var translate3d = "translate3d(" + (properties["x"] ? properties["x"] : 0) + "px, " + (properties["y"] ? properties["y"] : 0) + "px, " + (properties["z"] ? properties["z"] : 0) + "px)";
10760                var rotate3d = "rotateX(" + (properties["rotateX"] ? properties["rotateX"] : 0) + "deg) rotateY(" + (properties["rotateY"] ? properties["rotateY"] : 0) + "deg) rotateZ(" + (properties["rotateZ"] ? properties["rotateZ"] : 0) + "deg)";
10761                var scale3d = "scaleX(" + properties["scaleX"] + ") scaleY(" + properties["scaleY"] + ") scaleZ(" + properties["scaleZ"] + ")";
10762                var cssTransform = translate3d + " " + rotate3d + " " + scale3d + ";";
10763                this._log(cssTransform);
10764                $el.attr("style", "transform:" + cssTransform + " -webkit-transform:" + cssTransform + " " + style);
10765            }
10766        }, this));
10767        if(window.requestAnimationFrame) {
10768            window.requestAnimationFrame($.proxy(this._onScroll, this, false));
10769        }
10770        else {
10771            this._requestAnimationFrame($.proxy(this._onScroll, this, false));
10772        }
10773    }
10774};
10775;
10776(function($, window, undefined) {
10777
10778	'use strict';
10779
10780	// global
10781	var Modernizr = window.Modernizr,
10782		$body = $('body');
10783
10784	$.DLMenu = function(options, element) {
10785		this.$el = $(element);
10786		this._init(options);
10787	};
10788
10789	$.DLMenu.defaults = {
10790		animationClasses: {
10791			classin: 'mk-vm-animate-in-' + mk_vertical_header_anim,
10792			classout: 'mk-vm-animate-out-' + mk_vertical_header_anim
10793		},
10794		onLevelClick: function(el, name) {
10795			return false;
10796		},
10797		onLinkClick: function(el, ev) {
10798			return false;
10799		}
10800	};
10801
10802	$.DLMenu.prototype = {
10803		_init: function(options) {
10804
10805			this.options = $.extend(true, {}, $.DLMenu.defaults, options);
10806			this._config();
10807
10808			var animEndEventNames = {
10809					'WebkitAnimation': 'webkitAnimationEnd',
10810					'OAnimation': 'oAnimationEnd',
10811					'msAnimation': 'MSAnimationEnd',
10812					'animation': 'animationend'
10813				},
10814				transEndEventNames = {
10815					'WebkitTransition': 'webkitTransitionEnd',
10816					'MozTransition': 'transitionend',
10817					'OTransition': 'oTransitionEnd',
10818					'msTransition': 'MSTransitionEnd',
10819					'transition': 'transitionend'
10820				};
10821
10822			this.animEndEventName = animEndEventNames[Modernizr.prefixed('animation')] + '.dlmenu';
10823			this.transEndEventName = transEndEventNames[Modernizr.prefixed('transition')] + '.dlmenu';
10824
10825			this.animEndEventNameUnsufixed = animEndEventNames[Modernizr.prefixed('animation')];
10826			this.transEndEventNameUnsufixed = transEndEventNames[Modernizr.prefixed('transition')];
10827
10828			this.supportAnimations = Modernizr.cssanimations;
10829			this.supportTransitions = Modernizr.csstransitions;
10830
10831			this._initEvents();
10832
10833		},
10834		_config: function() {
10835			this.open = false;
10836			this.$trigger = this.$el.children('.mk-vm-trigger');
10837			this.$menu = this.$el.children('ul.mk-vm-menu');
10838			this.$menuitems = this.$menu.find('li:not(.mk-vm-back)');
10839			this.$back = this.$menu.find('li.mk-vm-back');
10840		},
10841		_initEvents: function() {
10842
10843			var self = this;
10844			
10845			$('.mk-vm-menuwrapper a').on('transitionend', function(event) {
10846				event.stopPropagation();
10847			});
10848
10849			this.$menuitems.on('click.dlmenu', 'a', function(event) {
10850
10851				// Breaks smooth scroll in vertical menu
10852				// event.stopPropagation();
10853
10854				var $item = $(event.delegateTarget),
10855					$submenu = $(event.currentTarget).siblings('ul.sub-menu');
10856
10857				if ($submenu.length > 0) {
10858					var $flyin = $submenu.clone().css('opacity', 0).insertAfter(self.$menu);
10859					var onAnimationEndFn = function() {
10860						var $parent = $item.parents('.mk-vm-subviewopen:first');
10861						self.$menu.off(self.animEndEventName).removeClass(self.options.animationClasses.classout).addClass('mk-vm-subview');
10862						$item.addClass('mk-vm-subviewopen')
10863						$parent.removeClass('mk-vm-subviewopen').addClass('mk-vm-subview');
10864						$flyin.remove();
10865
10866						// Redraw for firefox issues
10867						var $txt = $item.find('.meni-item-text');
10868						$txt.css('opacity', 0.99);
10869						setTimeout(function() { $txt.css('opacity', 1) }, 0);
10870					};
10871
10872					setTimeout(function() {
10873						$flyin.addClass(self.options.animationClasses.classin);
10874						self.$menu.addClass(self.options.animationClasses.classout);
10875						if (self.supportAnimations) {
10876							self.$menu.on(self.animEndEventName, onAnimationEndFn);
10877						} else {
10878							onAnimationEndFn.call();
10879						}
10880
10881						self.options.onLevelClick($item, $item.children('a:first').text());
10882					});
10883
10884
10885					// This caused firefox issue. Test properly if need to bring it back
10886					// if (self.open) {
10887					// 	self._closeMenu();
10888					// } else {
10889					// 	self._openMenu();
10890					// }
10891
10892					return false;
10893
10894				} else {
10895					self.options.onLinkClick($item, event);
10896				}
10897
10898			});
10899
10900
10901			// this.$trigger.on('click.dlmenu', function() {
10902
10903			// 	if (self.open) {
10904			// 		self._closeMenu();
10905			// 	} else {
10906			// 		// if( ! $(this).hasClass('menu-item-has-children') ) return false;
10907			// 		self._openMenu();
10908			// 	}
10909			// 	return false;
10910
10911			// });
10912
10913			this.$back.on('click.dlmenu', function(event) {
10914
10915				var $this = $(this),
10916					$submenu = $this.parents('ul.sub-menu:first'),
10917					$item = $submenu.parent(),
10918
10919					$flyin = $submenu.clone().insertAfter(self.$menu);
10920
10921				var onAnimationEndFn = function() {
10922					self.$menu.off(self.animEndEventName).removeClass(self.options.animationClasses.classin);
10923					$flyin.remove();
10924				};
10925
10926				setTimeout(function() {
10927					$flyin.addClass(self.options.animationClasses.classout);
10928					self.$menu.addClass(self.options.animationClasses.classin);
10929					if (self.supportAnimations) {
10930						self.$menu.on(self.animEndEventName, onAnimationEndFn);
10931					} else {
10932						onAnimationEndFn.call();
10933					}
10934
10935					$item.removeClass('mk-vm-subviewopen');
10936
10937					var $subview = $this.parents('.mk-vm-subview:first');
10938					if ($subview.is('li')) {
10939						$subview.addClass('mk-vm-subviewopen');
10940					}
10941					$subview.removeClass('mk-vm-subview');
10942				});
10943
10944				return false;
10945
10946			});
10947
10948		},
10949		closeMenu: function() {
10950			if (this.open) {
10951				this._closeMenu();
10952			}
10953		},
10954		_closeMenu: function() {
10955			var self = this,
10956				onTransitionEndFn = function() {
10957					self.$menu.off(self.transEndEventName);
10958					self._resetMenu();
10959				};
10960
10961			this.$menu.removeClass('mk-vm-menuopen');
10962			this.$menu.addClass('mk-vm-menu-toggle');
10963			this.$trigger.removeClass('mk-vm-active');
10964
10965			if (this.supportTransitions) {
10966				this.$menu.on(this.transEndEventName, onTransitionEndFn);
10967			} else {
10968				onTransitionEndFn.call();
10969			}
10970
10971			this.open = false;
10972		},
10973		openMenu: function() {
10974			if (!this.open) {
10975				this._openMenu();
10976			}
10977		},
10978		_openMenu: function() {
10979			var self = this;
10980			$body.off('click').on('click.dlmenu', function() {
10981				self._closeMenu();
10982			});
10983			this.$menu.addClass('mk-vm-menuopen mk-vm-menu-toggle').on(this.transEndEventName, function() {
10984				$(this).removeClass('mk-vm-menu-toggle');
10985			});
10986			this.$trigger.addClass('mk-vm-active');
10987			this.open = true;
10988		},
10989		_resetMenu: function() {
10990			this.$menu.removeClass('mk-vm-subview');
10991			this.$menuitems.removeClass('mk-vm-subview mk-vm-subviewopen');
10992		}
10993	};
10994
10995	var logError = function(message) {
10996		if (window.console) {
10997			window.console.error(message);
10998		}
10999	};
11000
11001	$.fn.dlmenu = function(options) {
11002		if (typeof options === 'string') {
11003			var args = Array.prototype.slice.call(arguments, 1);
11004			this.each(function() {
11005				var instance = $.data(this, 'dlmenu');
11006				if (!instance) {
11007					logError("cannot call methods on dlmenu prior to initialization; " +
11008						"attempted to call method '" + options + "'");
11009					return;
11010				}
11011				if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
11012					logError("no such method '" + options + "' for dlmenu instance");
11013					return;
11014				}
11015				instance[options].apply(instance, args);
11016			});
11017		} else {
11018			this.each(function() {
11019				var instance = $.data(this, 'dlmenu');
11020				if (instance) {
11021					instance._init();
11022				} else {
11023					instance = $.data(this, 'dlmenu', new $.DLMenu(options, this));
11024				}
11025			});
11026		}
11027		return this;
11028	};
11029
11030})(jQuery, window);
11031( function($) {
11032    'use strict';
11033
11034	/* 
11035	 * Define popup / hover states manually to prevent click for IE on touchdevices
11036	 */
11037
11038	$('.mk-main-navigation .menu-item-has-children').children('a').attr('aria-haspopup', 'true'); 
11039	$('.animated-column-item').attr('aria-haspopup', 'true');
11040
11041})( jQuery );
11042(function($) {
11043    'use strict';
11044
11045    var Accordion = function(el) { 
11046        // Private
11047        var that = this,
11048            $el = $(el),
11049            initial = $el.data('initialindex'),
11050            timeout;
11051
11052        // Public
11053        this.$el = $el;
11054        this.$single = $('.' + this.dom.single, $el);
11055        this.isExpendable = ($el.data('style') === 'toggle-action');
11056
11057        // Init 
11058        this.bindClicks();
11059        // Reveal initial tab on load event (wait for possible images inside)
11060        $(window).on('load', function() {
11061            if( initial !== -1 ) that.show(that.$single.eq(initial), true)
11062        });
11063        $(window).on('resize', function() {
11064            clearTimeout(timeout);
11065            timeout = setTimeout(that.bindClicks.bind(that), 500);
11066        }); 
11067    }
11068
11069    Accordion.prototype.dom = {
11070        // only class names please!
11071        single        : 'mk-accordion-single',
11072        tab           : 'mk-accordion-tab',
11073        pane          : 'mk-accordion-pane',
11074        current       : 'current',
11075        mobileToggle  : 'mobile-false',
11076        mobileBreakPoint : 767
11077    }
11078
11079    Accordion.prototype.bindClicks = function() {
11080        // Prevent multiple events binding
11081        this.$single.off('click', '.' + this.dom.tab);
11082
11083        if( !(window.matchMedia('(max-width: ' + this.dom.mobileBreakPoint +'px)').matches 
11084          && this.$el.hasClass(this.dom.mobileToggle)) ) {
11085
11086            this.$single.on('click', '.' + this.dom.tab, this.handleEvent.bind(this));
11087            // When website is loaded in mobile view and resized to desktop 'current' will 
11088            // inherit display: none from css. Repair it by calling show() on this element
11089            var $current = $('.' + this.dom.current, this.$el);
11090            if($('.' + this.dom.pane, $current).css('display') === 'none') this.show($current);
11091        }
11092    }
11093
11094    Accordion.prototype.handleEvent = function(e) {
11095        e.preventDefault();
11096        e.stopPropagation();
11097
11098        var $single = $(e.delegateTarget);
11099
11100        if(!$single.hasClass(this.dom.current)) {
11101            this.show($single);
11102        }
11103        else {
11104            if(this.isExpendable) this.hide($single);
11105        }
11106    }
11107
11108    Accordion.prototype.hide = function($single) {
11109        $single.removeClass(this.dom.current);
11110        $('.' + this.dom.pane, $single).slideUp();
11111    }
11112
11113    Accordion.prototype.show = function($single, initial) {
11114        // hide currently opened tab
11115        if(!this.isExpendable) {
11116            var that = this;
11117            this.hide($('.' + this.dom.current, that.$el));
11118        }
11119
11120        $single.addClass(this.dom.current);
11121        $('.' + this.dom.pane, $single).slideDown('', function() {
11122            if ( initial || ! $(this).parents('.mk-accordion').hasClass('scroll-click') ) {
11123                return;
11124            }
11125
11126            if (typeof $single.prev() === 'undefined') {
11127                $single = $single.prev()
11128            }
11129
11130            window.scrollTo({ top: $single.offset().top - 100, left: 0, behavior: 'smooth' });
11131        });
11132    }
11133
11134
11135
11136    // ///////////////////////////////////////
11137    //
11138    // Apply to:
11139    //
11140    // ///////////////////////////////////////
11141
11142	function init() {
11143		$('.mk-accordion').each(function() {
11144			new Accordion(this);
11145		});
11146	}
11147
11148	init();
11149	$(window).on('vc_reload', init);
11150
11151})(jQuery);
11152
11153(function($) {
11154
11155    'use strict';
11156
11157    var SkillDiagram = function( el ) {
11158        this.el = el;
11159    }
11160
11161    SkillDiagram.prototype = {
11162        init : function() {
11163            this.cacheElements();
11164            this.createDiagram();
11165            this.$skills.each( this.createSkill.bind( this ) );
11166        },
11167
11168        cacheElements : function() {
11169            this.$el = $( this.el );
11170            this.$skills = this.$el.find( '.mk-meter-arch');
11171            this.config  = this.$el.data();
11172            this.config.radius = this.config.dimension / 2;
11173        },
11174
11175        random : function( l, u ) {
11176            return Math.floor( ( Math.random() * ( u - l + 1 ) ) + l );
11177        },
11178
11179        createDiagram : function() {
11180            var self = this;
11181            $(this.el).find('svg').remove();
11182
11183            this.diagram = Raphael( this.el, this.config.dimension, this.config.dimension );
11184
11185            // Make svg scalable in different screen sizes
11186            this.diagram.setViewBox(0,0,this.config.dimension,this.config.dimension,true);
11187            this.diagram.setSize('90%', '90%');
11188
11189            this.diagram.circle( this.config.radius, this.config.radius, 80 ).attr({
11190                stroke: 'none',
11191                fill: this.config.circleColor
11192            });
11193
11194            // Export title
11195            this.title = this.diagram.text( this.config.radius, this.config.radius, this.config.defaultText ).attr({
11196                font: "22px helvetica",
11197                fill: this.config.defaultTextColor
11198            }).toFront();
11199
11200            this.diagram.customAttributes.arc = function(value, color, rad){
11201                var v = 3.6 * value,
11202                    alpha = v == 360 ? 359.99 : v,
11203                    r  = self.random( 91, 240 ),
11204                    a  = (r - alpha) * Math.PI/180,
11205                    b  = r * Math.PI/180,
11206                    sx = self.config.radius + rad * Math.cos(b),
11207                    sy = self.config.radius - rad * Math.sin(b),
11208                    x  = self.config.radius + rad * Math.cos(a),
11209                    y  = self.config.radius - rad * Math.sin(a),
11210                    path = [['M', sx, sy], ['A', rad, rad, 0, +(alpha > 180), 1, x, y]];
11211
11212                return {
11213                    path: path,
11214                    stroke: color
11215                }
11216            }
11217        },
11218
11219        createSkill : function( id, el ) {
11220            var self   = this,
11221                $this  = $( el ),
11222                config = $this.data(),
11223                radMin = 72,
11224                radVal = 27,
11225                newRad = radMin + ( radVal * (id + 1) );
11226
11227            var $path = this.diagram.path().attr({
11228                'stroke-width': 28,
11229                arc: [config.percent, config.color, newRad]
11230            });
11231
11232            $path.on('mouseover', function() {
11233                self.showSkill( this, config.name, config.percent );
11234            }).on('mouseout', function() {
11235                self.hideSkill( this )
11236            });
11237        },
11238
11239        showSkill : function( self, name, percent ) {
11240            var $this = self,
11241                time = 250;
11242
11243            //solves IE problem
11244            if(Raphael.type != 'VML') $this.toFront();
11245
11246            $this.animate({
11247                'stroke-width': 50,
11248                'opacity': 0.9,
11249            }, 800, 'elastic' );
11250
11251            this.title.stop()
11252                .animate({ opacity: 0 }, time, '>', function(){
11253                    this.attr({ text: name + '\n' + percent + '%' }).animate({ opacity: 1 }, time, '<');
11254                }).toFront();
11255        },
11256
11257        hideSkill : function( self ) {
11258            var $this = self,
11259                self = this,
11260                time = 250;
11261
11262            $this.stop().animate({
11263                'stroke-width': 28,
11264                opacity: 1
11265            }, time * 4, 'elastic' );
11266
11267            self.title.stop()
11268                .animate({ opacity: 0 }, time, '>', function(){
11269                    self.title.attr({ text: self.config.defaultText })
11270                    .animate({ opacity: 1 }, time, '<');
11271                });
11272        }
11273    }
11274
11275    var init = function init() {
11276        if( typeof Raphael === 'undefined' ) return;
11277        $( '.mk-skill-diagram' ).each( function() {
11278            var diagram = new SkillDiagram( this );
11279                diagram.init();
11280        });
11281    }
11282
11283    init();
11284    $(window).on('vc_reload', init);
11285
11286})(jQuery);
11287
11288/*
11289 * Tab delegation 
11290 * Action for modules when we don't have access to chidren DOM on processing templates
11291 * yet we want ass option of opening link in new tab. 
11292 * Helpful for use with external widgets like flickr
11293 */
11294
11295(function($) {
11296
11297	'use strict';
11298
11299	$( '[data-js="tab-delegation"]' ).each( tabDelegation );
11300
11301	function tabDelegation() {
11302		var $this = $( this ),
11303			data  = $this.data();
11304
11305		// Create delegation on parent element to affect async loaded children
11306		if( data.tab ) $this.on( 'click', 'a', openInTab );
11307	}
11308
11309	function openInTab( e ) {
11310		e.preventDefault(); 
11311
11312		var $this = $( this ),
11313			url = $this.attr( 'href' );
11314
11315		window.open( url, '_blank' );
11316	}
11317
11318})(jQuery);
11319(function($) {
11320    'use strict';
11321
11322    var init = function init() {
11323        var Toggle = function(el) {
11324        var that = this,
11325            $el = $(el);
11326
11327            this.$el = $el;
11328            $el.on('click', function() {
11329                $el.hasClass('active-toggle') ? that.close() : that.open()
11330            });
11331        };
11332
11333        Toggle.prototype.dom = {
11334            pane   : 'mk-toggle-pane',
11335            active : 'active-toggle'
11336        };
11337
11338        Toggle.prototype.open = function() {
11339            var $this = this.$el;
11340            $this.addClass(this.dom.active);
11341            $this.siblings('.' + this.dom.pane).slideDown(200);
11342        };
11343
11344        Toggle.prototype.close = function() {
11345            var $this = this.$el;
11346            $this.removeClass(this.dom.active);
11347            $this.siblings('.' + this.dom.pane).slideUp(200);
11348        };
11349
11350        // Apply to.
11351        var $toggle = $('.mk-toggle-title');
11352
11353        if(!$toggle.length) return;
11354
11355        $toggle.each(function() {
11356            new Toggle(this);
11357        });
11358    }
11359    $(window).on('load vc_reload', init);
11360
11361})(jQuery);
11362
11363//////////////////////////////////////////////////////////////////////////
11364//
11365//   Init all scripts
11366//
11367//////////////////////////////////////////////////////////////////////////
11368
11369// This is bad but we don't have other access to this scope.
11370// Ajax Portfolio  is defined as plugin and on success needs these to be reinited
11371// We'll refactor all of this.
11372window.ajaxInit = function() {
11373    mk_lightbox_init();
11374    mk_click_events();
11375    mk_social_share_global();
11376   // mk_social_share();
11377    mk_gallery();
11378    loop_audio_init();
11379};
11380
11381window.ajaxDelayedInit = function() {
11382    mk_flexslider_init();
11383    // mk_portfolio_ajax();
11384};
11385
11386$(document).ready(function() {
11387    mk_lightbox_init();
11388    mk_login_form();
11389    mk_backgrounds_parallax();
11390    mk_flexslider_init();
11391    mk_event_countdown();
11392    mk_skill_meter();
11393    mk_milestone();
11394    mk_ajax_search();
11395    mk_hover_events();
11396    mk_portfolio_ajax();
11397    product_loop_add_cart();
11398  //  mk_social_share();
11399    mk_portfolio_widget();
11400    mk_contact_form();
11401    mk_blog_carousel();
11402    mk_header_searchform();
11403    mk_click_events();
11404    mk_text_typer();
11405    mk_tab_slider_func();
11406    mkPositionSidebar();
11407
11408    $(window).on('load', function() {
11409        mk_unfold_footer();
11410        mk_tabs();
11411        mk_accordion_toggles_tooltip();
11412        mk_gallery();
11413        mk_theatre_responsive_calculator();
11414        mk_tabs_responsive();
11415        mk_start_tour_resize();
11416        mk_header_social_resize();
11417        mk_page_section_social_video_bg();
11418        loop_audio_init();
11419        mk_one_page_scroller();
11420
11421        setTimeout(function() {
11422            /*
11423                Somehow the values are not correctly updated for the screens
11424                and we need to put setTimeout to fix the issue
11425            */
11426            mk_mobile_tablet_responsive_calculator();
11427        }, 300);
11428
11429        console.log("ready for rock");
11430    });
11431
11432
11433    var onDebouncedResize = function() {
11434        mk_theatre_responsive_calculator();
11435        mk_mobile_tablet_responsive_calculator();
11436        mk_tabs_responsive();
11437        mk_accordion_toggles_tooltip();
11438        mk_start_tour_resize();
11439        mk_header_social_resize();
11440
11441        setTimeout(function() {
11442            mk_unfold_footer();
11443        }, 300);
11444    };
11445
11446    var debounceResize = null;
11447    $(window).on("resize", function() {
11448        if( debounceResize !== null ) { clearTimeout( debounceResize ); }
11449        debounceResize = setTimeout( onDebouncedResize, 300 );
11450    });
11451
11452    var onDebouncedScroll = function() {
11453        mk_skill_meter();
11454        //TODO: Ask to Bart how we can call javascript component
11455        //mk_charts();
11456        mk_milestone();
11457    };
11458
11459    var debounceScroll = null;
11460    $(window).on("scroll", function() {
11461        if( debounceScroll !== null ) { clearTimeout( debounceScroll ); }
11462        debounceScroll = setTimeout( onDebouncedScroll, 100 );
11463    });
11464
11465    if (MK.utils.isMobile()) {
11466        $('body').addClass('no-transform');
11467    }
11468
11469});
11470
11471/* VC frontend editor  */
11472/* -------------------------------------------------------------------- */
11473$(window).on("vc_reload",function () {
11474    mk_flexslider_init();
11475    loop_audio_init();
11476    mk_tab_slider_func();
11477    mk_event_countdown();
11478    videoLoadState();
11479    mk_page_section_social_video_bg();
11480    mk_hover_events();
11481
11482    setTimeout(function() {
11483        mkPositionSidebar();
11484    }, 200);
11485});
11486
11487// Replace this if new event for remove found.
11488$( document ).on( 'click', '.vc_control-btn-delete', function() {
11489    $( window ).trigger( 'vc_reload' );
11490} );
11491
11492$( document ).on( 'sortupdate', '.ui-sortable', function() {
11493    $( window ).trigger( 'vc_reload' );
11494} );
11495
11496/* Typer */
11497/* -------------------------------------------------------------------- */
11498function mk_text_typer() {
11499
11500    "use strict";
11501
11502    $('[data-typer-targets]').each(function() {
11503        var that = this;
11504        MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.typed.js' ], function() {
11505            var $this = $(that),
11506                $first_string = [$this.text()],
11507                $rest_strings = $this.attr('data-typer-targets').split(','),
11508                $strings = $first_string.concat($rest_strings);
11509
11510            $this.text('');
11511
11512            $this.typed({
11513                strings: $strings,
11514                typeSpeed: 30, // typing speed
11515                backDelay: 1200, // pause before backspacing
11516                loop: true, // loop on or off (true or false)
11517                loopCount: false, // number of loops, false = infinite
11518            });
11519        });
11520    });
11521}
11522
11523
11524
11525/* Tab Slider */
11526/* -------------------------------------------------------------------- */
11527
11528function mk_tab_slider_func() {
11529
11530    "use strict";
11531
11532    $('.mk-tab-slider').each(function() {
11533        var that = this;
11534
11535        MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.swiper.js' ], function() {
11536            var $this = $(that),
11537                id = $this.data('id'),
11538                $autoplayTime = $this.data('autoplay'),
11539                $content = $('.mk-slider-content');
11540
11541            var mk_tab_slider = $this.swiper({
11542                wrapperClass: 'mk-tab-slider-wrapper',
11543                slideClass: 'mk-tab-slider-item',
11544                calculateHeight: true,
11545                speed: 500,
11546                autoplay: isTest ? false : $autoplayTime,
11547                onSlideChangeStart: function() {
11548                    $('.mk-tab-slider-nav[data-id="' + id + '"]').find(".active").removeClass('active')
11549                    $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").eq(mk_tab_slider.activeIndex).addClass('active')
11550                }
11551            });
11552
11553            // Simple repaint for firefox issue (can't handle 100% height after plugin init)
11554            function repaintFirefox() {
11555                $content.css('display','block');
11556                setTimeout(function() {
11557                    mk_tab_slider.reInit();
11558                    $content.css('display','table');
11559                },100);
11560            }
11561
11562            $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").first().addClass('active');
11563
11564            $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").on('touchstart mousedown', function(e) {
11565                e.preventDefault()
11566                $('.mk-tab-slider-nav[data-id="' + id + '"]').find(".active").removeClass('active')
11567                $(this).addClass('active')
11568                mk_tab_slider.swipeTo($(this).index())
11569            });
11570
11571            $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").on('click',function(e) {
11572                e.preventDefault();
11573            });
11574
11575            repaintFirefox();
11576            $(window).on('resize', repaintFirefox);
11577        });
11578
11579    });
11580
11581}
11582
11583
11584
11585/* Edge One Pager */
11586/* -------------------------------------------------------------------- */
11587function mk_one_page_scroller() {
11588
11589    "use strict";
11590
11591    $('.mk-edge-one-pager').each(function() {
11592        var self = this;
11593
11594        MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.fullpage.js' ], function() {
11595
11596            var $this = $(self),
11597                anchorArr = [];
11598
11599            $this.find('.section').each(function() {
11600                anchorArr.push($(this).attr('data-title'));
11601            });
11602
11603            var scrollable = true;
11604            $this.find('.section').each(function() {
11605                var $section = $(this),
11606                    $content = $section.find('.edge-slide-content'),
11607                    sectionHeight = $section.height(),
11608                    contentHeight = $content.innerHeight();
11609
11610                if((contentHeight + 30) > $(window).height()) {
11611                    scrollable = false;
11612                }
11613            });
11614
11615            if(!scrollable){
11616                $this.find('.section').each(function() {
11617                    var $section = $(this);
11618                    $section.addClass('active').css({
11619                        'padding-bottom': '50px'
11620                    });
11621                });
11622            }
11623
11624            if(scrollable) {
11625                $this.fullpage({
11626                    verticalCentered: false,
11627                    resize: true,
11628                    slidesColor: ['#ccc', '#fff'],
11629                    anchors: anchorArr,
11630                    scrollingSpeed: 600,
11631                    easing: 'easeInQuart',
11632                    menu: false,
11633                    navigation: true,
11634                    navigationPosition: 'right',
11635                    navigationTooltips: false,
11636                    slidesNavigation: true,
11637                    slidesNavPosition: 'bottom',
11638                    loopBottom: false,
11639                    loopTop: false,
11640                    loopHorizontal: true,
11641                    autoScrolling: true,
11642                    scrollOverflow: false,
11643                    css3: true,
11644                    paddingTop: 0,
11645                    paddingBottom: 0,
11646                    normalScrollElements: '.mk-header, .mk-responsive-wrap',
11647                    normalScrollElementTouchThreshold: 5,
11648                    keyboardScrolling: true,
11649                    touchSensitivity: 15,
11650                    continuousVertical: false,
11651                    animateAnchor: true,
11652
11653                    onLeave: function(index, nextIndex, direction) {
11654                        var currentSkin = $this.find('.one-pager-slide').eq(nextIndex - 1).attr('data-header-skin');
11655                        MK.utils.eventManager.publish( 'firstElSkinChange', currentSkin );
11656                        $('#fullPage-nav').removeClass('light-skin dark-skin').addClass(currentSkin + '-skin');
11657
11658                    },
11659                    afterRender: function() {
11660
11661                        var $nav = $('#fullPage-nav');
11662
11663                        setTimeout(function() {
11664                            var currentSkin = $this.find('.one-pager-slide').eq(0).attr('data-header-skin');
11665                            MK.utils.eventManager.publish( 'firstElSkinChange', currentSkin );
11666                            if($nav.length) $nav.removeClass('light-skin dark-skin').addClass(currentSkin + '-skin');
11667                        }, 300);
11668
11669                        var $slide = $this.find('.section'),
11670                            headerHeight = MK.val.offsetHeaderHeight(0),
11671                            windowHeight = $(window).height();
11672
11673                        $slide.height(windowHeight - headerHeight);
11674
11675                        if($nav.length) {
11676                            $nav.css({
11677                                'top': 'calc(50% + ' + (headerHeight/2) + 'px)',
11678                                'marginTop': 0
11679                            });
11680
11681                            var style = $this.attr('data-pagination');
11682                            $nav.addClass('pagination-' + style);
11683                        }
11684
11685                        setTimeout(mk_one_pager_resposnive, 1000);
11686                    },
11687                    afterResize: function() {
11688                        var $slide = $this.find('.section'),
11689                            headerHeight = MK.val.offsetHeaderHeight(0),
11690                            windowHeight = $(window).height();
11691
11692                        $slide.height(windowHeight - headerHeight);
11693
11694                        $('#fullPage-nav').css({
11695                            'top': 'calc(50% + ' + (headerHeight/2) + 'px)',
11696                            'marginTop': 0
11697                        });
11698
11699                        setTimeout(mk_one_pager_resposnive, 1000);
11700                        console.log('Reposition pager content.');
11701                    },
11702                });
11703            }
11704
11705            // Linking to slides available for desktop and mobile scenarios
11706            function swipeTo(href, e) {
11707                href = '_' + href; // ensure a char before #
11708                if (!~href.indexOf('#')) return;
11709                var section = href.split('#')[1];
11710                if (~anchorArr.indexOf(section)) {
11711                    if (typeof e !== 'undefined') e.preventDefault();
11712                    if (scrollable) $.fn.fullpage.moveTo(section);
11713                    else MK.utils.scrollToAnchor('[data-title="'+section+'"]');
11714                }
11715            }
11716
11717            // onload
11718            var loc = window.location;
11719            if(loc.hash) swipeTo(loc.hash);
11720
11721            $(document).on('click', 'a', function(e) {
11722                var $link = $(e.currentTarget);
11723                swipeTo($link.attr('href'), e);
11724            });
11725        });
11726    });
11727
11728
11729
11730}
11731
11732
11733function mk_one_pager_resposnive() {
11734    "use strict";
11735
11736    $('.mk-edge-one-pager').each(function() {
11737        var $pager = $(this),
11738            headerHeight = MK.val.offsetHeaderHeight(0),
11739            windowHeight = $(window).height() - headerHeight;
11740
11741        $pager.find('.one-pager-slide').each(function() {
11742            var $slide = $(this),
11743                $content = $slide.find('.edge-slide-content');
11744
11745            if ($slide.hasClass('left_center') || $slide.hasClass('center_center') || $slide.hasClass('right_center')) {
11746                var contentHeight  = $content.height(),
11747                    distanceFromTop = (windowHeight - contentHeight) / 2;
11748
11749                distanceFromTop  = (distanceFromTop < 50) ? 50 + headerHeight : distanceFromTop;
11750
11751                $content.css('marginTop', distanceFromTop);
11752            }
11753
11754            if ($slide.hasClass('left_bottom') || $slide.hasClass('center_bottom') || $slide.hasClass('right_bottom')) {
11755                var distanceFromTop = windowHeight - $content.height() - 90;
11756                $content.css('marginTop', (distanceFromTop));
11757            }
11758        });
11759
11760        /**
11761         * Fix AM-2853
11762         *
11763         * @since 6.0.3
11764         *
11765         * At the init of Edge One Pager (EOP), EOP will render all image
11766         * background of each sections from top to bottom. In this case,
11767         * the page height will be more than screen height and the scroll
11768         * bar will appear. At the same time, the full width row will set
11769         * the container width into 100%. But, after all Slides are set up,
11770         * EOP height will be 100% of the screen height, so the scroll bar
11771         * will be disappeared. It's caused spacing issues on the left and
11772         * right side of the EOP container. To fix this, the row width
11773         * should be resized and row position should be readjusted.
11774         */
11775        var $row = $pager.parents( '.vc_row.vc_row-fluid.mk-fullwidth-true' );
11776
11777        // Run only if the Edge One Pager is wrapped inside full width row.
11778        if ( $row.length > 0 ) {
11779            // Set the wrapper and row width.
11780            var $wrapper = $( '.mk-main-wrapper-holder' );
11781            var $grid = $row.children( '.mk-grid' );
11782            var rowWidth = $row.width();         // Original width.
11783            var wrapperWidth = $wrapper.width(); // The new width.
11784
11785            // Run only if original width is smaller than the new width.
11786            if ( rowWidth >= wrapperWidth || $grid.length > 0 ) {
11787                return;
11788            }
11789
11790            // Get the content left offset.
11791            var $content = $wrapper.find( '.theme-content' );
11792            var oriPos = $content.position();
11793            var oriPadLeft = $content.css( 'padding-left' );
11794            var oriLeft = parseInt( oriPos.left ) + parseInt( oriPadLeft );
11795
11796            // Ensure the new width and left position is more than 0.
11797            if ( wrapperWidth <= 0 || oriLeft <= 0 ) {
11798                return;
11799            }
11800
11801            // Resize the width and left position of row full width.
11802            $row.css({
11803                'width': wrapperWidth,
11804                'left': oriLeft * -1,
11805            });
11806        }
11807    });
11808}
11809
11810/* Image Gallery */
11811/* -------------------------------------------------------------------- */
11812
11813function mk_gallery() {
11814
11815    "use strict";
11816
11817    $('.mk-gallery .mk-gallery-item.hover-overlay_layer .item-holder').each(function() {
11818        var itemHolder = $(this),
11819            galleryDesc = itemHolder.find('.gallery-desc');
11820
11821        function updatePosition() {
11822            var parentHeight = itemHolder.outerHeight(),
11823                contentHeight = galleryDesc.innerHeight();
11824
11825            var paddingVal = (parentHeight - contentHeight) / 2;
11826            galleryDesc.css({
11827                'top': paddingVal,
11828                // 'padding-bottom': paddingVal
11829            });
11830
11831            // console.log(parentHeight);
11832            // console.log(contentHeight);
11833
11834
11835        }
11836        updatePosition();
11837
11838        $(window).on('resize', function() {
11839            setTimeout(function() {
11840                updatePosition();
11841            }, 1000);
11842        });
11843    });
11844    // Execute hover state for mk gallery item
11845    if ($(window).width() <= 1024) {
11846        $('.mk-gallery .mk-gallery-item').on('click', function (e) {
11847            var clicks = $(this).data('clicks');
11848            if (clicks) {
11849                // First click
11850                $(this).toggleClass('hover-state');
11851            } else {
11852                // Second click
11853                $(this).toggleClass('hover-state');
11854            }
11855            $(this).data("clicks", !clicks);
11856        });
11857    }
11858}
11859
11860/* Theatre Slider Responsive Calculator */
11861/* -------------------------------------------------------------------- */
11862
11863function mk_theatre_responsive_calculator() {
11864    var $laptopContainer = $(".laptop-theatre-slider");
11865    var $computerContainer = $(".desktop-theatre-slider");
11866    $laptopContainer.each(function() {
11867        var $this = $(this),
11868            $window = $(window),
11869            $windowWidth = $window.outerWidth(),
11870            $windowHeight = $window.outerHeight(),
11871            $width = $this.outerWidth(),
11872            $height = $this.outerHeight(),
11873            $paddingTop = 38,
11874            $paddingRight = 143,
11875            $paddingBottom = 78,
11876            $paddingLeft = 143;
11877
11878        var $player = $this.find('.player-container');
11879
11880        if ($windowWidth > $width) {
11881            $player.css({
11882                'padding-left': parseInt(($width * $paddingLeft) / 1200),
11883                'padding-right': parseInt(($width * $paddingRight) / 1200),
11884                'padding-top': parseInt(($height * $paddingTop) / 690),
11885                'padding-bottom': parseInt(($height * $paddingBottom) / 690),
11886            });
11887        }
11888
11889    });
11890
11891    $computerContainer.each(function() {
11892        var $this = $(this),
11893            $window = $(window),
11894            $windowWidth = $window.outerWidth(),
11895            $windowHeight = $window.outerHeight(),
11896            $width = $this.outerWidth(),
11897            $height = $this.outerHeight(),
11898            $paddingTop = 60,
11899            $paddingRight = 52,
11900            $paddingBottom = 290,
11901            $paddingLeft = 49;
11902
11903        var $player = $this.find('.player-container');
11904
11905        if ($windowWidth > $width) {
11906            $player.css({
11907                'padding-left': parseInt(($width * $paddingLeft) / 1200),
11908                'padding-right': parseInt(($width * $paddingRight) / 1200),
11909                'padding-top': parseInt(($height * $paddingTop) / 969),
11910                'padding-bottom': parseInt(($height * $paddingBottom) / 969),
11911            });
11912        }
11913
11914    });
11915
11916}
11917
11918/* Mobile and Tablet Slideshow Responsive Calculator */
11919/* -------------------------------------------------------------------- */
11920function mk_mobile_tablet_responsive_calculator() {
11921    var $laptopSlideshow = $(".mk-laptop-slideshow-shortcode");
11922    var $lcdSlideshow = $(".mk-lcd-slideshow");
11923
11924    if ($.exists(".mk-laptop-slideshow-shortcode")) {
11925        $laptopSlideshow.each(function() {
11926            var $this = $(this),
11927                $window = $(window),
11928                $windowWidth = $window.outerWidth(),
11929                $windowHeight = $window.outerHeight(),
11930                $width = $this.outerWidth(),
11931                $height = $this.outerHeight(),
11932                $paddingTop = 28,
11933                $paddingRight = 102,
11934                $paddingBottom = 52,
11935                $paddingLeft = 102;
11936
11937            var $player = $this.find(".slideshow-container");
11938
11939            $player.css({
11940                "padding-left": parseInt(($width * $paddingLeft) / 836),
11941                "padding-right": parseInt(($width * $paddingRight) / 836),
11942                "padding-top": parseInt(($height * $paddingTop) / 481),
11943                "padding-bottom": parseInt(($height * $paddingBottom) / 481),
11944            });
11945
11946        });
11947    }
11948
11949    if ($.exists(".mk-lcd-slideshow")) {
11950        $lcdSlideshow.each(function() {
11951            var $this = $(this),
11952                $window = $(window),
11953                $windowWidth = $window.outerWidth(),
11954                $windowHeight = $window.outerHeight(),
11955                $width = $this.outerWidth(),
11956                $height = $this.outerHeight(),
11957                $paddingTop = 35,
11958                $paddingRight = 39,
11959                $paddingBottom = 213,
11960                $paddingLeft = 36;
11961
11962            var $player = $this.find(".slideshow-container");
11963            $player.css({
11964                "padding-left": parseInt(($width * $paddingLeft) / 886),
11965                "padding-right": parseInt(($width * $paddingRight) / 886),
11966                "padding-top": parseInt(($height * $paddingTop) / 713),
11967                "padding-bottom": parseInt(($height * $paddingBottom) / 713),
11968            });
11969        });
11970    }
11971}
11972
11973
11974/* Start a tour resize function */
11975/* -------------------------------------------------------------------- */
11976function mk_start_tour_resize() {
11977
11978    $('.mk-header-start-tour').each(function() {
11979
11980        var $windowWidth = $(document).width(),
11981            $this = $(this),
11982            $linkWidth = $this.width() + 15,
11983            $padding = ($windowWidth - mk_responsive_nav_width) / 2;
11984
11985
11986
11987        function updateStartTour(){
11988            if($windowWidth < mk_responsive_nav_width){
11989                $this.removeClass('hidden');
11990                $this.addClass('show');
11991            }else{
11992                if($padding < $linkWidth){
11993                    $this.removeClass('show');
11994                    $this.addClass('hidden');
11995                }else{
11996                    $this.removeClass('hidden');
11997                    $this.addClass('show');
11998                }
11999            }
12000        }
12001
12002        setTimeout(function() {
12003            updateStartTour();
12004        }, 300);
12005    });
12006}
12007
12008/* Header social resize function */
12009/* -------------------------------------------------------------------- */
12010function mk_header_social_resize() {
12011
12012    $('.mk-header-social.header-section').each(function() {
12013
12014        var $windowWidth = $(document).width(),
12015            $this = $(this),
12016            $linkWidth = $this.width() + 15,
12017            $padding = ($windowWidth - mk_responsive_nav_width) / 2;
12018
12019
12020
12021        function updateStartTour(){
12022            if($windowWidth < mk_responsive_nav_width){
12023                $this.removeClass('hidden');
12024                $this.addClass('show');
12025            }else{
12026                if($padding < $linkWidth){
12027                    $this.removeClass('show');
12028                    $this.addClass('hidden');
12029                }else{
12030                    $this.removeClass('hidden');
12031                    $this.addClass('show');
12032                }
12033            }
12034        }
12035
12036        setTimeout(function() {
12037            updateStartTour();
12038        }, 300);
12039    });
12040}
12041
12042/* Page Section Socail Video Player Controls */
12043/* -------------------------------------------------------------------- */
12044
12045function mk_page_section_social_video_bg() {
12046    $(".mk-page-section.social-hosted").each(function() {
12047        var $container = $(this),
12048            $sound = $container.data('sound'),
12049            $source = $container.data('source'),
12050            player,
12051            timer = 1000;
12052
12053        if ( $( 'body' ).hasClass( '.compose-mode' ) ) {
12054            timer = 2000;
12055        }
12056
12057        if ($source == 'youtube') {
12058            var youtube = $container.find('iframe')[0];
12059            try {
12060                player = new YT.Player(youtube, {
12061                    events: {
12062                        'onReady': function () {
12063                           player.playVideo();
12064                           if($sound == false) {
12065                               player.mute();
12066                           }
12067                       }
12068                    }
12069                });
12070
12071
12072            } catch (e) {
12073            	console.log( e );
12074            }
12075        }
12076        if ($source == 'vimeo') {
12077            var vimeo = $container.find('iframe')[0];
12078            player = $f(vimeo);
12079            setTimeout(function() {
12080                player.api('play');
12081                if($sound === false) {
12082                    player.api('setVolume', 0);
12083                }
12084            }, timer);
12085        }
12086
12087    });
12088}
12089
12090// Pre RequireJS hot bug fixing
12091
12092function videoLoadState() {
12093    $('.mk-section-video video').each(function() {
12094        var mkVideo = this;
12095
12096        mkVideo.play();
12097        this.onload = fire();
12098
12099        function fire() {
12100            setTimeout(function() {
12101                $(mkVideo).animate({
12102                    'opacity': 1
12103                }, 300);
12104            }, 1000);
12105        }
12106    });
12107}
12108videoLoadState();
12109
12110
12111// Gmap Widget
12112(function($) {
12113
12114    $(window).on('load vc_reload', initialize);
12115
12116    function initialize() {
12117        var $gmap = $('.gmap_widget');
12118        if($gmap.length && typeof google !== 'undefined') $gmap.each(run);
12119    }
12120
12121    function run() {
12122        var $mapHolder = $(this);
12123        var myLatlng = new google.maps.LatLng($mapHolder.data('latitude'), $mapHolder.data('longitude'));
12124        var mapOptions = $mapHolder.data('options');
12125            mapOptions.mapTypeId = google.maps.MapTypeId.ROADMAP;
12126            mapOptions.center = myLatlng;
12127        var map = new google.maps.Map(this, mapOptions);
12128
12129        new google.maps.Marker({
12130            position: myLatlng,
12131            map: map
12132        });
12133    }
12134
12135}(jQuery));
12136
12137// Instagram Widget
12138(function($) {
12139
12140    $(window).on('load', function() {
12141        var $feeds = $('.mk-instagram-feeds');
12142        if($feeds.length) $feeds.each(run);
12143    });
12144
12145    function run() {
12146        var options = $(this).data('options');
12147            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>';
12148        var feed = new Instafeed(options);
12149        feed.run();
12150    }
12151}(jQuery));
12152
12153
12154// Flipbox backface visibility fix for chrome
12155(function($) {
12156     $(window).on('load', function() {
12157         setTimeout( function() {
12158            $('.chrome-flipbox-backface-fix').removeClass('chrome-flipbox-backface-fix');
12159         }, 300);
12160     });
12161}(jQuery));
12162
12163
12164/* Product in VC Tab Bug Fix
12165/* -------------------------------------------------------------------- */
12166(function($) {
12167    $(window).on('load', function() {
12168        $('.vc_tta-tab a').on('click', function() {
12169            setTimeout( function() {
12170                $(window).trigger('resize');
12171            }, 100);
12172        });
12173    });
12174}(jQuery));
12175
12176
12177/* Vertical menu fix when childrens exceed screen height
12178/* -------------------------------------------------------------------- */
12179(function($) {
12180    $(window).on('load', function() {
12181        $('#mk-vm-menu .menu-item-has-children, #mk-vm-menu .mk-vm-back').on('mouseenter', function() {
12182            var $header_inner = $(this).closest('.mk-header-inner'),
12183                $header_inner_height = $header_inner.outerHeight(),
12184                $header_bg = $header_inner.find('.mk-header-bg'),
12185                total_height = 0;
12186            $header_bg.css('height', '100%');
12187            setTimeout( function() {
12188                $header_inner.children(':visible').each(function() {
12189                    total_height += $(this).outerHeight(true);
12190                });
12191                total_height -= $header_bg.height();
12192                if ( total_height < $header_inner_height ) {
12193                    $header_bg.css('height', '100%');
12194                } else {
12195                    $header_bg.css('height', total_height + 'px');
12196                }
12197            }, 600);
12198        });
12199    });
12200}(jQuery));
12201
12202
12203/* Woocommerce varitions lightbox fix
12204/* -------------------------------------------------------------------- */
12205(function($) {
12206    $(window).on('load', function() {
12207
12208        var $variations_form = $('.variations_form');
12209
12210        if ( $variations_form.length ) {
12211
12212            var $varitions_selects = $variations_form.find('.variations').find('.value').find('select');
12213            $varitions_selects.on('change', function() {
12214
12215                // Woocommerce variations lightbox with galleries
12216                var $all_img_container = $('.mk-product-image .mk-woocommerce-main-image');
12217                if ( $all_img_container.length ) {
12218                    $( $all_img_container ).each( set_lightbox_href );
12219                }
12220
12221            });
12222            $varitions_selects.trigger('change');
12223
12224        }
12225
12226    });
12227
12228    function set_lightbox_href() {
12229
12230        var $product_img = $( this ).find( 'img' ),
12231            $lightbox    = $( this ).find( '.mk-lightbox' );
12232
12233        setTimeout( function() {
12234            var image_url    = $product_img.attr( 'src' ),
12235                image_suffix = image_url.substr( image_url.lastIndexOf('.') - image_url.length ), // Get image suffix
12236                image_url    = image_url.slice( 0 , image_url.lastIndexOf('-') ); // Remove image size
12237            $lightbox.attr('href', image_url + image_suffix );
12238        }, 300);
12239    }
12240
12241}(jQuery));
12242
12243
12244/* Remove video section when on mobile */
12245/* -------------------------------------------------------------------- */
12246(function($) {
12247    if ( MK.utils.isMobile() ) {
12248      $('.mk-section-video video').remove();
12249    }
12250}(jQuery));
12251
12252
12253/* Yith AJAX Product Filter & Yith Infinite Scrolling Plugin Fix
12254/* -------------------------------------------------------------------- */
12255(function($) {
12256    $(window).on('load', function() {
12257
12258        $(document).on( 'yith-wcan-ajax-filtered yith_infs_added_elem yith-wcan-ajax-reset-filtered', function(){
12259            setTimeout( function() {
12260                MK.utils.eventManager.publish('ajaxLoaded');
12261                MK.core.initAll( document );
12262            }, 1000 );
12263        });
12264
12265        // Fixed YITH Filter plugin causes issue for dropdown sort
12266        $(document).on( 'yith-wcan-ajax-filtered yith-wcan-ajax-reset-filtered', function(){
12267            setTimeout( function() {
12268                $( '.woocommerce-ordering' ).on( 'change', 'select.orderby', function() {
12269                    $( this ).closest( 'form' ).submit();
12270                });
12271            }, 1000 );
12272        });
12273
12274    });
12275}(jQuery));
12276
12277
12278/* Toggle loading state in URL for anchor links.
12279 * - Add a filter to escape meta-chars from hash string.
12280/* -------------------------------------------------------------------- */
12281!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);
12282
12283
12284/* Determine the top spacing of sidebar for full-width page section & row.
12285/* -------------------------------------------------------------------- */
12286function mkPositionSidebar() {
12287
12288	var themeContent = $( '.theme-content' ),
12289		lastFullWidthChild = themeContent.find( '.vc_row-full-width' ).last(),
12290		top,
12291		sidebar = $( '#theme-page > .mk-main-wrapper-holder > .theme-page-wrapper > #mk-sidebar' );
12292
12293	if ( ! lastFullWidthChild.length ) {
12294		sidebar.removeAttr( 'style' );
12295		return;
12296	}
12297
12298	top = lastFullWidthChild.offset().top - themeContent.offset().top;
12299	sidebar.css( 'padding-top', top );
12300}
12301
12302function mk_accordion_toggles_tooltip() {
12303
12304  "use strict";
12305
12306
12307  /* Message Boxes */
12308  /* -------------------------------------------------------------------- */
12309
12310  $('.box-close-btn').on('click', function() {
12311    $(this).parent().fadeOut(300);
12312    return false;
12313
12314  });
12315
12316}
12317
12318function mk_portfolio_ajax() {
12319  "use strict";
12320
12321  var headerHeight = 0;
12322  if ($.exists("#wpadminbar")) {
12323    headerHeight += $("#wpadminbar").height();
12324  }
12325  if (!$.exists('.mk-vm-menuwrapper')) {
12326    headerHeight += parseInt($('.mk-header').attr('data-sticky-height'));
12327  }
12328
12329  function init() {
12330    var $portfolio = $('.portfolio-grid.portfolio-ajax-enabled');
12331    if (!$portfolio.length) return; // quit if no portfolio wrappers
12332    MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.ajax.portfolio.js' ], function() {
12333      // wait for ajax response propagation and insertion
12334      setTimeout(function() {
12335        $portfolio.each( function() {
12336          $(this).ajaxPortfolio({ extraOffset: headerHeight });
12337        });
12338      }, 100);
12339    });
12340  }
12341
12342  init();
12343
12344  // Reinit when ajax loaded stuff
12345  // We have global reinit on Components. so move the ajaxPortfolio to component namespace as a standalone module to get it right.
12346  MK.utils.eventManager.subscribe('ajaxLoaded', init);
12347}
12348
12349/**
12350 * Ajax Search on header nav.
12351 */
12352function mk_ajax_search() {
12353    "use strict";
12354
12355    // Check if ajax search box enabled.
12356    if (mk_ajax_search_option !== "beside_nav") {
12357        return;
12358    }
12359
12360    // Set minimum length of text to get ajax result.
12361    var minimumLengthToSearch = 3;
12362    var $mkAjaxSearchInput = $('#mk-ajax-search-input');
12363    var security = $mkAjaxSearchInput.siblings('input[name="security"]').val();
12364    var wpHttpReferer = $mkAjaxSearchInput.siblings('input[name="_wp_http_referer"]').val();
12365    var querySpliter = (ajaxurl.indexOf('?') > -1) ? '&' : '?';
12366    var ul = document.getElementById('mk-nav-search-result');
12367    var searchTerm; // Search term
12368    var requestCounter = 0;
12369    var responseCounter = 0;
12370
12371    // Add listener for getting result quickly while user entering text, past text and etc.
12372    $mkAjaxSearchInput.on('paste input propertychange', onSearchBoxInput);
12373
12374    /**
12375     * Callback function for entering search term listener (e.g. keyup).
12376     * It will generate AJAX request to get data.
12377     *
12378     * @param e
12379     */
12380    function onSearchBoxInput(e) {
12381        var target = e.target || e.srcElement;
12382        var newValue = target.value;
12383
12384        // Check if user change the value of text box
12385        if (searchTerm !== newValue) {
12386            searchTerm = newValue;
12387            ul.innerHTML = '';
12388            if (searchTerm.length >= minimumLengthToSearch) {
12389                // Show loading icon
12390                $mkAjaxSearchInput.addClass('ajax-searching');
12391                requestCounter++;
12392                $.getJSON(ajaxurl + querySpliter + 'callback=?&action=mk_ajax_search&security=' + security + '&_wp_http_referer=' + wpHttpReferer + '&term=' + searchTerm)
12393                    .done(showSearchResult)
12394                    .fail(showErrorMessage);
12395            }
12396        }
12397    }
12398
12399    /**
12400     * Callback function for the response of the search request.
12401     *
12402     * @param data
12403     */
12404    function showSearchResult(data) {
12405        responseCounter++;
12406
12407        // Only show response of latest request.
12408        if (isCorrectResponse()) {
12409            if (data.length > 0) {
12410                // Append result to result container
12411                for (var i = 0; i < data.length; i++) {
12412                    var item = data[i];
12413                    $('<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);
12414                }
12415            } else {
12416                // Show no result message
12417                ul.innerHTML = '<li class="mk-nav-search-result-zero">No Result.</li>';
12418            }
12419
12420            // Hide loading icon
12421            $mkAjaxSearchInput.parent('form').removeClass('ajax-searching').addClass('ajax-search-complete');
12422        }
12423    }
12424
12425    /**
12426     * If any errors, we need a handler to show error message.
12427     */
12428    function showErrorMessage() {
12429        responseCounter++;
12430
12431        if (isCorrectResponse()) {
12432            ul.innerHTML = '<li class="mk-nav-search-error-message">Can not search! Please try again.</li>';
12433        }
12434    }
12435
12436    /**
12437     * Check if the response is right for the request. we show latest response only.
12438     *
12439     * @returns {boolean}
12440     */
12441    function isCorrectResponse() {
12442        return requestCounter === responseCounter;
12443    }
12444}
12445/* Background Parallax Effects */
12446/* -------------------------------------------------------------------- */
12447
12448function mk_backgrounds_parallax() {
12449
12450  "use strict";
12451
12452  if (mk_header_parallax == true) {
12453    $('.mk-header-bg').addClass('mk-parallax-enabled');
12454  }
12455  if (mk_body_parallax == true) {
12456    $('body').addClass('mk-parallax-enabled');
12457  }
12458  if (mk_banner_parallax == true) {
12459    $('.mk-header').addClass('mk-parallax-enabled');
12460  }
12461  if (mk_footer_parallax == true) {
12462    $('#mk-footer').addClass('mk-parallax-enabled');
12463  }
12464
12465  $('.mk-parallax-enabled').each(function () {
12466    var $this = $( this );
12467    if (!MK.utils.isMobile()) {
12468      MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.parallax.js' ], function() {
12469        $this.parallax("49%", 0.3);
12470      });
12471    }
12472  });
12473
12474  $('.mk-fullwidth-slideshow.parallax-slideshow').each(function () {
12475    var $this = $( this );
12476    if (!MK.utils.isMobile()) {
12477      MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.parallax.js' ], function() {
12478        var speed_factor = $this.attr('data-speedFactor');
12479        $this.parallax("49%", speed_factor);
12480      });
12481    }
12482  });
12483
12484}
12485/* Blog, Portfolio Audio */
12486/* -------------------------------------------------------------------- */
12487
12488function loop_audio_init() {
12489  if ($.exists('.jp-jplayer')) {
12490    $('.jp-jplayer.mk-blog-audio').each(function () {
12491      var $this = $( this );
12492      MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.jplayer.js' ], function() {
12493        var css_selector_ancestor = "#" + $this.siblings('.jp-audio').attr('id');
12494        var ogg_file, mp3_file, mk_theme_js_path;
12495        ogg_file = $this.attr('data-ogg');
12496        mp3_file = $this.attr('data-mp3');
12497        $this.jPlayer({
12498          ready: function () {
12499            $this.jPlayer("setMedia", {
12500              mp3: mp3_file,
12501              ogg: ogg_file
12502            });
12503          },
12504          play: function () { // To avoid both jPlayers playing together.
12505            $this.jPlayer("pauseOthers");
12506          }, 
12507          swfPath: mk_theme_js_path,
12508          supplied: "mp3, ogg",
12509          cssSelectorAncestor: css_selector_ancestor,
12510          wmode: "window"
12511        });
12512      });
12513    });
12514  }
12515}
12516
12517
12518/* Blog Loop Carousel Shortcode */
12519/* -------------------------------------------------------------------- */
12520
12521
12522function mk_blog_carousel() {
12523
12524  "use strict";
12525
12526  if (!$.exists('.mk-blog-showcase')) {
12527    return;
12528  }
12529  $('.mk-blog-showcase ul li').each(function () {
12530
12531    $(this).mouseenter( function () {
12532
12533      $(this).siblings('li').removeClass('mk-blog-first-el').end().addClass('mk-blog-first-el');
12534
12535    });
12536
12537  });
12538
12539
12540}
12541
12542
12543
12544
12545/**
12546 * Contact Form
12547 *
12548 * Mostly implemented in Vanilla JS instead of jQuery.
12549 */
12550function mk_contact_form() {
12551    "use strict";
12552    var mkContactForms = document.getElementsByClassName('mk-contact-form');
12553    if (mkContactForms.length === 0) {
12554        return;
12555    }
12556    var captchaImageHolder = $('.captcha-image-holder');
12557    var activeClassName = 'is-active';
12558    var invalidClassName = 'mk-invalid';
12559    for (var i = 0; i < mkContactForms.length; i++) {
12560        initializeForm(mkContactForms[i], activeClassName, invalidClassName);
12561    }
12562    if (captchaImageHolder.length > 0) {
12563        $(window).on('load', initializeCaptchas);
12564    }
12565    /**
12566     * Initialize mk forms. e.g add activeClassName for inputs.
12567     *
12568     * @param form
12569     * @param activeClassName
12570     * @param invalidClassName
12571     */
12572    function initializeForm(form, activeClassName, invalidClassName) {
12573        var inputs = getFormInputs(form);
12574        for (var i = 0; i < inputs.length; i++) {
12575            markActiveClass(inputs[i]);
12576        }
12577        form.addEventListener('submit', function(e) {
12578            validateForm(e, invalidClassName);
12579        });
12580        /**
12581         * Set activeClassName for the parent node of the inout
12582         */
12583        function setActiveClass() {
12584            addClass(this.parentNode, activeClassName);
12585        }
12586        /**
12587         * Unset activeClassName from the parent node of the input.
12588         * We need to unset activeClassName only if the data was empty.
12589         * e.g. in the line style of the mk-contact-form, we set labels position based on activeClassName.
12590         */
12591        function unsetActiveClass() {
12592            if (this.value === '') {
12593                removeClass(this.parentNode, activeClassName);
12594            }
12595        }
12596        /**
12597         * Add event listeners (focus,blur) for input to set and unset activeClassName.
12598         *
12599         * @param input
12600         */
12601        function markActiveClass(input) {
12602            input.addEventListener('focus', setActiveClass);
12603            input.addEventListener('blur', unsetActiveClass);
12604        }
12605    }
12606    /**
12607     * Validate form when it's submitted. If everything was valid, we with post form in ajax request.
12608     *
12609     * @param e
12610     * @param invalidClassName
12611     */
12612    function validateForm(e, invalidClassName) {
12613        e.preventDefault();
12614        var form = e.target || e.srcElement;
12615        var inputs = getFormInputs(form);
12616        var isValidForm = true;
12617        var hasCaptchaField = false;
12618        for (var i = 0; i < inputs.length; i++) {
12619            var input = inputs[i];
12620            input.value = String(input.value).trim();
12621            switch (input.type) {
12622                case 'hidden':
12623                    break;
12624                case 'checkbox':
12625                    isValidForm = validateCheckBox(input, invalidClassName) && isValidForm;
12626                    break;
12627                case 'email':
12628                    isValidForm = validateEmail(input, invalidClassName) && isValidForm;
12629                    break;
12630                case 'textarea':
12631                    isValidForm = validateText(input, invalidClassName) && isValidForm;
12632                    break;
12633                case 'text':
12634                    /**
12635                     * Some old browsers such as IE 8 and 9 detect email type as text.
12636                     * So, we need to extra check for data-type attribute
12637                     */
12638                    if (input.dataset.type === 'captcha') {
12639                        isValidForm = validateText(input, invalidClassName) && isValidForm;
12640                        hasCaptchaField = true;
12641                    } else if (input.dataset.type === 'email') {
12642                        isValidForm = validateEmail(input, invalidClassName) && isValidForm;
12643                    } else {
12644                        isValidForm = validateText(input, invalidClassName) && isValidForm;
12645                    }
12646                    break;
12647                default:
12648                    /**
12649                     * e.g. validating for radiobox, selectbox and etc.
12650                     */
12651                    console.warn('Implement validation for ' + input.name + ':' + input.type);
12652                    break;
12653            }
12654        }
12655        if (isValidForm) {
12656            if (hasCaptchaField) {
12657                validateCaptcha(form, invalidClassName, sendForm);
12658            } else {
12659                sendForm(form);
12660            }
12661        }
12662    }
12663    /**
12664     * Validate captcha of form. If everything was, we will execute captchaIsValidCallback which as sendForm().
12665     *
12666     * @param form
12667     * @param invalidClassName
12668     * @param captchaIsValidCallback
12669     * @returns boolean
12670     */
12671    function validateCaptcha(form, invalidClassName, captchaIsValidCallback) {
12672        var input = form.querySelectorAll('[data-type="captcha"]')[0];
12673        if (input.value.length === 0) {
12674            addClass(input, invalidClassName);
12675            return false;
12676        } else {
12677            window.get.captcha(input.value).done(function(data) {
12678                loadCaptcha();
12679                input.value = '';
12680                if (data !== 'ok') {
12681                    addClass(input, invalidClassName);
12682                    addClass(input, 'contact-captcha-invalid');
12683                    removeClass(input, 'contact-captcha-valid');
12684                    input.placeholder = mk_captcha_invalid_txt;
12685                } else {
12686                    removeClass(input, invalidClassName);
12687                    removeClass(input, 'contact-captcha-invalid');
12688                    addClass(input, 'contact-captcha-valid');
12689                    input.placeholder = mk_captcha_correct_txt;
12690                    captchaIsValidCallback(form);
12691                }
12692            });
12693        }
12694    }
12695    /**
12696     * Send submitted form.
12697     *
12698     * @param form
12699     */
12700    function sendForm(form) {
12701        var $form = $(form);
12702        var data = getFormData(form);
12703        progressButton.loader($form);
12704        $.post(ajaxurl, data, function(response) {
12705            var res = JSON.parse(response);
12706            if (res.action_Status) {
12707                progressButton.success($form);
12708                $form.find('.text-input').val('');
12709                $form.find('textarea').val('');
12710                $form.find('input[type=checkbox]').attr("checked", false);
12711                $form.find('.contact-form-message').slideDown().addClass('state-success').html(res.message);
12712                setTimeout(function() {
12713                   $form.find('.contact-form-message').slideUp();  
12714                }, 5000);
12715            } else {
12716                progressButton.error($form);
12717                $form.find('.contact-form-message').removeClass('state-success').html(res.message);
12718            }
12719        });
12720    }
12721    /**
12722     * Initialize all captcha images for first time. All captcha images is always same. e.g. if we have multiple form,
12723     * all of them will have the same image.
12724     * It will also add event listener for '.captcha-change-image' objects to reload the captcha.
12725     */
12726    function initializeCaptchas() {
12727        var captchaChangeImageButtons = document.getElementsByClassName('captcha-change-image');
12728        for (var i = 0; i < captchaChangeImageButtons.length; i++) {
12729            captchaChangeImageButtons[i].addEventListener('click', loadCaptcha);
12730        }
12731    }
12732    /**
12733     * Load captcha text and append the image to captcha container.
12734     * If it used as a callback, it will prevent default behave of the event.
12735     * e.g. loading new captcha by click on <a> without changing url.
12736     */
12737    function loadCaptcha(e) {
12738        if (e) {
12739            e.preventDefault();
12740        }
12741        $.post(ajaxurl, {
12742            action: 'mk_create_captcha_image'
12743        }, appendImage);
12744        /**
12745         * The callback function for append or change old image src based on response. T
12746         * The captchaImageURL is the url of the captcha which is provided in ajax response of mk_create_captcha_image.
12747         * @param captchaImageURL
12748         */
12749        function appendImage(captchaImageURL) {
12750            if (captchaImageHolder.find('.captcha-image').length === 0) {
12751                captchaImageHolder.html('<img src="' + captchaImageURL + '" class="captcha-image" alt="captcha txt">');
12752            } else {
12753                captchaImageHolder.find('.captcha-image').attr("src", captchaImageURL + '?' + new Date().getTime());
12754            }
12755        }
12756    }
12757    /**
12758     * Get form inputs using querySelectorAll().
12759     * It returns <input> and <textarea> tags. If you need any other tags such as <select>, please update this function.
12760     *
12761     * @param form
12762     * @returns {NodeList}
12763     */
12764    function getFormInputs(form) {
12765        return form.querySelectorAll('input,textarea');
12766    }
12767    /**
12768     * Get data of the form inputs and textareas as a object.
12769     *
12770     * @param form
12771     * @returns {{action: string}}
12772     */
12773    function getFormData(form) {
12774        var data = {
12775            action: 'mk_contact_form'
12776        };
12777        var inputs = getFormInputs(form);
12778        for (var i = 0; i < inputs.length; i++) {
12779            data[inputs[i].name] = inputs[i].value;
12780        }
12781        return data;
12782    }
12783}
12784/* Ajax Login Form */
12785/* -------------------------------------------------------------------- */
12786function mk_login_form() {
12787    $('form.mk-login-form').each(function() {
12788        var $this = $(this);
12789        $this.on('submit', function(e) {
12790            $('p.mk-login-status', $this).show().text(ajax_login_object.loadingmessage);
12791            $.ajax({
12792                type: 'POST',
12793                dataType: 'json',
12794                url: ajax_login_object.ajaxurl,
12795                data: {
12796                    'action': 'ajaxlogin',
12797                    'username': $('#username', $this).val(),
12798                    'password': $('#password', $this).val(),
12799                    'security': $('#security', $this).val()
12800                },
12801                success: function(data) {
12802                    $('p.mk-login-status', $this).text(data.message);
12803                    if (data.loggedin === true) {
12804                        document.location.href = ajax_login_object.redirecturl;
12805                    }
12806                }
12807            });
12808            e.preventDefault();
12809        });
12810    });
12811}
12812/* Progress Button */
12813/* -------------------------------------------------------------------- */
12814var progressButton = {
12815    loader: function(form) {
12816        MK.core.loadDependencies([MK.core.path.plugins + 'tweenmax.js'], function() {
12817            var $form = form,
12818                progressBar = $form.find(".mk-progress-button .mk-progress-inner"),
12819                buttonText = $form.find(".mk-progress-button .mk-progress-button-content"),
12820                progressButton = new TimelineLite();
12821            progressButton.to(progressBar, 0, {
12822                width: "100%",
12823                scaleX: 0,
12824                scaleY: 1
12825            }).to(buttonText, .3, {
12826                y: -5
12827            }).to(progressBar, 1.5, {
12828                scaleX: 1,
12829                ease: Power2.easeInOut
12830            }, "-=.1").to(buttonText, .3, {
12831                y: 0
12832            }).to(progressBar, .3, {
12833                scaleY: 0
12834            });
12835        });
12836    },
12837    success: function(form) {
12838        MK.core.loadDependencies([MK.core.path.plugins + 'tweenmax.js'], function() {
12839            var $form = form,
12840                buttonText = $form.find(".mk-button .mk-progress-button-content, .mk-contact-button .mk-progress-button-content"),
12841                successIcon = $form.find(".mk-progress-button .state-success"),
12842                progressButtonSuccess = new TimelineLite({
12843                    onComplete: hideSuccessMessage
12844                });
12845            progressButtonSuccess.to(buttonText, .3, {
12846                paddingRight: 20,
12847                ease: Power2.easeInOut
12848            }, "+=1").to(successIcon, .3, {
12849                opacity: 1
12850            }).to(successIcon, 2, {
12851                opacity: 1
12852            });
12853
12854            function hideSuccessMessage() {
12855                progressButtonSuccess.reverse()
12856            }
12857        });
12858    },
12859    error: function(form) {
12860        MK.core.loadDependencies([MK.core.path.plugins + 'tweenmax.js'], function() {
12861            var $form = form,
12862                buttonText = $form.find(".mk-button .mk-progress-button-content, .mk-contact-button .mk-progress-button-content"),
12863                errorIcon = $form.find(".mk-progress-button .state-error"),
12864                progressButtonError = new TimelineLite({
12865                    onComplete: hideErrorMessage
12866                });
12867            progressButtonError.to(buttonText, .3, {
12868                paddingRight: 20
12869            }, "+=1").to(errorIcon, .3, {
12870                opacity: 1
12871            }).to(errorIcon, 2, {
12872                opacity: 1
12873            });
12874
12875            function hideErrorMessage() {
12876                progressButtonError.reverse()
12877            }
12878        });
12879    }
12880};
12881function mk_click_events() {
12882  "use strict";
12883
12884  var eventtype = 'click'; 
12885
12886  $(".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) {
12887    if (event.stopPropagation) {
12888      event.stopPropagation();
12889    } else if (window.event) {
12890      window.event.cancelBubble = true;
12891    }
12892  });
12893  $("html").on(eventtype, function() {
12894    $(".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);
12895    $('.mk-quick-contact-link').removeClass('quick-contact-active');
12896    // Removed By Maki for repairing fullnav scroll issue. Hope it odesnt break anything
12897    // $('body').css('overflow', 'visible');
12898  });
12899
12900  $('.mk-fullscreen-search-overlay').on(eventtype,function(){
12901    $(this).removeClass('mk-fullscreen-search-overlay-show');
12902  });
12903
12904  $('.mk-forget-password').on(eventtype, function() {
12905    $('.mk-forget-panel').siblings().hide().end().show();
12906  });
12907
12908  $('.mk-create-account').on(eventtype, function() {
12909    $('#mk-register-panel').siblings().hide().end().show();
12910  });
12911
12912  $('.mk-return-login').on(eventtype, function() {
12913    $('#mk-login-panel').siblings().hide().end().show();
12914  });
12915
12916
12917  $('.mk-quick-contact-link').on(eventtype, function() {
12918    var $this = $(this),
12919        $quickContact = $('#mk-quick-contact');
12920    if (!$this.hasClass('quick-contact-active')) {
12921      $quickContact.addClass('quick-contact-anim').fadeIn(250);
12922      $this.addClass('quick-contact-active');
12923    } else {
12924      $quickContact.removeClass('quick-contact-anim').fadeOut(100);
12925      $this.removeClass('quick-contact-active');
12926    }
12927    return false;
12928  });
12929
12930}
12931
12932function mk_social_share_global() {
12933
12934  "use strict";
12935
12936  var eventtype = 'click';
12937
12938  $('.twitter-share').on(eventtype, function() {
12939    var $this = $(this),
12940        $url = $this.attr('data-url'),
12941        $title = $this.attr('data-title');
12942
12943    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");
12944    return false;
12945  });
12946
12947  $('.pinterest-share').on(eventtype, function() {
12948    var $this = $(this),
12949        $url = $this.attr('data-url'),
12950        $title = $this.attr('data-title'),
12951        $image = $this.attr('data-image');
12952    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");
12953    return false;
12954  });
12955
12956  $('.facebook-share').on(eventtype, function() {
12957    var $url = $(this).attr('data-url');
12958    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");
12959    return false;
12960  });
12961
12962  $('.googleplus-share').on(eventtype, function() {
12963    var $url = $(this).attr('data-url');
12964    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");
12965    return false;
12966  });
12967
12968  $('.linkedin-share').on(eventtype, function() {
12969    var $this = $(this),
12970        $url = $this.attr('data-url'),
12971        $title = $this.attr('data-title'),
12972        $desc = $this.attr('data-desc');
12973    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");
12974    return false;
12975  });
12976}
12977
12978
12979/* Event Count Down */
12980/* -------------------------------------------------------------------- */
12981
12982function mk_event_countdown() {
12983  if ($.exists('.mk-event-countdown')) {
12984
12985    MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.countdown.js' ], function() {
12986
12987      $('.mk-event-countdown').each(function () {
12988        if (isTest) return;
12989        var $this = $(this),
12990          $date = $this.attr('data-date'),
12991          $offset = $this.attr('data-offset');
12992
12993        $this.downCount({
12994          date: $date,
12995          offset: $offset
12996        });
12997      });
12998      
12999    });
13000  }
13001}
13002/* Flexslider init */
13003/* -------------------------------------------------------------------- */
13004
13005function mk_flexslider_init() {
13006
13007  var $lcd = $('.mk-lcd-slideshow'),
13008      $laptop = $('.mk-laptop-slideshow-shortcode');
13009
13010  if($lcd.length) $lcd.find('.mk-lcd-image').fadeIn();
13011  if($laptop.length) $laptop.find(".mk-laptop-image").fadeIn();
13012
13013  $('.js-flexslider').each(function () {
13014
13015    if ($(this).parents('.mk-tabs').length || $(this).parents('.mk-accordion').length) {
13016      $(this).removeData("flexslider");
13017    }
13018
13019    var $this = $(this),
13020      $selector = $this.attr('data-selector'),
13021      $animation = $this.attr('data-animation'),
13022      $easing = $this.attr('data-easing'),
13023      $direction = $this.attr('data-direction'),
13024      $smoothHeight = $this.attr('data-smoothHeight') == "true" ? true : false,
13025      $slideshowSpeed = $this.attr('data-slideshowSpeed'),
13026      $animationSpeed = $this.attr('data-animationSpeed'),
13027      $controlNav = $this.attr('data-controlNav') == "true" ? true : false,
13028      $directionNav = $this.attr('data-directionNav') == "true" ? true : false,
13029      $pauseOnHover = $this.attr('data-pauseOnHover') == "true" ? true : false,
13030      $isCarousel = $this.attr('data-isCarousel') == "true" ? true : false;
13031
13032
13033    if ($selector !== undefined) {
13034      var $selector_class = $selector;
13035    } else {
13036      var $selector_class = ".mk-flex-slides > li";
13037    }
13038
13039    if ($isCarousel === true) {
13040      var $itemWidth = parseInt($this.attr('data-itemWidth')),
13041        $itemMargin = parseInt($this.attr('data-itemMargin')),
13042        $minItems = parseInt($this.attr('data-minItems')),
13043        $maxItems = parseInt($this.attr('data-maxItems')),
13044        $move = parseInt($this.attr('data-move'));
13045    } else {
13046      var $itemWidth = $itemMargin = $minItems = $maxItems = $move = 0;
13047    }
13048
13049    MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.flexslider.js' ], function() {
13050      $this.flexslider({
13051        selector: $selector_class,
13052        animation: $animation,
13053        easing: $easing,
13054        direction: $direction,
13055        smoothHeight: $smoothHeight,
13056        slideshow: !isTest, // autoplay
13057        slideshowSpeed: $slideshowSpeed,
13058        animationSpeed: $animationSpeed,
13059        controlNav: $controlNav,
13060        directionNav: $directionNav,
13061        pauseOnHover: $pauseOnHover,
13062        prevText: "",
13063        nextText: "",
13064        itemWidth: $itemWidth,
13065        itemMargin: $itemMargin,
13066        minItems: $minItems,
13067        maxItems: $maxItems,
13068        move: $move
13069      });
13070    });
13071
13072  });
13073
13074}
13075
13076/* Header Search Form */
13077/* -------------------------------------------------------------------- */
13078
13079function mk_header_searchform() {
13080
13081  $('.mk-search-trigger').on('click',function(){
13082    setTimeout(function() {
13083        $('#mk-ajax-search-input').focus();
13084    },500);
13085  });
13086
13087  "use strict";
13088
13089  $('.mk-header-toolbar .mk-header-searchform .text-input').on('focus', function () {
13090
13091    if ($('.mk-header-toolbar .mk-header-searchform .text-input').hasClass('on-close-state')) {
13092      $('.mk-header-toolbar .mk-header-searchform .text-input').removeClass('on-close-state').animate({
13093        'width': '200px'
13094      }, 200);
13095      return false;
13096    }
13097  });
13098
13099  $(".mk-header-toolbar .mk-header-searchform").on('click',function (event) {
13100    if (event.stopPropagation) {
13101      event.stopPropagation();
13102    } else if (window.event) {
13103      window.event.cancelBubble = true;
13104    }
13105  });
13106
13107
13108  $("html").on('click',function () {
13109    $(this).find(".mk-header-toolbar .mk-header-searchform .text-input").addClass('on-close-state').animate({
13110      'width': 90
13111    }, 300);
13112  });
13113
13114  // Fix search for edge browser
13115  if(MK.utils.browser.name === 'Edge') {
13116    $('#mk-fullscreen-search-input').on('keydown', function(e) {
13117      if (e.which == 13) {
13118        e.preventDefault();
13119        $('#mk-fullscreen-searchform').submit();
13120      }
13121    });
13122  }
13123
13124}
13125
13126
13127
13128
13129/* Hover Events */
13130/* -------------------------------------------------------------------- */
13131
13132function mk_hover_events() {
13133
13134  "use strict";
13135
13136  $('.shopping-cart-header').hover(
13137    function() {
13138      $(this).find('.mk-shopping-cart-box').stop(true, true).fadeIn(250);
13139    },
13140    function() {
13141      $(this).find('.mk-shopping-cart-box').stop(true, true).delay(500).fadeOut(250);
13142    }
13143  );
13144
13145
13146  $('.widget-sub-navigation > ul > li, .widget_nav_menu ul.menu > li, .widget_product_categories ul > .cat-item').each(function() {
13147
13148    var $this = $(this),
13149        $subLevel = $this.find('ul').first();
13150
13151    if ($this.hasClass('page_item_has_children') || $this.hasClass('menu-item-has-children') || $this.hasClass('cat-parent')) {
13152      $this.on('click', function() {
13153        if($this.hasClass('toggle-active')) {
13154            $subLevel.stop(true, true).slideUp(700);
13155            $this.removeClass('toggle-active');
13156        } else {
13157            $subLevel.stop(true, true).slideDown(700);
13158            $this.addClass('toggle-active');
13159        }
13160      });
13161
13162      $subLevel.on('click', function(e){
13163        e.stopPropagation();
13164      });
13165    }
13166
13167  });
13168
13169  // var eventtype = mobilecheck() ? 'touchstart' : 'click';
13170  var eventtype = 'click';
13171
13172  $('.mk-fullscreen-trigger').on(eventtype, function(e) {
13173    $('.mk-fullscreen-search-overlay').addClass('mk-fullscreen-search-overlay-show');
13174    setTimeout(function(){
13175      $("#mk-fullscreen-search-input").focus();
13176    }, 300);
13177    e.preventDefault();
13178  });
13179
13180  $('.mk-fullscreen-close').on(eventtype, function(e) {
13181    $('.mk-fullscreen-search-overlay').removeClass('mk-fullscreen-search-overlay-show');
13182    e.preventDefault();
13183  });
13184
13185}
13186
13187function mk_unfold_footer() {
13188  var $this = $('#mk-footer'),
13189      $spacer = $('#mk-footer-unfold-spacer'),
13190      $footerHeight = $this.outerHeight();
13191
13192  // Stick with CSS media query breakpoint to target exact screen width
13193  if( !window.matchMedia("(max-width: 767px)").matches ) {
13194      if ($this.hasClass('mk-footer-unfold')) {
13195        $spacer.css('height', $footerHeight);
13196      }
13197  } else {
13198     $spacer.css('height', 0);
13199  }
13200}
13201
13202/* jQuery fancybox lightbox */
13203/* -------------------------------------------------------------------- */
13204function mk_lightbox_init() {
13205
13206	$(".mk-lightbox").fancybox({
13207		loop: true,
13208	});
13209
13210	$.fancybox.defaults.hash = false;
13211
13212}
13213
13214
13215/* Milestone Number Shortcode */
13216/* -------------------------------------------------------------------- */
13217
13218function mk_milestone() {
13219
13220  "use strict";
13221
13222  if( isTest || !$.exists('.mk-milestone') ) return;
13223
13224  $('.mk-milestone').each(function () {
13225    var $this = $(this),
13226      stop_number = $this.find('.milestone-number').attr('data-stop'),
13227      animation_speed = parseInt($this.find('.milestone-number').attr('data-speed'));
13228
13229    var build = function() {
13230      if (!$this.hasClass('scroll-animated')) {
13231        $this.addClass('scroll-animated');
13232
13233        $({
13234          countNum: $this.find('.milestone-number').text()
13235        }).animate({
13236          countNum: stop_number
13237        }, {
13238          duration: animation_speed,
13239          easing: 'linear',
13240          step: function () {
13241            $this.find('.milestone-number').text(Math.floor(this.countNum));
13242          },
13243          complete: function () {
13244            $this.find('.milestone-number').text(this.countNum);
13245          }
13246        });
13247      }
13248    };
13249
13250    if ( !MK.utils.isMobile() ) {
13251      // refactored only :in-viewport logic. rest is to-do
13252      MK.utils.scrollSpy( this, {
13253          position: 'bottom',
13254          after: build
13255      });
13256    } else {
13257      build();
13258    }
13259
13260  });
13261
13262}
13263
13264
13265
13266
13267/* Recent Works Widget */
13268/* -------------------------------------------------------------------- */
13269
13270function mk_portfolio_widget() {
13271
13272  "use strict";
13273
13274  $('.widget_recent_portfolio li').each(function () {
13275
13276    $(this).find('.portfolio-widget-thumb').on('hover',function () {
13277
13278      $(this).siblings('.portfolio-widget-info').animate({
13279        'opacity': 1
13280      }, 200);
13281    }, function () {
13282
13283      $(this).siblings('.portfolio-widget-info').animate({
13284        'opacity': 0
13285      }, 200);
13286    });
13287
13288  });
13289}
13290
13291
13292
13293/* Skill Meter and Charts */
13294/* -------------------------------------------------------------------- */
13295function mk_skill_meter() {
13296    "use strict";
13297    if ($.exists('.mk-skill-meter')) {
13298        if (!MK.utils.isMobile()) {
13299            $(".mk-skill-meter .progress-outer").each(function() {
13300                var $this = $(this);
13301
13302                var build = function() {
13303                    if (!$this.hasClass('scroll-animated')) {
13304                        $this.addClass('scroll-animated');
13305                        $this.animate({
13306                            width: $this.attr("data-width") + '%'
13307                        }, 2000);
13308                    }
13309                };
13310
13311                MK.utils.scrollSpy( this, {
13312                    position: 'bottom',
13313                    after: build
13314                });
13315            });
13316        } else {
13317            $(".mk-skill-meter .progress-outer").each(function() {
13318                var $this = $(this);
13319                if (!$this.hasClass('scroll-animated')) {
13320                    $this.addClass('scroll-animated');
13321                    $this.css({
13322                        width: $(this).attr("data-width") + '%'
13323                    });
13324                }
13325            });
13326        }
13327    }
13328}
13329
13330// function mk_charts() {
13331//     "use strict";
13332
13333//     if( !$.exists('.mk-chart') ) return;
13334
13335//     MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.easyPieChart.js' ], function() {
13336
13337//         $('.mk-chart').each(function() {
13338
13339//             var $this = $(this),
13340//                 $parent_width = $(this).parent().width(),
13341//                 $chart_size = parseInt($this.attr('data-barSize'));
13342
13343//             if ($parent_width < $chart_size) {
13344//                 $chart_size = $parent_width;
13345//                 $this.css('line-height', $chart_size);
13346//                 $this.find('i').css({
13347//                     'line-height': $chart_size + 'px'
13348//                 });
13349//                 $this.css({
13350//                     'line-height': $chart_size + 'px'
13351//                 });
13352//             }
13353
13354//             var build = function() {
13355//                 $this.easyPieChart({
13356//                     animate: 1300,
13357//                     lineCap: 'butt',
13358//                     lineWidth: $this.attr('data-lineWidth'),
13359//                     size: $chart_size,
13360//                     barColor: $this.attr('data-barColor'),
13361//                     trackColor: $this.attr('data-trackColor'),
13362//                     scaleColor: 'transparent',
13363//                     onStep: function(value) {
13364//                         this.$el.find('.chart-percent span').text(Math.ceil(value));
13365//                     }
13366//                 });
13367//             };
13368
13369//             // refactored only :in-viewport logic. rest is to-do
13370//             MK.utils.scrollSpy( this, {
13371//                 position: 'bottom',
13372//                 after: build
13373//             });
13374
13375
13376//         });
13377//     });
13378// }
13379/* Toolbar subscribe form */
13380/* -------------------------------------------------------------------- */
13381
13382$( "#mc-embedded-subscribe-form" ).on('submit',function( e ){
13383    var $this = $(this);
13384
13385    e.preventDefault();
13386    $.ajax({
13387        url: MK.core.path.ajaxUrl,
13388        type: "POST",
13389        data: {
13390            action: "mk_ajax_subscribe",
13391            email: $this.find( ".mk-subscribe--email" ).val(),
13392            list_id: $this.find( ".mk-subscribe--list-id" ).val(),
13393            optin: $this.find( ".mk-subscribe--optin" ).val()
13394        },
13395        success: function ( res ) {
13396            $this.parent().find( ".mk-subscribe--message" ).html( $.parseJSON( res ).message );
13397        }
13398    });
13399});
13400
13401/**
13402 * Add class to tag. It's vanilla js instead of jQuery.
13403 * @param tag
13404 * @param className
13405 */
13406function addClass(tag, className) {
13407    tag.className += ' ' + className;
13408}
13409
13410/**
13411 * Remove class from tag. It's vanilla js instead of jQuery.
13412 * Replacing should be with g for replacing all occurrence.
13413 *
13414 * @param tag
13415 * @param className
13416 */
13417function removeClass(tag, className) {
13418    tag.className = tag.className.replace(new RegExp(className, 'g'), '');
13419}
13420
13421
13422/**
13423 * If we're running under Node for testing purpose.
13424 */
13425if(typeof exports !== 'undefined') {
13426    exports.addClass = addClass;
13427    exports.removeClass = removeClass;
13428}
13429
13430/*!
13431*  javascript-debounce 1.0.0
13432*
13433*  A lightweight, dependency-free JavaScript module for debouncing functions based on David Walsh's debounce function.
13434*
13435*  Source code available at: https://github.com/jgarber623/javascript-debounce
13436*
13437*  (c) 2015-present Jason Garber (http://sixtwothree.org)
13438*
13439*  javascript-debounce may be freely distributed under the MIT license.
13440*/
13441
13442(function(root, factory) {
13443	if (typeof define === "function" && define.amd) {
13444		define([], factory);
13445	} else if (typeof exports === "object") {
13446		module.exports = factory();
13447	} else {
13448		root.debounce = factory();
13449	}
13450})(this, function() {
13451	"use strict";
13452	return function(callback, delay) {
13453		var timeout;
13454		return function() {
13455			var context = this, args = arguments;
13456			clearTimeout(timeout);
13457			timeout = setTimeout(function() {
13458				callback.apply(context, args);
13459			}, delay);
13460		};
13461	};
13462});
13463
13464/**
13465 * Validate email address.
13466 *
13467 * @param input
13468 * @param invalidClassName
13469 * @returns boolean
13470 */
13471function validateEmail(input, invalidClassName) {
13472    var value = input.value.trim();
13473    if ((input.required || value.length > 0) && !/^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,63})$/i.test(value)) {
13474        if (invalidClassName) {
13475            addClass(input, invalidClassName);
13476        }
13477        return false;
13478    } else {
13479        if (invalidClassName) {
13480            removeClass(input, invalidClassName);
13481        }
13482        return true;
13483    }
13484}
13485/**
13486 * Validate text entry.
13487 *
13488 * @param input
13489 * @param invalidClassName
13490 * @returns boolean
13491 */
13492function validateText(input, invalidClassName) {
13493    var value = input.value.trim();
13494    if (input.required && value.length === 0) {
13495        if (invalidClassName) {
13496            addClass(input, invalidClassName);
13497        }
13498        return false;
13499    } else {
13500        if (invalidClassName) {
13501            removeClass(input, invalidClassName);
13502        }
13503        return true;
13504    }
13505}
13506/**
13507 * Validate Checkbox.
13508 *
13509 * @param input
13510 * @param invalidClassName
13511 * @returns boolean
13512 */
13513function validateCheckBox(input, invalidClassName) {
13514    if (input.required && input.checked == false) {
13515        if (invalidClassName) {
13516            addClass(input, invalidClassName);
13517        }
13518        return false;
13519    } else {
13520        if (invalidClassName) {
13521            removeClass(input, invalidClassName);
13522        }
13523        return true;
13524    }
13525}
13526/**
13527 * If we're running under Node for testing purpose.
13528 */
13529if (typeof exports !== 'undefined') {
13530    exports.validateEmail = validateEmail;
13531    exports.validateText = validateText;
13532}
13533(function( $ ) {
13534	'use strict';
13535
13536    var $wrapper = $('.js-bottom-corner-btns');
13537    var $contactBtn = $wrapper.find('.js-bottom-corner-btn--contact');
13538    var $backBtn = $wrapper.find('.js-bottom-corner-btn--back');
13539    var hasContactBtn = $contactBtn.length;
13540    var hasBackBtn = $backBtn.length;
13541
13542    if(!hasBackBtn) return;
13543
13544    function deactivate() {
13545        $contactBtn.removeClass('is-active');
13546        $backBtn.removeClass('is-active');
13547    }
13548
13549    function activate() { 
13550        $contactBtn.addClass('is-active');
13551        $backBtn.addClass('is-active');
13552    }
13553
13554    MK.utils.scrollSpy( 400, {
13555        before: deactivate,
13556        after: activate
13557    });
13558
13559})( jQuery );
13560(function( $ ) {
13561	'use strict';
13562
13563	MK.ui.preloader = {
13564		dom : {
13565			overlay: '.mk-body-loader-overlay'
13566		},
13567
13568		hide : function hide() {
13569			$( this.dom.overlay ).fadeOut(600, "easeInOutExpo", function() {
13570				$('body').removeClass('loading');
13571            //$( this ).remove();
13572         });
13573		}
13574	};  
13575
13576})( jQuery ); 
13577(function($) {
13578	'use strict';
13579	
13580	$('.mk-fullscreen-nav-close, .mk-fullscreen-nav-wrapper, #fullscreen-navigation a').on('click', function(e) {
13581		
13582		// Close nav with removing classes
13583		$('.mk-fullscreen-nav').removeClass('opened');
13584		$('.mk-dashboard-trigger').removeClass('fullscreen-active');
13585		$('body').removeClass('fullscreen-nav-opened'); 
13586		
13587		var anchor = MK.utils.detectAnchor( this ),
13588		$this = $( this );
13589		
13590		// Scroll to anchor if exists
13591		if( anchor.length ) {
13592			// Moved 4 these lines after anchor check because console error. If anchor
13593			// return false, split part will throw an error because $this is not a link.
13594			// Fix AM-2027
13595			var href = $this.attr( 'href' ).split( '#' )[0];
13596			var url = window.location.href;
13597			var isSamePage = url.indexOf( href ) !== -1;
13598
13599			if ( isSamePage ) {
13600				e.preventDefault();
13601			}
13602			MK.utils.scrollToAnchor( anchor );
13603			
13604		// Or do nothing if pointless # as href
13605		// BAD  PRACTICE: it is very popular to use "#" for click elements that we listen to with js.
13606		// GOOD PRACTICE: prefer "javascript:;" as easier to handle and more readable version
13607		} else if( $this.attr( 'href' ) === '#' ) {
13608			e.preventDefault();
13609		}
13610	});
13611	
13612	$('.fullscreen-navigation-ul .menu-sub-level-arrow').on('click', function(){
13613		$(this).siblings('.sub-menu').slideToggle();
13614	});
13615	
13616}(jQuery));
13617(function($) {
13618	'use strict';
13619
13620	/**
13621     * Mega menu
13622     */
13623    var $navList = $(".main-navigation-ul");
13624    var megaMenu = function megaMenu() {
13625
13626        $navList.MegaMenu({
13627            type: "vertical",
13628            delay: 200
13629        });
13630    };
13631
13632    $(window).on('load', megaMenu);
13633
13634}(jQuery));
13635(function($) {
13636	'use strict';
13637
13638	/**
13639     * One pager menu hash update. 
13640     * Smooth scroll is appended globally whenever the click element has corresponding #el
13641     */    
13642    var onePageNavItem = function onePageNavItem() {
13643        var $this = $( this ),
13644            link = $this.find( 'a' ),
13645            anchor = MK.utils.detectAnchor( link ); // anchor on current page
13646
13647        if( !anchor.length ) return;
13648
13649        $this.removeClass( 'current-menu-item current-menu-ancestor current-menu-parent' );
13650
13651        var activeNav = function( state ) {
13652            return function() {
13653                $this[ state ? 'addClass' : 'removeClass' ]( 'current-menu-item' );
13654                window.history.replaceState( undefined, undefined, [ state ? anchor : ' ' ] );
13655            };
13656        };
13657
13658        MK.utils.scrollSpy( $( anchor )[0], {
13659            before : activeNav( false ),
13660            active : activeNav( true ),
13661            after  : activeNav( false ),
13662        });
13663    };
13664
13665    var $navItems = $('.js-main-nav').find( 'li' );
13666    
13667    $(window).on('load', function() {
13668        // Wait with spying anchors so we do not assign anchor that is browser scroll to after page load
13669        // Especially when there are anchors on top - refreshing page can cause grabbing one of them into url
13670        // and force unwanted scroll
13671        setTimeout(function() {
13672            $navItems.each( onePageNavItem );
13673        }, 1000);
13674    });
13675	
13676}(jQuery));
13677(function($) {
13678    'use strict';
13679
13680    var $window = $(window);
13681    var $body = $('body');
13682    var $resMenuWrap = $('.mk-responsive-wrap');
13683    var $post_nav = $('.mk-post-nav');
13684    var $toolbar = $('.mk-header-toolbar');
13685    var $resMenuLink = $('.mk-nav-responsive-link');
13686
13687    // Flags
13688    var hasResMenu = ($resMenuWrap.length > 0);
13689
13690    //initial window and screen height
13691    var windowHeight = $window.height();
13692    var screenHeight = screen.height;
13693
13694    // We keep this handler above hasResMenu flag.
13695    // Even if our header doesn't contain droppable responsive menu (in favor of fullscreen or side menu) 
13696    // we still transform tollbar into collapsible menu part in responsive state
13697    $('.mk-toolbar-resposnive-icon').on('click', function(e) {
13698        e.preventDefault();
13699        console.log('clicked');
13700        if ($body.hasClass('toolbar-opened')) {
13701            $body.removeClass('toolbar-opened').addClass('toolbar-closed');
13702            $toolbar.hide();
13703        } else {
13704            $body.removeClass('toolbar-closed').addClass('toolbar-opened');
13705            $toolbar.show();
13706        }
13707    });
13708
13709
13710    if ( ! hasResMenu && ! $('.vc_mk_header') ) return;
13711
13712    function toggleResMenu(e) {
13713        e.preventDefault();
13714        var $this = $(this);
13715        var $headerInner = $this.parents('header');
13716        var $resMenu = $headerInner.find('.mk-responsive-wrap');
13717        var searchBox = $('.responsive-searchform .text-input');
13718        var adminBarHeight = $('#wpadminbar').height(); /* Fix AM-1918 */
13719
13720        if ($body.hasClass('mk-opened-nav')) {
13721            $this.removeClass('is-active');
13722            $body.removeClass('mk-opened-nav').addClass('mk-closed-nav').trigger('mk-closed-nav');
13723            $resMenu.hide();
13724            $post_nav.removeClass('post-nav-backward');
13725        } else {
13726            $this.addClass('is-active');
13727            $body.removeClass('mk-closed-nav').addClass('mk-opened-nav').trigger('mk-opened-nav');
13728            $resMenu.show();
13729            $post_nav.addClass('post-nav-backward');
13730
13731        }
13732
13733        //for iPhone 5 focus bug , remove search box focused class
13734        if(searchBox.hasClass('input-focused')){
13735            searchBox.removeClass('input-focused');
13736        }
13737        
13738    }
13739
13740    $resMenuLink.each(function() {
13741        $(this).on('click', toggleResMenu);
13742    });
13743
13744    $( window ).on( 'vc_reload', function () {
13745        $('.vc_mk_header .mk-nav-responsive-link').each(function() {
13746            $(this).on('click', toggleResMenu);
13747        });
13748    } )
13749
13750    var setResMenuHeight = function() {
13751        var height = $window.height() - MK.val.offsetHeaderHeight(0);
13752        $resMenuWrap.css('max-height', height);
13753    };
13754
13755    // check if device virtual keyboard is active 
13756    var isVirtualKeyboard = function() {
13757        var currentWindowHeight = $window.height();
13758        var currentScreenHeight = screen.height;
13759        var searchBox = $('.responsive-searchform .text-input');
13760        var searchBoxIsFocused = false; 
13761
13762        //for iPhone 5 focus bug , add class for detect focus state
13763        searchBox.on('touchstart touchend', function(e) {
13764            searchBox.addClass('input-focused');
13765        });
13766
13767        searchBoxIsFocused = (searchBox.is(':focus') || searchBox.hasClass("input-focused"));
13768
13769        if ($body.hasClass('mk-opened-nav') && searchBoxIsFocused && currentScreenHeight == screenHeight && currentWindowHeight != windowHeight) {
13770            return true;
13771        } else {
13772            return false;
13773        }
13774    };
13775
13776    var hideResMenu = function hideResMenu() {
13777        if (MK.utils.isResponsiveMenuState()) {
13778
13779            //when search box in responsive menu is focused , window resize fired but at this time responsive menu should be open
13780            if (!isVirtualKeyboard()) {
13781                // hide toggled menu and its states
13782                if ($body.hasClass('mk-opened-nav')) {
13783                    $resMenuLink.filter('.is-active').trigger('click');
13784                }
13785                // hide menu wrapper
13786                $resMenuWrap.hide();
13787
13788            }
13789        }
13790    };
13791
13792    $resMenuWrap.on('click', 'a', hideResMenu);
13793
13794}(jQuery));
13795
13796(function($) {
13797    'use strict';
13798
13799    var $header = $('.mk-header');    
13800    var hasHeader = ($header.length > 0);
13801
13802    if(!hasHeader && ! $('.vc_mk_header') ) return;
13803    
13804    var $sticky_style = $header.attr('data-header-style');
13805
13806    //if ($sticky_style !== 3) return;
13807
13808    $('.sidedash-navigation-ul > li').each(function() {
13809        var $this = $(this);
13810
13811        $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>');
13812    });
13813
13814    function toggleSubMenu(e) {
13815        e.preventDefault();
13816        var $this = $(this);
13817        
13818        if ($this.hasClass('mk-nav-sub-closed')) {
13819            $this.siblings('ul').slideDown(450).end().removeClass('mk-nav-sub-closed').addClass('mk-nav-sub-opened');
13820        } else {
13821            $this.siblings('ul').slideUp(450).end().removeClass('mk-nav-sub-opened').addClass('mk-nav-sub-closed');
13822        }
13823    };
13824
13825    function toggleFullMenu(e) {
13826        e.preventDefault();
13827        var $this = $(this),
13828            $body = $('body'),
13829            $fullscreen_box = $('.mk-fullscreen-nav');
13830
13831        if ($this.hasClass('dashboard-style')){
13832          if (!$this.hasClass('dashboard-active')) {
13833            $this.addClass('dashboard-active');
13834            $body.addClass('dashboard-opened');
13835          } else {
13836            $this.removeClass('dashboard-active'); 
13837            $body.removeClass('dashboard-opened');
13838          }
13839        }else if($this.hasClass('fullscreen-style')){
13840          if (!$this.hasClass('fullscreen-active')) {
13841            $this.addClass('fullscreen-active');
13842            $body.addClass('fullscreen-nav-opened');
13843            $fullscreen_box.addClass('opened');
13844            // MK.utils.scroll.disable();
13845          } else {
13846            $this.removeClass('fullscreen-active');
13847            $body.removeClass('fullscreen-nav-opened');
13848            $fullscreen_box.removeClass('opened');
13849          }
13850        }
13851    }
13852
13853    $('.mk-nav-arrow').each(function() {
13854        $(this).stop(true).on('click', toggleSubMenu);
13855    });
13856
13857    $('.mk-dashboard-trigger').each(function() {
13858        $(this).on('click', toggleFullMenu);
13859    });
13860
13861    $( window ).on( 'vc_reload', function () {
13862        $('.vc_mk_header .mk-dashboard-trigger').each(function() {
13863            $(this).on('click', toggleFullMenu);
13864        });
13865
13866        $('.vc_mk_header .mk-nav-arrow').each(function() {
13867            $(this).stop(true).on('click', toggleSubMenu);
13868       });
13869    } );
13870
13871    $('html').on('click', function() {
13872        $('body').removeClass('dashboard-opened');
13873        $('.mk-dashboard-trigger').removeClass('dashboard-active');
13874    });
13875
13876}(jQuery));
13877
13878(function($) {
13879	'use strict';
13880
13881    /**
13882     * Vertical menu
13883     */
13884    var $verticalMenu = $('#mk-vm-menu');
13885    var verticalMenu = function verticalMenu() {
13886        if(!$verticalMenu.data('vertical-menu') && !MK.utils.isResponsiveMenuState()) {
13887            $verticalMenu.dlmenu();
13888            $verticalMenu.data('vertical-menu', true);
13889        }
13890    };
13891
13892    verticalMenu();
13893    $(window).on('resize', verticalMenu);
13894	
13895}(jQuery));
13896(function($) {
13897    'use strict';
13898
13899    // WPML
13900    var $lang_item = $('.mk-main-navigation > .main-navigation-ul > .menu-item-language');
13901    $lang_item.addClass('no-mega-menu').css('visibility', 'visible');
13902    $('.mk-main-navigation .menu-item-language > a').addClass('menu-item-link');
13903
13904})(jQuery);
13905(function($) {
13906	'use strict';
13907
13908    var $header = $( '.mk-header' ).first(); // Theme header is always first, do not apply to shortcode headers.
13909    var hasHeader = ($header.length > 0);
13910
13911    if(!hasHeader) return;
13912
13913    var $window = $( window );
13914    var $document = $( document );
13915    var $headerHolder = $header.find( '.mk-header-holder' );
13916    var $paddingWrapper = $header.find('.mk-header-padding-wrapper');
13917    var config = $header.data();
13918
13919    /**
13920     * Flags
13921     * @type {Boolean}
13922     */
13923    var isStickyLazy = (config.stickyStyle === 'lazy');
13924    var isStickyFixed = (config.stickyStyle === 'fixed');
13925    var isStickySlide = (config.stickyStyle === 'slide');
13926
13927    function isSticky() { // Check for sticky compatibility
13928        //return config.headerStyle !== 4; header style 4 needs sticky state for transparent header.
13929        return true;
13930    }
13931
13932    function isColorable() { // Check for coloring compatibility
13933        // TODO make it explicit in DOM that header is transparent as this is only scenario for colorable header
13934        // Monkey patch - exclude header styles that don't fit colorable
13935        return config.headerStyle !== 4;
13936    }
13937
13938
13939    /**
13940     * Change header skin
13941     */
13942	function changeSkin( e, skin ) {
13943		$header.attr( 'data-transparent-skin', skin );
13944        // Fix for class based skining
13945        var contrast = skin === 'light' ? 'dark' : 'light';
13946        $header.addClass(skin + '-skin');
13947        $header.removeClass(contrast + '-skin');
13948	}
13949
13950    if(isColorable()) MK.utils.eventManager.subscribe( 'firstElSkinChange', changeSkin );
13951
13952
13953    // Assign sticky scenarions
13954    if (isSticky() && isStickyLazy) {
13955      if(config.headerStyle !== 2) {
13956        lazySticky();
13957      }
13958    }
13959    else if (isSticky() && isStickyFixed) fixedSticky();
13960    else if (isSticky() && isStickySlide) slideSticky();
13961
13962    /**
13963     * Sticky header behavior: Lazy
13964     */
13965    function lazySticky() {
13966        var elClassHidden = 'header--hidden';
13967        var elClassSticky = 'a-sticky';
13968        var wScrollCurrent = 0;
13969        var wScrollBefore = 0;
13970        var wScrollDiff = 0;
13971        var wHeight = 0;
13972        var dHeight = 0;
13973
13974        var setSizes = function setSizes() {
13975            dHeight = $document.height();
13976            wHeight = $window.height();
13977        };
13978
13979        var onScroll = function onScroll() {
13980            wScrollCurrent = MK.val.scroll();
13981            wScrollDiff = wScrollBefore - wScrollCurrent;
13982
13983            if( wScrollCurrent <= 0 ) { // scrolled to the very top; element sticks to the top
13984                $headerHolder.removeClass( elClassHidden );
13985                $header.removeClass( elClassSticky );
13986                $('body').trigger('mk:header-unsticky');
13987
13988            } else if( wScrollDiff > 0 && $headerHolder.hasClass( elClassHidden ) ) { // scrolled up; element slides in
13989                $headerHolder.removeClass( elClassHidden );
13990                $header.addClass( elClassSticky );
13991                $('body').trigger('mk:header-sticky');
13992
13993            } else if( wScrollDiff < 0 ) { // scrolled down
13994
13995                if( wScrollCurrent + wHeight >= dHeight && $headerHolder.hasClass( elClassHidden ) ) { // scrolled to the very bottom; element slides in
13996                    $headerHolder.removeClass( elClassHidden );
13997                    $header.addClass( elClassSticky );
13998                    $('body').trigger('mk:header-sticky');
13999                } else { // scrolled down; element slides out
14000                    $headerHolder.addClass( elClassHidden );
14001                    $header.removeClass( elClassSticky );
14002                    $('body').trigger('mk:header-unsticky');
14003                }
14004            }
14005
14006            wScrollBefore = wScrollCurrent;
14007        };
14008
14009        setSizes();
14010        onScroll();
14011        $window.on( 'resize', MK.utils.throttle( 100, setSizes ) );
14012        $window.on( 'scroll', MK.utils.throttle( 500, onScroll ) );
14013    }
14014
14015
14016    /**
14017     * Sticky header behavior: Fixed
14018     */
14019    function fixedSticky() {
14020        var sticked = false;
14021        var scrollPos;
14022
14023        var toggleState = function toggleState() {
14024            scrollPos = MK.val.scroll() + MK.val.adminbarHeight();
14025
14026            if( (scrollPos > MK.val.stickyOffset() ) && ! MK.utils.isResponsiveMenuState() ) {
14027                if(sticked) return; // stop if already sticked
14028                $header.addClass('a-sticky');
14029                sticked = true;
14030                $('body').trigger('mk:header-sticky');
14031            } else {
14032                if(!sticked) return; // stop if already unsticked
14033                $header.removeClass('a-sticky');
14034                sticked = false;
14035                $('body').trigger('mk:header-unsticky');
14036            }
14037        };
14038
14039        toggleState();
14040        $window.on( 'scroll', MK.utils.throttle( 100, toggleState) );
14041        $window.on( 'resize', MK.utils.throttle( 100, toggleState) );
14042    }
14043
14044
14045    /**
14046     * Sticky header behavior: Slide
14047     */
14048    function slideSticky() {
14049        var sticked = false;
14050        var onScroll = function onScroll() {
14051            if (MK.val.scroll() > MK.val.stickyOffset()) {
14052                if(sticked) return; // stop if already sticked
14053                $header.addClass('pre-sticky');
14054                $paddingWrapper.addClass('enable-padding');
14055                setTimeout(function() {
14056                    $header.addClass('a-sticky');
14057                    $('body').trigger('mk:header-sticky');
14058                }, 1);
14059                sticked = true;
14060            } else {
14061                if(!sticked) return; // stop if already unsticked
14062                $header.removeClass('a-sticky');
14063                $header.removeClass('pre-sticky');
14064                $paddingWrapper.removeClass('enable-padding');
14065                sticked = false;
14066                $('body').trigger('mk:header-unsticky');
14067            }
14068        };
14069
14070        onScroll();
14071        $window.on( 'scroll', MK.utils.throttle( 100, onScroll) );
14072    }
14073
14074    // TODO
14075    // var pageIntro = $('body').data('intro'); // block scrolling on page intro
14076
14077
14078})( jQuery );
14079
14080(function($){
14081	'use strict';
14082
14083	// Do not assign at all if no touch events
14084	var hasTouchscreen = ('ontouchstart' in document.documentElement);
14085	if(!hasTouchscreen) return;
14086
14087	$('.mk-main-navigation .menu-item-has-children').each( normalizeClick );
14088
14089	function normalizeClick() {
14090		$(this).on('click', handleClick);
14091	}
14092
14093	// 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.
14094	// 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
14095	function handleClick(e) {
14096		var $this = $(e.currentTarget);
14097		var $child = $this.find('> ul');
14098		var isVisible = $child.css('display') !== 'none';
14099
14100		if(!isVisible) {
14101			e.preventDefault();
14102			e.stopPropagation();
14103		}
14104	}
14105
14106}(jQuery));
14107(function($) {
14108	'use strict';
14109
14110    var _ajaxUrl = MK.core.path.ajaxUrl;
14111    var _instances = {};
14112
14113	MK.utils.ajaxLoader = function ajaxLoader(el) {
14114		// retrun a cached instance to have control over state from within multiple places
14115		// we may need for example to reset pageId when do filtering. It is really one instance that controls both filtering and pagination / load more
14116		var id = '#' + ($(el).attr('id'));
14117		if(typeof _instances[id] !== 'undefined') return _instances[id];
14118
14119		// else lets start new instance
14120		this.id = id;
14121		this.el = el;
14122		this.isLoading = false;
14123		this.xhrCounter = 0;
14124	};
14125
14126	MK.utils.ajaxLoader.prototype = { 
14127		init: function init() {
14128			// prevent double initialization of we return an instance
14129			if ( this.initialized && typeof window.vc_iframe === 'undefined' ) {
14130				return;
14131			}
14132
14133			this.createInstance();
14134			this.cacheElements();
14135
14136			this.initialized = true;
14137		},
14138
14139		cacheElements: function cacheElements() {
14140			this.$container = $(this.el);
14141			this.id = '#' + (this.$container.attr('id'));
14142	        this.categories = this.$container.data('loop-categories');
14143
14144			this.data = {};
14145			this.data.action = 'mk_load_more';
14146	        this.data.query = this.$container.data('query');
14147	        this.data.atts = this.$container.data('loop-atts');
14148	        this.data.loop_iterator = this.$container.data('loop-iterator');
14149	        this.data.author = this.$container.data('loop-author');
14150	        this.data.posts = this.$container.data('loop-posts');
14151	        this.data.safe_load_more = this.$container.siblings('#safe_load_more').val();
14152	        this.data._wp_http_referer = this.$container.siblings('input[name="_wp_http_referer"]').val();
14153	        this.data.paged = 1;
14154	        this.data.maxPages = this.$container.data('max-pages');
14155	        this.data.term = this.categories;
14156		},
14157
14158		createInstance: function() {
14159			_instances[this.id] = this;
14160		},
14161
14162		load: function load(unique) {
14163			var self = this;
14164			var seq = ++this.xhrCounter;
14165            this.isLoading = true;
14166			
14167			// If mk-ajax-loaded-posts span exists, get the post ids
14168			if ( this.$container.siblings('.mk-ajax-loaded-posts').length ) {
14169				var loaded_posts = this.$container.siblings('.mk-ajax-loaded-posts').attr('data-loop-loaded-posts');
14170				
14171				// Do not send looaded posts for Classic Pagination Navigation
14172				if ( this.$container.attr('data-pagination-style') != 1 ) {
14173					self.data.loaded_posts = loaded_posts.split(',');
14174				}
14175			}
14176
14177            return $.when(
14178	            $.ajax({
14179	                url 	: _ajaxUrl,
14180	                type 	: "POST",
14181	                data 	: self.data
14182	            })
14183	        ).done(function(response) {
14184	        	self.onDone(response, unique, seq);
14185	        });
14186		},
14187
14188		onDone: function(response, unique, seq) {
14189			if(seq === this.xhrCounter) {
14190				var self = this;
14191
14192				response = $.parseJSON(response);
14193				response.unique = unique;
14194				response.id = this.id;
14195				
14196				// If mk-ajax-loaded-posts span exists, update current post ids 
14197				// with new post ids from server's response
14198				if ( this.$container.siblings('.mk-ajax-loaded-posts').length ) {
14199					this.$container.siblings('.mk-ajax-loaded-posts').attr('data-loop-loaded-posts', response.loaded_posts);
14200				}
14201
14202	            this.setData({
14203	                maxPages: response.maxPages,
14204	                found_posts: response.found_posts,
14205	                loop_iterator: response.i
14206	            });
14207
14208				// Preload images first by creating object from returned content.
14209				// mk_imagesLoaded() method will create a promise that gets resolved when all images inside are loaded.
14210				// Our ajaxLoad is somehow more similar to window.onload event now.
14211				$(response.content).mk_imagesLoaded().then(function() {
14212					MK.utils.eventManager.publish('ajaxLoaded', response);
14213		        	self.isLoading = false;
14214		        	self.initNewComponents();
14215				});
14216
14217	        } else console.log('XHR request nr '+ seq +' aborted');
14218
14219        },
14220
14221		setData: function setData(atts) {
14222			for(var att in atts) {
14223				if(att === 'term' && atts[att] === '*') this.data.term = '';
14224				else this.data[att] = atts[att];
14225			}
14226		},
14227
14228		getData: function getData(att) {
14229			return this.data[att];
14230		},
14231
14232		initNewComponents: function initNewComponents() {
14233            // Legacy scripts reinit
14234            window.ajaxInit();
14235            setTimeout(window.ajaxDelayedInit, 1000);
14236            // New way to init apended things
14237            MK.core.initAll(this.el);
14238        }
14239	};
14240
14241}(jQuery));
14242(function( $ ) {
14243	'use strict';
14244
14245	var val = MK.val;
14246
14247	MK.component.FullHeight = function( el ) {
14248		var $window = $( window ),
14249			$this = $( el ),
14250			config = $this.data( 'fullheight-config' ),
14251			container = document.getElementById( 'mk-theme-container' ),
14252			minH = (config && config.min) ? config.min : 0,
14253			winH = null,
14254			height = null,
14255			update_count = 0,
14256			testing = MK.utils.getUrlParameter('testing'),
14257			offset = null;
14258
14259		// We need to provide height on the same specificity level for workaround to IE bug
14260		// connect.microsoft.com/IE/feedback/details/802625/min-height-and-flexbox-flex-direction-column-dont-work-together-in-ie-10-11-preview
14261		// stackoverflow.com/questions/19371626/flexbox-not-centering-vertically-in-ie
14262		if(MK.utils.browser.name === ('IE' || 'Edge')) $this.css( 'height', '1px' );
14263
14264		var update = function() {
14265
14266			if(update_count === 0) {
14267				winH = $window.height();
14268				// for correct calculate
14269				offset = $this.offset().top - 1;
14270				height = Math.max(minH, winH - val.offsetHeaderHeight( offset ));
14271				$this.css( 'min-height', height );
14272				if(testing !== undefined )
14273				update_count++;
14274			}
14275
14276		};
14277
14278		// TODO remove scroll listener by dynamic offset reader
14279		var init = function() {
14280			update();
14281			$window.on( 'resize', update );
14282			$window.on( 'scroll', update );
14283			window.addResizeListener( container, update );
14284		};
14285
14286		return {
14287			init : init
14288		};
14289	};
14290
14291})( jQuery );
14292
14293
14294(function( $ ) {
14295	'use strict';
14296
14297	/**
14298	 * A fork from original VC function.
14299	 * The original one is adding some padding which causes extra padding
14300	 * on our templates so we customized the codes.
14301	 *
14302	 * @since 5.9.8
14303	 * @since 6.0.1 Improve logic to handle LTR responsive state.
14304	 * @since 6.0.1 Fix missing padding-left if row has its own padding-left when
14305	 *              Vertical Header is active.
14306	 */
14307	function MkfullWidthRow() {
14308		var $windowWidth = $(document).width();
14309		var $elements = $('[data-mk-full-width="true"]');
14310		var direction = $('body.rtl').length ? 'right' : 'left';
14311		var verticalHeader = $('body.vertical-header-enabled').length ? true : false;
14312		var verticalHeaderWidth = ( $( '.header-style-4 .mk-header-inner' ).outerWidth() > 270 ) ? 0 : 270;
14313		var verticalHeaderRtl = $('body.rtl').length ? -1 : 1;
14314		var verticalHeaderRtlWidth = $('body.rtl.vertical-header-enabled').length ? verticalHeaderWidth : 0;
14315		var verticalHeaderRight = $('body.vertical-header-right').length ? -1 : 1;
14316		var verticalHeaderWidthBoxed = 0;
14317		var boxed = $('body.mk-boxed-enabled').length;
14318		var boxedOffset = ( boxed ) ? ( $(window).width() - $('#theme-page').outerWidth() ) / 2 : 0;
14319		var boxedMaxWidth = ( boxed ) ? $('#theme-page').outerWidth() : 'auto';
14320
14321		if ( verticalHeader && boxed ) {
14322			verticalHeaderWidthBoxed = ( $( '.header-style-4 .mk-header-inner' ).outerWidth() > 270 ) ? 0 : verticalHeaderRtl * verticalHeaderRight * 135;
14323		}
14324
14325		var transparentHeader = $('.transparent-header').length;
14326		if ( transparentHeader > 0 ) {
14327			verticalHeaderWidthBoxed = 0;
14328		}
14329
14330		$.each($elements, function(key, item) {
14331			var $el = $(this);
14332			var css;
14333			$el.addClass("vc_hidden");
14334			var $el_full = $el.next(".vc_row-full-width");
14335			if ($el_full.length || ($el_full = $el.parent().next(".vc_row-full-width")), $el_full.length) {
14336				var el_margin_left = parseInt($el.css("margin-left"), 10),
14337				el_margin_right = parseInt($el.css("margin-right"), 10),
14338				offset = 0 - $el_full.offset().left - el_margin_left,
14339				width = $(window).width();
14340				if (css = {
14341					position: "relative",
14342					"box-sizing": "border-box",
14343					width: $(window).width(),
14344					maxWidth: boxedMaxWidth
14345				},
14346				css[direction] = offset + boxedOffset + verticalHeaderWidthBoxed + ( verticalHeaderRight * verticalHeaderRtlWidth ),
14347				$el.css(css), !$el.data("mkStretchContent")) {
14348					var padding = -1 * offset;
14349					0 > padding && (padding = 0);
14350					var paddingRight = width - padding - $el_full.width() + el_margin_left + el_margin_right;
14351					padding = padding - paddingRight;
14352					if ( 0 > paddingRight && (paddingRight = 0) ) {
14353						css = {};
14354						if ( 'right' === direction ) {
14355							css["padding-left"] = padding + "px";
14356							css["padding-right"] = 0;
14357						} else {
14358							css["padding-right"] = padding + "px";
14359							css["padding-left"] = 0;
14360						}
14361
14362						$el.css(css)
14363					}
14364				}
14365
14366				/**
14367				 * Fix AM-2974
14368				 *
14369				 * When user set padding-left or padding-right in the row, both of them
14370				 * will be prioritized as important styles. It breaks padding-left set
14371				 * by Vertical Header to make the row content fit with the content
14372				 * container. We need to repopulate the padding-{side - based on Vertical
14373				 * Header position} value.
14374				 *
14375				 * Works when:
14376				 * - Vertical Header is active
14377				 * - Main layout is not boxed
14378				 * - Page Section is full layout
14379				 * - Row is full width layout and content
14380				 * - Row has its own padding-left and padding-right
14381				 * - There is no additional padding added
14382				 *
14383				 * How it works:
14384				 * Get current row padding-left and vertical header width. If both of them
14385				 * are equal, it means row position is correct related to Vertical Header.
14386				 * If not, we should sum both of them, then declare new padding-{side}
14387				 * style attribute.
14388				 *
14389				 * Tested with:
14390				 * - Main Layout: Full & Boxed Layout
14391				 * - Page Section: Full Layout and Non Full Layout
14392				 * - Row: Full Width, Full Width Content, and Non Full Width
14393				 * - Header: Non vertical headers
14394				 * - Transparent Header
14395				 * - RTL and LTR
14396				 */
14397				if ( verticalHeader && ! boxed && ! transparentHeader && ! css.hasOwnProperty( 'padding-left' ) && ! css.hasOwnProperty( 'padding-right' )) {
14398					// Get row padding-{side} and Vertical Header width.
14399					var side = 'left';
14400					if ( verticalHeaderRight === -1 ) {
14401						side = 'right';
14402					}
14403					var el_padding_dir = parseInt( $el.css( 'padding-' + side ), 10 );
14404					var header_padding_dir = $( '.header-style-4 .mk-header-inner' ).outerWidth();
14405					// Compare both of row and vertical header padding-{side}.
14406					if ( el_padding_dir != header_padding_dir) {
14407						if($windowWidth > mk_responsive_nav_width) {
14408							$el[0].style.setProperty( 'padding-' + side, header_padding_dir + 'px', 'important' );	
14409						} else {
14410							$el[0].style.removeProperty( 'padding-' + side);	
14411						}
14412						
14413
14414						// Reset padding-{side} for page section.
14415						var $el_page_section = $el.find( '.mk-page-section.full_layout' );
14416						if ( $el_page_section.length > 0 ) {
14417							$el_page_section[0].style.setProperty( 'padding-' + side, 'unset', 'important' );
14418						}
14419					}
14420				}
14421
14422				$el.attr("data-mk-full-width-init", "true"), $el.removeClass("vc_hidden"), $(document).trigger("vc-full-width-row-single", {
14423					el: $el,
14424					offset: offset,
14425					marginLeft: el_margin_left,
14426					marginRight: el_margin_right,
14427					elFull: $el_full,
14428					width: width
14429				})
14430			}
14431		}
14431), $(document).trigger("mk-full-width-row", $elements);
14432	}
14433
14434	MkfullWidthRow();
14435	var debounceResize = null;
14436	$(window).on("resize", function() {
14437		if( debounceResize !== null ) { clearTimeout( debounceResize ); }
14438		debounceResize = setTimeout( MkfullWidthRow, 100 );
14439	});
14440
14441})( jQuery );
14442
14443MK.component.BackgroundImageSetter = (function ($) {
14444
14445	'use strict';
14446
14447	var module = {};
14448
14449
14450	/*---------------------------------------------------------------------------------*/
14451	/* Private Variables
14452	/*---------------------------------------------------------------------------------*/
14453
14454	/**
14455	 *	Take all elements with data-mk-img-set attribute and evaluate best image according to given device orientation and resolution,
14456	 *	sets style for backround-image on the same node element.	 *
14457	 */
14458
14459	var $win = $(window),
14460		// $layers = $('[data-mk-img-set]'),
14461		screen = getScreenSize(),
14462		orientation = getOrientation(),
14463		device = getDevice(),
14464		lastOrientation = orientation,
14465		lastDevice = device;
14466
14467
14468	/*---------------------------------------------------------------------------------*/
14469	/* Private Methods
14470	/*---------------------------------------------------------------------------------*/
14471
14472	function run($layers) {
14473		$layers.filter( function() {
14474			return !this.hasAttribute("mk-img-loaded");
14475		}).each(applyBg);
14476	}
14477
14478	// Keep our main side effect out of calculations so they can be run once before loop of applying bg as a result
14479	function applyBg() {
14480		var $this = $(this),
14481			imgs = $this.data('mk-img-set');
14482
14483		$this.css('background-image', 'url('+ module.getImage(imgs) +')');
14484		$this.find('.mk-adaptive-image').attr('src', module.getImage(imgs));
14485	}
14486
14487	// Keep track of current screen size while resizing but update device reference
14488	// and reapply backgrounds only when we discover switch point
14489	function handleResize($layers) {
14490		updateScreenSize();
14491		if(hasSwitched()) {
14492			updateDevice();
14493			run($layers);
14494		}
14495	}
14496
14497	function getScreenSize() {
14498		return {
14499			w: $win.width(),
14500			h: $win.height()
14501		};
14502	}
14503
14504	// Name our device classes and add them id which simply means which one is wider
14505	function getDevice() {
14506		if     (screen.w > 1024) 	return {class: 'desktop', id: 2};
14507		else if(screen.w > 736) 	return {class: 'tablet',  id: 1};
14508		else 					 	return {class: 'mobile',  id: 0};
14509	}
14510
14511	function getOrientation() {
14512		if(screen.w > screen.h) 	return 'landscape';
14513		else 						return 'portrait';
14514	}
14515
14516	function updateScreenSize() {
14517		screen = getScreenSize();
14518	}
14519
14520	function updateDevice() {
14521		if(lastOrientation !== orientation) orientation = lastOrientation;
14522		// Switch device only if going from smaller size to bigger.
14523		// Bigger to smaller is perfectly handled by browsers and doesn't require change and reupload
14524		if(lastDevice.id > device.id) device = lastDevice;
14525	}
14526
14527	function hasSwitched() {
14528		lastOrientation = getOrientation();
14529		lastDevice = getDevice();
14530
14531		if(lastOrientation !== orientation || lastDevice.class !== device.class) return true;
14532		else return false;
14533	}
14534
14535
14536	/*---------------------------------------------------------------------------------*/
14537	/* Public Methods
14538	/*---------------------------------------------------------------------------------*/
14539
14540	// As desired image might be not available we have to evaluate the best match.
14541	module.getImage = function (imgs) {
14542		if (imgs['responsive'] === 'false') {
14543			return (imgs['landscape']['desktop']) ? imgs['landscape']['desktop'] : (imgs['landscape']['external'] ? imgs['landscape']['external'] : '');
14544
14545		}
14546		var hasOrientation = !!imgs[orientation];
14547		// there are only two orientations now and we may get them by string name if both are there
14548		// 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.
14549		// 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
14550		var imgOriented = imgs[ (hasOrientation ? orientation : Object.keys(imgs)[0]) ],
14551			imgExact    = (imgOriented[device.class]) ? imgOriented[device.class] : (imgOriented['external'] ? imgOriented['external'] : '');
14552		return imgExact;
14553	}
14554
14555	module.init = function ($layers) {
14556
14557		// Run and bind
14558		run($layers);
14559		$layers.attr('mk-img-loaded', '');
14560	};
14561
14562	module.onResize = function ($layers) {
14563		$win.on('resize', MK.utils.throttle( 500, function() {
14564			handleResize($layers);
14565		}));
14566	};
14567
14568	return module;
14569
14570}(jQuery));
14571
14572
14573jQuery(function($) {
14574
14575	var init = function init() {
14576		// Get All Layers, Excluding Edge Slider and Page Section
14577		$allLayers = $('[data-mk-img-set]').filter(function(index) {
14578			return !$(this).hasClass('mk-section-image') && !$(this).hasClass('background-layer') && !$(this).hasClass('mk-video-section-touch');
14579		});;
14580
14581		// Handle the resize
14582		MK.component.BackgroundImageSetter.onResize($allLayers);
14583
14584		// Set all the BG Layers
14585		MK.component.BackgroundImageSetter.init($allLayers);
14586	}
14587	init();
14588
14589	$(window).on('vc_reload', init);
14590
14591});
14592
14593(function( $ ) {
14594	'use strict';
14595
14596	var core  = MK.core,
14597		utils = MK.utils,
14598		path  = MK.core.path;
14599
14600
14601	MK.ui.FullScreenGallery = function( element, settings ) {
14602		this.element = element;
14603		this.config = settings;
14604
14605		this.isFullScreen = false;
14606	};
14607
14608
14609	// preload slick PLUGIN TO USE THIS
14610	MK.ui.FullScreenGallery.prototype = {
14611		dom : {
14612			fullScrBtn 		: '.slick-full-screen',
14613			exitFullScrBtn 	: '.slick-minimize',
14614			playBtn 		: '.slick-play',
14615			pauseBtn 		: '.slick-pause',
14616			shareBtn 		: '.slick-share',
14617			socialShare 	: '.slick-social-share',
14618		    wrapper 		: '.slick-slider-wrapper',
14619			slider 			: '.slick-slides',
14620			slides 			: '.slick-slide',
14621			dots 			: '.slick-dot',
14622			active 			: '.slick-active',
14623			hiddenClass 	: 'is-hidden',
14624			dataId 			: 'slick-index'
14625		},
14626
14627		tpl: {
14628			dot  : '<div class="slick-dot"></div>',
14629			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>',
14630			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>'
14631		},
14632
14633		init : function() { 
14634			var self = this;
14635
14636			// core.loadDependencies([ path.plugins + 'slick.js' ], function() {
14637				self.cacheElements();
14638				self.getViewportSizes();
14639				self.updateSizes( 'window' );
14640				self.create();
14641				// update cache with elements propagated by plugin
14642				self.updateCacheElements();
14643				self.createPagination();
14644				self.bindEvents();
14645			// });
14646		},
14647
14648		create : function() {
14649			var self = this;
14650
14651			this.slick = this.$gallery.slick({
14652		        dots: true,
14653		        arrows: true,
14654				infinite: true,
14655				speed: 300,
14656				slidesToShow: 1,
14657				centerMode: true,
14658				centerPadding: '0px',
14659				variableWidth: true,
14660				autoplay: false,
14661				autoplaySpeed: 3000,
14662        		useTransform: true,
14663                prevArrow: self.tpl.prev,
14664                nextArrow: self.tpl.next,
14665                customPaging: function(slider, i) {
14666                    return self.tpl.dot;
14667                },
14668			});
14669		},
14670
14671		cacheElements : function() {
14672			this.$window = $( window );
14673			this.$gallery = $( this.element );
14674
14675			this.$fullScrBtn = $( this.dom.fullScrBtn );
14676			this.$exitFullScrBtn = $( this.dom.exitFullScrBtn );
14677			this.$playBtn = $( this.dom.playBtn );
14678			this.$pauseBtn = $( this.dom.pauseBtn );
14679			this.$shareBtn = $( this.dom.shareBtn );
14680			this.$socialShare = $( this.dom.socialShare );
14681
14682		    this.$wrapper = $( this.dom.wrapper );
14683			this.$slider = $( this.dom.slider );
14684			this.$slides = $( this.dom.slides );
14685			this.$imgs = this.$slides.find( 'img' );
14686			// store reference to initial images without slides appended by pugin
14687			// - needed for creating of pagination
14688			this.$originalImgs = this.$imgs;
14689		},
14690
14691		updateCacheElements : function() {
14692			this.$slides = $( this.dom.slides );
14693			this.$imgs = this.$slides.find( 'img' );
14694			this.$dots = $( this.dom.dots );
14695		},
14696
14697		bindEvents : function() {
14698			var self = this;
14699			this.$fullScrBtn.on( 'click', this.toFullScreen.bind( this ) );
14700			this.$exitFullScrBtn.on( 'click', this.exitFullScreen.bind( this ) );
14701			this.$playBtn.on( 'click', this.play.bind( this ) );
14702			this.$pauseBtn.on( 'click', this.pause.bind( this ) );
14703			this.$shareBtn.on( 'click', this.toggleShare.bind( this ) );
14704			this.$socialShare.on( 'click', 'a', this.socialShare.bind( this ) );
14705			this.$window.on( 'resize', this.onResize.bind( this ) );
14706			this.$window.on( 'keydown', function(e) {
14707				if(e.keyCode === 39) self.$gallery.slick('slickNext');
14708				if(e.keyCode === 37) self.$gallery.slick('slickPrev');
14709			});
14710			$( document ).on( 'fullscreenchange mozfullscreenchange webkitfullscreenchange msfullcreenchange', this.exitFullScreen.bind( this ) );
14711		},
14712
14713		getViewportSizes : function() {
14714			this.screen = {
14715				w: screen.width,
14716				h: screen.height
14717			};
14718			this.window = {
14719				w: this.$window.width(),
14720				h: this.$window.height()
14721			};
14722		},
14723
14724		updateSizes : function( viewport ) {
14725			this.$wrapper.width( this[ viewport ].w );
14726			this.$wrapper.height( '100%' );
14727			this.$imgs.height( '100%');
14728		},
14729
14730		createPagination : function() {
14731			var self = this;
14732			this.$dots.each( function( i ) {
14733				var img = self.$originalImgs.eq( i ).attr( 'src' );
14734
14735				$( this ).css({
14736					'background-image': 'url('+ img +')'
14737				});
14738			});	
14739		},
14740
14741		play : function(e) {
14742			e.preventDefault();
14743			this.$playBtn.addClass( this.dom.hiddenClass );
14744			this.$pauseBtn.removeClass( this.dom.hiddenClass );
14745			$( this.element ).slick( 'slickPlay' );
14746		},
14747
14748		pause : function(e) {
14749			e.preventDefault();
14750			this.$pauseBtn.addClass( this.dom.hiddenClass );
14751			this.$playBtn.removeClass( this.dom.hiddenClass );
14752			$( this.element ).slick( 'slickPause' );
14753		},
14754
14755		toggleShare : function(e) {
14756			e.preventDefault();
14757			this.$socialShare.toggleClass( this.dom.hiddenClass );
14758		},
14759
14760		getCurentId : function() {
14761			return this.$slides.filter( this.dom.active ).data( this.dom.dataId );
14762		},
14763
14764		toFullScreen : function() {
14765			var self = this;
14766
14767			this.$fullScrBtn.addClass( this.dom.hiddenClass );
14768			this.$exitFullScrBtn.removeClass( this.dom.hiddenClass );
14769
14770			this.$slider.hide().fadeIn( 500 );
14771			utils.launchIntoFullscreen( document.documentElement );
14772			this.updateSizes( 'screen' );
14773			$( this.element ).slick( 'slickGoTo', this.getCurentId(), true );
14774
14775			// Update state with delay so we avoid triggering exitFullScreen fn from 
14776			// fullscreenchange event
14777			setTimeout( function() {
14778				self.isFullScreen = true;
14779			}, 1000);					
14780		},
14781
14782		exitFullScreen : function() {
14783			if( this.isFullScreen ) { 
14784				this.$exitFullScrBtn.addClass( this.dom.hiddenClass );
14785				this.$fullScrBtn.removeClass( this.dom.hiddenClass );
14786
14787				utils.exitFullscreen();
14788				this.updateSizes( 'window' );
14789				$( this.element ).slick( 'slickGoTo', this.getCurentId(), true );
14790
14791				this.isFullScreen = false;
14792			}
14793
14794		},
14795
14796		onResize : function() {
14797			this.getViewportSizes();
14798			this.updateSizes( this.isFullScreen ? 'screen' : 'window' );
14799			$( this.element ).slick( 'refresh' );  
14800			$( this.element ).slick( 'slickGoTo', this.getCurentId(), true );
14801			this.updateCacheElements();
14802			this.createPagination();
14803		},
14804
14805		socialShare : function( e ) {
14806			e.preventDefault();
14807			var $this = $( e.currentTarget ),
14808				network = $this.data( 'network' ),
14809				id = this.config.id,
14810				url = this.config.url,
14811				title = this.$wrapper.find( '.slick-title' ).text(),
14812				name;
14813				var picture = this.$slides.filter( this.dom.active ).children().first().attr( 'src' );
14814			switch( network ) {
14815				case 'facebook': 
14816					url = 'https://www.facebook.com/sharer/sharer.php?picture=' + picture+'&u=' + url + '#id=' + id;
14817					name = 'Facebook Share';
14818					break;
14819				case 'twitter':
14820					url = 'http://twitter.com/intent/tweet?text=' + url + '#id=' + id;
14821					name = 'Twitter Share';
14822					break;
14823				case 'pinterest':
14824					url = 'http://pinterest.com/pin/create/bookmarklet/?media=' + picture + '&url=' + url + '&is_video=false&description=' + title;
14825					// other available link paranmeters: media, description
14826					name = 'Pinterest Share';
14827					break;
14828
14829			}
14830
14831       		window.open( url, name, "height=380 ,width=660, resizable=0, toolbar=0, menubar=0, status=0, location=0, scrollbars=0" );
14832		}
14833	};
14834
14835})( jQuery );
14836(function($) {
14837    'use strict';
14838
14839    MK.component.Grid = function( el ) {
14840    	var $container = $(el);
14841    	var config = $container.data( 'grid-config' );
14842        var isSlideshow = $container.closest('[data-mk-component="SwipeSlideshow"]').length;
14843        var miniGridConfig = {
14844            container: el,
14845            item: config.item + ':not(.is-hidden)',
14846            gutter: 0 
14847        };
14848
14849        var init = function init(){
14850            // Flags for cancelling usage goes first :
14851            // Quit early if we discover that Grid is used inside SwipeSlideshow as it brings bug with crossoverriding positioning 
14852            // + grid is not really needed as we have single row all handled by slider.
14853            // It happens only in woocommerce carousel as of hardcoded Grid in loop-start.php
14854            if(isSlideshow) return; 
14855	        MK.core.loadDependencies([ MK.core.path.plugins + 'minigrid.js' ], create);
14856        };
14857
14858        // Remove el hidden without adding proper class
14859        var prepareForGrid = function prepareForGrid() {
14860            var $item = $(this);
14861            var isHidden = ($item.css('display') === 'none');
14862            if(isHidden) $item.addClass('is-hidden');
14863            else $item.removeClass('is-hidden');
14864        };
14865
14866        var create = function create() {
14867            var timer = null;
14868
14869	        function draw() { 
14870                // Prevent plugin breaking when feeding it with hidden elements
14871                $container.find(config.item).each( prepareForGrid );
14872	            minigrid(miniGridConfig);
14873	        }
14874
14875            function redraw() {
14876                if (timer) clearTimeout(timer);
14877                timer = setTimeout(draw, 100);
14878            }
14879
14880            // init
14881	        draw(); 
14882            // If reinitializing drop existing event handler
14883            $(window).off('resize', redraw);
14884            $(window).on('resize', redraw);
14885            MK.utils.eventManager.subscribe('item-expanded', redraw);
14886            MK.utils.eventManager.subscribe('ajaxLoaded', redraw);
14887            MK.utils.eventManager.subscribe('staticFilter', redraw);
14888        };
14889
14890        return {
14891         	init : init
14892        };
14893    };
14894
14895})(jQuery);
14896
14897
14898
14899
14900
14901
14902
14903
14904/**
14905 * ICON FACTORY @ Maki
14906 * 
14907 * Javascript part that translates css styles into link to server side manufacturer.
14908 * By passing extra args we generate icons as needed on server and send them back with ajax and attch them to DOM here.
14909 *
14910 * 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.
14911 * 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. 
14912 * 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. 
14913 * 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.
14914 * 
14915 * Prons:
14916 * - automated process where we can mimic old behaviour
14917 * - possible bugs are easy to patch 
14918 * - 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)
14919 * - icon generation moved to server side where our main templating is already happening
14920 * - we can easily switch how our Icon should be outputed - inline, img, object, iframe. Whatever our situation requires (img for responsive icons for example)
14921 *
14922 * Cons:
14923 * - possible bugs based on different nature of svgs / fonts. Need to be manually fixed
14924 * - some manual work to straighten things - litle css refactors here and there
14925 * - as the mapping the icons happens in server side, it may cause CPU bottlenecks and should be cashed in DB for repetitve usage.
14926 *
14927 *
14928 * TODO Refactor to config obj as parameter for easier passing it. Also decouple more - especially loops
14929 */
14930(function ($) {
14931	'use strict';
14932
14933	// As long as we can manage this manually it is better like so. We avoid delay based on waiting for ajax to finish
14934 	// $.get( MK.core.path.theme + '/assets/icons/icon-families.json', createAll);
14935 	var families = [
14936		['awesome-icons' , 'mk-icon-'], // [family, prefix]
14937		['icomoon' 		 , 'mk-moon-'],
14938		['pe-line-icons' , 'mk-li-'],
14939		['theme-icons' 	 , 'mk-jupiter-icon-'] 
14940	];
14941
14942	// Our css contains this extends for particular families of fonts. For now we automate the process and extend it here as well
14943	var extend = {
14944		'awesome-icons' : [], 
14945		'icomoon' : [],
14946		'pe-line-icons' : [],
14947		'theme-icons' : []
14948	};	
14949 	
14950 	// Cache holder for quick access to repeating icons. config / svg
14951	var _cache = {};
14952	var _cacheId = 0;
14953	// Merge configs to call it with single ajax
14954	var _config = [];
14955	// Counter for all families. We merge all our families for single ajax request and countdown when to trigger the download.
14956	var _roundCount = 0;
14957	// Mapper for icons - config / array with nodes
14958	var _iconMap = {};
14959
14960
14961	// Closure to merge $icons together and to run the download when we counted down icon families to 0
14962 	var getIconsSprite = (function() {
14963 		var $icons = null;
14964 		var iterator = 0;
14965
14966 		function run(callback) {
14967	 		var config = encodeURIComponent(JSON.stringify(_config));
14968
14969			$.ajax({
14970				url : MK.core.path.ajaxUrl,
14971				// dataType: 'xml',
14972				method: 'POST',
14973				data: {action : 'mk_get_icon', iterator: iterator++, config: config},
14974				success: function(sprite) { 
14975					callback(sprite, $icons);
14976					_config = [];
14977					_iconMap = {};
14978					$icons = null;
14979				},
14980				error: function(err) { 
14981					console.log('Icon load problem');
14982				}
14983			});
14984		}
14985
14986		return function(callback, $els, count) {
14987			if(!$icons) $icons = $els;
14988			else $icons.add($els);
14989			// console.log(count);
14990			if(!count) run(callback);
14991		};
14992 	}());
14993
14994 	// Wait for DOM manipulations and run where really needed
14995 	$(window).on('load', function() { 
14996 		setTimeout(function() {
14997 			createAll(document);
14998 			if($('.mk-header').length) createAll('.mk-header');
14999 			if($('.js-flexslider, .mk-flexslider').length) createAll('.js-flexslider, .mk-flexslider');
15000 			if($('.mk-accordion').length) createAll('.mk-accordion'); 
15001 		}, 1000); 
15002 	});
15003
15004 	MK.utils.eventManager.subscribe('ajaxLoaded', function() {
15005 		// Wait for actuall DOM insertion
15006 		setTimeout(createAll, 100, '.js-loop');
15007 	});
15008
15009	MK.utils.eventManager.subscribe('ajax-preview', function() {
15010 		setTimeout(createAll, 100, '.ajax-container');
15011	});
15012
15013	MK.utils.eventManager.subscribe('photoAlbum-open', function() {
15014 		setTimeout(createAll, 100, '.gallery-share');
15015	});
15016
15017	MK.utils.eventManager.subscribe('quickViewOpen', function() {
15018 		setTimeout(createAll, 300, '.mk-modal-content');
15019	});
15020
15021 	// Our main runner that creates all icons in given scope
15022 	function createAll(scope) {
15023		// iterate through families
15024 		for(var i = 0, l = families.length; i < l; i++) {
15025 			var family = families[i][0];
15026 			var prefix = families[i][1];
15027 			var $icons = getIcons(family, prefix, scope);
15028 			if($icons.length) {
15029 				_roundCount++;
15030 				// 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.
15031 				// We need it to pass all $icons first so we can merge all families before ajax request.
15032 				setTimeout(createIcons, 0, $icons, family, prefix);
15033 			}
15034 		}
15035 	}
15036
15037 	// Grab all els in given scope that contains our prefix, anywhere in class attribute. Extend if needed
15038 	function getIcons(family, prefix, scope) {
15039 		var $scope = $(scope);
15040 		var $icons = $scope.find('[class*='+ prefix +']');
15041 		var extraClassNames = extend[family];
15042 		// if nothing to extend just return what we have till now
15043 		if(!extraClassNames) return $icons; 
15044 		// Extend it with our css garbish
15045 		extraClassNames.forEach(function(className) {
15046 			var $icon = $scope.find(className);
15047 			$icons = $icons.add($icon);
15048 		});
15049 		// serve all
15050 		return $icons;
15051 	}
15052
15053
15054 	function createIcons($icons, family, prefix, i, unicode) {
15055 		var id   = i || 0;
15056		var icon = $icons[id];
15057
15058		// quick check point, if no more icons break recursion
15059		if(!icon) {
15060			_roundCount--;
15061			getIconsSprite(insertIcons, $icons, _roundCount, _config);
15062			return;
15063		}
15064
15065		var css       = getComputedStyle( icon, ':before');
15066		var classAttr = icon.getAttribute('class');
15067		var name      = (classAttr) ? matchClass(classAttr.split(' '), prefix) : false;
15068		var h         = getComputedStyle(icon).fontSize;
15069		var config    = createConfig(css, name, family, unicode, h);
15070		var cache 	  = JSON.stringify(config);
15071
15072		if(!config) {
15073			// 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)
15074			// As we expect empty response from server, we just skip to next icon
15075
15076		} else if(_cache[cache]) {
15077			// Use cached icon when possible
15078			// 
15079			if(typeof _iconMap[cache] === 'undefined') _iconMap[cache] = [$icons.eq(id)];
15080			else _iconMap[cache].push($icons.eq(id));
15081
15082		} else {
15083			if(typeof _iconMap[cache] === 'undefined') _iconMap[cache] = [$icons.eq(id)];
15084			else _iconMap[cache].push($icons.eq(id));
15085
15086			_cache[cache] = _cacheId.toString(); // number as string so we could do [var] key lookup after reversal
15087			config.id = _cacheId; // extend config for server only
15088			_config.push(config);
15089
15090			_cacheId++; // increment after caching
15091		}
15092
15093		createIcons($icons, family, prefix, ++id);
15094 	}
15095
15096 	function insertIcons(sprite, $icons) {
15097 		var $sprite = $(sprite);
15098 		var $svgs   = $sprite.find('svg');
15099 		var idMap   = invert(_cache);
15100
15101 		$sprite.each(function() {
15102 			var $svg = $(this);
15103 			var id   = $svg.attr('data-cacheid'); // read as string
15104 			var configKey = idMap[id];
15105
15106 			_cache[configKey] = this;
15107 			// console.log(id, this)
15108 		});
15109
15110 		// console.log('sprite',sprite)
15111 		// 
15112
15113 		Object.keys(_iconMap).forEach(function (cacheKey) {
15114		   	_iconMap[cacheKey].forEach(function($icons) {
15115		   		$icons.each(function() {
15116		   			var $svg = $(_cache[cacheKey]).clone();
15117		   			var $icon = $(this);
15118
15119		   			// console.log($icon[0], _cache[cacheKey]);  
15120		   			
15121		   			function remove() {
15122		   				// exclude problematic stuff
15123		   				if($icon.parents('.pricing-features')) return;
15124			   			$icon.not('.mk-jupiter-icon-xing') 
15125			   				 .not('.mk-jupiter-icon-square-xing')
15126			   				 .not('.mk-jupiter-icon-simple-xing')
15127			   				 .find('.mk-svg-icon') 
15128			   				 .not('[data-name="mk-moon-zoom-in"]')
15129			   				 .remove(); // and remove else to reapply styles with new loaded svg
15130		   			}
15131
15132		   			if($svg.length ) remove();
15133
15134		   			if(!$icon.find('svg').length) {
15135		   				if($icon.parents('.widget ul').length) $icon.prepend($svg);
15136		   				else $icon.append($svg);
15137					}
15138		   		});
15139		   	});
15140		});
15141
15142 		// Notify rest of app
15143		MK.utils.eventManager.publish('iconsInsert');
15144 	}
15145
15146 	// Prepare configuration for server side. We need to grab icons and manipulate them a little there
15147 	function createConfig(css, name, family, unicode, height) {
15148 		var hasGradient  = checkGradient(css);
15149 		var hasDirection = extractGradient('direction', css.background);
15150
15151 		var config = {
15152 			family: family, 
15153 			// this is mostly for Extends. Because we've been customizing singular elements and assigning content unicode manually, 
15154 			// now we don't have any proper anchor for usage with our json map
15155 			unicode: (unicode) ? unicode : decodeUnicode(css.content), 
15156 			name: name,
15157 			// fill: css.color,
15158 			gradient_type:  hasGradient ? extractGradient('type' , css.background) : false,
15159 			gradient_start: hasGradient ? extractGradient('start', css.background) : false,
15160 			gradient_stop:  hasGradient ? extractGradient('stop' , css.background) : false,
15161 			gradient_direction: hasDirection ? extractGradient('direction', css.background).replace(' ', '-') : false,
15162 			height: height
15163 		};
15164
15165 		// If there is no name or unicode the whole config is invalid
15166 		if(!config.name && !config.unicode) return false;
15167 		else return config;
15168 	}
15169
15170 	// Extract class name that represents the icon that we try to generate
15171 	function matchClass(classes, prefix) {
15172 		// var missing = '';
15173 		for(var i = 0, l = classes.length; i < l; i++) {
15174 			if(classes[i].indexOf(prefix) !== -1) return classes[i]; // return first matched class name
15175 			// else missing += ' .' + classes[i]; // collect not matching classes
15176 		}
15177 		// if we didn't returned anything within loop we output notification here. Keep it for testing only
15178 		// console.log('Possibility of missing icons for element with classes:' + missing);
15179 	}
15180
15181 	// Check if background conatains gradient declaration and return bg string if so or false 
15182 	function checkGradient(css) {
15183 		var bg = css.background;
15184 		if(bg.indexOf('radial') !== -1 || bg.indexOf('linear') !== -1) return bg;
15185 		else return false;
15186 	}
15187
15188 	// Extract background attribiutes from bg string.
15189 	// Multipurpose function which returns part we ask for
15190 	function extractGradient(attr, grad) {
15191 		// quit if gradient is falsy
15192 		// console.log(grad);
15193 		if(!grad) return false;
15194
15195 		var isRadial = grad.indexOf('radial')  !== -1;
15196 		var isLinear = grad.indexOf('linear')  !== -1;
15197 		var hasDirection = grad.indexOf('(to') !== -1;
15198 		var f, t; // from, to
15199
15200 		if(attr === 'type') {
15201 			if(isRadial) return 'radial';
15202 			if(isLinear) return 'linear';
15203
15204 		} else if(attr === 'start') {
15205 			f = getStrPosition(grad, 'rgb(', 1);
15206 			t = getStrPosition(grad, '0%'  , 1);
15207
15208 		} else if(attr === 'stop') {
15209 			f = getStrPosition(grad, 'rgb(', 2);
15210 			t = getStrPosition(grad, '100%', 1);
15211
15212 		} else if(attr === 'direction') {
15213 			if(!hasDirection) return false;
15214 			f = getStrPosition(grad, '(to', 1) + 4;
15215 			t = getStrPosition(grad, ', rgb(', 1);
15216
15217 		} else {
15218 			return false;
15219 		}
15220 		
15221 		return grad.slice(f, t);
15222 	}
15223
15224 	// Helper for getting indexOf but with lookup for instance of the string
15225 	// str - string to search
15226 	// m - what we're looking for
15227 	// i - instance, starting at 1
15228 	function getStrPosition(str, m, i) {
15229	   return str.split(m, i).join(m).length;
15230	}
15231
15232	// JS outputs unicode results rather than code representation. This helper function does the job
15233	function decodeUnicode(content) {
15234		// escape() kills \ escape signature and outputs it as %u
15235		// str replace to drop special chars
15236		// and we bring it all to lowercase to match filenames we keep on server
15237		if(content && content !== 'none') return escape(content).replace(/%22/g, '').replace('%u', '').toLowerCase();
15238		else return false; // just in case we haven't provided content to work with
15239	}
15240
15241	function invert(obj) {
15242	  	var new_obj = {};
15243	  	for (var prop in obj) {
15244	    	if(obj.hasOwnProperty(prop)) {
15245	      		new_obj[obj[prop]] = prop;
15246	    	}
15247	  	}
15248	  	return new_obj;
15249	}
15250
15251}(jQuery));
15252/*!
15253 * imagesLoaded PACKAGED v4.1.1
15254 * JavaScript is all like "You images are done yet or what?"
15255 * MIT License
15256 */
15257
15258!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
15258h(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});
15259
15260(function($, window){
15261    'use strict';
15262
15263    var scrollY = MK.val.scroll; 
15264    var dynamicHeight = MK.val.dynamicHeight;
15265
15266    var $window = $(window);
15267    var $containers = $('.js-loop');
15268
15269    $containers.each( pagination );
15270
15271	$window.on( 'vc_reload', function() {
15272		$('.js-loop').each( pagination );
15273	} );
15274
15275    function pagination() {
15276        var unique = Date.now();
15277        var $container = $(this);
15278        var $superContainer = $container.parent(); // should contain clearing so it stretches with floating children
15279        var $loadBtn = $container.siblings('.js-loadmore-holder').find('.js-loadmore-button');
15280        var $loadScroll = $('.js-load-more-scroll');
15281        var style = $container.data('pagination-style');
15282        var maxPages = $container.data('max-pages');
15283        var id = '#' + ($container.attr('id'));
15284        var ajaxLoader = new MK.utils.ajaxLoader(id);
15285        var isLoadBtn = (style === 2);
15286        var isInfiniteScroll = (style === 3); // add flag for last container
15287        var scrollCheckPoint = null;
15288        var isHandlerBinded = false;
15289
15290        ajaxLoader.init();
15291
15292        init();
15293
15294        function init() {
15295            MK.utils.eventManager.subscribe('ajaxLoaded', onLoad);
15296            bindHandlers();
15297            if( isInfiniteScroll ) scrollCheckPoint = spyScrollCheckPoint();
15298
15299			$window.on( 'vc_reload', function() {
15300				$window.off('scroll', handleScroll);
15301			} );
15302        }
15303
15304        function bindHandlers() {
15305            if( isLoadBtn ) $loadBtn.on('click', handleClick);
15306            if( isInfiniteScroll ) $window.on('scroll', handleScroll); 
15307            isHandlerBinded = true;
15308        }
15309
15310        function unbindHandlers() {
15311            if( isLoadBtn ) $loadBtn.off('click', handleClick);
15312            if( isInfiniteScroll ) $window.off('scroll', handleScroll);
15313            isHandlerBinded = false;
15314        }
15315
15316        function handleClick(e) {
15317            e.preventDefault();
15318            if(!ajaxLoader.isLoading) loadMore();
15319        }
15320
15321        function handleScroll() {
15322            if((scrollY() > scrollCheckPoint()) && !ajaxLoader.isLoading) loadMore();
15323        }
15324
15325        function loadMore() {
15326            loadingIndicatorStart();
15327            var page = ajaxLoader.getData('paged');
15328            ajaxLoader.setData({paged: ++page});
15329            ajaxLoader.load(unique);
15330        }
15331
15332        function onLoad(e, response) {
15333            if( typeof response !== 'undefined' && response.id === id) {
15334                // Checking found posts helps to fix all pagination styles 
15335                if( ajaxLoader.getData('found_posts') <= 0 && ajaxLoader.getData('paged') >= ajaxLoader.getData('maxPages')) loadingIndicatorHide();
15336                else loadingIndicatorShow();
15337                if(response.unique === unique) $container.append(response.content);
15338                loadingIndicatorStop();
15339            }
15340        }
15341
15342        function loadingIndicatorStart() {
15343            if(isLoadBtn) $loadBtn.addClass('is-active');
15344            else if(isInfiniteScroll) MK.ui.loader.add('.js-load-more-scroll');
15345
15346        }
15347
15348        function loadingIndicatorStop() {
15349            if(isLoadBtn) $loadBtn.removeClass('is-active');
15350            else if(isInfiniteScroll) MK.ui.loader.remove('.js-load-more-scroll');
15351        }
15352
15353        function loadingIndicatorShow() {
15354            if(isHandlerBinded) return;
15355            if(isLoadBtn) $loadBtn.show();
15356            else if(isInfiniteScroll) $loadScroll.show();
15357            bindHandlers();
15358        }
15359
15360        function loadingIndicatorHide() {
15361            if(!isHandlerBinded) return;
15362            if(isLoadBtn) $loadBtn.hide();
15363            else if(isInfiniteScroll) $loadScroll.hide();
15364            unbindHandlers();
15365        }
15366
15367
15368        function spyScrollCheckPoint() {
15369            var containerO = 0;
15370            var containerH = dynamicHeight( $superContainer );
15371            var winH = dynamicHeight( window );
15372 
15373            var setVals = function() {
15374                containerO = $superContainer.offset().top;
15375            };
15376
15377            setVals();
15378            $window.on('resize', function() { requestAnimationFrame(setVals); });
15379
15380            return function() {
15381                return (containerH() + containerO) - (winH() * 2);
15382            };
15383        }
15384    }
15385
15386})(jQuery, window);
15387(function($) {
15388	'use strict';
15389
15390	// Check if it's inside hidden parent
15391	// Cannot be position: fixed
15392	function isHidden(el) {
15393	    return (el.offsetParent === null);
15394	}
15395
15396	MK.component.Masonry = function(el) {
15397		var $window = $(window);
15398		var $container = $(el);
15399		var config = $container.data( 'masonry-config' );
15400		var $masonryItems = $container.find(config.item);
15401		var cols = config.cols || 8;
15402		var $filterItems = null; // assign only when apply filter
15403		var wall = null;
15404		
15405        var init = function init() {
15406        	MK.core.loadDependencies([ MK.core.path.plugins + 'freewall.js' ], onDepLoad);
15407        };
15408
15409        var onDepLoad = function onDepLoad() {
15410        	masonry();
15411
15412        	// Events
15413	        $window.on('resize', onResize);
15414            MK.utils.eventManager.subscribe('ajaxLoaded', onPostAddition);
15415			MK.utils.eventManager.subscribe('staticFilter', resize);
15416        };
15417
15418	    var masonry = function masonry() {
15419	    	// Quit for hidden elements for now.
15420	    	if(isHidden(el)) return;
15421
15422	    	var newCols;
15423	    	if(window.matchMedia( '(max-width:600px)' ).matches) newCols = 2;
15424	    	else if(window.matchMedia( '(max-width:850px)' ).matches) newCols = 4;
15425	    	else newCols = cols;
15426
15427	    	var colW = $container.width() / newCols;
15428
15429	        wall = new Freewall( config.container );
15430
15431	        // We need to pass settings to a plugin via reset method. Strange but works fine.
15432			wall.reset({
15433				selector: config.item + ':not(.is-hidden)',
15434				gutterX: 0, // set default gutter to 0 and again - apply margins to item holders in css
15435				gutterY: 0,
15436				cellW: colW,
15437				cellH: colW
15438			});
15439
15440	        wall.fillHoles();
15441	        wall.fitWidth();
15442
15443	        $masonryItems.each(function() {
15444	        	$(this).data('loaded', true);
15445	        });
15446        };
15447
15448
15449		// Clear attributes after the plugin. It's API method dosn't handle it properly
15450		var destroyContainer = function destroyContainer() {
15451			$container.removeAttr('style')
15452				 .removeData('wall-height')
15453				 .removeData('wall-width')
15454				 .removeData('min-width')
15455				 .removeData('total-col')
15456				 .removeData('total-row')
15457				 .removeAttr('data-wall-height')
15458				 .removeAttr('data-wall-width')
15459				 .removeAttr('data-min-width')
15460				 .removeAttr('data-total-col')
15461				 .removeAttr('data-total-row');
15462		};
15463
15464		var destroyItem = function destroyItem() {
15465			var $item = $(this);
15466			$item.removeAttr('style')
15467				 .removeData('delay')
15468				 .removeData('height')
15469				 .removeData('width')
15470				 .removeData('state')
15471				 .removeAttr('data-delay')
15472				 .removeAttr('data-height')
15473				 .removeAttr('data-width')
15474				 .removeAttr('data-state'); 
15475		};
15476
15477		var destroyAll = function destroyAll() {
15478	    	if( !wall ) return;
15479    		wall.destroy(); // API destroy
15480    		destroyContainer();
15481    		$masonryItems.each( destroyItem ); // run our deeper destroy
15482		};
15483
15484		var onResize = function onResize() {
15485			requestAnimationFrame(resize);
15486		};
15487
15488        var refresh = function refresh() {
15489	    	if( !wall ) return; 
15490	    	setTimeout(wall.fitWidth.bind(wall), 5);
15491        };
15492
15493        var resize = function resize() {
15494        	destroyAll();
15495	    	masonry();
15496        };
15497
15498        var onPostAddition = function onPostAddition() {
15499        	$masonryItems = $container.find(config.item);
15500
15501        	$masonryItems.each(function() {
15502        		var $item = $(this),
15503        			isLoaded = $item.data('loaded');
15504
15505        		if(!isLoaded) $item.css('visibility', 'hidden');
15506        	});
15507
15508        	
15509        	$container.mk_imagesLoaded().then(function() {
15510        		destroyAll();
15511        		masonry();
15512        	});
15513        };
15514
15515        return {
15516         	init : init
15517        };
15518	};
15519
15520}(jQuery));
15521(function($) {
15522	'use strict';
15523
15524	MK.component.Pagination = function(el) {
15525		this.el = el;
15526	};
15527
15528	MK.component.Pagination.prototype = {
15529		init: function init() {
15530			this.cacheElements(); 
15531			this.bindEvents();
15532			this.onInitLoad();
15533		},
15534
15535		cacheElements: function cacheElements() {
15536			this.lastId = 1;
15537			this.unique = Date.now();
15538			this.$pagination = $(this.el);
15539			this.$container = this.$pagination.prev('.js-loop');
15540			this.$pageLinks = this.$pagination.find('.js-pagination-page');
15541			this.$nextLink = this.$pagination.find('.js-pagination-next');
15542			this.$prevLink = this.$pagination.find('.js-pagination-prev');
15543			this.$current = this.$pagination.find('.js-current-page');
15544			this.$maxPages = this.$pagination.find('.pagination-max-pages'); // TODO change in DOM and here to js class
15545			this.containerId = '#' + this.$container.attr('id');
15546			this.pagePathname = window.location.pathname;
15547			this.pageSearch = window.location.search;
15548			this.popState = false;
15549			this.ajaxLoader = new MK.utils.ajaxLoader('#' + this.$container.attr('id'));
15550			this.ajaxLoader.init();
15551		},
15552
15553		bindEvents: function bindEvents() {
15554			this.$pageLinks.on('click', this.pageClick.bind(this));
15555			this.$nextLink.on('click', this.nextClick.bind(this));
15556			this.$prevLink.on('click', this.prevClick.bind(this)); 
15557			MK.utils.eventManager.subscribe('ajaxLoaded', this.onLoad.bind(this));
15558		},
15559
15560		pageClick: function pageClick(e) {
15561			e.preventDefault(); 
15562			var $this = $(e.currentTarget);
15563			var id = parseFloat($this.attr('data-page-id'));
15564
15565			if(id > this.ajaxLoader.getData('maxPages') || id < 1) return;
15566			this.load(id, $this);
15567			this.updatePagedNumUrl( id );
15568		},
15569
15570		nextClick: function nextClick(e) {
15571			e.preventDefault(); 
15572			if(this.ajaxLoader.getData('paged') === this.ajaxLoader.getData('maxPages')) return;
15573			this.load(++this.lastId, $(e.currentTarget));
15574			this.updatePagedNumUrl( this.lastId );
15575		},
15576
15577		prevClick: function prevClick(e) {
15578			e.preventDefault(); 
15579			if(this.ajaxLoader.getData('paged') === 1) return;
15580			this.load(--this.lastId, $(e.currentTarget));
15581			this.updatePagedNumUrl( this.lastId );
15582		},
15583
15584		load: function load(id, $el) {
15585			this.lastId = id;
15586			this.ajaxLoader.setData({paged: id});
15587			this.ajaxLoader.load(this.unique);
15588			this.removeIndicator();
15589			MK.ui.loader.add($el);
15590		},
15591
15592		onLoad: function success(e, response) {
15593			if( typeof response !== 'undefined' && response.id === this.containerId) {
15594				this.updatePagination();
15595				this.lastId = this.ajaxLoader.getData('paged');
15596
15597				if(response.unique === this.unique) {
15598					this.removeIndicator();
15599					this.scrollPage();
15600			        this.$container.html(response.content);  
15601				}   
15602			}         
15603        },
15604
15605        updatePagination: function updatePagination() {
15606        	var self = this;
15607
15608        	// Hide / show arrows
15609        	var isFirst = (this.ajaxLoader.getData('paged') === 1);
15610        	var isLast = (this.ajaxLoader.getData('paged') === this.ajaxLoader.getData('maxPages'));
15611
15612        	if(isFirst) this.$prevLink.addClass('is-vis-hidden');
15613        	else this.$prevLink.removeClass('is-vis-hidden');
15614
15615        	if(isLast) this.$nextLink.addClass('is-vis-hidden');
15616        	else this.$nextLink.removeClass('is-vis-hidden');
15617
15618			// X of Y
15619			this.$current.html(this.ajaxLoader.getData('paged'));
15620			this.$maxPages.html(this.ajaxLoader.getData('maxPages'));
15621
15622			// Move overfloating items
15623			var displayItems = 10;
15624			var centerAt = displayItems / 2;
15625
15626			if(this.ajaxLoader.getData('maxPages') > displayItems) {
15627				this.$pageLinks.each(function(i) {
15628
15629					var id = self.lastId - centerAt;
15630						id = Math.max(id, 1);
15631						id = Math.min(id, self.ajaxLoader.getData('maxPages') - displayItems + 1);
15632						id = id + i;
15633
15634					$(this).html( id ).attr('data-page-id', id).show();
15635
15636					if(i === 0 && id > 1) $(this).html('...');
15637					if(i === displayItems - 1 && id < self.ajaxLoader.getData('maxPages')) $(this).html('...');
15638				});
15639			} else {
15640				this.$pageLinks.each(function(i) {
15641					var $link = $(this);
15642					var id = i + 1;
15643
15644					$link.html(id).attr('data-page-id', id);
15645
15646					if( self.ajaxLoader.getData('maxPages') === 1) {
15647						self.$pageLinks.hide();
15648					} else {
15649						if(i > self.ajaxLoader.getData('maxPages') - 1) $link.hide();
15650						else $link.show();						
15651					}
15652
15653				});
15654			}
15655
15656        	// Highlight current only
15657			this.$pageLinks.filter('[data-page-id="' + this.ajaxLoader.getData('paged') + '"]' ).addClass('current-page')
15658				 .siblings().removeClass('current-page');
15659
15660        },
15661
15662        scrollPage: function scrollPage() {
15663            var containerOffset = this.$container.offset().top;
15664            var offset = containerOffset - MK.val.offsetHeaderHeight( containerOffset ) - 20; 
15665
15666            this.$container.find('a:first').focus()
15667            MK.utils.scrollTo( offset ); 
15668        },
15669
15670        removeIndicator: function removeIndicator() {
15671        	MK.ui.loader.remove('.js-pagination-page, .js-pagination-next, .js-pagination-prev');
15672        },
15673
15674		/**
15675		 * Set some actions when archive/category page is loaded. Actions list:
15676		 * - Select the correct paged ID on pagination list.
15677		 * - Set current paged ID on the label.
15678		 * - Add event listener onpopstate for handling prev/next button of Browser URL.
15679		 * - Set info for updatePagedNumUrl() about request comes from popstate.
15680		 *
15681		 * @since 5.9.8
15682		 */
15683		onInitLoad: function onInitLoad() {
15684			var initPagedID = this.$pagination.data( 'init-pagination' );
15685			if ( initPagedID && initPagedID > 1 ) {
15686				this.$current.html( initPagedID );
15687				this.$pageLinks.filter( '[data-page-id="' + initPagedID + '"]' ).addClass( 'current-page' ).siblings().removeClass( 'current-page' );
15688			}
15689
15690			// Run popstate only if it's supported by the browser.
15691			if ( 'onpopstate' in window ) {
15692				var thisPop = this;
15693				window.onpopstate = function( event ) {
15694					var id = 1;
15695
15696					// At start, state is always null. So, we should check it before processing.
15697					if ( typeof event.state === 'object' && event.state ) {
15698						var state = event.state;
15699
15700						// Set paged ID for updating page.
15701						if ( state.hasOwnProperty( 'MkPagination' ) ) {
15702							var currentState = state.MkPagination;
15703							if ( currentState.hasOwnProperty( 'paged' ) ) {
15704								id = parseFloat( currentState.paged );
15705							}
15706						}
15707					} else {
15708						id = parseFloat( thisPop.getURLPagedID() );
15709					}
15710
15711					// Tell updatePagedNumUrl() if request come from popstate.
15712					thisPop.popState = true;
15713					thisPop.$pageLinks.filter( '[data-page-id="' + id + '"]' ).trigger( 'click' );
15714				}
15715			}
15716		},
15717
15718		/**
15719		 * Update current pagination browser URL by adding/changing paged number. Only run if
15720		 * the browser support pushState and the request not coming from popstate.
15721		 *
15722		 * WordPress has some ways to set paged number:
15723		 * 1. page/[number], paged=[number] will be directed here.
15724		 * 2. page=[number]
15725		 * So, we should check which one the request is used here.
15726		 *
15727		 * @since 5.9.8
15728		 */
15729		updatePagedNumUrl: function updatePagedNumUrl( id ) {
15730			// Check pushState browser support and ignore if request come from popstate.
15731			if ( 'history' in window && 'pushState' in history && id && ! this.popState ) {
15732				var fullPage = this.pagePathname + this.pageSearch;
15733				var isQueryPage = false;
15734
15735				// Style 1 - /page/[number], as default value.
15736				var newPage = 'page/' + id + '/';
15737				var expPage = /page\/\d+\/?/;
15738				var result = this.pagePathname.match( /\/page\/\d+/ );
15739				var isPagedExist = ( result ) ? true : false;
15740
15741				// Style 2 - ?page=[number], only run if /page/ is not exist and URL query var exist.
15742				if ( ! isPagedExist && this.pageSearch ) {
15743					isQueryPage = this.pageSearch.match( /page\=\d+/ );
15744					if ( isQueryPage ) {
15745						newPage = 'page=' + id;
15746						expPage = /page\=\d+/;
15747					}
15748				}
15749
15750				// If page number is 1, remove paged number from URL.
15751				if ( id === 1 ) {
15752					newPage = '';
15753					if ( isQueryPage ) {
15754						expPage = ( this.pageSearch.match( /\&+/ ) ) ? /page\=\d+\&?/ : /\?page\=\d+\&?/;
15755					}
15756				}
15757
15758				// Set new pathname. Do replacement only if the new pathname contains paged number.
15759				var newURL = this.pagePathname + newPage + this.pageSearch;
15760				if ( fullPage.match( expPage ) ) {
15761					newURL = fullPage.replace( expPage, newPage );
15762				}
15763
15764				// Set history state and return popstate back to fal
15764se.
15765				var historyState = {
15766					MkPagination: {
15767						url: newURL,
15768						paged: id
15769					}
15770				}
15771				this.popState = false;
15772
15773				// Push new pathname to display/hide the paged number.
15774				window.history.pushState( historyState, null, newURL );
15775			}
15776			this.popState = false;
15777		},
15778
15779		/**
15780		 * Get current URL page ID. Notes:
15781		 * 1. page/[number], paged=[number] will be directed here.
15782		 * 2. page=[number]
15783		 *
15784		 * @return {integer} Current paged ID. Default 1.
15785		 */
15786		getURLPagedID: function getURLPagedID() {
15787			var pathname = window.location.pathname;
15788			var search = window.location.search;
15789			var pagedId = 1;
15790			var result = '';
15791			var isPagedExist = false;
15792
15793			// Search based on style 1.
15794			result = pathname.match( /\/page\/(\d+)/ );
15795			if ( result ) {
15796				isPagedExist = true;
15797				pagedId = ( result.hasOwnProperty( 1 ) ) ? result[1] : 1;
15798			}
15799
15800			// Search based on style 2.
15801			if ( ! isPagedExist && search ) {
15802				result = search.match( /page\=(\d+)/ );
15803				if ( result ) {
15804					isPagedExist = true;
15805					pagedId = ( result.hasOwnProperty( 1 ) ) ? result[1] : 1;
15806				}
15807			}
15808
15809			return pagedId;
15810		}
15811	};
15812
15813}(jQuery));
15814(function( $ ) {
15815	'use strict';
15816
15817	var val = MK.val,
15818		utils = MK.utils;
15819
15820	MK.component.Parallax = function( el ) {
15821		var self = this,
15822			$this = $( el ),
15823        	obj = $this[0],
15824			$window = $( window ),
15825		    container = document.getElementById( 'mk-theme-container' ),
15826			config = $this.data( 'parallax-config' ),
15827			$holder = $( config.holder ),
15828			headerHeight = null,
15829			offset = null,
15830			elHeight = null,
15831			ticking = false,
15832			isMobile = null;
15833
15834
15835		var clientRect = null;
15836
15837		var update = function() {
15838			// Clear styles to check for natural styles
15839			// then apply position and size
15840			obj.style.transform = null;
15841			obj.style.top = null;
15842			obj.style.bottom = null;
15843
15844			isMobile = MK.utils.isMobile();
15845
15846			if( isMobile ) {
15847        		$this.css( 'height', '' );
15848				return;
15849			}
15850
15851			clientRect = $this[ 0 ].getBoundingClientRect();
15852			offset = clientRect.top;
15853			elHeight = clientRect.height;
15854			headerHeight = val.offsetHeaderHeight( offset );
15855			offset = offset - headerHeight + val.scroll(); 
15856
15857			setPosition(); 
15858			setSize( ); 
15859		};
15860
15861
15862        var h = 0,
15863        	winH = 0,
15864        	proportion = 0,
15865        	height = 0;
15866
15867        // Position and background attachement should me moved to CSS but we repair it high specificity here as styles are not reliable currently
15868        var setSize = function() {
15869        	$this.css( 'height', '' );
15870        	winH = $window.height() - headerHeight;
15871        	h = obj.getBoundingClientRect().height; 
15872
15873        	if( config.speed <= 1 && config.speed > 0 ) {
15874        		if( offset === 0 ) {
15875	        		$this.css({
15876	        			backgroundAttachment: 'scroll',
15877	        			'will-change': 'transform'
15878	        		});
15879        		} else {
15880	        		$this.css({
15881						height : h + ( (winH - h) * config.speed ),
15882	        			backgroundAttachment: 'scroll',
15883	        			'will-change': 'transform' 
15884	        		}); 
15885	        	}
15886
15887        	} else if ( config.speed > 1 && h <= winH ) {
15888        		$this.css({
15889        			// good for full heights - 2 because it's viewable by 2 screen heights
15890        			height: ( winH  +  ( ( winH * config.speed ) - winH ) * 2 ),  
15891        			top: -( ( winH * config.speed ) - winH ),
15892        			backgroundAttachment: 'scroll',
15893        			'will-change': 'transform'
15894        		}); 
15895
15896        	} else if ( config.speed > 1 && h > winH ) {
15897        		proportion = h / winH;
15898        		height = ( winH  +  ( ( winH * config.speed ) - winH ) * (1 + proportion) );
15899 
15900        		$this.css({
15901        			height: height,
15902        			top: -( height - (winH * config.speed) ),
15903        			backgroundAttachment: 'scroll',
15904        			'will-change': 'transform'
15905        		}); 
15906
15907        	} else if ( config.speed < 0 && h >= winH ) {
15908        		height = h * (1  - config.speed);
15909        		$this.css({
15910					height: height + (height - h),
15911        			top: h - height,
15912        			backgroundAttachment: 'scroll',
15913        			'will-change': 'transform'
15914        		});   
15915
15916        	} else if ( config.speed < 0 && h < winH ) {
15917        		// candidate to change
15918        		var display = (winH + h) / winH;
15919        		height = h * -config.speed * display;
15920        		$this.css({
15921					height: h + (height * 2),
15922        			top: -height,
15923        			backgroundAttachment: 'scroll',
15924        			'will-change': 'transform'
15925        		});         		
15926        	}
15927        };
15928
15929
15930		var currentPoint = null,
15931			progressVal = null,
15932			startPoint = null,
15933			endPoint = null,
15934			$opacityLayer = config.opacity ? $this.find( config.opacity ) : null,
15935			scrollY = null;
15936
15937		var setPosition = function() {
15938			startPoint = offset - winH;
15939			endPoint = offset + elHeight + winH - headerHeight;
15940			scrollY = val.scroll();
15941
15942			if( scrollY < startPoint || scrollY > endPoint ) { 
15943				ticking = false;
15944				return; 
15945			}
15946
15947			currentPoint = (( -offset + scrollY ) * config.speed);
15948
15949            $this.css({
15950              	'-webkit-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
15951              	'-moz-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
15952              	'-ms-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
15953              	'-o-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
15954              	'transform': 'translateY(' + currentPoint + 'px) translateZ(0)'
15955            });  
15956
15957			ticking = false;
15958		};
15959
15960 
15961		var requestTick = function() {
15962			if( !ticking && !isMobile ) {
15963				ticking = true;
15964				window.requestAnimationFrame( setPosition );
15965			}
15966		};
15967
15968
15969		var init = function() { 
15970			// Disable scroll effects when smooth scroll is disabled
15971			if( !MK.utils.isSmoothScroll ) { return; }
15972
15973			update();
15974			setTimeout(update, 100);
15975			$window.on( 'load', update );
15976			$window.on( 'resize', update );
15977	        window.addResizeListener( container, update );
15978	        
15979			$window.on( 'scroll', requestTick );
15980		};
15981		
15982 
15983		return {
15984			init : init
15985		};
15986	};
15987
15988})( jQuery );
15989(function($) {
15990	'use strict';
15991
15992	MK.component.Preloader = function(el) {
15993		this.el = el;
15994	};
15995
15996	MK.component.Preloader.prototype = {
15997		init: function init() {
15998			this.cacheElements();
15999			this.bindEvents();
16000		},
16001
16002		cacheElements: function cacheElements() {
16003			this.$preloader = $(this.el);
16004		},
16005
16006		bindEvents: function bindEvents() {
16007			this.onLoad(); // all components inited on page load
16008		},
16009
16010		onLoad: function onLoad() {
16011			setTimeout(this.hidePreloader.bind(this), 300);
16012		},
16013
16014		hidePreloader: function hidePreloader() {
16015			this.$preloader.hide();
16016		}
16017	};
16018
16019}(jQuery));
16020
16021(function($) {
16022	'use strict';
16023
16024	// Image added for proportional scaling
16025	MK.ui.loader = {
16026		tpl : function() {
16027			return '<div class="mk-loading-indicator">' + 
16028						'<div class="mk-loading-indicator__inner">' +
16029							'<div class="mk-loading-indicator__icon"></div>' +
16030							'<img style="height:100%; width:auto;" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">' +
16031						'</div>' +
16032					'</div>';
16033		},
16034
16035		add : function(item) {
16036			$(item).append(this.tpl);
16037		},
16038
16039		remove : function(item) {
16040			if(item) $(item).find('.mk-loading-indicator').remove();
16041			else $('.mk-loading-indicator').remove();
16042		}
16043	};
16044
16045}(jQuery));
16046(function( $ ) {
16047	// IE / Edge fix for fixed positioned elements
16048	// MS clip path doesnt redraw properly so we expirience similar bug like with background attachement fixed on Chrome
16049	if (MK.utils.browser.name === 'Edge' || MK.utils.browser.name === 'IE') {
16050	 	var val = 1;
16051	 	var $edgeClipper = $('.mk-slider-slide'); // edge slider
16052	 	var $sectionClipper = $('.clipper-true'); // edge slider
16053	 	var $bgLayer = $('.background-layer'); // page section
16054
16055    	var onScroll = function onScroll() {
16056	    	val *= -1;
16057	    	if( $edgeClipper.length ) $edgeClipper.each( redraw );
16058	    	if( $sectionClipper.length ) $sectionClipper.each( redraw );
16059	    	if( $bgLayer.length ) $bgLayer.each( redraw );
16060    	};
16061
16062	 	var redraw = function redraw() {
16063	    	$(this).css('margin-top', val / 100);
16064	    };
16065
16066	    $(window).on("scroll", function () {	    	
16067	    	window.requestAnimationFrame(onScroll);
16068	    });
16069	 }
16070}(jQuery));
16071MK.component.ResponsiveImageSetter = (function ($) {
16072
16073	'use strict';
16074
16075	var module = {};
16076
16077
16078	/*---------------------------------------------------------------------------------*/
16079	/* Private Variables
16080	/*---------------------------------------------------------------------------------*/
16081
16082	var viewportClass = getViewportClass();
16083	var isRetina = window.devicePixelRatio >= 2;
16084
16085
16086	/*---------------------------------------------------------------------------------*/
16087	/* Private Methods
16088	/*---------------------------------------------------------------------------------*/
16089
16090	function run($imgs) {
16091		$imgs.filter( function() {
16092			return !this.hasAttribute("mk-img-src-setted");
16093		}).each(setSrcAttr);
16094	}
16095
16096	function setSrcAttr() {
16097		var $img = $(this);
16098		var set = $img.data('mk-image-src-set');
16099		// Set src attribute to img link suitable for our logic. It will load the image.
16100		if(set['responsive'] === 'false' && isRetina && set['2x']) $img.attr('src', set['2x']);
16101		else if(set['responsive'] === 'false') $img.attr('src', set.default);
16102		else if(viewportClass === 1 && isRetina && set['2x']) $img.attr('src', set['2x']); // default x2 for retina
16103		else if(viewportClass === 0 && set.mobile) $img.attr('src', set.mobile);
16104		else $img.attr('src', set.default);
16105
16106		$img.load(function() {
16107			$(window).trigger('mk-image-loaded')
16108		})
16109	}
16110
16111	function getViewportClass() {
16112		if(window.matchMedia('(max-width: 736px)').matches) return 0;
16113		else return 1;
16114	}
16115
16116	function handleResize($imgs) {
16117		if(!$imgs.length) return;
16117 // Do not run if empty collection
16118		var currentViewportClass = getViewportClass();
16119		// We don't need to reload bigger images when screen size is decreasing as browser already performs resize operation.
16120		// Run update on for increasing screen size
16121		if( currentViewportClass > viewportClass) {
16122			viewportClass = currentViewportClass; // update for further reference
16123			run($imgs);
16124		}
16125	}
16126
16127
16128	/*---------------------------------------------------------------------------------*/
16129	/* Public Methods
16130	/*---------------------------------------------------------------------------------*/
16131
16132	module.init = function ($imgs) {
16133
16134		// Do not run if empty collection
16135		if(!$imgs.length) return;
16136
16137		// Run and bind to events
16138		run($imgs);
16139		$imgs.attr('mk-img-src-setted', '');
16140
16141	};
16142
16143	module.onResize = function ($imgs) {
16144
16145		$(window).on( 'resize', MK.utils.throttle( 500, function() {
16146			handleResize($imgs);
16147		}));
16148
16149
16150	};
16151
16152
16153	module.handleAjax = function () {
16154    	setTimeout(function ajaxDelayedCallback() { // give it a chance to insert content first
16155	    	var $newImgs = $('img[data-mk-image-src-set]').filter( function() {
16156				return !this.hasAttribute("mk-lazyload");
16157			});
16158			if(!$newImgs.length) return;
16159	    	run($newImgs);
16160    	}, 100);
16161    }
16162
16163
16164	return module;
16165
16166}(jQuery));
16167
16168
16169jQuery(function($) {
16170
16171	var init = function init() {
16172		// Get All Responsive Images
16173		$allImages = $('img[data-mk-image-src-set]').filter(function(index) {
16174			var isNotPortfolioImage = !$(this).hasClass('portfolio-image'),
16175				isNotBlogImage = $(this).closest('.mk-blog-container').length == 0,
16176				isNotSwiperImage = !$(this).hasClass('swiper-slide-image'),
16177				isNotGalleryImage = !$(this).hasClass('mk-gallery-image');
16178			return isNotPortfolioImage && isNotBlogImage && isNotSwiperImage && isNotGalleryImage;
16179		});;
16180
16181		// Handle the resize
16182		MK.component.ResponsiveImageSetter.onResize($allImages);
16183
16184		MK.component.ResponsiveImageSetter.init($allImages);
16185
16186		MK.utils.eventManager.subscribe('ajaxLoaded', MK.component.ResponsiveImageSetter.handleAjax ); // ajax loops
16187		MK.utils.eventManager.subscribe('ajax-preview', MK.component.ResponsiveImageSetter.handleAjax ); // ajax portfolio
16188		MK.utils.eventManager.subscribe('quickViewOpen', MK.component.ResponsiveImageSetter.handleAjax );
16189	}
16190	init();
16191	$(window).on('vc_reload', init);
16192
16193});
16194
16195
16196
16197(function($) {
16198	'use strict';
16199
16200	// 
16201	// Constructor
16202	// 
16203	// /////////////////////////////////////////////////////////
16204
16205	MK.ui.Slider = function( container, config ) { 
16206
16207		var defaults = {
16208				slide 				: '.mk-slider-slide',
16209	            nav 	     		: '.mk-slider-nav',
16210                effect              : 'roulete',
16211                ease 				: 'easeOutQuart', // should not be changed, remove
16212                slidesPerView       : 1,
16213                slidesToView        : 1,
16214                transitionTime      : 700,
16215                displayTime         : 3000,
16216                autoplay            : true,
16217                hasNav              : true,
16218                hasPagination       : true,
16219                paginationTpl 		: '<span></span>',
16220                paginationEl 		: '#pagination',
16221                draggable           : true,
16222                fluidHeight 		: false,
16223                pauseOnHover		: false,
16224                lazyload			: false,
16225                activeClass 		: 'is-active',
16226                edgeSlider	 		: false,
16227                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>',
16228                onInitialize 		: function() {},
16229                onAfterSlide 		: function( id ) {},
16230                onBeforeSlide 		: function( id ) {}
16231		};
16232
16233		this.state = {
16234			id 						: 0,
16235			moveForward 			: true,
16236			running   				: false,
16237            zIFlow					: null,
16238            stop 					: false,
16239		};
16240
16241		this.config = $.extend( defaults, config );
16242		this.container = container;
16243
16244		this.initPerView = this.config.slidesPerView;
16245
16246		// Timer holder
16247		this.activeTimer = null;
16248		this.autoplay = null;
16249		this.timer = null;
16250		this.timerRemaining = parseInt(this.config.displayTime);
16251
16252		// Boolean 'Em All, Making sure it's not string
16253		this.config.lazyload = JSON.parse(this.config.lazyload);
16254		this.config.edgeSlider = JSON.parse(this.config.edgeSlider);
16255
16256		// Image Loader Instance
16257		this.imageLoader = null;
16258
16259		// Add abort command to imagesLoaded, Placing it inside script makes it to work with different versions
16260		// of imagesLoaded if loaded by other Plugins
16261		imagesLoaded.prototype.abort = function() {
16262			this.progress = this.complete = function() { };
16263		};
16264	};
16265
16266	
16267
16268	// 
16269	// Shared methods
16270	// 
16271	// /////////////////////////////////////////////////////////
16272
16273	MK.ui.Slider.prototype = {
16274
16275		init : function() {
16276			this.setPerViewItems();
16277			this.cacheElements();
16278			this.getSlideSize();
16279			this.bindEvents();
16280            this.setSize();
16281			this.setPos();
16282
16283			// Hack for preparing 'prev' on first click if needed
16284			this.updateId( -1 );
16285			this.updateId( 1 );
16286
16287			this.val = this.dynamicVal();
16288			this.timeline = this.prepareTimeline( this.config.transitionTime );
16289
16290			this.timeline.build();
16291
16292			if( this.config.hasPagination ) { this.buildPagination(); }
16293			
16294			if( this.config.autoplay && document.hasFocus() ) { this.setTimer(); }
16295
16296			if( typeof this.config.onInitialize === 'function' ) {
16297				this.config.onInitialize( this.slides );
16298			}
16299
16300			if( this.config.fluidHeight === true ) {
16301				$( this.slides ).height( 'auto' );
16302				$( this.container ).css( 'transition', 'height ' + 200 + 'ms ease-out' );
16303				this.setHeight( 0 );
16304			}
16305
16306
16307			if( this.config.fluidHeight === 'toHighest' ) {
16308				this.setHeightToHighest();
16309			}
16310
16311			// Create timer per slide if required
16312			$(this.slides).each(this.createTimer);
16313
16314			// If it's Edge Slider and Lazy Load is enabled 
16315			if ( this.config.lazyload && this.config.edgeSlider ) {
16316
16317				// If It's not a Video Slide
16318				if ( $(this.slides[this.state.id]).find('video').length === 0 ) {
16319					// Set the first slide's BG image
16320					var $slideImg = $(this.slides[this.state.id]).children('[data-mk-img-set]');
16321					MK.component.BackgroundImageSetter.init( $slideImg );
16322				}
16323				$(this.config.spinnerTpl).prependTo( this.$slides );
16324
16325			} else {
16326
16327				// Set all slides's BG images
16328				MK.component.BackgroundImageSetter.init( $(this.slides).children('[data-mk-img-set]') );
16329
16330			}
16331			
16332
16333
16334		},
16335
16336
16337		cacheElements : function () {
16338			this.container = this.isNode( this.container ) ? this.container 
16339				: document.querySelectorAll( this.container )[0];
16340			this.slides = this.container.querySelectorAll( this.config.slide );
16341			this.$slides = $(this.slides);
16342
16343			if( this.config.hasNav ) { this.$nav = $( this.config.nav ); }
16344			if( this.config.hasPagination ) { this.$pagination = $( this.config.paginationEl ); }
16345		},
16346
16347
16348		bindEvents : function() {
16349			var $window = $( window );
16350
16351			if( this.config.slidesPerView > 1 ) { $window.on( 'resize', this.setPerViewItems.bind( this ) ); }
16352			if( this.config.hasNav ) { this.eventsNav(); }
16353			if( this.config.hasPagination ) { this.eventsPag(); }
16354			if( this.config.draggable ) { this.dragHandler(); }
16355			if( this.config.autoplay ) {
16356				$window.on( 'focus', this.windowActive.bind( this ) );
16357				$window.on( 'blur', this.windowInactive.bind( this ) );
16358			}
16359			if( this.config.pauseOnHover ) {
16360				$(this.container).on( 'mouseleave', this.setTimer.bind( this ) );
16361				$(this.container).on( 'mouseenter', this.unsetTimer.bind( this ) );
16362			}
16363			if( this.config.fluidHeight === 'toHighest' ) {
16364				$window.on( 'resize', this.setHeightToHighest.bind( this ) );
16365			}
16366		},
16367
16368
16369		setPerViewItems: function() {
16370			if(window.matchMedia( '(max-width: 500px)' ).matches) { this.config.slidesPerView = 1; }
16371			else if(window.matchMedia( '(max-width: 767px)' ).matches && this.initPerView >= 2 ) { this.config.slidesPerView = 2; }
16372			else if(window.matchMedia( '(max-width: 1024px)' ).matches && this.initPerView >= 3 ) { this.config.slidesPerView = 3; }
16373			else { this.config.slidesPerView = this.initPerView; }
16374			
16375        	if( typeof this.slides === 'undefined' ) return; 
16376			this.getSlideSize();
16377			this.setSize();
16378			this.setPos();
16379			this.timeline = this.prepareTimeline( this.config.transitionTime );
16380			this.timeline.build();
16381		},
16382
16383
16384		eventsNav : function() {
16385			this.$nav.on( 'click', 'a', this.handleNav.bind( this ) );
16386		},
16387
16388
16389		eventsPag : function() {
16390			this.$pagination.on( 'click', 'a', this.handlePagination.bind( this ) );
16391		},
16392
16393
16394		handleNav : function( e ) {
16395			e.preventDefault();
16396
16397			if( this.state.running ) { return; }
16398			this.state.running = true;
16399
16400			var $this = $( e.currentTarget ),
16401				moveForward = $this.data( 'direction' ) === 'next';
16402
16403
16404			if( this.config.autoplay ) { 
16405				this.unsetTimer();
16406				setTimeout( this.setTimer.bind( this ), this.config.transitionTime );
16407			}
16408
16409			this.state.moveForward = moveForward;
16410			this.timeline.build();
16411			this.timeline.play();
16412
16413			this.setActive( this.nextId( moveForward ? 1 : -1 ) );
16414			if( this.config.fluidHeight ) { this.setHeight( this.nextId( moveForward ? 1 : -1 ) ); }
16415		},
16416
16417
16418		handlePagination : function( e ) {
16419			e.preventDefault();
16420
16421			var $this = $( e.currentTarget ),
16422				id = $this.index();
16423
16424			this.goTo( id );
16425		},
16426
16427
16428		reset: function() {
16429			this.state.stop = true;
16430			this.state.id = 0;
16431			this.setPos();
16432			this.unsetTimer();
16433			this.setTimer();
16434		},
16435
16436
16437		goTo : function(id) {
16438			if( this.state.running ) { return; }
16439			this.state.running = true;
16440
16441			var lastId = this.state.id;
16442
16443			if( lastId === id ) {
16444				return;
16445			} else if( lastId < id ) {
16446				this.state.moveForward = true;
16447			} else {
16448				this.state.moveForward = false;
16449			}
16450
16451			if( this.config.autoplay ) { 
16452				this.unsetTimer();
16453				setTimeout( this.setTimer.bind( this ), this.config.transitionTime );
16454			}
16455
16456			this.timeline.build( Math.abs( lastId - id ) );
16457			this.timeline.play();
16458
16459			this.setActive( id );
16460			if( this.config.fluidHeight ) { this.setHeight( id ); } 
16461		},
16462
16463
16464		windowActive : function() {
16465			this.setTimer(false, true);
16466			$(this.container).removeClass('is-paused'); 
16467		},
16468
16469
16470		windowInactive : function() {
16471			this.unsetTimer();
16472			$(this.container).addClass('is-paused');
16473		},
16474
16475
16476		updateId : function( val ) {
16477			this.state.id = this.nextId(val);
16478		},
16479
16480		nextId : function( val ) {
16481			var len = this.slides.length,
16482				insertVal = this.state.id + val;
16483				insertVal = ( insertVal >= 0 ) ? insertVal : len + val;
16484				insertVal = ( insertVal >= len ) ? 0 : insertVal;
16485
16486			return insertVal;
16487		},
16488
16489
16490		setStyle : function( obj, style ) {
16491            var hasT = style.transform,
16492            	t = {
16493	                x       : ( hasT ) ? style.transform.translateX : null,
16494	                y       : ( hasT ) ? style.transform.translateY : null,
16495	                scale   : ( hasT ) ? style.transform.scale 		: null,
16496	                rotate  : ( hasT ) ? style.transform.rotate 	: null,
16497	                rotateX : ( hasT ) ? style.transform.rotateX 	: null,
16498	                rotateY : ( hasT ) ? style.transform.rotateY 	: null
16499           		},
16500				z  = 'translateZ(0)',
16501            	x  = (t.x) ?  'translateX(' + t.x + '%)' 		: 'translateX(0)',
16502                y  = (t.y) ?  'translateY(' + t.y + '%)' 		: 'translateY(0)',
16503                s  = (t.scale)  ?  'scale(' + t.scale + ')' 	: 'scale(1)',
16504                r  = (t.rotate) ? 'rotate(' + t.rotate + 'deg)' : 'rotate(0)',
16505                rX = (t.rotateX) ? 'rotateX(' + t.rotateX + 'deg)' : '',
16506                rY = (t.rotateY) ? 'rotateY(' + t.rotateY + 'deg)' : '',
16507
16508           		o = style.opacity,
16509           		h = style.height,
16510           		w = style.width;
16511
16512            var c = z + x + y  + s + r + rX + rY;
16513
16514            if( c.length ) {
16515	            obj.style.webkitTransform 	= c;
16516	            obj.style.msTransform 		= c;
16517	            obj.style.transform 		= c;
16518	        }
16519
16520            if( typeof o === 'number' ) { obj.style.opacity = o; }
16521            if( h ) { obj.style.height  = h + '%'; }
16522            if( w ) { obj.style.width   = w + '%'; }
16523		},
16524
16525
16526		setPos : function() {
16527        	if( typeof this.slides === 'undefined' ) return; 
16528		    var id 			= this.state.id,
16529		    	i 			= 0,
16530		    	len 		= this.slides.length,
16531		    	animation 	= this.animation[ this.config.effect ],
16532		    	axis 		= animation.axis,
16533				animNext	= animation.next,
16534				animActi 	= animation.active,
16535				animPrev 	= animation.prev,
16536                perView 	= this.config.slidesPerView,
16537                slideId 	= null,
16538                zIFlow 		= null,
16539                style 		= {};
16540
16541            style.transform = {};
16542
16543
16544            for( ; i < len; i += 1 ) {
16545                if(i < perView) {
16546                	// Position for visible slides. Apply active styles
16547                	style = animActi;
16548                    style.transform[ 'translate' + axis ] = i * 100;
16549                } else {
16550                	// Rest slides move after edge based on axis and moveForward. Apply Next / Prev styles
16551                	style = this.state.moveForward ? animNext : animPrev;
16552                    style.transform[ 'translate' + axis ] =  this.state.moveForward ? perView * 100 : -100;
16553                }
16554
16555                this.slides[ i ].style.zIndex = 0;
16556
16557                slideId = ( i + id ) % len;
16558                this.setStyle( this.slides[ slideId ], style );
16559            }
16560		},
16561
16562
16563        // When we're setting animation along Y axis we're going to set up height
16564        // otherwise width. It is shared amongst all slides
16565        setSize : function() {
16566        	if( typeof this.slides === 'undefined' ) return; 
16567        	var i = 0,
16568		    	len = this.slides.length,
16569		    	axis = this.animation[ this.config.effect ].axis,
16570                slideSize = this.slideSize,
16571        		style = {};
16572
16573            if( axis === 'Y' ) {
16574                style.height = slideSize[ axis ];
16575            } else {
16576                style.width = slideSize[ axis ];
16577            }
16578
16579            for( ; i < len; i += 1 ) {
16580                this.setStyle( this.slides[ i ], style );
16581            }
16582        },
16583
16584
16585        setHeight : function( id ) {
16586			var $slides = $( this.slides ),
16587				$activeSlide = $slides.eq( id );
16588
16589        	var currentHeight = $activeSlide.height();
16590        	$( this.container ).height( currentHeight ); 
16591        },
16592
16593
16594        setHeightToHighest : function() {
16595        	// this is becouse of alliginig woocommrece carousel. Too much DOM
16596        	// Refactor someday
16597			var $slides = $( this.slides ),
16598				height = 0;
16599
16600        	$slides.each(function() {
16601        		height = Math.max(height, $(this).find('> div').outerHeight());
16602        	});
16603
16604        	$( this.container ).height( height ); 
16605        },
16606
16607
16608        // Little utility inspired by GreenSock.
16609        // We export this to this.timeline on init. 
16610        prepareTimeline : function( time ) {
16611			var self 		= this,
16612				iteration 	= 0,
16613            	totalIter 	= time / (1000 / 60),
16614            	animLoop 	= [],
16615            	aL 			= 0, // animation length
16616            	loops 		= 1,
16617				ease 		= this.config.ease, 
16618				currentStyle, timeProg, 
16619				build, move, add, play, reverse, progress, kill;
16620
16621
16622			// Build constants, run them only once
16623			// take out possibly
16624			var len 		= this.slides.length,
16625				perView   	= this.config.slidesPerView,
16626				animation 	= this.animation[ this.config.effect ],
16627				animAxis 	= animation.axis,
16628				animNext	= animation.next,
16629				animActi 	= animation.active,
16630				animPrev 	= animation.prev,
16631				style 		= {},
16632				slideId 	= null,
16633				zIFlow 		= null;
16634
16635				style.transform = {};
16636
16637
16638			build = function( repeats ) {
16639				var currentEase = ease;
16640				loops = repeats || loops;
16641
16642				// console.log('build', loops);
16643
16644				if( !loops ) { return; }
16645				if( loops > 1 ) {
16646					currentEase = 'linearEase';
16647				}
16648
16649				// clean before running new build
16650				kill();
16651				// set new positions
16652				self.setPos();
16653
16654				var id = self.state.id,
16655					moveForward = self.state.moveForward,
16656					i = 0,
16657					axisMove = (moveForward) ? -100 : 100;
16658
16659				for( ; i <= perView; i += 1 ) {
16660					slideId = ( (moveForward) ? i + id : i + id - 1 ) % len;
16661					slideId = ( slideId < 0 ) ? len + slideId : slideId;
16662
16663					if( i === 0 ) {
16664						style = moveForward ? animPrev : animActi;
16665					} else if( i === perView ) {
16666						style = moveForward ? animActi : animNext;
16667					} else {
16668						style = animActi;
16669	            	}
16670
16671               	 	zIFlow = (self.state.moveForward) ? animNext.zIndex : animPrev.zIndex; 
16672	                if( zIFlow ) { 
16673	                	// console.log( zIFlow );
16674	                	self.slides[ slideId ].style.zIndex = (zIFlow === '+') ? i + 1 : len - i;
16675	                }
16676
16677					style.transform[ 'translate' + animAxis ] = axisMove;
16678	            	add( self.slides[ slideId ], style, currentEase );
16679				}
16680			};
16681
16682			add = function( slide, toStyles, ease ) {
16683				if( typeof slide === 'undefined' ) {
16684					throw 'Add at least one slide';
16685				}
16686
16687	            var fromStyles = slide.style,
16688					style = self.refStyle( toStyles, fromStyles );
16689
16690				animLoop.push( [slide, style, ease] );
16691				aL += 1;
16692			};
16693
16694			move = function( startProg, mode ) {
16695				if (isTest) return;
16696				var currentTotalIter = totalIter;
16697
16698				if( loops > 1 ) {
16699				 	currentTotalIter = totalIter / 5;
16700				}
16701
16702				if( !self.state.running ) { self.state.running = true; }
16703
16704				if( startProg ) {
16705					// update iteration val to cached outside var
16706					// ceil to handle properly play after mouse up / touch end
16707					iteration = Math.ceil(startProg * currentTotalIter);
16708				}
16709				
16710				timeProg = iteration / currentTotalIter;
16711				progress( timeProg );
16712
16713				// Break loop
16714				if( iteration >= currentTotalIter && mode === 'play' || 
16715					iteration <= 0 && mode === 'reverse' ) { 
16716
16717					self.state.running = false;
16718					iteration = 0;
16719					kill();
16720	            	self.updateId( self.state.moveForward ? 1 : -1 );
16721					// If we're creating multiple animation loop we trigger outside only first pass to start all game.
16722					// the rest are triggered as callback
16723					loops -= 1;
16724					if( loops > 0 ) {
16725						build();
16726						play();
16727					}
16728
16729					// if we run all loops reset back the default value
16730					if( !loops ) {
16731						loops = 1;
16732						self.timerRemaining = parseInt(self.config.displayTime);
16733						self.config.onAfterSlide( self.state.id );
16734					}
16735
16736					return; 
16737				}
16738
16739				// Run in given mode
16740				if( mode === 'play') {
16741					iteration += 1;
16742				} else {
16743					iteration -= 1;
16744				}
16745
16746				requestAnimationFrame( function() {
16747					if(self.state.stop) return;
16748					move( 0, mode );
16749				});
16750			};
16751
16752			play = function( startProg ) {
16753
16754				var $nextSlide = $(self.slides[ self.nextId(self.state.moveForward ? 1 : -1) ] );
16755
16756				// If it's Edge Slider and Lazy Load is enabled and It's not a Video Slide
16757				if ( self.config.lazyload && self.config.edgeSlider ) {
16758
16759					// Set the next slide's BG Image
16760					var $slideImg = $nextSlide.find('[data-mk-img-set]');
16761					if ( $slideImg.length ) {
16762						MK.component.BackgroundImageSetter.init( $slideImg );
16763					}
16764
16765				}
16766
16767				self.config.onBeforeSlide( self.nextId(self.state.moveForward ? 1 : -1) );
16768				var start = startProg || 0;
16769				iteration = 0;
16770				self.state.stop = false;
16771				move( start, 'play' );
16772
16773			};
16774
16775			reverse = function( startProg ) {
16776				var start = startProg || 1;
16777				move( start, 'reverse' );
16778			};
16779
16780			progress = function( progVal ) {
16781            	var aI = 0, 
16782            		currentStyle;
16783
16784				for( aI; aI < aL; aI++ ) {
16785					if( progVal !== 1 && progVal !== 0 ) {
16786						currentStyle = self.currentStyle( progVal, animLoop[ aI ][ 1 ], animLoop[ aI ][ 2 ] );
16787					} else if( progVal === 1) {
16788						currentStyle = self.currentStyle( progVal, animLoop[ aI ][ 1 ], 'linearEase' );
16789					} else if ( progVal === 0 ) {
16790						currentStyle = self.currentStyle( progVal, animLoop[ aI ][ 1 ], 'linearEase' );
16791					} 
16792					self.setStyle( animLoop[ aI ][ 0 ], currentStyle );
16793				}
16794			};
16795
16796			// Clear previous loop
16797			kill = function() {
16798				animLoop = [];
16799            	aL = 0;
16800			};
16801
16802
16803			return {
16804				build 		: build,
16805				add 		: add,
16806				play 		: play,
16807				reverse 	: reverse,
16808				progress 	: progress
16809			};
16810		},
16811
16812
16813		// Build reference styles.
16814		// Return object with array containig initial style and change of its value
16815		// as required for easing functions
16816		refStyle : function( toStyles, fromStyles ) {
16817			var axis = this.animation[ this.config.effect ].axis,
16818            	style = {},
16819				initVal, changeVal, endVal, dynamicEnd, styleProp, transProp, transform;
16820
16821			for( styleProp in toStyles ) {
16822
16823				if( styleProp === 'transform' ) {
16824					transform = this.getTransforms( fromStyles );
16825					style.transform = {};
16826
16827					for( transProp in toStyles.transform ) {
16828						// don't care about z
16829						if( transProp === 'translateZ' ) { continue; }
16830
16831						initVal = transform[ transProp ] || 0; // if it is undefined it means it's 0
16832						dynamicEnd = ( transProp === 'translate' + axis ) ? initVal : 0;
16833						endVal  = toStyles.transform[ transProp ] + dynamicEnd; // it is dynamic, based on slide position in current set
16834						changeVal = endVal - initVal;
16835						style.transform[ transProp ] = [ initVal, changeVal ];
16836					}
16837				} else if( styleProp === 'zIndex' ) {
16838					// console.log( 'z' );
16839					continue;
16840				} else {
16841					initVal = parseFloat( fromStyles[ styleProp ] ) || 0; // if it is undefined it means it's 0
16842					endVal  = toStyles[ styleProp ];
16843					changeVal = endVal - initVal;
16844					style[ styleProp ] =  [ initVal, changeVal ];
16845				}
16846			}
16847
16848			return style;
16849		},
16850
16851
16852		currentStyle : function( progress, style, ease ) {
16853			var self = this,
16854				currentStyle = {},
16855            	currentVals, styleProp, transProp, prog;
16856
16857			// Redo same loop but construct currentStyle object out of cached values
16858			for( styleProp in style ) {
16859
16860				if( styleProp === 'transform' ) {
16861					currentStyle.transform = {};
16862
16863					for( transProp in style.transform ) {
16864						// remove this line. double check first if needed by logging
16865						if( transProp === 'translateZ' ) { continue; }
16866
16867						currentVals = style.transform[ transProp ];
16868						currentStyle.transform[ transProp ] = 
16869							// (currentIteration, startValue, changeInValue, totalIterations)
16870								self.ease[ ease ]( progress, currentVals[ 0 ], currentVals[ 1 ], 1 );
16871					}
16872				} else {
16873					currentVals = style[ styleProp ];
16874					currentStyle[ styleProp ] = 
16875						self.ease[ ease ]( progress, currentVals[ 0 ], currentVals[ 1 ], 1 );
16876				}
16877			}
16878
16879			return currentStyle;
16880		},
16881
16882
16883		setActive : function( id ) {
16884			var $slides = $( this.slides ),
16885				className = this.config.activeClass;
16886
16887			$slides.removeClass( className );
16888
16889			if( this.config.hasPagination ) {
16890				var $pagination = this.$pagination.find( 'a' );
16891				$pagination.removeClass( className );
16892				$pagination.eq( id ).addClass( className );
16893			}
16894
16895			if( this.activeTimer ) {
16896				clearTimeout( this.activeTimer );
16897				if ( this.imageLoader ) {
16898					this.imageLoader.abort();
16899				}
16900			} 
16901			
16902
16903			var self = this;
16904
16905			this.activeTimer = setTimeout( function() {
16906
16907				var $currentSlide = $slides.eq( id );
16908
16909				if ( self.config.lazyload && self.config.edgeSlider ) {  // If it's Edge Slider and Lazy Load is enabled
16910
16911					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
16912						
16913						var imgSet = $currentSlide.children('.mk-video-section-touch').data('mk-img-set');
16914						var exactImg = MK.component.BackgroundImageSetter.getImage( imgSet );
16915						var $bgImage = $('<img>').attr('src', exactImg );
16916
16917						self.imageLoader = imagesLoaded( $bgImage[0], function( instance ) {
16918							$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
16919							setTimeout( function() {
16920						 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
16921						 	}, 200);
16922							$currentSlide.addClass( className );
16923					 	});
16924
16925					} 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
16926
16927						$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
16928						setTimeout( function() {
16929					 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
16930					 	}, 200);
16931						$currentSlide.addClass( className );
16932						
16933					} else {  // If it's a Image Slide
16934
16935						if ( $currentSlide.children('[data-mk-img-set]').length ) {
16936							// Get the matching Image URL to start lazy loading
16937							var imgSet = $currentSlide.children('[data-mk-img-set]').data('mk-img-set');
16938							var exactImg = MK.component.BackgroundImageSetter.getImage( imgSet );
16939							var $bgImage = $('<img>').attr('src', exactImg );
16940
16941							// Prevent counting time on slide until the image loads
16942							self.unsetTimer();
16943							self.imageLoader = imagesLoaded( $bgImage[0], function( instance ) {
16944								// Hide spinner, Continue counting time on slide and show the content
16945							 	$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
16946							 	setTimeout( function() {
16947							 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
16948							 	}, 200);
16949								self.setTimer(false, false, $currentSlide.data('timer') || Number(self.config.displayTime) );
16950								$currentSlide.addClass( className );
16951							});
16952						} else {
16953							$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
16954						 	setTimeout( function() {
16955						 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
16956						 	}, 200);
16957							self.setTimer(false, false, $currentSlide.data('timer') || Number(self.config.displayTime) );
16958							$currentSlide.addClass( className );
16959						}
16960
16961					}
16962
16963				} else {
16964
16965					$currentSlide.addClass( className );
16966
16967				}
16968				
16969				
16970			}, this.config.transitionTime );
16971		},
16972
16973		createTimer : function() {
16974
16975			var $slide = $(this),
16976				video = $slide.find('video').get(0);
16977
16978			if(video) {
16979				// A hacky but reliable way to ge the video duration
16980				var interval = setInterval( function() {
16981					// If the metadata is ready
16982					if ( video.readyState > 0 ) {
16983						$slide.data('timer', (video.duration * 1000));
16984						$slide.attr('data-timer', (video.duration * 1000));
16985						clearInterval(interval);
16986					}
16987				}, 100);
16988			}
16989
16990		},
16991		
16992		setTimer : function( isFirst, isPaused, fixed_time ) {
16993			// check for custom timer
16994			var customTimer = this.$slides.eq(this.nextId(this.state.moveForward ? 1 : -1)).data('timer'),
16995				trans = parseInt( this.config.transitionTime ),
16996				interval = customTimer ? customTimer : parseInt( this.config.displayTime ),
16997				timer = interval + trans;
16998
16999			var self  = this,
17000				first = isFirst || true,
17001				fixed_time = fixed_time || 0,
17002				create, run;
17003
17004			this.timer = true;
17005			this.lastSetTimer = Date.now();
17006
17007			create = function() {	
17008
17009				if( self.autoplay ) { clearTimeout( self.autoplay ); }
17010				if( !self.timer ) {
17011					return;
17012				}
17013				self.state.moveForward = true;
17014				self.timeline.build();
17015				self.timeline.play();
17016				self.setActive( self.nextId( 1 ) );
17017				if( self.config.fluidHeight ) { self.setHeight( self.nextId( 1 ) ); }
17018				first = false;
17019				self.lastSetTimer = Date.now();
17020
17021				run();
17022			};
17023
17024			run = function(newInterval) {
17025				// check for custom timer
17026				customTimer = self.$slides.eq(self.nextId(self.state.moveForward ? 1 : -1)).data('timer');
17027				interval = customTimer ? customTimer : parseInt( self.config.displayTime );
17028				timer = interval + trans; // update timer with current val
17029
17030				var time = newInterval || timer;
17031				self.autoplay = setTimeout( create, time );
17032			};
17033
17034			if ( fixed_time ) {
17035				run( fixed_time );
17036			} else if (isPaused) {
17037				run( this.timerRemaining );
17038			} else {
17039				run();
17040			}
17041		},
17042
17043
17044		unsetTimer : function() {
17045			this.timer = false;
17046			this.lastUnsetTimer = Date.now();
17047			this.timerRemaining -= this.lastUnsetTimer - this.lastSetTimer;
17048			if( this.autoplay ) { clearTimeout( this.autoplay ); }
17049		},
17050
17051
17052		buildPagination : function() {
17053			var i   = 0,
17054				len = this.slides.length,
17055				tpl = '';
17056
17057			for( ; i < len; i += 1 ) {
17058				tpl += '<a href="javascript:;">' + this.config.paginationTpl + '</a>';
17059			}
17060
17061			this.$pagination.html( tpl );
17062			this.setActive( 0 );
17063		},
17064
17065
17066		getSlideSize : function() {
17067			this.slideSize = {
17068                X: 100 / this.config.slidesPerView,
17069                Y: 100 / this.config.slidesPerView
17070            };
17071		},
17072
17073
17074		getTransforms : function( style ) {
17075			// console.log( style );
17076		    var transform = style.transform || style.webkitTransform || style.mozTransform,
17077		    	regex = /(\w+)\(([^)]*)\)/g,
17078				match,
17079				T = {};
17080
17081			if( typeof transform !== 'string' ) {
17082				throw 'Transform prop is not a string.';
17083			}
17084
17085		    if( !transform ) { return; }
17086	
17087			// Run regex assignment
17088			while( match = regex.exec( transform ) ) {
17089				T[ match[ 1 ] ] = parseFloat( match[ 2 ] );
17090			}
17091
17092		    return T;
17093		},
17094
17095		isNode : function( o ) {
17096			return (
17097		    	typeof Node === "object" ? o instanceof Node : 
17098		   			o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string"
17099		  	);
17100		},
17101
17102
17103		dragHandler : function() {
17104			var self = this,
17105				$container = $( this.container ),
17106				prevBuild = false, 
17107				nextBuild = false,
17108				dragging = false,
17109				buffor = 5, // helpful for decoupling with click events
17110				dragStart, dragMove, dragEnd, progress;
17111
17112			progress = function( moveX ) {
17113				return moveX / self.val.viewportW();
17114			};
17115
17116			dragStart = function( moveX, startX ) {
17117				// console.log( 'start', moveX, startX );
17118			};
17119
17120			dragMove = function( moveX ) {
17121				// console.log('move');
17122				if( self.state.running ) return;
17123
17124				// Don't need to check for existance here
17125
17126				if( moveX < -buffor ) {
17127
17128					if( !nextBuild ) {
17129						self.state.moveForward = true;
17130						self.timeline.build();
17131						nextBuild = true;
17132						prevBuild = false;
17133						self.unsetTimer();
17134					} else {
17135						// turn progress into positive val
17136						self.timeline.progress( -progress( moveX ) );
17137					}
17138					dragging = true;
17139				} else if( moveX > buffor ) {
17140
17141					if( !prevBuild ) {
17142						self.state.moveForward = false;
17143						self.timeline.build();
17144						prevBuild = true;
17145						nextBuild = false;
17146						self.unsetTimer();
17147					} else {
17148						self.timeline.progress( progress( moveX ) );
17149					}
17150					dragging = true;
17151				}
17152			};
17153
17154			dragEnd = function( moveX ) {
17155				if( dragging ) {
17156					var prog = progress( moveX ),
17157						absProg = prog < 0 ? -prog : prog;
17158
17159					if( absProg > 0.1 ) {
17160						self.timeline.play( absProg );
17161						self.setActive( self.nextId( prog < 0 ? 1 : -1 ) );
17162						if( self.config.fluidHeight ) { self.setHeight( self.nextId( prog < 0 ? 1 : -1 ) ); }
17163					} else {
17164						self.timeline.reverse( absProg );
17165						// eventually move this to reverse callbacks	
17166						if(prog < 0) {
17167							self.updateId( -1 );
17168						} else {
17169							self.updateId( 1 );
17170						}
17171					}
17172
17173					prevBuild = false;
17174					nextBuild = false;
17175					dragging = false;
17176					if( self.config.autoplay ) { self.setTimer( false ); }
17177				}
17178			};
17179
17180			this.drag( $container, dragStart, dragMove, dragEnd );
17181		},
17182
17183
17184		drag : function( $el, startFn, moveFn, stopFn ) {
17185
17186		    var touchX, touchY, movX, movY, go, evt,
17187		   		prevent, start, move, stop;
17188
17189		    prevent = function( e ) {
17190		        e.preventDefault();
17191		    };
17192
17193		    start = function( e ) {
17194		        // $el.on("touchmove", prevent);
17195		        $el.on("mousemove", prevent);
17196		        $el.on("touchmove", move);
17197		        $el.on("mousemove", move);
17198
17199		        evt = (e.type === 'touchstart') ? e.originalEvent.touches[0] : e;
17200		        touchX = evt.pageX;
17201
17202		        if(typeof startFn === 'function') {
17203		        	startFn(movX, touchX);
17204		        }
17205		    };
17206
17207		    move = function( e ) {
17208		        evt = (e.type === 'touchmove') ? e.originalEvent.touches[0] : e;
17209		        movX = evt.pageX - touchX;
17210
17211	        	if(typeof moveFn === 'function') {
17212		        	moveFn(movX);
17213		        }
17214		    };
17215
17216		    stop = function( e ) {
17217		        // $el.off("touchmove", prevent);
17218		        $el.off("mousemove", prevent);
17219		        $el.off("touchmove", move);
17220		        $el.off("mousemove", move);
17221
17222		    	if(typeof stopFn === 'function') {
17223		        	stopFn(movX);
17224		        }
17225		    };
17226
17227		    $el.on("touchstart", start);
17228		    $el.on("mousedown", start);
17229		    $el.on("touchend", stop);
17230		    $el.on("touchleave", stop);
17231		    $el.on("touchcancel", stop);
17232		    $el.on("mouseup", stop);
17233		    $el.on("mouseleave", stop);
17234		},
17235
17236
17237		dynamicVal : function() {
17238			var $window = $( window ),
17239				update, 
17240				getViewportW, viewportW;
17241
17242			update = function() {
17243 				viewportW = $window.width();
17244			};
17245
17246			getViewportW = function() {
17247				return viewportW;
17248			};
17249
17250			update();
17251			$window.on( 'load', update );
17252			$window.on( 'resize', update );
17253
17254			return {
17255				viewportW : getViewportW
17256			};
17257		}
17258	};
17259
17260
17261
17262	// 
17263	// Set of default animations
17264	// 
17265	// /////////////////////////////////////////////////////////
17266
17267	MK.ui.Slider.prototype.animation = {
17268
17269        slide : {
17270        	axis : 'X', 
17271            next : { transform: {} },
17272            active : { transform: {} },
17273            prev : { transform: {} }
17274        },
17275
17276        vertical_slide : {
17277        	axis : 'Y',
17278            next : { transform: {} },
17279            active : { transform: {} },
17280            prev : { transform: {} }
17281        },
17282
17283        perspective_flip : {
17284        	axis : 'Y',
17285            next : { 
17286            	transform: {
17287            		rotateX : 80
17288            	} 
17289            },
17290            active : { 
17291            	transform: {
17292            		rotateX : 0
17293            	} 
17294            },
17295            prev : { 
17296            	transform: {
17297            		rotateX : 0
17298            	} 
17299            }
17300        },
17301
17302        zoom : {
17303			axis : 'Z',
17304            next: {
17305                opacity	: 0,
17306                transform : {
17307	                scale : 0.9
17308	            }
17309            },
17310            active: {
17311                opacity	: 1,
17312                transform : {
17313	                scale : 1
17314	            }
17315            },
17316            prev: {
17317                opacity	: 0,
17318                transform : {
17319	                scale : 1.1
17320	            }
17321            }
17322        },
17323
17324        fade : {
17325			axis : 'Z',
17326            next: {
17327                opacity	: 0,
17328                transform : {}
17329            },
17330            active: {
17331                opacity	: 1,
17332                transform : {}
17333            },
17334            prev: {
17335                opacity	: 0,
17336                transform : {}
17337            }
17338        },
17339
17340        kenburned : {
17341			axis : 'Z',
17342            next: {
17343                opacity	: 0,
17344                transform : {}
17345            },
17346            active: {
17347                opacity	: 1,
17348                transform : {}
17349            },
17350            prev: {
17351                opacity	: 0,
17352                transform : {}
17353            }
17354        },
17355
17356        zoom_out : {
17357			axis : 'Z',
17358            next: {
17359				zIndex : '+',
17360                opacity	: 1,
17361                transform : {
17362	                translateY : 100,
17363	                scale : 1
17364	            }
17365            },
17366            active: {
17367                opacity	: 1,
17368                transform : {
17369	                translateY : 0,
17370	                scale : 1
17371	            }
17372            },
17373            prev: {
17374				zIndex : '+',
17375                opacity	: 0,
17376                transform : {
17377	                translateY : 0,
17378	                scale : 0.5
17379	            }
17380            }
17381        },
17382
17383        // Problem with Z-Flow
17384        horizontal_curtain : {
17385			axis : 'Z',
17386            next: {
17387				zIndex : '+',
17388                transform : {
17389	                translateX : 100,
17390	            }
17391            },
17392            active: {
17393                transform : {
17394	                translateX : 0,
17395	            }
17396            },
17397            prev: {
17398				zIndex : '+',
17399                transform : {
17400	                translateX : -70,
17401	            }
17402            }
17403        },
17404
17405		roulete : {
17406			axis : 'X',
17407            next: {
17408                opacity	: 0.5,
17409                transform : {
17410	                scale : 0.5,
17411	                rotate : 10,
17412	                translateY : 20
17413	            }
17414            },
17415            active: {
17416                opacity	: 1,
17417                transform : {
17418	                scale : 1,
17419	                rotate : 0,
17420	                translateY : 0
17421	            }
17422            },
17423            prev: {
17424                opacity	: 0.3,
17425                transform : {
17426	                scale : 0.5,
17427	                rotate : -10,
17428	                translateY : 20
17429	            }
17430            }
17431		}
17432	};
17433
17434
17435
17436	// 
17437	// Penner's easing library
17438	// 
17439	// /////////////////////////////////////////////////////////
17440
17441	MK.ui.Slider.prototype.ease = {
17442		/*
17443		 *
17444		 * TERMS OF USE - EASING EQUATIONS
17445		 * 
17446		 * Open source under the BSD License. 
17447		 * 
17448		 * Copyright © 2001 Robert Penner
17449		 * All rights reserved.
17450		 * 
17451		 * Redistribution and use in source and binary forms, with or without modification, 
17452		 * are permitted provided that the following conditions are met:
17453		 * 
17454		 * Redistributions of source code must retain the above copyright notice, this list of 
17455		 * conditions and the following disclaimer.
17456		 * Redistributions in binary form must reproduce the above copyright notice, this list 
17457		 * of conditions and the following disclaimer in the documentation and/or other materials 
17458		 * provided with the distribution.
17459		 * 
17460		 * Neither the name of the author nor the names of contributors may be used to endorse 
17461		 * or promote products derived from this software without specific prior written permission.
17462		 * 
17463		 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
17464		 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17465		 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
17466		 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
17467		 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
17468		 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
17469		 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
17470		 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
17471		 * OF THE POSSIBILITY OF SUCH DAMAGE. 
17472		 *
17473		 */
17474		linearEase : function(currentIteration, startValue, changeInValue, totalIterations) {
17475			return changeInValue * currentIteration / totalIterations + startValue;
17476		},
17477
17478		easeInQuad : function(currentIteration, startValue, changeInValue, totalIterations) {
17479			return changeInValue * (currentIteration /= totalIterations) * currentIteration + startValue;
17480		},
17481
17482		easeOutQuad : function(currentIteration, startValue, changeInValue, totalIterations) {
17483			return -changeInValue * (currentIteration /= totalIterations) * (currentIteration - 2) + startValue;
17484		},
17485
17486		easeInOutQuad : function(currentIteration, startValue, changeInValue, totalIterations) {
17487			if ((currentIteration /= totalIterations / 2) < 1) {
17488				return changeInValue / 2 * currentIteration * currentIteration + startValue;
17489			}
17490			return -changeInValue / 2 * ((--currentIteration) * (currentIteration - 2) - 1) + startValue;
17491		},
17492
17493		easeInCubic : function(currentIteration, startValue, changeInValue, totalIterations) {
17494			return changeInValue * Math.pow(currentIteration / totalIterations, 3) + startValue;
17495		},
17496
17497		easeOutCubic : function(currentIteration, startValue, changeInValue, totalIterations) {
17498			return changeInValue * (Math.pow(currentIteration / totalIterations - 1, 3) + 1) + startValue;
17499		},
17500
17501		easeInOutCubic : function(currentIteration, startValue, changeInValue, totalIterations) {
17502			if ((currentIteration /= totalIterations / 2) < 1) {
17503				return changeInValue / 2 * Math.pow(currentIteration, 3) + startValue;
17504			}
17505			return changeInValue / 2 * (Math.pow(currentIteration - 2, 3) + 2) + startValue;
17506		},
17507
17508		easeInQuart : function(currentIteration, startValue, changeInValue, totalIterations) {
17509			return changeInValue * Math.pow (currentIteration / totalIterations, 4) + startValue;
17510		},
17511
17512		easeOutQuart : function(currentIteration, startValue, changeInValue, totalIterations) {
17513			return -changeInValue * (Math.pow(currentIteration / totalIterations - 1, 4) - 1) + startValue;
17514		},
17515
17516		easeInOutQuart : function(currentIteration, startValue, changeInValue, totalIterations) {
17517			if ((currentIteration /= totalIterations / 2) < 1) {
17518				return changeInValue / 2 * Math.pow(currentIteration, 4) + startValue;
17519			}
17520			return -changeInValue/2 * (Math.pow(currentIteration - 2, 4) - 2) + startValue;
17521		},
17522
17523		easeInQuint : function(currentIteration, startValue, changeInValue, totalIterations) {
17524			return changeInValue * Math.pow (currentIteration / totalIterations, 5) + startValue;
17525		},
17526
17527		easeOutQuint : function(currentIteration, startValue, changeInValue, totalIterations) {
17528			return changeInValue * (Math.pow(currentIteration / totalIterations - 1, 5) + 1) + startValue;
17529		},
17530
17531		easeInOutQuint : function(currentIteration, startValue, changeInValue, totalIterations) {
17532			if ((currentIteration /= totalIterations / 2) < 1) {
17533				return changeInValue / 2 * Math.pow(currentIteration, 5) + startValue;
17534			}
17535			return changeInValue / 2 * (Math.pow(currentIteration - 2, 5) + 2) + startValue;
17536		},
17537
17538		easeInSine : function(currentIteration, startValue, changeInValue, totalIterations) {
17539			return changeInValue * (1 - Math.cos(currentIteration / totalIterations * (Math.PI / 2))) + startValue;
17540		},
17541
17542		easeOutSine : function(currentIteration, startValue, changeInValue, totalIterations) {
17543			return changeInValue * Math.sin(currentIteration / totalIterations * (Math.PI / 2)) + startValue;
17544		},
17545
17546		easeInOutSine : function(currentIteration, startValue, changeInValue, totalIterations) {
17547			return changeInValue / 2 * (1 - Math.cos(Math.PI * currentIteration / totalIterations)) + startValue;
17548		},
17549
17550		easeInExpo : function(currentIteration, startValue, changeInValue, totalIterations) {
17551			return changeInValue * Math.pow(2, 10 * (currentIteration / totalIterations - 1)) + startValue;
17552		},
17553
17554		easeOutExpo : function(currentIteration, startValue, changeInValue, totalIterations) {
17555			return changeInValue * (-Math.pow(2, -10 * currentIteration / totalIterations) + 1) + startValue;
17556		},
17557
17558		easeInOutExpo : function(currentIteration, startValue, changeInValue, totalIterations) {
17559			if ((currentIteration /= totalIterations / 2) < 1) {
17560				return changeInValue / 2 * Math.pow(2, 10 * (currentIteration - 1)) + startValue;
17561			}
17562			return changeInValue / 2 * (-Math.pow(2, -10 * --currentIteration) + 2) + startValue;
17563		},
17564
17565		easeInCirc : function(currentIteration, startValue, changeInValue, totalIterations) {
17566			return changeInValue * (1 - Math.sqrt(1 - (currentIteration /= totalIterations) * currentIteration)) + startValue;
17567		},
17568
17569		easeOutCirc : function(currentIteration, startValue, changeInValue, totalIterations) {
17570			return changeInValue * Math.sqrt(1 - (currentIteration = currentIteration / totalIterations - 1) * currentIteration) + startValue;
17571		},
17572
17573		easeInOutCirc : function(currentIteration, startValue, changeInValue, totalIterations) {
17574			if ((currentIteration /= totalIterations / 2) < 1) {
17575				return changeInValue / 2 * (1 - Math.sqrt(1 - currentIteration * currentIteration)) + startValue;
17576			}
17577			return changeInValue / 2 * (Math.sqrt(1 - (currentIteration -= 2) * currentIteration) + 1) + startValue;
17578		}
17579	};
17580
17581})(jQuery);
17582(function( $ ) {
17583	'use strict';
17584
17585	var utils = MK.utils;
17586	var val   = MK.val;
17587
17588	/**
17589	 * Keep track of top Level sections so we can easly skip to next one.
17590	 * We must be explicit about DOM level to nested sections.
17591	 * 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).
17592	 * We keep track for the same sections in Footer for mutating window location with '!loading' to prevent native anchor behaviour.
17593	 */
17594	var $topLevelSections = $('#theme-page > .vc_row, #theme-page > .mk-main-wrapper-holder, #theme-page > .mk-page-section');
17595
17596	$( document ).on( 'click', '.mk-skip-to-next', function() {
17597		var $this = $( this ),
17598			/**
17599			 * Static height of button + the space to the bottom of the container.
17600			 *
17601			 * @TODO Possible to calculate dynamically.
17602			 */
17603			btnHeight = $this.hasClass( 'edge-skip-slider' ) ? 150 : 76,
17604			offset = $this.offset().top + btnHeight,
17605			nextOffset = utils.nextHigherVal( utils.offsets( $topLevelSections ), [offset] );
17606
17607		utils.scrollTo( nextOffset - val.offsetHeaderHeight( nextOffset ) );
17608	});
17609
17610})( jQuery );
17611
17612/* Social Share */
17613/* -------------------------------------------------------------------- */
17614(function($) {
17615    'use strict';
17616
17617    MK.component.SocialShare = function( el ) {
17618        var networks = {
17619			twitter : 'http://twitter.com/intent/tweet?text={title}&url={url}',
17620			pinterest : 'http://pinterest.com/pin/create/button/?url={url}&media={image}&description={title}',
17621			facebook : 'https://www.facebook.com/sharer/sharer.php?u={url}',
17622			googleplus : 'https://plus.google.com/share?url={url}',
17623			linkedin : 'http://www.linkedin.com/shareArticle?mini=true&url={url}&title={title}&summary={desc}',
17624			digg : 'http://digg.com/submit?url={url}&title={title}',
17625			reddit : 'http://reddit.com/submit?url={url}&title={title}',
17626        };
17627
17628        this.networks = networks;
17629        this.el = el;
17630    };
17631
17632
17633	MK.component.SocialShare.prototype = {
17634
17635        init : function() {
17636            this.cacheElements();
17637            this.bindEvents();
17638        },
17639
17640        cacheElements : function() {
17641            this.$this  = $( this.el );
17642
17643
17644        },
17645
17646        bindEvents : function() {
17647			var thisObject = this;
17648			var tempClass = "";
17649			$.each(this.networks, function( key, value ) {
17650				  thisObject.$tempClass = $('.' + key + '-share');
17651				  thisObject.$tempClass.click(thisObject.openSharingDialog.bind(self, this, key));
17652
17653			});
17654        },
17655
17656        openSharingDialog : function(url, site, args) {
17657			var urlWrapper = url;
17658			var rx = new RegExp('\{[a-z]*\}','g'), res;
17659			var match = rx.exec(url);
17660			while (match != null) {
17661				var pureAttr = match[0].replace("{", "").replace("}" , "");
17662				var attValue = $(args.currentTarget).attr('data-' + pureAttr);
17663				if (attValue === undefined || attValue === null) {
17664					attValue = "";
17665				}
17666				attValue = attValue.replace('#', '%23'); // fix for twitter description
17667				urlWrapper = urlWrapper.replace(match, attValue);
17668				match = rx.exec(url);
17669			}
17670
17671			window.open(urlWrapper, site + "Window", "height=320,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
17672
17673        },
17674
17675
17676    };
17677
17678
17679	//////////////////////////////////////////
17680    //
17681    // Apply to:
17682    //
17683    // ///////////////////////////////////////
17684
17685    var $body = $('body');
17686
17687    if(!$body.length) return;
17688
17689    $body.each(function() {
17690        var socialShare = new MK.component.SocialShare(this);
17691			socialShare.init();
17692    });
17693
17694})(jQuery);
17695
17696
17697
17698//function mk_social_share() {
17699//
17700//  "use strict";
17701//
17702//  $('.twitter-share').on('click', function () {
17703//    var $url = $(this).attr('data-url'),
17704//      $title = $(this).attr('data-title');
17705//
17706//    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");
17707//    return false;
17708//  });
17709//
17710//  $('.pinterest-share').on('click', function () {
17711//    var $url = $(this).attr('data-url'),
17712//      $title = $(this).attr('data-title'),
17713//      $image = $(this).attr('data-image');
17714//    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");
17715//    return false;
17716//  });
17717//
17718//  $('.facebook-share').on('click', function () {
17719//    var $url = $(this).attr('data-url');
17720//    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");
17721//    return false;
17722//  });
17723//
17724//  $('.googleplus-share').on('click', function () {
17725//    var $url = $(this).attr('data-url');
17726//    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");
17727//    return false;
17728//  });
17729//
17730//  $('.linkedin-share').on('click', function () {
17731//    var $url = $(this).attr('data-url'),
17732//      $title = $(this).attr('data-title'),
17733//      $desc = $(this).attr('data-desc');
17734//    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");
17735//    return false;
17736//  });
17737//}
17738
17739
17740
17741
17742(function($) {
17743	'use strict';
17744
17745	MK.component.Sortable = function(el) {
17746		this.el = el; 
17747	};
17748
17749	MK.component.Sortable.prototype = {
17750		init: function init() {
17751			this.cacheElements();
17752			this.bindEvents();
17753		},
17754
17755		cacheElements: function cacheElements() {
17756			this.unique = Date.now();
17757			this.$filter = $(this.el);
17758			this.config = this.$filter.data('sortable-config');
17759
17760			this.ajaxLoader = new MK.utils.ajaxLoader(this.config.container);
17761			this.ajaxLoader.init();
17762
17763			this.$container = $( this.config.container );
17764			this.$navItems = this.$filter.find('a');
17765			this.$filterItems = this.$container.find(this.config.item);
17766		},
17767
17768		bindEvents: function bindEvents() {
17769			this.$navItems.on('click', this.handleClick.bind(this));
17770			MK.utils.eventManager.subscribe('ajaxLoaded', this.onLoad.bind(this));
17771		},
17772
17773		handleClick: function handleClick(e) {
17774			e.preventDefault();
17775
17776			var $item = $(e.currentTarget);
17777			var term = $item.data('filter');
17778
17779			this.$navItems.removeClass('current');
17780			$item.addClass('current');
17781
17782			if(this.config.mode === 'ajax') this.inDB(term, $item);
17783	        else this.inPage(term);
17784		},
17785
17786		inDB: function inDB(term, $item) { 
17787			// Add load indicator only for long requests
17788			MK.ui.loader.remove(this.$filter);
17789			MK.ui.loader.add($item);
17790			
17791			// If mk-ajax-loaded-posts span exists and one of the filter is clicked,
17792			// clear post ids
17793			if ( this.$container.siblings('.mk-ajax-loaded-posts').length ) {		
17794				this.$container.siblings('.mk-ajax-loaded-posts').attr('data-loop-loaded-posts', '');
17795			}
17796
17797			this.ajaxLoader.setData({
17798				paged: 1,
17799				term: term
17800			});
17801            this.ajaxLoader.load(this.unique);
17802		},
17803
17804		inPage: function inPage(term) {
17805			var $filterItems = this.$container.find(this.config.item);
17806			$filterItems.removeClass('is-hidden'); // show all first
17807			// Replace all ', ' with ', .'. It's used to add '.' as class selector of each category.
17808			var className = term.replace( /, /g, ", ." );
17809			if(term !== '*') $filterItems.not( '.' + className ).addClass('is-hidden'); // hide filtered
17810			MK.utils.eventManager.publish('staticFilter');
17811		},
17812
17813		onLoad: function onLoad(e, response) {
17814			if(this.config.mode === 'static') {
17815				this.$navItems.removeClass('current').first().addClass('current');
17816			}
17817			if( typeof response !== 'undefined' &&  response.id === this.config.container) {
17818				MK.ui.loader.remove(this.$filter);
17819				if(response.unique === this.unique) {
17820		            this.$container.html(response.content);
17821					this.ajaxLoader.setData({paged: 1});
17822				}
17823			}
17824		}
17825	};
17826
17827})(jQuery);
17828(function($) {
17829    'use strict';
17830
17831    MK.component.Tabs = function( el ) {
17832        var defaults = {
17833            activeClass : 'is-active'
17834        };
17835
17836        this.config = defaults;
17837        this.el = el;
17838    };
17839
17840    MK.component.Tabs.prototype = {
17841
17842        init : function() {
17843            this.cacheElements();
17844            this.bindEvents();
17845        },
17846
17847        cacheElements : function() {
17848            this.$this  = $( this.el );
17849            this.$tabs  = this.$this.find( '.mk-tabs-tab' );
17850            this.$panes = this.$this.find( '.mk-tabs-pane' );
17851            this.currentId = 0;
17852        },
17853
17854        bindEvents : function() {
17855            var self = this;
17856
17857            this.$tabs.on( 'click', this.switchPane.bind( this ) );
17858        },
17859
17860        switchPane : function( evt ) {
17861            evt.preventDefault();
17862
17863            var clickedId = $( evt.currentTarget ).index();
17864
17865            this.hide( this.currentId );
17866            this.show( clickedId );
17867
17868            // Update current id
17869            this.currentId = clickedId;
17870
17871            // Notify rest of the app
17872            MK.utils.eventManager.publish('item-expanded');            
17873        },
17874
17875        show : function( id ) {
17876            this.$tabs.eq( id ).addClass( this.config.activeClass );
17877            this.$panes.eq( id ).addClass( this.config.activeClass );
17878        },
17879
17880        hide : function( id ) {
17881            this.$tabs.eq( id ).removeClass( this.config.activeClass );
17882            this.$panes.eq( id ).removeClass( this.config.activeClass );
17883        }
17884    };
17885
17886})(jQuery);
17887
17888
17889/* Tabs */
17890/* -------------------------------------------------------------------- */
17891
17892function mk_tabs() {
17893
17894  // "use strict";
17895
17896  // if ($.exists('.mk-tabs, .mk-news-tab, .mk-woo-tabs')) {
17897  //   $(".mk-tabs, .mk-news-tab, .mk-woo-tabs").tabs();
17898
17899  //    $('.mk-tabs').on('click', function () {
17900  //      $('.mk-theme-loop').isotope('layout');
17901  //    });
17902
17903  //   $('.mk-tabs.vertical-style').each(function () {
17904  //     $(this).find('.mk-tabs-pane').css('minHeight', $(this).find('.mk-tabs-tabs').height() - 1);
17905  //   });
17906
17907  // }
17908}
17909
17910function mk_tabs_responsive(){
17911  // $('.mk-tabs, .mk-news-tab').each(function () {
17912  //   $this = $(this);
17913  //   if ($this.hasClass('mobile-true')) {
17914  //     if (window.matchMedia('(max-width: 767px)').matches)
17915  //     {
17916  //         $this.tabs("destroy");
17917  //     } else {
17918  //       $this.tabs();
17919  //     }
17920  //   }
17921  // });
17922  
17923}
17924
17925
17926(function($) {
17927  'use strict';
17928
17929  $(document).on('click', function(e) {
17930    $('.mk-toggle-trigger').removeClass('mk-toggle-active');
17931  });
17932
17933  function toggle(e) {
17934      e.preventDefault();
17935      e.stopPropagation();
17936      var $this = $(e.currentTarget);
17937
17938      if (!$this.hasClass('mk-toggle-active')) {
17939
17940        $('.mk-box-to-trigger').fadeOut(200);
17941        $this.parent().find('.mk-box-to-trigger').fadeIn(250);
17942        $('.mk-toggle-trigger').removeClass('mk-toggle-active');
17943        $this.addClass('mk-toggle-active');
17944
17945      } else {
17946
17947        $('.mk-box-to-trigger').fadeOut(200);
17948        $this.removeClass('mk-toggle-active');
17949
17950      }
17951  }
17952
17953  function assignToggle() {
17954    // wait for ajax response propagation and insertion
17955    setTimeout(function() {
17956      $('.mk-toggle-trigger').off('click', toggle);
17957      $('.mk-toggle-trigger').on('click', toggle);
17958    }, 100);
17959  }
17960
17961  assignToggle();
17962  MK.utils.eventManager.subscribe('ajaxLoaded', assignToggle);
17963  MK.utils.eventManager.subscribe('ajax-preview', assignToggle);
17964
17965  $(window).on('vc_reload', function(){
17966    assignToggle();
17967    MK.utils.eventManager.subscribe('ajaxLoaded', assignToggle);
17968    MK.utils.eventManager.subscribe('ajax-preview', assignToggle);
17969  });
17970
17971}(jQuery));
17972(function($) {
17973	'use strict';
17974
17975	var $iframes = $('iframe');
17976
17977	$iframes.each(function() {
17978		var $iframe = $(this);
17979		var parent = $iframe.parent().get(0);
17980		var tagName = parent.tagName;
17981
17982		if(tagName === 'P') $iframe.wrap('<div class="mk-video-container"></div>');
17983	});
17984
17985}(jQuery));
17986(function( $ ) {
17987    'use strict';
17988    if( MK.utils.isMobile() ) {
17989        $('.mk-animate-element').removeClass('mk-animate-element');
17990        return;
17991    }
17992    var init = function init() {
17993        var $rootLevelEls = $('.js-master-row, .widget');
17994        $rootLevelEls.each( spyViewport );
17995        $rootLevelEls.each( function rootLevelEl() {
17996            var $animateEl = $(this).find( '.mk-animate-element' );
17997            $animateEl.each( spyViewport );
17998            /**
17999             * Firefox has known issue where horizontal scrollbar will appear if an
18000             * element uses animation CSS. The solution should be set the element
18001             * position as fixed or overflow-x as hidden. Position fixed is not possible
18002             * to use because it's only cause other big problems. The best way is
18003             * set overflow-x as hidden in the page content container #theme-page.
18004             *
18005             * NOTE: The problem is spotted on Right To Left viewport only. So, it's
18006             *       limited to '.right-to-left' selector only for now to avoid other
18007             *       problems. Please extend the functionallity if it's happen in
18008             *       other viewport animation effect.
18009             */
18010            var browserName  = MK.utils.browser.name;
18011            if ( browserName === 'Firefox' ) {
18012                var $rightToLeft = $( this ).find( '.right-to-left' );
18013                if ( $rightToLeft.length > 0 ) {
18014                    $( '#theme-page' ).css( 'overflow-x', 'hidden' );
18015                }
18016            }
18017        });
18018    };
18019    var spyViewport = function spyViewport(i) {
18020        var self = this;
18021        MK.utils.scrollSpy( this, {
18022            position  : 'bottom',
18023            threshold : 200,
18024            after     : function() {
18025                animate.call(self, i);
18026            }
18027        });
18028    };
18029    var animate = function animate(i) {
18030        var $this = $(this);
18031        setTimeout(function() {
18032            $this.addClass( 'mk-in-viewport' );
18033        }, 100 * i);
18034    };
18035    $(window).on('load vc_reload', init);
18036}(jQuery));
18037
18038function product_loop_add_cart() {
18039    var $body = $('body');
18040    $body.on('click', '.add_to_cart_button', function() {
18041        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>';
18042        var $holder = $(this).parents('.product:eq(0)');
18043        var $i = $holder.find('.product-loading-icon');
18044        $holder.addClass('adding-to-cart').removeClass('added-to-cart');
18045        $i.html(icon);
18046    });
18047    $body.bind('added_to_cart', function() {
18048        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>';
18049        var $holder = $('.adding-to-cart');
18050        var $i = $holder.find('.product-loading-icon');
18051        $holder.removeClass('adding-to-cart').addClass('added-to-cart');
18052        $i.html(icon);
18053    });
18054}
18055(function($) {
18056    'use strict';
18057
18058    /**
18059     * Entry point of application. Runs all components
18060     */
18061    $( window ).on( 'load', function() {
18062        MK.core.initAll( document );
18063        MK.utils.scrollToURLHash();
18064        // TODO move preloader to components and manage it state from within
18065        setTimeout( function() { 
18066            MK.ui.preloader.hide(); // site wide 
18067            $('.mk-preloader').hide(); // components
18068            $('body').removeClass('loading');
18069        }, 150 ); 
18070    });
18071
18072    /**
18073     * VC frontend editor. Init all components.
18074     */
18075    $( window ).on( 'vc_reload', function() {
18076        setTimeout(function(){ 
18077            MK.core.initAll( document ); 
18078        }, 100);
18079    });
18080
18081    /**
18082     * Assign global click handlers
18083     */
18084    $( document ).on( 'click', '.js-smooth-scroll, .js-main-nav a', smoothScrollToAnchor);
18085    $( '.side_dashboard_menu a' ).on( 'click', smoothScrollToAnchor);
18086
18087    function smoothScrollToAnchor( evt ) {
18088        var anchor = MK.utils.detectAnchor( this );
18089        var $this = $(evt.currentTarget);
18090        var loc = window.location;
18091        var currentPage = loc.origin + loc.pathname;
18092        var href = $this.attr( 'href' );
18093        var linkSplit = (href) ? href.split( '#' ) : '';
18094        var hrefPage  = linkSplit[0] ? linkSplit[0] : ''; 
18095        var hrefHash  = linkSplit[1] ? linkSplit[1] : '';
18096
18097        if( anchor.length ) {
18098            if(hrefPage === currentPage || hrefPage === '') evt.preventDefault();
18099            MK.utils.scrollToAnchor( anchor );
18100
18101        } else if( $this.attr( 'href' ) === '#' ) {
18102            evt.preventDefault();
18103        }
18104    }
18105    
18106}(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.