resources/dist/mobile.special.watchlist.scripts.js.map.json
{"version":3,"file":"mobile.special.watchlist.scripts.js","mappings":"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","sources":["webpack://mfModules/./src/mobile.special.watchlist.scripts/ScrollEndEventEmitter.js","webpack://mfModules/./src/mobile.special.watchlist.scripts/WatchList.js","webpack://mfModules/./src/mobile.special.watchlist.scripts/WatchListGateway.js","webpack://mfModules/./src/mobile.special.watchlist.scripts/mobile.special.watchlist.scripts.js"],"sourcesContent":["const util = require( '../mobile.startup/util' ),\n\tmfExtend = require( '../mobile.startup/mfExtend' );\n\n/**\n * Class to assist a view in implementing infinite scrolling on some DOM\n * element. This module itself is only responsible for emitting an Event when\n * the bottom of an Element is scrolled to.\n *\n * @class ScrollEndEventEmitter\n * @mixes OO.EventEmitter\n *\n * Use this class in a view to help it do infinite scrolling.\n *\n * 1. Initialize it in the constructor `initialize` and listen to the\n * EVENT_SCROLL_END event it emits (and call your loading function then)\n * 2. On preRender (once we have the DOM element) set it into the infinite\n * scrolling object and disable it until we've loaded.\n * 3. Once you have loaded the list and put it in the DOM, enable the\n * infinite scrolling detection.\n * - Every time the scroller detection triggers a load, it auto disables\n * to not trigger multiple times. After you have loaded, manually\n * re-enable it.\n *\n * Example:\n * @example\n * <code>\n * var\n * mfExtend = require( './mfExtend' ),\n * ScrollEndEventEmitter = require( './ScrollEndEventEmitter' ),\n * eventBus = require( './eventBusSingleton' );\n * mfExtend( PhotoList, View, {\n * //...\n * initialize: function ( options ) {\n * this.gateway = new PhotoListGateway( {\n * username: options.username\n * } );\n * // 1. Set up infinite scroll helper and listen to events\n * this.scrollEndEventEmitter = new ScrollEndEventEmitter( eventBus, 1000 );\n * this.scrollEndEventEmitter.on( ScrollEndEventEmitter.EVENT_SCROLL_END,\n * this._loadPhotos.bind( this ) );\n * View.prototype.initialize.apply( this, arguments );\n * },\n * preRender: function () {\n * // 2. Disable until we've got the list rendered and set DOM el\n * this.scrollEndEventEmitter.setElement( this.$el );\n * this.scrollEndEventEmitter.disable();\n * },\n * _loadPhotos: function () {\n * var self = this;\n * this.gateway.getPhotos().then( function ( photos ) {\n * // load photos into the DOM ...\n * // 3. and (re-)enable infinite scrolling\n * self.scrollEndEventEmitter.enable();\n * } );\n * }\n * } );\n * </code>\n *\n * @fires ScrollEndEventEmitter#ScrollEndEventEmitter-scrollEnd\n * @param {Object} eventBus object to listen for scroll:throttled events\n * @param {number} [threshold=100] distance in pixels used to calculate if scroll\n * position is near the end of the $el\n */\nfunction ScrollEndEventEmitter( eventBus, threshold ) {\n\tthis.threshold = threshold || 100;\n\tthis.eventBus = eventBus;\n\tthis.enable();\n\tOO.EventEmitter.call( this );\n}\nOO.mixinClass( ScrollEndEventEmitter, OO.EventEmitter );\n\n/**\n * Fired when scroll bottom has been reached.\n *\n * @event ScrollEndEventEmitter#ScrollEndEventEmitter-scrollEnd\n */\nScrollEndEventEmitter.EVENT_SCROLL_END = 'ScrollEndEventEmitter-scrollEnd';\n\nmfExtend( ScrollEndEventEmitter, {\n\t/**\n\t * Listen to scroll on window and notify this._onScroll\n\t *\n\t * @memberof ScrollEndEventEmitter\n\t * @instance\n\t * @private\n\t */\n\t_bindScroll() {\n\t\tif ( !this._scrollHandler ) {\n\t\t\tthis._scrollHandler = this._onScroll.bind( this );\n\t\t\tthis.eventBus.on( 'scroll:throttled', this._scrollHandler );\n\t\t}\n\t},\n\t/**\n\t * Unbind scroll handler\n\t *\n\t * @memberof ScrollEndEventEmitter\n\t * @instance\n\t * @private\n\t */\n\t_unbindScroll() {\n\t\tif ( this._scrollHandler ) {\n\t\t\tthis.eventBus.off( 'scroll:throttled', this._scrollHandler );\n\t\t\tthis._scrollHandler = null;\n\t\t}\n\t},\n\t/**\n\t * Scroll handler. Triggers load event when near the end of the container.\n\t *\n\t * @memberof ScrollEndEventEmitter\n\t * @instance\n\t * @private\n\t */\n\t_onScroll() {\n\t\tif ( this.$el && this.enabled && this.scrollNearEnd() ) {\n\t\t\t// Disable when triggering an event. Won't trigger again until\n\t\t\t// re-enabled.\n\t\t\tthis.disable();\n\t\t\tthis.emit( ScrollEndEventEmitter.EVENT_SCROLL_END );\n\t\t}\n\t},\n\t/**\n\t * Is the scroll position near the end of the container element?\n\t *\n\t * @memberof ScrollEndEventEmitter\n\t * @instance\n\t * @private\n\t * @return {boolean}\n\t */\n\tscrollNearEnd() {\n\t\tif ( !this.$el || !this.$el.offset() ) {\n\t\t\treturn false;\n\t\t}\n\t\tconst $window = util.getWindow(),\n\t\t\tscrollBottom = $window.scrollTop() + $window.height(),\n\t\t\tendPosition = this.$el.offset().top + this.$el.outerHeight();\n\t\treturn scrollBottom + this.threshold > endPosition;\n\t},\n\t/**\n\t * Enable the ScrollEndEventEmitter so that it triggers events.\n\t *\n\t * @memberof ScrollEndEventEmitter\n\t * @instance\n\t */\n\tenable() {\n\t\tthis.enabled = true;\n\t\tthis._bindScroll();\n\t},\n\t/**\n\t * Disable the ScrollEndEventEmitter so that it doesn't trigger events.\n\t *\n\t * @memberof ScrollEndEventEmitter\n\t * @instance\n\t */\n\tdisable() {\n\t\tthis.enabled = false;\n\t\tthis._unbindScroll();\n\t},\n\t/**\n\t * Set the element to compare to scroll position to\n\t *\n\t * @memberof ScrollEndEventEmitter\n\t * @instance\n\t * @param {jQuery.Object} $el jQuery element where we want to listen for\n\t * scroll end.\n\t */\n\tsetElement( $el ) {\n\t\tthis.$el = $el;\n\t}\n} );\n\nmodule.exports = ScrollEndEventEmitter;\n","const\n\tmfExtend = require( '../mobile.startup/mfExtend' ),\n\tPageList = require( '../mobile.startup/PageList' ),\n\tWatchstarPageList = require( '../mobile.startup/watchstar/WatchstarPageList' ),\n\tScrollEndEventEmitter = require( './ScrollEndEventEmitter' ),\n\tutil = require( '../mobile.startup/util' ),\n\tWatchListGateway = require( './WatchListGateway' );\n\n/**\n * An extension of the WatchstarPageList which preloads pages as all being\n * watched.\n *\n * @extends WatchstarPageList\n * @class WatchList\n * @uses ScrollEndEventEmitter\n *\n * @fires watched\n * @fires watch\n * @param {Object} params Configuration options\n * @param {OO.EventEmitter} params.eventBus Object used to listen for scroll:throttled events\n * @private\n */\nfunction WatchList( params ) {\n\tlet lastTitle;\n\tconst options = util.extend(\n\t\t{},\n\t\t{\n\t\t\tisBorderBox: false\n\t\t},\n\t\tparams\n\t);\n\n\t// Set up infinite scroll helper and listen to events\n\tthis.scrollEndEventEmitter = new ScrollEndEventEmitter( options.eventBus );\n\tthis.scrollEndEventEmitter.on( ScrollEndEventEmitter.EVENT_SCROLL_END,\n\t\tthis._loadPages.bind( this ) );\n\n\tif ( options.el ) {\n\t\tlastTitle = this.getLastTitle( options.el );\n\t}\n\tthis.gateway = new WatchListGateway( options.api, lastTitle );\n\n\tWatchstarPageList.call( this, options );\n}\n\nmfExtend( WatchList, WatchstarPageList, {\n\t/**\n\t * @inheritdoc\n\t * @memberof WatchList\n\t * @instance\n\t */\n\tpreRender: function () {\n\t\t// The DOM will be modified. Prevent any false scroll end events from\n\t\t// being emitted.\n\t\tthis.scrollEndEventEmitter.disable();\n\t\tthis.scrollEndEventEmitter.setElement( this.$el );\n\t},\n\t/**\n\t * Also sets a watch uploads funnel.\n\t *\n\t * @inheritdoc\n\t * @memberof WatchList\n\t * @instance\n\t */\n\tpostRender: function () {\n\t\t// Skip a level from WatchstarPageList directly to PageList.\n\t\tPageList.prototype.postRender.apply( this );\n\n\t\tconst $items = this.queryUnitializedItems();\n\n\t\t// WatchList requests list of watched pages. The list contains only\n\t\t// watched pages so it's safe to transform the title map to a status map\n\t\t// with each entry marked watched (true).\n\t\tconst statuses = Object.keys( this.parsePagesFromItems( $items ) )\n\t\t\t.reduce( function ( arr, title ) {\n\t\t\t\tarr[ title ] = true;\n\t\t\t\treturn arr;\n\t\t\t}, {} );\n\t\tthis.renderItems( $items, statuses );\n\n\t\t// The list has been extended. Re-enable scroll end events.\n\t\tthis.scrollEndEventEmitter.enable();\n\t},\n\n\t/**\n\t * Loads pages from the api and triggers render.\n\t * Infinite scroll is re-enabled in postRender.\n\t *\n\t * @memberof WatchList\n\t * @instance\n\t */\n\t_loadPages: function () {\n\t\tthis.gateway.loadWatchlist().then( function ( pages ) {\n\t\t\tpages.forEach( function ( page ) {\n\t\t\t\tthis.appendPage( page );\n\t\t\t}.bind( this ) );\n\t\t\tthis.render();\n\t\t}.bind( this ) );\n\t},\n\n\t/**\n\t * Appends a list item\n\t *\n\t * @memberof WatchList\n\t * @instance\n\t * @param {Page} page\n\t */\n\tappendPage: function ( page ) {\n\t\t// wikidata descriptions should not show in this view.\n\t\tconst templateOptions = util.extend( {}, page, {\n\t\t\twikidataDescription: undefined\n\t\t} );\n\t\tthis.$el.append( this.templatePartials.item.render( templateOptions ) );\n\t},\n\n\t/**\n\t * Get the last title from the rendered HTML.\n\t * Used for initializing the API\n\t *\n\t * @memberof WatchList\n\t * @instance\n\t * @param {jQuery.Object} $el Dom element of the list\n\t * @return {string}\n\t */\n\tgetLastTitle: function ( $el ) {\n\t\treturn $el.find( 'li' ).last().attr( 'title' );\n\t}\n} );\n\nmodule.exports = WatchList;\n","const\n\tpageJSONParser = require( '../mobile.startup/page/pageJSONParser' ),\n\tutil = require( '../mobile.startup/util' ),\n\textendSearchParams = require( '../mobile.startup/extendSearchParams' );\n\n/**\n * API for interacting with watchlist.\n *\n * @param {mw.Api} api\n * @param {string} lastTitle of page listed in Watchlist to be used as a continuation parameter\n * @private\n */\nfunction WatchListGateway( api, lastTitle ) {\n\tthis.api = api;\n\t// Try to keep it in sync with SpecialMobileEditWatchlist::LIMIT (php)\n\tthis.limit = 50;\n\n\tif ( lastTitle ) {\n\t\tthis.continueParams = {\n\t\t\tcontinue: 'gwrcontinue||',\n\t\t\tgwrcontinue: '0|' + lastTitle.replace( / /g, '_' )\n\t\t};\n\t\tthis.shouldSkipFirstTitle = true;\n\t} else {\n\t\tthis.continueParams = {\n\t\t\tcontinue: ''\n\t\t};\n\t\tthis.shouldSkipFirstTitle = false;\n\t}\n\n\tthis.canContinue = true;\n}\n\nWatchListGateway.prototype = {\n\t/**\n\t * Load the list of items on the watchlist\n\t *\n\t * @return {jQuery.Deferred}\n\t */\n\tloadWatchlist: function () {\n\t\tconst self = this,\n\t\t\tparams = extendSearchParams( 'watchlist', {\n\t\t\t\tprop: [ 'info', 'revisions' ],\n\t\t\t\trvprop: 'timestamp|user',\n\t\t\t\tgenerator: 'watchlistraw',\n\t\t\t\tgwrnamespace: '0',\n\t\t\t\tgwrlimit: this.limit\n\t\t\t}, this.continueParams );\n\n\t\tif ( this.canContinue === false ) {\n\t\t\treturn util.Deferred().resolve( [] );\n\t\t}\n\t\treturn this.api.get( params ).then( function ( data ) {\n\t\t\tif ( data.continue !== undefined ) {\n\t\t\t\tself.continueParams = data.continue;\n\t\t\t} else {\n\t\t\t\tself.canContinue = false;\n\t\t\t}\n\n\t\t\treturn self.parseData( data );\n\t\t} );\n\t},\n\n\t/**\n\t * Parse api response data into pagelist item format\n\t *\n\t * @param {Object[]} data\n\t * @return {Page[]}\n\t */\n\tparseData: function ( data ) {\n\t\tlet pages;\n\n\t\tif ( !data.query || !data.query.pages ) {\n\t\t\treturn [];\n\t\t}\n\n\t\tpages = data.query.pages;\n\n\t\t// Sort results alphabetically (the api map doesn't have any order). The\n\t\t// watchlist is ordered alphabetically right now.\n\t\tpages.sort( function ( p1, p2 ) {\n\t\t\treturn p1.title === p2.title ? 0 : ( p1.title < p2.title ? -1 : 1 );\n\t\t} );\n\n\t\t// If we requested from the last item of the previous page, we shall\n\t\t// remove the first result (to avoid it being repeated)\n\t\tif ( this.shouldSkipFirstTitle ) {\n\t\t\tpages = pages.slice( 1 );\n\t\t\tthis.shouldSkipFirstTitle = false;\n\t\t}\n\n\t\t// Transform the items to a sensible format\n\t\treturn pages.map( pageJSONParser.parse );\n\t}\n\n};\n\nmodule.exports = WatchListGateway;\n","/* global $ */\nconst WatchList = require( './WatchList' ),\n\teventBus = require( '../mobile.startup/eventBusSingleton' );\n\n/**\n * Initialises JavaScript on Special:Watchlist\n * @private\n */\nfunction init() {\n\tconst $watchlist = $( 'ul.mw-mf-watchlist-page-list' );\n\n\t// FIXME: find more elegant way to not show watchlist stars on recent changes\n\tif ( $( '.mw-mf-watchlist-selector' ).length === 0 ) {\n\t\t// eslint-disable-next-line no-new\n\t\tnew WatchList( {\n\t\t\tapi: new mw.Api(),\n\t\t\tel: $watchlist,\n\t\t\tfunnel: 'watchlist',\n\t\t\tskipTemplateRender: true,\n\t\t\teventBus: eventBus\n\t\t} );\n\t}\n\t// not needed now we have JS view which has infinite scrolling\n\t$watchlist.find( '.mw-mf-watchlist-more' ).remove();\n}\n\n$( function () {\n\tinit();\n} );\n"],"names":["util","require","mfExtend","ScrollEndEventEmitter","eventBus","threshold","this","enable","OO","EventEmitter","call","mixinClass","EVENT_SCROLL_END","_bindScroll","_scrollHandler","_onScroll","bind","on","_unbindScroll","off","$el","enabled","scrollNearEnd","disable","emit","offset","$window","getWindow","scrollBottom","scrollTop","height","endPosition","top","outerHeight","setElement","module","exports","PageList","WatchstarPageList","WatchListGateway","WatchList","params","lastTitle","options","extend","isBorderBox","scrollEndEventEmitter","_loadPages","el","getLastTitle","gateway","api","preRender","postRender","prototype","apply","$items","queryUnitializedItems","statuses","Object","keys","parsePagesFromItems","reduce","arr","title","renderItems","loadWatchlist","then","pages","forEach","page","appendPage","render","templateOptions","wikidataDescription","undefined","append","templatePartials","item","find","last","attr","pageJSONParser","extendSearchParams","limit","continueParams","continue","gwrcontinue","replace","shouldSkipFirstTitle","canContinue","self","prop","rvprop","generator","gwrnamespace","gwrlimit","Deferred","resolve","get","data","parseData","query","sort","p1","p2","slice","map","parse","$","$watchlist","length","mw","Api","funnel","skipTemplateRender","remove"],"sourceRoot":""}