%PDF- %PDF-
Direktori : /www/varak.net/wiki.varak.net/extensions/MobileFrontend/resources/dist/ |
Current File : /www/varak.net/wiki.varak.net/extensions/MobileFrontend/resources/dist/mobile.startup.js.map.json |
{"version":3,"sources":["webpack://mfModules.[name]/./src/mobile.startup/mfExtend.js","webpack://mfModules.[name]/./src/mobile.startup/util.js","webpack://mfModules.[name]/./src/mobile.startup/View.js","webpack://mfModules.[name]/./src/mobile.startup/icons.js","webpack://mfModules.[name]/./src/mobile.startup/Browser.js","webpack://mfModules.[name]/./src/mobile.startup/Page.js","webpack://mfModules.[name]/./src/mobile.startup/time.js","webpack://mfModules.[name]/./src/mobile.startup/Icon.js","webpack://mfModules.[name]/./src/mobile.startup/modules.js","webpack://mfModules.[name]/./src/mobile.startup/Section.js","webpack://mfModules.[name]/./src/mobile.startup/Thumbnail.js","webpack://mfModules.[name]/./src/mobile.startup/moduleSingleton.js","webpack://mfModules.[name]/./src/mobile.startup/cache.js","webpack://mfModules.[name]/./src/mobile.startup/OverlayManager.js","webpack://mfModules.[name]/./src/mobile.startup/Skin.js","webpack://mfModules.[name]/./src/mobile.startup/Button.js","webpack://mfModules.[name]/./src/mobile.startup/Anchor.js","webpack://mfModules.[name]/./src/mobile.startup/Overlay.js","webpack://mfModules.[name]/./src/mobile.startup/LoadingOverlay.js","webpack://mfModules.[name]/./src/mobile.startup/mobile.startup.js","webpack://mfModules.[name]/./src/mobile.startup/context.js","webpack://mfModules.[name]/./src/mobile.startup/user.js","webpack://mfModules.[name]/./src/mobile.startup/PageGateway.js","webpack://mfModules.[name]/./src/mobile.startup/Panel.js","webpack://mfModules.[name]/./src/mobile.startup/rlModuleLoader.js"],"names":["module","exports","Child","ParentOrPrototype","prototype","key","OO","inheritClass","initClass","escapeSelector","selector","$","grep","apply","arguments","docReady","fn","when","Deferred","d","warning","mw","log","deprecate","fail","always","done","getDocument","document","documentElement","getWindow","window","parseHTML","html","ctx","isNumeric","extend","escapeHash","hash","replace","isModifiedEvent","ev","altKey","ctrlKey","metaKey","shiftKey","repeatEvent","src","proxy","event","args","on","emit","util","__webpack_require__","mfExtend","delegateEventSplitter","idCounter","View","this","initialize","mixinClass","EventEmitter","className","undefined","tagName","isTemplateMode","isBorderBox","template","templatePartials","defaults","events","options","self","call","cid","prefix","id","toString","uniqueId","compile","el","$el","length","_postInitialize","addClass","render","preRender","postRender","data","undelegateEvents","skipTemplateRender","delegateEvents","query","find","match","method","delegate","bind","eventName","listener","off","undelegate","forEach","prop","Icon","spinner","name","label","msg","additionalClassNames","browser","memoize","memoized","cache","cacheId","join","Object","hasOwnProperty","Date","now","Math","random","Browser","ua","$container","userAgent","_fixIosLandscapeBug","isIos","lockViewport","addEventListener","version","ios","test","attr","isWideScreen","val","parseInt","config","get","innerWidth","innerHeight","supportsAnimations","elemStyle","createElement","style","supportsProperty","property","toUpperCase","slice","supportsTouchEvents","supportsGeoLocation","navigator","getSingleton","$html","HTML","time","Section","Thumbnail","HEADING_SELECTOR","BLACKLISTED_THUMBNAIL_CLASS_SELECTORS","Page","thumb","thumbnail","languageUrl","getUrl","title","displayTitle","getDisplayTitle","url","isMissing","width","isLandscape","height","wikidataDescription","namespaceNumber","protection","edit","sections","isMainPage","source","escape","inNamespace","namespace","findSectionHeadingByIndex","sectionIndex","filter","eq","findChildInSectionLead","$heading","$nextHeading","$lead","headingSelector","withNestedChildren","$matchingNodes","addBack","getLeadSectionElement","children","prevAll","hasClass","next","nextAll","nextUntil","isWikiText","isWatched","getRevisionId","revId","getTitle","getId","getNamespaceId","split","toLowerCase","isTalkPage","ns","_sectionLookup","sectionData","section","push","getThumbnails","blacklistSelector","thumbs","_thumbs","not","each","$a","$lazyImage","valid","parents","legacyMatch","RegExp","filename","decodeURIComponent","getSection","getSections","getRedLinks","newFromJSON","resp","revision","pageprops","displaytitle","terms","description","revisions","lastModified","getLastModifiedMessage","timestamp","getTime","user","pageid","missing","units","limits","timeAgo","timestampDelta","i","value","round","unit","getTimeAgoDelta","isNow","delta","ts","username","gender","historyUrl","seconds","minutes","hours","days","months","years","language","convertNumber","message","parse","text","getRegistrationMessage","isRecent","indexOf","hasText","modifier","href","setRotationClass","rotation","_rotationClass","Error","glyphPrefix","isSmall","base","getClassName","getGlyphClassName","toHtmlString","append","ModuleLoader","_register","require","registry","localRequire","loader","e","define","obj","deprecatedId","replacement","icons","tag","level","line","hasReferences","anchor","siblings","getDescription","getFileName","MemoryCache","_cache","NoCache","set","OverlayManager","router","_checkRoute","entries","stack","hideCurrent","_onHideOverlay","back","_showOverlay","overlay","once","show","_hideOverlay","result","hide","_processMatch","factoryResult","attachHideEvent","promise","then","current","scrollTop","pageYOffset","keys","reduce","m","_matchRoute","path","preventDefault","scrollTo","pageXOffset","entry","route","previous","getNext","factory","hasLoadError","shift","unshift","add","getPath","replaceCurrent","viewport","M","getSectionId","hSelector","$parent","parent","Skin","page","mainMenu","warn","referencesGateway","setupImageLoading","lazyLoadReferences","appendTo","getUnloadedImages","toArray","offset","loadImagesList","imagePlaceholders","_loadImages","images","placeholder","$placeholder","isElementCloseToViewport","is","shouldLoadImage","callbacks","loadImage","map","$downloadingImage","ownerDocument","replaceWith","resolve","reject","class","alt","srcset","$content","$spinner","gateway","wasExpanded","isReferenceSection","prependTo","getReferencesLists","lastId","refListIndex","getReferencesList","refListElements","remove","removeClass","loadImagesAndSetData","getLicenseMsg","licenseMsg","mfLicense","licensePlural","plural","link","Button","block","progressive","destructive","quiet","Anchor","Overlay","useVirtualKeyboardHack","hasFixedHeader","fullScreen","hideOnExitClick","appendToElement","header","button","saveMsg","cancelButton","backButton","headerButtonsListClassName","headerChrome","fixedHeader","click .cancel, .confirm, .initial-header .back","click","closeOnContentTap","showSpinner","hideSpinner","$overlayContent","setupEmulatedIosOverlayScrolling","onTouchStart","onTouchMove","setTimeout","_fixIosHeader","onExitClick","stopPropagation","EVENT_EXIT","startY","originalEvent","touches","pageY","y","contentOuterHeight","outerHeight","contentLength","$window","one","_resizeContent","detach","windowHeight","keyboardHeight","showHidden","LoadingOverlay","moduleLoader","context","PageGateway","Panel","rlModuleLoader","mobileFrontend","getMode","mwUser","tokens","isAnon","getName","getEditCount","getGroups","getSessionId","sessionId","inUserBucketA","sectionTemplate","transformSections","lastSection","existingSectionLevels","s","collapseLevel","min","assignToParent","listOfSections","child","api","getPage","endpoint","leadOnly","dataType","action","variant","redirect","noheadings","sectionprop","resolveObj","mv","error","mobileview","lastmodified","lastmodifiedby","Array","isArray","lead","mainpage","lastModifiedTimestamp","languageCount","languagecount","hasVariants","hasvariants","lastModifiedUserName","lastModifiedUserGender","invalidatePage","_getLanguageVariantsFromApiResponse","generalData","general","variantPath","variantarticlepath","variants","index","item","autonym","lang","code","getPageLanguages","meta","siprop","lllimit","titles","formatversion","llprop","llinlanguagecode","languages","pages","langlinks","_getAPIResponseFromHTML","substr","$span","getSectionsFromHTML","minHideDelay","click .cancel","onCancel","isVisible","toggle","loadModule","delegateHide","showLoadingOverlay","loadingOverlay","hideOverlayIfNeeded","using"],"mappings":"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","file":"mobile.startup.js","sourcesContent":["/**\n * Extends a class with new methods and member properties.\n *\n * @param {Function} Child function\n * @param {Object|Function} ParentOrPrototype class to inherit from\n * OR if no inheriting class a prototype to extend the class with\n * @param {Object} [prototype]\n */\nfunction mfExtend( Child, ParentOrPrototype, prototype ) {\n\tvar key;\n\tif ( prototype ) {\n\t\tOO.inheritClass( Child, ParentOrPrototype );\n\t} else {\n\t\tOO.initClass( Child );\n\t\tprototype = ParentOrPrototype;\n\t}\n\tfor ( key in prototype ) {\n\t\tChild.prototype[key] = prototype[key];\n\t}\n}\n\nmodule.exports = mfExtend;\n","/* global $ */\n\n/**\n * Utility library\n * @class util\n * @singleton\n */\nmodule.exports = {\n\t/**\n\t * Escape a string for use as a css selector\n\t * @memberof util\n\t * @instance\n\t * @param {string} selector\n\t * @return {string}\n\t */\n\tescapeSelector: function ( selector ) {\n\t\treturn $.escapeSelector( selector );\n\t},\n\t/**\n\t * Wrapper class for the $.grep\n\t * @memberof util\n\t * @instance\n\t * @return {jQuery.Deferred}\n\t */\n\tgrep: function () {\n\t\treturn $.grep.apply( $, arguments );\n\t},\n\t/**\n\t * Run method when document is ready.\n\t * @memberof util\n\t * @instance\n\t * @param {Function} fn\n\t * @return {jQuery.Object}\n\t */\n\tdocReady: function ( fn ) {\n\t\treturn $( fn );\n\t},\n\t/**\n\t * Wrapper class for the $.when\n\t * @memberof util\n\t * @instance\n\t * @return {jQuery.Deferred}\n\t */\n\twhen: function () {\n\t\treturn $.when.apply( $, arguments );\n\t},\n\t/**\n\t * Wrapper class for the Deferred method\n\t * @memberof util\n\t * @instance\n\t * @return {jQuery.Deferred}\n\t */\n\tDeferred: function () {\n\t\tvar d = $.Deferred(),\n\t\t\twarning = 'Use Promise compatible methods `then` and `catch` instead.';\n\n\t\t/* eslint-disable no-restricted-properties */\n\t\tmw.log.deprecate( d, 'fail', d.fail, warning );\n\t\tmw.log.deprecate( d, 'always', d.always, warning );\n\t\tmw.log.deprecate( d, 'done', d.done, warning );\n\t\t/* eslint-enable no-restricted-properties */\n\t\treturn d;\n\t},\n\t/**\n\t * Adds a class to the document\n\t * @memberof util\n\t * @instance\n\t * @return {jQuery.Object} element representing the documentElement\n\t */\n\tgetDocument: function () {\n\t\treturn $( document.documentElement );\n\t},\n\t/**\n\t * Get the window object\n\t * @memberof util\n\t * @instance\n\t * @return {jQuery.Object}\n\t */\n\tgetWindow: function () {\n\t\treturn $( window );\n\t},\n\t/**\n\t * Given some html, create new element(s).\n\t * Unlike jQuery.parseHTML this will return a jQuery object\n\t * not an array.\n\t * @memberof util\n\t * @instance\n\t * @param {string} html\n\t * @param {Element} [ctx] Document element to serve as the context\n\t * in which the HTML fragment will be created\n\t * @return {jQuery.Object}\n\t */\n\tparseHTML: function ( html, ctx ) {\n\t\treturn $( $.parseHTML( html, ctx ) );\n\t},\n\t/**\n\t * wrapper for jQuery util function to check if something is numeric\n\t * @memberof util\n\t * @instance\n\t * @return {boolean}\n\t */\n\tisNumeric: function () {\n\t\treturn $.isNumeric.apply( $, arguments );\n\t},\n\t/**\n\t * Wrapper for jQuery.extend method. In future this can be bound to Object.assign\n\t * when support allows.\n\t * @memberof util\n\t * @instance\n\t * @return {Object}\n\t */\n\textend: function () {\n\t\treturn $.extend.apply( $, arguments );\n\t},\n\t/**\n\t * Escape dots and colons in a hash, jQuery doesn't like them because they\n\t * look like CSS classes and pseudoclasses. See\n\t * http://bugs.jquery.com/ticket/5241\n\t * http://stackoverflow.com/questions/350292/how-do-i-get-jquery-to-select-elements-with-a-period-in-their-id\n\t * @memberof util\n\t * @instance\n\t * @param {string} hash A hash to escape\n\t * @return {string}\n\t */\n\tescapeHash: function ( hash ) {\n\t\treturn hash.replace( /(:|\\.)/g, '\\\\$1' );\n\t},\n\n\t/**\n\t * Heuristic for determining whether an Event should be handled by\n\t * MobileFrontend or allowed to bubble to the browser.\n\t * @memberof util\n\t * @instance\n\t * @param {Event} ev\n\t * @return {boolean} True if event is modified with control, alt, meta, or\n\t * shift keys and should probably be handled by the\n\t * browser.\n\t *\n\t * todo: move this function to a ClickUtil file once bundling and code\n\t * splitting is supported.\n\t */\n\tisModifiedEvent: function ( ev ) {\n\t\treturn ev.altKey || ev.ctrlKey || ev.metaKey || ev.shiftKey;\n\t},\n\n\t/**\n\t * Pipe event emitted by source through proxy. Subscribers to proxy will receive the event as\n\t * though proxy was the originator.\n\t *\n\t * @param {OO.EventEmitter} src\n\t * @param {OO.EventEmitter} proxy\n\t * @param {string} event Event type to listen for.\n\t * @param {any[]} [args] Arguments to pass to\n\t * subscribers, will be prepended to emitted arguments.\n\t * @return {OO.EventEmitter} The source.\n\t */\n\trepeatEvent: function ( src, proxy, event, args ) {\n\t\treturn src.on( event, function ( args ) { return proxy.emit( event, args ); }, args );\n\t}\n};\n","/* global $ */\nvar util = require( './util' ),\n\tmfExtend = require( './mfExtend' ),\n\t// Cached regex to split keys for `delegate`.\n\tdelegateEventSplitter = /^(\\S+)\\s*(.*)$/,\n\tidCounter = 0;\n\n/**\n * Generate a unique integer id (unique within the entire client session).\n * Useful for temporary DOM ids.\n * @param {string} prefix Prefix to be used when generating the id.\n * @return {string}\n */\nfunction uniqueId( prefix ) {\n\tvar id = ( ++idCounter ).toString();\n\treturn prefix ? prefix + id : id;\n}\n\n/**\n * Should be extended using extend().\n *\n * When options contains el property, this.$el in the constructed object\n * will be set to the corresponding jQuery object. Otherwise, this.$el\n * will be an empty div.\n *\n * When extended using extend(), if the extended prototype contains\n * template property, this.$el will be filled with rendered template (with\n * options parameter used as template data).\n *\n * template property can be a string which will be passed to mw.template.compile()\n * or an object that has a render() function which accepts an object with\n * template data as its argument (similarly to an object created by\n * mw.template.compile()).\n *\n * You can also define a defaults property which should be an object\n * containing default values for the template (if they're not present in\n * the options parameter).\n *\n * If this.$el is not a jQuery object bound to existing DOM element, the\n * view can be attached to an element using appendTo(), prependTo(),\n * insertBefore(), insertAfter() proxy functions.\n *\n * append(), prepend(), before(), after() can be used to modify $el. on()\n * can be used to bind events.\n *\n * You can also use declarative DOM events binding by specifying an `events`\n * map on the class. The keys will be 'event selector' and the value can be\n * either the name of a method to call, or a function. All methods and\n * functions will be executed on the context of the View.\n *\n * Inspired from Backbone.js\n * https://github.com/jashkenas/backbone/blob/master/backbone.js#L1128\n *\n * Example:\n * ```js\n * var MyComponent = View.extend( {\n * events: {\n *\t 'mousedown .title': 'edit',\n *\t 'click .button': 'save',\n *\t 'click .open': function(e) { ... }\n * },\n * edit: function ( ev ) {\n * //...\n * },\n * save: function ( ev ) {\n * //...\n * }\n * } );\n * ```\n *\n * Example:\n * ```js\n * var View, section;\n * function Section( options ) {\n * View.call( this, options );\n * }\n * View = require( './View' );\n * require( './mfExtend' )( Section, View, {\n * template: mw.template.compile( \"<h2>{{title}}</h2>\" ),\n * } );\n * section = new Section( { title: 'Test', text: 'Test section body' } );\n * section.appendTo( 'body' );\n * ```\n *\n * @class View\n * @mixins OO.EventEmitter\n */\nfunction View() {\n\tthis.initialize.apply( this, arguments );\n}\nOO.mixinClass( View, OO.EventEmitter );\nmfExtend( View, {\n\t/**\n\t * A css class to apply to the containing element of the View.\n\t * @memberof View\n\t * @instance\n\t * @property {string} className\n\t */\n\tclassName: undefined,\n\t/**\n\t * Name of tag that contains the rendered template\n\t * @memberof View\n\t * @instance\n\t * @property {string} tagName\n\t */\n\ttagName: 'div',\n\t/**\n\t * Tells the View to ignore tagName and className when constructing the element\n\t * and to rely solely on the template\n\t * @memberof View\n\t * @instance\n\t * @property {boolean} isTemplateMode\n\t */\n\tisTemplateMode: false,\n\n\t/**\n\t * Whether border box box sizing model should be used\n\t * @memberof View\n\t * @instance\n\t * @property {boolean} isBorderBox\n\t */\n\tisBorderBox: true,\n\t/**\n\t * @memberof View\n\t * @instance\n\t * @property {Mixed}\n\t * Specifies the template used in render(). Object|string|HoganTemplate\n\t */\n\ttemplate: undefined,\n\n\t/**\n\t * Specifies partials (sub-templates) for the main template. Example:\n\t *\n\t * @example\n\t * // example content for the \"some\" template (sub-template will be\n\t * // inserted where {{>content}} is):\n\t * // <h1>Heading</h1>\n\t * // {{>content}}\n\t *\n\t * oo.mfExtend( SomeView, View, {\n\t * template: M.template.get( 'some.hogan' ),\n\t * templatePartials: { content: M.template.get( 'sub.hogan' ) }\n\t * }\n\t *\n\t * @memberof View\n\t * @instance\n\t * @property {Object}\n\t */\n\ttemplatePartials: {},\n\n\t/**\n\t * A set of default options that are merged with options passed into the initialize\n\t * function.\n\t * @memberof View\n\t * @instance\n\t * @property {Object} defaults Default options hash.\n\t * @property {jQuery.Object|string} [defaults.el] jQuery selector to use for rendering.\n\t * @property {boolean} [defaults.skipTemplateRender] Whether to enhance views already in\n\t * DOM. When enabled, the template is disabled so that it is not rendered in the DOM.\n\t * Use in conjunction with View::defaults.$el to associate the View with an existing\n\t * already rendered element in the DOM.\n\t */\n\tdefaults: {},\n\n\t/**\n\t * Default events map\n\t * @memberof View\n\t * @instance\n\t */\n\tevents: null,\n\n\t/**\n\t * Run once during construction to set up the View\n\t * @memberof View\n\t * @instance\n\t * @param {Object} options Object passed to the constructor.\n\t */\n\tinitialize: function ( options ) {\n\t\tvar self = this;\n\n\t\tOO.EventEmitter.call( this );\n\t\toptions = util.extend( {}, this.defaults, options );\n\t\tthis.options = options;\n\t\t// Assign a unique id for dom events binding/unbinding\n\t\tthis.cid = uniqueId( 'view' );\n\n\t\t// TODO: if template compilation is too slow, don't compile them on a\n\t\t// per object basis, but don't worry about it now (maybe add cache to\n\t\t// M.template.compile())\n\t\tif ( typeof this.template === 'string' ) {\n\t\t\tthis.template = mw.template.compile( this.template );\n\t\t}\n\n\t\tif ( options.el ) {\n\t\t\t// Note the element may not be in the document so must use global jQuery here\n\t\t\tthis.$el = $( options.el );\n\t\t} else {\n\t\t\tthis.$el = this.parseHTML( '<' + this.tagName + '>' );\n\t\t}\n\n\t\t// Make sure the element is ready to be manipulated\n\t\tif ( this.$el.length ) {\n\t\t\tthis._postInitialize();\n\t\t} else {\n\t\t\tutil.docReady( function () {\n\t\t\t\t// Note the element may not be in the document so must use global jQuery here\n\t\t\t\tself.$el = $( options.el );\n\t\t\t\tself._postInitialize();\n\t\t\t} );\n\t\t}\n\t},\n\n\t/**\n\t * Called when this.$el is ready.\n\t * @memberof View\n\t * @instance\n\t * @private\n\t */\n\t_postInitialize: function () {\n\t\tthis.$el.addClass( this.className );\n\t\tif ( this.isBorderBox ) {\n\t\t\t// FIXME: Merge with className property (?)\n\t\t\tthis.$el.addClass( 'view-border-box' );\n\t\t}\n\t\tthis.render( this.options );\n\t},\n\n\t/**\n\t * Function called before the view is rendered. Can be redefined in\n\t * objects that extend View.\n\t * @memberof View\n\t * @instance\n\t */\n\tpreRender: function () {},\n\n\t/**\n\t * Function called after the view is rendered. Can be redefined in\n\t * objects that extend View.\n\t *\n\t * @memberof View\n\t * @instance\n\t */\n\tpostRender: function () {},\n\n\t// eslint-disable-next-line valid-jsdoc\n\t/**\n\t * Fill this.$el with template rendered using data if template is set.\n\t *\n\t * @memberof View\n\t * @instance\n\t * @param {Object} data Template data. Will be merged into the view's\n\t * options\n\t * @chainable\n\t */\n\trender: function ( data ) {\n\t\tvar html;\n\t\tutil.extend( this.options, data );\n\t\tthis.preRender();\n\t\tthis.undelegateEvents();\n\t\tif ( this.template && !this.options.skipTemplateRender ) {\n\t\t\thtml = this.template.render( this.options, this.templatePartials );\n\t\t\tif ( this.isTemplateMode ) {\n\t\t\t\tthis.$el = $( html );\n\t\t\t} else {\n\t\t\t\tthis.$el.html( html );\n\t\t\t}\n\t\t}\n\t\tthis.postRender();\n\t\tthis.delegateEvents();\n\t\treturn this;\n\t},\n\n\t/**\n\t * Wraps this.$el.find, so that you can search for elements in the view's\n\t * ($el's) scope.\n\t *\n\t * @memberof View\n\t * @instance\n\t * @param {string} query A jQuery CSS selector.\n\t * @return {JQuery.Object} jQuery object containing results of the search.\n\t */\n\t$: function ( query ) {\n\t\treturn this.$el.find( query );\n\t},\n\n\t/**\n\t * Set callbacks, where `this.events` is a hash of\n\t *\n\t * {\"event selector\": \"callback\"}\n\t *\n\t * {\n\t *\t'mousedown .title': 'edit',\n\t *\t'click .button': 'save',\n\t *\t'click .open': function(e) { ... }\n\t * }\n\t *\n\t * pairs. Callbacks will be bound to the view, with `this` set properly.\n\t * Uses event delegation for efficiency.\n\t * Omitting the selector binds the event to `this.el`.\n\t *\n\t * @memberof View\n\t * @instance\n\t * @param {Object} events Optionally set this events instead of the ones on this.\n\t */\n\tdelegateEvents: function ( events ) {\n\t\tvar match, key, method;\n\t\t// Take either the events parameter or the this.events to process\n\t\tevents = events || this.events;\n\t\tif ( events ) {\n\t\t\t// Remove current events before re-binding them\n\t\t\tthis.undelegateEvents();\n\t\t\tfor ( key in events ) {\n\t\t\t\tmethod = events[ key ];\n\t\t\t\t// If the method is a string name of this.method, get it\n\t\t\t\tif ( typeof method !== 'function' ) {\n\t\t\t\t\tmethod = this[ events[ key ] ];\n\t\t\t\t}\n\t\t\t\tif ( method ) {\n\t\t\t\t\t// Extract event and selector from the key\n\t\t\t\t\tmatch = key.match( delegateEventSplitter );\n\t\t\t\t\tthis.delegate( match[ 1 ], match[ 2 ], method.bind( this ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Add a single event listener to the view's element (or a child element\n\t * using `selector`). This only works for delegate-able events: not `focus`,\n\t * `blur`, and not `change`, `submit`, and `reset` in Internet Explorer.\n\t *\n\t * @memberof View\n\t * @instance\n\t * @param {string} eventName\n\t * @param {string} selector\n\t * @param {Function} listener\n\t */\n\tdelegate: function ( eventName, selector, listener ) {\n\t\tthis.$el.on( eventName + '.delegateEvents' + this.cid, selector,\n\t\t\tlistener );\n\t},\n\n\t/**\n\t * Clears all callbacks previously bound to the view by `delegateEvents`.\n\t * You usually don't need to use this, but may wish to if you have multiple\n\t * views attached to the same DOM element.\n\t * @memberof View\n\t * @instance\n\t */\n\tundelegateEvents: function () {\n\t\tif ( this.$el ) {\n\t\t\tthis.$el.off( '.delegateEvents' + this.cid );\n\t\t}\n\t},\n\n\t/**\n\t * A finer-grained `undelegateEvents` for removing a single delegated event.\n\t * `selector` and `listener` are both optional.\n\t *\n\t * @memberof View\n\t * @instance\n\t * @param {string} eventName\n\t * @param {string} selector\n\t * @param {Function} listener\n\t */\n\tundelegate: function ( eventName, selector, listener ) {\n\t\tthis.$el.off( eventName + '.delegateEvents' + this.cid, selector,\n\t\t\tlistener );\n\t},\n\n\t/**\n\t * See parseHTML method of util singleton\n\t *\n\t * @memberof View\n\t * @instance\n\t */\n\tparseHTML: util.parseHTML\n} );\n\n/**\n * @memberof View\n * @instance\n * @func append\n * @param {...(string|Node|Node[]|JQuery)} contents\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func append\n * @param {function(number, string): string|Node|Node[]|JQuery} contents\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func prepend\n * @param {...(string|Node|Node[]|JQuery)} contents\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func prepend\n * @param {function(number, string): string|Node|Node[]|JQuery} contents\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func appendTo\n * @param {string|Node|Node[]|JQuery} target\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func prependTo\n * @param {string|Node|Node[]|JQuery} target\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func after\n * @param {...(string|Node|Node[]|JQuery)} contents\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func after\n * @param {function(number, string): string|Node|Node[]|JQuery} contents\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func before\n * @param {...(string|Node|Node[]|JQuery)} contents\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func before\n * @param {function(number, string): string|Node|Node[]|JQuery} contents\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func insertAfter\n * @param {string|Node|Node[]|JQuery} target\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func insertBefore\n * @param {string|Node|Node[]|JQuery} target\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func remove\n * @param {string} [selector]\n * @return {this}\n */\n\n/**\n * @memberof View\n * @instance\n * @func detach\n * @param {string} [selector]\n * @return {this}\n */\n\n[\n\t'append',\n\t'prepend',\n\t'appendTo',\n\t'prependTo',\n\t'after',\n\t'before',\n\t'insertAfter',\n\t'insertBefore',\n\t'remove',\n\t'detach'\n].forEach( function ( prop ) {\n\tView.prototype[prop] = function () {\n\t\tthis.$el[prop].apply( this.$el, arguments );\n\t\treturn this;\n\t};\n} );\n\nmodule.exports = View;\n","var\n\tIcon = require( './Icon' ),\n\tutil = require( './util' );\n\n/**\n * A set of shared icons.\n *\n * Factory methods are used to keep separate features that use the same icons\n * from accidentally manipulating one another's DOM when calling methods like\n * `remove`.\n *\n * @class icons\n * @singleton\n * @uses Icon\n */\nmodule.exports = {\n\t/**\n\t * Gets a spinner icon.\n\t *\n\t * The icon should be used to inform the user that the front-end is\n\t * communicating with the back-end.\n\t * @memberof icons\n\t * @instance\n\t * @param {Object} [options] See `Icon` for more details\n\t * @return {Icon}\n\t */\n\tspinner: function ( options ) {\n\t\toptions = options || {};\n\n\t\treturn new Icon( util.extend( options, {\n\t\t\tname: 'spinner',\n\t\t\tlabel: mw.msg( 'mobile-frontend-loading-message' ),\n\t\t\tadditionalClassNames: 'spinner loading'\n\t\t} ) );\n\t}\n};\n","var\n\tutil = require( './util' ),\n\tbrowser;\n\n/**\n * Memoize a class method. Caches the result of the method based on the\n * arguments. Instances do not share a cache.\n * @param {Function} method Method to be memoized\n * @return {Function}\n */\nfunction memoize( method ) {\n\t/**\n\t * Memoized version of the method\n\t * @return {Function}\n\t */\n\tvar memoized = function () {\n\t\tvar cache = this[ '__cache' + memoized.cacheId ] ||\n\t\t\t( this[ '__cache' + memoized.cacheId ] = {} ),\n\t\t\tkey = [].join.call( arguments, '|' );\n\t\tif ( Object.prototype.hasOwnProperty.call( cache, key ) ) {\n\t\t\treturn cache[ key ];\n\t\t}\n\t\treturn ( cache[ key ] = method.apply( this, arguments ) );\n\t};\n\tmemoized.cacheId = Date.now().toString() + Math.random().toString();\n\treturn memoized;\n}\n\n/**\n * Representation of user's current browser\n * @class Browser\n * @param {string} ua the user agent of the current browser\n * @param {jQuery.Object} $container an element to associate with the Browser object\n */\nfunction Browser( ua, $container ) {\n\tthis.userAgent = ua;\n\tthis.$el = $container;\n\tthis._fixIosLandscapeBug();\n}\n\nBrowser.prototype = {\n\t/**\n\t * When rotating to landscape stop page zooming on ios 4 and 5.\n\t * @memberof Browser\n\t * @instance\n\t * @private\n\t */\n\t_fixIosLandscapeBug: function () {\n\t\tvar self = this,\n\t\t\tviewport = this.$el.find( 'meta[name=\"viewport\"]' )[0];\n\n\t\t// see http://adactio.com/journal/4470/ (fixed in ios 6)\n\t\tif ( viewport && ( this.isIos( 4 ) || this.isIos( 5 ) ) ) {\n\t\t\tthis.lockViewport();\n\t\t\tdocument.addEventListener( 'gesturestart', function () {\n\t\t\t\tself.lockViewport();\n\t\t\t}, false );\n\t\t}\n\t},\n\t/**\n\t * Returns whether the current browser is an ios device.\n\t * FIXME: jquery.client does not support iPad detection so we cannot use it.\n\t * @memberof Browser\n\t * @instance\n\t * @param {number} [version] integer describing a specific version you want to test against.\n\t * @return {boolean}\n\t */\n\tisIos: memoize( function ( version ) {\n\t\tvar ua = this.userAgent,\n\t\t\tios = /ipad|iphone|ipod/i.test( ua );\n\n\t\tif ( ios && version ) {\n\t\t\tswitch ( version ) {\n\t\t\t\tcase 8:\n\t\t\t\t\t// Test UA for iOS8. Or for simulator look for Version 8\n\t\t\t\t\t// In the iOS simulator the OS is the host machine OS version\n\t\t\t\t\t// This makes testing in iOS8 simulator work as expected\n\t\t\t\t\treturn /OS 8_/.test( ua ) || /Version\\/8/.test( ua );\n\t\t\t\tcase 4:\n\t\t\t\t\treturn /OS 4_/.test( ua );\n\t\t\t\tcase 5:\n\t\t\t\t\treturn /OS 5_/.test( ua );\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t} else {\n\t\t\treturn ios;\n\t\t}\n\t} ),\n\t/**\n\t * Locks the viewport so that pinch zooming is disabled\n\t * @memberof Browser\n\t * @instance\n\t */\n\tlockViewport: function () {\n\t\tif ( this.$el ) {\n\t\t\tthis.$el.find( 'meta[name=\"viewport\"]' )\n\t\t\t\t.attr( 'content', 'initial-scale=1.0, maximum-scale=1.0, user-scalable=no' );\n\t\t}\n\t},\n\t/**\n\t * Determine if a device has a widescreen.\n\t * @memberof Browser\n\t * @instance\n\t * @return {boolean}\n\t */\n\tisWideScreen: memoize( function () {\n\t\tvar val = parseInt( mw.config.get( 'wgMFDeviceWidthTablet' ), 10 );\n\t\t// Check portrait and landscape mode to be consistent\n\t\treturn window.innerWidth >= val || window.innerHeight >= val;\n\t} ),\n\t/**\n\t * Checks browser support for CSS transforms, transitions\n\t * and CSS animation.\n\t * Currently assumes support for the latter 2 in the case of the\n\t * former.\n\t * See http://stackoverflow.com/a/12621264/365238\n\t * @memberof Browser\n\t * @instance\n\t * @return {boolean}\n\t */\n\tsupportsAnimations: memoize( function () {\n\t\tvar elemStyle = document.createElement( 'foo' ).style;\n\t\tfunction supportsProperty( property ) {\n\t\t\t// We only test \"webkit-\", because that's the only prefix needed for the relevant\n\t\t\t// properties (in supportsAnimations) and supported browsers. If usage is expanded,\n\t\t\t// other prefixes may need to be checked as well.\n\t\t\treturn property in elemStyle ||\n\t\t\t\t( 'webkit' + property[ 0 ].toUpperCase() + property.slice( 1 ) ) in elemStyle;\n\t\t}\n\t\treturn supportsProperty( 'animationName' ) &&\n\t\t\tsupportsProperty( 'transform' ) &&\n\t\t\tsupportsProperty( 'transition' );\n\t} ),\n\t/**\n\t * Whether touchstart and other touch events are supported by the current browser.\n\t * @memberof Browser\n\t * @instance\n\t * @return {boolean}\n\t */\n\tsupportsTouchEvents: memoize( function () {\n\t\treturn 'ontouchstart' in window;\n\t} ),\n\t/**\n\t * Detect if browser supports geolocation\n\t * @memberof Browser\n\t * @instance\n\t * @return {boolean}\n\t */\n\tsupportsGeoLocation: memoize( function () {\n\t\treturn 'geolocation' in window.navigator;\n\t} )\n};\n\n/**\n * @memberof Browser\n * @return {Browser}\n */\nBrowser.getSingleton = function () {\n\tvar $html;\n\tif ( !browser ) {\n\t\t$html = util.getDocument();\n\t\tbrowser = new Browser( window.navigator.userAgent, $html );\n\t}\n\treturn browser;\n};\n\nmodule.exports = Browser;\n","var\n\tHTML = mw.html,\n\tmfExtend = require( './mfExtend' ),\n\ttime = require( './time' ),\n\tutil = require( './util' ),\n\tSection = require( './Section' ),\n\tThumbnail = require( './Thumbnail' ),\n\tView = require( './View' ),\n\tHEADING_SELECTOR = mw.config.get( 'wgMFMobileFormatterHeadings' ).join( ',' ),\n\tBLACKLISTED_THUMBNAIL_CLASS_SELECTORS = [ 'noviewer', 'metadata' ];\n\n/**\n * Mobile page view object\n *\n * @class Page\n * @uses Section\n * @extends View\n *\n * @param {Object} options Configuration options\n */\nfunction Page( options ) {\n\tvar thumb;\n\t// If thumbnail is not passed it should be made false (truthy) so that it\n\t// renders a placeholder when absent.\n\tif ( options.thumbnail === undefined ) {\n\t\toptions.thumbnail = false;\n\t}\n\tthis.options = options;\n\toptions.languageUrl = mw.util.getUrl( 'Special:MobileLanguages/' + options.title );\n\tView.call( this, options );\n\t// Fallback if no displayTitle provided\n\toptions.displayTitle = this.getDisplayTitle();\n\t// allow usage in templates.\n\t// FIXME: Should View map all options to properties?\n\tthis.title = options.title;\n\tthis.displayTitle = options.displayTitle;\n\tthis.thumbnail = options.thumbnail;\n\tthis.url = options.url || mw.util.getUrl( options.title );\n\tthis.id = options.id;\n\tthis.isMissing = options.isMissing !== undefined ? options.isMissing : options.id === 0;\n\tthumb = this.thumbnail;\n\tif ( thumb && thumb.width ) {\n\t\tthis.thumbnail.isLandscape = thumb.width > thumb.height;\n\t}\n\tthis.wikidataDescription = options.wikidataDescription;\n}\n\nmfExtend( Page, View, {\n\t/**\n\t * @memberof Page\n\t * @instance\n\t * @mixes View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {number} defaults.id Page ID. The default value of 0 represents a\n\t * new or missing page. Be sure to override it to avoid side effects.\n\t * @property {string} defaults.title Title of the page. It includes prefix where needed and\n\t * is human readable, e.g. Talk:The man who lived.\n\t * @property {string} defaults.displayTitle HTML title of the page for display. Falls back\n\t * to defaults.title (escaped) if no value is provided. Must be safe HTML!\n\t * @property {number} defaults.namespaceNumber the number of the\n\t * namespace the page belongs to\n\t * @property {Object} defaults.protection List of permissions as returned by API,\n\t * e.g. [{ edit: ['*'] }]\n\t * @property {Array} defaults.sections Array of {Section} objects.\n\t * @property {boolean} defaults.isMainPage Whether the page is the Main Page.\n\t * @property {boolean} defaults.isMissing Whether the page exists in the wiki.\n\t * @property {Object} defaults.thumbnail thumbnail definition corresponding to page image\n\t * @property {boolean} defaults.thumbnail.isLandscape whether the image is in\n\t * landscape format\n\t * @property {number} defaults.thumbnail.width of image in pixels.\n\t * @property {number} defaults.thumbnail.height of image in pixels.\n\t * @property {string} defaults.thumbnail.source url for image\n\t */\n\tdefaults: {\n\t\tid: 0,\n\t\ttitle: '',\n\t\tdisplayTitle: '',\n\t\tnamespaceNumber: 0,\n\t\tprotection: {\n\t\t\tedit: [ '*' ]\n\t\t},\n\t\tsections: [],\n\t\tisMissing: false,\n\t\tisMainPage: false,\n\t\turl: undefined,\n\t\tthumbnail: {\n\t\t\tisLandscape: undefined,\n\t\t\tsource: undefined,\n\t\t\twidth: undefined,\n\t\t\theight: undefined\n\t\t}\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof Page\n\t * @instance\n\t */\n\tisBorderBox: false,\n\t/**\n\t * Retrieve the title that should be displayed to the user\n\t * @memberof Page\n\t * @instance\n\t * @return {string} HTML\n\t */\n\tgetDisplayTitle: function () {\n\t\treturn this.options.displayTitle || HTML.escape( this.options.title );\n\t},\n\t/**\n\t * Determine if current page is in a specified namespace\n\t * @memberof Page\n\t * @instance\n\t * @param {string} namespace Name of namespace\n\t * @return {boolean}\n\t */\n\tinNamespace: function ( namespace ) {\n\t\treturn this.options.namespaceNumber === mw.config.get( 'wgNamespaceIds' )[namespace];\n\t},\n\n\t/**\n\t * Find the heading in the page.\n\t * This has the benefit of excluding any additional h2s and h3s that may\n\t * have been added programatically.\n\t * @method\n\t * @param {number} sectionIndex as defined by the PHP parser.\n\t * It should correspond to the section id\n\t * used in the edit link for the section.\n\t * Note, confusingly, this is different from section \"ID\" which is\n\t * used in methods\n\t * @return {jQuery.Object}\n\t */\n\tfindSectionHeadingByIndex: function ( sectionIndex ) {\n\t\tif ( sectionIndex < 1 ) {\n\t\t\t// negative indexes will search from the end, which is behaviour we do not want.\n\t\t\t// return an empty set when this happens.\n\t\t\treturn this.$();\n\t\t} else {\n\t\t\treturn this.$( HEADING_SELECTOR )\n\t\t\t\t// Headings must strictly be a child element of a section element\n\t\t\t\t// or the parser-output.\n\t\t\t\t// Not an ancestor!\n\t\t\t\t.filter( '.mw-parser-output > *, [class^=\"mf-section-\"] > *' ).eq( sectionIndex - 1 );\n\t\t}\n\t},\n\t/**\n\t * Finds all child elements that match the selector in a given section or subsection.\n\t * Returns any direct child elements that match the selector,\n\t * (i.e. searches only one level deep)\n\t * as well as any elements that match the selector within those children.\n\t * If the Page has no headings (e.g. a stub),\n\t * then the search will target all nodes within the page.\n\t *\n\t * This code should work on desktop (PHP parser HTML)\n\t * as well as mobile formatted HTML (PHP parser + MobileFormatter)\n\t * @method\n\t * @param {number} sectionIndex as defined by the PHP parser. It should correspond to\n\t * the section id used in the edit link for the section.\n\t * Note, confusingly, this is different from section \"ID\" which is\n\t * used in methods\n\t * @param {string} selector to match\n\t * @return {jQuery.Object}\n\t */\n\tfindChildInSectionLead: function ( sectionIndex, selector ) {\n\t\tvar $heading, $nextHeading, $container, $lead,\n\t\t\theadingSelector = HEADING_SELECTOR;\n\n\t\tfunction withNestedChildren( $matchingNodes ) {\n\t\t\treturn $matchingNodes.find( selector ).addBack();\n\t\t}\n\n\t\tif ( sectionIndex === 0 ) {\n\t\t\t// lead is easy\n\t\t\t$lead = this.getLeadSectionElement();\n\t\t\tif ( $lead && $lead.length ) {\n\t\t\t\treturn withNestedChildren( $lead.children( selector ) );\n\t\t\t} else {\n\t\t\t\t$heading = this.findSectionHeadingByIndex( 1 );\n\t\t\t\treturn $heading.length ? withNestedChildren( $heading.prevAll( selector ) ) :\n\t\t\t\t\t// this page is a stub so search entire page\n\t\t\t\t\tthis.$( selector );\n\t\t\t}\n\t\t}\n\n\t\t// find heading associated with the section by looking at its\n\t\t// index position in the article\n\t\t// section ids relate to the element position in the page and the first heading\n\t\t// lead has been dealt with above, so first heading corresponds to section 1,\n\t\t// the first heading in the article.\n\t\t$heading = this.findSectionHeadingByIndex( sectionIndex );\n\n\t\t// If section-heading is present on the heading,\n\t\t// then we know the page has been MobileFormatted\n\t\t// and that this is a wrapped section\n\t\tif ( $heading.hasClass( 'section-heading' ) ) {\n\t\t\t// get content of section\n\t\t\t$container = $heading.next();\n\t\t\t// inside section find the first heading\n\t\t\t$nextHeading = $container.find( headingSelector ).eq( 0 );\n\t\t\treturn $nextHeading.length ?\n\t\t\t\t// find all amboxes before the next heading\n\t\t\t\twithNestedChildren( $nextHeading.prevAll( selector ) ) :\n\t\t\t\t// There is no subheadings inside\n\t\t\t\t// Grab all issues in section\n\t\t\t\twithNestedChildren( $container.children( selector ) );\n\t\t} else {\n\t\t\t// the heading relates to a subsection (or unwrapped desktop section),\n\t\t\t// so grab elements between this and the next one\n\t\t\t$nextHeading = $heading.eq( 0 ).nextAll( headingSelector ).eq( 0 );\n\t\t\treturn $heading.nextUntil( $nextHeading, selector );\n\t\t}\n\t},\n\n\t/**\n\t * Get the lead section of the page view.\n\t * @memberof Page\n\t * @instance\n\t * @return {jQuery.Object|null}\n\t */\n\tgetLeadSectionElement: function () {\n\t\t/*\n\t\t * The page is formatted as follows:\n\t\t * <div id=\"bodyContent\">\n\t\t * <!-- content of the page.. -->\n\t\t * <div id=\"mw-content-text\">\n\t\t * <div class=\"mf-section-0\">lead section</div>\n\t\t * <h2></h2>\n\t\t * <div class=\"mf-section-1\">second section</div>\n\t\t * </div>\n\t\t * </div>\n\t\t */\n\t\tif ( this.$( '.mf-section-0' ).length ) {\n\t\t\treturn this.$( '.mf-section-0' );\n\t\t}\n\t\t// no lead section found\n\t\treturn null;\n\t},\n\n\t/**\n\t * Determines if content model is wikitext\n\t * @memberof Page\n\t * @instance\n\t * @return {boolean}\n\t */\n\tisWikiText: function () {\n\t\treturn mw.config.get( 'wgPageContentModel' ) === 'wikitext';\n\t},\n\n\t/**\n\t * Checks whether the current page is the main page\n\t * @memberof Page\n\t * @instance\n\t * @return {boolean}\n\t */\n\tisMainPage: function () {\n\t\treturn this.options.isMainPage;\n\t},\n\t/**\n\t * Checks whether the current page is watched\n\t * @memberof Page\n\t * @instance\n\t * @return {boolean}\n\t */\n\tisWatched: function () {\n\t\treturn this.options.isWatched;\n\t},\n\n\t/**\n\t * Return the latest revision id for this page\n\t * @memberof Page\n\t * @instance\n\t * @return {number}\n\t */\n\tgetRevisionId: function () {\n\t\treturn this.options.revId;\n\t},\n\n\t/**\n\t * Return prefixed page title\n\t * @memberof Page\n\t * @instance\n\t * @return {string}\n\t */\n\tgetTitle: function () {\n\t\treturn this.options.title;\n\t},\n\n\t/**\n\t * Return page id\n\t * @memberof Page\n\t * @instance\n\t * @return {number}\n\t */\n\tgetId: function () {\n\t\treturn this.options.id;\n\t},\n\n\t/**\n\t * return namespace id\n\t * @memberof Page\n\t * @instance\n\t * @return {number} namespace Number\n\t */\n\tgetNamespaceId: function () {\n\t\tvar nsId,\n\t\t\targs = this.options.title.split( ':' );\n\n\t\tif ( args[1] ) {\n\t\t\tnsId = mw.config.get( 'wgNamespaceIds' )[ args[0].toLowerCase().replace( ' ', '_' ) ] || 0;\n\t\t} else {\n\t\t\tnsId = 0;\n\t\t}\n\t\treturn nsId;\n\t},\n\n\t/**\n\t * Determines if current page is a talk page\n\t * @memberof Page\n\t * @instance\n\t * @return {boolean} Whether the page is a talk page or not\n\t */\n\tisTalkPage: function () {\n\t\tvar ns = this.getNamespaceId();\n\t\t// all talk pages are odd Numbers (except the case of special pages)\n\t\treturn ns > 0 && ns % 2 === 1;\n\t},\n\n\t/**\n\t * @inheritdoc\n\t * @memberof Page\n\t * @instance\n\t */\n\tpreRender: function () {\n\t\tthis.sections = [];\n\t\tthis._sectionLookup = {};\n\t\tthis.title = this.options.title;\n\n\t\tthis.options.sections.forEach( function ( sectionData ) {\n\t\t\tvar section = new Section( sectionData );\n\t\t\tthis.sections.push( section );\n\t\t\tthis._sectionLookup[section.id] = section;\n\t\t}.bind( this ) );\n\t},\n\n\t/**\n\t * Return all the thumbnails in the article.\n\t * Images which have a class or link container (.image|.thumbimage)\n\t * that matches one of the items of the constant BLACKLISTED_THUMBNAIL_CLASS_SELECTORS\n\t * will be excluded.\n\t * A thumbnail nested inside one of these classes will still be returned.\n\t * e.g. `<div class=\"noviewer\"><a class=\"image\"><img></a></div>` is not a valid thumbnail\n\t * `<a class=\"image noviewer\"><img></a>` is not a valid thumbnail\n\t * `<a class=\"image\"><img class=\"noviewer\"></a>` is not a valid thumbnail\n\t * @memberof Page\n\t * @instance\n\t * @return {Thumbnail[]}\n\t */\n\tgetThumbnails: function () {\n\t\tvar $thumbs,\n\t\t\t$el = this.$el,\n\t\t\tblacklistSelector = '.' + BLACKLISTED_THUMBNAIL_CLASS_SELECTORS.join( ',.' ),\n\t\t\tthumbs = [];\n\n\t\tif ( !this._thumbs ) {\n\t\t\t$thumbs = $el.find( 'a.image, a.thumbimage' )\n\t\t\t\t.not( blacklistSelector );\n\n\t\t\t$thumbs.each( function () {\n\t\t\t\tvar $a = $el.find( this ),\n\t\t\t\t\t$lazyImage = $a.find( '.lazy-image-placeholder' ),\n\t\t\t\t\t// Parents need to be checked as well.\n\t\t\t\t\tvalid = $a.parents( blacklistSelector ).length === 0 &&\n\t\t\t\t\t\t$a.find( blacklistSelector ).length === 0,\n\t\t\t\t\tlegacyMatch = $a.attr( 'href' ).match( /title=([^/&]+)/ ),\n\t\t\t\t\tmatch = $a.attr( 'href' ).match( /[^/]+$/ );\n\n\t\t\t\t// filter out invalid lazy loaded images if so far image is valid\n\t\t\t\tif ( $lazyImage.length && valid ) {\n\t\t\t\t\t// if the regex matches it means the image has one of the classes\n\t\t\t\t\t// thus we must invert the result\n\t\t\t\t\tvalid = !new RegExp( '\\\\b(' + BLACKLISTED_THUMBNAIL_CLASS_SELECTORS.join( '|' ) + ')\\\\b' )\n\t\t\t\t\t\t.test( $lazyImage.data( 'class' ) );\n\t\t\t\t}\n\n\t\t\t\tif ( valid && ( legacyMatch || match ) ) {\n\t\t\t\t\tthumbs.push(\n\t\t\t\t\t\tnew Thumbnail( {\n\t\t\t\t\t\t\tel: $a,\n\t\t\t\t\t\t\tfilename: decodeURIComponent(\n\t\t\t\t\t\t\t\tlegacyMatch ? legacyMatch[1] : match[0]\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t} )\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} );\n\t\t\tthis._thumbs = thumbs;\n\t\t}\n\t\treturn this._thumbs;\n\t},\n\n\t/**\n\t * FIXME: Change function signature to take the anchor of the heading\n\t * @memberof Page\n\t * @instance\n\t * @param {string} id of the section as defined by MobileFormatter.\n\t * Note, that currently, this is different from\n\t * the PHP parser in that it relates to top-level sections.\n\t * For example, mf-section-1 would relate to section 1. See FIXME.\n\t * @return {Section}\n\t */\n\tgetSection: function ( id ) {\n\t\treturn this._sectionLookup[ id ];\n\t},\n\n\t/**\n\t * Obtain the list of high level (and grouped) sections.\n\t * Note that this list will not include subsections.\n\t * @memberof Page\n\t * @instance\n\t * @return {Array} of Section instances\n\t */\n\tgetSections: function () {\n\t\treturn this.sections;\n\t},\n\n\t/**\n\t * Returns a jQuery object representing all redlinks on the page.\n\t * @memberof Page\n\t * @instance\n\t * @return {jQuery.Object}\n\t */\n\tgetRedLinks: function () {\n\t\treturn this.$( '.new' );\n\t}\n} );\n\n/**\n * Create a Page object from an API response.\n *\n * @memberof Page\n * @param {Object} resp as representing a page in the API\n * @return {Page}\n */\nPage.newFromJSON = function ( resp ) {\n\tvar revision, displayTitle,\n\t\tthumb = resp.thumbnail,\n\t\tpageprops = resp.pageprops || {\n\t\t\tdisplaytitle: HTML.escape( resp.title )\n\t\t},\n\t\tterms = resp.terms;\n\n\tif ( pageprops || terms ) {\n\t\t// The label is either the display title or the label pageprop\n\t\t// (the latter used by Wikidata)\n\t\t// Long term we want to consolidate these.\n\t\t// Note that pageprops.displaytitle is HTML, while\n\t\t// terms.label[0] is plain text.\n\t\tdisplayTitle = terms && terms.label ?\n\t\t\tHTML.escape( terms.label[0] ) : pageprops.displaytitle;\n\t}\n\t// Add Wikidata descriptions if available (T101719)\n\tresp.wikidataDescription = resp.description || undefined;\n\n\tif ( thumb ) {\n\t\tresp.thumbnail.isLandscape = thumb.width > thumb.height;\n\t}\n\n\t// page may or may not exist.\n\tif ( resp.revisions && resp.revisions[0] ) {\n\t\trevision = resp.revisions[0];\n\t\tresp.lastModified = time.getLastModifiedMessage(\n\t\t\tnew Date( revision.timestamp ).getTime() / 1000,\n\t\t\trevision.user\n\t\t);\n\t}\n\n\treturn new Page(\n\t\tutil.extend( resp, {\n\t\t\tid: resp.pageid,\n\t\t\tisMissing: !!resp.missing,\n\t\t\turl: mw.util.getUrl( resp.title ),\n\t\t\tdisplayTitle: displayTitle // this is HTML!\n\t\t} )\n\t);\n};\n\n/**\n * Selector for matching headings\n *\n * @memberof Page\n */\nPage.HEADING_SELECTOR = HEADING_SELECTOR;\n\nmodule.exports = Page;\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 * @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 * @memberof time\n * @instance\n * @param {number} timestamp\n * @return {{value: number, unit: string}}\n */\nfunction getTimeAgoDelta( timestamp ) {\n\tvar currentTimestamp = Math.round( new Date().getTime() / 1000 );\n\n\treturn timeAgo( currentTimestamp - timestamp );\n}\n\n/**\n * Whether timestamp delta is less than a day old\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 * @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 * @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, if omitted\n * returns plain text string rather than html\n * @return {string}\n */\nfunction getLastModifiedMessage( ts, username, gender, historyUrl ) {\n\tvar delta, html,\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\targs.push(\n\t\thistoryUrl || '#',\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 ? mw.util.getUrl( 'User:' + username ) : ''\n\t);\n\thtml = mw.message.apply( this, args ).parse();\n\tif ( historyUrl ) {\n\t\treturn html;\n\t} else {\n\t\treturn util.parseHTML( '<div>' ).html( html ).text();\n\t}\n}\n\n/**\n * Return a message relating to the registration date of the user\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","var\n\tmfExtend = require( './mfExtend' ),\n\tView = require( './View' );\n\n/**\n * A wrapper for creating an icon.\n * @class Icon\n * @extends View\n *\n * @param {Object} options Configuration options\n */\nfunction Icon( options ) {\n\tif ( options.hasText ) {\n\t\toptions.modifier = 'mw-ui-icon-before';\n\t}\n\tif ( options.href ) {\n\t\toptions.tagName = 'a';\n\t}\n\tView.call( this, options );\n}\n\nmfExtend( Icon, View, {\n\t/**\n\t * @inheritdoc\n\t * @memberof Icon\n\t * @instance\n\t */\n\tpreRender: function () {\n\t\tthis.setRotationClass();\n\t},\n\t/**\n\t * Internal method that sets the correct rotation class for the icon\n\t * based on the value of rotation\n\t * @memberof Icon\n\t * @instance\n\t * @private\n\t */\n\tsetRotationClass: function () {\n\t\tvar options = this.options;\n\t\tif ( options.rotation ) {\n\t\t\tswitch ( options.rotation ) {\n\t\t\t\tcase -180:\n\t\t\t\tcase 180:\n\t\t\t\t\toptions._rotationClass = 'mf-mw-ui-icon-rotate-flip';\n\t\t\t\t\tbreak;\n\t\t\t\tcase -90:\n\t\t\t\t\toptions._rotationClass = 'mf-mw-ui-icon-rotate-anti-clockwise';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 90:\n\t\t\t\t\toptions._rotationClass = 'mf-mw-ui-icon-rotate-clockwise';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0:\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error( 'Bad value for rotation given. Must be ±90, 0 or ±180.' );\n\t\t\t}\n\t\t}\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof Icon\n\t * @instance\n\t */\n\tisTemplateMode: true,\n\t/**\n\t * @memberof Icon\n\t * @instance\n\t * @mixes View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {boolean} defaults.hasText Whether the icon has text.\n\t * @property {boolean} defaults.isSmall Whether the icon should be small.\n\t * @property {string} [defaults.href] value of href attribute,\n\t * when set tagName will default to anchor tag\n\t * @property {string} defaults.tagName The name of the tag in which the icon is wrapped.\n\t * Defaults to 'a' when href option present.\n\t * @property {string} defaults.base String used as a base for generating class names.\n\t * Defaults to 'mw-ui-icon'.\n\t * @property {string} defaults.name Name of the icon.\n\t * @property {string} defaults.modifier Additional class name.\n\t * Defaults to 'mw-ui-icon-element'.\n\t * @property {string} defaults.title Tooltip text.\n\t * @property {boolean} defaults.rotation will rotate the icon by a certain number\n\t * of degrees.\n\t * Must be ±90, 0 or ±180 or will throw exception.\n\t */\n\tdefaults: {\n\t\trotation: 0,\n\t\thasText: false,\n\t\thref: undefined,\n\t\tglyphPrefix: 'mf',\n\t\ttagName: 'div',\n\t\tisSmall: false,\n\t\tbase: 'mw-ui-icon',\n\t\tname: '',\n\t\tmodifier: 'mw-ui-icon-element',\n\t\ttitle: ''\n\t},\n\t/**\n\t * Return the full class name that is required for the icon to render\n\t * @memberof Icon\n\t * @instance\n\t * @return {string}\n\t */\n\tgetClassName: function () {\n\t\treturn this.$el.attr( 'class' );\n\t},\n\t/**\n\t * Return the class that relates to the icon glyph\n\t * @memberof Icon\n\t * @instance\n\t * @return {string}\n\t */\n\tgetGlyphClassName: function () {\n\t\treturn this.options.base + '-' + this.options.glyphPrefix + '-' + this.options.name;\n\t},\n\t/**\n\t * Return the HTML representation of this view\n\t * @memberof Icon\n\t * @instance\n\t * @return {string}\n\t */\n\ttoHtmlString: function () {\n\t\treturn this.parseHTML( '<div>' ).append( this.$el ).html();\n\t},\n\ttemplate: mw.template.get( 'mobile.startup', 'icon.hogan' )\n} );\n\nmodule.exports = Icon;\n","/**\n * Class for managing modules\n *\n * A module in this context is essentially a Javascript class (not to be confused with\n * ResourceLoader modules).\n *\n * @class ModuleLoader\n * @extends OO.EventEmitter\n */\nfunction ModuleLoader() {\n\t/**\n\t * @property {Object} register of defined modules\n\t * @private\n\t */\n\tthis._register = {};\n\tOO.EventEmitter.call( this );\n}\n\nModuleLoader.prototype = {\n\t/**\n\t * Require (import) a module previously defined using define().\n\t * Searches core module registry using mw.loader.require before consulting\n\t * its own local registry. This method is deprecated, please do not use.\n\t * @memberof ModuleLoader\n\t * @instance\n\t * @param {string} id Required module id.\n\t * @return {Object} Required module, can be any JavaScript object.\n\t */\n\trequire: function ( id ) {\n\t\tvar module, args,\n\t\t\tregistry = this._register;\n\n\t\t/**\n\t\t * @return {Object} Module\n\t\t */\n\t\tfunction localRequire() {\n\t\t\tif ( !Object.hasOwnProperty.call( registry, id ) ) {\n\t\t\t\tthrow new Error( 'MobileFrontend Module not found: ' + id );\n\t\t\t}\n\t\t\treturn registry[ id ];\n\t\t}\n\t\targs = id.split( '/' );\n\t\ttry {\n\t\t\tmodule = mw.loader.require( args[0] );\n\t\t\tif ( module[ args[1] ] ) {\n\t\t\t\treturn module[ args[1] ];\n\t\t\t} else {\n\t\t\t\treturn localRequire();\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\treturn localRequire();\n\t\t}\n\t},\n\n\t/**\n\t * Define a module which can be later required (imported) using require().\n\t * @memberof ModuleLoader\n\t * @instance\n\t * @param {string} id Defined module id.\n\t * @param {Object} obj Defined module body, can be any JavaScript object.\n\t * @return {Object}\n\t */\n\tdefine: function ( id, obj ) {\n\t\tvar self = this;\n\n\t\tif ( Object.hasOwnProperty.call( this._register, id ) ) {\n\t\t\tthrow new Error( 'Module already exists: ' + id );\n\t\t}\n\t\tthis._register[ id ] = obj;\n\t\t// return an object of additionally functions to do with the registered module\n\t\treturn {\n\t\t\t/**\n\t\t\t * @see ModuleLoader#deprecate\n\t\t\t * @param {string} deprecatedId Defined module id, which is deprecated.\n\t\t\t * @ignore\n\t\t\t */\n\t\t\tdeprecate: function ( deprecatedId ) {\n\t\t\t\tself.deprecate( deprecatedId, obj, id );\n\t\t\t}\n\t\t};\n\t},\n\n\t/**\n\t * Deprecate a module and give an replacement (if there is any).\n\t * @memberof ModuleLoader\n\t * @instance\n\t * @param {string} id Defined module id, which is deprecated.\n\t * @param {Object} obj Defined module body, can be any JavaScript object.\n\t * @param {string} [replacement] Give an optional replacement for this module (which\n\t * needs to be already defined!)\n\t */\n\tdeprecate: function ( id, obj, replacement ) {\n\t\tvar msg;\n\t\tif ( replacement ) {\n\t\t\t// add an alternative for this module, if any given\n\t\t\tmsg = 'Use ' + replacement + ' instead.';\n\t\t}\n\t\t// register it as a deprecated one\n\t\tmw.log.deprecate( this._register, id, obj, msg );\n\t}\n};\n\nOO.mixinClass( ModuleLoader, OO.EventEmitter );\n\nmodule.exports = ModuleLoader;\n","var\n\tmfExtend = require( './mfExtend' ),\n\ticons = require( './icons' ),\n\tView = require( './View' );\n\n/**\n * Builds a section of a page\n * @class Section\n * @extends View\n *\n * @param {Object} options Configuration options\n */\nfunction Section( options ) {\n\tvar self = this;\n\toptions.tag = 'h' + options.level;\n\tthis.line = options.line;\n\tthis.text = options.text;\n\tthis.hasReferences = options.hasReferences || false;\n\tthis.id = options.id || null;\n\tthis.anchor = options.anchor;\n\tthis.children = [];\n\t( options.children || [] ).forEach( function ( section ) {\n\t\tself.children.push( new Section( section ) );\n\t} );\n\tView.call( this, options );\n}\n\nmfExtend( Section, View, {\n\ttemplate: mw.template.get( 'mobile.startup', 'Section.hogan' ),\n\t/**\n\t * @memberof Section\n\t * @instance\n\t * @mixes View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} defaults.text Section text.\n\t * @property {string} defaults.spinner HTML of the spinner icon.\n\t */\n\tdefaults: {\n\t\tline: undefined,\n\t\ttext: '',\n\t\tspinner: icons.spinner().toHtmlString()\n\t}\n} );\n\nmodule.exports = Section;\n","var\n\tmfExtend = require( './mfExtend' ),\n\tView = require( './View' );\n\n/**\n * Representation of a thumbnail\n *\n * @class Thumbnail\n * @extends View\n */\nfunction Thumbnail() {\n\tView.apply( this, arguments );\n}\n\nmfExtend( Thumbnail, View, {\n\t/**\n\t * @memberof Thumbnail\n\t * @instance\n\t * @mixes View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} defaults.filename uri decoded filename including File: prefix\n\t * associated with thumbnail\n\t */\n\tdefaults: {\n\t\tfilename: undefined\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof Thumbnail\n\t * @instance\n\t */\n\tisBorderBox: false,\n\t/**\n\t * @inheritdoc\n\t * @memberof Thumbnail\n\t * @instance\n\t */\n\tpostRender: function () {\n\t\tthis.options.description = this.$el.siblings( '.thumbcaption' ).text();\n\t},\n\t/**\n\t * Obtain description for thumbnail\n\t * @memberof Thumbnail\n\t * @instance\n\t * @return {string}\n\t */\n\tgetDescription: function () {\n\t\treturn this.options.description;\n\t},\n\t/**\n\t * Return the page title for the thumbnail\n\t * @memberof Thumbnail\n\t * @instance\n\t * @return {string}\n\t */\n\tgetFileName: function () {\n\t\treturn this.options.filename;\n\t}\n} );\n\nmodule.exports = Thumbnail;\n","var ModuleLoader = require( './modules' );\n\nmodule.exports = new ModuleLoader();\n","/* This module defines several types of cache classes to use in other\n * modules.\n * The interface, that all types use, is kept synchronous driven by current\n * usage patterns, but will need to be revisited in case usage patterns\n * suggest we need asynchronous caches.\n */\n\n/**\n * In memory cache implementation\n *\n * @class MemoryCache\n */\nfunction MemoryCache() {\n\tthis._cache = {};\n}\n\n/**\n * Retrieve a cached value from a key\n * @memberof MemoryCache\n * @instance\n * @param {string} key\n * @return {Mixed}\n */\nMemoryCache.prototype.get = function ( key ) {\n\treturn this._cache[ key ];\n};\n\n/**\n * Cache a value by key\n * @memberof MemoryCache\n * @instance\n * @param {string} key\n * @param {Mixed} value\n */\nMemoryCache.prototype.set = function ( key, value ) {\n\tthis._cache[ key ] = value;\n};\n\n/**\n * Null object cache implementation\n *\n * @class NoCache\n */\nfunction NoCache() { }\n\n/**\n * NoOp\n * @memberof NoCache\n * @instance\n */\nNoCache.prototype.get = function () { };\n\n/**\n * NoOp\n * @memberof NoCache\n * @instance\n */\nNoCache.prototype.set = function () { };\n\nmodule.exports = {\n\tMemoryCache: MemoryCache,\n\tNoCache: NoCache\n};\n","var\n\tutil = require( './util' ),\n\tmfExtend = require( './mfExtend' );\n\n/**\n * Manages opening and closing overlays when the URL hash changes to one\n * of the registered values (see OverlayManager.add()).\n *\n * This allows overlays to function like real pages, with similar browser back/forward\n * and refresh behavior.\n *\n * @class OverlayManager\n * @param {Router} router\n */\nfunction OverlayManager( router ) {\n\trouter.on( 'route', this._checkRoute.bind( this ) );\n\tthis.router = router;\n\t// use an object instead of an array for entries so that we don't\n\t// duplicate entries that already exist\n\tthis.entries = {};\n\t// stack of all the open overlays, stack[0] is the latest one\n\tthis.stack = [];\n\tthis.hideCurrent = true;\n}\n\nmfExtend( OverlayManager, {\n\t/**\n\t * Don't try to hide the active overlay on a route change event triggered\n\t * by hiding another overlay.\n\t * Called when hiding an overlay.\n\t * @memberof OverlayManager\n\t * @instance\n\t * @private\n\t */\n\t_onHideOverlay: function () {\n\t\tthis.hideCurrent = false;\n\n\t\tthis.router.back();\n\t},\n\n\t/**\n\t * Show the overlay and bind the '_om_hide' event to _onHideOverlay.\n\t * @memberof OverlayManager\n\t * @instance\n\t * @private\n\t * @param {Overlay} overlay to show\n\t */\n\t_showOverlay: function ( overlay ) {\n\t\t// if hidden using overlay (not hardware) button, update the state\n\t\toverlay.once( '_om_hide', this._onHideOverlay.bind( this ) );\n\n\t\toverlay.show();\n\t},\n\n\t/**\n\t * Hide overlay\n\t * @memberof OverlayManager\n\t * @instance\n\t * @private\n\t * @param {Overlay} overlay to hide\n\t * @return {boolean} Whether the overlay has been hidden\n\t */\n\t_hideOverlay: function ( overlay ) {\n\t\tvar result;\n\n\t\t// remove the callback for updating state when overlay closed using\n\t\t// overlay close button\n\t\toverlay.off( '_om_hide' );\n\n\t\tresult = overlay.hide( this.stack.length > 1 );\n\n\t\t// if closing prevented, reattach the callback\n\t\tif ( !result ) {\n\t\t\toverlay.once( '_om_hide', this._onHideOverlay.bind( this ) );\n\t\t}\n\n\t\treturn result;\n\t},\n\n\t/**\n\t * Show match's overlay if match is not null.\n\t * @memberof OverlayManager\n\t * @instance\n\t * @private\n\t * @param {Object|null} match Object with factory function's result. null if no match.\n\t */\n\t_processMatch: function ( match ) {\n\t\tvar factoryResult,\n\t\t\tself = this;\n\n\t\t/**\n\t\t * Attach an event to the overlays hide event\n\t\t * @param {Overlay} overlay\n\t\t */\n\t\tfunction attachHideEvent( overlay ) {\n\t\t\toverlay.on( 'hide', function () {\n\t\t\t\toverlay.emit( '_om_hide' );\n\t\t\t} );\n\t\t}\n\n\t\tif ( match ) {\n\t\t\tif ( match.overlay ) {\n\t\t\t\t// if the match is an overlay that was previously opened, reuse it\n\t\t\t\tself._showOverlay( match.overlay );\n\t\t\t} else {\n\t\t\t\t// else create an overlay using the factory function result (either\n\t\t\t\t// a promise or an overlay)\n\t\t\t\tfactoryResult = match.factoryResult;\n\t\t\t\t// http://stackoverflow.com/a/13075985/365238\n\t\t\t\tif ( typeof factoryResult.promise === 'function' ) {\n\t\t\t\t\tfactoryResult.then( function ( overlay ) {\n\t\t\t\t\t\tmatch.overlay = overlay;\n\t\t\t\t\t\tattachHideEvent( overlay );\n\t\t\t\t\t\tself._showOverlay( overlay );\n\t\t\t\t\t} );\n\t\t\t\t} else {\n\t\t\t\t\tmatch.overlay = factoryResult;\n\t\t\t\t\tattachHideEvent( match.overlay );\n\t\t\t\t\tself._showOverlay( factoryResult );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * A callback for Router's `route` event.\n\t * @memberof OverlayManager\n\t * @instance\n\t * @private\n\t * @param {jQuery.Event} ev Event object.\n\t */\n\t_checkRoute: function ( ev ) {\n\t\tvar\n\t\t\tcurrent = this.stack[0],\n\t\t\tmatch;\n\n\t\t// When entering an overlay for the first time,\n\t\t// the manager should remember the user's scroll position\n\t\t// overlays always open at top of page\n\t\t// and we'll want to restore it later.\n\t\t// This should happen before the call to _matchRoute which will \"show\" the overlay.\n\t\t// The Overlay has similar logic for overlays that are not managed via the overlay.\n\t\tif ( !current ) {\n\t\t\tthis.scrollTop = window.pageYOffset;\n\t\t}\n\n\t\tmatch = Object.keys( this.entries ).reduce( function ( m, id ) {\n\t\t\treturn m || this._matchRoute( ev.path, this.entries[ id ] );\n\t\t}.bind( this ), null );\n\n\t\t// if there is an overlay in the stack and it's opened, try to close it\n\t\tif (\n\t\t\tcurrent &&\n\t\t\tcurrent.overlay !== undefined &&\n\t\t\tthis.hideCurrent &&\n\t\t\t!this._hideOverlay( current.overlay )\n\t\t) {\n\t\t\t// if hide prevented, prevent route change event\n\t\t\tev.preventDefault();\n\t\t} else if ( !match ) {\n\t\t\t// if hidden and no new matches, reset the stack\n\t\t\tthis.stack = [];\n\t\t\t// restore the scroll position.\n\t\t\twindow.scrollTo( window.pageXOffset, this.scrollTop );\n\t\t}\n\n\t\tthis.hideCurrent = true;\n\t\tthis._processMatch( match );\n\t},\n\n\t/**\n\t * Check if a given path matches one of the entries.\n\t * @memberof OverlayManager\n\t * @instance\n\t * @private\n\t * @param {string} path Path (hash) to check.\n\t * @param {Object} entry Entry object created in OverlayManager#add.\n\t * @return {Object|null} Match object with factory function's result.\n\t * Returns null if no match.\n\t */\n\t_matchRoute: function ( path, entry ) {\n\t\tvar\n\t\t\tnext,\n\t\t\tmatch = path.match( entry.route ),\n\t\t\tprevious = this.stack[1],\n\t\t\tself = this;\n\n\t\t/**\n\t\t * Returns object to add to stack\n\t\t * @method\n\t\t * @ignore\n\t\t * @return {Object}\n\t\t */\n\t\tfunction getNext() {\n\t\t\treturn {\n\t\t\t\tpath: path,\n\t\t\t\tfactoryResult: entry.factory.apply( self, match.slice( 1 ) )\n\t\t\t};\n\t\t}\n\n\t\tif ( match ) {\n\t\t\t// if previous stacked overlay's path matches, assume we're going back\n\t\t\t// and reuse a previously opened overlay\n\t\t\tif ( previous && previous.path === path ) {\n\t\t\t\tif ( previous.overlay && previous.overlay.hasLoadError ) {\n\t\t\t\t\tself.stack.shift();\n\t\t\t\t\t// Loading of overlay failed so we want to replace it with a new\n\t\t\t\t\t// overlay (which will try to load successfully)\n\t\t\t\t\tself.stack[0] = getNext();\n\t\t\t\t\treturn self.stack[0];\n\t\t\t\t}\n\n\t\t\t\tself.stack.shift();\n\t\t\t\treturn previous;\n\t\t\t} else {\n\t\t\t\tnext = getNext();\n\t\t\t\tif ( this.stack[0] && next.path === this.stack[0].path ) {\n\t\t\t\t\t// current overlay path is same as path to check which means overlay\n\t\t\t\t\t// is attempting to refresh so just replace current overlay with new\n\t\t\t\t\t// overlay\n\t\t\t\t\tself.stack[0] = next;\n\t\t\t\t} else {\n\t\t\t\t\tself.stack.unshift( next );\n\t\t\t\t}\n\t\t\t\treturn next;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t},\n\n\t/**\n\t * Add an overlay that should be shown for a specific fragment identifier.\n\t *\n\t * The following code will display an overlay whenever a user visits a URL that\n\t * end with '#/hi/name'. The value of `name` will be passed to the overlay.\n\t *\n\t * @example\n\t * overlayManager.add( /\\/hi\\/(.*)/, function ( name ) {\n\t * var factoryResult = $.Deferred();\n\t *\n\t * mw.using( 'mobile.HiOverlay', function () {\n\t * var HiOverlay = M.require( 'HiOverlay' );\n\t * factoryResult.resolve( new HiOverlay( { name: name } ) );\n\t * } );\n\t *\n\t * return factoryResult;\n\t * } );\n\t *\n\t * @memberof OverlayManager\n\t * @instance\n\t * @param {RegExp} route route regular expression, optionally with parameters.\n\t * @param {Function} factory a function returning an overlay or a $.Deferred\n\t * which resolves to an overlay.\n\t */\n\tadd: function ( route, factory ) {\n\t\tvar self = this,\n\t\t\tentry = {\n\t\t\t\troute: route,\n\t\t\t\tfactory: factory\n\t\t\t};\n\n\t\tthis.entries[route] = entry;\n\t\t// Check if overlay should be shown for the current path.\n\t\t// The DOM must fully load before we can show the overlay because Overlay relies on it.\n\t\tutil.docReady( function () {\n\t\t\tself._processMatch( self._matchRoute( self.router.getPath(), entry ) );\n\t\t} );\n\t},\n\n\t/**\n\t * Replace the currently displayed overlay with a new overlay without changing the\n\t * URL. This is useful for when you want to switch overlays, but don't want to\n\t * change the back button or close box behavior.\n\t *\n\t * @memberof OverlayManager\n\t * @instance\n\t * @param {Object} overlay The overlay to display\n\t */\n\treplaceCurrent: function ( overlay ) {\n\t\tif ( this.stack.length === 0 ) {\n\t\t\tthrow new Error( 'Trying to replace OverlayManager\\'s current overlay, but stack is empty' );\n\t\t}\n\t\tthis._hideOverlay( this.stack[0].overlay );\n\t\tthis.stack[0].overlay = overlay;\n\t\tthis._showOverlay( overlay );\n\t}\n} );\n\nmodule.exports = OverlayManager;\n","var\n\tbrowser = require( './Browser' ).getSingleton(),\n\tView = require( './View' ),\n\tutil = require( './util' ),\n\tPage = require( './Page' ),\n\tDeferred = util.Deferred,\n\twhen = util.when,\n\ticons = require( './icons' ),\n\tviewport = mw.viewport,\n\tspinner = icons.spinner(),\n\tmfExtend = require( './mfExtend' ),\n\tM = require( './moduleSingleton' );\n\n/**\n * Get the id of the section $el belongs to.\n * @param {jQuery.Object} $el\n * @return {string|null} either the anchor (id attribute of the section heading\n * or null if none found)\n */\nfunction getSectionId( $el ) {\n\tvar id,\n\t\thSelector = Page.HEADING_SELECTOR,\n\t\t$parent = $el.parent(),\n\t\t// e.g. matches Subheading in\n\t\t// <h2>H</h2><div><h3 id=\"subheading\">Subh</h3><a class=\"element\"></a></div>\n\t\t$heading = $el.prevAll( hSelector ).eq( 0 );\n\n\tif ( $heading.length ) {\n\t\tid = $heading.find( '.mw-headline' ).attr( 'id' );\n\t\tif ( id ) {\n\t\t\treturn id;\n\t\t}\n\t}\n\tif ( $parent.length ) {\n\t\t// if we couldnt find a sibling heading, check the sibling of the parents\n\t\t// consider <div><h2 /><div><$el/></div></div>\n\t\treturn getSectionId( $parent );\n\t} else {\n\t\treturn null;\n\t}\n}\n\n/**\n * Representation of the current skin being rendered.\n *\n * @class Skin\n * @extends View\n * @uses Browser\n * @uses Page\n * @fires Skin#click\n * @fires Skin#references-loaded\n * @fires Skin#changed\n *\n * @param {Object} options Configuration options\n */\nfunction Skin( options ) {\n\tvar self = this;\n\n\tthis.page = options.page;\n\tthis.name = options.name;\n\tif ( options.mainMenu ) {\n\t\tthis.mainMenu = options.mainMenu;\n\t\tmw.log.warn( 'Skin: Use of mainMenu is deprecated.' );\n\t}\n\tView.call( this, options );\n\tthis.referencesGateway = options.referencesGateway;\n\n\tif (\n\t\tmw.config.get( 'wgMFLazyLoadImages' )\n\t) {\n\t\tutil.docReady( function () {\n\t\t\tself.setupImageLoading();\n\t\t} );\n\t}\n\n\tif ( mw.config.get( 'wgMFLazyLoadReferences' ) ) {\n\t\tM.on( 'before-section-toggled', this.lazyLoadReferences.bind( this ) );\n\t}\n}\n\nmfExtend( Skin, View, {\n\t/**\n\t * Skin contains components that we do not control\n\t * @inheritdoc\n\t * @memberof Skin\n\t * @instance\n\t */\n\tisBorderBox: false,\n\t/**\n\t * @memberof Skin\n\t * @instance\n\t * @mixes View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {Page} defaults.page page the skin is currently rendering\n\t * @property {ReferencesGateway} defaults.referencesGateway instance of references gateway\n\t */\n\tdefaults: {\n\t\tpage: undefined\n\t},\n\n\t/**\n\t * @inheritdoc\n\t * @memberof Skin\n\t * @instance\n\t */\n\tevents: {},\n\n\t/**\n\t * @inheritdoc\n\t * @memberof Skin\n\t * @instance\n\t */\n\tpostRender: function () {\n\t\tvar $el = this.$el;\n\t\tif ( browser.supportsAnimations() ) {\n\t\t\t$el.addClass( 'animations' );\n\t\t}\n\t\tif ( browser.supportsTouchEvents() ) {\n\t\t\t$el.addClass( 'touch-events' );\n\t\t}\n\t\tutil.parseHTML( '<div class=\"transparent-shield cloaked-element\">' )\n\t\t\t.appendTo( $el.find( '#mw-mf-page-center' ) );\n\t\t/**\n\t\t * Fired when appearance of skin changes.\n\t\t * @event Skin#changed\n\t\t */\n\t\tthis.emit( 'changed' );\n\n\t\t/**\n\t\t * Fired when the skin is clicked.\n\t\t * @event Skin#click\n\t\t */\n\t\tthis.$( '#mw-mf-page-center' ).on( 'click', this.emit.bind( this, 'click' ) );\n\t},\n\t/**\n\t * Get images that have not yet been loaded in the page\n\t * @memberof Skin\n\t * @instance\n\t * @param {jQuery.Object} [$container] The container that should be\n\t * searched for image placeholders. Defaults to \"#content\".\n\t * @return {Array} of unloaded image placeholders in the page\n\t */\n\tgetUnloadedImages: function ( $container ) {\n\t\t$container = $container || this.$( '#content' );\n\t\treturn $container.find( '.lazy-image-placeholder' ).toArray();\n\t},\n\t/**\n\t * Setup listeners to watch unloaded images and load them into the page\n\t * as and when they are needed.\n\t * @memberof Skin\n\t * @instance\n\t * @param {jQuery.Object} [$container] The container that should be\n\t * searched for image placeholders. Defaults to \"#content\".\n\t * @return {jQuery.Deferred} which will be resolved when the attempts to\n\t * load all images subject to loading have been completed.\n\t */\n\tsetupImageLoading: function ( $container ) {\n\t\tvar self = this,\n\t\t\toffset = util.getWindow().height() * 1.5,\n\t\t\tloadImagesList = this.loadImagesList.bind( this ),\n\t\t\timagePlaceholders = this.getUnloadedImages( $container );\n\n\t\t/**\n\t\t * Check whether an image should be loaded based on its proximity to the\n\t\t * viewport; and whether it is displayed to the user.\n\t\t * @param {jQuery.Object} $placeholder\n\t\t * @return {boolean}\n\t\t */\n\t\tfunction shouldLoadImage( $placeholder ) {\n\t\t\treturn viewport.isElementCloseToViewport( $placeholder[0], offset ) &&\n\t\t\t\t// If a placeholder is an inline element without a height attribute set\n\t\t\t\t// it will record as hidden\n\t\t\t\t// to circumvent this we also need to test the height (see T143768).\n\t\t\t\t( $placeholder.is( ':visible' ) || $placeholder.height() === 0 );\n\t\t}\n\n\t\t/**\n\t\t * Load remaining images in viewport\n\t\t * @return {jQuery.Deferred}\n\t\t */\n\t\tfunction _loadImages() {\n\t\t\tvar images = [];\n\t\t\t// Filter unloaded images to only the images that still need to be loaded\n\t\t\timagePlaceholders = util.grep( imagePlaceholders, function ( placeholder ) {\n\t\t\t\tvar $placeholder = self.$( placeholder );\n\t\t\t\t// Check length to ensure the image is still in the DOM.\n\t\t\t\tif ( $placeholder.length && shouldLoadImage( $placeholder ) ) {\n\t\t\t\t\timages.push( placeholder );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t} );\n\n\t\t\t// When no images are left unbind all events\n\t\t\tif ( !imagePlaceholders.length ) {\n\t\t\t\tM.off( 'scroll:throttled', _loadImages );\n\t\t\t\tM.off( 'resize:throttled', _loadImages );\n\t\t\t\tM.off( 'section-toggled', _loadImages );\n\t\t\t\tself.off( 'changed', _loadImages );\n\t\t\t}\n\n\t\t\t// load any remaining images.\n\t\t\treturn loadImagesList( images );\n\t\t}\n\n\t\tM.on( 'scroll:throttled', _loadImages );\n\t\tM.on( 'resize:throttled', _loadImages );\n\t\tM.on( 'section-toggled', _loadImages );\n\t\tthis.on( 'changed', _loadImages );\n\n\t\treturn _loadImages();\n\t},\n\t/**\n\t * Load an image on demand\n\t * @memberof Skin\n\t * @instance\n\t * @param {Array} [images] a list of images that have not been loaded.\n\t * If none given all will be loaded.\n\t * @return {jQuery.Deferred}\n\t */\n\tloadImagesList: function ( images ) {\n\t\tvar callbacks,\n\t\t\t$ = this.$.bind( this ),\n\t\t\tloadImage = this.loadImage.bind( this );\n\n\t\timages = images || this.getUnloadedImages();\n\t\tcallbacks = images.map( function ( placeholder ) {\n\t\t\treturn loadImage( $( placeholder ) );\n\t\t} );\n\n\t\treturn when.apply( null, callbacks );\n\t},\n\t/**\n\t * Load an image on demand\n\t * @memberof Skin\n\t * @instance\n\t * @param {jQuery.Object} $placeholder\n\t * @return {jQuery.Deferred}\n\t */\n\tloadImage: function ( $placeholder ) {\n\t\tvar\n\t\t\td = Deferred(),\n\t\t\twidth = $placeholder.attr( 'data-width' ),\n\t\t\theight = $placeholder.attr( 'data-height' ),\n\t\t\t// document must be passed to ensure image will start downloading\n\t\t\t$downloadingImage = util.parseHTML( '<img>', this.$el[0].ownerDocument );\n\n\t\t// When the image has loaded\n\t\t$downloadingImage.on( 'load', function () {\n\t\t\t// Swap the HTML inside the placeholder (to keep the layout and\n\t\t\t// dimensions the same and not trigger layouts\n\t\t\t$downloadingImage.addClass( 'image-lazy-loaded' );\n\t\t\t$placeholder.replaceWith( $downloadingImage );\n\t\t\td.resolve();\n\t\t} );\n\t\t$downloadingImage.on( 'error', function () {\n\t\t\td.reject();\n\t\t} );\n\n\t\t// Trigger image download after binding the load handler\n\t\t$downloadingImage.attr( {\n\t\t\t'class': $placeholder.attr( 'data-class' ),\n\t\t\twidth: width,\n\t\t\theight: height,\n\t\t\tsrc: $placeholder.attr( 'data-src' ),\n\t\t\talt: $placeholder.attr( 'data-alt' ),\n\t\t\tstyle: $placeholder.attr( 'style' ),\n\t\t\tsrcset: $placeholder.attr( 'data-srcset' )\n\t\t} );\n\t\treturn d;\n\t},\n\n\t/**\n\t * Load the references section content from API if it's not already loaded.\n\t *\n\t * All references tags content will be loaded per section.\n\t * @memberof Skin\n\t * @instance\n\t * @param {Object} data Information about the section. It's in the following form:\n\t * {\n\t * @property {string} page,\n\t * @property {boolean} wasExpanded,\n\t * @property {jQuery.Object} $heading,\n\t * @property {boolean} isReferenceSection\n\t * }\n\t * @return {jQuery.Promise} rejected when not a reference section.\n\t */\n\tlazyLoadReferences: function ( data ) {\n\t\tvar $content, $spinner,\n\t\t\tgateway = this.referencesGateway,\n\t\t\tgetUnloadedImages = this.getUnloadedImages.bind( this ),\n\t\t\tloadImagesList = this.loadImagesList.bind( this ),\n\t\t\tself = this;\n\n\t\t// If the section was expanded before toggling, do not load anything as\n\t\t// section is being collapsed now.\n\t\t// Also return early if lazy loading is not required or the section is\n\t\t// not a reference section\n\t\tif (\n\t\t\tdata.wasExpanded ||\n\t\t\t!data.isReferenceSection\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t$content = data.$heading.next();\n\n\t\tfunction loadImagesAndSetData() {\n\t\t\t// lazy load images if any\n\t\t\tloadImagesList( getUnloadedImages( $content ) );\n\t\t\t// Do not attempt further loading even if we're unable to load this time.\n\t\t\t$content.data( 'are-references-loaded', 1 );\n\t\t}\n\n\t\tif ( !$content.data( 'are-references-loaded' ) ) {\n\t\t\t$content.children().addClass( 'hidden' );\n\t\t\t$spinner = spinner.$el.prependTo( $content );\n\n\t\t\t// First ensure we retrieve all of the possible lists\n\t\t\treturn gateway.getReferencesLists( data.page )\n\t\t\t\t.then( function () {\n\t\t\t\t\tvar lastId;\n\n\t\t\t\t\t$content.find( '.mf-lazy-references-placeholder' ).each( function () {\n\t\t\t\t\t\tvar refListIndex = 0,\n\t\t\t\t\t\t\t$placeholder = $content.find( this ),\n\t\t\t\t\t\t\t// search for id of the collapsible heading\n\t\t\t\t\t\t\tid = getSectionId( $placeholder );\n\n\t\t\t\t\t\tif ( lastId !== id ) {\n\t\t\t\t\t\t\t// If the placeholder belongs to a new section reset index\n\t\t\t\t\t\t\trefListIndex = 0;\n\t\t\t\t\t\t\tlastId = id;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// otherwise increment it\n\t\t\t\t\t\t\trefListIndex++;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( id ) {\n\t\t\t\t\t\t\tgateway.getReferencesList( data.page, id )\n\t\t\t\t\t\t\t\t.then( function ( refListElements ) {\n\t\t\t\t\t\t\t\t\t// Note if no section html is provided\n\t\t\t\t\t\t\t\t\t// no substitution will happen\n\t\t\t\t\t\t\t\t\t// so user is forced to rely on placeholder link.\n\t\t\t\t\t\t\t\t\tif ( refListElements && refListElements[refListIndex] ) {\n\t\t\t\t\t\t\t\t\t\t$placeholder.replaceWith(\n\t\t\t\t\t\t\t\t\t\t\trefListElements[refListIndex]\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t\t// Show the section now the references lists have been placed.\n\t\t\t\t\t$spinner.remove();\n\t\t\t\t\t$content.children().removeClass( 'hidden' );\n\t\t\t\t\t/**\n\t\t\t\t\t * Fired when references list is loaded into the HTML\n\t\t\t\t\t * @event references-loaded\n\t\t\t\t\t */\n\t\t\t\t\tself.emit( 'references-loaded', self.page );\n\n\t\t\t\t\tloadImagesAndSetData();\n\t\t\t\t}, function () {\n\t\t\t\t\t$spinner.remove();\n\t\t\t\t\t// unhide on a failure\n\t\t\t\t\t$content.children().removeClass( 'hidden' );\n\n\t\t\t\t\tloadImagesAndSetData();\n\t\t\t\t} );\n\t\t} else {\n\t\t\treturn Deferred().reject().promise();\n\t\t}\n\t},\n\n\t/**\n\t * Returns the appropriate license message including links/name to\n\t * terms of use (if any) and license page\n\t * @memberof Skin\n\t * @instance\n\t * @return {string}\n\t */\n\tgetLicenseMsg: function () {\n\t\tvar licenseMsg,\n\t\t\tmfLicense = mw.config.get( 'wgMFLicense' ),\n\t\t\tlicensePlural = mw.language.convertNumber( mfLicense.plural );\n\n\t\tif ( mfLicense.link ) {\n\t\t\tif ( this.$( '#footer-places-terms-use' ).length > 0 ) {\n\t\t\t\tlicenseMsg = mw.msg(\n\t\t\t\t\t'mobile-frontend-editor-licensing-with-terms',\n\t\t\t\t\tmw.message(\n\t\t\t\t\t\t'mobile-frontend-editor-terms-link',\n\t\t\t\t\t\tthis.$( '#footer-places-terms-use a' ).attr( 'href' )\n\t\t\t\t\t).parse(),\n\t\t\t\t\tmfLicense.link,\n\t\t\t\t\tlicensePlural\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tlicenseMsg = mw.msg(\n\t\t\t\t\t'mobile-frontend-editor-licensing',\n\t\t\t\t\tmfLicense.link,\n\t\t\t\t\tlicensePlural\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn licenseMsg;\n\t}\n} );\n\nSkin.getSectionId = getSectionId;\n\nmodule.exports = Skin;\n","var\n\tmfExtend = require( './mfExtend' ),\n\tView = require( './View' );\n\n/**\n * A wrapper for creating a button.\n * @class Button\n * @extends View\n *\n * @param {Object} options Configuration options\n */\nfunction Button( options ) {\n\tif ( options.href ) {\n\t\toptions.tagName = 'a';\n\t}\n\tView.call( this, options );\n}\n\nmfExtend( Button, View, {\n\t/**\n\t * @inheritdoc\n\t * @memberof Button\n\t * @instance\n\t */\n\tisTemplateMode: true,\n\t/**\n\t * @memberof Button\n\t * @instance\n\t * @mixes View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} defaults.tagName The name of the tag in which the button is wrapped.\n\t * @property {boolean} defaults.block is stacked button\n\t * @property {boolean} defaults.progressive is progressive action\n\t * This option is deprecated. Please use `progressive`.\n\t * @property {boolean} defaults.quiet is quiet button\n\t * @property {boolean} defaults.destructive is destructive action\n\t * @property {string} defaults.additionalClassNames Additional class name(s).\n\t * @property {string} defaults.href url\n\t * @property {string} defaults.label of button\n\t */\n\tdefaults: {\n\t\ttagName: 'a',\n\t\tblock: undefined,\n\t\tprogressive: undefined,\n\t\tdestructive: undefined,\n\t\tquiet: undefined,\n\t\tadditionalClassNames: '',\n\t\thref: undefined,\n\t\tlabel: undefined\n\t},\n\t/**\n\t * @memberof Button\n\t * @instance\n\t */\n\ttemplate: mw.template.get( 'mobile.startup', 'button.hogan' )\n} );\n\nmodule.exports = Button;\n","var\n\tView = require( './View' ),\n\tmfExtend = require( './mfExtend' );\n\n/**\n * A wrapper for creating an anchor.\n * @class Anchor\n * @extends View\n */\nfunction Anchor() {\n\tView.apply( this, arguments );\n}\n\nmfExtend( Anchor, View, {\n\t/**\n\t * @inheritdoc\n\t * @memberof Anchor\n\t * @instance\n\t */\n\tisTemplateMode: true,\n\t/**\n\t * @memberof Anchor\n\t * @instance\n\t * @mixes View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {boolean} defaults.progressive is progressive action\n\t * @property {boolean} defaults.destructive is destructive action\n\t * @property {string} defaults.additionalClassNames Additional class name(s).\n\t * @property {string} defaults.href url\n\t * @property {string} defaults.label of anchor\n\t */\n\tdefaults: {\n\t\tprogressive: undefined,\n\t\tdestructive: undefined,\n\t\tadditionalClassNames: '',\n\t\thref: undefined,\n\t\tlabel: undefined\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof Anchor\n\t * @instance\n\t */\n\ttemplate: mw.template.get( 'mobile.startup', 'anchor.hogan' )\n} );\n\nmodule.exports = Anchor;\n","var\n\tView = require( './View' ),\n\tIcon = require( './Icon' ),\n\tButton = require( './Button' ),\n\tAnchor = require( './Anchor' ),\n\ticons = require( './icons' ),\n\tutil = require( './util' ),\n\tbrowser = require( './Browser' ).getSingleton(),\n\tmfExtend = require( './mfExtend' );\n\n/**\n * Mobile modal window\n * @class Overlay\n * @extends View\n * @uses Icon\n * @uses Button\n * @fires Overlay#Overlay-exit\n * @fires Overlay#hide\n */\nfunction Overlay() {\n\tthis.isIos = browser.isIos();\n\tthis.useVirtualKeyboardHack = browser.isIos( 4 ) || browser.isIos( 5 );\n\t// Set to true when overlay has failed to load\n\tthis.hasLoadError = false;\n\tView.apply( this, arguments );\n}\n\nmfExtend( Overlay, View, {\n\t/**\n\t * Identify whether the element contains position fixed elements\n\t * @memberof Overlay\n\t * @instance\n\t * @property {boolean}\n\t */\n\thasFixedHeader: true,\n\t/**\n\t * Is overlay fullscreen\n\t * @memberof Overlay\n\t * @instance\n\t * @property {boolean}\n\t */\n\tfullScreen: true,\n\n\t/**\n\t * True if this.hide() should be invoked before firing the Overlay-exit\n\t * event\n\t * @memberof Overlay\n\t * @instance\n\t * @property {boolean}\n\t */\n\thideOnExitClick: true,\n\n\t/**\n\t * use '#mw-mf-viewport' rather than 'body' - for some reasons this has\n\t * odd consequences on Opera Mobile (see bug 52361)\n\t * @memberof Overlay\n\t * @instance\n\t * @property {string|jQuery.Object}\n\t */\n\tappendToElement: '#mw-mf-viewport',\n\n\t/**\n\t * Default class name\n\t * @memberof Overlay\n\t * @instance\n\t * @property {string}\n\t */\n\tclassName: 'overlay',\n\ttemplatePartials: {\n\t\theader: mw.template.get( 'mobile.startup', 'header.hogan' ),\n\t\tanchor: Anchor.prototype.template,\n\t\tbutton: Button.prototype.template\n\t},\n\ttemplate: mw.template.get( 'mobile.startup', 'Overlay.hogan' ),\n\t/**\n\t * @memberof Overlay\n\t * @instance\n\t * @mixes View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} defaults.saveMessage Caption for save button on edit form.\n\t * @property {string} defaults.cancelButton HTML of the cancel button.\n\t * @property {string} defaults.backButton HTML of the back button.\n\t * @property {string} defaults.headerButtonsListClassName A comma separated string of class\n\t * names of the wrapper of the header buttons.\n\t * @property {boolean} defaults.headerChrome Whether the header has chrome.\n\t * @property {boolean} defaults.fixedHeader Whether the header is fixed.\n\t * @property {string} defaults.spinner HTML of the spinner icon.\n\t * @property {Object} [defaults.footerAnchor] options for an optional Anchor\n\t * that can appear in the footer\n\t */\n\tdefaults: {\n\t\tsaveMsg: mw.msg( 'mobile-frontend-editor-save' ),\n\t\tcancelButton: new Icon( {\n\t\t\ttagName: 'button',\n\t\t\tname: 'overlay-close',\n\t\t\tadditionalClassNames: 'cancel',\n\t\t\tlabel: mw.msg( 'mobile-frontend-overlay-close' )\n\t\t} ).toHtmlString(),\n\t\tbackButton: new Icon( {\n\t\t\ttagName: 'button',\n\t\t\tname: 'back',\n\t\t\tadditionalClassNames: 'back',\n\t\t\tlabel: mw.msg( 'mobile-frontend-overlay-close' )\n\t\t} ).toHtmlString(),\n\t\theaderButtonsListClassName: '',\n\t\theaderChrome: false,\n\t\tfixedHeader: true,\n\t\tspinner: icons.spinner().toHtmlString()\n\t},\n\t/**\n\t * @memberof Overlay\n\t * @instance\n\t */\n\tevents: {\n\t\t// FIXME: Remove .initial-header selector when bug 71203 resolved.\n\t\t'click .cancel, .confirm, .initial-header .back': 'onExitClick',\n\t\tclick: 'stopPropagation'\n\t},\n\t/**\n\t * Flag overlay to close on content tap\n\t * @memberof Overlay\n\t * @instance\n\t * @property {boolean}\n\t */\n\tcloseOnContentTap: false,\n\n\t/**\n\t * Shows the spinner right to the input field.\n\t * @memberof Overlay\n\t * @instance\n\t * @method\n\t */\n\tshowSpinner: function () {\n\t\tthis.$spinner.removeClass( 'hidden' );\n\t},\n\n\t/**\n\t * Hide the spinner near to the input field.\n\t * @memberof Overlay\n\t * @instance\n\t * @method\n\t */\n\thideSpinner: function () {\n\t\tthis.$spinner.addClass( 'hidden' );\n\t},\n\n\t/**\n\t * @inheritdoc\n\t * @memberof Overlay\n\t * @instance\n\t */\n\tpostRender: function () {\n\n\t\tthis.$overlayContent = this.$( '.overlay-content' );\n\t\tthis.$spinner = this.$( '.spinner' );\n\t\tif ( this.isIos ) {\n\t\t\tthis.$el.addClass( 'overlay-ios' );\n\t\t}\n\t\t// Truncate any text inside in the overlay header.\n\t\tthis.$( '.overlay-header h2 span' ).addClass( 'truncated-text' );\n\t\tthis.setupEmulatedIosOverlayScrolling();\n\t},\n\n\t/**\n\t * Setups an emulated scroll behaviour for overlays in ios.\n\t * @memberof Overlay\n\t * @instance\n\t */\n\tsetupEmulatedIosOverlayScrolling: function () {\n\t\tvar self = this;\n\t\tif ( this.isIos && this.hasFixedHeader ) {\n\t\t\tthis.$( '.overlay-content' ).on( 'touchstart', this.onTouchStart.bind( this ) )\n\t\t\t\t.on( 'touchmove', this.onTouchMove.bind( this ) );\n\t\t\t// wait for things to render before doing any calculations\n\t\t\tsetTimeout( function () {\n\t\t\t\tself._fixIosHeader( self.$( 'textarea, input' ) );\n\t\t\t}, 0 );\n\t\t}\n\t},\n\t/**\n\t * ClickBack event handler\n\t * @memberof Overlay\n\t * @instance\n\t * @param {Object} ev event object\n\t */\n\tonExitClick: function ( ev ) {\n\t\tev.preventDefault();\n\t\tev.stopPropagation();\n\t\tif ( this.hideOnExitClick ) {\n\t\t\tthis.hide();\n\t\t}\n\t\tthis.emit( Overlay.EVENT_EXIT );\n\t},\n\t/**\n\t * Event handler for touchstart, for IOS\n\t * @memberof Overlay\n\t * @instance\n\t * @param {Object} ev Event Object\n\t */\n\tonTouchStart: function ( ev ) {\n\t\tthis.startY = ev.originalEvent.touches[0].pageY;\n\t},\n\t/**\n\t * Event handler for touch move, for IOS\n\t * @memberof Overlay\n\t * @instance\n\t * @param {Object} ev Event Object\n\t */\n\tonTouchMove: function ( ev ) {\n\t\tvar\n\t\t\ty = ev.originalEvent.touches[0].pageY,\n\t\t\tcontentOuterHeight = this.$overlayContent.outerHeight(),\n\t\t\tcontentLength = this.$overlayContent.prop( 'scrollHeight' ) - contentOuterHeight;\n\n\t\tev.stopPropagation();\n\t\t// prevent scrolling and bouncing outside of .overlay-content\n\t\tif (\n\t\t\t( this.$overlayContent.scrollTop() === 0 && this.startY < y ) ||\n\t\t\t( this.$overlayContent.scrollTop() === contentLength && this.startY > y )\n\t\t) {\n\t\t\tev.preventDefault();\n\t\t}\n\t},\n\t/**\n\t * Stop clicks in the overlay from propagating to the page\n\t * (prevents non-fullscreen overlays from being closed when they're tapped)\n\t * @memberof Overlay\n\t * @instance\n\t * @param {Object} ev Event Object\n\t */\n\tstopPropagation: function ( ev ) {\n\t\tev.stopPropagation();\n\t},\n\t/**\n\t * Attach overlay to current view and show it.\n\t * @memberof Overlay\n\t * @instance\n\t */\n\tshow: function () {\n\t\tvar self = this,\n\t\t\t$html = util.getDocument(),\n\t\t\t$window = util.getWindow();\n\n\t\tthis.$el.appendTo( this.appendToElement );\n\t\tthis.scrollTop = window.pageYOffset;\n\n\t\tif ( this.fullScreen ) {\n\t\t\t$html.addClass( 'overlay-enabled' );\n\t\t\t// skip the URL bar if possible\n\t\t\twindow.scrollTo( 0, 1 );\n\t\t}\n\n\t\tif ( this.closeOnContentTap ) {\n\t\t\t$html.find( '#mw-mf-page-center' ).one( 'click', this.hide.bind( this ) );\n\t\t}\n\n\t\t// prevent scrolling and bouncing outside of .overlay-content\n\t\tif ( this.isIos && this.hasFixedHeader ) {\n\t\t\t$window\n\t\t\t\t.on( 'touchmove.ios', function ( ev ) {\n\t\t\t\t\tev.preventDefault();\n\t\t\t\t} )\n\t\t\t\t.on( 'resize.ios', function () {\n\t\t\t\t\tself._resizeContent( $window.height() );\n\t\t\t\t} );\n\t\t}\n\n\t\tthis.$el.addClass( 'visible' );\n\t},\n\t/**\n\t * Detach the overlay from the current view\n\t * @memberof Overlay\n\t * @instance\n\t * @param {boolean} [force] Whether the overlay should be closed regardless of\n\t * state (see PhotoUploadProgress)\n\t * @return {boolean} Whether the overlay was successfully hidden or not\n\t */\n\thide: function () {\n\t\tvar $window = util.getWindow(),\n\t\t\t$html = util.getDocument();\n\n\t\tif ( this.fullScreen ) {\n\t\t\t$html.removeClass( 'overlay-enabled' );\n\t\t\t// return to last known scroll position\n\t\t\twindow.scrollTo( window.pageXOffset, this.scrollTop );\n\t\t}\n\n\t\tthis.$el.detach();\n\n\t\tif ( this.isIos ) {\n\t\t\t$window.off( '.ios' );\n\t\t}\n\n\t\t/**\n\t\t * Fired when the overlay is closed.\n\t\t * @event Overlay#hide\n\t\t */\n\t\tthis.emit( 'hide' );\n\n\t\treturn true;\n\t},\n\n\t/**\n\t * Fit the overlay content height to the window taking overlay header and footer heights\n\t * into consideration.\n\t * @memberof Overlay\n\t * @instance\n\t * @private\n\t * @param {number} windowHeight The height of the window\n\t */\n\t_resizeContent: function ( windowHeight ) {\n\t\tthis.$overlayContent.height(\n\t\t\twindowHeight -\n\t\t\tthis.$( '.overlay-header-container' ).outerHeight() -\n\t\t\tthis.$( '.overlay-footer-container' ).outerHeight()\n\t\t);\n\t},\n\n\t/**\n\t * Resize .overlay-content to occupy 100% of screen space when virtual\n\t * keyboard is shown/hidden on iOS.\n\t *\n\t * This function supplements the custom styles for Overlays on iOS.\n\t * On iOS we scroll the content inside of .overlay-content div instead\n\t * of scrolling the whole page to achieve a consistent sticky header\n\t * effect (position: fixed doesn't work on iOS when the virtual keyboard\n\t * is open).\n\t *\n\t * @memberof Overlay\n\t * @instance\n\t * @private\n\t * @param {jQuery.Object} $el for elements that may trigger virtual\n\t * keyboard (usually inputs, textareas, contenteditables).\n\t */\n\t_fixIosHeader: function ( $el ) {\n\t\tvar self = this,\n\t\t\t$window = util.getWindow();\n\n\t\tif ( this.isIos ) {\n\t\t\tthis._resizeContent( $window.height() );\n\t\t\t$el\n\t\t\t\t.on( 'focus', function () {\n\t\t\t\t\tsetTimeout( function () {\n\t\t\t\t\t\tvar keyboardHeight = 0;\n\n\t\t\t\t\t\t// detect virtual keyboard height\n\t\t\t\t\t\tif ( self.useVirtualKeyboardHack ) {\n\t\t\t\t\t\t\t// this method does not work in iOS 8.02\n\t\t\t\t\t\t\t$window.scrollTop( 999 );\n\t\t\t\t\t\t\tkeyboardHeight = $window.scrollTop();\n\t\t\t\t\t\t\t$window.scrollTop( 0 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ( $window.height() > keyboardHeight ) {\n\t\t\t\t\t\t\tself._resizeContent( $window.height() - keyboardHeight );\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 0 );\n\t\t\t\t} )\n\t\t\t\t.on( 'blur', function () {\n\t\t\t\t\tself._resizeContent( $window.height() );\n\t\t\t\t\t// restore the fixed header in view.\n\t\t\t\t\t$window.scrollTop( 0 );\n\t\t\t\t} );\n\t\t}\n\t},\n\n\t/**\n\t * Show elements that are selected by the className.\n\t * Also hide .hideable elements\n\t * Can't use jQuery's hide() and show() because show() sets display: block.\n\t * And we want display: table for headers.\n\t * @memberof Overlay\n\t * @instance\n\t * @protected\n\t * @param {string} className CSS selector to show\n\t */\n\tshowHidden: function ( className ) {\n\t\tthis.$( '.hideable' ).addClass( 'hidden' );\n\t\tthis.$( className ).removeClass( 'hidden' );\n\t}\n} );\n\n/*\n * Fires when close button is clicked. Not to be confused with hide event.\n * @memberof Overlay\n * @event Overlay#Overlay-exit\n */\nOverlay.EVENT_EXIT = 'Overlay-exit';\n\nmodule.exports = Overlay;\n","var\n\tOverlay = require( './Overlay' ),\n\tmfExtend = require( './mfExtend' );\n\n/**\n * Overlay that initially shows loading animation until\n * caller hides it with .hide()\n * @class LoadingOverlay\n * @extends Overlay\n */\nfunction LoadingOverlay() {\n\tOverlay.apply( this, arguments );\n}\n\nmfExtend( LoadingOverlay, Overlay, {\n\t/**\n\t * @memberof LoadingOverlay\n\t * @instance\n\t */\n\tclassName: 'overlay overlay-loading',\n\t/**\n\t * @memberof LoadingOverlay\n\t * @instance\n\t */\n\ttemplate: mw.template.get( 'mobile.startup', 'LoadingOverlay.hogan' )\n} );\n\nmodule.exports = LoadingOverlay;\n","var\n\tmoduleLoader = require( './moduleSingleton' ),\n\tmfExtend = require( './mfExtend' ),\n\tcontext = require( './context' ),\n\ttime = require( './time' ),\n\tuser = require( './user' ),\n\tutil = require( './util' ),\n\tView = require( './View' ),\n\tPageGateway = require( './PageGateway' ),\n\tBrowser = require( './Browser' ),\n\tcache = require( './cache' ),\n\tButton = require( './Button' ),\n\tIcon = require( './Icon' ),\n\ticons = require( './icons' ),\n\tPanel = require( './Panel' ),\n\tSection = require( './Section' ),\n\tThumbnail = require( './Thumbnail' ),\n\tPage = require( './Page' ),\n\tAnchor = require( './Anchor' ),\n\tSkin = require( './Skin' ),\n\tOverlayManager = require( './OverlayManager' ),\n\tOverlay = require( './Overlay' ),\n\tLoadingOverlay = require( './LoadingOverlay' ),\n\trlModuleLoader = require( './rlModuleLoader' );\n\nmw.mobileFrontend = moduleLoader;\nmw.log.deprecate( moduleLoader, 'on', moduleLoader.on,\n\t'The global EventEmitter should not be used (T156186).' );\n\nOO.mfExtend = mfExtend;\n\n// I know there is a temptation to use moduleLoader here, but if you do resource-modules will fail\n// as webpack might change the variable name. Using mw.mobileFrontend means that the variable\n// will not be recast.\nmw.mobileFrontend.define( 'mobile.startup/util', util );\nmw.mobileFrontend.define( 'mobile.startup/View', View );\nmw.mobileFrontend.define( 'mobile.startup/Browser', Browser );\nmw.mobileFrontend.define( 'mobile.startup/cache', cache );\nmw.mobileFrontend.define( 'mobile.startup/time', time );\nmw.mobileFrontend.define( 'mobile.startup/context', context );\nmw.mobileFrontend.define( 'mobile.startup/user', user );\nmw.mobileFrontend.define( 'mobile.startup/PageGateway', PageGateway );\nmw.mobileFrontend.define( 'mobile.startup/Button', Button );\nmw.mobileFrontend.define( 'mobile.startup/Icon', Icon );\nmw.mobileFrontend.define( 'mobile.startup/icons', icons );\nmw.mobileFrontend.define( 'mobile.startup/Panel', Panel );\nmw.mobileFrontend.define( 'mobile.startup/Section', Section );\nmw.mobileFrontend.define( 'mobile.startup/Thumbnail', Thumbnail );\nmw.mobileFrontend.define( 'mobile.startup/Page', Page );\nmw.mobileFrontend.define( 'mobile.startup/Anchor', Anchor );\nmw.mobileFrontend.define( 'mobile.startup/Skin', Skin );\nmw.mobileFrontend.define( 'mobile.startup/OverlayManager', OverlayManager );\nmw.mobileFrontend.define( 'mobile.startup/Overlay', Overlay );\nmw.mobileFrontend.define( 'mobile.startup/LoadingOverlay', LoadingOverlay );\nmw.mobileFrontend.define( 'mobile.startup/rlModuleLoader', rlModuleLoader );\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\ttime: time,\n\tutil: util,\n\tView: View,\n\tBrowser: Browser,\n\tcontext: context,\n\tcache: cache,\n\tButton: Button,\n\tIcon: Icon,\n\ticons: icons,\n\tPanel: Panel,\n\tSection: Section,\n\tPage: Page,\n\tAnchor: Anchor,\n\tSkin: Skin,\n\tOverlayManager: OverlayManager,\n\tOverlay: Overlay,\n\tLoadingOverlay: LoadingOverlay,\n\trlModuleLoader: rlModuleLoader\n};\n","/**\n * Mobile mode helper class\n *\n * @class context\n * @singleton\n */\nvar context = {\n\t/**\n\t * Gets current mobile mode\n\t * @memberof context\n\t * @instance\n\t * @return {string} Name of mode\n\t */\n\tgetMode: function () {\n\t\treturn mw.config.get( 'wgMFMode' );\n\t}\n};\n\nmodule.exports = context;\n","var user,\n\tmwUser = mw.user,\n\tutil = require( './util' );\n\n/**\n * Utility library for looking up details on the current user\n * Note: most of this module is just for convenience. It should be removed\n * in favor of mw.user, or at very least reduced to convenience functions.\n * @class user\n * @singleton\n */\nuser = {\n\t/**\n\t * @memberof user\n\t * @instance\n\t * @see mediaWiki.user\n\t */\n\ttokens: mwUser.tokens,\n\t/**\n\t * @memberof user\n\t * @instance\n\t * @see mediaWiki.user\n\t */\n\tisAnon: mwUser.isAnon,\n\t/**\n\t * @memberof user\n\t * @instance\n\t * @see mediaWiki.user\n\t */\n\tgetName: mwUser.getName,\n\t/**\n\t * @memberof user\n\t * @instance\n\t * @see mediaWiki.user\n\t */\n\tgetId: mwUser.getId,\n\t/**\n\t * Find current users edit count\n\t * @memberof user\n\t * @instance\n\t * @return {number} the edit count of the current user on the current wiki.\n\t */\n\tgetEditCount: function () {\n\t\treturn mw.config.get( 'wgUserEditCount' );\n\t},\n\t/**\n\t * FIXME: Not sure why mw.user is asynchronous when the information is available\n\t * For reasons I do not understand getGroups in core causes an unnecessary ajax request\n\t * The information this returns is identical to the content of the config variable.\n\t * To avoid an unnecessary ajax request on every page view simply use config variable.\n\t * @memberof user\n\t * @instance\n\t * @return {jQuery.Deferred}\n\t */\n\tgetGroups: function () {\n\t\treturn util.Deferred().resolve( mw.config.get( 'wgUserGroups' ) );\n\t},\n\t/**\n\t * Wrapper for mw.user.sessionId().\n\t * @memberof user\n\t * @instance\n\t * @method\n\t * @return {string}\n\t */\n\tgetSessionId: function () {\n\t\treturn mwUser.sessionId();\n\t},\n\n\t/**\n\t * User Bucketing for A/B testing\n\t * (we want this to be the same everywhere)\n\t * @memberof user\n\t * @instance\n\t * @return {boolean}\n\t */\n\tinUserBucketA: function () {\n\t\treturn mw.config.get( 'wgUserId' ) % 2 === 0;\n\t}\n\n};\nmodule.exports = user;\n","var sectionTemplate = mw.template.get( 'mobile.startup', 'Section.hogan' ),\n\tutil = require( './util.js' ),\n\tcache = {};\n\n/**\n * Add child to listOfSections if the level of child is the same as the last\n * child of listOfSections, otherwise add it to the children of the last\n * section of listOfSections. If listOfSections is empty, just add child to it.\n * @private\n * @param {Array} listOfSections - Array of section ids\n * @param {Object} child - Section to be added to listOfSections\n */\nfunction assignToParent( listOfSections, child ) {\n\tvar section;\n\tif ( listOfSections.length === 0 ) {\n\t\tlistOfSections.push( child );\n\t} else {\n\t\t// take a look at the last child\n\t\tsection = listOfSections[listOfSections.length - 1];\n\t\t// If the level is the same as another section in this list it is a sibling\n\t\tif ( parseInt( section.level, 10 ) === parseInt( child.level, 10 ) ) {\n\t\t\tlistOfSections.push( child );\n\t\t} else {\n\t\t\t// Otherwise take a look at that sections children recursively\n\t\t\tassignToParent( section.children, child );\n\t\t}\n\t}\n}\n\n/**\n * Order sections hierarchically\n * @private\n * @param {Array} sections Array of section objects created from response HTML\n * @return {Array} Ordered array of sections\n */\nfunction transformSections( sections ) {\n\tvar sectionLevels = sections.map( function ( s ) { return s.level; } ),\n\t\texistingSectionLevels = sectionLevels.filter( function ( level ) {\n\t\t\treturn !!level;\n\t\t} ),\n\t\tcollapseLevel = Math.min.apply( this, existingSectionLevels ).toString(),\n\t\tlastSection,\n\t\tresult = [];\n\n\t// if the first section level is not equal to collapseLevel, this first\n\t// section will not have a parent and will be appended to the result.\n\tsections.forEach( function ( section ) {\n\t\tif ( section.line !== undefined ) {\n\t\t\tsection.line = section.line.replace( /<\\/?a\\b[^>]*>/g, '' );\n\t\t}\n\t\tsection.children = [];\n\n\t\tif (\n\t\t\t!lastSection ||\n\t\t\t(\n\t\t\t\t!section.level ||\n\t\t\t\tsection.level === collapseLevel\n\t\t\t) ||\n\t\t\t// make sure lastSections first child's level is bigger than section.level\n\t\t\t(\n\t\t\t\tlastSection.children.length &&\n\t\t\t\tlastSection.children[0].level > section.level\n\t\t\t) ||\n\t\t\t// also make sure section.level is not bigger than the lastSection.level\n\t\t\t(\n\t\t\t\tlastSection.level &&\n\t\t\t\tlastSection.level >= section.level\n\t\t\t)\n\t\t) {\n\t\t\tresult.push( section );\n\t\t\tlastSection = section;\n\t\t} else {\n\t\t\tassignToParent( lastSection.children, section );\n\t\t\tlastSection.text += sectionTemplate.render( section );\n\t\t}\n\t} );\n\n\treturn result;\n}\n\n/**\n * API for providing Page data\n * @class PageGateway\n * @param {mw.Api} api\n */\nfunction PageGateway( api ) {\n\tthis.api = api;\n}\n\nPageGateway.prototype = {\n\t/**\n\t * Retrieve a page from the api\n\t * @memberof PageGateway\n\t * @instance\n\t * @param {string} title the title of the page to be retrieved\n\t * @param {string} endpoint an alternative api url to retrieve the page from\n\t * @param {boolean} leadOnly When set only the lead section content is returned\n\t * @return {jQuery.Deferred} with parameter page data that can be passed to a Page view\n\t */\n\tgetPage: function ( title, endpoint, leadOnly ) {\n\t\tvar timestamp,\n\t\t\td = util.Deferred(),\n\t\t\toptions = endpoint ? {\n\t\t\t\turl: endpoint,\n\t\t\t\tdataType: 'jsonp'\n\t\t\t} : {},\n\t\t\tprotection = {\n\t\t\t\tedit: [ '*' ]\n\t\t\t};\n\n\t\tif ( !cache[title] ) {\n\t\t\tcache[title] = this.api.get( {\n\t\t\t\taction: 'mobileview',\n\t\t\t\tpage: title,\n\t\t\t\tvariant: mw.config.get( 'wgPageContentLanguage' ),\n\t\t\t\tredirect: 'yes',\n\t\t\t\tprop: 'id|sections|text|lastmodified|lastmodifiedby|languagecount|hasvariants|protection|displaytitle|revision',\n\t\t\t\tnoheadings: 'yes',\n\t\t\t\tsectionprop: 'level|line|anchor',\n\t\t\t\tsections: leadOnly ? 0 : 'all'\n\t\t\t}, options ).then( function ( resp ) {\n\t\t\t\tvar sections, lastModified, resolveObj, mv;\n\n\t\t\t\tif ( resp.error ) {\n\t\t\t\t\treturn d.reject( resp.error );\n\t\t\t\t} else if ( !resp.mobileview.sections ) {\n\t\t\t\t\treturn d.reject( 'No sections' );\n\t\t\t\t} else {\n\t\t\t\t\tmv = resp.mobileview;\n\t\t\t\t\tsections = transformSections( mv.sections );\n\t\t\t\t\t// Assume the timestamp is in the form TS_ISO_8601\n\t\t\t\t\t// and we don't care about old browsers\n\t\t\t\t\t// change to seconds to be consistent with PHP\n\t\t\t\t\ttimestamp = new Date( mv.lastmodified ).getTime() / 1000;\n\t\t\t\t\tlastModified = mv.lastmodifiedby;\n\n\t\t\t\t\t// FIXME: [API] the API sometimes returns an object and sometimes an array\n\t\t\t\t\t// There are various quirks with the format of protection level\n\t\t\t\t\t// as returned by api.\n\t\t\t\t\t// Also it is usually incomplete - if something is missing this means\n\t\t\t\t\t// that it has no protection level.\n\t\t\t\t\t// When an array this means there is no protection level set.\n\t\t\t\t\t// To keep the data type consistent either use the predefined\n\t\t\t\t\t// protection level,\n\t\t\t\t\t// or extend it with what is returned by API.\n\t\t\t\t\tprotection = Array.isArray( mv.protection ) ?\n\t\t\t\t\t\tprotection :\n\t\t\t\t\t\tutil.extend( protection, mv.protection );\n\n\t\t\t\t\tresolveObj = {\n\t\t\t\t\t\ttitle: title,\n\t\t\t\t\t\tid: mv.id,\n\t\t\t\t\t\trevId: mv.revId,\n\t\t\t\t\t\tprotection: protection,\n\t\t\t\t\t\tlead: sections[0].text,\n\t\t\t\t\t\tsections: sections.slice( 1 ),\n\t\t\t\t\t\tisMainPage: mv.mainpage !== undefined,\n\t\t\t\t\t\thistoryUrl: mw.util.getUrl( title, {\n\t\t\t\t\t\t\taction: 'history'\n\t\t\t\t\t\t} ),\n\t\t\t\t\t\tlastModifiedTimestamp: timestamp,\n\t\t\t\t\t\tlanguageCount: mv.languagecount,\n\t\t\t\t\t\thasVariants: mv.hasvariants !== undefined,\n\t\t\t\t\t\tdisplayTitle: mv.displaytitle\n\t\t\t\t\t};\n\t\t\t\t\t// Add non-anonymous user information\n\t\t\t\t\tif ( lastModified ) {\n\t\t\t\t\t\tutil.extend( resolveObj, {\n\t\t\t\t\t\t\tlastModifiedUserName: lastModified.name,\n\t\t\t\t\t\t\tlastModifiedUserGender: lastModified.gender\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t\t// FIXME: Return a Page class here\n\t\t\t\t\treturn resolveObj;\n\t\t\t\t}\n\t\t\t}, function ( msg ) {\n\t\t\t\treturn d.reject( msg );\n\t\t\t} );\n\t\t}\n\n\t\treturn cache[title];\n\t},\n\n\t/**\n\t * Invalidate the internal cache for a given page\n\t * @memberof PageGateway\n\t * @instance\n\t * @param {string} title the title of the page who's cache you want to invalidate\n\t */\n\tinvalidatePage: function ( title ) {\n\t\tdelete cache[title];\n\t},\n\n\t/**\n\t * Gets language variant list for a page; helper function for getPageLanguages()\n\t * @memberof PageGateway\n\t * @instance\n\t * @private\n\t * @param {string} title Name of the page to obtain variants for\n\t * @param {Object} data Data from API\n\t * @return {Array|boolean} List of language variant objects or false if no variants exist\n\t */\n\t_getLanguageVariantsFromApiResponse: function ( title, data ) {\n\t\tvar generalData = data.query.general,\n\t\t\tvariantPath = generalData.variantarticlepath,\n\t\t\tvariants = [];\n\n\t\tif ( !generalData.variants ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Create the data object for each variant and store it\n\t\tObject.keys( generalData.variants ).forEach( function ( index ) {\n\t\t\tvar item = generalData.variants[ index ],\n\t\t\t\tvariant = {\n\t\t\t\t\tautonym: item.name,\n\t\t\t\t\tlang: item.code\n\t\t\t\t};\n\n\t\t\tif ( variantPath ) {\n\t\t\t\tvariant.url = variantPath\n\t\t\t\t\t.replace( '$1', title )\n\t\t\t\t\t.replace( '$2', item.code );\n\t\t\t} else {\n\t\t\t\tvariant.url = mw.util.getUrl( title, {\n\t\t\t\t\tvariant: item.code\n\t\t\t\t} );\n\t\t\t}\n\t\t\tvariants.push( variant );\n\t\t} );\n\n\t\treturn variants;\n\t},\n\n\t/**\n\t * Retrieve available languages for a given title\n\t * @memberof PageGateway\n\t * @instance\n\t * @param {string} title the title of the page languages should be retrieved for\n\t * @param {string} [language] when provided the names of the languages returned\n\t * will be translated additionally into this language.\n\t * @return {jQuery.Deferred} which is called with an object containing langlinks\n\t * and variant links as defined @ https://en.m.wikipedia.org/w/api.php?action=help&modules=query%2Blanglinks\n\t */\n\tgetPageLanguages: function ( title, language ) {\n\t\tvar self = this,\n\t\t\targs = {\n\t\t\t\taction: 'query',\n\t\t\t\tmeta: 'siteinfo',\n\t\t\t\tsiprop: 'general',\n\t\t\t\tprop: 'langlinks',\n\t\t\t\tlllimit: 'max',\n\t\t\t\ttitles: title,\n\t\t\t\tformatversion: 2\n\t\t\t};\n\n\t\tif ( language ) {\n\t\t\targs.llprop = 'url|autonym|langname';\n\t\t\targs.llinlanguagecode = language;\n\t\t} else {\n\t\t\targs.llprop = 'url|autonym';\n\t\t}\n\t\treturn this.api.get( args ).then( function ( resp ) {\n\t\t\treturn {\n\t\t\t\tlanguages: resp.query.pages[0].langlinks || [],\n\t\t\t\tvariants: self._getLanguageVariantsFromApiResponse( title, resp )\n\t\t\t};\n\t\t}, function () {\n\t\t\treturn util.Deferred().reject();\n\t\t} );\n\t},\n\n\t/**\n\t * Extract sections from headings in $el\n\t * @memberof PageGateway\n\t * @instance\n\t * @private\n\t * @param {jQuery.Object} $el object from which sections are extracted\n\t * @return {Array} Array of section objects created from headings in $el\n\t * FIXME: Where's a better place for getSectionsFromHTML and this function to live?\n\t * Answer: Possibly Page.js\n\t */\n\t_getAPIResponseFromHTML: function ( $el ) {\n\t\t// FIXME: use Page.HEADING_SELECTOR\n\t\tvar $headings = $el.find( 'h1,h2,h3,h4,h5,h6' ),\n\t\t\tsections = [];\n\n\t\t$headings.each( function () {\n\t\t\tvar level = this.tagName.substr( 1 ),\n\t\t\t\t$span = $el.find( this ).find( '.mw-headline' );\n\n\t\t\tif ( $span.length ) {\n\t\t\t\tsections.push( {\n\t\t\t\t\tlevel: level,\n\t\t\t\t\tline: $span.html(),\n\t\t\t\t\tanchor: $span.attr( 'id' ) || '',\n\t\t\t\t\ttext: ''\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t\treturn sections;\n\t},\n\n\t/**\n\t * Order sections hierarchically\n\t * @memberof PageGateway\n\t * @instance\n\t * @param {jQuery.Object} $el object from which sections are extracted\n\t * @return {Array} Ordered array of sections\n\t */\n\tgetSectionsFromHTML: function ( $el ) {\n\t\treturn transformSections( this._getAPIResponseFromHTML( $el ) );\n\t}\n};\n\nmodule.exports = PageGateway;\n","var\n\tmfExtend = require( './mfExtend' ),\n\tView = require( './View' );\n\n/**\n * An abstract class for a {@link View} that comprises a simple panel.\n * @class Panel\n * @extends View\n *\n * @param {Object} options Configuration options\n */\nfunction Panel() {\n\tView.apply( this, arguments );\n}\n\nmfExtend( Panel, View, {\n\t/**\n\t * @inheritdoc\n\t * @memberof Panel\n\t * @instance\n\t */\n\tclassName: 'panel',\n\t// in milliseconds\n\tminHideDelay: 10,\n\tevents: {\n\t\t'click .cancel': 'onCancel'\n\t},\n\n\t/**\n\t * Cancel event handler\n\t * @memberof Panel\n\t * @instance\n\t * @param {Object} ev Event Object\n\t */\n\tonCancel: function ( ev ) {\n\t\tev.preventDefault();\n\t\tthis.hide();\n\t},\n\n\t/**\n\t * Shows panel after a slight delay\n\t * @memberof Panel\n\t * @instance\n\t * @method\n\t */\n\tshow: function () {\n\t\tvar self = this;\n\n\t\tif ( !self.isVisible() ) {\n\t\t\t// use setTimeout to allow the browser to redraw if render() was called\n\t\t\t// just before show(); this is important for animations to work\n\t\t\t// (0ms doesn't work on Firefox, 10ms is enough)\n\t\t\tsetTimeout( function () {\n\t\t\t\tself.$el.addClass( 'visible animated' );\n\t\t\t\tself.emit( 'show' );\n\t\t\t}, self.minHideDelay );\n\t\t}\n\t},\n\n\t/**\n\t * Hides panel\n\t * @memberof Panel\n\t * @instance\n\t */\n\thide: function () {\n\t\tvar self = this;\n\n\t\t// see comment in show()\n\t\tsetTimeout( function () {\n\t\t\tself.$el.removeClass( 'visible' );\n\t\t\tself.emit( 'hide' );\n\t\t}, self.minHideDelay );\n\t},\n\n\t/**\n\t * Determines if panel is visible\n\t * @memberof Panel\n\t * @instance\n\t * @return {boolean} Panel is visible\n\t */\n\tisVisible: function () {\n\t\treturn this.$el.hasClass( 'visible' );\n\t},\n\n\t/**\n\t * Shows or hides panel\n\t * @memberof Panel\n\t * @instance\n\t */\n\ttoggle: function () {\n\t\tif ( this.isVisible() ) {\n\t\t\tthis.hide();\n\t\t} else {\n\t\t\tthis.show();\n\t\t}\n\t}\n} );\n\nmodule.exports = Panel;\n","var LoadingOverlay = require( './LoadingOverlay' );\n\n/**\n * Utility library for looking up details on the current user\n * @class loader\n * @singleton\n */\nmodule.exports = {\n\t/**\n\t * Loads a module via ResourceLoader\n\t * and displays a full screen LoadingOverlay during load time.\n\t * @memberof loader\n\t * @instance\n\t * @param {string} name ResourceLoader module name to load asynchronously.\n\t * @param {boolean} delegateHide if true the caller is responsible for hiding\n\t * the intermediate loader.\n\t * @param {boolean} [showLoadingOverlay] if false a loading overlay will be hidden while\n\t * loading the module. Defaults to true.\n\t * @return {jQuery.Promise}\n\t */\n\tloadModule: function ( name, delegateHide, showLoadingOverlay ) {\n\t\tvar loadingOverlay = new LoadingOverlay();\n\n\t\tshowLoadingOverlay = ( showLoadingOverlay !== undefined ) ? showLoadingOverlay : true;\n\t\tif ( showLoadingOverlay ) {\n\t\t\tloadingOverlay.show();\n\t\t}\n\n\t\tfunction hideOverlayIfNeeded() {\n\t\t\tif ( !delegateHide && showLoadingOverlay ) {\n\t\t\t\tloadingOverlay.hide();\n\t\t\t}\n\t\t}\n\t\treturn mw.loader.using( name ).then( function () {\n\t\t\thideOverlayIfNeeded();\n\n\t\t\treturn loadingOverlay;\n\t\t}, function () {\n\t\t\thideOverlayIfNeeded();\n\t\t} );\n\t}\n};\n"],"sourceRoot":""}