https://www.mediawiki.org/wiki/Special:Code/MediaWiki/114577

Revision: 114577
Author:   raindrift
Date:     2012-03-28 21:37:23 +0000 (Wed, 28 Mar 2012)
Log Message:
-----------
adding waypoints jquery extension for working with window scroll position

Added Paths:
-----------
    trunk/extensions/PageTriage/modules/external/jquery.waypoints.js

Added: trunk/extensions/PageTriage/modules/external/jquery.waypoints.js
===================================================================
--- trunk/extensions/PageTriage/modules/external/jquery.waypoints.js            
                (rev 0)
+++ trunk/extensions/PageTriage/modules/external/jquery.waypoints.js    
2012-03-28 21:37:23 UTC (rev 114577)
@@ -0,0 +1,666 @@
+/*!
+jQuery Waypoints - v1.1.5
+Copyright (c) 2011-2012 Caleb Troughton
+Dual licensed under the MIT license and GPL license.
+https://github.com/imakewebthings/jquery-waypoints/blob/master/MIT-license.txt
+https://github.com/imakewebthings/jquery-waypoints/blob/master/GPL-license.txt
+*/
+
+/*
+Waypoints is a small jQuery plugin that makes it easy to execute a function
+whenever you scroll to an element.
+
+GitHub Repository: https://github.com/imakewebthings/jquery-waypoints
+Documentation and Examples: http://imakewebthings.github.com/jquery-waypoints
+
+Changelog:
+  v1.1.5
+       - Make plugin compatible with Browserify/RequireJS. (Thanks @cjroebuck)
+  v1.1.4
+       - Add handler option to give alternate binding method. (Issue #34)
+       v1.1.3
+               - Fix cases where waypoints are added post-load and should be 
triggered
+                 immediately. (Issue #28)
+       v1.1.2
+               - Fixed error thrown by waypoints with triggerOnce option that 
were
+                       triggered via resize refresh.
+       v1.1.1
+               - Fixed bug in initialization where all offsets were being 
calculated
+                 as if set to 0 initially, causing unwarranted triggers during 
the
+                 subsequent refresh.
+               - Added onlyOnScroll, an option for individual waypoints that 
disables
+                 triggers due to an offset refresh that crosses the current 
scroll
+                 point. (All credit to @knuton on this one.)
+       v1.1
+               - Moved the continuous option out of global settings and into 
the options
+                 object for individual waypoints.
+               - Added the context option, which allows for using waypoints 
within any
+                 scrollable element, not just the window.
+       v1.0.2
+               - Moved scroll and resize handler bindings out of load.  Should 
play nicer
+                 with async loaders like Head JS and LABjs.
+               - Fixed a 1px off error when using certain % offsets.
+               - Added unit tests.
+       v1.0.1
+               - Added $.waypoints('viewportHeight').
+               - Fixed iOS bug (using the new viewportHeight method).
+               - Added offset function alias: 'bottom-in-view'.
+       v1.0
+               - Initial release.
+       
+Support:
+       - jQuery versions 1.4.3+
+       - IE6+, FF3+, Chrome 6+, Safari 4+, Opera 11
+       - Other versions and browsers may work, these are just the ones I've 
looked at.
+*/
+
+(function($, wp, wps, window, undefined){
+       '$:nomunge';
+       
+       var $w = $(window),
+       
+       // Keeping common strings as variables = better minification
+       eventName = 'waypoint.reached',
+       
+       /*
+       For the waypoint and direction passed in, trigger the waypoint.reached
+       event and deal with the triggerOnce option.
+       */
+       triggerWaypoint = function(way, dir) {
+               way.element.trigger(eventName, dir);
+               if (way.options.triggerOnce) {
+                       way.element[wp]('destroy');
+               }
+       },
+       
+       /*
+       Given a jQuery element and Context, returns the index of that element 
in the waypoints
+       array.  Returns the index, or -1 if the element is not a waypoint.
+       */
+       waypointIndex = function(el, context) {
+               var i = context.waypoints.length - 1;
+               while (i >= 0 && context.waypoints[i].element[0] !== el[0]) {
+                       i -= 1;
+               }
+               return i;
+       },
+       
+       // Private list of all elements used as scrolling contexts for 
waypoints.
+       contexts = [],
+       
+       /*
+       Context Class - represents a scrolling context.  Properties include:
+               element: jQuery object containing a single HTML element.
+               waypoints: Array of waypoints operating under this scroll 
context.
+               oldScroll: Keeps the previous scroll position to determine 
scroll direction.
+               didScroll: Flag used in scrolling the context's scroll event.
+               didResize: Flag used in scrolling the context's resize event.
+               doScroll: Function that checks for crossed waypoints. Called 
from throttler.
+       */
+       Context = function(context) {
+               $.extend(this, {
+                       element: $(context),
+                       oldScroll: 0,
+                       
+                       /*
+                       List of all elements that have been registered as 
waypoints.
+                       Each object in the array contains:
+                               element: jQuery object containing a single HTML 
element.
+                               offset: The window scroll offset, in px, that 
triggers the waypoint event.
+                               options: Options object that was passed to the 
waypoint fn function.
+                       */
+                       'waypoints': [],
+                       
+                       didScroll: false,
+                       didResize: false,
+       
+                       doScroll: $.proxy(function() {
+                               var newScroll = this.element.scrollTop(),
+                               
+                               // Are we scrolling up or down? Used for 
direction argument in callback.
+                               isDown = newScroll > this.oldScroll,
+                               that = this,
+
+                               // Get a list of all waypoints that were 
crossed since last scroll move.
+                               pointsHit = $.grep(this.waypoints, function(el, 
i) {
+                                       return isDown ?
+                                               (el.offset > that.oldScroll && 
el.offset <= newScroll) :
+                                               (el.offset <= that.oldScroll && 
el.offset > newScroll);
+                               }),
+                               len = pointsHit.length;
+                               
+                               // iOS adjustment
+                               if (!this.oldScroll || !newScroll) {
+                                       $[wps]('refresh');
+                               }
+
+                               // Done with scroll comparisons, store new 
scroll before ejection
+                               this.oldScroll = newScroll;
+
+                               // No waypoints crossed? Eject.
+                               if (!len) return;
+
+                               // If several waypoints triggered, need to do 
so in reverse order going up
+                               if (!isDown) pointsHit.reverse();
+
+                               /*
+                               One scroll move may cross several waypoints.  
If the waypoint's continuous
+                               option is true it should fire even if it isn't 
the last waypoint.  If false,
+                               it will only fire if it's the last one.
+                               */
+                               $.each(pointsHit, function(i, point) {
+                                       if (point.options.continuous || i === 
len - 1) {
+                                               triggerWaypoint(point, [isDown 
? 'down' : 'up']);
+                                       }
+                               });
+                       }, this)
+               });
+               
+               // Setup scroll and resize handlers.  Throttled at the 
settings-defined rate limits.
+               $(context).scroll($.proxy(function() {
+                       if (!this.didScroll) {
+                               this.didScroll = true;
+                               window.setTimeout($.proxy(function() {
+                                       this.doScroll();
+                                       this.didScroll = false;
+                               }, this), $[wps].settings.scrollThrottle);
+                       }
+               }, this)).resize($.proxy(function() {
+                       if (!this.didResize) {
+                               this.didResize = true;
+                               window.setTimeout($.proxy(function() {
+                                       $[wps]('refresh');
+                                       this.didResize = false;
+                               }, this), $[wps].settings.resizeThrottle);
+                       }
+               }, this));
+               
+               $w.load($.proxy(function() {
+                       /*
+                       Fire a scroll check, should the page be loaded at a 
non-zero scroll value,
+                       as with a fragment id link or a page refresh.
+                       */
+                       this.doScroll();
+               }, this));
+       },
+       
+       /* Returns a Context object from the contexts array, given the raw HTML 
element
+       for that context. */
+       getContextByElement = function(element) {
+               var found = null;
+               
+               $.each(contexts, function(i, c) {
+                       if (c.element[0] === element) {
+                               found = c;
+                               return false;
+                       }
+               });
+               
+               return found;
+       },
+       
+       // Methods exposed to the effin' object 
+       methods = {
+               /*
+               jQuery.fn.waypoint([handler], [options])
+               
+               handler
+                       function, optional
+                       A callback function called when the user scrolls past 
the element.
+                       The function signature is function(event, direction) 
where event is
+                       a standard jQuery Event Object and direction is a 
string, either 'down'
+                       or 'up' indicating which direction the user is 
scrolling.
+                       
+               options
+                       object, optional
+                       A map of options to apply to this set of waypoints, 
including where on
+                       the browser window the waypoint is triggered. For a 
full list of
+                       options and their defaults, see $.fn.waypoint.defaults.
+                       
+               This is how you register an element as a waypoint. When the 
user scrolls past
+               that element it triggers waypoint.reached, a custom event. 
Since the
+               parameters for creating a waypoint are optional, we have a few 
different
+               possible signatures. Let’s look at each of them.
+
+               someElements.waypoint();
+                       
+               Calling .waypoint with no parameters will register the elements 
as waypoints
+               using the default options. The elements will fire the 
waypoint.reached event,
+               but calling it in this way does not bind any handler to the 
event. You can
+               bind to the event yourself, as with any other event, like so:
+
+               someElements.bind('waypoint.reached', function(event, 
direction) {
+                  // make it rain
+               });
+                       
+               You will usually want to create a waypoint and immediately bind 
a function to
+               waypoint.reached, and can do so by passing a handler as the 
first argument to
+               .waypoint:
+
+               someElements.waypoint(function(event, direction) {
+                  if (direction === 'down') {
+                     // do this on the way down
+                  }
+                  else {
+                     // do this on the way back up through the waypoint
+                  }
+               });
+                       
+               This will still use the default options, which will trigger the 
waypoint when
+               the top of the element hits the top of the window. We can pass 
.waypoint an
+               options object to customize things:
+
+               someElements.waypoint(function(event, direction) {
+                  // do something amazing
+               }, {
+                  offset: '50%'  // middle of the page
+               });
+                       
+               You can also pass just an options object.
+
+               someElements.waypoint({
+                  offset: 100  // 100px from the top
+               });
+                       
+               This behaves like .waypoint(), in that it registers the 
elements as waypoints
+               but binds no event handlers.
+
+               Calling .waypoint on an existing waypoint will extend the 
previous options.
+               If the call includes a handler, it will be bound to 
waypoint.reached without
+               unbinding any other handlers.
+               */
+               init: function(f, options) {
+                       // Register each element as a waypoint, add to array.
+                       this.each(function() {
+                               var cElement = $.fn[wp].defaults.context,
+                               context,
+                               $this = $(this);
+
+                               // Default window context or a specific element?
+                               if (options && options.context) {
+                                       cElement = options.context;
+                               }
+
+                               // Find the closest element that matches the 
context
+                               if (!$.isWindow(cElement)) {
+                                       cElement = $this.closest(cElement)[0];
+                               }
+                               context = getContextByElement(cElement);
+
+                               // Not a context yet? Create and push.
+                               if (!context) {
+                                       context = new Context(cElement);
+                                       contexts.push(context);
+                               }
+                               
+                               // Extend default and preexisting options
+                               var ndx = waypointIndex($this, context),
+                               base = ndx < 0 ? $.fn[wp].defaults : 
context.waypoints[ndx].options,
+                               opts = $.extend({}, base, options);
+                               
+                               // Offset aliases
+                               opts.offset = opts.offset === "bottom-in-view" ?
+                                       function() {
+                                               var cHeight = 
$.isWindow(cElement) ? $[wps]('viewportHeight')
+                                                       : $(cElement).height();
+                                               return cHeight - 
$(this).outerHeight();
+                                       } : opts.offset;
+
+                               // Update, or create new waypoint
+                               if (ndx < 0) {
+                                       context.waypoints.push({
+                                               'element': $this,
+                                               'offset': null,
+                                               'options': opts
+                                       });
+                               }
+                               else {
+                                       context.waypoints[ndx].options = opts;
+                               }
+                               
+                               // Bind the function if it was passed in.
+                               if (f) {
+                                       $this.bind(eventName, f);
+                               }
+                               // Bind the function in the handler option if 
it exists.
+                               if (options && options.handler) {
+                                       $this.bind(eventName, options.handler);
+                               }
+                       });
+                       
+                       // Need to re-sort+refresh the waypoints array after 
new elements are added.
+                       $[wps]('refresh');
+                       
+                       return this;
+               },
+               
+               
+               /*
+               jQuery.fn.waypoint('remove')
+               
+               Passing the string 'remove' to .waypoint unregisters the 
elements as waypoints
+               and wipes any custom options, but leaves the waypoint.reached 
events bound.
+               Calling .waypoint again in the future would reregister the 
waypoint and the old
+               handlers would continue to work.
+               */
+               remove: function() {
+                       return this.each(function(i, el) {
+                               var $el = $(el);
+                               
+                               $.each(contexts, function(i, c) {
+                                       var ndx = waypointIndex($el, c);
+
+                                       if (ndx >= 0) {
+                                               c.waypoints.splice(ndx, 1);
+                                       }
+                               });
+                       });
+               },
+               
+               /*
+               jQuery.fn.waypoint('destroy')
+               
+               Passing the string 'destroy' to .waypoint will unbind all 
waypoint.reached
+               event handlers on those elements and unregisters them as 
waypoints.
+               */
+               destroy: function() {
+                       return this.unbind(eventName)[wp]('remove');
+               }
+       },
+       
+       /*
+       Methods used by the jQuery object extension.
+       */
+       jQMethods = {
+               
+               /*
+               jQuery.waypoints('refresh')
+               
+               This will force a recalculation of each waypoint’s trigger 
point based on
+               its offset option and context. This is called automatically 
whenever the window
+               (or other defined context) is resized, new waypoints are added, 
or a waypoint’s
+               options are modified. If your project is changing the DOM or 
page layout without
+               doing one of these things, you may want to manually call this 
refresh.
+               */
+               refresh: function() {
+                       $.each(contexts, function(i, c) {
+                               var isWin = $.isWindow(c.element[0]),
+                               contextOffset = isWin ? 0 : 
c.element.offset().top,
+                               contextHeight = isWin ? 
$[wps]('viewportHeight') : c.element.height(),
+                               contextScroll = isWin ? 0 : 
c.element.scrollTop();
+                               
+                               $.each(c.waypoints, function(j, o) {
+                                  /* $.each isn't safe from element removal 
due to triggerOnce.
+                                  Should rewrite the loop but this is way 
easier. */
+                                  if (!o) return;
+                                  
+                                       // Adjustment is just the offset if 
it's a px value
+                                       var adjustment = o.options.offset,
+                                       oldOffset = o.offset;
+                                       
+                                       // Set adjustment to the return value 
if offset is a function.
+                                       if (typeof o.options.offset === 
"function") {
+                                               adjustment = 
o.options.offset.apply(o.element);
+                                       }
+                                       // Calculate the adjustment if offset 
is a percentage.
+                                       else if (typeof o.options.offset === 
"string") {
+                                               var amount = 
parseFloat(o.options.offset);
+                                               adjustment = 
o.options.offset.indexOf("%") ?
+                                                       Math.ceil(contextHeight 
* (amount / 100)) : amount;
+                                       }
+
+                                       /* 
+                                       Set the element offset to the window 
scroll offset, less
+                                       all our adjustments.
+                                       */
+                                       o.offset = o.element.offset().top - 
contextOffset
+                                               + contextScroll - adjustment;
+
+                                       /*
+                                       An element offset change across the 
current scroll point triggers
+                                       the event, just as if we scrolled past 
it unless prevented by an
+                                       optional flag.
+                                       */
+                                       if (o.options.onlyOnScroll) return;
+                                       
+                                       if (oldOffset !== null && c.oldScroll > 
oldOffset && c.oldScroll <= o.offset) {
+                                               triggerWaypoint(o, ['up']);
+                                       }
+                                       else if (oldOffset !== null && 
c.oldScroll < oldOffset && c.oldScroll >= o.offset) {
+                                               triggerWaypoint(o, ['down']);
+                                       }
+                                       /* For new waypoints added after load, 
check that down should have
+                                       already been triggered */
+                                       else if (!oldOffset && contextScroll > 
o.offset) {
+                                               triggerWaypoint(o, ['down']);
+                                       }
+                               });
+                               
+                               // Keep waypoints sorted by offset value.
+                               c.waypoints.sort(function(a, b) {
+                                       return a.offset - b.offset;
+                               });
+                       });
+               },
+               
+               
+               /*
+               jQuery.waypoints('viewportHeight')
+               
+               This will return the height of the viewport, adjusting for 
inconsistencies
+               that come with calling $(window).height() in iOS. Recommended 
for use
+               within any offset functions.
+               */
+               viewportHeight: function() {
+                       return (window.innerHeight ? window.innerHeight : 
$w.height());
+               },
+               
+               
+               /*
+               jQuery.waypoints()
+               
+               This will return a jQuery object with a collection of all 
registered waypoint
+               elements.
+
+               $('.post').waypoint();
+               $('.ad-unit').waypoint(function(event, direction) {
+                  // Passed an ad unit
+               });
+               console.log($.waypoints());
+               
+               The example above would log a jQuery object containing all 
.post and .ad-unit
+               elements.
+               */
+               aggregate: function() {
+                       var points = $();
+                       $.each(contexts, function(i, c) {
+                               $.each(c.waypoints, function(i, e) {
+                                       points = points.add(e.element);
+                               });
+                       });
+                       return points;
+               }
+       };
+
+       
+       /*
+       fn extension.  Delegates to appropriate method.
+       */
+       $.fn[wp] = function(method) {
+               
+               if (methods[method]) {
+                       return methods[method].apply(this, 
Array.prototype.slice.call(arguments, 1));
+               }
+               else if (typeof method === "function" || !method) {
+                       return methods.init.apply(this, arguments);
+               }
+               else if (typeof method === "object") {
+                       return methods.init.apply(this, [null, method]);
+               }
+               else {
+                       $.error( 'Method ' +  method + ' does not exist on 
jQuery ' + wp );
+               }
+       };
+       
+       
+       /*
+       The default options object that is extended when calling .waypoint. It 
has the
+       following properties:
+       
+       context
+               string | element | jQuery*
+               default: window
+               The context defines which scrollable element the waypoint 
belongs to and acts
+               within. The default, window, means the waypoint offset is 
calculated with relation
+               to the whole viewport.  You can set this to another element to 
use the waypoints
+               within that element.  Accepts a selector string, *but if you 
use jQuery 1.6+ it
+               also accepts a raw HTML element or jQuery object.
+       
+       continuous
+               boolean
+               default: true
+               If true, and multiple waypoints are triggered in one scroll, 
this waypoint will
+               trigger even if it is not the last waypoint reached.  If false, 
it will only
+               trigger if it is the last waypoint.
+               
+       handler
+               function
+               default: undefined
+               An alternative way to bind functions to the waypoint, without 
using the function
+               as the first argument to the waypoint function.
+
+       offset
+               number | string | function
+               default: 0
+               Determines how far the top of the element must be from the top 
of the browser
+               window to trigger a waypoint. It can be a number, which is 
taken as a number
+               of pixels, a string representing a percentage of the viewport 
height, or a
+               function that will return a number of pixels.
+               
+       onlyOnScroll
+               boolean
+               default: false
+               If true, this waypoint will not trigger if an offset change 
during a refresh
+               causes it to pass the current scroll point.
+               
+       triggerOnce
+               boolean
+               default: false
+               If true, the waypoint will be destroyed when triggered.
+       
+       An offset of 250 would trigger the waypoint when the top of the element 
is 250px
+       from the top of the viewport. Negative values for any offset work as 
you might
+       expect. A value of -100 would trigger the waypoint when the element is 
100px above
+       the top of the window.
+
+       offset: '100%'
+       
+       A string percentage will determine the pixel offset based on the height 
of the
+       window. When resizing the window, this offset will automatically be 
recalculated
+       without needing to call $.waypoints('refresh').
+
+       // The bottom of the element is in view
+       offset: function() {
+          return $.waypoints('viewportHeight') - $(this).outerHeight();
+       }
+       
+       Offset can take a function, which must return a number of pixels from 
the top of
+       the window. The this value will always refer to the raw HTML element of 
the
+       waypoint. As with % values, functions are recalculated automatically 
when the
+       window resizes. For more on recalculating offsets, see 
$.waypoints('refresh').
+       
+       An offset value of 'bottom-in-view' will act as an alias for the 
function in the
+       example above, as this is a common usage.
+       
+       offset: 'bottom-in-view'
+       
+       You can see this alias in use on the Scroll Analytics example page.
+
+       The triggerOnce flag, if true, will destroy the waypoint after the 
first trigger.
+       This is just a shortcut for calling .waypoint('destroy') within the 
waypoint
+       handler. This is useful in situations such as scroll analytics, where 
you only
+       want to record an event once for each page visit.
+       
+       The context option lets you use Waypoints within an element other than 
the window.
+       You can define the context with a selector string and the waypoint will 
act within
+       the nearest ancestor that matches this selector.
+       
+       $('.something-scrollable .waypoint').waypoint({
+          context: '.something-scrollable'
+       });
+       
+       You can see this in action on the Dial Controls example.
+       
+       The handler option gives authors an alternative way to bind functions 
when
+       creating a waypoint.  In place of:
+       
+       $('.item').waypoint(function(event, direction) {
+          // make things happen
+       });
+       
+       You may instead write:
+       
+       $('.item').waypoint({
+          handler: function(event, direction) {
+             // make things happen
+          }
+       });
+       
+       */
+       $.fn[wp].defaults = {
+               continuous: true,
+               offset: 0,
+               triggerOnce: false,
+               context: window
+       };
+       
+       
+       
+       
+       
+       /*
+       jQuery object extension. Delegates to appropriate methods above.
+       */
+       $[wps] = function(method) {
+               if (jQMethods[method]) {
+                       return jQMethods[method].apply(this);
+               }
+               else {
+                       return jQMethods['aggregate']();
+               }
+       };
+       
+       
+       /*
+       $.waypoints.settings
+       
+       Settings object that determines some of the plugin’s behavior.
+               
+       resizeThrottle
+               number
+               default: 200
+               For performance reasons, the refresh performed during resizes is
+               throttled. This value is the rate-limit in milliseconds between 
resize
+               refreshes. For more information on throttling, check out Ben 
Alman’s
+               throttle / debounce plugin.
+               http://benalman.com/projects/jquery-throttle-debounce-plugin/
+               
+       scrollThrottle
+               number
+               default: 100
+               For performance reasons, checking for any crossed waypoints 
during a
+               scroll event is throttled. This value is the rate-limit in 
milliseconds
+               between scroll checks. For more information on throttling, 
check out Ben
+               Alman’s throttle / debounce plugin.
+               http://benalman.com/projects/jquery-throttle-debounce-plugin/
+       */
+       $[wps].settings = {
+               resizeThrottle: 200,
+               scrollThrottle: 100
+       };
+       
+       $w.load(function() {
+               // Calculate everything once on load.
+               $[wps]('refresh');
+       });
+})(jQuery, 'waypoint', 'waypoints', window);


Property changes on: 
trunk/extensions/PageTriage/modules/external/jquery.waypoints.js
___________________________________________________________________
Added: svn:eol-style
   + native


_______________________________________________
MediaWiki-CVS mailing list
MediaWiki-CVS@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to