????JFIF??x?x????'
Server IP : 79.136.114.73 / Your IP : 18.117.121.244 Web Server : Apache/2.4.7 (Ubuntu) PHP/5.5.9-1ubuntu4.29 OpenSSL/1.0.1f System : Linux b8009 3.13.0-170-generic #220-Ubuntu SMP Thu May 9 12:40:49 UTC 2019 x86_64 User : www-data ( 33) PHP Version : 5.5.9-1ubuntu4.29 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority, MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /var/www/www.astacus.se/wp-content/themes/x/framework/js/dist/site/ |
Upload File : |
// ============================================================================= // JS/X-BODY.JS // ----------------------------------------------------------------------------- // Site specific functionality needed before the closing </body> tag. // ============================================================================= // ============================================================================= // TABLE OF CONTENTS // ----------------------------------------------------------------------------- // 01. Imports // ============================================================================= // Imports // ============================================================================= /*! * hoverIntent v1.8.0 // 2014.06.29 // jQuery v1.9.1+ * http://cherne.net/brian/resources/jquery.hoverIntent.html * * You may use hoverIntent under the terms of the MIT license. Basically that * means you are free to use hoverIntent as long as this header is left intact. * Copyright 2007, 2014 Brian Cherne */ /* hoverIntent is similar to jQuery's built-in "hover" method except that * instead of firing the handlerIn function immediately, hoverIntent checks * to see if the user's mouse has slowed down (beneath the sensitivity * threshold) before firing the event. The handlerOut function is only * called after a matching handlerIn. * * // basic usage ... just like .hover() * .hoverIntent( handlerIn, handlerOut ) * .hoverIntent( handlerInOut ) * * // basic usage ... with event delegation! * .hoverIntent( handlerIn, handlerOut, selector ) * .hoverIntent( handlerInOut, selector ) * * // using a basic configuration object * .hoverIntent( config ) * * @param handlerIn function OR configuration object * @param handlerOut function OR selector for delegation OR undefined * @param selector selector OR undefined * @author Brian Cherne <brian(at)cherne(dot)net> */ (function($) { $.fn.hoverIntent = function(handlerIn,handlerOut,selector) { // default configuration values var cfg = { interval: 100, sensitivity: 6, timeout: 0 }; if ( typeof handlerIn === "object" ) { cfg = $.extend(cfg, handlerIn ); } else if ($.isFunction(handlerOut)) { cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } ); } else { cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } ); } // instantiate variables // cX, cY = current X and Y position of mouse, updated by mousemove event // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval var cX, cY, pX, pY; // A private function for getting mouse position var track = function(ev) { cX = ev.pageX; cY = ev.pageY; }; // A private function for comparing current and previous mouse position var compare = function(ev,ob) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); // compare mouse positions to see if they've crossed the threshold if ( Math.sqrt( (pX-cX)*(pX-cX) + (pY-cY)*(pY-cY) ) < cfg.sensitivity ) { $(ob).off("mousemove.hoverIntent",track); // set hoverIntent state to true (so mouseOut can be called) ob.hoverIntent_s = true; return cfg.over.apply(ob,[ev]); } else { // set previous coordinates for next time pX = cX; pY = cY; // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs) ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval ); } }; // A private function for delaying the mouseOut function var delay = function(ev,ob) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); ob.hoverIntent_s = false; return cfg.out.apply(ob,[ev]); }; // A private function for handling mouse 'hovering' var handleHover = function(e) { // copy objects to be passed into t (required for event object to be passed in IE) var ev = $.extend({},e); var ob = this; // cancel hoverIntent timer if it exists if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); } // if e.type === "mouseenter" if (e.type === "mouseenter") { // set "previous" X and Y position based on initial entry point pX = ev.pageX; pY = ev.pageY; // update "current" X and Y position based on mousemove $(ob).on("mousemove.hoverIntent",track); // start polling interval (self-calling timeout) to compare mouse coordinates over time if (!ob.hoverIntent_s) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );} // else e.type == "mouseleave" } else { // unbind expensive mousemove event $(ob).off("mousemove.hoverIntent",track); // if hoverIntent state is true, then call the mouseOut function after the specified delay if (ob.hoverIntent_s) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );} } }; // listen for mouseenter and mouseleave return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector); }; })(jQuery); /** * Isotope v1.5.26 * An exquisite jQuery plugin for magical layouts * http://isotope.metafizzy.co * * Commercial use requires one-time purchase of a commercial license * http://isotope.metafizzy.co/docs/license.html * * Non-commercial use is licensed under the MIT License * * Copyright 2014 Metafizzy */ /*jshint asi: true, browser: true, curly: true, eqeqeq: true, forin: false, immed: false, newcap: true, noempty: true, strict: true, undef: true */ /*global jQuery: false */ (function( window, $, undefined ){ 'use strict'; // get global vars var document = window.document; var docElem = document.documentElement; var Modernizr = window.Modernizr; // helper function var capitalize = function( str ) { return str.charAt(0).toUpperCase() + str.slice(1); }; // ========================= getStyleProperty by kangax =============================== // http://perfectionkills.com/feature-testing-css-properties/ var prefixes = 'Moz Webkit O Ms'.split(' '); var getStyleProperty = function( propName ) { var style = docElem.style, prefixed; // test standard property first if ( typeof style[propName] === 'string' ) { return propName; } // capitalize propName = capitalize( propName ); // test vendor specific properties for ( var i=0, len = prefixes.length; i < len; i++ ) { prefixed = prefixes[i] + propName; if ( typeof style[ prefixed ] === 'string' ) { return prefixed; } } }; var transformProp = getStyleProperty('transform'), transitionProp = getStyleProperty('transitionProperty'); // ========================= miniModernizr =============================== // <3<3<3 and thanks to Faruk and Paul for doing the heavy lifting /*! * Modernizr v1.6ish: miniModernizr for Isotope * http://www.modernizr.com * * Developed by: * - Faruk Ates http://farukat.es/ * - Paul Irish http://paulirish.com/ * * Copyright (c) 2009-2010 * Dual-licensed under the BSD or MIT licenses. * http://www.modernizr.com/license/ */ /* * This version whittles down the script just to check support for * CSS transitions, transforms, and 3D transforms. */ var tests = { csstransforms: function() { return !!transformProp; }, csstransforms3d: function() { var test = !!getStyleProperty('perspective'); // double check for Chrome's false positive if ( test && 'webkitPerspective' in docElem.style ) { var $style = $('<style>@media (transform-3d),(-webkit-transform-3d)' + '{#modernizr{height:3px}}</style>').appendTo('head'), $div = $('<div id="modernizr" />').appendTo('html'); test = $div.height() === 3; $div.remove(); $style.remove(); } return test; }, csstransitions: function() { return !!transitionProp; } }; var testName; if ( Modernizr ) { // if there's a previous Modernzir, check if there are necessary tests for ( testName in tests) { if ( !Modernizr.hasOwnProperty( testName ) ) { // if test hasn't been run, use addTest to run it Modernizr.addTest( testName, tests[ testName ] ); } } } else { // or create new mini Modernizr that just has the 3 tests Modernizr = window.Modernizr = { _version : '1.6ish: miniModernizr for Isotope' }; var classes = ' '; var result; // Run through tests for ( testName in tests) { result = tests[ testName ](); Modernizr[ testName ] = result; classes += ' ' + ( result ? '' : 'no-' ) + testName; } // Add the new classes to the <html> element. $('html').addClass( classes ); } // ========================= isoTransform =============================== /** * provides hooks for .css({ scale: value, translate: [x, y] }) * Progressively enhanced CSS transforms * Uses hardware accelerated 3D transforms for Safari * or falls back to 2D transforms. */ if ( Modernizr.csstransforms ) { // i.e. transformFnNotations.scale(0.5) >> 'scale3d( 0.5, 0.5, 1)' var transformFnNotations = Modernizr.csstransforms3d ? { // 3D transform functions translate : function ( position ) { return 'translate3d(' + position[0] + 'px, ' + position[1] + 'px, 0) '; }, scale : function ( scale ) { return 'scale3d(' + scale + ', ' + scale + ', 1) '; } } : { // 2D transform functions translate : function ( position ) { return 'translate(' + position[0] + 'px, ' + position[1] + 'px) '; }, scale : function ( scale ) { return 'scale(' + scale + ') '; } } ; var setIsoTransform = function ( elem, name, value ) { // unpack current transform data var data = $.data( elem, 'isoTransform' ) || {}, newData = {}, fnName, transformObj = {}, transformValue; // i.e. newData.scale = 0.5 newData[ name ] = value; // extend new value over current data $.extend( data, newData ); for ( fnName in data ) { transformValue = data[ fnName ]; transformObj[ fnName ] = transformFnNotations[ fnName ]( transformValue ); } // get proper order // ideally, we could loop through this give an array, but since we only have // a couple transforms we're keeping track of, we'll do it like so var translateFn = transformObj.translate || '', scaleFn = transformObj.scale || '', // sorting so translate always comes first valueFns = translateFn + scaleFn; // set data back in elem $.data( elem, 'isoTransform', data ); // set name to vendor specific property elem.style[ transformProp ] = valueFns; }; // ==================== scale =================== $.cssNumber.scale = true; $.cssHooks.scale = { set: function( elem, value ) { // uncomment this bit if you want to properly parse strings // if ( typeof value === 'string' ) { // value = parseFloat( value ); // } setIsoTransform( elem, 'scale', value ); }, get: function( elem, computed ) { var transform = $.data( elem, 'isoTransform' ); return transform && transform.scale ? transform.scale : 1; } }; $.fx.step.scale = function( fx ) { $.cssHooks.scale.set( fx.elem, fx.now+fx.unit ); }; // ==================== translate =================== $.cssNumber.translate = true; $.cssHooks.translate = { set: function( elem, value ) { // uncomment this bit if you want to properly parse strings // if ( typeof value === 'string' ) { // value = value.split(' '); // } // // var i, val; // for ( i = 0; i < 2; i++ ) { // val = value[i]; // if ( typeof val === 'string' ) { // val = parseInt( val ); // } // } setIsoTransform( elem, 'translate', value ); }, get: function( elem, computed ) { var transform = $.data( elem, 'isoTransform' ); return transform && transform.translate ? transform.translate : [ 0, 0 ]; } }; } // ========================= get transition-end event =============================== var transitionEndEvent, transitionDurProp; if ( Modernizr.csstransitions ) { transitionEndEvent = { WebkitTransitionProperty: 'webkitTransitionEnd', // webkit MozTransitionProperty: 'transitionend', OTransitionProperty: 'oTransitionEnd otransitionend', transitionProperty: 'transitionend' }[ transitionProp ]; transitionDurProp = getStyleProperty('transitionDuration'); } // ========================= smartresize =============================== /* * smartresize: debounced resize event for jQuery * * latest version and complete README available on Github: * https://github.com/louisremi/jquery.smartresize.js * * Copyright 2011 @louis_remi * Licensed under the MIT license. */ var $event = $.event, dispatchMethod = 'dispatch', resizeTimeout; $event.special.smartresize = { setup: function() { $(this).bind( "resize", $event.special.smartresize.handler ); }, teardown: function() { $(this).unbind( "resize", $event.special.smartresize.handler ); }, handler: function( event, execAsap ) { // Save the context var context = this, args = arguments; // set correct event type event.type = "smartresize"; if ( resizeTimeout ) { clearTimeout( resizeTimeout ); } resizeTimeout = setTimeout(function() { $event[ dispatchMethod ].apply( context, args ); }, execAsap === "execAsap"? 0 : 100 ); } }; $.fn.smartresize = function( fn ) { return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] ); }; // ========================= Isotope =============================== // our "Widget" object constructor $.Isotope = function( options, element, callback ){ this.element = $( element ); this._create( options ); this._init( callback ); }; // styles of container element we want to keep track of var isoContainerStyles = [ 'width', 'height' ]; var $window = $(window); $.Isotope.settings = { resizable: true, layoutMode : 'masonry', containerClass : 'isotope', itemClass : 'isotope-item', hiddenClass : 'isotope-hidden', hiddenStyle: { opacity: 0, scale: 0.001 }, visibleStyle: { opacity: 1, scale: 1 }, containerStyle: { position: 'relative', overflow: 'hidden' }, animationEngine: 'best-available', animationOptions: { queue: false, duration: 800 }, sortBy : 'original-order', sortAscending : true, resizesContainer : true, transformsEnabled: true, itemPositionDataEnabled: false }; $.Isotope.prototype = { // sets up widget _create : function( options ) { this.options = $.extend( {}, $.Isotope.settings, options ); this.styleQueue = []; this.elemCount = 0; // get original styles in case we re-apply them in .destroy() var elemStyle = this.element[0].style; this.originalStyle = {}; // keep track of container styles var containerStyles = isoContainerStyles.slice(0); for ( var prop in this.options.containerStyle ) { containerStyles.push( prop ); } for ( var i=0, len = containerStyles.length; i < len; i++ ) { prop = containerStyles[i]; this.originalStyle[ prop ] = elemStyle[ prop ] || ''; } // apply container style from options this.element.css( this.options.containerStyle ); this._updateAnimationEngine(); this._updateUsingTransforms(); // sorting var originalOrderSorter = { 'original-order' : function( $elem, instance ) { instance.elemCount ++; return instance.elemCount; }, random : function() { return Math.random(); } }; this.options.getSortData = $.extend( this.options.getSortData, originalOrderSorter ); // need to get atoms this.reloadItems(); // get top left position of where the bricks should be this.offset = { left: parseInt( ( this.element.css('padding-left') || 0 ), 10 ), top: parseInt( ( this.element.css('padding-top') || 0 ), 10 ) }; // add isotope class first time around var instance = this; setTimeout( function() { instance.element.addClass( instance.options.containerClass ); }, 0 ); // bind resize method if ( this.options.resizable ) { $window.bind( 'smartresize.isotope', function() { instance.resize(); }); } // dismiss all click events from hidden events this.element.delegate( '.' + this.options.hiddenClass, 'click', function(){ return false; }); }, _getAtoms : function( $elems ) { var selector = this.options.itemSelector, // filter & find $atoms = selector ? $elems.filter( selector ).add( $elems.find( selector ) ) : $elems, // base style for atoms atomStyle = { position: 'absolute' }; // filter out text nodes $atoms = $atoms.filter( function( i, atom ) { return atom.nodeType === 1; }); if ( this.usingTransforms ) { atomStyle.left = 0; atomStyle.top = 0; } $atoms.css( atomStyle ).addClass( this.options.itemClass ); this.updateSortData( $atoms, true ); return $atoms; }, // _init fires when your instance is first created // (from the constructor above), and when you // attempt to initialize the widget again (by the bridge) // after it has already been initialized. _init : function( callback ) { this.$filteredAtoms = this._filter( this.$allAtoms ); this._sort(); this.reLayout( callback ); }, option : function( opts ){ // change options AFTER initialization: // signature: $('#foo').bar({ cool:false }); if ( $.isPlainObject( opts ) ){ this.options = $.extend( true, this.options, opts ); // trigger _updateOptionName if it exists var updateOptionFn; for ( var optionName in opts ) { updateOptionFn = '_update' + capitalize( optionName ); if ( this[ updateOptionFn ] ) { this[ updateOptionFn ](); } } } }, // ====================== updaters ====================== // // kind of like setters _updateAnimationEngine : function() { var animationEngine = this.options.animationEngine.toLowerCase().replace( /[ _\-]/g, ''); var isUsingJQueryAnimation; // set applyStyleFnName switch ( animationEngine ) { case 'css' : case 'none' : isUsingJQueryAnimation = false; break; case 'jquery' : isUsingJQueryAnimation = true; break; default : // best available isUsingJQueryAnimation = !Modernizr.csstransitions; } this.isUsingJQueryAnimation = isUsingJQueryAnimation; this._updateUsingTransforms(); }, _updateTransformsEnabled : function() { this._updateUsingTransforms(); }, _updateUsingTransforms : function() { var usingTransforms = this.usingTransforms = this.options.transformsEnabled && Modernizr.csstransforms && Modernizr.csstransitions && !this.isUsingJQueryAnimation; // prevent scales when transforms are disabled if ( !usingTransforms ) { delete this.options.hiddenStyle.scale; delete this.options.visibleStyle.scale; } this.getPositionStyles = usingTransforms ? this._translate : this._positionAbs; }, // ====================== Filtering ====================== _filter : function( $atoms ) { var filter = this.options.filter === '' ? '*' : this.options.filter; if ( !filter ) { return $atoms; } var hiddenClass = this.options.hiddenClass, hiddenSelector = '.' + hiddenClass, $hiddenAtoms = $atoms.filter( hiddenSelector ), $atomsToShow = $hiddenAtoms; if ( filter !== '*' ) { $atomsToShow = $hiddenAtoms.filter( filter ); var $atomsToHide = $atoms.not( hiddenSelector ).not( filter ).addClass( hiddenClass ); this.styleQueue.push({ $el: $atomsToHide, style: this.options.hiddenStyle }); } this.styleQueue.push({ $el: $atomsToShow, style: this.options.visibleStyle }); $atomsToShow.removeClass( hiddenClass ); return $atoms.filter( filter ); }, // ====================== Sorting ====================== updateSortData : function( $atoms, isIncrementingElemCount ) { var instance = this, getSortData = this.options.getSortData, $this, sortData; $atoms.each(function(){ $this = $(this); sortData = {}; // get value for sort data based on fn( $elem ) passed in for ( var key in getSortData ) { if ( !isIncrementingElemCount && key === 'original-order' ) { // keep original order original sortData[ key ] = $.data( this, 'isotope-sort-data' )[ key ]; } else { sortData[ key ] = getSortData[ key ]( $this, instance ); } } // apply sort data to element $.data( this, 'isotope-sort-data', sortData ); }); }, // used on all the filtered atoms _sort : function() { var sortBy = this.options.sortBy, getSorter = this._getSorter, sortDir = this.options.sortAscending ? 1 : -1, sortFn = function( alpha, beta ) { var a = getSorter( alpha, sortBy ), b = getSorter( beta, sortBy ); // fall back to original order if data matches if ( a === b && sortBy !== 'original-order') { a = getSorter( alpha, 'original-order' ); b = getSorter( beta, 'original-order' ); } return ( ( a > b ) ? 1 : ( a < b ) ? -1 : 0 ) * sortDir; }; this.$filteredAtoms.sort( sortFn ); }, _getSorter : function( elem, sortBy ) { return $.data( elem, 'isotope-sort-data' )[ sortBy ]; }, // ====================== Layout Helpers ====================== _translate : function( x, y ) { return { translate : [ x, y ] }; }, _positionAbs : function( x, y ) { return { left: x, top: y }; }, _pushPosition : function( $elem, x, y ) { x = Math.round( x + this.offset.left ); y = Math.round( y + this.offset.top ); var position = this.getPositionStyles( x, y ); this.styleQueue.push({ $el: $elem, style: position }); if ( this.options.itemPositionDataEnabled ) { $elem.data('isotope-item-position', {x: x, y: y} ); } }, // ====================== General Layout ====================== // used on collection of atoms (should be filtered, and sorted before ) // accepts atoms-to-be-laid-out to start with layout : function( $elems, callback ) { var layoutMode = this.options.layoutMode; // layout logic this[ '_' + layoutMode + 'Layout' ]( $elems ); // set the size of the container if ( this.options.resizesContainer ) { var containerStyle = this[ '_' + layoutMode + 'GetContainerSize' ](); this.styleQueue.push({ $el: this.element, style: containerStyle }); } this._processStyleQueue( $elems, callback ); this.isLaidOut = true; }, _processStyleQueue : function( $elems, callback ) { // are we animating the layout arrangement? // use plugin-ish syntax for css or animate var styleFn = !this.isLaidOut ? 'css' : ( this.isUsingJQueryAnimation ? 'animate' : 'css' ), animOpts = this.options.animationOptions, onLayout = this.options.onLayout, objStyleFn, processor, triggerCallbackNow, callbackFn; // default styleQueue processor, may be overwritten down below processor = function( i, obj ) { obj.$el[ styleFn ]( obj.style, animOpts ); }; if ( this._isInserting && this.isUsingJQueryAnimation ) { // if using styleQueue to insert items processor = function( i, obj ) { // only animate if it not being inserted objStyleFn = obj.$el.hasClass('no-transition') ? 'css' : styleFn; obj.$el[ objStyleFn ]( obj.style, animOpts ); }; } else if ( callback || onLayout || animOpts.complete ) { // has callback var isCallbackTriggered = false, // array of possible callbacks to trigger callbacks = [ callback, onLayout, animOpts.complete ], instance = this; triggerCallbackNow = true; // trigger callback only once callbackFn = function() { if ( isCallbackTriggered ) { return; } var hollaback; for (var i=0, len = callbacks.length; i < len; i++) { hollaback = callbacks[i]; if ( typeof hollaback === 'function' ) { hollaback.call( instance.element, $elems, instance ); } } isCallbackTriggered = true; }; if ( this.isUsingJQueryAnimation && styleFn === 'animate' ) { // add callback to animation options animOpts.complete = callbackFn; triggerCallbackNow = false; } else if ( Modernizr.csstransitions ) { // detect if first item has transition var i = 0, firstItem = this.styleQueue[0], testElem = firstItem && firstItem.$el, styleObj; // get first non-empty jQ object while ( !testElem || !testElem.length ) { styleObj = this.styleQueue[ i++ ]; // HACK: sometimes styleQueue[i] is undefined if ( !styleObj ) { return; } testElem = styleObj.$el; } // get transition duration of the first element in that object // yeah, this is inexact var duration = parseFloat( getComputedStyle( testElem[0] )[ transitionDurProp ] ); if ( duration > 0 ) { processor = function( i, obj ) { obj.$el[ styleFn ]( obj.style, animOpts ) // trigger callback at transition end .one( transitionEndEvent, callbackFn ); }; triggerCallbackNow = false; } } } // process styleQueue $.each( this.styleQueue, processor ); if ( triggerCallbackNow ) { callbackFn(); } // clear out queue for next time this.styleQueue = []; }, resize : function() { if ( this[ '_' + this.options.layoutMode + 'ResizeChanged' ]() ) { this.reLayout(); } }, reLayout : function( callback ) { this[ '_' + this.options.layoutMode + 'Reset' ](); this.layout( this.$filteredAtoms, callback ); }, // ====================== Convenience methods ====================== // ====================== Adding items ====================== // adds a jQuery object of items to a isotope container addItems : function( $content, callback ) { var $newAtoms = this._getAtoms( $content ); // add new atoms to atoms pools this.$allAtoms = this.$allAtoms.add( $newAtoms ); if ( callback ) { callback( $newAtoms ); } }, // convienence method for adding elements properly to any layout // positions items, hides them, then animates them back in <--- very sezzy insert : function( $content, callback ) { // position items this.element.append( $content ); var instance = this; this.addItems( $content, function( $newAtoms ) { var $newFilteredAtoms = instance._filter( $newAtoms ); instance._addHideAppended( $newFilteredAtoms ); instance._sort(); instance.reLayout(); instance._revealAppended( $newFilteredAtoms, callback ); }); }, // convienence method for working with Infinite Scroll appended : function( $content, callback ) { var instance = this; this.addItems( $content, function( $newAtoms ) { instance._addHideAppended( $newAtoms ); instance.layout( $newAtoms ); instance._revealAppended( $newAtoms, callback ); }); }, // adds new atoms, then hides them before positioning _addHideAppended : function( $newAtoms ) { this.$filteredAtoms = this.$filteredAtoms.add( $newAtoms ); $newAtoms.addClass('no-transition'); this._isInserting = true; // apply hidden styles this.styleQueue.push({ $el: $newAtoms, style: this.options.hiddenStyle }); }, // sets visible style on new atoms _revealAppended : function( $newAtoms, callback ) { var instance = this; // apply visible style after a sec setTimeout( function() { // enable animation $newAtoms.removeClass('no-transition'); // reveal newly inserted filtered elements instance.styleQueue.push({ $el: $newAtoms, style: instance.options.visibleStyle }); instance._isInserting = false; instance._processStyleQueue( $newAtoms, callback ); }, 10 ); }, // gathers all atoms reloadItems : function() { this.$allAtoms = this._getAtoms( this.element.children() ); }, // removes elements from Isotope widget remove: function( $content, callback ) { // remove elements immediately from Isotope instance this.$allAtoms = this.$allAtoms.not( $content ); this.$filteredAtoms = this.$filteredAtoms.not( $content ); // remove() as a callback, for after transition / animation var instance = this; var removeContent = function() { $content.remove(); if ( callback ) { callback.call( instance.element ); } }; if ( $content.filter( ':not(.' + this.options.hiddenClass + ')' ).length ) { // if any non-hidden content needs to be removed this.styleQueue.push({ $el: $content, style: this.options.hiddenStyle }); this._sort(); this.reLayout( removeContent ); } else { // remove it now removeContent(); } }, shuffle : function( callback ) { this.updateSortData( this.$allAtoms ); this.options.sortBy = 'random'; this._sort(); this.reLayout( callback ); }, // destroys widget, returns elements and container back (close) to original style destroy : function() { var usingTransforms = this.usingTransforms; var options = this.options; this.$allAtoms .removeClass( options.hiddenClass + ' ' + options.itemClass ) .each(function(){ var style = this.style; style.position = ''; style.top = ''; style.left = ''; style.opacity = ''; if ( usingTransforms ) { style[ transformProp ] = ''; } }); // re-apply saved container styles var elemStyle = this.element[0].style; for ( var prop in this.originalStyle ) { elemStyle[ prop ] = this.originalStyle[ prop ]; } this.element .unbind('.isotope') .undelegate( '.' + options.hiddenClass, 'click' ) .removeClass( options.containerClass ) .removeData('isotope'); $window.unbind('.isotope'); }, // ====================== LAYOUTS ====================== // calculates number of rows or columns // requires columnWidth or rowHeight to be set on namespaced object // i.e. this.masonry.columnWidth = 200 _getSegments : function( isRows ) { var namespace = this.options.layoutMode, measure = isRows ? 'rowHeight' : 'columnWidth', size = isRows ? 'height' : 'width', segmentsName = isRows ? 'rows' : 'cols', containerSize = this.element[ size ](), segments, // i.e. options.masonry && options.masonry.columnWidth segmentSize = this.options[ namespace ] && this.options[ namespace ][ measure ] || // or use the size of the first item, i.e. outerWidth this.$filteredAtoms[ 'outer' + capitalize(size) ](true) || // if there's no items, use size of container containerSize; segments = Math.floor( containerSize / segmentSize ); segments = Math.max( segments, 1 ); // i.e. this.masonry.cols = .... this[ namespace ][ segmentsName ] = segments; // i.e. this.masonry.columnWidth = ... this[ namespace ][ measure ] = segmentSize; }, _checkIfSegmentsChanged : function( isRows ) { var namespace = this.options.layoutMode, segmentsName = isRows ? 'rows' : 'cols', prevSegments = this[ namespace ][ segmentsName ]; // update cols/rows this._getSegments( isRows ); // return if updated cols/rows is not equal to previous return ( this[ namespace ][ segmentsName ] !== prevSegments ); }, // ====================== Masonry ====================== _masonryReset : function() { // layout-specific props this.masonry = {}; // FIXME shouldn't have to call this again this._getSegments(); var i = this.masonry.cols; this.masonry.colYs = []; while (i--) { this.masonry.colYs.push( 0 ); } }, _masonryLayout : function( $elems ) { var instance = this, props = instance.masonry; $elems.each(function(){ var $this = $(this), //how many columns does this brick span colSpan = Math.ceil( $this.outerWidth(true) / props.columnWidth ); colSpan = Math.min( colSpan, props.cols ); if ( colSpan === 1 ) { // if brick spans only one column, just like singleMode instance._masonryPlaceBrick( $this, props.colYs ); } else { // brick spans more than one column // how many different places could this brick fit horizontally var groupCount = props.cols + 1 - colSpan, groupY = [], groupColY, i; // for each group potential horizontal position for ( i=0; i < groupCount; i++ ) { // make an array of colY values for that one group groupColY = props.colYs.slice( i, i+colSpan ); // and get the max value of the array groupY[i] = Math.max.apply( Math, groupColY ); } instance._masonryPlaceBrick( $this, groupY ); } }); }, // worker method that places brick in the columnSet // with the the minY _masonryPlaceBrick : function( $brick, setY ) { // get the minimum Y value from the columns var minimumY = Math.min.apply( Math, setY ), shortCol = 0; // Find index of short column, the first from the left for (var i=0, len = setY.length; i < len; i++) { if ( setY[i] === minimumY ) { shortCol = i; break; } } // position the brick var x = this.masonry.columnWidth * shortCol, y = minimumY; this._pushPosition( $brick, x, y ); // apply setHeight to necessary columns var setHeight = minimumY + $brick.outerHeight(true), setSpan = this.masonry.cols + 1 - len; for ( i=0; i < setSpan; i++ ) { this.masonry.colYs[ shortCol + i ] = setHeight; } }, _masonryGetContainerSize : function() { var containerHeight = Math.max.apply( Math, this.masonry.colYs ); return { height: containerHeight }; }, _masonryResizeChanged : function() { return this._checkIfSegmentsChanged(); }, // ====================== fitRows ====================== _fitRowsReset : function() { this.fitRows = { x : 0, y : 0, height : 0 }; }, _fitRowsLayout : function( $elems ) { var instance = this, containerWidth = this.element.width(), props = this.fitRows; $elems.each( function() { var $this = $(this), atomW = $this.outerWidth(true), atomH = $this.outerHeight(true); if ( props.x !== 0 && atomW + props.x > containerWidth ) { // if this element cannot fit in the current row props.x = 0; props.y = props.height; } // position the atom instance._pushPosition( $this, props.x, props.y ); props.height = Math.max( props.y + atomH, props.height ); props.x += atomW; }); }, _fitRowsGetContainerSize : function () { return { height : this.fitRows.height }; }, _fitRowsResizeChanged : function() { return true; }, // ====================== cellsByRow ====================== _cellsByRowReset : function() { this.cellsByRow = { index : 0 }; // get this.cellsByRow.columnWidth this._getSegments(); // get this.cellsByRow.rowHeight this._getSegments(true); }, _cellsByRowLayout : function( $elems ) { var instance = this, props = this.cellsByRow; $elems.each( function(){ var $this = $(this), col = props.index % props.cols, row = Math.floor( props.index / props.cols ), x = ( col + 0.5 ) * props.columnWidth - $this.outerWidth(true) / 2, y = ( row + 0.5 ) * props.rowHeight - $this.outerHeight(true) / 2; instance._pushPosition( $this, x, y ); props.index ++; }); }, _cellsByRowGetContainerSize : function() { return { height : Math.ceil( this.$filteredAtoms.length / this.cellsByRow.cols ) * this.cellsByRow.rowHeight + this.offset.top }; }, _cellsByRowResizeChanged : function() { return this._checkIfSegmentsChanged(); }, // ====================== straightDown ====================== _straightDownReset : function() { this.straightDown = { y : 0 }; }, _straightDownLayout : function( $elems ) { var instance = this; $elems.each( function( i ){ var $this = $(this); instance._pushPosition( $this, 0, instance.straightDown.y ); instance.straightDown.y += $this.outerHeight(true); }); }, _straightDownGetContainerSize : function() { return { height : this.straightDown.y }; }, _straightDownResizeChanged : function() { return true; }, // ====================== masonryHorizontal ====================== _masonryHorizontalReset : function() { // layout-specific props this.masonryHorizontal = {}; // FIXME shouldn't have to call this again this._getSegments( true ); var i = this.masonryHorizontal.rows; this.masonryHorizontal.rowXs = []; while (i--) { this.masonryHorizontal.rowXs.push( 0 ); } }, _masonryHorizontalLayout : function( $elems ) { var instance = this, props = instance.masonryHorizontal; $elems.each(function(){ var $this = $(this), //how many rows does this brick span rowSpan = Math.ceil( $this.outerHeight(true) / props.rowHeight ); rowSpan = Math.min( rowSpan, props.rows ); if ( rowSpan === 1 ) { // if brick spans only one column, just like singleMode instance._masonryHorizontalPlaceBrick( $this, props.rowXs ); } else { // brick spans more than one row // how many different places could this brick fit horizontally var groupCount = props.rows + 1 - rowSpan, groupX = [], groupRowX, i; // for each group potential horizontal position for ( i=0; i < groupCount; i++ ) { // make an array of colY values for that one group groupRowX = props.rowXs.slice( i, i+rowSpan ); // and get the max value of the array groupX[i] = Math.max.apply( Math, groupRowX ); } instance._masonryHorizontalPlaceBrick( $this, groupX ); } }); }, _masonryHorizontalPlaceBrick : function( $brick, setX ) { // get the minimum Y value from the columns var minimumX = Math.min.apply( Math, setX ), smallRow = 0; // Find index of smallest row, the first from the top for (var i=0, len = setX.length; i < len; i++) { if ( setX[i] === minimumX ) { smallRow = i; break; } } // position the brick var x = minimumX, y = this.masonryHorizontal.rowHeight * smallRow; this._pushPosition( $brick, x, y ); // apply setHeight to necessary columns var setWidth = minimumX + $brick.outerWidth(true), setSpan = this.masonryHorizontal.rows + 1 - len; for ( i=0; i < setSpan; i++ ) { this.masonryHorizontal.rowXs[ smallRow + i ] = setWidth; } }, _masonryHorizontalGetContainerSize : function() { var containerWidth = Math.max.apply( Math, this.masonryHorizontal.rowXs ); return { width: containerWidth }; }, _masonryHorizontalResizeChanged : function() { return this._checkIfSegmentsChanged(true); }, // ====================== fitColumns ====================== _fitColumnsReset : function() { this.fitColumns = { x : 0, y : 0, width : 0 }; }, _fitColumnsLayout : function( $elems ) { var instance = this, containerHeight = this.element.height(), props = this.fitColumns; $elems.each( function() { var $this = $(this), atomW = $this.outerWidth(true), atomH = $this.outerHeight(true); if ( props.y !== 0 && atomH + props.y > containerHeight ) { // if this element cannot fit in the current column props.x = props.width; props.y = 0; } // position the atom instance._pushPosition( $this, props.x, props.y ); props.width = Math.max( props.x + atomW, props.width ); props.y += atomH; }); }, _fitColumnsGetContainerSize : function () { return { width : this.fitColumns.width }; }, _fitColumnsResizeChanged : function() { return true; }, // ====================== cellsByColumn ====================== _cellsByColumnReset : function() { this.cellsByColumn = { index : 0 }; // get this.cellsByColumn.columnWidth this._getSegments(); // get this.cellsByColumn.rowHeight this._getSegments(true); }, _cellsByColumnLayout : function( $elems ) { var instance = this, props = this.cellsByColumn; $elems.each( function(){ var $this = $(this), col = Math.floor( props.index / props.rows ), row = props.index % props.rows, x = ( col + 0.5 ) * props.columnWidth - $this.outerWidth(true) / 2, y = ( row + 0.5 ) * props.rowHeight - $this.outerHeight(true) / 2; instance._pushPosition( $this, x, y ); props.index ++; }); }, _cellsByColumnGetContainerSize : function() { return { width : Math.ceil( this.$filteredAtoms.length / this.cellsByColumn.rows ) * this.cellsByColumn.columnWidth }; }, _cellsByColumnResizeChanged : function() { return this._checkIfSegmentsChanged(true); }, // ====================== straightAcross ====================== _straightAcrossReset : function() { this.straightAcross = { x : 0 }; }, _straightAcrossLayout : function( $elems ) { var instance = this; $elems.each( function( i ){ var $this = $(this); instance._pushPosition( $this, instance.straightAcross.x, 0 ); instance.straightAcross.x += $this.outerWidth(true); }); }, _straightAcrossGetContainerSize : function() { return { width : this.straightAcross.x }; }, _straightAcrossResizeChanged : function() { return true; } }; // ======================= imagesLoaded Plugin =============================== /*! * jQuery imagesLoaded plugin v1.1.0 * http://github.com/desandro/imagesloaded * * MIT License. by Paul Irish et al. */ // $('#my-container').imagesLoaded(myFunction) // or // $('img').imagesLoaded(myFunction) // execute a callback when all images have loaded. // needed because .load() doesn't work on cached images // callback function gets image collection as argument // `this` is the container $.fn.imagesLoaded = function( callback ) { var $this = this, $images = $this.find('img').add( $this.filter('img') ), len = $images.length, blank = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==', loaded = []; function triggerCallback() { callback.call( $this, $images ); } function imgLoaded( event ) { var img = event.target; if ( img.src !== blank && $.inArray( img, loaded ) === -1 ){ loaded.push( img ); if ( --len <= 0 ){ setTimeout( triggerCallback ); $images.unbind( '.imagesLoaded', imgLoaded ); } } } // if no images, trigger immediately if ( !len ) { triggerCallback(); } $images.bind( 'load.imagesLoaded error.imagesLoaded', imgLoaded ).each( function() { // cached images don't fire load sometimes, so we reset src. var src = this.src; // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f // data uri bypasses webkit log warning (thx doug jones) this.src = blank; this.src = src; }); return $this; }; // helper function for logging errors // $.error breaks jQuery chaining var logError = function( message ) { if ( window.console ) { window.console.error( message ); } }; // ======================= Plugin bridge =============================== // leverages data method to either create or return $.Isotope constructor // A bit from jQuery UI // https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js // A bit from jcarousel // https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js $.fn.isotope = function( options, callback ) { if ( typeof options === 'string' ) { // call method var args = Array.prototype.slice.call( arguments, 1 ); this.each(function(){ var instance = $.data( this, 'isotope' ); if ( !instance ) { logError( "cannot call methods on isotope prior to initialization; " + "attempted to call method '" + options + "'" ); return; } if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) { logError( "no such method '" + options + "' for isotope instance" ); return; } // apply method instance[ options ].apply( instance, args ); }); } else { this.each(function() { var instance = $.data( this, 'isotope' ); if ( instance ) { // apply options & init instance.option( options ); instance._init( callback ); } else { // initialize new instance $.data( this, 'isotope', new $.Isotope( options, this, callback ) ); } }); } // return jQuery object // so plugin methods do not have to return this; }; })( window, jQuery ); /*! http://mths.be/placeholder v2.0.8 by @mathias */ ;(function(window, document, $) { // Opera Mini v7 doesn’t support placeholder although its DOM seems to indicate so var isOperaMini = Object.prototype.toString.call(window.operamini) == '[object OperaMini]'; var isInputSupported = 'placeholder' in document.createElement('input') && !isOperaMini; var isTextareaSupported = 'placeholder' in document.createElement('textarea') && !isOperaMini; var prototype = $.fn; var valHooks = $.valHooks; var propHooks = $.propHooks; var hooks; var placeholder; if (isInputSupported && isTextareaSupported) { placeholder = prototype.placeholder = function() { return this; }; placeholder.input = placeholder.textarea = true; } else { placeholder = prototype.placeholder = function() { var $this = this; $this .filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]') .not('.placeholder') .bind({ 'focus.placeholder': clearPlaceholder, 'blur.placeholder': setPlaceholder }) .data('placeholder-enabled', true) .trigger('blur.placeholder'); return $this; }; placeholder.input = isInputSupported; placeholder.textarea = isTextareaSupported; hooks = { 'get': function(element) { var $element = $(element); var $passwordInput = $element.data('placeholder-password'); if ($passwordInput) { return $passwordInput[0].value; } return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value; }, 'set': function(element, value) { var $element = $(element); var $passwordInput = $element.data('placeholder-password'); if ($passwordInput) { return $passwordInput[0].value = value; } if (!$element.data('placeholder-enabled')) { return element.value = value; } if (value == '') { element.value = value; // Issue #56: Setting the placeholder causes problems if the element continues to have focus. if (element != safeActiveElement()) { // We can't use `triggerHandler` here because of dummy text/password inputs :( setPlaceholder.call(element); } } else if ($element.hasClass('placeholder')) { clearPlaceholder.call(element, true, value) || (element.value = value); } else { element.value = value; } // `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363 return $element; } }; if (!isInputSupported) { valHooks.input = hooks; propHooks.value = hooks; } if (!isTextareaSupported) { valHooks.textarea = hooks; propHooks.value = hooks; } $(function() { // Look for forms $(document).delegate('form', 'submit.placeholder', function() { // Clear the placeholder values so they don't get submitted var $inputs = $('.placeholder', this).each(clearPlaceholder); setTimeout(function() { $inputs.each(setPlaceholder); }, 10); }); }); // Clear placeholder values upon page reload $(window).bind('beforeunload.placeholder', function() { $('.placeholder').each(function() { this.value = ''; }); }); } function args(elem) { // Return an object of element attributes var newAttrs = {}; var rinlinejQuery = /^jQuery\d+$/; $.each(elem.attributes, function(i, attr) { if (attr.specified && !rinlinejQuery.test(attr.name)) { newAttrs[attr.name] = attr.value; } }); return newAttrs; } function clearPlaceholder(event, value) { var input = this; var $input = $(input); if (input.value == $input.attr('placeholder') && $input.hasClass('placeholder')) { if ($input.data('placeholder-password')) { $input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id')); // If `clearPlaceholder` was called from `$.valHooks.input.set` if (event === true) { return $input[0].value = value; } $input.focus(); } else { input.value = ''; $input.removeClass('placeholder'); input == safeActiveElement() && input.select(); } } } function setPlaceholder() { var $replacement; var input = this; var $input = $(input); var id = this.id; if (input.value == '') { if (input.type == 'password') { if (!$input.data('placeholder-textinput')) { try { $replacement = $input.clone().attr({ 'type': 'text' }); } catch(e) { $replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' })); } $replacement .removeAttr('name') .data({ 'placeholder-password': $input, 'placeholder-id': id }) .bind('focus.placeholder', clearPlaceholder); $input .data({ 'placeholder-textinput': $replacement, 'placeholder-id': id }) .before($replacement); } $input = $input.removeAttr('id').hide().prev().attr('id', id).show(); // Note: `$input[0] != input` now! } $input.addClass('placeholder'); $input[0].value = $input.attr('placeholder'); } else { $input.removeClass('placeholder'); } } function safeActiveElement() { // Avoid IE9 `document.activeElement` of death // https://github.com/mathiasbynens/jquery-placeholder/pull/99 try { return document.activeElement; } catch (exception) {} } }(this, document, jQuery)); // ============================================================================= // JS/SRC/SITE/INC/X-BODY-CUSTOM.JS // ----------------------------------------------------------------------------- // Includes all miscellaneous, custom functionality to be output near the // closing </body> tag. // ============================================================================= // ============================================================================= // TABLE OF CONTENTS // ----------------------------------------------------------------------------- // 01. Custom Functionality // ============================================================================= // Custom Functionality // ============================================================================= jQuery(document).ready(function($) { // // Placeholder. // $('input, textarea').placeholder(); }); // ============================================================================= // JS/SRC/SITE/INC/X-BODY-SCROLLSPY.JS // ----------------------------------------------------------------------------- // A modified version of the Bootstrap ScrollSpy plugin. More information can // be found here: http://getbootstrap.com/javascript/#scrollspy // ============================================================================= // ============================================================================= // TABLE OF CONTENTS // ----------------------------------------------------------------------------- // 01. ScrollSpy Plugin // 02. Setup ScrollSpy Functionality // ============================================================================= // ScrollSpy Plugin // ============================================================================= +function ($) { "use strict"; // SCROLLSPY CLASS DEFINITION // ========================== function ScrollSpy(element, options) { var href var process = $.proxy(this.process, this) this.$element = $(element).is('body') ? $(window) : $(element) this.$body = $('body') this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process) this.options = $.extend({}, ScrollSpy.DEFAULTS, options) this.selector = (this.options.target || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 || '') + ' .x-nav li > a' this.offsets = $([]) this.targets = $([]) this.activeTarget = null this.refresh() this.process() } ScrollSpy.DEFAULTS = { offset: 10 } ScrollSpy.prototype.refresh = function () { var offsetMethod = this.$element[0] == window ? 'offset' : 'position' this.offsets = $([]) this.targets = $([]) var self = this var $targets = this.$body .find(this.selector) .map(function () { var $el = $(this) var href = $el.data('target') || $el.attr('href') var $href = /^#\w/.test(href) && $(href) return ($href && $href.length && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null }) .sort(function (a, b) { return a[0] - b[0] }) .each(function () { self.offsets.push(this[0]) self.targets.push(this[1]) }) } ScrollSpy.prototype.process = function () { var scrollTop = this.$scrollElement.scrollTop() + this.options.offset var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight var maxScroll = scrollHeight - this.$scrollElement.height() var offsets = this.offsets var targets = this.targets var activeTarget = this.activeTarget var i if (scrollTop >= maxScroll) { return activeTarget != (i = targets.last()[0]) && this.activate(i) } for (i = offsets.length; i--;) { activeTarget != targets[i] && scrollTop >= offsets[i] && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) && this.activate( targets[i] ) } } ScrollSpy.prototype.activate = function (target) { this.activeTarget = target $(this.selector) .parents('.current-menu-item') .removeClass('current-menu-item') var selector = this.selector + '[data-target="' + target + '"],' + this.selector + '[href="' + target + '"]' var active = $(selector) .parents('li') .addClass('current-menu-item') if (active.parent('.dropdown-menu').length) { active = active .closest('li.dropdown') .addClass('current-menu-item') } active.trigger('activate.bs.scrollspy') } // SCROLLSPY PLUGIN DEFINITION // =========================== var old = $.fn.scrollspy $.fn.scrollspy = function (option) { return this.each(function () { var $this = $(this) var data = $this.data('bs.scrollspy') var options = typeof option == 'object' && option if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) if (typeof option == 'string') data[option]() }) } $.fn.scrollspy.Constructor = ScrollSpy // SCROLLSPY NO CONFLICT // ===================== $.fn.scrollspy.noConflict = function () { $.fn.scrollspy = old return this } // SCROLLSPY DATA-API // ================== $(window).on('load', function () { $('[data-spy="scroll"]').each(function () { var $spy = $(this) $spy.scrollspy($spy.data()) }) }) }(jQuery); // Setup ScrollSpy Functionality // ============================================================================= jQuery(document).ready(function($) { var $body = $('body'); var bodyHeight = $body.outerHeight(); var adminbarHeight = $('#wpadminbar').outerHeight(); var navbarFixedTopHeight = $('.x-navbar-fixed-top-active .x-navbar').outerHeight(); var locHref = location.href; var locHashIndex = locHref.indexOf('#'); var locHash = locHref.substr(locHashIndex); // // Calculate the offset height for various elements and remove it from // the element's top offset so that fixed elements don't cover it up. // function animateOffset( element, ms, easing ) { $('html, body').animate({ scrollTop: $(element).offset().top - adminbarHeight - navbarFixedTopHeight + 1 }, ms, easing); } // // Page load offset (if necessary). // $(window).load(function() { if ( locHashIndex !== -1 && $(locHash).length ) { animateOffset(locHash, 1, 'linear'); } }); // // Scroll trigger. // $('a[href*="#"]').on('touchstart click', function(e) { href = $(this).attr('href'); notComments = href.indexOf('#comments') === -1; if ( href !== '#' && notComments ) { var theId = href.split('#').pop(); var $el = $('#' + theId); if ( $el.length > 0 ) { e.preventDefault(); animateOffset($el, 850, 'easeInOutExpo'); } } }); // // Initialize scrollspy. // if ( $body.hasClass('x-one-page-navigation-active') ) { $body.scrollspy({ target : '.x-nav-wrap.desktop', offset : adminbarHeight + navbarFixedTopHeight }); // // Refresh scrollspy as needed. // $(window).resize(function() { $body.scrollspy('refresh'); }); var timesRun = 0; var interval = setInterval(function() { timesRun += 1; var newBodyHeight = $body.outerHeight(); if ( newBodyHeight !== bodyHeight ) { $body.scrollspy('refresh'); } if ( timesRun === 10 ) { clearInterval(interval); } }, 500); } }); // ============================================================================= // JS/SRC/SITE/INC/X-BODY-SLIDER-SCROLL.JS // ----------------------------------------------------------------------------- // Includes all functionality pertaining to the scroll bottom anchor for the // sliders. // ============================================================================= // ============================================================================= // TABLE OF CONTENTS // ----------------------------------------------------------------------------- // 01. Slider Scroll Bottom Anchor // ============================================================================= // Slider Scroll Bottom Anchor // ============================================================================= jQuery(function($) { // // Slider above. // $('.x-slider-container.above .x-slider-scroll-bottom').on('touchstart click', function(e) { e.preventDefault(); $('html, body').animate({ scrollTop: $('.x-slider-container.above').outerHeight() }, 850, 'easeInOutExpo'); }); // // Slider below. // $('.x-slider-container.below .x-slider-scroll-bottom').on('touchstart click', function(e) { e.preventDefault(); var mastheadHeight = $('.masthead').outerHeight(); var navbarFixedTopHeight = $('.x-navbar-fixed-top-active .x-navbar').outerHeight(); var sliderAboveHeight = $('.x-slider-container.above').outerHeight(); var sliderBelowHeight = $('.x-slider-container.below').outerHeight(); var heightSum = mastheadHeight + sliderAboveHeight + sliderBelowHeight - navbarFixedTopHeight; $('html, body').animate({ scrollTop: heightSum }, 850, 'easeInOutExpo'); }); }); // ============================================================================= // JS/SRC/SITE/INC/X-BODY-WOOCOMMERCE.JS // ----------------------------------------------------------------------------- // Includes all additional WooCommerce functionality tied into the theme. // ============================================================================= // ============================================================================= // TABLE OF CONTENTS // ----------------------------------------------------------------------------- // 01. WooCommerce Functionality // ============================================================================= // WooCommerce Functionality // ============================================================================= jQuery(document).ready(function($) { // // Notifications. // var $notification = $('.x-cart-notification'); if ( $notification.length > 0 ) { $('.add_to_cart_button.product_type_simple').on('click', function(e) { $notification.addClass('bring-forward appear loading'); }); $('body').on('added_to_cart', function(e, fragments, cart_hash) { setTimeout(function() { $notification.removeClass('loading').addClass('added'); setTimeout(function() { $notification.removeClass('appear'); setTimeout(function() { $notification.removeClass('added bring-forward'); }, 650); }, 1000); }, 650); }); } // // Star ratings. // var $container = $('p.stars'); var $stars = $container.find('a'); function starsLeave(e) { if ( $container.hasClass('selected') ) { $container.find('a.active').nextAll('a').removeClass('x-active'); } else { $stars.removeClass('x-active'); } } function starClick(e) { $(this).nextAll('a').removeClass('x-active'); } function starOver(e) { starsLeave(); $(this).addClass('x-active').prevAll('a').addClass('x-active'); } $container.on('mouseleave', starsLeave); $stars.on('click', starClick); $stars.on('mouseover', starOver); });