Mercurial > web-octave
diff js/foundation/foundation.magellan.js @ 0:7abe02bf29ec
initial commit
author | Alex Krolick <whokilledtheelectricmonk@gmail.com> |
---|---|
date | Sat, 07 Nov 2015 18:04:42 -0800 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/foundation/foundation.magellan.js Sat Nov 07 18:04:42 2015 -0800 @@ -0,0 +1,214 @@ +;(function ($, window, document, undefined) { + 'use strict'; + + Foundation.libs['magellan-expedition'] = { + name : 'magellan-expedition', + + version : '5.5.3', + + 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) { + var sameHost = ((this.hostname === location.hostname) || !this.hostname), + samePath = self.filterPathname(location.pathname) === self.filterPathname(this.pathname), + testHash = this.hash.replace(/(:|\.|\/)/g, '\\$1'), + anchor = this; + + if (sameHost && samePath && testHash) { + 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, anchor.pathname + anchor.search + '#' + hash); + } else { + location.hash = anchor.pathname + anchor.search + '#' + hash; + } + }); + } + }) + .on('scroll.fndtn.magellan', self.throttle(this.check_for_arrivals.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'); + }, + + filterPathname : function (pathname) { + pathname = pathname || ''; + return pathname + .replace(/^\//,'') + .replace(/(?:index|default).[a-zA-Z]{3,4}$/,'') + .replace(/\/$/,''); + }, + + 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));