/* * jQuery Superfish Menu Plugin - v1.7.10 * Copyright (c) 2018 Joel Birch * * Dual licensed under the MIT and GPL licenses: * //www.opensource.org/licenses/mit-license.php * //www.gnu.org/licenses/gpl.html */ ;(function ($, w) { "use strict"; var methods = (function () { // private properties and methods go here var c = { bcClass: 'sf-breadcrumb', menuClass: 'sf-js-enabled', anchorClass: 'sf-with-ul', menuArrowClass: 'sf-arrows' }, ios = (function () { var ios = /^(?![\w\W]*Windows Phone)[\w\W]*(iPhone|iPad|iPod)/i.test(navigator.userAgent); if (ios) { // tap anywhere on iOS to unfocus a submenu $('html').css('cursor', 'pointer').on('click', $.noop); } return ios; })(), wp7 = (function () { var style = document.documentElement.style; return ('behavior' in style && 'fill' in style && /iemobile/i.test(navigator.userAgent)); })(), unprefixedPointerEvents = (function () { return (!!w.PointerEvent); })(), toggleMenuClasses = function ($menu, o, add) { var classes = c.menuClass, method; if (o.cssArrows) { classes += ' ' + c.menuArrowClass; } method = (add) ? 'addClass' : 'removeClass'; $menu[method](classes); }, setPathToCurrent = function ($menu, o) { return $menu.find('li.' + o.pathClass).slice(0, o.pathLevels) .addClass(o.hoverClass + ' ' + c.bcClass) .filter(function () { return ($(this).children(o.popUpSelector).hide().show().length); }).removeClass(o.pathClass); }, toggleAnchorClass = function ($li, add) { var method = (add) ? 'addClass' : 'removeClass'; $li.children('a')[method](c.anchorClass); }, toggleTouchAction = function ($menu) { var msTouchAction = $menu.css('ms-touch-action'); var touchAction = $menu.css('touch-action'); touchAction = touchAction || msTouchAction; touchAction = (touchAction === 'pan-y') ? 'auto' : 'pan-y'; $menu.css({ 'ms-touch-action': touchAction, 'touch-action': touchAction }); }, getMenu = function ($el) { return $el.closest('.' + c.menuClass); }, getOptions = function ($el) { return getMenu($el).data('sfOptions'); }, over = function () { var $this = $(this), o = getOptions($this); clearTimeout(o.sfTimer); $this.siblings().superfish('hide').end().superfish('show'); }, close = function (o) { o.retainPath = ($.inArray(this[0], o.$path) > -1); this.superfish('hide'); if (!this.parents('.' + o.hoverClass).length) { o.onIdle.call(getMenu(this)); if (o.$path.length) { $.proxy(over, o.$path)(); } } }, out = function () { var $this = $(this), o = getOptions($this); if (ios) { $.proxy(close, $this, o)(); } else { clearTimeout(o.sfTimer); o.sfTimer = setTimeout($.proxy(close, $this, o), o.delay); } }, touchHandler = function (e) { var $this = $(this), o = getOptions($this), $ul = $this.siblings(e.data.popUpSelector); if (o.onHandleTouch.call($ul) === false) { return this; } if ($ul.length > 0 && $ul.is(':hidden')) { $this.one('click.superfish', false); if (e.type === 'MSPointerDown' || e.type === 'pointerdown') { $this.trigger('focus'); } else { $.proxy(over, $this.parent('li'))(); } } }, applyHandlers = function ($menu, o) { var targets = 'li:has(' + o.popUpSelector + ')'; if ($.fn.hoverIntent && !o.disableHI) { $menu.hoverIntent(over, out, targets); } else { $menu .on('mouseenter.superfish', targets, over) .on('mouseleave.superfish', targets, out); } var touchevent = 'MSPointerDown.superfish'; if (unprefixedPointerEvents) { touchevent = 'pointerdown.superfish'; } if (!ios) { touchevent += ' touchend.superfish'; } if (wp7) { touchevent += ' mousedown.superfish'; } $menu .on('focusin.superfish', 'li', over) .on('focusout.superfish', 'li', out) .on(touchevent, 'a', o, touchHandler); }; return { // public methods hide: function (instant) { if (this.length) { var $this = this, o = getOptions($this); if (!o) { return this; } var not = (o.retainPath === true) ? o.$path : '', $ul = $this.find('li.' + o.hoverClass).add(this).not(not).removeClass(o.hoverClass).children(o.popUpSelector), speed = o.speedOut; if (instant) { $ul.show(); speed = 0; } o.retainPath = false; if (o.onBeforeHide.call($ul) === false) { return this; } $ul.stop(true, true).animate(o.animationOut, speed, function () { var $this = $(this); o.onHide.call($this); }); } return this; }, show: function () { var o = getOptions(this); if (!o) { return this; } var $this = this.addClass(o.hoverClass), $ul = $this.children(o.popUpSelector); if (o.onBeforeShow.call($ul) === false) { return this; } $ul.stop(true, true).animate(o.animation, o.speed, function () { o.onShow.call($ul); }); return this; }, destroy: function () { return this.each(function () { var $this = $(this), o = $this.data('sfOptions'), $hasPopUp; if (!o) { return false; } $hasPopUp = $this.find(o.popUpSelector).parent('li'); clearTimeout(o.sfTimer); toggleMenuClasses($this, o); toggleAnchorClass($hasPopUp); toggleTouchAction($this); // remove event handlers $this.off('.superfish').off('.hoverIntent'); // clear animation's inline display style $hasPopUp.children(o.popUpSelector).attr('style', function (i, style) { if (typeof style !== 'undefined') { return style.replace(/display[^;]+;?/g, ''); } }); // reset 'current' path classes o.$path.removeClass(o.hoverClass + ' ' + c.bcClass).addClass(o.pathClass); $this.find('.' + o.hoverClass).removeClass(o.hoverClass); o.onDestroy.call($this); $this.removeData('sfOptions'); }); }, init: function (op) { return this.each(function () { var $this = $(this); if ($this.data('sfOptions')) { return false; } var o = $.extend({}, $.fn.superfish.defaults, op), $hasPopUp = $this.find(o.popUpSelector).parent('li'); o.$path = setPathToCurrent($this, o); $this.data('sfOptions', o); toggleMenuClasses($this, o, true); toggleAnchorClass($hasPopUp, true); toggleTouchAction($this); applyHandlers($this, o); $hasPopUp.not('.' + c.bcClass).superfish('hide', true); o.onInit.call(this); }); } }; })(); $.fn.superfish = function (method, args) { if (methods[method]) { return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); } else if (typeof method === 'object' || ! method) { return methods.init.apply(this, arguments); } else { return $.error('Method ' + method + ' does not exist on jQuery.fn.superfish'); } }; $.fn.superfish.defaults = { popUpSelector: 'ul,.sf-mega', // within menu context hoverClass: 'sfHover', pathClass: 'overrideThisToUse', pathLevels: 1, delay: 800, animation: {opacity: 'show'}, animationOut: {opacity: 'hide'}, speed: 'normal', speedOut: 'fast', cssArrows: true, disableHI: false, onInit: $.noop, onBeforeShow: $.noop, onShow: $.noop, onBeforeHide: $.noop, onHide: $.noop, onIdle: $.noop, onDestroy: $.noop, onHandleTouch: $.noop }; })(jQuery, window); /*! * Modernizr v2.8.3 * www.modernizr.com * * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton * Available under the BSD and MIT licenses: www.modernizr.com/license/ */ /* * Modernizr tests which native CSS3 and HTML5 features are available in * the current UA and makes the results available to you in two ways: * as properties on a global Modernizr object, and as classes on the * element. This information allows you to progressively enhance * your pages with a granular level of control over the experience. * * Modernizr has an optional (not included) conditional resource loader * called Modernizr.load(), based on Yepnope.js (yepnopejs.com). * To get a build that includes Modernizr.load(), as well as choosing * which tests to include, go to www.modernizr.com/download/ * * Authors Faruk Ates, Paul Irish, Alex Sexton * Contributors Ryan Seddon, Ben Alman */ window.Modernizr = (function( window, document, undefined ) { var version = '2.8.3', Modernizr = {}, /*>>cssclasses*/ // option for enabling the HTML classes to be added enableClasses = true, /*>>cssclasses*/ docElement = document.documentElement, /** * Create our "modernizr" element that we do most feature tests on. */ mod = 'modernizr', modElem = document.createElement(mod), mStyle = modElem.style, /** * Create the input element for various Web Forms feature tests. */ inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ , /*>>smile*/ smile = ':)', /*>>smile*/ toString = {}.toString, // TODO :: make the prefixes more granular /*>>prefixes*/ // List of property values to set for css tests. See ticket #21 prefixes = ' -webkit- -moz- -o- -ms- '.split(' '), /*>>prefixes*/ /*>>domprefixes*/ // Following spec is to expose vendor-specific style properties as: // elem.style.WebkitBorderRadius // and the following would be incorrect: // elem.style.webkitBorderRadius // Webkit ghosts their properties in lowercase but Opera & Moz do not. // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+ // erik.eae.net/archives/2008/03/10/21.48.10/ // More here: github.com/Modernizr/Modernizr/issues/issue/21 omPrefixes = 'Webkit Moz O ms', cssomPrefixes = omPrefixes.split(' '), domPrefixes = omPrefixes.toLowerCase().split(' '), /*>>domprefixes*/ /*>>ns*/ ns = {'svg': '//www.w3.org/2000/svg'}, /*>>ns*/ tests = {}, inputs = {}, attrs = {}, classes = [], slice = classes.slice, featureName, // used in testing loop /*>>teststyles*/ // Inject element with style element and some CSS rules injectElementWithStyles = function( rule, callback, nodes, testnames ) { var style, ret, node, docOverflow, div = document.createElement('div'), // After page load injecting a fake body doesn't work so check if body exists body = document.body, // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it. fakeBody = body || document.createElement('body'); if ( parseInt(nodes, 10) ) { // In order not to give false positives we create a node for each test // This also allows the method to scale for unspecified uses while ( nodes-- ) { node = document.createElement('div'); node.id = testnames ? testnames[nodes] : mod + (nodes + 1); div.appendChild(node); } } // '].join(''); div.id = mod; // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody. // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270 (body ? div : fakeBody).innerHTML += style; fakeBody.appendChild(div); if ( !body ) { //avoid crashing IE8, if background image is used fakeBody.style.background = ''; //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible fakeBody.style.overflow = 'hidden'; docOverflow = docElement.style.overflow; docElement.style.overflow = 'hidden'; docElement.appendChild(fakeBody); } ret = callback(div, rule); // If this is done after page load we don't want to remove the body so check if body exists if ( !body ) { fakeBody.parentNode.removeChild(fakeBody); docElement.style.overflow = docOverflow; } else { div.parentNode.removeChild(div); } return !!ret; }, /*>>teststyles*/ /*>>mq*/ // adapted from matchMedia polyfill // by Scott Jehl and Paul Irish // gist.github.com/786768 testMediaQuery = function( mq ) { var matchMedia = window.matchMedia || window.msMatchMedia; if ( matchMedia ) { return matchMedia(mq) && matchMedia(mq).matches || false; } var bool; injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) { bool = (window.getComputedStyle ? getComputedStyle(node, null) : node.currentStyle)['position'] == 'absolute'; }); return bool; }, /*>>mq*/ /*>>hasevent*/ // // isEventSupported determines if a given element supports the given event // kangax.github.com/iseventsupported/ // // The following results are known incorrects: // Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative // Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333 // ... isEventSupported = (function() { var TAGNAMES = { 'select': 'input', 'change': 'input', 'submit': 'form', 'reset': 'form', 'error': 'img', 'load': 'img', 'abort': 'img' }; function isEventSupported( eventName, element ) { element = element || document.createElement(TAGNAMES[eventName] || 'div'); eventName = 'on' + eventName; // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those var isSupported = eventName in element; if ( !isSupported ) { // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element if ( !element.setAttribute ) { element = document.createElement('div'); } if ( element.setAttribute && element.removeAttribute ) { element.setAttribute(eventName, ''); isSupported = is(element[eventName], 'function'); // If property was created, "remove it" (by setting value to `undefined`) if ( !is(element[eventName], 'undefined') ) { element[eventName] = undefined; } element.removeAttribute(eventName); } } element = null; return isSupported; } return isEventSupported; })(), /*>>hasevent*/ // TODO :: Add flag for hasownprop ? didn't last time // hasOwnProperty shim by kangax needed for Safari 2.0 support _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) { hasOwnProp = function (object, property) { return _hasOwnProperty.call(object, property); }; } else { hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */ return ((property in object) && is(object.constructor.prototype[property], 'undefined')); }; } // Adapted from ES5-shim //github.com/kriskowal/es5-shim/blob/master/es5-shim.js // es5.github.com/#x15.3.4.5 if (!Function.prototype.bind) { Function.prototype.bind = function bind(that) { var target = this; if (typeof target != "function") { throw new TypeError(); } var args = slice.call(arguments, 1), bound = function () { if (this instanceof bound) { var F = function(){}; F.prototype = target.prototype; var self = new F(); var result = target.apply( self, args.concat(slice.call(arguments)) ); if (Object(result) === result) { return result; } return self; } else { return target.apply( that, args.concat(slice.call(arguments)) ); } }; return bound; }; } /** * setCss applies given styles to the Modernizr DOM node. */ function setCss( str ) { mStyle.cssText = str; } /** * setCssAll extrapolates all vendor-specific css strings. */ function setCssAll( str1, str2 ) { return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); } /** * is returns a boolean for if typeof obj is exactly type. */ function is( obj, type ) { return typeof obj === type; } /** * contains returns a boolean for if substr is found within str. */ function contains( str, substr ) { return !!~('' + str).indexOf(substr); } /*>>testprop*/ // testProps is a generic CSS / DOM property test. // In testing support for a given CSS property, it's legit to test: // `elem.style[styleName] !== undefined` // If the property is supported it will return an empty string, // if unsupported it will return undefined. // We'll take advantage of this quick test and skip setting a style // on our modernizr element, but instead just testing undefined vs // empty string. // Because the testing of the CSS property names (with "-", as // opposed to the camelCase DOM properties) is non-portable and // non-standard but works in WebKit and IE (but not Gecko or Opera), // we explicitly reject properties with dashes so that authors // developing in WebKit or IE first don't end up with // browser-specific content by accident. function testProps( props, prefixed ) { for ( var i in props ) { var prop = props[i]; if ( !contains(prop, "-") && mStyle[prop] !== undefined ) { return prefixed == 'pfx' ? prop : true; } } return false; } /*>>testprop*/ // TODO :: add testDOMProps /** * testDOMProps is a generic DOM property test; if a browser supports * a certain property, it won't return undefined for it. */ function testDOMProps( props, obj, elem ) { for ( var i in props ) { var item = obj[props[i]]; if ( item !== undefined) { // return the property name as a string if (elem === false) return props[i]; // let's bind a function if (is(item, 'function')){ // default to autobind unless override return item.bind(elem || obj); } // return the unbound function or obj or value return item; } } return false; } /*>>testallprops*/ /** * testPropsAll tests a list of DOM properties we want to check against. * We specify literally ALL possible (known and/or likely) properties on * the element including the non-vendor prefixed one, for forward- * compatibility. */ function testPropsAll( prop, prefixed, elem ) { var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); // did they call .prefixed('boxSizing') or are we just testing a prop? if(is(prefixed, "string") || is(prefixed, "undefined")) { return testProps(props, prefixed); // otherwise, they called .prefixed('requestAnimationFrame', window[, elem]) } else { props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); return testDOMProps(props, prefixed, elem); } } /*>>testallprops*/ /** * Tests * ----- */ // The *new* flexbox // dev.w3.org/csswg/css3-flexbox tests['flexbox'] = function() { return testPropsAll('flexWrap'); }; // The *old* flexbox // www.w3.org/TR/2009/WD-css3-flexbox-20090723/ tests['flexboxlegacy'] = function() { return testPropsAll('boxDirection'); }; // On the S60 and BB Storm, getContext exists, but always returns undefined // so we actually have to call getContext() to verify // github.com/Modernizr/Modernizr/issues/issue/97/ tests['canvas'] = function() { var elem = document.createElement('canvas'); return !!(elem.getContext && elem.getContext('2d')); }; tests['canvastext'] = function() { return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); }; // webk.it/70117 is tracking a legit WebGL feature detect proposal // We do a soft detect which may false positive in order to avoid // an expensive context creation: bugzil.la/732441 tests['webgl'] = function() { return !!window.WebGLRenderingContext; }; /* * The Modernizr.touch test only indicates if the browser supports * touch events, which does not necessarily reflect a touchscreen * device, as evidenced by tablets running Windows 7 or, alas, * the Palm Pre / WebOS (touch) phones. * * Additionally, Chrome (desktop) used to lie about its support on this, * but that has since been rectified: crbug.com/36415 * * We also test for Firefox 4 Multitouch Support. * * For more info, see: modernizr.github.com/Modernizr/touch.html */ tests['touch'] = function() { var bool; if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { bool = true; } else { injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) { bool = node.offsetTop === 9; }); } return bool; }; // geolocation is often considered a trivial feature detect... // Turns out, it's quite tricky to get right: // // Using !!navigator.geolocation does two things we don't want. It: // 1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513 // 2. Disables page caching in WebKit: webk.it/43956 // // Meanwhile, in Firefox < 8, an about:config setting could expose // a false positive that would throw an exception: bugzil.la/688158 tests['geolocation'] = function() { return 'geolocation' in navigator; }; tests['postmessage'] = function() { return !!window.postMessage; }; // Chrome incognito mode used to throw an exception when using openDatabase // It doesn't anymore. tests['websqldatabase'] = function() { return !!window.openDatabase; }; // Vendors had inconsistent prefixing with the experimental Indexed DB: // - Webkit's implementation is accessible through webkitIndexedDB // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB // For speed, we don't test the legacy (and beta-only) indexedDB tests['indexedDB'] = function() { return !!testPropsAll("indexedDB", window); }; // documentMode logic from YUI to filter out IE8 Compat Mode // which false positives. tests['hashchange'] = function() { return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); }; // Per 1.6: // This used to be Modernizr.historymanagement but the longer // name has been deprecated in favor of a shorter and property-matching one. // The old API is still available in 1.6, but as of 2.0 will throw a warning, // and in the first release thereafter disappear entirely. tests['history'] = function() { return !!(window.history && history.pushState); }; tests['draganddrop'] = function() { var div = document.createElement('div'); return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); }; // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10 // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17. // FF10 still uses prefixes, so check for it until then. // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/ tests['websockets'] = function() { return 'WebSocket' in window || 'MozWebSocket' in window; }; // css-tricks.com/rgba-browser-support/ tests['rgba'] = function() { // Set an rgba() color and check the returned value setCss('background-color:rgba(150,255,150,.5)'); return contains(mStyle.backgroundColor, 'rgba'); }; tests['hsla'] = function() { // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally, // except IE9 who retains it as hsla setCss('background-color:hsla(120,40%,100%,.5)'); return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); }; tests['multiplebgs'] = function() { // Setting multiple images AND a color on the background shorthand property // and then querying the style.background property value for the number of // occurrences of "url(" is a reliable method for detecting ACTUAL support for this! setCss('background:url(//),url(//),red url(//)'); // If the UA supports multiple backgrounds, there should be three occurrences // of the string "url(" in the return value for elemStyle.background return (/(url\s*\(.*?){3}/).test(mStyle.background); }; // this will false positive in Opera Mini // github.com/Modernizr/Modernizr/issues/396 tests['backgroundsize'] = function() { return testPropsAll('backgroundSize'); }; tests['borderimage'] = function() { return testPropsAll('borderImage'); }; // Super comprehensive table about all the unique implementations of // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance tests['borderradius'] = function() { return testPropsAll('borderRadius'); }; // WebOS unfortunately false positives on this test. tests['boxshadow'] = function() { return testPropsAll('boxShadow'); }; // FF3.0 will false positive on this test tests['textshadow'] = function() { return document.createElement('div').style.textShadow === ''; }; tests['opacity'] = function() { // Browsers that actually have CSS Opacity implemented have done so // according to spec, which means their return values are within the // range of [0.0,1.0] - including the leading zero. setCssAll('opacity:.55'); // The non-literal . in this regex is intentional: // German Chrome returns this value as 0,55 // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632 return (/^0.55$/).test(mStyle.opacity); }; // Note, Android < 4 will pass this test, but can only animate // a single property at a time // goo.gl/v3V4Gp tests['cssanimations'] = function() { return testPropsAll('animationName'); }; tests['csscolumns'] = function() { return testPropsAll('columnCount'); }; tests['cssgradients'] = function() { /** * For CSS Gradients syntax, please see: * webkit.org/blog/175/introducing-css-gradients/ * developer.mozilla.org/en/CSS/-moz-linear-gradient * developer.mozilla.org/en/CSS/-moz-radial-gradient * dev.w3.org/csswg/css3-images/#gradients- */ var str1 = 'background-image:', str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', str3 = 'linear-gradient(left top,#9f9, white);'; setCss( // legacy webkit syntax (FIXME: remove when syntax not in use anymore) (str1 + '-webkit- '.split(' ').join(str2 + str1) + // standard syntax // trailing 'background-image:' prefixes.join(str3 + str1)).slice(0, -str1.length) ); return contains(mStyle.backgroundImage, 'gradient'); }; tests['cssreflections'] = function() { return testPropsAll('boxReflect'); }; tests['csstransforms'] = function() { return !!testPropsAll('transform'); }; tests['csstransforms3d'] = function() { var ret = !!testPropsAll('perspective'); // Webkit's 3D transforms are passed off to the browser's own graphics renderer. // It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in // some conditions. As a result, Webkit typically recognizes the syntax but // will sometimes throw a false positive, thus we must do a more thorough check: if ( ret && 'webkitPerspective' in docElement.style ) { // Webkit allows this media query to succeed only if the feature is enabled. // `@media (transform-3d),(-webkit-transform-3d){ ... }` injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) { ret = node.offsetLeft === 9 && node.offsetHeight === 3; }); } return ret; }; tests['csstransitions'] = function() { return testPropsAll('transition'); }; /*>>fontface*/ // @font-face detection routine by Diego Perini // javascript.nwbox.com/CSSSupport/ // false positives: // WebOS github.com/Modernizr/Modernizr/issues/342 // WP7 github.com/Modernizr/Modernizr/issues/538 tests['fontface'] = function() { var bool; injectElementWithStyles('@font-face {font-family:"font";src:url("//")}', function( node, rule ) { var style = document.getElementById('smodernizr'), sheet = style.sheet || style.styleSheet, cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : ''; bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0; }); return bool; }; /*>>fontface*/ // CSS generated content detection tests['generatedcontent'] = function() { var bool; injectElementWithStyles(['#',mod,'{font:0/0 a}#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) { bool = node.offsetHeight >= 3; }); return bool; }; // These tests evaluate support of the video/audio elements, as well as // testing what types of content they support. // // We're using the Boolean constructor here, so that we can extend the value // e.g. Modernizr.video // true // Modernizr.video.ogg // 'probably' // // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845 // thx to NielsLeenheer and zcorpan // Note: in some older browsers, "no" was a return value instead of empty string. // It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2 // It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5 tests['video'] = function() { var elem = document.createElement('video'), bool = false; // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224 try { if ( bool = !!elem.canPlayType ) { bool = new Boolean(bool); bool.ogg = elem.canPlayType('video/ogg; codecs="theora"') .replace(/^no$/,''); // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546 bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,''); bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,''); } } catch(e) { } return bool; }; tests['audio'] = function() { var elem = document.createElement('audio'), bool = false; try { if ( bool = !!elem.canPlayType ) { bool = new Boolean(bool); bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,''); bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,''); // Mimetypes accepted: // developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements // bit.ly/iphoneoscodecs bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,''); bool.m4a = ( elem.canPlayType('audio/x-m4a;') || elem.canPlayType('audio/aac;')) .replace(/^no$/,''); } } catch(e) { } return bool; }; // In FF4, if disabled, window.localStorage should === null. // Normally, we could not test that directly and need to do a // `('localStorage' in window) && ` test first because otherwise Firefox will // throw bugzil.la/365772 if cookies are disabled // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem // will throw the exception: // QUOTA_EXCEEDED_ERRROR DOM Exception 22. // Peculiarly, getItem and removeItem calls do not throw. // Because we are forced to try/catch this, we'll go aggressive. // Just FWIW: IE8 Compat mode supports these features completely: // www.quirksmode.org/dom/html5.html // But IE8 doesn't support either with local files tests['localstorage'] = function() { try { localStorage.setItem(mod, mod); localStorage.removeItem(mod); return true; } catch(e) { return false; } }; tests['sessionstorage'] = function() { try { sessionStorage.setItem(mod, mod); sessionStorage.removeItem(mod); return true; } catch(e) { return false; } }; tests['webworkers'] = function() { return !!window.Worker; }; tests['applicationcache'] = function() { return !!window.applicationCache; }; // Thanks to Erik Dahlstrom tests['svg'] = function() { return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; }; // specifically for SVG inline in HTML, not within XHTML // test page: paulirish.com/demo/inline-svg tests['inlinesvg'] = function() { var div = document.createElement('div'); div.innerHTML = ''; return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; }; // SVG SMIL animation tests['smil'] = function() { return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); }; // This test is only for clip paths in SVG proper, not clip paths on HTML content // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg // However read the comments to dig into applying SVG clippaths to HTML content here: // github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491 tests['svgclippaths'] = function() { return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); }; /*>>webforms*/ // input features and input types go directly onto the ret object, bypassing the tests loop. // Hold this guy to execute in a moment. function webforms() { /*>>input*/ // Run through HTML5's new input attributes to see if the UA understands any. // We're using f which is the element created early on // Mike Taylr has created a comprehensive resource for testing these attributes // when applied to all input types: // miketaylr.com/code/input-type-attr.html // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary // Only input placeholder is tested while textarea's placeholder is not. // Currently Safari 4 and Opera 11 have support only for the input placeholder // Both tests are available in feature-detects/forms-placeholder.js Modernizr['input'] = (function( props ) { for ( var i = 0, len = props.length; i < len; i++ ) { attrs[ props[i] ] = !!(props[i] in inputElem); } if (attrs.list){ // safari false positive's on datalist: webk.it/74252 // see also github.com/Modernizr/Modernizr/issues/146 attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); } return attrs; })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); /*>>input*/ /*>>inputtypes*/ // Run through HTML5's new input types to see if the UA understands any. // This is put behind the tests runloop because it doesn't return a // true/false like all the other tests; instead, it returns an object // containing each input type with its corresponding true/false value // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/ Modernizr['inputtypes'] = (function(props) { for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) { inputElem.setAttribute('type', inputElemType = props[i]); bool = inputElem.type !== 'text'; // We first check to see if the type we give it sticks.. // If the type does, we feed it a textual value, which shouldn't be valid. // If the value doesn't stick, we know there's input sanitization which infers a custom UI if ( bool ) { inputElem.value = smile; inputElem.style.cssText = 'position:absolute;visibility:hidden;'; if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) { docElement.appendChild(inputElem); defaultView = document.defaultView; // Safari 2-4 allows the smiley as a value, despite making a slider bool = defaultView.getComputedStyle && defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && // Mobile android web browser has false positive, so must // check the height to see if the widget is actually there. (inputElem.offsetHeight !== 0); docElement.removeChild(inputElem); } else if ( /^(search|tel)$/.test(inputElemType) ){ // Spec doesn't define any special parsing or detectable UI // behaviors so we pass these through as true // Interestingly, opera fails the earlier test, so it doesn't // even make it here. } else if ( /^(url|email)$/.test(inputElemType) ) { // Real url and email support comes with prebaked validation. bool = inputElem.checkValidity && inputElem.checkValidity() === false; } else { // If the upgraded input compontent rejects the :) text, we got a winner bool = inputElem.value != smile; } } inputs[ props[i] ] = !!bool; } return inputs; })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); /*>>inputtypes*/ } /*>>webforms*/ // End of test definitions // ----------------------- // Run through all tests and detect their support in the current UA. // todo: hypothetically we could be doing an array of tests and use a basic loop here. for ( var feature in tests ) { if ( hasOwnProp(tests, feature) ) { // run the test, throw the return value into the Modernizr, // then based on that boolean, define an appropriate className // and push it into an array of classes we'll join later. featureName = feature.toLowerCase(); Modernizr[featureName] = tests[feature](); classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); } } /*>>webforms*/ // input tests need to run. Modernizr.input || webforms(); /*>>webforms*/ /** * addTest allows the user to define their own feature tests * the result will be added onto the Modernizr object, * as well as an appropriate className set on the html element * * @param feature - String naming the feature * @param test - Function returning true if feature is supported, false if not */ Modernizr.addTest = function ( feature, test ) { if ( typeof feature == 'object' ) { for ( var key in feature ) { if ( hasOwnProp( feature, key ) ) { Modernizr.addTest( key, feature[ key ] ); } } } else { feature = feature.toLowerCase(); if ( Modernizr[feature] !== undefined ) { // we're going to quit if you're trying to overwrite an existing test // if we were to allow it, we'd do this: // var re = new RegExp("\\b(no-)?" + feature + "\\b"); // docElement.className = docElement.className.replace( re, '' ); // but, no rly, stuff 'em. return Modernizr; } test = typeof test == 'function' ? test() : test; if (typeof enableClasses !== "undefined" && enableClasses) { docElement.className += ' ' + (test ? '' : 'no-') + feature; } Modernizr[feature] = test; } return Modernizr; // allow chaining. }; // Reset modElem.cssText to nothing to reduce memory footprint. setCss(''); modElem = inputElem = null; /*>>shiv*/ /** * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */ ;(function(window, document) { /*jshint evil:true */ /** version */ var version = '3.7.0'; /** Preset options */ var options = window.html5 || {}; /** Used to skip problem elements */ var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; /** Not all elements can be cloned in IE **/ var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; /** Detect whether the browser supports default html5 styles */ var supportsHtml5Styles; /** Name of the expando, to work with multiple documents or to re-shiv one document */ var expando = '_html5shiv'; /** The id for the the documents expando */ var expanID = 0; /** Cached data for each document */ var expandoData = {}; /** Detect whether the browser supports unknown elements */ var supportsUnknownElements; (function() { try { var a = document.createElement('a'); a.innerHTML = ''; //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles supportsHtml5Styles = ('hidden' in a); supportsUnknownElements = a.childNodes.length == 1 || (function() { // assign a false positive if unable to shiv (document.createElement)('a'); var frag = document.createDocumentFragment(); return ( typeof frag.cloneNode == 'undefined' || typeof frag.createDocumentFragment == 'undefined' || typeof frag.createElement == 'undefined' ); }()); } catch(e) { // assign a false positive if detection fails => unable to shiv supportsHtml5Styles = true; supportsUnknownElements = true; } }()); /*--------------------------------------------------------------------------*/ /** * Creates a style sheet with the given CSS text and adds it to the document. * @private * @param {Document} ownerDocument The document. * @param {String} cssText The CSS text. * @returns {StyleSheet} The style element. */ function addStyleSheet(ownerDocument, cssText) { var p = ownerDocument.createElement('p'), parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; p.innerHTML = 'x'; return parent.insertBefore(p.lastChild, parent.firstChild); } /** * Returns the value of `html5.elements` as an array. * @private * @returns {Array} An array of shived element node names. */ function getElements() { var elements = html5.elements; return typeof elements == 'string' ? elements.split(' ') : elements; } /** * Returns the data associated to the given document * @private * @param {Document} ownerDocument The document. * @returns {Object} An object of data. */ function getExpandoData(ownerDocument) { var data = expandoData[ownerDocument[expando]]; if (!data) { data = {}; expanID++; ownerDocument[expando] = expanID; expandoData[expanID] = data; } return data; } /** * returns a shived element for the given nodeName and document * @memberOf html5 * @param {String} nodeName name of the element * @param {Document} ownerDocument The context document. * @returns {Object} The shived element. */ function createElement(nodeName, ownerDocument, data){ if (!ownerDocument) { ownerDocument = document; } if(supportsUnknownElements){ return ownerDocument.createElement(nodeName); } if (!data) { data = getExpandoData(ownerDocument); } var node; if (data.cache[nodeName]) { node = data.cache[nodeName].cloneNode(); } else if (saveClones.test(nodeName)) { node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); } else { node = data.createElem(nodeName); } // Avoid adding some elements to fragments in IE < 9 because // * Attributes like `name` or `type` cannot be set/changed once an element // is inserted into a document/fragment // * Link elements with `src` attributes that are inaccessible, as with // a 403 response, will cause the tab/window to crash // * Script elements appended to fragments will execute when their `src` // or `text` property is set return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; } /** * returns a shived DocumentFragment for the given document * @memberOf html5 * @param {Document} ownerDocument The context document. * @returns {Object} The shived DocumentFragment. */ function createDocumentFragment(ownerDocument, data){ if (!ownerDocument) { ownerDocument = document; } if(supportsUnknownElements){ return ownerDocument.createDocumentFragment(); } data = data || getExpandoData(ownerDocument); var clone = data.frag.cloneNode(), i = 0, elems = getElements(), l = elems.length; for(;i>shiv*/ // Assign private properties to the return object with prefix Modernizr._version = version; // expose these for the plugin API. Look in the source for how to join() them against your input /*>>prefixes*/ Modernizr._prefixes = prefixes; /*>>prefixes*/ /*>>domprefixes*/ Modernizr._domPrefixes = domPrefixes; Modernizr._cssomPrefixes = cssomPrefixes; /*>>domprefixes*/ /*>>mq*/ // Modernizr.mq tests a given media query, live against the current state of the window // A few important notes: // * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false // * A max-width or orientation query will be evaluated against the current state, which may change later. // * You must specify values. Eg. If you are testing support for the min-width media query use: // Modernizr.mq('(min-width:0)') // usage: // Modernizr.mq('only screen and (max-width:768)') Modernizr.mq = testMediaQuery; /*>>mq*/ /*>>hasevent*/ // Modernizr.hasEvent() detects support for a given event, with an optional element to test on // Modernizr.hasEvent('gesturestart', elem) Modernizr.hasEvent = isEventSupported; /*>>hasevent*/ /*>>testprop*/ // Modernizr.testProp() investigates whether a given style property is recognized // Note that the property names must be provided in the camelCase variant. // Modernizr.testProp('pointerEvents') Modernizr.testProp = function(prop){ return testProps([prop]); }; /*>>testprop*/ /*>>testallprops*/ // Modernizr.testAllProps() investigates whether a given style property, // or any of its vendor-prefixed variants, is recognized // Note that the property names must be provided in the camelCase variant. // Modernizr.testAllProps('boxSizing') Modernizr.testAllProps = testPropsAll; /*>>testallprops*/ /*>>teststyles*/ // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... }) Modernizr.testStyles = injectElementWithStyles; /*>>teststyles*/ /*>>prefixed*/ // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input // Modernizr.prefixed('boxSizing') // 'MozBoxSizing' // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style. // Return values will also be the camelCase variant, if you need to translate that to hypenated style use: // // str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-'); // If you're trying to ascertain which transition end event to bind to, you might do something like... // // var transEndEventNames = { // 'WebkitTransition' : 'webkitTransitionEnd', // 'MozTransition' : 'transitionend', // 'OTransition' : 'oTransitionEnd', // 'msTransition' : 'MSTransitionEnd', // 'transition' : 'transitionend' // }, // transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ]; Modernizr.prefixed = function(prop, obj, elem){ if(!obj) { return testPropsAll(prop, 'pfx'); } else { // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame' return testPropsAll(prop, obj, elem); } }; /*>>prefixed*/ /*>>cssclasses*/ // Remove "no-js" class from element, if it exists: docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + // Add the new classes to the element. (enableClasses ? ' js ' + classes.join(' ') : ''); /*>>cssclasses*/ return Modernizr; })(this, this.document); /** * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */ ;(function(window, document) { /*jshint evil:true */ /** version */ var version = '3.7.3'; /** Preset options */ var options = window.html5 || {}; /** Used to skip problem elements */ var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; /** Not all elements can be cloned in IE **/ var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; /** Detect whether the browser supports default html5 styles */ var supportsHtml5Styles; /** Name of the expando, to work with multiple documents or to re-shiv one document */ var expando = '_html5shiv'; /** The id for the the documents expando */ var expanID = 0; /** Cached data for each document */ var expandoData = {}; /** Detect whether the browser supports unknown elements */ var supportsUnknownElements; (function() { try { var a = document.createElement('a'); a.innerHTML = ''; //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles supportsHtml5Styles = ('hidden' in a); supportsUnknownElements = a.childNodes.length == 1 || (function() { // assign a false positive if unable to shiv (document.createElement)('a'); var frag = document.createDocumentFragment(); return ( typeof frag.cloneNode == 'undefined' || typeof frag.createDocumentFragment == 'undefined' || typeof frag.createElement == 'undefined' ); }()); } catch(e) { // assign a false positive if detection fails => unable to shiv supportsHtml5Styles = true; supportsUnknownElements = true; } }()); /*--------------------------------------------------------------------------*/ /** * Creates a style sheet with the given CSS text and adds it to the document. * @private * @param {Document} ownerDocument The document. * @param {String} cssText The CSS text. * @returns {StyleSheet} The style element. */ function addStyleSheet(ownerDocument, cssText) { var p = ownerDocument.createElement('p'), parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; p.innerHTML = 'x'; return parent.insertBefore(p.lastChild, parent.firstChild); } /** * Returns the value of `html5.elements` as an array. * @private * @returns {Array} An array of shived element node names. */ function getElements() { var elements = html5.elements; return typeof elements == 'string' ? elements.split(' ') : elements; } /** * Extends the built-in list of html5 elements * @memberOf html5 * @param {String|Array} newElements whitespace separated list or array of new element names to shiv * @param {Document} ownerDocument The context document. */ function addElements(newElements, ownerDocument) { var elements = html5.elements; if(typeof elements != 'string'){ elements = elements.join(' '); } if(typeof newElements != 'string'){ newElements = newElements.join(' '); } html5.elements = elements +' '+ newElements; shivDocument(ownerDocument); } /** * Returns the data associated to the given document * @private * @param {Document} ownerDocument The document. * @returns {Object} An object of data. */ function getExpandoData(ownerDocument) { var data = expandoData[ownerDocument[expando]]; if (!data) { data = {}; expanID++; ownerDocument[expando] = expanID; expandoData[expanID] = data; } return data; } /** * returns a shived element for the given nodeName and document * @memberOf html5 * @param {String} nodeName name of the element * @param {Document|DocumentFragment} ownerDocument The context document. * @returns {Object} The shived element. */ function createElement(nodeName, ownerDocument, data){ if (!ownerDocument) { ownerDocument = document; } if(supportsUnknownElements){ return ownerDocument.createElement(nodeName); } if (!data) { data = getExpandoData(ownerDocument); } var node; if (data.cache[nodeName]) { node = data.cache[nodeName].cloneNode(); } else if (saveClones.test(nodeName)) { node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); } else { node = data.createElem(nodeName); } // Avoid adding some elements to fragments in IE < 9 because // * Attributes like `name` or `type` cannot be set/changed once an element // is inserted into a document/fragment // * Link elements with `src` attributes that are inaccessible, as with // a 403 response, will cause the tab/window to crash // * Script elements appended to fragments will execute when their `src` // or `text` property is set return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node; } /** * returns a shived DocumentFragment for the given document * @memberOf html5 * @param {Document} ownerDocument The context document. * @returns {Object} The shived DocumentFragment. */ function createDocumentFragment(ownerDocument, data){ if (!ownerDocument) { ownerDocument = document; } if(supportsUnknownElements){ return ownerDocument.createDocumentFragment(); } data = data || getExpandoData(ownerDocument); var clone = data.frag.cloneNode(), i = 0, elems = getElements(), l = elems.length; for(;i 1) { this.each(function() { $(this).bxSlider(options); }); return this; } // create a namespace to be used throughout the plugin var slider = {}, // set a reference to our slider element el = this, // get the original window dimens (thanks a lot IE) windowWidth = $(window).width(), windowHeight = $(window).height(); // Return if slider is already initialized if ($(el).data('bxSlider')) { return; } /** * =================================================================================== * = PRIVATE FUNCTIONS * =================================================================================== */ /** * Initializes namespace settings to be used throughout plugin */ var init = function() { // Return if slider is already initialized if ($(el).data('bxSlider')) { return; } // merge user-supplied options with the defaults slider.settings = $.extend({}, defaults, options); // parse slideWidth setting slider.settings.slideWidth = parseInt(slider.settings.slideWidth); // store the original children slider.children = el.children(slider.settings.slideSelector); // check if actual number of slides is less than minSlides / maxSlides if (slider.children.length < slider.settings.minSlides) { slider.settings.minSlides = slider.children.length; } if (slider.children.length < slider.settings.maxSlides) { slider.settings.maxSlides = slider.children.length; } // if random start, set the startSlide setting to random number if (slider.settings.randomStart) { slider.settings.startSlide = Math.floor(Math.random() * slider.children.length); } // store active slide information slider.active = { index: slider.settings.startSlide }; // store if the slider is in carousel mode (displaying / moving multiple slides) slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1; // if carousel, force preloadImages = 'all' if (slider.carousel) { slider.settings.preloadImages = 'all'; } // calculate the min / max width thresholds based on min / max number of slides // used to setup and update carousel slides dimensions slider.minThreshold = (slider.settings.minSlides * slider.settings.slideWidth) + ((slider.settings.minSlides - 1) * slider.settings.slideMargin); slider.maxThreshold = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); // store the current state of the slider (if currently animating, working is true) slider.working = false; // initialize the controls object slider.controls = {}; // initialize an auto interval slider.interval = null; // determine which property to use for transitions slider.animProp = slider.settings.mode === 'vertical' ? 'top' : 'left'; // determine if hardware acceleration can be used slider.usingCSS = slider.settings.useCSS && slider.settings.mode !== 'fade' && (function() { // create our test div element var div = document.createElement('div'), // css transition properties props = ['WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']; // test for each property for (var i = 0; i < props.length; i++) { if (div.style[props[i]] !== undefined) { slider.cssPrefix = props[i].replace('Perspective', '').toLowerCase(); slider.animProp = '-' + slider.cssPrefix + '-transform'; return true; } } return false; }()); // if vertical mode always make maxSlides and minSlides equal if (slider.settings.mode === 'vertical') { slider.settings.maxSlides = slider.settings.minSlides; } // save original style data el.data('origStyle', el.attr('style')); el.children(slider.settings.slideSelector).each(function() { $(this).data('origStyle', $(this).attr('style')); }); // perform all DOM / CSS modifications setup(); }; /** * Performs all DOM and CSS modifications */ var setup = function() { var preloadSelector = slider.children.eq(slider.settings.startSlide); // set the default preload selector (visible) // wrap el in a wrapper el.wrap('
'); // store a namespace reference to .bx-viewport slider.viewport = el.parent(); // add aria-live if the setting is enabled and ticker mode is disabled if (slider.settings.ariaLive && !slider.settings.ticker) { slider.viewport.attr('aria-live', 'polite'); } // add a loading div to display while images are loading slider.loader = $('
'); slider.viewport.prepend(slider.loader); // set el to a massive width, to hold any needed slides // also strip any margin and padding from el el.css({ width: slider.settings.mode === 'horizontal' ? (slider.children.length * 1000 + 215) + '%' : 'auto', position: 'relative' }); // if using CSS, add the easing property if (slider.usingCSS && slider.settings.easing) { el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing); // if not using CSS and no easing value was supplied, use the default JS animation easing (swing) } else if (!slider.settings.easing) { slider.settings.easing = 'swing'; } // make modifications to the viewport (.bx-viewport) slider.viewport.css({ width: '100%', overflow: 'hidden', position: 'relative' }); slider.viewport.parent().css({ maxWidth: getViewportMaxWidth() }); // apply css to all slider children slider.children.css({ // the float attribute is a reserved word in compressors like YUI compressor and need to be quoted #48 'float': slider.settings.mode === 'horizontal' ? 'left' : 'none', listStyle: 'none', position: 'relative' }); // apply the calculated width after the float is applied to prevent scrollbar interference slider.children.css('width', getSlideWidth()); // if slideMargin is supplied, add the css if (slider.settings.mode === 'horizontal' && slider.settings.slideMargin > 0) { slider.children.css('marginRight', slider.settings.slideMargin); } if (slider.settings.mode === 'vertical' && slider.settings.slideMargin > 0) { slider.children.css('marginBottom', slider.settings.slideMargin); } // if "fade" mode, add positioning and z-index CSS if (slider.settings.mode === 'fade') { slider.children.css({ position: 'absolute', zIndex: 0, display: 'none' }); // prepare the z-index on the showing element slider.children.eq(slider.settings.startSlide).css({zIndex: slider.settings.slideZIndex, display: 'block'}); } // create an element to contain all slider controls (pager, start / stop, etc) slider.controls.el = $('
'); // if captions are requested, add them if (slider.settings.captions) { appendCaptions(); } // check if startSlide is last slide slider.active.last = slider.settings.startSlide === getPagerQty() - 1; // if video is true, set up the fitVids plugin if (slider.settings.video) { el.fitVids(); } //preloadImages if (slider.settings.preloadImages === 'none') { preloadSelector = null; } else if (slider.settings.preloadImages === 'all' || slider.settings.ticker) { preloadSelector = slider.children; } // only check for control addition if not in "ticker" mode if (!slider.settings.ticker) { // if controls are requested, add them if (slider.settings.controls) { appendControls(); } // if auto is true, and auto controls are requested, add them if (slider.settings.auto && slider.settings.autoControls) { appendControlsAuto(); } // if pager is requested, add it if (slider.settings.pager) { appendPager(); } // if any control option is requested, add the controls wrapper if (slider.settings.controls || slider.settings.autoControls || slider.settings.pager) { slider.viewport.after(slider.controls.el); } // if ticker mode, do not allow a pager } else { slider.settings.pager = false; } if (preloadSelector === null) { start(); } else { loadElements(preloadSelector, start); } }; var loadElements = function(selector, callback) { var total = selector.find('img:not([src=""]), iframe').length, count = 0; if (total === 0) { callback(); return; } selector.find('img:not([src=""]), iframe').each(function() { $(this).one('load error', function() { if (++count === total) { callback(); } }).each(function() { if (this.complete || this.src == '') { $(this).trigger('load'); } }); }); }; /** * Start the slider */ var start = function() { // if infinite loop, prepare additional slides if (slider.settings.infiniteLoop && slider.settings.mode !== 'fade' && !slider.settings.ticker) { var slice = slider.settings.mode === 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides, sliceAppend = slider.children.slice(0, slice).clone(true).addClass('bx-clone'), slicePrepend = slider.children.slice(-slice).clone(true).addClass('bx-clone'); if (slider.settings.ariaHidden) { sliceAppend.attr('aria-hidden', true); slicePrepend.attr('aria-hidden', true); } el.append(sliceAppend).prepend(slicePrepend); } // remove the loading DOM element slider.loader.remove(); // set the left / top position of "el" setSlidePosition(); // if "vertical" mode, always use adaptiveHeight to prevent odd behavior if (slider.settings.mode === 'vertical') { slider.settings.adaptiveHeight = true; } // set the viewport height slider.viewport.height(getViewportHeight()); // make sure everything is positioned just right (same as a window resize) el.redrawSlider(); // onSliderLoad callback slider.settings.onSliderLoad.call(el, slider.active.index); // slider has been fully initialized slider.initialized = true; // add the resize call to the window if (slider.settings.responsive) { $(window).on('resize', resizeWindow); } // if auto is true and has more than 1 page, start the show if (slider.settings.auto && slider.settings.autoStart && (getPagerQty() > 1 || slider.settings.autoSlideForOnePage)) { initAuto(); } // if ticker is true, start the ticker if (slider.settings.ticker) { initTicker(); } // if pager is requested, make the appropriate pager link active if (slider.settings.pager) { updatePagerActive(slider.settings.startSlide); } // check for any updates to the controls (like hideControlOnEnd updates) if (slider.settings.controls) { updateDirectionControls(); } // if touchEnabled is true, setup the touch events if (slider.settings.touchEnabled && !slider.settings.ticker) { initTouch(); } // if keyboardEnabled is true, setup the keyboard events if (slider.settings.keyboardEnabled && !slider.settings.ticker) { $(document).keydown(keyPress); } }; /** * Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value */ var getViewportHeight = function() { var height = 0; // first determine which children (slides) should be used in our height calculation var children = $(); // if mode is not "vertical" and adaptiveHeight is false, include all children if (slider.settings.mode !== 'vertical' && !slider.settings.adaptiveHeight) { children = slider.children; } else { // if not carousel, return the single active child if (!slider.carousel) { children = slider.children.eq(slider.active.index); // if carousel, return a slice of children } else { // get the individual slide index var currentIndex = slider.settings.moveSlides === 1 ? slider.active.index : slider.active.index * getMoveBy(); // add the current slide to the children children = slider.children.eq(currentIndex); // cycle through the remaining "showing" slides for (i = 1; i <= slider.settings.maxSlides - 1; i++) { // if looped back to the start if (currentIndex + i >= slider.children.length) { children = children.add(slider.children.eq(i - 1)); } else { children = children.add(slider.children.eq(currentIndex + i)); } } } } // if "vertical" mode, calculate the sum of the heights of the children if (slider.settings.mode === 'vertical') { children.each(function(index) { height += $(this).outerHeight(); }); // add user-supplied margins if (slider.settings.slideMargin > 0) { height += slider.settings.slideMargin * (slider.settings.minSlides - 1); } // if not "vertical" mode, calculate the max height of the children } else { height = Math.max.apply(Math, children.map(function() { return $(this).outerHeight(false); }).get()); } if (slider.viewport.css('box-sizing') === 'border-box') { 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')); } else if (slider.viewport.css('box-sizing') === 'padding-box') { height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')); } return height; }; /** * Returns the calculated width to be used for the outer wrapper / viewport */ var getViewportMaxWidth = function() { var width = '100%'; if (slider.settings.slideWidth > 0) { if (slider.settings.mode === 'horizontal') { width = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); } else { width = slider.settings.slideWidth; } } return width; }; /** * Returns the calculated width to be applied to each slide */ var getSlideWidth = function() { var newElWidth = slider.settings.slideWidth, // start with any user-supplied slide width wrapWidth = slider.viewport.width(); // get the current viewport width // if slide width was not supplied, or is larger than the viewport use the viewport width if (slider.settings.slideWidth === 0 || (slider.settings.slideWidth > wrapWidth && !slider.carousel) || slider.settings.mode === 'vertical') { newElWidth = wrapWidth; // if carousel, use the thresholds to determine the width } else if (slider.settings.maxSlides > 1 && slider.settings.mode === 'horizontal') { if (wrapWidth > slider.maxThreshold) { return newElWidth; } else if (wrapWidth < slider.minThreshold) { newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides; } else if (slider.settings.shrinkItems) { newElWidth = Math.floor((wrapWidth + slider.settings.slideMargin) / (Math.ceil((wrapWidth + slider.settings.slideMargin) / (newElWidth + slider.settings.slideMargin))) - slider.settings.slideMargin); } } return newElWidth; }; /** * Returns the number of slides currently visible in the viewport (includes partially visible slides) */ var getNumberSlidesShowing = function() { var slidesShowing = 1, childWidth = null; if (slider.settings.mode === 'horizontal' && slider.settings.slideWidth > 0) { // if viewport is smaller than minThreshold, return minSlides if (slider.viewport.width() < slider.minThreshold) { slidesShowing = slider.settings.minSlides; // if viewport is larger than maxThreshold, return maxSlides } else if (slider.viewport.width() > slider.maxThreshold) { slidesShowing = slider.settings.maxSlides; // if viewport is between min / max thresholds, divide viewport width by first child width } else { childWidth = slider.children.first().width() + slider.settings.slideMargin; slidesShowing = Math.floor((slider.viewport.width() + slider.settings.slideMargin) / childWidth) || 1; } // if "vertical" mode, slides showing will always be minSlides } else if (slider.settings.mode === 'vertical') { slidesShowing = slider.settings.minSlides; } return slidesShowing; }; /** * Returns the number of pages (one full viewport of slides is one "page") */ var getPagerQty = function() { var pagerQty = 0, breakPoint = 0, counter = 0; // if moveSlides is specified by the user if (slider.settings.moveSlides > 0) { if (slider.settings.infiniteLoop) { pagerQty = Math.ceil(slider.children.length / getMoveBy()); } else { // when breakpoint goes above children length, counter is the number of pages while (breakPoint < slider.children.length) { ++pagerQty; breakPoint = counter + getNumberSlidesShowing(); counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing(); } return counter; } // if moveSlides is 0 (auto) divide children length by sides showing, then round up } else { pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing()); } return pagerQty; }; /** * Returns the number of individual slides by which to shift the slider */ var getMoveBy = function() { // if moveSlides was set by the user and moveSlides is less than number of slides showing if (slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()) { return slider.settings.moveSlides; } // if moveSlides is 0 (auto) return getNumberSlidesShowing(); }; /** * Sets the slider's (el) left or top position */ var setSlidePosition = function() { var position, lastChild, lastShowingIndex; // if last slide, not infinite loop, and number of children is larger than specified maxSlides if (slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop) { if (slider.settings.mode === 'horizontal') { // get the last child's position lastChild = slider.children.last(); position = lastChild.position(); // set the left position setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.outerWidth())), 'reset', 0); } else if (slider.settings.mode === 'vertical') { // get the last showing index's position lastShowingIndex = slider.children.length - slider.settings.minSlides; position = slider.children.eq(lastShowingIndex).position(); // set the top position setPositionProperty(-position.top, 'reset', 0); } // if not last slide } else { // get the position of the first showing slide position = slider.children.eq(slider.active.index * getMoveBy()).position(); // check for last slide if (slider.active.index === getPagerQty() - 1) { slider.active.last = true; } // set the respective position if (position !== undefined) { if (slider.settings.mode === 'horizontal') { setPositionProperty(-position.left, 'reset', 0); } else if (slider.settings.mode === 'vertical') { setPositionProperty(-position.top, 'reset', 0); } } } }; /** * Sets the el's animating property position (which in turn will sometimes animate el). * If using CSS, sets the transform property. If not using CSS, sets the top / left property. * * @param value (int) * - the animating property's value * * @param type (string) 'slide', 'reset', 'ticker' * - the type of instance for which the function is being * * @param duration (int) * - the amount of time (in ms) the transition should occupy * * @param params (array) optional * - an optional parameter containing any variables that need to be passed in */ var setPositionProperty = function(value, type, duration, params) { var animateObj, propValue; // use CSS transform if (slider.usingCSS) { // determine the translate3d value propValue = slider.settings.mode === 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)'; // add the CSS transition-duration el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's'); if (type === 'slide') { // set the property value el.css(slider.animProp, propValue); if (duration !== 0) { // add a callback method - executes when CSS transition completes el.on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) { //make sure it's the correct one if (!$(e.target).is(el)) { return; } // remove the callback el.off('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); updateAfterSlideTransition(); }); } else { //duration = 0 updateAfterSlideTransition(); } } else if (type === 'reset') { el.css(slider.animProp, propValue); } else if (type === 'ticker') { // make the transition use 'linear' el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear'); el.css(slider.animProp, propValue); if (duration !== 0) { el.on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) { //make sure it's the correct one if (!$(e.target).is(el)) { return; } // remove the callback el.off('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); // reset the position setPositionProperty(params.resetValue, 'reset', 0); // start the loop again tickerLoop(); }); } else { //duration = 0 setPositionProperty(params.resetValue, 'reset', 0); tickerLoop(); } } // use JS animate } else { animateObj = {}; animateObj[slider.animProp] = value; if (type === 'slide') { el.animate(animateObj, duration, slider.settings.easing, function() { updateAfterSlideTransition(); }); } else if (type === 'reset') { el.css(slider.animProp, value); } else if (type === 'ticker') { el.animate(animateObj, duration, 'linear', function() { setPositionProperty(params.resetValue, 'reset', 0); // run the recursive loop after animation tickerLoop(); }); } } }; /** * Populates the pager with proper amount of pages */ var populatePager = function() { var pagerHtml = '', linkContent = '', pagerQty = getPagerQty(); // loop through each pager item for (var i = 0; i < pagerQty; i++) { linkContent = ''; // if a buildPager function is supplied, use it to get pager link value, else use index + 1 if (slider.settings.buildPager && $.isFunction(slider.settings.buildPager) || slider.settings.pagerCustom) { linkContent = slider.settings.buildPager(i); slider.pagerEl.addClass('bx-custom-pager'); } else { linkContent = i + 1; slider.pagerEl.addClass('bx-default-pager'); } // var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1; // add the markup to the string pagerHtml += ''; } // populate the pager element with pager links slider.pagerEl.html(pagerHtml); }; /** * Appends the pager to the controls element */ var appendPager = function() { if (!slider.settings.pagerCustom) { // create the pager DOM element slider.pagerEl = $('
'); // if a pager selector was supplied, populate it with the pager if (slider.settings.pagerSelector) { $(slider.settings.pagerSelector).html(slider.pagerEl); // if no pager selector was supplied, add it after the wrapper } else { slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl); } // populate the pager populatePager(); } else { slider.pagerEl = $(slider.settings.pagerCustom); } // assign the pager click binding slider.pagerEl.on('click touchend', 'a', clickPagerBind); }; /** * Appends prev / next controls to the controls element */ var appendControls = function() { slider.controls.next = $('' + slider.settings.nextText + ''); slider.controls.prev = $('' + slider.settings.prevText + ''); // add click actions to the controls slider.controls.next.on('click touchend', clickNextBind); slider.controls.prev.on('click touchend', clickPrevBind); // if nextSelector was supplied, populate it if (slider.settings.nextSelector) { $(slider.settings.nextSelector).append(slider.controls.next); } // if prevSelector was supplied, populate it if (slider.settings.prevSelector) { $(slider.settings.prevSelector).append(slider.controls.prev); } // if no custom selectors were supplied if (!slider.settings.nextSelector && !slider.settings.prevSelector) { // add the controls to the DOM slider.controls.directionEl = $('
'); // add the control elements to the directionEl slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next); // slider.viewport.append(slider.controls.directionEl); slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl); } }; /** * Appends start / stop auto controls to the controls element */ var appendControlsAuto = function() { slider.controls.start = $(''); slider.controls.stop = $(''); // add the controls to the DOM slider.controls.autoEl = $('
'); // on click actions to the controls slider.controls.autoEl.on('click', '.bx-start', clickStartBind); slider.controls.autoEl.on('click', '.bx-stop', clickStopBind); // if autoControlsCombine, insert only the "start" control if (slider.settings.autoControlsCombine) { slider.controls.autoEl.append(slider.controls.start); // if autoControlsCombine is false, insert both controls } else { slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop); } // if auto controls selector was supplied, populate it with the controls if (slider.settings.autoControlsSelector) { $(slider.settings.autoControlsSelector).html(slider.controls.autoEl); // if auto controls selector was not supplied, add it after the wrapper } else { slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl); } // update the auto controls updateAutoControls(slider.settings.autoStart ? 'stop' : 'start'); }; /** * Appends image captions to the DOM */ var appendCaptions = function() { // cycle through each child slider.children.each(function(index) { // get the image title attribute var title = $(this).find('img:first').attr('title'); // append the caption if (title !== undefined && ('' + title).length) { $(this).append('
' + title + '
'); } }); }; /** * Click next binding * * @param e (event) * - DOM event object */ var clickNextBind = function(e) { e.preventDefault(); if (slider.controls.el.hasClass('disabled')) { return; } // if auto show is running, stop it if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); } el.goToNextSlide(); }; /** * Click prev binding * * @param e (event) * - DOM event object */ var clickPrevBind = function(e) { e.preventDefault(); if (slider.controls.el.hasClass('disabled')) { return; } // if auto show is running, stop it if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); } el.goToPrevSlide(); }; /** * Click start binding * * @param e (event) * - DOM event object */ var clickStartBind = function(e) { el.startAuto(); e.preventDefault(); }; /** * Click stop binding * * @param e (event) * - DOM event object */ var clickStopBind = function(e) { el.stopAuto(); e.preventDefault(); }; /** * Click pager binding * * @param e (event) * - DOM event object */ var clickPagerBind = function(e) { var pagerLink, pagerIndex; e.preventDefault(); if (slider.controls.el.hasClass('disabled')) { return; } // if auto show is running, stop it if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); } pagerLink = $(e.currentTarget); if (pagerLink.attr('data-slide-index') !== undefined) { pagerIndex = parseInt(pagerLink.attr('data-slide-index')); // if clicked pager link is not active, continue with the goToSlide call if (pagerIndex !== slider.active.index) { el.goToSlide(pagerIndex); } } }; /** * Updates the pager links with an active class * * @param slideIndex (int) * - index of slide to make active */ var updatePagerActive = function(slideIndex) { // if "short" pager type var len = slider.children.length; // nb of children if (slider.settings.pagerType === 'short') { if (slider.settings.maxSlides > 1) { len = Math.ceil(slider.children.length / slider.settings.maxSlides); } slider.pagerEl.html((slideIndex + 1) + slider.settings.pagerShortSeparator + len); return; } // remove all pager active classes slider.pagerEl.find('a').removeClass('active'); // apply the active class for all pagers slider.pagerEl.each(function(i, el) { $(el).find('a').eq(slideIndex).addClass('active'); }); }; /** * Performs needed actions after a slide transition */ var updateAfterSlideTransition = function() { // if infinite loop is true if (slider.settings.infiniteLoop) { var position = ''; // first slide if (slider.active.index === 0) { // set the new position position = slider.children.eq(0).position(); // carousel, last slide } else if (slider.active.index === getPagerQty() - 1 && slider.carousel) { position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position(); // last slide } else if (slider.active.index === slider.children.length - 1) { position = slider.children.eq(slider.children.length - 1).position(); } if (position) { if (slider.settings.mode === 'horizontal') { setPositionProperty(-position.left, 'reset', 0); } else if (slider.settings.mode === 'vertical') { setPositionProperty(-position.top, 'reset', 0); } } } // declare that the transition is complete slider.working = false; // onSlideAfter callback slider.settings.onSlideAfter.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); }; /** * Updates the auto controls state (either active, or combined switch) * * @param state (string) "start", "stop" * - the new state of the auto show */ var updateAutoControls = function(state) { // if autoControlsCombine is true, replace the current control with the new state if (slider.settings.autoControlsCombine) { slider.controls.autoEl.html(slider.controls[state]); // if autoControlsCombine is false, apply the "active" class to the appropriate control } else { slider.controls.autoEl.find('a').removeClass('active'); slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active'); } }; /** * Updates the direction controls (checks if either should be hidden) */ var updateDirectionControls = function() { if (getPagerQty() === 1) { slider.controls.prev.addClass('disabled'); slider.controls.next.addClass('disabled'); } else if (!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd) { // if first slide if (slider.active.index === 0) { slider.controls.prev.addClass('disabled'); slider.controls.next.removeClass('disabled'); // if last slide } else if (slider.active.index === getPagerQty() - 1) { slider.controls.next.addClass('disabled'); slider.controls.prev.removeClass('disabled'); // if any slide in the middle } else { slider.controls.prev.removeClass('disabled'); slider.controls.next.removeClass('disabled'); } } }; /* auto start and stop functions */ var windowFocusHandler = function() { el.startAuto(); }; var windowBlurHandler = function() { el.stopAuto(); }; /** * Initializes the auto process */ var initAuto = function() { // if autoDelay was supplied, launch the auto show using a setTimeout() call if (slider.settings.autoDelay > 0) { setTimeout(el.startAuto, slider.settings.autoDelay); // if autoDelay was not supplied, start the auto show normally } else { el.startAuto(); //add focus and blur events to ensure its running if timeout gets paused $(window).focus(windowFocusHandler).blur(windowBlurHandler); } // if autoHover is requested if (slider.settings.autoHover) { // on el hover el.hover(function() { // if the auto show is currently playing (has an active interval) if (slider.interval) { // stop the auto show and pass true argument which will prevent control update el.stopAuto(true); // create a new autoPaused value which will be used by the relative "mouseout" event slider.autoPaused = true; } }, function() { // if the autoPaused value was created be the prior "mouseover" event if (slider.autoPaused) { // start the auto show and pass true argument which will prevent control update el.startAuto(true); // reset the autoPaused value slider.autoPaused = null; } }); } }; /** * Initializes the ticker process */ var initTicker = function() { var startPosition = 0, position, transform, value, idx, ratio, property, newSpeed, totalDimens; // if autoDirection is "next", append a clone of the entire slider if (slider.settings.autoDirection === 'next') { el.append(slider.children.clone().addClass('bx-clone')); // if autoDirection is "prev", prepend a clone of the entire slider, and set the left position } else { el.prepend(slider.children.clone().addClass('bx-clone')); position = slider.children.first().position(); startPosition = slider.settings.mode === 'horizontal' ? -position.left : -position.top; } setPositionProperty(startPosition, 'reset', 0); // do not allow controls in ticker mode slider.settings.pager = false; slider.settings.controls = false; slider.settings.autoControls = false; // if autoHover is requested if (slider.settings.tickerHover) { if (slider.usingCSS) { idx = slider.settings.mode === 'horizontal' ? 4 : 5; slider.viewport.hover(function() { transform = el.css('-' + slider.cssPrefix + '-transform'); value = parseFloat(transform.split(',')[idx]); setPositionProperty(value, 'reset', 0); }, function() { totalDimens = 0; slider.children.each(function(index) { totalDimens += slider.settings.mode === 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true); }); // calculate the speed ratio (used to determine the new speed to finish the paused animation) ratio = slider.settings.speed / totalDimens; // determine which property to use property = slider.settings.mode === 'horizontal' ? 'left' : 'top'; // calculate the new speed newSpeed = ratio * (totalDimens - (Math.abs(parseInt(value)))); tickerLoop(newSpeed); }); } else { // on el hover slider.viewport.hover(function() { el.stop(); }, function() { // calculate the total width of children (used to calculate the speed ratio) totalDimens = 0; slider.children.each(function(index) { totalDimens += slider.settings.mode === 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true); }); // calculate the speed ratio (used to determine the new speed to finish the paused animation) ratio = slider.settings.speed / totalDimens; // determine which property to use property = slider.settings.mode === 'horizontal' ? 'left' : 'top'; // calculate the new speed newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property))))); tickerLoop(newSpeed); }); } } // start the ticker loop tickerLoop(); }; /** * Runs a continuous loop, news ticker-style */ var tickerLoop = function(resumeSpeed) { var speed = resumeSpeed ? resumeSpeed : slider.settings.speed, position = {left: 0, top: 0}, reset = {left: 0, top: 0}, animateProperty, resetValue, params; // if "next" animate left position to last child, then reset left to 0 if (slider.settings.autoDirection === 'next') { position = el.find('.bx-clone').first().position(); // if "prev" animate left position to 0, then reset left to first non-clone child } else { reset = slider.children.first().position(); } animateProperty = slider.settings.mode === 'horizontal' ? -position.left : -position.top; resetValue = slider.settings.mode === 'horizontal' ? -reset.left : -reset.top; params = {resetValue: resetValue}; setPositionProperty(animateProperty, 'ticker', speed, params); }; /** * Check if el is on screen */ var isOnScreen = function(el) { var win = $(window), viewport = { top: win.scrollTop(), left: win.scrollLeft() }, bounds = el.offset(); viewport.right = viewport.left + win.width(); viewport.bottom = viewport.top + win.height(); bounds.right = bounds.left + el.outerWidth(); bounds.bottom = bounds.top + el.outerHeight(); return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom)); }; /** * Initializes keyboard events */ var keyPress = function(e) { var activeElementTag = document.activeElement.tagName.toLowerCase(), tagFilters = 'input|textarea', p = new RegExp(activeElementTag,['i']), result = p.exec(tagFilters); if (result == null && isOnScreen(el)) { if (e.keyCode === 39) { clickNextBind(e); return false; } else if (e.keyCode === 37) { clickPrevBind(e); return false; } } }; /** * Initializes touch events */ var initTouch = function() { // initialize object to contain all touch values slider.touch = { start: {x: 0, y: 0}, end: {x: 0, y: 0} }; slider.viewport.on('touchstart MSPointerDown pointerdown', onTouchStart); //for browsers that have implemented pointer events and fire a click after //every pointerup regardless of whether pointerup is on same screen location as pointerdown or not slider.viewport.on('click', '.bxslider a', function(e) { if (slider.viewport.hasClass('click-disabled')) { e.preventDefault(); slider.viewport.removeClass('click-disabled'); } }); }; /** * Event handler for "touchstart" * * @param e (event) * - DOM event object */ var onTouchStart = function(e) { // watch only for left mouse, touch contact and pen contact // touchstart event object doesn`t have button property if (e.type !== 'touchstart' && e.button !== 0) { return; } e.preventDefault(); //disable slider controls while user is interacting with slides to avoid slider freeze that happens on touch devices when a slide swipe happens immediately after interacting with slider controls slider.controls.el.addClass('disabled'); if (slider.working) { slider.controls.el.removeClass('disabled'); } else { // record the original position when touch starts slider.touch.originalPos = el.position(); var orig = e.originalEvent, touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig]; var chromePointerEvents = typeof PointerEvent === 'function'; if (chromePointerEvents) { if (orig.pointerId === undefined) { return; } } // record the starting touch x, y coordinates slider.touch.start.x = touchPoints[0].pageX; slider.touch.start.y = touchPoints[0].pageY; if (slider.viewport.get(0).setPointerCapture) { slider.pointerId = orig.pointerId; slider.viewport.get(0).setPointerCapture(slider.pointerId); } // store original event data for click fixation slider.originalClickTarget = orig.originalTarget || orig.target; slider.originalClickButton = orig.button; slider.originalClickButtons = orig.buttons; slider.originalEventType = orig.type; // at this moment we don`t know what it is click or swipe slider.hasMove = false; // on a "touchmove" event to the viewport slider.viewport.on('touchmove MSPointerMove pointermove', onTouchMove); // on a "touchend" event to the viewport slider.viewport.on('touchend MSPointerUp pointerup', onTouchEnd); slider.viewport.on('MSPointerCancel pointercancel', onPointerCancel); } }; /** * Cancel Pointer for Windows Phone * * @param e (event) * - DOM event object */ var onPointerCancel = function(e) { e.preventDefault(); /* onPointerCancel handler is needed to deal with situations when a touchend doesn't fire after a touchstart (this happens on windows phones only) */ setPositionProperty(slider.touch.originalPos.left, 'reset', 0); //remove handlers slider.controls.el.removeClass('disabled'); slider.viewport.off('MSPointerCancel pointercancel', onPointerCancel); slider.viewport.off('touchmove MSPointerMove pointermove', onTouchMove); slider.viewport.off('touchend MSPointerUp pointerup', onTouchEnd); if (slider.viewport.get(0).releasePointerCapture) { slider.viewport.get(0).releasePointerCapture(slider.pointerId); } }; /** * Event handler for "touchmove" * * @param e (event) * - DOM event object */ var onTouchMove = function(e) { var orig = e.originalEvent, touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig], // if scrolling on y axis, do not prevent default xMovement = Math.abs(touchPoints[0].pageX - slider.touch.start.x), yMovement = Math.abs(touchPoints[0].pageY - slider.touch.start.y), value = 0, change = 0; // this is swipe slider.hasMove = true; // x axis swipe if ((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX) { e.preventDefault(); // y axis swipe } else if ((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY) { e.preventDefault(); } if (e.type !== 'touchmove') { e.preventDefault(); } if (slider.settings.mode !== 'fade' && slider.settings.oneToOneTouch) { // if horizontal, drag along x axis if (slider.settings.mode === 'horizontal') { change = touchPoints[0].pageX - slider.touch.start.x; value = slider.touch.originalPos.left + change; // if vertical, drag along y axis } else { change = touchPoints[0].pageY - slider.touch.start.y; value = slider.touch.originalPos.top + change; } setPositionProperty(value, 'reset', 0); } }; /** * Event handler for "touchend" * * @param e (event) * - DOM event object */ var onTouchEnd = function(e) { e.preventDefault(); slider.viewport.off('touchmove MSPointerMove pointermove', onTouchMove); //enable slider controls as soon as user stops interacing with slides slider.controls.el.removeClass('disabled'); var orig = e.originalEvent, touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig], value = 0, distance = 0; // record end x, y positions slider.touch.end.x = touchPoints[0].pageX; slider.touch.end.y = touchPoints[0].pageY; // if fade mode, check if absolute x distance clears the threshold if (slider.settings.mode === 'fade') { distance = Math.abs(slider.touch.start.x - slider.touch.end.x); if (distance >= slider.settings.swipeThreshold) { if (slider.touch.start.x > slider.touch.end.x) { el.goToNextSlide(); } else { el.goToPrevSlide(); } el.stopAuto(); } // not fade mode } else { // calculate distance and el's animate property if (slider.settings.mode === 'horizontal') { distance = slider.touch.end.x - slider.touch.start.x; value = slider.touch.originalPos.left; } else { distance = slider.touch.end.y - slider.touch.start.y; value = slider.touch.originalPos.top; } // if not infinite loop and first / last slide, do not attempt a slide transition if (!slider.settings.infiniteLoop && ((slider.active.index === 0 && distance > 0) || (slider.active.last && distance < 0))) { setPositionProperty(value, 'reset', 200); } else { // check if distance clears threshold if (Math.abs(distance) >= slider.settings.swipeThreshold) { if (distance < 0) { el.goToNextSlide(); } else { el.goToPrevSlide(); } el.stopAuto(); } else { // el.animate(property, 200); setPositionProperty(value, 'reset', 200); } } } slider.viewport.off('touchend MSPointerUp pointerup', onTouchEnd); if (slider.viewport.get(0).releasePointerCapture) { slider.viewport.get(0).releasePointerCapture(slider.pointerId); } // if slider had swipe with left mouse, touch contact and pen contact if (slider.hasMove === false && (slider.originalClickButton === 0 || slider.originalEventType === 'touchstart')) { // trigger click event (fix for Firefox59 and PointerEvent standard compatibility) $(slider.originalClickTarget).trigger({ type: 'click', button: slider.originalClickButton, buttons: slider.originalClickButtons }); } }; /** * Window resize event callback */ var resizeWindow = function(e) { // don't do anything if slider isn't initialized. if (!slider.initialized) { return; } // Delay if slider working. if (slider.working) { window.setTimeout(resizeWindow, 10); } else { // get the new window dimens (again, thank you IE) var windowWidthNew = $(window).width(), windowHeightNew = $(window).height(); // make sure that it is a true window resize // *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements // are resized. Can you just die already?* if (windowWidth !== windowWidthNew || windowHeight !== windowHeightNew) { // set the new window dimens windowWidth = windowWidthNew; windowHeight = windowHeightNew; // update all dynamic elements el.redrawSlider(); // Call user resize handler slider.settings.onSliderResize.call(el, slider.active.index); } } }; /** * Adds an aria-hidden=true attribute to each element * * @param startVisibleIndex (int) * - the first visible element's index */ var applyAriaHiddenAttributes = function(startVisibleIndex) { var numberOfSlidesShowing = getNumberSlidesShowing(); // only apply attributes if the setting is enabled and not in ticker mode if (slider.settings.ariaHidden && !slider.settings.ticker) { // add aria-hidden=true to all elements slider.children.attr('aria-hidden', 'true'); // get the visible elements and change to aria-hidden=false slider.children.slice(startVisibleIndex, startVisibleIndex + numberOfSlidesShowing).attr('aria-hidden', 'false'); } }; /** * Returns index according to present page range * * @param slideOndex (int) * - the desired slide index */ var setSlideIndex = function(slideIndex) { if (slideIndex < 0) { if (slider.settings.infiniteLoop) { return getPagerQty() - 1; }else { //we don't go to undefined slides return slider.active.index; } // if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop) } else if (slideIndex >= getPagerQty()) { if (slider.settings.infiniteLoop) { return 0; } else { //we don't move to undefined pages return slider.active.index; } // set active index to requested slide } else { return slideIndex; } }; /** * =================================================================================== * = PUBLIC FUNCTIONS * =================================================================================== */ /** * Performs slide transition to the specified slide * * @param slideIndex (int) * - the destination slide's index (zero-based) * * @param direction (string) * - INTERNAL USE ONLY - the direction of travel ("prev" / "next") */ el.goToSlide = function(slideIndex, direction) { // onSlideBefore, onSlideNext, onSlidePrev callbacks // Allow transition canceling based on returned value var performTransition = true, moveBy = 0, position = {left: 0, top: 0}, lastChild = null, lastShowingIndex, eq, value, requestEl; // store the old index slider.oldIndex = slider.active.index; //set new index slider.active.index = setSlideIndex(slideIndex); // if plugin is currently in motion, ignore request if (slider.working || slider.active.index === slider.oldIndex) { return; } // declare that plugin is in motion slider.working = true; performTransition = slider.settings.onSlideBefore.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); // If transitions canceled, reset and return if (typeof (performTransition) !== 'undefined' && !performTransition) { slider.active.index = slider.oldIndex; // restore old index slider.working = false; // is not in motion return; } if (direction === 'next') { // Prevent canceling in future functions or lack there-of from negating previous commands to cancel if (!slider.settings.onSlideNext.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) { performTransition = false; } } else if (direction === 'prev') { // Prevent canceling in future functions or lack there-of from negating previous commands to cancel if (!slider.settings.onSlidePrev.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) { performTransition = false; } } // check if last slide slider.active.last = slider.active.index >= getPagerQty() - 1; // update the pager with active class if (slider.settings.pager || slider.settings.pagerCustom) { updatePagerActive(slider.active.index); } // // check for direction control update if (slider.settings.controls) { updateDirectionControls(); } // if slider is set to mode: "fade" if (slider.settings.mode === 'fade') { // if adaptiveHeight is true and next height is different from current height, animate to the new height if (slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()) { slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); } // fade out the visible child and reset its z-index value slider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0}); // fade in the newly requested slide slider.children.eq(slider.active.index).css('zIndex', slider.settings.slideZIndex + 1).fadeIn(slider.settings.speed, function() { $(this).css('zIndex', slider.settings.slideZIndex); updateAfterSlideTransition(); }); // slider mode is not "fade" } else { // if adaptiveHeight is true and next height is different from current height, animate to the new height if (slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()) { slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); } // if carousel and not infinite loop if (!slider.settings.infiniteLoop && slider.carousel && slider.active.last) { if (slider.settings.mode === 'horizontal') { // get the last child position lastChild = slider.children.eq(slider.children.length - 1); position = lastChild.position(); // calculate the position of the last slide moveBy = slider.viewport.width() - lastChild.outerWidth(); } else { // get last showing index position lastShowingIndex = slider.children.length - slider.settings.minSlides; position = slider.children.eq(lastShowingIndex).position(); } // horizontal carousel, going previous while on first slide (infiniteLoop mode) } else if (slider.carousel && slider.active.last && direction === 'prev') { // get the last child position eq = slider.settings.moveSlides === 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides); lastChild = el.children('.bx-clone').eq(eq); position = lastChild.position(); // if infinite loop and "Next" is clicked on the last slide } else if (direction === 'next' && slider.active.index === 0) { // get the last clone position position = el.find('> .bx-clone').eq(slider.settings.maxSlides).position(); slider.active.last = false; // normal non-zero requests } else if (slideIndex >= 0) { //parseInt is applied to allow floats for slides/page requestEl = slideIndex * parseInt(getMoveBy()); position = slider.children.eq(requestEl).position(); } /* If the position doesn't exist * (e.g. if you destroy the slider on a next click), * it doesn't throw an error. */ if (typeof (position) !== 'undefined') { value = slider.settings.mode === 'horizontal' ? -(position.left - moveBy) : -position.top; // plugin values to be animated setPositionProperty(value, 'slide', slider.settings.speed); } slider.working = false; } if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); } }; /** * Transitions to the next slide in the show */ el.goToNextSlide = function() { // if infiniteLoop is false and last page is showing, disregard call if (!slider.settings.infiniteLoop && slider.active.last) { return; } if (slider.working === true){ return ;} var pagerIndex = parseInt(slider.active.index) + 1; el.goToSlide(pagerIndex, 'next'); }; /** * Transitions to the prev slide in the show */ el.goToPrevSlide = function() { // if infiniteLoop is false and last page is showing, disregard call if (!slider.settings.infiniteLoop && slider.active.index === 0) { return; } if (slider.working === true){ return ;} var pagerIndex = parseInt(slider.active.index) - 1; el.goToSlide(pagerIndex, 'prev'); }; /** * Starts the auto show * * @param preventControlUpdate (boolean) * - if true, auto controls state will not be updated */ el.startAuto = function(preventControlUpdate) { // if an interval already exists, disregard call if (slider.interval) { return; } // create an interval slider.interval = setInterval(function() { if (slider.settings.autoDirection === 'next') { el.goToNextSlide(); } else { el.goToPrevSlide(); } }, slider.settings.pause); //allback for when the auto rotate status changes slider.settings.onAutoChange.call(el, true); // if auto controls are displayed and preventControlUpdate is not true if (slider.settings.autoControls && preventControlUpdate !== true) { updateAutoControls('stop'); } }; /** * Stops the auto show * * @param preventControlUpdate (boolean) * - if true, auto controls state will not be updated */ el.stopAuto = function(preventControlUpdate) { // if slider is auto paused, just clear that state if (slider.autoPaused) slider.autoPaused = false; // if no interval exists, disregard call if (!slider.interval) { return; } // clear the interval clearInterval(slider.interval); slider.interval = null; //allback for when the auto rotate status changes slider.settings.onAutoChange.call(el, false); // if auto controls are displayed and preventControlUpdate is not true if (slider.settings.autoControls && preventControlUpdate !== true) { updateAutoControls('start'); } }; /** * Returns current slide index (zero-based) */ el.getCurrentSlide = function() { return slider.active.index; }; /** * Returns current slide element */ el.getCurrentSlideElement = function() { return slider.children.eq(slider.active.index); }; /** * Returns a slide element * @param index (int) * - The index (zero-based) of the element you want returned. */ el.getSlideElement = function(index) { return slider.children.eq(index); }; /** * Returns number of slides in show */ el.getSlideCount = function() { return slider.children.length; }; /** * Return slider.working variable */ el.isWorking = function() { return slider.working; }; /** * Update all dynamic slider elements */ el.redrawSlider = function() { // resize all children in ratio to new screen size slider.children.add(el.find('.bx-clone')).outerWidth(getSlideWidth()); // adjust the height slider.viewport.css('height', getViewportHeight()); // update the slide position if (!slider.settings.ticker) { setSlidePosition(); } // if active.last was true before the screen resize, we want // to keep it last no matter what screen size we end on if (slider.active.last) { slider.active.index = getPagerQty() - 1; } // if the active index (page) no longer exists due to the resize, simply set the index as last if (slider.active.index >= getPagerQty()) { slider.active.last = true; } // if a pager is being displayed and a custom pager is not being used, update it if (slider.settings.pager && !slider.settings.pagerCustom) { populatePager(); updatePagerActive(slider.active.index); } if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); } }; /** * Destroy the current instance of the slider (revert everything back to original state) */ el.destroySlider = function() { // don't do anything if slider has already been destroyed if (!slider.initialized) { return; } slider.initialized = false; $('.bx-clone', this).remove(); slider.children.each(function() { if ($(this).data('origStyle') !== undefined) { $(this).attr('style', $(this).data('origStyle')); } else { $(this).removeAttr('style'); } }); if ($(this).data('origStyle') !== undefined) { this.attr('style', $(this).data('origStyle')); } else { $(this).removeAttr('style'); } $(this).unwrap().unwrap(); if (slider.controls.el) { slider.controls.el.remove(); } if (slider.controls.next) { slider.controls.next.remove(); } if (slider.controls.prev) { slider.controls.prev.remove(); } if (slider.pagerEl && slider.settings.controls && !slider.settings.pagerCustom) { slider.pagerEl.remove(); } $('.bx-caption', this).remove(); if (slider.controls.autoEl) { slider.controls.autoEl.remove(); } clearInterval(slider.interval); if (slider.settings.responsive) { $(window).off('resize', resizeWindow); } if (slider.settings.keyboardEnabled) { $(document).off('keydown', keyPress); } //remove self reference in data $(this).removeData('bxSlider'); // remove global window handlers $(window).off('blur', windowBlurHandler).off('focus', windowFocusHandler); }; /** * Reload the slider (revert all DOM changes, and re-initialize) */ el.reloadSlider = function(settings) { if (settings !== undefined) { options = settings; } el.destroySlider(); init(); //store reference to self in order to access public functions later $(el).data('bxSlider', this); }; init(); $(el).data('bxSlider', this); // returns the current jQuery object return this; }; })(jQuery); (function($){ //create closure so we can safely use $ as alias for jQuery $(document).ready(function(){ "use strict"; /*-----------------------------------------------------------------------------------*/ /* Superfish Menu /*-----------------------------------------------------------------------------------*/ // initialise plugin var example = $('.sf-menu').superfish({ //add options here if required delay: 100, speed: 'fast', autoArrows: false }); /*-----------------------------------------------------------------------------------*/ /* bxSlider /*-----------------------------------------------------------------------------------*/ $('#featured-content .bxslider').show().bxSlider({ auto: true, preloadImages: 'all', pause: '6000', autoHover: true, adaptiveHeight: true, mode: 'fade', onSliderLoad: function(){ $("#featured-content .bxslider").css("display", "block"); $("#featured-content .bxslider").css("visibility", "visible"); $('#featured-content .entry-header').fadeIn("100"); $('#featured-content .gradient').fadeIn("100"); $(".featured-right").css("display", "block"); $(".ribbon").fadeIn('1000'); } }); $('.gallery-slider').show().bxSlider({ auto: true, preloadImages: 'all', pause: '6000', autoHover: true, adaptiveHeight: true, mode: 'fade', onSliderLoad: function(){ $(".single #primary .gallery-slider").css("display", "block"); } }); /*-----------------------------------------------------------------------------------*/ /* Back to Top /*-----------------------------------------------------------------------------------*/ // hide #back-top first $("#back-top").hide(); $(function () { // fade in #back-top $(window).scroll(function () { if ($(this).scrollTop() > 100) { $('#back-top').fadeIn('200'); } else { $('#back-top').fadeOut('200'); } }); // scroll body to 0px on click $('#back-top a').click(function () { $('body,html').animate({ scrollTop: 0 }, 400); return false; }); }); /*-----------------------------------------------------------------------------------*/ /* Misc. /*-----------------------------------------------------------------------------------*/ $('.widget_ad .widget-title').fadeIn("100"); /*-----------------------------------------------------------------------------------*/ /* Mobile Menu & Search /*-----------------------------------------------------------------------------------*/ /* Mobile Menu */ $('.slicknav_btn').click(function(){ $('.header-search').slideUp('fast', function() {}); $('.search-icon > .genericon-search').removeClass('active'); $('.search-icon > .genericon-close').removeClass('active'); }); /* Mobile Search */ $('.search-icon > .genericon-search').click(function(){ $('.header-search').slideDown('fast', function() {}); $('.search-icon > .genericon-search').toggleClass('active'); $('.search-icon > .genericon-close').toggleClass('active'); $('.slicknav_btn').removeClass('slicknav_open'); $('.slicknav_nav').addClass('slicknav_hidden'); $('.slicknav_nav').css('display','none'); }); $('.search-icon > .genericon-close').click(function(){ $('.header-search').slideUp('fast', function() {}); $('.search-icon > .genericon-search').toggleClass('active'); $('.search-icon > .genericon-close').toggleClass('active'); $('.slicknav_btn').removeClass('slicknav_open'); $('.slicknav_nav').addClass('slicknav_hidden'); $('.slicknav_nav').css('display','none'); }); }); })(jQuery);/*! * Infinite Scroll PACKAGED v3.0.4 * Automatically add next page * * Licensed GPLv3 for open source use * or Infinite Scroll Commercial License for commercial use * * //infinite-scroll.com * Copyright 2018 Metafizzy */ !function(gQefcG,aGeQcM){"function"==typeof define&&define.amd?define("jquery-bridget/jquery-bridget",["jquery"],function(eDeFeQ){return aGeQcM(gQefcG,eDeFeQ)}):"object"==typeof module&&module.exports?module.exports=aGeQcM(gQefcG,require("jquery")):gQefcG.jQueryBridget=aGeQcM(gQefcG,gQefcG.jQuery)}(window,function(gQefcG,aGeQcM){"use strict";function eDeFeQ(eDeFeQ,cHcUcY,fieNeI){function dbcedf(gQefcG,aGeQcM,bNeSbT){var aBcGeh,cHcUcY="$()."+eDeFeQ+'("'+aGeQcM+'")';return gQefcG.each(function(gQefcG,dbcedf){var dEfJba=fieNeI.data(dbcedf,eDeFeQ);if(!dEfJba)return void fOgAaR(eDeFeQ+" not initialized. Cannot call methods, i.e. "+cHcUcY);var gQefcGgQefcG=dEfJba[aGeQcM];if(!gQefcGgQefcG||"_"==aGeQcM.charAt(0))return void fOgAaR(cHcUcY+" is not a valid method");var aGeQcMgQefcG=gQefcGgQefcG.apply(dEfJba,bNeSbT);aBcGeh=void 0===aBcGeh?aGeQcMgQefcG:aBcGeh}),void 0!==aBcGeh?aBcGeh:gQefcG}function dEfJba(gQefcG,aGeQcM){gQefcG.each(function(gQefcG,bNeSbT){var aBcGeh=fieNeI.data(bNeSbT,eDeFeQ);aBcGeh?(aBcGeh.option(aGeQcM),aBcGeh._init()):(aBcGeh=new cHcUcY(bNeSbT,aGeQcM),fieNeI.data(bNeSbT,eDeFeQ,aBcGeh))})}fieNeI=fieNeI||aGeQcM||gQefcG.jQuery,fieNeI&&(cHcUcY.prototype.option||(cHcUcY.prototype.option=function(gQefcG){fieNeI.isPlainObject(gQefcG)&&(this.options=fieNeI.extend(!0,this.options,gQefcG))}),fieNeI.fn[eDeFeQ]=function(gQefcG){if("string"==typeof gQefcG){var aGeQcM=aBcGeh.call(arguments,1);return dbcedf(this,gQefcG,aGeQcM)}return dEfJba(this,gQefcG),this},bNeSbT(fieNeI))}function bNeSbT(gQefcG){!gQefcG||gQefcG&&gQefcG.bridget||(gQefcG.bridget=eDeFeQ)}var aBcGeh=Array.prototype.slice,cHcUcY=gQefcG.console,fOgAaR="undefined"==typeof cHcUcY?function(){}:function(gQefcG){cHcUcY.error(gQefcG)};return bNeSbT(aGeQcM||gQefcG.jQuery),eDeFeQ}),function(gQefcG,aGeQcM){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",aGeQcM):"object"==typeof module&&module.exports?module.exports=aGeQcM():gQefcG.EvEmitter=aGeQcM()}("undefined"!=typeof window?window:this,function(){function gQefcG(){}var aGeQcM=gQefcG.prototype;return aGeQcM.on=function(gQefcG,aGeQcM){if(gQefcG&&aGeQcM){var eDeFeQ=this._events=this._events||{},bNeSbT=eDeFeQ[gQefcG]=eDeFeQ[gQefcG]||[];return bNeSbT.indexOf(aGeQcM)==-1&&bNeSbT.push(aGeQcM),this}},aGeQcM.once=function(gQefcG,aGeQcM){if(gQefcG&&aGeQcM){this.on(gQefcG,aGeQcM);var eDeFeQ=this._onceEvents=this._onceEvents||{},bNeSbT=eDeFeQ[gQefcG]=eDeFeQ[gQefcG]||{};return bNeSbT[aGeQcM]=!0,this}},aGeQcM.off=function(gQefcG,aGeQcM){var eDeFeQ=this._events&&this._events[gQefcG];if(eDeFeQ&&eDeFeQ.length){var bNeSbT=eDeFeQ.indexOf(aGeQcM);return bNeSbT!=-1&&eDeFeQ.splice(bNeSbT,1),this}},aGeQcM.emitEvent=function(gQefcG,aGeQcM){var eDeFeQ=this._events&&this._events[gQefcG];if(eDeFeQ&&eDeFeQ.length){eDeFeQ=eDeFeQ.slice(0),aGeQcM=aGeQcM||[];for(var bNeSbT=this._onceEvents&&this._onceEvents[gQefcG],aBcGeh=0;aBcGeh=0,this.isPrefilling?(this.log("prefill"),this.loadNextPage()):this.stopPrefill()},fOgAaR.getPrefillDistance=function(){return this.options.elementScroll?this.scroller.clientHeight-this.scroller.scrollHeight:this.windowHeight-this.element.clientHeight},fOgAaR.stopPrefill=function(){this.log("stopPrefill"),this.off("append",this.prefill)},aGeQcM}),function(gQefcG,aGeQcM){"function"==typeof define&&define.amd?define("infinite-scroll/js/scroll-watch",["./core","fizzy-ui-utils/utils"],function(eDeFeQ,bNeSbT){return aGeQcM(gQefcG,eDeFeQ,bNeSbT)}):"object"==typeof module&&module.exports?module.exports=aGeQcM(gQefcG,require("./core"),require("fizzy-ui-utils")):aGeQcM(gQefcG,gQefcG.InfiniteScroll,gQefcG.fizzyUIUtils)}(window,function(gQefcG,aGeQcM,eDeFeQ){var bNeSbT=aGeQcM.prototype;return aGeQcM.defaults.scrollThreshold=400,aGeQcM.create.scrollWatch=function(){this.pageScrollHandler=this.onPageScroll.bind(this),this.resizeHandler=this.onResize.bind(this);var gQefcG=this.options.scrollThreshold,aGeQcM=gQefcG||0===gQefcG;aGeQcM&&this.enableScrollWatch()},aGeQcM.destroy.scrollWatch=function(){this.disableScrollWatch()},bNeSbT.enableScrollWatch=function(){this.isScrollWatching||(this.isScrollWatching=!0,this.updateMeasurements(),this.updateScroller(),this.on("last",this.disableScrollWatch),this.bindScrollWatchEvents(!0))},bNeSbT.disableScrollWatch=function(){this.isScrollWatching&&(this.bindScrollWatchEvents(!1),delete this.isScrollWatching)},bNeSbT.bindScrollWatchEvents=function(aGeQcM){var eDeFeQ=aGeQcM?"addEventListener":"removeEventListener";this.scroller[eDeFeQ]("scroll",this.pageScrollHandler),gQefcG[eDeFeQ]("resize",this.resizeHandler)},bNeSbT.onPageScroll=aGeQcM.throttle(function(){var gQefcG=this.getBottomDistance();gQefcG<=this.options.scrollThreshold&&this.dispatchEvent("scrollThreshold")}),bNeSbT.getBottomDistance=function(){return this.options.elementScroll?this.getElementBottomDistance():this.getWindowBottomDistance()},bNeSbT.getWindowBottomDistance=function(){var aGeQcM=this.top+this.element.clientHeight,eDeFeQ=gQefcG.pageYOffset+this.windowHeight;return aGeQcM-eDeFeQ},bNeSbT.getElementBottomDistance=function(){var gQefcG=this.scroller.scrollHeight,aGeQcM=this.scroller.scrollTop+this.scroller.clientHeight;return gQefcG-aGeQcM},bNeSbT.onResize=function(){this.updateMeasurements()},eDeFeQ.debounceMethod(aGeQcM,"onResize",150),aGeQcM}),function(gQefcG,aGeQcM){"function"==typeof define&&define.amd?define("infinite-scroll/js/history",["./core","fizzy-ui-utils/utils"],function(eDeFeQ,bNeSbT){return aGeQcM(gQefcG,eDeFeQ,bNeSbT)}):"object"==typeof module&&module.exports?module.exports=aGeQcM(gQefcG,require("./core"),require("fizzy-ui-utils")):aGeQcM(gQefcG,gQefcG.InfiniteScroll,gQefcG.fizzyUIUtils)}(window,function(gQefcG,aGeQcM,eDeFeQ){var bNeSbT=aGeQcM.prototype;aGeQcM.defaults.history="replace";var aBcGeh=document.createElement("a");return aGeQcM.create.history=function(){if(this.options.history){aBcGeh.href=this.getAbsolutePath();var gQefcG=aBcGeh.origin||aBcGeh.protocol+"//"+aBcGeh.host,aGeQcM=gQefcG==location.origin;return aGeQcM?void(this.options.append?this.createHistoryAppend():this.createHistoryPageLoad()):void console.error("[InfiniteScroll] cannot set history with different origin: "+aBcGeh.origin+" on "+location.origin+" . History behavior disabled.")}},bNeSbT.createHistoryAppend=function(){this.updateMeasurements(),this.updateScroller(),this.scrollPages=[{top:0,path:location.href,title:document.title}],this.scrollPageIndex=0,this.scrollHistoryHandler=this.onScrollHistory.bind(this),this.unloadHandler=this.onUnload.bind(this),this.scroller.addEventListener("scroll",this.scrollHistoryHandler),this.on("append",this.onAppendHistory),this.bindHistoryAppendEvents(!0)},bNeSbT.bindHistoryAppendEvents=function(aGeQcM){var eDeFeQ=aGeQcM?"addEventListener":"removeEventListener";this.scroller[eDeFeQ]("scroll",this.scrollHistoryHandler),gQefcG[eDeFeQ]("unload",this.unloadHandler)},bNeSbT.createHistoryPageLoad=function(){this.on("load",this.onPageLoadHistory)},aGeQcM.destroy.history=bNeSbT.destroyHistory=function(){var gQefcG=this.options.history&&this.options.append;gQefcG&&this.bindHistoryAppendEvents(!1)},bNeSbT.onAppendHistory=function(gQefcG,aGeQcM,eDeFeQ){if(eDeFeQ&&eDeFeQ.length){var bNeSbT=eDeFeQ[0],cHcUcY=this.getElementScrollY(bNeSbT);aBcGeh.href=aGeQcM,this.scrollPages.push({top:cHcUcY,path:aBcGeh.href,title:gQefcG.title})}},bNeSbT.getElementScrollY=function(gQefcG){return this.options.elementScroll?this.getElementElementScrollY(gQefcG):this.getElementWindowScrollY(gQefcG)},bNeSbT.getElementWindowScrollY=function(aGeQcM){var eDeFeQ=aGeQcM.getBoundingClientRect();return eDeFeQ.top+gQefcG.pageYOffset},bNeSbT.getElementElementScrollY=function(gQefcG){return gQefcG.offsetTop-this.top},bNeSbT.onScrollHistory=function(){for(var gQefcG,aGeQcM,eDeFeQ=this.getScrollViewY(),bNeSbT=0;bNeSbT=eDeFeQ)break;gQefcG=bNeSbT,aGeQcM=aBcGeh}gQefcG!=this.scrollPageIndex&&(this.scrollPageIndex=gQefcG,this.setHistory(aGeQcM.title,aGeQcM.path))},eDeFeQ.debounceMethod(aGeQcM,"onScrollHistory",150),bNeSbT.getScrollViewY=function(){return this.options.elementScroll?this.scroller.scrollTop+this.scroller.clientHeight/2:gQefcG.pageYOffset+this.windowHeight/2},bNeSbT.setHistory=function(gQefcG,aGeQcM){var eDeFeQ=this.options.history,bNeSbT=eDeFeQ&&history[eDeFeQ+"State"];bNeSbT&&(history[eDeFeQ+"State"](null,gQefcG,aGeQcM),this.options.historyTitle&&(document.title=gQefcG),this.dispatchEvent("history",null,[gQefcG,aGeQcM]))},bNeSbT.onUnload=function(){var aGeQcM=this.scrollPageIndex;if(0!==aGeQcM){var eDeFeQ=this.scrollPages[aGeQcM],bNeSbT=gQefcG.pageYOffset-eDeFeQ.top+this.top;this.destroyHistory(),scrollTo(0,bNeSbT)}},bNeSbT.onPageLoadHistory=function(gQefcG,aGeQcM){this.setHistory(gQefcG.title,aGeQcM)},aGeQcM}),function(gQefcG,aGeQcM){"function"==typeof define&&define.amd?define("infinite-scroll/js/button",["./core","fizzy-ui-utils/utils"],function(eDeFeQ,bNeSbT){return aGeQcM(gQefcG,eDeFeQ,bNeSbT)}):"object"==typeof module&&module.exports?module.exports=aGeQcM(gQefcG,require("./core"),require("fizzy-ui-utils")):aGeQcM(gQefcG,gQefcG.InfiniteScroll,gQefcG.fizzyUIUtils)}(window,function(gQefcG,aGeQcM,eDeFeQ){function bNeSbT(gQefcG,aGeQcM){this.element=gQefcG,this.infScroll=aGeQcM,this.clickHandler=this.onClick.bind(this),this.element.addEventListener("click",this.clickHandler),aGeQcM.on("request",this.disable.bind(this)),aGeQcM.on("load",this.enable.bind(this)),aGeQcM.on("error",this.hide.bind(this)),aGeQcM.on("last",this.hide.bind(this))}return aGeQcM.create.button=function(){var gQefcG=eDeFeQ.getQueryElement(this.options.button);if(gQefcG)return void(this.button=new bNeSbT(gQefcG,this))},aGeQcM.destroy.button=function(){this.button&&this.button.destroy()},bNeSbT.prototype.onClick=function(gQefcG){gQefcG.preventDefault(),this.infScroll.loadNextPage()},bNeSbT.prototype.enable=function(){this.element.removeAttribute("disabled")},bNeSbT.prototype.disable=function(){this.element.disabled="disabled"},bNeSbT.prototype.hide=function(){this.element.style.display="none"},bNeSbT.prototype.destroy=function(){this.element.removeEventListener("click",this.clickHandler)},aGeQcM.Button=bNeSbT,aGeQcM}),function(gQefcG,aGeQcM){"function"==typeof define&&define.amd?define("infinite-scroll/js/status",["./core","fizzy-ui-utils/utils"],function(eDeFeQ,bNeSbT){return aGeQcM(gQefcG,eDeFeQ,bNeSbT)}):"object"==typeof module&&module.exports?module.exports=aGeQcM(gQefcG,require("./core"),require("fizzy-ui-utils")):aGeQcM(gQefcG,gQefcG.InfiniteScroll,gQefcG.fizzyUIUtils)}(window,function(gQefcG,aGeQcM,eDeFeQ){function bNeSbT(gQefcG){cHcUcY(gQefcG,"none")}function aBcGeh(gQefcG){cHcUcY(gQefcG,"block")}function cHcUcY(gQefcG,aGeQcM){gQefcG&&(gQefcG.style.display=aGeQcM)}var fOgAaR=aGeQcM.prototype;return aGeQcM.create.status=function(){var gQefcG=eDeFeQ.getQueryElement(this.options.status);gQefcG&&(this.statusElement=gQefcG,this.statusEventElements={request:gQefcG.querySelector(".infinite-scroll-request"),error:gQefcG.querySelector(".infinite-scroll-error"),last:gQefcG.querySelector(".infinite-scroll-last")},this.on("request",this.showRequestStatus),this.on("error",this.showErrorStatus),this.on("last",this.showLastStatus),this.bindHideStatus("on"))},fOgAaR.bindHideStatus=function(gQefcG){var aGeQcM=this.options.append?"append":"load";this[gQefcG](aGeQcM,this.hideAllStatus)},fOgAaR.showRequestStatus=function(){this.showStatus("request")},fOgAaR.showErrorStatus=function(){this.showStatus("error")},fOgAaR.showLastStatus=function(){this.showStatus("last"),this.bindHideStatus("off")},fOgAaR.showStatus=function(gQefcG){aBcGeh(this.statusElement),this.hideStatusEventElements();var aGeQcM=this.statusEventElements[gQefcG];aBcGeh(aGeQcM)},fOgAaR.hideAllStatus=function(){bNeSbT(this.statusElement),this.hideStatusEventElements()},fOgAaR.hideStatusEventElements=function(){for(var gQefcG in this.statusEventElements){var aGeQcM=this.statusEventElements[gQefcG];bNeSbT(aGeQcM)}},aGeQcM}),function(gQefcG,aGeQcM){"function"==typeof define&&define.amd?define(["infinite-scroll/js/core","infinite-scroll/js/page-load","infinite-scroll/js/scroll-watch","infinite-scroll/js/history","infinite-scroll/js/button","infinite-scroll/js/status"],aGeQcM):"object"==typeof module&&module.exports&&(module.exports=aGeQcM(require("./core"),require("./page-load"),require("./scroll-watch"),require("./history"),require("./button"),require("./status")))}(window,function(gQefcG){return gQefcG}),function(gQefcG,aGeQcM){"use strict";"function"==typeof define&&define.amd?define("imagesloaded/imagesloaded",["ev-emitter/ev-emitter"],function(eDeFeQ){return aGeQcM(gQefcG,eDeFeQ)}):"object"==typeof module&&module.exports?module.exports=aGeQcM(gQefcG,require("ev-emitter")):gQefcG.imagesLoaded=aGeQcM(gQefcG,gQefcG.EvEmitter)}("undefined"!=typeof window?window:this,function(gQefcG,aGeQcM){function eDeFeQ(gQefcG,aGeQcM){for(var eDeFeQ in aGeQcM)gQefcG[eDeFeQ]=aGeQcM[eDeFeQ];return gQefcG}function bNeSbT(gQefcG){if(Array.isArray(gQefcG))return gQefcG;var aGeQcM="object"==typeof gQefcG&&"number"==typeof gQefcG.length;return aGeQcM?dEfJba.call(gQefcG):[gQefcG]}function aBcGeh(gQefcG,aGeQcM,cHcUcY){if(!(this instanceof aBcGeh))return new aBcGeh(gQefcG,aGeQcM,cHcUcY);var fOgAaR=gQefcG;return"string"==typeof gQefcG&&(fOgAaR=document.querySelectorAll(gQefcG)),fOgAaR?(this.elements=bNeSbT(fOgAaR),this.options=eDeFeQ({},this.options),"function"==typeof aGeQcM?cHcUcY=aGeQcM:eDeFeQ(this.options,aGeQcM),cHcUcY&&this.on("always",cHcUcY),this.getImages(),fieNeI&&(this.jqDeferred=new fieNeI.Deferred),void setTimeout(this.check.bind(this))):void dbcedf.error("Bad element for imagesLoaded "+(fOgAaR||gQefcG))}function cHcUcY(gQefcG){this.img=gQefcG}function fOgAaR(gQefcG,aGeQcM){this.url=gQefcG,this.element=aGeQcM,this.img=new Image}var fieNeI=gQefcG.jQuery,dbcedf=gQefcG.console,dEfJba=Array.prototype.slice;aBcGeh.prototype=Object.create(aGeQcM.prototype),aBcGeh.prototype.options={},aBcGeh.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)},aBcGeh.prototype.addElementImages=function(gQefcG){"IMG"==gQefcG.nodeName&&this.addImage(gQefcG),this.options.background===!0&&this.addElementBackgroundImages(gQefcG);var aGeQcM=gQefcG.nodeType;if(aGeQcM&&gQefcGgQefcG[aGeQcM]){for(var eDeFeQ=gQefcG.querySelectorAll("img"),bNeSbT=0;bNeSbT