1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | ;(function(factory) {
|
11 | 'use strict';
|
12 | if (typeof define === 'function' && define.amd) {
|
13 |
|
14 | define(['jquery'], factory);
|
15 | } else if (typeof module !== 'undefined' && module.exports) {
|
16 |
|
17 | module.exports = factory(require('jquery'));
|
18 | } else {
|
19 |
|
20 | factory(jQuery);
|
21 | }
|
22 | })(function($) {
|
23 | 'use strict';
|
24 |
|
25 | var $scrollTo = $.scrollTo = function(target, duration, settings) {
|
26 | return $(window).scrollTo(target, duration, settings);
|
27 | };
|
28 |
|
29 | $scrollTo.defaults = {
|
30 | axis:'xy',
|
31 | duration: 0,
|
32 | limit:true
|
33 | };
|
34 |
|
35 | function isWin(elem) {
|
36 | return !elem.nodeName ||
|
37 | $.inArray(elem.nodeName.toLowerCase(), ['iframe','#document','html','body']) !== -1;
|
38 | }
|
39 |
|
40 | $.fn.scrollTo = function(target, duration, settings) {
|
41 | if (typeof duration === 'object') {
|
42 | settings = duration;
|
43 | duration = 0;
|
44 | }
|
45 | if (typeof settings === 'function') {
|
46 | settings = { onAfter:settings };
|
47 | }
|
48 | if (target === 'max') {
|
49 | target = 9e9;
|
50 | }
|
51 |
|
52 | settings = $.extend({}, $scrollTo.defaults, settings);
|
53 |
|
54 | duration = duration || settings.duration;
|
55 |
|
56 | var queue = settings.queue && settings.axis.length > 1;
|
57 | if (queue) {
|
58 |
|
59 | duration /= 2;
|
60 | }
|
61 | settings.offset = both(settings.offset);
|
62 | settings.over = both(settings.over);
|
63 |
|
64 | return this.each(function() {
|
65 |
|
66 | if (target === null) return;
|
67 |
|
68 | var win = isWin(this),
|
69 | elem = win ? this.contentWindow || window : this,
|
70 | $elem = $(elem),
|
71 | targ = target,
|
72 | attr = {},
|
73 | toff;
|
74 |
|
75 | switch (typeof targ) {
|
76 |
|
77 | case 'number':
|
78 | case 'string':
|
79 | if (/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)) {
|
80 | targ = both(targ);
|
81 |
|
82 | break;
|
83 | }
|
84 |
|
85 | targ = win ? $(targ) : $(targ, elem);
|
86 | if (!targ.length) return;
|
87 |
|
88 | case 'object':
|
89 |
|
90 | if (targ.is || targ.style) {
|
91 |
|
92 | toff = (targ = $(targ)).offset();
|
93 | }
|
94 | }
|
95 |
|
96 | var offset = $.isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset;
|
97 |
|
98 | $.each(settings.axis.split(''), function(i, axis) {
|
99 | var Pos = axis === 'x' ? 'Left' : 'Top',
|
100 | pos = Pos.toLowerCase(),
|
101 | key = 'scroll' + Pos,
|
102 | prev = $elem[key](),
|
103 | max = $scrollTo.max(elem, axis);
|
104 |
|
105 | if (toff) {
|
106 | attr[key] = toff[pos] + (win ? 0 : prev - $elem.offset()[pos]);
|
107 |
|
108 |
|
109 | if (settings.margin) {
|
110 | attr[key] -= parseInt(targ.css('margin'+Pos), 10) || 0;
|
111 | attr[key] -= parseInt(targ.css('border'+Pos+'Width'), 10) || 0;
|
112 | }
|
113 |
|
114 | attr[key] += offset[pos] || 0;
|
115 |
|
116 | if (settings.over[pos]) {
|
117 |
|
118 | attr[key] += targ[axis === 'x'?'width':'height']() * settings.over[pos];
|
119 | }
|
120 | } else {
|
121 | var val = targ[pos];
|
122 |
|
123 | attr[key] = val.slice && val.slice(-1) === '%' ?
|
124 | parseFloat(val) / 100 * max
|
125 | : val;
|
126 | }
|
127 |
|
128 |
|
129 | if (settings.limit && /^\d+$/.test(attr[key])) {
|
130 |
|
131 | attr[key] = attr[key] <= 0 ? 0 : Math.min(attr[key], max);
|
132 | }
|
133 |
|
134 |
|
135 | if (!i && settings.axis.length > 1) {
|
136 | if (prev === attr[key]) {
|
137 |
|
138 | attr = {};
|
139 | } else if (queue) {
|
140 |
|
141 | animate(settings.onAfterFirst);
|
142 |
|
143 | attr = {};
|
144 | }
|
145 | }
|
146 | });
|
147 |
|
148 | animate(settings.onAfter);
|
149 |
|
150 | function animate(callback) {
|
151 | var opts = $.extend({}, settings, {
|
152 |
|
153 |
|
154 | queue: true,
|
155 | duration: duration,
|
156 | complete: callback && function() {
|
157 | callback.call(elem, targ, settings);
|
158 | }
|
159 | });
|
160 | $elem.animate(attr, opts);
|
161 | }
|
162 | });
|
163 | };
|
164 |
|
165 |
|
166 |
|
167 | $scrollTo.max = function(elem, axis) {
|
168 | var Dim = axis === 'x' ? 'Width' : 'Height',
|
169 | scroll = 'scroll'+Dim;
|
170 |
|
171 | if (!isWin(elem))
|
172 | return elem[scroll] - $(elem)[Dim.toLowerCase()]();
|
173 |
|
174 | var size = 'client' + Dim,
|
175 | doc = elem.ownerDocument || elem.document,
|
176 | html = doc.documentElement,
|
177 | body = doc.body;
|
178 |
|
179 | return Math.max(html[scroll], body[scroll]) - Math.min(html[size], body[size]);
|
180 | };
|
181 |
|
182 | function both(val) {
|
183 | return $.isFunction(val) || $.isPlainObject(val) ? val : { top:val, left:val };
|
184 | }
|
185 |
|
186 |
|
187 | $.Tween.propHooks.scrollLeft =
|
188 | $.Tween.propHooks.scrollTop = {
|
189 | get: function(t) {
|
190 | return $(t.elem)[t.prop]();
|
191 | },
|
192 | set: function(t) {
|
193 | var curr = this.get(t);
|
194 |
|
195 | if (t.options.interrupt && t._last && t._last !== curr) {
|
196 | return $(t.elem).stop();
|
197 | }
|
198 | var next = Math.round(t.now);
|
199 |
|
200 |
|
201 | if (curr !== next) {
|
202 | $(t.elem)[t.prop](next);
|
203 | t._last = this.get(t);
|
204 | }
|
205 | }
|
206 | };
|
207 |
|
208 |
|
209 | return $scrollTo;
|
210 | });
|