{"version":3,"sources":["webpack://mfModules.[name]/./src/mobile.startup/LanguageInfo.js","webpack://mfModules.[name]/./src/mobile.startup/languageOverlay/getDeviceLanguage.js","webpack://mfModules.[name]/./src/mobile.startup/languageOverlay/languageInfoOverlay.js","webpack://mfModules.[name]/./src/mobile.startup/languageOverlay/languageOverlay.js","webpack://mfModules.[name]/./src/mobile.startup/loadingOverlay.js","webpack://mfModules.[name]/./src/mobile.startup/mediaViewer/overlay.js","webpack://mfModules.[name]/./src/mobile.startup/mobile.startup.js","webpack://mfModules.[name]/./src/mobile.startup/references/ReferencesGateway.js","webpack://mfModules.[name]/./src/mobile.startup/references/ReferencesHtmlScraperGateway.js","webpack://mfModules.[name]/./src/mobile.startup/references/references.js","webpack://mfModules.[name]/./src/mobile.startup/search/SearchGateway.js","webpack://mfModules.[name]/./src/mobile.startup/search/SearchHeaderView.js","webpack://mfModules.[name]/./src/mobile.startup/search/SearchOverlay.js","webpack://mfModules.[name]/./src/mobile.startup/search/SearchResultsView.js","webpack://mfModules.[name]/./src/mobile.startup/search/searchHeader.js","webpack://mfModules.[name]/./src/mobile.startup/time.js"],"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","loadLanguageSearcher","pageGateway","getPageLanguages","config","onOpen","searcher","hook","fire","onBannerClick","languageOverlay","icons","overlay","noHeader","spinner","$el","appendTo","find","header","options","headers","cancel","Promise","all","ImageCarousel","moduleLoader","mfExtend","time","View","PageGateway","Browser","Button","Icon","ReferencesGateway","ReferencesHtmlScraperGateway","Page","currentPage","PageHTMLParser","currentPageHTMLParser","Anchor","Skin","OverlayManager","loadingOverlay","Drawer","CtaDrawer","showOnPageReload","toast","Watchstar","eventBusSingleton","Toggler","toc","TableOfContents","parseHTML","references","search","SearchOverlay","SearchGateway","lazyImages","lazyImageLoader","mediaViewer","amcOutreach","Section","mobileFrontend","define","getReference","ERROR_NOT_EXIST","ERROR_OTHER","apply","arguments","EXTERNAL_LINK_CLASS","getReferenceFromContainer","id","$container","$ol","$parent","result","escapeSelector","length","closest","hasClass","parent","addClass","resolve","text","getReferenceHtml","parentText","promise","$reference","first","html","hash","page","pageHTMLParser","percentDecodeFragment","slice","makeOnNestedReferenceClickHandler","onNestedReferenceClick","ev","target","currentTarget","querySelector","getAttribute","textContent","referenceDrawer","props","errorIcon","error","isSmall","extend","showCollapseIcon","events","preventDefault","children","append","type","additionalClassNames","showReference","refNumber","gateway","onShowNestedReference","reference","drawer","href","nestedDrawer","log","warn","document","body","appendChild","hide","show","err","pageJSONParser","extendSearchParams","searchCache","generator","searchNamespace","getApiData","prefix","redirects","pilimit","pithumbsize","tiny","_createSearchRegEx","str","replace","RegExp","_highlightSearchTerm","label","term","_getPage","pageInfo","parse","displayTitle","displaytext","index","_processData","self","results","pages","sort","a","b","xhr","request","isCached","jqXHR","searchId","getResponseHeader","abort","Boolean","SearchHeaderView","value","onInput","clearIcon","template","tagName","click","val","trigger","bind","attr","searchHeader","SearchResultsView","WatchstarPageList","params","placeholderMsg","action","performSearch","defaultSearchPage","headerChrome","isBorderBox","stopPropagation","call","gatewayClass","router","currentSearchId","onClickSearchContent","$form","parentNode","setTimeout","onClickOverlayContent","hideKeyboardOnScroll","$input","onClickResult","$link","back","clickUri","Uri","location","searchToken","navigateTo","path","toString","useReplaceState","window","postRender","timer","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","feedback","prompt","feedbackLink","prepend","formHeader","units","limits","timeAgo","timestampDelta","i","Math","round","unit","getTimeAgoDelta","timestamp","Date","now","isNow","delta","getLastModifiedMessage","ts","username","gender","historyUrl","lastEditedElement","usernameElement","linkAll","args","seconds","minutes","hours","days","months","years","convertNumber","getUrl","getRegistrationMessage","parseInt","isRecent","indexOf"],"mappings":"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","file":"mobile.startup.js","sourcesContent":["var util = require( './util.js' ),\n\tactionParams = require( './actionParams' );\n\n/**\n * API for providing language data.\n *\n * @class 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 LanguageInfo\n\t * @instance\n\t * @returns {jQuery.Deferred}\n\t */\n\tgetLanguages: function () {\n\t\treturn this.api.get( actionParams( {\n\t\t\tmeta: 'languageinfo',\n\t\t\tliprop: 'code|autonym|name|bcp47'\n\t\t} ) ).then( function ( 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( function ( 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}, function () {\n\t\t\treturn util.Deferred().reject();\n\t\t} ).then( function ( filteredLanguages ) {\n\t\t\treturn {\n\t\t\t\tlanguages: filteredLanguages.map( function ( data ) {\n\t\t\t\t\tdata.url = '#';\n\t\t\t\t\tdata.lang = data.code;\n\t\t\t\t\tdata.langname = data.name;\n\t\t\t\t\t// FIXME: This isn't a \"title\" in the sense of a MediaWiki\n\t\t\t\t\t// Title, and it is rendered as a subheader in the list\n\t\t\t\t\t// item, so a different name would be wiser, both here and\n\t\t\t\t\t// in LanguageSearcher's template. Also it would arguably\n\t\t\t\t\t// be more intuitive for the language name (localized) to\n\t\t\t\t\t// appear as the main emphasized element of each language\n\t\t\t\t\t// list element; but instead the autonym has that role.\n\t\t\t\t\t// A more thorough refactoring of LanguageSearcher to allow\n\t\t\t\t\t// for generic header/subheader elements is left for a\n\t\t\t\t\t// follow-up.\n\t\t\t\t\tdata.title = data.name;\n\t\t\t\t\treturn data;\n\t\t\t\t} )\n\t\t\t};\n\t\t}, function () {\n\t\t\treturn util.Deferred().reject();\n\t\t} );\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( function () {\n\t\treturn languageInfo.getLanguages();\n\t} ).then( function ( 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: showSuggestedLanguages,\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 * @param {LanguageInfo} languageInfo\n * @param {boolean} showSuggestedLanguages If the suggested languages section\n * should be rendered.\n * @return {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: loadLanguageInfoSearcher\n};\n\nmodule.exports = languageInfoOverlay;\n","const\n\tm = require( '../moduleLoaderSingleton' ),\n\tgetDeviceLanguage = require( './getDeviceLanguage' ),\n\tOverlay = require( '../Overlay' ),\n\tpromisedView = require( '../promisedView' );\n\n/**\n * @ignore\n * @param {PageGateway} pageGateway\n * getPageLanguages API call.\n * @return {jQuery.Promise} Resolves to LanguageSearcher\n */\nfunction loadLanguageSearcher( pageGateway ) {\n\treturn mw.loader.using( 'mobile.languages.structured' ).then( function () {\n\t\treturn pageGateway.getPageLanguages( mw.config.get( 'wgPageName' ), mw.config.get( 'wgUserLanguage' ) );\n\t} ).then( function ( 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\tonOpen: ( searcher ) => {\n\t\t\t\tmw.hook( 'mobileFrontend.languageSearcher.onOpen' ).fire( searcher );\n\t\t\t},\n\t\t\tonBannerClick: () => {\n\t\t\t\tmw.hook( 'mobileFrontend.languageSearcher.onBannerClick' ).fire();\n\t\t\t}\n\t\t} );\n\t} );\n}\n\n/**\n * Factory function that returns a language featured instance of an Overlay\n *\n * @param {PageGateway} pageGateway\n * @return {Overlay}\n */\nfunction languageOverlay( pageGateway ) {\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( pageGateway ) )\n\t);\n}\n\n// To make knowing when async logic has resolved easier in tests\nlanguageOverlay.test = {\n\tloadLanguageSearcher: loadLanguageSearcher\n};\n\nmodule.exports = languageOverlay;\n","var\n\ticons = require( './icons' ),\n\tOverlay = require( './Overlay' );\n\n/**\n * Overlay that initially shows loading animation until\n * caller hides it with .hide()\n *\n * @return {Overlay}\n */\nfunction loadingOverlay() {\n\tvar overlay = new Overlay( {\n\t\tclassName: 'overlay overlay-loading',\n\t\tnoHeader: true\n\t} );\n\ticons.spinner().$el.appendTo( overlay.$el.find( '.overlay-content' ) );\n\treturn overlay;\n}\n\nmodule.exports = loadingOverlay;\n","var 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 * @param {Object} options\n * @return {Overlay}\n */\nfunction mediaViewerOverlay( options ) {\n\tvar 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( function () {\n\t\t\t\tvar 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","var\n\tmoduleLoader = require( './moduleLoaderSingleton' ),\n\tutil = require( './util' );\n\n// Expose the entry chunk through libraryTarget and library. This allows\n// arbitrary file access via ResourceLoader like\n// `mfModules['mobile.startup'].moduleLoader.require('mobile.startup/LoadingOverlay')`.\nmodule.exports = {\n\tmoduleLoader: moduleLoader,\n\tmfExtend: require( './mfExtend' ),\n\ttime: require( './time' ),\n\tutil,\n\theaders: require( './headers' ),\n\tView: require( './View' ),\n\tPageGateway: require( './PageGateway' ),\n\tLanguageInfo: require( './LanguageInfo' ),\n\tBrowser: require( './Browser' ),\n\tButton: require( './Button' ),\n\tIcon: require( './Icon' ),\n\tReferencesGateway: require( './references/ReferencesGateway' ),\n\tReferencesHtmlScraperGateway: require( './references/ReferencesHtmlScraperGateway' ),\n\ticons: require( './icons' ),\n\tPage: require( './Page' ),\n\tcurrentPage: require( './currentPage' ),\n\tPageHTMLParser: require( './PageHTMLParser' ),\n\tcurrentPageHTMLParser: require( './currentPageHTMLParser' ),\n\tAnchor: require( './Anchor' ),\n\tSkin: require( './Skin' ),\n\tOverlayManager: require( './OverlayManager' ),\n\tOverlay: require( './Overlay' ),\n\tloadingOverlay: require( './loadingOverlay' ),\n\tDrawer: require( './Drawer' ),\n\tCtaDrawer: require( './CtaDrawer' ),\n\tshowOnPageReload: require( './showOnPageReload' ),\n\t// For Minerva compatibility (access deprecated)\n\ttoast: require( './showOnPageReload' ),\n\tWatchstar: require( './watchstar/watchstar' ),\n\teventBusSingleton: require( './eventBusSingleton' ),\n\tpromisedView: require( './promisedView' ),\n\tToggler: require( './Toggler' ),\n\ttoc: {\n\t\t// In case any old version of Minerva is cached.\n\t\tTableOfContents: () => {\n\t\t\treturn {\n\t\t\t\t// in the unlikely event old Minerva code got loaded with new MF.\n\t\t\t\t$el: util.parseHTML( '<div>' )\n\t\t\t};\n\t\t}\n\t},\n\treferences: require( './references/references' ),\n\tsearch: {\n\t\tSearchOverlay: require( './search/SearchOverlay' ),\n\t\tSearchGateway: require( './search/SearchGateway' )\n\t},\n\tlazyImages: {\n\t\tlazyImageLoader: require( './lazyImages/lazyImageLoader' )\n\t},\n\tlanguageOverlay: require( './languageOverlay/languageOverlay' ),\n\tlanguageInfoOverlay: require( './languageOverlay/languageInfoOverlay' ),\n\tmediaViewer: {\n\t\toverlay: require( './mediaViewer/overlay' )\n\t},\n\tamcOutreach: require( './amcOutreach/amcOutreach' ),\n\tSection: require( './Section' )\n};\n\nmw.mobileFrontend = moduleLoader;\n\n// Setup a single export for new modules to fold all of the above lines into.\n// One export to rule them all!\nmoduleLoader.define( 'mobile.startup', module.exports );\n","/**\n * Abstract base class\n * Gateway for retrieving references\n *\n * @class ReferencesGateway\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 ReferencesGateway\n * @instance\n * @param {string} id CSS selector\n * @param {Page} page to find reference for\n * @param {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 * @memberof ReferencesGateway\n * @property ERROR_NOT_EXIST error code to be returned by getReference\n *  when a reference does not exist.\n */\nReferencesGateway.ERROR_NOT_EXIST = 'NOT_EXIST_ERROR';\n/**\n * @memberof ReferencesGateway\n * @property 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 */\nReferencesGateway.ERROR_OTHER = 'OTHER_ERROR';\n\nmodule.exports = ReferencesGateway;\n","var 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 * @extends ReferencesGateway\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: function ( id, $container ) {\n\t\tvar $el, $ol, $parent,\n\t\t\tresult = util.Deferred();\n\n\t\t$el = $container.find( '#' + util.escapeSelector( id ) );\n\t\tif ( $el.length ) {\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\t$ol = $el.closest( 'ol' );\n\t\t\tif ( $ol.hasClass( 'mw-extended-references' ) ) {\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} );\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 * @param {jQuery.Object|undefined} $reference\n\t * @returns {string}\n\t */\n\tgetReferenceHtml: function ( $reference ) {\n\t\treturn $reference ?\n\t\t\t$reference.find( '.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 {PageHTMLParser} pageHTMLParser\n\t */\n\tgetReference: function ( hash, page, pageHTMLParser ) {\n\t\tvar 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","var references,\n\tDrawer = require( '../Drawer' ),\n\tutil = require( '../util' ),\n\ticons = require( '../icons' ),\n\tReferencesGateway = require( './ReferencesGateway' ),\n\tIcon = require( '../Icon' );\n\n/**\n * Create a callback for clicking references\n *\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 * @uses Icon\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 {Function} [props.onNestedReferenceClick] callback for when a reference\n *  inside the reference is clicked.\n * @return {Drawer}\n */\nfunction referenceDrawer( props ) {\n\tconst errorIcon = props.error ? new Icon( {\n\t\tname: 'error',\n\t\tisSmall: true\n\t} ).$el : null;\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\tisSmall: true,\n\t\t\t\t\t\t\t\tname: 'reference',\n\t\t\t\t\t\t\t\ttype: ''\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\ttype: 'element',\n\t\t\t\t\t\t\t\tadditionalClassNames: 'mw-ui-icon-flush-right'\n\t\t\t\t\t\t\t} ).$el\n\t\t\t\t\t\t] ),\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\tprops.parentText ?\n\t\t\t\t\t\t\tutil.parseHTML( '<div>' ).html( props.parentText ) :\n\t\t\t\t\t\t\t'',\n\t\t\t\t\t\tutil.parseHTML( '<sup>' ).text( props.title ),\n\t\t\t\t\t\tprops.text ?\n\t\t\t\t\t\t\tutil.parseHTML( '<span>' ).html( ' ' + props.text ) :\n\t\t\t\t\t\t\ticons.spinner().$el\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\nreferences = {\n\ttest: {\n\t\tmakeOnNestedReferenceClickHandler\n\t},\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 {PageHTMLParser} pageHTMLParser\n\t * @param {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: function ( id, page, refNumber, pageHTMLParser, gateway, props,\n\t\tonShowNestedReference\n\t) {\n\t\treturn gateway.getReference( id, page, pageHTMLParser ).then( function ( 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\tonNestedReferenceClick: function ( 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}, function ( 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","var\n\tpageJSONParser = require( '../page/pageJSONParser' ),\n\tutil = require( '../util' ),\n\textendSearchParams = require( '../extendSearchParams' );\n\n/**\n * @class SearchGateway\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: function ( query ) {\n\t\tvar 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: function ( 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: function ( label, term ) {\n\t\tlabel = util.parseHTML( '<span>' ).text( label ).html();\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: function ( query, pageInfo ) {\n\t\tvar 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: function ( query, data ) {\n\t\tvar self = this,\n\t\t\tresults = [];\n\n\t\tif ( data.query ) {\n\n\t\t\tresults = data.query.pages || {};\n\t\t\tresults = Object.keys( results ).map( function ( id ) {\n\t\t\t\treturn self._getPage( query, results[ id ] );\n\t\t\t} );\n\t\t\t// sort in order of index\n\t\t\tresults.sort( function ( a, b ) {\n\t\t\t\treturn a.index - b.index;\n\t\t\t} );\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: function ( query ) {\n\t\tvar xhr, request,\n\t\t\tself = this;\n\n\t\tif ( !this.isCached( query ) ) {\n\t\t\txhr = this.api.get( this.getApiData( query ) );\n\t\t\trequest = xhr\n\t\t\t\t.then( function ( 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: query,\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}, function () {\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: function () { xhr.abort(); }\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: function ( 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\tIcon = require( '../Icon' );\n\n/**\n * @extends 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 * @param {string} [props.searchTerm] default\n\t */\n\tconstructor( props ) {\n\t\tsuper(\n\t\t\tutil.extend( {}, 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\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\t/** @inheritdoc */\n\tget isTemplateMode() {\n\t\treturn true;\n\t}\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 mw-ui-background-icon-search\" type=\"search\" name=\"search\" autocomplete=\"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\t/** @inheritdoc */\n\tpostRender() {\n\t\tconst clearIcon = new Icon( {\n\t\t\ttagName: 'button',\n\t\t\tname: 'clear',\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","var\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 * @extends Overlay\n * @uses SearchGateway\n * @uses Icon\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\tvar header = searchHeader(\n\t\t\tparams.placeholderMsg,\n\t\t\tparams.action || mw.config.get( 'wgScript' ),\n\t\t\tfunction ( query ) {\n\t\t\t\tthis.performSearch( query );\n\t\t\t}.bind( this ),\n\t\t\tparams.defaultSearchPage || ''\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: function () {\n\t\tvar\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( function () {\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: function () {\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: function () {\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: function ( ev ) {\n\t\tvar\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\tvar clickUri = new mw.Uri( location.href );\n\t\t\t\tclickUri.query.searchToken = this.currentSearchId;\n\t\t\t\tself.router.navigateTo( document.title, {\n\t\t\t\t\tpath: clickUri.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: function () {\n\t\tvar 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\t\ttimer;\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', function ( searchData ) {\n\t\t\tif ( timer ) {\n\t\t\t\tclearSearch();\n\t\t\t}\n\t\t\ttimer = setTimeout( function () {\n\t\t\t\tself.$spinner.show();\n\t\t\t}, SEARCH_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: function () {\n\t\tvar 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: function () {\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: function ( query ) {\n\t\tvar\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( function () {\n\t\t\t\t\tvar xhr;\n\t\t\t\t\txhr = 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: api,\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( { abort: function () { xhr.abort(); } } );\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: function () {\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 * @class SearchResultsView\n * @extends 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\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\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\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( {\n\t\t\t\ttagName: 'a',\n\t\t\t\t// When this icon is clicked we want to reset the hash for subsequent views\n\t\t\t\thref: '#',\n\t\t\t\tname: 'articlesSearch',\n\t\t\t\tadditionalClassNames: 'mw-ui-icon-flush-left',\n\t\t\t\tlabel: mw.msg( 'mobile-frontend-search-content' )\n\t\t\t} ).$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 * @return {jQuery.Element}\n */\nfunction searchHeader( placeholderMsg, action, onInput, defaultSearchPage ) {\n\treturn formHeader(\n\t\tnew SearchHeaderView( {\n\t\t\tplaceholderMsg,\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\nmodule.exports = searchHeader;\n","var units = [ 'seconds', 'minutes', 'hours', 'days', 'months', 'years' ],\n\tutil = require( './util' ),\n\tlimits = [ 1, 60, 3600, 86400, 2592000, 31536000 ];\n\n/** @class time */\n\n/**\n * Calculate the correct unit of timestamp\n *\n * @memberof time\n * @instance\n * @param {number} timestampDelta\n * @return {{value: number, unit: string}}\n */\nfunction timeAgo( timestampDelta ) {\n\tvar 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 time\n * @instance\n * @param {number} timestamp\n * @return {{value: number, unit: string}}\n */\nfunction getTimeAgoDelta( timestamp ) {\n\tvar 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 * @memberof time\n * @instance\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 * @memberof time\n * @instance\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 * @memberof time\n * @instance\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\tvar delta,\n\t\tlastEditedElement, usernameElement,\n\t\tlinkAll = 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\tdelta = 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\tlastEditedElement = linkAll ?\n\t\tutil.parseHTML( '<strong>' ).attr( 'class', 'last-modified-text-accent' ) :\n\t\tutil.parseHTML( '<a>' ).attr( 'href', historyUrl || '#' );\n\tusernameElement = 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 * @memberof time\n * @instance\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\tvar delta, html,\n\t\tkeys = {\n\t\t\tseconds: 'mobile-frontend-joined-seconds',\n\t\t\tminutes: 'mobile-frontend-joined-minutes',\n\t\t\thours: 'mobile-frontend-joined-hours',\n\t\t\tdays: 'mobile-frontend-joined-days',\n\t\t\tmonths: 'mobile-frontend-joined-months',\n\t\t\tyears: 'mobile-frontend-joined-years'\n\t\t},\n\t\targs = [];\n\n\tgender = gender || 'unknown';\n\n\tdelta = 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\thtml = mw.message.apply( this, args ).parse();\n\treturn html;\n}\n\nmodule.exports = {\n\tgetLastModifiedMessage: getLastModifiedMessage,\n\tgetRegistrationMessage: getRegistrationMessage,\n\ttimeAgo: timeAgo,\n\tgetTimeAgoDelta: getTimeAgoDelta,\n\tisNow: isNow,\n\tisRecent: isRecent\n};\n"],"sourceRoot":""}