Current File : /home/jvzmxxx/wiki1/extensions/MobileFrontend/resources/mobile.infiniteScroll/InfiniteScroll.js
( function ( M, $ ) {
	/**
	 * Class to assist a view in implementing infinite scrolling on some DOM
	 * element.
	 *
	 * @class InfiniteScroll
	 * @mixins OO.EventEmitter
	 *
	 * Use this class in a view to help it do infinite scrolling.
	 *
	 * 1. Initialize it in the constructor `initialize` and listen to the 'load'
	 *   event it emits (and call your loading function then)
	 * 2. On preRender (once we have the dom element) set it into the infinite
	 *   scrolling object and disable it until we've loaded.
	 * 3. Once you have loaded the list and put it in the dom, enable the
	 *   infinite scrolling detection.
	 *   * Everytime the scroller detection triggers a load, it auto disables
	 *     to not trigger multiple times. After you have loaded, manually
	 *     re-enable it.
	 *
	 * Example:
	 *     @example
	 *     <code>
	 *       var InfiniteScroll = M.require( 'mobile.infiniteScroll/InfiniteScroll' );
	 *       OO.mfExtend( PhotoList, View, {
	 *         //...
	 *         initialize: function ( options ) {
	 *           this.gateway = new PhotoListGateway( {
	 *             username: options.username
	 *           } );
	 *           // 1. Set up infinite scroll helper and listen to events
	 *           this.infiniteScroll = new InfiniteScroll( 1000 );
	 *           this.infiniteScroll.on( 'load', $.proxy( this, '_loadPhotos' ) );
	 *           View.prototype.initialize.apply( this, arguments );
	 *         },
	 *         preRender: function () {
	 *           // 2. Disable until we've got the list rendered and set DOM el
	 *           this.infiniteScroll.setElement( this.$el );
	 *           this.infiniteScroll.disable();
	 *         },
	 *         _loadPhotos: function () {
	 *           var self = this;
	 *           this.gateway.getPhotos().done( function ( photos ) {
	 *             // load photos into the DOM ...
	 *             // 3. and (re-)enable infinite scrolling
	 *             self.infiniteScroll.enable();
	 *           } );
	 *         }
	 *       } );
	 *     </code>
	 */
	/**
	 * Constructor.
	 * @param {number} threshold distance in pixels used to calculate if scroll
	 * position is near the end of the $el
	 */
	function InfiniteScroll( threshold ) {
		this.threshold = threshold || 100;
		this.enable();
		OO.EventEmitter.call( this );
	}
	OO.mixinClass( InfiniteScroll, OO.EventEmitter );

	OO.mfExtend( InfiniteScroll, {
		/**
		 * Listen to scroll on window and notify this._onScroll
		 * @method
		 * @private
		 */
		_bindScroll: function () {
			if ( !this._scrollHandler ) {
				this._scrollHandler = $.proxy( this, '_onScroll' );
				M.on( 'scroll:throttled', this._scrollHandler );
			}
		},
		/**
		 * Unbind scroll handler
		 * @method
		 * @private
		 */
		_unbindScroll: function () {
			if ( this._scrollHandler ) {
				M.off( 'scroll:throttled', this._scrollHandler );
				this._scrollHandler = null;
			}
		},
		/**
		 * Scroll handler. Triggers load event when near the end of the container.
		 * @method
		 * @private
		 */
		_onScroll: function () {
			if ( this.$el && this.enabled && this.scrollNearEnd() ) {
				// Disable when triggering an event. Won't trigger again until
				// re-enabled.
				this.disable();
				/**
				 * @event load
				 * Fired when scroll bottom has been reached to give oportunity to
				 * load to owners.
				 */
				this.emit( 'load' );
			}
		},
		/**
		 * Is the scroll position near the end of the container element?
		 * @method
		 * @private
		 * @return {boolean}
		 */
		scrollNearEnd: function () {
			var scrollBottom = $( window ).scrollTop() + $( window ).height(),
				endPosition = this.$el.offset().top + this.$el.outerHeight();
			return scrollBottom + this.threshold > endPosition;
		},
		/**
		 * Enable the InfiniteScroll so that it triggers events.
		 * @method
		 */
		enable: function () {
			this.enabled = true;
			this._bindScroll();
		},
		/**
		 * Disable the InfiniteScroll so that it doesn't trigger events.
		 * @method
		 */
		disable: function () {
			this.enabled = false;
			this._unbindScroll();
		},
		/**
		 * Set the element to compare to scroll position to
		 * @param {jQuery.Object} $el jQuery element where we want to listen for
		 * infinite scrolling.
		 */
		setElement: function ( $el ) {
			this.$el = $el;
		}
	} );

	M.define( 'mobile.infiniteScroll/InfiniteScroll', InfiniteScroll );
}( mw.mobileFrontend, jQuery ) );