204 lines
7.4 KiB
JavaScript
204 lines
7.4 KiB
JavaScript
;(function ($, window, document, undefined) {
|
|
'use strict';
|
|
|
|
Foundation.libs['magellan-expedition'] = {
|
|
name : 'magellan-expedition',
|
|
|
|
version : '5.5.1',
|
|
|
|
settings : {
|
|
active_class : 'active',
|
|
threshold : 0, // pixels from the top of the expedition for it to become fixes
|
|
destination_threshold : 20, // pixels from the top of destination for it to be considered active
|
|
throttle_delay : 30, // calculation throttling to increase framerate
|
|
fixed_top : 0, // top distance in pixels assigend to the fixed element on scroll
|
|
offset_by_height : true, // whether to offset the destination by the expedition height. Usually you want this to be true, unless your expedition is on the side.
|
|
duration : 700, // animation duration time
|
|
easing : 'swing' // animation easing
|
|
},
|
|
|
|
init : function (scope, method, options) {
|
|
Foundation.inherit(this, 'throttle');
|
|
this.bindings(method, options);
|
|
},
|
|
|
|
events : function () {
|
|
var self = this,
|
|
S = self.S,
|
|
settings = self.settings;
|
|
|
|
// initialize expedition offset
|
|
self.set_expedition_position();
|
|
|
|
S(self.scope)
|
|
.off('.magellan')
|
|
.on('click.fndtn.magellan', '[' + self.add_namespace('data-magellan-arrival') + '] a[href^="#"]', function (e) {
|
|
e.preventDefault();
|
|
var expedition = $(this).closest('[' + self.attr_name() + ']'),
|
|
settings = expedition.data('magellan-expedition-init'),
|
|
hash = this.hash.split('#').join(''),
|
|
target = $('a[name="' + hash + '"]');
|
|
|
|
if (target.length === 0) {
|
|
target = $('#' + hash);
|
|
|
|
}
|
|
|
|
// Account for expedition height if fixed position
|
|
var scroll_top = target.offset().top - settings.destination_threshold + 1;
|
|
if (settings.offset_by_height) {
|
|
scroll_top = scroll_top - expedition.outerHeight();
|
|
}
|
|
|
|
$('html, body').stop().animate({
|
|
'scrollTop' : scroll_top
|
|
}, settings.duration, settings.easing, function () {
|
|
if (history.pushState) {
|
|
history.pushState(null, null, '#' + hash);
|
|
} else {
|
|
location.hash = '#' + hash;
|
|
}
|
|
});
|
|
})
|
|
.on('scroll.fndtn.magellan', self.throttle(this.check_for_arrivals.bind(this), settings.throttle_delay));
|
|
|
|
$(window)
|
|
.on('resize.fndtn.magellan', self.throttle(this.set_expedition_position.bind(this), settings.throttle_delay));
|
|
},
|
|
|
|
check_for_arrivals : function () {
|
|
var self = this;
|
|
self.update_arrivals();
|
|
self.update_expedition_positions();
|
|
},
|
|
|
|
set_expedition_position : function () {
|
|
var self = this;
|
|
$('[' + this.attr_name() + '=fixed]', self.scope).each(function (idx, el) {
|
|
var expedition = $(this),
|
|
settings = expedition.data('magellan-expedition-init'),
|
|
styles = expedition.attr('styles'), // save styles
|
|
top_offset, fixed_top;
|
|
|
|
expedition.attr('style', '');
|
|
top_offset = expedition.offset().top + settings.threshold;
|
|
|
|
//set fixed-top by attribute
|
|
fixed_top = parseInt(expedition.data('magellan-fixed-top'));
|
|
if (!isNaN(fixed_top)) {
|
|
self.settings.fixed_top = fixed_top;
|
|
}
|
|
|
|
expedition.data(self.data_attr('magellan-top-offset'), top_offset);
|
|
expedition.attr('style', styles);
|
|
});
|
|
},
|
|
|
|
update_expedition_positions : function () {
|
|
var self = this,
|
|
window_top_offset = $(window).scrollTop();
|
|
|
|
$('[' + this.attr_name() + '=fixed]', self.scope).each(function () {
|
|
var expedition = $(this),
|
|
settings = expedition.data('magellan-expedition-init'),
|
|
styles = expedition.attr('style'), // save styles
|
|
top_offset = expedition.data('magellan-top-offset');
|
|
|
|
//scroll to the top distance
|
|
if (window_top_offset + self.settings.fixed_top >= top_offset) {
|
|
// Placeholder allows height calculations to be consistent even when
|
|
// appearing to switch between fixed/non-fixed placement
|
|
var placeholder = expedition.prev('[' + self.add_namespace('data-magellan-expedition-clone') + ']');
|
|
if (placeholder.length === 0) {
|
|
placeholder = expedition.clone();
|
|
placeholder.removeAttr(self.attr_name());
|
|
placeholder.attr(self.add_namespace('data-magellan-expedition-clone'), '');
|
|
expedition.before(placeholder);
|
|
}
|
|
expedition.css({position :'fixed', top : settings.fixed_top}).addClass('fixed');
|
|
} else {
|
|
expedition.prev('[' + self.add_namespace('data-magellan-expedition-clone') + ']').remove();
|
|
expedition.attr('style', styles).css('position', '').css('top', '').removeClass('fixed');
|
|
}
|
|
});
|
|
},
|
|
|
|
update_arrivals : function () {
|
|
var self = this,
|
|
window_top_offset = $(window).scrollTop();
|
|
|
|
$('[' + this.attr_name() + ']', self.scope).each(function () {
|
|
var expedition = $(this),
|
|
settings = expedition.data(self.attr_name(true) + '-init'),
|
|
offsets = self.offsets(expedition, window_top_offset),
|
|
arrivals = expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']'),
|
|
active_item = false;
|
|
offsets.each(function (idx, item) {
|
|
if (item.viewport_offset >= item.top_offset) {
|
|
var arrivals = expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']');
|
|
arrivals.not(item.arrival).removeClass(settings.active_class);
|
|
item.arrival.addClass(settings.active_class);
|
|
active_item = true;
|
|
return true;
|
|
}
|
|
});
|
|
|
|
if (!active_item) {
|
|
arrivals.removeClass(settings.active_class);
|
|
}
|
|
});
|
|
},
|
|
|
|
offsets : function (expedition, window_offset) {
|
|
var self = this,
|
|
settings = expedition.data(self.attr_name(true) + '-init'),
|
|
viewport_offset = window_offset;
|
|
|
|
return expedition.find('[' + self.add_namespace('data-magellan-arrival') + ']').map(function (idx, el) {
|
|
var name = $(this).data(self.data_attr('magellan-arrival')),
|
|
dest = $('[' + self.add_namespace('data-magellan-destination') + '=' + name + ']');
|
|
if (dest.length > 0) {
|
|
var top_offset = dest.offset().top - settings.destination_threshold;
|
|
if (settings.offset_by_height) {
|
|
top_offset = top_offset - expedition.outerHeight();
|
|
}
|
|
top_offset = Math.floor(top_offset);
|
|
return {
|
|
destination : dest,
|
|
arrival : $(this),
|
|
top_offset : top_offset,
|
|
viewport_offset : viewport_offset
|
|
}
|
|
}
|
|
}).sort(function (a, b) {
|
|
if (a.top_offset < b.top_offset) {
|
|
return -1;
|
|
}
|
|
if (a.top_offset > b.top_offset) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
});
|
|
},
|
|
|
|
data_attr : function (str) {
|
|
if (this.namespace.length > 0) {
|
|
return this.namespace + '-' + str;
|
|
}
|
|
|
|
return str;
|
|
},
|
|
|
|
off : function () {
|
|
this.S(this.scope).off('.magellan');
|
|
this.S(window).off('.magellan');
|
|
},
|
|
|
|
reflow : function () {
|
|
var self = this;
|
|
// remove placeholder expeditions used for height calculation purposes
|
|
$('[' + self.add_namespace('data-magellan-expedition-clone') + ']', self.scope).remove();
|
|
}
|
|
};
|
|
}(jQuery, window, window.document));
|