// ------------- JQUERY Wallpaper------------------------------------------- //
// ============ https://github.com/Formstone/Wallpaper ===================== //
// ------------------------------------------------------------------------- //
!function(a,b){"use strict";function c(b){var c=a.extend({},F,b);t=a("body"),u=s(),v=u!==!1,v||(u="transitionend.wallpaper");for(var e=a(this),f=0,g=e.length;g>f;f++)d.apply(e.eq(f),[a.extend({},c)]);return t.hasClass("wallpaper-inititalized")||(t.addClass("wallpaper-inititalized"),x.on("resize.wallpaper",c,l)),e}function d(b){var c=a(this);if(!c.hasClass("wallpaper")){a.extend(b,c.data("wallpaper-options")),c.addClass("wallpaper").append('
'),b.guid="wallpaper-"+A++,b.youTubeGuid=0,b.$target=c,b.$container=b.$target.find(".wallpaper-container"),b.$target.data("wallpaper",b).on("resize.wallpaper",b,k);var d=b.source;b.source=null,e(d,b,!0),b.onReady.call()}}function e(a,c,d){if(a!==c.source){if(c.source=a,c.isYouTube=!1,"object"==typeof a&&"string"==typeof a.video){var e=a.video.match(/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i);e&&e.length>=1&&(c.isYouTube=!0,c.videoId=e[1])}if(c.isYouTube)c.playing=!1,c.playerReady=!1,c.posterLoaded=!1,h(a,c,d);else if("object"!=typeof a||a.hasOwnProperty("fallback")){if(c.responsiveSource)for(var i in c.responsiveSource)c.responsiveSource.hasOwnProperty(i)&&c.responsiveSource[i].mq.removeListener(m);if(c.responsive=!1,c.responsiveSource=null,"object"==typeof a){var j,k=[];for(var l in a)if(a.hasOwnProperty(l)){var n="fallback"===l?"(min-width: 0px)":l;if(n){var o=b.matchMedia(n.replace(1/0,"100000px"));o.addListener(m),k.push({mq:o,source:a[l]}),o.matches&&(j=a[l])}}c.responsive=!0,c.responsiveSource=k,a=j}f(a,c,!1,d)}else g(a,c,d)}else c.$target.trigger("wallpaper.loaded"),c.onLoad.call(c.$target)}function f(b,c,d,e){var f=a(''),g=f.find("img"),h=b;g.one("load.wallpaper",function(){z&&f.addClass("native").css({backgroundImage:"url('"+h+"')"}),f.on(u,function(b){r(b),a(b.target).is(f)&&(f.off(u),d||i(c))}),setTimeout(function(){f.css({opacity:1}),c.responsive&&e&&i(c)},0),k({data:c}),(!d||e)&&(c.$target.trigger("wallpaper.loaded"),c.onLoad.call(c.$target)),y=a(".wallpaper-responsive")}).attr("src",h),c.responsive&&f.addClass("wallpaper-responsive"),c.$container.append(f),(g[0].complete||4===g[0].readyState)&&g.trigger("load.wallpaper")}function g(b,c,d){if(c.source.poster&&(f(c.source.poster,c,!0,!0),d=!1),!E){var e='';e+="",e+="
";var g=a(e),h=g.find("video");h.one("loadedmetadata.wallpaper",function(){g.on(u,function(b){r(b),a(b.target).is(g)&&(g.off(u),i(c))}),setTimeout(function(){g.css({opacity:1})},0),k({data:c}),c.$target.trigger("wallpaper.loaded"),c.onLoad.call(c.$target),c.hoverPlay?c.$target.on("mouseover.boxer",G.play).on("mouseout.boxer",G.pause):c.autoPlay&&this.play()}),c.$container.append(g)}}function h(c,d,e){if(!d.videoId){var g=c.match(/^.*(?:youtu.be\/|v\/|e\/|u\/\w+\/|embed\/|v=)([^#\&\?]*).*/);d.videoId=g[1]}if(d.posterLoaded||(d.source.poster||(d.source.poster="http://img.youtube.com/vi/"+d.videoId+"/0.jpg"),d.posterLoaded=!0,f(d.source.poster,d,!0,e),e=!1),!E)if(a("script[src*='youtube.com/iframe_api']").length||a("head").append(''),B){var h=d.guid+"_"+d.youTubeGuid++,j="";j+='";var l=a(j);d.$container.append(l),d.player&&(d.oldPlayer=d.player,d.player=null),d.player=new b.YT.Player(h,{videoId:d.videoId,playerVars:{controls:0,rel:0,showinfo:0,wmode:"transparent",enablejsapi:1,version:3,playerapiid:h,loop:d.loop?1:0,autoplay:1,origin:b.location.protocol+"//"+b.location.host},events:{onReady:function(){d.playerReady=!0,d.mute&&d.player.mute(),d.hoverPlay?d.$target.on("mouseover.boxer",G.play).on("mouseout.boxer",G.pause):d.autoPlay&&d.player.playVideo()},onStateChange:function(c){d.playing||c.data!==b.YT.PlayerState.PLAYING?d.loop&&d.playing&&c.data===b.YT.PlayerState.ENDED&&d.player.playVideo():(d.playing=!0,(d.hoverPlay||!d.autoPlay)&&d.player.pauseVideo(),d.$target.trigger("wallpaper.loaded"),d.onLoad.call(d.$target),l.on(u,function(b){r(b),a(b.target).is(l)&&(l.off(u),i(d))}),l.css({opacity:1})),d.$target.find(".wallpaper-embed").addClass("ready")},onPlaybackQualityChange:function(){},onPlaybackRateChange:function(){},onError:function(){},onApiChange:function(){}}}),k({data:d})}else C.push({source:c,data:d})}function i(b){var c=b.$container.find(".wallpaper-media");c.length>=1&&(c.not(":last").remove(),b.oldPlayer=null),y=a(".wallpaper-responsive")}function j(b){var c=b.$container.find(".wallpaper-media");c.length>=1&&c.on(u,function(d){r(d),a(d.target).is(c)&&(a(this).remove(),delete b.source)}).css({opacity:0})}function k(a){r(a);for(var b=a.data,c=b.$container.find(".wallpaper-media"),d=0,e=c.length;e>d;d++){var f=c.eq(d),g=b.isYouTube?"iframe":f.find("video").length?"video":"img",h=f.find(g);if(h.length&&("img"!==g||!b.nativeSupport)){var i=b.$target.outerWidth(),j=b.$target.outerHeight(),k=q(b,h);b.width=k.naturalWidth,b.height=k.naturalHeight,b.left=0,b.top=0;var l=b.isYouTube?b.embedRatio:b.width/b.height;b.height=j,b.width=b.height*l,b.widthg;g++)if(d.hasOwnProperty(g)){var i=d[g].mq;i&&i.matches&&(e=g)}f(d[e].source,c,!1,!0),b.trigger("change.wallpaper")})}function o(a,b,c,d){return p(a,d),setTimeout(c,b)}function p(a){null!==a&&(clearInterval(a),a=null)}function q(a,b){if(a.isYouTube)return{naturalHeight:500,naturalWidth:500/a.embedRatio};if(b.is("img")){var c=b[0];if("undefined"!=typeof c.naturalHeight)return{naturalHeight:c.naturalHeight,naturalWidth:c.naturalWidth};var d=new Image;return d.src=c.src,{naturalHeight:d.height,naturalWidth:d.width}}return{naturalHeight:b[0].videoHeight,naturalWidth:b[0].videoWidth}}function r(a){a.preventDefault&&(a.stopPropagation(),a.preventDefault())}function s(){var a={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},b=document.createElement("div");for(var c in a)if(a.hasOwnProperty(c)&&c in b.style)return a[c]+".wallpaper";return!1}var t,u,v,w,x=a(b),y=null,z="backgroundSize"in document.documentElement.style,A=0,B=!1,C=[],D=b.navigator.userAgent||b.navigator.vendor||b.opera,E=/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(D),F=(D.toLowerCase().indexOf("safari")>=0&&D.toLowerCase().indexOf("chrome")<0,{autoPlay:!0,embedRatio:1.777777,hoverPlay:!1,loop:!0,mute:!0,onLoad:a.noop,onReady:a.noop,source:null}),G={defaults:function(b){return F=a.extend(F,b||{}),"object"==typeof this?a(this):!0},destroy:function(){var b=a(this).each(function(){var b=a(this).data("wallpaper");b&&(b.$container.remove(),b.$target.removeClass("wallpaper").off(".boxer").data("wallpaper",null))});return"undefined"!=typeof t&&"undefined"!=typeof x&&a(".wallpaper").length<1&&(t.removeClass("wallpaper-inititalized"),x.off(".wallpaper")),b},load:function(b){return a(this).each(function(){var c=a(this).data("wallpaper");c&&e(b,c)})},pause:function(){return a(this).each(function(){var b=a(this).data("wallpaper");if(b)if(b.isYouTube&&b.playerReady)b.player.pauseVideo();else{var c=b.$container.find("video");c.length&&c[0].pause()}})},play:function(){return a(this).each(function(){var b=a(this).data("wallpaper");if(b)if(b.isYouTube&&b.playerReady)b.player.playVideo();else{var c=b.$container.find("video");c.length&&c[0].play()}})},stop:function(){G.pause.apply(this)},unload:function(){return a(this).each(function(){var b=a(this).data("wallpaper");b&&j(b)})}};b.onYouTubeIframeAPIReady=function(){B=!0;for(var a in C)C.hasOwnProperty(a)&&h(C[a].source,C[a].data);C=[]},a.fn.wallpaper=function(a){return G[a]?G[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?this:c.apply(this,arguments)},a.wallpaper=function(a){"defaults"===a&&G.defaults.apply(this,Array.prototype.slice.call(arguments,1))}}(jQuery,window);
// ------------- JQUERY APPEAR ---------------------------------------------- //
// ============ https://github.com/morr/jquery.appear ====================== //
// -------------------------------------------------------------------------- //
(function($) {
var selectors = [];
var check_binded = false;
var check_lock = false;
var defaults = {
interval: 250,
force_process: false
}
var $window = $(window);
var $prior_appeared;
function process() {
check_lock = false;
for (var index = 0, selectorsLength = selectors.length; index < selectorsLength; index++) {
var $appeared = $(selectors[index]).filter(function() {
return $(this).is(':appeared');
});
$appeared.trigger('appear', [$appeared]);
if ($prior_appeared) {
var $disappeared = $prior_appeared.not($appeared);
$disappeared.trigger('disappear', [$disappeared]);
}
$prior_appeared = $appeared;
}
}
// "appeared" custom filter
$.expr[':']['appeared'] = function(element) {
var $element = $(element);
if (!$element.is(':visible')) {
return false;
}
var window_left = $window.scrollLeft();
var window_top = $window.scrollTop();
var offset = $element.offset();
var left = offset.left;
var top = offset.top;
if (top + $element.height() >= window_top &&
top - ($element.data('appear-top-offset') || 0) <= window_top + $window.height() &&
left + $element.width() >= window_left &&
left - ($element.data('appear-left-offset') || 0) <= window_left + $window.width()) {
return true;
} else {
return false;
}
}
$.fn.extend({
// watching for element's appearance in browser viewport
appear: function(options) {
var opts = $.extend({}, defaults, options || {});
var selector = this.selector || this;
if (!check_binded) {
var on_check = function() {
if (check_lock) {
return;
}
check_lock = true;
setTimeout(process, opts.interval);
};
$(window).scroll(on_check).resize(on_check);
check_binded = true;
}
if (opts.force_process) {
setTimeout(process, opts.interval);
}
selectors.push(selector);
return $(selector);
}
});
$.extend({
// force elements's appearance check
force_appear: function() {
if (check_binded) {
process();
return true;
};
return false;
}
});
})(jQuery);
// ------------- DRAW FILL SVG ---------------------------------------------- //
// ============ https://github.com/callmenick/Draw-Fill-SVG ================= //
// -------------------------------------------------------------------------- //
(function( window ){
'use strict';
/**
* Cross browser transition end events
*
* Use modernizr to detect cross browser transition end events. Make sure
* to include Modernizr in your doc and have "Modernizr.prefixed()" checked
* off in the extensibility section.
*/
var transEndEventNames = {
"WebkitTransition" : "webkitTransitionEnd",
"MozTransition" : "transitionend",
"OTransition" : "oTransitionEnd",
"msTransition" : "MSTransitionEnd",
"transition" : "transitionend"
},
transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
/**
* Extend obj function
*
*/
function extend( a, b ) {
for( var key in b ) {
if( b.hasOwnProperty( key ) ) {
a[key] = b[key];
}
}
return a;
}
/**
* DrawFillSVG constructor
*
*/
function DrawFillSVG( options ) {
this.options = extend( {}, this.options );
extend( this.options, options );
this._init();
}
/**
* DrawFillSVG options
*
* Available options:
* elementId - the ID of the element to draw
*/
DrawFillSVG.prototype.options = {
elementId : "svg"
}
/**
* DrawFillSVG _init
*
* Initialise DrawFillSVG
*/
DrawFillSVG.prototype._init = function() {
this.svg = document.getElementById(this.options.elementId);
this.paths = this.svg.querySelectorAll("path");
this._initAnimation();
}
/**
* DrawFillSVG _initAnimation()
*
* Reset some style properties on our paths, add some transitions, set the
* stroke-dasharray to the length of the path, and the stroke-dashoffset to
* the length of the path pushing it out of view initially. Then, set the
* stroke-dashoffset to 0, animating the strokes in a drawing manner. Then,
* run the path filler sequence.
*/
DrawFillSVG.prototype._initAnimation = function() {
for ( var i = 0; i < this.paths.length; i++ ) {
var path = this.paths[i];
var length = path.getTotalLength();
// reset opacities
path.style.fillOpacity = 0;
path.style.strokeOpacity = 1;
// reset transitions
path.style.transition = path.style.WebkitTransition = "none";
// reset stroke dash array and stroke dash offset
path.style.strokeDasharray = length + " " + length;
path.style.strokeDashoffset = length;
path.getBoundingClientRect();
// apply new transitions
path.style.transition = path.style.WebkitTransition = "stroke-dashoffset 2s ease-in-out";
// go baby go
path.style.strokeDashoffset = 0;
// fill the path
this._fillPath( path );
}
}
/**
* DrawFillSVG _fillPath()
*
* Resets the transition props, then fills the path and fades out the stroke
* by updating the styles.
*/
DrawFillSVG.prototype._fillPath = function( path ) {
path.addEventListener( transEndEventName, function() {
// reset transitions
path.style.transition = path.style.WebkitTransition = "none";
path.style.transition = path.style.WebkitTransition = "fill-opacity 1s ease-in-out, stroke-opacity 1s ease-in-out";
// edit props
path.style.fillOpacity = 1;
path.style.strokeOpacity = 0;
} );
}
/**
* DrawFillSVG replay
*
* A public function that allows you to replay the animation if you want. For
* example, click a button, and replay the animation.
*/
DrawFillSVG.prototype.replay = function() {
this._initAnimation();
}
/**
* Add to global namespace
*/
window.DrawFillSVG = DrawFillSVG;
})( window );
// ------------- JQUERY TYPED.JS -------------------------------------------- //
// ============ https://github.com/mattboldt/typed.js/ ====================== //
// -------------------------------------------------------------------------- //
!function($){
"use strict";
var Typed = function(el, options){
// chosen element to manipulate text
this.el = $(el);
// options
this.options = $.extend({}, $.fn.typed.defaults, options);
// text content of element
this.baseText = this.el.text() || this.el.attr('placeholder') || '';
// typing speed
this.typeSpeed = this.options.typeSpeed;
// add a delay before typing starts
this.startDelay = this.options.startDelay;
// backspacing speed
this.backSpeed = this.options.backSpeed;
// amount of time to wait before backspacing
this.backDelay = this.options.backDelay;
// input strings of text
this.strings = this.options.strings;
// character number position of current string
this.strPos = 0;
// current array position
this.arrayPos = 0;
// number to stop backspacing on.
// default 0, can change depending on how many chars
// you want to remove at the time
this.stopNum = 0;
// Looping logic
this.loop = this.options.loop;
this.loopCount = this.options.loopCount;
this.curLoop = 0;
// for stopping
this.stop = false;
// show cursor
this.showCursor = this.isInput ? false : this.options.showCursor;
// custom cursor
this.cursorChar = this.options.cursorChar;
// attribute to type
this.isInput = this.el.is('input');
this.attr = this.options.attr || (this.isInput ? 'placeholder' : null);
// All systems go!
this.build();
};
Typed.prototype = {
constructor: Typed
, init: function(){
// begin the loop w/ first current string (global self.string)
// current string will be passed as an argument each time after this
var self = this;
self.timeout = setTimeout(function() {
// Start typing
self.typewrite(self.strings[self.arrayPos], self.strPos);
}, self.startDelay);
}
, build: function(){
// Insert cursor
if (this.showCursor === true){
this.cursor = $("" + this.cursorChar + "");
this.el.after(this.cursor);
}
this.init();
}
// pass current string state to each function, types 1 char per call
, typewrite: function(curString, curStrPos){
// exit when stopped
if(this.stop === true)
return;
// varying values for setTimeout during typing
// can't be global since number changes each time loop is executed
var humanize = Math.round(Math.random() * (100 - 30)) + this.typeSpeed;
var self = this;
// ------------- optional ------------- //
// backpaces a certain string faster
// ------------------------------------ //
// if (self.arrayPos == 1){
// self.backDelay = 50;
// }
// else{ self.backDelay = 500; }
// contain typing function in a timeout humanize'd delay
self.timeout = setTimeout(function() {
// check for an escape character before a pause value
// format: \^\d+ .. eg: ^1000 .. should be able to print the ^ too using ^^
// single ^ are removed from string
var charPause = 0;
var substr = curString.substr(curStrPos);
if (substr.charAt(0) === '^') {
var skip = 1; // skip atleast 1
if(/^\^\d+/.test(substr)) {
substr = /\d+/.exec(substr)[0];
skip += substr.length;
charPause = parseInt(substr);
}
// strip out the escape character and pause value so they're not printed
curString = curString.substring(0,curStrPos)+curString.substring(curStrPos+skip);
}
// timeout for any pause after a character
self.timeout = setTimeout(function() {
if(curStrPos === curString.length) {
// fires callback function
self.options.onStringTyped(self.arrayPos);
// is this the final string
if(self.arrayPos === self.strings.length-1) {
// animation that occurs on the last typed string
self.options.callback();
self.curLoop++;
// quit if we wont loop back
if(self.loop === false || self.curLoop === self.loopCount)
return;
}
self.timeout = setTimeout(function(){
self.backspace(curString, curStrPos);
}, self.backDelay);
} else {
/* call before functions if applicable */
if(curStrPos === 0)
self.options.preStringTyped(self.arrayPos);
// start typing each new char into existing string
// curString: arg, self.baseText: original text inside element
var nextString = self.baseText + curString.substr(0, curStrPos+1);
if (self.attr) {
self.el.attr(self.attr, nextString);
} else {
self.el.text(nextString);
}
// add characters one by one
curStrPos++;
// loop the function
self.typewrite(curString, curStrPos);
}
// end of character pause
}, charPause);
// humanized value for typing
}, humanize);
}
, backspace: function(curString, curStrPos){
// exit when stopped
if (this.stop === true) {
return;
}
// varying values for setTimeout during typing
// can't be global since number changes each time loop is executed
var humanize = Math.round(Math.random() * (100 - 30)) + this.backSpeed;
var self = this;
self.timeout = setTimeout(function() {
// ----- this part is optional ----- //
// check string array position
// on the first string, only delete one word
// the stopNum actually represents the amount of chars to
// ------------- CUSTOM OPTIONS --------------------------------------------- //
// ========================================================================== //
// -------------------------------------------------------------------------- //
if (self.arrayPos == 1) {
self.stopNum = 17;
self.backDelay = 500;
}
else if (self.arrayPos == 2) {
self.stopNum = 54;
}
else{self.stopNum = 0;}
// ----- continue important stuff ----- //
// replace text with base text + typed characters
var nextString = self.baseText + curString.substr(0, curStrPos);
if (self.attr) {
self.el.attr(self.attr, nextString);
} else {
self.el.text(nextString);
}
// if the number (id of character in current string) is
// less than the stop number, keep going
if (curStrPos > self.stopNum){
// subtract characters one by one
curStrPos--;
// loop the function
self.backspace(curString, curStrPos);
}
// if the stop number has been reached, increase
// array position to next string
else if (curStrPos <= self.stopNum) {
self.arrayPos++;
if(self.arrayPos === self.strings.length) {
self.arrayPos = 0;
self.init();
} else
self.typewrite(self.strings[self.arrayPos], curStrPos);
}
// humanized value for typing
}, humanize);
}
// Start & Stop currently not working
// , stop: function() {
// var self = this;
// self.stop = true;
// clearInterval(self.timeout);
// }
// , start: function() {
// var self = this;
// if(self.stop === false)
// return;
// this.stop = false;
// this.init();
// }
// Reset and rebuild the element
, reset: function(){
var self = this;
clearInterval(self.timeout);
var id = this.el.attr('id');
this.el.after('')
this.el.remove();
this.cursor.remove();
// Send the callback
self.options.resetCallback();
}
};
$.fn.typed = function (option) {
return this.each(function () {
var $this = $(this)
, data = $this.data('typed')
, options = typeof option == 'object' && option;
if (!data) $this.data('typed', (data = new Typed(this, options)));
if (typeof option == 'string') data[option]();
});
};
$.fn.typed.defaults = {
strings: ["These are the default values...", "You know what you should do?", "Use your own!", "Have a great day!"],
// typing speed
typeSpeed: 0,
// time before typing starts
startDelay: 0,
// backspacing speed
backSpeed: 0,
// time before backspacing
backDelay: 500,
// loop
loop: false,
// false = infinite
loopCount: false,
// show cursor
showCursor: true,
// character for cursor
cursorChar: "|",
// attribute to type (null == text)
attr: null,
// call when done callback function
callback: function() {},
// starting callback function before each string
preStringTyped: function() {},
//callback for every typed string
onStringTyped: function() {},
// callback for reset
resetCallback: function() {}
};
}(window.jQuery);
// ------------- JQUERY SCROLLTO--------------------------------------------- //
// ============ https://github.com/balupton/jquery-scrollto ================= //
// -------------------------------------------------------------------------- //
/*global define:false require:false */
(function (name, context, definition) {
if (typeof module != 'undefined' && module.exports) module.exports = definition();
else if (typeof define == 'function' && define.amd) define(definition);
else context[name] = definition();
})('jquery-scrollto', this, function(){
// Prepare
var jQuery, $, ScrollTo;
jQuery = $ = window.jQuery || require('jquery');
// Fix scrolling animations on html/body on safari
$.propHooks.scrollTop = $.propHooks.scrollLeft = {
get: function(elem,prop) {
var result = null;
if ( elem.tagName === 'HTML' || elem.tagName === 'BODY' ) {
if ( prop === 'scrollLeft' ) {
result = window.scrollX;
} else if ( prop === 'scrollTop' ) {
result = window.scrollY;
}
}
if ( result == null ) {
result = elem[prop];
}
return result;
}
};
$.Tween.propHooks.scrollTop = $.Tween.propHooks.scrollLeft = {
get: function(tween) {
return $.propHooks.scrollTop.get(tween.elem, tween.prop);
},
set: function(tween) {
// Our safari fix
if ( tween.elem.tagName === 'HTML' || tween.elem.tagName === 'BODY' ) {
// Defaults
tween.options.bodyScrollLeft = (tween.options.bodyScrollLeft || window.scrollX);
tween.options.bodyScrollTop = (tween.options.bodyScrollTop || window.scrollY);
// Apply
if ( tween.prop === 'scrollLeft' ) {
tween.options.bodyScrollLeft = Math.round(tween.now);
}
else if ( tween.prop === 'scrollTop' ) {
tween.options.bodyScrollTop = Math.round(tween.now);
}
// Apply
window.scrollTo(tween.options.bodyScrollLeft, tween.options.bodyScrollTop);
}
// jQuery's IE8 Fix
else if ( tween.elem.nodeType && tween.elem.parentNode ) {
tween.elem[ tween.prop ] = tween.now;
}
}
};
// jQuery ScrollTo
ScrollTo = {
// Configuration
config: {
duration: 400,
easing: 'swing',
callback: undefined,
durationMode: 'each',
offsetTop: 0,
offsetLeft: 0
},
// Set Configuration
configure: function(options){
// Apply Options to Config
$.extend(ScrollTo.config, options||{});
// Chain
return this;
},
// Perform the Scroll Animation for the Collections
// We use $inline here, so we can determine the actual offset start for each overflow:scroll item
// Each collection is for each overflow:scroll item
scroll: function(collections, config){
// Prepare
var collection, $container, container, $target, $inline, position, containerTagName,
containerScrollTop, containerScrollLeft,
containerScrollTopEnd, containerScrollLeftEnd,
startOffsetTop, targetOffsetTop, targetOffsetTopAdjusted,
startOffsetLeft, targetOffsetLeft, targetOffsetLeftAdjusted,
scrollOptions,
callback;
// Determine the Scroll
collection = collections.pop();
$container = collection.$container;
$target = collection.$target;
containerTagName = $container.prop('tagName');
// Prepare the Inline Element of the Container
$inline = $('').css({
'position': 'absolute',
'top': '0px',
'left': '0px'
});
position = $container.css('position');
// Insert the Inline Element of the Container
$container.css({position:'relative'});
$inline.appendTo($container);
// Determine the top offset
startOffsetTop = $inline.offset().top;
targetOffsetTop = $target.offset().top;
targetOffsetTopAdjusted = targetOffsetTop - startOffsetTop - parseInt(config.offsetTop,10);
// Determine the left offset
startOffsetLeft = $inline.offset().left;
targetOffsetLeft = $target.offset().left;
targetOffsetLeftAdjusted = targetOffsetLeft - startOffsetLeft - parseInt(config.offsetLeft,10);
// Determine current scroll positions
containerScrollTop = $container.prop('scrollTop');
containerScrollLeft = $container.prop('scrollLeft');
// Reset the Inline Element of the Container
$inline.remove();
$container.css({position:position});
// Prepare the scroll options
scrollOptions = {};
// Prepare the callback
callback = function(event){
// Check
if ( collections.length === 0 ) {
// Callback
if ( typeof config.callback === 'function' ) {
config.callback();
}
}
else {
// Recurse
ScrollTo.scroll(collections,config);
}
// Return true
return true;
};
// Handle if we only want to scroll if we are outside the viewport
if ( config.onlyIfOutside ) {
// Determine current scroll positions
containerScrollTopEnd = containerScrollTop + $container.height();
containerScrollLeftEnd = containerScrollLeft + $container.width();
// Check if we are in the range of the visible area of the container
if ( containerScrollTop < targetOffsetTopAdjusted && targetOffsetTopAdjusted < containerScrollTopEnd ) {
targetOffsetTopAdjusted = containerScrollTop;
}
if ( containerScrollLeft < targetOffsetLeftAdjusted && targetOffsetLeftAdjusted < containerScrollLeftEnd ) {
targetOffsetLeftAdjusted = containerScrollLeft;
}
}
// Determine the scroll options
if ( targetOffsetTopAdjusted !== containerScrollTop ) {
scrollOptions.scrollTop = targetOffsetTopAdjusted;
}
if ( targetOffsetLeftAdjusted !== containerScrollLeft ) {
scrollOptions.scrollLeft = targetOffsetLeftAdjusted;
}
// Check to see if the scroll is necessary
if ( $container.prop('scrollHeight') === $container.width() ) {
delete scrollOptions.scrollTop;
}
if ( $container.prop('scrollWidth') === $container.width() ) {
delete scrollOptions.scrollLeft;
}
// Perform the scroll
if ( scrollOptions.scrollTop != null || scrollOptions.scrollLeft != null ) {
$container.animate(scrollOptions, {
duration: config.duration,
easing: config.easing,
complete: callback
});
}
else {
callback();
}
// Return true
return true;
},
// ScrollTo the Element using the Options
fn: function(options){
// Prepare
var collections, config, $container, container;
collections = [];
// Prepare
var $target = $(this);
if ( $target.length === 0 ) {
// Chain
return this;
}
// Handle Options
config = $.extend({},ScrollTo.config,options);
// Fetch
$container = $target.parent();
container = $container.get(0);
// Cycle through the containers
while ( ($container.length === 1) && (container !== document.body) && (container !== document) ) {
// Check Container for scroll differences
var containerScrollTop, containerScrollLeft;
containerScrollTop = $container.css('overflow-y') !== 'visible' && container.scrollHeight !== container.clientHeight;
containerScrollLeft = $container.css('overflow-x') !== 'visible' && container.scrollWidth !== container.clientWidth;
if ( containerScrollTop || containerScrollLeft ) {
// Push the Collection
collections.push({
'$container': $container,
'$target': $target
});
// Update the Target
$target = $container;
}
// Update the Container
$container = $container.parent();
container = $container.get(0);
}
// Add the final collection
collections.push({
'$container': $('html'),
// document.body doesn't work in firefox, html works for all
// internet explorer starts at the beggining
'$target': $target
});
// Adjust the Config
if ( config.durationMode === 'all' ) {
config.duration /= collections.length;
}
// Handle
ScrollTo.scroll(collections,config);
// Chain
return this;
}
};
// Apply our extensions to jQuery
$.ScrollTo = $.ScrollTo || ScrollTo;
$.fn.ScrollTo = $.fn.ScrollTo || ScrollTo.fn;
// Export
return ScrollTo;
});
// ------------- WOW ANIMATE ------------------------------------------------ //
// ==============https://github.com/matthieua/WOW =========================== //
// -------------------------------------------------------------------------- //
(function() {
var MutationObserver, Util, WeakMap, getComputedStyle, getComputedStyleRX,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
Util = (function() {
function Util() {}
Util.prototype.extend = function(custom, defaults) {
var key, value;
for (key in defaults) {
value = defaults[key];
if (custom[key] == null) {
custom[key] = value;
}
}
return custom;
};
Util.prototype.isMobile = function(agent) {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(agent);
};
Util.prototype.addEvent = function(elem, event, fn) {
if (elem.addEventListener != null) {
return elem.addEventListener(event, fn, false);
} else if (elem.attachEvent != null) {
return elem.attachEvent("on" + event, fn);
} else {
return elem[event] = fn;
}
};
Util.prototype.removeEvent = function(elem, event, fn) {
if (elem.removeEventListener != null) {
return elem.removeEventListener(event, fn, false);
} else if (elem.detachEvent != null) {
return elem.detachEvent("on" + event, fn);
} else {
return delete elem[event];
}
};
Util.prototype.innerHeight = function() {
if ('innerHeight' in window) {
return window.innerHeight;
} else {
return document.documentElement.clientHeight;
}
};
return Util;
})();
WeakMap = this.WeakMap || this.MozWeakMap || (WeakMap = (function() {
function WeakMap() {
this.keys = [];
this.values = [];
}
WeakMap.prototype.get = function(key) {
var i, item, _i, _len, _ref;
_ref = this.keys;
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
item = _ref[i];
if (item === key) {
return this.values[i];
}
}
};
WeakMap.prototype.set = function(key, value) {
var i, item, _i, _len, _ref;
_ref = this.keys;
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
item = _ref[i];
if (item === key) {
this.values[i] = value;
return;
}
}
this.keys.push(key);
return this.values.push(value);
};
return WeakMap;
})());
MutationObserver = this.MutationObserver || this.WebkitMutationObserver || this.MozMutationObserver || (MutationObserver = (function() {
function MutationObserver() {
if (typeof console !== "undefined" && console !== null) {
console.warn('MutationObserver is not supported by your browser.');
}
if (typeof console !== "undefined" && console !== null) {
console.warn('WOW.js cannot detect dom mutations, please call .sync() after loading new content.');
}
}
MutationObserver.notSupported = true;
MutationObserver.prototype.observe = function() {};
return MutationObserver;
})());
getComputedStyle = this.getComputedStyle || function(el, pseudo) {
this.getPropertyValue = function(prop) {
var _ref;
if (prop === 'float') {
prop = 'styleFloat';
}
if (getComputedStyleRX.test(prop)) {
prop.replace(getComputedStyleRX, function(_, char) {
return char.toUpperCase();
});
}
return ((_ref = el.currentStyle) != null ? _ref[prop] : void 0) || null;
};
return this;
};
getComputedStyleRX = /(\-([a-z]){1})/g;
this.WOW = (function() {
WOW.prototype.defaults = {
boxClass: 'wow',
animateClass: 'animated',
offset: 0,
mobile: true,
live: true
};
function WOW(options) {
if (options == null) {
options = {};
}
this.scrollCallback = __bind(this.scrollCallback, this);
this.scrollHandler = __bind(this.scrollHandler, this);
this.start = __bind(this.start, this);
this.scrolled = true;
this.config = this.util().extend(options, this.defaults);
this.animationNameCache = new WeakMap();
}
WOW.prototype.init = function() {
var _ref;
this.element = window.document.documentElement;
if ((_ref = document.readyState) === "interactive" || _ref === "complete") {
this.start();
} else {
this.util().addEvent(document, 'DOMContentLoaded', this.start);
}
return this.finished = [];
};
WOW.prototype.start = function() {
var box, _i, _len, _ref;
this.stopped = false;
this.boxes = (function() {
var _i, _len, _ref, _results;
_ref = this.element.querySelectorAll("." + this.config.boxClass);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
box = _ref[_i];
_results.push(box);
}
return _results;
}).call(this);
this.all = (function() {
var _i, _len, _ref, _results;
_ref = this.boxes;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
box = _ref[_i];
_results.push(box);
}
return _results;
}).call(this);
if (this.boxes.length) {
if (this.disabled()) {
this.resetStyle();
} else {
_ref = this.boxes;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
box = _ref[_i];
this.applyStyle(box, true);
}
this.util().addEvent(window, 'scroll', this.scrollHandler);
this.util().addEvent(window, 'resize', this.scrollHandler);
this.interval = setInterval(this.scrollCallback, 50);
}
}
if (this.config.live) {
return new MutationObserver((function(_this) {
return function(records) {
var node, record, _j, _len1, _results;
_results = [];
for (_j = 0, _len1 = records.length; _j < _len1; _j++) {
record = records[_j];
_results.push((function() {
var _k, _len2, _ref1, _results1;
_ref1 = record.addedNodes || [];
_results1 = [];
for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) {
node = _ref1[_k];
_results1.push(this.doSync(node));
}
return _results1;
}).call(_this));
}
return _results;
};
})(this)).observe(document.body, {
childList: true,
subtree: true
});
}
};
WOW.prototype.stop = function() {
this.stopped = true;
this.util().removeEvent(window, 'scroll', this.scrollHandler);
this.util().removeEvent(window, 'resize', this.scrollHandler);
if (this.interval != null) {
return clearInterval(this.interval);
}
};
WOW.prototype.sync = function(element) {
if (MutationObserver.notSupported) {
return this.doSync(this.element);
}
};
WOW.prototype.doSync = function(element) {
var box, _i, _len, _ref, _results;
if (element == null) {
element = this.element;
}
if (element.nodeType !== 1) {
return;
}
element = element.parentNode || element;
_ref = element.querySelectorAll("." + this.config.boxClass);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
box = _ref[_i];
if (__indexOf.call(this.all, box) < 0) {
this.boxes.push(box);
this.all.push(box);
if (this.stopped || this.disabled()) {
this.resetStyle();
} else {
this.applyStyle(box, true);
}
_results.push(this.scrolled = true);
} else {
_results.push(void 0);
}
}
return _results;
};
WOW.prototype.show = function(box) {
this.applyStyle(box);
return box.className = "" + box.className + " " + this.config.animateClass;
};
WOW.prototype.applyStyle = function(box, hidden) {
var delay, duration, iteration;
duration = box.getAttribute('data-wow-duration');
delay = box.getAttribute('data-wow-delay');
iteration = box.getAttribute('data-wow-iteration');
return this.animate((function(_this) {
return function() {
return _this.customStyle(box, hidden, duration, delay, iteration);
};
})(this));
};
WOW.prototype.animate = (function() {
if ('requestAnimationFrame' in window) {
return function(callback) {
return window.requestAnimationFrame(callback);
};
} else {
return function(callback) {
return callback();
};
}
})();
WOW.prototype.resetStyle = function() {
var box, _i, _len, _ref, _results;
_ref = this.boxes;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
box = _ref[_i];
_results.push(box.style.visibility = 'visible');
}
return _results;
};
WOW.prototype.customStyle = function(box, hidden, duration, delay, iteration) {
if (hidden) {
this.cacheAnimationName(box);
}
box.style.visibility = hidden ? 'hidden' : 'visible';
if (duration) {
this.vendorSet(box.style, {
animationDuration: duration
});
}
if (delay) {
this.vendorSet(box.style, {
animationDelay: delay
});
}
if (iteration) {
this.vendorSet(box.style, {
animationIterationCount: iteration
});
}
this.vendorSet(box.style, {
animationName: hidden ? 'none' : this.cachedAnimationName(box)
});
return box;
};
WOW.prototype.vendors = ["moz", "webkit"];
WOW.prototype.vendorSet = function(elem, properties) {
var name, value, vendor, _results;
_results = [];
for (name in properties) {
value = properties[name];
elem["" + name] = value;
_results.push((function() {
var _i, _len, _ref, _results1;
_ref = this.vendors;
_results1 = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
vendor = _ref[_i];
_results1.push(elem["" + vendor + (name.charAt(0).toUpperCase()) + (name.substr(1))] = value);
}
return _results1;
}).call(this));
}
return _results;
};
WOW.prototype.vendorCSS = function(elem, property) {
var result, style, vendor, _i, _len, _ref;
style = getComputedStyle(elem);
result = style.getPropertyCSSValue(property);
_ref = this.vendors;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
vendor = _ref[_i];
result = result || style.getPropertyCSSValue("-" + vendor + "-" + property);
}
return result;
};
WOW.prototype.animationName = function(box) {
var animationName;
try {
animationName = this.vendorCSS(box, 'animation-name').cssText;
} catch (_error) {
animationName = getComputedStyle(box).getPropertyValue('animation-name');
}
if (animationName === 'none') {
return '';
} else {
return animationName;
}
};
WOW.prototype.cacheAnimationName = function(box) {
return this.animationNameCache.set(box, this.animationName(box));
};
WOW.prototype.cachedAnimationName = function(box) {
return this.animationNameCache.get(box);
};
WOW.prototype.scrollHandler = function() {
return this.scrolled = true;
};
WOW.prototype.scrollCallback = function() {
var box;
if (this.scrolled) {
this.scrolled = false;
this.boxes = (function() {
var _i, _len, _ref, _results;
_ref = this.boxes;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
box = _ref[_i];
if (!(box)) {
continue;
}
if (this.isVisible(box)) {
this.show(box);
continue;
}
_results.push(box);
}
return _results;
}).call(this);
if (!(this.boxes.length || this.config.live)) {
return this.stop();
}
}
};
WOW.prototype.offsetTop = function(element) {
var top;
while (element.offsetTop === void 0) {
element = element.parentNode;
}
top = element.offsetTop;
while (element = element.offsetParent) {
top += element.offsetTop;
}
return top;
};
WOW.prototype.isVisible = function(box) {
var bottom, offset, top, viewBottom, viewTop;
offset = box.getAttribute('data-wow-offset') || this.config.offset;
viewTop = window.pageYOffset;
viewBottom = viewTop + Math.min(this.element.clientHeight, this.util().innerHeight()) - offset;
top = this.offsetTop(box);
bottom = top + box.clientHeight;
return top <= viewBottom && bottom >= viewTop;
};
WOW.prototype.util = function() {
return this._util != null ? this._util : this._util = new Util();
};
WOW.prototype.disabled = function() {
return !this.config.mobile && this.util().isMobile(navigator.userAgent);
};
return WOW;
})();
}).call(this);
// ------------- JQUERY SMOOTHSTATE ----------------------------------------- //
// ============ https://github.com/miguel-perez/jquery.smoothState.js ======= //
// -------------------------------------------------------------------------- //
;(function ( $, window, document, undefined ) {
"use strict";
var
/** Used later to scroll page to the top */
$body = $("html, body"),
/** Used in development mode to console out useful warnings */
consl = (window.console || false),
/** Plugin default options */
defaults = {
/** jquery element string to specify which anchors smoothstate should bind to */
anchors : "a",
/** If set to true, smoothState will prefetch a link's contents on hover */
prefetch : false,
/** A selecor that deinfes with links should be ignored by smoothState */
blacklist : ".no-smoothstate, [target]",
/** If set to true, smoothState will log useful debug information instead of aborting */
development : false,
/** The number of pages smoothState will try to store in memory and not request again */
pageCacheSize : 0,
/** A function that can be used to alter urls before they are used to request content */
alterRequestUrl : function (url) {
return url;
},
/** Run when a link has been activated */
onStart : {
duration: 0,
render: function (url, $container) {
$body.scrollTop(0);
}
},
/** Run if the page request is still pending and onStart has finished animating */
onProgress : {
duration: 0,
render: function (url, $container) {
$body.css("cursor", "wait");
$body.find("a").css("cursor", "wait");
}
},
/** Run when requested content is ready to be injected into the page */
onEnd : {
duration: 0,
render: function (url, $container, $content) {
$body.css("cursor", "auto");
$body.find("a").css("cursor", "auto");
$container.html($content);
}
},
/** Run when content has been injected and all animations are complete */
callback : function(url, $container, $content) {
}
},
/** Utility functions that are decoupled from SmoothState */
utility = {
/**
* Checks to see if the url is external
* @param {string} url - url being evaluated
* @see http://stackoverflow.com/questions/6238351/fastest-way-to-detect-external-urls
*
*/
isExternal: function (url) {
var match = url.match(/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/);
if (typeof match[1] === "string" && match[1].length > 0 && match[1].toLowerCase() !== window.location.protocol) {
return true;
}
if (typeof match[2] === "string" && match[2].length > 0 && match[2].replace(new RegExp(":(" + {"http:": 80, "https:": 443}[window.location.protocol] + ")?$"), "") !== window.location.host) {
return true;
}
return false;
},
/**
* Checks to see if the url is an internal hash
* @param {string} url - url being evaluated
*
*/
isHash: function (url) {
var hasPathname = (url.indexOf(window.location.pathname) > 0) ? true : false,
hasHash = (url.indexOf("#") > 0) ? true : false;
return (hasPathname && hasHash) ? true : false;
},
/**
* Checks to see if we should be loading this URL
* @param {string} url - url being evaluated
* @param {string} blacklist - jquery selector
*
*/
shouldLoad: function ($anchor, blacklist) {
var url = $anchor.prop("href");
// URL will only be loaded if it"s not an external link, hash, or blacklisted
return (!utility.isExternal(url) && !utility.isHash(url) && !$anchor.is(blacklist));
},
/**
* Prevents jQuery from stripping elements from $(html)
* @param {string} url - url being evaluated
* @author Ben Alman http://benalman.com/
* @see https://gist.github.com/cowboy/742952
*
*/
htmlDoc: function (html) {
var parent,
elems = $(),
matchTag = /<(\/?)(html|head|body|title|base|meta)(\s+[^>]*)?>/ig,
prefix = "ss" + Math.round(Math.random() * 100000),
htmlParsed = html.replace(matchTag, function(tag, slash, name, attrs) {
var obj = {};
if (!slash) {
elems = elems.add("<" + name + "/>");
if (attrs) {
$.each($("")[0].attributes, function(i, attr) {
obj[attr.name] = attr.value;
});
}
elems.eq(-1).attr(obj);
}
return "<" + slash + "div" + (slash ? "" : " id='" + prefix + (elems.length - 1) + "'") + ">";
});
// If no placeholder elements were necessary, just return normal
// jQuery-parsed HTML.
if (!elems.length) {
return $(html);
}
// Create parent node if it hasn"t been created yet.
if (!parent) {
parent = $("");
}
// Create the parent node and append the parsed, place-held HTML.
parent.html(htmlParsed);
// Replace each placeholder element with its intended element.
$.each(elems, function(i) {
var elem = parent.find("#" + prefix + i).before(elems[i]);
elems.eq(i).html(elem.contents());
elem.remove();
});
return parent.children().unwrap();
},
/**
* Resets an object if it has too many properties
*
* This is used to clear the "cache" object that stores
* all of the html. This would prevent the client from
* running out of memory and allow the user to hit the
* server for a fresh copy of the content.
*
* @param {object} obj
* @param {number} cap
*
*/
clearIfOverCapacity: function (obj, cap) {
// Polyfill Object.keys if it doesn"t exist
if (!Object.keys) {
Object.keys = function (obj) {
var keys = [],
k;
for (k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
keys.push(k);
}
}
return keys;
};
}
if (Object.keys(obj).length > cap) {
obj = {};
}
return obj;
},
/**
* Finds the inner content of an element, by an ID, from a jQuery object
* @param {string} id
* @param {object} $html
*
*/
getContentById: function (id, $html) {
$html = ($html instanceof jQuery) ? $html : utility.htmlDoc($html);
var $insideElem = $html.find(id),
updatedContainer = ($insideElem.length) ? $.trim($insideElem.html()) : $html.filter(id).html(),
newContent = (updatedContainer.length) ? $(updatedContainer) : null;
return newContent;
},
/**
* Stores html content as jquery object in given object
* @param {object} object - object contents will be stored into
* @param {string} url - url to be used as the prop
* @param {jquery} html - contents to store
*
*/
storePageIn: function (object, url, $html) {
$html = ($html instanceof jQuery) ? $html : utility.htmlDoc($html);
object[url] = { // Content is indexed by the url
status: "loaded",
title: $html.find("title").text(), // Stores the title of the page
html: $html // Stores the contents of the page
};
return object;
},
/**
* Triggers an "allanimationend" event when all animations are complete
* @param {object} $element - jQuery object that should trigger event
* @param {string} resetOn - which other events to trigger allanimationend on
*
*/
triggerAllAnimationEndEvent: function ($element, resetOn) {
resetOn = " " + resetOn || "";
var animationCount = 0,
animationstart = "animationstart webkitAnimationStart oanimationstart MSAnimationStart",
animationend = "animationend webkitAnimationEnd oanimationend MSAnimationEnd",
eventname = "allanimationend",
onAnimationStart = function (e) {
if ($(e.delegateTarget).is($element)) {
e.stopPropagation();
animationCount ++;
}
},
onAnimationEnd = function (e) {
if ($(e.delegateTarget).is($element)) {
e.stopPropagation();
animationCount --;
if(animationCount === 0) {
$element.trigger(eventname);
}
}
};
$element.on(animationstart, onAnimationStart);
$element.on(animationend, onAnimationEnd);
$element.on("allanimationend" + resetOn, function(){
animationCount = 0;
utility.redraw($element);
});
},
/** Forces browser to redraw elements */
redraw: function ($element) {
$element.height(0);
setTimeout(function(){$element.height("auto");}, 0);
}
},
/** Handles the popstate event, like when the user hits "back" */
onPopState = function ( e ) {
if(e.state !== null) {
var url = window.location.href,
$page = $("#" + e.state.id),
page = $page.data("smoothState");
if(page.href !== url && !utility.isHash(url)) {
page.load(url, true);
}
}
},
/** Constructor function */
SmoothState = function ( element, options ) {
var
/** Container element smoothState is run on */
$container = $(element),
/** Variable that stores pages after they are requested */
cache = {},
/** Url of the content that is currently displayed */
currentHref = window.location.href,
/**
* Loads the contents of a url into our container
*
* @param {string} url
* @param {bool} isPopped - used to determine if whe should
* add a new item into the history object
*
*/
load = function (url, isPopped) {
/** Makes this an optional variable by setting a default */
isPopped = isPopped || false;
var
/** Used to check if the onProgress function has been run */
hasRunCallback = false,
callbBackEnded = false,
/** List of responses for the states of the page request */
responses = {
/** Page is ready, update the content */
loaded: function() {
var eventName = hasRunCallback ? "ss.onProgressEnd" : "ss.onStartEnd";
if(!callbBackEnded || !hasRunCallback) {
$container.one(eventName, function(){
updateContent(url);
});
} else if(callbBackEnded) {
updateContent(url);
}
if(!isPopped) {
window.history.pushState({ id: $container.prop("id") }, cache[url].title, url);
}
},
/** Loading, wait 10 ms and check again */
fetching: function() {
if(!hasRunCallback) {
hasRunCallback = true;
// Run the onProgress callback and set trigger
$container.one("ss.onStartEnd", function(){
options.onProgress.render(url, $container, null);
setTimeout(function(){
$container.trigger("ss.onProgressEnd");
callbBackEnded = true;
}, options.onStart.duration);
});
}
setTimeout(function () {
// Might of been canceled, better check!
if(cache.hasOwnProperty(url)){
responses[cache[url].status]();
}
}, 10);
},
/** Error, abort and redirect */
error: function(){
window.location = url;
}
};
if (!cache.hasOwnProperty(url)) {
fetch(url);
}
// Run the onStart callback and set trigger
options.onStart.render(url, $container, null);
setTimeout(function(){
$container.trigger("ss.onStartEnd");
}, options.onStart.duration);
// Start checking for the status of content
responses[cache[url].status]();
},
/** Updates the contents from cache[url] */
updateContent = function (url) {
// If the content has been requested and is done:
var containerId = "#" + $container.prop("id"),
$content = cache[url] ? utility.getContentById(containerId, cache[url].html) : null;
if($content) {
document.title = cache[url].title;
$container.data("smoothState").href = url;
// Call the onEnd callback and set trigger
options.onEnd.render(url, $container, $content);
$container.one("ss.onEndEnd", function(){
options.callback(url, $container, $content);
});
setTimeout(function(){
$container.trigger("ss.onEndEnd");
}, options.onEnd.duration);
} else if (!$content && options.development && consl) {
// Throw warning to help debug in development mode
consl.warn("No element with an id of " + containerId + " in response from " + url + " in " + cache);
} else {
// No content availble to update with, aborting...
window.location = url;
}
},
/**
* Fetches the contents of a url and stores it in the "cache" varible
* @param {string} url
*
*/
fetch = function (url) {
// Don"t fetch we have the content already
if(cache.hasOwnProperty(url)) {
return;
}
cache = utility.clearIfOverCapacity(cache, options.pageCacheSize);
cache[url] = { status: "fetching" };
var requestUrl = options.alterRequestUrl(url) || url,
request = $.ajax(requestUrl);
// Store contents in cache variable if successful
request.success(function (html) {
// Clear cache varible if it"s getting too big
utility.storePageIn(cache, url, html);
$container.data("smoothState").cache = cache;
});
// Mark as error
request.error(function () {
cache[url].status = "error";
});
},
/**
* Binds to the hover event of a link, used for prefetching content
*
* @param {object} event
*
*/
hoverAnchor = function (event) {
var $anchor = $(event.currentTarget),
url = $anchor.prop("href");
if (utility.shouldLoad($anchor, options.blacklist)) {
event.stopPropagation();
fetch(url);
}
},
/**
* Binds to the click event of a link, used to show the content
*
* @param {object} event
*
*/
clickAnchor = function (event) {
var $anchor = $(event.currentTarget),
url = $anchor.prop("href");
// Ctrl (or Cmd) + click must open a new tab
if (!event.metaKey && !event.ctrlKey && utility.shouldLoad($anchor, options.blacklist)) {
// stopPropagation so that event doesn"t fire on parent containers.
event.stopPropagation();
event.preventDefault();
load(url);
}
},
/**
* Binds all events and inits functionality
*
* @param {object} event
*
*/
bindEventHandlers = function ($element) {
//@todo: Handle form submissions
$element.on("click", options.anchors, clickAnchor);
if (options.prefetch) {
$element.on("mouseover touchstart", options.anchors, hoverAnchor);
}
},
/** Used to restart css animations with a class */
toggleAnimationClass = function (classname) {
var classes = $container.addClass(classname).prop("class");
$container.removeClass(classes);
setTimeout(function(){
$container.addClass(classes);
},0);
$container.one("ss.onStartEnd ss.onProgressEnd ss.onEndEnd", function(){
$container.removeClass(classname);
});
};
/** Override defaults with options passed in */
options = $.extend(defaults, options);
/** Sets a default state */
if(window.history.state === null) {
window.history.replaceState({ id: $container.prop("id") }, document.title, currentHref);
}
/** Stores the current page in cache variable */
utility.storePageIn(cache, currentHref, document.documentElement.outerHTML);
/** Bind all of the event handlers on the container, not anchors */
utility.triggerAllAnimationEndEvent($container, "ss.onStartEnd ss.onProgressEnd ss.onEndEnd");
/** Bind all of the event handlers on the container, not anchors */
bindEventHandlers($container);
/** Public methods */
return {
href: currentHref,
cache: cache,
load: load,
fetch: fetch,
toggleAnimationClass: toggleAnimationClass
};
},
/** Returns elements with SmoothState attached to it */
declareSmoothState = function ( options ) {
return this.each(function () {
// Checks to make sure the smoothState element has an id and isn"t already bound
if(this.id && !$.data(this, "smoothState")) {
// Makes public methods available via $("element").data("smoothState");
$.data(this, "smoothState", new SmoothState(this, options));
} else if (!this.id && consl) {
// Throw warning if in development mode
consl.warn("Every smoothState container needs an id but the following one does not have one:", this);
}
});
};
/** Sets the popstate function */
window.onpopstate = onPopState;
/** Makes utility functions public for unit tests */
$.smoothStateUtility = utility;
/** Defines the smoothState plugin */
$.fn.smoothState = declareSmoothState;
})(jQuery, window, document);
// ------------- jQuery Cookie Plugin v1.4.1 -------------------------------- //
// ============ https://github.com/carhartl/jquery-cookie =================== //
// -------------------------------------------------------------------------- //
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// CommonJS
factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var pluses = /\+/g;
function encode(s) {
return config.raw ? s : encodeURIComponent(s);
}
function decode(s) {
return config.raw ? s : decodeURIComponent(s);
}
function stringifyCookieValue(value) {
return encode(config.json ? JSON.stringify(value) : String(value));
}
function parseCookieValue(s) {
if (s.indexOf('"') === 0) {
// This is a quoted cookie as according to RFC2068, unescape...
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
try {
// Replace server-side written pluses with spaces.
// If we can't decode the cookie, ignore it, it's unusable.
// If we can't parse the cookie, ignore it, it's unusable.
s = decodeURIComponent(s.replace(pluses, ' '));
return config.json ? JSON.parse(s) : s;
} catch(e) {}
}
function read(s, converter) {
var value = config.raw ? s : parseCookieValue(s);
return $.isFunction(converter) ? converter(value) : value;
}
var config = $.cookie = function (key, value, options) {
// Write
if (arguments.length > 1 && !$.isFunction(value)) {
options = $.extend({}, config.defaults, options);
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setTime(+t + days * 864e+5);
}
return (document.cookie = [
encode(key), '=', stringifyCookieValue(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// Read
var result = key ? undefined : {};
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling $.cookie().
var cookies = document.cookie ? document.cookie.split('; ') : [];
for (var i = 0, l = cookies.length; i < l; i++) {
var parts = cookies[i].split('=');
var name = decode(parts.shift());
var cookie = parts.join('=');
if (key && key === name) {
// If second argument (value) is a function it's a converter...
result = read(cookie, value);
break;
}
// Prevent storing a cookie that we couldn't decode.
if (!key && (cookie = read(cookie)) !== undefined) {
result[name] = cookie;
}
}
return result;
};
config.defaults = {};
$.removeCookie = function (key, options) {
if ($.cookie(key) === undefined) {
return false;
}
// Must not alter options, thus extending a fresh object...
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
return !$.cookie(key);
};
}));