{"version":3,"file":"mobile.common.js","mappings":"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","sources":["webpack://mfModules/./src/mobile.startup/Anchor.js","webpack://mfModules/./src/mobile.startup/Browser.js","webpack://mfModules/./src/mobile.startup/Button.js","webpack://mfModules/./src/mobile.startup/CtaDrawer.js","webpack://mfModules/./src/mobile.startup/Drawer.js","webpack://mfModules/./src/mobile.startup/Icon.js","webpack://mfModules/./src/mobile.startup/IconButton.js","webpack://mfModules/./src/mobile.startup/Overlay.js","webpack://mfModules/./src/mobile.startup/OverlayManager.js","webpack://mfModules/./src/mobile.startup/Page.js","webpack://mfModules/./src/mobile.startup/PageHTMLParser.js","webpack://mfModules/./src/mobile.startup/PageList.js","webpack://mfModules/./src/mobile.startup/Skin.js","webpack://mfModules/./src/mobile.startup/Thumbnail.js","webpack://mfModules/./src/mobile.startup/View.js","webpack://mfModules/./src/mobile.startup/actionParams.js","webpack://mfModules/./src/mobile.startup/amcOutreach/AmcEnableForm.js","webpack://mfModules/./src/mobile.startup/amcOutreach/amcOutreach.js","webpack://mfModules/./src/mobile.startup/amcOutreach/amcOutreachDrawer.js","webpack://mfModules/./src/mobile.startup/currentPage.js","webpack://mfModules/./src/mobile.startup/currentPageHTMLParser.js","webpack://mfModules/./src/mobile.startup/eventBusSingleton.js","webpack://mfModules/./src/mobile.startup/extendSearchParams.js","webpack://mfModules/./src/mobile.startup/headers.js","webpack://mfModules/./src/mobile.startup/icons.js","webpack://mfModules/./src/mobile.startup/lazyImages/lazyImageLoader.js","webpack://mfModules/./src/mobile.startup/moduleLoader.js","webpack://mfModules/./src/mobile.startup/moduleLoaderSingleton.js","webpack://mfModules/./src/mobile.startup/page/pageJSONParser.js","webpack://mfModules/./src/mobile.startup/promoCampaign/promoCampaign.js","webpack://mfModules/./src/mobile.startup/showOnPageReload.js","webpack://mfModules/./src/mobile.startup/util.js","webpack://mfModules/./src/mobile.startup/watchstar/WatchstarGateway.js","webpack://mfModules/./src/mobile.startup/watchstar/WatchstarPageList.js","webpack://mfModules/./src/mobile.startup/watchstar/watchstar.js"],"sourcesContent":["const\n\tView = require( './View' ),\n\tutil = require( './util' );\n\n/**\n * A wrapper for creating an anchor.\n *\n * @private\n */\nclass Anchor extends View {\n\t/**\n\t * @inheritdoc\n\t */\n\tget isTemplateMode() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {boolean} defaults.progressive is progressive action\n\t * @property {boolean} defaults.destructive is destructive action\n\t * @property {string} defaults.additionalClassNames Additional class name(s).\n\t * @property {string} defaults.href url\n\t * @property {string} defaults.label of anchor\n\t */\n\tget defaults() {\n\t\treturn {\n\t\t\tprogressive: undefined,\n\t\t\tdestructive: undefined,\n\t\t\tadditionalClassNames: '',\n\t\t\thref: undefined,\n\t\t\tlabel: undefined\n\t\t};\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tget template() {\n\t\treturn util.template( `\n<a {{#href}}href=\"{{href}}\"{{/href}} class=\"mw-mf-anchor\n\t{{#progressive}} mw-mf-anchor-progressive{{/progressive}}\n\t{{#destructive}} mw-mf-anchor-destructive{{/destructive}}\n\t {{additionalClassNames}}\">{{label}}</a>\n\t` );\n\t}\n}\n\nmodule.exports = Anchor;\n","const util = require( './util' );\n\nlet browser;\n\n/**\n * Memoize a class method. Caches the result of the method based on the\n * arguments. Instances do not share a cache.\n *\n * @private\n * @param {Function} method Method to be memoized\n * @return {Function}\n */\nfunction memoize( method ) {\n\t/**\n\t * Memoized version of the method\n\t *\n\t * @return {Function}\n\t */\n\tconst memoized = function () {\n\t\tconst cache = this[ '__cache' + memoized.cacheId ] ||\n\t\t\t( this[ '__cache' + memoized.cacheId ] = {} ),\n\t\t\tkey = [].join.call( arguments, '|' );\n\t\tif ( Object.prototype.hasOwnProperty.call( cache, key ) ) {\n\t\t\treturn cache[ key ];\n\t\t}\n\t\treturn ( cache[ key ] = method.apply( this, arguments ) );\n\t};\n\tmemoized.cacheId = Date.now().toString() + Math.random().toString();\n\treturn memoized;\n}\n\n/**\n * Representation of user's current browser\n *\n * @class Browser\n * @private\n */\nclass Browser {\n\t/**\n\t * @param {string} userAgent the user agent of the current browser\n\t * @param {jQuery.Object} $container an element to associate with the Browser object\n\t */\n\tconstructor( userAgent, $container ) {\n\t\tthis.userAgent = userAgent;\n\t\tthis.$el = $container;\n\t\t/**\n\t\t * Returns whether the current browser is an ios device.\n\t\t * FIXME: jquery.client does not support iPad detection so we cannot use it.\n\t\t *\n\t\t * @instance\n\t\t * @param {number} [version] integer describing a specific version you want to test against.\n\t\t * @return {boolean}\n\t\t */\n\t\tthis.isIos = memoize( function ( version ) {\n\t\t\tconst ua = this.userAgent,\n\t\t\t\tios = /ipad|iphone|ipod/i.test( ua );\n\n\t\t\tif ( ios && version ) {\n\t\t\t\tswitch ( version ) {\n\t\t\t\t\tcase 8:\n\t\t\t\t\t// Test UA for iOS8. Or for simulator look for Version 8\n\t\t\t\t\t// In the iOS simulator the OS is the host machine OS version\n\t\t\t\t\t// This makes testing in iOS8 simulator work as expected\n\t\t\t\t\t\treturn /OS 8_/.test( ua ) || /Version\\/8/.test( ua );\n\t\t\t\t\tcase 4:\n\t\t\t\t\t\treturn /OS 4_/.test( ua );\n\t\t\t\t\tcase 5:\n\t\t\t\t\t\treturn /OS 5_/.test( ua );\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn ios;\n\t\t\t}\n\t\t} );\n\t\t/**\n\t\t * Determine if a device has a widescreen.\n\t\t *\n\t\t * @instance\n\t\t * @return {boolean}\n\t\t */\n\t\tthis.isWideScreen = memoize( () => {\n\t\t\tconst val = parseInt( mw.config.get( 'wgMFDeviceWidthTablet' ), 10 );\n\t\t\t// Check viewport width to determine mobile vs tablet.\n\t\t\t// Note: Mobile devices held in landscape mode might receive tablet treatment.\n\t\t\treturn window.innerWidth >= val;\n\t\t} );\n\t\t/**\n\t\t * Whether touchstart and other touch events are supported by the current browser.\n\t\t *\n\t\t * @instance\n\t\t * @return {boolean}\n\t\t */\n\t\tthis.supportsTouchEvents = memoize( () => 'ontouchstart' in window );\n\t}\n\n\t/**\n\t * @return {Browser}\n\t */\n\tstatic getSingleton() {\n\t\tlet $html;\n\t\tif ( !browser ) {\n\t\t\t$html = util.getDocument();\n\t\t\tbrowser = new Browser( window.navigator.userAgent, $html );\n\t\t}\n\t\treturn browser;\n\t}\n}\n\nmodule.exports = Browser;\n","const\n\tutil = require( './util' ),\n\tView = require( './View' ),\n\tIconButton = require( './IconButton' );\n\n/**\n * A wrapper for creating a button.\n * FIXME: T343036 This file should be combined with IconButton, all gadgets/extentions\n * using Button.js and IconButton.js will need to be updated to reflect this\n *\n * @private\n */\nclass Button extends View {\n\t/**\n\t * @param {Object} options Configuration options\n\t */\n\tconstructor( options ) {\n\t\tsuper( options );\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tget isTemplateMode() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} defaults.tagName The name of the tag in which the button is wrapped.\n\t * @property {boolean} defaults.block is stacked button\n\t * @property {boolean} defaults.progressive is progressive action\n\t * @property {boolean} defaults.quiet is quiet button\n\t * @property {boolean} defaults.destructive is destructive action\n\t * @property {string} defaults.additionalClassNames Additional class name(s).\n\t * @property {string} defaults.href url\n\t * @property {string} defaults.label of button\n\t * @property {boolean} defaults.disabled should only be used with tagName button\n\t */\n\tget defaults() {\n\t\treturn {\n\t\t\ttagName: 'a',\n\t\t\tdisabled: false,\n\t\t\tblock: undefined,\n\t\t\tprogressive: undefined,\n\t\t\tdestructive: undefined,\n\t\t\tquiet: undefined,\n\t\t\tadditionalClassNames: '',\n\t\t\thref: undefined,\n\t\t\tlabel: undefined,\n\t\t\tsize: 'medium'\n\t\t};\n\t}\n\n\tget template() {\n\t\treturn util.template( '{{{_buttonHTML}}}' );\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tpreRender() {\n\t\t// Mapping existing props to Codex props used in IconButton\n\t\tlet action = 'default';\n\t\tif ( this.options.progressive ) {\n\t\t\taction = 'progressive';\n\t\t} else if ( this.options.destructive ) {\n\t\t\taction = 'destructive';\n\t\t}\n\t\tlet weight = this.options.quiet ? 'quiet' : 'normal';\n\t\tif ( this.options.progressive || this.options.destructive ) {\n\t\t\tweight = 'primary';\n\t\t}\n\t\tif ( this.options.block ) {\n\t\t\tthis.options.additionalClassNames += ' mf-button-block';\n\t\t}\n\t\tconst options = util.extend( {\n\t\t\tweight,\n\t\t\taction,\n\t\t\tisIconOnly: false,\n\t\t\ticon: null\n\t\t}, this.options );\n\n\t\tthis._button = new IconButton( options );\n\t\tthis.options._buttonHTML = this._button.$el.get( 0 ).outerHTML;\n\t}\n}\n\nmodule.exports = Button;\n","const\n\tDrawer = require( './Drawer' ),\n\tutil = require( './util' ),\n\tButton = require( './Button' ),\n\tAnchor = require( './Anchor' );\n\n/**\n * Represents a query string value.\n *\n * @typedef {string|number|boolean|undefined|string[]|boolean[]} module:mobile.startup~QueryVal\n */\n/**\n * Describes a combination of query string parameters.\n *\n * @typedef {Object.<string, module:mobile.startup~QueryVal>} module:mobile.startup~QueryParams\n */\n\n/**\n * Describes a call to action drawer.\n *\n * @memberof module:mobile.startup\n * @typedef {Object} CtaOptions\n * @prop {string} [returnTo]\n * @prop {module:mobile.startup~QueryParams} [queryParams]\n * @prop {module:mobile.startup~QueryParams} [signupQueryParams]\n * @prop {Object} [progressiveButton] button options for Button element for signing in.\n *  If omitted will create a login URL.\n * @prop {Object} [actionAnchor] anchor options for Anchor element for signing up. If omitted\n *   will create a sign up URL\n * @prop {string} content text - what is the call to action?\n */\n\n/**\n * Internal for use inside Minerva only, creates the drawer at the bottom of the screen that appears when an anonymous\n * user tries to perform an action that requires being logged in. It presents the user\n * with options to log in or sign up for a new account.\n *\n * @function CtaDrawer\n * @memberof module:mobile.startup\n * @param {module:mobile.startup.CtaOptions} options Options for drawer.\n * @return {module:mobile.startup/Drawer}\n */\nfunction CtaDrawer( options = {} ) {\n\tconst params = redirectParams( options.queryParams, options.returnTo );\n\treturn new Drawer(\n\t\tutil.extend( {\n\t\t\tchildren: [\n\t\t\t\tutil.parseHTML( '<p>' ).text( options.content ),\n\t\t\t\tnew Button( util.extend( {\n\t\t\t\t\tprogressive: true,\n\t\t\t\t\thref: mw.util.getUrl( 'Special:UserLogin', params ),\n\t\t\t\t\tlabel: mw.msg( 'mobile-frontend-watchlist-cta-button-login' )\n\t\t\t\t}, options.progressiveButton ) ).$el,\n\t\t\t\tutil.parseHTML( '<div>' ).addClass( 'cta-drawer__anchors' ).append(\n\t\t\t\t\t// Update Minerva first to avoid needing to keep this closeAnchor\n\t\t\t\t\tnew Anchor( util.extend( {\n\t\t\t\t\t\thref: mw.util.getUrl(\n\t\t\t\t\t\t\t'Special:UserLogin', signUpParams( params, options.signupQueryParams )\n\t\t\t\t\t\t),\n\t\t\t\t\t\tprogressive: true,\n\t\t\t\t\t\tlabel: mw.msg( 'mobile-frontend-watchlist-cta-button-signup' )\n\t\t\t\t\t}, options.actionAnchor ) ).$el\n\t\t\t\t)\n\t\t\t]\n\t\t}, options )\n\t);\n}\n\n/**\n * Special:UserLogin post-request redirect query parameters.\n *\n * @ignore\n * @param {QueryParams} params\n * @param {string} [redirectURL]\n * @return {QueryParams}\n */\nfunction redirectParams( params, redirectURL ) {\n\treturn util.extend( {\n\t\t// use wgPageName as this includes the namespace if outside Main\n\t\treturnto: redirectURL || mw.config.get( 'wgPageName' )\n\t}, params );\n}\n\n/**\n * Special:UserLogin account creation query parameters.\n *\n * @ignore\n * @param {...QueryParams} params\n * @return {QueryParams}\n */\nfunction signUpParams() {\n\t[].push.call( arguments, { type: 'signup' } );\n\treturn util.extend.apply( util, arguments );\n}\n\nCtaDrawer.prototype.test = {\n\tredirectParams,\n\tsignUpParams\n};\n\nmodule.exports = CtaDrawer;\n","const\n\tView = require( './View' ),\n\tutil = require( './util' ),\n\tIconButton = require( './IconButton' );\n\n/**\n * A {@link View} that pops up from the bottom of the screen.\n *\n * @final\n */\nclass Drawer extends View {\n\t/**\n\t * @param {Object} props\n\t * @param {string} [props.className] Additional CSS classes to add\n\t * @param {jQuery.Element[]} [props.children] An array of elements to append to\n\t * @param {Function} [props.onShow] Callback called before showing the drawer.\n\t *  It receives a promise given the show process is asynchronous. This is used in\n\t *  production by GrowthExperiments.\n\t * @param {Function} [props.onBeforeHide] Callback called before hiding the drawer\n\t */\n\tconstructor( props ) {\n\t\tsuper(\n\t\t\tutil.extend(\n\t\t\t\t{\n\t\t\t\t\tonBeforeHide: () => {},\n\t\t\t\t\tshowCollapseIcon: true\n\t\t\t\t},\n\t\t\t\tprops,\n\t\t\t\t{ events: util.extend( {\n\t\t\t\t\t'click .drawer-container__mask': () => {\n\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t},\n\t\t\t\t\t'click .cancel': ( ev ) => {\n\t\t\t\t\t\tev.preventDefault();\n\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t},\n\t\t\t\t\tclick( ev ) {\n\t\t\t\t\t\tev.stopPropagation();\n\t\t\t\t\t}\n\t\t\t\t}, props.events ) }\n\t\t\t)\n\t\t);\n\t}\n\n\tinitialize( props ) {\n\t\tthis.drawerClassName = props.className || '';\n\t\tprops.className = 'drawer-container';\n\t\tthis.collapseIcon = new IconButton( {\n\t\t\ticon: 'expand',\n\t\t\tadditionalClassNames: 'cancel',\n\t\t\tlabel: mw.msg( 'mobile-frontend-drawer-arrow-label' )\n\t\t} );\n\t\t// in milliseconds\n\t\tthis.minHideDelay = 100;\n\t\tsuper.initialize( props );\n\t}\n\n\t/**\n\t * Shows panel after a slight delay\n\t *\n\t * @memberof module:mobile.startup/Drawer\n\t * @instance\n\t * @method\n\t * @return {jQuery.Promise} which is used by GrowthExperiments\n\t */\n\tshow() {\n\t\tconst d = util.Deferred();\n\t\tthis.$el.prepend( this.$mask );\n\t\t// Force redraw by asking the browser to measure the element's width\n\t\tthis.$el.width();\n\t\tconst $drawer = this.$el.find( '.drawer' );\n\t\tthis.$mask.addClass( 'drawer-container__mask--visible' );\n\t\tif ( !$drawer.hasClass( 'visible' ) ) {\n\t\t\t$drawer.addClass( 'visible' );\n\t\t\t// IntersectionObserver doesn't fire for content\n\t\t\t// in drawers, so trigger manually (T361212)\n\t\t\tmw.hook( 'mobileFrontend.loadLazyImages' ).fire( this.$el );\n\t\t\tif ( this.options.onShow ) {\n\t\t\t\tthis.options.onShow( d );\n\t\t\t}\n\t\t\trequestAnimationFrame( () => d.resolve() );\n\t\t} else {\n\t\t\td.resolve();\n\t\t}\n\t\treturn d.promise();\n\t}\n\n\t/**\n\t * Hides panel\n\t */\n\thide() {\n\t\tconst $drawer = this.$el.find( '.drawer' );\n\t\t$drawer.removeClass( 'visible' );\n\t\tthis.$mask.removeClass( 'drawer-container__mask--visible' );\n\t\t// Should really use 'transitionend' event here, but as the\n\t\t// parent $drawer element is often detatched as well, this\n\t\t// might not fire until the next show animation.\n\t\tsetTimeout( () => {\n\t\t\tthis.$mask.detach();\n\t\t}, 100 );\n\t\trequestAnimationFrame( () => {\n\t\t\tthis.options.onBeforeHide( this );\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tpostRender() {\n\t\tthis.$mask = util.parseHTML( '<div>' ).addClass( 'drawer-container__mask' );\n\t\tconst props = this.options,\n\t\t\t// eslint-disable-next-line mediawiki/class-doc\n\t\t\t$drawer = util.parseHTML( '<div>' )\n\t\t\t\t.addClass( `drawer drawer-container__drawer position-fixed ${ this.drawerClassName }`.trim() );\n\n\t\tif ( props.showCollapseIcon ) {\n\t\t\t// append the collapse icon at the top of the drawer\n\t\t\t$drawer.prepend( this.collapseIcon.$el );\n\t\t}\n\n\t\tif ( props.children ) {\n\t\t\t// append children\n\t\t\t$drawer.append( props.children );\n\t\t}\n\t\tthis.$el.append( $drawer );\n\t}\n}\n\nmodule.exports = Drawer;\n","const\n\tutil = require( './util' ),\n\tView = require( './View' );\n\n/**\n * A wrapper for creating an icon.\n */\nclass Icon extends View {\n\t/**\n\t * @param {Object} options Configuration options\n\t */\n\tconstructor( options ) {\n\t\tsuper( options );\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tpreRender() {\n\t\tthis.options._iconClasses = this.getIconClasses();\n\t}\n\n\t/**\n\t * Internal method that sets the correct rotation class for the icon\n\t * based on the value of rotation\n\t *\n\t * @private\n\t */\n\tgetRotationClass() {\n\t\tlet rotationClass = '';\n\t\tif ( this.options.rotation ) {\n\t\t\tswitch ( this.options.rotation ) {\n\t\t\t\tcase -180:\n\t\t\t\tcase 180:\n\t\t\t\t\trotationClass = 'mf-icon-rotate-flip';\n\t\t\t\t\tbreak;\n\t\t\t\tcase -90:\n\t\t\t\t\trotationClass = 'mf-icon-rotate-anti-clockwise';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 90:\n\t\t\t\t\trotationClass = 'mf-icon-rotate-clockwise';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0:\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error( 'Bad value for rotation given. Must be ±90, 0 or ±180.' );\n\t\t\t}\n\t\t}\n\t\treturn rotationClass;\n\t}\n\n\t/**\n\t * Set icon glyph class and icon type class\n\t *\n\t * @private\n\t */\n\tgetIconClasses() {\n\t\tconst base = this.options.base;\n\t\tconst icon = this.options.icon;\n\t\tconst isSmall = this.options.isSmall;\n\t\tconst rotationClasses = this.getRotationClass();\n\t\tconst additionalClassNames = this.options.additionalClassNames;\n\n\t\tlet classes = base + ' ';\n\t\tif ( icon ) {\n\t\t\tclasses += this.getGlyphClassName() + ' ';\n\t\t}\n\t\tif ( isSmall ) {\n\t\t\tclasses += 'mf-icon--small ';\n\t\t}\n\t\tif ( additionalClassNames ) {\n\t\t\tclasses += additionalClassNames + ' ';\n\t\t}\n\n\t\treturn classes + rotationClasses;\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tget isTemplateMode() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults\n\t * @property {string} defaults.base Base icon class.\n\t * Defaults to 'mf-icon'.\n\t * @property {string} defaults.glyphPrefix Prefix for the icon class\n\t * Defaults to 'mf'.\n\t * @property {string} defaults.icon Name of the icon.\n\t * @property {boolean} defaults.rotation will rotate the icon by a certain number\n\t *  of degrees. Must be ±90, 0 or ±180 or will throw exception.\n\t * @property {boolean} defaults.isSmall If icon is small.\n\t * @property {string} defaults.addtionalClassNames Additional classes to be added to the icon.\n\t */\n\tget defaults() {\n\t\treturn {\n\t\t\tbase: 'mf-icon',\n\t\t\tglyphPrefix: null,\n\t\t\ticon: '',\n\t\t\trotation: 0,\n\t\t\tisSmall: false,\n\t\t\tadditionalClassNames: null\n\t\t};\n\t}\n\n\t/**\n\t * Return the full class name that is required for the icon to render\n\t *\n\t * @return {string}\n\t */\n\tgetClassName() {\n\t\treturn this.$el.attr( 'class' );\n\t}\n\n\t/**\n\t * Return the class that relates to the icon glyph\n\t *\n\t * @return {string}\n\t */\n\tgetGlyphClassName() {\n\t\tif ( this.options.glyphPrefix ) {\n\t\t\treturn 'mf-icon-' + this.options.glyphPrefix + '-' + this.options.icon;\n\t\t}\n\t\treturn 'mf-icon-' + this.options.icon;\n\t}\n\n\tget template() {\n\t\treturn util.template(\n\t\t\t'<span class=\"{{_iconClasses}}\"> </span>'\n\t\t);\n\t}\n}\n\nmodule.exports = Icon;\n","const\n\tutil = require( './util' ),\n\tView = require( './View' ),\n\tIcon = require( './Icon' );\n\n/**\n * A wrapper for creating an icon button.\n */\nclass IconButton extends View {\n\t/**\n\t * @param {Object} options Configuration options\n\t */\n\tconstructor( options ) {\n\t\tif ( options.href ) {\n\t\t\toptions.tagName = 'a';\n\t\t}\n\t\tif ( options.tagName === 'button' ) {\n\t\t\toptions.isTypeButton = true;\n\t\t}\n\t\tsuper( options );\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tpreRender() {\n\t\tthis.options._buttonClasses = this.getButtonClasses();\n\t\tthis.options._iconHTML = '';\n\t\tif ( this.options.icon ) {\n\t\t\tthis._icon = new Icon( {\n\t\t\t\tbase: this.options.base,\n\t\t\t\tglyphPrefix: this.options.glyphPrefix,\n\t\t\t\ticon: this.options.icon,\n\t\t\t\trotation: this.options.rotation,\n\t\t\t\tisSmall: this.options.isSmall\n\t\t\t} );\n\t\t\tthis.options._iconHTML = this._icon.$el.get( 0 ).outerHTML;\n\t\t}\n\t}\n\n\tgetButtonClasses() {\n\t\tconst additionalClassNames = this.options.additionalClassNames;\n\t\tconst size = this.options.size;\n\t\tconst weight = this.options.weight;\n\t\tconst action = this.options.action;\n\t\tconst isIconOnly = this.options.isIconOnly;\n\t\tlet classes = 'cdx-button ';\n\n\t\tif ( this.options.tagName !== 'button' ) {\n\t\t\tclasses += 'cdx-button--fake-button cdx-button--fake-button--enabled ';\n\t\t}\n\t\tif ( size ) {\n\t\t\tclasses += `cdx-button--size-${ size } `;\n\t\t}\n\t\tif ( weight ) {\n\t\t\tclasses += `cdx-button--weight-${ weight } `;\n\t\t}\n\t\tif ( action ) {\n\t\t\tclasses += `cdx-button--action-${ action } `;\n\t\t}\n\t\tif ( isIconOnly ) {\n\t\t\tclasses += 'cdx-button--icon-only ';\n\t\t}\n\t\treturn classes + additionalClassNames;\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tget isTemplateMode() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} defaults.tagName The name of the tag in which the button is wrapped.\n\t *  Defaults to 'a' when href option present.\n\t * @property {string} [defaults.href] value of href attribute,\n\t *  when set tagName will default to anchor tag\n\t * @property {string} defaults.additionalClassNames Additional classes to be added to the button\n\t * @property {string} defaults.title Tooltip text.\n\t * @property {string} defaults.size Button size.\n\t * Defaults to 'large'.\n\t * @property {boolean} defaults.weight Button weight.\n\t * Defaults to 'quiet'.\n\t * @property {boolean} defaults.action Button action.\n\t * @property {boolean} defaults.isIconOnly Whether button is an icon only button\n\t * Defaults to true.\n\t * @property {boolean} defaults.disabled should only be used with tagName button\n\t * @property {string} defaults.base String used as a base for generating class names.\n\t * Defaults to 'mf-icon'.\n\t * @property {string} defaults.glyphPrefix Prefix for the icon class\n\t * @property {string} defaults.icon Name of the icon.\n\t * @property {boolean} defaults.rotation will rotate the icon by a certain number\n\t *  of degrees. Must be ±90, 0 or ±180 or will throw exception.\n\t * @property {boolean} defaults.isSmall Whether the icon should be small.\n\t */\n\tget defaults() {\n\t\treturn {\n\t\t\ttagName: 'button',\n\t\t\thref: undefined,\n\t\t\tadditionalClassNames: '',\n\t\t\ttitle: '',\n\t\t\tsize: 'large',\n\t\t\tweight: 'quiet',\n\t\t\taction: '',\n\t\t\tisIconOnly: true,\n\t\t\tdisabled: false,\n\t\t\tbase: 'mf-icon',\n\t\t\ticon: '',\n\t\t\trotation: 0,\n\t\t\tisSmall: false\n\t\t};\n\t}\n\n\t/**\n\t * Return the full class name that is required for the icon to render\n\t *\n\t * @return {string}\n\t */\n\tgetClassName() {\n\t\treturn this.$el.attr( 'class' );\n\t}\n\n\tgetIcon() {\n\t\treturn this._icon;\n\t}\n\n\tget template() {\n\t\treturn util.template( `\n\t\t<{{tagName}}\n\t\t\ttype=\"button\"\n\t\t\t{{#isTypeButton}}{{#disabled}}disabled{{/disabled}}{{/isTypeButton}}\n\t\t\tclass=\"{{_buttonClasses}}\"\n\t\t\t{{#id}}id=\"{{id}}\"{{/id}}\n\t\t\t{{#href}}href=\"{{href}}\"{{/href}}\n\t\t\t{{#title}}title=\"{{title}}\"{{/title}}>\n\t\t\t\t{{{_iconHTML}}}\n\t\t\t\t<span>{{label}}</span>\n\t\t</{{tagName}}>\n\t\t` );\n\t}\n}\n\nmodule.exports = IconButton;\n","const\n\tView = require( './View' ),\n\theader = require( './headers' ).header,\n\tAnchor = require( './Anchor' ),\n\tutil = require( './util' ),\n\tbrowser = require( './Browser' ).getSingleton();\n\n/**\n * Mobile modal window\n *\n * @uses Icon\n * @uses Button\n * @fires Overlay#hide\n */\nclass Overlay extends View {\n\t/**\n\t * @param {Object} props\n\t * @param {Object} props.events - custom events to be bound to the overlay.\n\t * @param {boolean} [props.headerChrome] Whether the header has chrome.\n\t * @param {View[]} [props.headerActions] children (usually buttons or icons)\n\t *   that should be placed in the header actions. Ignored when `headers` used.\n\t * @param {string} [props.heading] heading for the overlay header. Use `headers` where\n\t *  overlays require more than one header. Ignored when `headers` used.\n\t * @param {boolean} props.noHeader renders an overlay without a header\n\t * @param {Element[]} [props.headers] allows overlays to have more than one\n\t *  header. When used it is an array of jQuery Objects representing\n\t *  headers created via the header util function. It is expected that only one of these\n\t *  should be visible. If undefined, headerActions and heading is used.\n\t * @param {Object} [props.footerAnchor] options for an optional Anchor\n\t *  that can appear in the footer\n\t * @param {Function} props.onBeforeExit allows a consumer to prevent exits in certain\n\t *  situations. This callback gets the following parameters:\n\t *  - 1) the exit function which should be run after the consumer has made their changes.\n\t *  - 2) the cancel function which should be run if the consumer explicitly changes their mind\n\t */\n\tconstructor( props ) {\n\t\tsuper(\n\t\t\tutil.extend(\n\t\t\t\ttrue,\n\t\t\t\t{\n\t\t\t\t\theaderChrome: false,\n\t\t\t\t\tclassName: 'overlay'\n\t\t\t\t},\n\t\t\t\tprops,\n\t\t\t\t{\n\t\t\t\t\tevents: util.extend(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// FIXME: Remove .initial-header selector\n\t\t\t\t\t\t\t'click .cancel, .confirm, .initial-header .back': 'onExitClick',\n\t\t\t\t\t\t\tclick: ( ev ) => ev.stopPropagation()\n\t\t\t\t\t\t},\n\t\t\t\t\t\tprops.events\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t)\n\t\t);\n\t}\n\n\tget template() {\n\t\treturn util.template( `\n{{^noHeader}}\n<div class=\"overlay-header-container header-container{{#headerChrome}}\n\theader-chrome{{/headerChrome}} position-fixed\">\n</div>\n{{/noHeader}}\n<div class=\"overlay-content\">\n\t{{>content}}\n</div>\n<div class=\"overlay-footer-container position-fixed\"></div>\n\t` );\n\t}\n\n\tget isIos() {\n\t\treturn browser.isIos();\n\t}\n\n\tset hideTimeout( timeout ) {\n\t\tthis._hideTimeout = timeout;\n\t}\n\n\tget hideTimeout() {\n\t\treturn this._hideTimeout;\n\t}\n\n\t/**\n\t * Shows the spinner right to the input field.\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t * @method\n\t */\n\tshowSpinner() {\n\t\tthis.$el.find( '.spinner' ).removeClass( 'hidden' );\n\t}\n\n\t/**\n\t * Hide the spinner near to the input field.\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t * @method\n\t */\n\thideSpinner() {\n\t\tthis.$el.find( '.spinner' ).addClass( 'hidden' );\n\t}\n\n\t/**\n\t * @inheritdoc\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t */\n\tpostRender() {\n\t\tconst footerAnchor = this.options.footerAnchor;\n\t\tthis.$overlayContent = this.$el.find( '.overlay-content' );\n\t\tif ( this.isIos ) {\n\t\t\tthis.$el.addClass( 'overlay-ios' );\n\t\t}\n\t\tif ( footerAnchor ) {\n\t\t\tthis.$el.find( '.overlay-footer-container' ).append( new Anchor( footerAnchor ).$el );\n\t\t}\n\t\tconst headers = this.options.headers || [\n\t\t\theader(\n\t\t\t\tthis.options.heading,\n\t\t\t\tthis.options.headerActions\n\t\t\t)\n\t\t];\n\t\tthis.$el.find( '.overlay-header-container' ).append( headers );\n\t}\n\n\t/**\n\t * ClickBack event handler\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t * @param {Object} ev event object\n\t */\n\tonExitClick( ev ) {\n\t\tconst exit = () => {\n\t\t\tthis.hide();\n\t\t};\n\t\tev.preventDefault();\n\t\tev.stopPropagation();\n\t\tif ( this.options.onBeforeExit ) {\n\t\t\tthis.options.onBeforeExit( exit, () => {\n\t\t\t} );\n\t\t} else {\n\t\t\texit();\n\t\t}\n\n\t}\n\n\t/**\n\t * Attach overlay to current view and show it.\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t */\n\tshow() {\n\t\tconst $html = util.getDocument();\n\n\t\tthis.scrollTop = window.pageYOffset;\n\n\t\t$html.addClass( 'overlay-enabled' );\n\t\t// skip the URL bar if possible\n\t\twindow.scrollTo( 0, 1 );\n\n\t\tthis.$el.addClass( 'visible' );\n\n\t\t// If .hide() was called earlier, and it scheduled an asynchronous detach\n\t\t// but it hasn't happened yet, cancel it\n\t\tif ( this.hideTimeout !== null ) {\n\t\t\tclearTimeout( this.hideTimeout );\n\t\t\tthis.hideTimeout = null;\n\t\t}\n\t}\n\n\t/**\n\t * Detach the overlay from the current view\n\t * Should not be overriden as soon to be deprecated.\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t * @final\n\t * @return {boolean} Whether the overlay was successfully hidden or not\n\t */\n\thide() {\n\t\tutil.getDocument().removeClass( 'overlay-enabled' );\n\t\t// return to last known scroll position\n\t\twindow.scrollTo( window.pageXOffset, this.scrollTop );\n\n\t\t// Since the hash change event caused by emitting hide will be detected later\n\t\t// and to avoid the article being shown during a transition from one overlay to\n\t\t// another, we regretfully detach the element asynchronously.\n\t\tthis.hideTimeout = setTimeout( () => {\n\t\t\tthis.$el.detach();\n\t\t\tthis.hideTimeout = null;\n\t\t}, 0 );\n\n\t\t/**\n\t\t * Fired when the overlay is closed.\n\t\t *\n\t\t * @event Overlay#hide\n\t\t */\n\t\tthis.emit( 'hide' );\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Show elements that are selected by the className.\n\t * Also hide .hideable elements\n\t * Can't use jQuery's hide() and show() because show() sets display: block.\n\t * And we want display: table for headers.\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t * @protected\n\t * @param {string} className CSS selector to show\n\t */\n\tshowHidden( className ) {\n\t\tthis.$el.find( '.hideable' ).addClass( 'hidden' );\n\t\tthis.$el.find( className ).removeClass( 'hidden' );\n\t}\n}\n\n/**\n * Factory method for an overlay with a single child\n *\n * @memberof module:mobile.startup/Overlay\n * @instance\n * @protected\n * @param {Object} options\n * @param {module:mobile.startup/View} view\n * @return {module:mobile.startup/Overlay}\n */\nOverlay.make = function ( options, view ) {\n\tconst overlay = new Overlay( options );\n\toverlay.$el.find( '.overlay-content' ).append( view.$el );\n\treturn overlay;\n};\n\n/**\n * ES5 compatible version of class for backwards compatibility\n *\n * @param {Object} props\n * @deprecated 1.44\n * @ignore\n */\nfunction ClassES5( props ) {\n\tmw.log.warn( '[1.44] Extending Overlay class constructor is deprecated. Please use Overlay.make' );\n\tView.ClassES5.call( this, util.extend(\n\t\ttrue,\n\t\t{\n\t\t\theaderChrome: false,\n\t\t\tclassName: 'overlay'\n\t\t},\n\t\tprops,\n\t\t{\n\t\t\tevents: util.extend(\n\t\t\t\t{\n\t\t\t\t\t// FIXME: Remove .initial-header selector\n\t\t\t\t\t'click .cancel, .confirm, .initial-header .back': 'onExitClick',\n\t\t\t\t\tclick: ( ev ) => ev.stopPropagation()\n\t\t\t\t},\n\t\t\t\tprops.events\n\t\t\t)\n\t\t}\n\t) );\n}\nClassES5.prototype = Overlay.prototype;\nClassES5.make = Overlay.make;\n\nOverlay.ClassES5 = ClassES5;\nmodule.exports = Overlay;\n","const util = require( './util' );\n\nlet overlayManager = null;\n\n// We pass this to history.pushState/replaceState to indicate that we're controlling the page URL.\n// Then we look for this marker on page load so that if the page is refreshed, we don't generate an\n// extra history entry (see #getSingleton below and T201852).\nconst MANAGED_STATE = 'MobileFrontend OverlayManager was here!';\n\n/**\n * Manages opening and closing overlays when the URL hash changes to one\n * of the registered values (see OverlayManager.add()).\n *\n * This allows overlays to function like real pages, with similar browser back/forward\n * and refresh behavior.\n */\nclass OverlayManager {\n\t/**\n\t * @param {Router} router\n\t * @param {Element} container where overlays should be managed\n\t */\n\tconstructor( router, container ) {\n\t\trouter.on( 'route', this._checkRoute.bind( this ) );\n\t\tthis.router = router;\n\t\t// use an object instead of an array for entries so that we don't\n\t\t// duplicate entries that already exist\n\t\tthis.entries = {};\n\t\t// stack of all the open overlays, stack[0] is the latest one\n\t\tthis.stack = [];\n\t\tthis.hideCurrent = true;\n\t\t// Set the element that overlays will be appended to\n\t\tthis.container = container;\n\t}\n\n\t/**\n\t * Don't try to hide the active overlay on a route change event triggered\n\t * by hiding another overlay.\n\t * Called when something other than OverlayManager calls Overlay.hide\n\t * on an overlay that it itself managed by the OverlayManager.\n\t * MUST be called when the stack is not empty.\n\t *\n\t * @private\n\t */\n\t_onHideOverlayOutsideOverlayManager() {\n\t\tif ( !this.stack.length ) {\n\t\t\treturn;\n\t\t}\n\t\tconst currentRoute = this.stack[0].route,\n\t\t\trouteIsString = typeof currentRoute === 'string',\n\t\t\tcurrentPath = this.router.getPath(),\n\t\t\t// Since routes can be strings or regexes, it's important to do an equality\n\t\t\t// check BEFORE a match check.\n\t\t\trouteIsSame = ( routeIsString && currentPath === currentRoute ) ||\n\t\t\t\tcurrentPath.match( currentRoute );\n\n\t\tthis.hideCurrent = false;\n\n\t\t// If the path hasn't changed then the user didn't close the overlay by\n\t\t// calling history.back() or triggering a route change. We must go back\n\t\t// to get out of the overlay. See T237677.\n\t\tif ( routeIsSame ) {\n\t\t\t// does the route need to change?\n\t\t\tthis.router.back();\n\t\t}\n\t}\n\n\t/**\n\t * Attach overlay to DOM\n\t *\n\t * @private\n\t * @param {module:mobile.startup/Overlay} overlay to attach\n\t */\n\t_attachOverlay( overlay ) {\n\t\tif ( !overlay.$el.parents().length ) {\n\t\t\tthis.container.appendChild( overlay.$el[0] );\n\t\t}\n\t}\n\n\t/**\n\t * Show the overlay and bind the '_om_hide' event to _onHideOverlay.\n\t *\n\t * @private\n\t * @param {module:mobile.startup/Overlay} overlay to show\n\t */\n\t_show( overlay ) {\n\t\t// Mark the state so that if the page is refreshed, we don't generate an extra history entry\n\t\t// (see #getSingleton below and T201852).\n\t\t// eslint-disable-next-line no-restricted-properties\n\t\twindow.history.replaceState( MANAGED_STATE, null, window.location.href );\n\n\t\t// the _om_hide event is added to an overlay that is displayed.\n\t\t// It will fire if an Overlay emits a hide event (See attachHideEvent)\n\t\t// in the case where a route change has not occurred (this event is disabled\n\t\t// inside _hideOverlay which is called inside _checkRoute)\n\t\toverlay.once( '_om_hide', () => this._onHideOverlayOutsideOverlayManager() );\n\n\t\tthis._attachOverlay( overlay );\n\t\toverlay.show();\n\t}\n\n\t/**\n\t * Hide overlay\n\t *\n\t * @private\n\t * @param {module:mobile.startup/Overlay} overlay to hide\n\t * @param {Function} onBeforeExitCancel to pass to onBeforeExit\n\t * @return {boolean} Whether the overlay has been hidden\n\t */\n\t_hideOverlay( overlay, onBeforeExitCancel ) {\n\t\tlet result;\n\n\t\tfunction exit() {\n\t\t\tresult = true;\n\t\t\toverlay.hide();\n\t\t}\n\n\t\t// remove the callback for updating state when overlay closed using\n\t\t// overlay close button\n\t\toverlay.off( '_om_hide' );\n\n\t\tif ( overlay.options && overlay.options.onBeforeExit ) {\n\t\t\toverlay.options.onBeforeExit( exit, onBeforeExitCancel );\n\t\t} else {\n\t\t\texit();\n\t\t}\n\n\t\t// if closing prevented, reattach the callback\n\t\tif ( !result ) {\n\t\t\toverlay.once( '_om_hide', () => this._onHideOverlayOutsideOverlayManager() );\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Show match's overlay if match is not null.\n\t *\n\t * @private\n\t * @param {Object|null} match Object with factory function's result. null if no match.\n\t */\n\t_processMatch( match ) {\n\t\tif ( match ) {\n\t\t\tif ( match.overlay ) {\n\t\t\t\t// if the match is an overlay that was previously opened, reuse it\n\t\t\t\tthis._show( match.overlay );\n\t\t\t} else {\n\t\t\t\t// else create an overlay using the factory function result\n\t\t\t\tconst factoryResult = match.factoryResult;\n\t\t\t\t// We were getting errors relating to no factoryResult.\n\t\t\t\t// This should never happen.\n\t\t\t\t// If it does an error should not be thrown.\n\t\t\t\tif ( factoryResult ) {\n\t\t\t\t\tmatch.overlay = factoryResult;\n\t\t\t\t\tattachHideEvent( match.overlay );\n\t\t\t\t\tthis._show( factoryResult );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * A callback for Router's `route` event.\n\t *\n\t * @private\n\t * @param {jQuery.Event} ev Event object.\n\t */\n\t_checkRoute( ev ) {\n\t\tconst current = this.stack[0];\n\n\t\t// When entering an overlay for the first time,\n\t\t// the manager should remember the user's scroll position\n\t\t// overlays always open at top of page\n\t\t// and we'll want to restore it later.\n\t\t// This should happen before the call to _matchRoute which will \"show\" the overlay.\n\t\t// The Overlay has similar logic for overlays that are not managed via the overlay.\n\t\tif ( !current ) {\n\t\t\tthis.scrollTop = window.pageYOffset;\n\t\t}\n\n\t\t// if there is an overlay in the stack and it's opened, try to close it\n\t\tif (\n\t\t\tcurrent &&\n\t\t\tcurrent.overlay !== undefined &&\n\t\t\tthis.hideCurrent &&\n\t\t\t!this._hideOverlay( current.overlay, () => {\n\t\t\t\t// if hide prevented, prevent route change event\n\t\t\t\tev.preventDefault();\n\t\t\t} )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst match = Object.keys( this.entries ).reduce( ( m, id ) => m ||\n\t\t\tthis._matchRoute( ev.path, this.entries[id] ), null );\n\n\t\tif ( !match ) {\n\t\t\t// if hidden and no new matches, reset the stack\n\t\t\tthis.stack = [];\n\t\t\t// restore the scroll position.\n\t\t\twindow.scrollTo( window.pageXOffset, this.scrollTop );\n\t\t}\n\n\t\tthis.hideCurrent = true;\n\t\tthis._processMatch( match );\n\t}\n\n\t/**\n\t * Check if a given path matches one of the existing entries and\n\t * remove it from the stack.\n\t *\n\t * @private\n\t * @param {string} path Path (hash) to check.\n\t * @param {Object} entry Entry object created in OverlayManager#add.\n\t * @return {Object|null} Match object with factory function's result.\n\t *  Returns null if no match.\n\t */\n\t_matchRoute( path, entry ) {\n\t\tlet\n\t\t\tdidMatch,\n\t\t\tcaptures,\n\t\t\tmatch;\n\n\t\tconst previous = this.stack[1];\n\n\t\tif ( typeof entry.route === 'string' ) {\n\t\t\tdidMatch = entry.route === path;\n\t\t\tcaptures = [];\n\t\t} else {\n\t\t\tmatch = path.match( entry.route );\n\t\t\tdidMatch = !!match;\n\t\t\tcaptures = didMatch ? match.slice( 1 ) : [];\n\t\t}\n\n\t\t/**\n\t\t * Returns object to add to stack\n\t\t *\n\t\t * @method\n\t\t * @ignore\n\t\t * @return {Object}\n\t\t */\n\t\tconst getNext = () => ( {\n\t\t\tpath,\n\t\t\t// Important for managing states of things such as the image overlay which change\n\t\t\t// overlay routing parameters during usage.\n\t\t\troute: entry.route,\n\t\t\tfactoryResult: entry.factory.apply( this, captures )\n\t\t} );\n\n\t\tif ( didMatch ) {\n\t\t\t// if previous stacked overlay's path matches, assume we're going back\n\t\t\t// and reuse a previously opened overlay\n\t\t\tif ( previous && previous.path === path ) {\n\t\t\t\tthis.stack.shift();\n\t\t\t\treturn previous;\n\t\t\t} else {\n\t\t\t\tconst next = getNext();\n\t\t\t\tif ( this.stack[0] && next.path === this.stack[0].path ) {\n\t\t\t\t\t// current overlay path is same as path to check which means overlay\n\t\t\t\t\t// is attempting to refresh so just replace current overlay with new\n\t\t\t\t\t// overlay\n\t\t\t\t\tthis.stack[0] = next;\n\t\t\t\t} else {\n\t\t\t\t\tthis.stack.unshift( next );\n\t\t\t\t}\n\t\t\t\treturn next;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Add an overlay that should be shown for a specific fragment identifier.\n\t *\n\t * The following code will display an overlay whenever a user visits a URL that\n\t * ends with '#/hi/name'. The value of `name` will be passed to the overlay.\n\t * Note the factory must return an Overlay.\n\t * If the overlay needs to load code asynchronously that should be done inside\n\t * the overlay.\n\t *\n\t *     @example\n\t *     overlayManager.add( /\\/hi\\/(.*)/, function ( name ) {\n\t *         var HiOverlay = M.require( 'HiOverlay' );\n\t *         return new HiOverlay( { name: name } ) );\n\t *     } );\n\t *\n\t * @param {RegExp|string} route definition that can be a regular\n\t * expression (optionally with parameters) or a string literal.\n\t *\n\t * T238364: Routes should only contain characters allowed by RFC3986 to ensure\n\t * compatibility across browsers. Encode the route with `encodeURIComponent()`\n\t * prior to registering it with OverlayManager if necessary (should probably\n\t * be done with all routes containing user generated characters) to avoid\n\t * inconsistencies with how different browsers encode illegal URI characters:\n\t *\n\t * ```\n\t *   var encodedRoute = encodeURIComponent('ugc < \" ` >');\n\t *\n\t *   overlayManager.add(\n\t *     encodedRoute,\n\t *     function () { return new Overlay(); }\n\t *   );\n\t *\n\t *   window.location.hash = '#' + encodedRoute;\n\t * ```\n\t * The above example shows how to register a string literal route with illegal\n\t * URI characters. Routes registered as a regex will likely NOT have to\n\t * perform any encoding (unless they explicitly contain illegal URI\n\t * characters) as their user generated content portion will likely just be a\n\t * capturing group (e.g. `/\\/hi\\/(.*)/`).\n\t * @param {Function} factory a function returning an overlay\n\t */\n\tadd( route, factory ) {\n\t\tconst entry = {\n\t\t\troute,\n\t\t\tfactory\n\t\t};\n\n\t\tthis.entries[route] = entry;\n\t\t// Check if overlay should be shown for the current path.\n\t\t// The DOM must fully load before we can show the overlay because Overlay relies on it.\n\t\tutil.docReady( () => this._processMatch( this._matchRoute( this.router.getPath(),\n\t\t\tentry ) ) );\n\t}\n\n\t/**\n\t * Replace the currently displayed overlay with a new overlay without changing the\n\t * URL. This is useful for when you want to switch overlays, but don't want to\n\t * change the back button or close box behavior.\n\t *\n\t * @param {Object} overlay The overlay to display\n\t */\n\treplaceCurrent( overlay ) {\n\t\tif ( this.stack.length === 0 ) {\n\t\t\tthrow new Error( \"Trying to replace OverlayManager's current overlay, but stack is empty\" );\n\t\t}\n\t\tconst stackOverlay = this.stack[0].overlay;\n\t\tif ( stackOverlay ) {\n\t\t\tthis._hideOverlay( stackOverlay );\n\t\t}\n\t\tthis.stack[0].overlay = overlay;\n\t\tattachHideEvent( overlay );\n\t\tthis._show( overlay );\n\t}\n\n\t/**\n\t * Retrieve a singleton instance using 'mediawiki.router'.\n\t *\n\t * @memberof module:mobile.startup/OverlayManager\n\t * @return {module:mobile.startup/OverlayManager}\n\t */\n\tstatic getSingleton() {\n\t\tif ( !overlayManager ) {\n\t\t\tconst\n\t\t\t\trouter = __non_webpack_require__( 'mediawiki.router' ),\n\t\t\t\tcontainer = document.createElement( 'div' ),\n\t\t\t\t// Note getPath returns hash minus the '#' character:\n\t\t\t\thash = router.getPath(),\n\t\t\t\t// eslint-disable-next-line no-restricted-properties\n\t\t\t\tstate = window.history.state;\n\t\t\tcontainer.className = 'mw-overlays-container';\n\t\t\tdocument.body.appendChild( container );\n\t\t\t// If an overlay was loaded by directly navigating to an URL with a hash (e.g. linked from\n\t\t\t// another page or browser bookmark), generate an extra history entry to allow closing the\n\t\t\t// overlay without leaving the page (see T201852). Put our marker into the entry state so\n\t\t\t// that we can detect it if the page is refreshed and do not generate another entry.\n\t\t\tif ( hash && state !== MANAGED_STATE ) {\n\t\t\t\t// eslint-disable-next-line no-restricted-properties\n\t\t\t\twindow.history.replaceState( null, null, '#' );\n\t\t\t\t// eslint-disable-next-line no-restricted-properties\n\t\t\t\twindow.history.pushState( MANAGED_STATE, null, `#${ hash }` );\n\t\t\t}\n\t\t\toverlayManager = new OverlayManager( router, container );\n\t\t}\n\t\treturn overlayManager;\n\t}\n}\n\n/**\n * Attach an event to the overlays hide event\n *\n * @param {module:mobile.startup/Overlay} overlay\n * @private\n */\nfunction attachHideEvent( overlay ) {\n\toverlay.on( 'hide', () => overlay.emit( '_om_hide' ) );\n}\n\nOverlayManager.test = {\n\tMANAGED_STATE,\n\t__clearCache: () => {\n\t\toverlayManager = null;\n\t}\n};\nmodule.exports = OverlayManager;\n","const\n\tHTML = mw.html,\n\tutil = require( './util' );\n\n/**\n * Mobile page view object\n */\nclass Page {\n\t/**\n\t * @param {Object} options Configuration options\n\t * @param {number} options.id Page ID. The default value of 0 represents a\n\t * new or missing page. Be sure to override it to avoid side effects.\n\t * @param {string} options.title Title of the page. It includes prefix where needed and\n\t * is human readable, e.g. Talk:The man who lived.\n\t * @param {Object} options.titleObj\n\t * @param {string} options.displayTitle HTML title of the page for display. Falls back\n\t * to defaults.title (escaped) if no value is provided. Must be safe HTML!\n\t * @param {number} options.namespaceNumber the number of the\n\t *  namespace the page belongs to\n\t * @param {Object} options.protection List of permissions as returned by API,\n\t * e.g. [{ edit: ['*'] }]\n\t * @param {string} options.url\n\t * @param {string} options.wikidataDescription\n\t * @param {boolean} options.isMainPage Whether the page is the Main Page.\n\t * @param {boolean} options.isMissing Whether the page exists in the wiki.\n\t * @param {string} options.anchor\n\t * @param {string} [options.relevantTitle] associated with page.\n\t *  For example Special:WhatLinksHere/Foo would be associated with the page `Foo`.\n\t * @param {number} options.revId  Revision ID. See `wgRevisionId`.\n\t * @param {boolean} options.isWatched Whether the page is being watched\n\t * @param {Object} options.thumbnail thumbnail definition corresponding to page image\n\t * @param {boolean} options.thumbnail.isLandscape whether the image is in\n\t *  landscape format\n\t * @param {number} options.thumbnail.width of image in pixels.\n\t * @param {number} options.thumbnail.height of image in pixels.\n\t * @param {string} options.thumbnail.source url for image\n\t */\n\tconstructor( options ) {\n\t\tconst title = options.title || '';\n\t\tutil.extend( this, {\n\t\t\tid: options.id || 0,\n\t\t\t// FIXME: Deprecate title property as it can be derived from titleObj\n\t\t\t// using getPrefixedText\n\t\t\ttitle,\n\t\t\trelevantTitle: options.relevantTitle || title,\n\t\t\ttitleObj: options.titleObj,\n\t\t\tdisplayTitle: options.displayTitle || HTML.escape( title ),\n\t\t\tnamespaceNumber: options.namespaceNumber || 0,\n\t\t\tprotection: options.protection,\n\t\t\turl: options.url || mw.util.getUrl( title ),\n\t\t\twikidataDescription: options.wikidataDescription,\n\t\t\t_isMainPage: options.isMainPage || false,\n\t\t\tisMissing: ( options.isMissing !== undefined ) ?\n\t\t\t\toptions.isMissing : options.id === 0,\n\t\t\tanchor: options.anchor,\n\t\t\trevId: options.revId,\n\t\t\t_isWatched: options.isWatched,\n\t\t\tthumbnail: ( Object.prototype.hasOwnProperty.call( options, 'thumbnail' ) ) ?\n\t\t\t\toptions.thumbnail : false\n\t\t} );\n\n\t\tif ( this.thumbnail && this.thumbnail.width ) {\n\t\t\tthis.thumbnail.isLandscape = this.thumbnail.width > this.thumbnail.height;\n\t\t}\n\t}\n\n\t/**\n\t * Retrieve the title that should be displayed to the user\n\t *\n\t * @return {string} HTML\n\t */\n\tgetDisplayTitle() {\n\t\treturn this.displayTitle;\n\t}\n\n\t/**\n\t * Determine if current page is in a specified namespace\n\t *\n\t * @param {string} namespace Name of namespace\n\t * @return {boolean}\n\t */\n\tinNamespace( namespace ) {\n\t\treturn this.namespaceNumber === mw.config.get( 'wgNamespaceIds' )[namespace];\n\t}\n\n\t/**\n\t * Determines if content model is wikitext\n\t *\n\t * @return {boolean}\n\t */\n\tisWikiText() {\n\t\treturn mw.config.get( 'wgPageContentModel' ) === 'wikitext';\n\t}\n\n\t/**\n\t * Check if the visual editor is available on this page\n\t *\n\t * @return {boolean}\n\t */\n\tisVEAvailable() {\n\t\treturn !!mw.config.get( 'wgVisualEditorConfig' ) &&\n\t\t\t!mw.config.get( 'wgVisualEditorDisabledByHook' ) &&\n\t\t\tthis.isWikiText();\n\t}\n\n\t/**\n\t * Check if the visual editor in visual mode is available on this page\n\t *\n\t * @return {boolean}\n\t */\n\tisVEVisualAvailable() {\n\t\tif ( !this.isVEAvailable() ) {\n\t\t\treturn false;\n\t\t}\n\t\tconst config = mw.config.get( 'wgVisualEditorConfig' );\n\t\tconst visualEditorNamespaces = config.namespaces || [];\n\n\t\treturn visualEditorNamespaces.indexOf( mw.config.get( 'wgNamespaceNumber' ) ) !== -1;\n\t}\n\n\t/**\n\t * Check if the visual editor in source mode is available on this page\n\t *\n\t * @return {boolean}\n\t */\n\tisVESourceAvailable() {\n\t\treturn this.isVEAvailable() &&\n\t\t\tmw.config.get( 'wgMFEnableVEWikitextEditor' );\n\t}\n\n\t/**\n\t * Checks whether the current page is the main page\n\t *\n\t * @return {boolean}\n\t */\n\tisMainPage() {\n\t\treturn this._isMainPage;\n\t}\n\n\t/**\n\t * Checks whether the current page is watched\n\t *\n\t * @return {boolean}\n\t */\n\tisWatched() {\n\t\treturn this._isWatched;\n\t}\n\n\t/**\n\t * Return the latest revision id for this page\n\t *\n\t * @return {number}\n\t */\n\tgetRevisionId() {\n\t\treturn this.revId;\n\t}\n\n\t/**\n\t * Return prefixed page title\n\t *\n\t * @return {string}\n\t */\n\tgetTitle() {\n\t\treturn this.title;\n\t}\n\n\t/**\n\t * return namespace id\n\t *\n\t * @return {number} namespace Number\n\t */\n\tgetNamespaceId() {\n\t\tlet nsId;\n\t\tconst args = this.title.split( ':' );\n\n\t\tif ( args[1] ) {\n\t\t\tnsId = mw.config.get( 'wgNamespaceIds' )[ args[0].toLowerCase().replace( ' ', '_' ) ] || 0;\n\t\t} else {\n\t\t\tnsId = 0;\n\t\t}\n\t\treturn nsId;\n\t}\n}\n\nmodule.exports = Page;\n","const\n\tThumbnail = require( './Thumbnail' ),\n\tHEADING_SELECTOR = mw.config.get( 'wgMFMobileFormatterHeadings', [ 'h1', 'h2', 'h3', 'h4', 'h5' ] ).join( ',' ),\n\tEXCLUDE_THUMBNAIL_CLASS_SELECTORS = [ 'noviewer', 'metadata' ],\n\tNOT_SELECTORS = EXCLUDE_THUMBNAIL_CLASS_SELECTORS.map( ( excludeSelector ) => `:not(.${ excludeSelector })` ).join( '' ),\n\tTHUMB_SELECTOR = [ 'a.image', 'a.thumbimage, a.mw-file-description' ].map(\n\t\t( selector ) => `${ selector }${ NOT_SELECTORS }`\n\t).join( ',' );\n\n/**\n * Parses an article and converts it into a queriable object.\n */\nclass PageHTMLParser {\n\t/**\n\t * @param {jQuery.Object} $container Used when parsing to find children within\n\t * this container\n\t */\n\tconstructor( $container ) {\n\t\tthis.$el = $container;\n\n\t\t// T220751: Cache headings as $el.find is a very expensive call.\n\t\t/** @private */\n\t\tthis.$headings = this.$el.find( HEADING_SELECTOR );\n\t}\n\n\t/**\n\t * Find the heading in the page.\n\t * This has the benefit of excluding any additional h2s and h3s that may\n\t * have been added programatically.\n\t *\n\t * @param {number} sectionIndex as defined by the PHP parser.\n\t *  It should correspond to the section id\n\t *  used in the edit link for the section.\n\t *  Note, confusingly, this is different from section \"ID\" which is\n\t * used in methods\n\t * @return {jQuery.Object}\n\t */\n\tfindSectionHeadingByIndex( sectionIndex ) {\n\t\tif ( sectionIndex < 1 ) {\n\t\t\t// negative indexes will search from the end, which is behaviour we do not want.\n\t\t\t// return an empty set when this happens.\n\t\t\t// eslint-disable-next-line no-undef\n\t\t\treturn $( [] );\n\t\t} else {\n\t\t\treturn this.$headings\n\t\t\t\t// Headings must strictly be a child element of a section element\n\t\t\t\t// or the parser-output.\n\t\t\t\t// Not an ancestor!\n\t\t\t\t.filter( '.mw-parser-output > *, [class^=\"mf-section-\"] > *' ).eq( sectionIndex - 1 );\n\t\t}\n\t}\n\n\t/**\n\t * Finds all child elements that match the selector in a given section or subsection.\n\t * Returns any direct child elements that match the selector,\n\t * (i.e. searches only one level deep)\n\t * as well as any elements that match the selector within those children.\n\t * If the Page has no headings (e.g. a stub),\n\t * then the search will target all nodes within the page.\n\t *\n\t * This code should work on desktop (PHP parser HTML)\n\t * as well as mobile formatted HTML (PHP parser + MobileFormatter)\n\t *\n\t * @param {number} sectionIndex as defined by the PHP parser. It should correspond to\n\t *  the section id used in the edit link for the section.\n\t *  Note, confusingly, this is different from section \"ID\" which is\n\t *  used in methods\n\t * @param {string} selector to match\n\t * @return {jQuery.Object}\n\t */\n\tfindChildInSectionLead( sectionIndex, selector ) {\n\t\tlet $heading, $nextHeading;\n\n\t\tconst headingSelector = HEADING_SELECTOR;\n\n\t\tfunction withNestedChildren( $matchingNodes ) {\n\t\t\treturn $matchingNodes.find( selector ).addBack();\n\t\t}\n\n\t\tif ( sectionIndex === 0 ) {\n\t\t\t// lead is easy\n\t\t\tconst $lead = this.getLeadSectionElement();\n\t\t\tif ( $lead && $lead.length ) {\n\n\t\t\t\t// Handle nested sections in Parsoid wikitext parset opt-in scenario.\n\t\t\t\tconst $nestedSection = $lead.find( 'section[data-mw-section-id=\"0\"]' );\n\t\t\t\tif ( $nestedSection.length ) {\n\t\t\t\t\treturn withNestedChildren( $nestedSection.children( selector ) );\n\t\t\t\t}\n\n\t\t\t\treturn withNestedChildren( $lead.children( selector ) );\n\t\t\t} else {\n\t\t\t\t$heading = this.findSectionHeadingByIndex( 1 );\n\t\t\t\treturn $heading.length ? withNestedChildren( $heading.prevAll( selector ) ) :\n\t\t\t\t\t// this page is a stub so search entire page\n\t\t\t\t\tthis.$el.find( selector );\n\t\t\t}\n\t\t}\n\n\t\t// find heading associated with the section by looking at its\n\t\t// index position in the article\n\t\t// section ids relate to the element position in the page and the first heading\n\t\t// lead has been dealt with above, so first heading corresponds to section 1,\n\t\t// the first heading in the article.\n\t\t$heading = this.findSectionHeadingByIndex( sectionIndex );\n\n\t\t// If section-heading is present on the heading,\n\t\t// then we know the page has been MobileFormatted\n\t\t// and that this is a wrapped section\n\t\tif ( $heading.hasClass( 'section-heading' ) ) {\n\t\t\t// get content of section\n\t\t\tconst $el = $heading.next();\n\t\t\t// inside section find the first heading\n\t\t\t$nextHeading = $el.find( headingSelector ).eq( 0 );\n\t\t\treturn $nextHeading.length ?\n\t\t\t\t// find all amboxes before the next heading\n\t\t\t\twithNestedChildren( $nextHeading.prevAll( selector ) ) :\n\t\t\t\t// There is no subheadings inside\n\t\t\t\t// Grab all issues in section\n\t\t\t\twithNestedChildren( $el.children( selector ) );\n\t\t} else {\n\t\t\t// the heading relates to a subsection (or unwrapped desktop section),\n\t\t\t// so grab elements between this and the next one\n\t\t\t$nextHeading = $heading.eq( 0 ).nextAll( headingSelector ).eq( 0 );\n\t\t\treturn $heading.nextUntil( $nextHeading, selector );\n\t\t}\n\t}\n\n\t/**\n\t * Get the lead section of the page view.\n\t *\n\t * @return {jQuery.Object|null}\n\t */\n\tgetLeadSectionElement() {\n\t\t/*\n\t\t * The page is formatted as follows:\n\t\t * <div id=\"bodyContent\">\n\t\t *   <!-- content of the page.. -->\n\t\t *   <div id=\"mw-content-text\">\n\t\t *     <div class=\"mf-section-0\">lead section</div>\n\t\t *     <h2></h2>\n\t\t *     <div class=\"mf-section-1\">second section</div>\n\t\t *   </div>\n\t\t * </div>\n\t\t */\n\t\tconst $leadSection = this.$el.find( '.mf-section-0' );\n\n\t\tif ( $leadSection.length ) {\n\t\t\treturn $leadSection;\n\t\t}\n\t\t// no lead section found\n\t\treturn null;\n\t}\n\n\t/**\n\t * Returns a Thumbnail object from an anchor element containing an image or\n\t * null if not valid.\n\t *\n\t * @param {jQuery} $a Anchor element that contains the image.\n\t * @return {Thumbnail|null}\n\t */\n\tgetThumbnail( $a ) {\n\t\tconst notSelector = '.' + EXCLUDE_THUMBNAIL_CLASS_SELECTORS.join( ',.' ),\n\t\t\t$lazyImage = $a.find( '.lazy-image-placeholder' ),\n\t\t\thref = $a.attr( 'href' ),\n\t\t\turl = href && new URL( href, location.href ),\n\t\t\tlegacyTitle = url && url.searchParams.get( 'title' ),\n\t\t\tmatch = url && url.pathname.match( /[^/]+$/ );\n\n\t\t// Parents need to be checked as well.\n\t\tlet valid = $a.parents( notSelector ).length === 0 &&\n\t\t\t$a.find( notSelector ).length === 0;\n\n\t\t// filter out invalid lazy loaded images if so far image is valid\n\t\tif ( $lazyImage.length && valid ) {\n\t\t\t// if the regex matches it means the image has one of the classes\n\t\t\t// thus we must invert the result\n\t\t\tvalid = !new RegExp( '\\\\b(' + EXCLUDE_THUMBNAIL_CLASS_SELECTORS.join( '|' ) + ')\\\\b' )\n\t\t\t\t.test( $lazyImage.data( 'class' ) );\n\t\t}\n\n\t\tif ( valid && ( legacyTitle !== null || match ) ) {\n\t\t\treturn new Thumbnail( {\n\t\t\t\tel: $a,\n\t\t\t\tfilename: mw.util.percentDecodeFragment(\n\t\t\t\t\tlegacyTitle !== null ? legacyTitle : match[0]\n\t\t\t\t)\n\t\t\t} );\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Return all the thumbnails in the article.\n\t * Images which have a class or link container (.image|.thumbimage)\n\t * that matches one of the items of the constant EXCLUDE_THUMBNAIL_CLASS_SELECTORS\n\t * will be excluded.\n\t * A thumbnail nested inside one of these classes will still be returned.\n\t * e.g. `<div class=\"noviewer\"><a class=\"image\"><img></a></div>` is not a valid thumbnail\n\t * `<a class=\"image noviewer\"><img></a>` is not a valid thumbnail\n\t * `<a class=\"image\"><img class=\"noviewer\"></a>` is not a valid thumbnail\n\t *\n\t * @param {jQuery} [$el] Container to search, defaults to this.$el.\n\t * @return {Thumbnail[]}\n\t */\n\tgetThumbnails( $el ) {\n\t\tconst thumbs = [];\n\n\t\t$el = $el || this.$el;\n\n\t\tconst $thumbs = $el.find( THUMB_SELECTOR );\n\n\t\t$thumbs.each( ( i, thumbEl ) => {\n\t\t\tconst $a = $el.find( thumbEl );\n\t\t\tconst thumb = this.getThumbnail( $a );\n\n\t\t\tif ( thumb ) {\n\t\t\t\tthumbs.push( thumb );\n\t\t\t}\n\t\t} );\n\t\treturn thumbs;\n\t}\n\n\t/**\n\t * Returns a jQuery object representing all redlinks on the page.\n\t *\n\t * @return {jQuery.Object}\n\t */\n\tgetRedLinks() {\n\t\treturn this.$el.find( '.new' );\n\t}\n\n\t/**\n\t * Returns an object consistent with MediaWiki API representing languages\n\t * associated with the page in the user's current language.\n\t *\n\t * @param {string} pageTitle to fallback to if none found\n\t * @return {Object} containing langlinks\n\t *   and variant links as defined @ https://en.m.wikipedia.org/w/api.php?action=help&modules=query%2Blanglinks\n\t */\n\tgetLanguages( pageTitle ) {\n\t\tconst mapLinkToLanguageObj = ( node ) => {\n\t\t\t// Name of language (e.g. עברית for Hebrew)\n\t\t\tconst autonym = node.textContent;\n\t\t\t// The name of the language in the current language\n\t\t\t// e.g. for english this would be Hebrew\n\t\t\tconst langname = node.getAttribute( 'data-language-local-name' ) || autonym;\n\t\t\tconst title = node.getAttribute( 'data-title' ) || pageTitle;\n\n\t\t\treturn {\n\t\t\t\tlang: node.getAttribute( 'hreflang' ),\n\t\t\t\tautonym,\n\t\t\t\tlangname,\n\t\t\t\ttitle,\n\t\t\t\turl: node.getAttribute( 'href' )\n\t\t\t};\n\t\t};\n\t\treturn {\n\t\t\tlanguages: Array.prototype.map.call(\n\t\t\t\tdocument.querySelectorAll( '#p-lang .interlanguage-link a' ),\n\t\t\t\tmapLinkToLanguageObj\n\t\t\t),\n\t\t\tvariants: Array.prototype.map.call(\n\t\t\t\tdocument.querySelectorAll( '#p-variants li a' ),\n\t\t\t\tmapLinkToLanguageObj\n\t\t\t)\n\t\t};\n\t}\n}\n\n/**\n * Selector for matching headings\n */\nPageHTMLParser.HEADING_SELECTOR = HEADING_SELECTOR;\n\n/**\n * Selector for thumbnails.\n */\nPageHTMLParser.THUMB_SELECTOR = THUMB_SELECTOR;\n\nmodule.exports = PageHTMLParser;\n","const util = require( './util.js' ),\n\tView = require( './View' ),\n\tbrowser = require( './Browser' ).getSingleton();\n\n/**\n * List of items page view\n */\nclass PageList extends View {\n\tconstructor( params ) {\n\t\tsuper( params );\n\t}\n\n\t/**\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {Page[]} defaults.pages Array of Page objects. These should match\n\t *                              the Page model and not necessarily the\n\t *                              underlying API format used.\n\t * E.g. [\n\t *   {\n\t *     heading: \"<strong>C</strong>laude Monet\",\n\t *     id: undefined,\n\t *     title: \"Claude Monet\",\n\t *     displayTitle: \"<i>Claude Monet</i>\",\n\t *     url: \"/wiki/Claude_Monet\",\n\t *     thumbnail: {\n\t *       height: 62,\n\t *       source: \"http://127.0.0.1:8080/images/thumb/thumb.jpg\",\n\t *       width: 80,\n\t *       isLandscape: true\n\t *     }\n\t *   }\n\t * ]\n\t */\n\tget defaults() {\n\t\treturn {\n\t\t\tpages: []\n\t\t};\n\t}\n\n\t/**\n\t * Render page images for the existing page list. Assumes no page images have been loaded.\n\t */\n\trenderPageImages() {\n\t\tsetTimeout( () => {\n\t\t\tthis.$el.find( '.list-thumb' ).each( ( i, thumbEl ) => {\n\t\t\t\tconst style = this.$el.find( thumbEl ).data( 'style' );\n\t\t\t\tthis.$el.find( thumbEl ).attr( 'style', style );\n\t\t\t} );\n\t\t\t// Delay an unnecessary load of images on mobile (slower?) connections\n\t\t\t// In particular on search results which can be regenerated quickly.\n\t\t}, browser.isWideScreen() ? 0 : 1000 );\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tpostRender() {\n\t\tthis.renderPageImages();\n\t}\n\n\tget template() {\n\t\treturn util.template( `\n<ul class=\"mw-mf-page-list thumbs actionable\">\n\t{{#pages}}\n\t\t{{>item}}\n\t{{/pages}}\n</ul>\n\t` );\n\t}\n\n\tget templatePartials() {\n\t\treturn {\n\t\t\t// The server uses a very different structure in\n\t\t\t// SpecialMobileEditWatchlist.getLineHtml(). Be aware of these differences\n\t\t\t// when updating server rendered items.\n\t\t\titem: util.template( `\n\t<li title=\"{{title}}\" data-id=\"{{id}}\" class=\"page-summary\">\n\t<a href=\"{{url}}\" class=\"title {{#isMissing}}new{{/isMissing}}\"\n\t\t{{#anchor}}name=\"{{anchor}}\"{{/anchor}}\n\t\tdata-title=\"{{title}}\">\n\t\t<div class=\"list-thumb\n\t\t{{#thumbnail.isLandscape}}list-thumb-y{{/thumbnail.isLandscape}}\n\t\t{{^thumbnail.isLandscape}}list-thumb-x{{/thumbnail.isLandscape}}\"\n\t\t{{#thumbnail}}data-style=\"background-image: url( {{thumbnail.source}} )\"{{/thumbnail}}>\n\t\t{{^thumbnail}}<span class=\"mf-icon-image\"></span>{{/thumbnail}}\n\t\t</div>\n\t\t<h3>{{{displayTitle}}}</h3>\n\t\t{{#wikidataDescription}}\n\t\t<div class=\"wikidata-description\">{{wikidataDescription}}</div>\n\t\t{{/wikidataDescription}}\n\t</a>\n\t</li>\n\t\t` )\n\t\t};\n\t}\n}\n\nmodule.exports = PageList;\n","const browser = require( './Browser' ).getSingleton(),\n\tView = require( './View' ),\n\tutil = require( './util' ),\n\tcurrentPage = require( './currentPage' ),\n\teventBus = require( './eventBusSingleton' );\n\nlet skin;\n\n/**\n * Representation of the current skin being rendered.\n *\n * @uses Browser\n * @uses Page\n * @fires Skin#click\n */\nclass Skin extends View {\n\t/**\n\t * @param {Object} params Configuration options\n\t * @param {OO.EventEmitter} params.eventBus Object used to listen for\n\t * @param {Page} params.page\n\t * scroll:throttled, resize:throttled, and section-toggled events\n\t */\n\tconstructor( params ) {\n\t\tconst options = util.extend( {\n\t\t\tisBorderBox: false\n\t\t}, params );\n\t\tsuper( options );\n\t\tthis.page = options.page;\n\t\tthis.name = options.name;\n\t\tthis.eventBus = options.eventBus;\n\t}\n\n\t/**\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {Page} defaults.page page the skin is currently rendering\n\t */\n\tget defaults() {\n\t\treturn {\n\t\t\tpage: undefined\n\t\t};\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tpostRender() {\n\t\tconst $el = this.$el;\n\n\t\tif ( browser.supportsTouchEvents() ) {\n\t\t\t$el.addClass( 'touch-events' );\n\t\t}\n\n\t\t/**\n\t\t * Fired when the skin is clicked.\n\t\t *\n\t\t * @event Skin#click\n\t\t */\n\t\tthis.$el.find( '#mw-mf-page-center' ).on( 'click', ( ev ) => {\n\t\t\tthis.emit( 'click', ev );\n\t\t} );\n\t}\n\n\t/**\n\t * @throws {Error} if mediawiki message is in unexpected format.\n\t * @return {jQuery.Object} a list of links\n\t */\n\tgetLicenseLinks() {\n\t\tconst mobileLicense = mw.message( 'mobile-frontend-license-links' );\n\t\tconst mobileMsgExists = mobileLicense.exists() && mobileLicense.text();\n\t\tconst userLanguage = mw.config.get( 'wgUserLanguage' );\n\t\tif ( userLanguage === 'qqx' ) {\n\t\t\t// Special handling for qqx code so we can easily debug what's going on here.\n\t\t\treturn mobileLicense.parseDom();\n\t\t} else {\n\t\t\treturn mobileMsgExists ? mobileLicense.parseDom() : this.$el.find( '#footer-info-copyright a' ).clone();\n\t\t}\n\t}\n\n\t/**\n\t * Returns the appropriate license message including links/name to\n\t * terms of use (if any) and license page\n\t *\n\t * @return {string|undefined}\n\t */\n\tgetLicenseMsg() {\n\t\tconst $licenseLinks = this.getLicenseLinks();\n\n\t\tlet licenseMsg;\n\t\tif ( $licenseLinks.length ) {\n\t\t\tconst licensePlural = mw.language.convertNumber(\n\t\t\t\t$licenseLinks.filter( 'a' ).length\n\t\t\t);\n\n\t\t\tif ( this.$el.find( '#footer-places-terms-use' ).length > 0 ) {\n\n\t\t\t\tconst $termsLink = mw.message(\n\t\t\t\t\t'mobile-frontend-editor-terms-link',\n\t\t\t\t\tthis.$el.find( '#footer-places-terms-use a' ).attr( 'href' )\n\t\t\t\t).parseDom();\n\t\t\t\tlicenseMsg = mw.message(\n\t\t\t\t\t'mobile-frontend-editor-licensing-with-terms',\n\t\t\t\t\t$termsLink,\n\t\t\t\t\t$licenseLinks,\n\t\t\t\t\tlicensePlural\n\t\t\t\t).parse();\n\t\t\t} else {\n\t\t\t\tlicenseMsg = mw.message(\n\t\t\t\t\t'mobile-frontend-editor-licensing',\n\t\t\t\t\t$licenseLinks,\n\t\t\t\t\tlicensePlural\n\t\t\t\t).parse();\n\t\t\t}\n\t\t}\n\n\t\treturn licenseMsg;\n\t}\n}\n\n/**\n * Get a skin singleton\n *\n * @return {Skin}\n */\nSkin.getSingleton = function () {\n\tif ( !skin ) {\n\t\tskin = new Skin( {\n\t\t\tel: 'body',\n\t\t\tpage: currentPage(),\n\t\t\teventBus\n\t\t} );\n\t}\n\treturn skin;\n};\nmodule.exports = Skin;\n","const\n\tutil = require( './util' ),\n\tView = require( './View' );\n\n/**\n * Representation of a thumbnail\n */\nclass Thumbnail extends View {\n\t/**\n\t * @param {Object} options\n\t */\n\tconstructor( options ) {\n\t\tsuper(\n\t\t\tutil.extend( { isBorderBox: false }, options )\n\t\t);\n\t}\n\n\t/**\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} defaults.filename uri decoded filename including File: prefix\n\t *  associated with thumbnail\n\t */\n\tget defaults() {\n\t\treturn {\n\t\t\tfilename: undefined\n\t\t};\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tpostRender() {\n\t\tthis.options.description = this.$el.siblings( '.thumbcaption, figcaption' )\n\t\t\t.prop( 'innerText' ) || '';\n\t}\n\n\t/**\n\t * Obtain description for thumbnail\n\t *\n\t * @return {string}\n\t */\n\tgetDescription() {\n\t\treturn this.options.description;\n\t}\n\n\t/**\n\t * Return the page title for the thumbnail\n\t *\n\t * @return {string}\n\t */\n\tgetFileName() {\n\t\treturn this.options.filename;\n\t}\n}\n\nmodule.exports = Thumbnail;\n","/* global $ */\nconst util = require( './util' ),\n\t// Cached regex to split keys for `delegate`.\n\tdelegateEventSplitter = /^(\\S+)\\s*(.*)$/;\n\nlet idCounter = 0;\n\n/**\n * Generate a unique integer id (unique within the entire client session).\n * Useful for temporary DOM ids.\n *\n * @private\n * @param {string} prefix Prefix to be used when generating the id.\n * @return {string}\n */\nfunction uniqueId( prefix ) {\n\tconst id = ( ++idCounter ).toString();\n\treturn prefix ? prefix + id : id;\n}\n\n/**\n * Describes a component for rendering.\n *\n * Should be extended using extend().\n *\n * When options contains el property, this.$el in the constructed object\n * will be set to the corresponding jQuery object. Otherwise, this.$el\n * will be an empty div.\n *\n * When extended using extend(), if the extended prototype contains\n * template property, this.$el will be filled with rendered template (with\n * options parameter used as template data).\n *\n * template property can be a string which will be passed to mw.template.compile()\n * or an object that has a render() function which accepts an object with\n * template data as its argument (similarly to an object created by\n * mw.template.compile()).\n *\n * You can also define a defaults property which should be an object\n * containing default values for the template (if they're not present in\n * the options parameter).\n *\n * If this.$el is not a jQuery object bound to existing DOM element, the\n * view can be attached to an element using appendTo(), prependTo(),\n * insertBefore(), insertAfter() proxy functions.\n *\n * append(), prepend(), before(), after() can be used to modify $el. on()\n * can be used to bind events.\n *\n * You can also use declarative DOM events binding by specifying an `events`\n * map on the class. The keys will be 'event selector' and the value can be\n * either the name of a method to call, or a function. All methods and\n * functions will be executed on the context of the View.\n *\n * Inspired from Backbone.js\n * https://github.com/jashkenas/backbone/blob/master/backbone.js#L1128\n *\n * Example:\n * ```js\n *     var\n *       MyComponent = View.extend( {\n *         edit: function ( ev ) {\n *           //...\n *         },\n *         save: function ( ev ) {\n *           //...\n *         }\n *       } ),\n *       instance = new MyComponent({\n *         events: {\n *           'mousedown .title': 'edit',\n *           'click .button': 'save',\n *           'click .open': function(e) { ... }\n *         }\n *       });\n * ```\n *\n * Example:\n * ```js\n *     var View, section;\n *     function Section( options ) {\n *       var defaultOptions = {\n *         events: {\n *           // ...\n *         }\n *       }\n *       View.call( this, util.extends( {}, defaultOptions, options ) );\n *     }\n *     View = require( './View' );\n *     class Section extends View {\n *       get template() {\n *         return mw.template.compile( \"&lt;h2&gt;{{title}}&lt;/h2&gt;\" ),\n *       }\n *     }\n *     section = new Section( { title: 'Test', text: 'Test section body' } );\n *     section.appendTo( 'body' );\n * ```\n *\n * @mixes OO.EventEmitter\n */\nclass View {\n\t/**\n\t * @param {Object} options Object passed to the constructor.\n\t * @param {Object.<string, string>} [options.events]\n\t */\n\tconstructor( options ) {\n\t\tthis.initialize( options );\n\t}\n\n\t/**\n\t * @property {Object}\n\t * Specifies the template used in render().\n\t */\n\tget template() {\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Specifies partials (sub-templates) for the main template. Example:\n\t *\n\t *     @example\n\t *     // example content for the \"some\" template (sub-template will be\n\t *     // inserted where {{>content}} is):\n\t *     // <h1>Heading</h1>\n\t *     // {{>content}}\n\t *\n\t *     class SomeView extends View {\n\t *       get template() { return util.template( '<source-code>' ) }\n\t *       get templatePartials() { return { content: util.template( '<source-code>' ) } }\n\t *     }\n\t *\n\t * @property {Object}\n\t */\n\tget templatePartials() {\n\t\treturn {};\n\t}\n\n\t/**\n\t * A set of default options that are merged with options passed into the initialize\n\t * function.\n\t *\n\t * @property {Object} defaults Default options hash.\n\t * @property {jQuery.Object|string} [defaults.el] jQuery selector to use for rendering.\n\t * @property {boolean} [defaults.skipTemplateRender] Whether to enhance views already in\n\t * DOM. When enabled, the template is disabled so that it is not rendered in the DOM.\n\t * Use in conjunction with View::defaults.$el to associate the View with an existing\n\t * already rendered element in the DOM.\n\t */\n\tget defaults() {\n\t\treturn {};\n\t}\n\n\t/**\n\t * Name of tag that contains the rendered template\n\t *\n\t * @property {string} tagName\n\t */\n\tget tagName() {\n\t\treturn this.options.tagName || 'div';\n\t}\n\n\t/**\n\t * Tells the View to ignore tagName and className when constructing the element\n\t * and to rely solely on the template\n\t *\n\t * @property {boolean} isTemplateMode\n\t */\n\tget isTemplateMode() {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Run once during construction to set up the View\n\t *\n\t * @param {Object} options Object passed to the constructor.\n\t * @param {Object.<string, string>} [options.events]\n\t */\n\tinitialize( options ) {\n\t\tOO.EventEmitter.call( this );\n\t\toptions = util.extend( {}, this.defaults, options );\n\t\tthis.options = options;\n\t\t// Assign a unique id for dom events binding/unbinding\n\t\tthis.cid = uniqueId( 'view' );\n\n\t\tif ( options.el ) {\n\t\t\t// Note the element may not be in the document so must use global jQuery here\n\t\t\tthis.$el = $( options.el );\n\t\t} else {\n\t\t\tthis.$el = this.parseHTML( '<' + this.tagName + '>' );\n\t\t}\n\n\t\t// Make sure the element is ready to be manipulated\n\t\tif ( this.$el.length ) {\n\t\t\tthis._postInitialize( options );\n\t\t} else {\n\t\t\tutil.docReady( () => {\n\t\t\t\t// Note the element may not be in the document so must use global jQuery here\n\t\t\t\tthis.$el = $( options.el );\n\t\t\t\tthis._postInitialize( options );\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Called when this.$el is ready.\n\t *\n\t * @private\n\t * @param {Object} props\n\t */\n\t_postInitialize( props ) {\n\t\t// eslint-disable-next-line mediawiki/class-doc\n\t\tthis.$el.addClass( props.className );\n\t\t// border-box will be added provided this flag is not set\n\t\tif ( props.isBorderBox !== false ) {\n\t\t\tthis.$el.addClass( 'view-border-box' );\n\t\t}\n\n\t\tthis.render( {} );\n\t}\n\n\t/**\n\t * Function called before the view is rendered. Can be redefined in\n\t * objects that extend View.\n\t */\n\tpreRender() {\n\t}\n\n\t/**\n\t * Function called after the view is rendered. Can be redefined in\n\t * objects that extend View.\n\t */\n\tpostRender() {\n\t}\n\n\t/**\n\t * Fill this.$el with template rendered using data if template is set.\n\t *\n\t * @param {Object} data Template data. Will be merged into the view's\n\t * options\n\t * @chainable\n\t */\n\trender( data ) {\n\t\tlet $el, html;\n\t\tutil.extend( this.options, data );\n\t\tthis.preRender();\n\t\tthis.undelegateEvents();\n\t\tif ( this.template && !this.options.skipTemplateRender ) {\n\t\t\thtml = this.template.render( this.options, this.templatePartials );\n\t\t\tif ( this.isTemplateMode ) {\n\t\t\t\t$el = $( html );\n\t\t\t\tthis.$el.replaceWith( $el );\n\t\t\t\tthis.$el = $el;\n\t\t\t} else {\n\t\t\t\tthis.$el.html( html );\n\t\t\t}\n\t\t}\n\t\tthis.postRender();\n\t\tthis.delegateEvents();\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set callbacks for events.\n\t *\n\t * `this.options.events` is a hash of pairs:\n\t *\n\t * ```\n\t * { 'event selector': 'callback' }\n\t *\n\t * {\n\t *   'mousedown .title': 'edit',\n\t *   'click .button': 'save',\n\t *   'click .open': function(e) { ... }\n\t * }\n\t * ```\n\t *\n\t * Callbacks will be bound to the view, with `this` set properly.\n\t * Uses event delegation for efficiency.\n\t * Omitting the selector binds the event to `this.el`.\n\t *\n\t * @param {Object} events Optionally set this events instead of the ones on this.\n\t */\n\tdelegateEvents( events ) {\n\t\tlet match, key, method;\n\t\tevents = events || this.options.events;\n\t\tif ( events ) {\n\t\t\t// Remove current events before re-binding them\n\t\t\tthis.undelegateEvents();\n\t\t\tfor ( key in events ) {\n\t\t\t\tmethod = events[key];\n\t\t\t\t// If the method is a string name of this.method, get it\n\t\t\t\tif ( typeof method !== 'function' ) {\n\t\t\t\t\tmethod = this[events[key]];\n\t\t\t\t}\n\t\t\t\tif ( method ) {\n\t\t\t\t\t// Extract event and selector from the key\n\t\t\t\t\tmatch = key.match( delegateEventSplitter );\n\t\t\t\t\tthis.delegate( match[1], match[2], method.bind( this ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Add a single event listener to the view's element (or a child element\n\t * using `selector`). This only works for delegate-able events: not `focus`\n\t * or `blur`.\n\t *\n\t * @param {string} eventName\n\t * @param {string} selector\n\t * @param {Function} listener\n\t */\n\tdelegate( eventName, selector, listener ) {\n\t\tthis.$el.on( eventName + '.delegateEvents' + this.cid, selector,\n\t\t\tlistener );\n\t}\n\n\t/**\n\t * Clears all callbacks previously bound to the view by `delegateEvents`.\n\t * You usually don't need to use this, but may wish to if you have multiple\n\t * views attached to the same DOM element.\n\t */\n\tundelegateEvents() {\n\t\tif ( this.$el ) {\n\t\t\tthis.$el.off( '.delegateEvents' + this.cid );\n\t\t}\n\t}\n\n\t/**\n\t * A finer-grained `undelegateEvents` for removing a single delegated event.\n\t * `selector` and `listener` are both optional.\n\t *\n\t * @param {string} eventName\n\t * @param {string} selector\n\t * @param {Function} listener\n\t */\n\tundelegate( eventName, selector, listener ) {\n\t\tthis.$el.off( eventName + '.delegateEvents' + this.cid, selector,\n\t\t\tlistener );\n\t}\n\n\t/**\n\t * See parseHTML method of util singleton\n\t *\n\t * @param {string} html to turn into a jQuery object.\n\t * @return {jQuery.Object}\n\t */\n\tparseHTML( html ) {\n\t\t// document is explicitly passed due to a bug we found in Safari 11.1.2 where failure\n\t\t// to use document resulted in an element without access to the documentElement\n\t\t// this should be redundant, but no problem in being explicit (T214451).\n\t\treturn util.parseHTML( html, document );\n\t}\n\n\t/**\n\t * Generates a view with children\n\t *\n\t * @param {Object} options\n\t * @param {jQuery.Element[]} children\n\t * @return {View}\n\t */\n\tstatic make( options = {}, children = [] ) {\n\t\tconst view = new View( options );\n\t\tchildren.forEach( ( $child ) => view.append( $child ) );\n\t\treturn view;\n\t}\n}\n\nOO.mixinClass( View, OO.EventEmitter );\n\n/**\n * @memberof View\n * @instance\n * @function append\n * @param {...(string|Node|Node[]|jQuery)} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function append\n * @param {function(number, string): string|Node|Node[]|jQuery} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function prepend\n * @param {...(string|Node|Node[]|jQuery)} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function prepend\n * @param {function(number, string): string|Node|Node[]|jQuery} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function appendTo\n * @param {string|Node|Node[]|jQuery} target\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function prependTo\n * @param {string|Node|Node[]|jQuery} target\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function after\n * @param {...(string|Node|Node[]|jQuery)} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function after\n * @param {function(number, string): string|Node|Node[]|jQuery} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @functiontion before\n * @param {...(string|Node|Node[]|jQuery)} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function before\n * @param {function(number, string): string|Node|Node[]|jQuery} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @property {jQuery.Object} $el\n */\n\n/**\n * @memberof View\n * @instance\n * @function insertAfter\n * @param {string|Node|Node[]|jQuery} target\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function insertBefore\n * @param {string|Node|Node[]|jQuery} target\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function remove\n * @param {string} [selector]\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function detach\n * @param {string} [selector]\n * @return {View}\n */\n\n[\n\t'append',\n\t'prepend',\n\t'appendTo',\n\t'prependTo',\n\t'after',\n\t'before',\n\t'insertAfter',\n\t'insertBefore',\n\t'remove',\n\t'detach'\n].forEach( ( prop ) => {\n\tView.prototype[prop] = function () {\n\t\tthis.$el[prop].apply( this.$el, arguments );\n\t\treturn this;\n\t};\n} );\n\n/**\n * ES5 compatible version of class for backwards compatibility\n *\n * @deprecated 1.44\n * @param {Object} options\n * @ignore\n */\nfunction ClassES5( options ) {\n\tmw.log.warn( '[1.44] Extending View class constructor is deprecated. Please use View.make' );\n\tthis.initialize( options );\n}\nClassES5.prototype = View.prototype;\nClassES5.make = View.make;\n\nView.ClassES5 = ClassES5;\nmodule.exports = View;\n","const util = require( './util' ),\n\tdefaultParams = {\n\t\taction: 'query',\n\t\tformatversion: 2\n\t};\n\n/**\n * Extends the default params for an action query with otherParams\n *\n * @ignore\n * @param {Object} otherParams\n * @return {Object}\n */\nmodule.exports = function actionParams( otherParams ) {\n\tconst scriptPath = mw.config.get( 'wgMFScriptPath' );\n\treturn util.extend( {}, defaultParams, {\n\t\torigin: scriptPath ? '*' : undefined\n\t}, otherParams );\n};\n","const\n\tButton = require( '../Button' ),\n\tutil = require( '../util' ),\n\tView = require( '../View' );\n\n/**\n * @typedef {Object} FormField\n * @private\n * @property {string} name\n * @property {string} value\n */\n\n/**\n * A form for enabling the advanced mobile editor mode.\n *\n * @ignore\n */\nclass AmcEnableForm extends View {\n\t/**\n\t * @param {Object} options\n\t * @param {string} options.postUrl Form will POST to this endpoint\n\t * @param {FormField[]} options.fields An array of hidden form fields\n\t * @param {string} options.buttonLabel Label for submit button\n\t */\n\tconstructor( options ) {\n\t\tsuper( options );\n\t}\n\n\t/** @inheritdoc */\n\tget isTemplateMode() {\n\t\treturn true;\n\t}\n\n\t/** @inheritdoc */\n\tget template() {\n\t\treturn util.template( `\n<form class=\"amc-enable-form\" action=\"{{postUrl}}\" method=\"POST\">\n\t{{#fields}}\n\t\t<input type=\"hidden\" name=\"{{name}}\" value=\"{{value}}\">\n\t{{/fields}}\n</form>\n\t\t` );\n\t}\n\n\t/** @inheritdoc */\n\tpostRender() {\n\t\tthis.$el.append(\n\t\t\tnew Button( {\n\t\t\t\ttagName: 'button',\n\t\t\t\tprogressive: true,\n\t\t\t\tlabel: this.options.buttonLabel\n\t\t\t} ).$el\n\t\t);\n\t}\n}\n\nmodule.exports = AmcEnableForm;\n","/**\n * Describes a promotional campaign for advanced mobile contributions.\n *\n * @typedef {Object} module:mobile.startup/AmcOutreach~PromoCampaign\n * @property {Function} showIfEligible\n * @property {Function} makeActionIneligible\n * @property {Function} makeAllActionsIneligible\n * @property {Function} isCampaignActive\n */\n\nconst\n\ttoast = require( '../showOnPageReload' ),\n\tcreatePromoCampaign = require( '../promoCampaign/promoCampaign' ),\n\tamcOutreachDrawer = require( './amcOutreachDrawer' ),\n\t// MW constants should be kept in sync with onMakeGlobalVariableScript() from\n\t// MobileFrontendHooks.php\n\tMW_CONFIG_CAMPAIGN_ACTIVE_NAME = 'wgMFAmcOutreachActive',\n\tMW_CONFIG_USER_ELIGIBLE_NAME = 'wgMFAmcOutreachUserEligible',\n\t// This object contains arbitrary actions that are meant to only be shown one\n\t// time at most. Each action is either 'eligible' or 'ineligible' at any given\n\t// time.\n\t//\n\t// When a new action is desired, it should be added to this object.\n\t//\n\t// In other languages, this would be an enum. However, because JS doesn't\n\t// support enums, the keys/value names are identical in an attempt to mimic\n\t// some of their functionality. The names in this object are used by\n\t// promoCampaign to mark when an action has become 'ineligible'.\n\tACTIONS = {\n\t\tonDesktopLink: 'onDesktopLink',\n\t\tonHistoryLink: 'onHistoryLink',\n\t\tonTalkLink: 'onTalkLink'\n\t},\n\tCAMPAIGN_NAME = 'amc-outreach';\n\n// singleton;\nlet campaign;\n\n/**\n * Internal for use inside Minerva only. See {@link module:mobile.startup} for access.\n *\n * @exports mobile.startup/AmcOutreach\n */\nmodule.exports = {\n\t/**\n\t * Loads a promotion campaign for advanced mobile contributions if the user is eligible.\n\t *\n\t * @return {module:mobile.startup/AmcOutreach~PromoCampaign}\n\t */\n\tloadCampaign: () => {\n\t\tif ( campaign ) {\n\t\t\treturn campaign;\n\t\t}\n\n\t\tcampaign = createPromoCampaign(\n\t\t\t/**\n\t\t\t * This callback is executed by promoCampaign's `showIfEligible` method.\n\t\t\t * promoCampaign will only execute it when an action is 'eligible'.\n\t\t\t *\n\t\t\t * @param {string} action Name of one of the actions in the ACTIONS\n\t\t\t * object. This is used by the drawer to notify promoCampaign when the\n\t\t\t * action has become 'ineligible' (e.g. after enabling or dismissing the\n\t\t\t * drawer).\n\t\t\t * @param {onBeforeHide} onBeforeHide Callback exected after user\n\t\t\t * dismisses drawer.\n\t\t\t * @param {string} returnToTitle Title of page to redirect to after user enables\n\t\t\t * AMC\n\t\t\t * @param {string} [returnToQuery] Optional query params to add to redirected\n\t\t\t * URL after user enables AMC. Can also include anchor (e.g.\n\t\t\t * `foo=bar#/Talk`\n\t\t\t * @return {module:mobile.startup/Drawer|null}\n\t\t\t */\n\t\t\t( action, onBeforeHide, returnToTitle, returnToQuery ) => amcOutreachDrawer(\n\t\t\t\taction,\n\t\t\t\tcampaign,\n\t\t\t\tmw.message,\n\t\t\t\tmw.util,\n\t\t\t\ttoast,\n\t\t\t\tmw.user.tokens.get( 'csrfToken' ),\n\t\t\t\tonBeforeHide,\n\t\t\t\treturnToTitle,\n\t\t\t\treturnToQuery\n\t\t\t),\n\t\t\tACTIONS,\n\t\t\tCAMPAIGN_NAME,\n\t\t\t// in minerva desktop, this config will not be set\n\t\t\t!!mw.config.get( MW_CONFIG_CAMPAIGN_ACTIVE_NAME ),\n\t\t\t!!mw.config.get( MW_CONFIG_USER_ELIGIBLE_NAME ),\n\t\t\tmw.storage\n\t\t);\n\n\t\treturn campaign;\n\t},\n\t/**\n\t * @private\n\t */\n\tACTIONS\n};\n","const\n\tDrawer = require( '../Drawer' ),\n\tAnchor = require( '../Anchor' ),\n\tutil = require( '../util' ),\n\tAmcEnableForm = require( './AmcEnableForm' ),\n\t// These constants should be kept in sync with SpecialMobileOptions.php\n\tAMC_ENABLE_FIELD_NAME = 'enableAMC',\n\tAMC_ENABLE_FIELD_VALUE = '1';\n\n/**\n * Callback intended to allow the client run extra logic (e.g. show a modal)\n * after the drawer is dismissed.\n *\n * @callback module:mobile.startup~onBeforeHide\n */\n\n/**\n * @ignore\n * @memberof module:mobile.startup\n * @param {string} action Used by the drawer to notify promoCampaign when the\n * action has become 'ineligible' (e.g. after enabling or dismissing the drawer).\n * @param {module:mobile.startup/AmcOutreach~PromoCampaign} promoCampaign\n * @param {mw.message} mwMessage Used for i18n\n * @param {mw.util} mwUtil Used to determine POST url for the enable form\n * @param {Toast} toast Displays success message after user submits enable form\n * @param {string} csrfToken\n * @param {onBeforeHide} onBeforeHide\n * @param {string} returnToTitle Title to redirect to after user enables\n * AMC\n * @param {string} [returnToQuery] Optional query params to add to redirected\n * URL after user enables AMC\n * @return {module:mobile.startup/Drawer} Returns the drawer that is shown\n */\nmodule.exports = function amcOutreachDrawer(\n\taction,\n\tpromoCampaign,\n\tmwMessage,\n\tmwUtil,\n\ttoast,\n\tcsrfToken,\n\tonBeforeHide,\n\treturnToTitle,\n\treturnToQuery\n) {\n\treturn new Drawer( {\n\t\tclassName: 'amc-outreach-drawer',\n\t\tchildren: [\n\t\t\tutil.parseHTML( '<div>' ).addClass( 'amc-outreach-image' ),\n\t\t\tutil.parseHTML( '<p>' ).append(\n\t\t\t\tutil.parseHTML( '<strong>' ).text(\n\t\t\t\t\tmwMessage( 'mobile-frontend-amc-outreach-intro' ).text()\n\t\t\t\t)\n\t\t\t),\n\t\t\tutil.parseHTML( '<p>' ).text(\n\t\t\t\tmwMessage( 'mobile-frontend-amc-outreach-description' ).text()\n\t\t\t),\n\t\t\tnew AmcEnableForm( {\n\t\t\t\tpostUrl: mwUtil.getUrl( 'Special:MobileOptions', {\n\t\t\t\t\treturnto: returnToTitle,\n\t\t\t\t\treturntoquery: returnToQuery || ''\n\t\t\t\t} ),\n\t\t\t\tfields: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'updateSingleOption',\n\t\t\t\t\t\tvalue: AMC_ENABLE_FIELD_NAME\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'enableAMC',\n\t\t\t\t\t\tvalue: AMC_ENABLE_FIELD_VALUE\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'token',\n\t\t\t\t\t\tvalue: csrfToken\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tbuttonLabel: mwMessage( 'mobile-frontend-amc-outreach-enable' ).text(),\n\t\t\t\tevents: {\n\t\t\t\t\tsubmit: () => {\n\t\t\t\t\t\tpromoCampaign.makeActionIneligible( action );\n\t\t\t\t\t\ttoast.showOnPageReload( mwMessage( 'mobile-frontend-amc-outreach-enabled-message' ).text() );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} ).$el,\n\t\t\tnew Anchor( {\n\t\t\t\thref: '#',\n\t\t\t\tadditionalClassNames: 'cancel',\n\t\t\t\tprogressive: true,\n\t\t\t\tlabel: mwMessage( 'mobile-frontend-amc-outreach-no-thanks' ).text()\n\t\t\t} ).$el\n\t\t],\n\t\tonBeforeHide: () => {\n\t\t\tpromoCampaign.makeActionIneligible( action );\n\t\t\tonBeforeHide();\n\t\t}\n\t} );\n};\n","/* global $ */\nconst\n\tPage = require( './Page' );\n\nlet page;\n\n/**\n * Constructs an incomplete Page model singleton representing the currently loaded page.\n *\n * Because this depends on the presence of certain DOM elements, it\n * should only be called after the DOMContentLoaded event.\n *\n * @ignore\n * @return {Page}\n */\nfunction loadCurrentPage() {\n\tif ( page ) {\n\t\treturn page;\n\t}\n\n\tconst permissions = [].concat( mw.config.get( 'wgRestrictionEdit', [] ) ),\n\t\trelevantTitle = mw.Title.newFromText( mw.config.get( 'wgRelevantPageName' ) ),\n\t\ttitle = mw.Title.newFromText( mw.config.get( 'wgPageName' ) );\n\n\tif ( permissions.length === 0 ) {\n\t\tpermissions.push( '*' );\n\t}\n\n\tpage = new Page( {\n\t\ttitle: title.getPrefixedText(),\n\t\ttitleObj: title,\n\t\trelevantTitle: relevantTitle.getPrefixedText(),\n\t\tprotection: {\n\t\t\tedit: permissions\n\t\t},\n\t\trevId: mw.config.get( 'wgRevisionId' ),\n\t\tisMainPage: mw.config.get( 'wgIsMainPage' ),\n\t\tisWatched: $( '#ca-watch' ).hasClass( 'watched' ),\n\t\tisMissing: mw.config.get( 'wgArticleId' ) === 0,\n\t\tid: mw.config.get( 'wgArticleId' ),\n\t\tnamespaceNumber: mw.config.get( 'wgNamespaceNumber' )\n\t} );\n\n\treturn page;\n}\n\nmodule.exports = loadCurrentPage;\n","/* global $ */\nconst\n\tPageHTMLParser = require( './PageHTMLParser' );\n\nlet pageHTMLParser;\n\n/**\n * Constructs a page parser singleton specific to the current page to find common child elements\n * more easily.\n *\n * Because this depends on the presence of certain DOM elements, it\n * should only be called after the DOMContentLoaded event.\n *\n * @ignore\n * @return {module:mobile.startup/PageHTMLParser}\n */\nfunction loadCurrentPageHTMLParser() {\n\tif ( pageHTMLParser ) {\n\t\treturn pageHTMLParser;\n\t}\n\n\tpageHTMLParser = new PageHTMLParser( $( '#content #bodyContent' ) );\n\n\treturn pageHTMLParser;\n}\n\nmodule.exports = loadCurrentPageHTMLParser;\n","/**\n * T156186: Please make judicious use of this singleton whose purpose is to\n * allow disparate components the ability to subscribe to a set of events and\n * react to those events.\n *\n * Prefer to use a more localized event bus when possible.\n *\n * Only import this in files at the edges. For example:\n *\n * Good: initialization scripts responsible for initializing classes such as\n * mobile.init/init.js\n * Bad: ImageOverlay.js or in any other component.\n *\n * By doing this, and using dependency injection of the event bus in the\n * components themselves, it will make it easier to switch this event bus out\n * for something more localized later on in our refactoring efforts.\n */\nmodule.exports = new OO.EventEmitter();\n","const util = require( './util' ),\n\tactionParams = require( './actionParams.js' );\n\n/**\n * Extends the API query parameters to include those parameters required to also fetch Wikibase\n * descriptions and appropriately sized thumbnail images as well as those required to make a query.\n *\n * This function wraps `util.extend` with some Wikibase-specific configuration\n * variable management\n * but, like `util.extend`, is variadic and so can be used as a replacement for it in search\n * gateways, e.g.\n *\n * ```\n * var params = extendSearchParams(\n *   'search',\n *   baseParams,\n *   specializedParams,\n *   moreSpecializedParams\n * );\n * ```\n *\n * @param {string} feature The name of the feature\n * @throws {Error} If `feature` isn't one that shows Wikidata descriptions. See the\n *  `wgMFDisplayWikibaseDescriptions` configuration variable for detail\n * @return {Object}\n */\nmodule.exports = function extendSearchParams( feature ) {\n\tconst displayWikibaseDescriptions = mw.config.get( 'wgMFDisplayWikibaseDescriptions' ) || {\n\t\t\t// These must be defined, as these are all the features that this can be used on.\n\t\t\t// If not defined, all these features will see their API calls broken\n\t\t\tsearch: true,\n\t\t\twatchlist: true,\n\t\t\ttagline: false\n\t\t},\n\t\tscriptPath = mw.config.get( 'wgMFScriptPath' );\n\n\tif ( !Object.prototype.hasOwnProperty.call( displayWikibaseDescriptions, feature ) ) {\n\t\tthrow new Error( '\"' + feature + '\" isn\\'t a feature that shows Wikibase descriptions.' );\n\t}\n\n\t// Construct the arguments for a call to `util.extend`\n\t// such that if it were hand-written, then it\n\t// would look like the following:\n\t//\n\t// ```\n\t// var result = util.extend( {\n\t//   prop: []\n\t// }, params, /* ..., */ mw.config.get( 'wgMFSearchAPIParams' ) );\n\t// ```\n\tconst args = Array.prototype.slice.call( arguments, 1 );\n\targs.unshift( {\n\t\tprop: []\n\t} );\n\targs.push( mw.config.get( 'wgMFSearchAPIParams' ) );\n\n\tconst result = util.extend.apply( {}, args );\n\tresult.prop = result.prop.concat( mw.config.get( 'wgMFQueryPropModules' ) );\n\n\tif ( displayWikibaseDescriptions[feature] ) {\n\t\tif ( result.prop.indexOf( 'description' ) === -1 ) {\n\t\t\tresult.prop.push( 'description' );\n\t\t}\n\t}\n\n\tif ( scriptPath ) {\n\t\t// A foreign api is being accessed! Enable anonymous CORS queries!\n\t\tresult.origin = '*';\n\t}\n\treturn actionParams( result );\n};\n","const util = require( './util' ),\n\tButton = require( './Button' ),\n\ticons = require( './icons' );\n\n/**\n * Creates a header\n *\n * @ignore\n * @param {string|View} headingOrView (HTML allowed)\n * @param {View[]} headerActions\n * @param {module:mobile.startup/View} [headerCancel] defaults to cancel button\n * @param {string} [additionalClassNames] (should be escaped)\n * @return {Element}\n */\nfunction makeHeader( headingOrView, headerActions, headerCancel, additionalClassNames ) {\n\tconst heading = typeof headingOrView === 'string' ? headingOrView : undefined,\n\t\ttemplateData = {\n\t\t\thasActions: headerActions && headerActions.length,\n\t\t\tisHidden: false,\n\t\t\theading\n\t\t},\n\t\thtml = util.template( `\n<div class=\"overlay-header header ${ additionalClassNames || '' } hideable\">\n\t<ul class=\"header-cancel\">\n\t\t<li></li>\n\t</ul>\n\t{{{heading}}}\n\t{{#hasActions}}\n\t<div class=\"header-action\"></div>\n\t{{/hasActions}}\n</div>\n\t\t` ).render( templateData );\n\theaderCancel = headerCancel || icons.cancel();\n\tconst $el = util.parseHTML( html );\n\t// Truncate any text inside in the overlay header.\n\t$el.find( 'h2 span' ).addClass( 'truncated-text' );\n\t$el.find( '.header-cancel li' ).append(\n\t\theaderCancel.$el\n\t);\n\tif ( heading === undefined ) {\n\t\theadingOrView.$el.insertAfter( $el.find( '.header-cancel' ) );\n\t}\n\tif ( headerActions && headerActions.length ) {\n\t\t$el.find( '.header-action' ).append(\n\t\t\theaderActions.map( ( component ) => component.$el )\n\t\t);\n\t}\n\treturn $el[0];\n}\n\n/**\n * Creates a header with a h2 heading, internal for use inside GrowthExperiments only.\n *\n * @function\n * @memberof module:mobile.startup\n * @param {string} heading (HTML allowed)\n * @param {module:mobile.startup/View[]} headerActions\n * @param {module:mobile.startup/View} [headerCancel] defaults to cancel button\n * @param {string} [additionalClassNames] (should be escaped)\n * @return {Element}\n */\nfunction header( heading, headerActions, headerCancel, additionalClassNames ) {\n\theading = `<div class=\"overlay-title\"><h2>${ heading }</h2></div>`;\n\treturn makeHeader( heading, headerActions, headerCancel, additionalClassNames );\n}\n\n/**\n * Creates a header with a form\n *\n * @ignore\n * @param {string|View} formHTMLOrView of the header\n * @param {View[]} headerActions\n * @param {module:mobile.startup/View} [headerCancel] defaults to cancel button\n * @param {string} [additionalClassNames] (should be escaped)\n * @return {Element}\n */\nfunction formHeader( formHTMLOrView, headerActions, headerCancel, additionalClassNames ) {\n\treturn makeHeader( formHTMLOrView, headerActions, headerCancel, additionalClassNames );\n}\n\n/**\n * Creates a header with a form\n *\n * @ignore\n * @param {string} heading of the header\n * @param {string} additionalClassNames of the header\n * @return {Element}\n */\nfunction saveHeader( heading, additionalClassNames ) {\n\treturn header(\n\t\theading,\n\t\t[\n\t\t\tnew Button( {\n\t\t\t\ttagName: 'button',\n\t\t\t\tadditionalClassNames: 'save submit',\n\t\t\t\tdisabled: true,\n\t\t\t\tlabel: util.saveButtonMessage(),\n\t\t\t\tsize: 'large'\n\t\t\t} )\n\t\t],\n\t\ticons.back(),\n\t\tadditionalClassNames\n\t);\n}\n/**\n * Creates a header with a form\n *\n * @ignore\n * @param {string} heading of the header\n * @param {string} additionalClassNames of the header\n * @return {Element}\n */\nfunction savingHeader( heading ) {\n\treturn header(\n\t\theading,\n\t\t[\n\t\t\ticons.spinner( {\n\t\t\t\tadditionalClassNames: 'savespinner loading'\n\t\t\t} )\n\t\t],\n\t\ticons.cancel(),\n\t\t'saving-header hidden'\n\t);\n}\n\nmodule.exports = {\n\tsavingHeader,\n\tsaveHeader,\n\tformHeader,\n\theader\n};\n","const\n\tCANCEL_GLYPH = 'close',\n\tIcon = require( './Icon' ),\n\tIconButton = require( './IconButton' );\n\n/**\n * A set of shared icons.\n *\n * Factory methods are used to keep separate features that use the same icons\n * from accidentally manipulating one another's DOM when calling methods like\n * `remove`.\n *\n * @class icons\n * @singleton\n * @uses Icon\n */\nconst icons = {\n\tCANCEL_GLYPH,\n\t// Exported to support testing and stubbing\n\tIcon,\n\tIconButton,\n\t/**\n\t * Gets a back icon\n\t *\n\t * The icon should be used to inform the user that the front-end is\n\t * communicating with the back-end.\n\t *\n\t * @return {IconButton}\n\t */\n\tback() {\n\t\treturn new icons.IconButton( {\n\t\t\ttagName: 'button',\n\t\t\ticon: 'previous',\n\t\t\tadditionalClassNames: 'back',\n\t\t\tlabel: mw.msg( 'mobile-frontend-overlay-close' )\n\t\t} );\n\t},\n\t/**\n\t * Gets a cancel icon\n\t *\n\t * The icon should be used to inform the user that the front-end is\n\t * communicating with the back-end.\n\t *\n\t * @param {string} [variant]\n\t * @param {Object} [props] to extend\n\t * @return {IconButton}\n\t */\n\tcancel( variant, props = {} ) {\n\t\tconst glyph = variant ? `${ CANCEL_GLYPH }-${ variant }` : `${ CANCEL_GLYPH }`;\n\t\tprops.additionalClassNames = props.additionalClassNames || '';\n\t\tprops.additionalClassNames += ' cancel';\n\n\t\treturn new icons.IconButton( Object.assign( {\n\t\t\ttagName: 'button',\n\t\t\ticon: glyph,\n\t\t\tlabel: mw.msg( 'mobile-frontend-overlay-close' )\n\t\t}, props ) );\n\t},\n\t/**\n\t * Gets a spinner icon. This uses IconButton but should never actually\n\t * be a button or have full button styles, as its purely presentational\n\t *\n\t * The icon should be used to inform the user that the front-end is\n\t * communicating with the back-end.\n\t *\n\t * @param {Object} [props] See `Icon` for more details\n\t * @return {IconButton}\n\t */\n\tspinner( props = {} ) {\n\t\tif ( props.additionalClassNames === undefined ) {\n\t\t\tprops.additionalClassNames = 'spinner loading';\n\t\t}\n\n\t\tconst spinner = new icons.IconButton( Object.assign( {\n\t\t\ttagName: 'span',\n\t\t\ticon: 'spinner',\n\t\t\tlabel: mw.msg( 'mobile-frontend-loading-message' )\n\t\t}, props ) );\n\n\t\t// Update the element to not use button classes or attributes\n\t\tspinner.$el.removeClass();\n\t\t// eslint-disable-next-line mediawiki/class-doc\n\t\tspinner.$el.addClass( props.additionalClassNames );\n\t\tspinner.$el.attr( 'type', '' );\n\t\tif ( spinner.options.isIconOnly ) {\n\t\t\tspinner.$el.addClass( 'mf-spinner-icon-element' );\n\t\t}\n\t\treturn spinner;\n\t},\n\t/**\n\t * Gets a failure (error) icon\n\t *\n\t * @return {IconButton}\n\t */\n\terror() {\n\t\treturn new icons.IconButton( {\n\t\t\ticon: 'alert-invert',\n\t\t\tadditionalClassNames: 'load-fail-msg-icon'\n\t\t} );\n\t},\n\t/**\n\t * Gets a non-filled watch star icon.\n\t *\n\t * @param {Object} props\n\t * @return {IconButton}\n\t */\n\twatch( props = {} ) {\n\t\tprops.additionalClassNames = props.additionalClassNames || '';\n\t\tprops.additionalClassNames += ' watch-this-article';\n\n\t\treturn new icons.IconButton( Object.assign( {\n\t\t\ticon: 'star-subtle'\n\t\t}, props ) );\n\t},\n\t/**\n\t * Gets a filled watch star icon.\n\t *\n\t * @param {Object} props\n\t * @return {IconButton}\n\t */\n\twatched( props = {} ) {\n\t\tprops.additionalClassNames = props.additionalClassNames || '';\n\t\tprops.additionalClassNames += ' watch-this-article watched';\n\n\t\treturn new icons.IconButton( Object.assign( {\n\t\t\ticon: 'unStar-progressive'\n\t\t}, props ) );\n\t}\n};\n\nmodule.exports = icons;\n","const\n\tutil = require( '../util' ),\n\tplaceholderClass = 'lazy-image-placeholder';\n\n/**\n * @ignore\n * @param {HTMLElement} root\n * @return {HTMLElement[]}\n */\nfunction queryPlaceholders( root ) {\n\treturn Array.prototype.slice.call(\n\t\troot.getElementsByClassName( placeholderClass )\n\t);\n}\n\n/**\n * Load an image on demand\n *\n * @ignore\n * @param {HTMLElement[]} placeholders a list of images that have not been loaded.\n * @return {jQuery.Deferred}\n */\nfunction loadImages( placeholders ) {\n\treturn util.Promise.all(\n\t\tplaceholders.map( ( placeholder ) => module.exports.loadImage( placeholder ).promise )\n\t);\n}\n\n/**\n * Load an image on demand\n *\n * @ignore\n * @param {HTMLElement} placeholder\n * @return {{promise: jQuery.Deferred<'load'|'error'>, image: HTMLImageElement}}\n */\nfunction loadImage( placeholder ) {\n\tconst\n\t\tdeferred = util.Deferred(),\n\t\t// data-width and height are attributes and do not specify dimension.\n\t\twidth = placeholder.dataset.width,\n\t\theight = placeholder.dataset.height,\n\t\timage = new Image();\n\n\tif ( width ) {\n\t\timage.setAttribute( 'width', parseInt( width, 10 ) );\n\t}\n\tif ( height ) {\n\t\timage.setAttribute( 'height', parseInt( height, 10 ) );\n\t}\n\n\t// eslint-disable-next-line mediawiki/class-doc\n\timage.className = placeholder.dataset.class || '';\n\timage.alt = placeholder.dataset.alt || '';\n\timage.useMap = placeholder.dataset.usemap;\n\timage.style.cssText = placeholder.style.cssText || '';\n\n\t// When the image has loaded\n\timage.addEventListener( 'load', () => {\n\t\t// Swap the HTML inside the placeholder (to keep the layout and\n\t\t// dimensions the same and not trigger layouts\n\t\timage.classList.add( 'image-lazy-loaded' );\n\t\tif ( placeholder.parentNode ) {\n\t\t\tplaceholder.parentNode.replaceChild( image, placeholder );\n\t\t}\n\t\tdeferred.resolve( 'load' );\n\t}, { once: true } );\n\timage.addEventListener( 'error', () => {\n\t\t// Swap the HTML and let the browser decide what to do with the broken image.\n\t\tif ( placeholder.parentNode ) {\n\t\t\tplaceholder.parentNode.replaceChild( image, placeholder );\n\t\t}\n\t\t// Never reject. Quietly resolve so that Promise.all() awaits for all Deferreds to complete.\n\t\t// Reevaluate using Deferred.reject in T136693.\n\t\tdeferred.resolve( 'error' );\n\t}, { once: true } );\n\n\t// Trigger image download after binding the load handler\n\tconst src = placeholder.dataset.mwSrc || '';\n\tif ( src ) {\n\t\timage.src = src;\n\t\timage.srcset = placeholder.dataset.mwSrcset || '';\n\t}\n\n\treturn {\n\t\tpromise: deferred,\n\t\timage\n\t};\n}\n\nmodule.exports = {\n\tplaceholderClass,\n\tqueryPlaceholders,\n\tloadImages,\n\tloadImage,\n\ttest: {\n\t\tplaceholderClass\n\t}\n};\n","/**\n * Class for managing modules\n *\n * A module in this context is essentially a Javascript class (not to be confused with\n * ResourceLoader modules).\n */\nclass ModuleLoader {\n\tconstructor() {\n\t\t/**\n\t\t * @property {Object} register of defined modules\n\t\t * @private\n\t\t */\n\t\tthis._register = {};\n\t}\n\n\t/**\n\t * Require (import) a module previously defined using define().\n\t * Searches core module registry using ResourceLoader require before consulting\n\t * its own local registry. This method is deprecated, please do not use.\n\t *\n\t * @param {string} id Required module id.\n\t * @return {Object} Required module, can be any JavaScript object.\n\t */\n\trequire( id ) {\n\t\tconst registry = this._register;\n\n\t\t/**\n\t\t * @return {Object} Module\n\t\t */\n\t\tfunction localRequire() {\n\t\t\tif ( !Object.hasOwnProperty.call( registry, id ) ) {\n\t\t\t\tthrow new Error( 'MobileFrontend Module not found: ' + id );\n\t\t\t}\n\t\t\treturn registry[id];\n\t\t}\n\n\t\tconst args = id.split( '/' );\n\t\ttry {\n\t\t\tconst module = __non_webpack_require__( args[0] );\n\t\t\tif ( module[args[1]] ) {\n\t\t\t\treturn module[args[1]];\n\t\t\t} else {\n\t\t\t\treturn localRequire();\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\treturn localRequire();\n\t\t}\n\t}\n\n\t/**\n\t * Define a module which can be later required (imported) using require().\n\t *\n\t * @param {string} id Defined module id.\n\t * @param {Object} obj Defined module body, can be any JavaScript object.\n\t * @return {Object}\n\t */\n\tdefine( id, obj ) {\n\t\tif ( Object.hasOwnProperty.call( this._register, id ) ) {\n\t\t\tthrow new Error( 'Module already exists: ' + id );\n\t\t}\n\t\tthis._register[id] = obj;\n\t\t// return an object of additional functions to do with the registered module\n\t\treturn {\n\t\t\t/**\n\t\t\t * @see ModuleLoader#deprecate\n\t\t\t * @param {string} deprecatedId Defined module id, which is deprecated.\n\t\t\t * @ignore\n\t\t\t */\n\t\t\tdeprecate: ( deprecatedId ) => {\n\t\t\t\tthis.deprecate( deprecatedId, obj, id );\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Deprecate a module and give an replacement (if there is any).\n\t *\n\t * @param {string} id Defined module id, which is deprecated.\n\t * @param {Object} obj Defined module body, can be any JavaScript object.\n\t * @param {string} [replacement] Give an optional replacement for this module (which\n\t * needs to be already defined!)\n\t */\n\tdeprecate( id, obj, replacement ) {\n\t\tlet msg;\n\t\tif ( replacement ) {\n\t\t\t// add an alternative for this module, if any given\n\t\t\tmsg = 'Use ' + replacement + ' instead.';\n\t\t}\n\t\t// register it as a deprecated one\n\t\tmw.log.deprecate( this._register, id, obj, msg );\n\t}\n}\n\nmodule.exports = ModuleLoader;\n","const ModuleLoader = require( './moduleLoader' );\n\nmodule.exports = new ModuleLoader();\n","const Page = require( '../Page' );\nconst util = require( '../util' );\n\n/**\n * Create a Page object from an API response.\n *\n * @memberof Page\n * @param {Object} resp as representing a page in the API\n * @return {Page}\n */\nfunction parse( resp ) {\n\tlet displayTitle;\n\tconst thumb = resp.thumbnail,\n\t\tpageprops = resp.pageprops || {\n\t\t\tdisplaytitle: mw.html.escape( resp.title )\n\t\t},\n\t\tterms = resp.terms || resp.entityterms;\n\n\tif ( pageprops || terms ) {\n\t\t// The label is either the display title or the label pageprop\n\t\t// (the latter used by Wikidata)\n\t\t// Long term we want to consolidate these.\n\t\t// Note that pageprops.displaytitle is HTML, while\n\t\t// terms.label[0] is plain text.\n\t\tdisplayTitle = terms && terms.label ?\n\t\t\tmw.html.escape( terms.label[0] ) : pageprops.displaytitle;\n\t}\n\t// Add Wikidata descriptions if available (T101719)\n\tresp.wikidataDescription = resp.description || undefined;\n\n\tif ( thumb ) {\n\t\tresp.thumbnail.isLandscape = thumb.width > thumb.height;\n\t}\n\n\treturn new Page(\n\t\tutil.extend( resp, {\n\t\t\tid: resp.pageid,\n\t\t\tisMissing: !!resp.missing,\n\t\t\turl: mw.util.getUrl( resp.title ),\n\t\t\tdisplayTitle // this is HTML!\n\t\t} )\n\t);\n}\n\nmodule.exports = { parse };\n","/**\n * Creates a campaign that makes showing promo drawers, modals, etc that should\n * only be shown once (using localStorage) per action (when page loads, when\n * user clicks on a link, etc) easier. The campaign executes a given callback\n * (e.g. showing a drawer or modal) for a specific action only when it is\n * eligible. A campaign can have multiple arbitrary actions via the supplied\n * `actions` object. An action is either 'eligible' or 'ineligible' at any given\n * time. If `ineligible`, the `showIfEligible` will not execute the `onShow`\n * callback.\n *\n * @ignore\n * @param {Function} onShow A callback intended to show something related to the\n * campaign (drawer, modal, etc) when executed. The callback will only execute\n * after the client calls `showIfEligible` and only if the passed in action is\n * 'eligible'.\n * @param {Object} actions Object of arbitrary actions that are intended to be\n * either \"eligible\" or \"ineligible\" at any given time (onPageLoad,\n * onHistoryLinkClick). The `onShow` callback will only be executed when an\n * action is 'eligible'. For each action, the key and value should be the same\n * (e.g. \"onLoad\":\"onLoad\") to mimic an enum. The client is responsible for\n * notifying when each action becomes \"ineligible\" by calling the\n * `makeActionIneligible` method. All actions can be marked as ineligible by\n * calling the `makeAllActionsIneligible` method.\n * @param {string} campaignName Name of campaign. This is only used to form part\n * of the localStorage key for each action.\n * @param {boolean} campaignActive Is campaign active\n * @param {boolean} userEligible Is current user eligible\n * @param {mw.storage} mwStorage Used to mark actions as ineligible\n * into localStorage\n * @return {mobile.startup/AmcOutreach~PromoCampaign}\n */\nfunction createPromoCampaign(\n\tonShow,\n\tactions,\n\tcampaignName,\n\tcampaignActive,\n\tuserEligible,\n\tmwStorage\n) {\n\t// This object maps actions to localStorage keys\n\tconst ACTIONS_TO_STORAGE_KEYS = {};\n\tfor ( const key in actions ) {\n\t\tconst a = actions[ key ];\n\t\tACTIONS_TO_STORAGE_KEYS[a] = `mobile-frontend-${ campaignName }-ineligible-${ a }`;\n\t}\n\n\t/**\n\t * @return {boolean}\n\t */\n\tfunction isCampaignActive() {\n\t\treturn campaignActive;\n\t}\n\n\t/**\n\t * @param {string} action\n\t * @throws {Error} Throws an error if action is not valid.\n\t */\n\tfunction validateAction( action ) {\n\t\tif ( !( action in actions ) ) {\n\t\t\tthrow new Error(\n\t\t\t\t`Action '${ action }' not found in 'actions' object. Please add this to\n\t\t\t\tthe object when creating a campaign with promoCampaign.js if you believe\n\t\t\t\tthis is a valid action.`\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * @param {string} action Will check the eligibility of this action. This\n\t * should be a value in the actions object.\n\t * @throws {Error} Throws an error if action is not valid.\n\t * @return {boolean}\n\t */\n\tfunction isActionEligible( action ) {\n\t\tvalidateAction( action );\n\n\t\treturn isCampaignActive() &&\n\t\t\tuserEligible &&\n\t\t\tmwStorage.get( ACTIONS_TO_STORAGE_KEYS[action] ) === null;\n\t}\n\n\treturn {\n\t\t/**\n\t\t * @ignore\n\t\t * @param {string} action Should be one of the values in the\n\t\t * actions param\n\t\t * @param {...*} [args] Args to pass to the onShow callback\n\t\t * @throws {Error} Throws an error if action is not valid.\n\t\t * @return {module:mobile.startup/Drawer|null} Returns Drawer if drawer is eligible to be shown and\n\t\t * null if not.\n\t\t */\n\t\tshowIfEligible( action, ...args ) {\n\t\t\tif ( !isActionEligible( action ) ) {\n\t\t\t\t// If not eligible, there is no sense in continuing.\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn onShow( action, ...args );\n\t\t},\n\t\t/**\n\t\t * @ignore\n\t\t * @param {string} action\n\t\t * @throws {Error} Throws an error if action is not valid.\n\t\t * @return {boolean} Whether the save operation was successful\n\t\t */\n\t\tmakeActionIneligible( action ) {\n\t\t\tvalidateAction( action );\n\n\t\t\t// The value here actually doesn't matter. The only thing that matters is\n\t\t\t// if this key exists in localStorage.\n\t\t\treturn mwStorage.set( ACTIONS_TO_STORAGE_KEYS[action], '~' );\n\t\t},\n\t\tmakeAllActionsIneligible() {\n\t\t\tlet key, action;\n\t\t\tfor ( key in actions ) {\n\t\t\t\taction = actions[key];\n\t\t\t\tthis.makeActionIneligible( action );\n\t\t\t}\n\t\t},\n\t\tisCampaignActive\n\t};\n}\n\nmodule.exports = createPromoCampaign;\n","const\n\tstorageKey = 'mobileFrontend/toast';\n\n/**\n * Show the previously saved toast data and delete it from storage\n *\n * @memberof Toast\n * @instance\n * @private\n */\nfunction showPending() {\n\tlet data = mw.storage.get( storageKey );\n\tif ( data ) {\n\t\tdata = JSON.parse( data );\n\t\tmw.notify( data.content, data.options );\n\t\tmw.storage.remove( storageKey );\n\t}\n}\n\nmw.requestIdleCallback( showPending );\n\n/**\n * Save the toast data in storage so that we can show it on page reload.\n * Also check whether there is a pending message that's not shown yet.\n * If yes, output a warning message and discard this message.\n * This is to ensure that the page needs to be reloaded before adding\n * a new message for showing later.\n *\n * @memberof Toast\n * @instance\n * @param {string} content Content to be placed in element\n * @param {Object|string} [options]\n *  If a string (deprecated) CSS class to add to the element\n *  If an object, more options for the notification see mw.notification.show.\n *  For backwards compatibility reasons if a string is given it will be\n *  treated as options.type\n */\nfunction showOnPageReload( content, options ) {\n\tif ( mw.storage.get( storageKey ) ) {\n\t\tmw.log.warn(\n\t\t\t'A pending toast message already exits. ' +\n\t\t\t\t'The page should have been reloaded by now.'\n\t\t);\n\t\treturn;\n\t}\n\tmw.storage.set( storageKey, JSON.stringify( {\n\t\tcontent,\n\t\toptions\n\t} ) );\n}\n\nmodule.exports = { showOnPageReload };\n","/* global $ */\n\n/**\n * Utility library\n *\n * @class util\n * @singleton\n */\nmodule.exports = {\n\t/**\n\t * Obtains the correct label for the save button which is project specific. It's either\n\t * \"save\" or \"publish\"\n\t *\n\t * @return {string}\n\t */\n\tsaveButtonMessage() {\n\t\treturn mw.config.get( 'wgEditSubmitButtonLabelPublish' ) ?\n\t\t\tmw.msg( 'mobile-frontend-editor-publish' ) : mw.msg( 'mobile-frontend-editor-save' );\n\t},\n\t/**\n\t * Wrapper class for Promises\n\t *\n\t * @memberof util\n\t * @instance\n\t */\n\tPromise: {\n\t\t/**\n\t\t * Wrapper class for the $.when that is compatible with Promise.all\n\t\t *\n\t\t * @memberof util\n\t\t * @param {jQuery.Promise[]} promises\n\t\t * @instance\n\t\t * @return {jQuery.Promise}\n\t\t */\n\t\tall( promises ) {\n\t\t\treturn $.when.apply( $, promises );\n\t\t}\n\t},\n\t/**\n\t * Escape a string for use as a css selector\n\t *\n\t * @memberof util\n\t * @instance\n\t * @param {string} selector\n\t * @return {string}\n\t */\n\tescapeSelector( selector ) {\n\t\treturn $.escapeSelector( selector );\n\t},\n\t/**\n\t * Run method when document is ready.\n\t *\n\t * @memberof util\n\t * @instance\n\t * @param {Function} fn\n\t * @return {jQuery.Object}\n\t */\n\tdocReady( fn ) {\n\t\treturn $( fn );\n\t},\n\t/**\n\t * Wrapper class for the Deferred method\n\t *\n\t * @memberof util\n\t * @instance\n\t * @return {jQuery.Deferred}\n\t */\n\tDeferred() {\n\t\treturn $.Deferred();\n\t},\n\t/**\n\t * Adds a class to the document\n\t *\n\t * @memberof util\n\t * @instance\n\t * @return {jQuery.Object} element representing the documentElement\n\t */\n\tgetDocument() {\n\t\treturn $( document.documentElement );\n\t},\n\t/**\n\t * Get the window object\n\t *\n\t * @memberof util\n\t * @instance\n\t * @return {jQuery.Object}\n\t */\n\tgetWindow() {\n\t\treturn $( window );\n\t},\n\t/**\n\t * Given some html, create new element(s).\n\t * Unlike jQuery.parseHTML this will return a jQuery object\n\t * not an array.\n\t *\n\t * @memberof util\n\t * @instance\n\t * @param {string} html\n\t * @param {Element} [ctx] Document element to serve as the context\n\t *  in which the HTML fragment will be created\n\t * @return {jQuery.Object}\n\t */\n\tparseHTML( html, ctx ) {\n\t\tctx = ctx || document;\n\t\treturn $( $.parseHTML( html, ctx ) );\n\t},\n\t/**\n\t * Wrapper for jQuery.extend method. In future this can be bound to Object.assign\n\t * when support allows.\n\t *\n\t * Warning: if only one argument is supplied to util.extend(), this means the target argument\n\t * was omitted. In this case, the jQuery object itself is assumed to be the target.\n\t *\n\t * @memberof util\n\t * @instance\n\t * @return {Object}\n\t */\n\textend() {\n\t\treturn $.extend.apply( $, arguments );\n\t},\n\n\ttemplate( source ) {\n\t\treturn {\n\t\t\t/**\n\t\t\t * @ignore\n\t\t\t * @return {string} The raw source code of the template\n\t\t\t */\n\t\t\tgetSource() {\n\t\t\t\treturn source;\n\t\t\t},\n\t\t\t/**\n\t\t\t * @ignore\n\t\t\t * @param {Object} data Data to render\n\t\t\t * @param {Object} partials Map partial names to Mustache template objects\n\t\t\t * @return {string} Rendered HTML\n\t\t\t */\n\t\t\trender( data, partials ) {\n\t\t\t\tconst partialSource = {};\n\t\t\t\t// Map MobileFrontend templates to partial strings\n\t\t\t\tObject.keys( partials || {} ).forEach( ( key ) => {\n\t\t\t\t\tpartialSource[key] = partials[key].getSource();\n\t\t\t\t} );\n\n\t\t\t\t// Use global Mustache which is loaded by mediawiki.template.mustache (a\n\t\t\t\t// dependency of the mobile.startup module)\n\t\t\t\t// eslint-disable-next-line no-undef\n\t\t\t\treturn Mustache.render(\n\t\t\t\t\tsource.trim(),\n\t\t\t\t\tdata,\n\t\t\t\t\tpartialSource\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\t}\n};\n","const util = require( '../util' ),\n\tactionParams = require( '../actionParams' );\n\n/**\n * @ignore\n * @typedef {string|number} PageID Page ID. 0 / \"0\" is a special no-ID value.\n * {@link https://www.mediawiki.org/wiki/Manual:Page_table#page_id Page ID}\n *\n * @ignore\n * @typedef {string} PageTitle Canonical page title.\n * {@link https://www.mediawiki.org/wiki/Manual:Title.php#Canonical_forms Canonical forms}\n *\n * @ignore\n * @typedef {boolean} WatchStatus Page watch status; true if watched, false if\n *                                unwatched.\n * {@link https://www.mediawiki.org/wiki/API:Info API:Info} (see inprop.watched)\n * {@link https://www.mediawiki.org/wiki/API:Watch API:Watch} (see unwatch)\n *\n * @ignore\n * @typedef {Object.<PageTitle, WatchStatus>} WatchStatusMap\n */\n\n/**\n * API for retrieving and modifying page watch statuses. This module interacts\n * with two endpoints, API:Info for GETs and API:Watch and for POSTs.\n */\nclass WatchstarGateway {\n\t/**\n\t * @param {mw.Api} api\n\t */\n\tconstructor( api ) {\n\t\tthis.api = api;\n\t}\n\n\t/**\n\t * Issues zero to two asynchronous HTTP requests for the watch status of\n\t * each page ID and title passed.\n\t *\n\t * Every watch entry has a title but not necessarily a page ID. Entries\n\t * without IDs are missing pages, i.e., pages that do not exist. These\n\t * entries are used to observe when a page with a given title is created.\n\t * Although it is convenient to use titles because they're always present,\n\t * IDs are preferred since they're far less likely to exceed the URL length\n\t * limit.\n\t *\n\t * No request is issued when no IDs and no titles are passed. Given that the\n\t * server state does not change between the two requests, overlapping title\n\t * and ID members will behave as expected but there is no reason to issue\n\t * such a request.\n\t *\n\t * @param {PageID[]} ids\n\t * @param {PageTitle[]} titles\n\t * @return {jQuery.Deferred<WatchStatusMap>}\n\t */\n\tgetStatuses( ids, titles ) {\n\t\t// Issue two requests and coalesce the results.\n\t\treturn util.Promise.all( [\n\t\t\tthis.getStatusesByID( ids ),\n\t\t\tthis.getStatusesByTitle( titles )\n\t\t] ).then( function () {\n\t\t\treturn util.extend.apply( util, arguments );\n\t\t} );\n\t}\n\n\t/**\n\t * @param {PageID[]} ids\n\t * @return {jQuery.Deferred<WatchStatusMap>}\n\t */\n\tgetStatusesByID( ids ) {\n\t\tif ( !ids.length ) {\n\t\t\treturn util.Deferred().resolve( {} );\n\t\t}\n\n\t\treturn this.api.get( {\n\t\t\tformatversion: 2,\n\t\t\taction: 'query',\n\t\t\tprop: 'info',\n\t\t\tinprop: 'watched',\n\t\t\tpageids: ids\n\t\t} ).then( ( rsp ) => this._unmarshalGetResponse( rsp ) );\n\t}\n\n\t/**\n\t * @param {PageTitle[]} titles\n\t * @return {jQuery.Deferred<WatchStatusMap>}\n\t */\n\tgetStatusesByTitle( titles ) {\n\t\tif ( !titles.length ) {\n\t\t\treturn util.Deferred().resolve( {} );\n\t\t}\n\n\t\treturn this.api.get( actionParams( {\n\t\t\tprop: 'info',\n\t\t\tinprop: 'watched',\n\t\t\ttitles\n\t\t} ) ).then( ( rsp ) => this._unmarshalGetResponse( rsp ) );\n\t}\n\n\t/**\n\t * @param {PageTitle[]} titles\n\t * @param {WatchStatus} watched\n\t * @return {jQuery.Deferred}\n\t */\n\tpostStatusesByTitle( titles, watched ) {\n\t\tconst params = {\n\t\t\taction: 'watch',\n\t\t\ttitles\n\t\t};\n\t\tif ( !watched ) {\n\t\t\tparams.unwatch = !watched;\n\t\t}\n\t\treturn this.api.postWithToken( 'watch', params );\n\t}\n\n\t/**\n\t * @param {Object} rsp The API:Info response.\n\t * @return {jQuery.Deferred<WatchStatusMap>}\n\t * @see getStatusesByID\n\t * @see getStatusesByTitle\n\t * @ignore\n\t */\n\t_unmarshalGetResponse( rsp ) {\n\t\tconst pages = rsp && rsp.query && rsp.query.pages || [];\n\t\treturn pages.reduce( ( statuses, page ) => {\n\t\t\tstatuses[page.title] = page.watched;\n\t\t\treturn statuses;\n\t\t}, {} );\n\t}\n}\n\nmodule.exports = WatchstarGateway;\n","const PageList = require( '../PageList' ),\n\twatchstar = require( './watchstar' ),\n\tuser = mw.user,\n\tutil = require( '../util' ),\n\tPage = require( '../Page' ),\n\tWatchstarGateway = require( './WatchstarGateway' );\n\n/**\n * @typedef {Object.<PageTitle, PageID>} PageTitleToPageIDMap\n * @ignore\n */\n\n/**\n * List of items page view\n *\n * @uses Page\n * @uses WatchstarGateway\n * @uses Watchstar\n * @ignore\n *\n * @fires WatchstarPageList#unwatch\n * @fires WatchstarPageList#watch\n */\nclass WatchstarPageList extends PageList {\n\n\t/**\n\t * @param {Object} options Configuration options\n\t */\n\tconstructor( options ) {\n\t\tsuper( options );\n\t}\n\n\tinitialize( options ) {\n\t\tthis.wsGateway = new WatchstarGateway( options.api );\n\t\tsuper.initialize( options );\n\t}\n\n\t/**\n\t * @instance\n\t * @mixes PageList#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {mw.Api} defaults.api\n\t */\n\tpostRender() {\n\t\tconst\n\t\t\tids = [],\n\t\t\ttitles = [];\n\n\t\tsuper.postRender();\n\n\t\tconst $items = this.queryUnitializedItems();\n\t\tconst pages = this.parsePagesFromItems( $items );\n\n\t\tObject.keys( pages ).forEach( ( title ) => {\n\t\t\tconst id = pages[title];\n\t\t\t// Favor IDs since they're short and unlikely to exceed URL length\n\t\t\t// limits when batched.\n\t\t\tif ( id && id !== '0' ) {\n\t\t\t\t// ID is present and valid.\n\t\t\t\tids.push( id );\n\t\t\t} else {\n\t\t\t\t// Only titles are available for missing pages.\n\t\t\t\ttitles.push( title );\n\t\t\t}\n\t\t} );\n\n\t\treturn this.getPages( ids, titles )\n\t\t\t.then( ( statuses ) => this.renderItems( $items, statuses ) );\n\t}\n\n\t/**\n\t * @param {jQuery.Element} $items\n\t * @param {WatchStatusMap} statuses\n\t * @ignore\n\t */\n\tqueryUnitializedItems() {\n\t\treturn this.$el.find( 'li:not(.with-watchstar)' );\n\t}\n\n\t/**\n\t * Retrieve pages\n\t *\n\t * @instance\n\t * @param {PageID[]} ids\n\t * @param {PageTitle[]} titles\n\t * @return {jQuery.Deferred<WatchStatusMap>}\n\t * @ignore\n\t */\n\tgetPages( ids, titles ) {\n\t\t// Rendering Watchstars for anonymous users is not useful. Short-circuit\n\t\t// the request.\n\t\tif ( user.isAnon() ) {\n\t\t\treturn util.Deferred().resolve( {} );\n\t\t}\n\n\t\treturn this.wsGateway.getStatuses( ids, titles );\n\t}\n\n\t/**\n\t * @param {jQuery.Element} $items\n\t * @return {PageTitleToPageIDMap}\n\t * @ignore\n\t */\n\tparsePagesFromItems( $items ) {\n\t\tconst\n\t\t\tpages = {};\n\t\t$items.each( ( _, item ) => {\n\t\t\tconst $item = this.$el.find( item );\n\t\t\tpages[$item.attr( 'title' )] = $item.data( 'id' );\n\t\t} );\n\t\treturn pages;\n\t}\n\n\t/**\n\t * @param {jQuery.Element} $items\n\t * @param {WatchStatusMap} statuses\n\t * @ignore\n\t */\n\trenderItems( $items, statuses ) {\n\t\t// Rendering Watchstars for anonymous users is not useful. Nothing to do.\n\t\tif ( user.isAnon() ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Create watch stars for each entry in list\n\t\t$items.each( ( _, item ) => {\n\t\t\tconst\n\t\t\t\t$item = this.$el.find( item ),\n\t\t\t\tpage = new Page( {\n\t\t\t\t\t// FIXME: Set sections so we don't hit the api (hacky)\n\t\t\t\t\tsections: [],\n\t\t\t\t\ttitle: $item.attr( 'title' ),\n\t\t\t\t\tid: $item.data( 'id' )\n\t\t\t\t} ),\n\t\t\t\twatched = statuses[page.getTitle()];\n\n\t\t\tthis._appendWatchstar( $item, page, watched );\n\t\t\t$item.addClass( 'with-watchstar' );\n\t\t} );\n\t}\n\n\t/**\n\t * @param {jQuery.Object} $item\n\t * @param {Page} page\n\t * @param {WatchStatus} watched\n\t * @private\n\t */\n\t_appendWatchstar( $item, page, watched ) {\n\t\twatchstar( {\n\t\t\t// WatchstarPageList.getPages() already retrieved the status of\n\t\t\t// each page. Explicitly set the watch state so another request\n\t\t\t// will not be issued by the Watchstar.\n\t\t\tisWatched: watched,\n\t\t\tpage\n\t\t} ).appendTo( $item );\n\t}\n}\n\nmodule.exports = WatchstarPageList;\n","const icons = require( '../icons' );\n\n/**\n * A clickable watchstar for logged in users.\n * Should not be used for anonymous users.\n *\n * @param {Object} options Configuration options\n * @param {Page} options.page\n * @param {boolean} options.isWatched is the article watched?\n * @return {IconButton}\n */\nmodule.exports = function ( options ) {\n\tconst isWatched = options.isWatched,\n\t\twatchstar = __non_webpack_require__( 'mediawiki.page.watch.ajax' ).watchstar,\n\t\taction = isWatched ? 'unwatch' : 'watch',\n\t\ticonProps = {\n\t\t\thref: mw.Title.newFromText( options.page.title ).getUrl( { action } )\n\t\t},\n\t\twatchButton = icons.watch( iconProps ),\n\t\twatchedButton = icons.watched( iconProps ),\n\t\tWATCH_BUTTON_CLASS = watchButton.getClassName(),\n\t\tWATCHED_BUTTON_CLASS = watchedButton.getClassName(),\n\t\tWATCH_CLASS = watchButton.getIcon().getClassName(),\n\t\tWATCHED_CLASS = watchedButton.getIcon().getClassName(),\n\t\tactiveIcon = isWatched ? watchedButton : watchButton,\n\t\tcallback = ( $link, watched ) => {\n\t\t\t$link.attr( 'class', watched ?\n\t\t\t\tWATCHED_BUTTON_CLASS : WATCH_BUTTON_CLASS );\n\t\t\tconst $icon = $link.find( '.mf-icon' );\n\t\t\t$icon.attr( 'class', watched ?\n\t\t\t\tWATCHED_CLASS : WATCH_CLASS );\n\t\t};\n\n\twatchstar( activeIcon.$el, options.page.title, callback );\n\treturn activeIcon;\n};\n"],"names":["View","util","module","exports","isTemplateMode","defaults","progressive","undefined","destructive","additionalClassNames","href","label","template","browser","memoize","method","memoized","cache","this","cacheId","key","join","call","arguments","Object","prototype","hasOwnProperty","apply","Date","now","toString","Math","random","Browser","constructor","userAgent","$container","$el","isIos","version","ua","ios","test","isWideScreen","val","parseInt","mw","config","get","window","innerWidth","supportsTouchEvents","getSingleton","$html","getDocument","navigator","IconButton","options","super","tagName","disabled","block","quiet","size","preRender","action","weight","extend","isIconOnly","icon","_button","_buttonHTML","outerHTML","Drawer","Button","Anchor","CtaDrawer","params","redirectParams","queryParams","returnTo","children","parseHTML","text","content","getUrl","msg","progressiveButton","addClass","append","signUpParams","signupQueryParams","actionAnchor","redirectURL","returnto","push","type","props","onBeforeHide","showCollapseIcon","events","hide","ev","preventDefault","click","stopPropagation","initialize","drawerClassName","className","collapseIcon","minHideDelay","show","d","Deferred","prepend","$mask","width","$drawer","find","hasClass","resolve","hook","fire","onShow","requestAnimationFrame","promise","removeClass","setTimeout","detach","postRender","trim","_iconClasses","getIconClasses","getRotationClass","rotationClass","rotation","Error","base","isSmall","rotationClasses","classes","getGlyphClassName","glyphPrefix","getClassName","attr","Icon","isTypeButton","_buttonClasses","getButtonClasses","_iconHTML","_icon","title","getIcon","header","Overlay","headerChrome","hideTimeout","timeout","_hideTimeout","showSpinner","hideSpinner","footerAnchor","$overlayContent","headers","heading","headerActions","onExitClick","exit","onBeforeExit","scrollTop","pageYOffset","scrollTo","clearTimeout","pageXOffset","emit","showHidden","ClassES5","log","warn","make","view","overlay","overlayManager","MANAGED_STATE","OverlayManager","router","container","on","_checkRoute","bind","entries","stack","hideCurrent","_onHideOverlayOutsideOverlayManager","length","currentRoute","route","routeIsString","currentPath","getPath","routeIsSame","match","back","_attachOverlay","parents","appendChild","_show","history","replaceState","location","once","_hideOverlay","onBeforeExitCancel","result","off","_processMatch","factoryResult","attachHideEvent","current","keys","reduce","m","id","_matchRoute","path","entry","didMatch","captures","previous","slice","getNext","factory","shift","next","unshift","add","docReady","replaceCurrent","stackOverlay","document","createElement","hash","state","body","pushState","__clearCache","HTML","html","relevantTitle","titleObj","displayTitle","escape","namespaceNumber","protection","url","wikidataDescription","_isMainPage","isMainPage","isMissing","anchor","revId","_isWatched","isWatched","thumbnail","isLandscape","height","getDisplayTitle","inNamespace","namespace","isWikiText","isVEAvailable","isVEVisualAvailable","namespaces","indexOf","isVESourceAvailable","getRevisionId","getTitle","getNamespaceId","nsId","args","split","toLowerCase","replace","Thumbnail","HEADING_SELECTOR","EXCLUDE_THUMBNAIL_CLASS_SELECTORS","NOT_SELECTORS","map","excludeSelector","THUMB_SELECTOR","selector","PageHTMLParser","$headings","findSectionHeadingByIndex","sectionIndex","$","filter","eq","findChildInSectionLead","$heading","$nextHeading","headingSelector","withNestedChildren","$matchingNodes","addBack","$lead","getLeadSectionElement","$nestedSection","prevAll","nextAll","nextUntil","$leadSection","getThumbnail","$a","notSelector","$lazyImage","URL","legacyTitle","searchParams","pathname","valid","RegExp","data","el","filename","percentDecodeFragment","getThumbnails","thumbs","each","i","thumbEl","thumb","getRedLinks","getLanguages","pageTitle","mapLinkToLanguageObj","node","autonym","textContent","langname","getAttribute","lang","languages","Array","querySelectorAll","variants","pages","renderPageImages","style","templatePartials","item","currentPage","eventBus","skin","Skin","isBorderBox","page","name","getLicenseLinks","mobileLicense","message","mobileMsgExists","exists","parseDom","clone","getLicenseMsg","$licenseLinks","licenseMsg","licensePlural","language","convertNumber","$termsLink","parse","description","siblings","prop","getDescription","getFileName","delegateEventSplitter","idCounter","OO","EventEmitter","cid","prefix","uniqueId","_postInitialize","render","undelegateEvents","skipTemplateRender","replaceWith","delegateEvents","delegate","eventName","listener","undelegate","forEach","$child","mixinClass","defaultParams","formatversion","otherParams","scriptPath","origin","buttonLabel","toast","createPromoCampaign","amcOutreachDrawer","ACTIONS","onDesktopLink","onHistoryLink","onTalkLink","campaign","loadCampaign","returnToTitle","returnToQuery","user","tokens","storage","AmcEnableForm","promoCampaign","mwMessage","mwUtil","csrfToken","postUrl","returntoquery","fields","value","submit","makeActionIneligible","showOnPageReload","Page","permissions","concat","Title","newFromText","getPrefixedText","edit","pageHTMLParser","actionParams","feature","displayWikibaseDescriptions","search","watchlist","tagline","icons","makeHeader","headingOrView","headerCancel","templateData","hasActions","isHidden","cancel","insertAfter","component","savingHeader","spinner","saveHeader","saveButtonMessage","formHeader","formHTMLOrView","CANCEL_GLYPH","variant","glyph","assign","error","watch","watched","placeholderClass","queryPlaceholders","root","getElementsByClassName","loadImages","placeholders","Promise","all","placeholder","loadImage","deferred","dataset","image","Image","setAttribute","class","alt","useMap","usemap","cssText","addEventListener","classList","parentNode","replaceChild","src","mwSrc","srcset","mwSrcset","_register","require","registry","localRequire","e","define","obj","deprecate","deprecatedId","replacement","ModuleLoader","resp","pageprops","displaytitle","terms","entityterms","pageid","missing","actions","campaignName","campaignActive","userEligible","mwStorage","ACTIONS_TO_STORAGE_KEYS","a","isCampaignActive","validateAction","showIfEligible","isActionEligible","set","makeAllActionsIneligible","storageKey","requestIdleCallback","JSON","notify","remove","stringify","promises","when","escapeSelector","fn","documentElement","getWindow","ctx","source","getSource","partials","partialSource","Mustache","api","getStatuses","ids","titles","getStatusesByID","getStatusesByTitle","then","inprop","pageids","rsp","_unmarshalGetResponse","postStatusesByTitle","unwatch","postWithToken","query","statuses","PageList","watchstar","WatchstarGateway","wsGateway","$items","queryUnitializedItems","parsePagesFromItems","getPages","renderItems","isAnon","_","$item","sections","_appendWatchstar","appendTo","iconProps","watchButton","watchedButton","WATCH_BUTTON_CLASS","WATCHED_BUTTON_CLASS","WATCH_CLASS","WATCHED_CLASS","activeIcon","$link"],"sourceRoot":""}