1/*! 2 * jQuery scrollintoview() plugin and :scrollable selector filter 3 * 4 * Version 1.8 (14 Jul 2011) 5 * Requires jQuery 1.4 or newer 6 * 7 * Copyright (c) 2011 Robert Koritnik 8 * Licensed under the terms of the MIT license 9 * http://www.opensource.org/licenses/mit-license.php 10 */ 11 12(function ($) { 13 var converter = { 14 vertical: { x: false, y: true }, 15 horizontal: { x: true, y: false }, 16 both: { x: true, y: true }, 17 x: { x: true, y: false }, 18 y: { x: false, y: true } 19 }; 20 21 var settings = { 22 duration: "fast", 23 direction: "both" 24 }; 25 26 var rootrx = /^(?:html)$/i; 27 28 // gets border dimensions 29 var borders = function (domElement, styles) { 30 styles = styles || (document.defaultView && document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(domElement, null) : domElement.currentStyle); 31 var px = document.defaultView && document.defaultView.getComputedStyle ? true : false; 32 var b = { 33 top: (parseFloat(px ? styles.borderTopWidth : $.css(domElement, "borderTopWidth")) || 0), 34 left: (parseFloat(px ? styles.borderLeftWidth : $.css(domElement, "borderLeftWidth")) || 0), 35 bottom: (parseFloat(px ? styles.borderBottomWidth : $.css(domElement, "borderBottomWidth")) || 0), 36 right: (parseFloat(px ? styles.borderRightWidth : $.css(domElement, "borderRightWidth")) || 0) 37 }; 38 return { 39 top: b.top, 40 left: b.left, 41 bottom: b.bottom, 42 right: b.right, 43 vertical: b.top + b.bottom, 44 horizontal: b.left + b.right 45 }; 46 }; 47 48 var dimensions = function ($element) { 49 var win = $(window); 50 var isRoot = rootrx.test($element[0].nodeName); 51 return { 52 border: isRoot ? { top: 0, left: 0, bottom: 0, right: 0} : borders($element[0]), 53 scroll: { 54 top: (isRoot ? win : $element).scrollTop(), 55 left: (isRoot ? win : $element).scrollLeft() 56 }, 57 scrollbar: { 58 right: isRoot ? 0 : $element.innerWidth() - $element[0].clientWidth, 59 bottom: isRoot ? 0 : $element.innerHeight() - $element[0].clientHeight 60 }, 61 rect: (function () { 62 var r = $element[0].getBoundingClientRect(); 63 return { 64 top: isRoot ? 0 : r.top, 65 left: isRoot ? 0 : r.left, 66 bottom: isRoot ? $element[0].clientHeight : r.bottom, 67 right: isRoot ? $element[0].clientWidth : r.right 68 }; 69 })() 70 }; 71 }; 72 73 $.fn.extend({ 74 scrollintoview: function (options) { 75 /// <summary>Scrolls the first element in the set into view by scrolling its closest scrollable parent.</summary> 76 /// <param name="options" type="Object">Additional options that can configure scrolling: 77 /// duration (default: "fast") - jQuery animation speed (can be a duration string or number of milliseconds) 78 /// direction (default: "both") - select possible scrollings ("vertical" or "y", "horizontal" or "x", "both") 79 /// complete (default: none) - a function to call when scrolling completes (called in context of the DOM element being scrolled) 80 /// </param> 81 /// <return type="jQuery">Returns the same jQuery set that this function was run on.</return> 82 83 options = $.extend({}, settings, options); 84 options.direction = converter[typeof (options.direction) === "string" && options.direction.toLowerCase()] || converter.both; 85 86 var dirStr = ""; 87 if (options.direction.x === true) dirStr = "horizontal"; 88 if (options.direction.y === true) dirStr = dirStr ? "both" : "vertical"; 89 90 var el = this.eq(0); 91 var scroller = el.closest(":scrollable(" + dirStr + ")"); 92 93 // check if there's anything to scroll in the first place 94 if (scroller.length > 0) 95 { 96 scroller = scroller.eq(0); 97 98 var dim = { 99 e: dimensions(el), 100 s: dimensions(scroller) 101 }; 102 103 var rel = { 104 top: dim.e.rect.top - (dim.s.rect.top + dim.s.border.top), 105 bottom: dim.s.rect.bottom - dim.s.border.bottom - dim.s.scrollbar.bottom - dim.e.re
105ct.bottom, 106 left: dim.e.rect.left - (dim.s.rect.left + dim.s.border.left), 107 right: dim.s.rect.right - dim.s.border.right - dim.s.scrollbar.right - dim.e.rect.right 108 }; 109 110 var animOptions = {}; 111 112 // vertical scroll 113 if (options.direction.y === true) 114 { 115 if (rel.top < 0) 116 { 117 animOptions.scrollTop = dim.s.scroll.top + rel.top; 118 } 119 else if (rel.top > 0 && rel.bottom < 0) 120 { 121 animOptions.scrollTop = dim.s.scroll.top + Math.min(rel.top, -rel.bottom); 122 } 123 } 124 125 // horizontal scroll 126 if (options.direction.x === true) 127 { 128 if (rel.left < 0) 129 { 130 animOptions.scrollLeft = dim.s.scroll.left + rel.left; 131 } 132 else if (rel.left > 0 && rel.right < 0) 133 { 134 animOptions.scrollLeft = dim.s.scroll.left + Math.min(rel.left, -rel.right); 135 } 136 } 137 138 // scroll if needed 139 if (!$.isEmptyObject(animOptions)) 140 { 141 if (rootrx.test(scroller[0].nodeName)) 142 { 143 scroller = $("html,body"); 144 } 145 scroller 146 .animate(animOptions, options.duration) 147 .eq(0) // we want function to be called just once (ref. "html,body") 148 .queue(function (next) { 149 $.isFunction(options.complete) && options.complete.call(scroller[0]); 150 next(); 151 }); 152 } 153 else 154 { 155 // when there's nothing to scroll, just call the "complete" function 156 $.isFunction(options.complete) && options.complete.call(scroller[0]); 157 } 158 } 159 160 // return set back 161 return this; 162 } 163 }); 164 165 var scrollValue = { 166 auto: true, 167 scroll: true, 168 visible: false, 169 hidden: false 170 }; 171 172 $.extend($.expr[":"], { 173 scrollable: function (element, index, meta, stack) { 174 var direction = converter[typeof (meta[3]) === "string" && meta[3].toLowerCase()] || converter.both; 175 var styles = (document.defaultView && document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(element, null) : element.currentStyle); 176 var overflow = { 177 x: scrollValue[styles.overflowX.toLowerCase()] || false, 178 y: scrollValue[styles.overflowY.toLowerCase()] || false, 179 isRoot: rootrx.test(element.nodeName) 180 }; 181 182 // check if completely unscrollable (exclude HTML element because it's special) 183 if (!overflow.x && !overflow.y && !overflow.isRoot) 184 { 185 return false; 186 } 187 188 var size = { 189 height: { 190 scroll: element.scrollHeight, 191 client: element.clientHeight 192 }, 193 width: { 194 scroll: element.scrollWidth, 195 client: element.clientWidth 196 }, 197 // check overflow.x/y because iPad (and possibly other tablets) don't dislay scrollbars 198 scrollableX: function () { 199 return (overflow.x || overflow.isRoot) && this.width.scroll > this.width.client; 200 }, 201 scrollableY: function () { 202 return (overflow.y || overflow.isRoot) && this.height.scroll > this.height.client; 203 } 204 }; 205 return direction.y && size.scrollableY() || direction.x && size.scrollableX(); 206 } 207 }); 208})(jQuery);
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.