PageSourceSearch

https://spell-check.io/js/jquery.scrollintoview.js

js spell-check.io collected 2026-10-03 20:08:51 UTC 6,717 bytes, 208 lines download raw bytes

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.