Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / ui / new_ui / ui / javascripts / jquery.scrollintoview.js @ 0467b6cd

History | View | Annotate | Download (6.6 kB)

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.rect.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);