Project

General

Profile

Download (7.55 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * jQuery.ScrollTo
3
 *
4
 * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
5
 * http://flesler.blogspot.com Dual licensed under the MIT
6
 * (http://www.opensource.org/licenses/mit-license.php) and GPL
7
 * (http://www.opensource.org/licenses/gpl-license.php) licenses. Date:
8
 * 2/19/2008
9
 *
10
 * @projectDescription Easy element scrolling using jQuery. Tested with jQuery
11
 *                     1.2.1. On FF 2.0.0.11, IE 6, Opera 9.22 and Safari 3
12
 *                     beta. on Windows.
13
 *
14
 * @author Ariel Flesler
15
 * @version 1.3.3
16
 *
17
 * @id jQuery.scrollTo
18
 * @id jQuery.fn.scrollTo
19
 * @param {String,
20
 *          Number, DOMElement, jQuery, Object} target Where to scroll the
21
 *          matched elements. The different options for target are: - A number
22
 *          position (will be applied to all axes). - A string position ('44',
23
 *          '100px', '+=90', etc ) will be applied to all axes - A jQuery/DOM
24
 *          element ( logically, child of the element to scroll ) - A string
25
 *          selector, that will be relative to the element to scroll (
26
 *          'li:eq(2)', etc ) - A hash { top:x, left:y }, x and y can be any
27
 *          kind of number/string like above.
28
 * @param {Number}
29
 *          duration The OVERALL length of the animation, this argument can be
30
 *          the settings object instead.
31
 * @param {Object}
32
 *          settings Hash of settings, optional.
33
 * @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or
34
 *         'yx'.
35
 * @option {Number} duration The OVERALL length of the animation.
36
 * @option {String} easing The easing method for the animation.
37
 * @option {Boolean} margin If true, the margin of the target element will be
38
 *         deducted from the final position.
39
 * @option {Object, Number} offset Add/deduct from the end position. One number
40
 *         for both axes or { top:x, left:y }.
41
 * @option {Object, Number} over Add/deduct the height/width multiplied by
42
 *         'over', can be { top:x, left:y } when using both axes.
43
 * @option {Boolean} queue If true, and both axis are given, the 2nd axis will
44
 *         only be animated after the first one ends.
45
 * @option {Function} onAfter Function to be called after the scrolling ends.
46
 * @option {Function} onAfterFirst If queuing is activated, this function will
47
 *         be called after the first scrolling ends.
48
 * @return {jQuery} Returns the same jQuery object, for chaining.
49
 *
50
 * @example $('div').scrollTo( 340 );
51
 *
52
 * @example $('div').scrollTo( '+=340px', { axis:'y' } );
53
 *
54
 * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing',
55
 *          queue:true, axis:'xy' } );
56
 *
57
 * @example var second_child =
58
 *          document.getElementById('container').firstChild.nextSibling;
59
 *          $('#container').scrollTo( second_child, { duration:500, axis:'x',
60
 *          onAfter:function(){ alert('scrolled!!'); }});
61
 * 
62
 * @example $('div').scrollTo( { top: 300, left:'+=200' }, { offset:-20 } );
63
 *
64
 * Notes: - jQuery.scrollTo will make the whole window scroll, it accepts the
65
 * same arguments as jQuery.fn.scrollTo. - If you are interested in animated
66
 * anchor navigation, check http://jquery.com/plugins/project/LocalScroll. - The
67
 * options margin, offset and over are ignored, if the target is not a jQuery
68
 * object or a DOM element. - The option 'queue' won't be taken into account, if
69
 * only 1 axis is given.
70
 */
71

    
72
(function($) {
73

    
74
  var $scrollTo = $.scrollTo = function(target, duration, settings) {
75
    $scrollTo.window().scrollTo(target, duration, settings);
76
  };
77

    
78
  $scrollTo.defaults = {
79
    axis : 'y',
80
    duration : 1
81
  };
82

    
83
  // Returns the element that needs to be animated to scroll the window.
84
  $scrollTo.window = function() {
85
    return $($.browser.safari ? 'body' : 'html');
86
  };
87

    
88
  $.fn.scrollTo = function(target, duration, settings) {
89
    if (typeof duration == 'object') {
90
      settings = duration;
91
      duration = 0;
92
    }
93
    settings = $.extend({}, $scrollTo.defaults, settings);
94

    
95
    // Speed is still recognized for backwards compatibility.
96
    duration = duration || settings.speed || settings.duration;
97

    
98
    // Make sure the settings are given right.
99
    settings.queue = settings.queue && settings.axis.length > 1;
100

    
101
    if (settings.queue)
102
      // Let's keep the overall speed, the same.
103
      duration /= 2;
104
    settings.offset = both(settings.offset);
105
    settings.over = both(settings.over);
106

    
107
    return this.each(function() {
108
          var elem = this, $elem = $(elem), t = target, toff, attr = {}, win = $elem
109
              .is('html,body');
110
          switch (typeof t) {
111
            // Will pass the regex.
112
            case 'number':
113
            case 'string':
114
              if (/^([+-]=)?\d+(px)?$/.test(t)) {
115
                t = both(t);
116
                // We are done,
117
                break;
118
              }
119
              // Relative selector, no break!
120
              t = $(t, this);
121
            case 'object':
122
           // DOM/jQuery
123
              if (t.is || t.style)
124
                // Get the real position of the target.
125
                toff = (t = $(t)).offset();
126
          }
127
          $.each(
128
                  settings.axis.split(''),
129
                  function(i, axis) {
130
                    var Pos = axis == 'x' ? 'Left' : 'Top', pos = Pos
131
                        .toLowerCase(), key = 'scroll' + Pos, act = elem[key], Dim = axis == 'x' ? 'Width'
132
                        : 'Height', dim = Dim.toLowerCase();
133
                    // jQuery/DOM
134
                    if (toff) {
135
                      attr[key] = toff[pos]
136
                          + (win ? 0 : act - $elem.offset()[pos]);
137
                      // If it's a dom element, reduce the margin.
138
                      if (settings.margin) {
139
                        attr[key] -= parseInt(t.css('margin' + Pos)) || 0;
140
                        attr[key] -= parseInt(t.css('border' + Pos + 'Width')) || 0;
141
                      }
142
                      // Add/deduct the offset.
143
                      attr[key] += settings.offset[pos] || 0;
144

    
145
                      if (settings.over[pos])// Scroll to a fraction of its
146
                        // width/height.
147
                        attr[key] += t[dim]() * settings.over[pos];
148
                    } else
149
                      // Remove the unnecessary 'px'.
150
                      attr[key] = t[pos];
151
                    
152
                    // Number or 'number'.
153
                    if (/^\d+$/.test(attr[key]))
154
                      // Check the limits.
155
                      attr[key] = attr[key] <= 0 ? 0 : Math.min(attr[key],
156
                          max(Dim));
157
                    // Queueing each axis is required.
158
                    if (!i && settings.queue) {
159
                      // Don't waste time animating, if there's no need.
160
                      if (act != attr[key])
161
                        // Intermediate animation.
162
                        animate(settings.onAfterFirst);
163
                      // Don't animate this axis again in the next iteration.
164
                      delete attr[key];
165
                    }
166
                  });
167
          animate(settings.onAfter);
168

    
169
          function animate(callback) {
170
            $elem.animate(attr, duration, settings.easing, callback
171
                && function() {
172
                  callback.call(this, target);
173
                });
174
          }
175
          ;
176
          function max(Dim) {
177
            var el = win ? $.browser.opera ? document.body
178
                : document.documentElement : elem;
179
            return el['scroll' + Dim] - el['client' + Dim];
180
          }
181
          ;
182
        });
183
  };
184

    
185
  function both(val) {
186
    return typeof val == 'object' ? val : {
187
      top : val,
188
      left : val
189
    };
190
  }
191
  ;
192

    
193
})(jQuery);
(5-5/5)