190 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			190 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | ;(function ($, window, document, undefined) { | ||
|  |   'use strict'; | ||
|  | 
 | ||
|  |   Foundation.libs['magellan-expedition'] = { | ||
|  |     name : 'magellan-expedition', | ||
|  | 
 | ||
|  |     version : '5.4.7', | ||
|  | 
 | ||
|  |     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
 | ||
|  |     }, | ||
|  | 
 | ||
|  |     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; | ||
|  |           scroll_top = scroll_top - expedition.outerHeight(); | ||
|  | 
 | ||
|  |           $('html, body').stop().animate({ | ||
|  |             'scrollTop': scroll_top | ||
|  |           }, 700, 'swing', 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 = Math.floor(dest.offset().top - settings.destination_threshold - expedition.outerHeight()); | ||
|  |           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)); |