1/* 2 * Slinky.js v0.1.3 3 * 4 * Copyright (c) 2015 Sorin Iclanzan 5 * Licensed under the MIT license. 6 */ 7 8(function ($, window, undefined) { 9 'use strict'; 10 11 var pluginName = 'slinky'; 12 13 var slinky = $.fn[pluginName] = function (options) { 14 options = $.extend({}, slinky.options, options); 15 16 return this.each(function () { 17 var $element = $(this); 18 // Prevent multiple instantiations on the same element. 19 if ($element.data(pluginName)) { 20 return; 21 } 22 $element.data(pluginName, true); 23 24 25 var $scroller = $element.children().first(); 26 var $sections, headers, scrollerHeight, timer; 27 28 function refresh() { 29 headers.forEach(function (header) { 30 var position = ''; 31 var top = header.$parent.position().top; 32 33 if (top <= header.top) { 34 position = 'top'; 35 } 36 else if (top + header.height >= scrollerHeight - header.bottom) { 37 position = 'bottom'; 38 } 39 40 if (position) { 41 // Donât do anything if the header is already positioned properly. 42 if (header.position != position) { 43 header.$parent.css('paddingTop', header.height); 44 header.$ 45 .css('position', 'absolute') 46 .css(position, header[position]) 47 .css(position == 'top' ? 'bottom' : 'top', ''); 48 header.position = position; 49 } 50 } 51 else { 52 header.$parent.css('paddingTop', ''); 53 header.$.css('position', ''); 54 header.position = ''; 55 } 56 }); 57 } 58 59 function init() { 60 scrollerHeight = $scroller.outerHeight(); 61 headers = []; 62 $sections = $scroller.children(); 63 $sections.each(function () { 64 var $section = $(this); 65 var $header = $section.children().first(); 66 headers.push({ 67 $: $header, 68 $parent: $section, 69 height: $header.outerHeight(), 70 position: '' // can be 'top' or 'bottom' 71 }); 72 }); 73 74 // Pre-calculate the offsets that the headers would have 75 // from the top or bottom of the scroller. 76 headers.forEach(function (header, i) { 77 header.top = i > 0 ? (headers[i - 1].top + headers[i - 1].height) : 0; 78 79 i = headers.length - i - 1; 80 headers[i].bottom = i < headers.length - 1 ? (headers[i + 1].bottom + headers[i + 1].height) : 0; 81 }); 82 83 refresh(); 84 } 85 86 function enablePointerEvents() { 87 $sections.css('pointer-events', ''); 88 timer = undefined; 89 } 90 91 init(); 92 93 $scroller 94 95 .on('wheel.' + pluginName, function () { 96 if (timer) { 97 clearTimeout(timer); 98 } 99 else { 100 $sections.css('pointer-events', 'none'); 101 } 102 timer = setTimeout(enablePointerEvents, 100); 103 }) 104 105 .on('scroll.' + pluginName, refresh); 106 107 // On window resize we need to recalculate everything in case relative 108 // units where used anywhere. 109 $(window).on('resize.' + pluginName, init); 110 111 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; 112 if (MutationObserver) { 113 var observer = new MutationObserver(init); 114 observer.observe($scroller[0], { 115 childList: true, characterData: true, subtree: true 116 }); 117 } 118 119 $element.on('remove.' + pluginName, function () { 120 $scroller.off('wheel.' + pluginName + ' scroll.' + pluginName); 121 $(window).off('resize.' + pluginName, init); 122 if (observer) { 123 observer.disconnect(); 124 } 125 }); 126 }); 127 }; 128}(jQuery, window));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.