PageSourceSearch

https://themtransit.com/wp-content/themes/jupiter/assets/js/core-scripts.6.12.4.js?ver=1786806169

js themtransit.com collected 2026-09-24 12:59:50 UTC 555,675 bytes, 18,272 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.
vendor: 1,418 bytes, lines 1093-1140
1093   * @private
1094   * @returns {Array} An array of shived element node names.
1095   */
1096  function getElements() {
1097    var elements = html5.elements;
1098    return typeof elements == 'string' ? elements.split(' ') : elements;
1099  }
1100
1101  /**
1102   * Extends the built-in list of html5 elements
1103   * @memberOf html5
1104   * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
1105   * @param {Document} ownerDocument The context document.
1106   */
1107  function addElements(newElements, ownerDocument) {
1108    var elements = html5.elements;
1109    if(typeof elements != 'string'){
1110      elements = elements.join(' ');
1111    }
1112    if(typeof newElements != 'string'){
1113      newElements = newElements.join(' ');
1114    }
1115    html5.elements = elements +' '+ newElements;
1116    shivDocument(ownerDocument);
1117  }
1118
1119   /**
1120   * Returns the data associated to the given document
1121   * @private
1122   * @param {Document} ownerDocument The document.
1123   * @returns {Object} An object of data.
1124   */
1125  function getExpandoData(ownerDocument) {
1126    var data = expandoData[ownerDocument[expando]];
1127    if (!data) {
1128        data = {};
1129        expanID++;
1130        ownerDocument[expando] = expanID;
1131        expandoData[expanID] = data;
1132    }
1133    return data;
1134  }
1135
1136  /**
1137   * returns a shived element for the given nodeName and document
1138   * @memberOf html5
1139   * @param {String} nodeName name of the element
1140   * @param {Document|DocumentFrag
vendor: 6,335 bytes, lines 1140-1342
1140ment} ownerDocument The context document.
1141   * @returns {Object} The shived element.
1142   */
1143  function createElement(nodeName, ownerDocument, data){
1144    if (!ownerDocument) {
1145        ownerDocument = document;
1146    }
1147    if(supportsUnknownElements){
1148        return ownerDocument.createElement(nodeName);
1149    }
1150    if (!data) {
1151        data = getExpandoData(ownerDocument);
1152    }
1153    var node;
1154
1155    if (data.cache[nodeName]) {
1156        node = data.cache[nodeName].cloneNode();
1157    } else if (saveClones.test(nodeName)) {
1158        node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
1159    } else {
1160        node = data.createElem(nodeName);
1161    }
1162
1163    // Avoid adding some elements to fragments in IE < 9 because
1164    // * Attributes like `name` or `type` cannot be set/changed once an element
1165    //   is inserted into a document/fragment
1166    // * Link elements with `src` attributes that are inaccessible, as with
1167    //   a 403 response, will cause the tab/window to crash
1168    // * Script elements appended to fragments will execute when their `src`
1169    //   or `text` property is set
1170    return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
1171  }
1172
1173  /**
1174   * returns a shived DocumentFragment for the given document
1175   * @memberOf html5
1176   * @param {Document} ownerDocument The context document.
1177   * @returns {Object} The shived DocumentFragment.
1178   */
1179  function createDocumentFragment(ownerDocument, data){
1180    if (!ownerDocument) {
1181        ownerDocument = document;
1182    }
1183    if(supportsUnknownElements){
1184        return ownerDocument.createDocumentFragment();
1185    }
1186    data = data || getExpandoData(ownerDocument);
1187    var clone = data.frag.cloneNode(),
1188        i = 0,
1189        elems = getElements(),
1190        l = elems.length;
1191    for(;i<l;i++){
1192        clone.createElement(elems[i]);
1193    }
1194    return clone;
1195  }
1196
1197  /**
1198   * Shivs the `createElement` and `createDocumentFragment` methods of the document.
1199   * @private
1200   * @param {Document|DocumentFragment} ownerDocument The document.
1201   * @param {Object} data of the document.
1202   */
1203  function shivMethods(ownerDocument, data) {
1204    if (!data.cache) {
1205        data.cache = {};
1206        data.createElem = ownerDocument.createElement;
1207        data.createFrag = ownerDocument.createDocumentFragment;
1208        data.frag = data.createFrag();
1209    }
1210
1211
1212    ownerDocument.createElement = function(nodeName) {
1213      //abort shiv
1214      if (!html5.shivMethods) {
1215          return data.createElem(nodeName);
1216      }
1217      return createElement(nodeName, ownerDocument, data);
1218    };
1219
1220    ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
1221      'var n=f.cloneNode(),c=n.createElement;' +
1222      'h.shivMethods&&(' +
1223        // unroll the `createElement` calls
1224        getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
1225          data.createElem(nodeName);
1226          data.frag.createElement(nodeName);
1227          return 'c("' + nodeName + '")';
1228        }) +
1229      ');return n}'
1230    )(html5, data.frag);
1231  }
1232
1233  /*--------------------------------------------------------------------------*/
1234
1235  /**
1236   * Shivs the given document.
1237   * @memberOf html5
1238   * @param {Document} ownerDocument The document to shiv.
1239   * @returns {Document} The shived document.
1240   */
1241  function shivDocument(ownerDocument) {
1242    if (!ownerDocument) {
1243        ownerDocument = document;
1244    }
1245    var data = getExpandoData(ownerDocument);
1246
1247    if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
1248      data.hasCSS = !!addStyleSheet(ownerDocument,
1249        // corrects block display not defined in IE6/7/8/9
1250        'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
1251        // adds styling not present in IE6/7/8/9
1252        'mark{background:#FF0;color:#000}' +
1253        // hides non-rendered elements
1254        'template{display:none}'
1255      );
1256    }
1257    if (!supportsUnknownElements) {
1258      shivMethods(ownerDocument, data);
1259    }
1260    return ownerDocument;
1261  }
1262
1263  /*--------------------------------------------------------------------------*/
1264
1265  /**
1266   * The `html5` object is exposed so that more elements can be shived and
1267   * existing shiving can be detected on iframes.
1268   * @type Object
1269   * @example
1270   *
1271   * // options can be changed before the script is included
1272   * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
1273   */
1274  var html5 = {
1275
1276    /**
1277     * An array or space separated string of node names of the elements to shiv.
1278     * @memberOf html5
1279     * @type Array|String
1280     */
1281    'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
1282
1283    /**
1284     * current version of html5shiv
1285     */
1286    'version': version,
1287
1288    /**
1289     * A flag to indicate that the HTML5 style sheet should be inserted.
1290     * @memberOf html5
1291     * @type Boolean
1292     */
1293    'shivCSS': (options.shivCSS !== false),
1294
1295    /**
1296     * Is equal to true if a browser supports creating unknown/HTML5 elements
1297     * @memberOf html5
1298     * @type boolean
1299     */
1300    'supportsUnknownElements': supportsUnknownElements,
1301
1302    /**
1303     * A flag to indicate that the document's `createElement` and `createDocumentFragment`
1304     * methods should be overwritten.
1305     * @memberOf html5
1306     * @type Boolean
1307     */
1308    'shivMethods': (options.shivMethods !== false),
1309
1310    /**
1311     * A string to describe the type of `html5` object ("default" or "default print").
1312     * @memberOf html5
1313     * @type String
1314     */
1315    'type': 'default',
1316
1317    // shivs the document according to the specified `html5` object options
1318    'shivDocument': shivDocument,
1319
1320    //creates a shived element
1321    createElement: createElement,
1322
1323    //creates a shived documentFragment
1324    createDocumentFragment: createDocumentFragment,
1325
1326    //extends list of elements
1327    addElements: addElements
1328  };
1329
1330  /*--------------------------------------------------------------------------*/
1331
1332  // expose html5
1333  window.html5 = html5;
1334
1335  // shiv the document
1336  shivDocument(document);
1337
1338  if(typeof module == 'object' && module.exports){
1339    module.exports = html5;
1340  }
1341
1342}(typeof window !== "undefined" ? window : this, document));
1343/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. Dual MIT/BSD license */
1344
1345window.matchMedia || (window.matchMedia = function() {
1346    "use strict";
1347
1348    // For browsers that support matchMedium api such as IE 9 and webkit
1349    var styleMedia = (window.styleMedia || window.media);
1350
1351    // For those that don't support matchMedium
1352    if (!styleMedia) {
1353        var style       = document.createElement('style'),
1354            script      = document.getElementsByTagName('script')[0],
1355            info        = null;
1356
1357        style.type  = 'text/css';
1358        style.id    = 'matchmediajs-test';
1359
1360        script.parentNode.insertBefore(style, script);
1361
1362        // 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers
1363        info = ('getComputedStyle' in window) && window.getComputedStyle(style, null) || style.currentStyle;
1364
1365        styleMedia = {
1366            matchMedium: function(media) {
1367                var text = '@media ' + media + '{ #matchmediajs-test { width: 1px; } }';
1368
1369                // 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers
1370                if (style.styleSheet) {
1371                    style.styleSheet.cssText = text;
1372                } else {
1373                    style.textContent = text;
1374                }
1375
1376                // Test if media query is true or false
1377                return info.width === '1px';
1378            }
1379        };
1380    }
1381
1382    return function(media) {
1383        return {
1384            matches: styleMedia.matchMedium(media || 'all'),
1385            media: media || 'all'
1386        };
1387    };
1388}());
1389
1390/*!
1391 * The MIT License
1392 *
1393 * Copyright (c) 2012 James Allardice
1394 *
1395 * Permission is hereby granted, free of charge, to any person obtaining a copy
1396 * of this software and associated documentation files (the "Software"), to
1397 * deal in the Software without restriction, including without limitation the
1398 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1399 * sell copies of the Software, and to permit persons to whom the Software is
1400 * furnished to do so, subject to the following conditions:
1401 *
1402 * The above copyright notice and this permission notice shall be included in
1403 * all copies or substantial portions of the Software.
1404 *
1405 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1406 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1407 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1408 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1409 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1410 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
1411 * IN THE SOFTWARE.
1412 */
1413
1414( function ( global ) {
1415
1416  'use strict';
1417
1418  //
1419  // Test for support. We do this as early as possible to optimise for browsers
1420  // that have native support for the attribute.
1421  //
1422
1423  var test = document.createElement('input');
1424  var nativeSupport = test.placeholder !== void 0;
1425
1426  global.Placeholders = {
1427    nativeSupport: nativeSupport,
1428    disable: nativeSupport ? noop : disablePlaceholders,
1429    enable: nativeSupport ? noop : enablePlaceholders
1430  };
1431
1432  if ( nativeSupport ) {
1433    return;
1434  }
1435
1436  //
1437  // If we reach this point then the browser does not have native support for
1438  // the attribute.
1439  //
1440
1441  // The list of input element types that support the placeholder attribute.
1442  var validTypes = [
1443    'text',
1444    'search',
1445    'url',
1446    'tel',
1447    'email',
1448    'password',
1449    'number',
1450    'textarea'
1451  ];
1452
1453  // The list of keycodes that are not allowed when the polyfill is configured
1454  // to hide-on-input.
1455  var badKeys = [
1456
1457    // The following keys all cause the caret to jump to the end of the input
1458    // value.
1459
1460    27, // Escape
1461    33, // Page up
1462    34, // Page down
1463    35, // End
1464    36, // Home
1465
1466    // Arrow keys allow you to move the caret manually, which should be
1467    // prevented when the placeholder is visible.
1468
1469    37, // Left
1470    38, // Up
1471    39, // Right
1472    40, // Down
1473
1474    // The following keys allow you to modify the placeholder text by removing
1475    // characters, which should be prevented when the placeholder is visible.
1476
1477    8, // Backspace
1478    46 // Delete
1479  ];
1480
1481  // Styling variables.
1482  var placeholderStyleColor = '#ccc';
1483  var placeholderClassName = 'placeholdersjs';
1484  var classNameRegExp = new RegExp('(?:^|\\s)' + placeholderClassName + '(?!\\S)');
1485
1486  // The various data-* attributes used by the polyfill.
1487  var ATTR_CURRENT_VAL = 'data-placeholder-value';
1488  var ATTR_ACTIVE = 'data-placeholder-active';
1489  var ATTR_INPUT_TYPE = 'data-placeholder-type';
1490  var ATTR_FORM_HANDLED = 'data-placeholder-submit';
1491  var ATTR_EVENTS_BOUND = 'data-placeholder-bound';
1492  var ATTR_OPTION_FOCUS = 'data-placeholder-focus';
1493  var ATTR_OPTION_LIVE = 'data-placeholder-live';
1494  var ATTR_MAXLENGTH = 'data-placeholder-maxlength';
1495
1496  // Various other variables used throughout the rest of the script.
1497  var UPDATE_INTERVAL = 100;
1498  var head = document.getElementsByTagName('head')[ 0 ];
1499  var root = document.documentElement;
1500  var Placeholders = global.Placeholders;
1501  var keydownVal;
1502
1503  // Get references to all the input and textarea elements currently in the DOM
1504  // (live NodeList objects to we only need to do this once).
1505  var inputs = document.getElementsByTagName('input');
1506  var textareas = document.getElementsByTagName('textarea');
1507
1508  // Get any settings declared as data-* attributes on the root element.
1509  // Currently the only options are whether to hide the placeholder on focus
1510  // or input and whether to auto-update.
1511  var hideOnInput = root.getAttribute(ATTR_OPTION_FOCUS) === 'false';
1512  var liveUpdates = root.getAttribute(ATTR_OPTION_LIVE) !== 'false';
1513
1514  // Create style element for placeholder styles (instead of directly setting
1515  // style properties on elements - allows for better flexibility alongside
1516  // user-defined styles).
1517  var styleElem = document.createElement('style');
1518  styleElem.type = 'text/css';
1519
1520  // Create style rules as text node.
1521  var styleRules = document.createTextNode(
1522    '.' + placeholderClassName + ' {' +
1523      'color:' + placeholderStyleColor + ';' +
1524    '}'
1525  );
1526
1527  // Append style rules to newly created stylesheet.
1528  if ( styleElem.styleSheet ) {
1529    styleElem.styleSheet.cssText = styleRules.nodeValue;
1530  } else {
1531    styleElem.appendChild(styleRules);
1532  }
1533
1534  // Prepend new style element to the head (before any existing stylesheets,
1535  // so user-defined rules take precedence).
1536  head.insertBefore(styleElem, head.firstChild);
1537
1538  // Set up the placeholders.
1539  var placeholder;
1540  var elem;
1541
1542  for ( var i = 0, len = inputs.length + textareas.length; i < len; i++ ) {
1543
1544    // Find the next element. If we've already done all the inputs we move on
1545    // to the textareas.
1546    elem = i < inputs.length ? inputs[ i ] : textareas[ i - inputs.length ];
1547
1548    // Get the value of the placeholder attribute, if any. IE10 emulating IE7
1549    // fails with getAttribute, hence the use of the attributes node.
1550    placeholder = elem.attributes.placeholder;
1551
1552    // If the element has a placeholder attribute we need to modify it.
1553    if ( placeholder ) {
1554
1555      // IE returns an empty object instead of undefined if the attribute is
1556      // not present.
1557      placeholder = placeholder.nodeValue;
1558
1559      // Only apply the polyfill if this element is of a type that supports
1560      // placeholders and has a placeholder attribute with a non-empty value.
1561      if ( placeholder && inArray(validTypes, elem.type) ) {
1562        newElement(elem);
1563      }
1564    }
1565  }
1566
1567  // If enabled, the polyfill will repeatedly check for changed/added elements
1568  // and apply to those as well.
1569  var timer = setInterval(function () {
1570    for ( var i = 0, len = inputs.length + textareas.length; i < len; i++ ) {
1571      elem = i < inputs.length ? inputs[ i ] : textareas[ i - inputs.length ];
1572
1573      // Only apply the polyfill if this element is of a type that supports
1574      // placeholders, and has a placeholder attribute with a non-empty value.
1575      placeholder = elem.attributes.placeholder;
1576
1577      if ( placeholder ) {
1578
1579        placeholder = placeholder.nodeValue;
1580
1581        if ( placeholder && inArray(validTypes, elem.type) ) {
1582
1583          // If the element hasn't had event handlers bound to it then add
1584          // them.
1585          if ( !elem.getAttribute(ATTR_EVENTS_BOUND) ) {
1586            newElement(elem);
1587          }
1588
1589          // If the placeholder value has changed or not been initialised yet
1590          // we need to update the display.
1591          if (
1592            placeholder !== elem.getAttribute(ATTR_CURRENT_VAL) ||
1593            ( elem.type === 'password' && !elem.getAttribute(ATTR_INPUT_TYPE) )
1594          ) {
1595
1596            // Attempt to change the type of password inputs (fails in IE < 9).
1597            if (
1598              elem.type === 'password' &&
1599              !elem.getAttribute(ATTR_INPUT_TYPE) &&
1600              changeType(elem, 'text')
1601            ) {
1602              elem.setAttribute(ATTR_INPUT_TYPE, 'password');
1603            }
1604
1605            // If the placeholder value has changed and the placeholder is
1606            // currently on display we need to change it.
1607            if ( elem.value === elem.getAttribute(ATTR_CURRENT_VAL) ) {
1608              elem.value = placeholder;
1609            }
1610
1611            // Keep a reference to the current placeholder value in case it
1612            // changes via another script.
1613            elem.setAttribute(ATTR_CURRENT_VAL, placeholder);
1614          }
1615        }
1616      } else if ( elem.getAttribute(ATTR_ACTIVE) ) {
1617        hidePlaceholder(elem);
1618        elem.removeAttribute(ATTR_CURRENT_VAL);
1619      }
1620    }
1621
1622    // If live updates are not enabled cancel the timer.
1623    if ( !liveUpdates ) {
1624      clearInterval(timer);
1625    }
1626  }, UPDATE_INTERVAL);
1627
1628  // Disabling placeholders before unloading the page prevents flash of
1629  // unstyled placeholders on load if the page was refreshed.
1630  addEventListener(global, 'beforeunload', function () {
1631    Placeholders.disable();
1632  });
1633
1634  //
1635  // Utility functions
1636  //
1637
1638  // No-op (used in place of public methods when native support is detected).
1639  function noop() {}
1640
1641  // Avoid IE9 activeElement of death when an iframe is used.
1642  //
1643  // More info:
1644  //  - http://bugs.jquery.com/ticket/13393
1645  //  - https://github.com/jquery/jquery/commit/85fc5878b3c6af73f42d61eedf73013e7faae408
1646  function safeActiveElement() {
1647    try {
1648      return document.activeElement;
1649    } catch ( err ) {}
1650  }
1651
1652  // Check whether an item is in an array. We don't use Array.prototype.indexOf
1653  // so we don't clobber any existing polyfills. This is a really simple
1654  // alternative.
1655  function inArray( arr, item ) {
1656    for ( var i = 0, len = arr.length; i < len; i++ ) {
1657      if ( arr[ i ] === item ) {
1658        return true;
1659      }
1660    }
1661    return false;
1662  }
1663
1664  // Cross-browser DOM event binding
1665  function addEventListener( elem, event, fn ) {
1666    if ( elem.addEventListener ) {
1667      return elem.addEventListener(event, fn, false);
1668    }
1669    if ( elem.attachEvent ) {
1670      return elem.attachEvent('on' + event, fn);
1671    }
1672  }
1673
1674  // Move the caret to the index position specified. Assumes that the element
1675  // has focus.
1676  function moveCaret( elem, index ) {
1677    var range;
1678    if ( elem.createTextRange ) {
1679      range = elem.createTextRange();
1680      range.move('character', index);
1681      range.select();
1682    } else if ( elem.selectionStart ) {
1683      elem.focus();
1684      elem.setSelectionRange(index, index);
1685    }
1686  }
1687
1688  // Attempt to change the type property of an input element.
1689  function changeType( elem, type ) {
1690    try {
1691      elem.type = type;
1692      return true;
1693    } catch ( e ) {
1694      // You can't change input type in IE8 and below.
1695      return false;
1696    }
1697  }
1698
1699  function handleElem( node, callback ) {
1700
1701    // Check if the passed in node is an input/textarea (in which case it can't
1702    // have any affected descendants).
1703    if ( node && node.getAttribute(ATTR_CURRENT_VAL) ) {
1704      callback(node);
1705    } else {
1706
1707      // If an element was passed in, get all affected descendants. Otherwise,
1708      // get all affected elements in document.
1709      var handleInputs = node ? node.getElementsByTagName('input') : input
1709s;
1710      var handleTextareas = node ? node.getElementsByTagName('textarea') : textareas;
1711
1712      var handleInputsLength = handleInputs ? handleInputs.length : 0;
1713      var handleTextareasLength = handleTextareas ? handleTextareas.length : 0;
1714
1715      // Run the callback for each element.
1716      var len = handleInputsLength + handleTextareasLength;
1717      var elem;
1718      for ( var i = 0; i < len; i++ ) {
1719
1720        elem = i < handleInputsLength ?
1721          handleInputs[ i ] :
1722          handleTextareas[ i - handleInputsLength ];
1723
1724        callback(elem);
1725      }
1726    }
1727  }
1728
1729  // Return all affected elements to their normal state (remove placeholder
1730  // value if present).
1731  function disablePlaceholders( node ) {
1732    handleElem(node, hidePlaceholder);
1733  }
1734
1735  // Show the placeholder value on all appropriate elements.
1736  function enablePlaceholders( node ) {
1737    handleElem(node, showPlaceholder);
1738  }
1739
1740  // Hide the placeholder value on a single element. Returns true if the
1741  // placeholder was hidden and false if it was not (because it wasn't visible
1742  // in the first place).
1743  function hidePlaceholder( elem, keydownValue ) {
1744
1745    var valueChanged = !!keydownValue && elem.value !== keydownValue;
1746    var isPlaceholderValue = elem.value === elem.getAttribute(ATTR_CURRENT_VAL);
1747
1748    if (
1749      ( valueChanged || isPlaceholderValue ) &&
1750      elem.getAttribute(ATTR_ACTIVE) === 'true'
1751    ) {
1752
1753      elem.removeAttribute(ATTR_ACTIVE);
1754      elem.value = elem.value.replace(elem.getAttribute(ATTR_CURRENT_VAL), '');
1755      elem.className = elem.className.replace(classNameRegExp, '');
1756
1757      // Restore the maxlength value. Old FF returns -1 if attribute not set.
1758      // See GH-56.
1759      var maxLength = elem.getAttribute(ATTR_MAXLENGTH);
1760      if ( parseInt(maxLength, 10) >= 0 ) {
1761        elem.setAttribute('maxLength', maxLength);
1762        elem.removeAttribute(ATTR_MAXLENGTH);
1763      }
1764
1765      // If the polyfill has changed the type of the element we need to change
1766      // it back.
1767      var type = elem.getAttribute(ATTR_INPUT_TYPE);
1768      if ( type ) {
1769        elem.type = type;
1770      }
1771
1772      return true;
1773    }
1774
1775    return false;
1776  }
1777
1778  // Show the placeholder value on a single element. Returns true if the
1779  // placeholder was shown and false if it was not (because it was already
1780  // visible).
1781  function showPlaceholder( elem ) {
1782
1783    var val = elem.getAttribute(ATTR_CURRENT_VAL);
1784
1785    if ( elem.value === '' && val ) {
1786
1787      elem.setAttribute(ATTR_ACTIVE, 'true');
1788      elem.value = val;
1789      elem.className += ' ' + placeholderClassName;
1790
1791      // Store and remove the maxlength value.
1792      var maxLength = elem.getAttribute(ATTR_MAXLENGTH);
1793      if ( !maxLength ) {
1794        elem.setAttribute(ATTR_MAXLENGTH, elem.maxLength);
1795        elem.removeAttribute('maxLength');
1796      }
1797
1798      // If the type of element needs to change, change it (e.g. password
1799      // inputs).
1800      var type = elem.getAttribute(ATTR_INPUT_TYPE);
1801      if ( type ) {
1802        elem.type = 'text';
1803      } else if ( elem.type === 'password' && changeType(elem, 'text') ) {
1804        elem.setAttribute(ATTR_INPUT_TYPE, 'password');
1805      }
1806
1807      return true;
1808    }
1809
1810    return false;
1811  }
1812
1813  // Returns a function that is used as a focus event handler.
1814  function makeFocusHandler( elem ) {
1815    return function () {
1816
1817      // Only hide the placeholder value if the (default) hide-on-focus
1818      // behaviour is enabled.
1819      if (
1820        hideOnInput &&
1821        elem.value === elem.getAttribute(ATTR_CURRENT_VAL) &&
1822        elem.getAttribute(ATTR_ACTIVE) === 'true'
1823      ) {
1824
1825        // Move the caret to the start of the input (this mimics the behaviour
1826        // of all browsers that do not hide the placeholder on focus).
1827        moveCaret(elem, 0);
1828      } else {
1829
1830        // Remove the placeholder.
1831        hidePlaceholder(elem);
1832      }
1833    };
1834  }
1835
1836  // Returns a function that is used as a blur event handler.
1837  function makeBlurHandler( elem ) {
1838    return function () {
1839      showPlaceholder(elem);
1840    };
1841  }
1842
1843  // Returns a function that is used as a submit event handler on form elements
1844  // that have children affected by this polyfill.
1845  function makeSubmitHandler( form ) {
1846    return function () {
1847
1848        // Turn off placeholders on all appropriate descendant elements.
1849        disablePlaceholders(form);
1850    };
1851  }
1852
1853  // Functions that are used as a event handlers when the hide-on-input
1854  // behaviour has been activated - very basic implementation of the 'input'
1855  // event.
1856  function makeKeydownHandler( elem ) {
1857    return function ( e ) {
1858      keydownVal = elem.value;
1859
1860      // Prevent the use of the arrow keys (try to keep the cursor before the
1861      // placeholder).
1862      if (
1863        elem.getAttribute(ATTR_ACTIVE) === 'true' &&
1864        keydownVal === elem.getAttribute(ATTR_CURRENT_VAL) &&
1865        inArray(badKeys, e.keyCode)
1866      ) {
1867        if ( e.preventDefault ) {
1868            e.preventDefault();
1869        }
1870        return false;
1871      }
1872    };
1873  }
1874
1875  function makeKeyupHandler(elem) {
1876    return function () {
1877      hidePlaceholder(elem, keydownVal);
1878
1879      // If the element is now empty we need to show the placeholder
1880      if ( elem.value === '' ) {
1881        elem.blur();
1882        moveCaret(elem, 0);
1883      }
1884    };
1885  }
1886
1887  function makeClickHandler(elem) {
1888    return function () {
1889      if (
1890        elem === safeActiveElement() &&
1891        elem.value === elem.getAttribute(ATTR_CURRENT_VAL) &&
1892        elem.getAttribute(ATTR_ACTIVE) === 'true'
1893      ) {
1894        moveCaret(elem, 0);
1895      }
1896    };
1897  }
1898
1899  // Bind event handlers to an element that we need to affect with the
1900  // polyfill.
1901  function newElement( elem ) {
1902
1903    // If the element is part of a form, make sure the placeholder string is
1904    // not submitted as a value.
1905    var form = elem.form;
1906    if ( form && typeof form === 'string' ) {
1907
1908      // Get the real form.
1909      form = document.getElementById(form);
1910
1911      // Set a flag on the form so we know it's been handled (forms can contain
1912      // multiple inputs).
1913      if ( !form.getAttribute(ATTR_FORM_HANDLED) ) {
1914        addEventListener(form, 'submit', makeSubmitHandler(form));
1915        form.setAttribute(ATTR_FORM_HANDLED, 'true');
1916      }
1917    }
1918
1919    // Bind event handlers to the element so we can hide/show the placeholder
1920    // as appropriate.
1921    addEventListener(elem, 'focus', makeFocusHandler(elem));
1922    addEventListener(elem, 'blur', makeBlurHandler(elem));
1923
1924    // If the placeholder should hide on input rather than on focus we need
1925    // additional event handlers
1926    if (hideOnInput) {
1927      addEventListener(elem, 'keydown', makeKeydownHandler(elem));
1928      addEventListener(elem, 'keyup', makeKeyupHandler(elem));
1929      addEventListener(elem, 'click', makeClickHandler(elem));
1930    }
1931
1932    // Remember that we've bound event handlers to this element.
1933    elem.setAttribute(ATTR_EVENTS_BOUND, 'true');
1934    elem.setAttribute(ATTR_CURRENT_VAL, placeholder);
1935
1936    // If the element doesn't have a value and is not focussed, set it to the
1937    // placeholder string.
1938    if ( hideOnInput || elem !== safeActiveElement() ) {
1939      showPlaceholder(elem);
1940    }
1941  }
1942
1943}(this) );
1944// IE spupport comes in IE10
1945(function rAFPolyfill() {
1946    var lastTime, vendors, x;
1947    lastTime = 0;
1948    vendors = ["webkit", "moz"];
1949    x = 0;
1950    while (x < vendors.length && !window.requestAnimationFrame) {
1951      window.requestAnimationFrame = window[vendors[x] + "RequestAnimationFrame"];
1952      window.cancelAnimationFrame = window[vendors[x] + "CancelAnimationFrame"] || window[vendors[x] + "CancelRequestAnimationFrame"];
1953      ++x;
1954    }
1955    if (!window.requestAnimationFrame) {
1956      window.requestAnimationFrame = function(callback, element) {
1957        var currTime, id, timeToCall;
1958        currTime = new Date().getTime();
1959        timeToCall = Math.max(0, 16 - (currTime - lastTime));
1960        id = window.setTimeout(function() {
1961          callback(currTime + timeToCall);
1962        }, timeToCall);
1963        lastTime = currTime + timeToCall;
1964        return id;
1965      };
1966    }
1967    if (!window.cancelAnimationFrame) {
1968      window.cancelAnimationFrame = function(id) {
1969        clearTimeout(id);
1970      };
1971    }
1972})();
1973
1974
1975
1976(function($) {
1977	'use strict';
1978
1979	var MK = window.MK || {};
1980
1981	/**
1982	 * MK.core holds most important methods that bootstraps whole application
1983	 * 
1984	 * @type {Object}
1985	 */
1986	MK.core = {};
1987
1988
1989
1990	/**
1991	 * State for referance of already loaded script files
1992	 * @type {Array}
1993	 */
1994	var _loadedDependencies = [];
1995
1996	/**
1997	 * State of queue represented as pairs of script ref => callback
1998	 * @type {Object}
1999	 */
2000	var _inQueue = {};
2001	
2002	/**
2003	 * Initializes all components in given scope (object or DOM reference) based on data attribute and 'pointer' css class '.js-el'.
2004	 * DOM work is reduced by single traversing for pointer class and later filtering through cached object. It expects init() method
2005	 * on every component. Component itself should be defined in MK.component namespace and assign to DOM element via data-mk-component.
2006	 * Use it once on DOM ready with document as a scope. For partial initialization after aja
2006x operations pass as a scope element
2007	 * where new DOM was inserted.
2008	 * 
2009	 * @param  {string|object}
2010	 */
2011	MK.core.initAll = function( scope ) {
2012		var $el = $( scope ).find( '.js-el' ), // single traversing
2013			$components = $el.filter( '[data-mk-component]' ),
2014			component = null;
2015
2016
2017		// initialize  component
2018		var init = function init(name, el) {
2019			var $el = $(el);
2020
2021			if ( $el.data('init-' + name) ) return; // do not initialize the same module twice
2022
2023			if ( typeof MK.component[ name ] !== 'function' ) console.log('Component init error: ', name);
2024			else {
2025				component = new MK.component[ name ]( el );
2026				component.init();
2027				$el.data('init-' + name, true); // mark as initialised
2028				// TODO add name
2029				MK.utils.eventManager.publish('component-inited');
2030			}
2031		};
2032
2033		$components.each( function() {
2034			var self = this,
2035				$this = $( this ),
2036				names = $this.data( 'mk-component' );
2037
2038			if( typeof names === 'string' ) {
2039				var name = names; // containes only single name. Keep it transparent.
2040				init(name, self);
2041			} else {
2042				names.forEach( function( name ) {
2043					init(name, self);
2044				});
2045			} 
2046		}); 
2047	};
2048
2049	/**
2050	 * Async loader for 3rd party plugins available from within theme or external CDNs / APIs.
2051	 * Take one argument as callback which is run when loading is finished. Also keeps track of already loaded scripts 
2052	 * and prevent duplication. Holds in queue multiple callbacks that where defined in different places but depend on the 
2053	 * same plugin.
2054	 *
2055	 * TODO: heavy test for multiple dependencies and crosssharing one dependency and different one dependency in queue, 
2056	 * bulletproof with single dependency
2057	 *
2058	 * @example MK.core.loadDependencies([MK.core.path.plugins + 'plugin.js'], function() {
2059	 *          	// do something when plugin is loaded
2060	 * 			})
2061	 * 
2062	 * @param  {array}
2063	 * @param  {function}
2064	 */
2065	MK.core.loadDependencies = function( dependencies, callback ) {
2066		var _callback = callback || function() {};
2067
2068        if( !dependencies ) {
2069        	// If no dependencies defined then run _callback imidietelly
2070        	_callback(); 
2071        	return;
2072        }
2073
2074		// Check for new dependencies
2075        var newDeps = dependencies.map( function( dep ) {
2076            if( _loadedDependencies.indexOf( dep ) === -1 ) {
2077            	 if( typeof _inQueue[ dep ] === 'undefined' ) {
2078        			// console.log( dep );
2079                	return dep;
2080                } else {
2081                	_inQueue[ dep ].push( _callback );
2082                	return true;
2083                }
2084            } else {
2085            	return false;
2086            }
2087        });
2088
2089        // The dependency is not new but it's not resolved yet
2090        // Callback is added to queue that will be run after the script is loaded
2091        // Don't run callback just yet.
2092        if( newDeps[0] === true ) {
2093        	// console.log('Waiting for ' + dependencies[0]);
2094        	return;
2095        }
2096
2097        // Dependency was loaded previously. We can run callback safely
2098        if( newDeps[0] === false ) {
2099        	_callback();
2100        	return;
2101        }
2102
2103        // Create queue and relationship script -> callback array to track
2104        // all callbacks that waits for ths script
2105        var queue = newDeps.map( function( script ) {
2106        	// console.log( script );
2107        	_inQueue[ script ] = [ _callback ];
2108            return $.getCachedScript( script );
2109        });
2110
2111        // Callbacks invoking
2112        var onLoad = function onLoad() {
2113        	var index;
2114        	newDeps.map( function( loaded ) {
2115        		_inQueue[ loaded ].forEach( function( callback ) {
2116        			callback();
2117        		});
2118        		delete _inQueue[ loaded ];
2119                _loadedDependencies.push( loaded );
2120        	});
2121        };
2122
2123        // Run callbacks when promise is resolved
2124        $.when.apply( null, queue ).done( onLoad );
2125	};
2126
2127	/**
2128	 * Single namespace for all paths recuired in application.
2129	 * @type {Object}
2130	 */
2131	MK.core.path = {
2132		theme   : mk_theme_dir,
2133		plugins : mk_theme_js_path + '/plugins/async/min/',
2134		ajaxUrl : window.PHP.ajax
2135	};
2136
2137
2138})(jQuery);
2139(function($) {
2140	'use strict';
2141
2142    var MK = window.MK || {};
2143	MK.utils = window.MK.utils || {};
2144
2145    /**
2146     * Enables to evaluate common methods through DOM JSON references by invoking from object with bracket notation MK.utils[var][var]
2147     * @type {Object}
2148     */
2149    MK.utils.actions = {};
2150
2151    MK.utils.actions.activate = function (el) {
2152        $(el).addClass('is-active');
2153    };
2154        
2155    MK.utils.actions.deactivate = function (el) {
2156        $(el).removeClass('is-active');
2157    };
2158
2159}(jQuery));
2160(function($) {
2161	'use strict';
2162
2163    var MK = window.MK || {};
2164	MK.utils = window.MK.utils || {};
2165
2166    /**
2167     * Gets user browser and its version
2168     * @return {Object} => {name, version}
2169     */
2170	MK.utils.browser = (function() {
2171        var dataBrowser = [
2172            {string: navigator.userAgent, subString: "Edge", identity: "Edge"},
2173            {string: navigator.userAgent, subString: "Chrome", identity: "Chrome"},
2174            {string: navigator.userAgent, subString: "MSIE", identity: "IE"},
2175            {string: navigator.userAgent, subString: "Trident", identity: "IE"},
2176            {string: navigator.userAgent, subString: "Firefox", identity: "Firefox"},
2177            {string: navigator.userAgent, subString: "Safari", identity: "Safari"},
2178            {string: navigator.userAgent, subString: "Opera", identity: "Opera"}
2179        ];
2180
2181		var versionSearchString = null;
2182        var searchString = function (data) {
2183            for (var i = 0; i < data.length; i++) {
2184                var dataString = data[i].string;
2185                versionSearchString = data[i].subString;
2186
2187                if (dataString.indexOf(data[i].subString) !== -1) {
2188                    return data[i].identity;
2189                }
2190            }
2191        };
2192        
2193        var searchVersion = function (dataString) {
2194            var index = dataString.indexOf(versionSearchString);
2195            if (index === -1) {
2196                return;
2197            }
2198
2199            var rv = dataString.indexOf("rv:");
2200            if (versionSearchString === "Trident" && rv !== -1) {
2201                return parseFloat(dataString.substring(rv + 3));
2202            } else {
2203                return parseFloat(dataString.substring(index + versionSearchString.length + 1));
2204            }
2205        };
2206
2207        var name = searchString(dataBrowser) || "Other";
2208        var version = searchVersion(navigator.userAgent) || searchVersion(navigator.appVersion) || "Unknown";
2209
2210        // Expose for css
2211        $('html').addClass(name).addClass(name + version);
2212
2213
2214        return {
2215        	name : name,
2216        	version : version
2217        };
2218        
2219	})();
2220
2221    /**
2222     * Gets user operating system
2223     * @return {String}
2224     */
2225	MK.utils.OS = (function() {
2226		if (navigator.appVersion.indexOf("Win")!=-1) return "Windows";
2227		if (navigator.appVersion.indexOf("Mac")!=-1) return "OSX";
2228		if (navigator.appVersion.indexOf("X11")!=-1) return "UNIX";
2229		if (navigator.appVersion.indexOf("Linux")!=-1) return "Linux";
2230	})();
2231	
2232    /**
2233     * Check if mobile device.
2234     * @return {Boolean}
2235     */
2236	MK.utils.isMobile = function() {
2237        // Problems with bigger tablets as users raport differences with behaviour. Switch to navigator sniffing
2238		// return ('ontouchstart' in document.documentElement) && matchMedia( '(max-width: 1024px)' ).matches;
2239     
2240        // http://www.abeautifulsite.net/detecting-mobile-devices-with-javascript/
2241        // if it still brings problem try to move to more sophisticated solution like
2242        // apachemobilefilter.org
2243        // detectright.com
2244        // web.wurfl.io
2245        // 
2246        // Seems as best solution here:
2247        // hgoebl.github.io/mobile-detect.js
2248
2249        function android() {
2250            return navigator.userAgent.match(/Android/i);
2251        }
2252
2253        function blackBerry() {
2254            return navigator.userAgent.match(/BlackBerry/i);
2255        }
2256
2257        function iOS() {
2258            return navigator.userAgent.match(/iPhone|iPad|iPod/i);
2259        }
2260
2261        function opera() {
2262            return navigator.userAgent.match(/Opera Mini/i);
2263        }
2264
2265        function windows() {
2266            return navigator.userAgent.match(/IEMobile/i);
2267        }
2268
2269        return (android() || blackBerry() || iOS() || opera() || windows() || matchMedia( '(max-width: 1024px)' ).matches); 
2270            
2271	};
2272
2273    /**
2274     * Check if menu is switched to responsive state based on user width settings
2275     * @return {Boolean} 
2276     */
2277    MK.utils.isResponsiveMenuState = function() {
2278        return window.matchMedia( '(max-width: '+ mk_responsive_nav_width +'px)').matches;
2279    };
2280
2281
2282
2283    MK.utils.getUrlParameter = function getUrlParameter(sParam) {
2284        var sPageURL = decodeURIComponent(window.location.search.substring(1)),
2285            sURLVariables = sPageURL.split('&'),
2286            sParameterName,
2287            i;
2288
2289        for (i = 0; i < sURLVariables.length; i++) {
2290            sParameterName = sURLVariables[i].split('=');
2291
2292            if (sParameterName[0] === sParam) {
2293                return sParameterName[1] === undefined ? true : sParameterName[1];
2294            }
2295        }
2296    };
2297
2298
2299    MK.utils.isSmoothScroll = (function() {
2300        var isUserChoice = (mk_smooth_scroll === 'true');
2301
2302        // We notify our app about smooth scroll option when user choose it from admin panel.
2303        return isUserChoice;
2304    }());
2305
2306    MK.utils.showBackgroundVideo = (function() {
2307        var isUserChoice = (mk_show_background_video === 'true');
2308
2309        return isUserChoice;
2310    }());
2311
2312}(jQuery));
2313
2314(function($) {
2315	'use strict';
2316
2317    var MK = window.MK || {};
2318	MK.utils = window.MK.utils || {};
2319
2320	/**
2321	 * Basic implementation of pub / sub pattern to avoid tight coupling with direct module communication
2322	 * @type {Object}
2323	 */
2324	MK.utils.eventManager = {};
2325
2326	/**
2327	 * Subscribe to custom event and run callbacks
2328	 * @param  {String}
2329	 * @param  {Function}
2330	 *
2331	 * @usage MK.utils.eventManager.subscribe('event', function(e, params) {} )
2332	 */
2333	MK.utils.eventManager.subscribe = function(evt, func) {
2334		$(this).on(evt, func);
2335	};
2336
2337	/**
2338	 * Unsubscribe from custom event
2339	 * @param  {String}
2340	 * @param  {Function}
2341	 */
2342	MK.utils.eventManager.unsubscribe = function(evt, func) {
2343		$(this).off(evt, func);
2344	};
2345
2346	/**
2347	 * Publish custom event to notify appliaction about state change
2348	 * @param  {String}
2349	 * 
2350	 * @usage MK.utils.eventManager.publish('event', {
2351	 *        	param: val
2352	 *        })
2353	 */
2354	MK.utils.eventManager.publish = function(evt, params) {
2355		$(this).trigger(evt, [params]);
2356	};
2357
2358}(jQuery));
2359(function($) {
2360	'use strict';
2361
2362    var MK = window.MK || {};
2363	MK.utils = window.MK.utils || {};
2364
2365	/**
2366	 * Control browser fullscreen mode
2367	 * @type {Object}
2368	 */
2369	MK.utils.fullscreen = {};
2370
2371	// TODO: move to namespace
2372	MK.utils.launchIntoFullscreen = function ( element ) {
2373	    if(element.requestFullscreen) {
2374	     	element.requestFullscreen();
2375	  	} else if(element.mozRequestFullScreen) {
2376	    	element.mozRequestFullScreen();
2377	  	} else if(element.webkitRequestFullscreen) {
2378	    	element.webkitRequestFullscreen();
2379	  	} else if(element.msRequestFullscreen) {
2380	    	element.msRequestFullscreen();
2381	  	}
2382	};
2383
2384	MK.utils.exitFullscreen = function () {
2385	  	if(document.exitFullscreen) {
2386	    	document.exitFullscreen();
2387	  	} else if(document.mozCancelFullScreen) {
2388	    	document.mozCancelFullScreen();
2389	  	} else if(document.webkitExitFullscreen) {
2390	    	document.webkitExitFullscreen();
2391	  	}
2392	};
2393
2394}(jQuery));
2395(function($) {
2396	'use strict';
2397
2398    var MK = window.MK || {};
2399	MK.utils = window.MK.utils || {};
2400
2401	MK.utils.misc = {};
2402	// TODO: move to namespace
2403
2404	/**
2405	 * Get all top offsets from jQuery collection
2406	 * 
2407	 * @param  {$Objects}
2408	 * @return {Aray}
2409	 */
2410	MK.utils.offsets = function( $els ) {
2411		return $.map( $els, function( el ) {
2412			return $( el ).offset().top;
2413		});
2414	};
2415
2416	/**
2417	 * Retrive from array of numbers first number that is higher than given parameter
2418	 * 
2419	 * @param  {Number}
2420	 * @param  {Array}
2421	 * @return {Number}
2422	 */
2423	MK.utils.nextHigherVal = function( val, arr ) {
2424		var i = 0,
2425			higher = null;
2426
2427		var check = function() {
2428			if( val > arr[ i ]) {
2429				i += 1;
2430				check();
2431			} else {
2432				higher = arr[ i ];
2433			}
2434		};
2435		check();
2436
2437		return higher;
2438	};
2439
2440
2441    MK.utils.throttle = function( delay, fn ) {
2442        var last;
2443        var deferTimer;
2444
2445        return function() {
2446            var context = this;
2447            var args = arguments;
2448            var now = +new Date;
2449            if( last && now < last + delay ) {
2450            	clearTimeout( deferTimer );
2451            	deferTimer = setTimeout( function() { 
2452            		last = now; fn.apply( context, args ); 
2453            	}, delay );
2454          	} else {
2455            	last = now;
2456            	fn.apply( context, args );
2457          	}
2458        };
2459    };
2460
2461    MK.utils.isElementInViewport = function( el ) {
2462        var elemTop = el.getBoundingClientRect().top;
2463	    var isVisible = (elemTop < window.innerHeight);
2464	    return isVisible;
2465    };
2466
2467})(jQuery); 
2468(function($) {
2469	'use strict';
2470
2471    var MK = window.MK || {};
2472	MK.utils = window.MK.utils || {};
2473
2474	/**
2475	 * Scrolls page to static pixel offset
2476	 * @param  {Number}
2477	 */
2478	MK.utils.scrollTo = function( offset ) {
2479		$('html, body').stop().animate({
2480			scrollTop: offset
2481			}, {
2482	  		duration: 1200,
2483	  		easing: "easeInOutExpo"
2484		});
2485	};
2486
2487	/**
2488	 * Scrolls to element passed in as object or DOM reference
2489	 * @param  {String|Object}
2490	 */
2491	MK.utils.scrollToAnchor = function( hash ) {
2492		// Escape meta-chars from hash name only.
2493		hash = hash.substring(1).replace(/[!"#$%&'()*+,./:;<=>?@[\]^`{|}~]/g, "\\$&");
2494		hash = "#" + hash;
2495		var $target = $( hash );
2496		// console.log( hash );
2497
2498		if( ! $target.length ) return;
2499
2500		var offset  = $target.offset().top;
2501		offset = offset - MK.val.offsetHeaderHeight( offset );
2502
2503		if( hash === '#top-of-page' ) window.history.replaceState( undefined, undefined, ' ' );
2504		else window.history.replaceState( undefined, undefined, hash );
2505
2506		MK.utils.scrollTo( offset );
2507	};
2508
2509	/**
2510	 * Controls native scroll behaviour
2511	 * @return {Object} => {disable, enable}
2512	 */
2513	MK.utils.scroll = (function() {
2514        // 37 - left arror, 38 - up arrow, 39 right arrow, 40 down arrow
2515	    var keys = [38, 40];
2516
2517        function preventDefault(e) {
2518          e = e || window.event;
2519          e.preventDefault();
2520          e.returnValue = false;  
2521        }
2522
2523        function wheel(e) {
2524          preventDefault(e);
2525        }
2526
2527        function keydown(e) {
2528            for (var i = keys.length; i--;) {
2529                if (e.keyCode === keys[i]) {
2530                    preventDefault(e);
2531                    return;
2532                }
2533            }
2534        }
2535
2536        function disableScroll() {
2537            if (window.addEventListener) {
2538                window.addEventListener('DOMMouseScroll', wheel, false);
2539            }
2540          	window.onmousewheel = document.onmousewheel = wheel;
2541          	document.onkeydown = keydown;
2542        }
2543
2544        function enableScroll() {            
2545          	if (window.removeEventListener) {
2546                window.removeEventListener('DOMMouseScroll', wheel, false);
2547            }
2548            window.onmousewheel = document.onmousewheel = document.onkeydown = null; 
2549        }	
2550
2551        return {
2552        	disable : disableScroll,
2553        	enable  : enableScroll
2554        };
2555
2556	})();
2557
2558	/**
2559	 * Checks if passed link element has anchor inside current page. Returns string like '#anchor' if so or false
2560	 * @param  {String|Object}
2561	 * @return {String|Boolean}
2562	 */
2563	MK.utils.detectAnchor = function( el ) {
2564		var $this = $( el ),
2565			loc = window.location,
2566			currentPage = loc.origin + loc.pathname,
2567			href = $this.attr( 'href' ),
2568			linkSplit = (href) ? href.split( '#' ) : '',
2569			hrefPage  = linkSplit[0] ? linkSplit[0] : '', 
2570			hrefHash  = linkSplit[1] ? linkSplit[1] : '';
2571
2572		if( typeof hrefHash !== 'undefined' && hrefHash !== '' ) {
2573			return '#' + hrefHash;
2574		} else {
2575			return false;
2576		}
2577	};
2578
2579	/**
2580	 * This should be invoked only on page load. 
2581	 * Scrolls to anchor from  address bar
2582	 */
2583	MK.utils.scrollToURLHash = function() {
2584		var loc = window.location,
2585			hash = loc.hash;
2586
2587		if ( hash.length && hash.substring(1).length ) {
2588			// !loading is added early after DOM is ready to prevent native jump to anchor
2589			hash = hash.replace( '!loading', '' );
2590
2591			// Wait for one second before animating 
2592			// Most of UI animations should be done by then and async operations complited
2593			setTimeout( function() {
2594				MK.utils.scrollToAnchor( hash );
2595			}, 1000 ); 
2596
2597			// Right after reset back address bar
2598			setTimeout( function() {
2599				window.history.replaceState(undefined, undefined, hash);
2600			}, 1001);
2601		}
2602	};
2603
2604	/**
2605	 * Scroll Spy implementation. Spy dynamic offsets of elements or static pixel offset
2606	 * @param  {Number|Element}
2607	 * @param  {Object} => callback object {before, active, after}
2608	 */
2609	MK.utils.scrollSpy = function( toSpy, config ) {
2610		var $window   = $( window ),
2611	        container = document.getElementById( 'mk-theme-container' ),
2612	        isObj     = ( typeof toSpy === 'object' ),
2613	        offset    = (isObj) ? MK.val.dynamicOffset( toSpy, config.position, config.threshold ) : function() { return toSpy; },
2614	        height    = (isObj) ? MK.val.dynamicHeight( toSpy ) : function() { return 0; },
2615	        cacheVals = {},
2616	        _p 		  = 'before'; // current position
2617
2618		var checkPosition = function() {
2619	    	var s = MK.val.scroll(), 
2620	    		o = offset(),
2621	    		h = height();
2622
2623	        if( s < o && _p !== 'before' ) {
2624	        	// console.log( toSpy, 'before' );
2625	        	if( config.before ) config.before();
2626	        	_p = 'before';
2627	        } 
2628	        else if( s >= o && s <= o + h && _p !== 'active' ) {
2629	        	// console.log( toSpy, 'active' );
2630	        	if( config.active ) config.active( o );
2631	        	_p = 'active';
2632	        }
2633	        else if( s > o + h && _p !== 'after' ) {
2634	        	// console.log( toSpy, 'after' );
2635	        	if( config.after) config.after( o + h );
2636	        	_p = 'after';
2637	        }
2638		};
2639
2640		var rAF = function() {
2641			window.requestAnimationFrame( checkPosition );
2642		};
2643
2644		var exportVals = function() {
2645			return cacheVals;    
2646		};
2647
2648		var updateCache = function() {
2649	    	var o = offset(),
2650	    		h = height();
2651	    		
2652	        cacheVals = {
2653	        	before : o - $window.height(),
2654	        	active : o,
2655	        	after : o + h
2656	        };
2657		};
2658
2659		if( config.cache ) {
2660			config.cache( exportVals );
2661		}
2662
2663	    checkPosition();
2664	    $window.on( 'load', checkPosition );
2665	    $window.on( 'resize', checkPosition );
2666	    $window.on( 'mouseup', checkPosition );
2667   		window.addResizeListener( container, checkPosition );
2668
2669	    $window.on( 'scroll', rAF ); 
2670
2671   		updateCache();
2672	    $window.on( 'load', updateCache );
2673	    $window.on( 'resize', updateCache );
2674   		window.addResizeListener( container, updateCache );
2675	};
2676
2677}(jQuery));
2678(function($) {
2679    'use strict';
2680
2681    // Create delagation event handler to behave as "live" listener. We may provide new elements with ajax etc later
2682    // Just add js-taphover class whatever element you'd like to immidietely bring hover on touch devices
2683    $("body").on("click touchend", '.js-taphover', function (e) {
2684        var $link = $(e.currentTarget); // grab target
2685        var $target = $(e.target);
2686
2687        // Rather than ":hover" state we operate on ".hover" class which gives us more control and chance to emulate it on click
2688        // yet it is easy to reason about in our CSS
2689        if ($link.hasClass('hover')) {
2690            return true;
2691        } else if ( MK.utils.isMobile() ) {
2692            if ( ($target.hasClass('hover-icon') || $target.closest('.hover-icon').length) && !$target.closest('.js-taphover').hasClass('hover') ) {
2693                e.preventDefault();
2694            }
2695            $link.addClass('hover');
2696            $('.js-taphover').not(e.currentTarget).removeClass('hover'); // remove it from previous element
2697            e.stopPropagation(); // do not leak to document root if expected element was touched
2698        }
2699    });
2700
2701    // Whenever click leaks to the root romve all hover classes
2702    $(document).on("click", function(e) {
2703        $('.js-taphover').removeClass('hover');
2704    });
2705
2706}(jQuery));
2707// (function() {
2708//     'use strict';
2709
2710//     // Make sure the video behaves like background-size: cover
2711//     window.videoCover = function( holderSelector, videoSelector ) {
2712//         var videos = document.querySelectorAll( videoSelector ),
2713//             holder = document.querySelectorAll( holderSelector )[0];
2714
2715//         [].forEach.call(videos, function(video) {
2716
2717//             var videoAspectRatio;
2718
2719//             resizeBackground(); 
2720
2721//             video.onloadedmetadata = function() {
2722//                 // get images aspect ratio
2723//                 videoAspectRatio = this.height / this.width;
2724//                 // attach resize event and fire it once
2725//                 window.onresize = resizeBackground;
2726//                 resizeBackground();
2727//             };
2728
2729//             function resizeBackground() {
2730//                 // get window size and aspect ratio
2731//                 var holderWidth = holder.innerWidth,
2732//                     holderHeight = holder.innerHeight,
2733//                     holderAspectRatio = holderHeight / holderWidth;
2734
2735//                 //compare holder ratio to image ratio so you know which way the image should fill
2736//                 if ( holderAspectRatio < videoAspectRatio ) {
2737//                     // we are fill width
2738//                     video.style.width = holderWidth + "px";
2739//                     // and applying the correct aspect to the height now
2740//                     video.style.height = (holderWidth * videoAspectRatio) + "px"; // this can be margin if your element is not positioned relatively, absolutely or fixed
2741//                     // make sure image is always centered
2742//                     video.style.left = "0px";
2743//                     video.style.top = (holderHeight - (holderWidth * videoAspectRatio)) / 2 + "px";
2744//                 } else { // same thing as above but filling height instead
2745//                     video.style.height = holderHeight + "px";
2746//                     video.style.width = (holderHeight / videoAspectRatio) + "px";
2747//                     video.style.left = (holderWidth - (holderHeight / videoAspectRatio)) / 2 + "px";
2748//                     video.style.top = "0px";
2749//                 }
2750//             }
2751
2752//         });
2753//     };
2754
2755// }());
2756// 
2757// 
2758// 
2759// TODO it is temp only. make it as a plugin
2760
2761(function($) {
2762    'use strict';
2763
2764    var $videoHolder = $('.mk-center-video'),
2765        $wrapper = $videoHolder.parent(),
2766        baseAspectRatio = 56.25;
2767
2768    var wrapperHeight,
2769        wrapperWidth,
2770        wrapperAspectRatio;
2771
2772    function calc() {
2773        wrapperHeight = $wrapper.height();
2774        wrapperWidth = $wrapper.width();
2775        wrapperAspectRatio = (wrapperHeight / wrapperWidth) * 100;
2776    } 
2777
2778    function apply() {        
2779        var width = (wrapperAspectRatio / baseAspectRatio) * 100,
2780            widthOverflow = (width - 100);
2781
2782        $videoHolder.css({
2783            'padding-top': wrapperAspectRatio + '%',
2784            'width': width + '%',
2785            'left': -(widthOverflow / 2) + '%'
2786        }); 
2787    }
2788
2789    function reset() {
2790        $videoHolder.css({
2791            'padding-top': baseAspectRatio + '%',
2792            'width': 100 + '%',
2793            'left': 0
2794        });
2795    }
2796
2797    function setCover() {
2798        reset();
2799        calc();
2800        if(wrapperAspectRatio > baseAspectRatio) apply();
2801    }
2802
2803    $(window).on('load', setCover);
2804    $(window).on('resize', setCover);
2805
2806
2807}(jQuery));
2808(function($) {
2809	'use strict';
2810
2811	var MK = window.MK || {};
2812
2813	/**
2814	* 	MK.val is collection of Lambdas responsible for returning up to date values of method type like scrollY or el offset.
2815	* 	The Lambda is responsible for keeping track of value of a particular property, usually takes as argument an object
2816	* 	(or DOM reference) and internally creates and updates data that is returned as primitive value - through variable reference.
2817	*
2818	*  Benefits of this approach:
2819	*  - reduced DOM reads
2820	*  - auto-updating values without need for additional logic where methods are called
2821	*  - updating values when needed to be updated not read
2822	*
2823	*  Downsides:
2824	*  - Memory overhead with closures and keeping state in memory ( still beter than read state from DOM, but use wisely -
2825	*    do not use it when you really need static value on runtime )
2826	*/
2827	MK.val = {};
2828
2829	/**
2830	* Current window offsetY position
2831	*
2832	* @uses   MK.val.scroll()
2833	* @return {number}
2834	*/
2835	MK.val.scroll = (function() {
2836		var offset = 0,
2837		$window = $(window),
2838		hasPageYOffset = (window.pageYOffset !== undefined),
2839		body = (document.documentElement || document.body.parentNode || document.body); // cross browser handling
2840
2841		var update = function() {
2842			offset = hasPageYOffset ? window.pageYOffset : body.scrollTop;
2843		};
2844
2845		var rAF = function() {
2846			window.requestAnimationFrame(update);
2847		};
2848
2849		update();
2850		$window.on('load', update);
2851		$window.on('resize', update);
2852		$window.on('scroll', rAF);
2853
2854		return function() {
2855			return offset;
2856		};
2857	})();
2858
2859
2860	/**
2861	* Changes number of percent to pixels based on viewport height
2862	*
2863	* @uses   MK.val.viewportPercentHeight({percent val})
2864	* @param  {number}
2865	* @return {number}
2866	*/
2867	MK.val.viewportPercentHeight = function(percent) {
2868		return $(window).height() * (percent / 100);
2869	};
2870
2871
2872	/**
2873	* Wordpress adminbar height based on wp media queries
2874	* @return {Number}
2875	*/
2876	MK.val.adminbarHeight = function() {
2877		if (php.hasAdminbar) {
2878			// apply WP native media-query and sizes
2879			return (window.matchMedia('( max-width: 782px )').matches) ? 46 : 32;
2880		} else {
2881			return 0;
2882		}
2883	};
2884
2885
2886	/**
2887	* Offset when header becomes sticky. Evaluates viewport % and header height to pixels for according options
2888	* @return {Number}
2889	*/
2890	MK.val.stickyOffset = (function() {
2891		var $header = $('.mk-header').not('.js-header-shortcode').first();
2892
2893		// We need to have returning function even when header is disabled
2894		if (!$header.length) {
2895			return function() {
2896				return 0;
2897			};
2898		}
2899
2900
2901
2902		var $toolbar = $header.find('.mk-header-toolbar'),
2903		config = $header.data(),
2904		hasToolbar = $toolbar.length,
2905		toolbarHeight = (hasToolbar) ? $toolbar.height() : 0,
2906		isVertical = (config.headerStyle === 4),
2907		headerHeight = (isVertical) ? 0 : config.height;
2908
2909		var type = ((typeof config.stickyOffset === 'number') ? 'number' : false) ||
2910		((config.stickyOffset === 'header') ? 'header' : false) ||
2911		'percent';
2912
2913		var stickyOffset = 0;
2914		var setOffset = function() {
2915
2916			//we calculate toolbar height for When the device is changed Size
2917			//Toolbar height in responsive state is 0
2918			toolbarHeight = (hasToolbar) ? $toolbar.height() : 0;
2919
2920			if (MK.utils.isResponsiveMenuState()) {
2921				headerHeight = config.responsiveHeight;
2922
2923				if (hasToolbar) {
2924					if ($toolbar.is(':hidden')) {
2925						toolbarHeight = 0;
2926					}
2927				}
2928			}
2929
2930			if (type === 'number') {
2931				stickyOffset = config.stickyOffset;
2932			} else if (type === 'header') {
2933
2934				stickyOffset = headerHeight + toolbarHeight + MK.val.adminbarHeight(); // add all header components here, make them 0 if needed
2935
2936			} else if (type === 'percent') {
2937				stickyOffset = MK.val.viewportPercentHeight(parseInt(config.stickyOffset));
2938			}
2939		};
2940
2941		setOffset();
2942		$(window).on('resize', setOffset);
2943
2944		return function() {
2945			return stickyOffset;
2946		};
2947	}());
2948
2949
2950
2951	/**
2952	* Gets header height on particular offsetY position. Use to determine logic for fullHeight, smooth scroll etc.
2953	* Takes one parameter which is offset position we're interested in.
2954	*
2955	* @uses   MK.val.offsetHeaderHeight({offset val})
2956	* @param  {number}
2957	* @return {number}
2958	*/
2959	MK.val.offsetHeaderHeight = (function() { // Closure avoids multiple DOM reads. We need to fetch header config only once.
2960		var $header = $('.mk-header').not('.js-header-shortcode').first();
2961
2962		// We need to have returning function even when header is disabled
2963		if (!$header.length) {
2964			return function() {
2965				return 0;
2966			};
2967		}
2968
2969		var $toolbar = $header.find('.mk-header-toolbar'),
2970		config = $header.data(),
2971		stickyHeight = config.stickyHeight,
2972		desktopHeight = config.height,
2973		mobileHeight = config.responsiveHeight,
2974		isTransparent = $header.hasClass('transparent-header'),
2975		isSticky = config.stickyStyle.length,
2976		isStickyLazy = config.stickyStyle === 'lazy',
2977		isVertical = config.headerStyle === 4,
2978		hasToolbar = $toolbar.length,
2979		toolbarHeight = hasToolbar ? $toolbar.height() : 0,
2980		bufor = 5;
2981
2982		/**
2983		 * The sticky section of header style 2 has fixed height.
2984		 * The stickey height option does not affect this header style.
2985		 */
2986		if ( config.headerStyle === 2 ) {
2987			stickyHeight = $header.find( '.mk-header-nav-container' ).outerHeight();
2988		}
2989
2990		// if header has border bottom we can calculate that (for responsive state)
2991		var $innerHeader = $header.find('.mk-header-inner');
2992		var hasInnerHeader = $innerHeader.length;
2993
2994		var headerHeight = function(offset) {
2995
2996			toolbarHeight = hasToolbar ? $toolbar.height() : 0
2997			var stickyOffset = MK.val.stickyOffset();
2998
2999
3000			if (MK.utils.isResponsiveMenuState()) { //  Header avaible only on top for mobile
3001
3002				if (hasToolbar && $toolbar.is(':hidden')) {
3003					toolbarHeight = 0;
3004				}
3005
3006				//in responsive state , .mk-header-holder position's changed to "relative"
3007				//and header's border affected to offset,so borders must be calculated
3008				var headerBorder = 0;
3009				headerBorder = parseInt($innerHeader.css('border-bottom-width'));
3010
3011				var totalHeight = mobileHeight + MK.val.adminbarHeight() + toolbarHeight + headerBorder;
3012
3013				if (offset <= totalHeight) return totalHeight;
3014				else return MK.val.adminbarHeight();
3015			} else {
3016				if (offset <= stickyOffset) {
3017					if (isVertical) {
3018						if (hasToolbar) {
3019							return toolbarHeight + MK.val.adminbarHeight();
3020						} else {
3021							return MK.val.adminbarHeight();
3022						}
3023					} else if (isTransparent) {
3024						return MK.val.adminbarHeight();
3025					} else {
3026						return desktopHeight + toolbarHeight + MK.val.adminbarHeight();
3027					} // For any other return regular desktop height
3028				} else if (offset > stickyOffset) {
3029					if (isVertical) {
3030						return MK.val.adminbarHeight();
3031					} else if (!isSticky) {
3032						return MK.val.adminbarHeight();
3033					} else if (isStickyLazy) {
3034						return MK.val.adminbarHeight();
3035					} else if (isSticky) {
3036						return stickyHeight + MK.val.adminbarHeight();
3037					}
3038				}
3039			}
3040			// default to 0 to prevent errors ( need to return number )
3041			// Anyway make sure all scenarios are covered in IFs
3042			return 0;
3043		};
3044
3045		return function(offset) {
3046			return headerHeight(offset - MK.val.adminbarHeight());
3047		};
3048	})();
3049
3050
3051	/**
3052	* Gets current offset of given element (passed as object or DOM reference) from top or bottom (default to top)
3053	* of screen  with possible threshold (default to 0)
3054	*
3055	* @uses   MK.val.dynamicOffset({obj reference}, {'top'|'bottom'}, {threshold val})
3056	* @param  {string|object}
3057	* @param  {string}
3058	* @param  {number}
3059	* @return {number}
3060	*/
3061	MK.val.dynamicOffset = function(el, position, threshold) {
3062		var $window = $(window),
3063		$el = $(el),
3064		pos = position || 'top',
3065		thr = threshold || 0,
3066		container = document.getElementById('mk-theme-container'),
3067		currentPos = 0;
3068
3069		var offset = 0,
3070		winH = 0,
3071		rect = 0,
3072		x = 0;
3073
3074		var update = function() {
3075			winH = $window.height();
3076			rect = $el[0].getBoundingClientRect();
3077			offset = (rect.top + MK.val.scroll());
3078			x = (pos === 'top') ? MK.val.offsetHeaderHeight(offset) : winH + (rect.height - thr);
3079			currentPos = offset - x - 1;
3080		};
3081
3082		update();
3083		$window.on('load', update);
3084		$window.on('resize', update);
3085		window.addResizeListener(container, update);
3086
3087		return function() {
3088			return currentPos;
3089		};
3090	};
3091
3092	/**
3093	* Gets current height of given element (passed as object or DOM reference)
3094	*
3095	* @uses   MK.val.dynamicHeight({obj reference})
3096	* @param  {string|object}
3097	* @return {number}
3098	*/
3099	MK.val.dynamicHeight = function(el) {
3100		var $window = $(window),
3101		$el = $(el),
3102		container = document.getElementById('mk-theme-container'),
3103		currentHeight = 0;
3104
3105		var update = function() {
3106			currentHeight = $el.outerHeight();
3107		};
3108
3109		update();
3110		$window.on('load', update);
3111		$window.on('resize', update);
3112		window.addResizeListener(container, update);
3113
3114		return function() {
3115			return currentHeight;
3116		};
3117	};
3118
3119})(jQuery);
3120
3121/*
3122 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
3123 *
3124 */
3125jQuery.easing["jswing"] = jQuery.easing["swing"];
3126jQuery.extend(jQuery.easing, {
3127        def: "easeOutQuad",
3128        swing: function (a, b, c, d, e) {
3129                return jQuery.easing[jQuery.easing.def](a, b, c, d, e)
3130        },
3131        easeInQuad: function (a, b, c, d, e) {
3132                return d * (b /= e) * b + c
3133        },
3134        easeOutQuad: function (a, b, c, d, e) {
3135                return -d * (b /= e) * (b - 2) + c
3136        },
3137        easeInOutQuad: function (a, b, c, d, e) {
3138                if ((b /= e / 2) < 1) return d / 2 * b * b + c;
3139                return -d / 2 * (--b * (b - 2) - 1) + c
3140        },
3141        easeInCubic: function (a, b, c, d, e) {
3142                return d * (b /= e) * b * b + c
3143        },
3144        easeOutCubic: function (a, b, c, d, e) {
3145                return d * ((b = b / e - 1) * b * b + 1) + c
3146        },
3147        easeInOutCubic: function (a, b, c, d, e) {
3148                if ((b /= e / 2) < 1) return d / 2 * b * b * b + c;
3149                return d / 2 * ((b -= 2) * b * b + 2) + c
3150        },
3151        easeInQuart: function (a, b, c, d, e) {
3152                return d * (b /= e) * b * b * b + c
3153        },
3154        easeOutQuart: function (a, b, c, d, e) {
3155                return -d * ((b = b / e - 1) * b * b * b - 1) + c
3156        },
3157        easeInOutQuart: function (a, b, c, d, e) {
3158                if ((b /= e / 2) < 1) return d / 2 * b * b * b * b + c;
3159                return -d / 2 * ((b -= 2) * b * b * b - 2) + c
3160        },
3161        easeInQuint: function (a, b, c, d, e) {
3162                return d * (b /= e) * b * b * b * b + c
3163        },
3164        easeOutQuint: function (a, b, c, d, e) {
3165                return d * ((b = b / e - 1) * b * b * b * b + 1) + c
3166        },
3167        easeInOutQuint: function (a, b, c, d, e) {
3168                if ((b /= e / 2) < 1) return d / 2 * b * b * b * b * b + c;
3169                return d / 2 * ((b -= 2) * b * b * b * b + 2) + c
3170        },
3171        easeInSine: function (a, b, c, d, e) {
3172                return -d * Math.cos(b / e * (Math.PI / 2)) + d + c
3173        },
3174        easeOutSine: function (a, b, c, d, e) {
3175                return d * Math.sin(b / e * (Math.PI / 2)) + c
3176        },
3177        easeInOutSine: function (a, b, c, d, e) {
3178                return -d / 2 * (Math.cos(Math.PI * b / e) - 1) + c
3179        },
3180        easeInExpo: function (a, b, c, d, e) {
3181                return b == 0 ? c : d * Math.pow(2, 10 * (b / e - 1)) + c
3182        },
3183        easeOutExpo: function (a, b, c, d, e) {
3184                return b == e ? c + d : d * (-Math.pow(2, -10 * b / e) + 1) + c
3185        },
3186        easeInOutExpo: function (a, b, c, d, e) {
3187                if (b == 0) return c;
3188                if (b == e) return c + d;
3189                if ((b /= e / 2) < 1) return d / 2 * Math.pow(2, 10 * (b - 1)) + c;
3190                return d / 2 * (-Math.pow(2, -10 * --b) + 2) + c
3191        },
3192        easeInCirc: function (a, b, c, d, e) {
3193                return -d * (Math.sqrt(1 - (b /= e) * b) - 1) + c
3194        },
3195        easeOutCirc: function (a, b, c, d, e) {
3196                return d * Math.sqrt(1 - (b = b / e - 1) * b) + c
3197        },
3198        easeInOutCirc: function (a, b, c, d, e) {
3199                if ((b /= e / 2) < 1) return -d / 2 * (Math.sqrt(1 - b * b) - 1) + c;
3200                return d / 2 * (Math.sqrt(1 - (b -= 2) * b) + 1) + c
3201        },
3202        easeInElastic: function (a, b, c, d, e) {
3203                var f = 1.70158;
3204                var g = 0;
3205                var h = d;
3206                if (b == 0) return c;
3207                if ((b /= e) == 1) return c + d;
3208                if (!g) g = e * .3;
3209                if (h < Math.abs(d)) {
3210                        h = d;
3211                        var f = g / 4
3212                } else var f = g / (2 * Math.PI) * Math.asin(d / h);
3213                return -(h * Math.pow(2, 10 * (b -= 1)) * Math.sin((b * e - f) * 2 * Math.PI / g)) + c
3214        },
3215        easeOutElastic: function (a, b, c, d, e) {
3216                var f = 1.70158;
3217                var g = 0;
3218                var h = d;
3219                if (b == 0) return c;
3220                if ((b /= e) == 1) return c + d;
3221                if (!g) g = e * .3;
3222                if (h < Math.abs(d)) {
3223                        h = d;
3224                        var f = g / 4
3225                } else var f = g / (2 * Math.PI) * Math.asin(d / h);
3226                return h * Math.pow(2, -10 * b) * Math.sin((b * e - f) * 2 * Math.PI / g) + d + c
3227        },
3228        easeInOutElastic: function (a, b, c, d, e) {
3229                var f = 1.70158;
3230                var g = 0;
3231                var h = d;
3232                if (b == 0) return c;
3233                if ((b /= e / 2) == 2) return c + d;
3234                if (!g) g = e * .3 * 1.5;
3235                if (h < Math.abs(d)) {
3236                        h = d;
3237                        var f = g / 4
3238                } else var f = g / (2 * Math.PI) * Math.asin(d / h);
3239                if (b < 1) return -.5 * h * Math.pow(2, 10 * (b -= 1)) * Math.sin((b * e - f) * 2 * Math.PI / g) + c;
3240                return h * Math.pow(2, -10 * (b -= 1)) * Math.sin((b * e - f) * 2 * Math.PI / g) * .5 + d + c
3241        },
3242        easeInBack: function (a, b, c, d, e, f) {
3243                if (f == undefined) f = 1.70158;
3244                return d * (b /= e) * b * ((f + 1) * b - f) + c
3245        },
3246        easeOutBack: function (a, b, c, d, e, f) {
3247                if (f == undefined) f = 1.70158;
3248                return d * ((b = b / e - 1) * b * ((f + 1) * b + f) + 1) + c
3249        },
3250        easeInOutBack: function (a, b, c, d, e, f) {
3251                if (f == undefined) f = 1.70158;
3252                if ((b /= e / 2) < 1) return d / 2 * b * b * (((f *= 1.525) + 1) * b - f) + c;
3253                return d / 2 * ((b -= 2) * b * (((f *= 1.525) + 1) * b + f) + 2) + c
3254        },
3255        easeInBounce: function (a, b, c, d, e) {
3256                return d - jQuery.easing.easeOutBounce(a, e - b, 0, d, e) + c
3257        },
3258        easeOutBounce: function (a, b, c, d, e) {
3259                if ((b /= e) < 1 / 2.75) {
3260                        return d * 7.5625 * b * b + c
3261                } else if (b < 2 / 2.75) {
3262                        return d * (7.5625 * (b -= 1.5 / 2.75) * b + .75) + c
3263                } else if (b < 2.5 / 2.75) {
3264                        return d * (7.5625 * (b -= 2.25 / 2.75) * b + .9375) + c
3265                } else {
3266                        return d * (7.5625 * (b -= 2.625 / 2.75) * b + .984375) + c
3267                }
3268        },
3269        easeInOutBounce: function (a, b, c, d, e) {
3270                if (b < e / 2) return jQuery.easing.easeInBounce(a, b * 2, 0, d, e) * .5 + c;
3271                return jQuery.easing.easeOutBounce(a, b * 2 - e, 0, d, e) * .5 + d * .5 + c
3272        }
3273});
3274// ==================================================
3275// fancyBox v3.5.7
3276//
3277// Licensed GPLv3 for open source use
3278// or fancyBox Commercial License for commercial use
3279//
3280// http://fancyapps.com/fancybox/
3281// Copyright 2019 fancyApps
3282//
3283// ==================================================
3284(function (window, document, $, undefined) {
3285	"use strict";
3286
3287	window.console = window.console || {
3288	  info: function (stuff) {}
3289	};
3290
3291	// If there's no jQuery, fancyBox can't work
3292	// =========================================
3293
3294	if (!$) {
3295	  return;
3296	}
3297
3298	// Check if fancyBox is already initialized
3299	// ========================================
3300
3301	if ($.fn.fancybox) {
3302	  console.info("fancyBox already initialized");
3303
3304	  return;
3305	}
3306
3307	// Private default settings
3308	// ========================
3309
3310	var defaults = {
3311	  // Close existing modals
vendor: 141,869 bytes, lines 3312-8848
3312	  // Set this to false if you do not need to stack multiple instances
3313	  closeExisting: false,
3314
3315	  // Enable infinite gallery navigation
3316	  loop: false,
3317
3318	  // Horizontal space between slides
3319	  gutter: 50,
3320
3321	  // Enable keyboard navigation
3322	  keyboard: true,
3323
3324	  // Should allow caption to overlap the content
3325	  preventCaptionOverlap: true,
3326
3327	  // Should display navigation arrows at the screen edges
3328	  arrows: true,
3329
3330	  // Should display counter at the top left corner
3331	  infobar: true,
3332
3333	  // Should display close button (using `btnTpl.smallBtn` template) over the content
3334	  // Can be true, false, "auto"
3335	  // If "auto" - will be automatically enabled for "html", "inline" or "ajax" items
3336	  smallBtn: "auto",
3337
3338	  // Should display toolbar (buttons at the top)
3339	  // Can be true, false, "auto"
3340	  // If "auto" - will be automatically hidden if "smallBtn" is enabled
3341	  toolbar: "auto",
3342
3343	  // What buttons should appear in the top right corner.
3344	  // Buttons will be created using templates from `btnTpl` option
3345	  // and they will be placed into toolbar (class="fancybox-toolbar"` element)
3346	  buttons: [
3347		"zoom",
3348		//"share",
3349		"slideShow",
3350		//"fullScreen",
3351		//"download",
3352		"thumbs",
3353		"close"
3354	  ],
3355
3356	  // Detect "idle" time in seconds
3357	  idleTime: 3,
3358
3359	  // Disable right-click and use simple image protection for images
3360	  protect: false,
3361
3362	  // Shortcut to make content "modal" - disable keyboard navigtion, hide buttons, etc
3363	  modal: false,
3364
3365	  image: {
3366		// Wait for images to load before displaying
3367		//   true  - wait for image to load and then display;
3368		//   false - display thumbnail and load the full-sized image over top,
3369		//           requires predefined image dimensions (`data-width` and `data-height` attributes)
3370		preload: false
3371	  },
3372
3373	  ajax: {
3374		// Object containing settings for ajax request
3375		settings: {
3376		  // This helps to indicate that request comes from the modal
3377		  // Feel free to change naming
3378		  data: {
3379			fancybox: true
3380		  }
3381		}
3382	  },
3383
3384	  iframe: {
3385		// Iframe template
3386		tpl: '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" allowfullscreen="allowfullscreen" allow="autoplay; fullscreen" src=""></iframe>',
3387
3388		// Preload iframe before displaying it
3389		// This allows to calculate iframe content width and height
3390		// (note: Due to "Same Origin Policy", you can't get cross domain data).
3391		preload: true,
3392
3393		// Custom CSS styling for iframe wrapping element
3394		// You can use this to set custom iframe dimensions
3395		css: {},
3396
3397		// Iframe tag attributes
3398		attr: {
3399		  scrolling: "auto"
3400		}
3401	  },
3402
3403	  // For HTML5 video only
3404	  video: {
3405		tpl: '<video class="fancybox-video" controls controlsList="nodownload" poster="{{poster}}">' +
3406		  '<source src="{{src}}" type="{{format}}" />' +
3407		  'Sorry, your browser doesn\'t support embedded videos, <a href="{{src}}">download</a> and watch with your favorite video player!' +
3408		  "</video>",
3409		format: "", // custom video format
3410		autoStart: true
3411	  },
3412
3413	  // Default content type if cannot be detected automatically
3414	  defaultType: "image",
3415
3416	  // Open/close animation type
3417	  // Possible values:
3418	  //   false            - disable
3419	  //   "zoom"           - zoom images from/to thumbnail
3420	  //   "fade"
3421	  //   "zoom-in-out"
3422	  //
3423	  animationEffect: "zoom",
3424
3425	  // Duration in ms for open/close animation
3426	  animationDuration: 366,
3427
3428	  // Should image change opacity while zooming
3429	  // If opacity is "auto", then opacity will be changed if image and thumbnail have different aspect ratios
3430	  zoomOpacity: "auto",
3431
3432	  // Transition effect between slides
3433	  //
3434	  // Possible values:
3435	  //   false            - disable
3436	  //   "fade'
3437	  //   "slide'
3438	  //   "circular'
3439	  //   "tube'
3440	  //   "zoom-in-out'
3441	  //   "rotate'
3442	  //
3443	  transitionEffect: "fade",
3444
3445	  // Duration in ms for transition animation
3446	  transitionDuration: 366,
3447
3448	  // Custom CSS class for slide element
3449	  slideClass: "",
3450
3451	  // Custom CSS class for layout
3452	  baseClass: "",
3453
3454	  // Base template for layout
3455	  baseTpl: '<div class="fancybox-container" role="dialog" tabindex="-1">' +
3456		'<div class="fancybox-bg"></div>' +
3457		'<div class="fancybox-inner">' +
3458		'<div class="fancybox-infobar"><span data-fancybox-index></span>&nbsp;/&nbsp;<span data-fancybox-count></span></div>' +
3459		'<div class="fancybox-toolbar">{{buttons}}</div>' +
3460		'<div class="fancybox-navigation">{{arrows}}</div>' +
3461		'<div class="fancybox-stage"></div>' +
3462		'<div class="fancybox-caption"><div class="fancybox-caption__body"></div></div>' +
3463		"</div>" +
3464		"</div>",
3465
3466	  // Loading indicator template
3467	  spinnerTpl: '<div class="fancybox-loading"></div>',
3468
3469	  // Error message template
3470	  errorTpl: '<div class="fancybox-error"><p>{{ERROR}}</p></div>',
3471
3472	  btnTpl: {
3473		download: '<a download data-fancybox-download class="fancybox-button fancybox-button--download" title="{{DOWNLOAD}}" href="javascript:;">' +
3474		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.62 17.09V19H5.38v-1.91zm-2.97-6.96L17 11.45l-5 4.87-5-4.87 1.36-1.32 2.68 2.64V5h1.92v7.77z"/></svg>' +
3475		  "</a>",
3476
3477		zoom: '<button data-fancybox-zoom class="fancybox-button fancybox-button--zoom" title="{{ZOOM}}">' +
3478		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18.7 17.3l-3-3a5.9 5.9 0 0 0-.6-7.6 5.9 5.9 0 0 0-8.4 0 5.9 5.9 0 0 0 0 8.4 5.9 5.9 0 0 0 7.7.7l3 3a1 1 0 0 0 1.3 0c.4-.5.4-1 0-1.5zM8.1 13.8a4 4 0 0 1 0-5.7 4 4 0 0 1 5.7 0 4 4 0 0 1 0 5.7 4 4 0 0 1-5.7 0z"/></svg>' +
3479		  "</button>",
3480
3481		close: '<button data-fancybox-close class="fancybox-button fancybox-button--close" title="{{CLOSE}}">' +
3482		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 10.6L6.6 5.2 5.2 6.6l5.4 5.4-5.4 5.4 1.4 1.4 5.4-5.4 5.4 5.4 1.4-1.4-5.4-5.4 5.4-5.4-1.4-1.4-5.4 5.4z"/></svg>' +
3483		  "</button>",
3484
3485		// Arrows
3486		arrowLeft: '<button data-fancybox-prev class="fancybox-button fancybox-button--arrow_left" title="{{PREV}}">' +
3487		  '<div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11.28 15.7l-1.34 1.37L5 12l4.94-5.07 1.34 1.38-2.68 2.72H19v1.94H8.6z"/></svg></div>' +
3488		  "</button>",
3489
3490		arrowRight: '<button data-fancybox-next class="fancybox-button fancybox-button--arrow_right" title="{{NEXT}}">' +
3491		  '<div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.4 12.97l-2.68 2.72 1.34 1.38L19 12l-4.94-5.07-1.34 1.38 2.68 2.72H5v1.94z"/></svg></div>' +
3492		  "</button>",
3493
3494		// This small close button will be appended to your html/inline/ajax content by default,
3495		// if "smallBtn" option is not set to false
3496		smallBtn: '<button type="button" data-fancybox-close class="fancybox-button fancybox-close-small" title="{{CLOSE}}">' +
3497		  '<svg xmlns="http://www.w3.org/2000/svg" version="1" viewBox="0 0 24 24"><path d="M13 12l5-5-1-1-5 5-5-5-1 1 5 5-5 5 1 1 5-5 5 5 1-1z"/></svg>' +
3498		  "</button>"
3499	  },
3500
3501	  // Container is injected into this element
3502	  parentEl: "body",
3503
3504	  // Hide browser vertical scrollbars; use at your own risk
3505	  hideScrollbar: true,
3506
3507	  // Focus handling
3508	  // ==============
3509
3510	  // Try to focus on the first focusable element after opening
3511	  autoFocus: true,
3512
3513	  // Put focus back to active element after closing
3514	  backFocus: true,
3515
3516	  // Do not let user to focus on element outside modal content
3517	  trapFocus: true,
3518
3519	  // Module specific options
3520	  // =======================
3521
3522	  fullScreen: {
3523		autoStart: false
3524	  },
3525
3526	  // Set `touch: false` to disable panning/swiping
3527	  touch: {
3528		vertical: true, // Allow to drag content vertically
3529		momentum: true // Continue movement after releasing mouse/touch when panning
3530	  },
3531
3532	  // Hash value when initializing manually,
3533	  // set `false` to disable hash change
3534	  hash: null,
3535
3536	  // Customize or add new media types
3537	  // Example:
3538	  /*
3539		media : {
3540		  youtube : {
3541			params : {
3542			  autoplay : 0
3543			}
3544		  }
3545		}
3546	  */
3547	  media: {},
3548
3549	  slideShow: {
3550		autoStart: false,
3551		speed: 3000
3552	  },
3553
3554	  thumbs: {
3555		autoStart: false, // Display thumbnails on opening
3556		hideOnClose: true, // Hide thumbnail grid when closing animation starts
3557		parentEl: ".fancybox-container", // Container is injected into this element
3558		axis: "y" // Vertical (y) or horizontal (x) scrolling
3559	  },
3560
3561	  // Use mousewheel to navigate gallery
3562	  // If 'auto' - enabled for images only
3563	  wheel: "auto",
3564
3565	  // Callbacks
3566	  //==========
3567
3568	  // See Documentation/API/Events for more information
3569	  // Example:
3570	  /*
3571		afterShow: function( instance, current ) {
3572		  console.info( 'Clicked element:' );
3573		  console.info( current.opts.$orig );
3574		}
3575	  */
3576
3577	  onInit: $.noop, // When instance has been initialized
3578
3579	  beforeLoad: $.noop, // Before the content of a slide is being loaded
3580	  afterLoad: $.noop, // When the content of a slide is done loading
3581
3582	  beforeShow: $.noop, // Before open animation starts
3583	  afterShow: $.noop, // When content is done loading and animating
3584
3585	  beforeClose: $.noop, // Before the instance attempts to close. Return false to cancel the close.
3586	  afterClose: $.noop, // After instance has been closed
3587
3588	  onActivate: $.noop, // When instance is brought to front
3589	  onDeactivate: $.noop, // When other instance has been activated
3590
3591	  // Interaction
3592	  // ===========
3593
3594	  // Use options below to customize taken action when user clicks or double clicks on the fancyBox area,
3595	  // each option can be string or method that returns value.
3596	  //
3597	  // Possible values:
3598	  //   "close"           - close instance
3599	  //   "next"            - move to next gallery item
3600	  //   "nextOrClose"     - move to next gallery item or close if gallery has only one item
3601	  //   "toggleControls"  - show/hide controls
3602	  //   "zoom"            - zoom image (if loaded)
3603	  //   false             - do nothing
3604
3605	  // Clicked on the content
3606	  clickContent: function (current, event) {
3607		return current.type === "image" ? "zoom" : false;
3608	  },
3609
3610	  // Clicked on the slide
3611	  clickSlide: "close",
3612
3613	  // Clicked on the background (backdrop) element;
3614	  // if you have not changed the layout, then most likely you need to use `clickSlide` option
3615	  clickOutside: "close",
3616
3617	  // Same as previous two, but for double click
3618	  dblclickContent: false,
3619	  dblclickSlide: false,
3620	  dblclickOutside: false,
3621
3622	  // Custom options when mobile device is detected
3623	  // =============================================
3624
3625	  mobile: {
3626		preventCaptionOverlap: false,
3627		idleTime: false,
3628		clickContent: function (current, event) {
3629		  return current.type === "image" ? "toggleControls" : false;
3630		},
3631		clickSlide: function (current, event) {
3632		  return current.type === "image" ? "toggleControls" : "close";
3633		},
3634		dblclickContent: function (current, event) {
3635		  return current.type === "image" ? "zoom" : false;
3636		},
3637		dblclickSlide: function (current, event) {
3638		  return current.type === "image" ? "zoom" : false;
3639		}
3640	  },
3641
3642	  // Internationalization
3643	  // ====================
3644
3645	  lang: "en",
3646	  i18n: {
3647		en: {
3648		  CLOSE: "Close",
3649		  NEXT: "Next",
3650		  PREV: "Previous",
3651		  ERROR: "The requested content cannot be loaded. <br/> Please try again later.",
3652		  PLAY_START: "Start slideshow",
3653		  PLAY_STOP: "Pause slideshow",
3654		  FULL_SCREEN: "Full screen",
3655		  THUMBS: "Thumbnails",
3656		  DOWNLOAD: "Download",
3657		  SHARE: "Share",
3658		  ZOOM: "Zoom"
3659		},
3660		de: {
3661		  CLOSE: "Schlie&szlig;en",
3662		  NEXT: "Weiter",
3663		  PREV: "Zur&uuml;ck",
3664		  ERROR: "Die angeforderten Daten konnten nicht geladen werden. <br/> Bitte versuchen Sie es sp&auml;ter nochmal.",
3665		  PLAY_START: "Diaschau starten",
3666		  PLAY_STOP: "Diaschau beenden",
3667		  FULL_SCREEN: "Vollbild",
3668		  THUMBS: "Vorschaubilder",
3669		  DOWNLOAD: "Herunterladen",
3670		  SHARE: "Teilen",
3671		  ZOOM: "Vergr&ouml;&szlig;ern"
3672		}
3673	  }
3674	};
3675
3676	// Few useful variables and methods
3677	// ================================
3678
3679	var $W = $(window);
3680	var $D = $(document);
3681
3682	var called = 0;
3683
3684	// Check if an object is a jQuery object and not a native JavaScript object
3685	// ========================================================================
3686	var isQuery = function (obj) {
3687	  return obj && obj.hasOwnProperty && obj instanceof $;
3688	};
3689
3690	// Handle multiple browsers for "requestAnimationFrame" and "cancelAnimationFrame"
3691	// ===============================================================================
3692	var requestAFrame = (function () {
3693	  return (
3694		window.requestAnimationFrame ||
3695		window.webkitRequestAnimationFrame ||
3696		window.mozRequestAnimationFrame ||
3697		window.oRequestAnimationFrame ||
3698		// if all else fails, use setTimeout
3699		function (callback) {
3700		  return window.setTimeout(callback, 1000 / 60);
3701		}
3702	  );
3703	})();
3704
3705	var cancelAFrame = (function () {
3706	  return (
3707		window.cancelAnimationFrame ||
3708		window.webkitCancelAnimationFrame ||
3709		window.mozCancelAnimationFrame ||
3710		window.oCancelAnimationFrame ||
3711		function (id) {
3712		  window.clearTimeout(id);
3713		}
3714	  );
3715	})();
3716
3717	// Detect the supported transition-end event property name
3718	// =======================================================
3719	var transitionEnd = (function () {
3720	  var el = document.createElement("fakeelement"),
3721		t;
3722
3723	  var transitions = {
3724		transition: "transitionend",
3725		OTransition: "oTransitionEnd",
3726		MozTransition: "transitionend",
3727		WebkitTransition: "webkitTransitionEnd"
3728	  };
3729
3730	  for (t in transitions) {
3731		if (el.style[t] !== undefined) {
3732		  return transitions[t];
3733		}
3734	  }
3735
3736	  return "transitionend";
3737	})();
3738
3739	// Force redraw on an element.
3740	// This helps in cases where the browser doesn't redraw an updated element properly
3741	// ================================================================================
3742	var forceRedraw = function ($el) {
3743	  return $el && $el.length && $el[0].offsetHeight;
3744	};
3745
3746	// Exclude array (`buttons`) options from deep merging
3747	// ===================================================
3748	var mergeOpts = function (opts1, opts2) {
3749	  var rez = $.extend(true, {}, opts1, opts2);
3750
3751	  $.each(opts2, function (key, value) {
3752		if ($.isArray(value)) {
3753		  rez[key] = value;
3754		}
3755	  });
3756
3757	  return rez;
3758	};
3759
3760	// How much of an element is visible in viewport
3761	// =============================================
3762
3763	var inViewport = function (elem) {
3764	  var elemCenter, rez;
3765
3766	  if (!elem || elem.ownerDocument !== document) {
3767		return false;
3768	  }
3769
3770	  $(".fancybox-container").css("pointer-events", "none");
3771
3772	  elemCenter = {
3773		x: elem.getBoundingClientRect().left + elem.offsetWidth / 2,
3774		y: elem.getBoundingClientRect().top + elem.offsetHeight / 2
3775	  };
3776
3777	  rez = document.elementFromPoint(elemCenter.x, elemCenter.y) === elem;
3778
3779	  $(".fancybox-container").css("pointer-events", "");
3780
3781	  return rez;
3782	};
3783
3784	// Class definition
3785	// ================
3786
3787	var FancyBox = function (content, opts, index) {
3788	  var self = this;
3789
3790	  self.opts = mergeOpts({
3791		index: index
3792	  }, $.fancybox.defaults);
3793
3794	  if ($.isPlainObject(opts)) {
3795		self.opts = mergeOpts(self.opts, opts);
3796	  }
3797
3798	  if ($.fancybox.isMobile) {
3799		self.opts = mergeOpts(self.opts, self.opts.mobile);
3800	  }
3801
3802	  self.id = self.opts.id || ++called;
3803
3804	  self.currIndex = parseInt(self.opts.index, 10) || 0;
3805	  self.prevIndex = null;
3806
3807	  self.prevPos = null;
3808	  self.currPos = 0;
3809
3810	  self.firstRun = true;
3811
3812	  // All group items
3813	  self.group = [];
3814
3815	  // Existing slides (for current, next and previous gallery items)
3816	  self.slides = {};
3817
3818	  // Create group elements
3819	  self.addContent(content);
3820
3821	  if (!self.group.length) {
3822		return;
3823	  }
3824
3825	  self.init();
3826	};
3827
3828	$.extend(FancyBox.prototype, {
3829	  // Create DOM structure
3830	  // ====================
3831
3832	  init: function () {
3833		var self = this,
3834		  firstItem = self.group[self.currIndex],
3835		  firstItemOpts = firstItem.opts,
3836		  $container,
3837		  buttonStr;
3838
3839		if (firstItemOpts.closeExisting) {
3840		  $.fancybox.close(true);
3841		}
3842
3843		// Hide scrollbars
3844		// ===============
3845
3846		$("body").addClass("fancybox-active");
3847
3848		if (
3849		  !$.fancybox.getInstance() &&
3850		  firstItemOpts.hideScrollbar !== false &&
3851		  !$.fancybox.isMobile &&
3852		  document.body.scrollHeight > window.innerHeight
3853		) {
3854		  $("head").append(
3855			'<style id="fancybox-style-noscroll" type="text/css">.compensate-for-scrollbar{margin-right:' +
3856			(window.innerWidth - document.documentElement.clientWidth) +
3857			"px;}</style>"
3858		  );
3859
3860		  $("body").addClass("compensate-for-scrollbar");
3861		}
3862
3863		// Build html markup and set references
3864		// ====================================
3865
3866		// Build html code for buttons and insert into main template
3867		buttonStr = "";
3868
3869		$.each(firstItemOpts.buttons, function (index, value) {
3870		  buttonStr += firstItemOpts.btnTpl[value] || "";
3871		});
3872
3873		// Create markup from base template, it will be initially hidden to
3874		// avoid unnecessary work like painting while initializing is not complete
3875		$container = $(
3876			self.translate(
3877			  self,
3878			  firstItemOpts.baseTpl
3879			  .replace("{{buttons}}", buttonStr)
3880			  .replace("{{arrows}}", firstItemOpts.btnTpl.arrowLeft + firstItemOpts.btnTpl.arrowRight)
3881			)
3882		  )
3883		  .attr("id", "fancybox-container-" + self.id)
3884		  .addClass(firstItemOpts.baseClass)
3885		  .data("FancyBox", self)
3886		  .appendTo(firstItemOpts.parentEl);
3887
3888		// Create object holding references to jQuery wrapped nodes
3889		self.$refs = {
3890		  container: $container
3891		};
3892
3893		["bg", "inner", "infobar", "toolbar", "stage", "caption", "navigation"].forEach(function (item) {
3894		  self.$refs[item] = $container.find(".fancybox-" + item);
3895		});
3896
3897		self.trigger("onInit");
3898
3899		// Enable events, deactive previous instances
3900		self.activate();
3901
3902		// Build slides, load and reveal content
3903		self.jumpTo(self.currIndex);
3904	  },
3905
3906	  // Simple i18n support - replaces object keys found in template
3907	  // with corresponding values
3908	  // ============================================================
3909
3910	  translate: function (obj, str) {
3911		var arr = obj.opts.i18n[obj.opts.lang] || obj.opts.i18n.en;
3912
3913		return str.replace(/\{\{(\w+)\}\}/g, function (match, n) {
3914		  return arr[n] === undefined ? match : arr[n];
3915		});
3916	  },
3917
3918	  // Populate current group with fresh content
3919	  // Check if each object has valid type and content
3920	  // ===============================================
3921
3922	  addContent: function (content) {
3923		var self = this,
3924		  items = $.makeArray(content),
3925		  thumbs;
3926
3927		$.each(items, function (i, item) {
3928		  var obj = {},
3929			opts = {},
3930			$item,
3931			type,
3932			found,
3933			src,
3934			srcParts;
3935
3936		  // Step 1 - Make sure we have an object
3937		  // ====================================
3938
3939		  if ($.isPlainObject(item)) {
3940			// We probably have manual usage here, something like
3941			// $.fancybox.open( [ { src : "image.jpg", type : "image" } ] )
3942
3943			obj = item;
3944			opts = item.opts || item;
3945		  } else if ($.type(item) === "object" && $(item).length) {
3946			// Here we probably have jQuery collection returned by some selector
3947			$item = $(item);
3948
3949			// Support attributes like `data-options='{"touch" : false}'` and `data-touch='false'`
3950			opts = $item.data() || {};
3951			opts = $.extend(true, {}, opts, opts.options);
3952
3953			// Here we store clicked element
3954			opts.$orig = $item;
3955
3956			obj.src = self.opts.src || opts.src || $item.attr("href");
3957
3958			// Assume that simple syntax is used, for example:
3959			//   `$.fancybox.open( $("#test"), {} );`
3960			if (!obj.type && !obj.src) {
3961			  obj.type = "inline";
3962			  obj.src = item;
3963			}
3964		  } else {
3965			// Assume we have a simple html code, for example:
3966			//   $.fancybox.open( '<div><h1>Hi!</h1></div>' );
3967			obj = {
3968			  type: "html",
3969			  src: item + ""
3970			};
3971		  }
3972
3973		  // Each gallery object has full collection of options
3974		  obj.opts = $.extend(true, {}, self.opts, opts);
3975
3976		  // Do not merge buttons array
3977		  if ($.isArray(opts.buttons)) {
3978			obj.opts.buttons = opts.buttons;
3979		  }
3980
3981		  if ($.fancybox.isMobile && obj.opts.mobile) {
3982			obj.opts = mergeOpts(obj.opts, obj.opts.mobile);
3983		  }
3984
3985		  // Step 2 - Make sure we have content type, if not - try to guess
3986		  // ==============================================================
3987
3988		  type = obj.type || obj.opts.type;
3989		  src = obj.src || "";
3990
3991		  if (!type && src) {
3992			if ((found = src.match(/\.(mp4|mov|ogv|webm)((\?|#).*)?$/i))) {
3993			  type = "video";
3994
3995			  if (!obj.opts.video.format) {
3996				obj.opts.video.format = "video/" + (found[1] === "ogv" ? "ogg" : found[1]);
3997			  }
3998			} else if (src.match(/(^data:image\/[a-z0-9+\/=]*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg|ico)((\?|#).*)?$)/i)) {
3999			  type = "image";
4000			} else if (src.match(/\.(pdf)((\?|#).*)?$/i)) {
4001			  type = "iframe";
4002			  obj = $.extend(true, obj, {
4003				contentType: "pdf",
4004				opts: {
4005				  iframe: {
4006					preload: false
4007				  }
4008				}
4009			  });
4010			} else if (src.charAt(0) === "#") {
4011			  type = "inline";
4012			}
4013		  }
4014
4015		  if (type) {
4016			obj.type = type;
4017		  } else {
4018			self.trigger("objectNeedsType", obj);
4019		  }
4020
4021		  if (!obj.contentType) {
4022			obj.contentType = $.inArray(obj.type, ["html", "inline", "ajax"]) > -1 ? "html" : obj.type;
4023		  }
4024
4025		  // Step 3 - Some adjustments
4026		  // =========================
4027
4028		  obj.index = self.group.length;
4029
4030		  if (obj.opts.smallBtn == "auto") {
4031			obj.opts.smallBtn = $.inArray(obj.type, ["html", "inline", "ajax"]) > -1;
4032		  }
4033
4034		  if (obj.opts.toolbar === "auto") {
4035			obj.opts.toolbar = !obj.opts.smallBtn;
4036		  }
4037
4038		  // Find thumbnail image, check if exists and if is in the viewport
4039		  obj.$thumb = obj.opts.$thumb || null;
4040
4041		  if (obj.opts.$trigger && obj.index === self.opts.index) {
4042			obj.$thumb = obj.opts.$trigger.find("img:first");
4043
4044			if (obj.$thumb.length) {
4045			  obj.opts.$orig = obj.opts.$trigger;
4046			}
4047		  }
4048
4049		  if (!(obj.$thumb && obj.$thumb.length) && obj.opts.$orig) {
4050			obj.$thumb = obj.opts.$orig.find("img:first");
4051		  }
4052
4053		  if (obj.$thumb && !obj.$thumb.length) {
4054			obj.$thumb = null;
4055		  }
4056
4057		  obj.thumb = obj.opts.thumb || (obj.$thumb ? obj.$thumb[0].src : null);
4058
4059		  // "caption" is a "special" option, it can be used to customize caption per gallery item
4060		  if ($.type(obj.opts.caption) === "function") {
4061			obj.opts.caption = obj.opts.caption.apply(item, [self, obj]);
4062		  }
4063
4064		  if ($.type(self.opts.caption) === "function") {
4065			obj.opts.caption = self.opts.caption.apply(item, [self, obj]);
4066		  }
4067
4068		  // Make sure we have caption as a string or jQuery object
4069		  if (!(obj.opts.caption instanceof $)) {
4070			obj.opts.caption = obj.opts.caption === undefined ? "" : obj.opts.caption + "";
4071		  }
4072
4073		  // Check if url contains "filter" used to filter the content
4074		  // Example: "ajax.html #something"
4075		  if (obj.type === "ajax") {
4076			srcParts = src.split(/\s+/, 2);
4077
4078			if (srcParts.length > 1) {
4079			  obj.src = srcParts.shift();
4080
4081			  obj.opts.filter = srcParts.shift();
4082			}
4083		  }
4084
4085		  // Hide all buttons and disable interactivity for modal items
4086		  if (obj.opts.modal) {
4087			obj.opts = $.extend(true, obj.opts, {
4088			  trapFocus: true,
4089			  // Remove buttons
4090			  infobar: 0,
4091			  toolbar: 0,
4092
4093			  smallBtn: 0,
4094
4095			  // Disable keyboard navigation
4096			  keyboard: 0,
4097
4098			  // Disable some modules
4099			  slideShow: 0,
4100			  fullScreen: 0,
4101			  thumbs: 0,
4102			  touch: 0,
4103
4104			  // Disable click event handlers
4105			  clickContent: false,
4106			  clickSlide: false,
4107			  clickOutside: false,
4108			  dblclickContent: false,
4109			  dblclickSlide: false,
4110			  dblclickOutside: false
4111			});
4112		  }
4113
4114		  // Step 4 - Add processed object to group
4115		  // ======================================
4116
4117		  self.group.push(obj);
4118		});
4119
4120		// Update controls if gallery is already opened
4121		if (Object.keys(self.slides).length) {
4122		  self.updateControls();
4123
4124		  // Update thumbnails, if needed
4125		  thumbs = self.Thumbs;
4126
4127		  if (thumbs && thumbs.isActive) {
4128			thumbs.create();
4129
4130			thumbs.focus();
4131		  }
4132		}
4133	  },
4134
4135	  // Attach an event handler functions for:
4136	  //   - navigation buttons
4137	  //   - browser scrolling, resizing;
4138	  //   - focusing
4139	  //   - keyboard
4140	  //   - detecting inactivity
4141	  // ======================================
4142
4143	  addEvents: function () {
4144		var self = this;
4145
4146		self.removeEvents();
4147
4148		// Make navigation elements clickable
4149		// ==================================
4150
4151		self.$refs.container
4152		  .on("click.fb-close", "[data-fancybox-close]", function (e) {
4153			e.stopPropagation();
4154			e.preventDefault();
4155
4156			self.close(e);
4157		  })
4158		  .on("touchstart.fb-prev click.fb-prev", "[data-fancybox-prev]", function (e) {
4159			e.stopPropagation();
4160			e.preventDefault();
4161
4162			self.previous();
4163		  })
4164		  .on("touchstart.fb-next click.fb-next", "[data-fancybox-next]", function (e) {
4165			e.stopPropagation();
4166			e.preventDefault();
4167
4168			self.next();
4169		  })
4170		  .on("click.fb", "[data-fancybox-zoom]", function (e) {
4171			// Click handler for zoom button
4172			self[self.isScaledDown() ? "scaleToActual" : "scaleToFit"]();
4173		  });
4174
4175		// Handle page scrolling and browser resizing
4176		// ==========================================
4177
4178		$W.on("orientationchange.fb resize.fb", function (e) {
4179		  if (e && e.originalEvent && e.originalEvent.type === "resize") {
4180			if (self.requestId) {
4181			  cancelAFrame(self.requestId);
4182			}
4183
4184			self.requestId = requestAFrame(function () {
4185			  self.update(e);
4186			});
4187		  } else {
4188			if (self.current && self.current.type === "iframe") {
4189			  self.$refs.stage.hide();
4190			}
4191
4192			setTimeout(
4193			  function () {
4194				self.$refs.stage.show();
4195
4196				self.update(e);
4197			  },
4198			  $.fancybox.isMobile ? 600 : 250
4199			);
4200		  }
4201		});
4202
4203		$D.on("keydown.fb", function (e) {
4204		  var instance = $.fancybox ? $.fancybox.getInstance() : null,
4205			current = instance.current,
4206			keycode = e.keyCode || e.which;
4207
4208		  // Trap keyboard focus inside of the modal
4209		  // =======================================
4210
4211		  if (keycode == 9) {
4212			if (current.opts.trapFocus) {
4213			  self.focus(e);
4214			}
4215
4216			return;
4217		  }
4218
4219		  // Enable keyboard navigation
4220		  // ==========================
4221
4222		  if (!current.opts.keyboard || e.ctrlKey || e.altKey || e.shiftKey || $(e.target).is("input,textarea,video,audio,select")) {
4223			return;
4224		  }
4225
4226		  // Backspace and Esc keys
4227		  if (keycode === 8 || keycode === 27) {
4228			e.preventDefault();
4229
4230			self.close(e);
4231
4232			return;
4233		  }
4234
4235		  // Left arrow and Up arrow
4236		  if (keycode === 37 || keycode === 38) {
4237			e.preventDefault();
4238
4239			self.previous();
4240
4241			return;
4242		  }
4243
4244		  // Righ arrow and Down arrow
4245		  if (keycode === 39 || keycode === 40) {
4246			e.preventDefault();
4247
4248			self.next();
4249
4250			return;
4251		  }
4252
4253		  self.trigger("afterKeydown", e, keycode);
4254		});
4255
4256		// Hide controls after some inactivity period
4257		if (self.group[self.currIndex].opts.idleTime) {
4258		  self.idleSecondsCounter = 0;
4259
4260		  $D.on(
4261			"mousemove.fb-idle mouseleave.fb-idle mousedown.fb-idle touchstart.fb-idle touchmove.fb-idle scroll.fb-idle keydown.fb-idle",
4262			function (e) {
4263			  self.idleSecondsCounter = 0;
4264
4265			  if (self.isIdle) {
4266				self.showControls();
4267			  }
4268
4269			  self.isIdle = false;
4270			}
4271		  );
4272
4273		  self.idleInterval = window.setInterval(function () {
4274			self.idleSecondsCounter++;
4275
4276			if (self.idleSecondsCounter >= self.group[self.currIndex].opts.idleTime && !self.isDragging) {
4277			  self.isIdle = true;
4278			  self.idleSecondsCounter = 0;
4279
4280			  self.hideControls();
4281			}
4282		  }, 1000);
4283		}
4284	  },
4285
4286	  // Remove events added by the core
4287	  // ===============================
4288
4289	  removeEvents: function () {
4290		var self = this;
4291
4292		$W.off("orientationchange.fb resize.fb");
4293		$D.off("keydown.fb .fb-idle");
4294
4295		this.$refs.container.off(".fb-close .fb-prev .fb-next");
4296
4297		if (self.idleInterval) {
4298		  window.clearInterval(self.idleInterval);
4299
4300		  self.idleInterval = null;
4301		}
4302	  },
4303
4304	  // Change to previous gallery item
4305	  // ===============================
4306
4307	  previous: function (duration) {
4308		return this.jumpTo(this.currPos - 1, duration);
4309	  },
4310
4311	  // Change to next gallery item
4312	  // ===========================
4313
4314	  next: function (duration) {
4315		return this.jumpTo(this.currPos + 1, duration);
4316	  },
4317
4318	  // Switch to selected gallery item
4319	  // ===============================
4320
4321	  jumpTo: function (pos, duration) {
4322		var self = this,
4323		  groupLen = self.group.length,
4324		  firstRun,
4325		  isMoved,
4326		  loop,
4327		  current,
4328		  previous,
4329		  slidePos,
4330		  stagePos,
4331		  prop,
4332		  diff;
4333
4334		if (self.isDragging || self.isClosing || (self.isAnimating && self.firstRun)) {
4335		  return;
4336		}
4337
4338		// Should loop?
4339		pos = parseInt(pos, 10);
4340		loop = self.current ? self.current.opts.loop : self.opts.loop;
4341
4342		if (!loop && (pos < 0 || pos >= groupLen)) {
4343		  return false;
4344		}
4345
4346		// Check if opening for the first time; this helps to speed things up
4347		firstRun = self.firstRun = !Object.keys(self.slides).length;
4348
4349		// Create slides
4350		previous = self.current;
4351
4352		self.prevIndex = self.currIndex;
4353		self.prevPos = self.currPos;
4354
4355		current = self.createSlide(pos);
4356
4357		if (groupLen > 1) {
4358		  if (loop || current.index < groupLen - 1) {
4359			self.createSlide(pos + 1);
4360		  }
4361
4362		  if (loop || current.index > 0) {
4363			self.createSlide(pos - 1);
4364		  }
4365		}
4366
4367		self.current = current;
4368		self.currIndex = current.index;
4369		self.currPos = current.pos;
4370
4371		self.trigger("beforeShow", firstRun);
4372
4373		self.updateControls();
4374
4375		// Validate duration length
4376		current.forcedDuration = undefined;
4377
4378		if ($.isNumeric(duration)) {
4379		  current.forcedDuration = duration;
4380		} else {
4381		  duration = current.opts[firstRun ? "animationDuration" : "transitionDuration"];
4382		}
4383
4384		duration = parseInt(duration, 10);
4385
4386		// Check if user has swiped the slides or if still animating
4387		isMoved = self.isMoved(current);
4388
4389		// Make sure current slide is visible
4390		current.$slide.addClass("fancybox-slide--current");
4391
4392		// Fresh start - reveal container, current slide and start loading content
4393		if (firstRun) {
4394		  if (current.opts.animationEffect && duration) {
4395			self.$refs.container.css("transition-duration", duration + "ms");
4396		  }
4397
4398		  self.$refs.container.addClass("fancybox-is-open").trigger("focus");
4399
4400		  // Attempt to load content into slide
4401		  // This will later call `afterLoad` -> `revealContent`
4402		  self.loadSlide(current);
4403
4404		  self.preload("image");
4405
4406		  return;
4407		}
4408
4409		// Get actual slide/stage positions (before cleaning up)
4410		slidePos = $.fancybox.getTranslate(previous.$slide);
4411		stagePos = $.fancybox.getTranslate(self.$refs.stage);
4412
4413		// Clean up all slides
4414		$.each(self.slides, function (index, slide) {
4415		  $.fancybox.stop(slide.$slide, true);
4416		});
4417
4418		if (previous.pos !== current.pos) {
4419		  previous.isComplete = false;
4420		}
4421
4422		previous.$slide.removeClass("fancybox-slide--complete fancybox-slide--current");
4423
4424		// If slides are out of place, then animate them to correct position
4425		if (isMoved) {
4426		  // Calculate horizontal swipe distance
4427		  diff = slidePos.left - (previous.pos * slidePos.width + previous.pos * previous.opts.gutter);
4428
4429		  $.each(self.slides, function (index, slide) {
4430			slide.$slide.removeClass("fancybox-animated").removeClass(function (index, className) {
4431			  return (className.match(/(^|\s)fancybox-fx-\S+/g) || []).join(" ");
4432			});
4433
4434			// Make sure that each slide is in equal distance
4435			// This is mostly needed for freshly added slides, because they are not yet positioned
4436			var leftPos = slide.pos * slidePos.width + slide.pos * slide.opts.gutter;
4437
4438			$.fancybox.setTranslate(slide.$slide, {
4439			  top: 0,
4440			  left: leftPos - stagePos.left + diff
4441			});
4442
4443			if (slide.pos !== current.pos) {
4444			  slide.$slide.addClass("fancybox-slide--" + (slide.pos > current.pos ? "next" : "previous"));
4445			}
4446
4447			// Redraw to make sure that transition will start
4448			forceRedraw(slide.$slide);
4449
4450			// Animate the slide
4451			$.fancybox.animate(
4452			  slide.$slide, {
4453				top: 0,
4454				left: (slide.pos - current.pos) * slidePos.width + (slide.pos - current.pos) * slide.opts.gutter
4455			  },
4456			  duration,
4457			  function () {
4458				slide.$slide
4459				  .css({
4460					transform: "",
4461					opacity: ""
4462				  })
4463				  .removeClass("fancybox-slide--next fancybox-slide--previous");
4464
4465				if (slide.pos === self.currPos) {
4466				  self.complete();
4467				}
4468			  }
4469			);
4470		  });
4471		} else if (duration && current.opts.transitionEffect) {
4472		  // Set transition effect for previously active slide
4473		  prop = "fancybox-animated fancybox-fx-" + current.opts.transitionEffect;
4474
4475		  previous.$slide.addClass("fancybox-slide--" + (previous.pos > current.pos ? "next" : "previous"));
4476
4477		  $.fancybox.animate(
4478			previous.$slide,
4479			prop,
4480			duration,
4481			function () {
4482			  previous.$slide.removeClass(prop).removeClass("fancybox-slide--next fancybox-slide--previous");
4483			},
4484			false
4485		  );
4486		}
4487
4488		if (current.isLoaded) {
4489		  self.revealContent(current);
4490		} else {
4491		  self.loadSlide(current);
4492		}
4493
4494		self.preload("image");
4495	  },
4496
4497	  // Create new "slide" element
4498	  // These are gallery items  that are actually added to DOM
4499	  // =======================================================
4500
4501	  createSlide: function (pos) {
4502		var self = this,
4503		  $slide,
4504		  index;
4505
4506		index = pos % self.group.length;
4507		index = index < 0 ? self.group.length + index : index;
4508
4509		if (!self.slides[pos] && self.group[index]) {
4510		  $slide = $('<div class="fancybox-slide"></div>').appendTo(self.$refs.stage);
4511
4512		  self.slides[pos] = $.extend(true, {}, self.group[index], {
4513			pos: pos,
4514			$slide: $slide,
4515			isLoaded: false
4516		  });
4517
4518		  self.updateSlide(self.slides[pos]);
4519		}
4520
4521		return self.slides[pos];
4522	  },
4523
4524	  // Scale image to the actual size of the image;
4525	  // x and y values should be relative to the slide
4526	  // ==============================================
4527
4528	  scaleToActual: function (x, y, duration) {
4529		var self = this,
4530		  current = self.current,
4531		  $content = current.$content,
4532		  canvasWidth = $.fancybox.getTranslate(current.$slide).width,
4533		  canvasHeight = $.fancybox.getTranslate(current.$slide).height,
4534		  newImgWidth = current.width,
4535		  newImgHeight = current.height,
4536		  imgPos,
4537		  posX,
4538		  posY,
4539		  scaleX,
4540		  scaleY;
4541
4542		if (self.isAnimating || self.isMoved() || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) {
4543		  return;
4544		}
4545
4546		self.isAnimating = true;
4547
4548		$.fancybox.stop($content);
4549
4550		x = x === undefined ? canvasWidth * 0.5 : x;
4551		y = y === undefined ? canvasHeight * 0.5 : y;
4552
4553		imgPos = $.fancybox.getTranslate($content);
4554
4555		imgPos.top -= $.fancybox.getTranslate(current.$slide).top;
4556		imgPos.left -= $.fancybox.getTranslate(current.$slide).left;
4557
4558		scaleX = newImgWidth / imgPos.width;
4559		scaleY = newImgHeight / imgPos.height;
4560
4561		// Get center position for original image
4562		posX = canvasWidth * 0.5 - newImgWidth * 0.5;
4563		posY = canvasHeight * 0.5 - newImgHeight * 0.5;
4564
4565		// Make sure image does not move away from edges
4566		if (newImgWidth > canvasWidth) {
4567		  posX = imgPos.left * scaleX - (x * scaleX - x);
4568
4569		  if (posX > 0) {
4570			posX = 0;
4571		  }
4572
4573		  if (posX < canvasWidth - newImgWidth) {
4574			posX = canvasWidth - newImgWidth;
4575		  }
4576		}
4577
4578		if (newImgHeight > canvasHeight) {
4579		  posY = imgPos.top * scaleY - (y * scaleY - y);
4580
4581		  if (posY > 0) {
4582			posY = 0;
4583		  }
4584
4585		  if (posY < canvasHeight - newImgHeight) {
4586			posY = canvasHeight - newImgHeight;
4587		  }
4588		}
4589
4590		self.updateCursor(newImgWidth, newImgHeight);
4591
4592		$.fancybox.animate(
4593		  $content, {
4594			top: posY,
4595			left: posX,
4596			scaleX: scaleX,
4597			scaleY: scaleY
4598		  },
4599		  duration || 366,
4600		  function () {
4601			self.isAnimating = false;
4602		  }
4603		);
4604
4605		// Stop slideshow
4606		if (self.SlideShow && self.SlideShow.isActive) {
4607		  self.SlideShow.stop();
4608		}
4609	  },
4610
4611	  // Scale image to fit inside parent element
4612	  // ========================================
4613
4614	  scaleToFit: function (duration) {
4615		var self = this,
4616		  current = self.current,
4617		  $content = current.$content,
4618		  end;
4619
4620		if (self.isAnimating || self.isMoved() || !$content || !(current.type == "image" && current.isLoaded && !current.hasError)) {
4621		  return;
4622		}
4623
4624		self.isAnimating = true;
4625
4626		$.fancybox.stop($content);
4627
4628		end = self.getFitPos(current);
4629
4630		self.updateCursor(end.width, end.height);
4631
4632		$.fancybox.animate(
4633		  $content, {
4634			top: end.top,
4635			left: end.left,
4636			scaleX: end.width / $content.width(),
4637			scaleY: end.height / $content.height()
4638		  },
4639		  duration || 366,
4640		  function () {
4641			self.isAnimating = false;
4642		  }
4643		);
4644	  },
4645
4646	  // Calculate image size to fit inside viewport
4647	  // ===========================================
4648
4649	  getFitPos: function (slide) {
4650		var self = this,
4651		  $content = slide.$content,
4652		  $slide = slide.$slide,
4653		  width = slide.width || slide.opts.width,
4654		  height = slide.height || slide.opts.height,
4655		  maxWidth,
4656		  maxHeight,
4657		  minRatio,
4658		  aspectRatio,
4659		  rez = {};
4660
4661		if (!slide.isLoaded || !$content || !$content.length) {
4662		  return false;
4663		}
4664
4665		maxWidth = $.fancybox.getTranslate(self.$refs.stage).width;
4666		maxHeight = $.fancybox.getTranslate(self.$refs.stage).height;
4667
4668		maxWidth -=
4669		  parseFloat($slide.css("paddingLeft")) +
4670		  parseFloat($slide.css("paddingRight")) +
4671		  parseFloat($content.css("marginLeft")) +
4672		  parseFloat($content.css("marginRight"));
4673
4674		maxHeight -=
4675		  parseFloat($slide.css("paddingTop")) +
4676		  parseFloat($slide.css("paddingBottom")) +
4677		  parseFloat($content.css("marginTop")) +
4678		  parseFloat($content.css("marginBottom"));
4679
4680		if (!width || !height) {
4681		  width = maxWidth;
4682		  height = maxHeight;
4683		}
4684
4685		minRatio = Math.min(1, maxWidth / width, maxHeight / height);
4686
4687		width = minRatio * width;
4688		height = minRatio * height;
4689
4690		// Adjust width/height to precisely fit into container
4691		if (width > maxWidth - 0.5) {
4692		  width = maxWidth;
4693		}
4694
4695		if (height > maxHeight - 0.5) {
4696		  height = maxHeight;
4697		}
4698
4699		if (slide.type === "image") {
4700		  rez.top = Math.floor((maxHeight - height) * 0.5) + parseFloat($slide.css("paddingTop"));
4701		  rez.left = Math.floor((maxWidth - width) * 0.5) + parseFloat($slide.css("paddingLeft"));
4702		} else if (slide.contentType === "video") {
4703		  // Force aspect ratio for the video
4704		  // "I say the whole world must learn of our peaceful ways… by force!"
4705		  aspectRatio = slide.opts.width && slide.opts.height ? width / height : slide.opts.ratio || 16 / 9;
4706
4707		  if (height > width / aspectRatio) {
4708			height = width / aspectRatio;
4709		  } else if (width > height * aspectRatio) {
4710			width = height * aspectRatio;
4711		  }
4712		}
4713
4714		rez.width = width;
4715		rez.height = height;
4716
4717		return rez;
4718	  },
4719
4720	  // Update content size and position for all slides
4721	  // ==============================================
4722
4723	  update: function (e) {
4724		var self = this;
4725
4726		$.each(self.slides, function (key, slide) {
4727		  self.updateSlide(slide, e);
4728		});
4729	  },
4730
4731	  // Update slide content position and size
4732	  // ======================================
4733
4734	  updateSlide: function (slide, e) {
4735		var self = this,
4736		  $content = slide && slide.$content,
4737		  width = slide.width || slide.opts.width,
4738		  height = slide.height || slide.opts.height,
4739		  $slide = slide.$slide;
4740
4741		// First, prevent caption overlap, if needed
4742		self.adjustCaption(slide);
4743
4744		// Then resize content to fit inside the slide
4745		if ($content && (width || height || slide.contentType === "video") && !slide.hasError) {
4746		  $.fancybox.stop($content);
4747
4748		  $.fancybox.setTranslate($content, self.getFitPos(slide));
4749
4750		  if (slide.pos === self.currPos) {
4751			self.isAnimating = false;
4752
4753			self.updateCursor();
4754		  }
4755		}
4756
4757		// Then some adjustments
4758		self.adjustLayout(slide);
4759
4760		if ($slide.length) {
4761		  $slide.trigger("refresh");
4762
4763		  if (slide.pos === self.currPos) {
4764			self.$refs.toolbar
4765			  .add(self.$refs.navigation.find(".fancybox-button--arrow_right"))
4766			  .toggleClass("compensate-for-scrollbar", $slide.get(0).scrollHeight > $slide.get(0).clientHeight);
4767		  }
4768		}
4769
4770		self.trigger("onUpdate", slide, e);
4771	  },
4772
4773	  // Horizontally center slide
4774	  // =========================
4775
4776	  centerSlide: function (duration) {
4777		var self = this,
4778		  current = self.current,
4779		  $slide = current.$slide;
4780
4781		if (self.isClosing || !current) {
4782		  return;
4783		}
4784
4785		$slide.siblings().css({
4786		  transform: "",
4787		  opacity: ""
4788		});
4789
4790		$slide
4791		  .parent()
4792		  .children()
4793		  .removeClass("fancybox-slide--previous fancybox-slide--next");
4794
4795		$.fancybox.animate(
4796		  $slide, {
4797			top: 0,
4798			left: 0,
4799			opacity: 1
4800		  },
4801		  duration === undefined ? 0 : duration,
4802		  function () {
4803			// Clean up
4804			$slide.css({
4805			  transform: "",
4806			  opacity: ""
4807			});
4808
4809			if (!current.isComplete) {
4810			  self.complete();
4811			}
4812		  },
4813		  false
4814		);
4815	  },
4816
4817	  // Check if current slide is moved (swiped)
4818	  // ========================================
4819
4820	  isMoved: function (slide) {
4821		var current = slide || this.current,
4822		  slidePos,
4823		  stagePos;
4824
4825		if (!current) {
4826		  return false;
4827		}
4828
4829		stagePos = $.fancybox.getTranslate(this.$refs.stage);
4830		slidePos = $.fancybox.getTranslate(current.$slide);
4831
4832		return (
4833		  !current.$slide.hasClass("fancybox-animated") &&
4834		  (Math.abs(slidePos.top - stagePos.top) > 0.5 || Math.abs(slidePos.left - stagePos.left) > 0.5)
4835		);
4836	  },
4837
4838	  // Update cursor style depending if content can be zoomed
4839	  // ======================================================
4840
4841	  updateCursor: function (nextWidth, nextHeight) {
4842		var self = this,
4843		  current = self.current,
4844		  $container = self.$refs.container,
4845		  canPan,
4846		  isZoomable;
4847
4848		if (!current || self.isClosing || !self.Guestures) {
4849		  return;
4850		}
4851
4852		$container.removeClass("fancybox-is-zoomable fancybox-can-zoomIn fancybox-can-zoomOut fancybox-can-swipe fancybox-can-pan");
4853
4854		canPan = self.canPan(nextWidth, nextHeight);
4855
4856		isZoomable = canPan ? true : self.isZoomable();
4857
4858		$container.toggleClass("fancybox-is-zoomable", isZoomable);
4859
4860		$("[data-fancybox-zoom]").prop("disabled", !isZoomable);
4861
4862		if (canPan) {
4863		  $container.addClass("fancybox-can-pan");
4864		} else if (
4865		  isZoomable &&
4866		  (current.opts.clickContent === "zoom" || ($.isFunction(current.opts.clickContent) && current.opts.clickContent(current) == "zoom"))
4867		) {
4868		  $container.addClass("fancybox-can-zoomIn");
4869		} else if (current.opts.touch && (current.opts.touch.vertical || self.group.length > 1) && current.contentType !== "video") {
4870		  $container.addClass("fancybox-can-swipe");
4871		}
4872	  },
4873
4874	  // Check if current slide is zoomable
4875	  // ==================================
4876
4877	  isZoomable: function () {
4878		var self = this,
4879		  current = self.current,
4880		  fitPos;
4881
4882		// Assume that slide is zoomable if:
4883		//   - image is still loading
4884		//   - actual size of the image is smaller than available area
4885		if (current && !self.isClosing && current.type === "image" && !current.hasError) {
4886		  if (!current.isLoaded) {
4887			return true;
4888		  }
4889
4890		  fitPos = self.getFitPos(current);
4891
4892		  if (fitPos && (current.width > fitPos.width || current.height > fitPos.height)) {
4893			return true;
4894		  }
4895		}
4896
4897		return false;
4898	  },
4899
4900	  // Check if current image dimensions are smaller than actual
4901	  // =========================================================
4902
4903	  isScaledDown: function (nextWidth, nextHeight) {
4904		var self = this,
4905		  rez = false,
4906		  current = self.current,
4907		  $content = current.$content;
4908
4909		if (nextWidth !== undefined && nextHeight !== undefined) {
4910		  rez = nextWidth < current.width && nextHeight < current.height;
4911		} else if ($content) {
4912		  rez = $.fancybox.getTranslate($content);
4913		  rez = rez.width < current.width && rez.height < current.height;
4914		}
4915
4916		return rez;
4917	  },
4918
4919	  // Check if image dimensions exceed parent element
4920	  // ===============================================
4921
4922	  canPan: function (nextWidth, nextHeight) {
4923		var self = this,
4924		  current = self.current,
4925		  pos = null,
4926		  rez = false;
4927
4928		if (current.type === "image" && (current.isComplete || (nextWidth && nextHeight)) && !current.hasError) {
4929		  rez = self.getFitPos(current);
4930
4931		  if (nextWidth !== undefined && nextHeight !== undefined) {
4932			pos = {
4933			  width: nextWidth,
4934			  height: nextHeight
4935			};
4936		  } else if (current.isComplete) {
4937			pos = $.fancybox.getTranslate(current.$content);
4938		  }
4939
4940		  if (pos && rez) {
4941			rez = Math.abs(pos.width - rez.width) > 1.5 || Math.abs(pos.height - rez.height) > 1.5;
4942		  }
4943		}
4944
4945		return rez;
4946	  },
4947
4948	  // Load content into the slide
4949	  // ===========================
4950
4951	  loadSlide: function (slide) {
4952		var self = this,
4953		  type,
4954		  $slide,
4955		  ajaxLoad;
4956
4957		if (slide.isLoading || slide.isLoaded) {
4958		  return;
4959		}
4960
4961		slide.isLoading = true;
4962
4963		if (self.trigger("beforeLoad", slide) === false) {
4964		  slide.isLoading = false;
4965
4966		  return false;
4967		}
4968
4969		type = slide.type;
4970		$slide = slide.$slide;
4971
4972		$slide
4973		  .off("refresh")
4974		  .trigger("onReset")
4975		  .addClass(slide.opts.slideClass);
4976
4977		// Create content depending on the type
4978		switch (type) {
4979		  case "image":
4980			self.setImage(slide);
4981
4982			break;
4983
4984		  case "iframe":
4985			self.setIframe(slide);
4986
4987			break;
4988
4989		  case "html":
4990			self.setContent(slide, slide.src || slide.content);
4991
4992			break;
4993
4994		  case "video":
4995			self.setContent(
4996			  slide,
4997			  slide.opts.video.tpl
4998			  .replace(/\{\{src\}\}/gi, slide.src)
4999			  .replace("{{format}}", slide.opts.videoFormat || slide.opts.video.format || "")
5000			  .replace("{{poster}}", slide.thumb || "")
5001			);
5002
5003			break;
5004
5005		  case "inline":
5006			if ($(slide.src).length) {
5007			  self.setContent(slide, $(slide.src));
5008			} else {
5009			  self.setError(slide);
5010			}
5011
5012			break;
5013
5014		  case "ajax":
5015			self.showLoading(slide);
5016
5017			ajaxLoad = $.ajax(
5018			  $.extend({}, slide.opts.ajax.settings, {
5019				url: slide.src,
5020				success: function (data, textStatus) {
5021				  if (textStatus === "success") {
5022					self.setContent(slide, data);
5023				  }
5024				},
5025				error: function (jqXHR, textStatus) {
5026				  if (jqXHR && textStatus !== "abort") {
5027					self.setError(slide);
5028				  }
5029				}
5030			  })
5031			);
5032
5033			$slide.one("onReset", function () {
5034			  ajaxLoad.abort();
5035			});
5036
5037			break;
5038
5039		  default:
5040			self.setError(slide);
5041
5042			break;
5043		}
5044
5045		return true;
5046	  },
5047
5048	  // Use thumbnail image, if possible
5049	  // ================================
5050
5051	  setImage: function (slide) {
5052		var self = this,
5053		  ghost;
5054
5055		// Check if need to show loading icon
5056		setTimeout(function () {
5057		  var $img = slide.$image;
5058
5059		  if (!self.isClosing && slide.isLoading && (!$img || !$img.length || !$img[0].complete) && !slide.hasError) {
5060			self.showLoading(slide);
5061		  }
5062		}, 50);
5063
5064		//Check if image has srcset
5065		self.checkSrcset(slide);
5066
5067		// This will be wrapper containing both ghost and actual image
5068		slide.$content = $('<div class="fancybox-content"></div>')
5069		  .addClass("fancybox-is-hidden")
5070		  .appendTo(slide.$slide.addClass("fancybox-slide--image"));
5071
5072		// If we have a thumbnail, we can display it while actual image is loading
5073		// Users will not stare at black screen and actual image will appear gradually
5074		if (slide.opts.preload !== false && slide.opts.width && slide.opts.height && slide.thumb) {
5075		  slide.width = slide.opts.width;
5076		  slide.height = slide.opts.height;
5077
5078		  ghost = document.createElement("img");
5079
5080		  ghost.onerror = function () {
5081			$(this).remove();
5082
5083			slide.$ghost = null;
5084		  };
5085
5086		  ghost.onload = function () {
5087			self.afterLoad(slide);
5088		  };
5089
5090		  slide.$ghost = $(ghost)
5091			.addClass("fancybox-image")
5092			.appendTo(slide.$content)
5093			.attr("src", slide.thumb);
5094		}
5095
5096		// Start loading actual image
5097		self.setBigImage(slide);
5098	  },
5099
5100	  // Check if image has srcset and get the source
5101	  // ============================================
5102	  checkSrcset: function (slide) {
5103		var srcset = slide.opts.srcset || slide.opts.image.srcset,
5104		  found,
5105		  temp,
5106		  pxRatio,
5107		  windowWidth;
5108
5109		// If we have "srcset", then we need to find first matching "src" value.
5110		// This is necessary, because when you set an src attribute, the browser will preload the image
5111		// before any javascript or even CSS is applied.
5112		if (srcset) {
5113		  pxRatio = window.devicePixelRatio || 1;
5114		  windowWidth = window.innerWidth * pxRatio;
5115
5116		  temp = srcset.split(",").map(function (el) {
5117			var ret = {};
5118
5119			el.trim()
5120			  .split(/\s+/)
5121			  .forEach(function (el, i) {
5122				var value = parseInt(el.substring(0, el.length - 1), 10);
5123
5124				if (i === 0) {
5125				  return (ret.url = el);
5126				}
5127
5128				if (value) {
5129				  ret.value = value;
5130				  ret.postfix = el[el.length - 1];
5131				}
5132			  });
5133
5134			return ret;
5135		  });
5136
5137		  // Sort by value
5138		  temp.sort(function (a, b) {
5139			return a.value - b.value;
5140		  });
5141
5142		  // Ok, now we have an array of all srcset values
5143		  for (var j = 0; j < temp.length; j++) {
5144			var el = temp[j];
5145
5146			if ((el.postfix === "w" && el.value >= windowWidth) || (el.postfix === "x" && el.value >= pxRatio)) {
5147			  found = el;
5148			  break;
5149			}
5150		  }
5151
5152		  // If not found, take the last one
5153		  if (!found && temp.length) {
5154			found = temp[temp.length - 1];
5155		  }
5156
5157		  if (found) {
5158			slide.src = found.url;
5159
5160			// If we have default width/height values, we can calculate height for matching source
5161			if (slide.width && slide.height && found.postfix == "w") {
5162			  slide.height = (slide.width / slide.height) * found.value;
5163			  slide.width = found.value;
5164			}
5165
5166			slide.opts.srcset = srcset;
5167		  }
5168		}
5169	  },
5170
5171	  // Create full-size image
5172	  // ======================
5173
5174	  setBigImage: function (slide) {
5175		var self = this,
5176		  img = document.createElement("img"),
5177		  $img = $(img);
5178
5179		slide.$image = $img
5180		  .one("error", function () {
5181			self.setError(slide);
5182		  })
5183		  .one("load", function () {
5184			var sizes;
5185
5186			if (!slide.$ghost) {
5187			  self.resolveImageSlideSize(slide, this.naturalWidth, this.naturalHeight);
5188
5189			  self.afterLoad(slide);
5190			}
5191
5192			if (self.isClosing) {
5193			  return;
5194			}
5195
5196			if (slide.opts.srcset) {
5197			  sizes = slide.opts.sizes;
5198
5199			  if (!sizes || sizes === "auto") {
5200				sizes =
5201				  (slide.width / slide.height > 1 && $W.width() / $W.height() > 1 ? "100" : Math.round((slide.width / slide.height) * 100)) +
5202				  "vw";
5203			  }
5204
5205			  $img.attr("sizes", sizes).attr("srcset", slide.opts.srcset);
5206			}
5207
5208			// Hide temporary image after some delay
5209			if (slide.$ghost) {
5210			  setTimeout(function () {
5211				if (slide.$ghost && !self.isClosing) {
5212				  slide.$ghost.hide();
5213				}
5214			  }, Math.min(300, Math.max(1000, slide.height / 1600)));
5215			}
5216
5217			self.hideLoading(slide);
5218		  })
5219		  .addClass("fancybox-image")
5220		  .attr("src", slide.src)
5221		  .appendTo(slide.$content);
5222
5223		if ((img.complete || img.readyState == "complete") && $img.naturalWidth && $img.naturalHeight) {
5224		  $img.trigger("load");
5225		} else if (img.error) {
5226		  $img.trigger("error");
5227		}
5228	  },
5229
5230	  // Computes the slide size from image size and maxWidth/maxHeight
5231	  // ==============================================================
5232
5233	  resolveImageSlideSize: function (slide, imgWidth, imgHeight) {
5234		var maxWidth = parseInt(slide.opts.width, 10),
5235		  maxHeight = parseInt(slide.opts.height, 10);
5236
5237		// Sets the default values from the image
5238		slide.width = imgWidth;
5239		slide.height = imgHeight;
5240
5241		if (maxWidth > 0) {
5242		  slide.width = maxWidth;
5243		  slide.height = Math.floor((maxWidth * imgHeight) / imgWidth);
5244		}
5245
5246		if (maxHeight > 0) {
5247		  slide.width = Math.floor((maxHeight * imgWidth) / imgHeight);
5248		  slide.height = maxHeight;
5249		}
5250	  },
5251
5252	  // Create iframe wrapper, iframe and bindings
5253	  // ==========================================
5254
5255	  setIframe: function (slide) {
5256		var self = this,
5257		  opts = slide.opts.iframe,
5258		  $slide = slide.$slide,
5259		  $iframe;
5260
5261		slide.$content = $('<div class="fancybox-content' + (opts.preload ? " fancybox-is-hidden" : "") + '"></div>')
5262		  .css(opts.css)
5263		  .appendTo($slide);
5264
5265		$slide.addClass("fancybox-slide--" + slide.contentType);
5266
5267		slide.$iframe = $iframe = $(opts.tpl.replace(/\{rnd\}/g, new Date().getTime()))
5268		  .attr(opts.attr)
5269		  .appendTo(slide.$content);
5270
5271		if (opts.preload) {
5272		  self.showLoading(slide);
5273
5274		  // Unfortunately, it is not always possible to determine if iframe is successfully loaded
5275		  // (due to browser security policy)
5276
5277		  $iframe.on("load.fb error.fb", function (e) {
5278			this.isReady = 1;
5279
5280			slide.$slide.trigger("refresh");
5281
5282			self.afterLoad(slide);
5283		  });
5284
5285		  // Recalculate iframe content size
5286		  // ===============================
5287
5288		  $slide.on("refresh.fb", function () {
5289			var $content = slide.$content,
5290			  frameWidth = opts.css.width,
5291			  frameHeight = opts.css.height,
5292			  $contents,
5293			  $body;
5294
5295			if ($iframe[0].isReady !== 1) {
5296			  return;
5297			}
5298
5299			try {
5300			  $contents = $iframe.contents();
5301			  $body = $contents.find("body");
5302			} catch (ignore) {}
5303
5304			// Calculate content dimensions, if it is accessible
5305			if ($body && $body.length && $body.children().length) {
5306			  // Avoid scrolling to top (if multiple instances)
5307			  $slide.css("overflow", "visible");
5308
5309			  $content.css({
5310				width: "100%",
5311				"max-width": "100%",
5312				height: "9999px"
5313			  });
5314
5315			  if (frameWidth === undefined) {
5316				frameWidth = Math.ceil(Math.max($body[0].clientWidth, $body.outerWidth(true)));
5317			  }
5318
5319			  $content.css("width", frameWidth ? frameWidth : "").css("max-width", "");
5320
5321			  if (frameHeight === undefined) {
5322				frameHeight = Math.ceil(Math.max($body[0].clientHeight, $body.outerHeight(true)));
5323			  }
5324
5325			  $content.css("height", frameHeight ? frameHeight : "");
5326
5327			  $slide.css("overflow", "auto");
5328			}
5329
5330			$content.removeClass("fancybox-is-hidden");
5331		  });
5332		} else {
5333		  self.afterLoad(slide);
5334		}
5335
5336		$iframe.attr("src", slide.src);
5337
5338		// Remove iframe if closing or changing gallery item
5339		$slide.one("onReset", function () {
5340		  // This helps IE not to throw errors when closing
5341		  try {
5342			$(this)
5343			  .find("iframe")
5344			  .hide()
5345			  .unbind()
5346			  .attr("src", "//about:blank");
5347		  } catch (ignore) {}
5348
5349		  $(this)
5350			.off("refresh.fb")
5351			.empty();
5352
5353		  slide.isLoaded = false;
5354		  slide.isRevealed = false;
5355		});
5356	  },
5357
5358	  // Wrap and append content to the slide
5359	  // ======================================
5360
5361	  setContent: function (slide, content) {
5362		var self = this;
5363
5364		if (self.isClosing) {
5365		  return;
5366		}
5367
5368		self.hideLoading(slide);
5369
5370		if (slide.$content) {
5371		  $.fancybox.stop(slide.$content);
5372		}
5373
5374		slide.$slide.empty();
5375
5376		// If content is a jQuery object, then it will be moved to the slide.
5377		// The placeholder is created so we will know where to put it back.
5378		if (isQuery(content) && content.parent().length) {
5379		  // Make sure content is not already moved to fancyBox
5380		  if (content.hasClass("fancybox-content") || content.parent().hasClass("fancybox-content")) {
5381			content.parents(".fancybox-slide").trigger("onReset");
5382		  }
5383
5384		  // Create temporary element marking original place of the content
5385		  slide.$placeholder = $("<div>")
5386			.hide()
5387			.insertAfter(content);
5388
5389		  // Make sure content is visible
5390		  content.css("display", "inline-block");
5391		} else if (!slide.hasError) {
5392		  // If content is just a plain text, try to convert it to html
5393		  if ($.type(content) === "string") {
5394			content = $("<div>")
5395			  .append($.trim(content))
5396			  .contents();
5397		  }
5398
5399		  // If "filter" option is provided, then filter content
5400		  if (slide.opts.filter) {
5401			content = $("<div>")
5402			  .html(content)
5403			  .find(slide.opts.filter);
5404		  }
5405		}
5406
5407		slide.$slide.one("onReset", function () {
5408		  // Pause all html5 video/audio
5409		  $(this)
5410			.find("video,audio")
5411			.trigger("pause");
5412
5413		  // Put content back
5414		  if (slide.$placeholder) {
5415			slide.$placeholder.after(content.removeClass("fancybox-content").hide()).remove();
5416
5417			slide.$placeholder = null;
5418		  }
5419
5420		  // Remove custom close button
5421		  if (slide.$smallBtn) {
5422			slide.$smallBtn.remove();
5423
5424			slide.$smallBtn = null;
5425		  }
5426
5427		  // Remove content and mark slide as not loaded
5428		  if (!slide.hasError) {
5429			$(this).empty();
5430
5431			slide.isLoaded = false;
5432			slide.isRevealed = false;
5433		  }
5434		});
5435
5436		$(content).appendTo(slide.$slide);
5437
5438		if ($(content).is("video,audio")) {
5439		  $(content).addClass("fancybox-video");
5440
5441		  $(content).wrap("<div></div>");
5442
5443		  slide.contentType = "video";
5444
5445		  slide.opts.width = slide.opts.width || $(content).attr("width");
5446		  slide.opts.height = slide.opts.height || $(content).attr("height");
5447		}
5448
5449		slide.$content = slide.$slide
5450		  .children()
5451		  .filter("div,form,main,video,audio,article,.fancybox-content")
5452		  .first();
5453
5454		slide.$content.siblings().hide();
5455
5456		// Re-check if there is a valid content
5457		// (in some cases, ajax response can contain various elements or plain text)
5458		if (!slide.$content.length) {
5459		  slide.$content = slide.$slide
5460			.wrapInner("<div></div>")
5461			.children()
5462			.first();
5463		}
5464
5465		slide.$content.addClass("fancybox-content");
5466
5467		slide.$slide.addClass("fancybox-slide--" + slide.contentType);
5468
5469		self.afterLoad(slide);
5470	  },
5471
5472	  // Display error message
5473	  // =====================
5474
5475	  setError: function (slide) {
5476		slide.hasError = true;
5477
5478		slide.$slide
5479		  .trigger("onReset")
5480		  .removeClass("fancybox-slide--" + slide.contentType)
5481		  .addClass("fancybox-slide--error");
5482
5483		slide.contentType = "html";
5484
5485		this.setContent(slide, this.translate(slide, slide.opts.errorTpl));
5486
5487		if (slide.pos === this.currPos) {
5488		  this.isAnimating = false;
5489		}
5490	  },
5491
5492	  // Show loading icon inside the slide
5493	  // ==================================
5494
5495	  showLoading: function (slide) {
5496		var self = this;
5497
5498		slide = slide || self.current;
5499
5500		if (slide && !slide.$spinner) {
5501		  slide.$spinner = $(self.translate(self, self.opts.spinnerTpl))
5502			.appendTo(slide.$slide)
5503			.hide()
5504			.fadeIn("fast");
5505		}
5506	  },
5507
5508	  // Remove loading icon from the slide
5509	  // ==================================
5510
5511	  hideLoading: function (slide) {
5512		var self = this;
5513
5514		slide = slide || self.current;
5515
5516		if (slide && slide.$spinner) {
5517		  slide.$spinner.stop().remove();
5518
5519		  delete slide.$spinner;
5520		}
5521	  },
5522
5523	  // Adjustments after slide content has been loaded
5524	  // ===============================================
5525
5526	  afterLoad: function (slide) {
5527		var self = this;
5528
5529		if (self.isClosing) {
5530		  return;
5531		}
5532
5533		slide.isLoading = false;
5534		slide.isLoaded = true;
5535
5536		self.trigger("afterLoad", slide);
5537
5538		self.hideLoading(slide);
5539
5540		// Add small close button
5541		if (slide.opts.smallBtn && (!slide.$smallBtn || !slide.$smallBtn.length)) {
5542		  slide.$smallBtn = $(self.translate(slide, slide.opts.btnTpl.smallBtn)).appendTo(slide.$content);
5543		}
5544
5545		// Disable right click
5546		if (slide.opts.protect && slide.$content && !slide.hasError) {
5547		  slide.$content.on("contextmenu.fb", function (e) {
5548			if (e.button == 2) {
5549			  e.preventDefault();
5550			}
5551
5552			return true;
5553		  });
5554
5555		  // Add fake element on top of the image
5556		  // This makes a bit harder for user to select image
5557		  if (slide.type === "image") {
5558			$('<div class="fancybox-spaceball"></div>').appendTo(slide.$content);
5559		  }
5560		}
5561
5562		self.adjustCaption(slide);
5563
5564		self.adjustLayout(slide);
5565
5566		if (slide.pos === self.currPos) {
5567		  self.updateCursor();
5568		}
5569
5570		self.revealContent(slide);
5571	  },
5572
5573	  // Prevent caption overlap,
5574	  // fix css inconsistency across browsers
5575	  // =====================================
5576
5577	  adjustCaption: function (slide) {
5578		var self = this,
5579		  current = slide || self.current,
5580		  caption = current.opts.caption,
5581		  preventOverlap = current.opts.preventCaptionOverlap,
5582		  $caption = self.$refs.caption,
5583		  $clone,
5584		  captionH = false;
5585
5586		$caption.toggleClass("fancybox-caption--separate", preventOverlap);
5587
5588		if (preventOverlap && caption && caption.length) {
5589		  if (current.pos !== self.currPos) {
5590			$clone = $caption.clone().appendTo($caption.parent());
5591
5592			$clone
5593			  .children()
5594			  .eq(0)
5595			  .empty()
5596			  .html(caption);
5597
5598			captionH = $clone.outerHeight(true);
5599
5600			$clone.empty().remove();
5601		  } else if (self.$caption) {
5602			captionH = self.$caption.outerHeight(true);
5603		  }
5604
5605		  current.$slide.css("padding-bottom", captionH || "");
5606		}
5607	  },
5608
5609	  // Simple hack to fix inconsistency across browsers, described here (affects Edge, too):
5610	  // https://bugzilla.mozilla.org/show_bug.cgi?id=748518
5611	  // ====================================================================================
5612
5613	  adjustLayout: function (slide) {
5614		var self = this,
5615		  current = slide || self.current,
5616		  scrollHeight,
5617		  marginBottom,
5618		  inlinePadding,
5619		  actualPadding;
5620
5621		if (current.isLoaded && current.opts.disableLayoutFix !== true) {
5622		  current.$content.css("margin-bottom", "");
5623
5624		  // If we would always set margin-bottom for the content,
5625		  // then it would potentially break vertical align
5626		  if (current.$content.outerHeight() > current.$slide.height() + 0.5) {
5627			inlinePadding = current.$slide[0].style["padding-bottom"];
5628			actualPadding = current.$slide.css("padding-bottom");
5629
5630			if (parseFloat(actualPadding) > 0) {
5631			  scrollHeight = current.$slide[0].scrollHeight;
5632
5633			  current.$slide.css("padding-bottom", 0);
5634
5635			  if (Math.abs(scrollHeight - current.$slide[0].scrollHeight) < 1) {
5636				marginBottom = actualPadding;
5637			  }
5638
5639			  current.$slide.css("padding-bottom", inlinePadding);
5640			}
5641		  }
5642
5643		  current.$content.css("margin-bottom", marginBottom);
5644		}
5645	  },
5646
5647	  // Make content visible
5648	  // This method is called right after content has been loaded or
5649	  // user navigates gallery and transition should start
5650	  // ============================================================
5651
5652	  revealContent: function (slide) {
5653		var self = this,
5654		  $slide = slide.$slide,
5655		  end = false,
5656		  start = false,
5657		  isMoved = self.isMoved(slide),
5658		  isRevealed = slide.isRevealed,
5659		  effect,
5660		  effectClassName,
5661		  duration,
5662		  opacity;
5663
5664		slide.isRevealed = true;
5665
5666		effect = slide.opts[self.firstRun ? "animationEffect" : "transitionEffect"];
5667		duration = slide.opts[self.firstRun ? "animationDuration" : "transitionDuration"];
5668
5669		duration = parseInt(slide.forcedDuration === undefined ? duration : slide.forcedDuration, 10);
5670
5671		if (isMoved || slide.pos !== self.currPos || !duration) {
5672		  effect = false;
5673		}
5674
5675		// Check if can zoom
5676		if (effect === "zoom") {
5677		  if (slide.pos === self.currPos && duration && slide.type === "image" && !slide.hasError && (start = self.getThumbPos(slide))) {
5678			end = self.getFitPos(slide);
5679		  } else {
5680			effect = "fade";
5681		  }
5682		}
5683
5684		// Zoom animation
5685		// ==============
5686		if (effect === "zoom") {
5687		  self.isAnimating = true;
5688
5689		  end.scaleX = end.width / start.width;
5690		  end.scaleY = end.height / start.height;
5691
5692		  // Check if we need to animate opacity
5693		  opacity = slide.opts.zoomOpacity;
5694
5695		  if (opacity == "auto") {
5696			opacity = Math.abs(slide.width / slide.height - start.width / start.height) > 0.1;
5697		  }
5698
5699		  if (opacity) {
5700			start.opacity = 0.1;
5701			end.opacity = 1;
5702		  }
5703
5704		  // Draw image at start position
5705		  $.fancybox.setTranslate(slide.$content.removeClass("fancybox-is-hidden"), start);
5706
5707		  forceRedraw(slide.$content);
5708
5709		  // Start animation
5710		  $.fancybox.animate(slide.$content, end, duration, function () {
5711			self.isAnimating = false;
5712
5713			self.complete();
5714		  });
5715
5716		  return;
5717		}
5718
5719		self.updateSlide(slide);
5720
5721		// Simply show content if no effect
5722		// ================================
5723		if (!effect) {
5724		  slide.$content.removeClass("fancybox-is-hidden");
5725
5726		  if (!isRevealed && isMoved && slide.type === "image" && !slide.hasError) {
5727			slide.$content.hide().fadeIn("fast");
5728		  }
5729
5730		  if (slide.pos === self.currPos) {
5731			self.complete();
5732		  }
5733
5734		  return;
5735		}
5736
5737		// Prepare for CSS transiton
5738		// =========================
5739		$.fancybox.stop($slide);
5740
5741		//effectClassName = "fancybox-animated fancybox-slide--" + (slide.pos >= self.prevPos ? "next" : "previous") + " fancybox-fx-" + effect;
5742		effectClassName = "fancybox-slide--" + (slide.pos >= self.prevPos ? "next" : "previous") + " fancybox-animated fancybox-fx-" + effect;
5743
5744		$slide.addClass(effectClassName).removeClass("fancybox-slide--current"); //.addClass(effectClassName);
5745
5746		slide.$content.removeClass("fancybox-is-hidden");
5747
5748		// Force reflow
5749		forceRedraw($slide);
5750
5751		if (slide.type !== "image") {
5752		  slide.$content.hide().show(0);
5753		}
5754
5755		$.fancybox.animate(
5756		  $slide,
5757		  "fancybox-slide--current",
5758		  duration,
5759		  function () {
5760			$slide.removeClass(effectClassName).css({
5761			  transform: "",
5762			  opacity: ""
5763			});
5764
5765			if (slide.pos === self.currPos) {
5766			  self.complete();
5767			}
5768		  },
5769		  true
5770		);
5771	  },
5772
5773	  // Check if we can and have to zoom from thumbnail
5774	  //================================================
5775
5776	  getThumbPos: function (slide) {
5777		var rez = false,
5778		  $thumb = slide.$thumb,
5779		  thumbPos,
5780		  btw,
5781		  brw,
5782		  bbw,
5783		  blw;
5784
5785		if (!$thumb || !inViewport($thumb[0])) {
5786		  return false;
5787		}
5788
5789		thumbPos = $.fancybox.getTranslate($thumb);
5790
5791		btw = parseFloat($thumb.css("border-top-width") || 0);
5792		brw = parseFloat($thumb.css("border-right-width") || 0);
5793		bbw = parseFloat($thumb.css("border-bottom-width") || 0);
5794		blw = parseFloat($thumb.css("border-left-width") || 0);
5795
5796		rez = {
5797		  top: thumbPos.top + btw,
5798		  left: thumbPos.left + blw,
5799		  width: thumbPos.width - brw - blw,
5800		  height: thumbPos.height - btw - bbw,
5801		  scaleX: 1,
5802		  scaleY: 1
5803		};
5804
5805		return thumbPos.width > 0 && thumbPos.height > 0 ? rez : false;
5806	  },
5807
5808	  // Final adjustments after current gallery item is moved to position
5809	  // and it`s content is loaded
5810	  // ==================================================================
5811
5812	  complete: function () {
5813		var self = this,
5814		  current = self.current,
5815		  slides = {},
5816		  $el;
5817
5818		if (self.isMoved() || !current.isLoaded) {
5819		  return;
5820		}
5821
5822		if (!current.isComplete) {
5823		  current.isComplete = true;
5824
5825		  current.$slide.siblings().trigger("onReset");
5826
5827		  self.preload("inline");
5828
5829		  // Trigger any CSS transiton inside the slide
5830		  forceRedraw(current.$slide);
5831
5832		  current.$slide.addClass("fancybox-slide--complete");
5833
5834		  // Remove unnecessary slides
5835		  $.each(self.slides, function (key, slide) {
5836			if (slide.pos >= self.currPos - 1 && slide.pos <= self.currPos + 1) {
5837			  slides[slide.pos] = slide;
5838			} else if (slide) {
5839			  $.fancybox.stop(slide.$slide);
5840
5841			  slide.$slide.off().remove();
5842			}
5843		  });
5844
5845		  self.slides = slides;
5846		}
5847
5848		self.isAnimating = false;
5849
5850		self.updateCursor();
5851
5852		self.trigger("afterShow");
5853
5854		// Autoplay first html5 video/audio
5855		if (!!current.opts.video.autoStart) {
5856		  current.$slide
5857			.find("video,audio")
5858			.filter(":visible:first")
5859			.trigger("play")
5860			.one("ended", function () {
5861			  if (Document.exitFullscreen) {
5862				Document.exitFullscreen();
5863			  } else if (this.webkitExitFullscreen) {
5864				this.webkitExitFullscreen();
5865			  }
5866
5867			  self.next();
5868			});
5869		}
5870
5871		// Try to focus on the first focusable element
5872		if (current.opts.autoFocus && current.contentType === "html") {
5873		  // Look for the first input with autofocus attribute
5874		  $el = current.$content.find("input[autofocus]:enabled:visible:first");
5875
5876		  if ($el.length) {
5877			$el.trigger("focus");
5878		  } else {
5879			self.focus(null, true);
5880		  }
5881		}
5882
5883		// Avoid jumping
5884		current.$slide.scrollTop(0).scrollLeft(0);
5885	  },
5886
5887	  // Preload next and previous slides
5888	  // ================================
5889
5890	  preload: function (type) {
5891		var self = this,
5892		  prev,
5893		  next;
5894
5895		if (self.group.length < 2) {
5896		  return;
5897		}
5898
5899		next = self.slides[self.currPos + 1];
5900		prev = self.slides[self.currPos - 1];
5901
5902		if (prev && prev.type === type) {
5903		  self.loadSlide(prev);
5904		}
5905
5906		if (next && next.type === type) {
5907		  self.loadSlide(next);
5908		}
5909	  },
5910
5911	  // Try to find and focus on the first focusable element
5912	  // ====================================================
5913
5914	  focus: function (e, firstRun) {
5915		var self = this,
5916		  focusableStr = [
5917			"a[href]",
5918			"area[href]",
5919			'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',
5920			"select:not([disabled]):not([aria-hidden])",
5921			"textarea:not([disabled]):not([aria-hidden])",
5922			"button:not([disabled]):not([aria-hidden])",
5923			"iframe",
5924			"object",
5925			"embed",
5926			"video",
5927			"audio",
5928			"[contenteditable]",
5929			'[tabindex]:not([tabindex^="-"])'
5930		  ].join(","),
5931		  focusableItems,
5932		  focusedItemIndex;
5933
5934		if (self.isClosing) {
5935		  return;
5936		}
5937
5938		if (e || !self.current || !self.current.isComplete) {
5939		  // Focus on any element inside fancybox
5940		  focusableItems = self.$refs.container.find("*:visible");
5941		} else {
5942		  // Focus inside current slide
5943		  focusableItems = self.current.$slide.find("*:visible" + (firstRun ? ":not(.fancybox-close-small)" : ""));
5944		}
5945
5946		focusableItems = focusableItems.filter(focusableStr).filter(function () {
5947		  return $(this).css("visibility") !== "hidden" && !$(this).hasClass("disabled");
5948		});
5949
5950		if (focusableItems.length) {
5951		  focusedItemIndex = focusableItems.index(document.activeElement);
5952
5953		  if (e && e.shiftKey) {
5954			// Back tab
5955			if (focusedItemIndex < 0 || focusedItemIndex == 0) {
5956			  e.preventDefault();
5957
5958			  focusableItems.eq(focusableItems.length - 1).trigger("focus");
5959			}
5960		  } else {
5961			// Outside or Forward tab
5962			if (focusedItemIndex < 0 || focusedItemIndex == focusableItems.length - 1) {
5963			  if (e) {
5964				e.preventDefault();
5965			  }
5966
5967			  focusableItems.eq(0).trigger("focus");
5968			}
5969		  }
5970		} else {
5971		  self.$refs.container.trigger("focus");
5972		}
5973	  },
5974
5975	  // Activates current instance - brings container to the front and enables keyboard,
5976	  // notifies other instances about deactivating
5977	  // =================================================================================
5978
5979	  activate: function () {
5980		var self = this;
5981
5982		// Deactivate all instances
5983		$(".fancybox-container").each(function () {
5984		  var instance = $(this).data("FancyBox");
5985
5986		  // Skip self and closing instances
5987		  if (instance && instance.id !== self.id && !instance.isClosing) {
5988			instance.trigger("onDeactivate");
5989
5990			instance.removeEvents();
5991
5992			instance.isVisible = false;
5993		  }
5994		});
5995
5996		self.isVisible = true;
5997
5998		if (self.current || self.isIdle) {
5999		  self.update();
6000
6001		  self.updateControls();
6002		}
6003
6004		self.trigger("onActivate");
6005
6006		self.addEvents();
6007	  },
6008
6009	  // Start closing procedure
6010	  // This will start "zoom-out" animation if needed and clean everything up afterwards
6011	  // =================================================================================
6012
6013	  close: function (e, d) {
6014		var self = this,
6015		  current = self.current,
6016		  effect,
6017		  duration,
6018		  $content,
6019		  domRect,
6020		  opacity,
6021		  start,
6022		  end;
6023
6024		var done = function () {
6025		  self.cleanUp(e);
6026		};
6027
6028		if (self.isClosing) {
6029		  return false;
6030		}
6031
6032		self.isClosing = true;
6033
6034		// If beforeClose callback prevents closing, make sure content is centered
6035		if (self.trigger("beforeClose", e) === false) {
6036		  self.isClosing = false;
6037
6038		  requestAFrame(function () {
6039			self.update();
6040		  });
6041
6042		  return false;
6043		}
6044
6045		// Remove all events
6046		// If there are multiple instances, they will be set again by "activate" method
6047		self.removeEvents();
6048
6049		$content = current.$content;
6050		effect = current.opts.animationEffect;
6051		duration = $.isNumeric(d) ? d : effect ? current.opts.animationDuration : 0;
6052
6053		current.$slide.removeClass("fancybox-slide--complete fancybox-slide--next fancybox-slide--previous fancybox-animated");
6054
6055		if (e !== true) {
6056		  $.fancybox.stop(current.$slide);
6057		} else {
6058		  effect = false;
6059		}
6060
6061		// Remove other slides
6062		current.$slide
6063		  .siblings()
6064		  .trigger("onReset")
6065		  .remove();
6066
6067		// Trigger animations
6068		if (duration) {
6069		  self.$refs.container
6070			.removeClass("fancybox-is-open")
6071			.addClass("fancybox-is-closing")
6072			.css("transition-duration", duration + "ms");
6073		}
6074
6075		// Clean up
6076		self.hideLoading(current);
6077
6078		self.hideControls(true);
6079
6080		self.updateCursor();
6081
6082		// Check if possible to zoom-out
6083		if (
6084		  effect === "zoom" &&
6085		  !($content && duration && current.type === "image" && !self.isMoved() && !current.hasError && (end = self.getThumbPos(current)))
6086		) {
6087		  effect = "fade";
6088		}
6089
6090		if (effect === "zoom") {
6091		  $.fancybox.stop($content);
6092
6093		  domRect = $.fancybox.getTranslate($content);
6094
6095		  start = {
6096			top: domRect.top,
6097			left: domRect.left,
6098			scaleX: domRect.width / end.width,
6099			scaleY: domRect.height / end.height,
6100			width: end.width,
6101			height: end.height
6102		  };
6103
6104		  // Check if we need to animate opacity
6105		  opacity = current.opts.zoomOpacity;
6106
6107		  if (opacity == "auto") {
6108			opacity = Math.abs(current.width / current.height - end.width / end.height) > 0.1;
6109		  }
6110
6111		  if (opacity) {
6112			end.opacity = 0;
6113		  }
6114
6115		  $.fancybox.setTranslate($content, start);
6116
6117		  forceRedraw($content);
6118
6119		  $.fancybox.animate($content, end, duration, done);
6120
6121		  return true;
6122		}
6123
6124		if (effect && duration) {
6125		  $.fancybox.animate(
6126			current.$slide.addClass("fancybox-slide--previous").removeClass("fancybox-slide--current"),
6127			"fancybox-animated fancybox-fx-" + effect,
6128			duration,
6129			done
6130		  );
6131		} else {
6132		  // If skip animation
6133		  if (e === true) {
6134			setTimeout(done, duration);
6135		  } else {
6136			done();
6137		  }
6138		}
6139
6140		return true;
6141	  },
6142
6143	  // Final adjustments after removing the instance
6144	  // =============================================
6145
6146	  cleanUp: function (e) {
6147		var self = this,
6148		  instance,
6149		  $focus = self.current.opts.$orig,
6150		  x,
6151		  y;
6152
6153		self.current.$slide.trigger("onReset");
6154
6155		self.$refs.container.empty().remove();
6156
6157		self.trigger("afterClose", e);
6158
6159		// Place back focus
6160		if (!!self.current.opts.backFocus) {
6161		  if (!$focus || !$focus.length || !$focus.is(":visible")) {
6162			$focus = self.$trigger;
6163		  }
6164
6165		  if ($focus && $focus.length) {
6166			x = window.scrollX;
6167			y = window.scrollY;
6168
6169			$focus.trigger("focus");
6170
6171			$("html, body")
6172			  .scrollTop(y)
6173			  .scrollLeft(x);
6174		  }
6175		}
6176
6177		self.current = null;
6178
6179		// Check if there are other instances
6180		instance = $.fancybox.getInstance();
6181
6182		if (instance) {
6183		  instance.activate();
6184		} else {
6185		  $("body").removeClass("fancybox-active compensate-for-scrollbar");
6186
6187		  $("#fancybox-style-noscroll").remove();
6188		}
6189	  },
6190
6191	  // Call callback and trigger an event
6192	  // ==================================
6193
6194	  trigger: function (name, slide) {
6195		var args = Array.prototype.slice.call(arguments, 1),
6196		  self = this,
6197		  obj = slide && slide.opts ? slide : self.current,
6198		  rez;
6199
6200		if (obj) {
6201		  args.unshift(obj);
6202		} else {
6203		  obj = self;
6204		}
6205
6206		args.unshift(self);
6207
6208		if ($.isFunction(obj.opts[name])) {
6209		  rez = obj.opts[name].apply(obj, args);
6210		}
6211
6212		if (rez === false) {
6213		  return rez;
6214		}
6215
6216		if (name === "afterClose" || !self.$refs) {
6217		  $D.trigger(name + ".fb", args);
6218		} else {
6219		  self.$refs.container.trigger(name + ".fb", args);
6220		}
6221	  },
6222
6223	  // Update infobar values, navigation button states and reveal caption
6224	  // ==================================================================
6225
6226	  updateControls: function () {
6227		var self = this,
6228		  current = self.current,
6229		  index = current.index,
6230		  $container = self.$refs.container,
6231		  $caption = self.$refs.caption,
6232		  caption = current.opts.caption;
6233
6234		// Recalculate content dimensions
6235		current.$slide.trigger("refresh");
6236
6237		// Set caption
6238		if (caption && caption.length) {
6239		  self.$caption = $caption;
6240
6241		  $caption
6242			.children()
6243			.eq(0)
6244			.html(caption);
6245		} else {
6246		  self.$caption = null;
6247		}
6248
6249		if (!self.hasHiddenControls && !self.isIdle) {
6250		  self.showControls();
6251		}
6252
6253		// Update info and navigation elements
6254		$container.find("[data-fancybox-count]").html(self.group.length);
6255		$container.find("[data-fancybox-index]").html(index + 1);
6256
6257		$container.find("[data-fancybox-prev]").prop("disabled", !current.opts.loop && index <= 0);
6258		$container.find("[data-fancybox-next]").prop("disabled", !current.opts.loop && index >= self.group.length - 1);
6259
6260		if (current.type === "image") {
6261		  // Re-enable buttons; update download button source
6262		  $container
6263			.find("[data-fancybox-zoom]")
6264			.show()
6265			.end()
6266			.find("[data-fancybox-download]")
6267			.attr("href", current.opts.image.src || current.src)
6268			.show();
6269		} else if (current.opts.toolbar) {
6270		  $container.find("[data-fancybox-download],[data-fancybox-zoom]").hide();
6271		}
6272
6273		// Make sure focus is not on disabled button/element
6274		if ($(document.activeElement).is(":hidden,[disabled]")) {
6275		  self.$refs.container.trigger("focus");
6276		}
6277	  },
6278
6279	  // Hide toolbar and caption
6280	  // ========================
6281
6282	  hideControls: function (andCaption) {
6283		var self = this,
6284		  arr = ["infobar", "toolbar", "nav"];
6285
6286		if (andCaption || !self.current.opts.preventCaptionOverlap) {
6287		  arr.push("caption");
6288		}
6289
6290		this.$refs.container.removeClass(
6291		  arr
6292		  .map(function (i) {
6293			return "fancybox-show-" + i;
6294		  })
6295		  .join(" ")
6296		);
6297
6298		this.hasHiddenControls = true;
6299	  },
6300
6301	  showControls: function () {
6302		var self = this,
6303		  opts = self.current ? self.current.opts : self.opts,
6304		  $container = self.$refs.container;
6305
6306		self.hasHiddenControls = false;
6307		self.idleSecondsCounter = 0;
6308
6309		$container
6310		  .toggleClass("fancybox-show-toolbar", !!(opts.toolbar && opts.buttons))
6311		  .toggleClass("fancybox-show-infobar", !!(opts.infobar && self.group.length > 1))
6312		  .toggleClass("fancybox-show-caption", !!self.$caption)
6313		  .toggleClass("fancybox-show-nav", !!(opts.arrows && self.group.length > 1))
6314		  .toggleClass("fancybox-is-modal", !!opts.modal);
6315	  },
6316
6317	  // Toggle toolbar and caption
6318	  // ==========================
6319
6320	  toggleControls: function () {
6321		if (this.hasHiddenControls) {
6322		  this.showControls();
6323		} else {
6324		  this.hideControls();
6325		}
6326	  }
6327	});
6328
6329	$.fancybox = {
6330	  version: "3.5.7",
6331	  defaults: defaults,
6332
6333	  // Get current instance and execute a command.
6334	  //
6335	  // Examples of usage:
6336	  //
6337	  //   $instance = $.fancybox.getInstance();
6338	  //   $.fancybox.getInstance().jumpTo( 1 );
6339	  //   $.fancybox.getInstance( 'jumpTo', 1 );
6340	  //   $.fancybox.getInstance( function() {
6341	  //       console.info( this.currIndex );
6342	  //   });
6343	  // ======================================================
6344
6345	  getInstance: function (command) {
6346		var instance = $('.fancybox-container:not(".fancybox-is-closing"):last').data("FancyBox"),
6347		  args = Array.prototype.slice.call(arguments, 1);
6348
6349		if (instance instanceof FancyBox) {
6350		  if ($.type(command) === "string") {
6351			instance[command].apply(instance, args);
6352		  } else if ($.type(command) === "function") {
6353			command.apply(instance, args);
6354		  }
6355
6356		  return instance;
6357		}
6358
6359		return false;
6360	  },
6361
6362	  // Create new instance
6363	  // ===================
6364
6365	  open: function (items, opts, index) {
6366		return new FancyBox(items, opts, index);
6367	  },
6368
6369	  // Close current or all instances
6370	  // ==============================
6371
6372	  close: function (all) {
6373		var instance = this.getInstance();
6374
6375		if (instance) {
6376		  instance.close();
6377
6378		  // Try to find and close next instance
6379		  if (all === true) {
6380			this.close(all);
6381		  }
6382		}
6383	  },
6384
6385	  // Close all instances and unbind all events
6386	  // =========================================
6387
6388	  destroy: function () {
6389		this.close(true);
6390
6391		$D.add("body").off("click.fb-start", "**");
6392	  },
6393
6394	  // Try to detect mobile devices
6395	  // ============================
6396
6397	  isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
6398
6399	  // Detect if 'translate3d' support is available
6400	  // ============================================
6401
6402	  use3d: (function () {
6403		var div = document.createElement("div");
6404
6405		return (
6406		  window.getComputedStyle &&
6407		  window.getComputedStyle(div) &&
6408		  window.getComputedStyle(div).getPropertyValue("transform") &&
6409		  !(document.documentMode && document.documentMode < 11)
6410		);
6411	  })(),
6412
6413	  // Helper function to get current visual state of an element
6414	  // returns array[ top, left, horizontal-scale, vertical-scale, opacity ]
6415	  // =====================================================================
6416
6417	  getTranslate: function ($el) {
6418		var domRect;
6419
6420		if (!$el || !$el.length) {
6421		  return false;
6422		}
6423
6424		domRect = $el[0].getBoundingClientRect();
6425
6426		return {
6427		  top: domRect.top || 0,
6428		  left: domRect.left || 0,
6429		  width: domRect.width,
6430		  height: domRect.height,
6431		  opacity: parseFloat($el.css("opacity"))
6432		};
6433	  },
6434
6435	  // Shortcut for setting "translate3d" properties for element
6436	  // Can set be used to set opacity, too
6437	  // ========================================================
6438
6439	  setTranslate: function ($el, props) {
6440		var str = "",
6441		  css = {};
6442
6443		if (!$el || !props) {
6444		  return;
6445		}
6446
6447		if (props.left !== undefined || props.top !== undefined) {
6448		  str =
6449			(props.left === undefined ? $el.position().left : props.left) +
6450			"px, " +
6451			(props.top === undefined ? $el.position().top : props.top) +
6452			"px";
6453
6454		  if (this.use3d) {
6455			str = "translate3d(" + str + ", 0px)";
6456		  } else {
6457			str = "translate(" + str + ")";
6458		  }
6459		}
6460
6461		if (props.scaleX !== undefined && props.scaleY !== undefined) {
6462		  str += " scale(" + props.scaleX + ", " + props.scaleY + ")";
6463		} else if (props.scaleX !== undefined) {
6464		  str += " scaleX(" + props.scaleX + ")";
6465		}
6466
6467		if (str.length) {
6468		  css.transform = str;
6469		}
6470
6471		if (props.opacity !== undefined) {
6472		  css.opacity = props.opacity;
6473		}
6474
6475		if (props.width !== undefined) {
6476		  css.width = props.width;
6477		}
6478
6479		if (props.height !== undefined) {
6480		  css.height = props.height;
6481		}
6482
6483		return $el.css(css);
6484	  },
6485
6486	  // Simple CSS transition handler
6487	  // =============================
6488
6489	  animate: function ($el, to, duration, callback, leaveAnimationName) {
6490		var self = this,
6491		  from;
6492
6493		if ($.isFunction(duration)) {
6494		  callback = duration;
6495		  duration = null;
6496		}
6497
6498		self.stop($el);
6499
6500		from = self.getTranslate($el);
6501
6502		$el.on(transitionEnd, function (e) {
6503		  // Skip events from child elements and z-index change
6504		  if (e && e.originalEvent && (!$el.is(e.originalEvent.target) || e.originalEvent.propertyName == "z-index")) {
6505			return;
6506		  }
6507
6508		  self.stop($el);
6509
6510		  if ($.isNumeric(duration)) {
6511			$el.css("transition-duration", "");
6512		  }
6513
6514		  if ($.isPlainObject(to)) {
6515			if (to.scaleX !== undefined && to.scaleY !== undefined) {
6516			  self.setTranslate($el, {
6517				top: to.top,
6518				left: to.left,
6519				width: from.width * to.scaleX,
6520				height: from.height * to.scaleY,
6521				scaleX: 1,
6522				scaleY: 1
6523			  });
6524			}
6525		  } else if (leaveAnimationName !== true) {
6526			$el.removeClass(to);
6527		  }
6528
6529		  if ($.isFunction(callback)) {
6530			callback(e);
6531		  }
6532		});
6533
6534		if ($.isNumeric(duration)) {
6535		  $el.css("transition-duration", duration + "ms");
6536		}
6537
6538		// Start animation by changing CSS properties or class name
6539		if ($.isPlainObject(to)) {
6540		  if (to.scaleX !== undefined && to.scaleY !== undefined) {
6541			delete to.width;
6542			delete to.height;
6543
6544			if ($el.parent().hasClass("fancybox-slide--image")) {
6545			  $el.parent().addClass("fancybox-is-scaling");
6546			}
6547		  }
6548
6549		  $.fancybox.setTranslate($el, to);
6550		} else {
6551		  $el.addClass(to);
6552		}
6553
6554		// Make sure that `transitionend` callback gets fired
6555		$el.data(
6556		  "timer",
6557		  setTimeout(function () {
6558			$el.trigger(transitionEnd);
6559		  }, duration + 33)
6560		);
6561	  },
6562
6563	  stop: function ($el, callCallback) {
6564		if ($el && $el.length) {
6565		  clearTimeout($el.data("timer"));
6566
6567		  if (callCallback) {
6568			$el.trigger(transitionEnd);
6569		  }
6570
6571		  $el.off(transitionEnd).css("transition-duration", "");
6572
6573		  $el.parent().removeClass("fancybox-is-scaling");
6574		}
6575	  }
6576	};
6577
6578	// Default click handler for "fancyboxed" links
6579	// ============================================
6580
6581	function _run(e, opts) {
6582	  var items = [],
6583		index = 0,
6584		$target,
6585		value,
6586		instance;
6587
6588	  // Avoid opening multiple times
6589	  if (e && e.isDefaultPrevented()) {
6590		return;
6591	  }
6592
6593	  e.preventDefault();
6594
6595	  opts = opts || {};
6596
6597	  if (e && e.data) {
6598		opts = mergeOpts(e.data.options, opts);
6599	  }
6600
6601	  $target = opts.$target || $(e.currentTarget).trigger("blur");
6602	  instance = $.fancybox.getInstance();
6603
6604	  if (instance && instance.$trigger && instance.$trigger.is($target)) {
6605		return;
6606	  }
6607
6608	  if (opts.selector) {
6609		items = $(opts.selector);
6610	  } else {
6611		// Get all related items and find index for clicked one
6612		value = $target.attr("data-fancybox") || "";
6613
6614		if (value) {
6615		  items = e.data ? e.data.items : [];
6616		  items = items.length ? items.filter('[data-fancybox="' + value + '"]') : $('[data-fancybox="' + value + '"]');
6617		} else {
6618		  items = [$target];
6619		}
6620	  }
6621
6622	  index = $(items).index($target);
6623
6624	  // Sometimes current item can not be found
6625	  if (index < 0) {
6626		index = 0;
6627	  }
6628
6629	  instance = $.fancybox.open(items, opts, index);
6630
6631	  // Save last active element
6632	  instance.$trigger = $target;
6633	}
6634
6635	// Create a jQuery plugin
6636	// ======================
6637
6638	$.fn.fancybox = function (options) {
6639	  var selector;
6640
6641	  options = options || {};
6642	  selector = options.selector || false;
6643
6644	  if (selector) {
6645		// Use body element instead of document so it executes first
6646		$("body")
6647		  .off("click.fb-start", selector)
6648		  .on("click.fb-start", selector, {
6649			options: options
6650		  }, _run);
6651	  } else {
6652		this.off("click.fb-start").on(
6653		  "click.fb-start", {
6654			items: this,
6655			options: options
6656		  },
6657		  _run
6658		);
6659	  }
6660
6661	  return this;
6662	};
6663
6664	// Self initializing plugin for all elements having `data-fancybox` attribute
6665	// ==========================================================================
6666
6667	$D.on("click.fb-start", "[data-fancybox]", _run);
6668
6669	// Enable "trigger elements"
6670	// =========================
6671
6672	$D.on("click.fb-start", "[data-fancybox-trigger]", function (e) {
6673	  $('[data-fancybox="' + $(this).attr("data-fancybox-trigger") + '"]')
6674		.eq($(this).attr("data-fancybox-index") || 0)
6675		.trigger("click.fb-start", {
6676		  $trigger: $(this)
6677		});
6678	});
6679
6680	// Track focus event for better accessibility styling
6681	// ==================================================
6682	(function () {
6683	  var buttonStr = ".fancybox-button",
6684		focusStr = "fancybox-focus",
6685		$pressed = null;
6686
6687	  $D.on("mousedown mouseup focus blur", buttonStr, function (e) {
6688		switch (e.type) {
6689		  case "mousedown":
6690			$pressed = $(this);
6691			break;
6692		  case "mouseup":
6693			$pressed = null;
6694			break;
6695		  case "focusin":
6696			$(buttonStr).removeClass(focusStr);
6697
6698			if (!$(this).is($pressed) && !$(this).is("[disabled]")) {
6699			  $(this).addClass(focusStr);
6700			}
6701			break;
6702		  case "focusout":
6703			$(buttonStr).removeClass(focusStr);
6704			break;
6705		}
6706	  });
6707	})();
6708  })(window, document, jQuery);
6709  // ==========================================================================
6710  //
6711  // Media
6712  // Adds additional media type support
6713  //
6714  // ==========================================================================
6715  (function ($) {
6716	"use strict";
6717
6718	// Object containing properties for each media type
6719	var defaults = {
6720	  youtube: {
6721		matcher: /(youtube\.com|youtu\.be|youtube\-nocookie\.com)\/(watch\?(.*&)?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*))(.*)/i,
6722		params: {
6723		  autoplay: 1,
6724		  autohide: 1,
6725		  fs: 1,
6726		  rel: 0,
6727		  hd: 1,
6728		  wmode: "transparent",
6729		  enablejsapi: 1,
6730		  html5: 1
6731		},
6732		paramPlace: 8,
6733		type: "iframe",
6734		url: "https://www.youtube-nocookie.com/embed/$4",
6735		thumb: "https://img.youtube.com/vi/$4/hqdefault.jpg"
6736	  },
6737
6738	  vimeo: {
6739		matcher: /^.+vimeo.com\/(.*\/)?([\d]+)(.*)?/,
6740		params: {
6741		  autoplay: 1,
6742		  hd: 1,
6743		  show_title: 1,
6744		  show_byline: 1,
6745		  show_portrait: 0,
6746		  fullscreen: 1
6747		},
6748		paramPlace: 3,
6749		type: "iframe",
6750		url: "//player.vimeo.com/video/$2"
6751	  },
6752
6753	  instagram: {
6754		matcher: /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
6755		type: "image",
6756		url: "//$1/p/$2/media/?size=l"
6757	  },
6758
6759	  // Examples:
6760	  // http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
6761	  // https://www.google.com/maps/@37.7852006,-122.4146355,14.65z
6762	  // https://www.google.com/maps/@52.2111123,2.9237542,6.61z?hl=en
6763	  // https://www.google.com/maps/place/Googleplex/@37.4220041,-122.0833494,17z/data=!4m5!3m4!1s0x0:0x6c296c66619367e0!8m2!3d37.4219998!4d-122.0840572
6764	  gmap_place: {
6765		matcher: /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(((maps\/(place\/(.*)\/)?\@(.*),(\d+.?\d+?)z))|(\?ll=))(.*)?/i,
6766		type: "iframe",
6767		url: function (rez) {
6768		  return (
6769			"//maps.google." +
6770			rez[2] +
6771			"/?ll=" +
6772			(rez[9] ? rez[9] + "&z=" + Math.floor(rez[10]) + (rez[12] ? rez[12].replace(/^\//, "&") : "") : rez[12] + "").replace(/\?/, "&") +
6773			"&output=" +
6774			(rez[12] && rez[12].indexOf("layer=c") > 0 ? "svembed" : "embed")
6775		  );
6776		}
6777	  },
6778
6779	  // Examples:
6780	  // https://www.google.com/maps/search/Empire+State+Building/
6781	  // https://www.google.com/maps/search/?api=1&query=centurylink+field
6782	  // https://www.google.com/maps/search/?api=1&query=47.5951518,-122.3316393
6783	  gmap_search: {
6784		matcher: /(maps\.)?google\.([a-z]{2,3}(\.[a-z]{2})?)\/(maps\/search\/)(.*)/i,
6785		type: "iframe",
6786		url: function (rez) {
6787		  return "//maps.google." + rez[2] + "/maps?q=" + rez[5].replace("query=", "q=").replace("api=1", "") + "&output=embed";
6788		}
6789	  }
6790	};
6791
6792	// Formats matching url to final form
6793	var format = function (url, rez, params) {
6794	  if (!url) {
6795		return;
6796	  }
6797
6798	  params = params || "";
6799
6800	  if ($.type(params) === "object") {
6801		params = $.param(params, true);
6802	  }
6803
6804	  $.each(rez, function (key, value) {
6805		url = url.replace("$" + key, value || "");
6806	  });
6807
6808	  if (params.length) {
6809		url += (url.indexOf("?") > 0 ? "&" : "?") + params;
6810	  }
6811
6812	  return url;
6813	};
6814
6815	$(document).on("objectNeedsType.fb", function (e, instance, item) {
6816	  var url = item.src || "",
6817		type = false,
6818		media,
6819		thumb,
6820		rez,
6821		params,
6822		urlParams,
6823		paramObj,
6824		provider;
6825
6826	  media = $.extend(true, {}, defaults, item.opts.media);
6827
6828	  // Look for any matching media type
6829	  $.each(media, function (providerName, providerOpts) {
6830		rez = url.match(providerOpts.matcher);
6831
6832		if (!rez) {
6833		  return;
6834		}
6835
6836		type = providerOpts.type;
6837		provider = providerName;
6838		paramObj = {};
6839
6840		if (providerOpts.paramPlace && rez[providerOpts.paramPlace]) {
6841		  urlParams = rez[providerOpts.paramPlace];
6842
6843		  if (urlParams[0] == "?") {
6844			urlParams = urlParams.substring(1);
6845		  }
6846
6847		  urlParams = urlParams.split("&");
6848
6849		  for (var m = 0; m < urlParams.length; ++m) {
6850			var p = urlParams[m].split("=", 2);
6851
6852			if (p.length == 2) {
6853			  paramObj[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
6854			}
6855		  }
6856		}
6857
6858		params = $.extend(true, {}, providerOpts.params, item.opts[providerName], paramObj);
6859
6860		url =
6861		  $.type(providerOpts.url) === "function" ? providerOpts.url.call(this, rez, params, item) : format(providerOpts.url, rez, params);
6862
6863		thumb =
6864		  $.type(providerOpts.thumb) === "function" ? providerOpts.thumb.call(this, rez, params, item) : format(providerOpts.thumb, rez);
6865
6866		if (providerName === "youtube") {
6867		  url = url.replace(/&t=((\d+)m)?(\d+)s/, function (match, p1, m, s) {
6868			return "&start=" + ((m ? parseInt(m, 10) * 60 : 0) + parseInt(s, 10));
6869		  });
6870		} else if (providerName === "vimeo") {
6871		  url = url.replace("&%23", "#");
6872		}
6873
6874		return false;
6875	  });
6876
6877	  // If it is found, then change content type and update the url
6878
6879	  if (type) {
6880		if (!item.opts.thumb && !(item.opts.$thumb && item.opts.$thumb.length)) {
6881		  item.opts.thumb = thumb;
6882		}
6883
6884		if (type === "iframe") {
6885		  item.opts = $.extend(true, item.opts, {
6886			iframe: {
6887			  preload: false,
6888			  attr: {
6889				scrolling: "no"
6890			  }
6891			}
6892		  });
6893		}
6894
6895		$.extend(item, {
6896		  type: type,
6897		  src: url,
6898		  origSrc: item.src,
6899		  contentSource: provider,
6900		  contentType: type === "image" ? "image" : provider == "gmap_place" || provider == "gmap_search" ? "map" : "video"
6901		});
6902	  } else if (url) {
6903		item.type = item.opts.defaultType;
6904	  }
6905	});
6906
6907	// Load YouTube/Video API on request to detect when video finished playing
6908	var VideoAPILoader = {
6909	  youtube: {
6910		src: "https://www.youtube.com/iframe_api",
6911		class: "YT",
6912		loading: false,
6913		loaded: false
6914	  },
6915
6916	  vimeo: {
6917		src: "https://player.vimeo.com/api/player.js",
6918		class: "Vimeo",
6919		loading: false,
6920		loaded: false
6921	  },
6922
6923	  load: function (vendor) {
6924		var _this = this,
6925		  script;
6926
6927		if (this[vendor].loaded) {
6928		  setTimeout(function () {
6929			_this.done(vendor);
6930		  });
6931		  return;
6932		}
6933
6934		if (this[vendor].loading) {
6935		  return;
6936		}
6937
6938		this[vendor].loading = true;
6939
6940		script = document.createElement("script");
6941		script.type = "text/javascript";
6942		script.src = this[vendor].src;
6943
6944		if (vendor === "youtube") {
6945		  window.onYouTubeIframeAPIReady = function () {
6946			_this[vendor].loaded = true;
6947			_this.done(vendor);
6948		  };
6949		} else {
6950		  script.onload = function () {
6951			_this[vendor].loaded = true;
6952			_this.done(vendor);
6953		  };
6954		}
6955
6956		document.body.appendChild(script);
6957	  },
6958	  done: function (vendor) {
6959		var instance, $el, player;
6960
6961		if (vendor === "youtube") {
6962		  delete window.onYouTubeIframeAPIReady;
6963		}
6964
6965		instance = $.fancybox.getInstance();
6966
6967		if (instance) {
6968		  $el = instance.current.$content.find("iframe");
6969
6970		  if (vendor === "youtube" && YT !== undefined && YT) {
6971			player = new YT.Player($el.attr("id"), {
6972			  events: {
6973				onStateChange: function (e) {
6974				  if (e.data == 0) {
6975					instance.next();
6976				  }
6977				}
6978			  }
6979			});
6980		  } else if (vendor === "vimeo" && Vimeo !== undefined && Vimeo) {
6981			player = new Vimeo.Player($el);
6982
6983			player.on("ended", function () {
6984			  instance.next();
6985			});
6986		  }
6987		}
6988	  }
6989	};
6990
6991	$(document).on({
6992	  "afterShow.fb": function (e, instance, current) {
6993		if (instance.group.length > 1 && (current.contentSource === "youtube" || current.contentSource === "vimeo")) {
6994		  VideoAPILoader.load(current.contentSource);
6995		}
6996	  }
6997	});
6998  })(jQuery);
6999  // ==========================================================================
7000  //
7001  // Guestures
7002  // Adds touch guestures, handles click and tap events
7003  //
7004  // ==========================================================================
7005  (function (window, document, $) {
7006	"use strict";
7007
7008	var requestAFrame = (function () {
7009	  return (
7010		window.requestAnimationFrame ||
7011		window.webkitRequestAnimationFrame ||
7012		window.mozRequestAnimationFrame ||
7013		window.oRequestAnimationFrame ||
7014		// if all else fails, use setTimeout
7015		function (callback) {
7016		  return window.setTimeout(callback, 1000 / 60);
7017		}
7018	  );
7019	})();
7020
7021	var cancelAFrame = (function () {
7022	  return (
7023		window.cancelAnimationFrame ||
7024		window.webkitCancelAnimationFrame ||
7025		window.mozCancelAnimationFrame ||
7026		window.oCancelAnimationFrame ||
7027		function (id) {
7028		  window.clearTimeout(id);
7029		}
7030	  );
7031	})();
7032
7033	var getPointerXY = function (e) {
7034	  var result = [];
7035
7036	  e = e.originalEvent || e || window.e;
7037	  e = e.touches && e.touches.length ? e.touches : e.changedTouches && e.changedTouches.length ? e.changedTouches : [e];
7038
7039	  for (var key in e) {
7040		if (e[key].pageX) {
7041		  result.push({
7042			x: e[key].pageX,
7043			y: e[key].pageY
7044		  });
7045		} else if (e[key].clientX) {
7046		  result.push({
7047			x: e[key].clientX,
7048			y: e[key].clientY
7049		  });
7050		}
7051	  }
7052
7053	  return result;
7054	};
7055
7056	var distance = function (point2, point1, what) {
7057	  if (!point1 || !point2) {
7058		return 0;
7059	  }
7060
7061	  if (what === "x") {
7062		return point2.x - point1.x;
7063	  } else if (what === "y") {
7064		return point2.y - point1.y;
7065	  }
7066
7067	  return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
7068	};
7069
7070	var isClickable = function ($el) {
7071	  if (
7072		$el.is('a,area,button,[role="button"],input,label,select,summary,textarea,video,audio,iframe') ||
7073		$.isFunction($el.get(0).onclick) ||
7074		$el.data("selectable")
7075	  ) {
7076		return true;
7077	  }
7078
7079	  // Check for attributes like data-fancybox-next or data-fancybox-close
7080	  for (var i = 0, atts = $el[0].attributes, n = atts.length; i < n; i++) {
7081		if (atts[i].nodeName.substr(0, 14) === "data-fancybox-") {
7082		  return true;
7083		}
7084	  }
7085
7086	  return false;
7087	};
7088
7089	var hasScrollbars = function (el) {
7090	  var overflowY = window.getComputedStyle(el)["overflow-y"],
7091		overflowX = window.getComputedStyle(el)["overflow-x"],
7092		vertical = (overflowY === "scroll" || overflowY === "auto") && el.scrollHeight > el.clientHeight,
7093		horizontal = (overflowX === "scroll" || overflowX === "auto") && el.scrollWidth > el.clientWidth;
7094
7095	  return vertical || horizontal;
7096	};
7097
7098	var isScrollable = function ($el) {
7099	  var rez = false;
7100
7101	  while (true) {
7102		rez = hasScrollbars($el.get(0));
7103
7104		if (rez) {
7105		  break;
7106		}
7107
7108		$el = $el.parent();
7109
7110		if (!$el.length || $el.hasClass("fancybox-stage") || $el.is("body")) {
7111		  break;
7112		}
7113	  }
7114
7115	  return rez;
7116	};
7117
7118	var Guestures = function (instance) {
7119	  var self = this;
7120
7121	  self.instance = instance;
7122
7123	  self.$bg = instance.$refs.bg;
7124	  self.$stage = instance.$refs.stage;
7125	  self.$container = instance.$refs.container;
7126
7127	  self.destroy();
7128
7129	  self.$container.on("touchstart.fb.touch mousedown.fb.touch", $.proxy(self, "ontouchstart"));
7130	};
7131
7132	Guestures.prototype.destroy = function () {
7133	  var self = this;
7134
7135	  self.$container.off(".fb.touch");
7136
7137	  $(document).off(".fb.touch");
7138
7139	  if (self.requestId) {
7140		cancelAFrame(self.requestId);
7141		self.requestId = null;
7142	  }
7143
7144	  if (self.tapped) {
7145		clearTimeout(self.tapped);
7146		self.tapped = null;
7147	  }
7148	};
7149
7150	Guestures.prototype.ontouchstart = function (e) {
7151	  var self = this,
7152		$target = $(e.target),
7153		instance = self.instance,
7154		current = instance.current,
7155		$slide = current.$slide,
7156		$content = current.$content,
7157		isTouchDevice = e.type == "touchstart";
7158
7159	  // Do not respond to both (touch and mouse) events
7160	  if (isTouchDevice) {
7161		self.$container.off("mousedown.fb.touch");
7162	  }
7163
7164	  // Ignore right click
7165	  if (e.originalEvent && e.originalEvent.button == 2) {
7166		return;
7167	  }
7168
7169	  // Ignore taping on links, buttons, input elements
7170	  if (!$slide.length || !$target.length || isClickable($target) || isClickable($target.parent())) {
7171		return;
7172	  }
7173	  // Ignore clicks on the scrollbar
7174	  if (!$target.is("img") && e.originalEvent.clientX > $target[0].clientWidth + $target.offset().left) {
7175		return;
7176	  }
7177
7178	  // Ignore clicks while zooming or closing
7179	  if (!current || instance.isAnimating || current.$slide.hasClass("fancybox-animated")) {
7180		e.stopPropagation();
7181		e.preventDefault();
7182
7183		return;
7184	  }
7185
7186	  self.realPoints = self.startPoints = getPointerXY(e);
7187
7188	  if (!self.startPoints.length) {
7189		return;
7190	  }
7191
7192	  // Allow other scripts to catch touch event if "touch" is set to false
7193	  if (current.touch) {
7194		e.stopPropagation();
7195	  }
7196
7197	  self.startEvent = e;
7198
7199	  self.canTap = true;
7200	  self.$target = $target;
7201	  self.$content = $content;
7202	  self.opts = current.opts.touch;
7203
7204	  self.isPanning = false;
7205	  self.isSwiping = false;
7206	  self.isZooming = false;
7207	  self.isScrolling = false;
7208	  self.canPan = instance.canPan();
7209
7210	  self.startTime = new Date().getTime();
7211	  self.distanceX = self.distanceY = self.distance = 0;
7212
7213	  self.canvasWidth = Math.round($slide[0].clientWidth);
7214	  self.canvasHeight = Math.round($slide[0].clientHeight);
7215
7216	  self.contentLastPos = null;
7217	  self.contentStartPos = $.fancybox.getTranslate(self.$content) || {
7218		top: 0,
7219		left: 0
7220	  };
7221	  self.sliderStartPos = $.fancybox.getTranslate($slide);
7222
7223	  // Since position will be absolute, but we need to make it relative to the stage
7224	  self.stagePos = $.fancybox.getTranslate(instance.$refs.stage);
7225
7226	  self.sliderStartPos.top -= self.stagePos.top;
7227	  self.sliderStartPos.left -= self.stagePos.left;
7228
7229	  self.contentStartPos.top -= self.stagePos.top;
7230	  self.contentStartPos.left -= self.stagePos.left;
7231
7232	  $(document)
7233		.off(".fb.touch")
7234		.on(isTouchDevice ? "touchend.fb.touch touchcancel.fb.touch" : "mouseup.fb.touch mouseleave.fb.touch", $.proxy(self, "ontouchend"))
7235		.on(isTouchDevice ? "touchmove.fb.touch" : "mousemove.fb.touch", $.proxy(self, "ontouchmove"));
7236
7237	  if ($.fancybox.isMobile) {
7238		document.addEventListener("scroll", self.onscroll, true);
7239	  }
7240
7241	  // Skip if clicked outside the sliding area
7242	  if (!(self.opts || self.canPan) || !($target.is(self.$stage) || self.$stage.find($target).length)) {
7243		if ($target.is(".fancybox-image")) {
7244		  e.preventDefault();
7245		}
7246
7247		if (!($.fancybox.isMobile && $target.parents(".fancybox-caption").length)) {
7248		  return;
7249		}
7250	  }
7251
7252	  self.isScrollable = isScrollable($target) || isScrollable($target.parent());
7253
7254	  // Check if element is scrollable and try to prevent default behavior (scrolling)
7255	  if (!($.fancybox.isMobile && self.isScrollable)) {
7256		e.preventDefault();
7257	  }
7258
7259	  // One finger or mouse click - swipe or pan an image
7260	  if (self.startPoints.length === 1 || current.hasError) {
7261		if (self.canPan) {
7262		  $.fancybox.stop(self.$content);
7263
7264		  self.isPanning = true;
7265		} else {
7266		  self.isSwiping = true;
7267		}
7268
7269		self.$container.addClass("fancybox-is-grabbing");
7270	  }
7271
7272	  // Two fingers - zoom image
7273	  if (self.startPoints.length === 2 && current.type === "image" && (current.isLoaded || current.$ghost)) {
7274		self.canTap = false;
7275		self.isSwiping = false;
7276		self.isPanning = false;
7277
7278		self.isZooming = true;
7279
7280		$.fancybox.stop(self.$content);
7281
7282		self.centerPointStartX = (self.startPoints[0].x + self.startPoints[1].x) * 0.5 - $(window).scrollLeft();
7283		self.centerPointStartY = (self.startPoints[0].y + self.startPoints[1].y) * 0.5 - $(window).scrollTop();
7284
7285		self.percentageOfImageAtPinchPointX = (self.centerPointStartX - self.contentStartPos.left) / self.contentStartPos.width;
7286		self.percentageOfImageAtPinchPointY = (self.centerPointStartY - self.contentStartPos.top) / self.contentStartPos.height;
7287
7288		self.startDistanceBetweenFingers = distance(self.startPoints[0], self.startPoints[1]);
7289	  }
7290	};
7291
7292	Guestures.prototype.onscroll = function (e) {
7293	  var self = this;
7294
7295	  self.isScrolling = true;
7296
7297	  document.removeEventListener("scroll", self.onscroll, true);
7298	};
7299
7300	Guestures.prototype.ontouchmove = function (e) {
7301	  var self = this;
7302
7303	  // Make sure user has not released over iframe or disabled element
7304	  if (e.originalEvent.buttons !== undefined && e.originalEvent.buttons === 0) {
7305		self.ontouchend(e);
7306		return;
7307	  }
7308
7309	  if (self.isScrolling) {
7310		self.canTap = false;
7311		return;
7312	  }
7313
7314	  self.newPoints = getPointerXY(e);
7315
7316	  if (!(self.opts || self.canPan) || !self.newPoints.length || !self.newPoints.length) {
7317		return;
7318	  }
7319
7320	  if (!(self.isSwiping && self.isSwiping === true)) {
7321		e.preventDefault();
7322	  }
7323
7324	  self.distanceX = distance(self.newPoints[0], self.startPoints[0], "x");
7325	  self.distanceY = distance(self.newPoints[0], self.startPoints[0], "y");
7326
7327	  self.distance = distance(self.newPoints[0], self.startPoints[0]);
7328
7329	  // Skip false ontouchmove events (Chrome)
7330	  if (self.distance > 0) {
7331		if (self.isSwiping) {
7332		  self.onSwipe(e);
7333		} else if (self.isPanning) {
7334		  self.onPan();
7335		} else if (self.isZooming) {
7336		  self.onZoom();
7337		}
7338	  }
7339	};
7340
7341	Guestures.prototype.onSwipe = function (e) {
7342	  var self = this,
7343		instance = self.instance,
7344		swiping = self.isSwiping,
7345		left = self.sliderStartPos.left || 0,
7346		angle;
7347
7348	  // If direction is not yet determined
7349	  if (swiping === true) {
7350		// We need at least 10px distance to correctly calculate an angle
7351		if (Math.abs(self.distance) > 10) {
7352		  self.canTap = false;
7353
7354		  if (instance.group.length < 2 && self.opts.vertical) {
7355			self.isSwiping = "y";
7356		  } else if (instance.isDragging || self.opts.vertical === false || (self.opts.vertical === "auto" && $(window).width() > 800)) {
7357			self.isSwiping = "x";
7358		  } else {
7359			angle = Math.abs((Math.atan2(self.distanceY, self.distanceX) * 180) / Math.PI);
7360
7361			self.isSwiping = angle > 45 && angle < 135 ? "y" : "x";
7362		  }
7363
7364		  if (self.isSwiping === "y" && $.fancybox.isMobile && self.isScrollable) {
7365			self.isScrolling = true;
7366
7367			return;
7368		  }
7369
7370		  instance.isDragging = self.isSwiping;
7371
7372		  // Reset points to avoid jumping, because we dropped first swipes to calculate the angle
7373		  self.startPoints = self.newPoints;
7374
7375		  $.each(instance.slides, function (index, slide) {
7376			var slidePos, stagePos;
7377
7378			$.fancybox.stop(slide.$slide);
7379
7380			slidePos = $.fancybox.getTranslate(slide.$slide);
7381			stagePos = $.fancybox.getTranslate(instance.$refs.stage);
7382
7383			slide.$slide
7384			  .css({
7385				transform: "",
7386				opacity: "",
7387				"transition-duration": ""
7388			  })
7389			  .removeClass("fancybox-animated")
7390			  .removeClass(function (index, className) {
7391				return (className.match(/(^|\s)fancybox-fx-\S+/g) || []).join(" ");
7392			  });
7393
7394			if (slide.pos === instance.current.pos) {
7395			  self.sliderStartPos.top = slidePos.top - stagePos.top;
7396			  self.sliderStartPos.left = slidePos.left - stagePos.left;
7397			}
7398
7399			$.fancybox.setTranslate(slide.$slide, {
7400			  top: slidePos.top - stagePos.top,
7401			  left: slidePos.left - stagePos.left
7402			});
7403		  });
7404
7405		  // Stop slideshow
7406		  if (instance.SlideShow && instance.SlideShow.isActive) {
7407			instance.SlideShow.stop();
7408		  }
7409		}
7410
7411		return;
7412	  }
7413
7414	  // Sticky edges
7415	  if (swiping == "x") {
7416		if (
7417		  self.distanceX > 0 &&
7418		  (self.instance.group.length < 2 || (self.instance.current.index === 0 && !self.instance.current.opts.loop))
7419		) {
7420		  left = left + Math.pow(self.distanceX, 0.8);
7421		} else if (
7422		  self.distanceX < 0 &&
7423		  (self.instance.group.length < 2 ||
7424			(self.instance.current.index === self.instance.group.length - 1 && !self.instance.current.opts.loop))
7425		) {
7426		  left = left - Math.pow(-self.distanceX, 0.8);
7427		} else {
7428		  left = left + self.distanceX;
7429		}
7430	  }
7431
7432	  self.sliderLastPos = {
7433		top: swiping == "x" ? 0 : self.sliderStartPos.top + self.distanceY,
7434		left: left
7435	  };
7436
7437	  if (self.requestId) {
7438		cancelAFrame(self.requestId);
7439
7440		self.requestId = null;
7441	  }
7442
7443	  self.requestId = requestAFrame(function () {
7444		if (self.sliderLastPos) {
7445		  $.each(self.instance.slides, function (index, slide) {
7446			var pos = slide.pos - self.instance.currPos;
7447
7448			$.fancybox.setTranslate(slide.$slide, {
7449			  top: self.sliderLastPos.top,
7450			  left: self.sliderLastPos.left + pos * self.canvasWidth + pos * slide.opts.gutter
7451			});
7452		  });
7453
7454		  self.$container.addClass("fancybox-is-sliding");
7455		}
7456	  });
7457	};
7458
7459	Guestures.prototype.onPan = function () {
7460	  var self = this;
7461
7462	  // Prevent accidental movement (sometimes, when tapping casually, finger can move a bit)
7463	  if (distance(self.newPoints[0], self.realPoints[0]) < ($.fancybox.isMobile ? 10 : 5)) {
7464		self.startPoints = self.newPoints;
7465		return;
7466	  }
7467
7468	  self.canTap = false;
7469
7470	  self.contentLastPos = self.limitMovement();
7471
7472	  if (self.requestId) {
7473		cancelAFrame(self.requestId);
7474	  }
7475
7476	  self.requestId = requestAFrame(function () {
7477		$.fancybox.setTranslate(self.$content, self.contentLastPos);
7478	  });
7479	};
7480
7481	// Make panning sticky to the edges
7482	Guestures.prototype.limitMovement = function () {
7483	  var self = this;
7484
7485	  var canvasWidth = self.canvasWidth;
7486	  var canvasHeight = self.canvasHeight;
7487
7488	  var distanceX = self.distanceX;
7489	  var distanceY = self.distanceY;
7490
7491	  var contentStartPos = self.contentStartPos;
7492
7493	  var currentOffsetX = contentStartPos.left;
7494	  var currentOffsetY = contentStartPos.top;
7495
7496	  var currentWidth = contentStartPos.width;
7497	  var currentHeight = contentStartPos.height;
7498
7499	  var minTranslateX, minTranslateY, maxTranslateX, maxTranslateY, newOffsetX, newOffsetY;
7500
7501	  if (currentWidth > canvasWidth) {
7502		newOffsetX = currentOffsetX + distanceX;
7503	  } else {
7504		newOffsetX = currentOffsetX;
7505	  }
7506
7507	  newOffsetY = currentOffsetY + distanceY;
7508
7509	  // Slow down proportionally to traveled distance
7510	  minTranslateX = Math.max(0, canvasWidth * 0.5 - currentWidth * 0.5);
7511	  minTranslateY = Math.max(0, canvasHeight * 0.5 - currentHeight * 0.5);
7512
7513	  maxTranslateX = Math.min(canvasWidth - currentWidth, canvasWidth * 0.5 - currentWidth * 0.5);
7514	  maxTranslateY = Math.min(canvasHeight - currentHeight, canvasHeight * 0.5 - currentHeight * 0.5);
7515
7516	  //   ->
7517	  if (distanceX > 0 && newOffsetX > minTranslateX) {
7518		newOffsetX = minTranslateX - 1 + Math.pow(-minTranslateX + currentOffsetX + distanceX, 0.8) || 0;
7519	  }
7520
7521	  //    <-
7522	  if (distanceX < 0 && newOffsetX < maxTranslateX) {
7523		newOffsetX = maxTranslateX + 1 - Math.pow(maxTranslateX - currentOffsetX - distanceX, 0.8) || 0;
7524	  }
7525
7526	  //   \/
7527	  if (distanceY > 0 && newOffsetY > minTranslateY) {
7528		newOffsetY = minTranslateY - 1 + Math.pow(-minTranslateY + currentOffsetY + distanceY, 0.8) || 0;
7529	  }
7530
7531	  //   /\
7532	  if (distanceY < 0 && newOffsetY < maxTranslateY) {
7533		newOffsetY = maxTranslateY + 1 - Math.pow(maxTranslateY - currentOffsetY - distanceY, 0.8) || 0;
7534	  }
7535
7536	  return {
7537		top: newOffsetY,
7538		left: newOffsetX
7539	  };
7540	};
7541
7542	Guestures.prototype.limitPosition = function (newOffsetX, newOffsetY, newWidth, newHeight) {
7543	  var self = this;
7544
7545	  var canvasWidth = self.canvasWidth;
7546	  var canvasHeight = self.canvasHeight;
7547
7548	  if (newWidth > canvasWidth) {
7549		newOffsetX = newOffsetX > 0 ? 0 : newOffsetX;
7550		newOffsetX = newOffsetX < canvasWidth - newWidth ? canvasWidth - newWidth : newOffsetX;
7551	  } else {
7552		// Center horizontally
7553		newOffsetX = Math.max(0, canvasWidth / 2 - newWidth / 2);
7554	  }
7555
7556	  if (newHeight > canvasHeight) {
7557		newOffsetY = newOffsetY > 0 ? 0 : newOffsetY;
7558		newOffsetY = newOffsetY < canvasHeight - newHeight ? canvasHeight - newHeight : newOffsetY;
7559	  } else {
7560		// Center vertically
7561		newOffsetY = Math.max(0, canvasHeight / 2 - newHeight / 2);
7562	  }
7563
7564	  return {
7565		top: newOffsetY,
7566		left: newOffsetX
7567	  };
7568	};
7569
7570	Guestures.prototype.onZoom = function () {
7571	  var self = this;
7572
7573	  // Calculate current distance between points to get pinch ratio and new width and height
7574	  var contentStartPos = self.contentStartPos;
7575
7576	  var currentWidth = contentStartPos.width;
7577	  var currentHeight = contentStartPos.height;
7578
7579	  var currentOffsetX = contentStartPos.left;
7580	  var currentOffsetY = contentStartPos.top;
7581
7582	  var endDistanceBetweenFingers = distance(self.newPoints[0], self.newPoints[1]);
7583
7584	  var pinchRatio = endDistanceBetweenFingers / self.startDistanceBetweenFingers;
7585
7586	  var newWidth = Math.floor(currentWidth * pinchRatio);
7587	  var newHeight = Math.floor(currentHeight * pinchRatio);
7588
7589	  // This is the translation due to pinch-zooming
7590	  var translateFromZoomingX = (currentWidth - newWidth) * self.percentageOfImageAtPinchPointX;
7591	  var translateFromZoomingY = (currentHeight - newHeight) * self.percentageOfImageAtPinchPointY;
7592
7593	  // Point between the two touches
7594	  var centerPointEndX = (self.newPoints[0].x + self.newPoints[1].x) / 2 - $(window).scrollLeft();
7595	  var centerPointEndY = (self.newPoints[0].y + self.newPoints[1].y) / 2 - $(window).scrollTop();
7596
7597	  // And this is the translation due to translation of the centerpoint
7598	  // between the two fingers
7599	  var translateFromTranslatingX = centerPointEndX - self.centerPointStartX;
7600	  var translateFromTranslatingY = centerPointEndY - self.centerPointStartY;
7601
7602	  // The new offset is the old/current one plus the total translation
7603	  var newOffsetX = currentOffsetX + (translateFromZoomingX + translateFromTranslatingX);
7604	  var newOffsetY = currentOffsetY + (translateFromZoomingY + translateFromTranslatingY);
7605
7606	  var newPos = {
7607		top: newOffsetY,
7608		left: newOffsetX,
7609		scaleX: pinchRatio,
7610		scaleY: pinchRatio
7611	  };
7612
7613	  self.canTap = false;
7614
7615	  self.newWidth = newWidth;
7616	  self.newHeight = newHeight;
7617
7618	  self.contentLastPos = newPos;
7619
7620	  if (self.requestId) {
7621		cancelAFrame(self.requestId);
7622	  }
7623
7624	  self.requestId = requestAFrame(function () {
7625		$.fancybox.setTranslate(self.$content, self.contentLastPos);
7626	  });
7627	};
7628
7629	Guestures.prototype.ontouchend = function (e) {
7630	  var self = this;
7631
7632	  var swiping = self.isSwiping;
7633	  var panning = self.isPanning;
7634	  var zooming = self.isZooming;
7635	  var scrolling = self.isScrolling;
7636
7637	  self.endPoints = getPointerXY(e);
7638	  self.dMs = Math.max(new Date().getTime() - self.startTime, 1);
7639
7640	  self.$container.removeClass("fancybox-is-grabbing");
7641
7642	  $(document).off(".fb.touch");
7643
7644	  document.removeEventListener("scroll", self.onscroll, true);
7645
7646	  if (self.requestId) {
7647		cancelAFrame(self.requestId);
7648
7649		self.requestId = null;
7650	  }
7651
7652	  self.isSwiping = false;
7653	  self.isPanning = false;
7654	  self.isZooming = false;
7655	  self.isScrolling = false;
7656
7657	  self.instance.isDragging = false;
7658
7659	  if (self.canTap) {
7660		return self.onTap(e);
7661	  }
7662
7663	  self.speed = 100;
7664
7665	  // Speed in px/ms
7666	  self.velocityX = (self.distanceX / self.dMs) * 0.5;
7667	  self.velocityY = (self.distanceY / self.dMs) * 0.5;
7668
7669	  if (panning) {
7670		self.endPanning();
7671	  } else if (zooming) {
7672		self.endZooming();
7673	  } else {
7674		self.endSwiping(swiping, scrolling);
7675	  }
7676
7677	  return;
7678	};
7679
7680	Guestures.prototype.endSwiping = function (swiping, scrolling) {
7681	  var self = this,
7682		ret = false,
7683		len = self.instance.group.length,
7684		distanceX = Math.abs(self.distanceX),
7685		canAdvance = swiping == "x" && len > 1 && ((self.dMs > 130 && distanceX > 10) || distanceX > 50),
7686		speedX = 300;
7687
7688	  self.sliderLastPos = null;
7689
7690	  // Close if swiped vertically / navigate if horizontally
7691	  if (swiping == "y" && !scrolling && Math.abs(self.distanceY) > 50) {
7692		// Continue vertical movement
7693		$.fancybox.animate(
7694		  self.instance.current.$slide, {
7695			top: self.sliderStartPos.top + self.distanceY + self.velocityY * 150,
7696			opacity: 0
7697		  },
7698		  200
7699		);
7700		ret = self.instance.close(true, 250);
7701	  } else if (canAdvance && self.distanceX > 0) {
7702		ret = self.instance.previous(speedX);
7703	  } else if (canAdvance && self.distanceX < 0) {
7704		ret = self.instance.next(speedX);
7705	  }
7706
7707	  if (ret === false && (swiping == "x" || swiping == "y")) {
7708		self.instance.centerSlide(200);
7709	  }
7710
7711	  self.$container.removeClass("fancybox-is-sliding");
7712	};
7713
7714	// Limit panning from edges
7715	// ========================
7716	Guestures.prototype.endPanning = function () {
7717	  var self = this,
7718		newOffsetX,
7719		newOffsetY,
7720		newPos;
7721
7722	  if (!self.contentLastPos) {
7723		return;
7724	  }
7725
7726	  if (self.opts.momentum === false || self.dMs > 350) {
7727		newOffsetX = self.contentLastPos.left;
7728		newOffsetY = self.contentLastPos.top;
7729	  } else {
7730		// Continue movement
7731		newOffsetX = self.contentLastPos.left + self.velocityX * 500;
7732		newOffsetY = self.contentLastPos.top + self.velocityY * 500;
7733	  }
7734
7735	  newPos = self.limitPosition(newOffsetX, newOffsetY, self.contentStartPos.width, self.contentStartPos.height);
7736
7737	  newPos.width = self.contentStartPos.width;
7738	  newPos.height = self.contentStartPos.height;
7739
7740	  $.fancybox.animate(self.$content, newPos, 366);
7741	};
7742
7743	Guestures.prototype.endZooming = function () {
7744	  var self = this;
7745
7746	  var current = self.instance.current;
7747
7748	  var newOffsetX, newOffsetY, newPos, reset;
7749
7750	  var newWidth = self.newWidth;
7751	  var newHeight = self.newHeight;
7752
7753	  if (!self.contentLastPos) {
7754		return;
7755	  }
7756
7757	  newOffsetX = self.contentLastPos.left;
7758	  newOffsetY = self.contentLastPos.top;
7759
7760	  reset = {
7761		top: newOffsetY,
7762		left: newOffsetX,
7763		width: newWidth,
7764		height: newHeight,
7765		scaleX: 1,
7766		scaleY: 1
7767	  };
7768
7769	  // Reset scalex/scaleY values; this helps for perfomance and does not break animation
7770	  $.fancybox.setTranslate(self.$content, reset);
7771
7772	  if (newWidth < self.canvasWidth && newHeight < self.canvasHeight) {
7773		self.instance.scaleToFit(150);
7774	  } else if (newWidth > current.width || newHeight > current.height) {
7775		self.instance.scaleToActual(self.centerPointStartX, self.centerPointStartY, 150);
7776	  } else {
7777		newPos = self.limitPosition(newOffsetX, newOffsetY, newWidth, newHeight);
7778
7779		$.fancybox.animate(self.$content, newPos, 150);
7780	  }
7781	};
7782
7783	Guestures.prototype.onTap = function (e) {
7784	  var self = this;
7785	  var $target = $(e.target);
7786
7787	  var instance = self.instance;
7788	  var current = instance.current;
7789
7790	  var endPoints = (e && getPointerXY(e)) || self.startPoints;
7791
7792	  var tapX = endPoints[0] ? endPoints[0].x - $(window).scrollLeft() - self.stagePos.left : 0;
7793	  var tapY = endPoints[0] ? endPoints[0].y - $(window).scrollTop() - self.stagePos.top : 0;
7794
7795	  var where;
7796
7797	  var process = function (prefix) {
7798		var action = current.opts[prefix];
7799
7800		if ($.isFunction(action)) {
7801		  action = action.apply(instance, [current, e]);
7802		}
7803
7804		if (!action) {
7805		  return;
7806		}
7807
7808		switch (action) {
7809		  case "close":
7810			instance.close(self.startEvent);
7811
7812			break;
7813
7814		  case "toggleControls":
7815			instance.toggleControls();
7816
7817			break;
7818
7819		  case "next":
7820			instance.next();
7821
7822			break;
7823
7824		  case "nextOrClose":
7825			if (instance.group.length > 1) {
7826			  instance.next();
7827			} else {
7828			  instance.close(self.startEvent);
7829			}
7830
7831			break;
7832
7833		  case "zoom":
7834			if (current.type == "image" && (current.isLoaded || current.$ghost)) {
7835			  if (instance.canPan()) {
7836				instance.scaleToFit();
7837			  } else if (instance.isScaledDown()) {
7838				instance.scaleToActual(tapX, tapY);
7839			  } else if (instance.group.length < 2) {
7840				instance.close(self.startEvent);
7841			  }
7842			}
7843
7844			break;
7845		}
7846	  };
7847
7848	  // Ignore right click
7849	  if (e.originalEvent && e.originalEvent.button == 2) {
7850		return;
7851	  }
7852
7853	  // Skip if clicked on the scrollbar
7854	  if (!$target.is("img") && tapX > $target[0].clientWidth + $target.offset().left) {
7855		return;
7856	  }
7857
7858	  // Check where is clicked
7859	  if ($target.is(".fancybox-bg,.fancybox-inner,.fancybox-outer,.fancybox-container")) {
7860		where = "Outside";
7861	  } else if ($target.is(".fancybox-slide")) {
7862		where = "Slide";
7863	  } else if (
7864		instance.current.$content &&
7865		instance.current.$content
7866		.find($target)
7867		.addBack()
7868		.filter($target).length
7869	  ) {
7870		where = "Content";
7871	  } else {
7872		return;
7873	  }
7874
7875	  // Check if this is a double tap
7876	  if (self.tapped) {
7877		// Stop previously created single tap
7878		clearTimeout(self.tapped);
7879		self.tapped = null;
7880
7881		// Skip if distance between taps is too big
7882		if (Math.abs(tapX - self.tapX) > 50 || Math.abs(tapY - self.tapY) > 50) {
7883		  return this;
7884		}
7885
7886		// OK, now we assume that this is a double-tap
7887		process("dblclick" + where);
7888	  } else {
7889		// Single tap will be processed if user has not clicked second time within 300ms
7890		// or there is no need to wait for double-tap
7891		self.tapX = tapX;
7892		self.tapY = tapY;
7893
7894		if (current.opts["dblclick" + where] && current.opts["dblclick" + where] !== current.opts["click" + where]) {
7895		  self.tapped = setTimeout(function () {
7896			self.tapped = null;
7897
7898			if (!instance.isAnimating) {
7899			  process("click" + where);
7900			}
7901		  }, 500);
7902		} else {
7903		  process("click" + where);
7904		}
7905	  }
7906
7907	  return this;
7908	};
7909
7910	$(document)
7911	  .on("onActivate.fb", function (e, instance) {
7912		if (instance && !instance.Guestures) {
7913		  instance.Guestures = new Guestures(instance);
7914		}
7915	  })
7916	  .on("beforeClose.fb", function (e, instance) {
7917		if (instance && instance.Guestures) {
7918		  instance.Guestures.destroy();
7919		}
7920	  });
7921  })(window, document, jQuery);
7922  // ==========================================================================
7923  //
7924  // SlideShow
7925  // Enables slideshow functionality
7926  //
7927  // Example of usage:
7928  // $.fancybox.getInstance().SlideShow.start()
7929  //
7930  // ==========================================================================
7931  (function (document, $) {
7932	"use strict";
7933
7934	$.extend(true, $.fancybox.defaults, {
7935	  btnTpl: {
7936		slideShow: '<button data-fancybox-play class="fancybox-button fancybox-button--play" title="{{PLAY_START}}">' +
7937		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.5 5.4v13.2l11-6.6z"/></svg>' +
7938		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M8.33 5.75h2.2v12.5h-2.2V5.75zm5.15 0h2.2v12.5h-2.2V5.75z"/></svg>' +
7939		  "</button>"
7940	  },
7941	  slideShow: {
7942		autoStart: false,
7943		speed: 3000,
7944		progress: true
7945	  }
7946	});
7947
7948	var SlideShow = function (instance) {
7949	  this.instance = instance;
7950	  this.init();
7951	};
7952
7953	$.extend(SlideShow.prototype, {
7954	  timer: null,
7955	  isActive: false,
7956	  $button: null,
7957
7958	  init: function () {
7959		var self = this,
7960		  instance = self.instance,
7961		  opts = instance.group[instance.currIndex].opts.slideShow;
7962
7963		self.$button = instance.$refs.toolbar.find("[data-fancybox-play]").on("click", function () {
7964		  self.toggle();
7965		});
7966
7967		if (instance.group.length < 2 || !opts) {
7968		  self.$button.hide();
7969		} else if (opts.progress) {
7970		  self.$progress = $('<div class="fancybox-progress"></div>').appendTo(instance.$refs.inner);
7971		}
7972	  },
7973
7974	  set: function (force) {
7975		var self = this,
7976		  instance = self.instance,
7977		  current = instance.current;
7978
7979		// Check if reached last element
7980		if (current && (force === true || current.opts.loop || instance.currIndex < instance.group.length - 1)) {
7981		  if (self.isActive && current.contentType !== "video") {
7982			if (self.$progress) {
7983			  $.fancybox.animate(self.$progress.show(), {
7984				scaleX: 1
7985			  }, current.opts.slideShow.speed);
7986			}
7987
7988			self.timer = setTimeout(function () {
7989			  if (!instance.current.opts.loop && instance.current.index == instance.group.length - 1) {
7990				instance.jumpTo(0);
7991			  } else {
7992				instance.next();
7993			  }
7994			}, current.opts.slideShow.speed);
7995		  }
7996		} else {
7997		  self.stop();
7998		  instance.idleSecondsCounter = 0;
7999		  instance.showControls();
8000		}
8001	  },
8002
8003	  clear: function () {
8004		var self = this;
8005
8006		clearTimeout(self.timer);
8007
8008		self.timer = null;
8009
8010		if (self.$progress) {
8011		  self.$progress.removeAttr("style").hide();
8012		}
8013	  },
8014
8015	  start: function () {
8016		var self = this,
8017		  current = self.instance.current;
8018
8019		if (current) {
8020		  self.$button
8021			.attr("title", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_STOP)
8022			.removeClass("fancybox-button--play")
8023			.addClass("fancybox-button--pause");
8024
8025		  self.isActive = true;
8026
8027		  if (current.isComplete) {
8028			self.set(true);
8029		  }
8030
8031		  self.instance.trigger("onSlideShowChange", true);
8032		}
8033	  },
8034
8035	  stop: function () {
8036		var self = this,
8037		  current = self.instance.current;
8038
8039		self.clear();
8040
8041		self.$button
8042		  .attr("title", (current.opts.i18n[current.opts.lang] || current.opts.i18n.en).PLAY_START)
8043		  .removeClass("fancybox-button--pause")
8044		  .addClass("fancybox-button--play");
8045
8046		self.isActive = false;
8047
8048		self.instance.trigger("onSlideShowChange", false);
8049
8050		if (self.$progress) {
8051		  self.$progress.removeAttr("style").hide();
8052		}
8053	  },
8054
8055	  toggle: function () {
8056		var self = this;
8057
8058		if (self.isActive) {
8059		  self.stop();
8060		} else {
8061		  self.start();
8062		}
8063	  }
8064	});
8065
8066	$(document).on({
8067	  "onInit.fb": function (e, instance) {
8068		if (instance && !instance.SlideShow) {
8069		  instance.SlideShow = new SlideShow(instance);
8070		}
8071	  },
8072
8073	  "beforeShow.fb": function (e, instance, current, firstRun) {
8074		var SlideShow = instance && instance.SlideShow;
8075
8076		if (firstRun) {
8077		  if (SlideShow && current.opts.slideShow.autoStart) {
8078			SlideShow.start();
8079		  }
8080		} else if (SlideShow && SlideShow.isActive) {
8081		  SlideShow.clear();
8082		}
8083	  },
8084
8085	  "afterShow.fb": function (e, instance, current) {
8086		var SlideShow = instance && instance.SlideShow;
8087
8088		if (SlideShow && SlideShow.isActive) {
8089		  SlideShow.set();
8090		}
8091	  },
8092
8093	  "afterKeydown.fb": function (e, instance, current, keypress, keycode) {
8094		var SlideShow = instance && instance.SlideShow;
8095
8096		// "P" or Spacebar
8097		if (SlideShow && current.opts.slideShow && (keycode === 80 || keycode === 32) && !$(document.activeElement).is("button,a,input")) {
8098		  keypress.preventDefault();
8099
8100		  SlideShow.toggle();
8101		}
8102	  },
8103
8104	  "beforeClose.fb onDeactivate.fb": function (e, instance) {
8105		var SlideShow = instance && instance.SlideShow;
8106
8107		if (SlideShow) {
8108		  SlideShow.stop();
8109		}
8110	  }
8111	});
8112
8113	// Page Visibility API to pause slideshow when window is not active
8114	$(document).on("visibilitychange", function () {
8115	  if ( $.fancybox.version != '3.5.7' ) {
8116		  return;
8117	  }
8118
8119	  var instance = $.fancybox.getInstance(),
8120		SlideShow = instance && instance.SlideShow;
8121
8122	  if (SlideShow && SlideShow.isActive) {
8123		if (document.hidden) {
8124		  SlideShow.clear();
8125		} else {
8126		  SlideShow.set();
8127		}
8128	  }
8129	});
8130  })(document, jQuery);
8131  // ==========================================================================
8132  //
8133  // FullScreen
8134  // Adds fullscreen functionality
8135  //
8136  // ==========================================================================
8137  (function (document, $) {
8138	"use strict";
8139
8140	// Collection of methods supported by user browser
8141	var fn = (function () {
8142	  var fnMap = [
8143		["requestFullscreen", "exitFullscreen", "fullscreenElement", "fullscreenEnabled", "fullscreenchange", "fullscreenerror"],
8144		// new WebKit
8145		[
8146		  "webkitRequestFullscreen",
8147		  "webkitExitFullscreen",
8148		  "webkitFullscreenElement",
8149		  "webkitFullscreenEnabled",
8150		  "webkitfullscreenchange",
8151		  "webkitfullscreenerror"
8152		],
8153		// old WebKit (Safari 5.1)
8154		[
8155		  "webkitRequestFullScreen",
8156		  "webkitCancelFullScreen",
8157		  "webkitCurrentFullScreenElement",
8158		  "webkitCancelFullScreen",
8159		  "webkitfullscreenchange",
8160		  "webkitfullscreenerror"
8161		],
8162		[
8163		  "mozRequestFullScreen",
8164		  "mozCancelFullScreen",
8165		  "mozFullScreenElement",
8166		  "mozFullScreenEnabled",
8167		  "mozfullscreenchange",
8168		  "mozfullscreenerror"
8169		],
8170		["msRequestFullscreen", "msExitFullscreen", "msFullscreenElement", "msFullscreenEnabled", "MSFullscreenChange", "MSFullscreenError"]
8171	  ];
8172
8173	  var ret = {};
8174
8175	  for (var i = 0; i < fnMap.length; i++) {
8176		var val = fnMap[i];
8177
8178		if (val && val[1] in document) {
8179		  for (var j = 0; j < val.length; j++) {
8180			ret[fnMap[0][j]] = val[j];
8181		  }
8182
8183		  return ret;
8184		}
8185	  }
8186
8187	  return false;
8188	})();
8189
8190	if (fn) {
8191	  var FullScreen = {
8192		request: function (elem) {
8193		  elem = elem || document.documentElement;
8194
8195		  elem[fn.requestFullscreen](elem.ALLOW_KEYBOARD_INPUT);
8196		},
8197		exit: function () {
8198		  document[fn.exitFullscreen]();
8199		},
8200		toggle: function (elem) {
8201		  elem = elem || document.documentElement;
8202
8203		  if (this.isFullscreen()) {
8204			this.exit();
8205		  } else {
8206			this.request(elem);
8207		  }
8208		},
8209		isFullscreen: function () {
8210		  return Boolean(document[fn.fullscreenElement]);
8211		},
8212		enabled: function () {
8213		  return Boolean(document[fn.fullscreenEnabled]);
8214		}
8215	  };
8216
8217	  $.extend(true, $.fancybox.defaults, {
8218		btnTpl: {
8219		  fullScreen: '<button data-fancybox-fullscreen class="fancybox-button fancybox-button--fsenter" title="{{FULL_SCREEN}}">' +
8220			'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>' +
8221			'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5 16h3v3h2v-5H5zm3-8H5v2h5V5H8zm6 11h2v-3h3v-2h-5zm2-11V5h-2v5h5V8z"/></svg>' +
8222			"</button>"
8223		},
8224		fullScreen: {
8225		  autoStart: false
8226		}
8227	  });
8228
8229	  $(document).on(fn.fullscreenchange, function () {
8230		var isFullscreen = FullScreen.isFullscreen(),
8231		  instance = $.fancybox.getInstance();
8232
8233		if (instance) {
8234		  // If image is zooming, then force to stop and reposition properly
8235		  if (instance.current && instance.current.type === "image" && instance.isAnimating) {
8236			instance.isAnimating = false;
8237
8238			instance.update(true, true, 0);
8239
8240			if (!instance.isComplete) {
8241			  instance.complete();
8242			}
8243		  }
8244
8245		  instance.trigger("onFullscreenChange", isFullscreen);
8246
8247		  instance.$refs.container.toggleClass("fancybox-is-fullscreen", isFullscreen);
8248
8249		  instance.$refs.toolbar
8250			.find("[data-fancybox-fullscreen]")
8251			.toggleClass("fancybox-button--fsenter", !isFullscreen)
8252			.toggleClass("fancybox-button--fsexit", isFullscreen);
8253		}
8254	  });
8255	}
8256
8257	$(document).on({
8258	  "onInit.fb": function (e, instance) {
8259		var $container;
8260
8261		if (!fn) {
8262		  instance.$refs.toolbar.find("[data-fancybox-fullscreen]").remove();
8263
8264		  return;
8265		}
8266
8267		if (instance && instance.group[instance.currIndex].opts.fullScreen) {
8268		  $container = instance.$refs.container;
8269
8270		  $container.on("click.fb-fullscreen", "[data-fancybox-fullscreen]", function (e) {
8271			e.stopPropagation();
8272			e.preventDefault();
8273
8274			FullScreen.toggle();
8275		  });
8276
8277		  if (instance.opts.fullScreen && instance.opts.fullScreen.autoStart === true) {
8278			FullScreen.request();
8279		  }
8280
8281		  // Expose API
8282		  instance.FullScreen = FullScreen;
8283		} else if (instance) {
8284		  instance.$refs.toolbar.find("[data-fancybox-fullscreen]").hide();
8285		}
8286	  },
8287
8288	  "afterKeydown.fb": function (e, instance, current, keypress, keycode) {
8289		// "F"
8290		if (instance && instance.FullScreen && keycode === 70) {
8291		  keypress.preventDefault();
8292
8293		  instance.FullScreen.toggle();
8294		}
8295	  },
8296
8297	  "beforeClose.fb": function (e, instance) {
8298		if (instance && instance.FullScreen && instance.$refs.container.hasClass("fancybox-is-fullscreen")) {
8299		  FullScreen.exit();
8300		}
8301	  }
8302	});
8303  })(document, jQuery);
8304  // ==========================================================================
8305  //
8306  // Thumbs
8307  // Displays thumbnails in a grid
8308  //
8309  // ==========================================================================
8310  (function (document, $) {
8311	"use strict";
8312
8313	var CLASS = "fancybox-thumbs",
8314	  CLASS_ACTIVE = CLASS + "-active";
8315
8316	// Make sure there are default values
8317	$.fancybox.defaults = $.extend(
8318	  true, {
8319		btnTpl: {
8320		  thumbs: '<button data-fancybox-thumbs class="fancybox-button fancybox-button--thumbs" title="{{THUMBS}}">' +
8321			'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14.59 14.59h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76H5.65v-3.76zm8.94-4.47h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76h-3.76v-3.76zm-4.47 0h3.76v3.76H5.65v-3.76zm8.94-4.47h3.76v3.76h-3.76V5.65zm-4.47 0h3.76v3.76h-3.76V5.65zm-4.47 0h3.76v3.76H5.65V5.65z"/></svg>' +
8322			"</button>"
8323		},
8324		thumbs: {
8325		  autoStart: false, // Display thumbnails on opening
8326		  hideOnClose: true, // Hide thumbnail grid when closing animation starts
8327		  parentEl: ".fancybox-container", // Container is injected into this element
8328		  axis: "y" // Vertical (y) or horizontal (x) scrolling
8329		}
8330	  },
8331	  $.fancybox.defaults
8332	);
8333
8334	var FancyThumbs = function (instance) {
8335	  this.init(instance);
8336	};
8337
8338	$.extend(FancyThumbs.prototype, {
8339	  $button: null,
8340	  $grid: null,
8341	  $list: null,
8342	  isVisible: false,
8343	  isActive: false,
8344
8345	  init: function (instance) {
8346		var self = this,
8347		  group = instance.group,
8348		  enabled = 0;
8349
8350		self.instance = instance;
8351		self.opts = group[instance.currIndex].opts.thumbs;
8352
8353		instance.Thumbs = self;
8354
8355		self.$button = instance.$refs.toolbar.find("[data-fancybox-thumbs]");
8356
8357		// Enable thumbs if at least two group items have thumbnails
8358		for (var i = 0, len = group.length; i < len; i++) {
8359		  if (group[i].thumb) {
8360			enabled++;
8361		  }
8362
8363		  if (enabled > 1) {
8364			break;
8365		  }
8366		}
8367
8368		if (enabled > 1 && !!self.opts) {
8369		  self.$button.removeAttr("style").on("click", function () {
8370			self.toggle();
8371		  });
8372
8373		  self.isActive = true;
8374		} else {
8375		  self.$button.hide();
8376		}
8377	  },
8378
8379	  create: function () {
8380		var self = this,
8381		  instance = self.instance,
8382		  parentEl = self.opts.parentEl,
8383		  list = [],
8384		  src;
8385
8386		if (!self.$grid) {
8387		  // Create main element
8388		  self.$grid = $('<div class="' + CLASS + " " + CLASS + "-" + self.opts.axis + '"></div>').appendTo(
8389			instance.$refs.container
8390			.find(parentEl)
8391			.addBack()
8392			.filter(parentEl)
8393		  );
8394
8395		  // Add "click" event that performs gallery navigation
8396		  self.$grid.on("click", "a", function () {
8397			instance.jumpTo($(this).attr("data-index"));
8398		  });
8399		}
8400
8401		// Build the list
8402		if (!self.$list) {
8403		  self.$list = $('<div class="' + CLASS + '__list">').appendTo(self.$grid);
8404		}
8405
8406		$.each(instance.group, function (i, item) {
8407		  src = item.thumb;
8408
8409		  if (!src && item.type === "image") {
8410			src = item.src;
8411		  }
8412
8413		  list.push(
8414			'<a href="javascript:;" tabindex="0" data-index="' +
8415			i +
8416			'"' +
8417			(src && src.length ? ' style="background-image:url(' + src + ')"' : 'class="fancybox-thumbs-missing"') +
8418			"></a>"
8419		  );
8420		});
8421
8422		self.$list[0].innerHTML = list.join("");
8423
8424		if (self.opts.axis === "x") {
8425		  // Set fixed width for list element to enable horizontal scrolling
8426		  self.$list.width(
8427			parseInt(self.$grid.css("padding-right"), 10) +
8428			instance.group.length *
8429			self.$list
8430			.children()
8431			.eq(0)
8432			.outerWidth(true)
8433		  );
8434		}
8435	  },
8436
8437	  focus: function (duration) {
8438		var self = this,
8439		  $list = self.$list,
8440		  $grid = self.$grid,
8441		  thumb,
8442		  thumbPos;
8443
8444		if (!self.instance.current) {
8445		  return;
8446		}
8447
8448		thumb = $list
8449		  .children()
8450		  .removeClass(CLASS_ACTIVE)
8451		  .filter('[data-index="' + self.instance.current.index + '"]')
8452		  .addClass(CLASS_ACTIVE);
8453
8454		thumbPos = thumb.position();
8455
8456		// Check if need to scroll to make current thumb visible
8457		if (self.opts.axis === "y" && (thumbPos.top < 0 || thumbPos.top > $list.height() - thumb.outerHeight())) {
8458		  $list.stop().animate({
8459			  scrollTop: $list.scrollTop() + thumbPos.top
8460			},
8461			duration
8462		  );
8463		} else if (
8464		  self.opts.axis === "x" &&
8465		  (thumbPos.left < $grid.scrollLeft() || thumbPos.left > $grid.scrollLeft() + ($grid.width() - thumb.outerWidth()))
8466		) {
8467		  $list
8468			.parent()
8469			.stop()
8470			.animate({
8471				scrollLeft: thumbPos.left
8472			  },
8473			  duration
8474			);
8475		}
8476	  },
8477
8478	  update: function () {
8479		var that = this;
8480		that.instance.$refs.container.toggleClass("fancybox-show-thumbs", this.isVisible);
8481
8482		if (that.isVisible) {
8483		  if (!that.$grid) {
8484			that.create();
8485		  }
8486
8487		  that.instance.trigger("onThumbsShow");
8488
8489		  that.focus(0);
8490		} else if (that.$grid) {
8491		  that.instance.trigger("onThumbsHide");
8492		}
8493
8494		// Update content position
8495		that.instance.update();
8496	  },
8497
8498	  hide: function () {
8499		this.isVisible = false;
8500		this.update();
8501	  },
8502
8503	  show: function () {
8504		this.isVisible = true;
8505		this.update();
8506	  },
8507
8508	  toggle: function () {
8509		this.isVisible = !this.isVisible;
8510		this.update();
8511	  }
8512	});
8513
8514	$(document).on({
8515	  "onInit.fb": function (e, instance) {
8516		var Thumbs;
8517
8518		if (instance && !instance.Thumbs) {
8519		  Thumbs = new FancyThumbs(instance);
8520
8521		  if (Thumbs.isActive && Thumbs.opts.autoStart === true) {
8522			Thumbs.show();
8523		  }
8524		}
8525	  },
8526
8527	  "beforeShow.fb": function (e, instance, item, firstRun) {
8528		var Thumbs = instance && instance.Thumbs;
8529
8530		if (Thumbs && Thumbs.isVisible) {
8531		  Thumbs.focus(firstRun ? 0 : 250);
8532		}
8533	  },
8534
8535	  "afterKeydown.fb": function (e, instance, current, keypress, keycode) {
8536		var Thumbs = instance && instance.Thumbs;
8537
8538		// "G"
8539		if (Thumbs && Thumbs.isActive && keycode === 71) {
8540		  keypress.preventDefault();
8541
8542		  Thumbs.toggle();
8543		}
8544	  },
8545
8546	  "beforeClose.fb": function (e, instance) {
8547		var Thumbs = instance && instance.Thumbs;
8548
8549		if (Thumbs && Thumbs.isVisible && Thumbs.opts.hideOnClose !== false) {
8550		  Thumbs.$grid.hide();
8551		}
8552	  }
8553	});
8554  })(document, jQuery);
8555  //// ==========================================================================
8556  //
8557  // Share
8558  // Displays simple form for sharing current url
8559  //
8560  // ==========================================================================
8561  (function (document, $) {
8562	"use strict";
8563
8564	$.extend(true, $.fancybox.defaults, {
8565	  btnTpl: {
8566		share: '<button data-fancybox-share class="fancybox-button fancybox-button--share" title="{{SHARE}}">' +
8567		  '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M2.55 19c1.4-8.4 9.1-9.8 11.9-9.8V5l7 7-7 6.3v-3.5c-2.8 0-10.5 2.1-11.9 4.2z"/></svg>' +
8568		  "</button>"
8569	  },
8570	  share: {
8571		url: function (instance, item) {
8572		  return (
8573			(!instance.currentHash && !(item.type === "inline" || item.type === "html") ? item.origSrc || item.src : false) || window.location
8574		  );
8575		},
8576		tpl: '<div class="fancybox-share">' +
8577		  "<h1>{{SHARE}}</h1>" +
8578		  "<p>" +
8579		  '<a class="fancybox-share__button fancybox-share__button--fb" href="https://www.facebook.com/sharer/sharer.php?u={{url}}">' +
8580		  '<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m287 456v-299c0-21 6-35 35-35h38v-63c-7-1-29-3-55-3-54 0-91 33-91 94v306m143-254h-205v72h196" /></svg>' +
8581		  "<span>Facebook</span>" +
8582		  "</a>" +
8583		  '<a class="fancybox-share__button fancybox-share__button--tw" href="https://twitter.com/intent/tweet?url={{url}}&text={{descr}}">' +
8584		  '<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m456 133c-14 7-31 11-47 13 17-10 30-27 37-46-15 10-34 16-52 20-61-62-157-7-141 75-68-3-129-35-169-85-22 37-11 86 26 109-13 0-26-4-37-9 0 39 28 72 65 80-12 3-25 4-37 2 10 33 41 57 77 57-42 30-77 38-122 34 170 111 378-32 359-208 16-11 30-25 41-42z" /></svg>' +
8585		  "<span>Twitter</span>" +
8586		  "</a>" +
8587		  '<a class="fancybox-share__button fancybox-share__button--pt" href="https://www.pinterest.com/pin/create/button/?url={{url}}&description={{descr}}&media={{media}}">' +
8588		  '<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m265 56c-109 0-164 78-164 144 0 39 15 74 47 87 5 2 10 0 12-5l4-19c2-6 1-8-3-13-9-11-15-25-15-45 0-58 43-110 113-110 62 0 96 38 96 88 0 67-30 122-73 122-24 0-42-19-36-44 6-29 20-60 20-81 0-19-10-35-31-35-25 0-44 26-44 60 0 21 7 36 7 36l-30 125c-8 37-1 83 0 87 0 3 4 4 5 2 2-3 32-39 42-75l16-64c8 16 31 29 56 29 74 0 124-67 124-157 0-69-58-132-146-132z" fill="#fff"/></svg>' +
8589		  "<span>Pinterest</span>" +
8590		  "</a>" +
8591		  "</p>" +
8592		  '<p><input class="fancybox-share__input" type="text" value="{{url_raw}}" onclick="select()" /></p>' +
8593		  "</div>"
8594	  }
8595	});
8596
8597	function escapeHtml(string) {
8598	  var entityMap = {
8599		"&": "&amp;",
8600		"<": "&lt;",
8601		">": "&gt;",
8602		'"': "&quot;",
8603		"'": "&#39;",
8604		"/": "&#x2F;",
8605		"`": "&#x60;",
8606		"=": "&#x3D;"
8607	  };
8608
8609	  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
8610		return entityMap[s];
8611	  });
8612	}
8613
8614	$(document).on("click", "[data-fancybox-share]", function () {
8615	  var instance = $.fancybox.getInstance(),
8616		current = instance.current || null,
8617		url,
8618		tpl;
8619
8620	  if (!current) {
8621		return;
8622	  }
8623
8624	  if ($.type(current.opts.share.url) === "function") {
8625		url = current.opts.share.url.apply(current, [instance, current]);
8626	  }
8627
8628	  tpl = current.opts.share.tpl
8629		.replace(/\{\{media\}\}/g, current.type === "image" ? encodeURIComponent(current.src) : "")
8630		.replace(/\{\{url\}\}/g, encodeURIComponent(url))
8631		.replace(/\{\{url_raw\}\}/g, escapeHtml(url))
8632		.replace(/\{\{descr\}\}/g, instance.$caption ? encodeURIComponent(instance.$caption.text()) : "");
8633
8634	  $.fancybox.open({
8635		src: instance.translate(instance, tpl),
8636		type: "html",
8637		opts: {
8638		  touch: false,
8639		  animationEffect: false,
8640		  afterLoad: function (shareInstance, shareCurrent) {
8641			// Close self if parent instance is closing
8642			instance.$refs.container.one("beforeClose.fb", function () {
8643			  shareInstance.close(null, 0);
8644			});
8645
8646			// Opening links in a popup window
8647			shareCurrent.$content.find(".fancybox-share__button").on('click',function () {
8648			  window.open(this.href, "Share", "width=550, height=450");
8649			  return false;
8650			});
8651		  },
8652		  mobile: {
8653			autoFocus: false
8654		  }
8655		}
8656	  });
8657	});
8658  })(document, jQuery);
8659  // ==========================================================================
8660  //
8661  // Hash
8662  // Enables linking to each modal
8663  //
8664  // ==========================================================================
8665  (function (window, document, $) {
8666	"use strict";
8667
8668	// Simple $.escapeSelector polyfill (for jQuery prior v3)
8669	if (!$.escapeSelector) {
8670	  $.escapeSelector = function (sel) {
8671		var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
8672		var fcssescape = function (ch, asCodePoint) {
8673		  if (asCodePoint) {
8674			// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
8675			if (ch === "\0") {
8676			  return "\uFFFD";
8677			}
8678
8679			// Control characters and (dependent upon position) numbers get escaped as code points
8680			return ch.slice(0, -1) + "\\" + ch.charCodeAt(ch.length - 1).toString(16) + " ";
8681		  }
8682
8683		  // Other potentially-special ASCII characters get backslash-escaped
8684		  return "\\" + ch;
8685		};
8686
8687		return (sel + "").replace(rcssescape, fcssescape);
8688	  };
8689	}
8690
8691	// Get info about gallery name and current index from url
8692	function parseUrl() {
8693	  var hash = window.location.hash.substr(1),
8694		rez = hash.split("-"),
8695		index = rez.length > 1 && /^\+?\d+$/.test(rez[rez.length - 1]) ? parseInt(rez.pop(-1), 10) || 1 : 1,
8696		gallery = rez.join("-");
8697
8698	  return {
8699		hash: hash,
8700		/* Index is starting from 1 */
8701		index: index < 1 ? 1 : index,
8702		gallery: gallery
8703	  };
8704	}
8705
8706	// Trigger click evnt on links to open new fancyBox instance
8707	function triggerFromUrl(url) {
8708	  if (url.gallery !== "") {
8709		// If we can find element matching 'data-fancybox' atribute,
8710		// then triggering click event should start fancyBox
8711		$("[data-fancybox='" + $.escapeSelector(url.gallery) + "']")
8712		  .eq(url.index - 1)
8713		  .focus()
8714		  .trigger("click.fb-start");
8715	  }
8716	}
8717
8718	// Get gallery name from current instance
8719	function getGalleryID(instance) {
8720	  var opts, ret;
8721
8722	  if (!instance) {
8723		return false;
8724	  }
8725
8726	  opts = instance.current ? instance.current.opts : instance.opts;
8727	  ret = opts.hash || (opts.$orig ? opts.$orig.data("fancybox") || opts.$orig.data("fancybox-trigger") : "");
8728
8729	  return ret === "" ? false : ret;
8730	}
8731
8732	// Start when DOM becomes ready
8733	$(function () {
8734	  if ( $.fancybox.version != '3.5.7' ) {
8735		  return;
8736	  }
8737
8738	  // Check if user has disabled this module
8739	  if ($.fancybox.defaults.hash === false) {
8740		return;
8741	  }
8742
8743	  // Update hash when opening/closing fancyBox
8744	  $(document).on({
8745		"onInit.fb": function (e, instance) {
8746		  var url, gallery;
8747
8748		  if (instance.group[instance.currIndex].opts.hash === false) {
8749			return;
8750		  }
8751
8752		  url = parseUrl();
8753		  gallery = getGalleryID(instance);
8754
8755		  // Make sure gallery start index matches index from hash
8756		  if (gallery && url.gallery && gallery == url.gallery) {
8757			instance.currIndex = url.index - 1;
8758		  }
8759		},
8760
8761		"beforeShow.fb": function (e, instance, current, firstRun) {
8762		  var gallery;
8763
8764		  if (!current || current.opts.hash === false) {
8765			return;
8766		  }
8767
8768		  // Check if need to update window hash
8769		  gallery = getGalleryID(instance);
8770
8771		  if (!gallery) {
8772			return;
8773		  }
8774
8775		  // Variable containing last hash value set by fancyBox
8776		  // It will be used to determine if fancyBox needs to close after hash change is detected
8777		  instance.currentHash = gallery + (instance.group.length > 1 ? "-" + (current.index + 1) : "");
8778
8779		  // If current hash is the same (this instance most likely is opened by hashchange), then do nothing
8780		  if (window.location.hash === "#" + instance.currentHash) {
8781			return;
8782		  }
8783
8784		  if (firstRun && !instance.origHash) {
8785			instance.origHash = window.location.hash;
8786		  }
8787
8788		  if (instance.hashTimer) {
8789			clearTimeout(instance.hashTimer);
8790		  }
8791
8792		  // Update hash
8793		  instance.hashTimer = setTimeout(function () {
8794			if ("replaceState" in window.history) {
8795			  window.history[firstRun ? "pushState" : "replaceState"]({},
8796				document.title,
8797				window.location.pathname + window.location.search + "#" + instance.currentHash
8798			  );
8799
8800			  if (firstRun) {
8801				instance.hasCreatedHistory = true;
8802			  }
8803			} else {
8804			  window.location.hash = instance.currentHash;
8805			}
8806
8807			instance.hashTimer = null;
8808		  }, 300);
8809		},
8810
8811		"beforeClose.fb": function (e, instance, current) {
8812		  if (!current || current.opts.hash === false) {
8813			return;
8814		  }
8815
8816		  clearTimeout(instance.hashTimer);
8817
8818		  // Goto previous history entry
8819		  if (instance.currentHash && instance.hasCreatedHistory) {
8820			window.history.back();
8821		  } else if (instance.currentHash) {
8822			if ("replaceState" in window.history) {
8823			  window.history.replaceState({}, document.title, window.location.pathname + window.location.search + (instance.origHash || ""));
8824			} else {
8825			  window.location.hash = instance.origHash;
8826			}
8827		  }
8828
8829		  instance.currentHash = null;
8830		}
8831	  });
8832
8833	  // Check if need to start/close after url has changed
8834	  $(window).on("hashchange.fb", function () {
8835		var url = parseUrl(),
8836		  fb = null;
8837
8838		// Find last fancyBox instance that has "hash"
8839		$.each(
8840		  $(".fancybox-container")
8841		  .get()
8842		  .reverse(),
8843		  function (index, value) {
8844			var tmp = $(value).data("FancyBox");
8845
8846			if (tmp && tmp.currentHash) {
8847			  fb = tmp;
8848			  return false;
8849			}
8850		  }
8851		);
8852
8853		if (fb) {
8854		  // Now, compare hash values
8855		  if (fb.currentHash !== url.gallery + "-" + url.index && !(url.index === 1 && fb.currentHash == url.gallery)) {
8856			fb.currentHash = null;
8857
8858			fb.close();
8859		  }
8860		} else if (url.gallery !== "") {
8861		  triggerFromUrl(url);
8862		}
8863	  });
8864
8865	  // Check current hash and trigger click event on matching element to start fancyBox, if needed
8866	  setTimeout(function () {
8867		if ( $.fancybox.version != '3.5.7' ) {
8868			return;
8869		}
8870
8871		if (!$.fancybox.getInstance()) {
8872		  triggerFromUrl(parseUrl());
8873		}
8874	  }, 50);
8875	});
8876  })(window, document, jQuery);
8877  // ==========================================================================
8878  //
8879  // Wheel
8880  // Basic mouse weheel support for gallery navigation
8881  //
8882  // ==========================================================================
8883  (function (document, $) {
8884	"use strict";
8885
8886	var prevTime = new Date().getTime();
8887
8888	$(document).on({
8889	  "onInit.fb": function (e, instance, current) {
8890		instance.$refs.stage.on("mousewheel DOMMouseScroll wheel MozMousePixelScroll", function (e) {
8891		  var current = instance.current,
8892			currTime = new Date().getTime();
8893
8894		  if (instance.group.length < 2 || current.opts.wheel === false || (current.opts.wheel === "auto" && current.type !== "image")) {
8895			return;
8896		  }
8897
8898		  e.preventDefault();
8899		  e.stopPropagation();
8900
8901		  if (current.$slide.hasClass("fancybox-animated")) {
8902			return;
8903		  }
8904
8905		  e = e.originalEvent || e;
8906
8907		  if (currTime - prevTime < 250) {
8908			return;
8909		  }
8910
8911		  prevTime = currTime;
8912
8913		  instance[(-e.deltaY || -e.deltaX || e.wheelDelta || -e.detail) < 0 ? "next" : "previous"]();
8914		});
8915	  }
8916	});
8917  })(document, jQuery);
8918
8919;
8920(function ($, window, document, undefined) {
8921
8922  var pluginName = "MegaMenu",
8923    defaults = {
8924      propertyName: "value"
8925    };
8926
8927  // Set delay time for mouseout
8928  var delayOut = 400; // Default delay time is 200
8929
8930  // the list of menus
8931  var menus = [];
8932
8933  function CustomMenu(element, options) {
8934    this.element = element;
8935
8936    this.options = $.extend({}, defaults, options);
8937
8938    this._defaults = defaults;
8939    this._name = pluginName;
8940
8941    this.init();
8942  }
8943
8944  CustomMenu.prototype = {
8945    isOpen: false,
8946    timeout: null,
8947    init: function () {
8948
8949      var that = this;
8950
8951      $(this).each(function(index, menu) {
8952        that.node = menu.element;
8953        that.addListeners(menu.element);
8954
8955        var $menu = $(menu.element);
8956        $menu.addClass("dropdownJavascript");
8957        menus.push(menu.element);
8958
8959        $menu.find('ul > li').each(function(index, submenu) {
8960          if ($(submenu).find('ul').length > 0 ) {
8961            $(submenu).addClass('with-menu');
8962          }
8963        });
8964      });
8965    },
8966    addListeners: function(menu) {
8967      var that = this;
8968      $(menu).on('mouseover',function(e) {
8969        that.handleMouseOver.call(that, e);
8970      }).on('mouseout',function(e) {
8971          that.handleMouseOut.call(that, e);
8972        });
8973    },
8974    handleMouseOver: function (e) {
8975      var that = this;
8976      // clear the timeout
8977      this.clearTimeout();
8978
8979      // find the parent list item
8980      //var item = ('target' in e ? e.target : e.srcElement);
8981      var item = e.target || e.srcElement;
8982      while (item.nodeName != 'LI' && item != this.node) {
8983        item = item.parentNode;
8984      }
8985
8986      // if the target is within a list item, set the timeout
8987      if (item.nodeName == 'LI') {
8988        this.toOpen = item;
8989        this.timeout = setTimeout(function() {
8990          that.open.call(that);
8991        }, this.options.delay);
8992      }
8993
8994    },
8995    handleMouseOut: function () {
8996      var that = this;
8997      // clear the timeout
8998      this.clearTimeout();
8999
9000      // Check mouseout delay overriding
9001      var _delayOut = this.options.delay;
9002      if ( delayOut ) {
9003        _delayOut = delayOut;
9004      }
9005
9006      this.timeout = setTimeout(function() {
9007        that.close.call(that);
9008      }, _delayOut );
9009
9010    },
9011    clearTimeout: function () {
9012
9013      // clear the timeout
9014      if (this.timeout) {
9015        clearTimeout(this.timeout);
9016        this.timeout = null;
9017      }
9018
9019    },
9020    open: function () {
9021
9022      var that = this;
9023      // store that the menu is open
9024      this.isOpen = true;
9025
9026      // loop over the list items with the same parent
9027      var items = $(this.toOpen).parent().children('li');
9028      $(items).each(function(index, item) {
9029        $(item).find("ul").each(function(index, submenu) {
9030          if (item != that.toOpen) {
9031            // close the submenu
9032            $(item).removeClass("dropdownOpen");
9033            that.close(item);
9034
9035          } else if (!$(item).hasClass('dropdownOpen')) {
9036
9037            // open the submenu
9038            //if ( !$(item).parents('li').hasClass('has-mega-menu') ) {
9039              $(item).addClass("dropdownOpen");
9040            //}
9041
9042
9043            // determine the location of the edges of the submenu
9044            var left = 0;
9045            var node = submenu;
9046            while (node) {
9047              //abs is because when you make menus right to left
9048              //the offsetLeft would be negative
9049              left += Math.abs(node.offsetLeft);
9050              node = node.offsetParent;
9051            }
9052            var right = left + submenu.offsetWidth;
9053
9054
9055            //We should refactor this code to execute only when menu is vertical
9056            var menuHeight = $(submenu).outerHeight();
9057            var parentTop = $(submenu).offset().top - $(window).scrollTop();
9058            var totalHeight = menuHeight + parentTop;
9059            var windowHeight = window.innerHeight;
9060
9061           /* if (totalHeight > windowHeight) {
9062              var bestTop = (windowHeight - totalHeight) - 20;
9063              $(submenu).css('margin-top', bestTop + "px");
9064            }*/
9065
9066            //remove any previous classes
9067            $(item).removeClass('dropdownRightToLeft');
9068
9069            // move the submenu to the right of the item if appropriate
9070            if (left < 0) $(item).addClass('dropdownLeftToRight');
9071
9072            // move the submenu to the left of the item if appropriate
9073            if (right > document.body.clientWidth) {
9074              $(item).addClass('dropdownRightToLeft');
9075            }
9076
9077          }
9078        });
9079      });
9080
9081    },
9082
9083
9084    close: function (node) {
9085
9086      // if no node was specified, close all menus
9087      if (!node) {
9088        this.isOpen = false;
9089        node = this.node;
9090      }
9091
9092      // loop over the items, closing their submenus
9093      $(node).find('li').each(function(index, item) {
9094        $(item).removeClass('dropdownOpen');
9095      });
9096
9097    }
9098  };
9099
9100  $.fn[pluginName] = function (options) {
9101    return this.each(function () {
9102      if (!$.data(this, "plugin_" + pluginName)) {
9103        $.data(this, "plugin_" + pluginName,
9104          new CustomMenu(this, options));
9105      }
9106    });
9107  };
9108
9109})(jQuery, window, document);
9110
9111/*!
9112 * modernizr v3.3.1
9113 * Build https://modernizr.com/download?-cssanimations-csstransitions-touchevents-domprefixes-prefixed-prefixes-setclasses-shiv-testallprops-testprop-teststyles-dontmin
9114 *
9115 * Copyright (c)
9116 *  Faruk Ates
9117 *  Paul Irish
9118 *  Alex Sexton
9119 *  Ryan Seddon
9120 *  Patrick Kettner
9121 *  Stu Cox
9122 *  Richard Herrera
9123
9124 * MIT License
9125 */
9126
9127/*
9128 * Modernizr tests which native CSS3 and HTML5 features are available in the
9129 * current UA and makes the results available to you in two ways: as properties on
9130 * a global `Modernizr` object, and as classes on the `<html>` element. This
9131 * information allows you to progressively enhance your pages with a granular level
9132 * of control over the experience.
9133*/
9134
9135;(function(window, document, undefined){
9136  var classes = [];
9137  
9138
9139  var tests = [];
9140  
9141
9142  /**
9143   *
9144   * ModernizrProto is the constructor for Modernizr
9145   *
9146   * @class
9147   * @access public
9148   */
9149
9150  var ModernizrProto = {
9151    // The current version, dummy
9152    _version: '3.3.1',
9153
9154    // Any settings that don't work as separate modules
9155    // can go in here as configuration.
9156    _config: {
9157      'classPrefix': '',
9158      'enableClasses': true,
9159      'enableJSClass': true,
9160      'usePrefixes': true
9161    },
9162
9163    // Queue of tests
9164    _q: [],
9165
9166    // Stub these for people who are listening
9167    on: function(test, cb) {
9168      // I don't really think people should do this, but we can
9169      // safe guard it a bit.
9170      // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.
9171      // This is in case people listen to synchronous tests. I would leave it out,
9172      // but the code to *disallow* sync tests in the real version of this
9173      // function is actually larger than this.
9174      var self = this;
9175      setTimeout(function() {
9176        cb(self[test]);
9177      }, 0);
9178    },
9179
9180    addTest: function(name, fn, options) {
9181      tests.push({name: name, fn: fn, options: options});
9182    },
9183
9184    addAsyncTest: function(fn) {
9185      tests.push({name: null, fn: fn});
9186    }
9187  };
9188
9189  
9190
9191  // Fake some of Object.create so we can force non test results to be non "own" properties.
9192  var Modernizr = function() {};
9193  Modernizr.prototype = ModernizrProto;
9194
9195  // Leak modernizr globally when you `require` it rather than force it here.
9196  // Overwrite name so constructor name is nicer :D
9197  Modernizr = new Modernizr();
9198
9199  
9200
9201  /**
9202   * List of property values to set for css tests. See ticket #21
9203   * http://git.io/vUGl4
9204   *
9205   * @memberof Modernizr
9206   * @name Modernizr._prefixes
9207   * @optionName Modernizr._prefixes
9208   * @optionProp prefixes
9209   * @access public
9210   * @example
9211   *
9212   * Modernizr._prefixes is the internal list of prefixes that we test against
9213   * inside of things like [prefixed](#modernizr-prefixed) and [prefixedCSS](#-code-modernizr-prefixedcss). It is simply
9214   * an array of kebab-case vendor prefixes you can use within your code.
9215   *
9216   * Some common use cases include
9217   *
9218   * Generating all possible prefixed version of a CSS property
9219   * ```js
9220   * var rule = Modernizr._prefixes.join('transform: rotate(20deg); ');
9221   *
9222   * rule === 'transform: rotate(20deg); webkit-transform: rotate(20deg); moz-transform: rotate(20deg); o-transform: rotate(20deg); ms-transform: rotate(20deg);'
9223   * ```
9224   *
9225   * Generating all possible prefixed version of a CSS value
9226   * ```js
9227   * rule = 'display:' +  Modernizr._prefixes.join('flex; display:') + 'flex';
9228   *
9229   * rule === 'display:flex; display:-webkit-flex; display:-moz-flex; display:-o-flex; display:-ms-flex; display:flex'
9230   * ```
9231   */
9232
9233  // we use ['',''] rather than an empty array in order to allow a pattern of .`join()`ing prefixes to test
9234  // values in feature detects to continue to work
9235  var prefixes = (ModernizrProto._config.usePrefixes ? ' -webkit- -moz- -o- -ms- '.split(' ') : ['','']);
9236
9237  // expose these for the plugin API. Look in the source for how to join() them against your input
9238  ModernizrProto._prefixes = prefixes;
9239
9240  
9241
9242  /**
9243   * is returns a boolean if the typeof an obj is exactly type.
9244   *
9245   * @access private
9246   * @function is
9247   * @param {*} obj - A thing we want to check the type of
9248   * @param {string} type - A string to compare the typeof against
9249   * @returns {boolean}
9250   */
9251
9252  function is(obj, type) {
9253    return typeof obj === type;
9254  }
9255  ;
9256
9257  /**
9258   * Run through all tests and detect their support in the current UA.
9259   *
9260   * @access private
9261   */
9262
9263  function testRunner() {
9264    var featureNames;
9265    var feature;
9266    var aliasIdx;
9267    var result;
9268    var nameIdx;
9269    var featureName;
9270    var featureNameSplit;
9271
9272    for (var featureIdx in tests) {
9273      if (tests.hasOwnProperty(featureIdx)) {
9274        featureNames = [];
9275        feature = tests[featureIdx];
9276        // run the test, throw the return value into the Modernizr,
9277        // then based on that boolean, define an appropriate className
9278        // and push it into an array of classes we'll join later.
9279        //
9280        // If there is no name, it's an 'async' test that is run,
9281        // but not directly added to the object. That should
9282        // be done with a post-run addTest call.
9283        if (feature.name) {
9284          featureNames.push(feature.name.toLowerCase());
9285
9286          if (feature.options && feature.options.aliases && feature.options.aliases.length) {
9287            // Add all the aliases into the names list
9288            for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {
9289              featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());
9290            }
9291          }
9292        }
9293
9294        // Run the test, or use the raw value if it's not a function
9295        result = is(feature.fn, 'function') ? feature.fn() : feature.fn;
9296
9297
9298        // Set each of the names on the Modernizr object
9299        for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {
9300          featureName = featureNames[nameIdx];
9301          // Support dot properties as sub tests. We don't do checking to make sure
9302          // that the implied parent tests have been added. You must call them in
9303          // order (either in the test, or make the parent test a dependency).
9304          //
9305          // Cap it to TWO to make the logic simple and because who needs that kind of subtesting
9306          // hashtag famous last words
9307          featureNameSplit = featureName.split('.');
9308
9309          if (featureNameSplit.length === 1) {
9310            Modernizr[featureNameSplit[0]] = result;
9311          } else {
9312            // cast to a Boolean, if not one already
9313            /* jshint -W053 */
9314            if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
9315              Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
9316            }
9317
9318            Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;
9319          }
9320
9321          classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));
9322        }
9323      }
9324    }
9325  }
9326  ;
9327
9328  /**
9329   * docElement is a convenience wrapper to grab the root element of the document
9330   *
9331   * @access private
9332   * @returns {HTMLElement|SVGElement} The root element of the document
9333   */
9334
9335  var docElement = document.documentElement;
9336  
9337
9338  /**
9339   * A convenience helper to check if the document we are running in is an SVG document
9340   *
9341   * @access private
9342   * @returns {boolean}
9343   */
9344
9345  var isSVG = docElement.nodeName.toLowerCase() === 'svg';
9346  
9347
9348  /**
9349   * setClasses takes an array of class names and adds them to the root element
9350   *
9351   * @access private
9352   * @function setClasses
9353   * @param {string[]} classes - Array of class names
9354   */
9355
9356  // Pass in an and array of class names, e.g.:
9357  //  ['no-webp', 'borderradius', ...]
9358  function setClasses(classes) {
9359    var className = docElement.className;
9360    var classPrefix = Modernizr._config.classPrefix || '';
9361
9362    if (isSVG) {
9363      className = className.baseVal;
9364    }
9365
9366    // Change `no-js` to `js` (independently of the `enableClasses` option)
9367    // Handle classPrefix on this too
9368    if (Modernizr._config.enableJSClass) {
9369      var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)');
9370      className = className.replace(reJS, '$1' + classPrefix + 'js$2');
9371    }
9372
9373    if (Modernizr._config.enableClasses) {
9374      // Add the new classes
9375      className += ' ' + classPrefix + classes.join(' ' + classPrefix);
9376      isSVG ? docElement.className.baseVal = className : docElement.className = className;
9377    }
9378
9379  }
9380
9381  ;
9382
9383/**
9384  * @optionName html5shiv
9385  * @optionProp html5shiv
9386  */
9387
9388  // Take the html5 variable out of the html5shiv scope so we can return it.
9389  var html5;
9390  if (!isSVG) {
9391    /**
9392     * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
9393     */
9394    ;(function(window, document) {
9395      /*jshint evil:true */
9396      /** version */
9397      var version = '3.7.3';
9398
9399      /** Preset options */
9400      var options = window.html5 || {};
9401
9402      /** Used to skip problem elements */
9403      var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
9404
9405      /** Not all elements can be cloned in IE **/
9406      var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
9407
9408      /** Detect whether the browser supports default html5 styles */
9409      var supportsHtml5Styles;
9410
9411      /** Name of the expando, to work with multiple documents or to re-shiv one document */
9412      var expando = '_html5shiv';
9413
9414      /** The id for the the documents expando */
9415      var expanID = 0;
9416
9417      /** Cached data for each document */
9418      var expandoData = {};
9419
9420      /** Detect whether the browser supports unknown elements */
9421      var supportsUnknownElements;
9422
9423      (function() {
9424        try {
9425          var a = document.createElement('a');
9426          a.innerHTML = '<xyz></xyz>';
9427          //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
9428          supportsHtml5Styles = ('hidden' in a);
9429
9430          supportsUnknownElements = a.childNodes.length == 1 || (function() {
9431            // assign a false positive if unable to shiv
9432            (document.createElement)('a');
9433            var frag = document.createDocumentFragment();
9434            return (
9435              typeof frag.cloneNode == 'undefined' ||
9436                typeof frag.createDocumentFragment == 'undefined' ||
9437                typeof frag.createElement == 'undefined'
9438            );
9439          }());
9440        } catch(e) {
9441          // assign a false positive if detection fails => unable to shiv
9442          supportsHtml5Styles = true;
9443          supportsUnknownElements = true;
9444        }
9445
9446      }());
9447
9448      /*--------------------------------------------------------------------------*/
9449
9450      /**
9451       * Creates a style sheet with the given CSS text and adds it to the document.
9452       * @private
9453       * @param {Document} ownerDocument The document.
9454       * @param {String} cssText The CSS text.
9455       * @returns {StyleSheet} The style element.
9456       */
9457      function addStyleSheet(ownerDocument, cssText) {
9458        var p = ownerDocument.createElement('p'),
9459          parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
9460
9461        p.innerHTML = 'x<style>' + cssText + '</style>';
9462        return parent.insertBefore(p.lastChild, parent.firstChild);
9463      }
9464
9465      /**
9466       * Returns the value of `html5.elements` as an array.
9467       * @private
9468       * @returns {Array} An array of shived element node names.
9469       */
9470      function getElements() {
9471        var elements = html5.elements;
9472        return typeof elements == 'string' ? elements.split(' ') : elements;
9473      }
9474
9475      /**
9476       * Extends the built-in list of html5 elements
9477       * @memberOf html5
9478       * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
9479       * @param {Document} ownerDocument The context document.
9480       */
9481      function addElements(newElements, ownerDocument) {
9482        var elements = html5.elements;
9483        if(typeof elements != 'string'){
9484          elements = elements.join(' ');
9485        }
9486        if(typeof newElements != 'string'){
9487          newElements = newElements.join(' ');
9488        }
9489        html5.elements = elements +' '+ newElements;
9490        shivDocument(ownerDocument);
9491      }
9492
9493      /**
9494       * Returns the data associated to the given document
9495       * @private
9496       * @param {Document} ownerDocument The document.
9497       * @returns {Object} An object of data.
9498       */
9499      function getExpandoData(ownerDocument) {
9500        var data = expandoData[ownerDocument[expando]];
9501        if (!data) {
9502          data = {};
9503          expanID++;
9504          ownerDocument[expando] = expanID;
9505          expandoData[expanID] = data;
9506        }
9507        return data;
9508      }
9509
9510      /**
9511       * returns a shived element for the given nodeName and document
9512       * @memberOf html5
9513       * @param {String}
vendor: 4,418 bytes, lines 9513-9624
9513 nodeName name of the element
9514       * @param {Document|DocumentFragment} ownerDocument The context document.
9515       * @returns {Object} The shived element.
9516       */
9517      function createElement(nodeName, ownerDocument, data){
9518        if (!ownerDocument) {
9519          ownerDocument = document;
9520        }
9521        if(supportsUnknownElements){
9522          return ownerDocument.createElement(nodeName);
9523        }
9524        if (!data) {
9525          data = getExpandoData(ownerDocument);
9526        }
9527        var node;
9528
9529        if (data.cache[nodeName]) {
9530          node = data.cache[nodeName].cloneNode();
9531        } else if (saveClones.test(nodeName)) {
9532          node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
9533        } else {
9534          node = data.createElem(nodeName);
9535        }
9536
9537        // Avoid adding some elements to fragments in IE < 9 because
9538        // * Attributes like `name` or `type` cannot be set/changed once an element
9539        //   is inserted into a document/fragment
9540        // * Link elements with `src` attributes that are inaccessible, as with
9541        //   a 403 response, will cause the tab/window to crash
9542        // * Script elements appended to fragments will execute when their `src`
9543        //   or `text` property is set
9544        return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
9545      }
9546
9547      /**
9548       * returns a shived DocumentFragment for the given document
9549       * @memberOf html5
9550       * @param {Document} ownerDocument The context document.
9551       * @returns {Object} The shived DocumentFragment.
9552       */
9553      function createDocumentFragment(ownerDocument, data){
9554        if (!ownerDocument) {
9555          ownerDocument = document;
9556        }
9557        if(supportsUnknownElements){
9558          return ownerDocument.createDocumentFragment();
9559        }
9560        data = data || getExpandoData(ownerDocument);
9561        var clone = data.frag.cloneNode(),
9562          i = 0,
9563          elems = getElements(),
9564          l = elems.length;
9565        for(;i<l;i++){
9566          clone.createElement(elems[i]);
9567        }
9568        return clone;
9569      }
9570
9571      /**
9572       * Shivs the `createElement` and `createDocumentFragment` methods of the document.
9573       * @private
9574       * @param {Document|DocumentFragment} ownerDocument The document.
9575       * @param {Object} data of the document.
9576       */
9577      function shivMethods(ownerDocument, data) {
9578        if (!data.cache) {
9579          data.cache = {};
9580          data.createElem = ownerDocument.createElement;
9581          data.createFrag = ownerDocument.createDocumentFragment;
9582          data.frag = data.createFrag();
9583        }
9584
9585
9586        ownerDocument.createElement = function(nodeName) {
9587          //abort shiv
9588          if (!html5.shivMethods) {
9589            return data.createElem(nodeName);
9590          }
9591          return createElement(nodeName, ownerDocument, data);
9592        };
9593
9594        ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
9595                                                        'var n=f.cloneNode(),c=n.createElement;' +
9596                                                        'h.shivMethods&&(' +
9597                                                        // unroll the `createElement` calls
9598                                                        getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
9599          data.createElem(nodeName);
9600          data.frag.createElement(nodeName);
9601          return 'c("' + nodeName + '")';
9602        }) +
9603          ');return n}'
9604                                                       )(html5, data.frag);
9605      }
9606
9607      /*--------------------------------------------------------------------------*/
9608
9609      /**
9610       * Shivs the given document.
9611       * @memberOf html5
9612       * @param {Document} ownerDocument The document to shiv.
9613       * @returns {Document} The shived document.
9614       */
9615      function shivDocument(ownerDocument) {
9616        if (!ownerDocument) {
9617          ownerDocument = document;
9618        }
9619        var data = getExpandoData(ownerDocument);
9620
9621        if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
9622          data.hasCSS = !!addStyleSheet(ownerDocument,
9623                                        // corrects block display not defined in IE6/7/8/9
9624                                        'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{dis
9624play:block}' +
9625                                        // adds styling not present in IE6/7/8/9
9626                                        'mark{background:#FF0;color:#000}' +
9627                                        // hides non-rendered elements
9628                                        'template{display:none}'
9629                                       );
9630        }
9631        if (!supportsUnknownElements) {
9632          shivMethods(ownerDocument, data);
9633        }
9634        return ownerDocument;
9635      }
9636
9637      /*--------------------------------------------------------------------------*/
9638
9639      /**
9640       * The `html5` object is exposed so that more elements can be shived and
9641       * existing shiving can be detected on iframes.
9642       * @type Object
9643       * @example
9644       *
9645       * // options can be changed before the script is included
9646       * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
9647       */
9648      var html5 = {
9649
9650        /**
9651         * An array or space separated string of node names of the elements to shiv.
9652         * @memberOf html5
9653         * @type Array|String
9654         */
9655        'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
9656
9657        /**
9658         * current version of html5shiv
9659         */
9660        'version': version,
9661
9662        /**
9663         * A flag to indicate that the HTML5 style sheet should be inserted.
9664         * @memberOf html5
9665         * @type Boolean
9666         */
9667        'shivCSS': (options.shivCSS !== false),
9668
9669        /**
9670         * Is equal to true if a browser supports creating unknown/HTML5 elements
9671         * @memberOf html5
9672         * @type boolean
9673         */
9674        'supportsUnknownElements': supportsUnknownElements,
9675
9676        /**
9677         * A flag to indicate that the document's `createElement` and `createDocumentFragment`
9678         * methods should be overwritten.
9679         * @memberOf html5
9680         * @type Boolean
9681         */
9682        'shivMethods': (options.shivMethods !== false),
9683
9684        /**
9685         * A string to describe the type of `html5` object ("default" or "default print").
9686         * @memberOf html5
9687         * @type String
9688         */
9689        'type': 'default',
9690
9691        // shivs the document according to the specified `html5` object options
9692        'shivDocument': shivDocument,
9693
9694        //creates a shived element
9695        createElement: createElement,
9696
9697        //creates a shived documentFragment
9698        createDocumentFragment: createDocumentFragment,
9699
9700        //extends list of elements
9701        addElements: addElements
9702      };
9703
9704      /*--------------------------------------------------------------------------*/
9705
9706      // expose html5
9707      window.html5 = html5;
9708
9709      // shiv the document
9710      shivDocument(document);
9711
9712      if(typeof module == 'object' && module.exports){
9713        module.exports = html5;
9714      }
9715
9716    }(typeof window !== "undefined" ? window : this, document));
9717  }
9718;
9719
9720  /**
9721   * If the browsers follow the spec, then they would expose vendor-specific style as:
9722   *   elem.style.WebkitBorderRadius
9723   * instead of something like the following, which would be technically incorrect:
9724   *   elem.style.webkitBorderRadius
9725
9726   * Webkit ghosts their properties in lowercase but Opera & Moz do not.
9727   * Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
9728   *   erik.eae.net/archives/2008/03/10/21.48.10/
9729
9730   * More here: github.com/Modernizr/Modernizr/issues/issue/21
9731   *
9732   * @access private
9733   * @returns {string} The string representing the vendor-specific style properties
9734   */
9735
9736  var omPrefixes = 'Moz O ms Webkit';
9737  
9738
9739  /**
9740   * List of JavaScript DOM values used for tests
9741   *
9742   * @memberof Modernizr
9743   * @name Modernizr._domPrefixes
9744   * @optionName Modernizr._domPrefixes
9745   * @optionProp domPrefixes
9746   * @access public
9747   * @example
9748   *
9749   * Modernizr._domPrefixes is exactly the same as [_prefixes](#modernizr-_prefixes), but rather
9750   * than kebab-case properties, all properties are their Capitalized variant
9751   *
9752   * ```js
9753   * Modernizr._domPrefixes === [ "Moz", "O", "ms", "Webkit" ];
9754   * ```
9755   */
9756
9757  var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []);
9758  ModernizrProto._domPrefixes = domPrefixes;
9759  
9760
9761  /**
9762   * cssToDOM takes a kebab-case string and converts it to camelCase
9763   * e.g. box-sizing -> boxSizing
9764   *
9765   * @access private
9766   * @function cssToDOM
9767   * @param {string} name - String name of kebab-case prop we want to convert
9768   * @returns {string} The camelCase version of the supplied name
9769   */
9770
9771  function cssToDOM(name) {
9772    return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {
9773      return m1 + m2.toUpperCase();
9774    }).replace(/^-/, '');
9775  }
9776  ;
9777
9778  var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []);
9779  ModernizrProto._cssomPrefixes = cssomPrefixes;
9780  
9781
9782  /**
9783   * atRule returns a given CSS property at-rule (eg @keyframes), possibly in
9784   * some prefixed form, or false, in the case of an unsupported rule
9785   *
9786   * @memberof Modernizr
9787   * @name Modernizr.atRule
9788   * @optionName Modernizr.atRule()
9789   * @optionProp atRule
9790   * @access public
9791   * @function atRule
9792   * @param {string} prop - String name of the @-rule to test for
9793   * @returns {string|boolean} The string representing the (possibly prefixed)
9794   * valid version of the @-rule, or `false` when it is unsupported.
9795   * @example
9796   * ```js
9797   *  var keyframes = Modernizr.atRule('@keyframes');
9798   *
9799   *  if (keyframes) {
9800   *    // keyframes are supported
9801   *    // could be `@-webkit-keyframes` or `@keyframes`
9802   *  } else {
9803   *    // keyframes === `false`
9804   *  }
9805   * ```
9806   *
9807   */
9808
9809  var atRule = function(prop) {
9810    var length = prefixes.length;
9811    var cssrule = window.CSSRule;
9812    var rule;
9813
9814    if (typeof cssrule === 'undefined') {
9815      return undefined;
9816    }
9817
9818    if (!prop) {
9819      return false;
9820    }
9821
9822    // remove literal @ from beginning of provided property
9823    prop = prop.replace(/^@/, '');
9824
9825    // CSSRules use underscores instead of dashes
9826    rule = prop.replace(/-/g, '_').toUpperCase() + '_RULE';
9827
9828    if (rule in cssrule) {
9829      return '@' + prop;
9830    }
9831
9832    for (var i = 0; i < length; i++) {
9833      // prefixes gives us something like -o-, and we want O_
9834      var prefix = prefixes[i];
9835      var thisRule = prefix.toUpperCase() + '_' + rule;
9836
9837      if (thisRule in cssrule) {
9838        return '@-' + prefix.toLowerCase() + '-' + prop;
9839      }
9840    }
9841
9842    return false;
9843  };
9844
9845  ModernizrProto.atRule = atRule;
9846
9847  
9848
9849
9850  /**
9851   * contains checks to see if a string contains another string
9852   *
9853   * @access private
9854   * @function contains
9855   * @param {string} str - The string we want to check for substrings
9856   * @param {string} substr - The substring we want to search the first string for
9857   * @returns {boolean}
9858   */
9859
9860  function contains(str, substr) {
9861    return !!~('' + str).indexOf(substr);
9862  }
9863
9864  ;
9865
9866  /**
9867   * createElement is a convenience wrapper around document.createElement. Since we
9868   * use createElement all over the place, this allows for (slightly) smaller code
9869   * as well as abstracting away issues with creating elements in contexts other than
9870   * HTML documents (e.g. SVG documents).
9871   *
9872   * @access private
9873   * @function createElement
9874   * @returns {HTMLElement|SVGElement} An HTML or SVG element
9875   */
9876
9877  function createElement() {
9878    if (typeof document.createElement !== 'function') {
9879      // This is the case in IE7, where the type of createElement is "object".
9880      // For this reason, we cannot call apply() as Object is not a Function.
9881      return document.createElement(arguments[0]);
9882    } else if (isSVG) {
9883      return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);
9884    } else {
9885      return document.createElement.apply(document, arguments);
9886    }
9887  }
9888
9889  ;
9890
9891  /**
9892   * getBody returns the body of a document, or an element that can stand in for
9893   * the body if a real body does not exist
9894   *
9895   * @access private
9896   * @function getBody
9897   * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an
9898   * artificially created element that stands in for the body
9899   */
9900
9901  function getBody() {
9902    // After page load injecting a fake body doesn't work so check if body exists
9903    var body = document.body;
9904
9905    if (!body) {
9906      // Can't use the real body create a fake one.
9907      body = createElement(isSVG ? 'svg' : 'body');
9908      body.fake = true;
9909    }
9910
9911    return body;
9912  }
9913
9914  ;
9915
9916  /**
9917   * injectElementWithStyles injects an element with style element and some CSS rules
9918   *
9919   * @access private
9920   * @function injectElementWithStyles
9921   * @param {string} rule - String representing a css rule
9922   * @param {function} callback - A function that is used to test the injected element
9923   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
9924   * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes
9925   * @returns {boolean}
9926   */
9927
9928  function injectElementWithStyles(rule, callback, nodes, testnames) {
9929    var mod = 'modernizr';
9930    var style;
9931    var ret;
9932    var node;
9933    var docOverflow;
9934    var div = createElement('div');
9935    var body = getBody();
9936
9937    if (parseInt(nodes, 10)) {
9938      // In order not to give false positives we create a node for each test
9939      // This also allows the method to scale for unspecified uses
9940      while (nodes--) {
9941        node = createElement('div');
9942        node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
9943        div.appendChild(node);
9944      }
9945    }
9946
9947    style = createElement('style');
9948    style.type = 'text/css';
9949    style.id = 's' + mod;
9950
9951    // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.
9952    // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
9953    (!body.fake ? div : body).appendChild(style);
9954    body.appendChild(div);
9955
9956    if (style.styleSheet) {
9957      style.styleSheet.cssText = rule;
9958    } else {
9959      style.appendChild(document.createTextNode(rule));
9960    }
9961    div.id = mod;
9962
9963    if (body.fake) {
9964      //avoid crashing IE8, if background image is used
9965      body.style.background = '';
9966      //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
9967      body.style.overflow = 'hidden';
9968      docOverflow = docElement.style.overflow;
9969      docElement.style.overflow = 'hidden';
9970      docElement.appendChild(body);
9971    }
9972
9973    ret = callback(div, rule);
9974    // If this is done after page load we don't want to remove the body so check if body exists
9975    if (body.fake) {
9976      body.parentNode.removeChild(body);
9977      docElement.style.overflow = docOverflow;
9978      // Trigger layout so kinetic scrolling isn't disabled in iOS6+
9979      docElement.offsetHeight;
9980    } else {
9981      div.parentNode.removeChild(div);
9982    }
9983
9984    return !!ret;
9985
9986  }
9987
9988  ;
9989
9990  /**
9991   * testStyles injects an element with style element and some CSS rules
9992   *
9993   * @memberof Modernizr
9994   * @name Modernizr.testStyles
9995   * @optionName Modernizr.testStyles()
9996   * @optionProp testStyles
9997   * @access public
9998   * @function testStyles
9999   * @param {string} rule - String representing a css rule
10000   * @param {function} callback - A function that is used to test the injected element
10001   * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
10002   * @param {string[]}
10002 [testnames] - An array of strings that are used as ids for the additional nodes
10003   * @returns {boolean}
10004   * @example
10005   *
10006   * `Modernizr.testStyles` takes a CSS rule and injects it onto the current page
10007   * along with (possibly multiple) DOM elements. This lets you check for features
10008   * that can not be detected by simply checking the [IDL](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Interface_development_guide/IDL_interface_rules).
10009   *
10010   * ```js
10011   * Modernizr.testStyles('#modernizr { width: 9px; color: papayawhip; }', function(elem, rule) {
10012   *   // elem is the first DOM node in the page (by default #modernizr)
10013   *   // rule is the first argument you supplied - the CSS rule in string form
10014   *
10015   *   addTest('widthworks', elem.style.width === '9px')
10016   * });
10017   * ```
10018   *
10019   * If your test requires multiple nodes, you can include a third argument
10020   * indicating how many additional div elements to include on the page. The
10021   * additional nodes are injected as children of the `elem` that is returned as
10022   * the first argument to the callback.
10023   *
10024   * ```js
10025   * Modernizr.testStyles('#modernizr {width: 1px}; #modernizr2 {width: 2px}', function(elem) {
10026   *   document.getElementById('modernizr').style.width === '1px'; // true
10027   *   document.getElementById('modernizr2').style.width === '2px'; // true
10028   *   elem.firstChild === document.getElementById('modernizr2'); // true
10029   * }, 1);
10030   * ```
10031   *
10032   * By default, all of the additional elements have an ID of `modernizr[n]`, where
10033   * `n` is its index (e.g. the first additional, second overall is `#modernizr2`,
10034   * the second additional is `#modernizr3`, etc.).
10035   * If you want to have more meaningful IDs for your function, you can provide
10036   * them as the fourth argument, as an array of strings
10037   *
10038   * ```js
10039   * Modernizr.testStyles('#foo {width: 10px}; #bar {height: 20px}', function(elem) {
10040   *   elem.firstChild === document.getElementById('foo'); // true
10041   *   elem.lastChild === document.getElementById('bar'); // true
10042   * }, 2, ['foo', 'bar']);
10043   * ```
10044   *
10045   */
10046
10047  var testStyles = ModernizrProto.testStyles = injectElementWithStyles;
10048  
10049
10050  /**
10051   * fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill.
10052   *
10053   * @access private
10054   * @function fnBind
10055   * @param {function} fn - a function you want to change `this` reference to
10056   * @param {object} that - the `this` you want to call the function with
10057   * @returns {function} The wrapped version of the supplied function
10058   */
10059
10060  function fnBind(fn, that) {
10061    return function() {
10062      return fn.apply(that, arguments);
10063    };
10064  }
10065
10066  ;
10067
10068  /**
10069   * testDOMProps is a generic DOM property test; if a browser supports
10070   *   a certain property, it won't return undefined for it.
10071   *
10072   * @access private
10073   * @function testDOMProps
10074   * @param {array.<string>} props - An array of properties to test for
10075   * @param {object} obj - An object or Element you want to use to test the parameters again
10076   * @param {boolean|object} elem - An Element to bind the property lookup again. Use `false` to prevent the check
10077   */
10078  function testDOMProps(props, obj, elem) {
10079    var item;
10080
10081    for (var i in props) {
10082      if (props[i] in obj) {
10083
10084        // return the property name as a string
10085        if (elem === false) {
10086          return props[i];
10087        }
10088
10089        item = obj[props[i]];
10090
10091        // let's bind a function
10092        if (is(item, 'function')) {
10093          // bind to obj unless overriden
10094          return fnBind(item, elem || obj);
10095        }
10096
10097        // return the unbound function or obj or value
10098        return item;
10099      }
10100    }
10101    return false;
10102  }
10103
10104  ;
10105
10106  /**
10107   * Create our "modernizr" element that we do most feature tests on.
10108   *
10109   * @access private
10110   */
10111
10112  var modElem = {
10113    elem: createElement('modernizr')
10114  };
10115
10116  // Clean up this element
10117  Modernizr._q.push(function() {
10118    delete modElem.elem;
10119  });
10120
10121  
10122
10123  var mStyle = {
10124    style: modElem.elem.style
10125  };
10126
10127  // kill ref for gc, must happen before mod.elem is removed, so we unshift on to
10128  // the front of the queue.
10129  Modernizr._q.unshift(function() {
10130    delete mStyle.style;
10131  });
10132
10133  
10134
10135  /**
10136   * domToCSS takes a camelCase string and converts it to kebab-case
10137   * e.g. boxSizing -> box-sizing
10138   *
10139   * @access private
10140   * @function domToCSS
10141   * @param {string} name - String name of camelCase prop we want to convert
10142   * @returns {string} The kebab-case version of the supplied name
10143   */
10144
10145  function domToCSS(name) {
10146    return name.replace(/([A-Z])/g, function(str, m1) {
10147      return '-' + m1.toLowerCase();
10148    }).replace(/^ms-/, '-ms-');
10149  }
10150  ;
10151
10152  /**
10153   * nativeTestProps allows for us to use native feature detection functionality if available.
10154   * some prefixed form, or false, in the case of an unsupported rule
10155   *
10156   * @access private
10157   * @function nativeTestProps
10158   * @param {array} props - An array of property names
10159   * @param {string} value - A string representing the value we want to check via @supports
10160   * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise
10161   */
10162
10163  // Accepts a list of property names and a single value
10164  // Returns `undefined` if native detection not available
10165  function nativeTestProps(props, value) {
10166    var i = props.length;
10167    // Start with the JS API: http://www.w3.org/TR/css3-conditional/#the-css-interface
10168    if ('CSS' in window && 'supports' in window.CSS) {
10169      // Try every prefixed variant of the property
10170      while (i--) {
10171        if (window.CSS.supports(domToCSS(props[i]), value)) {
10172          return true;
10173        }
10174      }
10175      return false;
10176    }
10177    // Otherwise fall back to at-rule (for Opera 12.x)
10178    else if ('CSSSupportsRule' in window) {
10179      // Build a condition string for every prefixed variant
10180      var conditionText = [];
10181      while (i--) {
10182        conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');
10183      }
10184      conditionText = conditionText.join(' or ');
10185      return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {
10186        return getComputedStyle(node, null).position == 'absolute';
10187      });
10188    }
10189    return undefined;
10190  }
10191  ;
10192
10193  // testProps is a generic CSS / DOM property test.
10194
10195  // In testing support for a given CSS property, it's legit to test:
10196  //    `elem.style[styleName] !== undefined`
10197  // If the property is supported it will return an empty string,
10198  // if unsupported it will return undefined.
10199
10200  // We'll take advantage of this quick test and skip setting a style
10201  // on our modernizr element, but instead just testing undefined vs
10202  // empty string.
10203
10204  // Property names can be provided in either camelCase or kebab-case.
10205
10206  function testProps(props, prefixed, value, skipValueTest) {
10207    skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;
10208
10209    // Try native detect first
10210    if (!is(value, 'undefined')) {
10211      var result = nativeTestProps(props, value);
10212      if (!is(result, 'undefined')) {
10213        return result;
10214      }
10215    }
10216
10217    // Otherwise do it properly
10218    var afterInit, i, propsLength, prop, before;
10219
10220    // If we don't have a style element, that means we're running async or after
10221    // the core tests, so we'll need to create our own elements to use
10222
10223    // inside of an SVG element, in certain browsers, the `style` element is only
10224    // defined for valid tags. Therefore, if `modernizr` does not have one, we
10225    // fall back to a less used element and hope for the best.
10226    // for strict XHTML browsers the hardly used samp element is used
10227    var elems = ['modernizr', 'tspan', 'samp'];
10228    while (!mStyle.style && elems.length) {
10229      afterInit = true;
10230      mStyle.modElem = createElement(elems.shift());
10231      mStyle.style = mStyle.modElem.style;
10232    }
10233
10234    // Delete the objects if we created them.
10235    function cleanElems() {
10236      if (afterInit) {
10237        delete mStyle.style;
10238        delete mStyle.modElem;
10239      }
10240    }
10241
10242    propsLength = props.length;
10243    for (i = 0; i < propsLength; i++) {
10244      prop = props[i];
10245      before = mStyle.style[prop];
10246
10247      if (contains(prop, '-')) {
10248        prop = cssToDOM(prop);
10249      }
10250
10251      if (mStyle.style[prop] !== undefined) {
10252
10253        // If value to test has been passed in, do a set-and-check test.
10254        // 0 (integer) is a valid property value, so check that `value` isn't
10255        // undefined, rather than just checking it's truthy.
10256        if (!skipValueTest && !is(value, 'undefined')) {
10257
10258          // Needs a try catch block because of old IE. This is slow, but will
10259          // be avoided in most cases because `skipValueTest` will be used.
10260          try {
10261            mStyle.style[prop] = value;
10262          } catch (e) {}
10263
10264          // If the property value has changed, we assume the value used is
10265          // supported. If `value` is empty string, it'll fail here (because
10266          // it hasn't changed), which matches how browsers have implemented
10267          // CSS.supports()
10268          if (mStyle.style[prop] != before) {
10269            cleanElems();
10270            return prefixed == 'pfx' ? prop : true;
10271          }
10272        }
10273        // Otherwise just return true, or the property name if this is a
10274        // `prefixed()` call
10275        else {
10276          cleanElems();
10277          return prefixed == 'pfx' ? prop : true;
10278        }
10279      }
10280    }
10281    cleanElems();
10282    return false;
10283  }
10284
10285  ;
10286
10287  /**
10288   * testProp() investigates whether a given style property is recognized
10289   * Property names can be provided in either camelCase or kebab-case.
10290   *
10291   * @memberof Modernizr
10292   * @name Modernizr.testProp
10293   * @access public
10294   * @optionName Modernizr.testProp()
10295   * @optionProp testProp
10296   * @function testProp
10297   * @param {string} prop - Name of the CSS property to check
10298   * @param {string} [value] - Name of the CSS value to check
10299   * @param {boolean} [useValue] - Whether or not to check the value if @supports isn't supported
10300   * @returns {boolean}
10301   * @example
10302   *
10303   * Just like [testAllProps](#modernizr-testallprops), only it does not check any vendor prefixed
10304   * version of the string.
10305   *
10306   * Note that the property name must be provided in camelCase (e.g. boxSizing not box-sizing)
10307   *
10308   * ```js
10309   * Modernizr.testProp('pointerEvents')  // true
10310   * ```
10311   *
10312   * You can also provide a value as an optional second argument to check if a
10313   * specific value is supported
10314   *
10315   * ```js
10316   * Modernizr.testProp('pointerEvents', 'none') // true
10317   * Modernizr.testProp('pointerEvents', 'penguin') // false
10318   * ```
10319   */
10320
10321  var testProp = ModernizrProto.testProp = function(prop, value, useValue) {
10322    return testProps([prop], undefined, value, useValue);
10323  };
10324  
10325
10326  /**
10327   * testPropsAll tests a list of DOM properties we want to check against.
10328   * We specify literally ALL possible (known and/or likely) properties on
10329   * the element including the non-vendor prefixed one, for forward-
10330   * compatibility.
10331   *
10332   * @access private
10333   * @function testPropsAll
10334   * @param {string} prop - A string of the property to test for
10335   * @param {string|object} [prefixed] - An object to check the prefixed properties on. Use a string to skip
10336   * @param {HTMLElement|SVGElement} [elem] - An element used to test the property and value against
10337   * @param {string} [value] - A string of a css value
10338   * @param {boolean} [skipValueTest] - An boolean representing if you want to test if value sticks when set
10339   */
10340  function testPropsAll(prop, prefixed, elem, value, skipValueTest) {
10341
10342    var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
10343    props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
10344
10345    // did they call .prefixed('boxSizing') or are we just testing a prop?
10346    if (is(prefixed, 'string') || is(prefixed, 'undefined')) {
10347      return testProps(props, prefixed, value, skipValueTest);
10348
10349      // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
10350    } else {
10351      props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
10352      return testDOMProps(props, prefixed, elem);
10353    }
10354  }
10355
10356  // Modernizr.testAllProps() investigates whether a given style property,
10357  // or any of its vendor-prefixed variants, is recognized
10358  //
10359  // Note that the property names must be provided in the camelCase variant.
10360  // Modernizr.testAllProps('boxSizing')
10361  ModernizrProto.testAllProps = testPropsAll;
10362
10363  
10364
10365  /**
10366   * prefixed returns the prefixed or nonprefixed property name variant of your input
10367   *
10368   * @memberof Modernizr
10369   * @name Modernizr.prefixed
10370   * @optionName Modernizr.prefixed()
10371   * @optionProp prefixed
10372   * @access public
10373   * @function prefixed
10374   * @param {string} prop - String name of the property to test for
10375   * @param {object} [obj] - An object to test for the prefixed properties on
10376   * @param {HTMLElement} [elem] - An element used to test specific properties against
10377   * @returns {string|false} The string representing the (possibly prefixed) valid
10378   * version of the property, or `false` when it is unsupported.
10379   * @example
10380   *
10381   * Modernizr.prefixed takes a string css value in the DOM style camelCase (as
10382   * opposed to the css style kebab-case) form and returns the (possibly prefixed)
10383   * version of that property that the browser actually supports.
10384   *
10385   * For example, in older Firefox...
10386   * ```js
10387   * prefixed('boxSizing')
10388   * ```
10389   * returns 'MozBoxSizing'
10390   *
10391   * In newer Firefox, as well as any other browser that support the unprefixed
10392   * version would simply return `boxSizing`. Any browser that does not support
10393   * the property at all, it will return `false`.
10394   *
10395   * By default, prefixed is checked against a DOM element. If you want to check
10396   * for a property on another object, just pass it as a second argument
10397   *
10398   * ```js
10399   * var rAF = prefixed('requestAnimationFrame', window);
10400   *
10401   * raf(function() {
10402   *  renderFunction();
10403   * })
10404   * ```
10405   *
10406   * Note that this will return _the actual function_ - not the name of the function.
10407   * If you need the actual name of the property, pass in `false` as a third argument
10408   *
10409   * ```js
10410   * var rAFProp = prefixed('requestAnimationFrame', window, false);
10411   *
10412   * rafProp === 'WebkitRequestAnimationFrame' // in older webkit
10413   * ```
10414   *
10415   * One common use case for prefixed is if you're trying to determine which transition
10416   * end event to bind to, you might do something like...
10417   * ```js
10418   * var transEndEventNames = {
10419   *     'WebkitTransition' : 'webkitTransitionEnd', * Saf 6, Android Browser
10420   *     'MozTransition'    : 'transitionend',       * only for FF < 15
10421   *     'transition'       : 'transitionend'        * IE10, Opera, Chrome, FF 15+, Saf 7+
10422   * };
10423   *
10424   * var transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
10425   * ```
10426   *
10427   * If you want a similar lookup, but in kebab-case, you can use [prefixedCSS](#modernizr-prefixedcss).
10428   */
10429
10430  var prefixed = ModernizrProto.prefixed = function(prop, obj, elem) {
10431    if (prop.indexOf('@') === 0) {
10432      return atRule(prop);
10433    }
10434
10435    if (prop.indexOf('-') != -1) {
10436      // Convert kebab-case to camelCase
10437      prop = cssToDOM(prop);
10438    }
10439    if (!obj) {
10440      return testPropsAll(prop, 'pfx');
10441    } else {
10442      // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
10443      return testPropsAll(prop, obj, elem);
10444    }
10445  };
10446
10447  
10448
10449  /**
10450   * testAllProps determines whether a given CSS property is supported in the browser
10451   *
10452   * @memberof Modernizr
10453   * @name Modernizr.testAllProps
10454   * @optionName Modernizr.testAllProps()
10455   * @optionProp testAllProps
10456   * @access public
10457   * @function testAllProps
10458   * @param {string} prop - String naming the property to test (either camelCase or kebab-case)
10459   * @param {string} [value] - String of the value to test
10460   * @param {boolean} [skipValueTest=false] - Whether to skip testing that the value is supported when using non-native detection
10461   * @example
10462   *
10463   * testAllProps determines whether a given CSS property, in some prefixed form,
10464   * is supported by the browser.
10465   *
10466   * ```js
10467   * testAllProps('boxSizing')  // true
10468   * ```
10469   *
10470   * It can optionally be given a CSS value in string form to test if a property
10471   * value is valid
10472   *
10473   * ```js
10474   * testAllProps('display', 'block') // true
10475   * testAllProps('display', 'penguin') // false
10476   * ```
10477   *
10478   * A boolean can be passed as a third parameter to skip the value check when
10479   * native detection (@supports) isn't available.
10480   *
10481   * ```js
10482   * testAllProps('shapeOutside', 'content-box', true);
10483   * ```
10484   */
10485
10486  function testAllProps(prop, value, skipValueTest) {
10487    return testPropsAll(prop, undefined, undefined, value, skipValueTest);
10488  }
10489  ModernizrProto.testAllProps = testAllProps;
10490  
10491/*!
10492{
10493  "name": "CSS Animations",
10494  "property": "cssanimations",
10495  "caniuse": "css-animation",
10496  "polyfills": ["transformie", "csssandpaper"],
10497  "tags": ["css"],
10498  "warnings": ["Android < 4 will pass this test, but can only animate a single property at a time"],
10499  "notes": [{
10500    "name" : "Article: 'Dispelling the Android CSS animation myths'",
10501    "href": "https://goo.gl/OGw5Gm"
10502  }]
10503}
10504!*/
10505/* DOC
10506Detects whether or not elements can be animated using CSS
10507*/
10508
10509  Modernizr.addTest('cssanimations', testAllProps('animationName', 'a', true));
10510
10511/*!
10512{
10513  "name": "CSS Transitions",
10514  "property": "csstransitions",
10515  "caniuse": "css-transitions",
10516  "tags": ["css"]
10517}
10518!*/
10519
10520  Modernizr.addTest('csstransitions', testAllProps('transition', 'all', true));
10521
10522/*!
10523{
10524  "name": "Touch Events",
10525  "property": "touchevents",
10526  "caniuse" : "touch",
10527  "tags": ["media", "attribute"],
10528  "notes": [{
10529    "name": "Touch Events spec",
10530    "href": "https://www.w3.org/TR/2013/WD-touch-events-20130124/"
10531  }],
10532  "warnings": [
10533    "Indicates if the browser supports the Touch Events spec, and does not necessarily reflect a touchscreen device"
10534  ],
10535  "knownBugs": [
10536    "False-positive on some configurations of Nokia N900",
10537    "False-positive on some BlackBerry 6.0 builds – https://github.com/Modernizr/Modernizr/issues/372#issuecomment-3112695"
10538  ]
10539}
10540!*/
10541/* DOC
10542Indicates if the browser supports the W3C Touch Events API.
10543
10544This *does not* necessarily reflect a touchscreen device:
10545
10546* Older touchscreen devices only emulate mouse events
10547* Modern IE touch devices implement the Pointer Events API instead: use `Modernizr.pointerevents` to detect support for that
10548* Some browsers & OS setups may enable touch APIs when no touchscreen is connected
10549* Future browsers may implement other event models for touch interactions
10550
10551See this article: [You Can't Detect A Touchscreen](http://www.stucox.com/blog/you-cant-detect-a-touchscreen/).
10552
10553It's recommended to bind both mouse and touch/pointer events simultaneously – see [this HTML5 Rocks tutorial](http://www.html5rocks.com/en/mobile/touchandmouse/).
10554
10555This test will also return `true` for Firefox 4 Multitouch support.
10556*/
10557
10558  // Chrome (desktop) used to lie about its support on this, but that has since been rectified: http://crbug.com/36415
10559  Modernizr.addTest('touchevents', function() {
10560    var bool;
10561    if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
10562      bool = true;
10563    } else {
10564      // include the 'heartz' as a way to have a non matching MQ to help terminate the join
10565      // https://git.io/vznFH
10566      var query = ['@media (', prefixes.join('touch-enabled),('), 'heartz', ')', '{#modernizr{top:9px;position:absolute}}'].join('');
10567      testStyles(query, function(node) {
10568        bool = node.offsetTop === 9;
10569      });
10570    }
10571    return bool;
10572  });
10573
10574
10575  // Run each test
10576  testRunner();
10577
10578  // Remove the "no-js" class if it exists
10579  setClasses(classes);
10580
10581  delete ModernizrProto.addTest;
10582  delete ModernizrProto.addAsyncTest;
10583
10584  // Run the things that are supposed to run after the tests
10585  for (var i = 0; i < Modernizr._q.length; i++) {
10586    Modernizr._q[i]();
10587  }
10588
10589  // Leak Modernizr namespace
10590  window.Modernizr = Modernizr;
10591
10592
10593;
10594
10595})(window, document);
10596$(function() {
10597    ParallaxScroll.init();
10598});
10599
10600// Credit: https://github.com/alumbo/jquery.parallax-scroll
10601var ParallaxScroll = {
10602    /* PUBLIC VARIABLES */
10603    showLogs: false,
10604    round: 1000,
10605
10606    /* PUBLIC FUNCTIONS */
10607    init: function() {
10608        this._log("init");
10609        if (this._inited) {
10610            this._log("Already Inited");
10611            this._inited = true;
10612            return;
10613        }
10614        this._requestAnimationFrame = (function(){
10615          return  window.requestAnimationFrame       || 
10616                  window.webkitRequestAnimationFrame || 
10617                  window.mozRequestAnimationFrame    || 
10618                  window.oRequestAnimationFrame      || 
10619                  window.msRequestAnimationFrame     || 
10620                  function(/* function */ callback, /* DOMElement */ element){
10621                      window.setTimeout(callback, 1000 / 60);
10622                  };
10623        })();
10624        this._onScroll(true);
10625    },
10626
10627    /* PRIVATE VARIABLES */
10628    _inited: false,
10629    _properties: ['x', 'y', 'z', 'rotateX', 'rotateY', 'rotateZ', 'scaleX', 'scaleY', 'scaleZ', 'scale'],
10630    _requestAnimationFrame:null,
10631
10632    /* PRIVATE FUNCTIONS */
10633    _log: function(message) {
10634        if (this.showLogs) console.log("Parallax Scroll / " + message);
10635    },
10636    _onScroll: function(noSmooth) {
10637        var scroll = $(document).scrollTop();
10638        var windowHeight = $(window).height();
10639        this._log("onScroll " + scroll);
10640        $("[data-parallax]").each($.proxy(function(index, el) {
10641            var $el = $(el);
10642            var properties = [];
10643            var applyProperties = false;
10644            var style = $el.data("style");
10645            if (style == undefined) {
10646                style = $el.attr("style") || "";
10647                $el.data("style", style);
10648            }
10649            var datas = [$el.data("parallax")];
10650            var iData;
10651            for(iData = 2; ; iData++) {
10652                if($el.data("parallax"+iData)) {
10653                    datas.push($el.data("parallax-"+iData));
10654                }
10655                else {
10656                    break;
10657                }
10658            }
10659            var datasLength = datas.length;
10660            for(iData = 0; iData < datasLength; iData ++) {
10661                var data = datas[iData];
10662                var scrollFrom = data["from-scroll"];
10663                if (scrollFrom == undefined) scrollFrom = Math.max(0, $(el).offset().top - windowHeight);
10664                scrollFrom = scrollFrom | 0;
10665                var scrollDistance = data["distance"];
10666                var scrollTo = data["to-scroll"];
10667                if (scrollDistance == undefined && scrollTo == undefined) scrollDistance = windowHeight;
10668                scrollDistance = Math.max(scrollDistance | 0, 1);
10669                var easing = data["easing"];
10670                var easingReturn = data["easing-return"];
10671                if (easing == undefined || !$.easing|| !$.easing[easing]) easing = null;
10672                if (easingReturn == undefined || !$.easing|| !$.easing[easingReturn]) easingReturn = easing;
10673                if (easing) {
10674                    var totalTime = data["duration"];
10675                    if (totalTime == undefined) totalTime = scrollDistance;
10676                    totalTime = Math.max(totalTime | 0, 1);
10677                    var totalTimeReturn = data["duration-return"];
10678                    if (totalTimeReturn == undefined) totalTimeReturn = totalTime;
10679                    scrollDistance = 1;
10680                    var currentTime = $el.data("current-time");
10681                    if(currentTime == undefined) currentTime = 0;
10682                }
10683                if (scrollTo == undefined) scrollTo = scrollFrom + scrollDistance;
10684                scrollTo = scrollTo | 0;
10685                var smoothness = data["smoothness"];
10686                if (smoothness == undefined) smoothness = 30;
10687                smoothness = smoothness | 0;
10688                if (noSmooth || smoothness == 0) smoothness = 1;
10689                smoothness = smoothness | 0;
10690                var scrollCurrent = scroll;
10691                scrollCurrent = Math.max(scrollCurrent, scrollFrom);
10692                scrollCurrent = Math.min(scrollCurrent, scrollTo);
10693                if(easing) {
10694                    if($el.data("sens") == undefined) $el.data("sens", "back");
10695                    if(scrollCurrent>scrollFrom) {
10696                        if($el.data("sens") == "back") {
10697                            currentTime = 1;
10698                            $el.data("sens", "go");
10699                        }
10700                        else {
10701                            currentTime++;
10702                        }
10703                    }
10704                    if(scrollCurrent<scrollTo) {
10705                        if($el.data("sens") == "go") {
10706                            currentTime = 1;
10707                            $el.data("sens", "back");
10708                        }
10709                        else {
10710                            currentTime++;
10711                        }
10712                    }
10713                    if(noSmooth) currentTime = totalTime;
10714                    $el.data("current-time", currentTime);
10715                }
10716                this._properties.map($.proxy(function(prop) {
10717                    var defaultProp = 0;
10718                    var to = data[prop];
10719                    if (to == undefined) return;
10720                    if(prop=="scale" || prop=="scaleX" || prop=="scaleY" || prop=="scaleZ" ) {
10721                        defaultProp = 1;
10722                    }
10723                    else {
10724                        to = to | 0;
10725                    }
10726                    var prev = $el.data("_" + prop);
10727                    if (prev == undefined) prev = defaultProp;
10728                    var next = ((to-defaultProp) * ((scrollCurrent - scrollFrom) / (scrollTo - scrollFrom))) + defaultProp;
10729                    var val = prev + (next - prev) / smoothness;
10730                    if(easing && currentTime>0 && currentTime<=totalTime) {
10731                        var from = defaultProp;
10732                        if($el.data("sens") == "back") {
10733                            from = to;
10734                            to = -to;
10735                            easing = easingReturn;
10736                            totalTime = totalTimeReturn;
10737                        }
10738                        val = $.easing[easing](null, currentTime, from, to, totalTime);
10739                    }
10740                    val = Math.ceil(val * this.round) / this.round;
10741                    if(val==prev&&next==to) val = to;
10742                    if(!properties[prop]) properties[prop] = 0;
10743                    properties[prop] += val;
10744                    if (prev != properties[prop]) {
10745                        $el.data("_" + prop, properties[prop]);
10746                        applyProperties = true;
10747                    }
10748                }, this));
10749            }
10750            if (applyProperties) {
10751                if (properties["z"] != undefined) {
10752                    var perspective = data["perspective"];
10753                    if (perspective == undefined) perspective = 800;
10754                    var $parent = $el.parent();
10755                    if(!$parent.data("style")) $parent.data("style", $parent.attr("style") || "");
10756                    $parent.attr("style", "perspective:" + perspective + "px; -webkit-perspective:" + perspective + "px; "+ $parent.data("style"));
10757                }
10758                if(properties["scaleX"] == undefined) properties["scaleX"] = 1;
10759                if(properties["scaleY"] == undefined) properties["scaleY"] = 1;
10760                if(properties["scaleZ"] == undefined) properties["scaleZ"] = 1;
10761                if (properties["scale"] != undefined) {
10762                    properties["scaleX"] *= properties["scale"];
10763                    properties["scaleY"] *= properties["scale"];
10764                    properties["scaleZ"] *= properties["scale"];
10765                }
10766                var translate3d = "translate3d(" + (properties["x"] ? properties["x"] : 0) + "px, " + (properties["y"] ? properties["y"] : 0) + "px, " + (properties["z"] ? properties["z"] : 0) + "px)";
10767                var rotate3d = "rotateX(" + (properties["rotateX"] ? properties["rotateX"] : 0) + "deg) rotateY(" + (properties["rotateY"] ? properties["rotateY"] : 0) + "deg) rotateZ(" + (properties["rotateZ"] ? properties["rotateZ"] : 0) + "deg)";
10768                var scale3d = "scaleX(" + properties["scaleX"] + ") scaleY(" + properties["scaleY"] + ") scaleZ(" + properties["scaleZ"] + ")";
10769                var cssTransform = translate3d + " " + rotate3d + " " + scale3d + ";";
10770                this._log(cssTransform);
10771                $el.attr("style", "transform:" + cssTransform + " -webkit-transform:" + cssTransform + " " + style);
10772            }
10773        }, this));
10774        if(window.requestAnimationFrame) {
10775            window.requestAnimationFrame($.proxy(this._onScroll, this, false));
10776        }
10777        else {
10778            this._requestAnimationFrame($.proxy(this._onScroll, this, false));
10779        }
10780    }
10781};
10782;
10783(function($, window, undefined) {
10784
10785	'use strict';
10786
10787	// global
10788	var Modernizr = window.Modernizr,
10789		$body = $('body');
10790
10791	$.DLMenu = function(options, element) {
10792		this.$el = $(element);
10793		this._init(options);
10794	};
10795
10796	$.DLMenu.defaults = {
10797		animationClasses: {
10798			classin: 'mk-vm-animate-in-' + mk_vertical_header_anim,
10799			classout: 'mk-vm-animate-out-' + mk_vertical_header_anim
10800		},
10801		onLevelClick: function(el, name) {
10802			return false;
10803		},
10804		onLinkClick: function(el, ev) {
10805			return false;
10806		}
10807	};
10808
10809	$.DLMenu.prototype = {
10810		_init: function(options) {
10811
10812			this.options = $.extend(true, {}, $.DLMenu.defaults, options);
10813			this._config();
10814
10815			var animEndEventNames = {
10816					'WebkitAnimation': 'webkitAnimationEnd',
10817					'OAnimation': 'oAnimationEnd',
10818					'msAnimation': 'MSAnimationEnd',
10819					'animation': 'animationend'
10820				},
10821				transEndEventNames = {
10822					'WebkitTransition': 'webkitTransitionEnd',
10823					'MozTransition': 'transitionend',
10824					'OTransition': 'oTransitionEnd',
10825					'msTransition': 'MSTransitionEnd',
10826					'transition': 'transitionend'
10827				};
10828
10829			this.animEndEventName = animEndEventNames[Modernizr.prefixed('animation')] + '.dlmenu';
10830			this.transEndEventName = transEndEventNames[Modernizr.prefixed('transition')] + '.dlmenu';
10831
10832			this.animEndEventNameUnsufixed = animEndEventNames[Modernizr.prefixed('animation')];
10833			this.transEndEventNameUnsufixed = transEndEventNames[Modernizr.prefixed('transition')];
10834
10835			this.supportAnimations = Modernizr.cssanimations;
10836			this.supportTransitions = Modernizr.csstransitions;
10837
10838			this._initEvents();
10839
10840		},
10841		_config: function() {
10842			this.open = false;
10843			this.$trigger = this.$el.children('.mk-vm-trigger');
10844			this.$menu = this.$el.children('ul.mk-vm-menu');
10845			this.$menuitems = this.$menu.find('li:not(.mk-vm-back)');
10846			this.$back = this.$menu.find('li.mk-vm-back');
10847		},
10848		_initEvents: function() {
10849
10850			var self = this;
10851			
10852			$('.mk-vm-menuwrapper a').on('transitionend', function(event) {
10853				event.stopPropagation();
10854			});
10855
10856			this.$menuitems.on('click.dlmenu', 'a', function(event) {
10857
10858				// Breaks smooth scroll in vertical menu
10859				// event.stopPropagation();
10860
10861				var $item = $(event.delegateTarget),
10862					$submenu = $(event.currentTarget).siblings('ul.sub-menu');
10863
10864				if ($submenu.length > 0) {
10865					var $flyin = $submenu.clone().css('opacity', 0).insertAfter(self.$menu);
10866					var onAnimationEndFn = function() {
10867						var $parent = $item.parents('.mk-vm-subviewopen:first');
10868						self.$menu.off(self.animEndEventName).removeClass(self.options.animationClasses.classout).addClass('mk-vm-subview');
10869						$item.addClass('mk-vm-subviewopen')
10870						$parent.removeClass('mk-vm-subviewopen').addClass('mk-vm-subview');
10871						$flyin.remove();
10872
10873						// Redraw for firefox issues
10874						var $txt = $item.find('.meni-item-text');
10875						$txt.css('opacity', 0.99);
10876						setTimeout(function() { $txt.css('opacity', 1) }, 0);
10877					};
10878
10879					setTimeout(function() {
10880						$flyin.addClass(self.options.animationClasses.classin);
10881						self.$menu.addClass(self.options.animationClasses.classout);
10882						if (self.supportAnimations) {
10883							self.$menu.on(self.animEndEventName, onAnimationEndFn);
10884						} else {
10885							onAnimationEndFn.call();
10886						}
10887
10888						self.options.onLevelClick($item, $item.children('a:first').text());
10889					});
10890
10891
10892					// This caused firefox issue. Test properly if need to bring it back
10893					// if (self.open) {
10894					// 	self._closeMenu();
10895					// } else {
10896					// 	self._openMenu();
10897					// }
10898
10899					return false;
10900
10901				} else {
10902					self.options.onLinkClick($item, event);
10903				}
10904
10905			});
10906
10907
10908			// this.$trigger.on('click.dlmenu', function() {
10909
10910			// 	if (self.open) {
10911			// 		self._closeMenu();
10912			// 	} else {
10913			// 		// if( ! $(this).hasClass('menu-item-has-children') ) return false;
10914			// 		self._openMenu();
10915			// 	}
10916			// 	return false;
10917
10918			// });
10919
10920			this.$back.on('click.dlmenu', function(event) {
10921
10922				var $this = $(this),
10923					$submenu = $this.parents('ul.sub-menu:first'),
10924					$item = $submenu.parent(),
10925
10926					$flyin = $submenu.clone().insertAfter(self.$menu);
10927
10928				var onAnimationEndFn = function() {
10929					self.$menu.off(self.animEndEventName).removeClass(self.options.animationClasses.classin);
10930					$flyin.remove();
10931				};
10932
10933				setTimeout(function() {
10934					$flyin.addClass(self.options.animationClasses.classout);
10935					self.$menu.addClass(self.options.animationClasses.classin);
10936					if (self.supportAnimations) {
10937						self.$menu.on(self.animEndEventName, onAnimationEndFn);
10938					} else {
10939						onAnimationEndFn.call();
10940					}
10941
10942					$item.removeClass('mk-vm-subviewopen');
10943
10944					var $subview = $this.parents('.mk-vm-subview:first');
10945					if ($subview.is('li')) {
10946						$subview.addClass('mk-vm-subviewopen');
10947					}
10948					$subview.removeClass('mk-vm-subview');
10949				});
10950
10951				return false;
10952
10953			});
10954
10955		},
10956		closeMenu: function() {
10957			if (this.open) {
10958				this._closeMenu();
10959			}
10960		},
10961		_closeMenu: function() {
10962			var self = this,
10963				onTransitionEndFn = function() {
10964					self.$menu.off(self.transEndEventName);
10965					self._resetMenu();
10966				};
10967
10968			this.$menu.removeClass('mk-vm-menuopen');
10969			this.$menu.addClass('mk-vm-menu-toggle');
10970			this.$trigger.removeClass('mk-vm-active');
10971
10972			if (this.supportTransitions) {
10973				this.$menu.on(this.transEndEventName, onTransitionEndFn);
10974			} else {
10975				onTransitionEndFn.call();
10976			}
10977
10978			this.open = false;
10979		},
10980		openMenu: function() {
10981			if (!this.open) {
10982				this._openMenu();
10983			}
10984		},
10985		_openMenu: function() {
10986			var self = this;
10987			$body.off('click').on('click.dlmenu', function() {
10988				self._closeMenu();
10989			});
10990			this.$menu.addClass('mk-vm-menuopen mk-vm-menu-toggle').on(this.transEndEventName, function() {
10991				$(this).removeClass('mk-vm-menu-toggle');
10992			});
10993			this.$trigger.addClass('mk-vm-active');
10994			this.open = true;
10995		},
10996		_resetMenu: function() {
10997			this.$menu.removeClass('mk-vm-subview');
10998			this.$menuitems.removeClass('mk-vm-subview mk-vm-subviewopen');
10999		}
11000	};
11001
11002	var logError = function(message) {
11003		if (window.console) {
11004			window.console.error(message);
11005		}
11006	};
11007
11008	$.fn.dlmenu = function(options) {
11009		if (typeof options === 'string') {
11010			var args = Array.prototype.slice.call(arguments, 1);
11011			this.each(function() {
11012				var instance = $.data(this, 'dlmenu');
11013				if (!instance) {
11014					logError("cannot call methods on dlmenu prior to initialization; " +
11015						"attempted to call method '" + options + "'");
11016					return;
11017				}
11018				if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
11019					logError("no such method '" + options + "' for dlmenu instance");
11020					return;
11021				}
11022				instance[options].apply(instance, args);
11023			});
11024		} else {
11025			this.each(function() {
11026				var instance = $.data(this, 'dlmenu');
11027				if (instance) {
11028					instance._init();
11029				} else {
11030					instance = $.data(this, 'dlmenu', new $.DLMenu(options, this));
11031				}
11032			});
11033		}
11034		return this;
11035	};
11036
11037})(jQuery, window);
11038( function($) {
11039    'use strict';
11040
11041	/* 
11042	 * Define popup / hover states manually to prevent click for IE on touchdevices
11043	 */
11044
11045	$('.mk-main-navigation .menu-item-has-children').children('a').attr('aria-haspopup', 'true'); 
11046	$('.animated-column-item').attr('aria-haspopup', 'true');
11047
11048})( jQuery );
11049(function($) {
11050    'use strict';
11051
11052    var Accordion = function(el) { 
11053        // Private
11054        var that = this,
11055            $el = $(el),
11056            initial = $el.data('initialindex'),
11057            timeout;
11058
11059        // Public
11060        this.$el = $el;
11061        this.$single = $('.' + this.dom.single, $el);
11062        this.isExpendable = ($el.data('style') === 'toggle-action');
11063
11064        // Init 
11065        this.bindClicks();
11066        // Reveal initial tab on load event (wait for possible images inside)
11067        $(window).on('load', function() {
11068            if( initial !== -1 ) that.show(that.$single.eq(initial), true)
11069        });
11070        $(window).on('resize', function() {
11071            clearTimeout(timeout);
11072            timeout = setTimeout(that.bindClicks.bind(that), 500);
11073        }); 
11074    }
11075
11076    Accordion.prototype.dom = {
11077        // only class names please!
11078        single        : 'mk-accordion-single',
11079        tab           : 'mk-accordion-tab',
11080        pane          : 'mk-accordion-pane',
11081        current       : 'current',
11082        mobileToggle  : 'mobile-false',
11083        mobileBreakPoint : 767
11084    }
11085
11086    Accordion.prototype.bindClicks = function() {
11087        // Prevent multiple events binding
11088        this.$single.off('click', '.' + this.dom.tab);
11089
11090        if( !(window.matchMedia('(max-width: ' + this.dom.mobileBreakPoint +'px)').matches 
11091          && this.$el.hasClass(this.dom.mobileToggle)) ) {
11092
11093            this.$single.on('click', '.' + this.dom.tab, this.handleEvent.bind(this));
11094            // When website is loaded in mobile view and resized to desktop 'current' will 
11095            // inherit display: none from css. Repair it by calling show() on this element
11096            var $current = $('.' + this.dom.current, this.$el);
11097            if($('.' + this.dom.pane, $current).css('display') === 'none') this.show($current);
11098        }
11099    }
11100
11101    Accordion.prototype.handleEvent = function(e) {
11102        e.preventDefault();
11103        e.stopPropagation();
11104
11105        var $single = $(e.delegateTarget);
11106
11107        if(!$single.hasClass(this.dom.current)) {
11108            this.show($single);
11109        }
11110        else {
11111            if(this.isExpendable) this.hide($single);
11112        }
11113    }
11114
11115    Accordion.prototype.hide = function($single) {
11116        $single.removeClass(this.dom.current);
11117        $('.' + this.dom.pane, $single).slideUp();
11118    }
11119
11120    Accordion.prototype.show = function($single, initial) {
11121        // hide currently opened tab
11122        if(!this.isExpendable) {
11123            var that = this;
11124            this.hide($('.' + this.dom.current, that.$el));
11125        }
11126
11127        $single.addClass(this.dom.current);
11128        $('.' + this.dom.pane, $single).slideDown('', function() {
11129            if ( initial || ! $(this).parents('.mk-accordion').hasClass('scroll-click') ) {
11130                return;
11131            }
11132
11133            if (typeof $single.prev() === 'undefined') {
11134                $single = $single.prev()
11135            }
11136
11137            window.scrollTo({ top: $single.offset().top - 100, left: 0, behavior: 'smooth' });
11138        });
11139    }
11140
11141
11142
11143    // ///////////////////////////////////////
11144    //
11145    // Apply to:
11146    //
11147    // ///////////////////////////////////////
11148
11149	function init() {
11150		$('.mk-accordion').each(function() {
11151			new Accordion(this);
11152		});
11153	}
11154
11155	init();
11156	$(window).on('vc_reload', init);
11157
11158})(jQuery);
11159
11160(function($) {
11161
11162    'use strict';
11163
11164    var SkillDiagram = function( el ) {
11165        this.el = el;
11166    }
11167
11168    SkillDiagram.prototype = {
11169        init : function() {
11170            this.cacheElements();
11171            this.createDiagram();
11172            this.$skills.each( this.createSkill.bind( this ) );
11173        },
11174
11175        cacheElements : function() {
11176            this.$el = $( this.el );
11177            this.$skills = this.$el.find( '.mk-meter-arch');
11178            this.config  = this.$el.data();
11179            this.config.radius = this.config.dimension / 2;
11180        },
11181
11182        random : function( l, u ) {
11183            return Math.floor( ( Math.random() * ( u - l + 1 ) ) + l );
11184        },
11185
11186        createDiagram : function() {
11187            var self = this;
11188            $(this.el).find('svg').remove();
11189
11190            this.diagram = Raphael( this.el, this.config.dimension, this.config.dimension );
11191
11192            // Make svg scalable in different screen sizes
11193            this.diagram.setViewBox(0,0,this.config.dimension,this.config.dimension,true);
11194            this.diagram.setSize('90%', '90%');
11195
11196            this.diagram.circle( this.config.radius, this.config.radius, 80 ).attr({
11197                stroke: 'none',
11198                fill: this.config.circleColor
11199            });
11200
11201            // Export title
11202            this.title = this.diagram.text( this.config.radius, this.config.radius, this.config.defaultText ).attr({
11203                font: "22px helvetica",
11204                fill: this.config.defaultTextColor
11205            }).toFront();
11206
11207            this.diagram.customAttributes.arc = function(value, color, rad){
11208                var v = 3.6 * value,
11209                    alpha = v == 360 ? 359.99 : v,
11210                    r  = self.random( 91, 240 ),
11211                    a  = (r - alpha) * Math.PI/180,
11212                    b  = r * Math.PI/180,
11213                    sx = self.config.radius + rad * Math.cos(b),
11214                    sy = self.config.radius - rad * Math.sin(b),
11215                    x  = self.config.radius + rad * Math.cos(a),
11216                    y  = self.config.radius - rad * Math.sin(a),
11217                    path = [['M', sx, sy], ['A', rad, rad, 0, +(alpha > 180), 1, x, y]];
11218
11219                return {
11220                    path: path,
11221                    stroke: color
11222                }
11223            }
11224        },
11225
11226        createSkill : function( id, el ) {
11227            var self   = this,
11228                $this  = $( el ),
11229                config = $this.data(),
11230                radMin = 72,
11231                radVal = 27,
11232                newRad = radMin + ( radVal * (id + 1) );
11233
11234            var $path = this.diagram.path().attr({
11235                'stroke-width': 28,
11236                arc: [config.percent, config.color, newRad]
11237            });
11238
11239            $path.mouseover( function() {
11240                self.showSkill( this, config.name, config.percent );
11241            }).mouseout( function() {
11242                self.hideSkill( this )
11243            });
11244        },
11245
11246        showSkill : function( self, name, percent ) {
11247            var $this = self,
11248                time = 250;
11249
11250            //solves IE problem
11251            if(Raphael.type != 'VML') $this.toFront();
11252
11253            $this.animate({
11254                'stroke-width': 50,
11255                'opacity': 0.9,
11256            }, 800, 'elastic' );
11257
11258            this.title.stop()
11259                .animate({ opacity: 0 }, time, '>', function(){
11260                    this.attr({ text: name + '\n' + percent + '%' }).animate({ opacity: 1 }, time, '<');
11261                }).toFront();
11262        },
11263
11264        hideSkill : function( self ) {
11265            var $this = self,
11266                self = this,
11267                time = 250;
11268
11269            $this.stop().animate({
11270                'stroke-width': 28,
11271                opacity: 1
11272            }, time * 4, 'elastic' );
11273
11274            self.title.stop()
11275                .animate({ opacity: 0 }, time, '>', function(){
11276                    self.title.attr({ text: self.config.defaultText })
11277                    .animate({ opacity: 1 }, time, '<');
11278                });
11279        }
11280    }
11281
11282    var init = function init() {
11283        if( typeof Raphael === 'undefined' ) return;
11284        $( '.mk-skill-diagram' ).each( function() {
11285            var diagram = new SkillDiagram( this );
11286                diagram.init();
11287        });
11288    }
11289
11290    init();
11291    $(window).on('vc_reload', init);
11292
11293})(jQuery);
11294
11295/*
11296 * Tab delegation 
11297 * Action for modules when we don't have access to chidren DOM on processing templates
11298 * yet we want ass option of opening link in new tab. 
11299 * Helpful for use with external widgets like flickr
11300 */
11301
11302(function($) {
11303
11304	'use strict';
11305
11306	$( '[data-js="tab-delegation"]' ).each( tabDelegation );
11307
11308	function tabDelegation() {
11309		var $this = $( this ),
11310			data  = $this.data();
11311
11312		// Create delegation on parent element to affect async loaded children
11313		if( data.tab ) $this.on( 'click', 'a', openInTab );
11314	}
11315
11316	function openInTab( e ) {
11317		e.preventDefault(); 
11318
11319		var $this = $( this ),
11320			url = $this.attr( 'href' );
11321
11322		window.open( url, '_blank' );
11323	}
11324
11325})(jQuery);
11326(function($) {
11327    'use strict';
11328
11329    var init = function init() {
11330        var Toggle = function(el) {
11331        var that = this,
11332            $el = $(el);
11333
11334            this.$el = $el;
11335            $el.on('click', function() {
11336                $el.hasClass('active-toggle') ? that.close() : that.open()
11337            });
11338        };
11339
11340        Toggle.prototype.dom = {
11341            pane   : 'mk-toggle-pane',
11342            active : 'active-toggle'
11343        };
11344
11345        Toggle.prototype.open = function() {
11346            var $this = this.$el;
11347            $this.addClass(this.dom.active);
11348            $this.siblings('.' + this.dom.pane).slideDown(200);
11349        };
11350
11351        Toggle.prototype.close = function() {
11352            var $this = this.$el;
11353            $this.removeClass(this.dom.active);
11354            $this.siblings('.' + this.dom.pane).slideUp(200);
11355        };
11356
11357        // Apply to.
11358        var $toggle = $('.mk-toggle-title');
11359
11360        if(!$toggle.length) return;
11361
11362        $toggle.each(function() {
11363            new Toggle(this);
11364        });
11365    }
11366    $(window).on('load vc_reload', init);
11367
11368})(jQuery);
11369
11370//////////////////////////////////////////////////////////////////////////
11371//
11372//   Init all scripts
11373//
11374//////////////////////////////////////////////////////////////////////////
11375
11376// This is bad but we don't have other access to this scope.
11377// Ajax Portfolio  is defined as plugin and on success needs these to be reinited
11378// We'll refactor all of this.
11379window.ajaxInit = function() {
11380    mk_lightbox_init();
11381    mk_click_events();
11382    mk_social_share_global();
11383   // mk_social_share();
11384    mk_gallery();
11385    loop_audio_init();
11386};
11387
11388window.ajaxDelayedInit = function() {
11389    mk_flexslider_init();
11390    // mk_portfolio_ajax();
11391};
11392
11393$(document).ready(function() {
11394    mk_lightbox_init();
11395    mk_login_form();
11396    mk_backgrounds_parallax();
11397    mk_flexslider_init();
11398    mk_event_countdown();
11399    mk_skill_meter();
11400    mk_milestone();
11401    mk_ajax_search();
11402    mk_hover_events();
11403    mk_portfolio_ajax();
11404    product_loop_add_cart();
11405  //  mk_social_share();
11406    loop_audio_init();
11407    mk_portfolio_widget();
11408    mk_contact_form();
11409    mk_blog_carousel();
11410    mk_header_searchform();
11411    mk_click_events();
11412    mk_text_typer();
11413    mk_tab_slider_func();
11414    mkPositionSidebar();
11415
11416    $(window).on('load', function() {
11417        mk_unfold_footer();
11418        mk_tabs();
11419        mk_accordion_toggles_tooltip();
11420        mk_gallery();
11421        mk_theatre_responsive_calculator();
11422        mk_tabs_responsive();
11423        mk_start_tour_resize();
11424        mk_header_social_resize();
11425        mk_page_section_social_video_bg();
11426        mk_one_page_scroller();
11427
11428        setTimeout(function() {
11429            /*
11430                Somehow the values are not correctly updated for the screens
11431                and we need to put setTimeout to fix the issue
11432            */
11433            mk_mobile_tablet_responsive_calculator();
11434        }, 300);
11435
11436        console.log("ready for rock");
11437    });
11438
11439
11440    var onDebouncedResize = function() {
11441        mk_theatre_responsive_calculator();
11442        mk_mobile_tablet_responsive_calculator();
11443        mk_tabs_responsive();
11444        mk_accordion_toggles_tooltip();
11445        mk_start_tour_resize();
11446        mk_header_social_resize();
11447
11448        setTimeout(function() {
11449            mk_unfold_footer();
11450        }, 300);
11451    };
11452
11453    var debounceResize = null;
11454    $(window).on("resize", function() {
11455        if( debounceResize !== null ) { clearTimeout( debounceResize ); }
11456        debounceResize = setTimeout( onDebouncedResize, 300 );
11457    });
11458
11459    var onDebouncedScroll = function() {
11460        mk_skill_meter();
11461        //TODO: Ask to Bart how we can call javascript component
11462        //mk_charts();
11463        mk_milestone();
11464    };
11465
11466    var debounceScroll = null;
11467    $(window).on("scroll", function() {
11468        if( debounceScroll !== null ) { clearTimeout( debounceScroll ); }
11469        debounceScroll = setTimeout( onDebouncedScroll, 100 );
11470    });
11471
11472    if (MK.utils.isMobile()) {
11473        $('body').addClass('no-transform');
11474    }
11475
11476});
11477
11478/* VC frontend editor  */
11479/* -------------------------------------------------------------------- */
11480$(window).on("vc_reload",function () {
11481    mk_flexslider_init();
11482    loop_audio_init();
11483    mk_tab_slider_func();
11484    mk_event_countdown();
11485    videoLoadState();
11486    mk_page_section_social_video_bg();
11487    mk_hover_events();
11488
11489    setTimeout(function() {
11490        mkPositionSidebar();
11491    }, 200);
11492});
11493
11494// Replace this if new event for remove found.
11495$( document ).on( 'click', '.vc_control-btn-delete', function() {
11496    $( window ).trigger( 'vc_reload' );
11497} );
11498
11499$( document ).on( 'sortupdate', '.ui-sortable', function() {
11500    $( window ).trigger( 'vc_reload' );
11501} );
11502
11503/* Typer */
11504/* -------------------------------------------------------------------- */
11505function mk_text_typer() {
11506
11507    "use strict";
11508
11509    $('[data-typer-targets]').each(function() {
11510        var that = this;
11511        MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.typed.js' ], function() {
11512            var $this = $(that),
11513                $first_string = [$this.text()],
11514                $rest_strings = $this.attr('data-typer-targets').split(','),
11515                $strings = $first_string.concat($rest_strings);
11516
11517            $this.text('');
11518
11519            $this.typed({
11520                strings: $strings,
11521                typeSpeed: 30, // typing speed
11522                backDelay: 1200, // pause before backspacing
11523                loop: true, // loop on or off (true or false)
11524                loopCount: false, // number of loops, false = infinite
11525            });
11526        });
11527    });
11528}
11529
11530
11531
11532/* Tab Slider */
11533/* -------------------------------------------------------------------- */
11534
11535function mk_tab_slider_func() {
11536
11537    "use strict";
11538
11539    $('.mk-tab-slider').each(function() {
11540        var that = this;
11541
11542        MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.swiper.js' ], function() {
11543            var $this = $(that),
11544                id = $this.data('id'),
11545                $autoplayTime = $this.data('autoplay'),
11546                $content = $('.mk-slider-content');
11547
11548            var mk_tab_slider = $this.swiper({
11549                wrapperClass: 'mk-tab-slider-wrapper',
11550                slideClass: 'mk-tab-slider-item',
11551                calculateHeight: true,
11552                speed: 500,
11553                autoplay: isTest ? false : $autoplayTime,
11554                onSlideChangeStart: function() {
11555                    $('.mk-tab-slider-nav[data-id="' + id + '"]').find(".active").removeClass('active')
11556                    $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").eq(mk_tab_slider.activeIndex).addClass('active')
11557                }
11558            });
11559
11560            // Simple repaint for firefox issue (can't handle 100% height after plugin init)
11561            function repaintFirefox() {
11562                $content.css('display','block');
11563                setTimeout(function() {
11564                    mk_tab_slider.reInit();
11565                    $content.css('display','table');
11566                },100);
11567            }
11568
11569            $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").first().addClass('active');
11570
11571            $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").on('touchstart mousedown', function(e) {
11572                e.preventDefault()
11573                $('.mk-tab-slider-nav[data-id="' + id + '"]').find(".active").removeClass('active')
11574                $(this).addClass('active')
11575                mk_tab_slider.swipeTo($(this).index())
11576            });
11577
11578            $('.mk-tab-slider-nav[data-id="' + id + '"]').find("a").on('click',function(e) {
11579                e.preventDefault();
11580            });
11581
11582            repaintFirefox();
11583            $(window).on('resize', repaintFirefox);
11584        });
11585
11586    });
11587
11588}
11589
11590
11591
11592/* Edge One Pager */
11593/* -------------------------------------------------------------------- */
11594function mk_one_page_scroller() {
11595
11596    "use strict";
11597
11598    $('.mk-edge-one-pager').each(function() {
11599        var self = this;
11600
11601        MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.fullpage.js' ], function() {
11602
11603            var $this = $(self),
11604                anchorArr = [];
11605
11606            $this.find('.section').each(function() {
11607                anchorArr.push($(this).attr('data-title'));
11608            });
11609
11610            var scrollable = true;
11611            $this.find('.section').each(function() {
11612                var $section = $(this),
11613                    $content = $section.find('.edge-slide-content'),
11614                    sectionHeight = $section.height(),
11615                    contentHeight = $content.innerHeight();
11616
11617                if((contentHeight + 30) > $(window).height()) {
11618                    scrollable = false;
11619                }
11620            });
11621
11622            if(!scrollable){
11623                $this.find('.section').each(function() {
11624                    var $section = $(this);
11625                    $section.addClass('active').css({
11626                        'padding-bottom': '50px'
11627                    });
11628                });
11629            }
11630
11631            if(scrollable) {
11632                $this.fullpage({
11633                    verticalCentered: false,
11634                    resize: true,
11635                    slidesColor: ['#ccc', '#fff'],
11636                    anchors: anchorArr,
11637                    scrollingSpeed: 600,
11638                    easing: 'easeInQuart',
11639                    menu: false,
11640                    navigation: true,
11641                    navigationPosition: 'right',
11642                    navigationTooltips: false,
11643                    slidesNavigation: true,
11644                    slidesNavPosition: 'bottom',
11645                    loopBottom: false,
11646                    loopTop: false,
11647                    loopHorizontal: true,
11648                    autoScrolling: true,
11649                    scrollOverflow: false,
11650                    css3: true,
11651                    paddingTop: 0,
11652                    paddingBottom: 0,
11653                    normalScrollElements: '.mk-header, .mk-responsive-wrap',
11654                    normalScrollElementTouchThreshold: 5,
11655                    keyboardScrolling: true,
11656                    touchSensitivity: 15,
11657                    continuousVertical: false,
11658                    animateAnchor: true,
11659
11660                    onLeave: function(index, nextIndex, direction) {
11661                        var currentSkin = $this.find('.one-pager-slide').eq(nextIndex - 1).attr('data-header-skin');
11662                        MK.utils.eventManager.publish( 'firstElSkinChange', currentSkin );
11663                        $('#fullPage-nav').removeClass('light-skin dark-skin').addClass(currentSkin + '-skin');
11664
11665                    },
11666                    afterRender: function() {
11667
11668                        var $nav = $('#fullPage-nav');
11669
11670                        setTimeout(function() {
11671                            var currentSkin = $this.find('.one-pager-slide').eq(0).attr('data-header-skin');
11672                            MK.utils.eventManager.publish( 'firstElSkinChange', currentSkin );
11673                            if($nav.length) $nav.removeClass('light-skin dark-skin').addClass(currentSkin + '-skin');
11674                        }, 300);
11675
11676                        var $slide = $this.find('.section'),
11677                            headerHeight = MK.val.offsetHeaderHeight(0),
11678                            windowHeight = $(window).height();
11679
11680                        $slide.height(windowHeight - headerHeight);
11681
11682                        if($nav.length) {
11683                            $nav.css({
11684                                'top': 'calc(50% + ' + (headerHeight/2) + 'px)',
11685                                'marginTop': 0
11686                            });
11687
11688                            var style = $this.attr('data-pagination');
11689                            $nav.addClass('pagination-' + style);
11690                        }
11691
11692                        setTimeout(mk_one_pager_resposnive, 1000);
11693                    },
11694                    afterResize: function() {
11695                        var $slide = $this.find('.section'),
11696                            headerHeight = MK.val.offsetHeaderHeight(0),
11697                            windowHeight = $(window).height();
11698
11699                        $slide.height(windowHeight - headerHeight);
11700
11701                        $('#fullPage-nav').css({
11702                            'top': 'calc(50% + ' + (headerHeight/2) + 'px)',
11703                            'marginTop': 0
11704                        });
11705
11706                        setTimeout(mk_one_pager_resposnive, 1000);
11707                        console.log('Reposition pager content.');
11708                    },
11709                });
11710            }
11711
11712            // Linking to slides available for desktop and mobile scenarios
11713            function swipeTo(href, e) {
11714                href = '_' + href; // ensure a char before #
11715                if (!~href.indexOf('#')) return;
11716                var section = href.split('#')[1];
11717                if (~anchorArr.indexOf(section)) {
11718                    if (typeof e !== 'undefined') e.preventDefault();
11719                    if (scrollable) $.fn.fullpage.moveTo(section);
11720                    else MK.utils.scrollToAnchor('[data-title="'+section+'"]');
11721                }
11722            }
11723
11724            // onload
11725            var loc = window.location;
11726            if(loc.hash) swipeTo(loc.hash);
11727
11728            $(document).on('click', 'a', function(e) {
11729                var $link = $(e.currentTarget);
11730                swipeTo($link.attr('href'), e);
11731            });
11732        });
11733    });
11734
11735
11736
11737}
11738
11739
11740function mk_one_pager_resposnive() {
11741    "use strict";
11742
11743    $('.mk-edge-one-pager').each(function() {
11744        var $pager = $(this),
11745            headerHeight = MK.val.offsetHeaderHeight(0),
11746            windowHeight = $(window).height() - headerHeight;
11747
11748        $pager.find('.one-pager-slide').each(function() {
11749            var $slide = $(this),
11750                $content = $slide.find('.edge-slide-content');
11751
11752            if ($slide.hasClass('left_center') || $slide.hasClass('center_center') || $slide.hasClass('right_center')) {
11753                var contentHeight  = $content.height(),
11754                    distanceFromTop = (windowHeight - contentHeight) / 2;
11755
11756                distanceFromTop  = (distanceFromTop < 50) ? 50 + headerHeight : distanceFromTop;
11757
11758                $content.css('marginTop', distanceFromTop);
11759            }
11760
11761            if ($slide.hasClass('left_bottom') || $slide.hasClass('center_bottom') || $slide.hasClass('right_bottom')) {
11762                var distanceFromTop = windowHeight - $content.height() - 90;
11763                $content.css('marginTop', (distanceFromTop));
11764            }
11765        });
11766
11767        /**
11768         * Fix AM-2853
11769         *
11770         * @since 6.0.3
11771         *
11772         * At the init of Edge One Pager (EOP), EOP will render all image
11773         * background of each sections from top to bottom. In this case,
11774         * the page height will be more than screen height and the scroll
11775         * bar will appear. At the same time, the full width row will set
11776         * the container width into 100%. But, after all Slides are set up,
11777         * EOP height will be 100% of the screen height, so the scroll bar
11778         * will be disappeared. It's caused spacing issues on the left and
11779         * right side of the EOP container. To fix this, the row width
11780         * should be resized and row position should be readjusted.
11781         */
11782        var $row = $pager.parents( '.vc_row.vc_row-fluid.mk-fullwidth-true' );
11783
11784        // Run only if the Edge One Pager is wrapped inside full width row.
11785        if ( $row.length > 0 ) {
11786            // Set the wrapper and row width.
11787            var $wrapper = $( '.mk-main-wrapper-holder' );
11788            var $grid = $row.children( '.mk-grid' );
11789            var rowWidth = $row.width();         // Original width.
11790            var wrapperWidth = $wrapper.width(); // The new width.
11791
11792            // Run only if original width is smaller than the new width.
11793            if ( rowWidth >= wrapperWidth || $grid.length > 0 ) {
11794                return;
11795            }
11796
11797            // Get the content left offset.
11798            var $content = $wrapper.find( '.theme-content' );
11799            var oriPos = $content.position();
11800            var oriPadLeft = $content.css( 'padding-left' );
11801            var oriLeft = parseInt( oriPos.left ) + parseInt( oriPadLeft );
11802
11803            // Ensure the new width and left position is more than 0.
11804            if ( wrapperWidth <= 0 || oriLeft <= 0 ) {
11805                return;
11806            }
11807
11808            // Resize the width and left position of row full width.
11809            $row.css({
11810                'width': wrapperWidth,
11811                'left': oriLeft * -1,
11812            });
11813        }
11814    });
11815}
11816
11817/* Image Gallery */
11818/* -------------------------------------------------------------------- */
11819
11820function mk_gallery() {
11821
11822    "use strict";
11823
11824    $('.mk-gallery .mk-gallery-item.hover-overlay_layer .item-holder').each(function() {
11825        var itemHolder = $(this),
11826            galleryDesc = itemHolder.find('.gallery-desc');
11827
11828        function updatePosition() {
11829            var parentHeight = itemHolder.outerHeight(),
11830                contentHeight = galleryDesc.innerHeight();
11831
11832            var paddingVal = (parentHeight - contentHeight) / 2;
11833            galleryDesc.css({
11834                'top': paddingVal,
11835                // 'padding-bottom': paddingVal
11836            });
11837
11838            // console.log(parentHeight);
11839            // console.log(contentHeight);
11840
11841
11842        }
11843        updatePosition();
11844
11845        $(window).on('resize', function() {
11846            setTimeout(function() {
11847                updatePosition();
11848            }, 1000);
11849        });
11850    });
11851    // Execute hover state for mk gallery item
11852    if ($(window).width() <= 1024) {
11853        $('.mk-gallery .mk-gallery-item').on('click', function (e) {
11854            var clicks = $(this).data('clicks');
11855            if (clicks) {
11856                // First click
11857                $(this).toggleClass('hover-state');
11858            } else {
11859                // Second click
11860                $(this).toggleClass('hover-state');
11861            }
11862            $(this).data("clicks", !clicks);
11863        });
11864    }
11865}
11866
11867/* Theatre Slider Responsive Calculator */
11868/* -------------------------------------------------------------------- */
11869
11870function mk_theatre_responsive_calculator() {
11871    var $laptopContainer = $(".laptop-theatre-slider");
11872    var $computerContainer = $(".desktop-theatre-slider");
11873    $laptopContainer.each(function() {
11874        var $this = $(this),
11875            $window = $(window),
11876            $windowWidth = $window.outerWidth(),
11877            $windowHeight = $window.outerHeight(),
11878            $width = $this.outerWidth(),
11879            $height = $this.outerHeight(),
11880            $paddingTop = 38,
11881            $paddingRight = 143,
11882            $paddingBottom = 78,
11883            $paddingLeft = 143;
11884
11885        var $player = $this.find('.player-container');
11886
11887        if ($windowWidth > $width) {
11888            $player.css({
11889                'padding-left': parseInt(($width * $paddingLeft) / 1200),
11890                'padding-right': parseInt(($width * $paddingRight) / 1200),
11891                'padding-top': parseInt(($height * $paddingTop) / 690),
11892                'padding-bottom': parseInt(($height * $paddingBottom) / 690),
11893            });
11894        }
11895
11896    });
11897
11898    $computerContainer.each(function() {
11899        var $this = $(this),
11900            $window = $(window),
11901            $windowWidth = $window.outerWidth(),
11902            $windowHeight = $window.outerHeight(),
11903            $width = $this.outerWidth(),
11904            $height = $this.outerHeight(),
11905            $paddingTop = 60,
11906            $paddingRight = 52,
11907            $paddingBottom = 290,
11908            $paddingLeft = 49;
11909
11910        var $player = $this.find('.player-container');
11911
11912        if ($windowWidth > $width) {
11913            $player.css({
11914                'padding-left': parseInt(($width * $paddingLeft) / 1200),
11915                'padding-right': parseInt(($width * $paddingRight) / 1200),
11916                'padding-top': parseInt(($height * $paddingTop) / 969),
11917                'padding-bottom': parseInt(($height * $paddingBottom) / 969),
11918            });
11919        }
11920
11921    });
11922
11923}
11924
11925/* Mobile and Tablet Slideshow Responsive Calculator */
11926/* -------------------------------------------------------------------- */
11927function mk_mobile_tablet_responsive_calculator() {
11928    var $laptopSlideshow = $(".mk-laptop-slideshow-shortcode");
11929    var $lcdSlideshow = $(".mk-lcd-slideshow");
11930
11931    if ($.exists(".mk-laptop-slideshow-shortcode")) {
11932        $laptopSlideshow.each(function() {
11933            var $this = $(this),
11934                $window = $(window),
11935                $windowWidth = $window.outerWidth(),
11936                $windowHeight = $window.outerHeight(),
11937                $width = $this.outerWidth(),
11938                $height = $this.outerHeight(),
11939                $paddingTop = 28,
11940                $paddingRight = 102,
11941                $paddingBottom = 52,
11942                $paddingLeft = 102;
11943
11944            var $player = $this.find(".slideshow-container");
11945
11946            $player.css({
11947                "padding-left": parseInt(($width * $paddingLeft) / 836),
11948                "padding-right": parseInt(($width * $paddingRight) / 836),
11949                "padding-top": parseInt(($height * $paddingTop) / 481),
11950                "padding-bottom": parseInt(($height * $paddingBottom) / 481),
11951            });
11952
11953        });
11954    }
11955
11956    if ($.exists(".mk-lcd-slideshow")) {
11957        $lcdSlideshow.each(function() {
11958            var $this = $(this),
11959                $window = $(window),
11960                $windowWidth = $window.outerWidth(),
11961                $windowHeight = $window.outerHeight(),
11962                $width = $this.outerWidth(),
11963                $height = $this.outerHeight(),
11964                $paddingTop = 35,
11965                $paddingRight = 39,
11966                $paddingBottom = 213,
11967                $paddingLeft = 36;
11968
11969            var $player = $this.find(".slideshow-container");
11970            $player.css({
11971                "padding-left": parseInt(($width * $paddingLeft) / 886),
11972                "padding-right": parseInt(($width * $paddingRight) / 886),
11973                "padding-top": parseInt(($height * $paddingTop) / 713),
11974                "padding-bottom": parseInt(($height * $paddingBottom) / 713),
11975            });
11976        });
11977    }
11978}
11979
11980
11981/* Start a tour resize function */
11982/* -------------------------------------------------------------------- */
11983function mk_start_tour_resize() {
11984
11985    $('.mk-header-start-tour').each(function() {
11986
11987        var $windowWidth = $(document).width(),
11988            $this = $(this),
11989            $linkWidth = $this.width() + 15,
11990            $padding = ($windowWidth - mk_responsive_nav_width) / 2;
11991
11992
11993
11994        function updateStartTour(){
11995            if($windowWidth < mk_responsive_nav_width){
11996                $this.removeClass('hidden');
11997                $this.addClass('show');
11998            }else{
11999                if($padding < $linkWidth){
12000                    $this.removeClass('show');
12001                    $this.addClass('hidden');
12002                }else{
12003                    $this.removeClass('hidden');
12004                    $this.addClass('show');
12005                }
12006            }
12007        }
12008
12009        setTimeout(function() {
12010            updateStartTour();
12011        }, 300);
12012    });
12013}
12014
12015/* Header social resize function */
12016/* -------------------------------------------------------------------- */
12017function mk_header_social_resize() {
12018
12019    $('.mk-header-social.header-section').each(function() {
12020
12021        var $windowWidth = $(document).width(),
12022            $this = $(this),
12023            $linkWidth = $this.width() + 15,
12024            $padding = ($windowWidth - mk_responsive_nav_width) / 2;
12025
12026
12027
12028        function updateStartTour(){
12029            if($windowWidth < mk_responsive_nav_width){
12030                $this.removeClass('hidden');
12031                $this.addClass('show');
12032            }else{
12033                if($padding < $linkWidth){
12034                    $this.removeClass('show');
12035                    $this.addClass('hidden');
12036                }else{
12037                    $this.removeClass('hidden');
12038                    $this.addClass('show');
12039                }
12040            }
12041        }
12042
12043        setTimeout(function() {
12044            updateStartTour();
12045        }, 300);
12046    });
12047}
12048
12049/* Page Section Socail Video Player Controls */
12050/* -------------------------------------------------------------------- */
12051
12052function mk_page_section_social_video_bg() {
12053    $(".mk-page-section.social-hosted").each(function() {
12054        var $container = $(this),
12055            $sound = $container.data('sound'),
12056            $source = $container.data('source'),
12057            player,
12058            timer = 1000;
12059
12060        if ( $( 'body' ).hasClass( '.compose-mode' ) ) {
12061            timer = 2000;
12062        }
12063
12064        if ($source == 'youtube') {
12065            var youtube = $container.find('iframe')[0];
12066            try {
12067                player = new YT.Player(youtube, {
12068                    events: {
12069                        'onReady': function () {
12070                           player.playVideo();
12071                           if($sound == false) {
12072                               player.mute();
12073                           }
12074                       }
12075                    }
12076                });
12077
12078
12079            } catch (e) {
12080            	console.log( e );
12081            }
12082        }
12083        if ($source == 'vimeo') {
12084            var vimeo = $container.find('iframe')[0];
12085            player = $f(vimeo);
12086            setTimeout(function() {
12087                player.api('play');
12088                if($sound === false) {
12089                    player.api('setVolume', 0);
12090                }
12091            }, timer);
12092        }
12093
12094    });
12095}
12096
12097// Pre RequireJS hot bug fixing
12098
12099function videoLoadState() {
12100    $('.mk-section-video video').each(function() {
12101        var mkVideo = this;
12102
12103        mkVideo.play();
12104        this.onload = fire();
12105
12106        function fire() {
12107            setTimeout(function() {
12108                $(mkVideo).animate({
12109                    'opacity': 1
12110                }, 300);
12111            }, 1000);
12112        }
12113    });
12114}
12115videoLoadState();
12116
12117
12118// Gmap Widget
12119(function($) {
12120
12121    $(window).on('load vc_reload', initialize);
12122
12123    function initialize() {
12124        var $gmap = $('.gmap_widget');
12125        if($gmap.length && typeof google !== 'undefined') $gmap.each(run);
12126    }
12127
12128    function run() {
12129        var $mapHolder = $(this);
12130        var myLatlng = new google.maps.LatLng($mapHolder.data('latitude'), $mapHolder.data('longitude'));
12131        var mapOptions = $mapHolder.data('options');
12132            mapOptions.mapTypeId = google.maps.MapTypeId.ROADMAP;
12133            mapOptions.center = myLatlng;
12134        var map = new google.maps.Map(this, mapOptions);
12135
12136        new google.maps.Marker({
12137            position: myLatlng,
12138            map: map
12139        });
12140    }
12141
12142}(jQuery));
12143
12144// Instagram Widget
12145(function($) {
12146
12147    $(window).on('load', function() {
12148        var $feeds = $('.mk-instagram-feeds');
12149        if($feeds.length) $feeds.each(run);
12150    });
12151
12152    function run() {
12153        var options = $(this).data('options');
12154            options.template = '<a class="featured-image '+options.tmp_col+'-columns" href="{{link}}" target="_'+options.tmp_target+'"><div class="item-holder"><img src="{{image}}" /><div class="image-hover-overlay"></div></div></a>';
12155        var feed = new Instafeed(options);
12156        feed.run();
12157    }
12158}(jQuery));
12159
12160
12161// Flipbox backface visibility fix for chrome
12162(function($) {
12163     $(window).on('load', function() {
12164         setTimeout( function() {
12165            $('.chrome-flipbox-backface-fix').removeClass('chrome-flipbox-backface-fix');
12166         }, 300);
12167     });
12168}(jQuery));
12169
12170
12171/* Product in VC Tab Bug Fix
12172/* -------------------------------------------------------------------- */
12173(function($) {
12174    $(window).on('load', function() {
12175        $('.vc_tta-tab a').on('click', function() {
12176            setTimeout( function() {
12177                $(window).trigger('resize');
12178            }, 100);
12179        });
12180    });
12181}(jQuery));
12182
12183
12184/* Vertical menu fix when childrens exceed screen height
12185/* -------------------------------------------------------------------- */
12186(function($) {
12187    $(window).on('load', function() {
12188        $('#mk-vm-menu .menu-item-has-children, #mk-vm-menu .mk-vm-back').on('mouseenter', function() {
12189            var $header_inner = $(this).closest('.mk-header-inner'),
12190                $header_inner_height = $header_inner.outerHeight(),
12191                $header_bg = $header_inner.find('.mk-header-bg'),
12192                total_height = 0;
12193            $header_bg.css('height', '100%');
12194            setTimeout( function() {
12195                $header_inner.children(':visible').each(function() {
12196                    total_height += $(this).outerHeight(true);
12197                });
12198                total_height -= $header_bg.height();
12199                if ( total_height < $header_inner_height ) {
12200                    $header_bg.css('height', '100%');
12201                } else {
12202                    $header_bg.css('height', total_height + 'px');
12203                }
12204            }, 600);
12205        });
12206    });
12207}(jQuery));
12208
12209
12210/* Woocommerce varitions lightbox fix
12211/* -------------------------------------------------------------------- */
12212(function($) {
12213    $(window).on('load', function() {
12214
12215        if ( $('.woo-variation-gallery-thumbnail-wrapper').length > 0 ) {
12216            return;
12217        }
12218
12219        var $variations_form = $('.variations_form');
12220
12221        if ( $variations_form.length ) {
12222
12223            var $varitions_selects = $variations_form.find('.variations').find('.value').find('select');
12224            $varitions_selects.on('change', function() {
12225
12226                // Woocommerce variations lightbox with galleries
12227                var $all_img_container = $('.mk-product-image .mk-woocommerce-main-image');
12228                if ( $all_img_container.length ) {
12229                    $( $all_img_container ).each( set_lightbox_href );
12230                }
12231
12232            });
12233            $varitions_selects.trigger('change');
12234
12235        }
12236
12237    });
12238
12239    function set_lightbox_href() {
12240
12241        var $product_img = $( this ).find( 'img' ),
12242            $lightbox    = $( this ).find( '.mk-lightbox' );
12243
12244        setTimeout( function() {
12245            var image_url    = $product_img.attr( 'src' ),
12246                image_suffix = image_url.substr( image_url.lastIndexOf('.') - image_url.length ), // Get image suffix
12247                image_url    = image_url.slice( 0 , image_url.lastIndexOf('-') ); // Remove image size
12248            $lightbox.attr('href', image_url + image_suffix );
12249        }, 300);
12250    }
12251
12252}(jQuery));
12253
12254
12255/* Remove video section when on mobile */
12256/* -------------------------------------------------------------------- */
12257if( ! MK.utils.showBackgroundVideo ) {
12258	(function($) {
12259		if ( MK.utils.isMobile() ) {
12260		  $('.mk-section-video video').remove();
12261		  $('.mk-section-video').addClass('mk-section-video-disable');
12262		}
12263	}(jQuery));
12264}
12265
12266
12267/* Yith AJAX Product Filter & Yith Infinite Scrolling Plugin Fix
12268/* -------------------------------------------------------------------- */
12269(function($) {
12270    $(window).on('load', function() {
12271
12272        $(document).on( 'yith-wcan-ajax-filtered yith_infs_added_elem yith-wcan-ajax-reset-filtered', function(){
12273            setTimeout( function() {
12274                MK.utils.eventManager.publish('ajaxLoaded');
12275                MK.core.initAll( document );
12276            }, 1000 );
12277        });
12278
12279        // Fixed YITH Filter plugin causes issue for dropdown sort
12280        $(document).on( 'yith-wcan-ajax-filtered yith-wcan-ajax-reset-filtered', function(){
12281            setTimeout( function() {
12282                $( '.woocommerce-ordering' ).on( 'change', 'select.orderby', function() {
12283                    $( this ).closest( 'form' ).submit();
12284                });
12285            }, 1000 );
12286        });
12287
12288    });
12289}(jQuery));
12290
12291
12292/* Toggle loading state in URL for anchor links.
12293 * - Add a filter to escape meta-chars from hash string.
12294/* -------------------------------------------------------------------- */
12295!function(e){var a=window.location,n=a.hash;if(n.length&&n.substring(1).length){var hSuf = n.substring(1).replace(/[!"#$%&'()*+,./:;<=>?@[\]^`{|}~]/g, "\\$&");var r=e(".vc_row, .mk-main-wrapper-holder, .mk-page-section, #comments"),t=r.filter("#"+hSuf);if(!t.length)return;n=n.replace("!loading","");var i=n+"!loading";a.hash=i}}(jQuery);
12296
12297
12298/* Determine the top spacing of sidebar for full-width page section & row.
12299/* -------------------------------------------------------------------- */
12300function mkPositionSidebar() {
12301
12302	var themeContent = $( '.theme-content' ),
12303		lastFullWidthChild = themeContent.find( '.vc_row-full-width' ).last(),
12304		top,
12305		sidebar = $( '#theme-page > .mk-main-wrapper-holder > .theme-page-wrapper > #mk-sidebar' );
12306
12307	if ( ! lastFullWidthChild.length ) {
12308		sidebar.removeAttr( 'style' );
12309		return;
12310	}
12311
12312	top = lastFullWidthChild.offset().top - themeContent.offset().top;
12313	sidebar.css( 'padding-top', top );
12314}
12315
12316function mk_accordion_toggles_tooltip() {
12317
12318  "use strict";
12319
12320
12321  /* Message Boxes */
12322  /* -------------------------------------------------------------------- */
12323
12324  $('.box-close-btn').on('click', function() {
12325    $(this).parent().fadeOut(300);
12326    return false;
12327
12328  });
12329
12330}
12331
12332function mk_portfolio_ajax() {
12333  "use strict";
12334
12335  var headerHeight = 0;
12336  if ($.exists("#wpadminbar")) {
12337    headerHeight += $("#wpadminbar").height();
12338  }
12339  if (!$.exists('.mk-vm-menuwrapper')) {
12340    headerHeight += parseInt($('.mk-header').attr('data-sticky-height'));
12341  }
12342
12343  function init() {
12344    var $portfolio = $('.portfolio-grid.portfolio-ajax-enabled');
12345    if (!$portfolio.length) return; // quit if no portfolio wrappers
12346    MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.ajax.portfolio.js' ], function() {
12347      // wait for ajax response propagation and insertion
12348      setTimeout(function() {
12349        $portfolio.each( function() {
12350          $(this).ajaxPortfolio({ extraOffset: headerHeight });
12351        });
12352      }, 100);
12353    });
12354  }
12355
12356  init();
12357
12358  // Reinit when ajax loaded stuff
12359  // We have global reinit on Components. so move the ajaxPortfolio to component namespace as a standalone module to get it right.
12360  MK.utils.eventManager.subscribe('ajaxLoaded', init);
12361}
12362
12363/**
12364 * Ajax Search on header nav.
12365 */
12366function mk_ajax_search() {
12367    "use strict";
12368
12369    // Check if ajax search box enabled.
12370    if (mk_ajax_search_option !== "beside_nav") {
12371        return;
12372    }
12373
12374    // Set minimum length of text to get ajax result.
12375    var minimumLengthToSearch = 3;
12376    var $mkAjaxSearchInput = $('#mk-ajax-search-input');
12377    var security = $mkAjaxSearchInput.siblings('input[name="security"]').val();
12378    var wpHttpReferer = $mkAjaxSearchInput.siblings('input[name="_wp_http_referer"]').val();
12379    var querySpliter = (ajaxurl.indexOf('?') > -1) ? '&' : '?';
12380    var ul = document.getElementById('mk-nav-search-result');
12381    var searchTerm; // Search term
12382    var requestCounter = 0;
12383    var responseCounter = 0;
12384
12385    // Add listener for getting result quickly while user entering text, past text and etc.
12386    $mkAjaxSearchInput.on('paste input propertychange', onSearchBoxInput);
12387
12388    /**
12389     * Callback function for entering search term listener (e.g. keyup).
12390     * It will generate AJAX request to get data.
12391     *
12392     * @param e
12393     */
12394    function onSearchBoxInput(e) {
12395        var target = e.target || e.srcElement;
12396        var newValue = target.value;
12397
12398        // Check if user change the value of text box
12399        if (searchTerm !== newValue) {
12400            searchTerm = newValue;
12401            ul.innerHTML = '';
12402            if (searchTerm.length >= minimumLengthToSearch) {
12403                // Show loading icon
12404                $mkAjaxSearchInput.addClass('ajax-searching');
12405                requestCounter++;
12406                $.getJSON(ajaxurl + querySpliter + 'callback=?&action=mk_ajax_search&security=' + security + '&_wp_http_referer=' + wpHttpReferer + '&term=' + searchTerm)
12407                    .done(showSearchResult)
12408                    .fail(showErrorMessage);
12409            }
12410        }
12411    }
12412
12413    /**
12414     * Callback function for the response of the search request.
12415     *
12416     * @param data
12417     */
12418    function showSearchResult(data) {
12419        responseCounter++;
12420
12421        // Only show response of latest request.
12422        if (isCorrectResponse()) {
12423            if (data.length > 0) {
12424                // Append result to result container
12425                for (var i = 0; i < data.length; i++) {
12426                    var item = data[i];
12427                    $('<li>').append('<a href="' + item.link + '">' + item.image + '<span class="search-title">' + item.label + '</span><span class="search-date">' + item.date + '</span></a>').appendTo(ul);
12428                }
12429            } else {
12430                // Show no result message
12431                ul.innerHTML = '<li class="mk-nav-search-result-zero">No Result.</li>';
12432            }
12433
12434            // Hide loading icon
12435            $mkAjaxSearchInput.parent('form').removeClass('ajax-searching').addClass('ajax-search-complete');
12436        }
12437    }
12438
12439    /**
12440     * If any errors, we need a handler to show error message.
12441     */
12442    function showErrorMessage() {
12443        responseCounter++;
12444
12445        if (isCorrectResponse()) {
12446            ul.innerHTML = '<li class="mk-nav-search-error-message">Can not search! Please try again.</li>';
12447        }
12448    }
12449
12450    /**
12451     * Check if the response is right for the request. we show latest response only.
12452     *
12453     * @returns {boolean}
12454     */
12455    function isCorrectResponse() {
12456        return requestCounter === responseCounter;
12457    }
12458}
12459/* Background Parallax Effects */
12460/* -------------------------------------------------------------------- */
12461
12462function mk_backgrounds_parallax() {
12463
12464  "use strict";
12465
12466  if (mk_header_parallax == true) {
12467    $('.mk-header-bg').addClass('mk-parallax-enabled');
12468  }
12469  if (mk_body_parallax == true) {
12470    $('body').addClass('mk-parallax-enabled');
12471  }
12472  if (mk_banner_parallax == true) {
12473    $('.mk-header').addClass('mk-parallax-enabled');
12474  }
12475  if (mk_footer_parallax == true) {
12476    $('#mk-footer').addClass('mk-parallax-enabled');
12477  }
12478
12479  $('.mk-parallax-enabled').each(function () {
12480    var $this = $( this );
12481    if (!MK.utils.isMobile()) {
12482      MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.parallax.js' ], function() {
12483        $this.parallax("49%", 0.3);
12484      });
12485    }
12486  });
12487
12488  $('.mk-fullwidth-slideshow.parallax-slideshow').each(function () {
12489    var $this = $( this );
12490    if (!MK.utils.isMobile()) {
12491      MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.parallax.js' ], function() {
12492        var speed_factor = $this.attr('data-speedFactor');
12493        $this.parallax("49%", speed_factor);
12494      });
12495    }
12496  });
12497
12498}
12499/* Blog, Portfolio Audio */
12500/* -------------------------------------------------------------------- */
12501
12502function loop_audio_init() {
12503  if (!$.exists('.jp-jplayer')) {
12504    return;
12505  }
12506
12507  $('.jp-jplayer.mk-blog-audio').each(function () {
12508    var $this = $(this);
12509    var $thisControls = $this.next('.jp-audio');
12510    var audio = $this.find( '.mk-audio' )[0];
12511
12512    // Set initial values.
12513    $thisControls.find('.jp-current-time').text('0:0');
12514    $thisControls.find('.jp-volume-bar-value').css('width', 25);
12515
12516    /*
12517     * When audio data is loaded.
12518     */
12519    audio.addEventListener('loadeddata', jsPlayerloaded(audio, $thisControls), false);
12520
12521    audio.addEventListener('loadedmetadata', function() {
12522      var minutes = Math.floor(audio.duration / 60);
12523      var seconds = Math.floor(audio.duration % 60);
12524
12525      // Update the duration time.
12526      if (!isNaN(minutes)) {
12527        $thisControls.find('.jp-duration').text(minutes + ':' + seconds);
12528      }
12529
12530      // Show play button when audio is loaded.
12531      $thisControls.removeClass('jp-audio-loading').addClass('jp-audio-loaded');
12532    });
12533
12534    /*
12535     * When audio is playing.
12536     */
12537    audio.addEventListener('timeupdate', function() {
12538      var minutes = Math.floor(audio.currentTime / 60);
12539      var seconds = Math.floor(audio.currentTime % 60);
12540
12541      // Update curren time.
12542      $thisControls.find('.jp-current-time').text(minutes + ':' + seconds);
12543
12544      // Convert length of audio to 0 - 100 while keeping ratio.
12545      var position = ((audio.currentTime - 0) / (audio.duration - 0)) * (100 - 0) + 0;
12546
12547      // Update position of progress bar.
12548      $thisControls.find('.jp-play-bar').css('width', position + '%');
12549    });
12550
12551    /*
12552     * When audio is ended.
12553     */
12554    audio.addEventListener('ended', function() {
12555      // Show play button.
12556      $thisControls.removeClass('jp-audio-playing');
12557
12558      // Reset the position of progress bar.
12559      $thisControls.find('.jp-play-bar').css('width', 0);
12560
12561      // Reset the current time.
12562      $thisControls.find('.jp-current-time').text('0:0');
12563    });
12564
12565    /*
12566     * Play the audio.
12567     */
12568    $thisControls.find('.jp-play').on('click', function() {
12569      audio.play();
12570
12571      // Show pause button.
12572      $thisControls.addClass('jp-audio-playing').removeClass('jp-audio-paused');
12573    });
12574
12575    /*
12576     * Pause the audio..
12577     */
12578    $thisControls.find('.jp-pause').on('click', function() {
12579      audio.pause();
12580
12581      // Show play button.
12582      $thisControls.addClass('jp-audio-paused').removeClass('jp-audio-playing');
12583    });
12584
12585    /*
12586     * Mute the audio.
12587     */
12588    $thisControls.find('.jp-volume-bar svg').on('click', function() {
12589      audio.muted = !audio.muted;
12590
12591      $(this).parent().toggleClass('jp-muted');
12592    });
12593
12594    /*
12595     * Adjust the volume.
12596     */
12597    $thisControls.find('.inner-value-adjust').on('click', function(e) {
12598      // Get the posiiton of mouse click, between 0 to 25.
12599      var position = e.pageX - $(this).offset().left;
12600
12601      // Scale the number from 0 - 25 to 0 - 1 while keeping ratio.
12602      var volume = ((position - 0) / (25 - 0)) * (1 - 0) + 0;
12603
12604      // Set volume.
12605      audio.volume = volume;
12606
12607      // Update the position of volume bar.
12608      $(this).find('.jp-volume-bar-value').css('width', position);
12609    });
12610
12611    /*
12612     * Adjust current time from progress bar.
12613     */
12614    $thisControls.find('.jp-seek-bar').on('click', function(e) {
12615      // Get the position of mouse click.
12616      var position = e.pageX - $(this).offset().left;
12617
12618      // Scale the number from 0 - currentTime to 0 - 100 while keeping ratio.
12619      var currnetTime = ((position - 0) / ($(this).width() - 0)) * (audio.duration - 0) + 0;
12620
12621      // Set current time.
12622      audio.currentTime = currnetTime;
12623
12624      // Update the position of progress bar.
12625      $thisControls.find('.jp-play-bar').css('width', currnetTime + '%');
12626    });
12627  });
12628
12629  function jsPlayerloaded(audio, $thisControls) {
12630    var minutes = Math.floor(audio.duration / 60);
12631    var seconds = Math.floor(audio.duration % 60);
12632
12633    // Update the duration time.
12634    if (!isNaN(minutes)) {
12635      $thisControls.find('.jp-duration').text(minutes + ':' + seconds);
12636    }
12637
12638    // Show play button when audio is loaded.
12639    $thisControls.removeClass('jp-audio-loading').addClass('jp-audio-loaded');
12640  }
12641}
12642
12643/* Blog Loop Carousel Shortcode */
12644/* -------------------------------------------------------------------- */
12645
12646
12647function mk_blog_carousel() {
12648
12649  "use strict";
12650
12651  if (!$.exists('.mk-blog-showcase')) {
12652    return;
12653  }
12654  $('.mk-blog-showcase ul li').each(function () {
12655
12656    $(this).mouseenter( function () {
12657
12658      $(this).siblings('li').removeClass('mk-blog-first-el').end().addClass('mk-blog-first-el');
12659
12660    });
12661
12662  });
12663
12664
12665}
12666
12667
12668
12669
12670/**
12671 * Contact Form
12672 *
12673 * Mostly implemented in Vanilla JS instead of jQuery.
12674 */
12675function mk_contact_form() {
12676    "use strict";
12677    var mkContactForms = document.getElementsByClassName('mk-contact-form');
12678    if (mkContactForms.length === 0) {
12679        return;
12680    }
12681    var captchaImageHolder = $('.captcha-image-holder');
12682    var activeClassName = 'is-active';
12683    var invalidClassName = 'mk-invalid';
12684    for (var i = 0; i < mkContactForms.length; i++) {
12685        initializeForm(mkContactForms[i], activeClassName, invalidClassName);
12686    }
12687    if (captchaImageHolder.length > 0) {
12688        $(window).on('load', initializeCaptchas);
12689    }
12690
12691    window.jupiterCaptchaContactFormCaptchaToken = function( token ) {
12692        window.jupiterContactFormNewCreatedCaptchaToken = token;
12693    };
12694
12695    /**
12696     * Initialize mk forms. e.g add activeClassName for inputs.
12697     *
12698     * @param form
12699     * @param activeClassName
12700     * @param invalidClassName
12701     */
12702    function initializeForm(form, activeClassName, invalidClassName) {
12703        var inputs = getFormInputs(form);
12704        for (var i = 0; i < inputs.length; i++) {
12705            markActiveClass(inputs[i]);
12706        }
12707        form.addEventListener('submit', function(e) {
12708            validateForm(e, invalidClassName);
12709        });
12710        /**
12711         * Set activeClassName for the parent node of the inout
12712         */
12713        function setActiveClass() {
12714            addClass(this.parentNode, activeClassName);
12715        }
12716        /**
12717         * Unset activeClassName from the parent node of the input.
12718         * We need to unset activeClassName only if the data was empty.
12719         * e.g. in the line style of the mk-contact-form, we set labels position based on activeClassName.
12720         */
12721        function unsetActiveClass() {
12722            if (this.value === '') {
12723                removeClass(this.parentNode, activeClassName);
12724            }
12725        }
12726        /**
12727         * Add event listeners (focus,blur) for input to set and unset activeClassName.
12728         *
12729         * @param input
12730         */
12731        function markActiveClass(input) {
12732            input.addEventListener('focus', setActiveClass);
12733            input.addEventListener('blur', unsetActiveClass);
12734        }
12735    }
12736    /**
12737     * Validate form when it's submitted. If everything was valid, we with post form in ajax request.
12738     *
12739     * @param e
12740     * @param invalidClassName
12741     */
12742    function validateForm(e, invalidClassName) {
12743        e.preventDefault();
12744        var form = e.target || e.srcElement;
12745        var inputs = getFormInputs(form);
12746        var isValidForm = true;
12747        var hasCaptchaField = false;
12748        for (var i = 0; i < inputs.length; i++) {
12749            var input = inputs[i];
12750            input.value = String(input.value).trim();
12751            switch (input.type) {
12752                case 'hidden':
12753                    break;
12754                case 'checkbox':
12755                    isValidForm = validateCheckBox(input, invalidClassName) && isValidForm;
12756                    break;
12757                case 'email':
12758                    isValidForm = validateEmail(input, invalidClassName) && isValidForm;
12759                    break;
12760                case 'textarea':
12761                    isValidForm = validateText(input, invalidClassName) && isValidForm;
12762                    break;
12763                case 'text':
12764                    /**
12765                     * Some old browsers such as IE 8 and 9 detect email type as text.
12766                     * So, we need to extra check for data-type attribute
12767                     */
12768                    if (input.dataset.type === 'captcha') {
12769                        isValidForm = validateText(input, invalidClassName) && isValidForm;
12770                        hasCaptchaField = true;
12771                    } else if (input.dataset.type === 'email') {
12772                        isValidForm = validateEmail(input, invalidClassName) && isValidForm;
12773                    } else {
12774                        isValidForm = validateText(input, invalidClassName) && isValidForm;
12775                    }
12776                    break;
12777                default:
12778                    /**
12779                     * e.g. validating for radiobox, selectbox and etc.
12780                     */
12781                    console.warn('Implement validation for ' + input.name + ':' + input.type);
12782                    break;
12783            }
12784        }
12785        if (isValidForm) {
12786            if (hasCaptchaField) {
12787                validateCaptcha(form, invalidClassName, sendForm);
12788            } else {
12789                sendForm(form);
12790            }
12791        }
12792    }
12793    /**
12794     * Validate captcha of form. If everything was, we will execute captchaIsValidCallback which as sendForm().
12795     *
12796     * @param form
12797     * @param invalidClassName
12798     * @param captchaIsValidCallback
12799     * @returns boolean
12800     */
12801    function validateCaptcha(form, invalidClassName, captchaIsValidCallback) {
12802        var input = form.querySelectorAll('[data-type="captcha"]')[0];
12803        if (input.value.length === 0) {
12804            addClass(input, invalidClassName);
12805            return false;
12806        } else {
12807            window.get.captcha(input.value).done(function(data) {
12808                loadCaptcha();
12809                input.value = '';
12810                if (data !== 'ok') {
12811                    addClass(input, invalidClassName);
12812                    addClass(input, 'contact-captcha-invalid');
12813                    removeClass(input, 'contact-captcha-valid');
12814                    input.placeholder = mk_captcha_invalid_txt;
12815                } else {
12816                    removeClass(input, invalidClassName);
12817                    removeClass(input, 'contact-captcha-invalid');
12818                    addClass(input, 'contact-captcha-valid');
12819                    input.placeholder = mk_captcha_correct_txt;
12820                    captchaIsValidCallback(form);
12821                }
12822            });
12823        }
12824    }
12825
12826    function callTheAjax( data, $form, progressButton ) {
12827      $.post(ajaxurl, data, function(response) {
12828        var res = JSON.parse(response);
12829        if (res.action_Status) {
12830            progressButton.success($form);
12831            $form.find('.text-input').val('');
12832            $form.find('textarea').val('');
12833            $form.find('input[type=checkbox]').attr("checked", false);
12834            $form.find('.contact-form-message').slideDown().addClass('state-success').html(res.message);
12835            setTimeout(function() {
12836                $form.find('.contact-form-message').slideUp();
12837            }, 5000);
12838        } else {
12839            progressButton.error($form);
12840            $form.find('.contact-form-message').removeClass('state-success').html(res.message);
12841        }
12842      });
12843    }
12844
12845    /**
12846     * Send submitted form.
12847     *
12848     * @param form
12849     */
12850    function sendForm(form) {
12851      var $form = $(form);
12852      var data = getFormData(form);
12853      progressButton.loader($form);
12854
12855      // No captcha enabled.
12856      if ( $form.find( '.g-recaptcha' ).length < 1 ) {
12857        callTheAjax( data, $form, progressButton );
12858        return;
12859      }
12860
12861      const siteKey = $form.find( '.g-recaptcha' ).attr( 'data-sitekey' );
12862      const captchaVersion = $form.find( '.g-recaptcha' ).attr( 'data-type' );
12863
12864      // Captcha v3 enabled.
12865      if ( 'v3' === captchaVersion ) {
12866        grecaptcha.execute( siteKey, { action: 'submit' } ).then( function( token ) {
12867          data['g-recaptcha-response'] = token;
12868          data['g-recaptcha-version'] = captchaVersion;
12869
12870          callTheAjax( data, $form, progressButton )
12871        } );
12872      }
12873
12874      // Captcha v2 enabled
12875      if ( 'v2' === captchaVersion ) {
12876          grecaptcha.execute().then( function() {
12877            setTimeout( function() {
12878              data['g-recaptcha-response'] = jupiterContactFormNewCreatedCaptchaToken;
12879              data['g-recaptcha-version'] = captchaVersion;
12880
12881              callTheAjax( data, $form, progressButton )
12882            }, 2000 );
12883          } );
12884      }
12885    }
12886    /**
12887     * Initialize all captcha images for first time. All captcha images is always same. e.g. if we have multiple form,
12888     * all of them will have the same image.
12889     * It will also add event listener for '.captcha-change-image' objects to reload the captcha.
12890     */
12891    function initializeCaptchas() {
12892        var captchaChangeImageButtons = document.getElementsByClassName('captcha-change-image');
12893        for (var i = 0; i < captchaChangeImageButtons.length; i++) {
12894            captchaChangeImageButtons[i].addEventListener('click', loadCaptcha);
12895        }
12896    }
12897    /**
12898     * Load captcha text and append the image to captcha container.
12899     * If it used as a callback, it will prevent default behave of the event.
12900     * e.g. loading new captcha by click on <a> without changing url.
12901     */
12902    function loadCaptcha(e) {
12903        if (e) {
12904            e.preventDefault();
12905        }
12906        $.post(ajaxurl, {
12907            action: 'mk_create_captcha_image'
12908        }, appendImage);
12909        /**
12910         * The callback function for append or change old image src based on response. T
12911         * The captchaImageURL is the url of the captcha which is provided in ajax response of mk_create_captcha_image.
12912         * @param captchaImageURL
12913         */
12914        function appendImage(captchaImageURL) {
12915            if (captchaImageHolder.find('.captcha-image').length === 0) {
12916                captchaImageHolder.html('<img src="' + captchaImageURL + '" class="captcha-image" alt="captcha txt">');
12917            } else {
12918                captchaImageHolder.find('.captcha-image').attr("src", captchaImageURL + '?' + new Date().getTime());
12919            }
12920        }
12921    }
12922    /**
12923     * Get form inputs using querySelectorAll().
12924     * It returns <input> and <textarea> tags. If you need any other tags such as <select>, please update this function.
12925     *
12926     * @param form
12927     * @returns {NodeList}
12928     */
12929    function getFormInputs(form) {
12930        return form.querySelectorAll('input,textarea');
12931    }
12932    /**
12933     * Get data of the form inputs and textareas as a object.
12934     *
12935     * @param form
12936     * @returns {{action: string}}
12937     */
12938    function getFormData(form) {
12939        var data = {
12940            action: 'mk_contact_form'
12941        };
12942        var inputs = getFormInputs(form);
12943        for (var i = 0; i < inputs.length; i++) {
12944            data[inputs[i].name] = inputs[i].value;
12945        }
12946        return data;
12947    }
12948}
12949/* Ajax Login Form */
12950/* -------------------------------------------------------------------- */
12951function mk_login_form() {
12952    $('form.mk-login-form').each(function() {
12953        var $this = $(this);
12954        $this.on('submit', function(e) {
12955            $('p.mk-login-status', $this).show().text(ajax_login_object.loadingmessage);
12956            $.ajax({
12957                type: 'POST',
12958                dataType: 'json',
12959                url: ajax_login_object.ajaxurl,
12960                data: {
12961                    'action': 'ajaxlogin',
12962                    'username': $('#username', $this).val(),
12963                    'password': $('#password', $this).val(),
12964                    'security': $('#security', $this).val()
12965                },
12966                success: function(data) {
12967                    $('p.mk-login-status', $this).text(data.message);
12968                    if (data.loggedin === true) {
12969                        document.location.href = ajax_login_object.redirecturl;
12970                    }
12971                }
12972            });
12973            e.preventDefault();
12974        });
12975    });
12976}
12977/* Progress Button */
12978/* -------------------------------------------------------------------- */
12979var progressButton = {
12980    loader: function(form) {
12981        MK.core.loadDependencies([MK.core.path.plugins + 'tweenmax.js'], function() {
12982            var $form = form,
12983                progressBar = $form.find(".mk-progress-button .mk-progress-inner"),
12984                buttonText = $form.find(".mk-progress-button .mk-progress-button-content"),
12985                progressButton = new TimelineLite();
12986            progressButton.to(progressBar, 0, {
12987                width: "100%",
12988                scaleX: 0,
12989                scaleY: 1
12990            }).to(buttonText, .3, {
12991                y: -5
12992            }).to(progressBar, 1.5, {
12993                scaleX: 1,
12994                ease: Power2.easeInOut
12995            }, "-=.1").to(buttonText, .3, {
12996                y: 0
12997            }).to(progressBar, .3, {
12998                scaleY: 0
12999            });
13000        });
13001    },
13002    success: function(form) {
13003        MK.core.loadDependencies([MK.core.path.plugins + 'tweenmax.js'], function() {
13004            var $form = form,
13005                buttonText = $form.find(".mk-button .mk-progress-button-content, .mk-contact-button .mk-progress-button-content"),
13006                successIcon = $form.find(".mk-progress-button .state-success"),
13007                progressButtonSuccess = new TimelineLite({
13008                    onComplete: hideSuccessMessage
13009                });
13010            progressButtonSuccess.to(buttonText, .3, {
13011                paddingRight: 20,
13012                ease: Power2.easeInOut
13013            }, "+=1").to(successIcon, .3, {
13014                opacity: 1
13015            }).to(successIcon, 2, {
13016                opacity: 1
13017            });
13018
13019            function hideSuccessMessage() {
13020                progressButtonSuccess.reverse()
13021            }
13022        });
13023    },
13024    error: function(form) {
13025        MK.core.loadDependencies([MK.core.path.plugins + 'tweenmax.js'], function() {
13026            var $form = form,
13027                buttonText = $form.find(".mk-button .mk-progress-button-content, .mk-contact-button .mk-progress-button-content"),
13028                errorIcon = $form.find(".mk-progress-button .state-error"),
13029                progressButtonError = new TimelineLite({
13030                    onComplete: hideErrorMessage
13031                });
13032            progressButtonError.to(buttonText, .3, {
13033                paddingRight: 20
13034            }, "+=1").to(errorIcon, .3, {
13035                opacity: 1
13036            }).to(errorIcon, 2, {
13037                opacity: 1
13038            });
13039
13040            function hideErrorMessage() {
13041                progressButtonError.reverse()
13042            }
13043        });
13044    }
13045};
13046
13047function mk_click_events() {
13048  "use strict";
13049
13050  var eventtype = 'click'; 
13051
13052  $(".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) {
13053    if (event.stopPropagation) {
13054      event.stopPropagation();
13055    } else if (window.event) {
13056      window.event.cancelBubble = true;
13057    }
13058  });
13059  $("html").on(eventtype, function() {
13060    $(".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);
13061    $('.mk-quick-contact-link').removeClass('quick-contact-active');
13062    // Removed By Maki for repairing fullnav scroll issue. Hope it odesnt break anything
13063    // $('body').css('overflow', 'visible');
13064  });
13065
13066  $('.mk-fullscreen-search-overlay').on(eventtype,function(){
13067    $(this).removeClass('mk-fullscreen-search-overlay-show');
13068  });
13069
13070  $('.mk-forget-password').on(eventtype, function() {
13071    $('.mk-forget-panel').siblings().hide().end().show();
13072  });
13073
13074  $('.mk-create-account').on(eventtype, function() {
13075    $('#mk-register-panel').siblings().hide().end().show();
13076  });
13077
13078  $('.mk-return-login').on(eventtype, function() {
13079    $('#mk-login-panel').siblings().hide().end().show();
13080  });
13081
13082
13083  $('.mk-quick-contact-link').on(eventtype, function() {
13084    var $this = $(this),
13085        $quickContact = $('#mk-quick-contact');
13086    if (!$this.hasClass('quick-contact-active')) {
13087      $quickContact.addClass('quick-contact-anim').fadeIn(250);
13088      $this.addClass('quick-contact-active');
13089    } else {
13090      $quickContact.removeClass('quick-contact-anim').fadeOut(100);
13091      $this.removeClass('quick-contact-active');
13092    }
13093    return false;
13094  });
13095
13096}
13097
13098function mk_social_share_global() {
13099
13100  "use strict";
13101
13102  var eventtype = 'click';
13103
13104  $('.twitter-share').on(eventtype, function() {
13105    var $this = $(this),
13106        $url = $this.attr('data-url'),
13107        $title = $this.attr('data-title');
13108
13109    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");
13110    return false;
13111  });
13112
13113  $('.pinterest-share').on(eventtype, function() {
13114    var $this = $(this),
13115        $url = $this.attr('data-url'),
13116        $title = $this.attr('data-title'),
13117        $image = $this.attr('data-image');
13118    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");
13119    return false;
13120  });
13121
13122  $('.facebook-share').on(eventtype, function() {
13123    var $url = $(this).attr('data-url');
13124    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");
13125    return false;
13126  });
13127
13128  $('.googleplus-share').on(eventtype, function() {
13129    var $url = $(this).attr('data-url');
13130    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");
13131    return false;
13132  });
13133
13134  $('.linkedin-share').on(eventtype, function() {
13135    var $this = $(this),
13136        $url = $this.attr('data-url'),
13137        $title = $this.attr('data-title'),
13138        $desc = $this.attr('data-desc');
13139    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");
13140    return false;
13141  });
13142}
13143
13144
13145/* Event Count Down */
13146/* -------------------------------------------------------------------- */
13147
13148function mk_event_countdown() {
13149  if ($.exists('.mk-event-countdown')) {
13150
13151    MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.countdown.js' ], function() {
13152
13153      $('.mk-event-countdown').each(function () {
13154        if (isTest) return;
13155        var $this = $(this),
13156          $date = $this.attr('data-date'),
13157          $offset = $this.attr('data-offset');
13158
13159        $this.downCount({
13160          date: $date,
13161          offset: $offset
13162        });
13163      });
13164      
13165    });
13166  }
13167}
13168/* Flexslider init */
13169/* -------------------------------------------------------------------- */
13170
13171function mk_flexslider_init() {
13172
13173  var $lcd = $('.mk-lcd-slideshow'),
13174      $laptop = $('.mk-laptop-slideshow-shortcode');
13175
13176  if($lcd.length) $lcd.find('.mk-lcd-image').fadeIn();
13177  if($laptop.length) $laptop.find(".mk-laptop-image").fadeIn();
13178
13179  $('.js-flexslider').each(function () {
13180
13181    if ($(this).parents('.mk-tabs').length || $(this).parents('.mk-accordion').length) {
13182      $(this).removeData("flexslider");
13183    }
13184
13185    var $this = $(this),
13186      $selector = $this.attr('data-selector'),
13187      $animation = $this.attr('data-animation'),
13188      $easing = $this.attr('data-easing'),
13189      $direction = $this.attr('data-direction'),
13190      $smoothHeight = $this.attr('data-smoothHeight') == "true" ? true : false,
13191      $slideshowSpeed = $this.attr('data-slideshowSpeed'),
13192      $animationSpeed = $this.attr('data-animationSpeed'),
13193      $controlNav = $this.attr('data-controlNav') == "true" ? true : false,
13194      $directionNav = $this.attr('data-directionNav') == "true" ? true : false,
13195      $pauseOnHover = $this.attr('data-pauseOnHover') == "true" ? true : false,
13196      $isCarousel = $this.attr('data-isCarousel') == "true" ? true : false;
13197
13198
13199    if ($selector !== undefined) {
13200      var $selector_class = $selector;
13201    } else {
13202      var $selector_class = ".mk-flex-slides > li";
13203    }
13204
13205    if ($isCarousel === true) {
13206      var $itemWidth = parseInt($this.attr('data-itemWidth')),
13207        $itemMargin = parseInt($this.attr('data-itemMargin')),
13208        $minItems = parseInt($this.attr('data-minItems')),
13209        $maxItems = parseInt($this.attr('data-maxItems')),
13210        $move = parseInt($this.attr('data-move'));
13211    } else {
13212      var $itemWidth = $itemMargin = $minItems = $maxItems = $move = 0;
13213    }
13214
13215    MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.flexslider.js' ], function() {
13216      $this.flexslider({
13217        selector: $selector_class,
13218        animation: $animation,
13219        easing: $easing,
13220        direction: $direction,
13221        smoothHeight: $smoothHeight,
13222        slideshow: !isTest, // autoplay
13223        slideshowSpeed: $slideshowSpeed,
13224        animationSpeed: $animationSpeed,
13225        controlNav: $controlNav,
13226        directionNav: $directionNav,
13227        pauseOnHover: $pauseOnHover,
13228        prevText: "",
13229        nextText: "",
13230        itemWidth: $itemWidth,
13231        itemMargin: $itemMargin,
13232        minItems: $minItems,
13233        maxItems: $maxItems,
13234        move: $move
13235      });
13236    });
13237
13238  });
13239
13240}
13241
13242/* Header Search Form */
13243/* -------------------------------------------------------------------- */
13244
13245function mk_header_searchform() {
13246
13247  $('.mk-search-trigger').on('click',function(){
13248    setTimeout(function() {
13249        $('#mk-ajax-search-input').focus();
13250    },500);
13251  });
13252
13253  "use strict";
13254
13255  $('.mk-header-toolbar .mk-header-searchform .text-input').on('focus', function () {
13256
13257    if ($('.mk-header-toolbar .mk-header-searchform .text-input').hasClass('on-close-state')) {
13258      $('.mk-header-toolbar .mk-header-searchform .text-input').removeClass('on-close-state').animate({
13259        'width': '200px'
13260      }, 200);
13261      return false;
13262    }
13263  });
13264
13265  $(".mk-header-toolbar .mk-header-searchform").on('click',function (event) {
13266    if (event.stopPropagation) {
13267      event.stopPropagation();
13268    } else if (window.event) {
13269      window.event.cancelBubble = true;
13270    }
13271  });
13272
13273
13274  $("html").on('click',function () {
13275    $(this).find(".mk-header-toolbar .mk-header-searchform .text-input").addClass('on-close-state').animate({
13276      'width': 90
13277    }, 300);
13278  });
13279
13280  // Fix search for edge browser
13281  if(MK.utils.browser.name === 'Edge') {
13282    $('#mk-fullscreen-search-input').on('keydown', function(e) {
13283      if (e.which == 13) {
13284        e.preventDefault();
13285        $('#mk-fullscreen-searchform').submit();
13286      }
13287    });
13288  }
13289
13290}
13291
13292
13293
13294
13295/* Hover Events */
13296/* -------------------------------------------------------------------- */
13297
13298function mk_hover_events() {
13299
13300  "use strict";
13301
13302  $('.shopping-cart-header').hover(
13303    function() {
13304      $(this).find('.mk-shopping-cart-box').stop(true, true).fadeIn(250);
13305    },
13306    function() {
13307      $(this).find('.mk-shopping-cart-box').stop(true, true).delay(500).fadeOut(250);
13308    }
13309  );
13310
13311
13312  $('.widget-sub-navigation > ul > li, .widget_nav_menu ul.menu > li, .widget_product_categories ul > .cat-item').each(function() {
13313
13314    var $this = $(this),
13315        $subLevel = $this.find('ul').first();
13316
13317    if ($this.hasClass('page_item_has_children') || $this.hasClass('menu-item-has-children') || $this.hasClass('cat-parent')) {
13318      $this.on('click', function() {
13319        if($this.hasClass('toggle-active')) {
13320            $subLevel.stop(true, true).slideUp(700);
13321            $this.removeClass('toggle-active');
13322        } else {
13323            $subLevel.stop(true, true).slideDown(700);
13324            $this.addClass('toggle-active');
13325        }
13326      });
13327
13328      $subLevel.on('click', function(e){
13329        e.stopPropagation();
13330      });
13331    }
13332
13333  });
13334
13335  // var eventtype = mobilecheck() ? 'touchstart' : 'click';
13336  var eventtype = 'click';
13337
13338  $('.mk-fullscreen-trigger').on(eventtype, function(e) {
13339    $('.mk-fullscreen-search-overlay').addClass('mk-fullscreen-search-overlay-show');
13340    setTimeout(function(){
13341      $("#mk-fullscreen-search-input").focus();
13342    }, 300);
13343    e.preventDefault();
13344  });
13345
13346  $('.mk-fullscreen-close').on(eventtype, function(e) {
13347    $('.mk-fullscreen-search-overlay').removeClass('mk-fullscreen-search-overlay-show');
13348    e.preventDefault();
13349  });
13350
13351}
13352
13353function mk_unfold_footer() {
13354  var $this = $('#mk-footer'),
13355      $spacer = $('#mk-footer-unfold-spacer'),
13356      $footerHeight = $this.outerHeight();
13357
13358  // Stick with CSS media query breakpoint to target exact screen width
13359  if( !window.matchMedia("(max-width: 767px)").matches ) {
13360      if ($this.hasClass('mk-footer-unfold')) {
13361        $spacer.css('height', $footerHeight);
13362      }
13363  } else {
13364     $spacer.css('height', 0);
13365  }
13366}
13367
13368/* jQuery fancybox lightbox */
13369/* -------------------------------------------------------------------- */
13370function mk_lightbox_init() {
13371
13372	$(".mk-lightbox").fancybox({
13373		loop: true,
13374	});
13375
13376	$.fancybox.defaults.hash = false;
13377
13378}
13379
13380
13381/* Milestone Number Shortcode */
13382/* -------------------------------------------------------------------- */
13383
13384function mk_milestone() {
13385
13386  "use strict";
13387
13388  if( isTest || !$.exists('.mk-milestone') ) return;
13389
13390  $('.mk-milestone').each(function () {
13391    var $this = $(this),
13392      stop_number = $this.find('.milestone-number').attr('data-stop'),
13393      animation_speed = parseInt($this.find('.milestone-number').attr('data-speed'));
13394
13395    var build = function() {
13396      if (!$this.hasClass('scroll-animated')) {
13397        $this.addClass('scroll-animated');
13398
13399        $({
13400          countNum: $this.find('.milestone-number').text()
13401        }).animate({
13402          countNum: stop_number
13403        }, {
13404          duration: animation_speed,
13405          easing: 'linear',
13406          step: function () {
13407            $this.find('.milestone-number').text(Math.floor(this.countNum));
13408          },
13409          complete: function () {
13410            $this.find('.milestone-number').text(this.countNum);
13411          }
13412        });
13413      }
13414    };
13415
13416    if ( !MK.utils.isMobile() ) {
13417      // refactored only :in-viewport logic. rest is to-do
13418      MK.utils.scrollSpy( this, {
13419          position: 'bottom',
13420          after: build
13421      });
13422    } else {
13423      build();
13424    }
13425
13426  });
13427
13428}
13429
13430
13431
13432
13433/* Recent Works Widget */
13434/* -------------------------------------------------------------------- */
13435
13436function mk_portfolio_widget() {
13437
13438  "use strict";
13439
13440  $('.widget_recent_portfolio li').each(function () {
13441
13442    $(this).find('.portfolio-widget-thumb').on('hover',function () {
13443
13444      $(this).siblings('.portfolio-widget-info').animate({
13445        'opacity': 1
13446      }, 200);
13447    }, function () {
13448
13449      $(this).siblings('.portfolio-widget-info').animate({
13450        'opacity': 0
13451      }, 200);
13452    });
13453
13454  });
13455}
13456
13457
13458
13459/* Skill Meter and Charts */
13460/* -------------------------------------------------------------------- */
13461function mk_skill_meter() {
13462    "use strict";
13463    if ($.exists('.mk-skill-meter')) {
13464        if (!MK.utils.isMobile()) {
13465            $(".mk-skill-meter .progress-outer").each(function() {
13466                var $this = $(this);
13467
13468                var build = function() {
13469                    if (!$this.hasClass('scroll-animated')) {
13470                        $this.addClass('scroll-animated');
13471                        $this.animate({
13472                            width: $this.attr("data-width") + '%'
13473                        }, 2000);
13474                    }
13475                };
13476
13477                MK.utils.scrollSpy( this, {
13478                    position: 'bottom',
13479                    after: build
13480                });
13481            });
13482        } else {
13483            $(".mk-skill-meter .progress-outer").each(function() {
13484                var $this = $(this);
13485                if (!$this.hasClass('scroll-animated')) {
13486                    $this.addClass('scroll-animated');
13487                    $this.css({
13488                        width: $(this).attr("data-width") + '%'
13489                    });
13490                }
13491            });
13492        }
13493    }
13494}
13495
13496// function mk_charts() {
13497//     "use strict";
13498
13499//     if( !$.exists('.mk-chart') ) return;
13500
13501//     MK.core.loadDependencies([ MK.core.path.plugins + 'jquery.easyPieChart.js' ], function() {
13502
13503//         $('.mk-chart').each(function() {
13504
13505//             var $this = $(this),
13506//                 $parent_width = $(this).parent().width(),
13507//                 $chart_size = parseInt($this.attr('data-barSize'));
13508
13509//             if ($parent_width < $chart_size) {
13510//                 $chart_size = $parent_width;
13511//                 $this.css('line-height', $chart_size);
13512//                 $this.find('i').css({
13513//                     'line-height': $chart_size + 'px'
13514//                 });
13515//                 $this.css({
13516//                     'line-height': $chart_size + 'px'
13517//                 });
13518//             }
13519
13520//             var build = function() {
13521//                 $this.easyPieChart({
13522//                     animate: 1300,
13523//                     lineCap: 'butt',
13524//                     lineWidth: $this.attr('data-lineWidth'),
13525//                     size: $chart_size,
13526//                     barColor: $this.attr('data-barColor'),
13527//                     trackColor: $this.attr('data-trackColor'),
13528//                     scaleColor: 'transparent',
13529//                     onStep: function(value) {
13530//                         this.$el.find('.chart-percent span').text(Math.ceil(value));
13531//                     }
13532//                 });
13533//             };
13534
13535//             // refactored only :in-viewport logic. rest is to-do
13536//             MK.utils.scrollSpy( this, {
13537//                 position: 'bottom',
13538//                 after: build
13539//             });
13540
13541
13542//         });
13543//     });
13544// }
13545/* Toolbar subscribe form */
13546/* -------------------------------------------------------------------- */
13547
13548$( "#mc-embedded-subscribe-form" ).on('submit',function( e ){
13549    var $this = $(this);
13550
13551    e.preventDefault();
13552    $.ajax({
13553        url: MK.core.path.ajaxUrl,
13554        type: "POST",
13555        data: {
13556            action: "mk_ajax_subscribe",
13557            email: $this.find( ".mk-subscribe--email" ).val(),
13558            list_id: $this.find( ".mk-subscribe--list-id" ).val(),
13559            optin: $this.find( ".mk-subscribe--optin" ).val()
13560        },
13561        success: function ( res ) {
13562            $this.parent().find( ".mk-subscribe--message" ).html( $.parseJSON( res ).message );
13563        }
13564    });
13565});
13566
13567/**
13568 * Add class to tag. It's vanilla js instead of jQuery.
13569 * @param tag
13570 * @param className
13571 */
13572function addClass(tag, className) {
13573    tag.className += ' ' + className;
13574}
13575
13576/**
13577 * Remove class from tag. It's vanilla js instead of jQuery.
13578 * Replacing should be with g for replacing all occurrence.
13579 *
13580 * @param tag
13581 * @param className
13582 */
13583function removeClass(tag, className) {
13584    tag.className = tag.className.replace(new RegExp(className, 'g'), '');
13585}
13586
13587
13588/**
13589 * If we're running under Node for testing purpose.
13590 */
13591if(typeof exports !== 'undefined') {
13592    exports.addClass = addClass;
13593    exports.removeClass = removeClass;
13594}
13595
13596/*!
13597*  javascript-debounce 1.0.0
13598*
13599*  A lightweight, dependency-free JavaScript module for debouncing functions based on David Walsh's debounce function.
13600*
13601*  Source code available at: https://github.com/jgarber623/javascript-debounce
13602*
13603*  (c) 2015-present Jason Garber (http://sixtwothree.org)
13604*
13605*  javascript-debounce may be freely distributed under the MIT license.
13606*/
13607
13608(function(root, factory) {
13609	if (typeof define === "function" && define.amd) {
13610		define([], factory);
13611	} else if (typeof exports === "object") {
13612		module.exports = factory();
13613	} else {
13614		root.debounce = factory();
13615	}
13616})(this, function() {
13617	"use strict";
13618	return function(callback, delay) {
13619		var timeout;
13620		return function() {
13621			var context = this, args = arguments;
13622			clearTimeout(timeout);
13623			timeout = setTimeout(function() {
13624				callback.apply(context, args);
13625			}, delay);
13626		};
13627	};
13628});
13629
13630/**
13631 * Validate email address.
13632 *
13633 * @param input
13634 * @param invalidClassName
13635 * @returns boolean
13636 */
13637function validateEmail(input, invalidClassName) {
13638    var value = input.value.trim();
13639    if ((input.required || value.length > 0) && !/^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,63})$/i.test(value)) {
13640        if (invalidClassName) {
13641            addClass(input, invalidClassName);
13642        }
13643        return false;
13644    } else {
13645        if (invalidClassName) {
13646            removeClass(input, invalidClassName);
13647        }
13648        return true;
13649    }
13650}
13651/**
13652 * Validate text entry.
13653 *
13654 * @param input
13655 * @param invalidClassName
13656 * @returns boolean
13657 */
13658function validateText(input, invalidClassName) {
13659    var value = input.value.trim();
13660    if (input.required && value.length === 0) {
13661        if (invalidClassName) {
13662            addClass(input, invalidClassName);
13663        }
13664        return false;
13665    } else {
13666        if (invalidClassName) {
13667            removeClass(input, invalidClassName);
13668        }
13669        return true;
13670    }
13671}
13672/**
13673 * Validate Checkbox.
13674 *
13675 * @param input
13676 * @param invalidClassName
13677 * @returns boolean
13678 */
13679function validateCheckBox(input, invalidClassName) {
13680    if (input.required && input.checked == false) {
13681        if (invalidClassName) {
13682            addClass(input, invalidClassName);
13683        }
13684        return false;
13685    } else {
13686        if (invalidClassName) {
13687            removeClass(input, invalidClassName);
13688        }
13689        return true;
13690    }
13691}
13692/**
13693 * If we're running under Node for testing purpose.
13694 */
13695if (typeof exports !== 'undefined') {
13696    exports.validateEmail = validateEmail;
13697    exports.validateText = validateText;
13698}
13699(function( $ ) {
13700	'use strict';
13701
13702    var $wrapper = $('.js-bottom-corner-btns');
13703    var $contactBtn = $wrapper.find('.js-bottom-corner-btn--contact');
13704    var $backBtn = $wrapper.find('.js-bottom-corner-btn--back');
13705    var hasContactBtn = $contactBtn.length;
13706    var hasBackBtn = $backBtn.length;
13707
13708    if(!hasBackBtn) return;
13709
13710    function deactivate() {
13711        $contactBtn.removeClass('is-active');
13712        $backBtn.removeClass('is-active');
13713    }
13714
13715    function activate() { 
13716        $contactBtn.addClass('is-active');
13717        $backBtn.addClass('is-active');
13718    }
13719
13720    MK.utils.scrollSpy( 400, {
13721        before: deactivate,
13722        after: activate
13723    });
13724
13725})( jQuery );
13726(function($) {
13727	'use strict';
13728	
13729	$('.mk-fullscreen-nav-close, .mk-fullscreen-nav-wrapper, #fullscreen-navigation a').on('click', function(e) {
13730		
13731		// Close nav with removing classes
13732		$('.mk-fullscreen-nav').removeClass('opened');
13733		$('.mk-dashboard-trigger').removeClass('fullscreen-active');
13734		$('body').removeClass('fullscreen-nav-opened'); 
13735		
13736		var anchor = MK.utils.detectAnchor( this ),
13737		$this = $( this );
13738		
13739		// Scroll to anchor if exists
13740		if( anchor.length ) {
13741			// Moved 4 these lines after anchor check because console error. If anchor
13742			// return false, split part will throw an error because $this is not a link.
13743			// Fix AM-2027
13744			var href = $this.attr( 'href' ).split( '#' )[0];
13745			var url = window.location.href;
13746			var isSamePage = url.indexOf( href ) !== -1;
13747
13748			if ( isSamePage ) {
13749				e.preventDefault();
13750			}
13751			MK.utils.scrollToAnchor( anchor );
13752			
13753		// Or do nothing if pointless # as href
13754		// BAD  PRACTICE: it is very popular to use "#" for click elements that we listen to with js.
13755		// GOOD PRACTICE: prefer "javascript:;" as easier to handle and more readable version
13756		} else if( $this.attr( 'href' ) === '#' ) {
13757			e.preventDefault();
13758		}
13759	});
13760	
13761	$('.fullscreen-navigation-ul .menu-sub-level-arrow').on('click', function(){
13762		$(this).siblings('.sub-menu').slideToggle();
13763	});
13764	
13765}(jQuery));
13766(function($) {
13767	'use strict';
13768
13769	/**
13770     * Mega menu
13771     */
13772    var $navList = $(".main-navigation-ul");
13773    var megaMenu = function megaMenu() {
13774
13775        $navList.MegaMenu({
13776            type: "vertical",
13777            delay: 200
13778        });
13779    };
13780
13781    $(window).on('load', megaMenu);
13782
13783}(jQuery));
13784(function($) {
13785	'use strict';
13786
13787	/**
13788     * One pager menu hash update. 
13789     * Smooth scroll is appended globally whenever the click element has corresponding #el
13790     */    
13791    var onePageNavItem = function onePageNavItem() {
13792        var $this = $( this ),
13793            link = $this.find( 'a' ),
13794            anchor = MK.utils.detectAnchor( link ); // anchor on current page
13795
13796        if( !anchor.length ) return;
13797
13798        $this.removeClass( 'current-menu-item current-menu-ancestor current-menu-parent' );
13799
13800        var activeNav = function( state ) {
13801            return function() {
13802                $this[ state ? 'addClass' : 'removeClass' ]( 'current-menu-item' );
13803                window.history.replaceState( undefined, undefined, [ state ? anchor : ' ' ] );
13804            };
13805        };
13806
13807        MK.utils.scrollSpy( $( anchor )[0], {
13808            before : activeNav( false ),
13809            active : activeNav( true ),
13810            after  : activeNav( false ),
13811        });
13812    };
13813
13814    var $navItems = $('.js-main-nav').find( 'li' );
13815    
13816    $(window).on('load', function() {
13817        // Wait with spying anchors so we do not assign anchor that is browser scroll to after page load
13818        // Especially when there are anchors on top - refreshing page can cause grabbing one of them into url
13819        // and force unwanted scroll
13820        setTimeout(function() {
13821            $navItems.each( onePageNavItem );
13822        }, 1000);
13823    });
13824	
13825}(jQuery));
13826(function($) {
13827    'use strict';
13828
13829    var $window = $(window);
13830    var $body = $('body');
13831    var $resMenuWrap = $('.mk-responsive-wrap');
13832    var $post_nav = $('.mk-post-nav');
13833    var $toolbar = $('.mk-header-toolbar');
13834    var $resMenuLink = $('.mk-nav-responsive-link');
13835
13836    // Flags
13837    var hasResMenu = ($resMenuWrap.length > 0);
13838
13839    //initial window and screen height
13840    var windowHeight = $window.height();
13841    var screenHeight = screen.height;
13842
13843    // We keep this handler above hasResMenu flag.
13844    // Even if our header doesn't contain droppable responsive menu (in favor of fullscreen or side menu) 
13845    // we still transform tollbar into collapsible menu part in responsive state
13846    $('.mk-toolbar-resposnive-icon').on('click', function(e) {
13847        e.preventDefault();
13848        console.log('clicked');
13849        if ($body.hasClass('toolbar-opened')) {
13850            $body.removeClass('toolbar-opened').addClass('toolbar-closed');
13851            $toolbar.hide();
13852        } else {
13853            $body.removeClass('toolbar-closed').addClass('toolbar-opened');
13854            $toolbar.show();
13855        }
13856    });
13857
13858
13859    if ( ! hasResMenu && ! $('.vc_mk_header') ) return;
13860
13861    function toggleResMenu(e) {
13862        e.preventDefault();
13863        var $this = $(this);
13864        var $headerInner = $this.parents('header');
13865        var $resMenu = $headerInner.find('.mk-responsive-wrap');
13866        var searchBox = $('.responsive-searchform .text-input');
13867        var adminBarHeight = $('#wpadminbar').height(); /* Fix AM-1918 */
13868
13869        if ($body.hasClass('mk-opened-nav')) {
13870            $this.removeClass('is-active');
13871            $body.removeClass('mk-opened-nav').addClass('mk-closed-nav').trigger('mk-closed-nav');
13872            $resMenu.hide();
13873            $post_nav.removeClass('post-nav-backward');
13874        } else {
13875            $this.addClass('is-active');
13876            $body.removeClass('mk-closed-nav').addClass('mk-opened-nav').trigger('mk-opened-nav');
13877            $resMenu.show();
13878            $post_nav.addClass('post-nav-backward');
13879
13880        }
13881
13882        //for iPhone 5 focus bug , remove search box focused class
13883        if(searchBox.hasClass('input-focused')){
13884            searchBox.removeClass('input-focused');
13885        }
13886        
13887    }
13888
13889    $resMenuLink.each(function() {
13890        $(this).on('click', toggleResMenu);
13891    });
13892
13893    $( window ).on( 'vc_reload', function () {
13894        $('.vc_mk_header .mk-nav-responsive-link').each(function() {
13895            $(this).on('click', toggleResMenu);
13896        });
13897    } )
13898
13899    var setResMenuHeight = function() {
13900        var height = $window.height() - MK.val.offsetHeaderHeight(0);
13901        $resMenuWrap.css('max-height', height);
13902    };
13903
13904    // check if device virtual keyboard is active 
13905    var isVirtualKeyboard = function() {
13906        var currentWindowHeight = $window.height();
13907        var currentScreenHeight = screen.height;
13908        var searchBox = $('.responsive-searchform .text-input');
13909        var searchBoxIsFocused = false; 
13910
13911        //for iPhone 5 focus bug , add class for detect focus state
13912        searchBox.on('touchstart touchend', function(e) {
13913            searchBox.addClass('input-focused');
13914        });
13915
13916        searchBoxIsFocused = (searchBox.is(':focus') || searchBox.hasClass("input-focused"));
13917
13918        if ($body.hasClass('mk-opened-nav') && searchBoxIsFocused && currentScreenHeight == screenHeight && currentWindowHeight != windowHeight) {
13919            return true;
13920        } else {
13921            return false;
13922        }
13923    };
13924
13925    var hideResMenu = function hideResMenu() {
13926        if (MK.utils.isResponsiveMenuState()) {
13927
13928            //when search box in responsive menu is focused , window resize fired but at this time responsive menu should be open
13929            if (!isVirtualKeyboard()) {
13930                // hide toggled menu and its states
13931                if ($body.hasClass('mk-opened-nav')) {
13932                    $resMenuLink.filter('.is-active').trigger('click');
13933                }
13934                // hide menu wrapper
13935                $resMenuWrap.hide();
13936
13937            }
13938        }
13939    };
13940
13941    $resMenuWrap.on('click', 'a', hideResMenu);
13942
13943}(jQuery));
13944
13945(function($) {
13946    'use strict';
13947
13948    var $header = $('.mk-header');    
13949    var hasHeader = ($header.length > 0);
13950
13951    if(!hasHeader && ! $('.vc_mk_header') ) return;
13952    
13953    var $sticky_style = $header.attr('data-header-style');
13954
13955    //if ($sticky_style !== 3) return;
13956
13957    $('.sidedash-navigation-ul > li').each(function() {
13958        var $this = $(this);
13959
13960        $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>');
13961    });
13962
13963    function toggleSubMenu(e) {
13964        e.preventDefault();
13965        var $this = $(this);
13966        
13967        if ($this.hasClass('mk-nav-sub-closed')) {
13968            $this.siblings('ul').slideDown(450).end().removeClass('mk-nav-sub-closed').addClass('mk-nav-sub-opened');
13969        } else {
13970            $this.siblings('ul').slideUp(450).end().removeClass('mk-nav-sub-opened').addClass('mk-nav-sub-closed');
13971        }
13972    };
13973
13974    function toggleFullMenu(e) {
13975        e.preventDefault();
13976        var $this = $(this),
13977            $body = $('body'),
13978            $fullscreen_box = $('.mk-fullscreen-nav');
13979
13980        if ($this.hasClass('dashboard-style')){
13981          if (!$this.hasClass('dashboard-active')) {
13982            $this.addClass('dashboard-active');
13983            $body.addClass('dashboard-opened');
13984          } else {
13985            $this.removeClass('dashboard-active'); 
13986            $body.removeClass('dashboard-opened');
13987          }
13988        }else if($this.hasClass('fullscreen-style')){
13989          if (!$this.hasClass('fullscreen-active')) {
13990            $this.addClass('fullscreen-active');
13991            $body.addClass('fullscreen-nav-opened');
13992            $fullscreen_box.addClass('opened');
13993            // MK.utils.scroll.disable();
13994          } else {
13995            $this.removeClass('fullscreen-active');
13996            $body.removeClass('fullscreen-nav-opened');
13997            $fullscreen_box.removeClass('opened');
13998          }
13999        }
14000    }
14001
14002    $('.mk-nav-arrow').each(function() {
14003        $(this).stop(true).on('click', toggleSubMenu);
14004    });
14005
14006    $('.mk-dashboard-trigger').each(function() {
14007        $(this).on('click', toggleFullMenu);
14008    });
14009
14010    $( window ).on( 'vc_reload', function () {
14011        $('.vc_mk_header .mk-dashboard-trigger').each(function() {
14012            $(this).on('click', toggleFullMenu);
14013        });
14014
14015        $('.vc_mk_header .mk-nav-arrow').each(function() {
14016            $(this).stop(true).on('click', toggleSubMenu);
14017       });
14018    } );
14019
14020    $('html').on('click', function() {
14021        $('body').removeClass('dashboard-opened');
14022        $('.mk-dashboard-trigger').removeClass('dashboard-active');
14023    });
14024
14025}(jQuery));
14026
14027(function($) {
14028	'use strict';
14029
14030    /**
14031     * Vertical menu
14032     */
14033    var $verticalMenu = $('#mk-vm-menu');
14034    var verticalMenu = function verticalMenu() {
14035        if(!$verticalMenu.data('vertical-menu') && !MK.utils.isResponsiveMenuState()) {
14036            $verticalMenu.dlmenu();
14037            $verticalMenu.data('vertical-menu', true);
14038        }
14039    };
14040
14041    verticalMenu();
14042    $(window).on('resize', verticalMenu);
14043	
14044}(jQuery));
14045(function($) {
14046    'use strict';
14047
14048    // WPML
14049    var $lang_item = $('.mk-main-navigation > .main-navigation-ul > .menu-item-language');
14050    $lang_item.addClass('no-mega-menu').css('visibility', 'visible');
14051    $('.mk-main-navigation .menu-item-language > a').addClass('menu-item-link');
14052
14053})(jQuery);
14054(function($) {
14055	'use strict';
14056
14057    var $header = $( '.mk-header' ).first(); // Theme header is always first, do not apply to shortcode headers.
14058    var hasHeader = ($header.length > 0);
14059
14060    if(!hasHeader) return;
14061
14062    var $window = $( window );
14063    var $document = $( document );
14064    var $headerHolder = $header.find( '.mk-header-holder' );
14065    var $paddingWrapper = $header.find('.mk-header-padding-wrapper');
14066    var config = $header.data();
14067
14068    /**
14069     * Flags
14070     * @type {Boolean}
14071     */
14072    var isStickyLazy = (config.stickyStyle === 'lazy');
14073    var isStickyFixed = (config.stickyStyle === 'fixed');
14074    var isStickySlide = (config.stickyStyle === 'slide');
14075
14076    function isSticky() { // Check for sticky compatibility
14077        //return config.headerStyle !== 4; header style 4 needs sticky state for transparent header.
14078        return true;
14079    }
14080
14081    function isColorable() { // Check for coloring compatibility
14082        // TODO make it explicit in DOM that header is transparent as this is only scenario for colorable header
14083        // Monkey patch - exclude header styles that don't fit colorable
14084        return config.headerStyle !== 4;
14085    }
14086
14087
14088    /**
14089     * Change header skin
14090     */
14091	function changeSkin( e, skin ) {
14092		$header.attr( 'data-transparent-skin', skin );
14093        // Fix for class based skining
14094        var contrast = skin === 'light' ? 'dark' : 'light';
14095        $header.addClass(skin + '-skin');
14096        $header.removeClass(contrast + '-skin');
14097	}
14098
14099    if(isColorable()) MK.utils.eventManager.subscribe( 'firstElSkinChange', changeSkin );
14100
14101
14102    // Assign sticky scenarions
14103    if (isSticky() && isStickyLazy) {
14104      if(config.headerStyle !== 2) {
14105        lazySticky();
14106      }
14107    }
14108    else if (isSticky() && isStickyFixed) fixedSticky();
14109    else if (isSticky() && isStickySlide) slideSticky();
14110
14111    /**
14112     * Sticky header behavior: Lazy
14113     */
14114    function lazySticky() {
14115        var elClassHidden = 'header--hidden';
14116        var elClassSticky = 'a-sticky';
14117        var wScrollCurrent = 0;
14118        var wScrollBefore = 0;
14119        var wScrollDiff = 0;
14120        var wHeight = 0;
14121        var dHeight = 0;
14122
14123        var setSizes = function setSizes() {
14124            dHeight = $document.height();
14125            wHeight = $window.height();
14126        };
14127
14128        var onScroll = function onScroll() {
14129            wScrollCurrent = MK.val.scroll();
14130            wScrollDiff = wScrollBefore - wScrollCurrent;
14131
14132            if( wScrollCurrent <= 0 ) { // scrolled to the very top; element sticks to the top
14133                $headerHolder.removeClass( elClassHidden );
14134                $header.removeClass( elClassSticky );
14135                $('body').trigger('mk:header-unsticky');
14136
14137            } else if( wScrollDiff > 0 && $headerHolder.hasClass( elClassHidden ) ) { // scrolled up; element slides in
14138                $headerHolder.removeClass( elClassHidden );
14139                $header.addClass( elClassSticky );
14140                $('body').trigger('mk:header-sticky');
14141
14142            } else if( wScrollDiff < 0 ) { // scrolled down
14143
14144                if( wScrollCurrent + wHeight >= dHeight && $headerHolder.hasClass( elClassHidden ) ) { // scrolled to the very bottom; element slides in
14145                    $headerHolder.removeClass( elClassHidden );
14146                    $header.addClass( elClassSticky );
14147                    $('body').trigger('mk:header-sticky');
14148                } else { // scrolled down; element slides out
14149                    $headerHolder.addClass( elClassHidden );
14150                    $header.removeClass( elClassSticky );
14151                    $('body').trigger('mk:header-unsticky');
14152                }
14153            }
14154
14155            wScrollBefore = wScrollCurrent;
14156        };
14157
14158        setSizes();
14159        onScroll();
14160        $window.on( 'resize', MK.utils.throttle( 100, setSizes ) );
14161        $window.on( 'scroll', MK.utils.throttle( 500, onScroll ) );
14162    }
14163
14164
14165    /**
14166     * Sticky header behavior: Fixed
14167     */
14168    function fixedSticky() {
14169        var sticked = false;
14170        var scrollPos;
14171
14172        var toggleState = function toggleState() {
14173            scrollPos = MK.val.scroll() + MK.val.adminbarHeight();
14174
14175            if( (scrollPos > MK.val.stickyOffset() ) && ! MK.utils.isResponsiveMenuState() ) {
14176                if(sticked) return; // stop if already sticked
14177                $header.addClass('a-sticky');
14178                sticked = true;
14179                $('body').trigger('mk:header-sticky');
14180            } else {
14181                if(!sticked) return; // stop if already unsticked
14182                $header.removeClass('a-sticky');
14183                sticked = false;
14184                $('body').trigger('mk:header-unsticky');
14185            }
14186        };
14187
14188        toggleState();
14189        $window.on( 'scroll', MK.utils.throttle( 100, toggleState) );
14190        $window.on( 'resize', MK.utils.throttle( 100, toggleState) );
14191    }
14192
14193
14194    /**
14195     * Sticky header behavior: Slide
14196     */
14197    function slideSticky() {
14198        var sticked = false;
14199        var onScroll = function onScroll() {
14200            if (MK.val.scroll() > MK.val.stickyOffset()) {
14201                if(sticked) return; // stop if already sticked
14202                $header.addClass('pre-sticky');
14203                $paddingWrapper.addClass('enable-padding');
14204                setTimeout(function() {
14205                    $header.addClass('a-sticky');
14206                    $('body').trigger('mk:header-sticky');
14207                }, 1);
14208                sticked = true;
14209            } else {
14210                if(!sticked) return; // stop if already unsticked
14211                $header.removeClass('a-sticky');
14212                $header.removeClass('pre-sticky');
14213                $paddingWrapper.removeClass('enable-padding');
14214                sticked = false;
14215                $('body').trigger('mk:header-unsticky');
14216            }
14217        };
14218
14219        onScroll();
14220        $window.on( 'scroll', MK.utils.throttle( 100, onScroll) );
14221    }
14222
14223    // TODO
14224    // var pageIntro = $('body').data('intro'); // block scrolling on page intro
14225
14226
14227})( jQuery );
14228
14229(function($){
14230	'use strict';
14231
14232	// Do not assign at all if no touch events
14233	var hasTouchscreen = ('ontouchstart' in document.documentElement);
14234	if(!hasTouchscreen) return;
14235
14236	$('.mk-main-navigation .menu-item-has-children').each( normalizeClick );
14237
14238	function normalizeClick() {
14239		$(this).on('click', handleClick);
14240	}
14241
14242	// 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.
14243	// 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
14244	function handleClick(e) {
14245		var $this = $(e.currentTarget);
14246		var $child = $this.find('> ul');
14247		var isVisible = $child.css('display') !== 'none';
14248
14249		if(!isVisible) {
14250			e.preventDefault();
14251			e.stopPropagation();
14252		}
14253	}
14254
14255}(jQuery));
14256(function( $ ) {
14257	'use strict';
14258
14259	MK.ui.preloader = {
14260		dom : {
14261			overlay: '.mk-body-loader-overlay'
14262		},
14263
14264		hide : function hide() {
14265			$( this.dom.overlay ).fadeOut(600, "easeInOutExpo", function() {
14266				$('body').removeClass('loading');
14267            //$( this ).remove();
14268         });
14269		}
14270	};  
14271
14272})( jQuery ); 
14273(function($) {
14274	'use strict';
14275
14276    var _ajaxUrl = MK.core.path.ajaxUrl;
14277    var _instances = {};
14278
14279	MK.utils.ajaxLoader = function ajaxLoader(el) {
14280		// retrun a cached instance to have control over state from within multiple places
14281		// we may need for example to reset pageId when do filtering. It is really one instance that controls both filtering and pagination / load more
14282		var id = '#' + ($(el).attr('id'));
14283		if(typeof _instances[id] !== 'undefined') return _instances[id];
14284
14285		// else lets start new instance
14286		this.id = id;
14287		this.el = el;
14288		this.isLoading = false;
14289		this.xhrCounter = 0;
14290	};
14291
14292	MK.utils.ajaxLoader.prototype = { 
14293		init: function init() {
14294			// prevent double initialization of we return an instance
14295			if ( this.initialized && typeof window.vc_iframe === 'undefined' ) {
14296				return;
14297			}
14298
14299			this.createInstance();
14300			this.cacheElements();
14301
14302			this.initialized = true;
14303		},
14304
14305		cacheElements: function cacheElements() {
14306			this.$container = $(this.el);
14307			this.id = '#' + (this.$container.attr('id'));
14308	        this.categories = this.$container.data('loop-categories');
14309
14310			this.data = {};
14311			this.data.action = 'mk_load_more';
14312	        this.data.query = this.$container.data('query');
14313	        this.data.atts = this.$container.data('loop-atts');
14314	        this.data.loop_iterator = this.$container.data('loop-iterator');
14315	        this.data.author = this.$container.data('loop-author');
14316	        this.data.posts = this.$container.data('loop-posts');
14317	        this.data.safe_load_more = this.$container.siblings('#safe_load_more').val();
14318	        this.data._wp_http_referer = this.$container.siblings('input[name="_wp_http_referer"]').val();
14319	        this.data.paged = 1;
14320	        this.data.maxPages = this.$container.data('max-pages');
14321	        this.data.term = this.categories;
14322		},
14323
14324		createInstance: function() {
14325			_instances[this.id] = this;
14326		},
14327
14328		load: function load(unique) {
14329			var self = this;
14330			var seq = ++this.xhrCounter;
14331            this.isLoading = true;
14332			
14333			// If mk-ajax-loaded-posts span exists, get the post ids
14334			if ( this.$container.siblings('.mk-ajax-loaded-posts').length ) {
14335				var loaded_posts = this.$container.siblings('.mk-ajax-loaded-posts').attr('data-loop-loaded-posts');
14336				
14337				// Do not send looaded posts for Classic Pagination Navigation
14338				if ( this.$container.attr('data-pagination-style') != 1 ) {
14339					self.data.loaded_posts = loaded_posts.split(',');
14340				}
14341			}
14342
14343            return $.when(
14344	            $.ajax({
14345	                url 	: _ajaxUrl,
14346	                type 	: "POST",
14347	                data 	: self.data
14348	            })
14349	        ).done(function(response) {
14350	        	self.onDone(response, unique, seq);
14351	        });
14352		},
14353
14354		onDone: function(response, unique, seq) {
14355			if(seq === this.xhrCounter) {
14356				var self = this;
14357
14358				response = $.parseJSON(response);
14359				response.unique = unique;
14360				response.id = this.id;
14361				
14362				// If mk-ajax-loaded-posts span exists, update current post ids 
14363				// with new post ids from server's response
14364				if ( this.$container.siblings('.mk-ajax-loaded-posts').length ) {
14365					this.$container.siblings('.mk-ajax-loaded-posts').attr('data-loop-loaded-posts', response.loaded_posts);
14366				}
14367
14368	            this.setData({
14369	                maxPages: response.maxPages,
14370	                found_posts: response.found_posts,
14371	                loop_iterator: response.i
14372	            });
14373
14374				// Preload images first by creating object from returned content.
14375				// mk_imagesLoaded() method will create a promise that gets resolved when all images inside are loaded.
14376				// Our ajaxLoad is somehow more similar to window.onload event now.
14377				$(response.content).mk_imagesLoaded().then(function() {
14378					MK.utils.eventManager.publish('ajaxLoaded', response);
14379		        	self.isLoading = false;
14380		        	self.initNewComponents();
14381				});
14382
14383	        } else console.log('XHR request nr '+ seq +' aborted');
14384
14385        },
14386
14387		setData: function setData(atts) {
14388			for(var att in atts) {
14389				if(att === 'term' && atts[att] === '*') this.data.term = '';
14390				else this.data[att] = atts[att];
14391			}
14392		},
14393
14394		getData: function getData(att) {
14395			return this.data[att];
14396		},
14397
14398		initNewComponents: function initNewComponents() {
14399            // Legacy scripts reinit
14400            window.ajaxInit();
14401            setTimeout(window.ajaxDelayedInit, 1000);
14402            // New way to init apended things
14403            MK.core.initAll(this.el);
14404        }
14405	};
14406
14407}(jQuery));
14408MK.component.BackgroundImageSetter = (function ($) {
14409
14410	'use strict';
14411
14412	var module = {};
14413
14414
14415	/*---------------------------------------------------------------------------------*/
14416	/* Private Variables
14417	/*---------------------------------------------------------------------------------*/
14418
14419	/**
14420	 *	Take all elements with data-mk-img-set attribute and evaluate best image according to given device orientation and resolution,
14421	 *	sets style for backround-image on the same node element.	 *
14422	 */
14423
14424	var $win = $(window),
14425		// $layers = $('[data-mk-img-set]'),
14426		screen = getScreenSize(),
14427		orientation = getOrientation(),
14428		device = getDevice(),
14429		lastOrientation = orientation,
14430		lastDevice = device;
14431
14432
14433	/*---------------------------------------------------------------------------------*/
14434	/* Private Methods
14435	/*---------------------------------------------------------------------------------*/
14436
14437	function run($layers) {
14438		$layers.filter( function() {
14439			return !this.hasAttribute("mk-img-loaded");
14440		}).each(applyBg);
14441	}
14442
14443	// Keep our main side effect out of calculations so they can be run once before loop of applying bg as a result
14444	function applyBg() {
14445		var $this = $(this),
14446			imgs = $this.data('mk-img-set');
14447
14448		$this.css('background-image', 'url('+ module.getImage(imgs) +')');
14449		$this.find('.mk-adaptive-image').attr('src', module.getImage(imgs));
14450	}
14451
14452	// Keep track of current screen size while resizing but update device reference
14453	// and reapply backgrounds only when we discover switch point
14454	function handleResize($layers) {
14455		updateScreenSize();
14456		if(hasSwitched()) {
14457			updateDevice();
14458			run($layers);
14459		}
14460	}
14461
14462	function getScreenSize() {
14463		return {
14464			w: $win.width(),
14465			h: $win.height()
14466		};
14467	}
14468
14469	// Name our device classes and add them id which simply means which one is wider
14470	function getDevice() {
14471		if     (screen.w > 1024) 	return {class: 'desktop', id: 2};
14472		else if(screen.w > 736) 	return {class: 'tablet',  id: 1};
14473		else 					 	return {class: 'mobile',  id: 0};
14474	}
14475
14476	function getOrientation() {
14477		if(screen.w > screen.h) 	return 'landscape';
14478		else 						return 'portrait';
14479	}
14480
14481	function updateScreenSize() {
14482		screen = getScreenSize();
14483	}
14484
14485	function updateDevice() {
14486		if(lastOrientation !== orientation) orientation = lastOrientation;
14487		// Switch device only if going from smaller size to bigger.
14488		// Bigger to smaller is perfectly handled by browsers and doesn't require change and reupload
14489		if(lastDevice.id > device.id) device = lastDevice;
14490	}
14491
14492	function hasSwitched() {
14493		lastOrientation = getOrientation();
14494		lastDevice = getDevice();
14495
14496		if(lastOrientation !== orientation || lastDevice.class !== device.class) return true;
14497		else return false;
14498	}
14499
14500
14501	/*---------------------------------------------------------------------------------*/
14502	/* Public Methods
14503	/*---------------------------------------------------------------------------------*/
14504
14505	// As desired image might be not available we have to evaluate the best match.
14506	module.getImage = function (imgs) {
14507		if (imgs['responsive'] === 'false') {
14508			return (imgs['landscape']['desktop']) ? imgs['landscape']['desktop'] : (imgs['landscape']['external'] ? imgs['landscape']['external'] : '');
14509
14510		}
14511		var hasOrientation = !!imgs[orientation];
14512		// there are only two orientations now and we may get them by string name if both are there
14513		// 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.
14514		// 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
14515		var imgOriented = imgs[ (hasOrientation ? orientation : Object.keys(imgs)[0]) ],
14516			imgExact    = (imgOriented[device.class]) ? imgOriented[device.class] : (imgOriented['external'] ? imgOriented['external'] : '');
14517		return imgExact;
14518	}
14519
14520	module.init = function ($layers) {
14521
14522		// Run and bind
14523		run($layers);
14524		$layers.attr('mk-img-loaded', '');
14525	};
14526
14527	module.onResize = function ($layers) {
14528		$win.on('resize', MK.utils.throttle( 500, function() {
14529			handleResize($layers);
14530		}));
14531	};
14532
14533	return module;
14534
14535}(jQuery));
14536
14537
14538jQuery(function($) {
14539
14540	var init = function init() {
14541		// Get All Layers, Excluding Edge Slider and Page Section
14542		$allLayers = $('[data-mk-img-set]').filter(function(index) {
14543			return !$(this).hasClass('mk-section-image') && !$(this).hasClass('background-layer') && !$(this).hasClass('mk-video-section-touch');
14544		});;
14545
14546		// Handle the resize
14547		MK.component.BackgroundImageSetter.onResize($allLayers);
14548
14549		// Set all the BG Layers
14550		MK.component.BackgroundImageSetter.init($allLayers);
14551	}
14552	init();
14553
14554	$(window).on('vc_reload', init);
14555
14556});
14557
14558(function( $ ) {
14559	'use strict';
14560
14561	var val = MK.val;
14562
14563	MK.component.FullHeight = function( el ) {
14564		var $window = $( window ),
14565			$this = $( el ),
14566			config = $this.data( 'fullheight-config' ),
14567			container = document.getElementById( 'mk-theme-container' ),
14568			minH = (config && config.min) ? config.min : 0,
14569			winH = null,
14570			height = null,
14571			update_count = 0,
14572			testing = MK.utils.getUrlParameter('testing'),
14573			offset = null;
14574
14575		// We need to provide height on the same specificity level for workaround to IE bug
14576		// connect.microsoft.com/IE/feedback/details/802625/min-height-and-flexbox-flex-direction-column-dont-work-together-in-ie-10-11-preview
14577		// stackoverflow.com/questions/19371626/flexbox-not-centering-vertically-in-ie
14578		if(MK.utils.browser.name === ('IE' || 'Edge')) $this.css( 'height', '1px' );
14579
14580		var update = function() {
14581
14582			if(update_count === 0) {
14583				winH = $window.height();
14584				// for correct calculate
14585				offset = $this.offset().top - 1;
14586				height = Math.max(minH, winH - val.offsetHeaderHeight( offset ));
14587				$this.css( 'min-height', height );
14588				if(testing !== undefined )
14589				update_count++;
14590			}
14591
14592		};
14593
14594		// TODO remove scroll listener by dynamic offset reader
14595		var init = function() {
14596			update();
14597			$window.on( 'resize', update );
14598			$window.on( 'scroll', update );
14599			window.addResizeListener( container, update );
14600		};
14601
14602		return {
14603			init : init
14604		};
14605	};
14606
14607})( jQuery );
14608
14609
14610(function( $ ) {
14611	'use strict';
14612
14613	var core  = MK.core,
14614		utils = MK.utils,
14615		path  = MK.core.path;
14616
14617
14618	MK.ui.FullScreenGallery = function( element, settings ) {
14619		this.element = element;
14620		this.config = settings;
14621
14622		this.isFullScreen = false;
14623	};
14624
14625
14626	// preload slick PLUGIN TO USE THIS
14627	MK.ui.FullScreenGallery.prototype = {
14628		dom : {
14629			fullScrBtn 		: '.slick-full-screen',
14630			exitFullScrBtn 	: '.slick-minimize',
14631			playBtn 		: '.slick-play',
14632			pauseBtn 		: '.slick-pause',
14633			shareBtn 		: '.slick-share',
14634			socialShare 	: '.slick-social-share',
14635		    wrapper 		: '.slick-slider-wrapper',
14636			slider 			: '.slick-slides',
14637			slides 			: '.slick-slide',
14638			dots 			: '.slick-dot',
14639			active 			: '.slick-active',
14640			hiddenClass 	: 'is-hidden',
14641			dataId 			: 'slick-index'
14642		},
14643
14644		tpl: {
14645			dot  : '<div class="slick-dot"></div>',
14646			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>',
14647			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>'
14648		},
14649
14650		init : function() { 
14651			var self = this;
14652
14653			// core.loadDependencies([ path.plugins + 'slick.js' ], function() {
14654				self.cacheElements();
14655				self.getViewportSizes();
14656				self.updateSizes( 'window' );
14657				self.create();
14658				// update cache with elements propagated by plugin
14659				self.updateCacheElements();
14660				self.createPagination();
14661				self.bindEvents();
14662			// });
14663		},
14664
14665		create : function() {
14666			var self = this;
14667
14668			this.slick = this.$gallery.slick({
14669		        dots: true,
14670		        arrows: true,
14671				infinite: true,
14672				speed: 300,
14673				slidesToShow: 1,
14674				centerMode: true,
14675				centerPadding: '0px',
14676				variableWidth: true,
14677				autoplay: false,
14678				autoplaySpeed: 3000,
14679        		useTransform: true,
14680                prevArrow: self.tpl.prev,
14681                nextArrow: self.tpl.next,
14682                customPaging: function(slider, i) {
14683                    return self.tpl.dot;
14684                },
14685			});
14686		},
14687
14688		cacheElements : function() {
14689			this.$window = $( window );
14690			this.$gallery = $( this.element );
14691
14692			this.$fullScrBtn = $( this.dom.fullScrBtn );
14693			this.$exitFullScrBtn = $( this.dom.exitFullScrBtn );
14694			this.$playBtn = $( this.dom.playBtn );
14695			this.$pauseBtn = $( this.dom.pauseBtn );
14696			this.$shareBtn = $( this.dom.shareBtn );
14697			this.$socialShare = $( this.dom.socialShare );
14698
14699		    this.$wrapper = $( this.dom.wrapper );
14700			this.$slider = $( this.dom.slider );
14701			this.$slides = $( this.dom.slides );
14702			this.$imgs = this.$slides.find( 'img' );
14703			// store reference to initial images without slides appended by pugin
14704			// - needed for creating of pagination
14705			this.$originalImgs = this.$imgs;
14706		},
14707
14708		updateCacheElements : function() {
14709			this.$slides = $( this.dom.slides );
14710			this.$imgs = this.$slides.find( 'img' );
14711			this.$dots = $( this.dom.dots );
14712		},
14713
14714		bindEvents : function() {
14715			var self = this;
14716			this.$fullScrBtn.on( 'click', this.toFullScreen.bind( this ) );
14717			this.$exitFullScrBtn.on( 'click', this.exitFullScreen.bind( this ) );
14718			this.$playBtn.on( 'click', this.play.bind( this ) );
14719			this.$pauseBtn.on( 'click', this.pause.bind( this ) );
14720			this.$shareBtn.on( 'click', this.toggleShare.bind( this ) );
14721			this.$socialShare.on( 'click', 'a', this.socialShare.bind( this ) );
14722			this.$window.on( 'resize', this.onResize.bind( this ) );
14723			this.$window.on( 'keydown', function(e) {
14724				if(e.keyCode === 39) self.$gallery.slick('slickNext');
14725				if(e.keyCode === 37) self.$gallery.slick('slickPrev');
14726			});
14727			$( document ).on( 'fullscreenchange mozfullscreenchange webkitfullscreenchange msfullcreenchange', this.exitFullScreen.bind( this ) );
14728		},
14729
14730		getViewportSizes : function() {
14731			this.screen = {
14732				w: screen.width,
14733				h: screen.height
14734			};
14735			this.window = {
14736				w: this.$window.width(),
14737				h: this.$window.height()
14738			};
14739		},
14740
14741		updateSizes : function( viewport ) {
14742			this.$wrapper.width( this[ viewport ].w );
14743			this.$wrapper.height( '100%' );
14744			this.$imgs.height( '100%');
14745		},
14746
14747		createPagination : function() {
14748			var self = this;
14749			this.$dots.each( function( i ) {
14750				var img = self.$originalImgs.eq( i ).attr( 'src' );
14751
14752				$( this ).css({
14753					'background-image': 'url('+ img +')'
14754				});
14755			});	
14756		},
14757
14758		play : function(e) {
14759			e.preventDefault();
14760			this.$playBtn.addClass( this.dom.hiddenClass );
14761			this.$pauseBtn.removeClass( this.dom.hiddenClass );
14762			$( this.element ).slick( 'slickPlay' );
14763		},
14764
14765		pause : function(e) {
14766			e.preventDefault();
14767			this.$pauseBtn.addClass( this.dom.hiddenClass );
14768			this.$playBtn.removeClass( this.dom.hiddenClass );
14769			$( this.element ).slick( 'slickPause' );
14770		},
14771
14772		toggleShare : function(e) {
14773			e.preventDefault();
14774			this.$socialShare.toggleClass( this.dom.hiddenClass );
14775		},
14776
14777		getCurentId : function() {
14778			return this.$slides.filter( this.dom.active ).data( this.dom.dataId );
14779		},
14780
14781		toFullScreen : function() {
14782			var self = this;
14783
14784			this.$fullScrBtn.addClass( this.dom.hiddenClass );
14785			this.$exitFullScrBtn.removeClass( this.dom.hiddenClass );
14786
14787			this.$slider.hide().fadeIn( 500 );
14788			utils.launchIntoFullscreen( document.documentElement );
14789			this.updateSizes( 'screen' );
14790			$( this.element ).slick( 'slickGoTo', this.getCurentId(), true );
14791
14792			// Update state with delay so we avoid triggering exitFullScreen fn from 
14793			// fullscreenchange event
14794			setTimeout( function() {
14795				self.isFullScreen = true;
14796			}, 1000);					
14797		},
14798
14799		exitFullScreen : function() {
14800			if( this.isFullScreen ) { 
14801				this.$exitFullScrBtn.addClass( this.dom.hiddenClass );
14802				this.$fullScrBtn.removeClass( this.dom.hiddenClass );
14803
14804				utils.exitFullscreen();
14805				this.updateSizes( 'window' );
14806				$( this.element ).slick( 'slickGoTo', this.getCurentId(), true );
14807
14808				this.isFullScreen = false;
14809			}
14810
14811		},
14812
14813		onResize : function() {
14814			this.getViewportSizes();
14815			this.updateSizes( this.isFullScreen ? 'screen' : 'window' );
14816			$( this.element ).slick( 'refresh' );  
14817			$( this.element ).slick( 'slickGoTo', this.getCurentId(), true );
14818			this.updateCacheElements();
14819			this.createPagination();
14820		},
14821
14822		socialShare : function( e ) {
14823			e.preventDefault();
14824			var $this = $( e.currentTarget ),
14825				network = $this.data( 'network' ),
14826				id = this.config.id,
14827				url = this.config.url,
14828				title = this.$wrapper.find( '.slick-title' ).text(),
14829				name;
14830				var picture = this.$slides.filter( this.dom.active ).children().first().attr( 'src' );
14831			switch( network ) {
14832				case 'facebook': 
14833					url = 'https://www.facebook.com/sharer/sharer.php?picture=' + picture+'&u=' + url + '#id=' + id;
14834					name = 'Facebook Share';
14835					break;
14836				case 'twitter':
14837					url = 'http://twitter.com/intent/tweet?text=' + url + '#id=' + id;
14838					name = 'Twitter Share';
14839					break;
14840				case 'pinterest':
14841					url = 'http://pinterest.com/pin/create/bookmarklet/?media=' + picture + '&url=' + url + '&is_video=false&description=' + title;
14842					// other available link paranmeters: media, description
14843					name = 'Pinterest Share';
14844					break;
14845
14846			}
14847
14848       		window.open( url, name, "height=380 ,width=660, resizable=0, toolbar=0, menubar=0, status=0, location=0, scrollbars=0" );
14849		}
14850	};
14851
14852})( jQuery );
14853(function( $ ) {
14854	'use strict';
14855
14856	/**
14857	 * A fork from original VC function.
14858	 * The original one is adding some padding which causes extra padding
14859	 * on our templates so we customized the codes.
14860	 *
14861	 * @since 5.9.8
14862	 * @since 6.0.1 Improve logic to handle LTR responsive state.
14863	 * @since 6.0.1 Fix missing padding-left if row has its own padding-left when
14864	 *              Vertical Header is active.
14865	 */
14866	function MkfullWidthRow() {
14867		var $windowWidth = $(document).width();
14868		var $elements = $('[data-mk-full-width="true"]');
14869		var direction = $('body.rtl').length ? 'right' : 'left';
14870		var verticalHeader = $('body.vertical-header-enabled').length ? true : false;
14871		var verticalHeaderWidth = ( $( '.header-style-4 .mk-header-inner' ).outerWidth() > 270 ) ? 0 : 270;
14872		var verticalHeaderRtl = $('body.rtl').length ? -1 : 1;
14873		var verticalHeaderRtlWidth = $('body.rtl.vertical-header-enabled').length ? verticalHeaderWidth : 0;
14874		var verticalHeaderRight = $('body.vertical-header-right').length ? -1 : 1;
14875		var verticalHeaderWidthBoxed = 0;
14876		var boxed = $('body.mk-boxed-enabled').length;
14877		var boxedOffset = ( boxed ) ? ( $(window).width() - $('#theme-page').outerWidth() ) / 2 : 0;
14878		var boxedMaxWidth = ( boxed ) ? $('#theme-page').outerWidth() : 'auto';
14879
14880		if ( verticalHeader && boxed ) {
14881			verticalHeaderWidthBoxed = ( $( '.header-style-4 .mk-header-inner' ).outerWidth() > 270 ) ? 0 : verticalHeaderRtl * verticalHeaderRight * 135;
14882		}
14883
14884		var transparentHeader = $('.transparent-header').length;
14885		if ( transparentHeader > 0 ) {
14886			verticalHeaderWidthBoxed = 0;
14887		}
14888
14889		$.each($elements, function(key, item) {
14890			var $el = $(this);
14891			var css;
14892			$el.addClass("vc_hidden");
14893			var $el_full = $el.next(".vc_row-full-width");
14894			if ($el_full.length || ($el_full = $el.parent().next(".vc_row-full-width")), $el_full.length) {
14895				var el_margin_left = parseInt($el.css("margin-left"), 10),
14896				el_margin_right = parseInt($el.css("margin-right"), 10),
14897				offset = 0 - $el_full.offset().left - el_margin_left,
14898				width = $(window).width();
14899				if (css = {
14900					position: "relative",
14901					"box-sizing": "border-box",
14902					width: $(window).width(),
14903					maxWidth: boxedMaxWidth
14904				},
14905				css[direction] = offset + boxedOffset + verticalHeaderWidthBoxed + ( verticalHeaderRight * verticalHeaderRtlWidth ),
14906				$el.css(css), !$el.data("mkStretchContent")) {
14907					var padding = -1 * offset;
14908					0 > padding && (padding = 0);
14909					var paddingRight = width - padding - $el_full.width() + el_margin_left + el_margin_right;
14910					padding = padding - paddingRight;
14911					if ( 0 > paddingRight && (paddingRight = 0) ) {
14912						css = {};
14913						if ( 'right' === direction ) {
14914							css["padding-left"] = padding + "px";
14915							css["padding-right"] = 0;
14916						} else {
14917							css["padding-right"] = padding + "px";
14918							css["padding-left"] = 0;
14919						}
14920
14921						$el.css(css)
14922					}
14923				}
14924
14925				/**
14926				 * Fix AM-2974
14927				 *
14928				 * When user set padding-left or padding-right in the row, both of them
14929				 * will be prioritized as important styles. It breaks padding-left set
14930				 * by Vertical Header to make the row content fit with the content
14931				 * container. We need to repopulate the padding-{side - based on Vertical
14932				 * Header position} value.
14933				 *
14934				 * Works when:
14935				 * - Vertical Header is active
14936				 * - Main layout is not boxed
14937				 * - Page Section is full layout
14938				 * - Row is full width layout and content
14939				 * - Row has its own padding-left and padding-right
14940				 * - There is no additional padding added
14941				 *
14942				 * How it works:
14943				 * Get current row padding-left and vertical header width. If both of them
14944				 * are equal, it means row position is correct related to Vertical Header.
14945				 * If not, we should sum both of them, then declare new padding-{side}
14946				 * style attribute.
14947				 *
14948				 * Tested with:
14949				 * - Main Layout: Full & Boxed Layout
14950				 * - Page Section: Full Layout and Non Full Layout
14951				 * - Row: Full Width, Full Width Content, and Non Full Width
14952				 * - Header: Non vertical headers
14953				 * - Transparent Header
14954				 * - RTL and LTR
14955				 */
14956				if ( verticalHeader && ! boxed && ! transparentHeader && ! css.hasOwnProperty( 'padding-left' ) && ! css.hasOwnProperty( 'padding-right' )) {
14957					// Get row padding-{side} and Vertical Header width.
14958					var side = 'left';
14959					if ( verticalHeaderRight === -1 ) {
14960						side = 'right';
14961					}
14962					var el_padding_dir = parseInt( $el.css( 'padding-' + side ), 10 );
14963					var header_padding_dir = $( '.header-style-4 .mk-header-inner' ).outerWidth();
14964					// Compare both of row and vertical header padding-{side}.
14965					if ( el_padding_dir != header_padding_dir) {
14966						if($windowWidth > mk_responsive_nav_width) {
14967							$el[0].style.setProperty( 'padding-' + side, header_padding_dir + 'px', 'important' );	
14968						} else {
14969							$el[0].style.removeProperty( 'padding-' + side);	
14970						}
14971						
14972
14973						// Reset padding-{side} for page section.
14974						var $el_page_section = $el.find( '.mk-page-section.full_layout' );
14975						if ( $el_page_section.length > 0 ) {
14976							$el_page_section[0].style.setProperty( 'padding-' + side, 'unset', 'important' );
14977						}
14978					}
14979				}
14980
14981				$el.attr("data-mk-full-width-init", "true"), $el.removeClass("vc_hidden"), $(document).trigger("vc-full-width-row-single", {
14982					el: $el,
14983					offset: offset,
14984					marginLeft: el_margin_left,
14985					marginRight: el_margin_right,
14986					elFull: $el_full,
14987					width: width
14988				})
14989			}
14990		}
14990), $(document).trigger("mk-full-width-row", $elements);
14991	}
14992
14993	MkfullWidthRow();
14994	var debounceResize = null;
14995	$(window).on("resize", function() {
14996		if( debounceResize !== null ) { clearTimeout( debounceResize ); }
14997		debounceResize = setTimeout( MkfullWidthRow, 100 );
14998	});
14999
15000})( jQuery );
15001
15002(function($) {
15003    'use strict';
15004
15005    MK.component.Grid = function( el ) {
15006    	var $container = $(el);
15007    	var config = $container.data( 'grid-config' );
15008        var isSlideshow = $container.closest('[data-mk-component="SwipeSlideshow"]').length;
15009        var miniGridConfig = {
15010            container: el,
15011            item: config.item + ':not(.is-hidden)',
15012            gutter: 0 
15013        };
15014
15015        var init = function init(){
15016            // Flags for cancelling usage goes first :
15017            // Quit early if we discover that Grid is used inside SwipeSlideshow as it brings bug with crossoverriding positioning 
15018            // + grid is not really needed as we have single row all handled by slider.
15019            // It happens only in woocommerce carousel as of hardcoded Grid in loop-start.php
15020            if(isSlideshow) return; 
15021	        MK.core.loadDependencies([ MK.core.path.plugins + 'minigrid.js' ], create);
15022        };
15023
15024        // Remove el hidden without adding proper class
15025        var prepareForGrid = function prepareForGrid() {
15026            var $item = $(this);
15027            var isHidden = ($item.css('display') === 'none');
15028            if(isHidden) $item.addClass('is-hidden');
15029            else $item.removeClass('is-hidden');
15030        };
15031
15032        var create = function create() {
15033            var timer = null;
15034
15035	        function draw() { 
15036                // Prevent plugin breaking when feeding it with hidden elements
15037                $container.find(config.item).each( prepareForGrid );
15038	            minigrid(miniGridConfig);
15039	        }
15040
15041            function redraw() {
15042                if (timer) clearTimeout(timer);
15043                timer = setTimeout(draw, 100);
15044            }
15045
15046            // init
15047	        draw(); 
15048            // If reinitializing drop existing event handler
15049            $(window).off('resize', redraw);
15050            $(window).on('resize', redraw);
15051            MK.utils.eventManager.subscribe('item-expanded', redraw);
15052            MK.utils.eventManager.subscribe('ajaxLoaded', redraw);
15053            MK.utils.eventManager.subscribe('staticFilter', redraw);
15054        };
15055
15056        return {
15057         	init : init
15058        };
15059    };
15060
15061})(jQuery);
15062
15063
15064
15065
15066
15067
15068
15069
15070/**
15071 * ICON FACTORY @ Maki
15072 * 
15073 * Javascript part that translates css styles into link to server side manufacturer.
15074 * By passing extra args we generate icons as needed on server and send them back with ajax and attch them to DOM here.
15075 *
15076 * 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.
15077 * 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. 
15078 * 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. 
15079 * 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.
15080 * 
15081 * Prons:
15082 * - automated process where we can mimic old behaviour
15083 * - possible bugs are easy to patch 
15084 * - 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)
15085 * - icon generation moved to server side where our main templating is already happening
15086 * - we can easily switch how our Icon should be outputed - inline, img, object, iframe. Whatever our situation requires (img for responsive icons for example)
15087 *
15088 * Cons:
15089 * - possible bugs based on different nature of svgs / fonts. Need to be manually fixed
15090 * - some manual work to straighten things - litle css refactors here and there
15091 * - as the mapping the icons happens in server side, it may cause CPU bottlenecks and should be cashed in DB for repetitve usage.
15092 *
15093 *
15094 * TODO Refactor to config obj as parameter for easier passing it. Also decouple more - especially loops
15095 */
15096(function ($) {
15097	'use strict';
15098
15099	// As long as we can manage this manually it is better like so. We avoid delay based on waiting for ajax to finish
15100 	// $.get( MK.core.path.theme + '/assets/icons/icon-families.json', createAll);
15101 	var families = [
15102		['awesome-icons' , 'mk-icon-'], // [family, prefix]
15103		['icomoon' 		 , 'mk-moon-'],
15104		['pe-line-icons' , 'mk-li-'],
15105		['theme-icons' 	 , 'mk-jupiter-icon-'] 
15106	];
15107
15108	// Our css contains this extends for particular families of fonts. For now we automate the process and extend it here as well
15109	var extend = {
15110		'awesome-icons' : [], 
15111		'icomoon' : [],
15112		'pe-line-icons' : [],
15113		'theme-icons' : []
15114	};	
15115 	
15116 	// Cache holder for quick access to repeating icons. config / svg
15117	var _cache = {};
15118	var _cacheId = 0;
15119	// Merge configs to call it with single ajax
15120	var _config = [];
15121	// Counter for all families. We merge all our families for single ajax request and countdown when to trigger the download.
15122	var _roundCount = 0;
15123	// Mapper for icons - config / array with nodes
15124	var _iconMap = {};
15125
15126
15127	// Closure to merge $icons together and to run the download when we counted down icon families to 0
15128 	var getIconsSprite = (function() {
15129 		var $icons = null;
15130 		var iterator = 0;
15131
15132 		function run(callback) {
15133	 		var config = encodeURIComponent(JSON.stringify(_config));
15134
15135			$.ajax({
15136				url : MK.core.path.ajaxUrl,
15137				// dataType: 'xml',
15138				method: 'POST',
15139				data: {action : 'mk_get_icon', iterator: iterator++, config: config},
15140				success: function(sprite) { 
15141					callback(sprite, $icons);
15142					_config = [];
15143					_iconMap = {};
15144					$icons = null;
15145				},
15146				error: function(err) { 
15147					console.log('Icon load problem');
15148				}
15149			});
15150		}
15151
15152		return function(callback, $els, count) {
15153			if(!$icons) $icons = $els;
15154			else $icons.add($els);
15155			// console.log(count);
15156			if(!count) run(callback);
15157		};
15158 	}());
15159
15160 	// Wait for DOM manipulations and run where really needed
15161 	$(window).on('load', function() { 
15162 		setTimeout(function() {
15163 			createAll(document);
15164 			if($('.mk-header').length) createAll('.mk-header');
15165 			if($('.js-flexslider, .mk-flexslider').length) createAll('.js-flexslider, .mk-flexslider');
15166 			if($('.mk-accordion').length) createAll('.mk-accordion'); 
15167 		}, 1000); 
15168 	});
15169
15170 	MK.utils.eventManager.subscribe('ajaxLoaded', function() {
15171 		// Wait for actuall DOM insertion
15172 		setTimeout(createAll, 100, '.js-loop');
15173 	});
15174
15175	MK.utils.eventManager.subscribe('ajax-preview', function() {
15176 		setTimeout(createAll, 100, '.ajax-container');
15177	});
15178
15179	MK.utils.eventManager.subscribe('photoAlbum-open', function() {
15180 		setTimeout(createAll, 100, '.gallery-share');
15181	});
15182
15183	MK.utils.eventManager.subscribe('quickViewOpen', function() {
15184 		setTimeout(createAll, 300, '.mk-modal-content');
15185	});
15186
15187 	// Our main runner that creates all icons in given scope
15188 	function createAll(scope) {
15189		// iterate through families
15190 		for(var i = 0, l = families.length; i < l; i++) {
15191 			var family = families[i][0];
15192 			var prefix = families[i][1];
15193 			var $icons = getIcons(family, prefix, scope);
15194 			if($icons.length) {
15195 				_roundCount++;
15196 				// 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.
15197 				// We need it to pass all $icons first so we can merge all families before ajax request.
15198 				setTimeout(createIcons, 0, $icons, family, prefix);
15199 			}
15200 		}
15201 	}
15202
15203 	// Grab all els in given scope that contains our prefix, anywhere in class attribute. Extend if needed
15204 	function getIcons(family, prefix, scope) {
15205 		var $scope = $(scope);
15206 		var $icons = $scope.find('[class*='+ prefix +']');
15207 		var extraClassNames = extend[family];
15208 		// if nothing to extend just return what we have till now
15209 		if(!extraClassNames) return $icons; 
15210 		// Extend it with our css garbish
15211 		extraClassNames.forEach(function(className) {
15212 			var $icon = $scope.find(className);
15213 			$icons = $icons.add($icon);
15214 		});
15215 		// serve all
15216 		return $icons;
15217 	}
15218
15219
15220 	function createIcons($icons, family, prefix, i, unicode) {
15221 		var id   = i || 0;
15222		var icon = $icons[id];
15223
15224		// quick check point, if no more icons break recursion
15225		if(!icon) {
15226			_roundCount--;
15227			getIconsSprite(insertIcons, $icons, _roundCount, _config);
15228			return;
15229		}
15230
15231		var css       = getComputedStyle( icon, ':before');
15232		var classAttr = icon.getAttribute('class');
15233		var name      = (classAttr) ? matchClass(classAttr.split(' '), prefix) : false;
15234		var h         = getComputedStyle(icon).fontSize;
15235		var config    = createConfig(css, name, family, unicode, h);
15236		var cache 	  = JSON.stringify(config);
15237
15238		if(!config) {
15239			// 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)
15240			// As we expect empty response from server, we just skip to next icon
15241
15242		} else if(_cache[cache]) {
15243			// Use cached icon when possible
15244			// 
15245			if(typeof _iconMap[cache] === 'undefined') _iconMap[cache] = [$icons.eq(id)];
15246			else _iconMap[cache].push($icons.eq(id));
15247
15248		} else {
15249			if(typeof _iconMap[cache] === 'undefined') _iconMap[cache] = [$icons.eq(id)];
15250			else _iconMap[cache].push($icons.eq(id));
15251
15252			_cache[cache] = _cacheId.toString(); // number as string so we could do [var] key lookup after reversal
15253			config.id = _cacheId; // extend config for server only
15254			_config.push(config);
15255
15256			_cacheId++; // increment after caching
15257		}
15258
15259		createIcons($icons, family, prefix, ++id);
15260 	}
15261
15262 	function insertIcons(sprite, $icons) {
15263 		var $sprite = $(sprite);
15264 		var $svgs   = $sprite.find('svg');
15265 		var idMap   = invert(_cache);
15266
15267 		$sprite.each(function() {
15268 			var $svg = $(this);
15269 			var id   = $svg.attr('data-cacheid'); // read as string
15270 			var configKey = idMap[id];
15271
15272 			_cache[configKey] = this;
15273 			// console.log(id, this)
15274 		});
15275
15276 		// console.log('sprite',sprite)
15277 		// 
15278
15279 		Object.keys(_iconMap).forEach(function (cacheKey) {
15280		   	_iconMap[cacheKey].forEach(function($icons) {
15281		   		$icons.each(function() {
15282		   			var $svg = $(_cache[cacheKey]).clone();
15283		   			var $icon = $(this);
15284
15285		   			// console.log($icon[0], _cache[cacheKey]);  
15286		   			
15287		   			function remove() {
15288		   				// exclude problematic stuff
15289		   				if($icon.parents('.pricing-features')) return;
15290			   			$icon.not('.mk-jupiter-icon-xing') 
15291			   				 .not('.mk-jupiter-icon-square-xing')
15292			   				 .not('.mk-jupiter-icon-simple-xing')
15293			   				 .find('.mk-svg-icon') 
15294			   				 .not('[data-name="mk-moon-zoom-in"]')
15295			   				 .remove(); // and remove else to reapply styles with new loaded svg
15296		   			}
15297
15298		   			if($svg.length ) remove();
15299
15300		   			if(!$icon.find('svg').length) {
15301		   				if($icon.parents('.widget ul').length) $icon.prepend($svg);
15302		   				else $icon.append($svg);
15303					}
15304		   		});
15305		   	});
15306		});
15307
15308 		// Notify rest of app
15309		MK.utils.eventManager.publish('iconsInsert');
15310 	}
15311
15312 	// Prepare configuration for server side. We need to grab icons and manipulate them a little there
15313 	function createConfig(css, name, family, unicode, height) {
15314 		var hasGradient  = checkGradient(css);
15315 		var hasDirection = extractGradient('direction', css.background);
15316
15317 		var config = {
15318 			family: family, 
15319 			// this is mostly for Extends. Because we've been customizing singular elements and assigning content unicode manually, 
15320 			// now we don't have any proper anchor for usage with our json map
15321 			unicode: (unicode) ? unicode : decodeUnicode(css.content), 
15322 			name: name,
15323 			// fill: css.color,
15324 			gradient_type:  hasGradient ? extractGradient('type' , css.background) : false,
15325 			gradient_start: hasGradient ? extractGradient('start', css.background) : false,
15326 			gradient_stop:  hasGradient ? extractGradient('stop' , css.background) : false,
15327 			gradient_direction: hasDirection ? extractGradient('direction', css.background).replace(' ', '-') : false,
15328 			height: height
15329 		};
15330
15331 		// If there is no name or unicode the whole config is invalid
15332 		if(!config.name && !config.unicode) return false;
15333 		else return config;
15334 	}
15335
15336 	// Extract class name that represents the icon that we try to generate
15337 	function matchClass(classes, prefix) {
15338 		// var missing = '';
15339 		for(var i = 0, l = classes.length; i < l; i++) {
15340 			if(classes[i].indexOf(prefix) !== -1) return classes[i]; // return first matched class name
15341 			// else missing += ' .' + classes[i]; // collect not matching classes
15342 		}
15343 		// if we didn't returned anything within loop we output notification here. Keep it for testing only
15344 		// console.log('Possibility of missing icons for element with classes:' + missing);
15345 	}
15346
15347 	// Check if background conatains gradient declaration and return bg string if so or false 
15348 	function checkGradient(css) {
15349 		var bg = css.background;
15350 		if(bg.indexOf('radial') !== -1 || bg.indexOf('linear') !== -1) return bg;
15351 		else return false;
15352 	}
15353
15354 	// Extract background attribiutes from bg string.
15355 	// Multipurpose function which returns part we ask for
15356 	function extractGradient(attr, grad) {
15357 		// quit if gradient is falsy
15358 		// console.log(grad);
15359 		if(!grad) return false;
15360
15361 		var isRadial = grad.indexOf('radial')  !== -1;
15362 		var isLinear = grad.indexOf('linear')  !== -1;
15363 		var hasDirection = grad.indexOf('(to') !== -1;
15364 		var f, t; // from, to
15365
15366 		if(attr === 'type') {
15367 			if(isRadial) return 'radial';
15368 			if(isLinear) return 'linear';
15369
15370 		} else if(attr === 'start') {
15371 			f = getStrPosition(grad, 'rgb(', 1);
15372 			t = getStrPosition(grad, '0%'  , 1);
15373
15374 		} else if(attr === 'stop') {
15375 			f = getStrPosition(grad, 'rgb(', 2);
15376 			t = getStrPosition(grad, '100%', 1);
15377
15378 		} else if(attr === 'direction') {
15379 			if(!hasDirection) return false;
15380 			f = getStrPosition(grad, '(to', 1) + 4;
15381 			t = getStrPosition(grad, ', rgb(', 1);
15382
15383 		} else {
15384 			return false;
15385 		}
15386 		
15387 		return grad.slice(f, t);
15388 	}
15389
15390 	// Helper for getting indexOf but with lookup for instance of the string
15391 	// str - string to search
15392 	// m - what we're looking for
15393 	// i - instance, starting at 1
15394 	function getStrPosition(str, m, i) {
15395	   return str.split(m, i).join(m).length;
15396	}
15397
15398	// JS outputs unicode results rather than code representation. This helper function does the job
15399	function decodeUnicode(content) {
15400		// escape() kills \ escape signature and outputs it as %u
15401		// str replace to drop special chars
15402		// and we bring it all to lowercase to match filenames we keep on server
15403		if(content && content !== 'none') return escape(content).replace(/%22/g, '').replace('%u', '').toLowerCase();
15404		else return false; // just in case we haven't provided content to work with
15405	}
15406
15407	function invert(obj) {
15408	  	var new_obj = {};
15409	  	for (var prop in obj) {
15410	    	if(obj.hasOwnProperty(prop)) {
15411	      		new_obj[obj[prop]] = prop;
15412	    	}
15413	  	}
15414	  	return new_obj;
15415	}
15416
15417}(jQuery));
15418/*!
15419 * imagesLoaded PACKAGED v4.1.1
15420 * JavaScript is all like "You images are done yet or what?"
15421 * MIT License
15422 */
15423
15424!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
15424h(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});
15425
15426(function($, window){
15427    'use strict';
15428
15429    var scrollY = MK.val.scroll; 
15430    var dynamicHeight = MK.val.dynamicHeight;
15431
15432    var $window = $(window);
15433    var $containers = $('.js-loop');
15434
15435    $containers.each( pagination );
15436
15437	$window.on( 'vc_reload', function() {
15438		$('.js-loop').each( pagination );
15439	} );
15440
15441    function pagination() {
15442        var unique = Date.now();
15443        var $container = $(this);
15444        var $superContainer = $container.parent(); // should contain clearing so it stretches with floating children
15445        var $loadBtn = $container.siblings('.js-loadmore-holder').find('.js-loadmore-button');
15446        var $loadScroll = $('.js-load-more-scroll');
15447        var style = $container.data('pagination-style');
15448        var maxPages = $container.data('max-pages');
15449        var id = '#' + ($container.attr('id'));
15450        var ajaxLoader = new MK.utils.ajaxLoader(id);
15451        var isLoadBtn = (style === 2);
15452        var isInfiniteScroll = (style === 3); // add flag for last container
15453        var scrollCheckPoint = null;
15454        var isHandlerBinded = false;
15455
15456        ajaxLoader.init();
15457
15458        init();
15459
15460        function init() {
15461            MK.utils.eventManager.subscribe('ajaxLoaded', onLoad);
15462            bindHandlers();
15463            if( isInfiniteScroll ) scrollCheckPoint = spyScrollCheckPoint();
15464
15465			$window.on( 'vc_reload', function() {
15466				$window.off('scroll', handleScroll);
15467			} );
15468        }
15469
15470        function bindHandlers() {
15471            if( isLoadBtn ) $loadBtn.on('click', handleClick);
15472            if( isInfiniteScroll ) $window.on('scroll', handleScroll); 
15473            isHandlerBinded = true;
15474        }
15475
15476        function unbindHandlers() {
15477            if( isLoadBtn ) $loadBtn.off('click', handleClick);
15478            if( isInfiniteScroll ) $window.off('scroll', handleScroll);
15479            isHandlerBinded = false;
15480        }
15481
15482        function handleClick(e) {
15483            e.preventDefault();
15484            if(!ajaxLoader.isLoading) loadMore();
15485        }
15486
15487        function handleScroll() {
15488            if((scrollY() > scrollCheckPoint()) && !ajaxLoader.isLoading) loadMore();
15489        }
15490
15491        function loadMore() {
15492            loadingIndicatorStart();
15493            var page = ajaxLoader.getData('paged');
15494            ajaxLoader.setData({paged: ++page});
15495            ajaxLoader.load(unique);
15496        }
15497
15498        function onLoad(e, response) {
15499            if( typeof response !== 'undefined' && response.id === id) {
15500                // Checking found posts helps to fix all pagination styles 
15501                if( ajaxLoader.getData('found_posts') <= 0 && ajaxLoader.getData('paged') >= ajaxLoader.getData('maxPages')) loadingIndicatorHide();
15502                else loadingIndicatorShow();
15503                if(response.unique === unique) $container.append(response.content);
15504                loadingIndicatorStop();
15505            }
15506        }
15507
15508        function loadingIndicatorStart() {
15509            if(isLoadBtn) $loadBtn.addClass('is-active');
15510            else if(isInfiniteScroll) MK.ui.loader.add('.js-load-more-scroll');
15511
15512        }
15513
15514        function loadingIndicatorStop() {
15515            if(isLoadBtn) $loadBtn.removeClass('is-active');
15516            else if(isInfiniteScroll) MK.ui.loader.remove('.js-load-more-scroll');
15517        }
15518
15519        function loadingIndicatorShow() {
15520            if(isHandlerBinded) return;
15521            if(isLoadBtn) $loadBtn.show();
15522            else if(isInfiniteScroll) $loadScroll.show();
15523            bindHandlers();
15524        }
15525
15526        function loadingIndicatorHide() {
15527            if(!isHandlerBinded) return;
15528            if(isLoadBtn) $loadBtn.hide();
15529            else if(isInfiniteScroll) $loadScroll.hide();
15530            unbindHandlers();
15531        }
15532
15533
15534        function spyScrollCheckPoint() {
15535            var containerO = 0;
15536            var containerH = dynamicHeight( $superContainer );
15537            var winH = dynamicHeight( window );
15538 
15539            var setVals = function() {
15540                containerO = $superContainer.offset().top;
15541            };
15542
15543            setVals();
15544            $window.on('resize', function() { requestAnimationFrame(setVals); });
15545
15546            return function() {
15547                return (containerH() + containerO) - (winH() * 2);
15548            };
15549        }
15550    }
15551
15552})(jQuery, window);
15553(function($) {
15554	'use strict';
15555
15556	// Check if it's inside hidden parent
15557	// Cannot be position: fixed
15558	function isHidden(el) {
15559	    return (el.offsetParent === null);
15560	}
15561
15562	MK.component.Masonry = function(el) {
15563		var $window = $(window);
15564		var $container = $(el);
15565		var config = $container.data( 'masonry-config' );
15566		var $masonryItems = $container.find(config.item);
15567		var cols = config.cols || 8;
15568		var $filterItems = null; // assign only when apply filter
15569		var wall = null;
15570		
15571        var init = function init() {
15572        	MK.core.loadDependencies([ MK.core.path.plugins + 'freewall.js' ], onDepLoad);
15573        };
15574
15575        var onDepLoad = function onDepLoad() {
15576        	masonry();
15577
15578        	// Events
15579	        $window.on('resize', onResize);
15580            MK.utils.eventManager.subscribe('ajaxLoaded', onPostAddition);
15581			MK.utils.eventManager.subscribe('staticFilter', resize);
15582        };
15583
15584	    var masonry = function masonry() {
15585	    	// Quit for hidden elements for now.
15586	    	if(isHidden(el)) return;
15587
15588	    	var newCols;
15589	    	if(window.matchMedia( '(max-width:600px)' ).matches) newCols = 2;
15590	    	else if(window.matchMedia( '(max-width:850px)' ).matches) newCols = 4;
15591	    	else newCols = cols;
15592
15593	    	var colW = $container.width() / newCols;
15594
15595	        wall = new Freewall( config.container );
15596
15597	        // We need to pass settings to a plugin via reset method. Strange but works fine.
15598			wall.reset({
15599				selector: config.item + ':not(.is-hidden)',
15600				gutterX: 0, // set default gutter to 0 and again - apply margins to item holders in css
15601				gutterY: 0,
15602				cellW: colW,
15603				cellH: colW
15604			});
15605
15606	        wall.fillHoles();
15607	        wall.fitWidth();
15608
15609	        $masonryItems.each(function() {
15610	        	$(this).data('loaded', true);
15611	        });
15612        };
15613
15614
15615		// Clear attributes after the plugin. It's API method dosn't handle it properly
15616		var destroyContainer = function destroyContainer() {
15617			$container.removeAttr('style')
15618				 .removeData('wall-height')
15619				 .removeData('wall-width')
15620				 .removeData('min-width')
15621				 .removeData('total-col')
15622				 .removeData('total-row')
15623				 .removeAttr('data-wall-height')
15624				 .removeAttr('data-wall-width')
15625				 .removeAttr('data-min-width')
15626				 .removeAttr('data-total-col')
15627				 .removeAttr('data-total-row');
15628		};
15629
15630		var destroyItem = function destroyItem() {
15631			var $item = $(this);
15632			$item.removeAttr('style')
15633				 .removeData('delay')
15634				 .removeData('height')
15635				 .removeData('width')
15636				 .removeData('state')
15637				 .removeAttr('data-delay')
15638				 .removeAttr('data-height')
15639				 .removeAttr('data-width')
15640				 .removeAttr('data-state'); 
15641		};
15642
15643		var destroyAll = function destroyAll() {
15644	    	if( !wall ) return;
15645    		wall.destroy(); // API destroy
15646    		destroyContainer();
15647    		$masonryItems.each( destroyItem ); // run our deeper destroy
15648		};
15649
15650		var onResize = function onResize() {
15651			requestAnimationFrame(resize);
15652		};
15653
15654        var refresh = function refresh() {
15655	    	if( !wall ) return; 
15656	    	setTimeout(wall.fitWidth.bind(wall), 5);
15657        };
15658
15659        var resize = function resize() {
15660        	destroyAll();
15661	    	masonry();
15662        };
15663
15664        var onPostAddition = function onPostAddition() {
15665        	$masonryItems = $container.find(config.item);
15666
15667        	$masonryItems.each(function() {
15668        		var $item = $(this),
15669        			isLoaded = $item.data('loaded');
15670
15671        		if(!isLoaded) $item.css('visibility', 'hidden');
15672        	});
15673
15674        	
15675        	$container.mk_imagesLoaded().then(function() {
15676        		destroyAll();
15677        		masonry();
15678        	});
15679        };
15680
15681        return {
15682         	init : init
15683        };
15684	};
15685
15686}(jQuery));
15687(function($) {
15688	'use strict';
15689
15690	MK.component.Pagination = function(el) {
15691		this.el = el;
15692	};
15693
15694	MK.component.Pagination.prototype = {
15695		init: function init() {
15696			this.cacheElements(); 
15697			this.bindEvents();
15698			this.onInitLoad();
15699		},
15700
15701		cacheElements: function cacheElements() {
15702			this.lastId = 1;
15703			this.unique = Date.now();
15704			this.$pagination = $(this.el);
15705			this.$container = this.$pagination.prev('.js-loop');
15706			this.$pageLinks = this.$pagination.find('.js-pagination-page');
15707			this.$nextLink = this.$pagination.find('.js-pagination-next');
15708			this.$prevLink = this.$pagination.find('.js-pagination-prev');
15709			this.$current = this.$pagination.find('.js-current-page');
15710			this.$maxPages = this.$pagination.find('.pagination-max-pages'); // TODO change in DOM and here to js class
15711			this.containerId = '#' + this.$container.attr('id');
15712			this.pagePathname = window.location.pathname;
15713			this.pageSearch = window.location.search;
15714			this.popState = false;
15715			this.ajaxLoader = new MK.utils.ajaxLoader('#' + this.$container.attr('id'));
15716			this.ajaxLoader.init();
15717		},
15718
15719		bindEvents: function bindEvents() {
15720			this.$pageLinks.on('click', this.pageClick.bind(this));
15721			this.$nextLink.on('click', this.nextClick.bind(this));
15722			this.$prevLink.on('click', this.prevClick.bind(this)); 
15723			MK.utils.eventManager.subscribe('ajaxLoaded', this.onLoad.bind(this));
15724		},
15725
15726		pageClick: function pageClick(e) {
15727			e.preventDefault(); 
15728			var $this = $(e.currentTarget);
15729			var id = parseFloat($this.attr('data-page-id'));
15730
15731			if(id > this.ajaxLoader.getData('maxPages') || id < 1) return;
15732			this.load(id, $this);
15733			this.updatePagedNumUrl( id );
15734		},
15735
15736		nextClick: function nextClick(e) {
15737			e.preventDefault(); 
15738			if(this.ajaxLoader.getData('paged') === this.ajaxLoader.getData('maxPages')) return;
15739			this.load(++this.lastId, $(e.currentTarget));
15740			this.updatePagedNumUrl( this.lastId );
15741		},
15742
15743		prevClick: function prevClick(e) {
15744			e.preventDefault(); 
15745			if(this.ajaxLoader.getData('paged') === 1) return;
15746			this.load(--this.lastId, $(e.currentTarget));
15747			this.updatePagedNumUrl( this.lastId );
15748		},
15749
15750		load: function load(id, $el) {
15751			this.lastId = id;
15752			this.ajaxLoader.setData({paged: id});
15753			this.ajaxLoader.load(this.unique);
15754			this.removeIndicator();
15755			MK.ui.loader.add($el);
15756		},
15757
15758		onLoad: function success(e, response) {
15759			if( typeof response !== 'undefined' && response.id === this.containerId) {
15760				this.updatePagination();
15761				this.lastId = this.ajaxLoader.getData('paged');
15762
15763				if(response.unique === this.unique) {
15764					this.removeIndicator();
15765					this.scrollPage();
15766			        this.$container.html(response.content);  
15767				}   
15768			}         
15769        },
15770
15771        updatePagination: function updatePagination() {
15772        	var self = this;
15773
15774        	// Hide / show arrows
15775        	var isFirst = (this.ajaxLoader.getData('paged') === 1);
15776        	var isLast = (this.ajaxLoader.getData('paged') === this.ajaxLoader.getData('maxPages'));
15777
15778        	if(isFirst) this.$prevLink.addClass('is-vis-hidden');
15779        	else this.$prevLink.removeClass('is-vis-hidden');
15780
15781        	if(isLast) this.$nextLink.addClass('is-vis-hidden');
15782        	else this.$nextLink.removeClass('is-vis-hidden');
15783
15784			// X of Y
15785			this.$current.html(this.ajaxLoader.getData('paged'));
15786			this.$maxPages.html(this.ajaxLoader.getData('maxPages'));
15787
15788			// Move overfloating items
15789			var displayItems = 10;
15790			var centerAt = displayItems / 2;
15791
15792			if(this.ajaxLoader.getData('maxPages') > displayItems) {
15793				this.$pageLinks.each(function(i) {
15794
15795					var id = self.lastId - centerAt;
15796						id = Math.max(id, 1);
15797						id = Math.min(id, self.ajaxLoader.getData('maxPages') - displayItems + 1);
15798						id = id + i;
15799
15800					$(this).html( id ).attr('data-page-id', id).show();
15801
15802					if(i === 0 && id > 1) $(this).html('...');
15803					if(i === displayItems - 1 && id < self.ajaxLoader.getData('maxPages')) $(this).html('...');
15804				});
15805			} else {
15806				this.$pageLinks.each(function(i) {
15807					var $link = $(this);
15808					var id = i + 1;
15809
15810					$link.html(id).attr('data-page-id', id);
15811
15812					if( self.ajaxLoader.getData('maxPages') === 1) {
15813						self.$pageLinks.hide();
15814					} else {
15815						if(i > self.ajaxLoader.getData('maxPages') - 1) $link.hide();
15816						else $link.show();						
15817					}
15818
15819				});
15820			}
15821
15822        	// Highlight current only
15823			this.$pageLinks.filter('[data-page-id="' + this.ajaxLoader.getData('paged') + '"]' ).addClass('current-page')
15824				 .siblings().removeClass('current-page');
15825
15826        },
15827
15828        scrollPage: function scrollPage() {
15829            var containerOffset = this.$container.offset().top;
15830            var offset = containerOffset - MK.val.offsetHeaderHeight( containerOffset ) - 20; 
15831
15832            this.$container.find('a:first').focus()
15833            MK.utils.scrollTo( offset ); 
15834        },
15835
15836        removeIndicator: function removeIndicator() {
15837        	MK.ui.loader.remove('.js-pagination-page, .js-pagination-next, .js-pagination-prev');
15838        },
15839
15840		/**
15841		 * Set some actions when archive/category page is loaded. Actions list:
15842		 * - Select the correct paged ID on pagination list.
15843		 * - Set current paged ID on the label.
15844		 * - Add event listener onpopstate for handling prev/next button of Browser URL.
15845		 * - Set info for updatePagedNumUrl() about request comes from popstate.
15846		 *
15847		 * @since 5.9.8
15848		 */
15849		onInitLoad: function onInitLoad() {
15850			var initPagedID = this.$pagination.data( 'init-pagination' );
15851			if ( initPagedID && initPagedID > 1 ) {
15852				this.$current.html( initPagedID );
15853				this.$pageLinks.filter( '[data-page-id="' + initPagedID + '"]' ).addClass( 'current-page' ).siblings().removeClass( 'current-page' );
15854			}
15855
15856			// Run popstate only if it's supported by the browser.
15857			if ( 'onpopstate' in window ) {
15858				var thisPop = this;
15859				window.onpopstate = function( event ) {
15860					var id = 1;
15861
15862					// At start, state is always null. So, we should check it before processing.
15863					if ( typeof event.state === 'object' && event.state ) {
15864						var state = event.state;
15865
15866						// Set paged ID for updating page.
15867						if ( state.hasOwnProperty( 'MkPagination' ) ) {
15868							var currentState = state.MkPagination;
15869							if ( currentState.hasOwnProperty( 'paged' ) ) {
15870								id = parseFloat( currentState.paged );
15871							}
15872						}
15873					} else {
15874						id = parseFloat( thisPop.getURLPagedID() );
15875					}
15876
15877					// Tell updatePagedNumUrl() if request come from popstate.
15878					thisPop.popState = true;
15879					thisPop.$pageLinks.filter( '[data-page-id="' + id + '"]' ).trigger( 'click' );
15880				}
15881			}
15882		},
15883
15884		/**
15885		 * Update current pagination browser URL by adding/changing paged number. Only run if
15886		 * the browser support pushState and the request not coming from popstate.
15887		 *
15888		 * WordPress has some ways to set paged number:
15889		 * 1. page/[number], paged=[number] will be directed here.
15890		 * 2. page=[number]
15891		 * So, we should check which one the request is used here.
15892		 *
15893		 * @since 5.9.8
15894		 */
15895		updatePagedNumUrl: function updatePagedNumUrl( id ) {
15896			// Check pushState browser support and ignore if request come from popstate.
15897			if ( 'history' in window && 'pushState' in history && id && ! this.popState ) {
15898				var fullPage = this.pagePathname + this.pageSearch;
15899				var isQueryPage = false;
15900
15901				// Style 1 - /page/[number], as default value.
15902				var newPage = 'page/' + id + '/';
15903				var expPage = /page\/\d+\/?/;
15904				var result = this.pagePathname.match( /\/page\/\d+/ );
15905				var isPagedExist = ( result ) ? true : false;
15906
15907				// Style 2 - ?page=[number], only run if /page/ is not exist and URL query var exist.
15908				if ( ! isPagedExist && this.pageSearch ) {
15909					isQueryPage = this.pageSearch.match( /page\=\d+/ );
15910					if ( isQueryPage ) {
15911						newPage = 'page=' + id;
15912						expPage = /page\=\d+/;
15913					}
15914				}
15915
15916				// If page number is 1, remove paged number from URL.
15917				if ( id === 1 ) {
15918					newPage = '';
15919					if ( isQueryPage ) {
15920						expPage = ( this.pageSearch.match( /\&+/ ) ) ? /page\=\d+\&?/ : /\?page\=\d+\&?/;
15921					}
15922				}
15923
15924				// Set new pathname. Do replacement only if the new pathname contains paged number.
15925				var newURL = this.pagePathname + newPage + this.pageSearch;
15926				if ( fullPage.match( expPage ) ) {
15927					newURL = fullPage.replace( expPage, newPage );
15928				}
15929
15930				// Set history state and return popstate back to fal
15930se.
15931				var historyState = {
15932					MkPagination: {
15933						url: newURL,
15934						paged: id
15935					}
15936				}
15937				this.popState = false;
15938
15939				// Push new pathname to display/hide the paged number.
15940				window.history.pushState( historyState, null, newURL );
15941			}
15942			this.popState = false;
15943		},
15944
15945		/**
15946		 * Get current URL page ID. Notes:
15947		 * 1. page/[number], paged=[number] will be directed here.
15948		 * 2. page=[number]
15949		 *
15950		 * @return {integer} Current paged ID. Default 1.
15951		 */
15952		getURLPagedID: function getURLPagedID() {
15953			var pathname = window.location.pathname;
15954			var search = window.location.search;
15955			var pagedId = 1;
15956			var result = '';
15957			var isPagedExist = false;
15958
15959			// Search based on style 1.
15960			result = pathname.match( /\/page\/(\d+)/ );
15961			if ( result ) {
15962				isPagedExist = true;
15963				pagedId = ( result.hasOwnProperty( 1 ) ) ? result[1] : 1;
15964			}
15965
15966			// Search based on style 2.
15967			if ( ! isPagedExist && search ) {
15968				result = search.match( /page\=(\d+)/ );
15969				if ( result ) {
15970					isPagedExist = true;
15971					pagedId = ( result.hasOwnProperty( 1 ) ) ? result[1] : 1;
15972				}
15973			}
15974
15975			return pagedId;
15976		}
15977	};
15978
15979}(jQuery));
15980(function( $ ) {
15981	'use strict';
15982
15983	var val = MK.val,
15984		utils = MK.utils;
15985
15986	MK.component.Parallax = function( el ) {
15987		var self = this,
15988			$this = $( el ),
15989        	obj = $this[0],
15990			$window = $( window ),
15991		    container = document.getElementById( 'mk-theme-container' ),
15992			config = $this.data( 'parallax-config' ),
15993			$holder = $( config.holder ),
15994			headerHeight = null,
15995			offset = null,
15996			elHeight = null,
15997			ticking = false,
15998			isMobile = null;
15999
16000
16001		var clientRect = null;
16002
16003		var update = function() {
16004			// Clear styles to check for natural styles
16005			// then apply position and size
16006			obj.style.transform = null;
16007			obj.style.top = null;
16008			obj.style.bottom = null;
16009
16010			isMobile = MK.utils.isMobile();
16011
16012			if( isMobile ) {
16013        		$this.css( 'height', '' );
16014				return;
16015			}
16016
16017			clientRect = $this[ 0 ].getBoundingClientRect();
16018			offset = clientRect.top;
16019			elHeight = clientRect.height;
16020			headerHeight = val.offsetHeaderHeight( offset );
16021			offset = offset - headerHeight + val.scroll(); 
16022
16023			setPosition(); 
16024			setSize( ); 
16025		};
16026
16027
16028        var h = 0,
16029        	winH = 0,
16030        	proportion = 0,
16031        	height = 0;
16032
16033        // Position and background attachement should me moved to CSS but we repair it high specificity here as styles are not reliable currently
16034        var setSize = function() {
16035        	$this.css( 'height', '' );
16036        	winH = $window.height() - headerHeight;
16037        	h = obj.getBoundingClientRect().height; 
16038
16039        	if( config.speed <= 1 && config.speed > 0 ) {
16040        		if( offset === 0 ) {
16041	        		$this.css({
16042	        			backgroundAttachment: 'scroll',
16043	        			'will-change': 'transform'
16044	        		});
16045        		} else {
16046	        		$this.css({
16047						height : h + ( (winH - h) * config.speed ),
16048	        			backgroundAttachment: 'scroll',
16049	        			'will-change': 'transform' 
16050	        		}); 
16051	        	}
16052
16053        	} else if ( config.speed > 1 && h <= winH ) {
16054        		$this.css({
16055        			// good for full heights - 2 because it's viewable by 2 screen heights
16056        			height: ( winH  +  ( ( winH * config.speed ) - winH ) * 2 ),  
16057        			top: -( ( winH * config.speed ) - winH ),
16058        			backgroundAttachment: 'scroll',
16059        			'will-change': 'transform'
16060        		}); 
16061
16062        	} else if ( config.speed > 1 && h > winH ) {
16063        		proportion = h / winH;
16064        		height = ( winH  +  ( ( winH * config.speed ) - winH ) * (1 + proportion) );
16065 
16066        		$this.css({
16067        			height: height,
16068        			top: -( height - (winH * config.speed) ),
16069        			backgroundAttachment: 'scroll',
16070        			'will-change': 'transform'
16071        		}); 
16072
16073        	} else if ( config.speed < 0 && h >= winH ) {
16074        		height = h * (1  - config.speed);
16075        		$this.css({
16076					height: height + (height - h),
16077        			top: h - height,
16078        			backgroundAttachment: 'scroll',
16079        			'will-change': 'transform'
16080        		});   
16081
16082        	} else if ( config.speed < 0 && h < winH ) {
16083        		// candidate to change
16084        		var display = (winH + h) / winH;
16085        		height = h * -config.speed * display;
16086        		$this.css({
16087					height: h + (height * 2),
16088        			top: -height,
16089        			backgroundAttachment: 'scroll',
16090        			'will-change': 'transform'
16091        		});         		
16092        	}
16093        };
16094
16095
16096		var currentPoint = null,
16097			progressVal = null,
16098			startPoint = null,
16099			endPoint = null,
16100			$opacityLayer = config.opacity ? $this.find( config.opacity ) : null,
16101			scrollY = null;
16102
16103		var setPosition = function() {
16104			startPoint = offset - winH;
16105			endPoint = offset + elHeight + winH - headerHeight;
16106			scrollY = val.scroll();
16107
16108			if( scrollY < startPoint || scrollY > endPoint ) { 
16109				ticking = false;
16110				return; 
16111			}
16112
16113			currentPoint = (( -offset + scrollY ) * config.speed);
16114
16115            $this.css({
16116              	'-webkit-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
16117              	'-moz-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
16118              	'-ms-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
16119              	'-o-transform': 'translateY(' + currentPoint + 'px) translateZ(0)',
16120              	'transform': 'translateY(' + currentPoint + 'px) translateZ(0)'
16121            });  
16122
16123			ticking = false;
16124		};
16125
16126 
16127		var requestTick = function() {
16128			if( !ticking && !isMobile ) {
16129				ticking = true;
16130				window.requestAnimationFrame( setPosition );
16131			}
16132		};
16133
16134
16135		var init = function() { 
16136			// Disable scroll effects when smooth scroll is disabled
16137			if( !MK.utils.isSmoothScroll ) { return; }
16138
16139			update();
16140			setTimeout(update, 100);
16141			$window.on( 'load', update );
16142			$window.on( 'resize', update );
16143	        window.addResizeListener( container, update );
16144	        
16145			$window.on( 'scroll', requestTick );
16146		};
16147		
16148 
16149		return {
16150			init : init
16151		};
16152	};
16153
16154})( jQuery );
16155(function($) {
16156	'use strict';
16157
16158	MK.component.Preloader = function(el) {
16159		this.el = el;
16160	};
16161
16162	MK.component.Preloader.prototype = {
16163		init: function init() {
16164			this.cacheElements();
16165			this.bindEvents();
16166		},
16167
16168		cacheElements: function cacheElements() {
16169			this.$preloader = $(this.el);
16170		},
16171
16172		bindEvents: function bindEvents() {
16173			this.onLoad(); // all components inited on page load
16174		},
16175
16176		onLoad: function onLoad() {
16177			setTimeout(this.hidePreloader.bind(this), 300);
16178		},
16179
16180		hidePreloader: function hidePreloader() {
16181			this.$preloader.hide();
16182		}
16183	};
16184
16185}(jQuery));
16186
16187(function($) {
16188	'use strict';
16189
16190	// Image added for proportional scaling
16191	MK.ui.loader = {
16192		tpl : function() {
16193			return '<div class="mk-loading-indicator">' + 
16194						'<div class="mk-loading-indicator__inner">' +
16195							'<div class="mk-loading-indicator__icon"></div>' +
16196							'<img style="height:100%; width:auto;" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">' +
16197						'</div>' +
16198					'</div>';
16199		},
16200
16201		add : function(item) {
16202			$(item).append(this.tpl);
16203		},
16204
16205		remove : function(item) {
16206			if(item) $(item).find('.mk-loading-indicator').remove();
16207			else $('.mk-loading-indicator').remove();
16208		}
16209	};
16210
16211}(jQuery));
16212(function( $ ) {
16213	// IE / Edge fix for fixed positioned elements
16214	// MS clip path doesnt redraw properly so we expirience similar bug like with background attachement fixed on Chrome
16215	if (MK.utils.browser.name === 'Edge' || MK.utils.browser.name === 'IE') {
16216	 	var val = 1;
16217	 	var $edgeClipper = $('.mk-slider-slide'); // edge slider
16218	 	var $sectionClipper = $('.clipper-true'); // edge slider
16219	 	var $bgLayer = $('.background-layer'); // page section
16220
16221    	var onScroll = function onScroll() {
16222	    	val *= -1;
16223	    	if( $edgeClipper.length ) $edgeClipper.each( redraw );
16224	    	if( $sectionClipper.length ) $sectionClipper.each( redraw );
16225	    	if( $bgLayer.length ) $bgLayer.each( redraw );
16226    	};
16227
16228	 	var redraw = function redraw() {
16229	    	$(this).css('margin-top', val / 100);
16230	    };
16231
16232	    $(window).on("scroll", function () {	    	
16233	    	window.requestAnimationFrame(onScroll);
16234	    });
16235	 }
16236}(jQuery));
16237MK.component.ResponsiveImageSetter = (function ($) {
16238
16239	'use strict';
16240
16241	var module = {};
16242
16243
16244	/*---------------------------------------------------------------------------------*/
16245	/* Private Variables
16246	/*---------------------------------------------------------------------------------*/
16247
16248	var viewportClass = getViewportClass();
16249	var isRetina = window.devicePixelRatio >= 2;
16250
16251
16252	/*---------------------------------------------------------------------------------*/
16253	/* Private Methods
16254	/*---------------------------------------------------------------------------------*/
16255
16256	function run($imgs) {
16257		$imgs.filter( function() {
16258			return !this.hasAttribute("mk-img-src-setted");
16259		}).each(setSrcAttr);
16260	}
16261
16262	function setSrcAttr() {
16263		var $img = $(this);
16264		var set = $img.data('mk-image-src-set');
16265		// Set src attribute to img link suitable for our logic. It will load the image.
16266		if(set['responsive'] === 'false' && isRetina && set['2x']) $img.attr('src', set['2x']);
16267		else if(set['responsive'] === 'false') $img.attr('src', set.default);
16268		else if(viewportClass === 1 && isRetina && set['2x']) $img.attr('src', set['2x']); // default x2 for retina
16269		else if(viewportClass === 0 && set.mobile) $img.attr('src', set.mobile);
16270		else $img.attr('src', set.default);
16271
16272		$img.load(function() {
16273			$(window).trigger('mk-image-loaded')
16274		})
16275	}
16276
16277	function getViewportClass() {
16278		if(window.matchMedia('(max-width: 736px)').matches) return 0;
16279		else return 1;
16280	}
16281
16282	function handleResize($imgs) {
16283		if(!$imgs.length) return;
16283 // Do not run if empty collection
16284		var currentViewportClass = getViewportClass();
16285		// We don't need to reload bigger images when screen size is decreasing as browser already performs resize operation.
16286		// Run update on for increasing screen size
16287		if( currentViewportClass > viewportClass) {
16288			viewportClass = currentViewportClass; // update for further reference
16289			run($imgs);
16290		}
16291	}
16292
16293
16294	/*---------------------------------------------------------------------------------*/
16295	/* Public Methods
16296	/*---------------------------------------------------------------------------------*/
16297
16298	module.init = function ($imgs) {
16299
16300		// Do not run if empty collection
16301		if(!$imgs.length) return;
16302
16303		// Run and bind to events
16304		run($imgs);
16305		$imgs.attr('mk-img-src-setted', '');
16306
16307	};
16308
16309	module.onResize = function ($imgs) {
16310
16311		$(window).on( 'resize', MK.utils.throttle( 500, function() {
16312			handleResize($imgs);
16313		}));
16314
16315
16316	};
16317
16318
16319	module.handleAjax = function () {
16320    	setTimeout(function ajaxDelayedCallback() { // give it a chance to insert content first
16321	    	var $newImgs = $('img[data-mk-image-src-set]').filter( function() {
16322				return !this.hasAttribute("mk-lazyload");
16323			});
16324			if(!$newImgs.length) return;
16325	    	run($newImgs);
16326    	}, 100);
16327    }
16328
16329
16330	return module;
16331
16332}(jQuery));
16333
16334
16335jQuery(function($) {
16336
16337	var init = function init() {
16338		// Get All Responsive Images
16339		$allImages = $('img[data-mk-image-src-set]').filter(function(index) {
16340			var isNotPortfolioImage = !$(this).hasClass('portfolio-image'),
16341				isNotBlogImage = $(this).closest('.mk-blog-container').length == 0,
16342				isNotSwiperImage = !$(this).hasClass('swiper-slide-image'),
16343				isNotGalleryImage = !$(this).hasClass('mk-gallery-image');
16344			return isNotPortfolioImage && isNotBlogImage && isNotSwiperImage && isNotGalleryImage;
16345		});;
16346
16347		// Handle the resize
16348		MK.component.ResponsiveImageSetter.onResize($allImages);
16349
16350		MK.component.ResponsiveImageSetter.init($allImages);
16351
16352		MK.utils.eventManager.subscribe('ajaxLoaded', MK.component.ResponsiveImageSetter.handleAjax ); // ajax loops
16353		MK.utils.eventManager.subscribe('ajax-preview', MK.component.ResponsiveImageSetter.handleAjax ); // ajax portfolio
16354		MK.utils.eventManager.subscribe('quickViewOpen', MK.component.ResponsiveImageSetter.handleAjax );
16355	}
16356	init();
16357	$(window).on('vc_reload', init);
16358
16359});
16360
16361
16362
16363(function( $ ) {
16364	'use strict';
16365
16366	var utils = MK.utils;
16367	var val   = MK.val;
16368
16369	/**
16370	 * Keep track of top Level sections so we can easly skip to next one.
16371	 * We must be explicit about DOM level to nested sections.
16372	 * 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).
16373	 * We keep track for the same sections in Footer for mutating window location with '!loading' to prevent native anchor behaviour.
16374	 */
16375	var $topLevelSections = $('#theme-page > .vc_row, #theme-page > .mk-main-wrapper-holder, #theme-page > .mk-page-section');
16376
16377	$( document ).on( 'click', '.mk-skip-to-next', function() {
16378		var $this = $( this ),
16379			/**
16380			 * Static height of button + the space to the bottom of the container.
16381			 *
16382			 * @TODO Possible to calculate dynamically.
16383			 */
16384			btnHeight = $this.hasClass( 'edge-skip-slider' ) ? 150 : 76,
16385			offset = $this.offset().top + btnHeight,
16386			nextOffset = utils.nextHigherVal( utils.offsets( $topLevelSections ), [offset] );
16387
16388		utils.scrollTo( nextOffset - val.offsetHeaderHeight( nextOffset ) );
16389	});
16390
16391})( jQuery );
16392
16393(function($) {
16394	'use strict';
16395
16396	// 
16397	// Constructor
16398	// 
16399	// /////////////////////////////////////////////////////////
16400
16401	MK.ui.Slider = function( container, config ) { 
16402
16403		var defaults = {
16404				slide 				: '.mk-slider-slide',
16405	            nav 	     		: '.mk-slider-nav',
16406                effect              : 'roulete',
16407                ease 				: 'easeOutQuart', // should not be changed, remove
16408                slidesPerView       : 1,
16409                slidesToView        : 1,
16410                transitionTime      : 700,
16411                displayTime         : 3000,
16412                autoplay            : true,
16413                hasNav              : true,
16414                hasPagination       : true,
16415                paginationTpl 		: '<span></span>',
16416                paginationEl 		: '#pagination',
16417                draggable           : true,
16418                fluidHeight 		: false,
16419                pauseOnHover		: false,
16420                lazyload			: false,
16421                activeClass 		: 'is-active',
16422                edgeSlider	 		: false,
16423                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>',
16424                onInitialize 		: function() {},
16425                onAfterSlide 		: function( id ) {},
16426                onBeforeSlide 		: function( id ) {}
16427		};
16428
16429		this.state = {
16430			id 						: 0,
16431			moveForward 			: true,
16432			running   				: false,
16433            zIFlow					: null,
16434            stop 					: false,
16435		};
16436
16437		this.config = $.extend( defaults, config );
16438		this.container = container;
16439
16440		this.initPerView = this.config.slidesPerView;
16441
16442		// Timer holder
16443		this.activeTimer = null;
16444		this.autoplay = null;
16445		this.timer = null;
16446		this.timerRemaining = parseInt(this.config.displayTime);
16447
16448		// Boolean 'Em All, Making sure it's not string
16449		this.config.lazyload = JSON.parse(this.config.lazyload);
16450		this.config.edgeSlider = JSON.parse(this.config.edgeSlider);
16451
16452		// Image Loader Instance
16453		this.imageLoader = null;
16454
16455		// Add abort command to imagesLoaded, Placing it inside script makes it to work with different versions
16456		// of imagesLoaded if loaded by other Plugins
16457		imagesLoaded.prototype.abort = function() {
16458			this.progress = this.complete = function() { };
16459		};
16460	};
16461
16462	
16463
16464	// 
16465	// Shared methods
16466	// 
16467	// /////////////////////////////////////////////////////////
16468
16469	MK.ui.Slider.prototype = {
16470
16471		init : function() {
16472			this.setPerViewItems();
16473			this.cacheElements();
16474			this.getSlideSize();
16475			this.bindEvents();
16476            this.setSize();
16477			this.setPos();
16478
16479			// Hack for preparing 'prev' on first click if needed
16480			this.updateId( -1 );
16481			this.updateId( 1 );
16482
16483			this.val = this.dynamicVal();
16484			this.timeline = this.prepareTimeline( this.config.transitionTime );
16485
16486			this.timeline.build();
16487
16488			if( this.config.hasPagination ) { this.buildPagination(); }
16489			
16490			if( this.config.autoplay && document.hasFocus() ) { this.setTimer(); }
16491
16492			if( typeof this.config.onInitialize === 'function' ) {
16493				this.config.onInitialize( this.slides );
16494			}
16495
16496			if( this.config.fluidHeight === true ) {
16497				$( this.slides ).height( 'auto' );
16498				$( this.container ).css( 'transition', 'height ' + 200 + 'ms ease-out' );
16499				this.setHeight( 0 );
16500			}
16501
16502
16503			if( this.config.fluidHeight === 'toHighest' ) {
16504				this.setHeightToHighest();
16505			}
16506
16507			// Create timer per slide if required
16508			$(this.slides).each(this.createTimer);
16509
16510			// If it's Edge Slider and Lazy Load is enabled 
16511			if ( this.config.lazyload && this.config.edgeSlider ) {
16512
16513				// If It's not a Video Slide
16514				if ( $(this.slides[this.state.id]).find('video').length === 0 ) {
16515					// Set the first slide's BG image
16516					var $slideImg = $(this.slides[this.state.id]).children('[data-mk-img-set]');
16517					MK.component.BackgroundImageSetter.init( $slideImg );
16518				}
16519				$(this.config.spinnerTpl).prependTo( this.$slides );
16520
16521			} else {
16522
16523				// Set all slides's BG images
16524				MK.component.BackgroundImageSetter.init( $(this.slides).children('[data-mk-img-set]') );
16525
16526			}
16527			
16528
16529
16530		},
16531
16532
16533		cacheElements : function () {
16534			this.container = this.isNode( this.container ) ? this.container 
16535				: document.querySelectorAll( this.container )[0];
16536			this.slides = this.container.querySelectorAll( this.config.slide );
16537			this.$slides = $(this.slides);
16538
16539			if( this.config.hasNav ) { this.$nav = $( this.config.nav ); }
16540			if( this.config.hasPagination ) { this.$pagination = $( this.config.paginationEl ); }
16541		},
16542
16543
16544		bindEvents : function() {
16545			var $window = $( window );
16546
16547			if( this.config.slidesPerView > 1 ) { $window.on( 'resize', this.setPerViewItems.bind( this ) ); }
16548			if( this.config.hasNav ) { this.eventsNav(); }
16549			if( this.config.hasPagination ) { this.eventsPag(); }
16550			if( this.config.draggable ) { this.dragHandler(); }
16551			if( this.config.autoplay ) {
16552				$window.on( 'focus', this.windowActive.bind( this ) );
16553				$window.on( 'blur', this.windowInactive.bind( this ) );
16554			}
16555			if( this.config.pauseOnHover ) {
16556				$(this.container).on( 'mouseleave', this.setTimer.bind( this ) );
16557				$(this.container).on( 'mouseenter', this.unsetTimer.bind( this ) );
16558			}
16559			if( this.config.fluidHeight === 'toHighest' ) {
16560				$window.on( 'resize', this.setHeightToHighest.bind( this ) );
16561			}
16562		},
16563
16564
16565		setPerViewItems: function() {
16566			if(window.matchMedia( '(max-width: 500px)' ).matches) { this.config.slidesPerView = 1; }
16567			else if(window.matchMedia( '(max-width: 767px)' ).matches && this.initPerView >= 2 ) { this.config.slidesPerView = 2; }
16568			else if(window.matchMedia( '(max-width: 1024px)' ).matches && this.initPerView >= 3 ) { this.config.slidesPerView = 3; }
16569			else { this.config.slidesPerView = this.initPerView; }
16570			
16571        	if( typeof this.slides === 'undefined' ) return; 
16572			this.getSlideSize();
16573			this.setSize();
16574			this.setPos();
16575			this.timeline = this.prepareTimeline( this.config.transitionTime );
16576			this.timeline.build();
16577		},
16578
16579
16580		eventsNav : function() {
16581			this.$nav.on( 'click', 'a', this.handleNav.bind( this ) );
16582		},
16583
16584
16585		eventsPag : function() {
16586			this.$pagination.on( 'click', 'a', this.handlePagination.bind( this ) );
16587		},
16588
16589
16590		handleNav : function( e ) {
16591			e.preventDefault();
16592
16593			if( this.state.running ) { return; }
16594			this.state.running = true;
16595
16596			var $this = $( e.currentTarget ),
16597				moveForward = $this.data( 'direction' ) === 'next';
16598
16599
16600			if( this.config.autoplay ) { 
16601				this.unsetTimer();
16602				setTimeout( this.setTimer.bind( this ), this.config.transitionTime );
16603			}
16604
16605			this.state.moveForward = moveForward;
16606			this.timeline.build();
16607			this.timeline.play();
16608
16609			this.setActive( this.nextId( moveForward ? 1 : -1 ) );
16610			if( this.config.fluidHeight ) { this.setHeight( this.nextId( moveForward ? 1 : -1 ) ); }
16611		},
16612
16613
16614		handlePagination : function( e ) {
16615			e.preventDefault();
16616
16617			var $this = $( e.currentTarget ),
16618				id = $this.index();
16619
16620			this.goTo( id );
16621		},
16622
16623
16624		reset: function() {
16625			this.state.stop = true;
16626			this.state.id = 0;
16627			this.setPos();
16628			this.unsetTimer();
16629			this.setTimer();
16630		},
16631
16632
16633		goTo : function(id) {
16634			if( this.state.running ) { return; }
16635			this.state.running = true;
16636
16637			var lastId = this.state.id;
16638
16639			if( lastId === id ) {
16640				return;
16641			} else if( lastId < id ) {
16642				this.state.moveForward = true;
16643			} else {
16644				this.state.moveForward = false;
16645			}
16646
16647			if( this.config.autoplay ) { 
16648				this.unsetTimer();
16649				setTimeout( this.setTimer.bind( this ), this.config.transitionTime );
16650			}
16651
16652			this.timeline.build( Math.abs( lastId - id ) );
16653			this.timeline.play();
16654
16655			this.setActive( id );
16656			if( this.config.fluidHeight ) { this.setHeight( id ); } 
16657		},
16658
16659
16660		windowActive : function() {
16661			this.setTimer(false, true);
16662			$(this.container).removeClass('is-paused'); 
16663		},
16664
16665
16666		windowInactive : function() {
16667			this.unsetTimer();
16668			$(this.container).addClass('is-paused');
16669		},
16670
16671
16672		updateId : function( val ) {
16673			this.state.id = this.nextId(val);
16674		},
16675
16676		nextId : function( val ) {
16677			var len = this.slides.length,
16678				insertVal = this.state.id + val;
16679				insertVal = ( insertVal >= 0 ) ? insertVal : len + val;
16680				insertVal = ( insertVal >= len ) ? 0 : insertVal;
16681
16682			return insertVal;
16683		},
16684
16685
16686		setStyle : function( obj, style ) {
16687            var hasT = style.transform,
16688            	t = {
16689	                x       : ( hasT ) ? style.transform.translateX : null,
16690	                y       : ( hasT ) ? style.transform.translateY : null,
16691	                scale   : ( hasT ) ? style.transform.scale 		: null,
16692	                rotate  : ( hasT ) ? style.transform.rotate 	: null,
16693	                rotateX : ( hasT ) ? style.transform.rotateX 	: null,
16694	                rotateY : ( hasT ) ? style.transform.rotateY 	: null
16695           		},
16696				z  = 'translateZ(0)',
16697            	x  = (t.x) ?  'translateX(' + t.x + '%)' 		: 'translateX(0)',
16698                y  = (t.y) ?  'translateY(' + t.y + '%)' 		: 'translateY(0)',
16699                s  = (t.scale)  ?  'scale(' + t.scale + ')' 	: 'scale(1)',
16700                r  = (t.rotate) ? 'rotate(' + t.rotate + 'deg)' : 'rotate(0)',
16701                rX = (t.rotateX) ? 'rotateX(' + t.rotateX + 'deg)' : '',
16702                rY = (t.rotateY) ? 'rotateY(' + t.rotateY + 'deg)' : '',
16703
16704           		o = style.opacity,
16705           		h = style.height,
16706           		w = style.width;
16707
16708            var c = z + x + y  + s + r + rX + rY;
16709
16710            if( c.length ) {
16711	            obj.style.webkitTransform 	= c;
16712	            obj.style.msTransform 		= c;
16713	            obj.style.transform 		= c;
16714	        }
16715
16716            if( typeof o === 'number' ) { obj.style.opacity = o; }
16717            if( h ) { obj.style.height  = h + '%'; }
16718            if( w ) { obj.style.width   = w + '%'; }
16719		},
16720
16721
16722		setPos : function() {
16723        	if( typeof this.slides === 'undefined' ) return; 
16724		    var id 			= this.state.id,
16725		    	i 			= 0,
16726		    	len 		= this.slides.length,
16727		    	animation 	= this.animation[ this.config.effect ],
16728		    	axis 		= animation.axis,
16729				animNext	= animation.next,
16730				animActi 	= animation.active,
16731				animPrev 	= animation.prev,
16732                perView 	= this.config.slidesPerView,
16733                slideId 	= null,
16734                zIFlow 		= null,
16735                style 		= {};
16736
16737            style.transform = {};
16738
16739
16740            for( ; i < len; i += 1 ) {
16741                if(i < perView) {
16742                	// Position for visible slides. Apply active styles
16743                	style = animActi;
16744                    style.transform[ 'translate' + axis ] = i * 100;
16745                } else {
16746                	// Rest slides move after edge based on axis and moveForward. Apply Next / Prev styles
16747                	style = this.state.moveForward ? animNext : animPrev;
16748                    style.transform[ 'translate' + axis ] =  this.state.moveForward ? perView * 100 : -100;
16749                }
16750
16751                this.slides[ i ].style.zIndex = 0;
16752
16753                slideId = ( i + id ) % len;
16754                this.setStyle( this.slides[ slideId ], style );
16755            }
16756		},
16757
16758
16759        // When we're setting animation along Y axis we're going to set up height
16760        // otherwise width. It is shared amongst all slides
16761        setSize : function() {
16762        	if( typeof this.slides === 'undefined' ) return; 
16763        	var i = 0,
16764		    	len = this.slides.length,
16765		    	axis = this.animation[ this.config.effect ].axis,
16766                slideSize = this.slideSize,
16767        		style = {};
16768
16769            if( axis === 'Y' ) {
16770                style.height = slideSize[ axis ];
16771            } else {
16772                style.width = slideSize[ axis ];
16773            }
16774
16775            for( ; i < len; i += 1 ) {
16776                this.setStyle( this.slides[ i ], style );
16777            }
16778        },
16779
16780
16781        setHeight : function( id ) {
16782			var $slides = $( this.slides ),
16783				$activeSlide = $slides.eq( id );
16784
16785        	var currentHeight = $activeSlide.height();
16786        	$( this.container ).height( currentHeight ); 
16787        },
16788
16789
16790        setHeightToHighest : function() {
16791        	// this is becouse of alliginig woocommrece carousel. Too much DOM
16792        	// Refactor someday
16793			var $slides = $( this.slides ),
16794				height = 0;
16795
16796        	$slides.each(function() {
16797        		height = Math.max(height, $(this).find('> div').outerHeight());
16798        	});
16799
16800        	$( this.container ).height( height ); 
16801        },
16802
16803
16804        // Little utility inspired by GreenSock.
16805        // We export this to this.timeline on init. 
16806        prepareTimeline : function( time ) {
16807			var self 		= this,
16808				iteration 	= 0,
16809            	totalIter 	= time / (1000 / 60),
16810            	animLoop 	= [],
16811            	aL 			= 0, // animation length
16812            	loops 		= 1,
16813				ease 		= this.config.ease, 
16814				currentStyle, timeProg, 
16815				build, move, add, play, reverse, progress, kill;
16816
16817
16818			// Build constants, run them only once
16819			// take out possibly
16820			var len 		= this.slides.length,
16821				perView   	= this.config.slidesPerView,
16822				animation 	= this.animation[ this.config.effect ],
16823				animAxis 	= animation.axis,
16824				animNext	= animation.next,
16825				animActi 	= animation.active,
16826				animPrev 	= animation.prev,
16827				style 		= {},
16828				slideId 	= null,
16829				zIFlow 		= null;
16830
16831				style.transform = {};
16832
16833
16834			build = function( repeats ) {
16835				var currentEase = ease;
16836				loops = repeats || loops;
16837
16838				// console.log('build', loops);
16839
16840				if( !loops ) { return; }
16841				if( loops > 1 ) {
16842					currentEase = 'linearEase';
16843				}
16844
16845				// clean before running new build
16846				kill();
16847				// set new positions
16848				self.setPos();
16849
16850				var id = self.state.id,
16851					moveForward = self.state.moveForward,
16852					i = 0,
16853					axisMove = (moveForward) ? -100 : 100;
16854
16855				for( ; i <= perView; i += 1 ) {
16856					slideId = ( (moveForward) ? i + id : i + id - 1 ) % len;
16857					slideId = ( slideId < 0 ) ? len + slideId : slideId;
16858
16859					if( i === 0 ) {
16860						style = moveForward ? animPrev : animActi;
16861					} else if( i === perView ) {
16862						style = moveForward ? animActi : animNext;
16863					} else {
16864						style = animActi;
16865	            	}
16866
16867               	 	zIFlow = (self.state.moveForward) ? animNext.zIndex : animPrev.zIndex; 
16868	                if( zIFlow ) { 
16869	                	// console.log( zIFlow );
16870	                	self.slides[ slideId ].style.zIndex = (zIFlow === '+') ? i + 1 : len - i;
16871	                }
16872
16873					style.transform[ 'translate' + animAxis ] = axisMove;
16874	            	add( self.slides[ slideId ], style, currentEase );
16875				}
16876			};
16877
16878			add = function( slide, toStyles, ease ) {
16879				if( typeof slide === 'undefined' ) {
16880					throw 'Add at least one slide';
16881				}
16882
16883	            var fromStyles = slide.style,
16884					style = self.refStyle( toStyles, fromStyles );
16885
16886				animLoop.push( [slide, style, ease] );
16887				aL += 1;
16888			};
16889
16890			move = function( startProg, mode ) {
16891				if (isTest) return;
16892				var currentTotalIter = totalIter;
16893
16894				if( loops > 1 ) {
16895				 	currentTotalIter = totalIter / 5;
16896				}
16897
16898				if( !self.state.running ) { self.state.running = true; }
16899
16900				if( startProg ) {
16901					// update iteration val to cached outside var
16902					// ceil to handle properly play after mouse up / touch end
16903					iteration = Math.ceil(startProg * currentTotalIter);
16904				}
16905				
16906				timeProg = iteration / currentTotalIter;
16907				progress( timeProg );
16908
16909				// Break loop
16910				if( iteration >= currentTotalIter && mode === 'play' || 
16911					iteration <= 0 && mode === 'reverse' ) { 
16912
16913					self.state.running = false;
16914					iteration = 0;
16915					kill();
16916	            	self.updateId( self.state.moveForward ? 1 : -1 );
16917					// If we're creating multiple animation loop we trigger outside only first pass to start all game.
16918					// the rest are triggered as callback
16919					loops -= 1;
16920					if( loops > 0 ) {
16921						build();
16922						play();
16923					}
16924
16925					// if we run all loops reset back the default value
16926					if( !loops ) {
16927						loops = 1;
16928						self.timerRemaining = parseInt(self.config.displayTime);
16929						self.config.onAfterSlide( self.state.id );
16930					}
16931
16932					return; 
16933				}
16934
16935				// Run in given mode
16936				if( mode === 'play') {
16937					iteration += 1;
16938				} else {
16939					iteration -= 1;
16940				}
16941
16942				requestAnimationFrame( function() {
16943					if(self.state.stop) return;
16944					move( 0, mode );
16945				});
16946			};
16947
16948			play = function( startProg ) {
16949
16950				var $nextSlide = $(self.slides[ self.nextId(self.state.moveForward ? 1 : -1) ] );
16951
16952				// If it's Edge Slider and Lazy Load is enabled and It's not a Video Slide
16953				if ( self.config.lazyload && self.config.edgeSlider ) {
16954
16955					// Set the next slide's BG Image
16956					var $slideImg = $nextSlide.find('[data-mk-img-set]');
16957					if ( $slideImg.length ) {
16958						MK.component.BackgroundImageSetter.init( $slideImg );
16959					}
16960
16961				}
16962
16963				self.config.onBeforeSlide( self.nextId(self.state.moveForward ? 1 : -1) );
16964				var start = startProg || 0;
16965				iteration = 0;
16966				self.state.stop = false;
16967				move( start, 'play' );
16968
16969			};
16970
16971			reverse = function( startProg ) {
16972				var start = startProg || 1;
16973				move( start, 'reverse' );
16974			};
16975
16976			progress = function( progVal ) {
16977            	var aI = 0, 
16978            		currentStyle;
16979
16980				for( aI; aI < aL; aI++ ) {
16981					if( progVal !== 1 && progVal !== 0 ) {
16982						currentStyle = self.currentStyle( progVal, animLoop[ aI ][ 1 ], animLoop[ aI ][ 2 ] );
16983					} else if( progVal === 1) {
16984						currentStyle = self.currentStyle( progVal, animLoop[ aI ][ 1 ], 'linearEase' );
16985					} else if ( progVal === 0 ) {
16986						currentStyle = self.currentStyle( progVal, animLoop[ aI ][ 1 ], 'linearEase' );
16987					} 
16988					self.setStyle( animLoop[ aI ][ 0 ], currentStyle );
16989				}
16990			};
16991
16992			// Clear previous loop
16993			kill = function() {
16994				animLoop = [];
16995            	aL = 0;
16996			};
16997
16998
16999			return {
17000				build 		: build,
17001				add 		: add,
17002				play 		: play,
17003				reverse 	: reverse,
17004				progress 	: progress
17005			};
17006		},
17007
17008
17009		// Build reference styles.
17010		// Return object with array containig initial style and change of its value
17011		// as required for easing functions
17012		refStyle : function( toStyles, fromStyles ) {
17013			var axis = this.animation[ this.config.effect ].axis,
17014            	style = {},
17015				initVal, changeVal, endVal, dynamicEnd, styleProp, transProp, transform;
17016
17017			for( styleProp in toStyles ) {
17018
17019				if( styleProp === 'transform' ) {
17020					transform = this.getTransforms( fromStyles );
17021					style.transform = {};
17022
17023					for( transProp in toStyles.transform ) {
17024						// don't care about z
17025						if( transProp === 'translateZ' ) { continue; }
17026
17027						initVal = transform[ transProp ] || 0; // if it is undefined it means it's 0
17028						dynamicEnd = ( transProp === 'translate' + axis ) ? initVal : 0;
17029						endVal  = toStyles.transform[ transProp ] + dynamicEnd; // it is dynamic, based on slide position in current set
17030						changeVal = endVal - initVal;
17031						style.transform[ transProp ] = [ initVal, changeVal ];
17032					}
17033				} else if( styleProp === 'zIndex' ) {
17034					// console.log( 'z' );
17035					continue;
17036				} else {
17037					initVal = parseFloat( fromStyles[ styleProp ] ) || 0; // if it is undefined it means it's 0
17038					endVal  = toStyles[ styleProp ];
17039					changeVal = endVal - initVal;
17040					style[ styleProp ] =  [ initVal, changeVal ];
17041				}
17042			}
17043
17044			return style;
17045		},
17046
17047
17048		currentStyle : function( progress, style, ease ) {
17049			var self = this,
17050				currentStyle = {},
17051            	currentVals, styleProp, transProp, prog;
17052
17053			// Redo same loop but construct currentStyle object out of cached values
17054			for( styleProp in style ) {
17055
17056				if( styleProp === 'transform' ) {
17057					currentStyle.transform = {};
17058
17059					for( transProp in style.transform ) {
17060						// remove this line. double check first if needed by logging
17061						if( transProp === 'translateZ' ) { continue; }
17062
17063						currentVals = style.transform[ transProp ];
17064						currentStyle.transform[ transProp ] = 
17065							// (currentIteration, startValue, changeInValue, totalIterations)
17066								self.ease[ ease ]( progress, currentVals[ 0 ], currentVals[ 1 ], 1 );
17067					}
17068				} else {
17069					currentVals = style[ styleProp ];
17070					currentStyle[ styleProp ] = 
17071						self.ease[ ease ]( progress, currentVals[ 0 ], currentVals[ 1 ], 1 );
17072				}
17073			}
17074
17075			return currentStyle;
17076		},
17077
17078
17079		setActive : function( id ) {
17080			var $slides = $( this.slides ),
17081				className = this.config.activeClass;
17082
17083			$slides.removeClass( className );
17084
17085			if( this.config.hasPagination ) {
17086				var $pagination = this.$pagination.find( 'a' );
17087				$pagination.removeClass( className );
17088				$pagination.eq( id ).addClass( className );
17089			}
17090
17091			if( this.activeTimer ) {
17092				clearTimeout( this.activeTimer );
17093				if ( this.imageLoader ) {
17094					this.imageLoader.abort();
17095				}
17096			} 
17097			
17098
17099			var self = this;
17100
17101			this.activeTimer = setTimeout( function() {
17102
17103				var $currentSlide = $slides.eq( id );
17104
17105				if ( self.config.lazyload && self.config.edgeSlider ) {  // If it's Edge Slider and Lazy Load is enabled
17106
17107					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
17108						
17109						var imgSet = $currentSlide.children('.mk-video-section-touch').data('mk-img-set');
17110						var exactImg = MK.component.BackgroundImageSetter.getImage( imgSet );
17111						var $bgImage = $('<img>').attr('src', exactImg );
17112
17113						self.imageLoader = imagesLoaded( $bgImage[0], function( instance ) {
17114							$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
17115							setTimeout( function() {
17116						 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
17117						 	}, 200);
17118							$currentSlide.addClass( className );
17119					 	});
17120
17121					} 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
17122
17123						$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
17124						setTimeout( function() {
17125					 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
17126					 	}, 200);
17127						$currentSlide.addClass( className );
17128						
17129					} else {  // If it's a Image Slide
17130
17131						if ( $currentSlide.children('[data-mk-img-set]').length ) {
17132							// Get the matching Image URL to start lazy loading
17133							var imgSet = $currentSlide.children('[data-mk-img-set]').data('mk-img-set');
17134							var exactImg = MK.component.BackgroundImageSetter.getImage( imgSet );
17135							var $bgImage = $('<img>').attr('src', exactImg );
17136
17137							// Prevent counting time on slide until the image loads
17138							self.unsetTimer();
17139							self.imageLoader = imagesLoaded( $bgImage[0], function( instance ) {
17140								// Hide spinner, Continue counting time on slide and show the content
17141							 	$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
17142							 	setTimeout( function() {
17143							 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
17144							 	}, 200);
17145								self.setTimer(false, false, $currentSlide.data('timer') || Number(self.config.displayTime) );
17146								$currentSlide.addClass( className );
17147							});
17148						} else {
17149							$currentSlide.children('.mk-slider-spinner-wrap').addClass('mk-slider-spinner-wrap-hidden');
17150						 	setTimeout( function() {
17151						 		$currentSlide.children('.mk-slider-spinner-wrap').hide();
17152						 	}, 200);
17153							self.setTimer(false, false, $currentSlide.data('timer') || Number(self.config.displayTime) );
17154							$currentSlide.addClass( className );
17155						}
17156
17157					}
17158
17159				} else {
17160
17161					$currentSlide.addClass( className );
17162
17163				}
17164				
17165				
17166			}, this.config.transitionTime );
17167		},
17168
17169		createTimer : function() {
17170
17171			var $slide = $(this),
17172				video = $slide.find('video').get(0);
17173
17174			if(video) {
17175				// A hacky but reliable way to ge the video duration
17176				var interval = setInterval( function() {
17177					// If the metadata is ready
17178					if ( video.readyState > 0 ) {
17179						$slide.data('timer', (video.duration * 1000));
17180						$slide.attr('data-timer', (video.duration * 1000));
17181						clearInterval(interval);
17182					}
17183				}, 100);
17184			}
17185
17186		},
17187		
17188		setTimer : function( isFirst, isPaused, fixed_time ) {
17189			// check for custom timer
17190			var customTimer = this.$slides.eq(this.nextId(this.state.moveForward ? 1 : -1)).data('timer'),
17191				trans = parseInt( this.config.transitionTime ),
17192				interval = customTimer ? customTimer : parseInt( this.config.displayTime ),
17193				timer = interval + trans;
17194
17195			var self  = this,
17196				first = isFirst || true,
17197				fixed_time = fixed_time || 0,
17198				create, run;
17199
17200			this.timer = true;
17201			this.lastSetTimer = Date.now();
17202
17203			create = function() {	
17204
17205				if( self.autoplay ) { clearTimeout( self.autoplay ); }
17206				if( !self.timer ) {
17207					return;
17208				}
17209				self.state.moveForward = true;
17210				self.timeline.build();
17211				self.timeline.play();
17212				self.setActive( self.nextId( 1 ) );
17213				if( self.config.fluidHeight ) { self.setHeight( self.nextId( 1 ) ); }
17214				first = false;
17215				self.lastSetTimer = Date.now();
17216
17217				run();
17218			};
17219
17220			run = function(newInterval) {
17221				// check for custom timer
17222				customTimer = self.$slides.eq(self.nextId(self.state.moveForward ? 1 : -1)).data('timer');
17223				interval = customTimer ? customTimer : parseInt( self.config.displayTime );
17224				timer = interval + trans; // update timer with current val
17225
17226				var time = newInterval || timer;
17227				self.autoplay = setTimeout( create, time );
17228			};
17229
17230			if ( fixed_time ) {
17231				run( fixed_time );
17232			} else if (isPaused) {
17233				run( this.timerRemaining );
17234			} else {
17235				run();
17236			}
17237		},
17238
17239
17240		unsetTimer : function() {
17241			this.timer = false;
17242			this.lastUnsetTimer = Date.now();
17243			this.timerRemaining -= this.lastUnsetTimer - this.lastSetTimer;
17244			if( this.autoplay ) { clearTimeout( this.autoplay ); }
17245		},
17246
17247
17248		buildPagination : function() {
17249			var i   = 0,
17250				len = this.slides.length,
17251				tpl = '';
17252
17253			for( ; i < len; i += 1 ) {
17254				tpl += '<a href="javascript:;">' + this.config.paginationTpl + '</a>';
17255			}
17256
17257			this.$pagination.html( tpl );
17258			this.setActive( 0 );
17259		},
17260
17261
17262		getSlideSize : function() {
17263			this.slideSize = {
17264                X: 100 / this.config.slidesPerView,
17265                Y: 100 / this.config.slidesPerView
17266            };
17267		},
17268
17269
17270		getTransforms : function( style ) {
17271			// console.log( style );
17272		    var transform = style.transform || style.webkitTransform || style.mozTransform,
17273		    	regex = /(\w+)\(([^)]*)\)/g,
17274				match,
17275				T = {};
17276
17277			if( typeof transform !== 'string' ) {
17278				throw 'Transform prop is not a string.';
17279			}
17280
17281		    if( !transform ) { return; }
17282	
17283			// Run regex assignment
17284			while( match = regex.exec( transform ) ) {
17285				T[ match[ 1 ] ] = parseFloat( match[ 2 ] );
17286			}
17287
17288		    return T;
17289		},
17290
17291		isNode : function( o ) {
17292			return (
17293		    	typeof Node === "object" ? o instanceof Node : 
17294		   			o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string"
17295		  	);
17296		},
17297
17298
17299		dragHandler : function() {
17300			var self = this,
17301				$container = $( this.container ),
17302				prevBuild = false, 
17303				nextBuild = false,
17304				dragging = false,
17305				buffor = 5, // helpful for decoupling with click events
17306				dragStart, dragMove, dragEnd, progress;
17307
17308			progress = function( moveX ) {
17309				return moveX / self.val.viewportW();
17310			};
17311
17312			dragStart = function( moveX, startX ) {
17313				// console.log( 'start', moveX, startX );
17314			};
17315
17316			dragMove = function( moveX ) {
17317				// console.log('move');
17318				if( self.state.running ) return;
17319
17320				// Don't need to check for existance here
17321
17322				if( moveX < -buffor ) {
17323
17324					if( !nextBuild ) {
17325						self.state.moveForward = true;
17326						self.timeline.build();
17327						nextBuild = true;
17328						prevBuild = false;
17329						self.unsetTimer();
17330					} else {
17331						// turn progress into positive val
17332						self.timeline.progress( -progress( moveX ) );
17333					}
17334					dragging = true;
17335				} else if( moveX > buffor ) {
17336
17337					if( !prevBuild ) {
17338						self.state.moveForward = false;
17339						self.timeline.build();
17340						prevBuild = true;
17341						nextBuild = false;
17342						self.unsetTimer();
17343					} else {
17344						self.timeline.progress( progress( moveX ) );
17345					}
17346					dragging = true;
17347				}
17348			};
17349
17350			dragEnd = function( moveX ) {
17351				if( dragging ) {
17352					var prog = progress( moveX ),
17353						absProg = prog < 0 ? -prog : prog;
17354
17355					if( absProg > 0.1 ) {
17356						self.timeline.play( absProg );
17357						self.setActive( self.nextId( prog < 0 ? 1 : -1 ) );
17358						if( self.config.fluidHeight ) { self.setHeight( self.nextId( prog < 0 ? 1 : -1 ) ); }
17359					} else {
17360						self.timeline.reverse( absProg );
17361						// eventually move this to reverse callbacks	
17362						if(prog < 0) {
17363							self.updateId( -1 );
17364						} else {
17365							self.updateId( 1 );
17366						}
17367					}
17368
17369					prevBuild = false;
17370					nextBuild = false;
17371					dragging = false;
17372					if( self.config.autoplay ) { self.setTimer( false ); }
17373				}
17374			};
17375
17376			this.drag( $container, dragStart, dragMove, dragEnd );
17377		},
17378
17379
17380		drag : function( $el, startFn, moveFn, stopFn ) {
17381
17382		    var touchX, touchY, movX, movY, go, evt,
17383		   		prevent, start, move, stop;
17384
17385		    prevent = function( e ) {
17386		        e.preventDefault();
17387		    };
17388
17389		    start = function( e ) {
17390		        // $el.on("touchmove", prevent);
17391		        $el.on("mousemove", prevent);
17392		        $el.on("touchmove", move);
17393		        $el.on("mousemove", move);
17394
17395		        evt = (e.type === 'touchstart') ? e.originalEvent.touches[0] : e;
17396		        touchX = evt.pageX;
17397
17398		        if(typeof startFn === 'function') {
17399		        	startFn(movX, touchX);
17400		        }
17401		    };
17402
17403		    move = function( e ) {
17404		        evt = (e.type === 'touchmove') ? e.originalEvent.touches[0] : e;
17405		        movX = evt.pageX - touchX;
17406
17407	        	if(typeof moveFn === 'function') {
17408		        	moveFn(movX);
17409		        }
17410		    };
17411
17412		    stop = function( e ) {
17413		        // $el.off("touchmove", prevent);
17414		        $el.off("mousemove", prevent);
17415		        $el.off("touchmove", move);
17416		        $el.off("mousemove", move);
17417
17418		    	if(typeof stopFn === 'function') {
17419		        	stopFn(movX);
17420		        }
17421		    };
17422
17423		    $el.on("touchstart", start);
17424		    $el.on("mousedown", start);
17425		    $el.on("touchend", stop);
17426		    $el.on("touchleave", stop);
17427		    $el.on("touchcancel", stop);
17428		    $el.on("mouseup", stop);
17429		    $el.on("mouseleave", stop);
17430		},
17431
17432
17433		dynamicVal : function() {
17434			var $window = $( window ),
17435				update, 
17436				getViewportW, viewportW;
17437
17438			update = function() {
17439 				viewportW = $window.width();
17440			};
17441
17442			getViewportW = function() {
17443				return viewportW;
17444			};
17445
17446			update();
17447			$window.on( 'load', update );
17448			$window.on( 'resize', update );
17449
17450			return {
17451				viewportW : getViewportW
17452			};
17453		}
17454	};
17455
17456
17457
17458	// 
17459	// Set of default animations
17460	// 
17461	// /////////////////////////////////////////////////////////
17462
17463	MK.ui.Slider.prototype.animation = {
17464
17465        slide : {
17466        	axis : 'X', 
17467            next : { transform: {} },
17468            active : { transform: {} },
17469            prev : { transform: {} }
17470        },
17471
17472        vertical_slide : {
17473        	axis : 'Y',
17474            next : { transform: {} },
17475            active : { transform: {} },
17476            prev : { transform: {} }
17477        },
17478
17479        perspective_flip : {
17480        	axis : 'Y',
17481            next : { 
17482            	transform: {
17483            		rotateX : 80
17484            	} 
17485            },
17486            active : { 
17487            	transform: {
17488            		rotateX : 0
17489            	} 
17490            },
17491            prev : { 
17492            	transform: {
17493            		rotateX : 0
17494            	} 
17495            }
17496        },
17497
17498        zoom : {
17499			axis : 'Z',
17500            next: {
17501                opacity	: 0,
17502                transform : {
17503	                scale : 0.9
17504	            }
17505            },
17506            active: {
17507                opacity	: 1,
17508                transform : {
17509	                scale : 1
17510	            }
17511            },
17512            prev: {
17513                opacity	: 0,
17514                transform : {
17515	                scale : 1.1
17516	            }
17517            }
17518        },
17519
17520        fade : {
17521			axis : 'Z',
17522            next: {
17523                opacity	: 0,
17524                transform : {}
17525            },
17526            active: {
17527                opacity	: 1,
17528                transform : {}
17529            },
17530            prev: {
17531                opacity	: 0,
17532                transform : {}
17533            }
17534        },
17535
17536        kenburned : {
17537			axis : 'Z',
17538            next: {
17539                opacity	: 0,
17540                transform : {}
17541            },
17542            active: {
17543                opacity	: 1,
17544                transform : {}
17545            },
17546            prev: {
17547                opacity	: 0,
17548                transform : {}
17549            }
17550        },
17551
17552        zoom_out : {
17553			axis : 'Z',
17554            next: {
17555				zIndex : '+',
17556                opacity	: 1,
17557                transform : {
17558	                translateY : 100,
17559	                scale : 1
17560	            }
17561            },
17562            active: {
17563                opacity	: 1,
17564                transform : {
17565	                translateY : 0,
17566	                scale : 1
17567	            }
17568            },
17569            prev: {
17570				zIndex : '+',
17571                opacity	: 0,
17572                transform : {
17573	                translateY : 0,
17574	                scale : 0.5
17575	            }
17576            }
17577        },
17578
17579        // Problem with Z-Flow
17580        horizontal_curtain : {
17581			axis : 'Z',
17582            next: {
17583				zIndex : '+',
17584                transform : {
17585	                translateX : 100,
17586	            }
17587            },
17588            active: {
17589                transform : {
17590	                translateX : 0,
17591	            }
17592            },
17593            prev: {
17594				zIndex : '+',
17595                transform : {
17596	                translateX : -70,
17597	            }
17598            }
17599        },
17600
17601		roulete : {
17602			axis : 'X',
17603            next: {
17604                opacity	: 0.5,
17605                transform : {
17606	                scale : 0.5,
17607	                rotate : 10,
17608	                translateY : 20
17609	            }
17610            },
17611            active: {
17612                opacity	: 1,
17613                transform : {
17614	                scale : 1,
17615	                rotate : 0,
17616	                translateY : 0
17617	            }
17618            },
17619            prev: {
17620                opacity	: 0.3,
17621                transform : {
17622	                scale : 0.5,
17623	                rotate : -10,
17624	                translateY : 20
17625	            }
17626            }
17627		}
17628	};
17629
17630
17631
17632	// 
17633	// Penner's easing library
17634	// 
17635	// /////////////////////////////////////////////////////////
17636
17637	MK.ui.Slider.prototype.ease = {
17638		/*
17639		 *
17640		 * TERMS OF USE - EASING EQUATIONS
17641		 * 
17642		 * Open source under the BSD License. 
17643		 * 
17644		 * Copyright © 2001 Robert Penner
17645		 * All rights reserved.
17646		 * 
17647		 * Redistribution and use in source and binary forms, with or without modification, 
17648		 * are permitted provided that the following conditions are met:
17649		 * 
17650		 * Redistributions of source code must retain the above copyright notice, this list of 
17651		 * conditions and the following disclaimer.
17652		 * Redistributions in binary form must reproduce the above copyright notice, this list 
17653		 * of conditions and the following disclaimer in the documentation and/or other materials 
17654		 * provided with the distribution.
17655		 * 
17656		 * Neither the name of the author nor the names of contributors may be used to endorse 
17657		 * or promote products derived from this software without specific prior written permission.
17658		 * 
17659		 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
17660		 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17661		 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
17662		 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
17663		 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
17664		 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
17665		 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
17666		 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
17667		 * OF THE POSSIBILITY OF SUCH DAMAGE. 
17668		 *
17669		 */
17670		linearEase : function(currentIteration, startValue, changeInValue, totalIterations) {
17671			return changeInValue * currentIteration / totalIterations + startValue;
17672		},
17673
17674		easeInQuad : function(currentIteration, startValue, changeInValue, totalIterations) {
17675			return changeInValue * (currentIteration /= totalIterations) * currentIteration + startValue;
17676		},
17677
17678		easeOutQuad : function(currentIteration, startValue, changeInValue, totalIterations) {
17679			return -changeInValue * (currentIteration /= totalIterations) * (currentIteration - 2) + startValue;
17680		},
17681
17682		easeInOutQuad : function(currentIteration, startValue, changeInValue, totalIterations) {
17683			if ((currentIteration /= totalIterations / 2) < 1) {
17684				return changeInValue / 2 * currentIteration * currentIteration + startValue;
17685			}
17686			return -changeInValue / 2 * ((--currentIteration) * (currentIteration - 2) - 1) + startValue;
17687		},
17688
17689		easeInCubic : function(currentIteration, startValue, changeInValue, totalIterations) {
17690			return changeInValue * Math.pow(currentIteration / totalIterations, 3) + startValue;
17691		},
17692
17693		easeOutCubic : function(currentIteration, startValue, changeInValue, totalIterations) {
17694			return changeInValue * (Math.pow(currentIteration / totalIterations - 1, 3) + 1) + startValue;
17695		},
17696
17697		easeInOutCubic : function(currentIteration, startValue, changeInValue, totalIterations) {
17698			if ((currentIteration /= totalIterations / 2) < 1) {
17699				return changeInValue / 2 * Math.pow(currentIteration, 3) + startValue;
17700			}
17701			return changeInValue / 2 * (Math.pow(currentIteration - 2, 3) + 2) + startValue;
17702		},
17703
17704		easeInQuart : function(currentIteration, startValue, changeInValue, totalIterations) {
17705			return changeInValue * Math.pow (currentIteration / totalIterations, 4) + startValue;
17706		},
17707
17708		easeOutQuart : function(currentIteration, startValue, changeInValue, totalIterations) {
17709			return -changeInValue * (Math.pow(currentIteration / totalIterations - 1, 4) - 1) + startValue;
17710		},
17711
17712		easeInOutQuart : function(currentIteration, startValue, changeInValue, totalIterations) {
17713			if ((currentIteration /= totalIterations / 2) < 1) {
17714				return changeInValue / 2 * Math.pow(currentIteration, 4) + startValue;
17715			}
17716			return -changeInValue/2 * (Math.pow(currentIteration - 2, 4) - 2) + startValue;
17717		},
17718
17719		easeInQuint : function(currentIteration, startValue, changeInValue, totalIterations) {
17720			return changeInValue * Math.pow (currentIteration / totalIterations, 5) + startValue;
17721		},
17722
17723		easeOutQuint : function(currentIteration, startValue, changeInValue, totalIterations) {
17724			return changeInValue * (Math.pow(currentIteration / totalIterations - 1, 5) + 1) + startValue;
17725		},
17726
17727		easeInOutQuint : function(currentIteration, startValue, changeInValue, totalIterations) {
17728			if ((currentIteration /= totalIterations / 2) < 1) {
17729				return changeInValue / 2 * Math.pow(currentIteration, 5) + startValue;
17730			}
17731			return changeInValue / 2 * (Math.pow(currentIteration - 2, 5) + 2) + startValue;
17732		},
17733
17734		easeInSine : function(currentIteration, startValue, changeInValue, totalIterations) {
17735			return changeInValue * (1 - Math.cos(currentIteration / totalIterations * (Math.PI / 2))) + startValue;
17736		},
17737
17738		easeOutSine : function(currentIteration, startValue, changeInValue, totalIterations) {
17739			return changeInValue * Math.sin(currentIteration / totalIterations * (Math.PI / 2)) + startValue;
17740		},
17741
17742		easeInOutSine : function(currentIteration, startValue, changeInValue, totalIterations) {
17743			return changeInValue / 2 * (1 - Math.cos(Math.PI * currentIteration / totalIterations)) + startValue;
17744		},
17745
17746		easeInExpo : function(currentIteration, startValue, changeInValue, totalIterations) {
17747			return changeInValue * Math.pow(2, 10 * (currentIteration / totalIterations - 1)) + startValue;
17748		},
17749
17750		easeOutExpo : function(currentIteration, startValue, changeInValue, totalIterations) {
17751			return changeInValue * (-Math.pow(2, -10 * currentIteration / totalIterations) + 1) + startValue;
17752		},
17753
17754		easeInOutExpo : function(currentIteration, startValue, changeInValue, totalIterations) {
17755			if ((currentIteration /= totalIterations / 2) < 1) {
17756				return changeInValue / 2 * Math.pow(2, 10 * (currentIteration - 1)) + startValue;
17757			}
17758			return changeInValue / 2 * (-Math.pow(2, -10 * --currentIteration) + 2) + startValue;
17759		},
17760
17761		easeInCirc : function(currentIteration, startValue, changeInValue, totalIterations) {
17762			return changeInValue * (1 - Math.sqrt(1 - (currentIteration /= totalIterations) * currentIteration)) + startValue;
17763		},
17764
17765		easeOutCirc : function(currentIteration, startValue, changeInValue, totalIterations) {
17766			return changeInValue * Math.sqrt(1 - (currentIteration = currentIteration / totalIterations - 1) * currentIteration) + startValue;
17767		},
17768
17769		easeInOutCirc : function(currentIteration, startValue, changeInValue, totalIterations) {
17770			if ((currentIteration /= totalIterations / 2) < 1) {
17771				return changeInValue / 2 * (1 - Math.sqrt(1 - currentIteration * currentIteration)) + startValue;
17772			}
17773			return changeInValue / 2 * (Math.sqrt(1 - (currentIteration -= 2) * currentIteration) + 1) + startValue;
17774		}
17775	};
17776
17777})(jQuery);
17778/* Social Share */
17779/* -------------------------------------------------------------------- */
17780(function($) {
17781    'use strict';
17782
17783    MK.component.SocialShare = function( el ) {
17784        var networks = {
17785			twitter : 'http://twitter.com/intent/tweet?text={title}&url={url}',
17786			pinterest : 'http://pinterest.com/pin/create/button/?url={url}&media={image}&description={title}',
17787			facebook : 'https://www.facebook.com/sharer/sharer.php?u={url}',
17788			googleplus : 'https://plus.google.com/share?url={url}',
17789			linkedin : 'http://www.linkedin.com/shareArticle?mini=true&url={url}&title={title}&summary={desc}',
17790			digg : 'http://digg.com/submit?url={url}&title={title}',
17791			reddit : 'http://reddit.com/submit?url={url}&title={title}',
17792        };
17793
17794        this.networks = networks;
17795        this.el = el;
17796    };
17797
17798
17799	MK.component.SocialShare.prototype = {
17800
17801        init : function() {
17802            this.cacheElements();
17803            this.bindEvents();
17804        },
17805
17806        cacheElements : function() {
17807            this.$this  = $( this.el );
17808
17809
17810        },
17811
17812        bindEvents : function() {
17813			var thisObject = this;
17814			var tempClass = "";
17815			$.each(this.networks, function( key, value ) {
17816				  thisObject.$tempClass = $('.' + key + '-share');
17817				  thisObject.$tempClass.click(thisObject.openSharingDialog.bind(self, this, key));
17818
17819			});
17820        },
17821
17822        openSharingDialog : function(url, site, args) {
17823			var urlWrapper = url;
17824			var rx = new RegExp('\{[a-z]*\}','g'), res;
17825			var match = rx.exec(url);
17826			while (match != null) {
17827				var pureAttr = match[0].replace("{", "").replace("}" , "");
17828				var attValue = $(args.currentTarget).attr('data-' + pureAttr);
17829				if (attValue === undefined || attValue === null) {
17830					attValue = "";
17831				}
17832				attValue = attValue.replace('#', '%23'); // fix for twitter description
17833				urlWrapper = urlWrapper.replace(match, attValue);
17834				match = rx.exec(url);
17835			}
17836
17837			window.open(urlWrapper, site + "Window", "height=320,width=660,resizable=0,toolbar=0,menubar=0,status=0,location=0,scrollbars=0");
17838
17839        },
17840
17841
17842    };
17843
17844
17845	//////////////////////////////////////////
17846    //
17847    // Apply to:
17848    //
17849    // ///////////////////////////////////////
17850
17851    var $body = $('body');
17852
17853    if(!$body.length) return;
17854
17855    $body.each(function() {
17856        var socialShare = new MK.component.SocialShare(this);
17857			socialShare.init();
17858    });
17859
17860})(jQuery);
17861
17862
17863
17864//function mk_social_share() {
17865//
17866//  "use strict";
17867//
17868//  $('.twitter-share').on('click', function () {
17869//    var $url = $(this).attr('data-url'),
17870//      $title = $(this).attr('data-title');
17871//
17872//    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");
17873//    return false;
17874//  });
17875//
17876//  $('.pinterest-share').on('click', function () {
17877//    var $url = $(this).attr('data-url'),
17878//      $title = $(this).attr('data-title'),
17879//      $image = $(this).attr('data-image');
17880//    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");
17881//    return false;
17882//  });
17883//
17884//  $('.facebook-share').on('click', function () {
17885//    var $url = $(this).attr('data-url');
17886//    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");
17887//    return false;
17888//  });
17889//
17890//  $('.googleplus-share').on('click', function () {
17891//    var $url = $(this).attr('data-url');
17892//    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");
17893//    return false;
17894//  });
17895//
17896//  $('.linkedin-share').on('click', function () {
17897//    var $url = $(this).attr('data-url'),
17898//      $title = $(this).attr('data-title'),
17899//      $desc = $(this).attr('data-desc');
17900//    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");
17901//    return false;
17902//  });
17903//}
17904
17905
17906
17907
17908(function($) {
17909	'use strict';
17910
17911	MK.component.Sortable = function(el) {
17912		this.el = el; 
17913	};
17914
17915	MK.component.Sortable.prototype = {
17916		init: function init() {
17917			this.cacheElements();
17918			this.bindEvents();
17919		},
17920
17921		cacheElements: function cacheElements() {
17922			this.unique = Date.now();
17923			this.$filter = $(this.el);
17924			this.config = this.$filter.data('sortable-config');
17925
17926			this.ajaxLoader = new MK.utils.ajaxLoader(this.config.container);
17927			this.ajaxLoader.init();
17928
17929			this.$container = $( this.config.container );
17930			this.$navItems = this.$filter.find('a');
17931			this.$filterItems = this.$container.find(this.config.item);
17932		},
17933
17934		bindEvents: function bindEvents() {
17935			this.$navItems.on('click', this.handleClick.bind(this));
17936			MK.utils.eventManager.subscribe('ajaxLoaded', this.onLoad.bind(this));
17937		},
17938
17939		handleClick: function handleClick(e) {
17940			e.preventDefault();
17941
17942			var $item = $(e.currentTarget);
17943			var term = $item.data('filter');
17944
17945			this.$navItems.removeClass('current');
17946			$item.addClass('current');
17947
17948			if(this.config.mode === 'ajax') this.inDB(term, $item);
17949	        else this.inPage(term);
17950		},
17951
17952		inDB: function inDB(term, $item) { 
17953			// Add load indicator only for long requests
17954			MK.ui.loader.remove(this.$filter);
17955			MK.ui.loader.add($item);
17956			
17957			// If mk-ajax-loaded-posts span exists and one of the filter is clicked,
17958			// clear post ids
17959			if ( this.$container.siblings('.mk-ajax-loaded-posts').length ) {		
17960				this.$container.siblings('.mk-ajax-loaded-posts').attr('data-loop-loaded-posts', '');
17961			}
17962
17963			this.ajaxLoader.setData({
17964				paged: 1,
17965				term: term
17966			});
17967            this.ajaxLoader.load(this.unique);
17968		},
17969
17970		inPage: function inPage(term) {
17971			var $filterItems = this.$container.find(this.config.item);
17972			$filterItems.removeClass('is-hidden'); // show all first
17973			// Replace all ', ' with ', .'. It's used to add '.' as class selector of each category.
17974			var className = term.replace( /, /g, ", ." );
17975			if(term !== '*') $filterItems.not( '.' + className ).addClass('is-hidden'); // hide filtered
17976			MK.utils.eventManager.publish('staticFilter');
17977		},
17978
17979		onLoad: function onLoad(e, response) {
17980			if(this.config.mode === 'static') {
17981				this.$navItems.removeClass('current').first().addClass('current');
17982			}
17983			if( typeof response !== 'undefined' &&  response.id === this.config.container) {
17984				MK.ui.loader.remove(this.$filter);
17985				if(response.unique === this.unique) {
17986		            this.$container.html(response.content);
17987					this.ajaxLoader.setData({paged: 1});
17988				}
17989			}
17990		}
17991	};
17992
17993})(jQuery);
17994(function($) {
17995    'use strict';
17996
17997    MK.component.Tabs = function( el ) {
17998        var defaults = {
17999            activeClass : 'is-active'
18000        };
18001
18002        this.config = defaults;
18003        this.el = el;
18004    };
18005
18006    MK.component.Tabs.prototype = {
18007
18008        init : function() {
18009            this.cacheElements();
18010            this.bindEvents();
18011        },
18012
18013        cacheElements : function() {
18014            this.$this  = $( this.el );
18015            this.$tabs  = this.$this.find( '.mk-tabs-tab' );
18016            this.$panes = this.$this.find( '.mk-tabs-pane' );
18017            this.currentId = 0;
18018        },
18019
18020        bindEvents : function() {
18021            var self = this;
18022
18023            this.$tabs.on( 'click', this.switchPane.bind( this ) );
18024        },
18025
18026        switchPane : function( evt ) {
18027            evt.preventDefault();
18028
18029            var clickedId = $( evt.currentTarget ).index();
18030
18031            this.hide( this.currentId );
18032            this.show( clickedId );
18033
18034            // Update current id
18035            this.currentId = clickedId;
18036
18037            // Notify rest of the app
18038            MK.utils.eventManager.publish('item-expanded');            
18039        },
18040
18041        show : function( id ) {
18042            this.$tabs.eq( id ).addClass( this.config.activeClass );
18043            this.$panes.eq( id ).addClass( this.config.activeClass );
18044        },
18045
18046        hide : function( id ) {
18047            this.$tabs.eq( id ).removeClass( this.config.activeClass );
18048            this.$panes.eq( id ).removeClass( this.config.activeClass );
18049        }
18050    };
18051
18052})(jQuery);
18053
18054
18055/* Tabs */
18056/* -------------------------------------------------------------------- */
18057
18058function mk_tabs() {
18059
18060  // "use strict";
18061
18062  // if ($.exists('.mk-tabs, .mk-news-tab, .mk-woo-tabs')) {
18063  //   $(".mk-tabs, .mk-news-tab, .mk-woo-tabs").tabs();
18064
18065  //    $('.mk-tabs').on('click', function () {
18066  //      $('.mk-theme-loop').isotope('layout');
18067  //    });
18068
18069  //   $('.mk-tabs.vertical-style').each(function () {
18070  //     $(this).find('.mk-tabs-pane').css('minHeight', $(this).find('.mk-tabs-tabs').height() - 1);
18071  //   });
18072
18073  // }
18074}
18075
18076function mk_tabs_responsive(){
18077  // $('.mk-tabs, .mk-news-tab').each(function () {
18078  //   $this = $(this);
18079  //   if ($this.hasClass('mobile-true')) {
18080  //     if (window.matchMedia('(max-width: 767px)').matches)
18081  //     {
18082  //         $this.tabs("destroy");
18083  //     } else {
18084  //       $this.tabs();
18085  //     }
18086  //   }
18087  // });
18088  
18089}
18090
18091
18092(function($) {
18093  'use strict';
18094
18095  $(document).on('click', function(e) {
18096    $('.mk-toggle-trigger').removeClass('mk-toggle-active');
18097  });
18098
18099  function toggle(e) {
18100      e.preventDefault();
18101      e.stopPropagation();
18102      var $this = $(e.currentTarget);
18103
18104      if (!$this.hasClass('mk-toggle-active')) {
18105
18106        $('.mk-box-to-trigger').fadeOut(200);
18107        $this.parent().find('.mk-box-to-trigger').fadeIn(250);
18108        $('.mk-toggle-trigger').removeClass('mk-toggle-active');
18109        $this.addClass('mk-toggle-active');
18110
18111      } else {
18112
18113        $('.mk-box-to-trigger').fadeOut(200);
18114        $this.removeClass('mk-toggle-active');
18115
18116      }
18117  }
18118
18119  function assignToggle() {
18120    // wait for ajax response propagation and insertion
18121    setTimeout(function() {
18122      $('.mk-toggle-trigger').off('click', toggle);
18123      $('.mk-toggle-trigger').on('click', toggle);
18124    }, 100);
18125  }
18126
18127  assignToggle();
18128  MK.utils.eventManager.subscribe('ajaxLoaded', assignToggle);
18129  MK.utils.eventManager.subscribe('ajax-preview', assignToggle);
18130
18131  $(window).on('vc_reload', function(){
18132    assignToggle();
18133    MK.utils.eventManager.subscribe('ajaxLoaded', assignToggle);
18134    MK.utils.eventManager.subscribe('ajax-preview', assignToggle);
18135  });
18136
18137}(jQuery));
18138(function( $ ) {
18139    'use strict';
18140    if( MK.utils.isMobile() ) {
18141        $('.mk-animate-element').removeClass('mk-animate-element');
18142        return;
18143    }
18144    var init = function init() {
18145        var $rootLevelEls = $('.js-master-row, .widget');
18146        $rootLevelEls.each( spyViewport );
18147        $rootLevelEls.each( function rootLevelEl() {
18148            var $animateEl = $(this).find( '.mk-animate-element' );
18149            $animateEl.each( spyViewport );
18150            /**
18151             * Firefox has known issue where horizontal scrollbar will appear if an
18152             * element uses animation CSS. The solution should be set the element
18153             * position as fixed or overflow-x as hidden. Position fixed is not possible
18154             * to use because it's only cause other big problems. The best way is
18155             * set overflow-x as hidden in the page content container #theme-page.
18156             *
18157             * NOTE: The problem is spotted on Right To Left viewport only. So, it's
18158             *       limited to '.right-to-left' selector only for now to avoid other
18159             *       problems. Please extend the functionallity if it's happen in
18160             *       other viewport animation effect.
18161             */
18162            var browserName  = MK.utils.browser.name;
18163            if ( browserName === 'Firefox' ) {
18164                var $rightToLeft = $( this ).find( '.right-to-left' );
18165                if ( $rightToLeft.length > 0 ) {
18166                    $( '#theme-page' ).css( 'overflow-x', 'hidden' );
18167                }
18168            }
18169        });
18170    };
18171    var spyViewport = function spyViewport(i) {
18172        var self = this;
18173        MK.utils.scrollSpy( this, {
18174            position  : 'bottom',
18175            threshold : 200,
18176            after     : function() {
18177                animate.call(self, i);
18178            }
18179        });
18180    };
18181    var animate = function animate(i) {
18182        var $this = $(this);
18183        setTimeout(function() {
18184            $this.addClass( 'mk-in-viewport' );
18185        }, 100 * i);
18186    };
18187    $(window).on('load vc_reload', init);
18188}(jQuery));
18189
18190function product_loop_add_cart() {
18191    var $body = $('body');
18192    $body.on('click', '.add_to_cart_button', function() {
18193        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>';
18194        var $holder = $(this).parents('.product:eq(0)');
18195        var $i = $holder.find('.product-loading-icon');
18196        $holder.addClass('adding-to-cart').removeClass('added-to-cart');
18197        $i.html(icon);
18198    });
18199    $body.bind('added_to_cart', function() {
18200        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>';
18201        var $holder = $('.adding-to-cart');
18202        var $i = $holder.find('.product-loading-icon');
18203        $holder.removeClass('adding-to-cart').addClass('added-to-cart');
18204        $i.html(icon);
18205    });
18206}
18207(function($) {
18208	'use strict';
18209
18210	var $iframes = $('iframe');
18211
18212	$iframes.each(function() {
18213		var $iframe = $(this);
18214		var parent = $iframe.parent().get(0);
18215		var tagName = parent.tagName;
18216
18217		if(tagName === 'P') $iframe.wrap('<div class="mk-video-container"></div>');
18218	});
18219
18220}(jQuery));
18221(function($) {
18222    'use strict';
18223
18224    /**
18225     * Entry point of application. Runs all components
18226     */
18227    $( window ).on( 'load', function() {
18228        MK.core.initAll( document );
18229        MK.utils.scrollToURLHash();
18230        // TODO move preloader to components and manage it state from within
18231        setTimeout( function() { 
18232            MK.ui.preloader.hide(); // site wide 
18233            $('.mk-preloader').hide(); // components
18234            $('body').removeClass('loading');
18235        }, 150 ); 
18236    });
18237
18238    /**
18239     * VC frontend editor. Init all components.
18240     */
18241    $( window ).on( 'vc_reload', function() {
18242        setTimeout(function(){ 
18243            MK.core.initAll( document ); 
18244        }, 100);
18245    });
18246
18247    /**
18248     * Assign global click handlers
18249     */
18250    $( document ).on( 'click', '.js-smooth-scroll, .js-main-nav a', smoothScrollToAnchor);
18251    $( '.side_dashboard_menu a' ).on( 'click', smoothScrollToAnchor);
18252
18253    function smoothScrollToAnchor( evt ) {
18254        var anchor = MK.utils.detectAnchor( this );
18255        var $this = $(evt.currentTarget);
18256        var loc = window.location;
18257        var currentPage = loc.origin + loc.pathname;
18258        var href = $this.attr( 'href' );
18259        var linkSplit = (href) ? href.split( '#' ) : '';
18260        var hrefPage  = linkSplit[0] ? linkSplit[0] : ''; 
18261        var hrefHash  = linkSplit[1] ? linkSplit[1] : '';
18262
18263        if( anchor.length ) {
18264            if(hrefPage === currentPage || hrefPage === '') evt.preventDefault();
18265            MK.utils.scrollToAnchor( anchor );
18266
18267        } else if( $this.attr( 'href' ) === '#' ) {
18268            evt.preventDefault();
18269        }
18270    }
18271    
18272}(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.