1 /*global define:false require:false */
2 (function (name, context, definition) {
3 if (typeof module != 'undefined' && module.exports) module.exports = definition();
4 else if (typeof define == 'function' && define.amd) define(definition);
5 else context[name] = definition();
6 })('jquery-scrollto', this, function(){
8 var jQuery, $, ScrollTo;
9 jQuery = $ = window.jQuery || require('jquery');
11 // Fix scrolling animations on html/body on safari
12 $.propHooks.scrollTop = $.propHooks.scrollLeft = {
13 get: function(elem,prop) {
15 if ( elem.tagName === 'HTML' || elem.tagName === 'BODY' ) {
16 if ( prop === 'scrollLeft' ) {
17 result = window.scrollX;
18 } else if ( prop === 'scrollTop' ) {
19 result = window.scrollY;
22 if ( result == null ) {
28 $.Tween.propHooks.scrollTop = $.Tween.propHooks.scrollLeft = {
29 get: function(tween) {
30 return $.propHooks.scrollTop.get(tween.elem, tween.prop);
32 set: function(tween) {
34 if ( tween.elem.tagName === 'HTML' || tween.elem.tagName === 'BODY' ) {
36 tween.options.bodyScrollLeft = (tween.options.bodyScrollLeft || window.scrollX);
37 tween.options.bodyScrollTop = (tween.options.bodyScrollTop || window.scrollY);
40 if ( tween.prop === 'scrollLeft' ) {
41 tween.options.bodyScrollLeft = Math.round(tween.now);
43 else if ( tween.prop === 'scrollTop' ) {
44 tween.options.bodyScrollTop = Math.round(tween.now);
48 window.scrollTo(tween.options.bodyScrollLeft, tween.options.bodyScrollTop);
51 else if ( tween.elem.nodeType && tween.elem.parentNode ) {
52 tween.elem[ tween.prop ] = tween.now;
70 configure: function(options){
71 // Apply Options to Config
72 $.extend(ScrollTo.config, options||{});
78 // Perform the Scroll Animation for the Collections
79 // We use $inline here, so we can determine the actual offset start for each overflow:scroll item
80 // Each collection is for each overflow:scroll item
81 scroll: function(collections, config){
83 var collection, $container, container, $target, $inline, position, containerTagName,
84 containerScrollTop, containerScrollLeft,
85 containerScrollTopEnd, containerScrollLeftEnd,
86 startOffsetTop, targetOffsetTop, targetOffsetTopAdjusted,
87 startOffsetLeft, targetOffsetLeft, targetOffsetLeftAdjusted,
91 // Determine the Scroll
92 collection = collections.pop();
93 $container = collection.$container;
94 $target = collection.$target;
95 containerTagName = $container.prop('tagName');
97 // Prepare the Inline Element of the Container
98 $inline = $('<span/>').css({
99 'position': 'absolute',
103 position = $container.css('position');
105 // Insert the Inline Element of the Container
106 $container.css({position:'relative'});
107 $inline.appendTo($container);
109 // Determine the top offset
110 startOffsetTop = $inline.offset().top;
111 targetOffsetTop = $target.offset().top;
112 targetOffsetTopAdjusted = targetOffsetTop - startOffsetTop - parseInt(config.offsetTop,10);
114 // Determine the left offset
115 startOffsetLeft = $inline.offset().left;
116 targetOffsetLeft = $target.offset().left;
117 targetOffsetLeftAdjusted = targetOffsetLeft - startOffsetLeft - parseInt(config.offsetLeft,10);
119 // Determine current scroll positions
120 containerScrollTop = $container.prop('scrollTop');
121 containerScrollLeft = $container.prop('scrollLeft');
123 // Reset the Inline Element of the Container
125 $container.css({position:position});
127 // Prepare the scroll options
130 // Prepare the callback
131 callback = function(event){
133 if ( collections.length === 0 ) {
135 if ( typeof config.callback === 'function' ) {
141 ScrollTo.scroll(collections,config);
147 // Handle if we only want to scroll if we are outside the viewport
148 if ( config.onlyIfOutside ) {
149 // Determine current scroll positions
150 containerScrollTopEnd = containerScrollTop + $container.height();
151 containerScrollLeftEnd = containerScrollLeft + $container.width();
153 // Check if we are in the range of the visible area of the container
154 if ( containerScrollTop < targetOffsetTopAdjusted && targetOffsetTopAdjusted < containerScrollTopEnd ) {
155 targetOffsetTopAdjusted = containerScrollTop;
157 if ( containerScrollLeft < targetOffsetLeftAdjusted && targetOffsetLeftAdjusted < containerScrollLeftEnd ) {
158 targetOffsetLeftAdjusted = containerScrollLeft;
162 // Determine the scroll options
163 if ( targetOffsetTopAdjusted !== containerScrollTop ) {
164 scrollOptions.scrollTop = targetOffsetTopAdjusted;
166 if ( targetOffsetLeftAdjusted !== containerScrollLeft ) {
167 scrollOptions.scrollLeft = targetOffsetLeftAdjusted;
170 // Check to see if the scroll is necessary
171 if ( $container.prop('scrollHeight') === $container.width() ) {
172 delete scrollOptions.scrollTop;
174 if ( $container.prop('scrollWidth') === $container.width() ) {
175 delete scrollOptions.scrollLeft;
178 // Perform the scroll
179 if ( scrollOptions.scrollTop != null || scrollOptions.scrollLeft != null ) {
180 $container.animate(scrollOptions, {
181 duration: config.duration,
182 easing: config.easing,
194 // ScrollTo the Element using the Options
195 fn: function(options){
197 var collections, config, $container, container;
201 var $target = $(this);
202 if ( $target.length === 0 ) {
208 config = $.extend({},ScrollTo.config,options);
211 $container = $target.parent();
212 container = $container.get(0);
214 // Cycle through the containers
215 while ( ($container.length === 1) && (container !== document.body) && (container !== document) ) {
216 // Check Container for scroll differences
217 var containerScrollTop, containerScrollLeft;
218 containerScrollTop = $container.css('overflow-y') !== 'visible' && container.scrollHeight !== container.clientHeight;
219 containerScrollLeft = $container.css('overflow-x') !== 'visible' && container.scrollWidth !== container.clientWidth;
220 if ( containerScrollTop || containerScrollLeft ) {
221 // Push the Collection
223 '$container': $container,
227 $target = $container;
229 // Update the Container
230 $container = $container.parent();
231 container = $container.get(0);
234 // Add the final collection
236 '$container': $('html'),
237 // document.body doesn't work in firefox, html works for all
238 // internet explorer starts at the beggining
243 if ( config.durationMode === 'all' ) {
244 config.duration /= collections.length;
248 ScrollTo.scroll(collections,config);
255 // Apply our extensions to jQuery
256 $.ScrollTo = $.ScrollTo || ScrollTo;
257 $.fn.ScrollTo = $.fn.ScrollTo || ScrollTo.fn;