/*!
* parallax.js v1.5.0 (http://pixelcog.github.io/parallax.js/)
* @copyright 2016 pixelcog, inc.
* @license mit (https://github.com/pixelcog/parallax.js/blob/master/license)
*/
;(function ( $, window, document, undefined ) {
// polyfill for requestanimationframe
// via: https://gist.github.com/paulirish/1579671
(function() {
var lasttime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestanimationframe; ++x) {
window.requestanimationframe = window[vendors[x]+'requestanimationframe'];
window.cancelanimationframe = window[vendors[x]+'cancelanimationframe'] || window[vendors[x]+'cancelrequestanimationframe'];
}
if (!window.requestanimationframe)
window.requestanimationframe = function(callback) {
var currtime = new date().gettime();
var timetocall = math.max(0, 16 - (currtime - lasttime));
var id = window.settimeout(function() { callback(currtime + timetocall); },
timetocall);
lasttime = currtime + timetocall;
return id;
};
if (!window.cancelanimationframe)
window.cancelanimationframe = function(id) {
cleartimeout(id);
};
}());
// parallax constructor
function parallax(element, options) {
var self = this;
if (typeof options == 'object') {
delete options.refresh;
delete options.render;
$.extend(this, options);
}
this.$element = $(element);
if (!this.imagesrc && this.$element.is('img')) {
this.imagesrc = this.$element.attr('src');
}
var positions = (this.position + '').tolowercase().match(/\s+/g) || [];
if (positions.length < 1) {
positions.push('center');
}
if (positions.length == 1) {
positions.push(positions[0]);
}
if (positions[0] == 'top' || positions[0] == 'bottom' || positions[1] == 'left' || positions[1] == 'right') {
positions = [positions[1], positions[0]];
}
if (this.positionx !== undefined) positions[0] = this.positionx.tolowercase();
if (this.positiony !== undefined) positions[1] = this.positiony.tolowercase();
self.positionx = positions[0];
self.positiony = positions[1];
if (this.positionx != 'left' && this.positionx != 'right') {
if (isnan(parseint(this.positionx))) {
this.positionx = 'center';
} else {
this.positionx = parseint(this.positionx);
}
}
if (this.positiony != 'top' && this.positiony != 'bottom') {
if (isnan(parseint(this.positiony))) {
this.positiony = 'center';
} else {
this.positiony = parseint(this.positiony);
}
}
this.position =
this.positionx + (isnan(this.positionx)? '' : 'px') + ' ' +
this.positiony + (isnan(this.positiony)? '' : 'px');
if (navigator.useragent.match(/(ipod|iphone|ipad)/)) {
if (this.imagesrc && this.iosfix && !this.$element.is('img')) {
this.$element.css({
backgroundimage: 'url(' + this.imagesrc + ')',
backgroundsize: 'cover',
backgroundposition: this.position
});
}
return this;
}
if (navigator.useragent.match(/(android)/)) {
if (this.imagesrc && this.androidfix && !this.$element.is('img')) {
this.$element.css({
backgroundimage: 'url(' + this.imagesrc + ')',
backgroundsize: 'cover',
backgroundposition: this.position
});
}
return this;
}
this.$mirror = $('
').prependto(this.mirrorcontainer);
var slider = this.$element.find('>.parallax-slider');
var sliderexisted = false;
if (slider.length == 0)
this.$slider = $('
').prependto(this.$mirror);
else {
this.$slider = slider.prependto(this.$mirror)
sliderexisted = true;
}
this.$mirror.addclass('parallax-mirror').css({
visibility: 'hidden',
zindex: this.zindex,
position: 'fixed',
top: 0,
left: 0,
overflow: 'hidden'
});
this.$slider.addclass('parallax-slider').one('load', function() {
if (!self.naturalheight || !self.naturalwidth) {
self.naturalheight = this.naturalheight || this.height || 1;
self.naturalwidth = this.naturalwidth || this.width || 1;
}
self.aspectratio = self.naturalwidth / self.naturalheight;
parallax.issetup || parallax.setup();
parallax.sliders.push(self);
parallax.isfresh = false;
parallax.requestrender();
});
if (!sliderexisted)
this.$slider[0].src = this.imagesrc;
if (this.naturalheight && this.naturalwidth || this.$slider[0].complete || slider.length > 0) {
this.$slider.trigger('load');
}
}
// parallax instance methods
$.extend(parallax.prototype, {
speed: 0.2,
bleed: 0,
zindex: -100,
iosfix: false,
androidfix: false,
position: 'center',
overscrollfix: false,
mirrorcontainer: 'body',
refresh: function() {
this.boxwidth = this.$element.outerwidth();
this.boxheight = this.$element.outerheight() + this.bleed * 2;
this.boxoffsettop = this.$element.offset().top - this.bleed;
this.boxoffsetleft = this.$element.offset().left;
this.boxoffsetbottom = this.boxoffsettop + this.boxheight;
var winheight = parallax.winheight;
var docheight = parallax.docheight;
var maxoffset = math.min(this.boxoffsettop, docheight - winheight);
var minoffset = math.max(this.boxoffsettop + this.boxheight - winheight, 0);
var imageheightmin = this.boxheight + (maxoffset - minoffset) * (1 - this.speed) | 0;
var imageoffsetmin = (this.boxoffsettop - maxoffset) * (1 - this.speed) | 0;
var margin;
if (imageheightmin * this.aspectratio >= this.boxwidth) {
this.imagewidth = imageheightmin * this.aspectratio | 0;
this.imageheight = imageheightmin;
this.offsetbasetop = imageoffsetmin;
margin = this.imagewidth - this.boxwidth;
if (this.positionx == 'left') {
this.offsetleft = 0;
} else if (this.positionx == 'right') {
this.offsetleft = - margin;
} else if (!isnan(this.positionx)) {
this.offsetleft = math.max(this.positionx, - margin);
} else {
this.offsetleft = - margin / 2 | 0;
}
} else {
this.imagewidth = this.boxwidth;
this.imageheight = this.boxwidth / this.aspectratio | 0;
this.offsetleft = 0;
margin = this.imageheight - imageheightmin;
if (this.positiony == 'top') {
this.offsetbasetop = imageoffsetmin;
} else if (this.positiony == 'bottom') {
this.offsetbasetop = imageoffsetmin - margin;
} else if (!isnan(this.positiony)) {
this.offsetbasetop = imageoffsetmin + math.max(this.positiony, - margin);
} else {
this.offsetbasetop = imageoffsetmin - margin / 2 | 0;
}
}
},
render: function() {
var scrolltop = parallax.scrolltop;
var scrollleft = parallax.scrollleft;
var overscroll = this.overscrollfix ? parallax.overscroll : 0;
var scrollbottom = scrolltop + parallax.winheight;
if (this.boxoffsetbottom > scrolltop && this.boxoffsettop <= scrollbottom) {
this.visibility = 'visible';
this.mirrortop = this.boxoffsettop - scrolltop;
this.mirrorleft = this.boxoffsetleft - scrollleft;
this.offsettop = this.offsetbasetop - this.mirrortop * (1 - this.speed);
} else {
this.visibility = 'hidden';
}
this.$mirror.css({
transform: 'translate3d('+this.mirrorleft+'px, '+(this.mirrortop - overscroll)+'px, 0px)',
visibility: this.visibility,
height: this.boxheight,
width: this.boxwidth
});
this.$slider.css({
transform: 'translate3d('+this.offsetleft+'px, '+this.offsettop+'px, 0px)',
position: 'absolute',
height: this.imageheight,
width: this.imagewidth,
maxwidth: 'none'
});
}
});
// parallax static methods
$.extend(parallax, {
scrolltop: 0,
scrollleft: 0,
winheight: 0,
winwidth: 0,
docheight: 1 << 30,
docwidth: 1 << 30,
sliders: [],
isready: false,
isfresh: false,
isbusy: false,
setup: function() {
if (this.isready) return;
var self = this;
var $doc = $(document), $win = $(window);
var loaddimensions = function() {
parallax.winheight = $win.height();
parallax.winwidth = $win.width();
parallax.docheight = $doc.height();
parallax.docwidth = $doc.width();
};
var loadscrollposition = function() {
var winscrolltop = $win.scrolltop();
var scrolltopmax = parallax.docheight - parallax.winheight;
var scrollleftmax = parallax.docwidth - parallax.winwidth;
parallax.scrolltop = math.max(0, math.min(scrolltopmax, winscrolltop));
parallax.scrollleft = math.max(0, math.min(scrollleftmax, $win.scrollleft()));
parallax.overscroll = math.max(winscrolltop - scrolltopmax, math.min(winscrolltop, 0));
};
$win.on('resize.px.parallax load.px.parallax', function() {
loaddimensions();
self.refresh();
parallax.isfresh = false;
parallax.requestrender();
})
.on('scroll.px.parallax load.px.parallax', function() {
loadscrollposition();
parallax.requestrender();
});
loaddimensions();
loadscrollposition();
this.isready = true;
var lastposition = -1;
function frameloop() {
if (lastposition == window.pageyoffset) { // avoid overcalculations
window.requestanimationframe(frameloop);
return false;
} else lastposition = window.pageyoffset;
self.render();
window.requestanimationframe(frameloop);
}
frameloop();
},
configure: function(options) {
if (typeof options == 'object') {
delete options.refresh;
delete options.render;
$.extend(this.prototype, options);
}
},
refresh: function() {
$.each(this.sliders, function(){ this.refresh(); });
this.isfresh = true;
},
render: function() {
this.isfresh || this.refresh();
$.each(this.sliders, function(){ this.render(); });
},
requestrender: function() {
var self = this;
self.render();
self.isbusy = false;
},
destroy: function(el){
var i,
parallaxelement = $(el).data('px.parallax');
parallaxelement.$mirror.remove();
for(i=0; i < this.sliders.length; i+=1){
if(this.sliders[i] == parallaxelement){
this.sliders.splice(i, 1);
}
}
$(el).data('px.parallax', false);
if(this.sliders.length === 0){
$(window).off('scroll.px.parallax resize.px.parallax load.px.parallax');
this.isready = false;
parallax.issetup = false;
}
}
});
// parallax plugin definition
function plugin(option) {
return this.each(function () {
var $this = $(this);
var options = typeof option == 'object' && option;
if (this == window || this == document || $this.is('body')) {
parallax.configure(options);
}
else if (!$this.data('px.parallax')) {
options = $.extend({}, $this.data(), options);
$this.data('px.parallax', new parallax(this, options));
}
else if (typeof option == 'object')
{
$.extend($this.data('px.parallax'), options);
}
if (typeof option == 'string') {
if(option == 'destroy'){
parallax.destroy(this);
}else{
parallax[option]();
}
}
});
}
var old = $.fn.parallax;
$.fn.parallax = plugin;
$.fn.parallax.constructor = parallax;
// parallax no conflict
$.fn.parallax.noconflict = function () {
$.fn.parallax = old;
return this;
};
// parallax data-api
$( function () {
$('[data-parallax="scroll"]').parallax();
});
}(jquery, window, document));