PageSourceSearch

https://solfrids-quiltestove.no/assets/js/theme.js?m=1787069055

js solfrids-quiltestove.no collected 2026-09-27 10:26:36 UTC 200,427 bytes, 5,876 lines download raw bytes

1sincosJsonp([5],{
2
3/***/ 0:
4/***/ function(module, exports, __webpack_require__) {
5
6	"use strict";
7
8	__webpack_require__(217);
9
10	__webpack_require__(212);
11
12	__webpack_require__(219);
13
14	__webpack_require__(204);
15
16	__webpack_require__(206);
17
18	__webpack_require__(205);
19
20	__webpack_require__(215);
21
22	__webpack_require__(218);
23
24	__webpack_require__(211);
25
26	__webpack_require__(253);
27
28		__webpack_require__(199);
29
30/***/ },
31
32/***/ 199:
33/***/ function(module, exports, __webpack_require__) {
34
35	/* WEBPACK VAR INJECTION */(function($) {"use strict";
36
37	$(".accordion-trigger").click(function () {
38	    var panel = $(this).siblings('.accordion-panel')[0];
39	    if (panel.style.maxHeight) {
40	        panel.style.maxHeight = null;
41	    } else {
42	        panel.style.maxHeight = panel.scrollHeight + "px";
43	    }
44	});
45	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
46
47/***/ },
48
49/***/ 202:
50/***/ function(module, exports, __webpack_require__) {
51
52	/* WEBPACK VAR INJECTION */(function(jQuery) {'use strict';
53
54	/* Source: http://osvaldas.info/flexbox-based-responsive-equal-height-blocks-with-javascript-fallback */
55
56	;(function ($, window, document, undefined) {
57	    'use strict';
58
59	    var s = document.body || document.documentElement,
60	        s = s.style;
61
62	    var $list = $('.equal-height-columns'),
63	        $items = $list.find('.equal-height-column'),
64	        getMaxHeight = function getMaxHeight(items) {
65	        var maxHeight = 0,
66	            itemHeight = 0;
67
68	        items.each(function () {
69	            itemHeight = parseInt($(this).outerHeight());
70	            if (itemHeight > maxHeight) {
71	                maxHeight = itemHeight;
72	            }
73	        });
74
75	        return maxHeight;
76	    },
77	        setHeights = function setHeights() {
78	        $items.css('height', 'auto');
79
80	        var perRow = Math.floor($list.width() / $items.width());
81
82	        if (perRow === null || perRow < 2) {
83	            return true;
84	        }
85
86	        var maxHeight = null;
87	        var $row = null;
88
89	        for (var i = 0, j = $items.length; i < j; i += perRow) {
90	            $row = $items.slice(i, i + perRow);
91	            maxHeight = getMaxHeight($row);
92	            $row.css('height', maxHeight);
93	        }
94	    };
95
96	    setHeights();
97	    $(window).on('resize', setHeights);
98	    $list.find('img').on('load', setHeights);
99		})(jQuery, window, document);
100	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
101
102/***/ },
103
104/***/ 204:
105/***/ function(module, exports, __webpack_require__) {
106
107	/* WEBPACK VAR INJECTION */(function(jQuery) {'use strict';
108
109	/**
110	 * BxSlider v4.1.2 - Fully loaded, responsive content slider
111	 * http://bxslider.com
112	 *
113	 * Copyright 2014, Steven Wanderski - http://stevenwanderski.com - http://bxcreative.com
114	 * Written while drinking Belgian ales and listening to jazz
115	 *
116	 * Released under the MIT license - http://opensource.org/licenses/MIT
117	 */
118
119	;(function ($) {
120
121		var plugin = {};
122
123		var defaults = {
124
125			// GENERAL
126			mode: 'horizontal',
127			slideSelector: '',
128			infiniteLoop: true,
129			hideControlOnEnd: false,
130			speed: 500,
131			easing: null,
132			slideMargin: 0,
133			startSlide: 0,
134			randomStart: false,
135			captions: false,
136			ticker: false,
137			tickerHover: false,
138			adaptiveHeight: false,
139			adaptiveHeightSpeed: 500,
140			video: false,
141			useCSS: true,
142			preloadImages: 'visible',
143			responsive: true,
144			slideZIndex: 50,
145			wrapperClass: 'bx-wrapper',
146
147			// TOUCH
148			touchEnabled: true,
149			swipeThreshold: 50,
150			oneToOneTouch: true,
151			preventDefaultSwipeX: true,
152			preventDefaultSwipeY: false,
153
154			// PAGER
155			pager: true,
156			pagerType: 'full',
157			pagerShortSeparator: ' / ',
158			pagerSelector: null,
159			buildPager: null,
160			pagerCustom: null,
161
162			// CONTROLS
163			controls: true,
164			nextText: 'Next',
165			prevText: 'Prev',
166			nextSelector: null,
167			prevSelector: null,
168			autoControls: false,
169			startText: 'Start',
170			stopText: 'Stop',
171			autoControlsCombine: false,
172			autoControlsSelector: null,
173
174			// AUTO
175			auto: false,
176			pause: 4000,
177			autoStart: true,
178			autoDirection: 'next',
179			autoHover: false,
180			autoDelay: 0,
181			autoSlideForOnePage: false,
182
183			// CAROUSEL
184			minSlides: 1,
185			maxSlides: 1,
186			moveSlides: 0,
187			slideWidth: 0,
188
189			// CALLBACKS
190			onSliderLoad: function onSliderLoad() {},
191			onSlideBefore: function onSlideBefore() {},
192			onSlideAfter: function onSlideAfter() {},
193			onSlideNext: function onSlideNext() {},
194			onSlidePrev: function onSlidePrev() {},
195			onSliderResize: function onSliderResize() {}
196		};
197
198		$.fn.bxSlider = function (options) {
199
200			if (this.length == 0) return this;
201
202			// support mutltiple elements
203			if (this.length > 1) {
204				this.each(function () {
205					$(this).bxSlider(options);
206				});
207				return this;
208			}
209
210			// create a namespace to be used throughout the plugin
211			var slider = {};
212			// set a reference to our slider element
213			var el = this;
214			plugin.el = this;
215
216			/**
217	   * Makes slideshow responsive
218	   */
219			// first get the original window dimens (thanks alot IE)
220			var windowWidth = $(window).width();
221			var windowHeight = $(window).height();
222
223			// Strict mode does not allow implicit globals
224			var speed;
225
226			/**
227	   * ===================================================================================
228	   * = PRIVATE FUNCTIONS
229	   * ===================================================================================
230	   */
231
232			/**
233	   * Initializes namespace settings to be used throughout plugin
234	   */
235			var init = function init() {
236				// merge user-supplied options with the defaults
237				slider.settings = $.extend({}, defaults, options);
238				// parse slideWidth setting
239				slider.settings.slideWidth = parseInt(slider.settings.slideWidth);
240				// store the original children
241				slider.children = el.children(slider.settings.slideSelector);
242				// check if actual number of slides is less than minSlides / maxSlides
243				if (slider.children.length < slider.settings.minSlides) slider.settings.minSlides = slider.children.length;
244				if (slider.children.length < slider.settings.maxSlides) slider.settings.maxSlides = slider.children.length;
245				// if random start, set the startSlide setting to random number
246				if (slider.settings.randomStart) slider.settings.startSlide = Math.floor(Math.random() * slider.children.length);
247				// store active slide information
248				slider.active = { index: slider.settings.startSlide };
249				// store if the slider is in carousel mode (displaying / moving multiple slides)
250				slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1;
251				// if carousel, force preloadImages = 'all'
252				if (slider.carousel) slider.settings.preloadImages = 'all';
253				// calculate the min / max width thresholds based on min / max number of slides
254				// used to setup and update carousel slides dimensions
255				slider.minThreshold = slider.settings.minSlides * slider.settings.slideWidth + (slider.settings.minSlides - 1) * slider.settings.slideMargin;
256				slider.maxThreshold = slider.settings.maxSlides * slider.settings.slideWidth + (slider.settings.maxSlides - 1) * slider.settings.slideMargin;
257				// store the current state of the slider (if currently animating, working is true)
258				slider.working = false;
259				// initialize the controls object
260				slider.controls = {};
261				// initialize an auto interval
262				slider.interval = null;
263				// determine which property to use for transitions
264				slider.animProp = slider.settings.mode == 'vertical' ? 'top' : 'left';
265				// determine if hardware acceleration can be used
266				slider.usingCSS = slider.settings.useCSS && slider.settings.mode != 'fade' && function () {
267					// create our test div element
268					var div = document.createElement('div');
269					// css transition properties
270					var props = ['WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
271					// test for each property
272					for (var i in props) {
273						if (div.style[props[i]] !== undefined) {
274							slider.cssPrefix = props[i].replace('Perspective', '').toLowerCase();
275							slider.animProp = '-' + slider.cssPrefix + '-transform';
276							return true;
277						}
278					}
279					return false;
280				}();
281				// if vertical mode always make maxSlides and minSlides equal
282				if (slider.settings.mode == 'vertical') slider.settings.maxSlides = slider.settings.minSlides;
283				// save original style data
284				el.data("origStyle", el.attr("style"));
285				el.children(slider.settings.slideSelector).each(function () {
286					$(this).data("origStyle", $(this).attr("style"));
287				});
288				// perform all DOM / CSS modifications
289				setup();
290			};
291
292			/**
293	   * Performs all DOM and CSS modifications
294	   */
295			var setup = function setup() {
296				// wrap el in a wrapper
297				el.wrap('<div class="' + slider.settings.wrapperClass + '"><div class="bx-viewport"></div></div>');
298				// store a namspace reference to .bx-viewport
299				slider.viewport = el.parent();
300				// add a loading div to display while images are loading
301				slider.loader = $('<div class="bx-loading" />');
302				slider.viewport.prepend(slider.loader);
303				// set el to a massive width, to hold any needed slides
304				// also strip any margin and padding from el
305				el.css({
306					width: slider.settings.mode == 'horizontal' ? slider.children.length * 100 + 215 + '%' : 'auto',
307					position: 'relative'
308				});
309				// if using CSS, add the easing property
310				if (slider.usingCSS && slider.settings.easing) {
311					el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing);
312					// if not using CSS and no easing value was supplied, use the default JS animation easing (swing)
313				} else if (!slider.settings.easing) {
314						slider.settings.easing = 'swing';
315					}
316				var slidesShowing = getNumberSlidesShowing();
317				// make modifications to the viewport (.bx-viewport)
318				slider.viewport.css({
319					width: '100%',
320					overflow: 'hidden',
321					position: 'relative'
322				});
323				slider.viewport.parent().css({
324					maxWidth: getViewportMaxWidth()
325				});
326				// make modification to the wrapper (.bx-wrapper)
327				if (!slider.settings.pager) {
328					slider.viewport.parent().css({
329						margin: '0 auto 0px'
330					});
331				}
332				// apply css to all slider children
333				slider.children.css({
334					'float': slider.settings.mode == 'horizontal' ? 'left' : 'none',
335					listStyle: 'none',
336					position: 'relative'
337				});
338				// apply the calculated width after the float is applied to prevent scrollbar interference
339				slider.children.css('width', getSlideWidth());
340				// if slideMargin is supplied, add the css
341				if (slider.settings.mode == 'horizontal' && slider.settings.slideMargin > 0) slider.children.css('marginRight', slider.settings.slideMargin);
342				if (slider.settings.mode == 'vertical' && slider.settings.slideMargin > 0) slider.children.css('marginBottom', slider.settings.slideMargin);
343				// if "fade" mode, add positioning and z-index CSS
344				if (slider.settings.mode == 'fade') {
345					slider.children.css({
346						position: 'absolute',
347						zIndex: 0,
348						display: 'none'
349					});
350					// prepare the z-index on the showing element
351					slider.children.eq(slider.settings.startSlide).css({ zIndex: slider.settings.slideZIndex, display: 'block' });
352				}
353				// create an element to contain all slider controls (pager, start / stop, etc)
354				slider.controls.el = $('<div class="bx-controls" />');
355				// if captions are requested, add them
356				if (slider.settings.captions) appendCaptions();
357				// check if startSlide is last slide
358				slider.active.last = slider.settings.startSlide == getPagerQty() - 1;
359				// if video is true, set up the fitVids plugin
360				if (slider.settings.video) el.fitVids();
361				// set the default preload selector (visible)
362				var preloadSelector = slider.children.eq(slider.settings.startSlide);
363				if (slider.settings.preloadImages == "all") preloadSelector = slider.children;
364				// only check for control addition if not in "ticker" mode
365				if (!slider.settings.ticker) {
366					// if pager is requested, add it
367					if (slider.settings.pager) appendPager();
368					// if controls are requested, add them
369					if (slider.settings.controls) appendControls();
370					// if auto is true, and auto controls are requested, add them
371					if (slider.settings.auto && slider.settings.autoControls) appendControlsAuto();
372					// if any control option is requested, add the controls wrapper
373					if (slider.settings.controls || slider.settings.autoControls || slider.settings.pager) slider.viewport.after(slider.controls.el);
374					// if ticker mode, do not allow a pager
375				} else {
376						slider.settings.pager = false;
377					}
378				// preload all images, then perform final DOM / CSS modifications that depend on images being loaded
379				loadElements(preloadSelector, start);
380			};
381
382			var loadElements = function loadElements(selector, callback) {
383				var total = selector.find('img, iframe').length;
384				if (total == 0) {
385					callback();
386					return;
387				}
388				var count = 0;
389				selector.find('img, iframe').each(function () {
390					$(this).one('load', function () {
391						if (++count == total) callback();
392					}).each(function () {
393						if (this.complete) $(this).load();
394					});
395				});
396			};
397
398			/**
399	   * Start the slider
400	   */
401			var start = function start() {
402				// if infinite loop, prepare additional slides
403				if (slider.settings.infiniteLoop && slider.settings.mode != 'fade' && !slider.settings.ticker) {
404					var slice = slider.settings.mode == 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides;
405					var sliceAppend = slider.children.slice(0, slice).clone().addClass('bx-clone');
406					var slicePrepend = slider.children.slice(-slice).clone().addClass('bx-clone');
407					el.append(sliceAppend).prepend(slicePrepend);
408				}
409				// remove the loading DOM element
410				slider.loader.remove();
411				// set the left / top position of "el"
412				setSlidePosition();
413				// if "vertical" mode, always use adaptiveHeight to prevent odd behavior
414				if (slider.settings.mode == 'vertical') slider.settings.adaptiveHeight = true;
415				// set the viewport height
416				slider.viewport.height(getViewportHeight());
417				// make sure everything is positioned just right (same as a window resize)
418				el.redrawSlider();
419				// onSliderLoad callback
420				slider.settings.onSliderLoad(slider.active.index);
421				// slider has been fully initialized
422				slider.initialized = true;
423				// bind the resize call to the window
424				if (slider.settings.responsive) $(window).bind('resize', resizeWindow);
425				// if auto is true and has more than 1 page, start the show
426				if (slider.settings.auto && slider.settings.autoStart && (getPagerQty() > 1 || slider.settings.autoSlideForOnePage)) initAuto();
427				// if ticker is true, start the ticker
428				if (slider.settings.ticker) initTicker();
429				// if pager is requested, make the appropriate pager link active
430				if (slider.settings.pager) updatePagerActive(slider.settings.startSlide);
431				// check for any updates to the controls (like hideControlOnEnd updates)
432				if (slider.settings.controls) updateDirectionControls();
433				// if touchEnabled is true, setup the touch events
434				if (slider.settings.touchEnabled && !slider.settings.ticker) initTouch();
435			};
436
437			/**
438	   * Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value
439	   */
440			var getViewportHeight = function getViewportHeight() {
441				var height = 0;
442				// first determine which children (slides) should be used in our height calculation
443				var children = $();
444				// if mode is not "vertical" and adaptiveHeight is false, include all children
445				if (slider.settings.mode != 'vertical' && !slider.settings.adaptiveHeight) {
446					children = slider.children;
447				} else {
448					// if not carousel, return the single active child
449					if (!slider.carousel) {
450						children = slider.children.eq(slider.active.index);
451						// if carousel, return a slice of children
452					} else {
453							// get the individual slide index
454							var currentIndex = slider.settings.moveSlides == 1 ? slider.active.index : slider.active.index * getMoveBy();
455							// add the current slide to the children
456							children = slider.children.eq(currentIndex);
457							// cycle through the remaining "showing" slides
458							for (var i = 1; i <= slider.settings.maxSlides - 1; i++) {
459								// if looped back to the start
460								if (currentIndex + i >= slider.children.length) {
461									children = children.add(slider.children.eq(i - 1));
462								} else {
463									children = children.add(slider.children.eq(currentIndex + i
463));
464								}
465							}
466						}
467				}
468				// if "vertical" mode, calculate the sum of the heights of the children
469				if (slider.settings.mode == 'vertical') {
470					children.each(function (index) {
471						height += $(this).outerHeight();
472					});
473					// add user-supplied margins
474					if (slider.settings.slideMargin > 0) {
475						height += slider.settings.slideMargin * (slider.settings.minSlides - 1);
476					}
477					// if not "vertical" mode, calculate the max height of the children
478				} else {
479						height = Math.max.apply(Math, children.map(function () {
480							return $(this).outerHeight(false);
481						}).get());
482					}
483
484				if (slider.viewport.css('box-sizing') == 'border-box') {
485					height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')) + parseFloat(slider.viewport.css('border-top-width')) + parseFloat(slider.viewport.css('border-bottom-width'));
486				} else if (slider.viewport.css('box-sizing') == 'padding-box') {
487					height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom'));
488				}
489
490				return height;
491			};
492
493			/**
494	   * Returns the calculated width to be used for the outer wrapper / viewport
495	   */
496			var getViewportMaxWidth = function getViewportMaxWidth() {
497				var width = '100%';
498				if (slider.settings.slideWidth > 0) {
499					if (slider.settings.mode == 'horizontal') {
500						width = slider.settings.maxSlides * slider.settings.slideWidth + (slider.settings.maxSlides - 1) * slider.settings.slideMargin;
501					} else {
502						width = slider.settings.slideWidth;
503					}
504				}
505				return width;
506			};
507
508			/**
509	   * Returns the calculated width to be applied to each slide
510	   */
511			var getSlideWidth = function getSlideWidth() {
512				// start with any user-supplied slide width
513				var newElWidth = slider.settings.slideWidth;
514				// get the current viewport width
515				var wrapWidth = slider.viewport.width();
516				// if slide width was not supplied, or is larger than the viewport use the viewport width
517				if (slider.settings.slideWidth == 0 || slider.settings.slideWidth > wrapWidth && !slider.carousel || slider.settings.mode == 'vertical') {
518					newElWidth = wrapWidth;
519					// if carousel, use the thresholds to determine the width
520				} else if (slider.settings.maxSlides > 1 && slider.settings.mode == 'horizontal') {
521						if (wrapWidth > slider.maxThreshold) {
522							// newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.maxSlides - 1))) / slider.settings.maxSlides;
523						} else if (wrapWidth < slider.minThreshold) {
524								newElWidth = (wrapWidth - slider.settings.slideMargin * (slider.settings.minSlides - 1)) / slider.settings.minSlides;
525							}
526					}
527				return newElWidth;
528			};
529
530			/**
531	   * Returns the number of slides currently visible in the viewport (includes partially visible slides)
532	   */
533			var getNumberSlidesShowing = function getNumberSlidesShowing() {
534				var slidesShowing = 1;
535				if (slider.settings.mode == 'horizontal' && slider.settings.slideWidth > 0) {
536					// if viewport is smaller than minThreshold, return minSlides
537					if (slider.viewport.width() < slider.minThreshold) {
538						slidesShowing = slider.settings.minSlides;
539						// if viewport is larger than minThreshold, return maxSlides
540					} else if (slider.viewport.width() > slider.maxThreshold) {
541							slidesShowing = slider.settings.maxSlides;
542							// if viewport is between min / max thresholds, divide viewport width by first child width
543						} else {
544								var childWidth = slider.children.first().width() + slider.settings.slideMargin;
545								slidesShowing = Math.floor((slider.viewport.width() + slider.settings.slideMargin) / childWidth);
546							}
547					// if "vertical" mode, slides showing will always be minSlides
548				} else if (slider.settings.mode == 'vertical') {
549						slidesShowing = slider.settings.minSlides;
550					}
551				return slidesShowing;
552			};
553
554			/**
555	   * Returns the number of pages (one full viewport of slides is one "page")
556	   */
557			var getPagerQty = function getPagerQty() {
558				var pagerQty = 0;
559				// if moveSlides is specified by the user
560				if (slider.settings.moveSlides > 0) {
561					if (slider.settings.infiniteLoop) {
562						pagerQty = Math.ceil(slider.children.length / getMoveBy());
563					} else {
564						// use a while loop to determine pages
565						var breakPoint = 0;
566						var counter = 0;
567						// when breakpoint goes above children length, counter is the number of pages
568						while (breakPoint < slider.children.length) {
569							++pagerQty;
570							breakPoint = counter + getNumberSlidesShowing();
571							counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing();
572						}
573					}
574					// if moveSlides is 0 (auto) divide children length by sides showing, then round up
575				} else {
576						pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing());
577					}
578				return pagerQty;
579			};
580
581			/**
582	   * Returns the number of indivual slides by which to shift the slider
583	   */
584			var getMoveBy = function getMoveBy() {
585				// if moveSlides was set by the user and moveSlides is less than number of slides showing
586				if (slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()) {
587					return slider.settings.moveSlides;
588				}
589				// if moveSlides is 0 (auto)
590				return getNumberSlidesShowing();
591			};
592
593			/**
594	   * Sets the slider's (el) left or top position
595	   */
596			var setSlidePosition = function setSlidePosition() {
597				// if last slide, not infinite loop, and number of children is larger than specified maxSlides
598				if (slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop) {
599					if (slider.settings.mode == 'horizontal') {
600						// get the last child's position
601						var lastChild = slider.children.last();
602						var position = lastChild.position();
603						// set the left position
604						setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.outerWidth())), 'reset', 0);
605					} else if (slider.settings.mode == 'vertical') {
606						// get the last showing index's position
607						var lastShowingIndex = slider.children.length - slider.settings.minSlides;
608						var position = slider.children.eq(lastShowingIndex).position();
609						// set the top position
610						setPositionProperty(-position.top, 'reset', 0);
611					}
612					// if not last slide
613				} else {
614						// get the position of the first showing slide
615						var position = slider.children.eq(slider.active.index * getMoveBy()).position();
616						// check for last slide
617						if (slider.active.index == getPagerQty() - 1) slider.active.last = true;
618						// set the repective position
619						if (position != undefined) {
620							if (slider.settings.mode == 'horizontal') setPositionProperty(-position.left, 'reset', 0);else if (slider.settings.mode == 'vertical') setPositionProperty(-position.top, 'reset', 0);
621						}
622					}
623			};
624
625			/**
626	   * Sets the el's animating property position (which in turn will sometimes animate el).
627	   * If using CSS, sets the transform property. If not using CSS, sets the top / left property.
628	   *
629	   * @param value (int)
630	   *  - the animating property's value
631	   *
632	   * @param type (string) 'slider', 'reset', 'ticker'
633	   *  - the type of instance for which the function is being
634	   *
635	   * @param duration (int)
636	   *  - the amount of time (in ms) the transition should occupy
637	   *
638	   * @param params (array) optional
639	   *  - an optional parameter containing any variables that need to be passed in
640	   */
641			var setPositionProperty = function setPositionProperty(value, type, duration, params) {
642				// use CSS transform
643				if (slider.usingCSS) {
644					// determine the translate3d value
645					var propValue = slider.settings.mode == 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)';
646					// add the CSS transition-duration
647					el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's');
648					if (type == 'slide') {
649						// set the property value
650						el.css(slider.animProp, propValue);
651						// bind a callback method - executes when CSS transition completes
652						el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function () {
653							// unbind the callback
654							el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
655							updateAfterSlideTransition();
656						});
657					} else if (type == 'reset') {
658						el.css(slider.animProp, propValue);
659					} else if (type == 'ticker') {
660						// make the transition use 'linear'
661						el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear');
662						el.css(slider.animProp, propValue);
663						// bind a callback method - executes when CSS transition completes
664						el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function () {
665							// unbind the callback
666							el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
667							// reset the position
668							setPositionProperty(params['resetValue'], 'reset', 0);
669							// start the loop again
670							tickerLoop();
671						});
672					}
673					// use JS animate
674				} else {
675						var animateObj = {};
676						animateObj[slider.animProp] = value;
677						if (type == 'slide') {
678							el.animate(animateObj, duration, slider.settings.easing, function () {
679								updateAfterSlideTransition();
680							});
681						} else if (type == 'reset') {
682							el.css(slider.animProp, value);
683						} else if (type == 'ticker') {
684							el.animate(animateObj, speed, 'linear', function () {
685								setPositionProperty(params['resetValue'], 'reset', 0);
686								// run the recursive loop after animation
687								tickerLoop();
688							});
689						}
690					}
691			};
692
693			/**
694	   * Populates the pager with proper amount of pages
695	   */
696			var populatePager = function populatePager() {
697				var pagerHtml = '';
698				var pagerQty = getPagerQty();
699				// loop through each pager item
700				for (var i = 0; i < pagerQty; i++) {
701					var linkContent = '';
702					// if a buildPager function is supplied, use it to get pager link value, else use index + 1
703					if (slider.settings.buildPager && $.isFunction(slider.settings.buildPager)) {
704						linkContent = slider.settings.buildPager(i);
705						slider.pagerEl.addClass('bx-custom-pager');
706					} else {
707						linkContent = i + 1;
708						slider.pagerEl.addClass('bx-default-pager');
709					}
710					// var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1;
711					// add the markup to the string
712					pagerHtml += '<div class="bx-pager-item">
712<a href="" data-slide-index="' + i + '" class="bx-pager-link">' + linkContent + '</a></div>';
713				}
714				// populate the pager element with pager links
715				slider.pagerEl.html(pagerHtml);
716			};
717
718			/**
719	   * Appends the pager to the controls element
720	   */
721			var appendPager = function appendPager() {
722				if (!slider.settings.pagerCustom) {
723					// create the pager DOM element
724					slider.pagerEl = $('<div class="bx-pager" />');
725					// if a pager selector was supplied, populate it with the pager
726					if (slider.settings.pagerSelector) {
727						$(slider.settings.pagerSelector).html(slider.pagerEl);
728						// if no pager selector was supplied, add it after the wrapper
729					} else {
730							slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl);
731						}
732					// populate the pager
733					populatePager();
734				} else {
735					slider.pagerEl = $(slider.settings.pagerCustom);
736				}
737				// assign the pager click binding
738				slider.pagerEl.on('click', 'a', clickPagerBind);
739			};
740
741			/**
742	   * Appends prev / next controls to the controls element
743	   */
744			var appendControls = function appendControls() {
745				slider.controls.next = $('<a class="bx-next" href="">' + slider.settings.nextText + '</a>');
746				slider.controls.prev = $('<a class="bx-prev" href="">' + slider.settings.prevText + '</a>');
747				// bind click actions to the controls
748				slider.controls.next.bind('click', clickNextBind);
749				slider.controls.prev.bind('click', clickPrevBind);
750				// if nextSlector was supplied, populate it
751				if (slider.settings.nextSelector) {
752					$(slider.settings.nextSelector).append(slider.controls.next);
753				}
754				// if prevSlector was supplied, populate it
755				if (slider.settings.prevSelector) {
756					$(slider.settings.prevSelector).append(slider.controls.prev);
757				}
758				// if no custom selectors were supplied
759				if (!slider.settings.nextSelector && !slider.settings.prevSelector) {
760					// add the controls to the DOM
761					slider.controls.directionEl = $('<div class="bx-controls-direction" />');
762					// add the control elements to the directionEl
763					slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next);
764					// slider.viewport.append(slider.controls.directionEl);
765					slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl);
766				}
767			};
768
769			/**
770	   * Appends start / stop auto controls to the controls element
771	   */
772			var appendControlsAuto = function appendControlsAuto() {
773				slider.controls.start = $('<div class="bx-controls-auto-item"><a class="bx-start" href="">' + slider.settings.startText + '</a></div>');
774				slider.controls.stop = $('<div class="bx-controls-auto-item"><a class="bx-stop" href="">' + slider.settings.stopText + '</a></div>');
775				// add the controls to the DOM
776				slider.controls.autoEl = $('<div class="bx-controls-auto" />');
777				// bind click actions to the controls
778				slider.controls.autoEl.on('click', '.bx-start', clickStartBind);
779				slider.controls.autoEl.on('click', '.bx-stop', clickStopBind);
780				// if autoControlsCombine, insert only the "start" control
781				if (slider.settings.autoControlsCombine) {
782					slider.controls.autoEl.append(slider.controls.start);
783					// if autoControlsCombine is false, insert both controls
784				} else {
785						slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop);
786					}
787				// if auto controls selector was supplied, populate it with the controls
788				if (slider.settings.autoControlsSelector) {
789					$(slider.settings.autoControlsSelector).html(slider.controls.autoEl);
790					// if auto controls selector was not supplied, add it after the wrapper
791				} else {
792						slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl);
793					}
794				// update the auto controls
795				updateAutoControls(slider.settings.autoStart ? 'stop' : 'start');
796			};
797
798			/**
799	   * Appends image captions to the DOM
800	   */
801			var appendCaptions = function appendCaptions() {
802				// cycle through each child
803				slider.children.each(function (index) {
804					// get the image title attribute
805					var title = $(this).find('img:first').attr('title');
806					// append the caption
807					if (title != undefined && ('' + title).length) {
808						$(this).append('<div class="bx-caption"><span>' + title + '</span></div>');
809					}
810				});
811			};
812
813			/**
814	   * Click next binding
815	   *
816	   * @param e (event)
817	   *  - DOM event object
818	   */
819			var clickNextBind = function clickNextBind(e) {
820				// if auto show is running, stop it
821				if (slider.settings.auto) el.stopAuto();
822				el.goToNextSlide();
823				e.preventDefault();
824			};
825
826			/**
827	   * Click prev binding
828	   *
829	   * @param e (event)
830	   *  - DOM event object
831	   */
832			var clickPrevBind = function clickPrevBind(e) {
833				// if auto show is running, stop it
834				if (slider.settings.auto) el.stopAuto();
835				el.goToPrevSlide();
836				e.preventDefault();
837			};
838
839			/**
840	   * Click start binding
841	   *
842	   * @param e (event)
843	   *  - DOM event object
844	   */
845			var clickStartBind = function clickStartBind(e) {
846				el.startAuto();
847				e.preventDefault();
848			};
849
850			/**
851	   * Click stop binding
852	   *
853	   * @param e (event)
854	   *  - DOM event object
855	   */
856			var clickStopBind = function clickStopBind(e) {
857				el.stopAuto();
858				e.preventDefault();
859			};
860
861			/**
862	   * Click pager binding
863	   *
864	   * @param e (event)
865	   *  - DOM event object
866	   */
867			var clickPagerBind = function clickPagerBind(e) {
868				// if auto show is running, stop it
869				if (slider.settings.auto) el.stopAuto();
870				var pagerLink = $(e.currentTarget);
871				if (pagerLink.attr('data-slide-index') !== undefined) {
872					var pagerIndex = parseInt(pagerLink.attr('data-slide-index'));
873					// if clicked pager link is not active, continue with the goToSlide call
874					if (pagerIndex != slider.active.index) el.goToSlide(pagerIndex);
875					e.preventDefault();
876				}
877			};
878
879			/**
880	   * Updates the pager links with an active class
881	   *
882	   * @param slideIndex (int)
883	   *  - index of slide to make active
884	   */
885			var updatePagerActive = function updatePagerActive(slideIndex) {
886				// if "short" pager type
887				var len = slider.children.length; // nb of children
888				if (slider.settings.pagerType == 'short') {
889					if (slider.settings.maxSlides > 1) {
890						len = Math.ceil(slider.children.length / slider.settings.maxSlides);
891					}
892					slider.pagerEl.html(slideIndex + 1 + slider.settings.pagerShortSeparator + len);
893					return;
894				}
895				// remove all pager active classes
896				slider.pagerEl.find('a').removeClass('active');
897				// apply the active class for all pagers
898				slider.pagerEl.each(function (i, el) {
899					$(el).find('a').eq(slideIndex).addClass('active');
900				});
901			};
902
903			/**
904	   * Performs needed actions after a slide transition
905	   */
906			var updateAfterSlideTransition = function updateAfterSlideTransition() {
907				// if infinte loop is true
908				if (slider.settings.infiniteLoop) {
909					var position = '';
910					// first slide
911					if (slider.active.index == 0) {
912						// set the new position
913						position = slider.children.eq(0).position();
914						// carousel, last slide
915					} else if (slider.active.index == getPagerQty() - 1 && slider.carousel) {
916							position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position();
917							// last slide
918						} else if (slider.active.index == slider.children.length - 1) {
919								position = slider.children.eq(slider.children.length - 1).position();
920							}
921					if (position) {
922						if (slider.settings.mode == 'horizontal') {
923							setPositionProperty(-position.left, 'reset', 0);
924						} else if (slider.settings.mode == 'vertical') {
925							setPositionProperty(-position.top, 'reset', 0);
926						}
927					}
928				}
929				// declare that the transition is complete
930				slider.working = false;
931				// onSlideAfter callback
932				slider.settings.onSlideAfter(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
933			};
934
935			/**
936	   * Updates the auto controls state (either active, or combined switch)
937	   *
938	   * @param state (string) "start", "stop"
939	   *  - the new state of the auto show
940	   */
941			var updateAutoControls = function updateAutoControls(state) {
942				// if autoControlsCombine is true, replace the current control with the new state
943				if (slider.settings.autoControlsCombine) {
944					slider.controls.autoEl.html(slider.controls[state]);
945					// if autoControlsCombine is false, apply the "active" class to the appropriate control
946				} else {
947						slider.controls.autoEl.find('a').removeClass('active');
948						slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active');
949					}
950			};
951
952			/**
953	   * Updates the direction controls (checks if either should be hidden)
954	   */
955			var updateDirectionControls = function updateDirectionControls() {
956				if (getPagerQty() == 1) {
957					slider.controls.prev.addClass('disabled');
958					slider.controls.next.addClass('disabled');
959				} else if (!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd) {
960					// if first slide
961					if (slider.active.index == 0) {
962						slider.controls.prev.addClass('disabled');
963						slider.controls.next.removeClass('disabled');
964						// if last slide
965					} else if (slider.active.index == getPagerQty() - 1) {
966							slider.controls.next.addClass('disabled');
967							slider.controls.prev.removeClass('disabled');
968							// if any slide in the middle
969						} else {
970								slider.controls.prev.removeClass('disabled');
971								slider.controls.next.removeClass('disabled');
972							}
973				}
974			};
975
976			/**
977	   * Initialzes the auto process
978	   */
979			var initAuto = function initAuto() {
980				// if autoDelay was supplied, launch the auto show using a setTimeout() call
981				if (slider.settings.autoDelay > 0) {
982					var timeout = setTimeout(el.startAuto, slider.settings.autoDelay);
983					// if autoDelay was not supplied, start the auto show normally
984				} else {
985						el.startAuto();
986					}
987				// if autoHover is requested
988				if (slider.settings.autoHover) {
989					// on el hover
990					el.hover(function () {
991						// if the auto show is currently playing (has an active interval)
992						if (slider.interval) {
993							// stop the auto show and pass true agument which will prevent control update
994							el.stopAuto(true);
995							// create a new autoPaused value which will be used by the relative "mouseout" event
996							slider.autoPaused = true;
997						}
998					}, function () {
999						// if the autoPaused value was created be the prior "mouseover" event
1000						if (slider.autoPaused) {
1001							// start the auto show and pass true agument which will prevent control update
1002							el.startAuto(true);
1003							// reset the autoPaused value
1004							slider.autoPaused = null;
1005						}
1006					});
1007				}
1008			};
1009
1010			/**
1011	   * Initialzes the ticker process
1012	   */
1013			var initTicker = function initTicker() {
1014				var startPosition = 0;
1015				// if autoDirection is "next", append a clone of the entire slider
1016				if (slider.settings.autoDirection == 'next') {
1017					el.append(slider.children.clone().addClass('bx-clone'));
1018					// if autoDirection is "prev", prepend a clone of the entire slider, and set the left position
1019				} else {
1020						el.prepend(slider.children.clone().addClass('bx-clone'));
1021						var position = slider.children.first().position();
1022						startPosition = slider.settings.mode == 'horizontal' ? -position.left : -position.top;
1023					}
1024				setPositionProperty(startPosition, 'reset', 0);
1025				// do not allow controls in ticker mode
1026				slider.settings.pager = false;
1027				slider.settings.controls = false;
1028				slider.settings.autoControls = false;
1029				// if autoHover is requested
1030				if (slider.settings.tickerHover && !slider.usingCSS) {
1031					// on el hover
1032					slider.viewport.hover(function () {
1033						el.stop();
1034					}, function () {
1035						// calculate the total width of children (used to calculate the speed ratio)
1036						var totalDimens = 0;
1037						slider.children.each(function (index) {
1038							totalDimens += slider.settings.mode == 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);
1039						});
1040						// calculate the speed ratio (used to determine the new speed to finish the paused animation)
1041						var ratio = slider.settings.speed / totalDimens;
1042						// determine which property to use
1043						var property = slider.settings.mode == 'horizontal' ? 'left' : 'top';
1044						// calculate the new speed
1045						var newSpeed = ratio * (totalDimens - Math.abs(parseInt(el.css(property))));
1046						tickerLoop(newSpeed);
1047					});
1048				}
1049				// start the ticker loop
1050				tickerLoop();
1051			};
1052
1053			/**
1054	   * Runs a continuous loop, news ticker-style
1055	   */
1056			var tickerLoop = function tickerLoop(resumeSpeed) {
1057				speed = resumeSpeed ? resumeSpeed : slider.settings.speed;
1058				var position = { left: 0, top: 0 };
1059				var reset = { left: 0, top: 0 };
1060				// if "next" animate left position to last child, then reset left to 0
1061				if (slider.settings.autoDirection == 'next') {
1062					position = el.find('.bx-clone').first().position();
1063					// if "prev" animate left position to 0, then reset left to first non-clone child
1064				} else {
1065						reset = slider.children.first().position();
1066					}
1067				var animateProperty = slider.settings.mode == 'horizontal' ? -position.left : -position.top;
1068				var resetValue = slider.settings.mode == 'horizontal' ? -reset.left : -reset.top;
1069				var params = { resetValue: resetValue };
1070				setPositionProperty(animateProperty, 'ticker', speed, params);
1071			};
1072
1073			/**
1074	   * Initializes touch events
1075	   */
1076			var initTouch = function initTouch() {
1077				// initialize object to contain all touch values
1078				slider.touch = {
1079					start: { x: 0, y: 0 },
1080					end: { x: 0, y: 0 }
1081				};
1082				slider.viewport.bind('touchstart', onTouchStart);
1083			};
1084
1085			/**
1086	   * Event handler for "touchstart"
1087	   *
1088	   * @param e (event)
1089	   *  - DOM event object
1090	   */
1091			var onTouchStart = function onTouchStart(e) {
1092				if (slider.working) {
1093					e.preventDefault();
1094				} else {
1095					// record the original position when touch starts
1096					slider.touch.originalPos = el.position();
1097					var orig = e.originalEvent;
1098					// record the starting touch x, y coordinates
1099					slider.touch.start.x = orig.changedTouches[0].pageX;
1100					slider.touch.start.y = orig.changedTouches[0].pageY;
1101					// bind a "touchmove" event to the viewport
1102					slider.viewport.bind('touchmove', onTouchMove);
1103					// bind a "touchend" event to the viewport
1104					slider.viewport.bind('touchend', onTouchEnd);
1105				}
1106			};
1107
1108			/**
1109	   * Event handler for "touchmove"
1110	   *
1111	   * @param e (event)
1112	   *  - DOM event object
1113	   */
1114			var onTouchMove = function onTouchMove(e) {
1115				var orig = e.originalEvent;
1116				// if scrolling on y axis, do not prevent default
1117				var xMovement = Math.abs(orig.changedTouches[0].pageX - slider.touch.start.x);
1118				var yMovement = Math.abs(orig.changedTouches[0].pageY - slider.touch.start.y);
1119				// x axis swipe
1120				if (xMovement * 3 > yMovement && slider.settings.preventDefaultSwipeX) {
1121					e.preventDefault();
1122					// y axis swipe
1123				} else if (yMovement * 3 > xMovement && slider.settings.preventDefaultSwipeY) {
1124						e.preventDefault();
1125					}
1126				if (slider.settings.mode != 'fade' && slider.settings.oneToOneTouch) {
1127					var value = 0;
1128					// if horizontal, drag along x axis
1129					if (slider.settings.mode == 'horizontal') {
1130						var change = orig.changedTouches[0].pageX - slider.touch.start.x;
1131						value = slider.touch.originalPos.left + change;
1132						// if vertical, drag along y axis
1133					} else {
1134							var change = orig.changedTouches[0].pageY - slider.touch.start.y;
1135							value = slider.touch.originalPos.top + change;
1136						}
1137					setPositionProperty(value, 'reset', 0);
1138				}
1139			};
1140
1141			/**
1142	   * Event handler for "touchend"
1143	   *
1144	   * @param e (event)
1145	   *  - DOM event object
1146	   */
1147			var onTouchEnd = function onTouchEnd(e) {
1148				slider.viewport.unbind('touchmove', onTouchMove);
1149				var orig = e.originalEvent;
1150				var value = 0;
1151				// record end x, y positions
1152				slider.touch.end.x = orig.changedTouches[0].pageX;
1153				slider.touch.end.y = orig.changedTouches[0].pageY;
1154				// if fade mode, check if absolute x distance clears the threshold
1155				if (slider.settings.mode == 'fade') {
1156					var distance = Math.abs(slider.touch.start.x - slider.touch.end.x);
1157					if (distance >= slider.settings.swipeThreshold) {
1158						slider.touch.start.x > slider.touch.end.x ? el.goToNextSlide() : el.goToPrevSlide();
1159						el.stopAuto();
1160					}
1161					// not fade mode
1162				} else {
1163						var distance = 0;
1164						// calculate distance and el's animate property
1165						if (slider.settings.mode == 'horizontal') {
1166							distance = slider.touch.end.x - slider.touch.start.x;
1167							value = slider.touch.originalPos.left;
1168						} else {
1169							distance = slider.touch.end.y - slider.touch.start.y;
1170							value = slider.touch.originalPos.top;
1171						}
1172						// if not infinite loop and first / last slide, do not attempt a slide transition
1173						if (!slider.settings.infiniteLoop && (slider.active.index == 0 && distance > 0 || slider.active.last && distance < 0)) {
1174							setPositionProperty(value, 'reset', 200);
1175						} else {
1176							// check if distance clears threshold
1177							if (Math.abs(distance) >= slider.settings.swipeThreshold) {
1178								distance < 0 ? el.goToNextSlide() : el.goToPrevSlide();
1179								el.stopAuto();
1180							} else {
1181								// el.animate(property, 200);
1182								setPositionProperty(value, 'reset', 200);
1183							}
1184						}
1185					}
1186				slider.viewport.unbind('touchend', onTouchEnd);
1187			};
1188
1189			/**
1190	   * Window resize event callback
1191	   */
1192			var resizeWindow = function resizeWindow(e) {
1193				// don't do anything if slider isn't initialized.
1194				if (!slider.initialized) return;
1195				// get the new window dimens (again, thank you IE)
1196				var windowWidthNew = $(window).width();
1197				var windowHeightNew = $(window).height();
1198				// make sure that it is a true window resize
1199				// *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements
1200				// are resized. Can you just die already?*
1201				if (windowWidth != windowWidthNew || windowHeight != windowHeightNew) {
1202					// set the new window dimens
1203					windowWidth = windowWidthNew;
1204					windowHeight = windowHeightNew;
1205					// update all dynamic elements
1206					el.redrawSlider();
1207					// Call user resize handler
1208					slider.settings.onSliderResize.call(el, slider.active.index);
1209				}
1210			};
1211
1212			/**
1213	   * ===================================================================================
1214	   * = PUBLIC FUNCTIONS
1215	   * ===================================================================================
1216	   */
1217
1218			/**
1219	   * Performs slide transition to the specified slide
1220	   *
1221	   * @param slideIndex (int)
1222	   *  - the destination slide's index (zero-based)
1223	   *
1224	   * @param direction (string)
1225	   *  - INTERNAL USE ONLY - the direction of travel ("prev" / "next")
1226	   */
1227			el.goToSlide = function (slideIndex, direction) {
1228				// if plugin is currently in motion, ignore request
1229				if (slider.working || slider.active.index == slideIndex) return;
1230				// declare that plugin is in motion
1231				slider.working = true;
1232				// store the old index
1233				slider.oldIndex = slider.active.index;
1234				// if slideIndex is less than zero, set active index to last child (this happens during infinite loop)
1235				if (slideIndex < 0) {
1236					slider.active.index = getPagerQty() - 1;
1237					// if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop)
1238				} else if (slideIndex >= getPagerQty()) {
1239						slider.active.index = 0;
1240						// set active index to requested slide
1241					} else {
1242							slider.active.index = slideIndex;
1243						}
1244				// onSlideBefore, onSlideNext, onSlidePrev callbacks
1245				slider.settings.onSlideBefore(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
1246				if (direction == 'next') {
1247					slider.settings.onSlideNext(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
1248				} else if (direction == 'prev') {
1249					slider.settings.onSlidePrev(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
1250				}
1251				// check if last slide
1252				slider.active.last = slider.active.index >= getPagerQty() - 1;
1253				// update the pager with active class
1254				if (slider.settings.pager) updatePagerActive(slider.active.index);
1255				// // check for direction control update
1256				if (slider.settings.controls) updateDirectionControls();
1257				// if slider is set to mode: "fade"
1258				if (slider.settings.mode == 'fade') {
1259					// if adaptiveHeight is true and next height is different from current height, animate to the new height
1260					if (slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHe
1260ight()) {
1261						slider.viewport.animate({ height: getViewportHeight() }, slider.settings.adaptiveHeightSpeed);
1262					}
1263					// fade out the visible child and reset its z-index value
1264					slider.children.filter(':visible').fadeOut(slider.settings.speed).css({ zIndex: 0 });
1265					// fade in the newly requested slide
1266					slider.children.eq(slider.active.index).css('zIndex', slider.settings.slideZIndex + 1).fadeIn(slider.settings.speed, function () {
1267						$(this).css('zIndex', slider.settings.slideZIndex);
1268						updateAfterSlideTransition();
1269					});
1270					// slider mode is not "fade"
1271				} else {
1272						// if adaptiveHeight is true and next height is different from current height, animate to the new height
1273						if (slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()) {
1274							slider.viewport.animate({ height: getViewportHeight() }, slider.settings.adaptiveHeightSpeed);
1275						}
1276						var moveBy = 0;
1277						var position = { left: 0, top: 0 };
1278						// if carousel and not infinite loop
1279						if (!slider.settings.infiniteLoop && slider.carousel && slider.active.last) {
1280							if (slider.settings.mode == 'horizontal') {
1281								// get the last child position
1282								var lastChild = slider.children.eq(slider.children.length - 1);
1283								position = lastChild.position();
1284								// calculate the position of the last slide
1285								moveBy = slider.viewport.width() - lastChild.outerWidth();
1286							} else {
1287								// get last showing index position
1288								var lastShowingIndex = slider.children.length - slider.settings.minSlides;
1289								position = slider.children.eq(lastShowingIndex).position();
1290							}
1291							// horizontal carousel, going previous while on first slide (infiniteLoop mode)
1292						} else if (slider.carousel && slider.active.last && direction == 'prev') {
1293								// get the last child position
1294								var eq = slider.settings.moveSlides == 1 ? slider.settings.maxSlides - getMoveBy() : (getPagerQty() - 1) * getMoveBy() - (slider.children.length - slider.settings.maxSlides);
1295								var lastChild = el.children('.bx-clone').eq(eq);
1296								position = lastChild.position();
1297								// if infinite loop and "Next" is clicked on the last slide
1298							} else if (direction == 'next' && slider.active.index == 0) {
1299									// get the last clone position
1300									position = el.find('> .bx-clone').eq(slider.settings.maxSlides).position();
1301									slider.active.last = false;
1302									// normal non-zero requests
1303								} else if (slideIndex >= 0) {
1304										var requestEl = slideIndex * getMoveBy();
1305										position = slider.children.eq(requestEl).position();
1306									}
1307
1308						/* If the position doesn't exist
1309	      * (e.g. if you destroy the slider on a next click),
1310	      * it doesn't throw an error.
1311	      */
1312						if ("undefined" !== typeof position) {
1313							var value = slider.settings.mode == 'horizontal' ? -(position.left - moveBy) : -position.top;
1314							// plugin values to be animated
1315							setPositionProperty(value, 'slide', slider.settings.speed);
1316						}
1317					}
1318			};
1319
1320			/**
1321	   * Transitions to the next slide in the show
1322	   */
1323			el.goToNextSlide = function () {
1324				// if infiniteLoop is false and last page is showing, disregard call
1325				if (!slider.settings.infiniteLoop && slider.active.last) return;
1326				var pagerIndex = parseInt(slider.active.index) + 1;
1327				el.goToSlide(pagerIndex, 'next');
1328			};
1329
1330			/**
1331	   * Transitions to the prev slide in the show
1332	   */
1333			el.goToPrevSlide = function () {
1334				// if infiniteLoop is false and last page is showing, disregard call
1335				if (!slider.settings.infiniteLoop && slider.active.index == 0) return;
1336				var pagerIndex = parseInt(slider.active.index) - 1;
1337				el.goToSlide(pagerIndex, 'prev');
1338			};
1339
1340			/**
1341	   * Starts the auto show
1342	   *
1343	   * @param preventControlUpdate (boolean)
1344	   *  - if true, auto controls state will not be updated
1345	   */
1346			el.startAuto = function (preventControlUpdate) {
1347				// if an interval already exists, disregard call
1348				if (slider.interval) return;
1349				// create an interval
1350				slider.interval = setInterval(function () {
1351					slider.settings.autoDirection == 'next' ? el.goToNextSlide() : el.goToPrevSlide();
1352				}, slider.settings.pause);
1353				// if auto controls are displayed and preventControlUpdate is not true
1354				if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('stop');
1355			};
1356
1357			/**
1358	   * Stops the auto show
1359	   *
1360	   * @param preventControlUpdate (boolean)
1361	   *  - if true, auto controls state will not be updated
1362	   */
1363			el.stopAuto = function (preventControlUpdate) {
1364				// if no interval exists, disregard call
1365				if (!slider.interval) return;
1366				// clear the interval
1367				clearInterval(slider.interval);
1368				slider.interval = null;
1369				// if auto controls are displayed and preventControlUpdate is not true
1370				if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('start');
1371			};
1372
1373			/**
1374	   * Returns current slide index (zero-based)
1375	   */
1376			el.getCurrentSlide = function () {
1377				return slider.active.index;
1378			};
1379
1380			/**
1381	   * Returns current slide element
1382	   */
1383			el.getCurrentSlideElement = function () {
1384				return slider.children.eq(slider.active.index);
1385			};
1386
1387			/**
1388	   * Returns number of slides in show
1389	   */
1390			el.getSlideCount = function () {
1391				return slider.children.length;
1392			};
1393
1394			/**
1395	   * Update all dynamic slider elements
1396	   */
1397			el.redrawSlider = function () {
1398				// resize all children in ratio to new screen size
1399				slider.children.add(el.find('.bx-clone')).width(getSlideWidth());
1400				// adjust the height
1401				slider.viewport.css('height', getViewportHeight());
1402				// update the slide position
1403				if (!slider.settings.ticker) setSlidePosition();
1404				// if active.last was true before the screen resize, we want
1405				// to keep it last no matter what screen size we end on
1406				if (slider.active.last) slider.active.index = getPagerQty() - 1;
1407				// if the active index (page) no longer exists due to the resize, simply set the index as last
1408				if (slider.active.index >= getPagerQty()) slider.active.last = true;
1409				// if a pager is being displayed and a custom pager is not being used, update it
1410				if (slider.settings.pager && !slider.settings.pagerCustom) {
1411					populatePager();
1412					updatePagerActive(slider.active.index);
1413				}
1414			};
1415
1416			/**
1417	   * Destroy the current instance of the slider (revert everything back to original state)
1418	   */
1419			el.destroySlider = function () {
1420				// don't do anything if slider has already been destroyed
1421				if (!slider.initialized) return;
1422				slider.initialized = false;
1423				$('.bx-clone', this).remove();
1424				slider.children.each(function () {
1425					$(this).data("origStyle") != undefined ? $(this).attr("style", $(this).data("origStyle")) : $(this).removeAttr('style');
1426				});
1427				$(this).data("origStyle") != undefined ? this.attr("style", $(this).data("origStyle")) : $(this).removeAttr('style');
1428				$(this).unwrap().unwrap();
1429				if (slider.controls.el) slider.controls.el.remove();
1430				if (slider.controls.next) slider.controls.next.remove();
1431				if (slider.controls.prev) slider.controls.prev.remove();
1432				if (slider.pagerEl && slider.settings.controls) slider.pagerEl.remove();
1433				$('.bx-caption', this).remove();
1434				if (slider.controls.autoEl) slider.controls.autoEl.remove();
1435				clearInterval(slider.interval);
1436				if (slider.settings.responsive) $(window).unbind('resize', resizeWindow);
1437			};
1438
1439			/**
1440	   * Reload the slider (revert all DOM changes, and re-initialize)
1441	   */
1442			el.reloadSlider = function (settings) {
1443				if (settings != undefined) options = settings;
1444				el.destroySlider();
1445				init();
1446			};
1447
1448			init();
1449
1450			// returns the current jQuery object
1451			return this;
1452		};
1453		})(jQuery);
1454	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
1455
1456/***/ },
1457
1458/***/ 205:
1459/***/ function(module, exports, __webpack_require__) {
1460
1461	/* WEBPACK VAR INJECTION */(function(jQuery) {'use strict';
1462
1463	(function ($) {
1464	    $.cart = function (element, options) {
1465	        var cart = this;
1466	        var $cart_btn = $(element);
1467
1468	        cart.settings = {};
1469
1470	        // Merge options with defaults
1471	        cart.settings = $.extend({
1472	            buyButtonSelector: '.js-product__buy-button',
1473	            buyBundleButtonSelector: '.js-bundle__buy-button',
1474	            cartHighlightClass: 'cart-button--highlighted',
1475	            productFormSelector: '.product__form',
1476	            quantitySelector: '.cart-button__quantity',
1477	            sumSelector: '.cart-button__sum'
1478	        }, options);
1479
1480	        // Init the cart plugin
1481	        var init = function init() {
1482	            cart.quantityContainer = $(cart.settings.quantitySelector);
1483	            cart.sumContainer = $(cart.settings.sumSelector);
1484	            cart.messageContainer = $(cart.settings.messageBoxSelector);
1485	            if ($cart_btn.length === 1) {
1486	                setupBuyButtons();
1487	            }
1488	        };
1489
1490	        // Get data for ajax submission
1491	        var getProductData = function getProductData(productId, caller) {
1492	            // If quickbuy, we need to compose product data
1493	            var productData = '';
1494	            var productForm = $(cart.settings.productFormSelector);
1495
1496	            if (productForm.length === 1 && productForm.children('input[name="id"]').val() === productId) {
1497	                // We are on the product page
1498	                productData = productForm.serialize();
1499	            } else if (productForm.hasClass('bundle__form')) {
1500	                // we're on a bundle form, may contain multiple products with attributes
1501	                productData = $(caller).serialize();
1502	            } else {
1503	                // we're on a "quick buy" page, like a category or the frontpage
1504	                productData = getProductQuickbuyData(productId);
1505	            }
1506
1507	            return productData;
1508	        };
1509
1510	        // Update the shopping cart
1511	        var update = function update(newQuantity, newSum) {
1512	            if (newQuantity !== getQuantity()) {
1513	                highlightCart();
1514	            }
1515	            cart.setQuantity(newQuantity);
1516	            cart.setSum(newSum);
1517	        };
1518
1519	        var setupBuyButtons = function setupBuyButtons() {
1520	            // Buy button event
1521	            var buyButtons = $(cart.settings.buyButtonSelector);
1522	            var buyBundleButtons = $(cart.settings.buyBundleButtonSelector);
1523
1524	            buyButtons.off('click').click(function (event) {
1525	                event.preventDefault();
1526	                var form = $(this).closest('form')[0];
1527	                var productId = $(this).attr('data-product-id');
1528	                $.post('/handlevogn/leggtil/ajax', getProductData(productId, form), function (data) {
1529	                    update(data.contents.length, data.total_pricified.total);
1530	                    if (data.msg !== '' && data.msg !== undefined) {
1531	                        $.growl({ message: data.msg, type: 'warning' });
1532	                    } else {
1533	                        if (window.FEATURES.get('modal_cart')) {
1534	                            window.CART_INIT_DATA = data;
1535	                            window.showCart();
1536	                        } else {
1537	                            $.growl({ message: $(event.target).data('success-msg'), template_selector: '#cart-notify' });
1538	                        }
1539	                    }
1540	                }, 'json');
1541	            });
1542
1543	            buyBundleButtons.off('click').click(function (event) {
1544	                event.preventDefault();
1545	                var form = $(this).closest('form')[0];
1546	                var formData = $(form).serialize();
1547	                $.post('/handlevogn/addBundle', formData, function (data) {
1548	                    console.log(data);
1549	                    update(data.items, data.total);
1550	                    if (data.msg !== '') {
1551	                        $.growl({ message: data.msg, type: 'warning' });
1552	                    } else {
1553	                        if (window.FEATURES.get('modal_cart')) {
1554	                            window.CART_INIT_DATA = data;
1555	                            window.showCart();
1556	                        } else {
1557	                            $.growl({ message: $(event.target).data('success-msg'), template_selector: '#cart-notify' });
1558	                        }
1559	                    }
1560	                }, 'json');
1561	            });
1562	        };
1563
1564	        // Get quickbuy data for ajax submission
1565	        var getProductQuickbuyData = function getProductQuickbuyData(productId) {
1566	            return 'id=' + productId + '&path=' + encodeURIComponent(window.location.pathname.split('?')[0]) + // return path, in case of errors
1567	            '&' + encodeURI("attributt[][0]") + '=' + '&antall=1' + '&ekstra_tekst=' + '&ekstra_velg=0';
1568	        };
1569
1570	        // Set cart quantity
1571	        cart.setQuantity = function (quantity) {
1572	            if (parseInt(quantity, 10) > 99) {
1573	                cart.quantityContainer.html('<i class="icon-larger-than"></i>99');
1574	            } else {
1575	                cart.quantityContainer.text(quantity);
1576	            }
1577
1578	            if (quantity > 0) {
1579	                $cart_btn.removeClass('cart-button--empty');
1580	            } else {
1581	                $cart_btn.addClass('cart-button--empty');
1582	            }
1583	        };
1584
1585	        // Find quantity
1586	        var getQuantity = function getQuantity() {
1587	            var quantity = cart.quantityContainer.html().replace('<i class="icon-larger-than"></i>', ''); // Strip > if number is ">99"
1588	            return parseInt(quantity, 10);
1589	        };
1590
1591	        // Set cart sum
1592	        cart.setSum = function (sum) {
1593	            cart.sumContainer.html(sum);
1594	        };
1595
1596	        // Highlight the cart
1597	        var highlightCart = function highlightCart() {
1598	            $cart_btn.addClass(cart.settings.cartHighlightClass);
1599	            setTimeout(function () {
1600	                $cart_btn.removeClass(cart.settings.cartHighlightClass);
1601	            }, 200);
1602	        };
1603
1604	        init();
1605	    };
1606
1607	    $.fn.cart = function (options) {
1608	        return this.each(function () {
1609	            if (undefined === $(this).data('cart')) {
1610	                var plugin = new $.cart(this, options);
1611	                $(this).data('cart', plugin);
1612	            }
1613	        });
1614	    };
1615		})(jQuery);
1616	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
1617
1618/***/ },
1619
1620/***/ 206:
1621/***/ function(module, exports, __webpack_require__) {
1622
1623	/* WEBPACK VAR INJECTION */(function(jQuery) {"use strict";
1624
1625	/*!
1626	 * fancyBox - jQuery Plugin
1627	 * version: 2.1.5 (Fri, 14 Jun 2013)
1628	 * @requires jQuery v1.6 or later
1629	 *
1630	 * Examples at http://fancyapps.com/fancybox/
1631	 * License: www.fancyapps.com/fancybox/#license
1632	 *
1633	 * Copyright 2012 Janis Skarnelis - [email protected]
1634	 *
1635	 */
1636
1637	(function (window, document, $, undefined) {
1638		"use strict";
1639
1640		var H = $("html"),
1641		    W = $(window),
1642		    D = $(document),
1643		    F = $.fancybox = function () {
1644			F.open.apply(this, arguments);
1645		},
1646		    IE = navigator.userAgent.match(/msie/i),
1647		    didUpdate = null,
1648		    isTouch = document.createTouch !== undefined,
1649		    isQuery = function isQuery(obj) {
1650			return obj && obj.hasOwnProperty && obj instanceof $;
1651		},
1652		    isString = function isString(str) {
1653			return str && $.type(str) === "string";
1654		},
1655		    isPercentage = function isPercentage(str) {
1656			return isString(str) && str.indexOf('%') > 0;
1657		},
1658		    isScrollable = function isScrollable(el) {
1659			return el && !(el.style.overflow && el.style.overflow === 'hidden') && (el.clientWidth && el.scrollWidth > el.clientWidth || el.clientHeight && el.scrollHeight > el.clientHeight);
1660		},
1661		    getScalar = function getScalar(orig, dim) {
1662			var value = parseInt(orig, 10) || 0;
1663
1664			if (dim && isPercentage(orig)) {
1665				value = F.getViewport()[dim] / 100 * value;
1666			}
1667
1668			return Math.ceil(value);
1669		},
1670		    getValue = function getValue(value, dim) {
1671			return getScalar(value, dim) + 'px';
1672		};
1673
1674		$.extend(F, {
1675			// The current version of fancyBox
1676			version: '2.1.5',
1677
1678			defaults: {
1679				padding: 15,
1680				margin: 20,
1681
1682				width: 800,
1683				height: 600,
1684				minWidth: 100,
1685				minHeight: 100,
1686				maxWidth: 9999,
1687				maxHeight: 9999,
1688				pixelRatio: 1, // Set to 2 for retina display support
1689
1690				autoSize: true,
1691				autoHeight: false,
1692				autoWidth: false,
1693
1694				autoResize: true,
1695				autoCenter: !isTouch,
1696				fitToView: true,
1697				aspectRatio: false,
1698				topRatio: 0.5,
1699				leftRatio: 0.5,
1700
1701				scrolling: 'auto', // 'auto', 'yes' or 'no'
1702				wrapCSS: '',
1703
1704				arrows: true,
1705				closeBtn: true,
1706				closeClick: false,
1707				nextClick: false,
1708				mouseWheel: true,
1709				autoPlay: false,
1710				playSpeed: 3000,
1711				preload: 3,
1712				modal: false,
1713				loop: true,
1714
1715				ajax: {
1716					dataType: 'html',
1717					headers: { 'X-fancyBox': true }
1718				},
1719				iframe: {
1720					scrolling: 'auto',
1721					preload: true
1722				},
1723				swf: {
1724					wmode: 'transparent',
1725					allowfullscreen: 'true',
1726					allowscriptaccess: 'always'
1727				},
1728
1729				keys: {
1730					next: {
1731						13: 'left', // enter
1732						34: 'up', // page down
1733						39: 'left', // right arrow
1734						40: 'up' // down arrow
1735					},
1736					prev: {
1737						8: 'right', // backspace
1738						33: 'down', // page up
1739						37: 'right', // left arrow
1740						38: 'down' // up arrow
1741					},
1742					close: [27], // escape key
1743					play: [32], // space - start/stop slideshow
1744					toggle: [70] // letter "f" - toggle fullscreen
1745				},
1746
1747				direction: {
1748					next: 'left',
1749					prev: 'right'
1750				},
1751
1752				scrollOutside: true,
1753
1754				// Override some properties
1755				index: 0,
1756				type: null,
1757				href: null,
1758				content: null,
1759				title: null,
1760
1761				// HTML templates
1762				tpl: {
1763					wrap: '<div class="fancybox-wrap" tabIndex="-1"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>',
1764					image: '<img class="fancybox-image" src="{href}" alt="" />',
1765					iframe: '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen' + (IE ? ' allowtransparency="true"' : '') + '></iframe>',
1766					error: '<p class="fancybox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',
1767					closeBtn: '<a title="Close" class="fancybox-item fancybox-close" href="javascript:;"></a>',
1768					next: '<a title="Next" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>',
1769					prev: '<a title="Previous" class="fancybox-nav fancybox-prev" href="javascript:;"><span></span></a>'
1770				},
1771
1772				// Properties for each animation type
1773				// Opening fancyBox
1774				openEffect: 'fade', // 'elastic', 'fade' or 'none'
1775				openSpeed: 250,
1776				openEasing: 'swing',
1777				openOpacity: true,
1778				openMethod: 'zoomIn',
1779
1780				// Closing fancyBox
1781				closeEffect: 'fade', // 'elastic', 'fade' or 'none'
1782				closeSpeed: 250,
1783				closeEasing: 'swing',
1784				closeOpacity: true,
1785				closeMethod: 'zoomOut',
1786
1787				// Changing next gallery item
1788				nextEffect: 'elastic', // 'elastic', 'fade' or 'none'
1789				nextSpeed: 250,
1790				nextEasing: 'swing',
1791				nextMethod: 'changeIn',
1792
1793				// Changing previous gallery item
1794				prevEffect: 'elastic', // 'elastic', 'fade' or 'none'
1795				prevSpeed: 250,
1796				prevEasing: 'swing',
1797				prevMethod: 'changeOut',
1798
1799				// Enable default helpers
1800				helpers: {
1801					overlay: true,
1802					title: true
1803				},
1804
1805				// Callbacks
1806				onCancel: $.noop, // If canceling
1807				beforeLoad: $.noop, // Before loading
1808				afterLoad: $.noop, // After loading
1809				beforeShow: $.noop, // Before changing in current item
1810				afterShow: $.noop, // After opening
1811				beforeChange: $.noop, // Before changing gallery item
1812				beforeClose: $.noop, // Before closing
1813				afterClose: $.noop // After closing
1814			},
1815
1816			//Current state
1817			group: {}, // Selected group
1818			opts: {}, // Group options
1819			previous: null, // Previous element
vendor: 4,724 bytes, lines 1820-2029
1820			coming: null, // Element being loaded
1821			current: null, // Currently loaded element
1822			isActive: false, // Is activated
1823			isOpen: false, // Is currently open
1824			isOpened: false, // Have been fully opened at least once
1825
1826			wrap: null,
1827			skin: null,
1828			outer: null,
1829			inner: null,
1830
1831			player: {
1832				timer: null,
1833				isActive: false
1834			},
1835
1836			// Loaders
1837			ajaxLoad: null,
1838			imgPreload: null,
1839
1840			// Some collections
1841			transitions: {},
1842			helpers: {},
1843
1844			/*
1845	   *	Static methods
1846	   */
1847
1848			open: function open(group, opts) {
1849				if (!group) {
1850					return;
1851				}
1852
1853				if (!$.isPlainObject(opts)) {
1854					opts = {};
1855				}
1856
1857				// Close if already active
1858				if (false === F.close(true)) {
1859					return;
1860				}
1861
1862				// Normalize group
1863				if (!$.isArray(group)) {
1864					group = isQuery(group) ? $(group).get() : [group];
1865				}
1866
1867				// Recheck if the type of each element is `object` and set content type (image, ajax, etc)
1868				$.each(group, function (i, element) {
1869					var obj = {},
1870					    href,
1871					    title,
1872					    content,
1873					    type,
1874					    rez,
1875					    hrefParts,
1876					    selector;
1877
1878					if ($.type(element) === "object") {
1879						// Check if is DOM element
1880						if (element.nodeType) {
1881							element = $(element);
1882						}
1883
1884						if (isQuery(element)) {
1885							obj = {
1886								href: element.data('fancybox-href') || element.attr('href'),
1887								title: element.data('fancybox-title') || element.attr('title'),
1888								isDom: true,
1889								element: element
1890							};
1891
1892							if ($.metadata) {
1893								$.extend(true, obj, element.metadata());
1894							}
1895						} else {
1896							obj = element;
1897						}
1898					}
1899
1900					href = opts.href || obj.href || (isString(element) ? element : null);
1901					title = opts.title !== undefined ? opts.title : obj.title || '';
1902
1903					content = opts.content || obj.content;
1904					type = content ? 'html' : opts.type || obj.type;
1905
1906					if (!type && obj.isDom) {
1907						type = element.data('fancybox-type');
1908
1909						if (!type) {
1910							rez = element.prop('class').match(/fancybox\.(\w+)/);
1911							type = rez ? rez[1] : null;
1912						}
1913					}
1914
1915					if (isString(href)) {
1916						// Try to guess the content type
1917						if (!type) {
1918							if (F.isImage(href)) {
1919								type = 'image';
1920							} else if (F.isSWF(href)) {
1921								type = 'swf';
1922							} else if (href.charAt(0) === '#') {
1923								type = 'inline';
1924							} else if (isString(element)) {
1925								type = 'html';
1926								content = element;
1927							}
1928						}
1929
1930						// Split url into two pieces with source url and content selector, e.g,
1931						// "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id"
1932						if (type === 'ajax') {
1933							hrefParts = href.split(/\s+/, 2);
1934							href = hrefParts.shift();
1935							selector = hrefParts.shift();
1936						}
1937					}
1938
1939					if (!content) {
1940						if (type === 'inline') {
1941							if (href) {
1942								content = $(isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href); //strip for ie7
1943							} else if (obj.isDom) {
1944									content = element;
1945								}
1946						} else if (type === 'html') {
1947							content = href;
1948						} else if (!type && !href && obj.isDom) {
1949							type = 'inline';
1950							content = element;
1951						}
1952					}
1953
1954					$.extend(obj, {
1955						href: href,
1956						type: type,
1957						content: content,
1958						title: title,
1959						selector: selector
1960					});
1961
1962					group[i] = obj;
1963				});
1964
1965				// Extend the defaults
1966				F.opts = $.extend(true, {}, F.defaults, opts);
1967
1968				// All options are merged recursive except keys
1969				if (opts.keys !== undefined) {
1970					F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false;
1971				}
1972
1973				F.group = group;
1974
1975				return F._start(F.opts.index);
1976			},
1977
1978			// Cancel image loading or abort ajax request
1979			cancel: function cancel() {
1980				var coming = F.coming;
1981
1982				if (!coming || false === F.trigger('onCancel')) {
1983					return;
1984				}
1985
1986				F.hideLoading();
1987
1988				if (F.ajaxLoad) {
1989					F.ajaxLoad.abort();
1990				}
1991
1992				F.ajaxLoad = null;
1993
1994				if (F.imgPreload) {
1995					F.imgPreload.onload = F.imgPreload.onerror = null;
1996				}
1997
1998				if (coming.wrap) {
1999					coming.wrap.stop(true, true).trigger('onReset').remove();
2000				}
2001
2002				F.coming = null;
2003
2004				// If the first item has been canceled, then clear everything
2005				if (!F.current) {
2006					F._afterZoomOut(coming);
2007				}
2008			},
2009
2010			// Start closing animation if is open; remove immediately if opening/closing
2011			close: function close(event) {
2012				F.cancel();
2013
2014				if (false === F.trigger('beforeClose')) {
2015					return;
2016				}
2017
2018				F.unbindEvents();
2019
2020				if (!F.isActive) {
2021					return;
2022				}
2023
2024				if (!F.isOpen || event === true) {
2025					$('.fancybox-wrap').stop(true).trigger('onReset').remove();
2026
2027					F._afterZoomOut();
2028				} else {
2029					F.isOpen = F.isOpened = false;
2030					F.isClosing = true;
2031
2032					$('.fancybox-item, .fancybox-nav').remove();
2033
2034					F.wrap.stop(true, true).removeClass('fancybox-opened');
2035
2036					F.transitions[F.current.closeMethod]();
2037				}
2038			},
2039
2040			// Manage slideshow:
2041			//   $.fancybox.play(); - toggle slideshow
2042			//   $.fancybox.play( true ); - start
2043			//   $.fancybox.play( false ); - stop
2044			play: function play(action) {
2045				var clear = function clear() {
2046					clearTimeout(F.player.timer);
2047				},
2048				    set = function set() {
2049					clear();
2050
2051					if (F.current && F.player.isActive) {
2052						F.player.timer = setTimeout(F.next, F.current.playSpeed);
2053					}
2054				},
2055				    stop = function stop() {
2056					clear();
2057
2058					D.unbind('.player');
2059
2060					F.player.isActive = false;
2061
2062					F.trigger('onPlayEnd');
2063				},
2064				    start = function start() {
2065					if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) {
2066						F.player.isActive = true;
2067
2068						D.bind({
2069							'onCancel.player beforeClose.player': stop,
2070							'onUpdate.player': set,
2071							'beforeLoad.player': clear
2072						});
2073
2074						set();
2075
2076						F.trigger('onPlayStart');
2077					}
2078				};
2079
2080				if (action === true || !F.player.isActive && action !== false) {
2081					start();
2082				} else {
2083					stop();
2084				}
2085			},
2086
2087			// Navigate to next gallery item
2088			next: function next(direction) {
2089				var current = F.current;
2090
2091				if (current) {
2092					if (!isString(direction)) {
2093						direction = current.direction.next;
2094					}
2095
2096					F.jumpto(current.index + 1, direction, 'next');
2097				}
2098			},
2099
2100			// Navigate to previous gallery item
2101			prev: function prev(direction) {
2102				var current = F.current;
2103
2104				if (current) {
2105					if (!isString(direction)) {
2106						direction = current.direction.prev;
2107					}
2108
2109					F.jumpto(current.index - 1, direction, 'prev');
2110				}
2111			},
2112
2113			// Navigate to gallery item by index
2114			jumpto: function jumpto(index, direction, router) {
2115				var current = F.current;
2116
2117				if (!current) {
2118					return;
2119				}
2120
2121				index = getScalar(index);
2122
2123				F.direction = direction || current.direction[index >= current.index ? 'next' : 'prev'];
2124				F.router = router || 'jumpto';
2125
2126				if (current.loop) {
2127					if (index < 0) {
2128						index = current.group.length + index % current.group.length;
2129					}
2130
2131					index = index % current.group.length;
2132				}
2133
2134				if (current.group[index] !== undefined) {
2135					F.cancel();
2136
2137					F._start(index);
2138				}
2139			},
2140
2141			// Center inside viewport and toggle position type to fixed or absolute if needed
2142			reposition: function reposition(e, onlyAbsolute) {
2143				var current = F.current,
2144				    wrap = current ? current.wrap : null,
2145				    pos;
2146
2147				if (wrap) {
2148					pos = F._getPosition(onlyAbsolute);
2149
2150					if (e && e.type === 'scroll') {
2151						delete pos.position;
2152
2153						wrap.stop(true, true).animate(pos, 200);
2154					} else {
2155						wrap.css(pos);
2156
2157						current.pos = $.extend({}, current.dim, pos);
2158					}
2159				}
2160			},
2161
2162			update: function update(e) {
2163				var type = e && e.type,
2164				    anyway = !type || type === 'orientationchange';
2165
2166				if (anyway) {
2167					clearTimeout(didUpdate);
2168
2169					didUpdate = null;
2170				}
2171
2172				if (!F.isOpen || didUpdate) {
2173					return;
2174				}
2175
2176				didUpdate = setTimeout(function () {
2177					var current = F.current;
2178
2179					if (!current || F.isClosing) {
2180						return;
2181					}
2182
2183					F.wrap.removeClass('fancybox-tmp');
2184
2185					if (anyway || type === 'load' || type === 'resize' && current.autoResize) {
2186						F._setDimension();
2187					}
2188
2189					if (!(type === 'scroll' && current.canShrink)) {
2190						F.reposition(e);
2191					}
2192
2193					F.trigger('onUpdate');
2194
2195					didUpdate = null;
2196				}, anyway && !isTouch ? 0 : 300);
2197			},
2198
2199			// Shrink content to fit inside viewport or restore if resized
2200			toggle: function toggle(action) {
2201				if (F.isOpen) {
2202					F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView;
2203
2204					// Help browser to restore document dimensions
2205					if (isTouch) {
2206						F.wrap.removeAttr('style').addClass('fancybox-tmp');
2207
2208						F.trigger('onUpdate');
2209					}
2210
2211					F.update();
2212				}
2213			},
2214
2215			hideLoading: function hideLoading() {
2216				D.unbind('.loading');
2217
2218				$('#fancybox-loading').remove();
2219			},
2220
2221			showLoading: function showLoading() {
2222				var el, viewport;
2223
2224				F.hideLoading();
2225
2226				el = $('<div id="fancybox-loading"><div></div></div>').click(F.cancel).appendTo('body');
2227
2228				// If user will press the escape-button, the request will be canceled
2229				D.bind('keydown.loading', function (e) {
2230					if ((e.which || e.keyCode) === 27) {
2231						e.preventDefault();
2232
2233						F.cancel();
2234					}
2235				});
2236
2237				if (!F.defaults.fixed) {
2238					viewport = F.getViewport();
2239
2240					el.css({
2241						position: 'absolute',
2242						top: viewport.h * 0.5 + viewport.y,
2243						left: viewport.w * 0.5 + viewport.x
2244					});
2245				}
2246			},
2247
2248			getViewport: function getViewport() {
2249				var locked = F.current && F.current.locked || false,
2250				    rez = {
2251					x: W.scrollLeft(),
2252					y: W.scrollTop()
2253				};
2254
2255				if (locked) {
2256					rez.w = locked[0].clientWidth;
2257					rez.h = locked[0].clientHeight;
2258				} else {
2259					// See http://bugs.jquery.com/ticket/6724
2260					rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width();
2261					rez.h = isTouch && window.innerHeight ? window.innerHeight : W.he
vendor: 26,499 bytes, lines 2261-3280
2261ight();
2262				}
2263
2264				return rez;
2265			},
2266
2267			// Unbind the keyboard / clicking actions
2268			unbindEvents: function unbindEvents() {
2269				if (F.wrap && isQuery(F.wrap)) {
2270					F.wrap.unbind('.fb');
2271				}
2272
2273				D.unbind('.fb');
2274				W.unbind('.fb');
2275			},
2276
2277			bindEvents: function bindEvents() {
2278				var current = F.current,
2279				    keys;
2280
2281				if (!current) {
2282					return;
2283				}
2284
2285				// Changing document height on iOS devices triggers a 'resize' event,
2286				// that can change document height... repeating infinitely
2287				W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update);
2288
2289				keys = current.keys;
2290
2291				if (keys) {
2292					D.bind('keydown.fb', function (e) {
2293						var code = e.which || e.keyCode,
2294						    target = e.target || e.srcElement;
2295
2296						// Skip esc key if loading, because showLoading will cancel preloading
2297						if (code === 27 && F.coming) {
2298							return false;
2299						}
2300
2301						// Ignore key combinations and key events within form elements
2302						if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) {
2303							$.each(keys, function (i, val) {
2304								if (current.group.length > 1 && val[code] !== undefined) {
2305									F[i](val[code]);
2306
2307									e.preventDefault();
2308									return false;
2309								}
2310
2311								if ($.inArray(code, val) > -1) {
2312									F[i]();
2313
2314									e.preventDefault();
2315									return false;
2316								}
2317							});
2318						}
2319					});
2320				}
2321
2322				if ($.fn.mousewheel && current.mouseWheel) {
2323					F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) {
2324						var target = e.target || null,
2325						    parent = $(target),
2326						    canScroll = false;
2327
2328						while (parent.length) {
2329							if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) {
2330								break;
2331							}
2332
2333							canScroll = isScrollable(parent[0]);
2334							parent = $(parent).parent();
2335						}
2336
2337						if (delta !== 0 && !canScroll) {
2338							if (F.group.length > 1 && !current.canShrink) {
2339								if (deltaY > 0 || deltaX > 0) {
2340									F.prev(deltaY > 0 ? 'down' : 'left');
2341								} else if (deltaY < 0 || deltaX < 0) {
2342									F.next(deltaY < 0 ? 'up' : 'right');
2343								}
2344
2345								e.preventDefault();
2346							}
2347						}
2348					});
2349				}
2350			},
2351
2352			trigger: function trigger(event, o) {
2353				var ret,
2354				    obj = o || F.coming || F.current;
2355
2356				if (!obj) {
2357					return;
2358				}
2359
2360				if ($.isFunction(obj[event])) {
2361					ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1));
2362				}
2363
2364				if (ret === false) {
2365					return false;
2366				}
2367
2368				if (obj.helpers) {
2369					$.each(obj.helpers, function (helper, opts) {
2370						if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) {
2371							F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj);
2372						}
2373					});
2374				}
2375
2376				D.trigger(event);
2377			},
2378
2379			isImage: function isImage(str) {
2380				return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i);
2381			},
2382
2383			isSWF: function isSWF(str) {
2384				return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i);
2385			},
2386
2387			_start: function _start(index) {
2388				var coming = {},
2389				    obj,
2390				    href,
2391				    type,
2392				    margin,
2393				    padding;
2394
2395				index = getScalar(index);
2396				obj = F.group[index] || null;
2397
2398				if (!obj) {
2399					return false;
2400				}
2401
2402				coming = $.extend(true, {}, F.opts, obj);
2403
2404				// Convert margin and padding properties to array - top, right, bottom, left
2405				margin = coming.margin;
2406				padding = coming.padding;
2407
2408				if ($.type(margin) === 'number') {
2409					coming.margin = [margin, margin, margin, margin];
2410				}
2411
2412				if ($.type(padding) === 'number') {
2413					coming.padding = [padding, padding, padding, padding];
2414				}
2415
2416				// 'modal' propery is just a shortcut
2417				if (coming.modal) {
2418					$.extend(true, coming, {
2419						closeBtn: false,
2420						closeClick: false,
2421						nextClick: false,
2422						arrows: false,
2423						mouseWheel: false,
2424						keys: null,
2425						helpers: {
2426							overlay: {
2427								closeClick: false
2428							}
2429						}
2430					});
2431				}
2432
2433				// 'autoSize' property is a shortcut, too
2434				if (coming.autoSize) {
2435					coming.autoWidth = coming.autoHeight = true;
2436				}
2437
2438				if (coming.width === 'auto') {
2439					coming.autoWidth = true;
2440				}
2441
2442				if (coming.height === 'auto') {
2443					coming.autoHeight = true;
2444				}
2445
2446				/*
2447	    * Add reference to the group, so it`s possible to access from callbacks, example:
2448	    * afterLoad : function() {
2449	    *     this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : '');
2450	    * }
2451	    */
2452
2453				coming.group = F.group;
2454				coming.index = index;
2455
2456				// Give a chance for callback or helpers to update coming item (type, title, etc)
2457				F.coming = coming;
2458
2459				if (false === F.trigger('beforeLoad')) {
2460					F.coming = null;
2461
2462					return;
2463				}
2464
2465				type = coming.type;
2466				href = coming.href;
2467
2468				if (!type) {
2469					F.coming = null;
2470
2471					//If we can not determine content type then drop silently or display next/prev item if looping through gallery
2472					if (F.current && F.router && F.router !== 'jumpto') {
2473						F.current.index = index;
2474
2475						return F[F.router](F.direction);
2476					}
2477
2478					return false;
2479				}
2480
2481				F.isActive = true;
2482
2483				if (type === 'image' || type === 'swf') {
2484					coming.autoHeight = coming.autoWidth = false;
2485					coming.scrolling = 'visible';
2486				}
2487
2488				if (type === 'image') {
2489					coming.aspectRatio = true;
2490				}
2491
2492				if (type === 'iframe' && isTouch) {
2493					coming.scrolling = 'scroll';
2494				}
2495
2496				// Build the neccessary markup
2497				coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo(coming.parent || 'body');
2498
2499				$.extend(coming, {
2500					skin: $('.fancybox-skin', coming.wrap),
2501					outer: $('.fancybox-outer', coming.wrap),
2502					inner: $('.fancybox-inner', coming.wrap)
2503				});
2504
2505				$.each(["Top", "Right", "Bottom", "Left"], function (i, v) {
2506					coming.skin.css('padding' + v, getValue(coming.padding[i]));
2507				});
2508
2509				F.trigger('onReady');
2510
2511				// Check before try to load; 'inline' and 'html' types need content, others - href
2512				if (type === 'inline' || type === 'html') {
2513					if (!coming.content || !coming.content.length) {
2514						return F._error('content');
2515					}
2516				} else if (!href) {
2517					return F._error('href');
2518				}
2519
2520				if (type === 'image') {
2521					F._loadImage();
2522				} else if (type === 'ajax') {
2523					F._loadAjax();
2524				} else if (type === 'iframe') {
2525					F._loadIframe();
2526				} else {
2527					F._afterLoad();
2528				}
2529			},
2530
2531			_error: function _error(type) {
2532				$.extend(F.coming, {
2533					type: 'html',
2534					autoWidth: true,
2535					autoHeight: true,
2536					minWidth: 0,
2537					minHeight: 0,
2538					scrolling: 'no',
2539					hasError: type,
2540					content: F.coming.tpl.error
2541				});
2542
2543				F._afterLoad();
2544			},
2545
2546			_loadImage: function _loadImage() {
2547				// Reset preload image so it is later possible to check "complete" property
2548				var img = F.imgPreload = new Image();
2549
2550				img.onload = function () {
2551					this.onload = this.onerror = null;
2552
2553					F.coming.width = this.width / F.opts.pixelRatio;
2554					F.coming.height = this.height / F.opts.pixelRatio;
2555
2556					F._afterLoad();
2557				};
2558
2559				img.onerror = function () {
2560					this.onload = this.onerror = null;
2561
2562					F._error('image');
2563				};
2564
2565				img.src = F.coming.href;
2566
2567				if (img.complete !== true) {
2568					F.showLoading();
2569				}
2570			},
2571
2572			_loadAjax: function _loadAjax() {
2573				var coming = F.coming;
2574
2575				F.showLoading();
2576
2577				F.ajaxLoad = $.ajax($.extend({}, coming.ajax, {
2578					url: coming.href,
2579					error: function error(jqXHR, textStatus) {
2580						if (F.coming && textStatus !== 'abort') {
2581							F._error('ajax', jqXHR);
2582						} else {
2583							F.hideLoading();
2584						}
2585					},
2586					success: function success(data, textStatus) {
2587						if (textStatus === 'success') {
2588							coming.content = data;
2589
2590							F._afterLoad();
2591						}
2592					}
2593				}));
2594			},
2595
2596			_loadIframe: function _loadIframe() {
2597				var coming = F.coming,
2598				    iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime())).attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling).attr('src', coming.href);
2599
2600				// This helps IE
2601				$(coming.wrap).bind('onReset', function () {
2602					try {
2603						$(this).find('iframe').hide().attr('src', '//about:blank').end().empty();
2604					} catch (e) {}
2605				});
2606
2607				if (coming.iframe.preload) {
2608					F.showLoading();
2609
2610					iframe.one('load', function () {
2611						$(this).data('ready', 1);
2612
2613						// iOS will lose scrolling if we resize
2614						if (!isTouch) {
2615							$(this).bind('load.fb', F.update);
2616						}
2617
2618						// Without this trick:
2619						//   - iframe won't scroll on iOS devices
2620						//   - IE7 sometimes displays empty iframe
2621						$(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show();
2622
2623						F._afterLoad();
2624					});
2625				}
2626
2627				coming.content = iframe.appendTo(coming.inner);
2628
2629				if (!coming.iframe.preload) {
2630					F._afterLoad();
2631				}
2632			},
2633
2634			_preloadImages: function _preloadImages() {
2635				var group = F.group,
2636				    current = F.current,
2637				    len = group.length,
2638				    cnt = current.preload ? Math.min(current.preload, len - 1) : 0,
2639				    item,
2640				    i;
2641
2642				for (i = 1; i <= cnt; i += 1) {
2643					item = group[(current.index + i) % len];
2644
2645					if (item.type === 'image' && item.href) {
2646						new Image().src = item.href;
2647					}
2648				}
2649			},
2650
2651			_afterLoad: function _afterLoad() {
2652				var coming = F.coming,
2653				    previous = F.current,
2654				    placeholder = 'fancybox-placeholder',
2655				    current,
2656				    content,
2657				    type,
2658				    scrolling,
2659				    href,
2660				    embed;
2661
2662				F.hideLoading();
2663
2664				if (!coming || F.isActive === false) {
2665					return;
2666				}
2667
2668				if (false === F.trigger('afterLoad', coming, previous)) {
2669					coming.wrap.stop(true).trigger('onReset').remove();
2670
2671					F.coming = null;
2672
2673					return;
2674				}
2675
2676				if (previous) {
2677					F.trigger('beforeChange', previous);
2678
2679					previous.wrap.stop(true).removeClass('fancybox-opened').find('.fancybox-item, .fancybox-nav').remove();
2680				}
2681
2682				F.unbindEvents();
2683
2684				current = coming;
2685				content = coming.content;
2686				type = coming.type;
2687				scrolling = coming.scrolling;
2688
2689				$.extend(F, {
2690					wrap: current.wrap,
2691					skin: current.skin,
2692					outer: current.outer,
2693					inner: current.inner,
2694					current: current,
2695					previous: previous
2696				});
2697
2698				href = current.href;
2699
2700				switch (type) {
2701					case 'inline':
2702					case 'ajax':
2703					case 'html':
2704						if (current.selector) {
2705							content = $('<div>').html(content).find(current.selector);
2706						} else if (isQuery(content)) {
2707							if (!content.data(placeholder)) {
2708								content.data(placeholder, $('<div class="' + placeholder + '"></div>').insertAfter(content).hide());
2709							}
2710
2711							content = content.show().detach();
2712
2713							current.wrap.bind('onReset', function () {
2714								if ($(this).find(content).length) {
2715									content.hide().replaceAll(content.data(placeholder)).data(placeholder, false);
2716								}
2717							});
2718						}
2719						break;
2720
2721					case 'image':
2722						content = current.tpl.image.replace('{href}', href);
2723						break;
2724
2725					case 'swf':
2726						content = '<object id="fancybox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="' + href + '"></param>';
2727						embed = '';
2728
2729						$.each(current.swf, function (name, val) {
2730							content += '<param name="' + name + '" value="' + val + '"></param>';
2731							embed += ' ' + name + '="' + val + '"';
2732						});
2733
2734						content += '<embed src="' + href + '" type="application/x-shockwave-flash" width="100%" height="100%"' + embed + '></embed></object>';
2735						break;
2736				}
2737
2738				if (!(isQuery(content) && content.parent().is(current.inner))) {
2739					current.inner.append(content);
2740				}
2741
2742				// Give a chance for helpers or callbacks to update elements
2743				F.trigger('beforeShow');
2744
2745				// Set scrolling before calculating dimensions
2746				current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : scrolling === 'no' ? 'hidden' : scrolling);
2747
2748				// Set initial dimensions and start position
2749				F._setDimension();
2750
2751				F.reposition();
2752
2753				F.isOpen = false;
2754				F.coming = null;
2755
2756				F.bindEvents();
2757
2758				if (!F.isOpened) {
2759					$('.fancybox-wrap').not(current.wrap).stop(true).trigger('onReset').remove();
2760				} else if (previous.prevMethod) {
2761					F.transitions[previous.prevMethod]();
2762				}
2763
2764				F.transitions[F.isOpened ? current.nextMethod : current.openMethod]();
2765
2766				F._preloadImages();
2767			},
2768
2769			_setDimension: function _setDimension() {
2770				var viewport = F.getViewport(),
2771				    steps = 0,
2772				    canShrink = false,
2773				    canExpand = false,
2774				    wrap = F.wrap,
2775				    skin = F.skin,
2776				    inner = F.inner,
2777				    current = F.current,
2778				    width = current.width,
2779				    height = current.height,
2780				    minWidth = current.minWidth,
2781				    minHeight = current.minHeight,
2782				    maxWidth = current.maxWidth,
2783				    maxHeight = current.maxHeight,
2784				    scrolling = current.scrolling,
2785				    scrollOut = current.scrollOutside ? current.scrollbarWidth : 0,
2786				    margin = current.margin,
2787				    wMargin = getScalar(margin[1] + margin[3]),
2788				    hMargin = getScalar(margin[0] + margin[2]),
2789				    wPadding,
2790				    hPadding,
2791				    wSpace,
2792				    hSpace,
2793				    origWidth,
2794				    origHeight,
2795				    origMaxWidth,
2796				    origMaxHeight,
2797				    ratio,
2798				    width_,
2799				    height_,
2800				    maxWidth_,
2801				    maxHeight_,
2802				    iframe,
2803				    body;
2804
2805				// Reset dimensions so we could re-check actual size
2806				wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp');
2807
2808				wPadding = getScalar(skin.outerWidth(true) - skin.width());
2809				hPadding = getScalar(skin.outerHeight(true) - skin.height());
2810
2811				// Any space between content and viewport (margin, padding, border, title)
2812				wSpace = wMargin + wPadding;
2813				hSpace = hMargin + hPadding;
2814
2815				origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width;
2816				origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height;
2817
2818				if (current.type === 'iframe') {
2819					iframe = current.content;
2820
2821					if (current.autoHeight && iframe.data('ready') === 1) {
2822						try {
2823							if (iframe[0].contentWindow.document.location) {
2824								inner.width(origWidth).height(9999);
2825
2826								body = iframe.contents().find('body');
2827
2828								if (scrollOut) {
2829									body.css('overflow-x', 'hidden');
2830								}
2831
2832								origHeight = body.outerHeight(true);
2833							}
2834						} catch (e) {}
2835					}
2836				} else if (current.autoWidth || current.autoHeight) {
2837					inner.addClass('fancybox-tmp');
2838
2839					// Set width or height in case we need to calculate only one dimension
2840					if (!current.autoWidth) {
2841						inner.width(origWidth);
2842					}
2843
2844					if (!current.autoHeight) {
2845						inner.height(origHeight);
2846					}
2847
2848					if (current.autoWidth) {
2849						origWidth = inner.width();
2850					}
2851
2852					if (current.autoHeight) {
2853						origHeight = inner.height();
2854					}
2855
2856					inner.removeClass('fancybox-tmp');
2857				}
2858
2859				width = getScalar(origWidth);
2860				height = getScalar(origHeight);
2861
2862				ratio = origWidth / origHeight;
2863
2864				// Calculations for the content
2865				minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth);
2866				maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth);
2867
2868				minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight);
2869				maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight);
2870
2871				// These will be used to determine if wrap can fit in the viewport
2872				origMaxWidth = maxWidth;
2873				origMaxHeight = maxHeight;
2874
2875				if (current.fitToView) {
2876					maxWidth = Math.min(viewport.w - wSpace, maxWidth);
2877					maxHeight = Math.min(viewport.h - hSpace, maxHeight);
2878				}
2879
2880				maxWidth_ = viewport.w - wMargin;
2881				maxHeight_ = viewport.h - hMargin;
2882
2883				if (current.aspectRatio) {
2884					if (width > maxWidth) {
2885						width = maxWidth;
2886						height = getScalar(width / ratio);
2887					}
2888
2889					if (height > maxHeight) {
2890						height = maxHeight;
2891						width = getScalar(height * ratio);
2892					}
2893
2894					if (width < minWidth) {
2895						width = minWidth;
2896						height = getScalar(width / ratio);
2897					}
2898
2899					if (height < minHeight) {
2900						height = minHeight;
2901						width = getScalar(height * ratio);
2902					}
2903				} else {
2904					width = Math.max(minWidth, Math.min(width, maxWidth));
2905
2906					if (current.autoHeight && current.type !== 'iframe') {
2907						inner.width(width);
2908
2909						height = inner.height();
2910					}
2911
2912					height = Math.max(minHeight, Math.min(height, maxHeight));
2913				}
2914
2915				// Try to fit inside viewport (including the title)
2916				if (current.fitToView) {
2917					inner.width(width).height(height);
2918
2919					wrap.width(width + wPadding);
2920
2921					// Real wrap dimensions
2922					width_ = wrap.width();
2923					height_ = wrap.height();
2924
2925					if (current.aspectRatio) {
2926						while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) {
2927							if (steps++ > 19) {
2928								break;
2929							}
2930
2931							height = Math.max(minHeight, Math.min(maxHeight, height - 10));
2932							width = getScalar(height * ratio);
2933
2934							if (width < minWidth) {
2935								width = minWidth;
2936								height = getScalar(width / ratio);
2937							}
2938
2939							if (width > maxWidth) {
2940								width = maxWidth;
2941								height = getScalar(width / ratio);
2942							}
2943
2944							inner.width(width).height(height);
2945
2946							wrap.width(width + wPadding);
2947
2948							width_ = wrap.width();
2949							height_ = wrap.height();
2950						}
2951					} else {
2952						width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_)));
2953						height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_)));
2954					}
2955				}
2956
2957				if (scrollOut && scrolling === 'auto' && height < origHeight && width + wPadding + scrollOut < maxWidth_) {
2958					width += scrollOut;
2959				}
2960
2961				inner.width(width).height(height);
2962
2963				wrap.width(width + wPadding);
2964
2965				width_ = wrap.width();
2966				height_ = wrap.height();
2967
2968				canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight;
2969				canExpand = current.aspectRatio ? width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight : (width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight);
2970
2971				$.extend(current, {
2972					dim: {
2973						width: getValue(width_),
2974						height: getValue(height_)
2975					},
2976					origWidth: origWidth,
2977					origHeight: origHeight,
2978					canShrink: canShrink,
2979					canExpand: canExpand,
2980					wPadding: wPadding,
2981					hPadding: hPadding,
2982					wrapSpace: height_ - skin.outerHeight(true),
2983					skinSpace: skin.height() - height
2984				});
2985
2986				if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) {
2987					inner.height('auto');
2988				}
2989			},
2990
2991			_getPosition: function _getPosition(onlyAbsolute) {
2992				var current = F.current,
2993				    viewport = F.getViewport(),
2994				    margin = current.margin,
2995				    width = F.wrap.width() + margin[1] + margin[3],
2996				    height = F.wrap.height() + margin[0] + margin[2],
2997				    rez = {
2998					position: 'absolute',
2999					top: margin[0],
3000					left: margin[3]
3001				};
3002
3003				if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) {
3004					rez.position = 'fixed';
3005				} else if (!current.locked) {
3006					rez.top += viewport.y;
3007					rez.left += viewport.x;
3008				}
3009
3010				rez.top = getValue(Math.max(rez.top, rez.top + (viewport.h - height) * current.topRatio));
3011				rez.left = getValue(Math.max(rez.left, rez.left + (viewport.w - width) * current.leftRatio));
3012
3013				return rez;
3014			},
3015
3016			_afterZoomIn: function _afterZoomIn() {
3017				var current = F.current;
3018
3019				if (!current) {
3020					return;
3021				}
3022
3023				F.isOpen = F.isOpened = true;
3024
3025				F.wrap.css('overflow', 'visible').addClass('fancybox-opened');
3026
3027				F.update();
3028
3029				// Assign a click event
3030				if (current.closeClick || current.nextClick && F.group.length > 1) {
3031					F.inner.css('cursor', 'pointer').bind('click.fb', function (e) {
3032						if (!$(e.target).is('a') && !$(e.target).parent().is('a')) {
3033							e.preventDefault();
3034
3035							F[current.closeClick ? 'close' : 'next']();
3036						}
3037					});
3038				}
3039
3040				// Create a close button
3041				if (current.closeBtn) {
3042					$(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function (e) {
3043						e.preventDefault();
3044
3045						F.close();
3046					});
3047				}
3048
3049				// Create navigation arrows
3050				if (current.arrows && F.group.length > 1) {
3051					if (current.loop || current.index > 0) {
3052						$(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev);
3053					}
3054
3055					if (current.loop || current.index < F.group.length - 1) {
3056						$(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next);
3057					}
3058				}
3059
3060				F.trigger('afterShow');
3061
3062				// Stop the slideshow if this is the last item
3063				if (!current.loop && current.index === current.group.length - 1) {
3064					F.play(false);
3065				} else if (F.opts.autoPlay && !F.player.isActive) {
3066					F.opts.autoPlay = false;
3067
3068					F.play();
3069				}
3070			},
3071
3072			_afterZoomOut: function _afterZoomOut(obj) {
3073				obj = obj || F.current;
3074
3075				$('.fancybox-wrap').trigger('onReset').remove();
3076
3077				$.extend(F, {
3078					group: {},
3079					opts: {},
3080					router: false,
3081					current: null,
3082					isActive: false,
3083					isOpened: false,
3084					isOpen: false,
3085					isClosing: false,
3086					wrap: null,
3087					skin: null,
3088					outer: null,
3089					inner: null
3090				});
3091
3092				F.trigger('afterClose', obj);
3093			}
3094		});
3095
3096		/*
3097	  *	Default transitions
3098	  */
3099
3100		F.transitions = {
3101			getOrigPosition: function getOrigPosition() {
3102				var current = F.current,
3103				    element = current.element,
3104				    orig = current.orig,
3105				    pos = {},
3106				    width = 50,
3107				    height = 50,
3108				    hPadding = current.hPadding,
3109				    wPadding = current.wPadding,
3110				    viewport = F.getViewport();
3111
3112				if (!orig && current.isDom && element.is(':visible')) {
3113					orig = element.find('img:first');
3114
3115					if (!orig.length) {
3116						orig = element;
3117					}
3118				}
3119
3120				if (isQuery(orig)) {
3121					pos = orig.offset();
3122
3123					if (orig.is('img')) {
3124						width = orig.outerWidth();
3125						height = orig.outerHeight();
3126					}
3127				} else {
3128					pos.top = viewport.y + (viewport.h - height) * current.topRatio;
3129					pos.left = viewport.x + (viewport.w - width) * current.leftRatio;
3130				}
3131
3132				if (F.wrap.css('position') === 'fixed' || current.locked) {
3133					pos.top -= viewport.y;
3134					pos.left -= viewport.x;
3135				}
3136
3137				pos = {
3138					top: getValue(pos.top - hPadding * current.topRatio),
3139					left: getValue(pos.left - wPadding * current.leftRatio),
3140					width: getValue(width + wPadding),
3141					height: getValue(height + hPadding)
3142				};
3143
3144				return pos;
3145			},
3146
3147			step: function step(now, fx) {
3148				var ratio,
3149				    padding,
3150				    value,
3151				    prop = fx.prop,
3152				    current = F.current,
3153				    wrapSpace = current.wrapSpace,
3154				    skinSpace = current.skinSpace;
3155
3156				if (prop === 'width' || prop === 'height') {
3157					ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start);
3158
3159					if (F.isClosing) {
3160						ratio = 1 - ratio;
3161					}
3162
3163					padding = prop === 'width' ? current.wPadding : current.hPadding;
3164					value = now - padding;
3165
3166					F.skin[prop](getScalar(prop === 'width' ? value : value - wrapSpace * ratio));
3167					F.inner[prop](getScalar(prop === 'width' ? value : value - wrapSpace * ratio - skinSpace * ratio));
3168				}
3169			},
3170
3171			zoomIn: function zoomIn() {
3172				var current = F.current,
3173				    startPos = current.pos,
3174				    effect = current.openEffect,
3175				    elastic = effect === 'elastic',
3176				    endPos = $.extend({ opacity: 1 }, startPos);
3177
3178				// Remove "position" property that breaks older IE
3179				delete endPos.position;
3180
3181				if (elastic) {
3182					startPos = this.getOrigPosition();
3183
3184					if (current.openOpacity) {
3185						startPos.opacity = 0.1;
3186					}
3187				} else if (effect === 'fade') {
3188					startPos.opacity = 0.1;
3189				}
3190
3191				F.wrap.css(startPos).animate(endPos, {
3192					duration: effect === 'none' ? 0 : current.openSpeed,
3193					easing: current.openEasing,
3194					step: elastic ? this.step : null,
3195					complete: F._afterZoomIn
3196				});
3197			},
3198
3199			zoomOut: function zoomOut() {
3200				var current = F.current,
3201				    effect = current.closeEffect,
3202				    elastic = effect === 'elastic',
3203				    endPos = { opacity: 0.1 };
3204
3205				if (elastic) {
3206					endPos = this.getOrigPosition();
3207
3208					if (current.closeOpacity) {
3209						endPos.opacity = 0.1;
3210					}
3211				}
3212
3213				F.wrap.animate(endPos, {
3214					duration: effect === 'none' ? 0 : current.closeSpeed,
3215					easing: current.closeEasing,
3216					step: elastic ? this.step : null,
3217					complete: F._afterZoomOut
3218				});
3219			},
3220
3221			changeIn: function changeIn() {
3222				var current = F.current,
3223				    effect = current.nextEffect,
3224				    startPos = current.pos,
3225				    endPos = { opacity: 1 },
3226				    direction = F.direction,
3227				    distance = 200,
3228				    field;
3229
3230				startPos.opacity = 0.1;
3231
3232				if (effect === 'elastic') {
3233					field = direction === 'down' || direction === 'up' ? 'top' : 'left';
3234
3235					if (direction === 'down' || direction === 'right') {
3236						startPos[field] = getValue(getScalar(startPos[field]) - distance);
3237						endPos[field] = '+=' + distance + 'px';
3238					} else {
3239						startPos[field] = getValue(getScalar(startPos[field]) + distance);
3240						endPos[field] = '-=' + distance + 'px';
3241					}
3242				}
3243
3244				// Workaround for http://bugs.jquery.com/ticket/12273
3245				if (effect === 'none') {
3246					F._afterZoomIn();
3247				} else {
3248					F.wrap.css(startPos).animate(endPos, {
3249						duration: current.nextSpeed,
3250						easing: current.nextEasing,
3251						complete: F._afterZoomIn
3252					});
3253				}
3254			},
3255
3256			changeOut: function changeOut() {
3257				var previous = F.previous,
3258				    effect = previous.prevEffect,
3259				    endPos = { opacity: 0.1 },
3260				    direction = F.direction,
3261				    distance = 200;
3262
3263				if (effect === 'elastic') {
3264					endPos[direction === 'down' || direction === 'up' ? 'top' : 'left'] = (direction === 'up' || direction === 'left' ? '-' : '+') + '=' + distance + 'px';
3265				}
3266
3267				previous.wrap.animate(endPos, {
3268					duration: effect === 'none' ? 0 : previous.prevSpeed,
3269					easing: previous.prevEasing,
3270					complete: function complete() {
3271						$(this).trigger('onReset').remove();
3272					}
3273				});
3274			}
3275		};
3276
3277		/*
3278	  *	Overlay helper
3279	  */
3280
3281		F.helpers.overlay = {
3282			defaults: {
3283				closeClick: true, // if true, fancyBox will be closed when user clicks on the overlay
3284				speedOut: 200, // duration of fadeOut animation
3285				showEarly: true, // indicates if should be opened immediately or wait until the content is ready
3286				css: {}, // custom CSS properties
3287				locked: !isTouch, // if true, the content will be locked into overlay
3288				fixed: true // if false, the overlay CSS position property will not be set to "fixed"
3289			},
3290
3291			overlay: null, // current handle
3292			fixed: false, // indicates if the overlay has position "fixed"
3293			el: $('html'), // element that contains "the lock"
3294
3295			// Public methods
3296			create: function create(opts) {
3297				opts = $.extend({}, this.defaults, opts);
3298
3299				if (this.overlay) {
3300					this.close();
3301				}
3302
3303				this.overlay = $('<div class="fancybox-overlay"></div>').appendTo(F.coming ? F.coming.parent : opts.parent);
3304				this.fixed = false;
3305
3306				if (opts.fixed && F.defaults.fixed) {
3307					this.overlay.addClass('fancybox-overlay-fixed');
3308
3309					this.fixed = true;
3310				}
3311			},
3312
3313			open: function open(opts) {
3314				var that = this;
3315
3316				opts = $.extend({}, this.defaults, opts);
3317
3318				if (this.overlay) {
3319					this.overlay.unbind('.overlay').width('auto').height('auto');
3320				} else {
3321					this.create(opts);
3322				}
3323
3324				if (!this.fixed) {
3325					W.bind('resize.overlay', $.proxy(this.update, this));
3326
3327					this.update();
3328				}
3329
3330				if (opts.closeClick) {
3331					this.overlay.bind('click.overlay', function (e) {
3332						if ($(e.target).hasClass('fancybox-overlay')) {
3333							if (F.isActive) {
3334								F.close();
3335							} else {
3336								that.close();
3337							}
3338
3339							return false;
3340						}
3341					});
3342				}
3343
3344				this.overlay.css(opts.css).show();
3345			},
3346
3347			close: function close() {
3348				var scrollV, scrollH;
3349
3350				W.unbind('resize.overlay');
3351
3352				if (this.el.hasClass('fancybox-lock')) {
3353					$('.fancybox-margin').removeClass('fancybox-margin');
3354
3355					scrollV = W.scrollTop();
3356					scrollH = W.scrollLeft();
3357
3358					this.el.removeClass('fancybox-lock');
3359
3360					W.scrollTop(scrollV).scrollLeft(scrollH);
3361				}
3362
3363				$('.fancybox-overlay').remove().hide();
3364
3365				$.extend(this, {
3366					overlay: null,
3367					fixed: false
3368				});
3369			},
3370
3371			// Private, callbacks
3372
3373			update: function update() {
3374				var width = '100%',
3375				    offsetWidth;
3376
3377				// Reset width/height so it will not mess
3378				this.overlay.width(width).height('100%');
3379
3380				// jQuery does not return reliable result for IE
3381				if (IE) {
3382					offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth);
3383
3384					if (D.width() > offsetWidth) {
3385						width = D.width();
3386					}
3387				} else if (D.width() > W.width()) {
3388					width = D.width();
3389				}
3390
3391				this.overlay.width(width).height(D.height());
3392			},
3393
3394			// This is where we can manipulate DOM, because later it would cause iframes to reload
3395			onReady: function onReady(opts, obj) {
3396				var overlay = this.overlay;
3397
3398				$('.fancybox-overlay').stop(true, true);
3399
3400				if (!overlay) {
3401					this.create(opts);
3402				}
3403
3404				if (opts.locked && this.fixed && obj.fixed) {
3405					if (!overlay) {
3406						this.margin = D.height() > W.height() ? $('html').css('margin-right').replace("px", "") : false;
3407					}
3408
3409					obj.locked = this.overlay.append(obj.wrap);
3410					obj.fixed = false;
3411				}
3412
3413				if (opts.showEarly === true) {
3414					this.beforeShow.apply(this, arguments);
3415				}
3416			},
3417
3418			beforeShow: function beforeShow(opts, obj) {
3419				var scrollV, scrollH;
3420
3421				if (obj.locked) {
3422					if (this.margin !== false) {
3423						$('*').filter(function () {
3424							return $(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && !$(this).hasClass("fancybox-wrap");
3425						}).addClass('fancybox-margin');
3426
3427						this.el.addClass('fancybox-margin');
3428					}
3429
3430					scrollV = W.scrollTop();
3431					scrollH = W.scrollLeft();
3432
3433					this.el.addClass('fancybox-lock');
3434
3435					W.scrollTop(scrollV).scrollLeft(scrollH);
3436				}
3437
3438				this.open(opts);
3439			},
3440
3441			onUpdate: function onUpdate() {
3442				if (!this.fixed) {
3443					this.update();
3444				}
3445			},
3446
3447			afterClose: function afterClose(opts) {
3448				// Remove overlay if exists and fancyBox is not opening
3449				// (e.g., it is not being open using afterClose callback)
3450				//if (this.overlay && !F.isActive) {
3451				if (this.overlay && !F.coming) {
3452					this.overlay.fadeOut(opts.speedOut, $.proxy(this.close, this));
3453				}
3454			}
3455		};
3456
3457		/*
3458	  *	Title helper
3459	  */
3460
3461		F.helpers.title = {
3462			defaults: {
3463				type: 'float', // 'float', 'inside', 'outside' or 'over',
3464				position: 'bottom' // 'top' or 'bottom'
3465			},
3466
3467			beforeShow: function beforeShow(opts) {
3468				var current = F.current,
3469				    text = current.title,
3470				    type = opts.type,
3471				    title,
3472				    target;
3473
3474				if ($.isFunction(text)) {
3475					text = text.call(current.element, current);
3476				}
3477
3478				if (!isString(text) || $.trim(text) === '') {
3479					return;
3480				}
3481
3482				title = $('<div class="fancybox-title fancybox-title-' + type + '-wrap">
vendor: 4,072 bytes, lines 3482-3641
3482' + text + '</div>');
3483
3484				switch (type) {
3485					case 'inside':
3486						target = F.skin;
3487						break;
3488
3489					case 'outside':
3490						target = F.wrap;
3491						break;
3492
3493					case 'over':
3494						target = F.inner;
3495						break;
3496
3497					default:
3498						// 'float'
3499						target = F.skin;
3500
3501						title.appendTo('body');
3502
3503						if (IE) {
3504							title.width(title.width());
3505						}
3506
3507						title.wrapInner('<span class="child"></span>');
3508
3509						//Increase bottom margin so this title will also fit into viewport
3510						F.current.margin[2] += Math.abs(getScalar(title.css('margin-bottom')));
3511						break;
3512				}
3513
3514				title[opts.position === 'top' ? 'prependTo' : 'appendTo'](target);
3515			}
3516		};
3517
3518		// jQuery plugin initialization
3519		$.fn.fancybox = function (options) {
3520			var index,
3521			    that = $(this),
3522			    selector = this.selector || '',
3523			    run = function run(e) {
3524				var what = $(this).blur(),
3525				    idx = index,
3526				    relType,
3527				    relVal;
3528
3529				if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) {
3530					relType = options.groupAttr || 'data-fancybox-group';
3531					relVal = what.attr(relType);
3532
3533					if (!relVal) {
3534						relType = 'rel';
3535						relVal = what.get(0)[relType];
3536					}
3537
3538					if (relVal && relVal !== '' && relVal !== 'nofollow') {
3539						what = selector.length ? $(selector) : that;
3540						what = what.filter('[' + relType + '="' + relVal + '"]');
3541						idx = what.index(this);
3542					}
3543
3544					options.index = idx;
3545
3546					// Stop an event from bubbling if everything is fine
3547					if (F.open(what, options) !== false) {
3548						e.preventDefault();
3549					}
3550				}
3551			};
3552
3553			options = options || {};
3554			index = options.index || 0;
3555
3556			if (!selector || options.live === false) {
3557				that.unbind('click.fb-start').bind('click.fb-start', run);
3558			} else {
3559				D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run);
3560			}
3561
3562			this.filter('[data-fancybox-start=1]').trigger('click');
3563
3564			return this;
3565		};
3566
3567		// Tests that need a body at doc ready
3568		D.ready(function () {
3569			var w1, w2;
3570
3571			if ($.scrollbarWidth === undefined) {
3572				// http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth
3573				$.scrollbarWidth = function () {
3574					var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body'),
3575					    child = parent.children(),
3576					    width = child.innerWidth() - child.height(99).innerWidth();
3577
3578					parent.remove();
3579
3580					return width;
3581				};
3582			}
3583
3584			if ($.support.fixedPosition === undefined) {
3585				$.support.fixedPosition = function () {
3586					var elem = $('<div style="position:fixed;top:20px;"></div>').appendTo('body'),
3587					    fixed = elem[0].offsetTop === 20 || elem[0].offsetTop === 15;
3588
3589					elem.remove();
3590
3591					return fixed;
3592				}();
3593			}
3594
3595			$.extend(F.defaults, {
3596				scrollbarWidth: $.scrollbarWidth(),
3597				fixed: $.support.fixedPosition,
3598				parent: $('body')
3599			});
3600
3601			//Get real width of page scroll-bar
3602			w1 = $(window).width();
3603
3604			H.addClass('fancybox-lock-test');
3605
3606			w2 = $(window).width();
3607
3608			H.removeClass('fancybox-lock-test');
3609
3610			$("<style type='text/css'>.fancybox-margin{margin-right:" + (w2 - w1) + "px;}</style>").appendTo("head");
3611		});
3612		})(window, document, jQuery);
3613	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
3614
3615/***/ },
3616
3617/***/ 211:
3618/***/ function(module, exports, __webpack_require__) {
3619
3620	/* WEBPACK VAR INJECTION */(function(jQuery) {'use strict';
3621
3622	/* global sincos, jQuery */
3623
3624	(function ($) {
3625
3626	    $.productsearch = function (element, options) {
3627
3628	        var productsearch = this;
3629
3630	        var $productsearch_input = $(element);
3631
3632	        productsearch.settings = {};
3633
3634	        // Merge options with defaults
3635	        productsearch.settings = $.extend({
3636	            searchSubmitSelector: '.js-product-search-submit',
3637	            lastSearchString: '',
3638	            resultsWrapper: 'ul',
3639	            resultsWrapperClass: 'product-search__output',
3640	            resultElementWrapper: 'li',
3641	            resultElementWrapperClass: 'product-search__element',
3642	            outputContainerSelector: '.js-product-search__container',
3643	            outputWrapper: '.js-product-search-results',
3644	            extraHitsSelector: '.js-product-search__extra-hits',
3645	            numHitsSelector: '.js-product-search__num-extra-hits',
3646	            noHitsSelector: '.js-product-search__no-hits',
3647	            linkClass: 'themed-nav',
3648	            minQueryLength: 3
3649	        }, options);
3650
3651	        // Init the plugin
3652	        var init = function init() {
3653	            productsearch.output_container = $(productsearch.settings.outputContainerSelector);
3654	            productsearch.output_wrapper = $(productsearch.settings.outputWrapper);
3655	            productsearch.no_hits = $(productsearch.settings.noHitsSelector);
3656	            productsearch.extra_hits = $(productsearch.settings.extraHitsSelector);
3657	            productsearch.num_extra_hits = $(productsearch.settings.numHitsSelector);
3658	            setupListeners();
3659	        };
3660
3661	        // Which events should we listen for
3662	        var setupListeners = function setupListeners() {
3663	            $productsearch_input.on('keydown', function (event) {
3664	                // Blur the field if 'esc' is pressed
3665	                if (event.keyCode == 27) {
3666	                    return $(this).blur();
3667	                }
3668
3669	                // Cannot cache this selector as new search results load async
3670	                var links = productsearch.output_container.find('a.themed-nav:visible'),
3671	                    active = links.filter('.active'),
3672	                    index = $.inArray(active[0] || active, links);
3673
3674	                //Can't do shit with no links
3675	                if (links.length) {
3676	                    //Down/tab 40/9
3677	                    if (event.keyCode == 40 || event.keyCode == 9) {
3678	                        event.preventDefault();
3679
3680	                        var next = Math.min(index + 1, links.length - 1);
3681	                        links.removeClass('active');
3682	                        $(links[next]).addClass('active');
3683	                    }
3684	                    //Up/shift+tab 38/9+
3685	                    if (event.keyCode == 38 || event.keyCode == 9 && event.shiftKey === true) {
3686	                        event.preventDefault();
3687
3688	                        var prev = Math.max(index - 1, -1);
3689	                        links.removeClass('active');
3690	                        //Allow user to deselect results instead of force selecting the first result
3691	                        if (prev > -1) $(links[prev]).addClass('active');
3692	                    }
3693	                    //Return/enter 10/13, if no result is .active then allow user to see search results page when hitting enter
3694	                    if (event.keyCode == 10 || event.keyCode == 13 && active.length) {
3695	                        event.preventDefault();
3696
3697	                        active[0].click(); //Emulate native browser click
3698	                    }
3699	                }
3700	            });
3701	            $productsearch_input.on('change keyup', sincos.functions.debounce(search, 300));
3702	            $productsearch_input.on('focus', focusSearch);
3703	            $productsearch_input.on('blur', sincos.functions.debounce(hideResults, 500));
3704	            productsearch.extra_hits.click(function (event) {
3705	                event.preventDefault();
3706	                $(productsearch.settings.searchSubmitSelector).trigger('click');
3707	            });
3708	        };
3709
3710	        var focusSearch = function focusSearch() {
3711	            if (hasResults()) {
3712	                showResults();
3713	            }
3714	        };
3715
3716	        var setActivityIndicator = function setActivityIndicator() {
3717	            $productsearch_input.closest('form').addClass('search-box--loading');
3718	        },
3719	            resetActivityIndicator = function resetActivityIndicator() {
3720	            $productsearch_input.closest('form').removeClass('search-box--loading');
3721	        };
3722
3723	        var search = function search() {
3724	            var query = getSearchString();
3725
3726	            // Prevent querying the server for the same stuff twice
3727	            // Prevent searching for short search terms
3728	            if (query != productsearch.settings.lastSearchString && query.length >= productsearch.settings.minQueryLength) {
3729	                productsearch.settings.lastSearchString = query;
3730
3731	                setActivityIndicator();
3732	                $.ajax({
3733	                    url: '/search',
3734	                    data: $productsearch_input.serialize(),
3735	                    dataType: 'json'
3736	                }).done(function (data) {
3737	                    outputResults(data);
3738	                }).always(resetActivityIndicator).error(clearResults);
3739	            } else if (query.length < productsearch.settings.minQueryLength) {
3740	                clearResults();
3741	                productsearch.settings.lastSearchString = query;
3742	                resetActivityIndicator();
3743	            }
3744	        };
3745
3746	        var getSearchString = function getSearchString() {
3747	            return $productsearch_input.val().trim();
3748	        };
3749
3750	        var hasValidSearchString = function hasValidSearchString() {
3751	            var query = getSearchString();
3752	            return query.length >= productsearch.settings.minQueryLength;
3753	        };
3754
3755	        var outputResults = function outputResults(results) {
3756	            productsearch.output_container.removeClass('is-hidden');
3757	            $productsearch_input.addClass('is-results');
3758
3759	            var output = $(document.createElement(productsearch.settings.resultsWrapper)).addClass(productsearch.settings.resultsWrapperClass);
3760	            var row = $(document.createElement(productsearch.settings.resultElementWrapper)).addClass(productsearch.settings.resultElementWrapperClass);
3761	            var i = 0;
3762
3763	            $.each(results.produkter, function (index, elem) {
3764	                output.append(row.clone().attr('id', 'prod-' + elem.id).html('<a class="' + productsearch.settings.linkClass + '" href="/produkt/' + elem.sti + '/' + elem.navn + '">' + elem.overskrift + '</a>').on('focusout', sincos.functions.debounce(hideResults, 500)));
3765	                i++;
3766	            });
3767
3768	            // If large number of hits, display number of extra hits
3769	            productsearch.num_extra_hits.text(results.antall - i);
3770
3771	            productsearch.output_container.html(output);
3772
3773	            showResults();
3774
3775	            trackPageView();
3776	        };
3777
3778	        var hasResults = function hasResults() {
3779	            return productsearch.output_container.find(productsearch.settings.resultElementWrapper).length > 0;
3780	        };
3781
3782	        var hasExtraResults = function hasExtraResults() {
3783	            return parseInt(productsearch.num_extra_hits.text(), 10) > 0;
3784	        };
3785
3786	        var showResults = function showResults() {
3787	            if (hasResults()) {
3788	                productsearch.no_hits.addClass('is-hidden');
3789	                productsearch.output_wrapper.removeClass('is-hidden');
3790	                productsearch.output_container.removeClass('is-hidden');
3791	                $productsearch_input.addClass('is-results');
3792
3793	                if (hasExtraResults()) {
3794	                    productsearch.extra_hits.removeClass('is-hidden');
3795	                } else {
3796	                    productsearch.extra_hits.addClass('is-hidden');
3797	                }
3798	            } else if (hasValidSearchString()) {
3799	                displayEmptyResults();
3800	            }
3801	        };
3802
3803	        var trackPageView = function trackPageView() {
3804	            if ('ga' in window) {
3805	                window.ga('send', 'pageview', 'search/?q=' + getSearchString());
3806	            }
3807	        };
3808
3809	        var hideResults = function hideResults() {
3810	            // If focus is not in the resultset, hide the resultset
3811	            if (!$.contains(productsearch.output_wrapper.get(0), document.activeElement)) {
3812	                productsearch.output_wrapper.addClass('is-hidden');
3813	                productsearch.extra_hits.addClass('is-hidden');
3814	                productsearch.output_container.addClass('is-hidden');
3815	                $productsearch_input.removeClass('is-results');
3816	            }
3817	        };
3818
3819	        var clearResults = function clearResults() {
3820	            productsearch.output_container.empty().addClass('is-hidden');
3821	            $productsearch_input.removeClass('is-results');
3822	            productsearch.output_wrapper.addClass('is-hidden');
3823	            productsearch.extra_hits.addClass('is-hidden');
3824	            productsearch.no_hits.addClass('is-hidden');
3825	        };
3826
3827	        var displayEmptyResults = function displayEmptyResults() {
3828	            productsearch.no_hits.removeClass('is-hidden');
3829	            productsearch.extra_hits.addClass('is-hidden');
3830	            productsearch.output_wrapper.removeClass('is-hidden');
3831	        };
3832
3833	        init();
3834	    };
3835
3836	    $.fn.productsearch = function (options) {
3837	        return this.each(function () {
3838	            if (undefined === $(this).data('productsearch')) {
3839	                var plugin = new $.productsearch(this, options);
3840	                $(this).data('productsearch', plugin);
3841	            }
3842	        });
3843	    };
3844		})(jQuery);
3845	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
3846
3847/***/ },
3848
3849/***/ 212:
3850/***/ function(module, exports, __webpack_require__) {
3851
3852	/* WEBPACK VAR INJECTION */(function(jQuery) {'use strict';
3853
3854	/*!
3855	 * SmartMenus jQuery Plugin - v0.9.7 - August 25, 2014
3856	 * http://www.smartmenus.org/
3857	 *
3858	 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd.
3859	 * http://vadikom.com
3860	 *
3861	 * Licensed MIT
3862	 */
3863
3864	(function ($) {
3865
3866		var menuTrees = [],
3867		    IE = !!window.createPopup,
3868		    // detect it for the iframe shim
3869		mouse = false,
3870		    // optimize for touch by default - we will detect for mouse input
3871		mouseDetectionEnabled = false;
3872
3873		// Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.)
3874		function initMouseDetection(disable) {
3875			var eNS = '.smartmenus_mouse';
3876			if (!mouseDetectionEnabled && !disable) {
3877				// if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present
3878				// in practice, this seems like impossible to trick unintentianally with a real mouse and a pretty safe detection on touch devices (even with older browsers that do not support touch events)
3879				var firstTime = true,
3880				    lastMove = null;
3881				$(document).bind(getEventsNS([['mousemove', function (e) {
3882					var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() };
3883					if (lastMove) {
3884						var deltaX = Math.abs(lastMove.x - thisMove.x),
3885						    deltaY = Math.abs(lastMove.y - thisMove.y);
3886						if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) {
3887							mouse = true;
3888							// if this is the first check after page load, check if we are not over some item by chance and call the mouseenter handler if yes
3889							if (firstTime) {
3890								var $a = $(e.target).closest('a');
3891								if ($a.is('a')) {
3892									$.each(menuTrees, function () {
3893										if ($.contains(this.$root[0], $a[0])) {
3894											this.itemEnter({ currentTarget: $a[0] });
3895											return false;
3896										}
3897									});
3898								}
3899								firstTime = false;
3900							}
3901						}
3902					}
3903					lastMove = thisMove;
3904				}], [touchEvents() ? 'touchstart' : 'pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut', function (e) {
3905					if (isTouchEvent(e.originalEvent)) {
3906						mouse = false;
3907					}
3908				}]], eNS));
3909				mouseDetectionEnabled = true;
3910			} else if (mouseDetectionEnabled && disable) {
3911				$(document).unbind(eNS);
3912				mouseDetectionEnabled = false;
3913			}
3914		}
3915
3916		function isTouchEvent(e) {
3917			return !/^(4|mouse)$/.test(e.pointerType);
3918		}
3919
3920		// we use this just to choose between toucn and pointer events when we need to, not for touch screen detection
3921		function touchEvents() {
3922			return 'ontouchstart' in window;
3923		}
3924
3925		// returns a jQuery bind() ready object
3926		function getEventsNS(defArr, eNS) {
3927			if (!eNS) {
3928				eNS = '';
3929			}
3930			var obj = {};
3931			$.each(defArr, function (index, value) {
3932				obj[value[0].split(' ').join(eNS + ' ') + eNS] = value[1];
3933			});
3934			return obj;
3935		}
3936
3937		$.SmartMenus = function (elm, options) {
3938			this.$root = $(elm);
3939			this.opts = options;
3940			this.rootId = ''; // internal
3941			this.$subArrow = null;
3942			this.subMenus = []; // all sub menus in the tree (UL elms) in no particular order (only real - e.g. UL's in mega sub menus won't be counted)
3943			this.activatedItems = []; // stores last activated A's for each level
3944			this.visibleSubMenus = []; // stores visible sub menus UL's
3945			this.showTimeout = 0;
3946			this.hideTimeout = 0;
3947			this.scrollTimeout = 0;
3948			this.clickActivated = false;
3949			this.zIndexInc = 0;
3950			this.$firstLink = null; // we'll use these for some tests
3951			this.$firstSub = null; // at runtime so we'll cache them
3952			this.disabled = false;
3953			this.$disableOverlay = null;
3954			this.isTouchScrolling = false;
3955			this.init();
3956		};
3957
3958		$.extend($.SmartMenus, {
3959			hideAll: function hideAll() {
3960				$.each(menuTrees, function () {
3961					this.menuHideAll();
3962				});
3963			},
3964			destroy: function destroy() {
3965				while (menuTrees.length) {
3966					menuTrees[0].destroy();
3967				}
3968				initMouseDetection(true);
3969			},
3970			prototype: {
3971				init: function init(refresh) {
3972					var self = this;
3973
3974					if (!refresh) {
3975						menuTrees.push(this);
3976
3977						this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, '');
3978
3979						if (this.$root.hasClass('sm-rtl')) {
3980							this.opts.rightToLeftSubMenus = true;
3981						}
3982
3983						// init root (main menu)
3984						var eNS = '.smartmenus';
3985						this.$root.data('smartmenus', this).attr('data-smartmenus-id', this.rootId).dataSM('level', 1).bind(getEventsNS([['mouseover focusin', $.proxy(this.rootOver, this)], ['mouseout focusout', $.proxy(this.rootOut, this)]], eNS)).delegate('a', getEventsNS([['mouseenter', $.proxy(this.itemEnter, this)], ['mouseleave', $.proxy(this.itemLeave, this)], ['mousedown', $.proxy(this.itemDown, this)], ['focus', $.proxy(this.itemFocus, this)], ['blur', $.proxy(this.itemBlur, this)], ['click', $.proxy(this.itemClick, this)], ['touchend', $.proxy(this.itemTouchEnd, this)]], eNS));
3986
3987						// hide menus on tap or click outside the root UL
3988						eNS += this.rootId;
3989						if (this.opts.hideOnClick) {
3990							$(document).bind(getEventsNS([['touchstart', $.proxy(this.docTouchStart, this)], ['touchmove', $.proxy(this.docTouchMove, this)], ['touchend', $.proxy(this.docTouchEnd, this)],
3991							// for Opera Mobile < 11.5, webOS browser, etc. we'll check click too
3992							['click', $.proxy(this.docClick, this)]], eNS));
3993						}
3994						// hide sub menus on resize
3995						$(window).bind(getEventsNS([['resize orientationchange', $.proxy(this.winResize, this)]], eNS));
3996
3997						if (this.opts.subIndicators) {
3998							this.$subArrow = $('<span/>').addClass('sub-arrow');
3999							if (this.opts.subIndicatorsText) {
4000								this.$subArrow.html(this.opts.subIndicatorsText);
4001							}
4002						}
4003
4004						// make sure mouse detection is enabled
4005						initMouseDetection();
4006					}
4007
4008					// init sub menus
4009					this.$firstSub = this.$root.find('ul').each(function () {
4010						self.menuInit($(this));
4011					}).eq(0);
4012
4013					this.$firstLink = this.$root.find('a').eq(0);
4014
4015					// find current item
4016					if (this.opts.markCurrentItem) {
4017						var reDefaultDoc = /(index|default)\.[^#\?\/]*/i,
4018						    reHash = /#.*/,
4019						    locHref = window.location.href.replace(reDefaultDoc, ''),
4020						    locHrefNoHash = locHref.replace(reHash, '');
4021						this.$root.find('a').each(function () {
4022							var href = this.href.replace(reDefaultDoc, ''),
4023							    $this = $(this);
4024							if (href == locHref || href == locHrefNoHash) {
4025								$this.addClass('current');
4026								if (self.opts.markCurrentTree) {
4027									$this.parent().parentsUntil('[data-smartmenus-id]', 'li').children('a').addClass('current');
4028								}
4029							}
4030						});
4031					}
4032				},
4033				destroy: function destroy() {
4034					this.menuHideAll();
4035					var eNS = '.smartmenus';
4036					this.$root.removeData('smartmenus').removeAttr('data-smartmenus-id').removeDataSM('level').unbind(eNS).undelegate(eNS);
4037					eNS += this.rootId;
4038					$(document).unbind(eNS);
4039					$(window).unbind(eNS);
4040					if (this.opts.subIndicators) {
4041						this.$subArrow = null;
4042					}
4043					var self = this;
4044					$.each(this.subMenus, function () {
4045						if (this.hasClass('mega-menu')) {
4046							this.find('ul').removeDataSM('in-mega');
4047						}
4048						if (this.dataSM('shown-before')) {
4049							if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) {
4050								this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap');
4051							}
4052							if (this.dataSM('scroll-arrows')) {
4053								this.dataSM('scroll-arrows').remove();
4054							}
4055							this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' });
4056						}
4057						if (self.opts.subIndicators) {
4058							this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove();
4059						}
4060						this.removeDataSM('shown-before').removeDataSM('ie-shim').removeDataSM('scroll-arrows').removeDataSM('parent-a').removeDataSM('level').removeDataSM('beforefirstshowfired').parent().removeDataSM('sub');
4061					});
4062					if (this.opts.markCurrentItem) {
4063						this.$root.find('a.current').removeClass('current');
4064					}
4065					this.$root = null;
4066					this.$firstLink = null;
4067					this.$firstSub = null;
4068					if (this.$disableOverlay) {
4069						this.$disableOverlay.remove();
4070						this.$disableOverlay = null;
4071					}
4072					menuTrees.splice($.inArray(this, menuTrees), 1);
4073				},
4074				disable: function disable(noOverlay) {
4075					if (!this.disabled) {
4076						this.menuHideAll();
4077						// display overlay over the menu to prevent interaction
4078						if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) {
4079							var pos = this.$root.offset();
4080							this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({
4081								position: 'absolute',
4082								top: pos.top,
4083								left: pos.left,
4084								width: this.$root.outerWidth(),
4085								height: this.$root.outerHeight(),
4086								zIndex: this.getStartZIndex(true),
4087								opacity: 0
4088							}).appendTo(document.body);
4089						}
4090						this.disabled = true;
4091					}
4092				},
4093				docClick: function docClick(e) {
4094					if (this.isTouchScrolling) {
4095						this.isTouchScrolling = false;
4096						return;
4097					}
4098					// hide on any click outside the menu or on a menu link
4099					if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) {
4100						this.menuHideAll();
4101					}
4102				},
4103				docTouchEnd: function docTouchEnd(e) {
4104					if (!this.lastTouch) {
4105						return;
4106					}
4107					if (this.visibleSubMenus.length && (this.lastTouch.x2 === undefined || this.lastTouch.x1 == this.lastTouch.x2) && (this.lastTouch.y2 === undefined || this.lastTouch.y1 == this.lastTouch.y2) && (!this.lastTouch.target || !$.contains(this.$root[0], this.lastTouch.target))) {
4108						if (this.hideTimeout) {
4109							clearTimeout(this.hideTimeout);
4110							this.hideTimeout = 0;
4111						}
4112						// hide with a delay to prevent triggering accidental unwanted click on some page element
4113						var self = this;
4114						this.hideTimeout = setTimeout(function () {
4115							self.menuHideAll();
4116						}, 350);
4117					}
4118					this.lastTouch = null;
4119				},
4120				docTouchMove: function docTouchMove(e) {
4121					if (!this.lastTouch) {
4122						return;
4123					}
4124					var touchPoint = e.originalEvent.touches[0];
4125					this.lastTouch.x2 = touchPoint.pageX;
4126					this.lastTouch.y2 = touchPoint.pageY;
4127				},
4128				docTouchStart: function docTouchStart(e) {
4129					var touchPoint = e.originalEvent.touches[0];
4130					this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target };
4131				},
4132				enable: function enable() {
4133					if (this.disabled) {
4134						if (this.$disableOverlay) {
4135							this.$disableOverlay.remove();
4136							this.$disableOverlay = null;
4137						}
4138						this.disabled = false;
4139					}
4140				},
4141				getClosestMenu: function getClosestMenu(elm) {
4142					var $closestMenu = $(elm).closest('ul');
4143					while ($closestMenu.dataSM('in-mega')) {
4144						$closestMenu = $closestMenu.parent().closest('ul');
4145					}
4146					return $closestMenu[0] || null;
4147				},
4148				getHeight: function getHeight($elm) {
4149					return this.getOffset($elm, true);
4150				},
4151				// returns precise width/height float values
4152				getOffset: function getOffset($elm, height) {
4153					var old;
4154					if ($elm.css('display') == 'none') {
4155						old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility };
4156						$elm.css({ position: 'absolute', visibility: 'hidden' }).show();
4157					}
4158					var box = $elm[0].getBoundingClientRect && $elm[0].getBoundingClientRect(),
4159					    val = box && (height ? box.height || box.bottom - box.top : box.width || box.right - box.left);
4160					if (!val && val !== 0) {
4161						val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth;
4162					}
4163					if (old) {
4164						$elm.hide().css(old);
4165					}
4166					return val;
4167				},
4168				getStartZIndex: function getStartZIndex(root) {
4169					var zIndex = parseInt(this[root ? '$root' : '$firstSub'].css('z-index'));
4170					if (!root && isNaN(zIndex)) {
4171						zIndex = parseInt(this.$root.css('z-index'));
4172					}
4173					return !isNaN(zIndex) ? zIndex : 1;
4174				},
4175				getTouchPoint: function getTouchPoint(e) {
4176					return e.touches && e.touches[0] || e.changedTouches && e.changedTouches[0] || e;
4177				},
4178				getViewport: function getViewport(height) {
4179					var name = height ? 'Height' : 'Width',
4180					    val = document.documentElement['client' + name],
4181					    val2 = window['inner' + name];
4182					if (val2) {
4183						val = Math.min(val, val2);
4184					}
4185					return val;
4186				},
4187				getViewportHeight: function getViewportHeight() {
4188					return this.getViewport(true);
4189				},
4190				getViewportWidth: function getViewportWidth() {
4191					return this.getViewport();
4192				},
4193				getWidth: function getWidth($elm) {
4194					return this.getOffset($elm);
4195				},
4196				handleEvents: function handleEvents() {
4197					return !this.disabled && this.isCSSOn();
4198				},
4199				handleItemEvents: function handleItemEvents($a) {
4200					return this.handleEvents() && !this.isLinkInMegaMenu($a);
4201				},
4202				isCollapsible: function isCollapsible() {
4203					return this.$firstSub.css('position') == 'static';
4204				},
4205				isCSSOn: function isCSSOn() {
4206					return this.$firstLink.css('display') == 'block';
4207				},
4208				isFixed: function isFixed() {
4209					var isFixed = this.$root.css('position') == 'fixed';
4210					if (!isFixed) {
4211						this.$root.parentsUntil('body').each(function () {
4212							if ($(this).css('position') == 'fixed') {
4213								isFixed = true;
4214								return false;
4215							}
4216						});
4217					}
4218					return isFixed;
4219				},
4220				isLinkInMegaMenu: function isLinkInMegaMenu($a) {
4221					return !$a.parent().parent().dataSM('level');
4222				},
4223				isTouchMode: function isTouchMode() {
4224					return !mouse || this.isCollapsible();
4225				},
4226				itemActivate: function itemActivate($a) {
4227					var $li = $a.parent(),
4228					    $ul = $li.parent(),
4229					    level = $ul.dataSM('level');
4230					// if for some reason the parent item is not activated (e.g. this is an API call to activate the item), activate all parent items first
4231					if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) {
4232						var self = this;
4233						$($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function () {
4234							self.itemActivate($(this).dataSM('parent-a'));
4235						});
4236					}
4237					// hide any visible deeper level sub menus
4238					if (this.visibleSubMenus.length > level) {
4239						this.menuHideSubMenus(!this.activatedItems[level - 1] || this.activatedItems[level - 1][0] != $a[0] ? level - 1 : level);
4240					}
4241					// save new active item and sub menu for this level
4242					this.activatedItems[level - 1] = $a;
4243					this.visibleSubMenus[level - 1] = $ul;
4244					if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) {
4245						return;
4246					}
4247					// show the sub menu if this item has one
4248					var $sub = $li.dataSM('sub');
4249					if ($sub && (this.isTouchMode() || !this.opts.showOnClick || this.clickActivated)) {
4250						this.menuShow($sub);
4251					}
4252				},
4253				itemBlur: function itemBlur(e) {
4254					var $a = $(e.currentTarget);
4255					if (!this.handleItemEvents($a)) {
4256						return;
4257					}
4258					this.$root.triggerHandler('blur.smapi', $a[0]);
4259				},
4260				itemClick: function itemClick(e) {
4261					if (this.isTouchScrolling) {
4262						this.isTouchScrolling = false;
4263						e.stopPropagation();
4264						return false;
4265					}
4266					var $a = $(e.currentTarget);
4267					if (!this.handleItemEvents($a)) {
4268						return;
4269					}
4270					$a.removeDataSM('mousedown');
4271					if (this.$root.triggerHandler('click.smapi', $a[0]) === false) {
4272						return false;
4273					}
4274					var $sub = $a.parent().dataSM('sub');
4275					if (this.isTouchMode()) {
4276						// undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu
4277						if ($a.dataSM('href')) {
4278							$a.attr('href', $a.dataSM('href')).removeDataSM('href');
4279						}
4280						// if the sub is not visible
4281						if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
4282							// try to activate the item and show the sub
4283							this.itemActivate($a);
4284							// if "itemActivate" showed the sub, prevent the click so that the link is not loaded
4285							// if it couldn't show it, then the sub menus are disabled with an !important declaration (e.g. via mobile styles) so let the link get loaded
4286							if ($sub.is(':visible')) {
4287								return false;
4288							}
4289						}
4290					} else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) {
4291						this.clickActivated = true;
4292						this.menuShow($sub);
4293						return false;
4294					}
4295					if ($a.hasClass('disabled')) {
4296						return false;
4297					}
4298					if (this.$root.triggerHandler('select.smapi', $a[0]) === false) {
4299						return false;
4300					}
4301				},
4302				itemDown: function itemDown(e) {
4303					var $a = $(e.currentTarget);
4304					if (!this.handleItemEvents($a)) {
4305						return;
4306					}
4307					$a.dataSM('mousedown', true);
4308				},
4309				itemEnter: function itemEnter(e) {
4310					var $a = $(e.currentTarget);
4311					if (!this.handleItemEvents($a)) {
4312						return;
4313					}
4314					if (!this.isTouchMode()) {
4315						if (this.showTimeout) {
4316							clearTimeout(this.showTimeout);
4317							this.showTimeout = 0;
4318						}
4319						var self = this;
4320						this.showTimeout = setTimeout(function () {
4321							self.itemActivate($a);
4322						}, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout);
4323					}
4324					this.$root.triggerHandler('mouseenter.smapi', $a[0]);
4325				},
4326				itemFocus: function itemFocus(e) {
4327					var $a = $(e.currentTarget);
4328					if (!this.handleItemEvents($a)) {
4329						return;
4330					}
4331					// fix (the mousedown check): in some browsers a tap/click produces consecutive focus + click events so we don't need to activate the item on focus
4332					if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) {
4333						this.itemActivate($a);
4334					}
4335					this.$root.triggerHandler('focus.smapi', $a[0]);
4336				},
4337				itemLeave: function itemLeave(e) {
4338					var $a = $(e.currentTarget);
4339					if (!this.handleItemEvents($a)) {
4340						return;
4341					}
4342					if (!this.isTouchMode()) {
4343						if ($a[0].blur) {
4344							$a[0].blur();
4345						}
4346						if (this.showTimeout) {
4347							clearTimeout(this.showTimeout);
4348							this.showTimeout = 0;
4349						}
4350					}
4351					$a.removeDataSM('mousedown');
4352					this.$root.triggerHandler('mouseleave.smapi', $a[0]);
4353				},
4354				itemTouchEnd: function itemTouchEnd(e) {
4355					var $a = $(e.currentTarget);
4356					if (!this.handleItemEvents($a)) {
4357						return;
4358					}
4359					// prevent the address bar on iPhone from sliding down when expanding a sub menu
4360					var $sub = $a.parent().dataSM('sub');
4361					if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
4362						$a.dataSM('href', $a.attr('href'));
4363						$a.attr('href', '#');
4364					}
4365				},
4366				menuFixLayout: function menuFixLayout($ul) {
4367					// fixes a menu that is being shown for the first time
4368					if (!$ul.dataSM('shown-before')) {
4369						$ul.hide().dataSM('shown-before', true);
4370					}
4371				},
4372				menuHide: function menuHide($sub) {
4373					if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) {
4374						return;
4375					}
4376					$sub.stop(true, true);
4377					if ($sub.is(':visible')) {
4378						var complete = function complete() {
4379							// unset z-index
4380							$sub.css('z-index', '');
4381						};
4382						// if sub is collapsible (mobile view)
4383						if (this.isCollapsible()) {
4384							if (this.opts.collapsibleHideFunction) {
4385								this.opts.collapsibleHideFunction.call(this, $sub, complete);
4386							} else {
4387								$sub.hide(this.opts.collapsibleHideDuration, complete);
4388							}
4389						} else {
4390							if (this.opts.hideFunction) {
4391								this.opts.hideFunction.call(this, $sub, complete);
4392							} else {
4393								$sub.hide(this.opts.hideDuration, complete);
4394							}
4395						}
4396						// remove IE iframe shim
4397						if ($sub.dataSM('ie-shim')) {
4398							$sub.dataSM('ie-shim').remove();
4399						}
4400						// deactivate scrolling if it is activated for this sub
4401						if ($sub.dataSM('scroll')) {
4402							this.menuScrollStop($sub);
4403							$sub.css({ 'touch-action': '', '-ms-touch-action': '' }).unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
4404						}
4405						// unhighlight parent item
4406						$sub.dataSM('parent-a').removeClass('highlighted');
4407						var level = $sub.dataSM('level');
4408						this.activatedItems.splice(level - 1, 1);
4409						this.visibleSubMenus.splice(level - 1, 1);
4410						this.$root.triggerHandler('hide.smapi', $sub[0]);
4411					}
4412				},
4413				menuHideAll: function menuHideAll() {
4414					if (this.showTimeout) {
4415						clearTimeout(this.showTimeout);
4416						this.showTimeout = 0;
4417					}
4418					// hide all subs
4419					this.menuHideSubMenus();
4420					// hide root if it's popup
4421					if (this.opts.isPopup) {
4422						this.$root.stop(true, true);
4423						if (this.$root.is(':visible')) {
4424							if (this.opts.hideFunction) {
4425								this.opts.hideFunction.call(this, this.$root);
4426							} else {
4427								this.$root.hide(this.opts.hideDuration);
4428							}
4429							// remove IE iframe shim
4430							if (this.$root.dataSM('ie-shim')) {
4431								this.$root.dataSM('ie-shim').remove();
4432							}
4433						}
4434					}
4435					this.activatedItems = [];
4436					this.visibleSubMenus = [];
4437					this.clickActivated = false;
4438					// reset z-index increment
4439					this.zIndexInc = 0;
4440				},
4441				menuHideSubMenus: function menuHideSubMenus(level) {
4442					if (!level) level = 0;
4443					for (var i = this.visibleSubMenus.length - 1; i > level; i--) {
4444						this.menuHide(this.visibleSubMenus[i]);
4445					}
4446				},
4447				menuIframeShim: function menuIframeShim($ul) {
4448					// create iframe shim for the menu
4449					if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
4450						$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }).css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }));
4451					}
4452				},
4453				menuInit: function menuInit($ul) {
4454					if (!$ul.dataSM('in-mega')) {
4455						this.subMenus.push($ul);
4456						// mark UL's in mega drop downs (if any) so we can neglect them
4457						if ($ul.hasClass('mega-menu')) {
4458							$ul.find('ul').dataSM('in-mega', true);
4459						}
4460						// get level (much faster than, for example, using parentsUntil)
4461						var level = 2,
4462						    par = $ul[0];
4463						while ((par = par.parentNode.parentNode) != this.$root[0]) {
4464							level++;
4465						}
4466						// cache stuff
4467						$ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)).dataSM('level', level).parent().dataSM('sub', $ul);
4468						// add sub indicator to parent item
4469						if (this.opts.subIndicators) {
4470							$ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone());
4471						}
4472					}
4473				},
4474				menuPosition: function menuPosition($sub) {
4475					var $a = $sub.dataSM('parent-a'),
4476					    $ul = $sub.parent().parent(),
4477					    level = $sub.dataSM('level'),
4478					    subW = this.getWidth($sub),
4479					    subH = this.getHeight($sub),
4480					    itemOffset = $a.offset(),
4481					    itemX = itemOffset.left,
4482					    itemY = itemOffset.top,
4483					    itemW = this.getWidth($a),
4484					    itemH = this.getHeight($a),
4485					    $win = $(window),
4486					    winX = $win.scrollLeft(),
4487					    winY = $win.scrollTop(),
4488					    winW = this.getViewportWidth(),
4489					    winH = this.getViewportHeight(),
4490					    horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'),
4491					    subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
4492					    subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
4493					    x,
4494					    y;
4495					if (horizontalParent) {
4496						x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX;
4497						y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
4498					} else {
4499						x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : itemW - subOffsetX;
4500						y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
4501					}
4502					if (this.opts.keepInViewport && !this.isCollapsible()) {
4503						var absX = itemX + x,
4504						    absY = itemY + y;
4505						if (this.opts.rightToLeftSubMenus && absX < winX) {
4506							x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
4507						} else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + winW) {
4508							x = horizontalParent ? winX + winW - subW - absX + x : subOffsetX - subW;
4509						}
4510						if (!horizontalParent) {
4511							if (subH < winH && absY + subH > winY + winH) {
4512								y += winY + winH - subH - absY;
4513							} else if (subH >= winH || absY < winY) {
4514								y += winY - absY;
4515							}
4516						}
4517						// do we need scrolling?
4518						// 0.49 used for better precision when dealing with float values
4519						if (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49) {
4520							var self = this;
4521							if (!$sub.dataSM('scroll-arrows')) {
4522								$sub.dataSM('scroll-arrows', $([$('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0], $('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]]).bind({
4523									mouseenter: function mouseenter() {
4524										$sub.dataSM('scroll').up = $(this).hasClass('scroll-up');
4525										self.menuScroll($sub);
4526									},
4527									mouseleave: function mouseleave(e) {
4528										self.menuScrollStop($sub);
4529										self.menuScrollOut($sub, e);
4530									},
4531									'mousewheel DOMMouseScroll': function mousewheelDOMMouseScroll(e) {
4532										e.preventDefault();
4533									}
4534								}).insertAfter($sub));
4535							}
4536							// bind scroll events and save scroll data for this sub
4537							var eNS = '.smartmenus_scroll';
4538							$sub.dataSM('scroll', {
4539								step: 1,
4540								// cache stuff for faster recalcs later
4541								itemH: itemH,
4542								subH: subH,
4543								arrowDownH: this.getHeight($sub.dataSM('scroll-arrows').eq(1))
4544							}).bind(getEventsNS([['mouseover', function (e) {
4545								self.menuScrollOver($sub, e);
4546							}], ['mouseout', function (e) {
4547								self.menuScrollOut($sub, e);
4548							}], ['mousewheel DOMMouseScroll', function (e) {
4549								self.menuScrollMousewheel($sub, e);
4550							}]], eNS)).dataSM('scroll-arrows').css({ top: 'auto', left: '0', marginLeft: x + (parseInt($sub.css('border-left-width')) || 0), width: subW - (parseInt($sub.css('border-left-width')) || 0) - (parseInt($sub.css('border-right-width')) || 0), zIndex: $sub.css('z-index') }).eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
4551							// when a menu tree is fixed positioned we allow scrolling via touch too
4552							// since there is no other way to access such long sub menus if no mouse is present
4553							if (this.isFixed()) {
4554								$sub.css({ 'touch-action': 'none', '-ms-touch-action': 'none' }).bind(getEventsNS([[touchEvents() ? 'touchstart touchmove touchend' : 'pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp', function (e) {
4555									self.menuScrollTouch($sub, e);
4556								}]], eNS));
4557							}
4558						}
4559					}
4560					$sub.css({ top: 'auto', left: '0', marginLeft: x, marginTop: y - itemH });
4561					// IE iframe shim
4562					this.menuIframeShim($sub);
4563					if ($sub.dataSM('ie-shim')) {
4564						$sub.dataSM('ie-shim').css({ zIndex: $sub.css('z-index'), width: subW, height: subH, marginLeft: x, marginTop: y - itemH });
4565					}
4566				},
4567				menuScroll: function menuScroll($sub, once, step) {
4568					var data = $sub.dataSM('scroll'),
4569					    $arrows = $sub.dataSM('scroll-arrows'),
4570					    y = parseFloat($sub.css('margin-top')),
4571					    end = data.up ? data.upEnd : data.downEnd,
4572					    diff;
4573					if (!once && data.velocity) {
4574						data.velocity *= 0.9;
4575						diff = data.velocity;
4576						if (diff < 0.5) {
4577							this.menuScrollStop($sub);
4578							return;
4579						}
4580					} else {
4581						diff = step || (once || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor(data.step));
4582					}
4583					// hide any visible deeper level sub menus
4584					var level = $sub.dataSM('level');
4585					if (this.visibleSubMenus.length > level) {
4586						this.menuHideSubMenus(level - 1);
4587					}
4588					var newY = data.up && end <= y || !data.up && end >= y ? y : Math.abs(end - y) > diff ? y + (data.up ? diff : -diff) : end;
4589					$sub.add($sub.dataSM('ie-shim')).css('margin-top', newY);
4590					// show opposite arrow if appropriate
4591					if (mouse && (data.up && newY > data.downEnd || !data.up && newY < data.upEnd)) {
4592						$arrows.eq(data.up ? 1 : 0).show();
4593					}
4594					// if we've reached the end
4595					if (newY == end) {
4596						if (mouse) {
4597							$arrows.eq(data.up ? 0 : 1).hide();
4598						}
4599						this.menuScrollStop($sub);
4600					} else if (!once) {
4601						if (this.opts.scrollAccelerate && data.step < this.opts.scrollStep) {
4602							data.step += 0.5;
4603						}
4604						var self = this;
4605						this.scrollTimeout = setTimeout(function () {
4606							self.menuScroll($sub);
4607						}, this.opts.scrollInterval);
4608					}
4609				},
4610				menuScrollMousewheel: function menuScrollMousewheel($sub, e) {
4611					if (this.getClosestMenu(e.target) == $sub[0]) {
4612						e = e.originalEvent;
4613						var up = (e.wheelDelta || -e.detail) > 0;
4614						if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
4615							$sub.dataSM('scroll').up = up;
4616							this.menuScroll($sub, true);
4617						}
4618					}
4619					e.preventDefault();
4620				},
4621				menuScrollOut: function menuScrollOut($sub, e) {
4622					if (mouse) {
4623						if (!/^scroll-(up|down)/.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || this.getClosestMenu(e.relatedTarget) != $sub[0])) {
4624							$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
4625						}
4626					}
4627				},
4628				menuScrollOver: function menuScrollOver($sub, e) {
4629					if (mouse) {
4630						if (!/^scroll-(up|down)/.test(e.target.className) && this.getClosestMenu(e.target) == $sub[0]) {
4631							this.menuScrollRefreshData($sub);
4632							var data = $sub.dataSM('scroll');
4633							$sub.dataSM('scroll-arrows').eq(0).css('margin-top', data.upEnd).end().eq(1).css('margin-top', data.downEnd + data.subH - data.arrowDownH).end().css('visibility', 'visible');
4634						}
4635					}
4636				},
4637				menuScrollRefreshData: function menuScrollRefreshData($sub) {
4638					var data = $sub.dataSM('scroll'),
4639					    $win = $(window),
4640					    vportY = $win.scrollTop() - $sub.dataSM('parent-a').offset().top - data.itemH;
4641					$.extend(data, {
4642						upEnd: vportY,
4643						downEnd: vportY + this.getViewportHeight() - data.subH
4644					});
4645				},
4646				menuScrollStop: function menuScrollStop($sub) {
4647					if (this.scrollTimeout) {
4648						clearTimeout(this.scrollTimeout);
4649						this.scrollTimeout = 0;
4650						$.extend($sub.dataSM('scroll'), {
4651							step: 1,
4652							velocity: 0
4653						});
4654						return true;
4655					}
4656				},
4657				menuScrollTouch: function menuScrollTouch($sub, e) {
4658					e = e.originalEvent;
4659					if (isTouchEvent(e)) {
4660						var touchPoint = this.getTouchPoint(e);
4661						// neglect event if we touched a visible deeper level sub menu
4662						if (this.getClosestMenu(touchPoint.target) == $sub[0]) {
4663							var data = $sub.dataSM('scroll');
4664							if (/(start|down)$/i.test(e.type)) {
4665								if (this.menuScrollStop($sub)) {
4666									// if we were scrolling, just stop and don't activate any link on the first touch
4667									e.preventDefault();
4668									this.isTouchScrolling = true;
4669								} else {
4670									this.isTouchScrolling = false;
4671								}
4672								// update scroll data since the user might have zoomed, etc.
4673								this.menuScrollRefreshData($sub);
4674								// extend it with the touch properties
4675								$.extend(data, {
4676									touchY: touchPoint.pageY,
4677									touchTimestamp: e.timeStamp,
4678									velocity: 0
4679								});
4680							} else if (/move$/i.test(e.type)) {
4681								var prevY = data.touchY;
4682								if (prevY !== undefined && prevY != touchPoint.pageY) {
4683									this.isTouchScrolling = true;
4684									$.extend(data, {
4685										up: prevY < touchPoint.pageY,
4686										touchY: touchPoint.pageY,
4687										touchTimestamp: e.timeStamp,
4688										velocity: data.velocity + Math.abs(touchPoint.pageY - prevY) * 0.5
4689									});
4690									this.menuScroll($sub, true, Math.abs(data.touchY - prevY));
4691								}
4692								e.preventDefault();
4693							} else {
4694								// touchend/pointerup
4695								if (data.touchY !== undefined) {
4696									// check if we need to scroll
4697									if (e.timeStamp - data.touchTimestamp < 120 && data.velocity > 0) {
4698										data.velocity *= 0.5;
4699										this.menuScrollStop($sub);
4700										this.menuScroll($sub);
4701										e.preventDefault();
4702									}
4703									delete data.touchY;
4704								}
4705							}
4706						}
4707					}
4708				},
4709				menuShow: function menuShow($sub) {
4710					if (!$sub.dataSM('beforefirstshowfired')) {
4711						$sub.dataSM('beforefirstshowfired', true);
4712						if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
4713							return;
4714						}
4715					}
4716					if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
4717						return;
4718					}
4719					this.menuFixLayout($sub);
4720					$sub.stop(true, true);
4721					if (!$sub.is(':visible')) {
4722						// set z-index
4723						$sub.css('z-index', this.zIndexInc = (this.zIndexInc || this.get
4723StartZIndex()) + 1);
4724						// highlight parent item
4725						if (this.opts.keepHighlighted || this.isCollapsible()) {
4726							$sub.dataSM('parent-a').addClass('highlighted');
4727						}
4728						// min/max-width fix - no way to rely purely on CSS as all UL's are nested
4729						if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
4730							$sub.css({ width: 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
4731							if (this.opts.subMenusMinWidth) {
4732								$sub.css('min-width', this.opts.subMenusMinWidth);
4733							}
4734							if (this.opts.subMenusMaxWidth) {
4735								var noMaxWidth = this.getWidth($sub);
4736								$sub.css('max-width', this.opts.subMenusMaxWidth);
4737								if (noMaxWidth > this.getWidth($sub)) {
4738									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
4739								}
4740							}
4741						}
4742						this.menuPosition($sub);
4743						// insert IE iframe shim
4744						if ($sub.dataSM('ie-shim')) {
4745							$sub.dataSM('ie-shim').insertBefore($sub);
4746						}
4747						var complete = function complete() {
4748							// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
4749							$sub.css('overflow', '');
4750						};
4751						// if sub is collapsible (mobile view)
4752						if (this.isCollapsible()) {
4753							if (this.opts.collapsibleShowFunction) {
4754								this.opts.collapsibleShowFunction.call(this, $sub, complete);
4755							} else {
4756								$sub.show(this.opts.collapsibleShowDuration, complete);
4757							}
4758						} else {
4759							if (this.opts.showFunction) {
4760								this.opts.showFunction.call(this, $sub, complete);
4761							} else {
4762								$sub.show(this.opts.showDuration, complete);
4763							}
4764						}
4765						// save new sub menu for this level
4766						this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub;
4767						this.$root.triggerHandler('show.smapi', $sub[0]);
4768					}
4769				},
4770				popupHide: function popupHide(noHideTimeout) {
4771					if (this.hideTimeout) {
4772						clearTimeout(this.hideTimeout);
4773						this.hideTimeout = 0;
4774					}
4775					var self = this;
4776					this.hideTimeout = setTimeout(function () {
4777						self.menuHideAll();
4778					}, noHideTimeout ? 1 : this.opts.hideTimeout);
4779				},
4780				popupShow: function popupShow(left, top) {
4781					if (!this.opts.isPopup) {
4782						alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
4783						return;
4784					}
4785					if (this.hideTimeout) {
4786						clearTimeout(this.hideTimeout);
4787						this.hideTimeout = 0;
4788					}
4789					this.menuFixLayout(this.$root);
4790					this.$root.stop(true, true);
4791					if (!this.$root.is(':visible')) {
4792						this.$root.css({ left: left, top: top });
4793						// IE iframe shim
4794						this.menuIframeShim(this.$root);
4795						if (this.$root.dataSM('ie-shim')) {
4796							this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left: left, top: top }).insertBefore(this.$root);
4797						}
4798						// show menu
4799						var self = this,
4800						    complete = function complete() {
4801							self.$root.css('overflow', '');
4802						};
4803						if (this.opts.showFunction) {
4804							this.opts.showFunction.call(this, this.$root, complete);
4805						} else {
4806							this.$root.show(this.opts.showDuration, complete);
4807						}
4808						this.visibleSubMenus[0] = this.$root;
4809					}
4810				},
4811				refresh: function refresh() {
4812					this.menuHideAll();
4813					this.$root.find('ul').each(function () {
4814						var $this = $(this);
4815						if ($this.dataSM('scroll-arrows')) {
4816							$this.dataSM('scroll-arrows').remove();
4817						}
4818					}).removeDataSM('in-mega').removeDataSM('shown-before').removeDataSM('ie-shim').removeDataSM('scroll-arrows').removeDataSM('parent-a').removeDataSM('level').removeDataSM('beforefirstshowfired');
4819					this.$root.find('a.has-submenu').removeClass('has-submenu').parent().removeDataSM('sub');
4820					if (this.opts.subIndicators) {
4821						this.$root.find('span.sub-arrow').remove();
4822					}
4823					if (this.opts.markCurrentItem) {
4824						this.$root.find('a.current').removeClass('current');
4825					}
4826					this.subMenus = [];
4827					this.init(true);
4828				},
4829				rootOut: function rootOut(e) {
4830					if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
4831						return;
4832					}
4833					if (this.hideTimeout) {
4834						clearTimeout(this.hideTimeout);
4835						this.hideTimeout = 0;
4836					}
4837					if (!this.opts.showOnClick || !this.opts.hideOnClick) {
4838						var self = this;
4839						this.hideTimeout = setTimeout(function () {
4840							self.menuHideAll();
4841						}, this.opts.hideTimeout);
4842					}
4843				},
4844				rootOver: function rootOver(e) {
4845					if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
4846						return;
4847					}
4848					if (this.hideTimeout) {
4849						clearTimeout(this.hideTimeout);
4850						this.hideTimeout = 0;
4851					}
4852				},
4853				winResize: function winResize(e) {
4854					if (!this.handleEvents()) {
4855						// we still need to resize the disable overlay if it's visible
4856						if (this.$disableOverlay) {
4857							var pos = this.$root.offset();
4858							this.$disableOverlay.css({
4859								top: pos.top,
4860								left: pos.left,
4861								width: this.$root.outerWidth(),
4862								height: this.$root.outerHeight()
4863							});
4864						}
4865						return;
4866					}
4867					// hide sub menus on resize - on mobile do it only on orientation change
4868					if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) {
4869						if (this.activatedItems.length) {
4870							this.activatedItems[this.activatedItems.length - 1][0].blur();
4871						}
4872						this.menuHideAll();
4873					}
4874				}
4875			}
4876		});
4877
4878		$.fn.dataSM = function (key, val) {
4879			if (val) {
4880				return this.data(key + '_smartmenus', val);
4881			}
4882			return this.data(key + '_smartmenus');
4883		};
4884
4885		$.fn.removeDataSM = function (key) {
4886			return this.removeData(key + '_smartmenus');
4887		};
4888
4889		$.fn.smartmenus = function (options) {
4890			if (typeof options == 'string') {
4891				var args = arguments,
4892				    method = options;
4893				Array.prototype.shift.call(args);
4894				return this.each(function () {
4895					var smartmenus = $(this).data('smartmenus');
4896					if (smartmenus && smartmenus[method]) {
4897						smartmenus[method].apply(smartmenus, args);
4898					}
4899				});
4900			}
4901			var opts = $.extend({}, $.fn.smartmenus.defaults, options);
4902			return this.each(function () {
4903				new $.SmartMenus(this, opts);
4904			});
4905		};
4906
4907		// default settings
4908		$.fn.smartmenus.defaults = {
4909			isPopup: false, // is this a popup menu (can be shown via the popupS
4909how/popupHide methods) or a permanent menu bar
4910			mainMenuSubOffsetX: 0, // pixels offset from default position
4911			mainMenuSubOffsetY: 0, // pixels offset from default position
4912			subMenusSubOffsetX: 0, // pixels offset from default position
4913			subMenusSubOffsetY: 0, // pixels offset from default position
4914			subMenusMinWidth: '10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
4915			subMenusMaxWidth: '20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
4916			subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A
4917			subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append')
4918			subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
4919			scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height
4920			scrollInterval: 30, // interval between each scrolling step
4921			scrollAccelerate: true, // accelerate scrolling or use a fixed step
4922			showTimeout: 250, // timeout before showing the sub menus
4923			hideTimeout: 500, // timeout before hiding the sub menus
4924			showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null
4925			showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show')
4926			// don't forget to call complete() at the end of whatever you do
4927			// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
4928			hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
4929			hideFunction: function hideFunction($ul, complete) {
4930				$ul.fadeOut(200, complete);
4931			}, // custom function to use when hiding a sub menu (the default is the jQuery 'hide')
4932			// don't forget to call complete() at the end of whatever you do
4933			// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
4934			collapsibleShowDuration: 0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
4935			collapsibleShowFunction: function collapsibleShowFunction($ul, complete) {
4936				$ul.slideDown(200, complete);
4937			}, // custom function to use when showing a collapsible sub menu
4938			// (i.e. when mobile styles are used to make the sub menus collapsible)
4939			collapsibleHideDuration: 0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
4940			collapsibleHideFunction: function collapsibleHideFunction($ul, complete) {
4941				$ul.slideUp(200, complete);
4942			}, // custom function to use when hiding a collapsible sub menu
4943			// (i.e. when mobile styles are used to make the sub menus collapsible)
4944			showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input)
4945			hideOnClick: true, // hide the sub menus on click/tap anywhere on the page
4946			keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport
4947			keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
4948			markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL
4949			markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item
4950			rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position)
4951			bottomToTopSubMenus: false, // bottom to top display of the sub menus
4952			overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
4953		};
4954		})(jQuery);
4955	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
4956
4957/***/ },
4958
4959/***/ 213:
4960/***/ function(module, exports, __webpack_require__) {
4961
4962	/* WEBPACK VAR INJECTION */(function(jQuery) {'use strict';
4963
4964	/*!
4965	 * SmartMenus jQuery Plugin Keyboard Addon - v0.1.0 - August 25, 2014
4966	 * http://www.smartmenus.org/
4967	 *
4968	 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd.
4969	 * http://vadikom.com
4970	 *
4971	 * Licensed MIT
4972	 */
4973
4974	(function ($) {
4975
4976		function getFirstItemLink($ul) {
4977			return $ul.find('> li > a:not(.disabled)').eq(0);
4978		}
4979		function getLastItemLink($ul) {
4980			return $ul.find('> li > a:not(.disabled)').eq(-1);
4981		}
4982		function getNextItemLink($li, noLoop) {
4983			var $a = $li.nextAll('li').children('a:not(.disabled)').eq(0);
4984			return noLoop || $a.length ? $a : getFirstItemLink($li.parent());
4985		}
4986		function getPreviousItemLink($li, noLoop) {
4987			var $a = $li.prevAll('li').children('a:not(.disabled)').eq(0);
4988			return noLoop || $a.length ? $a : getLastItemLink($li.parent());
4989		}
4990
4991		// jQuery's .focus() is unreliable in some versions, so we're going to call the links' native JS focus method
4992		$.fn.focusSM = function () {
4993			if (this.length && this[0].focus) {
4994				this[0].focus();
4995			}
4996			return this;
4997		};
4998
4999		$.extend($.SmartMenus.Keyboard = {}, {
5000			docKeydown: function docKeydown(e) {
5001				var keyCode = e.keyCode;
5002				if (!/(27|37|38|39|40)/.test(keyCode)) {
5003					return;
5004				}
5005				var $root = $(this),
5006				    obj = $root.data('smartmenus'),
5007				    $target = $(e.target);
5008				if (!obj || !$target.is('a')) {
5009					return;
5010				}
5011				var $li = $target.parent(),
5012				    $ul = $li.parent(),
5013				    level = $ul.dataSM('level');
5014				// exit it if this is an A inside a mega drop-down
5015				if (!level) {
5016					return;
5017				}
5018				// swap left & right keys
5019				if (obj.opts.rightToLeftSubMenus) {
5020					if (keyCode == 37) {
5021						keyCode = 39;
5022					} else if (keyCode == 39) {
5023						keyCode = 37;
5024					}
5025				}
5026				switch (keyCode) {
5027					case 27:
5028						// Esc
5029						if (obj.visibleSubMenus[level]) {
5030							obj.menuHide(obj.visibleSubMenus[level]);
5031						} else if (level == 1) {
5032							if (obj.opts.isPopup) {
5033								obj.menuHideAll();
5034							}
5035							if (obj.opts.keyboardEscapeFocus) {
5036								try {
5037									obj.opts.keyboardEscapeFocus.focusSM();
5038								} catch (e) {};
5039								// focus next focusable page element
5040							} else {
5041									var $lastMenuFocusable = $root.find('a, input, select, button, textarea').eq(-1),
5042									    $allFocusables = $('a, input, select, button, textarea'),
5043									    nextFocusableIndex = $allFocusables.index($lastMenuFocusable[0]) + 1;
5044									$allFocusables.eq(nextFocusableIndex).focusSM();
5045								}
5046						} else {
5047							$ul.dataSM('parent-a').focusSM();
5048							obj.menuHide(obj.visibleSubMenus[level - 1]);
5049						}
5050						break;
5051					case 37:
5052						// Left
5053						if (obj.isCollapsible()) {
5054							break;
5055						}
5056						if (level > 2 || level == 2 && $root.hasClass('sm-vertical')) {
5057							obj.activatedItems[level - 2].focusSM();
5058							// move to previous non-disabled parent item (make sure we cycle so it might be the last item)
5059						} else if (!$root.hasClass('sm-vertical')) {
5060								getPreviousItemLink(obj.activatedItems[0].parent()).focusSM();
5061							}
5062						break;
5063					case 38:
5064						// Up
5065						if (obj.isCollapsible()) {
5066							var $firstItem;
5067							// if this is the first item of a sub menu, move to the parent item
5068							if (level > 1 && ($firstItem = getFirstItemLink($ul)).length && $target[0] == $firstItem[0]) {
5069								obj.activatedItems[level - 2].focusSM();
5070							} else {
5071								getPreviousItemLink($li).focusSM();
5072							}
5073						} else {
5074							if (level == 1 && !$root.hasClass('sm-vertical') && obj.visibleSubMenus[level] && obj.opts.bottomToTopSubMenus) {
5075								getLastItemLink(obj.visibleSubMenus[level]).focusSM();
5076							} else if (level > 1 || $root.hasClass('sm-vertical')) {
5077								getPreviousItemLink($li).focusSM();
5078							}
5079						}
5080						break;
5081					case 39:
5082						// Right
5083						if (obj.isCollapsible()) {
5084							break;
5085						}
5086						// move to next non-disabled parent item (make sure we cycle so it might be the last item)
5087						if ((level == 1 || !obj.visibleSubMenus[level]) && !$root.hasClass('sm-vertical')) {
5088							getNextItemLink(obj.activatedItems[0].parent()).focusSM();
5089						} else if (obj.visibleSubMenus[level] && !obj.visibleSubMenus[level].hasClass('mega-menu')) {
5090							getFirstItemLink(obj.visibleSubMenus[level]).focusSM();
5091						}
5092						break;
5093					case 40:
5094						// Down
5095						if (obj.isCollapsible()) {
5096							var $firstSubItem, $lastItem;
5097							// move to sub menu if appropriate
5098							if (obj.visibleSubMenus[level] && !obj.visibleSubMenus[level].hasClass('mega-menu') && ($firstSubItem = getFirstItemLink(obj.visibleSubMenus[level])).length) {
5099								$firstSubItem.focusSM();
5100								// if this is the last item of a sub menu, move to the next parent item
5101							} else if (level > 1 && ($lastItem = getLastItemLink($ul)).length && $target[0] == $lastItem[0]) {
5102									var $parentItem = obj.activatedItems[level - 2].parent(),
5103									    $nextParentItem = null;
5104									while ($parentItem.is('li')) {
5105										if (($nextParentItem = getNextItemLink($parentItem, true)).length) {
5106											break;
5107										}
5108										$parentItem = $parentItem.parent().parent();
5109									}
5110									$nextParentItem.focusSM();
5111								} else {
5112									getNextItemLink($li).focusSM();
5113								}
5114						} else {
5115							if (level == 1 && !$root.hasClass('sm-vertical') && obj.visibleSubMenus[level] && !obj.opts.bottomToTopSubMenus) {
5116								getFirstItemLink(obj.visibleSubMenus[level]).focusSM();
5117							} else if (level > 1 || $root.hasClass('sm-vertical')) {
5118								getNextItemLink($li).focusSM();
5119							}
5120						}
5121						break;
5122				}
5123				e.stopPropagation();
5124				e.preventDefault();
5125			}
5126		});
5127
5128		// hook it
5129		$(document).delegate('ul.sm', 'keydown.smartmenus', $.SmartMenus.Keyboard.docKeydown);
5130
5131		$.extend($.SmartMenus.prototype, {
5132			keyboardSetEscapeFocus: function keyboardSetEscapeFocus($elm) {
5133				this.opts.keyboardEscapeFocus = $elm;
5134			},
5135			keyboardSetHotkey: function keyboardSetHotkey(keyCode, modifiers) {
5136				var self = this;
5137				$(document).bind('keydown.smartmenus' + this.rootId, function (e) {
5138					if (keyCode == e.keyCode) {
5139						var procede = true;
5140						if (modifiers) {
5141							if (typeof modifiers == 'string') {
5142								modifiers = [modifiers];
5143							}
5144							$.each(['ctrlKey', 'shiftKey', 'altKey', 'metaKey'], function (index, value) {
5145								if ($.inArray(value, modifiers) >= 0 && !e[value] || $.inArray(value, modifiers) < 0 && e[value]) {
5146									procede = false;
5147									return false;
5148								}
5149							});
5150						}
5151						if (procede) {
5152							getFirstItemLink(self.$root).focusSM();
5153							e.stopPropagation();
5154							e.preventDefault();
5155						}
5156					}
5157				});
5158			}
5159		});
5160		})(jQuery);
5161	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
5162
5163/***/ },
5164
5165/***/ 215:
5166/***/ function(module, exports, __webpack_require__) {
5167
5168	/* WEBPACK VAR INJECTION */(function(jQuery) {'use strict';
5169
5170	(function ($) {
5171
5172	    $.fn.wishlistButton = function (options) {
5173
5174	        var wishlistBtn = this;
5175	        wishlistBtn.settings = {};
5176
5177	        // Merge options with defaults
5178	        wishlistBtn.settings = $.extend({
5179	            productFormSelector: '.product__form'
5180	        }, options);
5181
5182	        // Init the cart plugin
5183	        var init = function init() {
5184
5185	            wishlistBtn.click(function () {
5186	                if (wishlistBtn.hasClass('disabled')) {
5187	                    $.growl({ message: wishlistBtn.data('disabled-msg'), type: 'info' });
5188	                } else {
5189	                    $.post("/ajax/onskeliste", $(wishlistBtn.settings.productFormSelector).serialize(), function () {
5190	                        $.growl({ message: wishlistBtn.data('success') });
5191	                        trackAddToWishlist();
5192	                    });
5193	                    return false;
5194	                }
5195	            });
5196	        };
5197
5198	        var trackAddToWishlist = function trackAddToWishlist() {
5199	            if ('ga' in window) {
5200	                window.ga('send', 'event', {
5201	                    eventCategory: 'Wishlist',
5202	                    eventAction: 'Added product to wishlist',
5203	                    eventLabel: $('.product__title').text() + ', id ' + $('input[name="id"]').val()
5204	                });
5205	            }
5206	        };
5207
5208	        init();
5209	    };
5210		})(jQuery);
5211	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
5212
5213/***/ },
5214
5215/***/ 217:
5216/***/ function(module, exports, __webpack_require__) {
5217
5218	/* WEBPACK VAR INJECTION */(function($) {'use strict';
5219
5220	$(function () {
5221	    var navOpenButton = $('#nav-open-btn');
5222	    var navOpenCheckbox = $('#nav-open-checkbox');
5223	    var html = $('html');
5224	    var navClass = 'js-nav';
5225
5226	    html.addClass('js-ready');
5227
5228	    if (navOpenButton.length > 0) {
5229	        navOpenButton.click(function (event) {
5230	            event.preventDefault();
5231	            html.toggleClass(navClass);
5232	        });
5233	    } else {
5234	        if (navOpenCheckbox.length > 0) {
5235	            navOpenCheckbox.change(function () {
5236	                html.toggleClass(navClass);
5237	            });
5238	        }
5239	    }
5240
5241	    $('#nav-close-btn').click(function (event) {
5242	        event.preventDefault();
5243	        html.toggleClass(navClass);
5244
5245	        if (navOpenCheckbox.length > 0) {
5246	            navOpenCheckbox.prop('checked', false);
5247	        }
5248	    });
5249	});
5250	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
5251
5252/***/ },
5253
5254/***/ 218:
5255/***/ function(module, exports, __webpack_require__) {
5256
5257	/* WEBPACK VAR INJECTION */(function(jQuery, $) {'use strict';
5258
5259	// Version three of the sincos script collection
5260	/* jshint esversion: 6 */
5261	/* global Foundation, Modernizr, jQuery, $ */
5262
5263	if (!window.sincos) window.sincos = { 'settings': {}, 'functions': {}, 'behaviors': {}, 'themes': {}, 'locale': {} };
5264	var sincos = window.sincos;
5265	sincos.jsEnabled = true;
5266
5267	sincos.attachBehaviors = function (context) {
5268	    context = context || document;
5269	    jQuery.each(sincos.behaviors, function () {
5270	        this(context);
5271	    });
5272	};
5273
5274	// Slider
5275	sincos.behaviors.bxslider = function () {
5276	    var slider_selector = '.js-product-image-slider';
5277	    var prod_img_slider = $(slider_selector).bxSlider({
5278	        captions: true,
5279	        adaptiveHeight: true,
5280	        adaptiveHeightSpeed: 200,
5281	        speed: 300,
5282	        pagerCustom: '#js-product-image-slider-thumbs',
5283	        onSliderLoad: function onSliderLoad(currentIndex) {
5284	            // set tabindex=0 for the current slide
5285	            $(slider_selector + ' > :not(.bx-clone):eq(' + currentIndex + ') > .bx-slide').attr('tabindex', 0);
5286	            $('.product__images').addClass('slider-loaded');
5287	        },
5288	        onSlideAfter: function onSlideAfter(elem) {
5289	            // set tabindex=0 for active slide, -1 for others
5290	            elem.find('.bx-slide').attr('tabindex', 0);
5291	            elem.siblings().find('.bx-slide').attr('tabindex', -1);
5292	        }
5293	    });
5294
5295	    // Add keybord navigation if we have only one slider on the page
5296	    // and if focus is not in another item that uses arrow key navigation
5297	    if (prod_img_slider.length === 1) {
5298	        $('html').keydown(function (e) {
5299	            if (e.keyCode === 39 || e.keyCode === 37) {
5300	                if ($(':focus').parents('.js-arrow-key-nav').length === 0 && $(':focus').parents('form').length === 0 && !$('.fancybox-wrap').is(':visible')) {
5301	                    if (e.keyCode === 39) {
5302	                        prod_img_slider.goToNextSlide();
5303	                    } else if (e.keyCode === 37) {
5304	                        prod_img_slider.goToPrevSlide();
5305	                    }
5306	                }
5307	            }
5308	        });
5309	    }
5310	};
5311
5312	// See jquery.cart.js
5313	sincos.behaviors.cart = function () {
5314	    var cart_btn = $('.cart-button');
5315	    cart_btn.cart();
5316	    sincos.cart = cart_btn.data('cart');
5317	};
5318
5319	sincos.behaviors.addToCart = function () {
5320	    $('.js-product__buy-button').one("click", function (e) {
5321	        var parent = $(this).parents('[itemtype="http://schema.org/Product"]');
5322	        var productId = parent.find("[data-product-id]").data("product-id");
5323	        var price = parent.find('meta[itemprop="price"]').attr("content");
5324	        var currency = parent.find('.offers').find('meta[itemprop="priceCurrency"]').attr("content");
5325
5326	        $(document).trigger("productAddedToCart", [productId, price, currency]);
5327	    });
5328	};
5329
5330	sincos.behaviors.addBundleToCartOne = function () {
5331	    $('.js-bundle__buy-button').one("click", function (e) {
5332	        var parent = $(this).parents('[itemtype="http://schema.org/Product"]');
5333	        var productId = parent.find("[data-product-id]").data("product-id");
5334	        var price = parent.find('meta[itemprop="price"]').attr("content");
5335	        var currency = parent.find('.offers').find('meta[itemprop="priceCurrency"]').attr("content");
5336
5337	        $(document).trigger("productAddedToCart", [productId, price, currency]);
5338	    });
5339	};
5340
5341	// Init smartmenus
5342	if (typeof $.fn.smartmenus == "function") {
5343	    sincos.behaviors.smartmenus = function () {
5344	        var context = arguments.length <= 0 || arguments[0] === undefined ? document : arguments[0];
5345	        var selector = arguments.length <= 1 || arguments[1] === undefined ? '#main-menu' : arguments[1];
5346	        var dynamic = arguments[2];
5347	        var mediumUp = arguments[3];
5348
5349	        //@TODO rewrite to use $menu.smartmenus('refresh'); instead of dom cloning toggling display
5350	        if (dynamic !== false) {
5351	            var label = $(selector).data('mer') || 'Mer';
5352	            var submenu = $('<li class="main-nav__item parent level-0 main-nav__item--more"><a href="#">' + label + '</a><ul class="main-nav__submenu level-1"></ul></li>');
5353	            var clones = $(selector + ' > li').clone();
5354	            submenu.find('.main-nav__submenu.level-1').append(clones);
5355	            submenu.find('li').each(function (key, el) {
5356	                var $el = $(el);
5357	                var level = $(el).parents('ul').length;
5358
5359	                $el.removeClass('level-' + (level - 1)).addClass('level-' + level);
5360	                $el.children('ul').removeClass('level-' + level).addClass('level-' + (level + 1));
5361	            });
5362	            $(selector).append(submenu);
5363	        }
5364
5365	        $(selector).smartmenus({
5366	            'subIndicators': false,
5367	            'subMenusMinWidth': false,
5368	            'subMenusMaxWidth': false,
5369	            'keepInViewport': true,
5370	            'hideDuration': 300,
5371	            'hideTimeout': 600,
5372	            'hideOnClick': false //Only needed when menus are shown on click, not :hover
5373	        });
5374	        // Prevent crash edge cases on slower iOS devices
5375	        $(document).off('touchstart.smartmenus_mouse');
5376
5377	        var refreshThrottle,
5378	            menu = $(selector),
5379	            section = menu.parent(),
5380	            lastChild = menu.children().not('.main-nav__item--more').filter(':last').addClass('main-nav__item--last-child'),
5381	            handleResize = function handleResize(e) {
5382	            // Only do this when we're not in tablet mode or mobile
5383	            if (window.Foundation && !Foundation.utils[mediumUp ? 'is_medium_up' : 'is_large_up']()) {
5384	                menu.children().css('display', '');
5385	                menu.find('.main-nav__item--more').hide();
5386
5387	                return e;
5388	            }
5389
5390	            var getOuterWidth = function getOuterWidth(el) {
5391	                return el[0] && el.outerWidth(true) || 0;
5392	            };
5393
5394	            var moreMenuWidth = getOuterWidth(menu.find('.main-nav__item--more'));
5395	            var offsetPadding = getOuterWidth(menu.find('li:visible > .main-nav__frontpage-link'));
5396	            var availableWidth = menu.innerWidth();
5397
5398	            var growing = 0;
5399
5400	            var startedHiding = false;
5401	            menu.children().each(function (key, el) {
5402	                var $el = $(el);
5403	                if ($el.is('.main-nav__item--more')) return;
5404
5405	                var width = $el.is(':first-child:not(:visible)') ? 0 : getOuterWidth($el);
5406	                growing += width;
5407	                // Add a 5px margin of error
5408	                if (growing + 5 >= availableWidth) {
5409	                    $el.hide();
5410	                    menu.find('.main-nav__item--more > ul').children(':eq(' + key + ')').css('display', '');
5411
5412	                    // Check if there is not enough room to render the More button
5413	                    if (availableWidth < growing + 5 - width + moreMenuWidth && !startedHiding) {
5414	                        $el.prev().hide();
5415	                        menu.find('.main-nav__item--more > ul').children(':eq(' + (key - 1) + ')').css('display', '');
5416	                        startedHiding = true;
5417	                    }
5418	                } else {
5419	                    $el.css('display', '');
5420	                    menu.find('.main-nav__item--more > ul').children(':eq(' + key + ')').hide();
5421	                }
5422	            });
5423
5424	            menu.find('.main-nav__item--more').css({
5425	                'display': menu.find('.main-nav__item--more > ul').children(':not([style*="display: none"])').length === 0 ? 'none' : ''
5426	            }).toggleClass('selected', menu.find('.main-nav__item--more .selected:not([style*="display: none"])').length > 0);
5427
5428	            // Refresh throttle
5429	            clearTimeout(refreshThrottle);
5430	            refreshThrottle = setTimeout(function () {
5431	                menu.smartmenus('refresh');
5432	            }, 3000);
5433	        };
5434
5435	        if (dynamic !== false) {
5436	            $(window).on('resize load sticky_nav_change', handleResize);
5437	            handleResize();
5438	        }
5439	    };
5440	}
5441
5442	// Ajax product search - Disabled for now
5443	sincos.behaviors.productsearch = function () {
5444	    var product_search_field = $('.js-product-search');
5445	    product_search_field.productsearch();
5446	    sincos.productsearch = product_search_field.data('productsearch');
5447	};
5448
5449	// Easier styling of search inputs with focus states than pure css :focus
5450	sincos.behaviors.searchsugar = function () {
5451	    $('input.search-box__input').on({
5452	        focus: function focus() {
5453	            $(this).addClass('active');
5454	        },
5455	        blur: function blur() {
5456	            var value = this.value.trim();
5457	            if (!value.length || value === this.defaultValue) $(this).removeClass('active');
5458	        }
5459	    });
5460	};
5461
5462	sincos.behaviors.fancybox = function () {
5463	    // Use fancybox for product image popup big medium screens and up
5464	    if (window.Modernizr && window.Foundation && Modernizr.mq(Foundation.media_queries.medium)) {
5465	        // Avoid including clones in the gallery, which are created by the bxslider
5466	        $('.js-fancybox-gallery > li:not(.bx-clone) > .product__main-images__link').fancybox();
5467	    } else {
5468	        $('.product__main-images__link').click(function (event) {
5469	            event.preventDefault();
5470	        });
5471	    }
5472
5473	    // Use fancybox for the login popup in the checkout
5474	    $(".js-login-popup").fancybox({
5475	        padding: 20,
5476	        minWidth: 250,
5477	        maxWidth: 400,
5478	        fitToView: true,
5479	        autoSize: true,
5480	        closeClick: false,
5481	        scrolling: 'no',
5482	        openEffect: 'none',
5483	        closeEffect: 'none'
5484	    });
5485
5486	    $('.js-checkout-login-close').click(function () {
5487	        $.fancybox.close();
5488	    });
5489	};
5490
5491	// Initialize tabs
5492	sincos.behaviors.tabs = function () {
5493	    $('.js-tabs').easyResponsiveTabs();
5494	};
5495
5496	// See jquery.wishlist.js
5497	sincos.behaviors.onskeliste = function () {
5498	    $('.product__wishlist-button').wishlistButton();
5499	};
5500
5501	// Handle ajax submissions on product review forms
5502	sincos.behaviors.review_form = function (context) {
5503	    $('.js-review-form .button', context).each(function () {
5504	        $(this).click(function () {
5505	            $.post("/ajax/produktanmeldelse", $(".js-review-form").serialize(), function (data) {
5506	                $('.js-review-form').html(data);
5507	                $('#produkt_anmeldelser_form_validert').each(function () {
5508	                    $('.js-review-form .button').hide();
5509	                    $('.comments-guidelines').hide();
5510	                });
5511	            });
5512	            return false;
5513	        });
5514	    });
5515	};
5516
5517	// Close the parent element when clicking .close buttons
5518	sincos.behaviors.close = function () {
5519	    $('body').on('click', '.close', function () {
5520	        $(this).parent().slideUp('fast');
5521	    });
5522	};
5523
5524	/**
5525	 * Toggle visibility of element(s)
5526	 * @return {void} [description]
5527	 */
5528	sincos.behaviors.showHide = function () {
5529	    $('.js-toggle-visibility').click(function (event) {
5530	        var btn = $(this);
5531	        if (btn.prop('tagName') === 'A') {
5532	            event.preventDefault();
5533	        }
5534
5535	        var toggle_toggler_class = btn.data('toggle-toggler-class') || 'toggled';
5536
5537	        if (btn.data('close') !== 'undefined') {
5538	            $(btn.data('close')).slideUp('fast');
5539	        }
5540
5541	        sincos.functions.showHide(btn.data('toggle'));
5542	        btn.toggleClass(toggle_toggler_class);
5543
5544	        if (btn.data('toggle-close-label') !== 'undefined') {
5545	            var temp = btn.html();
5546	            btn.html(btn.data('toggle-close-label'));
5547	            btn.data('toggle-close-label', temp);
5548	        }
5549	    });
5550	};
5551
5552	sincos.behaviors.stateful = function () {
5553	    var stateful_forms = $('.js-stateful');
5554
5555	    $.each(stateful_forms, function (index, value) {
5556	        var form = $(value);
5557	        var form_submit = form.find('[type="submit"]');
5558	        var form_state = form.serialize();
5559	        form_submit.attr('disabled', true);
5560
5561	        form.find('select, input, textarea').on('change keyup', function () {
5562	            if (form.serialize() !== form_state) {
5563	                form_submit.attr('disabled', false);
5564	            } else {
5565	                form_submit.attr('disabled', true);
5566	            }
5567	        });
5568	    });
5569	};
5570
5571	sincos.behaviors.byttmva = function (context) {
5572	    $('.bytt_mva').click(function (event) {
5573	        event.preventDefault();
5574	        $("#bytt_mva_form").submit();
5575	    });
5576	};
5577
5578	sincos.behaviors.cookie_notice = function () {
5579	    $('#cookie_notice_remove').click(function () {
5580	        document.cookie = 'cookie_notice=0; path=/; max-age=' + 60 * 60 * 24 * 365;
5581	        $('.cookie_notice').hide();
5582	        return false;
5583	    });
5584	};
5585
5586	document.cookie = 'javascript=1; path=/';
5587
5588	sincos.functions.showHide = function (selector) {
5589	    $(selector).animate({
5590	        height: 'toggle',
5591	        opacity: 'toggle'
5592	    }, 200).toggleClass('toggled');
5593	};
5594
5595	sincos.functions.cancel_login = function () {
5596	    $('.kasse_one_logginn_cancel').click(function () {
5597	        $.fancybox.close();
5598	    });
5599	};
5600
5601	/**
5602	 * Debounce, for throttling function calls
5603	 * @param  {object} fn    function oblect
5604	 * @param  {int}       delay ms delay
5605	 * @return {object}       function
5606	 */
5607	sincos.functions.debounce = function (fn, delay_input) {
5608	    var timer = null;
5609	    var delay = delay_input || 500;
5610	    return function () {
5611	        var context = this,
5612	            args = arguments;
5613	        clearTimeout(timer);
5614	        timer = setTimeout(function () {
5615	            fn.apply(context, args);
5616	        }, delay);
5617	    };
5618	};
5619
5620	// Attach all behaviors.
5621	$(function () {
5622	    sincos.attachBehaviors(window);
5623	});
5624	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2), __webpack_require__(2)))
5625
5626/***/ },
5627
5628/***/ 219:
5629/***/ function(module, exports, __webpack_require__) {
5630
5631	/* WEBPACK VAR INJECTION */(function(jQuery) {'use strict';
5632
5633	// Easy Responsive Tabs Plugin
5634	// Author: Samson.Onna <Email : [email protected]>
5635	// https://github.com/samsono/Easy-Responsive-Tabs-to-Accordion/
5636	(function ($) {
5637	    $.fn.extend({
5638	        easyResponsiveTabs: function easyResponsiveTabs(options) {
5639	            //Set the default values, use comma to separate the settings, example:
5640	            var defaults = {
5641	                type: 'default', //default, vertical, accordion;
5642	                width: 'auto',
5643	                fit: true,
5644	                closed: false,
5645	                activate: function activate() {}
5646	            };
5647
5648	            //Variables
5649	            var options = $.extend(defaults, options);
5650	            var opt = options,
5651	                jtype = opt.type,
5652	                jfit = opt.fit,
5653	                jwidth = opt.width,
5654	                vtabs = 'vertical',
5655	                accord = 'accordion';
5656	            var hash = window.location.hash;
5657	            var historyApi = !!(window.history && history.replaceState);
5658
5659	            //Events
5660	            $(this).bind('tabactivate', function (e, currentTab) {
5661	                if (typeof options.activate === 'function') {
5662	                    options.activate.call(currentTab, e);
5663	                }
5664	            });
5665
5666	            //Main function
5667	            this.each(function () {
5668	                var $respTabs = $(this);
5669	                var $respTabsList = $respTabs.find('ul.resp-tabs-list');
5670	                var respTabsId = $respTabs.attr('id');
5671	                $respTabs.find('ul.resp-tabs-list li').addClass('resp-tab-item');
5672	                $respTabs.css({
5673	                    'display': 'block',
5674	                    'width': jwidth
5675	                });
5676
5677	                $respTabs.find('.resp-tabs-container > div').addClass('resp-tab-content');
5678	                jtab_options();
5679	                //Properties Function
5680	                function jtab_options() {
5681	                    if (jtype == vtabs) {
5682	                        $respTabs.addClass('resp-vtabs');
5683	                    }
5684	                    if (jfit == true) {
5685	                        $respTabs.css({ width: '100%', margin: '0px' });
5686	                    }
5687	                    if (jtype == accord) {
5688	                        $respTabs.addClass('resp-easy-accordion');
5689	                        $respTabs.find('.resp-tabs-list').css('display', 'none');
5690	                    }
5691	                }
5692
5693	                //Assigning the h2 markup to accordion title
5694	                var $tabItemh2;
5695	                $respTabs.find('.resp-tab-content').before("<h2 class='resp-accordion' tabindex='0' role='tab'><span class='resp-arrow'></span></h2>");
5696
5697	                var itemCount = 0;
5698	                $respTabs.find('.resp-accordion').each(function () {
5699	                    $tabItemh2 = $(this);
5700	                    var $tabItem = $respTabs.find('.resp-tab-item:eq(' + itemCount + ')');
5701	                    var $accItem = $respTabs.find('.resp-accordion:eq(' + itemCount + ')');
5702	                    $accItem.append($tabItem.html());
5703	                    $accItem.data($tabItem.data());
5704	                    $tabItemh2.attr('aria-controls', 'tab_item-' + itemCount);
5705	                    itemCount++;
5706	                });
5707
5708	                //Assigning the 'aria-controls' to Tab items
5709	                var count = 0;
5710	                $respTabs.find('.resp-tab-item').each(function () {
5711	                    var $tabItem = $(this);
5712	                    $tabItem.attr('aria-controls', 'tab_item-' + count);
5713	                    $tabItem.attr('role', 'tab');
5714
5715	                    //Assigning the 'aria-labelledby' attr to tab-content
5716	                    var tabcount = 0;
5717	                    $respTabs.find('.resp-tab-content').each(function () {
5718	                        var $tabContent = $(this);
5719	                        $tabContent.attr('aria-labelledby', 'tab_item-' + tabcount);
5720	                        tabcount++;
5721	                    });
5722	                    count++;
5723	                });
5724
5725	                // Show correct content area
5726	                var tabNum = 0;
5727	                if (hash != '') {
5728	                    var matches = hash.match(new RegExp(respTabsId + "([0-9]+)"));
5729	                    if (matches !== null && matches.length === 2) {
5730	                        tabNum = parseInt(matches[1], 10) - 1;
5731	                        if (tabNum > count) {
5732	                            tabNum = 0;
5733	                        }
5734	                    }
5735	                }
5736
5737	                //Active correct tab
5738	                $($respTabs.find('.resp-tab-item')[tabNum]).addClass('resp-tab-active');
5739
5740	                //keep closed if option = 'closed' or option is 'accordion' and the element is in accordion mode
5741	                if (options.closed !== true && !(options.closed === 'accordion' && !$respTabsList.is(':visible')) && !(options.closed === 'tabs' && $respTabsList.is(':visible'))) {
5742	                    $($respTabs.find('.resp-accordion')[tabNum]).addClass('resp-tab-active');
5743	                    $($respTabs.find('.resp-tab-content')[tabNum]).addClass('resp-tab-content-active').attr('style', 'display:block');
5744	                }
5745	                //assign proper classes for when tabs mode is activated before making a selection in accordion mode
5746	                else {
5747	                        $($respTabs.find('.resp-tab-content')[tabNum]).addClass('resp-tab-content-active resp-accordion-closed');
5748	                    }
5749
5750	                //Tab Click action function
5751	                $respTabs.find("[role=tab]").each(function () {
5752
5753	                    var $currentTab = $(this);
5754
5755	                    $currentTab.keypress(function (e) {
5756	                        if (e.keyCode == 13 || e.keyCode == 32) {
5757	                            $currentTab.click();
5758	                        }
5759	                    });
5760
5761	                    $currentTab.click(function () {
5762
5763	                        var $currentTab = $(this);
5764	                        var $tabAria = $currentTab.attr('aria-controls');
5765
5766	                        if ($currentTab.hasClass('resp-accordion') && $currentTab.hasClass('resp-tab-active')) {
5767	                            $respTabs.find('.resp-tab-content-active').slideUp('', function () {
5768	                                $(this).addClass('resp-accordion-closed');
5769	                            });
5770	                            $currentTab.removeClass('resp-tab-active');
5771	                            return false;
5772	                        }
5773	                        if (!$currentTab.hasClass('resp-tab-active') && $currentTab.hasClass('resp-accordion')) {
5774	                            $respTabs.find('.resp-tab-active').removeClass('resp-tab-active');
5775	                            $respTabs.find('.resp-tab-content-active').slideUp().removeClass('resp-tab-content-active resp-accordion-closed');
5776	                            $respTabs.find("[aria-controls=" + $tabAria + "]").addClass('resp-tab-active');
5777
5778	                            $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').slideDown().addClass('resp-tab-content-active');
5779	                        } else {
5780	                            $respTabs.find('.resp-tab-active').removeClass('resp-tab-active');
5781	                            $respTabs.find('.resp-tab-content-active').removeAttr('style').removeClass('resp-tab-content-active').removeClass('resp-accordion-closed');
5782	                            $respTabs.find("[aria-controls=" + $tabAria + "]").addClass('resp-tab-active');
5783	                            $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').addClass('resp-tab-content-active').attr('style', 'display:block');
5784	                        }
5785	                        //Trigger tab activation event
5786	                        $currentTab.trigger('tabactivate', $currentTab);
5787
5788	                        //Update Browser History
5789	                        if (historyApi) {
5790	                            var currentHash = window.location.hash;
5791	                            var newHash = respTabsId + (parseInt($tabAria.substring(9), 10) + 1).toString();
5792	                            if (currentHash != "") {
5793	                                var re = new RegExp(respTabsId + "[0-9]+");
5794	                                if (currentHash.match(re) != null) {
5795	                                    newHash = currentHash.replace(re, newHash);
5796	                                } else {
5797	                                    newHash = currentHash + "|" + newHash;
5798	                                }
5799	                            } else {
5800	                                newHash = '#' + newHash;
5801	                            }
5802
5803	                            history.replaceState(null, null, newHash);
5804	                        }
5805	                    });
5806	                });
5807
5808	                //Window resize function                  
5809	                $(window).resize(function () {
5810	                    $respTabs.find('.resp-accordion-closed').removeAttr('style');
5811	                });
5812	            });
5813	        }
5814	    });
5815		})(jQuery);
5816	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
5817
5818/***/ },
5819
5820/***/ 253:
5821/***/ function(module, exports, __webpack_require__) {
5822
5823	'use strict';
5824
5825	// Keyboard navigation for the menu on large screens
5826	if (window.Modernizr && window.Foundation && Modernizr.mq(Foundation.media_queries.large)) {
5827	    // Load the smartmenus keyboard only when needed, keeping the main theme.checkout.js small
5828	    //require.ensure([], function(){
5829	    __webpack_require__(213);
5830	    //}, 'jquery.smartmenus_keyboard');
5831	}
5832
5833	// Polyfill for equal height column grid
5834	if (window.Modernizr && !Modernizr.flexbox) {
5835	    // Load the smartmenus keyboard only when needed, keeping the main theme.checkout.js small
5836	    //require.ensure([], function(){
5837	    __webpack_require__(202);
5838	    //}, 'equal_height_columns');
5839	}
5840
5841	// If on product page, load thumb connector script
5842	if (document.location.pathname.indexOf("/produkt/") === 0 && window.FEATURES.get('thumb_attribute_connection')) {
5843	    __webpack_require__.e/* nsure */(3, function () {
5844	        __webpack_require__(123);
5845	    });
5846	}
5847
5848	// Load RCT tag tracking
5849	if (window.FEATURES.get('abandoncart_email')) {
5850	    __webpack_require__.e/* nsure */(1, function () {
5851	        __webpack_require__(474);
5852	    });
5853	}
5854
5855	if (window.FEATURES.get('facebook_dpa')) {
5856	    __webpack_require__.e/* nsure */(2, function () {
5857	        __webpack_require__(473);
5858	    });
5859	}
5860
5861	// Fastclick for touch screens
5862	/* Deactivated until we can prevent double click events from happening
5863	if(Modernizr.touch) {
5864	    require.ensure([], function(){
5865	        var FastClick = require('assets/fastclick');
5866	        jQuery(function() {
5867	             FastClick.attach(document.body);
5868	         });
5869	    }, 'fastclick');
5870	}
5871	//*/
5872
5873/***/ }
5874
5875});
5876//# sourceMappingURL=theme.js.map

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.