wikimedia/mediawiki-extensions-MobileFrontend

View on GitHub
resources/dist/mobile.startup.js.map.json

Summary

Maintainability
Test Coverage
{"version":3,"file":"mobile.startup.js","mappings":"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","sources":["webpack://mfModules/./src/mobile.startup/LanguageInfo.js","webpack://mfModules/./src/mobile.startup/languageOverlay/getDeviceLanguage.js","webpack://mfModules/./src/mobile.startup/languageOverlay/languageInfoOverlay.js","webpack://mfModules/./src/mobile.startup/languageOverlay/languageOverlay.js","webpack://mfModules/./src/mobile.startup/mediaViewer/overlay.js","webpack://mfModules/./src/mobile.startup/mobile.startup.js","webpack://mfModules/./src/mobile.startup/promisedView.js","webpack://mfModules/./src/mobile.startup/references/ReferencesGateway.js","webpack://mfModules/./src/mobile.startup/references/ReferencesHtmlScraperGateway.js","webpack://mfModules/./src/mobile.startup/references/references.js","webpack://mfModules/./src/mobile.startup/search/SearchGateway.js","webpack://mfModules/./src/mobile.startup/search/SearchHeaderView.js","webpack://mfModules/./src/mobile.startup/search/SearchOverlay.js","webpack://mfModules/./src/mobile.startup/search/SearchResultsView.js","webpack://mfModules/./src/mobile.startup/search/searchHeader.js","webpack://mfModules/./src/mobile.startup/time.js"],"sourcesContent":["const util = require( './util.js' ),\n\tactionParams = require( './actionParams' );\n\n/**\n * API for providing language data.\n *\n * @class module:mobile.startup/languages~LanguageInfo\n * @param {mw.Api} api\n */\nfunction LanguageInfo( api ) {\n\tthis.api = api;\n}\n\nLanguageInfo.prototype = {\n\n\t/**\n\t * Get languageinfo API data from the local wiki, and transform it into a\n\t * format usable by LanguageSearcher.\n\t *\n\t * @memberof module:mobile.startup/languages~LanguageInfo\n\t * @instance\n\t * @returns {jQuery.Deferred}\n\t */\n\tgetLanguages() {\n\t\treturn this.api.get( actionParams( {\n\t\t\tmeta: 'languageinfo',\n\t\t\tliprop: 'code|autonym|name|bcp47'\n\t\t} ) ).then( ( resp ) => {\n\t\t\tconst filteredLanguages = [];\n\t\t\t// Filter out legacy languages and require an autonym.\n\t\t\t// If the bcp47 (https://w.wiki/Y7A) does not match the language\n\t\t\t// code, that is in an indication that the language code is outdated\n\t\t\t// and should not be used.\n\t\t\tObject.keys( resp.query.languageinfo ).forEach( ( key ) => {\n\t\t\t\tconst language = resp.query.languageinfo[key];\n\t\t\t\tif ( ( language.code.toLowerCase() === language.bcp47.toLowerCase() ) &&\n\t\t\t\t\tlanguage.autonym ) {\n\t\t\t\t\tfilteredLanguages.push( language );\n\t\t\t\t}\n\t\t\t} );\n\t\t\treturn filteredLanguages;\n\t\t}, () => util.Deferred().reject() ).then( ( filteredLanguages ) => ( {\n\t\t\tlanguages: filteredLanguages.map( ( data ) => {\n\t\t\t\tdata.url = '#';\n\t\t\t\tdata.lang = data.code;\n\t\t\t\tdata.langname = data.name;\n\t\t\t\t// FIXME: This isn't a \"title\" in the sense of a MediaWiki\n\t\t\t\t// Title, and it is rendered as a subheader in the list\n\t\t\t\t// item, so a different name would be wiser, both here and\n\t\t\t\t// in LanguageSearcher's template. Also it would arguably\n\t\t\t\t// be more intuitive for the language name (localized) to\n\t\t\t\t// appear as the main emphasized element of each language\n\t\t\t\t// list element; but instead the autonym has that role.\n\t\t\t\t// A more thorough refactoring of LanguageSearcher to allow\n\t\t\t\t// for generic header/subheader elements is left for a\n\t\t\t\t// follow-up.\n\t\t\t\tdata.title = data.name;\n\t\t\t\treturn data;\n\t\t\t} )\n\t\t} ), () => util.Deferred().reject() );\n\t}\n};\n\nmodule.exports = LanguageInfo;\n","/**\n * Return the language code of the device in lowercase\n *\n * @ignore\n * @param {window.navigator} navigator\n * @return {string|undefined}\n */\nfunction getDeviceLanguage( navigator ) {\n\tconst lang = navigator.languages ?\n\t\tnavigator.languages[ 0 ] :\n\t\tnavigator.language || navigator.userLanguage ||\n\t\t\t\tnavigator.browserLanguage || navigator.systemLanguage;\n\n\treturn lang ? lang.toLowerCase() : undefined;\n}\n\nmodule.exports = getDeviceLanguage;\n","const\n\tm = require( '../moduleLoaderSingleton' ),\n\tgetDeviceLanguage = require( './getDeviceLanguage' ),\n\tOverlay = require( '../Overlay' ),\n\tpromisedView = require( '../promisedView' );\n\n/**\n * @ignore\n * @param {LanguageInfo} languageInfo\n * @param {boolean} showSuggestedLanguages If the suggested languages section\n * should be rendered.\n * @return {jQuery.Promise} Resolves to LanguageSearcher\n */\nfunction loadLanguageInfoSearcher( languageInfo, showSuggestedLanguages ) {\n\treturn mw.loader.using( 'mobile.languages.structured' ).then( () => languageInfo.getLanguages() ).then( ( data ) => {\n\t\tconst LanguageSearcher = m.require( 'mobile.languages.structured/LanguageSearcher' );\n\t\treturn new LanguageSearcher( {\n\t\t\tlanguages: data.languages,\n\t\t\tvariants: data.variants,\n\t\t\tshowSuggestedLanguages,\n\t\t\tdeviceLanguage: getDeviceLanguage( navigator )\n\t\t} );\n\n\t} );\n}\n\n/**\n * Factory function that returns a language info featured instance of an Overlay\n *\n * @ignore\n * @function\n * @memberof module:mobile.startup/languages\n * @param {module:mobile.startup/languages~LanguageInfo} languageInfo\n * @param {boolean} showSuggestedLanguages If the suggested languages section\n * should be rendered.\n * @return {module:mobile.startup/Overlay}\n */\nfunction languageInfoOverlay( languageInfo, showSuggestedLanguages ) {\n\treturn Overlay.make(\n\t\t{\n\t\t\theading: mw.msg( 'mobile-frontend-language-heading' ),\n\t\t\tclassName: 'overlay language-info-overlay'\n\t\t}, promisedView( loadLanguageInfoSearcher( languageInfo, showSuggestedLanguages ) )\n\t);\n}\n\n// To make knowing when async logic has resolved easier in tests\nlanguageInfoOverlay.test = {\n\tloadLanguageInfoSearcher\n};\n\nmodule.exports = languageInfoOverlay;\n","const\n\tm = require( '../moduleLoaderSingleton' ),\n\tgetDeviceLanguage = require( './getDeviceLanguage' ),\n\tOverlay = require( '../Overlay' ),\n\tMessageBox = require( '../MessageBox' ),\n\tcurrentPageHTMLParser = require( '../currentPageHTMLParser' )(),\n\tpromisedView = require( '../promisedView' );\n\n/**\n * @ignore\n * @return {jQuery.Promise} Resolves to LanguageSearcher\n */\nfunction loadLanguageSearcher() {\n\treturn mw.loader.using( 'mobile.languages.structured' ).then( () =>\n\t\tcurrentPageHTMLParser.getLanguages(\n\t\t\tmw.config.get( 'wgTitle' )\n\t\t) ).then( ( data ) => {\n\t\tconst LanguageSearcher = m.require( 'mobile.languages.structured/LanguageSearcher' );\n\n\t\treturn new LanguageSearcher( {\n\t\t\tlanguages: data.languages,\n\t\t\tvariants: data.variants,\n\t\t\tshowSuggestedLanguages: true,\n\t\t\tdeviceLanguage: getDeviceLanguage( navigator ),\n\t\t\t/**\n\t\t\t * Stable for use inside ContentTranslation.\n\t\t\t * @event ~'mobileFrontend.languageSearcher.onOpen'\n\t\t\t * @memberof Hooks\n\t\t\t * @param {Hooks~LanguageSearcher} searcher\n\t\t\t */\n\t\t\tonOpen: ( searcher ) => mw.hook( 'mobileFrontend.languageSearcher.onOpen' ).fire( searcher )\n\t\t} );\n\t}, () =>\n\t\tnew MessageBox( {\n\t\t\ttype: 'error',\n\t\t\tclassName: 'content',\n\t\t\tmsg: mw.msg( 'mobile-frontend-languages-structured-overlay-error' )\n\t\t} ) );\n}\n\n/**\n * Factory function that returns a language featured instance of an Overlay.\n *\n * @function\n * @memberof module:mobile.startup/languages\n * @return {module:mobile.startup/Overlay}\n */\nfunction languageOverlay() {\n\treturn Overlay.make(\n\t\t{\n\t\t\theading: mw.msg( 'mobile-frontend-language-heading' ),\n\t\t\tclassName: 'overlay language-overlay'\n\t\t}, promisedView( loadLanguageSearcher() )\n\t);\n}\n\n// To make knowing when async logic has resolved easier in tests\nlanguageOverlay.test = {\n\tloadLanguageSearcher\n};\n\nmodule.exports = languageOverlay;\n","/**\n * Internal for use inside Minerva only. See {@link module:mobile.startup} for access.\n *\n * @module mobile.startup/mediaViewer\n */\nconst m = require( '../moduleLoaderSingleton' ),\n\tpromisedView = require( '../promisedView' ),\n\tutil = require( '../util' ),\n\theader = require( '../headers' ).header,\n\ticons = require( '../icons' ),\n\tOverlay = require( '../Overlay' );\n\n/**\n * Produce an overlay for mediaViewer\n *\n * @name overlay\n * @memberof module:mobile.startup/mediaViewer\n * @param {Object} options\n * @return {module:mobile.startup/Overlay}\n */\nfunction mediaViewerOverlay( options ) {\n\tconst overlay = Overlay.make(\n\t\t{\n\t\t\theaders: [\n\t\t\t\theader( '', [], icons.cancel( 'gray' ) )\n\t\t\t],\n\t\t\tclassName: 'overlay media-viewer'\n\t\t},\n\t\tpromisedView(\n\t\t\tutil.Promise.all( [\n\t\t\t\tmw.loader.using( 'mobile.mediaViewer' )\n\t\t\t] ).then( () => {\n\t\t\t\tconst ImageCarousel = m.require( 'mobile.mediaViewer' ).ImageCarousel;\n\t\t\t\treturn new ImageCarousel( options );\n\t\t\t} )\n\t\t)\n\t);\n\n\treturn overlay;\n}\n\nmodule.exports = mediaViewerOverlay;\n","const currentPageHTMLParser = require( './currentPageHTMLParser' );\nconst time = require( './time' );\nconst LanguageInfo = require( './LanguageInfo' );\nconst currentPage = require( './currentPage' );\nconst Drawer = require( './Drawer' );\nconst CtaDrawer = require( './CtaDrawer' );\nconst lazyImageLoader = require( './lazyImages/lazyImageLoader' );\nconst icons = require( './icons' );\nconst PageHTMLParser = require( './PageHTMLParser' );\nconst showOnPageReload = require( './showOnPageReload' );\nconst OverlayManager = require( './OverlayManager' );\nconst View = require( './View' );\nconst Overlay = require( './Overlay' );\nconst references = require( './references/references' );\nconst search = {\n\tSearchOverlay: require( './search/SearchOverlay' ),\n\tSearchGateway: require( './search/SearchGateway' )\n};\nconst promisedView = require( './promisedView' );\nconst headers = require( './headers' );\nconst Skin = require( './Skin' );\nconst mediaViewer = {\n\toverlay: require( './mediaViewer/overlay' )\n};\nconst languageInfoOverlay = require( './languageOverlay/languageInfoOverlay' );\nconst languageOverlay = require( './languageOverlay/languageOverlay' );\nconst amcOutreach = require( './amcOutreach/amcOutreach' );\n\n// Expose chunk to temporary variable which will be deleted and exported via ResourceLoader\n// package inside mobile.startup.exports.\n\n/**\n * The main library for accessing MobileFrontend's stable APIs.\n *\n * @module mobile.startup\n */\nmw._mobileFrontend = {\n\t/**\n\t * Internal for use inside Minerva only\n\t *\n\t * @memberof module:mobile.startup\n\t * @type module:mobile.startup/AmcOutreach\n\t */\n\n\tamcOutreach,\n\t// Internal for use inside GrowthExperiments only.\n\toverlayHeader: headers.header,\n\t/**\n\t * Internal for use inside Minerva, GrowthExperiments only.\n\t * @type module:mobile.startup/Drawer\n\t */\n\tDrawer,\n\t// Internal for use inside Minerva only.\n\tCtaDrawer,\n\t/**\n\t * Internal for use inside Minerva, ExternalGuidance and Echo only.\n\t *\n\t * @memberof module:mobile.startup\n\t * @type module:mobile.startup/View\n\t */\n\tView,\n\t/**\n\t * Internal for use inside Minerva, ExternalGuidance,\n\t *  GrowthExperiments and Echo only.\n\t *\n\t * @memberof module:mobile.startup\n\t * @type module:mobile.startup/Overlay\n\t */\n\tOverlay,\n\t/**\n\t * Internal for use inside Minerva only.\n\t *\n\t * @memberof module:mobile.startup\n\t * @type module:mobile.startup/PageHTMLParser\n\t */\n\tcurrentPageHTMLParser,\n\t/**\n\t * Internal for use inside Minerva, ExternalGuidance and Echo only.\n\t *\n\t * @memberof module:mobile.startup\n\t * @return {module:mobile.startup/OverlayManager}\n\t */\n\tgetOverlayManager: () => {\n\t\treturn OverlayManager.getSingleton();\n\t},\n\t/**\n\t * Internal for use inside Minerva only.\n\t * @type module:mobile.startup/Page\n\t * @memberof module:mobile.startup\n\t */\n\tcurrentPage,\n\t/**\n\t * Internal for use inside Minerva only.\n\t * @type module:mobile.startup/PageHTMLParser\n\t * @memberof module:mobile.startup\n\t */\n\tPageHTMLParser,\n\t/**\n\t * Internal for use inside Minerva only.\n\t * @type module:mobile.startup/Icon\n\t * @memberof module:mobile.startup\n\t */\n\tspinner: icons.spinner,\n\t/**\n\t * Internal for use inside Minerva only.\n\t *\n\t * @memberof module:mobile.startup\n\t * @type module:mobile.startup/mediaViewer\n\t */\n\tmediaViewer,\n\t/**\n\t * Internal for use inside Minerva only.\n\t *\n\t * @memberof module:mobile.startup\n\t * @type module:mobile.startup/references\n\t */\n\treferences,\n\t/**\n\t * Internal for use inside Minerva only.\n\t *\n\t * @memberof module:mobile.startup\n\t * @type module:mobile.startup/search\n\t */\n\tsearch,\n\t/**\n\t * Internal for use inside Minerva only.\n\t *\n\t * @memberof module:mobile.startup\n\t * @type module:mobile.startup/time\n\t */\n\ttime,\n\t// Internal for use inside Echo, GrowthExperiments only.\n\tpromisedView,\n\t/**\n\t * Loads all images on the page, stable to call.\n\t *\n\t * @memberof module:mobile.startup\n\t * @return {jQuery.Deferred}\n\t */\n\tloadAllImagesInPage: () => {\n\t\treturn lazyImageLoader.loadImages(\n\t\t\tlazyImageLoader.queryPlaceholders( document.getElementById( 'content' ) )\n\t\t);\n\t},\n\t/**\n\t * Show a notification on page reload, internal for Minerva\n\t *\n\t * @memberof module:mobile.startup\n\t * @param {string} msg\n\t * @return {jQuery.Deferred}\n\t */\n\tnotifyOnPageReload: ( msg ) => showOnPageReload( msg ),\n\t/**\n\t * Internal for use inside VisualEditor\n\t *\n\t * @memberof module:mobile.startup\n\t * @return {string|undefined}\n\t */\n\tlicense() {\n\t\tconst skin = Skin.getSingleton();\n\t\treturn skin.getLicenseMsg();\n\t},\n\t/**\n\t * Internal for use inside Minerva. See {@link module:mobile.startup} for access.\n\t *\n\t * @module mobile.startup/languages\n\t */\n\t/**\n\t * Access to language overlays for usage inside Minerva only.\n\t *\n\t * @memberof module:mobile.startup\n\t * @type module:mobile.startup/languages\n\t */\n\tlanguages: {\n\t\tlanguageOverlay,\n\t\t/**\n\t\t * Shows information about suggested languages.\n\t\t *\n\t\t * @memberof module:mobile.startup/languages\n\t\t * @param {mw.Api} api\n\t\t * @param {boolean} showSuggestedLanguage If the suggested languages section\n\t\t * should be rendered.\n\t\t */\n\t\tlanguageInfoOverlay( api, showSuggestedLanguage ) {\n\t\t\treturn languageInfoOverlay( new LanguageInfo( api ), showSuggestedLanguage );\n\t\t}\n\t}\n};\n","const\n\ticons = require( './icons' ),\n\tView = require( './View' );\n\n/**\n * Internal for use inside Echo, GrowthExperiments only.\n * It's a view that spins until the promise resolves!\n * If the promise successfully resolves, the newView will be shown. if the\n * promise rejects and rejects to a view, the errorView will be shown.\n *\n * @function promisedView\n * @memberof module:mobile.startup\n * @param {jQuery.Promise} promise\n * @return {module:mobile.startup/View}\n */\nmodule.exports = function promisedView( promise ) {\n\tconst view = new View( {\n\t\tclassName: 'promised-view'\n\t} );\n\tview.$el.append( icons.spinner().$el );\n\tpromise.then( ( newView ) => {\n\t\tview.$el.replaceWith( newView.$el );\n\t\t// update the internal reference.\n\t\tview.$el = newView.$el;\n\t}, ( errorView ) => {\n\t\tif ( !errorView || !errorView.$el ) {\n\t\t\t// return early to keep backwards compatibility with clients of\n\t\t\t// promisedView that do not reject to an error view\n\t\t\treturn;\n\t\t}\n\n\t\tview.$el.replaceWith( errorView.$el );\n\t\t// update the internal reference.\n\t\tview.$el = errorView.$el;\n\t} );\n\n\treturn view;\n};\n","/**\n * Abstract base class\n * Gateway for retrieving references\n *\n * @class module:mobile.startup/references~Gateway\n * @abstract\n *\n * @param {mw.Api} api\n */\nfunction ReferencesGateway( api ) {\n\tthis.api = api;\n}\n\n/**\n * Return the matched reference via API or DOM query\n *\n * @memberof module:mobile.startup/references~Gateway\n * @instance\n * @param {string} id CSS selector\n * @param {Page} page to find reference for\n * @param {module:mobile.startup/PageHTMLParser} pageHTMLParser\n * @return {jQuery.Promise} resolves with an Object representing reference\n *  with a `text` property\n *  The promise should be rejected with ReferenceGateway.ERROR_NOT_EXIST:\n *  if the reference is not found.\n *  If for some reason locating the reference fails return ReferenceGateway.ERROR_OTHER.\n */\nReferencesGateway.prototype.getReference = null;\n\n/**\n * ERROR_NOT_EXIST error code to be returned by getReference\n *  when a reference does not exist.\n *\n * @memberof module:mobile.startup/references~Gateway\n * @type string\n */\nReferencesGateway.ERROR_NOT_EXIST = 'NOT_EXIST_ERROR';\n/**\n * ERROR_OTHER error code to be returned by getReference\n *  under any other circumstance not covered\n *  by ERROR_NOT_EXIST. It should be used if it is unclear whether a reference exists or not.\n *\n * @memberof module:mobile.startup/references~Gateway\n * @type string\n */\nReferencesGateway.ERROR_OTHER = 'OTHER_ERROR';\n\nmodule.exports = ReferencesGateway;\n","const ReferencesGateway = require( './ReferencesGateway' ),\n\tmfExtend = require( './../mfExtend' ),\n\tutil = require( './../util' );\n\n/**\n * Gateway for retrieving references via the content of the Page\n *\n * @class ReferencesHtmlScraperGateway\n * @memberof module:mobile.startup/references\n * @extends module:mobile.startup/references~Gateway\n * @inheritdoc\n */\nfunction ReferencesHtmlScraperGateway() {\n\tReferencesGateway.apply( this, arguments );\n}\n\nmfExtend( ReferencesHtmlScraperGateway, ReferencesGateway, {\n\t/**\n\t * @memberof ReferencesHtmlScraperGateway\n\t * @property EXTERNAL_LINK_CLASS a CSS class to place on external links\n\t * in addition to the default 'external' class.\n\t */\n\tEXTERNAL_LINK_CLASS: 'external--reference',\n\t/**\n\t * @memberof ReferencesHtmlScraperGateway\n\t * @instance\n\t * @param {string} id ID of a DOM element in the page.\n\t * @param {jQuery.Object} $container to scan for an element\n\t * @return {jQuery.Promise} that can be used by getReference\n\t */\n\tgetReferenceFromContainer( id, $container ) {\n\t\tconst result = util.Deferred();\n\n\t\tconst $el = $container.find( '#' + util.escapeSelector( id ) );\n\t\tif ( $el.length ) {\n\t\t\tlet $parent;\n\n\t\t\t// This finds either the inner <ol class=\"mw-extended-references\">, or the outer\n\t\t\t// <ol class=\"references\">\n\t\t\tconst $ol = $el.closest( 'ol' );\n\t\t\tconst isSubref = $ol.hasClass( 'mw-extended-references' );\n\t\t\tif ( isSubref ) {\n\t\t\t\t$parent = $ol.parent();\n\t\t\t}\n\t\t\t// The following classes are used here:\n\t\t\t// * external--reference\n\t\t\t// * other values of EXTERNAL_LINK_CLASS in sub-classes\n\t\t\t( $parent || $el ).find( '.external' ).addClass( this.EXTERNAL_LINK_CLASS );\n\t\t\tresult.resolve( {\n\t\t\t\ttext: this.getReferenceHtml( $el ),\n\t\t\t\tparentText: this.getReferenceHtml( $parent ),\n\t\t\t\tisSubref\n\t\t\t} );\n\t\t} else {\n\t\t\tresult.reject( ReferencesGateway.ERROR_NOT_EXIST );\n\t\t}\n\t\treturn result.promise();\n\t},\n\t/**\n\t * @memberof ReferencesHtmlScraperGateway\n\t * @param {jQuery.Object|undefined} $reference\n\t * @return {string|undefined}\n\t */\n\tgetReferenceHtml( $reference ) {\n\t\treturn $reference ?\n\t\t\t$reference.children( '.mw-reference-text, .reference-text' ).first().html() :\n\t\t\t'';\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof ReferencesHtmlScraperGateway\n\t * @instance\n\t * @param {string} hash Hash fragment with leading '#'\n\t * @param {Page} page (unused)\n\t * @param {module:mobile.startup/PageHTMLParser} pageHTMLParser\n\t */\n\tgetReference( hash, page, pageHTMLParser ) {\n\t\tconst id = mw.util.percentDecodeFragment( hash.slice( 1 ) );\n\t\t// If an id is not found it's possible the id passed needs decoding (per T188547).\n\t\treturn this.getReferenceFromContainer( id, pageHTMLParser.$el.find( 'ol.references' ) );\n\t}\n} );\n\nmodule.exports = ReferencesHtmlScraperGateway;\n","const Drawer = require( '../Drawer' ),\n\tutil = require( '../util' ),\n\ticons = require( '../icons' ),\n\tReferencesGateway = require( './ReferencesGateway' ),\n\tIcon = require( '../Icon' ),\n\tReferencesHtmlScraperGateway = require( './ReferencesHtmlScraperGateway' ),\n\tIconButton = require( '../IconButton' );\n\n/**\n * Create a callback for clicking references\n *\n * @ignore\n * @param {Function} onNestedReferenceClick\n * @return {Function}\n */\nfunction makeOnNestedReferenceClickHandler( onNestedReferenceClick ) {\n\treturn ( ev ) => {\n\t\tconst target = ev.currentTarget.querySelector( 'a' );\n\t\tif ( target ) {\n\t\t\tonNestedReferenceClick(\n\t\t\t\ttarget.getAttribute( 'href' ),\n\t\t\t\ttarget.textContent\n\t\t\t);\n\t\t\t// Don't hide the already shown drawer via propagation\n\t\t\treturn false;\n\t\t}\n\t};\n}\n\n/**\n * Drawer for references\n *\n * @memberof module:mobile.startup/references\n * @uses IconButton\n * @param {Object} props\n * @param {boolean} [props.error] whether an error has occurred\n * @param {string} props.title of reference e.g [1]\n * @param {string} props.text is the HTML of the reference\n * @param {string} [props.parentText] is the HTML of the parent reference if there is one\n * @param {boolean} props.isSubref true when this reference has a parent\n * @param {Function} [props.onNestedReferenceClick] callback for when a reference\n *  inside the reference is clicked.\n * @return {module:mobile.startup/Drawer}\n */\nfunction referenceDrawer( props ) {\n\tconst errorIcon = props.error ? new IconButton( {\n\t\tname: 'error',\n\t\tisSmall: true\n\t} ).$el : null;\n\n\tconst mainRef = props.isSubref ? props.parentText : props.text;\n\tconst mainRefHtml = util.parseHTML( '<div>' )\n\t\t.addClass( 'main-reference-content' )\n\t\t.html( mainRef );\n\tif ( !mainRef ) {\n\t\tmainRefHtml.append( icons.spinner().$el );\n\t}\n\tconst subRefHtml = props.isSubref ?\n\t\tutil.parseHTML( '<div>' ).html( props.text ) : '';\n\n\treturn new Drawer(\n\t\tutil.extend(\n\t\t\t{\n\t\t\t\tshowCollapseIcon: false,\n\t\t\t\tclassName: 'drawer position-fixed text references-drawer',\n\t\t\t\tevents: {\n\t\t\t\t\t'click sup a': function ( ev ) {\n\t\t\t\t\t\t// Stop default scroll to hash fragment behaviour.\n\t\t\t\t\t\tev.preventDefault();\n\t\t\t\t\t},\n\t\t\t\t\t'click sup': props.onNestedReferenceClick &&\n\t\t\t\t\t\tmakeOnNestedReferenceClickHandler( props.onNestedReferenceClick )\n\t\t\t\t},\n\t\t\t\tchildren: [\n\t\t\t\t\tutil.parseHTML( '<div>' )\n\t\t\t\t\t\t.addClass( 'references-drawer__header' )\n\t\t\t\t\t\t.append( [\n\t\t\t\t\t\t\tnew Icon( {\n\t\t\t\t\t\t\t\ticon: 'reference',\n\t\t\t\t\t\t\t\tisSmall: true\n\t\t\t\t\t\t\t} ).$el,\n\t\t\t\t\t\t\tutil.parseHTML( '<span>' ).addClass( 'references-drawer__title' ).text( mw.msg( 'mobile-frontend-references-citation' ) ),\n\t\t\t\t\t\t\ticons.cancel( 'gray', {\n\t\t\t\t\t\t\t\tisSmall: true,\n\t\t\t\t\t\t\t\tadditionalClassNames: 'mf-button-flush-right'\n\t\t\t\t\t\t\t} ).$el\n\t\t\t\t\t\t] ),\n\n\t\t\t\t\t// Add .mw-parser-output so that TemplateStyles styles apply (T244510)\n\t\t\t\t\tutil.parseHTML( '<div>' ).addClass( 'mw-parser-output' ).append( [\n\t\t\t\t\t\terrorIcon,\n\t\t\t\t\t\tutil.parseHTML( '<sup>' ).text( props.title ),\n\t\t\t\t\t\tmainRefHtml,\n\t\t\t\t\t\tsubRefHtml\n\t\t\t\t\t] )\n\t\t\t\t]\n\t\t\t},\n\t\t\tprops\n\t\t)\n\t);\n}\n\n/**\n * Internal for use inside Minerva only. See {@link module:mobile.startup} for access.\n *\n * @exports module:mobile.startup/references\n */\nconst references = {\n\ttest: {\n\t\tmakeOnNestedReferenceClickHandler\n\t},\n\tReferencesHtmlScraperGateway,\n\treferenceDrawer,\n\t/**\n\t * Fetch and render nested reference upon click\n\t *\n\t * @param {string} id of the reference to be retrieved\n\t * @param {Page} page to locate reference for\n\t * @param {string} refNumber the number it identifies as in the page\n\t * @param {module:mobile.startup/PageHTMLParser} pageHTMLParser\n\t * @param {module:mobile.startup/references~Gateway} gateway\n\t * @param {Object} props for referenceDrawer\n\t * @param {Function} onShowNestedReference function call when a nested reference is triggered.\n\t * @return {jQuery.Deferred}\n\t */\n\tshowReference( id, page, refNumber, pageHTMLParser, gateway, props,\n\t\tonShowNestedReference\n\t) {\n\t\treturn gateway.getReference( id, page, pageHTMLParser ).then( ( reference ) => {\n\t\t\tconst drawer = referenceDrawer( util.extend( {\n\t\t\t\ttitle: refNumber,\n\t\t\t\ttext: reference.text,\n\t\t\t\tparentText: reference.parentText,\n\t\t\t\tisSubref: reference.isSubref,\n\t\t\t\tonNestedReferenceClick( href, text ) {\n\t\t\t\t\treferences.showReference(\n\t\t\t\t\t\thref,\n\t\t\t\t\t\tpage,\n\t\t\t\t\t\ttext,\n\t\t\t\t\t\tpageHTMLParser,\n\t\t\t\t\t\tgateway\n\t\t\t\t\t).then( ( nestedDrawer ) => {\n\t\t\t\t\t\tif ( props.onShowNestedReference ) {\n\t\t\t\t\t\t\tonShowNestedReference( drawer, nestedDrawer );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmw.log.warn( 'Please provide onShowNestedReferences parameter.' );\n\t\t\t\t\t\t\tdocument.body.appendChild( nestedDrawer.$el[0] );\n\t\t\t\t\t\t\tdrawer.hide();\n\t\t\t\t\t\t\tnestedDrawer.show();\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}, props ) );\n\t\t\treturn drawer;\n\t\t}, ( err ) => {\n\t\t\t// If non-existent reference nothing to do.\n\t\t\tif ( err === ReferencesGateway.ERROR_NOT_EXIST ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\treturn referenceDrawer( {\n\t\t\t\terror: true,\n\t\t\t\ttitle: refNumber,\n\t\t\t\ttext: mw.msg( 'mobile-frontend-references-citation-error' )\n\t\t\t} );\n\t\t} );\n\t}\n};\n\nmodule.exports = references;\n","/**\n * Internal for use inside Minerva only. See {@link module:mobile.startup} for access.\n *\n * @module module:mobile.startup/search\n */\nconst\n\tpageJSONParser = require( '../page/pageJSONParser' ),\n\tutil = require( '../util' ),\n\textendSearchParams = require( '../extendSearchParams' );\n\n/**\n * Interact with MediaWiki search API.\n *\n * @memberof module:mobile.startup/search\n * @uses mw.Api\n * @param {mw.Api} api\n */\nfunction SearchGateway( api ) {\n\tthis.api = api;\n\tthis.searchCache = {};\n\tthis.generator = mw.config.get( 'wgMFSearchGenerator' );\n}\n\nSearchGateway.prototype = {\n\t/**\n\t * The namespace to search in.\n\t *\n\t * @memberof SearchGateway\n\t * @instance\n\t * @type {number}\n\t */\n\tsearchNamespace: 0,\n\n\t/**\n\t * Get the data used to do the search query api call.\n\t *\n\t * @memberof SearchGateway\n\t * @instance\n\t * @param {string} query to search for\n\t * @return {Object}\n\t */\n\tgetApiData( query ) {\n\t\tconst prefix = this.generator.prefix,\n\t\t\tdata = extendSearchParams( 'search', {\n\t\t\t\tgenerator: this.generator.name\n\t\t\t} );\n\n\t\tdata.redirects = '';\n\n\t\tdata['g' + prefix + 'search'] = query;\n\t\tdata['g' + prefix + 'namespace'] = this.searchNamespace;\n\t\tdata['g' + prefix + 'limit'] = 15;\n\n\t\t// If PageImages is being used configure further.\n\t\tif ( data.pilimit ) {\n\t\t\tdata.pilimit = 15;\n\t\t\tdata.pithumbsize = mw.config.get( 'wgMFThumbnailSizes' ).tiny;\n\t\t}\n\t\treturn data;\n\t},\n\n\t/**\n\t * Escapes regular expression wildcards (metacharacters) by adding a \\\\ prefix\n\t *\n\t * @memberof SearchGateway\n\t * @instance\n\t * @param {string} str a string\n\t * @return {Object} a regular expression that can be used to search for that str\n\t * @private\n\t */\n\t_createSearchRegEx( str ) {\n\t\t// '\\[' can be unescaped, but leave it balanced with '`]'\n\t\t// eslint-disable-next-line no-useless-escape\n\t\tstr = str.replace( /[-\\[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&' );\n\t\treturn new RegExp( '^(' + str + ')', 'ig' );\n\t},\n\n\t/**\n\t * Takes a label potentially beginning with term\n\t * and highlights term if it is present with strong\n\t *\n\t * @memberof SearchGateway\n\t * @instance\n\t * @param {string} label a piece of text\n\t * @param {string} term a string to search for from the start\n\t * @return {string} safe html string with matched terms encapsulated in strong tags\n\t * @private\n\t */\n\t_highlightSearchTerm( label, term ) {\n\t\tlabel = util.parseHTML( '<span>' ).text( label ).html();\n\t\tterm = term.trim();\n\t\tterm = util.parseHTML( '<span>' ).text( term ).html();\n\n\t\treturn label.replace( this._createSearchRegEx( term ), '<strong>$1</strong>' );\n\t},\n\n\t/**\n\t * Return data used for creating {Page} objects\n\t *\n\t * @memberof SearchGateway\n\t * @instance\n\t * @param {string} query to search for\n\t * @param {Object} pageInfo from the API\n\t * @return {Object} data needed to create a {Page}\n\t * @private\n\t */\n\t_getPage( query, pageInfo ) {\n\t\tconst page = pageJSONParser.parse( pageInfo );\n\n\t\t// If displaytext is set in the generator result (eg. by Wikibase),\n\t\t// use that as display title.\n\t\t// Otherwise default to the page's title.\n\t\t// FIXME: Given that displayTitle could have html in it be safe and just highlight text.\n\t\t// Note that highlightSearchTerm does full HTML escaping before highlighting.\n\t\tpage.displayTitle = this._highlightSearchTerm(\n\t\t\tpageInfo.displaytext ? pageInfo.displaytext : page.title,\n\t\t\tquery\n\t\t);\n\t\tpage.index = pageInfo.index;\n\n\t\treturn page;\n\t},\n\n\t/**\n\t * Process the data returned by the api call.\n\t *\n\t * @memberof SearchGateway\n\t * @instance\n\t * @param {string} query to search for\n\t * @param {Object} data from api\n\t * @return {Array}\n\t * @private\n\t */\n\t_processData( query, data ) {\n\t\tconst self = this;\n\n\t\tlet results = [];\n\n\t\tif ( data.query ) {\n\n\t\t\tresults = data.query.pages || {};\n\t\t\tresults = Object.keys( results ).map( ( id ) => self._getPage( query, results[id] ) );\n\t\t\t// sort in order of index\n\t\t\tresults.sort( ( a, b ) => a.index - b.index );\n\t\t}\n\n\t\treturn results;\n\t},\n\n\t/**\n\t * Perform a search for the given query.\n\t *\n\t * @memberof SearchGateway\n\t * @instance\n\t * @param {string} query to search for\n\t * @return {jQuery.Deferred}\n\t */\n\tsearch( query ) {\n\t\tconst scriptPath = mw.config.get( 'wgMFScriptPath' ),\n\t\t\tself = this;\n\n\t\tif ( !this.isCached( query ) ) {\n\t\t\tconst xhr = this.api.get( this.getApiData( query ), scriptPath ? {\n\t\t\t\turl: scriptPath\n\t\t\t} : undefined );\n\t\t\tconst request = xhr\n\t\t\t\t.then( ( data, jqXHR ) => {\n\t\t\t\t\t// resolve the Deferred object\n\t\t\t\t\treturn {\n\t\t\t\t\t\tquery,\n\t\t\t\t\t\tresults: self._processData( query, data ),\n\t\t\t\t\t\tsearchId: jqXHR && jqXHR.getResponseHeader( 'x-search-id' )\n\t\t\t\t\t};\n\t\t\t\t}, () => {\n\t\t\t\t\t// reset cached result, it maybe contains no value\n\t\t\t\t\tself.searchCache[query] = undefined;\n\t\t\t\t} );\n\n\t\t\t// cache the result to prevent the execution of one search query twice\n\t\t\t// in one session\n\t\t\tthis.searchCache[query] = request.promise( {\n\t\t\t\tabort() {\n\t\t\t\t\txhr.abort();\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\treturn this.searchCache[query];\n\t},\n\n\t/**\n\t * Check if the search has already been performed in given session.\n\t *\n\t * @memberof SearchGateway\n\t * @instance\n\t * @param {string} query\n\t * @return {boolean}\n\t */\n\tisCached( query ) {\n\t\treturn Boolean( this.searchCache[query] );\n\t}\n};\n\nmodule.exports = SearchGateway;\n","const util = require( '../util' ),\n\tView = require( '../View' ),\n\tIconButton = require( '../IconButton' );\n\n/**\n * @extends module:mobile.startup/View\n */\nclass SearchHeaderView extends View {\n\t/**\n\t * constructor\n\t *\n\t * @inheritdoc\n\t * @param {Object} props\n\t * @param {Function} props.onInput executed every time input changes\n\t * @param {string} props.placeholderMsg\n\t * @param {string} props.action\n\t * @parm {string} [props.autocapitalize] none or sentences\n\t * @param {string} [props.searchTerm] default\n\t */\n\tconstructor( props ) {\n\t\tsuper(\n\t\t\tutil.extend( {\n\t\t\t\tautocapitalize: 'sentences'\n\t\t\t}, props, {\n\t\t\t\tevents: {\n\t\t\t\t\t'input input': 'onInput'\n\t\t\t\t}\n\t\t\t} )\n\t\t);\n\t}\n\n\t/** @inheritdoc */\n\tonInput( ev ) {\n\t\tconst query = ev.target.value;\n\t\tthis.options.onInput( query );\n\t\tif ( query ) {\n\t\t\tthis.clearIcon.$el.show();\n\t\t} else {\n\t\t\tthis.clearIcon.$el.hide();\n\t\t}\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( `<div class=\"overlay-title search-header-view\">\n\t\t<form method=\"get\" action=\"{{action}}\" class=\"search-box\">\n\t\t<input class=\"search mf-icon-search\" type=\"search\" name=\"search\"\n\t\t\tautocapitalize=\"{{autocapitalize}}\"\n\t\t\tautocomplete=\"off\" placeholder=\"{{placeholderMsg}}\" aria-label=\"{{placeholderMsg}}\" value=\"{{searchTerm}}\">\n\t\t<input type=\"hidden\" name=\"title\" value=\"{{defaultSearchPage}}\">\n\t\t</form>\n</div>` );\n\t}\n\n\t/** @inheritdoc */\n\tpostRender() {\n\t\tconst clearIcon = new IconButton( {\n\t\t\ttagName: 'button',\n\t\t\ticon: 'clear',\n\t\t\tsize: 'medium',\n\t\t\tisSmall: true,\n\t\t\tlabel: mw.msg( 'mobile-frontend-clear-search' ),\n\t\t\tadditionalClassNames: 'clear',\n\t\t\tevents: {\n\t\t\t\tclick: function () {\n\t\t\t\t\tthis.$el.find( 'input' ).val( '' ).trigger( 'focus' );\n\t\t\t\t\tthis.options.onInput( '' );\n\t\t\t\t\tclearIcon.$el.hide();\n\t\t\t\t\t// In beta the clear button is on top of the search input.\n\t\t\t\t\t// Stop propagation so that the input doesn't receive the click.\n\t\t\t\t\treturn false;\n\t\t\t\t}.bind( this )\n\t\t\t}\n\t\t} );\n\t\tthis.clearIcon = clearIcon;\n\t\tclearIcon.$el.hide();\n\t\tclearIcon.$el.attr( 'aria-hidden', 'true' );\n\t\tthis.$el.find( 'form' ).append( clearIcon.$el );\n\t}\n}\n\nmodule.exports = SearchHeaderView;\n","const\n\tmfExtend = require( '../mfExtend' ),\n\tOverlay = require( '../Overlay' ),\n\tutil = require( '../util' ),\n\tsearchHeader = require( './searchHeader' ),\n\tSearchResultsView = require( './SearchResultsView' ),\n\tWatchstarPageList = require( '../watchstar/WatchstarPageList' ),\n\tSEARCH_DELAY = 300,\n\tSEARCH_SPINNER_DELAY = 2000;\n\n/**\n * Overlay displaying search results\n *\n * @class SearchOverlay\n * @memberof module:mobile.startup/search\n * @extends Overlay\n * @uses SearchGateway\n * @uses IconButton\n *\n * @param {Object} params Configuration options\n * @param {string} params.placeholderMsg Search input placeholder text.\n * @param {string} [params.action] of form defaults to the value of wgScript\n * @param {string} [params.defaultSearchPage] The default search page e.g. Special:Search\n * @param {SearchGateway} [params.gateway]\n */\nfunction SearchOverlay( params ) {\n\tconst header = searchHeader(\n\t\t\tparams.placeholderMsg,\n\t\t\tparams.action || mw.config.get( 'wgScript' ),\n\t\t\t( query ) => this.performSearch( query ),\n\t\t\tparams.defaultSearchPage || '',\n\t\t\tparams.autocapitalize\n\t\t),\n\t\toptions = util.extend( true, {\n\t\t\theaderChrome: true,\n\t\t\tisBorderBox: false,\n\t\t\tclassName: 'overlay search-overlay',\n\t\t\theaders: [ header ],\n\t\t\tevents: {\n\t\t\t\t'click .search-content': 'onClickSearchContent',\n\t\t\t\t'click .overlay-content': 'onClickOverlayContent',\n\t\t\t\t'click .overlay-content > div': function ( ev ) {\n\t\t\t\t\tev.stopPropagation();\n\t\t\t\t},\n\t\t\t\t'touchstart .results': 'hideKeyboardOnScroll',\n\t\t\t\t'mousedown .results': 'hideKeyboardOnScroll',\n\t\t\t\t'click .results a': 'onClickResult'\n\t\t\t}\n\t\t},\n\t\tparams );\n\n\tthis.header = header;\n\tOverlay.call( this, options );\n\n\tthis.api = options.api;\n\t// eslint-disable-next-line new-cap\n\tthis.gateway = options.gateway || new options.gatewayClass( this.api );\n\n\tthis.router = options.router;\n\n\tthis.currentSearchId = null;\n}\n\nmfExtend( SearchOverlay, Overlay, {\n\n\t/**\n\t * Initialize 'search within pages' functionality\n\t *\n\t * @memberof SearchOverlay\n\t * @instance\n\t */\n\tonClickSearchContent() {\n\t\tconst\n\t\t\t$form = this.$el.find( 'form' ),\n\t\t\t$el = $form[0].parentNode;\n\n\t\t// Add fulltext input to force fulltext search\n\t\tthis.parseHTML( '<input>' )\n\t\t\t.attr( {\n\t\t\t\ttype: 'hidden',\n\t\t\t\tname: 'fulltext',\n\t\t\t\tvalue: 'search'\n\t\t\t} )\n\t\t\t.appendTo( $form );\n\t\t// history.back queues a task so might run after this call. Thus we use setTimeout\n\t\t// http://www.w3.org/TR/2011/WD-html5-20110113/webappapis.html#queue-a-task\n\t\tsetTimeout( () => {\n\t\t\t// Firefox doesn't allow submission of a form not in the DOM\n\t\t\t// so temporarily re-add it if it's gone.\n\t\t\tif ( !$form[0].parentNode ) {\n\t\t\t\t$form.appendTo( $el );\n\t\t\t}\n\t\t\t$form.trigger( 'submit' );\n\t\t}, 0 );\n\t},\n\n\t/**\n\t * Tapping on background only should hide the overlay\n\t *\n\t * @memberof SearchOverlay\n\t * @instance\n\t */\n\tonClickOverlayContent() {\n\t\tthis.$el.find( '.cancel' ).trigger( 'click' );\n\t},\n\n\t/**\n\t * Hide the keyboard when scrolling starts (avoid weird situation when\n\t * user taps on an item, the keyboard hides and wrong item is clicked).\n\t *\n\t * @memberof SearchOverlay\n\t * @instance\n\t */\n\thideKeyboardOnScroll() {\n\t\tthis.$input.trigger( 'blur' );\n\t},\n\n\t/**\n\t * Handle the user clicking a result.\n\t *\n\t * @memberof SearchOverlay\n\t * @instance\n\t * @param {jQuery.Event} ev\n\t */\n\tonClickResult( ev ) {\n\t\tconst\n\t\t\tself = this,\n\t\t\t$link = this.$el.find( ev.currentTarget );\n\t\t/**\n\t\t * Fired when the user clicks a search result\n\t\t *\n\t\t * @type {Object}\n\t\t * @property {jQuery.Object} result The jQuery-wrapped DOM element that\n\t\t *  the user clicked\n\t\t * @property {number} resultIndex The zero-based index of the\n\t\t *  result in the set of results\n\t\t * @property {jQuery.Event} originalEvent The original event\n\t\t */\n\t\t// FIXME: ugly hack that removes search from browser history\n\t\t// when navigating to search results\n\t\tev.preventDefault();\n\t\tthis.router.back().then( function () {\n\t\t\t// T308288: Appends the current search id as a url param on clickthroughs\n\t\t\tif ( this.currentSearchId ) {\n\t\t\t\tconst clickUrl = new URL( location.href );\n\t\t\t\tclickUrl.searchParams.set( 'searchToken', this.currentSearchId );\n\t\t\t\tself.router.navigateTo( document.title, {\n\t\t\t\t\tpath: clickUrl.toString(),\n\t\t\t\t\tuseReplaceState: true\n\t\t\t\t} );\n\t\t\t\tthis.currentSearchId = null;\n\t\t\t}\n\t\t\t// Router.navigate does not support changing href.\n\t\t\t// FIXME: Needs upstream change T189173\n\t\t\t// eslint-disable-next-line no-restricted-properties\n\t\t\twindow.location.href = $link.attr( 'href' );\n\t\t} );\n\t},\n\n\t/**\n\t * @inheritdoc\n\t * @memberof SearchOverlay\n\t * @instance\n\t */\n\tpostRender() {\n\t\tconst self = this,\n\t\t\tsearchResults = new SearchResultsView( {\n\t\t\t\tsearchContentLabel: mw.msg( 'mobile-frontend-search-content' ),\n\t\t\t\tnoResultsMsg: mw.msg( 'mobile-frontend-search-no-results' ),\n\t\t\t\tsearchContentNoResultsMsg: mw.message( 'mobile-frontend-search-content-no-results' ).parse()\n\t\t\t} );\n\t\tlet timer;\n\n\t\tthis.$el.find( '.overlay-content' ).append( searchResults.$el );\n\t\tOverlay.prototype.postRender.call( this );\n\n\t\t// FIXME: `this.$input` should not be set. Isolate to searchHeader function\n\t\tthis.$input = this.$el.find( this.header ).find( 'input' );\n\t\t// FIXME: `this.$searchContent` should not be set. Isolate to SearchResultsView class.\n\t\tthis.$searchContent = searchResults.$el.hide();\n\t\t// FIXME: `this.$resultContainer` should not be set. Isolate to SearchResultsView class.\n\t\tthis.$resultContainer = searchResults.$el.find( '.results-list-container' );\n\n\t\t// On iOS a touchstart event while the keyboard is open will result in a scroll\n\t\t// leading to an accidental click (T299846)\n\t\t// Stopping propagation when the input is focused will prevent scrolling while\n\t\t// the keyboard is collapsed.\n\t\tthis.$resultContainer[0].addEventListener( 'touchstart', ( ev ) => {\n\t\t\tif ( document.activeElement === this.$input[0] ) {\n\t\t\t\tev.stopPropagation();\n\t\t\t}\n\t\t} );\n\n\t\t/**\n\t\t * Hide the spinner and abort timed spinner shows.\n\t\t * FIXME: Given this manipulates SearchResultsView this should be moved into that class\n\t\t */\n\t\tfunction clearSearch() {\n\t\t\tself.$spinner.hide();\n\t\t\tclearTimeout( timer );\n\t\t}\n\n\t\t// Show a spinner on top of search results\n\t\t// FIXME: Given this manipulates SearchResultsView this should be moved into that class\n\t\tthis.$spinner = searchResults.$el.find( '.spinner-container' );\n\t\tthis.on( 'search-start', ( searchData ) => {\n\t\t\tif ( timer ) {\n\t\t\t\tclearSearch();\n\t\t\t}\n\t\t\ttimer = setTimeout( () => self.$spinner.show(),\n\t\t\t\tSEARCH_SPINNER_DELAY - searchData.delay );\n\t\t} );\n\t\tthis.on( 'search-results', clearSearch );\n\t},\n\n\t/**\n\t * Trigger a focus() event on search input in order to\n\t * bring up the virtual keyboard.\n\t *\n\t * @memberof SearchOverlay\n\t * @instance\n\t */\n\tshowKeyboard() {\n\t\tconst len = this.$input.val().length;\n\t\tthis.$input.trigger( 'focus' );\n\t\t// Cursor to the end of the input\n\t\tif ( this.$input[0].setSelectionRange ) {\n\t\t\tthis.$input[0].setSelectionRange( len, len );\n\t\t}\n\t},\n\n\t/**\n\t * @inheritdoc\n\t * @memberof SearchOverlay\n\t * @instance\n\t */\n\tshow() {\n\t\t// Overlay#show defines the actual overlay visibility.\n\t\tOverlay.prototype.show.apply( this, arguments );\n\n\t\tthis.showKeyboard();\n\t},\n\n\t/**\n\t * Perform search and render results inside current view.\n\t * FIXME: Much of the logic for caching and pending queries inside this function should\n\t * actually live in SearchGateway, please move out.\n\t *\n\t * @memberof SearchOverlay\n\t * @instance\n\t * @param {string} query\n\t */\n\tperformSearch( query ) {\n\t\tconst\n\t\t\tself = this,\n\t\t\tapi = this.api,\n\t\t\tdelay = this.gateway.isCached( query ) ? 0 : SEARCH_DELAY;\n\n\t\t// it seems the input event can be fired when virtual keyboard is closed\n\t\t// (Chrome for Android)\n\t\tif ( query !== this.lastQuery ) {\n\t\t\tif ( self._pendingQuery ) {\n\t\t\t\tself._pendingQuery.abort();\n\t\t\t}\n\t\t\tclearTimeout( this.timer );\n\n\t\t\tif ( query.length ) {\n\t\t\t\tthis.timer = setTimeout( () => {\n\t\t\t\t\tconst xhr = self.gateway.search( query );\n\t\t\t\t\tself._pendingQuery = xhr.then( function ( data ) {\n\t\t\t\t\t\tthis.currentSearchId = data.searchId;\n\t\t\t\t\t\t// FIXME: Given this manipulates SearchResultsView\n\t\t\t\t\t\t// this should be moved into that class\n\t\t\t\t\t\t// check if we're getting the rights response in case of out of\n\t\t\t\t\t\t// order responses (need to get the current value of the input)\n\t\t\t\t\t\tif ( data && data.query === self.$input.val() ) {\n\t\t\t\t\t\t\tself.$el.toggleClass( 'no-results', data.results.length === 0 );\n\t\t\t\t\t\t\tself.$searchContent\n\t\t\t\t\t\t\t\t.show()\n\t\t\t\t\t\t\t\t.find( 'p' )\n\t\t\t\t\t\t\t\t.hide()\n\t\t\t\t\t\t\t\t.filter( data.results.length ? '.with-results' : '.without-results' )\n\t\t\t\t\t\t\t\t.show();\n\n\t\t\t\t\t\t\t// eslint-disable-next-line no-new\n\t\t\t\t\t\t\tnew WatchstarPageList( {\n\t\t\t\t\t\t\t\tapi,\n\t\t\t\t\t\t\t\tfunnel: 'search',\n\t\t\t\t\t\t\t\tpages: data.results,\n\t\t\t\t\t\t\t\tel: self.$resultContainer\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\tself.$results = self.$resultContainer.find( 'li' );\n\t\t\t\t\t\t}\n\t\t\t\t\t} ).promise( {\n\t\t\t\t\t\tabort() {\n\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t}, delay );\n\t\t\t} else {\n\t\t\t\tself.resetSearch();\n\t\t\t}\n\n\t\t\tthis.lastQuery = query;\n\t\t}\n\t},\n\t/**\n\t * Clear results\n\t *\n\t * @private\n\t */\n\tresetSearch() {\n\t\tthis.$el.find( '.overlay-content' ).children().hide();\n\t}\n} );\n\nmodule.exports = SearchOverlay;\n","const View = require( '../View' ),\n\tIcon = require( '../Icon' ),\n\tAnchor = require( '../Anchor' ),\n\ticons = require( '../icons' ),\n\t$spinner = icons.spinner().$el,\n\tutil = require( '../util' );\n\n/**\n * Render search results.\n *\n * @extends module:mobile.startup/View\n * @param {Object} options\n * @param {string} options.searchContentLabel actionable label to tell the user they can \"search\n *  within pages rather than doing a full text search\n * @param {string} options.noResultsMsg shows when no results displayed\n * @param {string} options.searchContentNoResultsMsg alternative to options.searchContentLabel that\n * shows when no search results have been displayed.\n */\nclass SearchResultsView extends View {\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<div class=\"search-results-view\">\n\t<div class=\"search-content\">\n\t\t<div class=\"caption\">\n\t\t\t<p class=\"with-results\">{{searchContentLabel}}</p>\n\t\t\t<p class=\"without-results\">{{noResultsMsg}}</p>\n\t\t\t<p class=\"without-results\">{{{searchContentNoResultsMsg}}}</p>\n\t\t</div>\n\t</div>\n\t<div class=\"spinner-container position-fixed\"></div>\n\t<div class=\"results\">\n\t\t<div class=\"results-list-container\"></div>\n\t\t{{#feedback}}\n\t\t\t<div class=\"search-feedback\">\n\t\t\t\t{{prompt}}\n\t\t\t</div>\n\t\t{{/feedback}}\n\t</div>\n</div>`\n\t\t);\n\t}\n\n\t/** @inheritdoc */\n\tpreRender() {\n\t\tconst feedbackLink = mw.config.get( 'wgCirrusSearchFeedbackLink' );\n\t\tif ( feedbackLink ) {\n\t\t\tthis.options.feedback = {\n\t\t\t\tprompt: mw.msg( 'mobile-frontend-search-feedback-prompt' ) };\n\t\t}\n\t}\n\n\t/** @inheritdoc */\n\tpostRender( options ) {\n\t\tconst feedbackLink = mw.config.get( 'wgCirrusSearchFeedbackLink' );\n\t\tsuper.postRender( options );\n\t\tthis.$el.find( '.search-content' ).prepend(\n\t\t\tnew Icon( { icon: 'articlesSearch' } ).$el\n\t\t);\n\t\tthis.$el.find( '.spinner-container' ).append( $spinner );\n\t\tif ( feedbackLink ) {\n\t\t\tthis.$el.find( '.search-feedback' ).append(\n\t\t\t\tnew Anchor( {\n\t\t\t\t\tlabel: mw.msg( 'mobile-frontend-search-feedback-link-text' ),\n\t\t\t\t\thref: feedbackLink\n\t\t\t\t} ).$el\n\t\t\t);\n\t\t}\n\t}\n}\n\nmodule.exports = SearchResultsView;\n","const formHeader = require( '../headers' ).formHeader,\n\tSearchHeaderView = require( './SearchHeaderView' ),\n\ticons = require( '../icons' );\n\n/**\n * Generate a search header\n *\n * @param {string} placeholderMsg\n * @param {string} action\n * @param {Function} onInput\n * @param {string} defaultSearchPage\n * @param {string} autocapitalize\n * @return {jQuery.Element}\n */\nmodule.exports = function searchHeader( placeholderMsg, action, onInput, defaultSearchPage, autocapitalize ) {\n\treturn formHeader(\n\t\tnew SearchHeaderView( {\n\t\t\tplaceholderMsg,\n\t\t\tautocapitalize,\n\t\t\taction,\n\t\t\tonInput,\n\t\t\tdefaultSearchPage\n\t\t} ),\n\t\t[\n\t\t\ticons.cancel()\n\t\t],\n\t\tfalse\n\t);\n};\n","const units = [ 'seconds', 'minutes', 'hours', 'days', 'months', 'years' ],\n\tutil = require( './util' ),\n\tlimits = [ 1, 60, 3600, 86400, 2592000, 31536000 ];\n\n/**\n * Calculate the correct unit of timestamp\n *\n * @memberof module:mobile.startup/time\n * @instance\n * @param {number} timestampDelta\n * @return {{value: number, unit: string}}\n */\nfunction timeAgo( timestampDelta ) {\n\tlet i = 0;\n\twhile ( i < limits.length && timestampDelta > limits[i + 1] ) {\n\t\t++i;\n\t}\n\treturn {\n\t\tvalue: Math.round( timestampDelta / limits[i] ),\n\t\tunit: units[i]\n\t};\n}\n\n/**\n * Calculate the correct unit of timestamp delta\n *\n * @memberof module:mobile.startup/time\n * @param {number} timestamp\n * @return {{value: number, unit: string}}\n */\nfunction getTimeAgoDelta( timestamp ) {\n\tconst currentTimestamp = Math.round( Date.now() / 1000 );\n\n\treturn timeAgo( currentTimestamp - timestamp );\n}\n\n/**\n * Whether timestamp delta is less than a day old\n *\n * @instance\n * @memberof module:mobile.startup/time\n * @param {{value: number, unit: string}} delta Object of timestamp and its label\n * @return {boolean}\n */\nfunction isRecent( delta ) {\n\treturn [ 'seconds', 'minutes', 'hours' ].indexOf( delta.unit ) > -1;\n}\n\n/**\n * Is delta less than 10 seconds?\n *\n * @instance\n * @memberof module:mobile.startup/time\n * @param {{value: number, unit: string}} delta Object of timestamp and its label\n * @return {boolean}\n */\nfunction isNow( delta ) {\n\treturn delta.unit === 'seconds' && delta.value < 10;\n}\n\n/**\n * Return a message relating to the last modified relative time.\n *\n * @instance\n * @memberof module:mobile.startup/time\n * @param {number} ts timestamp\n * @param {string} username of the last user to modify the page\n * @param {string} gender of the last user to modify the page\n * @param {string} historyUrl url to the history page for the message (deprecated)\n * @return {string}\n */\nfunction getLastModifiedMessage( ts, username, gender, historyUrl ) {\n\tconst linkAll = typeof historyUrl === 'undefined',\n\t\tkeys = {\n\t\t\tseconds: 'mobile-frontend-last-modified-with-user-seconds',\n\t\t\tminutes: 'mobile-frontend-last-modified-with-user-minutes',\n\t\t\thours: 'mobile-frontend-last-modified-with-user-hours',\n\t\t\tdays: 'mobile-frontend-last-modified-with-user-days',\n\t\t\tmonths: 'mobile-frontend-last-modified-with-user-months',\n\t\t\tyears: 'mobile-frontend-last-modified-with-user-years'\n\t\t},\n\t\targs = [];\n\n\tgender = gender || 'unknown';\n\n\tconst delta = getTimeAgoDelta( ts );\n\tif ( isNow( delta ) ) {\n\t\targs.push( 'mobile-frontend-last-modified-with-user-just-now', gender, username );\n\t} else {\n\t\targs.push( keys[ delta.unit ], gender, username,\n\t\t\tmw.language.convertNumber( delta.value )\n\t\t);\n\t}\n\n\tconst lastEditedElement = linkAll ?\n\t\tutil.parseHTML( '<strong>' ).attr( 'class', 'last-modified-text-accent' ) :\n\t\tutil.parseHTML( '<a>' ).attr( 'href', historyUrl || '#' );\n\tconst usernameElement = linkAll ?\n\t\tutil.parseHTML( '<span>' ).attr( 'class', 'last-modified-text-accent' ) :\n\t\tutil.parseHTML( '<a>' ).attr( 'href', mw.util.getUrl( 'User:' + username ) );\n\n\targs.push(\n\t\tlastEditedElement,\n\t\t// Abuse PLURAL support to determine if the user is anonymous or not\n\t\tmw.language.convertNumber( username ? 1 : 0 ),\n\t\t// Our abuse of PLURAL support means we have to pass the relative URL\n\t\t// rather than construct it from a wikilink\n\t\tusername ? usernameElement : ''\n\t);\n\n\treturn mw.message.apply( this, args ).parse();\n}\n\n/**\n * Return a message relating to the registration date of the user\n *\n * @instance\n * @memberof module:mobile.startup/time\n * @param {string} ts timestamp\n * @param {string} [gender] of the last user editing this page\n * @return {string}\n */\nfunction getRegistrationMessage( ts, gender ) {\n\tconst keys = {\n\t\tseconds: 'mobile-frontend-joined-seconds',\n\t\tminutes: 'mobile-frontend-joined-minutes',\n\t\thours: 'mobile-frontend-joined-hours',\n\t\tdays: 'mobile-frontend-joined-days',\n\t\tmonths: 'mobile-frontend-joined-months',\n\t\tyears: 'mobile-frontend-joined-years'\n\t};\n\n\tconst args = [];\n\n\tgender = gender || 'unknown';\n\n\tconst delta = getTimeAgoDelta( parseInt( ts, 10 ) );\n\tif ( isNow( delta ) ) {\n\t\targs.push( 'mobile-frontend-joined-just-now', gender );\n\t} else {\n\t\targs.push( keys[ delta.unit ], gender, mw.language.convertNumber( delta.value ) );\n\t}\n\tconst html = mw.message.apply( this, args ).parse();\n\treturn html;\n}\n\n/**\n * Utility library for relative time.\n *\n * @exports module:mobile.startup/time\n */\nmodule.exports = {\n\tgetLastModifiedMessage,\n\tgetRegistrationMessage,\n\ttimeAgo,\n\tgetTimeAgoDelta,\n\tisNow,\n\tisRecent\n};\n"],"names":["util","require","actionParams","LanguageInfo","api","this","prototype","getLanguages","get","meta","liprop","then","resp","filteredLanguages","Object","keys","query","languageinfo","forEach","key","language","code","toLowerCase","bcp47","autonym","push","Deferred","reject","languages","map","data","url","lang","langname","name","title","module","exports","navigator","userLanguage","browserLanguage","systemLanguage","undefined","m","getDeviceLanguage","Overlay","promisedView","loadLanguageInfoSearcher","languageInfo","showSuggestedLanguages","mw","loader","using","variants","deviceLanguage","languageInfoOverlay","make","heading","msg","className","test","MessageBox","currentPageHTMLParser","loadLanguageSearcher","config","onOpen","searcher","hook","fire","type","languageOverlay","header","icons","options","headers","cancel","Promise","all","ImageCarousel","time","currentPage","Drawer","CtaDrawer","lazyImageLoader","PageHTMLParser","showOnPageReload","OverlayManager","View","references","search","SearchOverlay","SearchGateway","Skin","mediaViewer","overlay","amcOutreach","_mobileFrontend","overlayHeader","getOverlayManager","getSingleton","spinner","loadAllImagesInPage","loadImages","queryPlaceholders","document","getElementById","notifyOnPageReload","license","getLicenseMsg","showSuggestedLanguage","promise","view","$el","append","newView","replaceWith","errorView","ReferencesGateway","getReference","ERROR_NOT_EXIST","ERROR_OTHER","mfExtend","ReferencesHtmlScraperGateway","apply","arguments","EXTERNAL_LINK_CLASS","getReferenceFromContainer","id","$container","result","find","escapeSelector","length","$parent","$ol","closest","isSubref","hasClass","parent","addClass","resolve","text","getReferenceHtml","parentText","$reference","children","first","html","hash","page","pageHTMLParser","percentDecodeFragment","slice","Icon","IconButton","makeOnNestedReferenceClickHandler","onNestedReferenceClick","ev","target","currentTarget","querySelector","getAttribute","textContent","referenceDrawer","props","errorIcon","error","isSmall","mainRef","mainRefHtml","parseHTML","subRefHtml","extend","showCollapseIcon","events","preventDefault","icon","additionalClassNames","showReference","refNumber","gateway","onShowNestedReference","reference","drawer","href","nestedDrawer","log","warn","body","appendChild","hide","show","err","pageJSONParser","extendSearchParams","searchCache","generator","searchNamespace","getApiData","prefix","redirects","pilimit","pithumbsize","tiny","_createSearchRegEx","str","replace","RegExp","_highlightSearchTerm","label","term","trim","_getPage","pageInfo","parse","displayTitle","displaytext","index","_processData","self","results","pages","sort","a","b","scriptPath","isCached","xhr","request","jqXHR","searchId","getResponseHeader","abort","Boolean","SearchHeaderView","_View","_classCallCheck","_callSuper","autocapitalize","_inherits","value","onInput","clearIcon","template","tagName","size","click","val","trigger","bind","attr","searchHeader","SearchResultsView","WatchstarPageList","params","_this","placeholderMsg","action","performSearch","defaultSearchPage","headerChrome","isBorderBox","stopPropagation","call","gatewayClass","router","currentSearchId","onClickSearchContent","$form","parentNode","appendTo","setTimeout","onClickOverlayContent","hideKeyboardOnScroll","$input","onClickResult","$link","back","clickUrl","URL","location","searchParams","set","navigateTo","path","toString","useReplaceState","window","postRender","timer","_this2","searchResults","searchContentLabel","noResultsMsg","searchContentNoResultsMsg","message","clearSearch","$spinner","clearTimeout","$searchContent","$resultContainer","addEventListener","activeElement","on","searchData","delay","showKeyboard","len","setSelectionRange","lastQuery","_pendingQuery","toggleClass","filter","funnel","el","$results","resetSearch","Anchor","feedback","prompt","feedbackLink","prepend","formHeader","units","limits","timeAgo","timestampDelta","i","Math","round","unit","getTimeAgoDelta","timestamp","Date","now","isNow","delta","getLastModifiedMessage","ts","username","gender","historyUrl","linkAll","args","seconds","minutes","hours","days","months","years","convertNumber","lastEditedElement","usernameElement","getUrl","getRegistrationMessage","parseInt","isRecent","indexOf"],"sourceRoot":""}