{"version":3,"sources":["webpack://mfModules.[name]/./src/mobile.editor.overlay/AbuseFilterOverlay.js","webpack://mfModules.[name]/./src/mobile.editor.overlay/AbuseFilterPanel.js","webpack://mfModules.[name]/./src/mobile.editor.overlay/BlockMessage.js","webpack://mfModules.[name]/./src/mobile.editor.overlay/EditorGateway.js","webpack://mfModules.[name]/./src/mobile.editor.overlay/EditorOverlay.js","webpack://mfModules.[name]/./src/mobile.editor.overlay/EditorOverlayBase.js","webpack://mfModules.[name]/./src/mobile.editor.overlay/VisualEditorOverlay.js","webpack://mfModules.[name]/./src/mobile.editor.overlay/mobile.editor.overlay.js","webpack://mfModules.[name]/./src/mobile.editor.overlay/saveFailureMessage.js","webpack://mfModules.[name]/./src/mobile.editor.overlay/schemaEditAttemptStep.js"],"names":["Button","require","util","mfExtend","Overlay","AbuseFilterOverlay","props","call","this","extend","className","defaults","prototype","confirmButton","additionalClassNames","progressive","options","templatePartials","button","template","content","mw","get","postRender","apply","$el","find","attr","module","exports","View","AbuseFilterPanel","isDisallowed","overlayManager","readMoreMsg","msg","show","type","message","add","text","removeClass","hide","addClass","Drawer","Icon","BlockMessage","arguments","stopHandIcon","name","userIcon","tagName","okButton","label","createDetailsAnchorHref","getUrl","wpTarget","blockId","createDetailsAnchorLabel","createTitle","partial","reasonHeader","creatorHeader","user","gender","expiryHeader","icon","parseSaveError","actionParams","EditorGateway","api","title","sectionId","oldId","isNewPage","undefined","hasChanged","getBlockInfo","pageObj","blockedError","actions","edit","Array","isArray","some","error","indexOf","code","data","blockinfo","loader","load","getContent","self","resolve","Deferred","userinfo","prop","meta","rvprop","titles","intestactions","intestactionsdetail","uiprop","rvstartid","isNumeric","rvsection","then","resp","revision","reject","query","pages","missing","revisions","timestamp","originalContent","setContent","setPrependText","prependtext","save","result","apiOptions","action","summary","captchaid","captchaId","captchaword","captchaWord","basetimestamp","starttimestamp","section","postWithToken","saveContent","abortPreview","_pending","abort","getPreview","request","sectionLine","sectionpreview","pst","mobileformat","post","parse","sections","anchor","line","id","promise","EditorOverlayBase","Section","saveFailureMessage","VisualEditorOverlay","MessageBox","EditorOverlay","isFirefox","test","window","navigator","userAgent","gateway","readOnly","isVisualEditorEnabled","editSwitcher","editingMsg","isVisualEditor","previewingMsg","events","input .wikitext-editor","editor","ns","config","namespaces","onInputWikitextEditor","val","onClickContinue","ev","isAnon","target","hasClass","_showEditorAfterWarning","onClickBack","_hidePreview","$anonWarning","using","switchToolbar","toolFactory","OO","ui","ToolFactory","toolGroupFactory","ToolGroupFactory","register","libs","ve","MWEditModeVisualTool","MWEditModeSourceTool","Toolbar","classes","on","mode","confirm","onStageChanges","_switchToVisualEditor","setup","include","html","$element","emit","$preview","$content","length","prepend","_renderAnonWarning","$anonHiddenButtons","hideSpinner","abuseFilterPanel","appendTo","_resizeEditor","bind","_loadContent","params","returnto","returnTo","returntoquery","warning","queryParams","signupParams","signupQueryParams","anonymousEditorActions","block","href","append","map","showSpinner","hideSpinnerAndShowPreview","scrollTop","getDocument","mainpage","parsedText","parsedSectionLine","parseHTML","el","scrollTo","showHidden","container","$scrollContainer","Element","static","getClosestScrollableContainer","css","height","_parseBlockInfo","blockInfo","expiry","reason","moment","blockpartial","creator","blockedby","url","duration","blockid","blockexpiry","format","to","blockreason","wikitext","parser","ast","jqueryMsg","wikiTextToAst","emitter","e","jqueryMsgParse","escape","escaped","toggle","reportError","log","mechanism","storage","set","targetLoader","addPlugin","loadModules","switched","switching","replaceCurrent","_showAbuseFilter","onSaveBegin","confirmAborted","location","onSaveComplete","onSaveFailure","heading","details","handleCaptcha","PageGateway","toast","mwUser","EditVeTool","toolGroup","super","isBorderBox","click .back","click .continue","click .submit","placeholder","summaryRequestMsg","pageGateway","editCount","isNewEditor","sessionId","allowCloseWindow","confirmCloseWindow","namespace","inheritClass","Tool","group","onSelect","onUpdateState","hasToolbar","continueMsg","cancelMsg","closeMsg","summaryMsg","waitMsg","waitIcon","toHtmlString","captchaMsg","captchaTryAgainMsg","switchMsg","confirmMsg","licenseMsg","editHeader","previewHeader","saveHeader","track","editor_interface","editing_session_id","confirmSave","$window","getWindow","saved","invalidatePage","showOnPageReload","hash","off","reload","key","editconflict","wasdeleted","abusefilter-disallowed","captcha","spamprotectiontext","titleblacklist-forbidden-edit","errorNotice","$errorNoticeContainer","hideErrorNotice","empty","skipPreview","nextStep","saveMsg","hook","fire","onClickSubmit","windowManager","getWindowManager","addWindows","widgets","AbandonEditDialog","openWindow","closed","release","edited","shouldConfirmLeave","force","$input","captchaShown","setTimeout","mime","detach","question","applyHeaderOptions","isVE","destroyTarget","destroy","init","targetFactory","create","once","dataPromise","overlay","retval","switchToEditor","switchToSourceEditor","getSurface","getModel","hasBeenModified","m","schemaEditAttemptStep","define","readonlyreason","info","trackdebug","getParamValue","getState","Schema","eventLog","sampleRate","actionPrefixMap","saveIntent","saveAttempt","saveSuccess","saveFailure","timing","page_id","revision_id","page_title","page_ns","user_id","getId","user_class","user_editcount","mw_version","platform","integration","page_token","getPageviewToken","session_token","version","trackSubscribe","topic","timeStamp","actionPrefix","Math","round","event","ready","warn","abort_type","computeDuration","is_oversample","inSample","console"],"mappings":"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","file":"mobile.editor.overlay.js","sourcesContent":["var Button = require( '../mobile.startup/Button' ),\n\tutil = require( '../mobile.startup/util' ),\n\tmfExtend = require( '../mobile.startup/mfExtend' ),\n\tOverlay = require( '../mobile.startup/Overlay' );\n\n/**\n * Overlay that shows a message about abuse.\n * This overlay is rendered when the error code from the API\n * is related to the abusefilter extension.\n * @class AbuseFilterOverlay\n * @extends Overlay\n * @param {Object} props\n */\nfunction AbuseFilterOverlay( props ) {\n\tOverlay.call( this,\n\t\tutil.extend( {\n\t\t\tclassName: 'overlay abusefilter-overlay'\n\t\t}, props )\n\t);\n}\n\nmfExtend( AbuseFilterOverlay, Overlay, {\n\t/**\n\t * @memberof AbuseFilterOverlay\n\t * @instance\n\t * @mixes Overlay#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {Object} defaults.confirmButton options for a confirm Button\n\t */\n\tdefaults: util.extend( {}, Overlay.prototype.defaults, {\n\t\tconfirmButton: new Button( {\n\t\t\tadditionalClassNames: 'cancel',\n\t\t\tprogressive: true\n\t\t} ).options\n\t} ),\n\t/**\n\t * @memberof AbuseFilterOverlay\n\t * @instance\n\t */\n\ttemplatePartials: util.extend( {}, Overlay.prototype.templatePartials, {\n\t\tbutton: Button.prototype.template,\n\t\tcontent: mw.template.get( 'mobile.editor.overlay', 'AbuseFilterOverlay.hogan' )\n\t} ),\n\t/**\n\t * @inheritdoc\n\t * @memberof AbuseFilterOverlay\n\t * @instance\n\t */\n\tpostRender: function () {\n\t\tOverlay.prototype.postRender.apply( this );\n\t\t// make links open in separate tabs\n\t\tthis.$el.find( 'a' ).attr( 'target', '_blank' );\n\t}\n} );\n\nmodule.exports = AbuseFilterOverlay;\n","var util = require( '../mobile.startup/util' ),\n\tView = require( '../mobile.startup/View' ),\n\tmfExtend = require( '../mobile.startup/mfExtend' ),\n\tAbuseFilterOverlay = require( './AbuseFilterOverlay' );\n\n/**\n * Panel that shows an error message related to the abusefilter extension.\n * @class AbuseFilterPanel\n * @extends View\n * @uses AbuseFilterOverlay\n *\n * @param {Object} options Configuration options\n * FIXME: should extend Panel not View. Or the name should be changed to something meaningful.\n */\nfunction AbuseFilterPanel( options ) {\n\tthis.isDisallowed = false;\n\tthis.overlayManager = options.overlayManager;\n\tView.call( this,\n\t\tutil.extend( {\n\t\t\tclassName: 'panel hidden'\n\t\t}, options )\n\t);\n}\n\nmfExtend( AbuseFilterPanel, View, {\n\t/**\n\t * @memberof AbuseFilterPanel\n\t * @instance\n\t * @mixes View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} defaults.readMoreMsg A caption for the button\n\t * allowing the user to read more about the problems with their edit.\n\t * @property {OverlayManager} defaults.overlayManager instance\n\t */\n\tdefaults: {\n\t\treadMoreMsg: mw.msg( 'mobile-frontend-editor-abusefilter-read-more' )\n\t},\n\t/**\n\t * @memberof AbuseFilterPanel\n\t * @instance\n\t */\n\ttemplate: mw.template.get( 'mobile.editor.overlay', 'AbuseFilterPanel.hogan' ),\n\t/**\n\t * Show the panel. Create a route to show AbuseFilterOverlay with message.\n\t * @memberof AbuseFilterPanel\n\t * @instance\n\t * @param {string} type The type of alert, e.g. 'warning' or 'disallow'\n\t * @param {string} message Message to show in the AbuseFilter overlay\n\t */\n\tshow: function ( type, message ) {\n\t\tvar msg;\n\n\t\t// OverlayManager will replace previous instance of the route if present\n\t\tthis.overlayManager.add( /^\\/abusefilter$/, function () {\n\t\t\treturn new AbuseFilterOverlay( {\n\t\t\t\tmessage: message\n\t\t\t} );\n\t\t} );\n\n\t\tif ( type === 'warning' ) {\n\t\t\tmsg = mw.msg( 'mobile-frontend-editor-abusefilter-warning' );\n\t\t} else if ( type === 'disallow' ) {\n\t\t\tmsg = mw.msg( 'mobile-frontend-editor-abusefilter-disallow' );\n\t\t\tthis.isDisallowed = true;\n\t\t}\n\n\t\tthis.$el.find( '.message p' ).text( msg );\n\t\tthis.$el.removeClass( 'hidden' );\n\t},\n\n\t/**\n\t * Hide the panel.\n\t * @memberof AbuseFilterPanel\n\t * @instance\n\t */\n\thide: function () {\n\t\tthis.$el.addClass( 'hidden' );\n\t}\n} );\n\nmodule.exports = AbuseFilterPanel;\n","'use strict';\nvar Drawer = require( '../mobile.startup/Drawer' ),\n\tButton = require( '../mobile.startup/Button' ),\n\tmfExtend = require( '../mobile.startup/mfExtend' ),\n\tIcon = require( '../mobile.startup/Icon' ),\n\tutil = require( '../mobile.startup/util' );\n\n/**\n * This creates the drawer at the bottom of the screen that appears when a\n * blocked user tries to edit.\n * @class BlockReason\n * @extends Drawer\n */\nfunction BlockMessage() {\n\tDrawer.apply( this, arguments );\n}\n\nmfExtend( BlockMessage, Drawer, {\n\t/**\n\t * @memberof BlockMessage\n\t * @instance\n\t */\n\tdefaults: util.extend( {}, Drawer.prototype.defaults, {\n\t\tstopHandIcon: new Icon( {\n\t\t\tname: 'stop-hand'\n\t\t} ).options,\n\t\tuserIcon: new Icon( {\n\t\t\ttagName: 'span',\n\t\t\tname: 'profile'\n\t\t} ).options,\n\t\tokButton: new Button( {\n\t\t\tlabel: mw.msg( 'ok' ),\n\t\t\ttagName: 'button',\n\t\t\tprogressive: true,\n\t\t\tadditionalClassNames: 'cancel'\n\t\t} ).options,\n\t\tcreateDetailsAnchorHref: function () {\n\t\t\treturn mw.util.getUrl( 'Special:BlockList', { wpTarget: '#' + this.blockId } );\n\t\t},\n\t\tcreateDetailsAnchorLabel: function () {\n\t\t\treturn mw.msg( 'mobile-frontend-editor-blocked-drawer-help' );\n\t\t},\n\t\tcreateTitle: function () {\n\t\t\treturn this.partial ? mw.msg( 'mobile-frontend-editor-blocked-drawer-title-partial' ) : mw.msg( 'mobile-frontend-editor-blocked-drawer-title' );\n\t\t},\n\t\treasonHeader: mw.msg( 'mobile-frontend-editor-blocked-drawer-reason-header' ),\n\t\tcreatorHeader: function () {\n\t\t\t// The gender is the subject (the blockee) not the object (the blocker).\n\t\t\treturn mw.msg( 'mobile-frontend-editor-blocked-drawer-creator-header',\n\t\t\t\tthis.user.options.gender || 'unknown' );\n\t\t},\n\t\texpiryHeader: mw.msg( 'mobile-frontend-editor-blocked-drawer-expiry-header' )\n\t} ),\n\t/**\n\t * @memberof BlockMessage\n\t * @instance\n\t */\n\ttemplatePartials: util.extend( {}, Drawer.prototype.templatePartials, {\n\t\tbutton: Button.prototype.template,\n\t\ticon: Icon.prototype.template\n\t} ),\n\t/**\n\t * @memberof BlockMessage\n\t * @instance\n\t */\n\ttemplate: mw.template.get( 'mobile.editor.overlay', 'BlockMessage.hogan' )\n} );\n\nmodule.exports = BlockMessage;\n","var util = require( '../mobile.startup/util' ),\n\tparseSaveError = require( './parseSaveError' ),\n\tactionParams = require( '../mobile.startup/actionParams' );\n\n/**\n * API that helps save and retrieve page content\n * @class EditorGateway\n *\n * @param {Object} options Configuration options\n * @param {mw.Api} options.api an Api to use.\n * @param {string} options.title the title to edit\n * @param {number} options.sectionId the id of the section to operate edits on.\n * @param {number} [options.oldId] revision to operate on. If absent defaults to latest.\n * @param {boolean} [options.isNewPage] whether the page being created is new\n */\nfunction EditorGateway( options ) {\n\tthis.api = options.api;\n\tthis.title = options.title;\n\tthis.sectionId = options.sectionId;\n\tthis.oldId = options.oldId;\n\t// return an empty section for new pages\n\tthis.content = options.isNewPage ? '' : undefined;\n\tthis.hasChanged = false;\n}\n\nEditorGateway.prototype = {\n\t/**\n\t * Get the block (if there is one) from the result.\n\t * @memberof EditorGateway\n\t * @param {Object} pageObj\n\t * @return {Object|null}\n\t */\n\tgetBlockInfo: function ( pageObj ) {\n\t\tvar blockedError;\n\n\t\tif ( pageObj.actions &&\n\t\t\tpageObj.actions.edit &&\n\t\t\tArray.isArray( pageObj.actions.edit )\n\t\t) {\n\t\t\tpageObj.actions.edit.some( function ( error ) {\n\t\t\t\tif ( [ 'blocked', 'autoblocked' ].indexOf( error.code ) !== -1 ) {\n\t\t\t\t\tblockedError = error;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} );\n\n\t\t\tif ( blockedError && blockedError.data && blockedError.data.blockinfo ) {\n\t\t\t\t// Preload library used by EditorOverlay\n\t\t\t\t// to format block expiry datetime and duration\n\t\t\t\tmw.loader.load( 'moment' );\n\n\t\t\t\treturn blockedError.data.blockinfo;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t},\n\t/**\n\t * Get the content of a page.\n\t * @memberof EditorGateway\n\t * @instance\n\t * @return {jQuery.Promise}\n\t */\n\tgetContent: function () {\n\t\tvar options,\n\t\t\tself = this;\n\n\t\tfunction resolve() {\n\t\t\treturn util.Deferred().resolve( {\n\t\t\t\ttext: self.content || '',\n\t\t\t\tblockinfo: self.blockinfo,\n\t\t\t\tuserinfo: self.userinfo\n\t\t\t} );\n\t\t}\n\n\t\tif ( this.content !== undefined ) {\n\t\t\treturn resolve();\n\t\t} else {\n\t\t\toptions = actionParams( {\n\t\t\t\tprop: [ 'revisions', 'info' ],\n\t\t\t\tmeta: 'userinfo',\n\t\t\t\trvprop: [ 'content', 'timestamp' ],\n\t\t\t\ttitles: self.title,\n\t\t\t\t// get block information for this user\n\t\t\t\tintestactions: 'edit',\n\t\t\t\tintestactionsdetail: 'full',\n\t\t\t\tuiprop: 'options'\n\t\t\t} );\n\t\t\t// Load text of old revision if desired\n\t\t\tif ( this.oldId ) {\n\t\t\t\toptions.rvstartid = this.oldId;\n\t\t\t}\n\t\t\t// See Bug 50136 - passing rvsection will fail with non wikitext\n\t\t\tif ( util.isNumeric( this.sectionId ) ) {\n\t\t\t\toptions.rvsection = this.sectionId;\n\t\t\t}\n\t\t\treturn this.api.get( options ).then( function ( resp ) {\n\t\t\t\tvar revision, pageObj;\n\n\t\t\t\tif ( resp.error ) {\n\t\t\t\t\treturn util.Deferred().reject( resp.error.code );\n\t\t\t\t}\n\n\t\t\t\tpageObj = resp.query.pages[0];\n\t\t\t\t// page might not exist and caller might not have known.\n\t\t\t\tif ( pageObj.missing !== undefined ) {\n\t\t\t\t\tself.content = '';\n\t\t\t\t} else {\n\t\t\t\t\trevision = pageObj.revisions[0];\n\t\t\t\t\tself.content = revision.content;\n\t\t\t\t\tself.timestamp = revision.timestamp;\n\t\t\t\t}\n\n\t\t\t\tself.userinfo = resp.query.userinfo;\n\n\t\t\t\t// save content a second time to be able to check for changes\n\t\t\t\tself.originalContent = self.content;\n\t\t\t\tself.blockinfo = self.getBlockInfo( pageObj );\n\n\t\t\t\treturn resolve();\n\t\t\t} );\n\t\t}\n\t},\n\n\t/**\n\t * Mark content as modified and set changes to be submitted when #save\n\t * is invoked.\n\t * @memberof EditorGateway\n\t * @instance\n\t * @param {string} content New section content.\n\t */\n\tsetContent: function ( content ) {\n\t\tif ( this.originalContent !== content ) {\n\t\t\tthis.hasChanged = true;\n\t\t} else {\n\t\t\tthis.hasChanged = false;\n\t\t}\n\t\tthis.content = content;\n\t},\n\n\t/**\n\t * Mark content as modified and set text that should be prepended to given\n\t * section when #save is invoked.\n\t * @memberof EditorGateway\n\t * @instance\n\t * @param {string} text Text to be prepended.\n\t */\n\tsetPrependText: function ( text ) {\n\t\tthis.prependtext = text;\n\t\tthis.hasChanged = true;\n\t},\n\n\t/**\n\t * Save the new content of the section, previously set using #setContent.\n\t * @memberof EditorGateway\n\t * @instance\n\t * @param {Object} options Configuration options\n\t * @param {string} [options.summary] Optional summary for the edit.\n\t * @param {string} [options.captchaId] If CAPTCHA was requested, ID of the\n\t * captcha.\n\t * @param {string} [options.captchaWord] If CAPTCHA was requested, term\n\t * displayed in the CAPTCHA.\n\t * @return {jQuery.Deferred} On failure callback is passed an object with\n\t * `type` and `details` properties. `type` is a string describing the type\n\t * of error, `details` can be any object (usually error message).\n\t */\n\tsave: function ( options ) {\n\t\tvar self = this,\n\t\t\tresult = util.Deferred();\n\n\t\toptions = options || {};\n\n\t\t/**\n\t\t * Save content. Make an API request.\n\t\t * @return {jQuery.Deferred}\n\t\t */\n\t\tfunction saveContent() {\n\t\t\tvar apiOptions = {\n\t\t\t\taction: 'edit',\n\t\t\t\ttitle: self.title,\n\t\t\t\tsummary: options.summary,\n\t\t\t\tcaptchaid: options.captchaId,\n\t\t\t\tcaptchaword: options.captchaWord,\n\t\t\t\tbasetimestamp: self.timestamp,\n\t\t\t\tstarttimestamp: self.timestamp\n\t\t\t};\n\n\t\t\tif ( self.content !== undefined ) {\n\t\t\t\tapiOptions.text = self.content;\n\t\t\t} else if ( self.prependtext ) {\n\t\t\t\tapiOptions.prependtext = self.prependtext;\n\t\t\t}\n\n\t\t\tif ( util.isNumeric( self.sectionId ) ) {\n\t\t\t\tapiOptions.section = self.sectionId;\n\t\t\t}\n\n\t\t\tself.api.postWithToken( 'csrf', apiOptions ).then( function ( data ) {\n\t\t\t\tif ( data && data.edit && data.edit.result === 'Success' ) {\n\t\t\t\t\tself.hasChanged = false;\n\t\t\t\t\tresult.resolve();\n\t\t\t\t} else {\n\t\t\t\t\tresult.reject( parseSaveError( data ) );\n\t\t\t\t}\n\t\t\t}, function ( code, data ) {\n\t\t\t\tresult.reject( parseSaveError( data, code || 'unknown' ) );\n\t\t\t} );\n\t\t\treturn result;\n\t\t}\n\n\t\treturn saveContent();\n\t},\n\n\t/**\n\t * Abort any pending previews.\n\t * @memberof EditorGateway\n\t * @instance\n\t */\n\tabortPreview: function () {\n\t\tif ( this._pending ) {\n\t\t\tthis._pending.abort();\n\t\t}\n\t},\n\n\t/**\n\t * Get page preview from the API and abort any existing previews.\n\t * @memberof EditorGateway\n\t * @instance\n\t * @param {Object} options API query parameters\n\t * @return {jQuery.Deferred}\n\t */\n\tgetPreview: function ( options ) {\n\t\tvar result = util.Deferred(),\n\t\t\tsectionLine = '',\n\t\t\tsectionId = '',\n\t\t\trequest,\n\t\t\tself = this;\n\n\t\tutil.extend( options, {\n\t\t\taction: 'parse',\n\t\t\t// Enable section preview mode to avoid errors (bug 49218)\n\t\t\tsectionpreview: true,\n\t\t\t// needed for pre-save transform to work (bug 53692)\n\t\t\tpst: true,\n\t\t\t// Output mobile HTML (bug 54243)\n\t\t\tmobileformat: true,\n\t\t\ttitle: this.title,\n\t\t\tprop: [ 'text', 'sections' ]\n\t\t} );\n\n\t\tthis.abortPreview();\n\n\t\trequest = this.api.post( options );\n\t\tthis._pending = request.then( function ( resp ) {\n\t\t\tif ( resp && resp.parse && resp.parse.text ) {\n\t\t\t\t// section 0 haven't a section name so skip\n\t\t\t\tif ( self.sectionId !== 0 &&\n\t\t\t\t\tresp.parse.sections !== undefined &&\n\t\t\t\t\tresp.parse.sections[0] !== undefined\n\t\t\t\t) {\n\t\t\t\t\tif ( resp.parse.sections[0].anchor !== undefined ) {\n\t\t\t\t\t\tsectionId = resp.parse.sections[0].anchor;\n\t\t\t\t\t}\n\t\t\t\t\tif ( resp.parse.sections[0].line !== undefined ) {\n\t\t\t\t\t\tsectionLine = resp.parse.sections[0].line;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult.resolve( {\n\t\t\t\t\ttext: resp.parse.text['*'],\n\t\t\t\t\tid: sectionId,\n\t\t\t\t\tline: sectionLine\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tresult.reject();\n\t\t\t}\n\t\t}, function () {\n\t\t\tresult.reject();\n\t\t} ).promise( {\n\t\t\tabort: function () { request.abort(); }\n\t\t} );\n\n\t\treturn result;\n\t}\n};\n\nmodule.exports = EditorGateway;\n","var EditorOverlayBase = require( './EditorOverlayBase' ),\n\tutil = require( '../mobile.startup/util' ),\n\tSection = require( '../mobile.startup/Section' ),\n\tsaveFailureMessage = require( './saveFailureMessage' ),\n\tEditorGateway = require( './EditorGateway' ),\n\tAbuseFilterPanel = require( './AbuseFilterPanel' ),\n\tButton = require( '../mobile.startup/Button' ),\n\tmfExtend = require( '../mobile.startup/mfExtend' ),\n\tBlockMessage = require( './BlockMessage' ),\n\tVisualEditorOverlay = require( './VisualEditorOverlay' ),\n\tMessageBox = require( '../mobile.startup/MessageBox' );\n\n/**\n * Overlay that shows an editor\n * @class EditorOverlay\n * @uses Section\n * @uses AbuseFilterPanel\n * @uses EditorGateway\n * @uses VisualEditorOverlay\n * @extends EditorOverlayBase\n *\n * @param {Object} options Configuration options\n */\nfunction EditorOverlay( options ) {\n\tthis.isFirefox = /firefox/i.test( window.navigator.userAgent );\n\tthis.gateway = new EditorGateway( {\n\t\tapi: options.api,\n\t\ttitle: options.title,\n\t\tsectionId: options.sectionId,\n\t\toldId: options.oldId,\n\t\tisNewPage: options.isNewPage\n\t} );\n\tthis.readOnly = !!options.oldId; // If old revision, readOnly mode\n\tif ( this.isVisualEditorEnabled() ) {\n\t\toptions.editSwitcher = true;\n\t}\n\tif ( this.readOnly ) {\n\t\toptions.readOnly = true;\n\t\toptions.editingMsg = mw.msg( 'mobile-frontend-editor-viewing-source-page', options.title );\n\t} else {\n\t\toptions.editingMsg = mw.msg( 'mobile-frontend-editor-editing-page', options.title );\n\t}\n\t// be explicit here. This may have been initialized from VE.\n\toptions.isVisualEditor = false;\n\toptions.previewingMsg = mw.msg( 'mobile-frontend-editor-previewing-page', options.title );\n\tEditorOverlayBase.call(\n\t\tthis,\n\t\tutil.extend( true,\n\t\t\t{ events: { 'input .wikitext-editor': 'onInputWikitextEditor' } },\n\t\t\toptions\n\t\t)\n\t);\n}\n\nmfExtend( EditorOverlay, EditorOverlayBase, {\n\t/**\n\t * @inheritdoc\n\t * @memberof EditorOverlay\n\t * @instance\n\t */\n\ttemplatePartials: util.extend( {}, EditorOverlayBase.prototype.templatePartials, {\n\t\tcontent: mw.template.get( 'mobile.editor.overlay', 'content.hogan' )\n\t} ),\n\t/**\n\t * @memberof EditorOverlay\n\t * @instance\n\t */\n\teditor: 'wikitext',\n\t/**\n\t * @memberof EditorOverlay\n\t * @instance\n\t */\n\tsectionLine: '',\n\n\t/**\n\t * Check whether VisualEditor is enabled or not.\n\t * @memberof EditorOverlay\n\t * @instance\n\t * @return {boolean}\n\t */\n\tisVisualEditorEnabled: function () {\n\t\tvar ns = mw.config.get( 'wgVisualEditorConfig' ) &&\n\t\t\tmw.config.get( 'wgVisualEditorConfig' ).namespaces;\n\n\t\treturn ns &&\n\t\t\tns.indexOf(\n\t\t\t\tmw.config.get( 'wgNamespaceNumber' )\n\t\t\t) > -1 &&\n\t\t\tmw.config.get( 'wgTranslatePageTranslation' ) !== 'translation' &&\n\t\t\tmw.config.get( 'wgPageContentModel' ) === 'wikitext';\n\t},\n\t/**\n\t * Wikitext Editor input handler\n\t * @memberof EditorOverlay\n\t * @instance\n\t */\n\tonInputWikitextEditor: function () {\n\t\tthis.gateway.setContent( this.$el.find( '.wikitext-editor' ).val() );\n\t\tthis.$el.find( '.continue, .submit' ).prop( 'disabled', false );\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof EditorOverlay\n\t * @instance\n\t */\n\tonClickContinue: function ( ev ) {\n\t\t// handle the click on \"Edit without logging in\"\n\t\tif ( this.options.isAnon && this.$el.find( ev.target ).hasClass( 'anonymous' ) ) {\n\t\t\tthis._showEditorAfterWarning();\n\t\t\treturn false;\n\t\t}\n\t\tEditorOverlayBase.prototype.onClickContinue.apply( this, arguments );\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof EditorOverlay\n\t * @instance\n\t */\n\tonClickBack: function () {\n\t\tEditorOverlayBase.prototype.onClickBack.apply( this, arguments );\n\t\tthis._hidePreview();\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof EditorOverlay\n\t * @instance\n\t */\n\tpostRender: function () {\n\t\tvar self = this,\n\t\t\toptions = this.options,\n\t\t\t$anonWarning = this.$el.find( '.anonwarning' );\n\n\t\tif ( this.isVisualEditorEnabled() ) {\n\t\t\tmw.loader.using( 'ext.visualEditor.switching' ).then( function () {\n\t\t\t\tvar switchToolbar,\n\t\t\t\t\ttoolFactory = new OO.ui.ToolFactory(),\n\t\t\t\t\ttoolGroupFactory = new OO.ui.ToolGroupFactory();\n\n\t\t\t\ttoolFactory.register( mw.libs.ve.MWEditModeVisualTool );\n\t\t\t\ttoolFactory.register( mw.libs.ve.MWEditModeSourceTool );\n\t\t\t\tswitchToolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory, {\n\t\t\t\t\tclasses: [ 'editor-switcher' ]\n\t\t\t\t} );\n\n\t\t\t\tswitchToolbar.on( 'switchEditor', function ( mode ) {\n\t\t\t\t\tif ( mode === 'visual' ) {\n\t\t\t\t\t\t// If the user tries to switch to the VisualEditor,\n\t\t\t\t\t\t// check if any changes have been made,\n\t\t\t\t\t\t// and if so, tell the user they have to save first.\n\t\t\t\t\t\tif ( !self.gateway.hasChanged ) {\n\t\t\t\t\t\t\t// TODO: Be more selective in which options we pass between editors\n\t\t\t\t\t\t\tself._switchToVisualEditor( self.options );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// TODO: Replace with an OOUI dialog\n\t\t\t\t\t\t\tif ( window.confirm( mw.msg( 'mobile-frontend-editor-switch-confirm' ) ) ) {\n\t\t\t\t\t\t\t\tself.onStageChanges();\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\n\t\t\t\tswitchToolbar.setup( [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'editMode',\n\t\t\t\t\t\ttype: 'list',\n\t\t\t\t\t\ticon: 'edit',\n\t\t\t\t\t\ttitle: mw.msg( 'visualeditor-mweditmode-tooltip' ),\n\t\t\t\t\t\tinclude: [ 'editModeVisual', 'editModeSource' ]\n\t\t\t\t\t}\n\t\t\t\t] );\n\n\t\t\t\tself.$el.find( '.switcher-container' ).html( switchToolbar.$element );\n\t\t\t\tswitchToolbar.emit( 'updateState' );\n\t\t\t} );\n\t\t}\n\n\t\tEditorOverlayBase.prototype.postRender.apply( this );\n\n\t\tthis.$preview = this.$el.find( '.preview' );\n\t\tthis.$content = this.$el.find( '.wikitext-editor' );\n\t\tthis.$content.addClass( 'mw-editfont-' + mw.user.options.get( 'editfont' ) );\n\t\tif ( options.isAnon ) {\n\t\t\t// add anonymous warning actions if present\n\t\t\tif ( $anonWarning.length ) {\n\t\t\t\t$anonWarning.find( ' > div' ).prepend(\n\t\t\t\t\tnew MessageBox( {\n\t\t\t\t\t\tclassName: 'warningbox anon-msg',\n\t\t\t\t\t\tmsg: mw.msg( 'mobile-frontend-editor-anonwarning' )\n\t\t\t\t\t} ).$el\n\t\t\t\t);\n\t\t\t\tif ( options.isAnon ) {\n\t\t\t\t\tthis._renderAnonWarning( $anonWarning, options );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.$anonWarning = $anonWarning;\n\t\t\tthis.$content.hide();\n\t\t\t// the user has to click login, signup or edit without login,\n\t\t\t// disable \"Next\" button on top right\n\t\t\tthis.$anonHiddenButtons = this.$el.find( '.overlay-header .continue, .editor-switcher' ).hide();\n\t\t\tthis.hideSpinner();\n\t\t}\n\t\t// make license links open in separate tabs\n\t\tthis.$el.find( '.license a' ).attr( 'target', '_blank' );\n\n\t\tthis.abuseFilterPanel = new AbuseFilterPanel( {\n\t\t\toverlayManager: this.overlayManager\n\t\t} ).appendTo( this.$el.find( '.panels' ) );\n\n\t\t// If in readOnly mode, make textarea readonly\n\t\tif ( this.readOnly ) {\n\t\t\tthis.$content.prop( 'readonly', true );\n\t\t}\n\n\t\tthis.$content.on( 'input', this._resizeEditor.bind( this ) );\n\n\t\tif ( !self.options.isAnon ) {\n\t\t\tthis._loadContent();\n\t\t}\n\t},\n\n\t/**\n\t * Sets additional values used for anonymous editing warning.\n\t * @memberof EditorOverlay\n\t * @instance\n\t * @private\n\t * @param {jQuery.Element} $anonWarning\n\t * @param {Object} options\n\t */\n\t_renderAnonWarning: function ( $anonWarning, options ) {\n\t\tvar params = util.extend( {\n\t\t\t// use wgPageName as this includes the namespace if outside Main\n\t\t\t\treturnto: options.returnTo || mw.config.get( 'wgPageName' ),\n\t\t\t\treturntoquery: 'action=edit&section=' + options.sectionId,\n\t\t\t\twarning: 'mobile-frontend-edit-login-action'\n\t\t\t}, options.queryParams ),\n\t\t\tsignupParams = util.extend( {\n\t\t\t\ttype: 'signup',\n\t\t\t\twarning: 'mobile-frontend-edit-signup-action'\n\t\t\t}, options.signupQueryParams ),\n\t\t\tanonymousEditorActions = [\n\t\t\t\tnew Button( {\n\t\t\t\t\tlabel: mw.msg( 'mobile-frontend-editor-anon' ),\n\t\t\t\t\tblock: true,\n\t\t\t\t\tadditionalClassNames: 'continue anonymous',\n\t\t\t\t\tprogressive: true\n\t\t\t\t} ),\n\t\t\t\tnew Button( {\n\t\t\t\t\tblock: true,\n\t\t\t\t\thref: mw.util.getUrl( 'Special:UserLogin', params ),\n\t\t\t\t\tlabel: mw.msg( 'mobile-frontend-watchlist-cta-button-login' )\n\t\t\t\t} ),\n\t\t\t\tnew Button( {\n\t\t\t\t\tblock: true,\n\t\t\t\t\thref: mw.util.getUrl( 'Special:UserLogin', util.extend( params, signupParams ) ),\n\t\t\t\t\tlabel: mw.msg( 'mobile-frontend-watchlist-cta-button-signup' )\n\t\t\t\t} )\n\t\t\t];\n\n\t\t$anonWarning.find( '.actions' ).append(\n\t\t\tanonymousEditorActions.map( function ( action ) {\n\t\t\t\treturn action.$el;\n\t\t\t} )\n\t\t);\n\t},\n\n\t/**\n\t * Handles click on \"Edit without login\" in anonymous editing warning.\n\t * @memberof EditorOverlay\n\t * @instance\n\t * @private\n\t */\n\t_showEditorAfterWarning: function () {\n\t\tthis.showSpinner();\n\t\tthis.$anonWarning.hide();\n\t\t// reenable \"Next\" button\n\t\tthis.$anonHiddenButtons.show();\n\t\tthis._loadContent();\n\t},\n\n\t/**\n\t * Prepares the preview interface and reveals the save screen of the overlay\n\t * @inheritdoc\n\t * @memberof EditorOverlay\n\t * @instance\n\t */\n\tonStageChanges: function () {\n\t\tvar self = this,\n\t\t\tparams = {\n\t\t\t\ttext: this.getContent()\n\t\t\t};\n\n\t\tthis.scrollTop = util.getDocument().find( 'body' ).scrollTop();\n\t\tthis.$content.hide();\n\t\tthis.showSpinner();\n\n\t\tif ( mw.config.get( 'wgIsMainPage' ) ) {\n\t\t\tparams.mainpage = 1; // Setting it to 0 will have the same effect\n\t\t}\n\n\t\tfunction hideSpinnerAndShowPreview() {\n\t\t\tself.hideSpinner();\n\t\t\tself.$preview.show();\n\t\t}\n\n\t\tthis.gateway.getPreview( params ).then( function ( result ) {\n\t\t\tvar parsedText = result.text,\n\t\t\t\tparsedSectionLine = result.line;\n\n\t\t\tself.sectionId = result.id;\n\t\t\t// On desktop edit summaries strip tags. Mimic this behavior on mobile devices\n\t\t\tself.sectionLine = self.parseHTML( '<div>' ).html( parsedSectionLine ).text();\n\t\t\tnew Section( {\n\t\t\t\tel: self.$preview,\n\t\t\t\ttext: parsedText\n\t\t\t} ).$el.find( 'a' ).on( 'click', false );\n\n\t\t\thideSpinnerAndShowPreview();\n\t\t}, function () {\n\t\t\tself.$preview.addClass( 'error' ).text( mw.msg( 'mobile-frontend-editor-error-preview' ) );\n\n\t\t\thideSpinnerAndShowPreview();\n\t\t} );\n\n\t\tEditorOverlayBase.prototype.onStageChanges.apply( this, arguments );\n\t},\n\n\t/**\n\t * Hides the preview and reverts back to initial screen.\n\t * @memberof EditorOverlay\n\t * @instance\n\t * @private\n\t */\n\t_hidePreview: function () {\n\t\tthis.gateway.abortPreview();\n\t\tthis.hideSpinner();\n\t\tthis.$preview.removeClass( 'error' ).hide();\n\t\tthis.$content.show();\n\t\twindow.scrollTo( 0, this.scrollTop );\n\t\tthis.showHidden( '.initial-header' );\n\t\tthis.abuseFilterPanel.hide();\n\t},\n\n\t/**\n\t * Resize the editor textarea, maintaining scroll position in iOS\n\t * @memberof EditorOverlay\n\t * @instance\n\t */\n\t_resizeEditor: function () {\n\t\tvar scrollTop, container, $scrollContainer;\n\n\t\t// exiting early for firefox due to a bug that causes the page to scroll to top\n\t\t// whenever a caret is inserted T214880\n\t\tif ( this.isFirefox ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !this.$scrollContainer ) {\n\t\t\tcontainer = OO.ui.Element.static\n\t\t\t\t.getClosestScrollableContainer( this.$content[ 0 ] );\n\t\t\t// The scroll container will be either within the view\n\t\t\t// or the document element itself.\n\t\t\t$scrollContainer = this.$el.find( container ).length ?\n\t\t\t\tthis.$el.find( container ) : util.getDocument();\n\t\t\tthis.$scrollContainer = $scrollContainer;\n\t\t\tthis.$content.css( 'padding-bottom', this.$scrollContainer.height() * 0.6 );\n\t\t} else {\n\t\t\t$scrollContainer = this.$scrollContainer;\n\t\t}\n\n\t\t// Only do this if scroll container exists\n\t\tif ( this.$content.prop( 'scrollHeight' ) && $scrollContainer.length ) {\n\t\t\tscrollTop = $scrollContainer.scrollTop();\n\t\t\tthis.$content\n\t\t\t\t.css( 'height', 'auto' )\n\t\t\t\t// can't reuse prop( 'scrollHeight' ) because we need the current value\n\t\t\t\t.css( 'height', ( this.$content.prop( 'scrollHeight' ) + 2 ) + 'px' );\n\t\t\t$scrollContainer.scrollTop( scrollTop );\n\t\t}\n\t},\n\n\t/**\n\t * Set content to the user input field.\n\t * @memberof EditorOverlay\n\t * @instance\n\t * @param {string} content The content to set.\n\t */\n\tsetContent: function ( content ) {\n\t\tthis.$content\n\t\t\t.show()\n\t\t\t.val( content );\n\t\tthis._resizeEditor();\n\t},\n\n\t/**\n\t * Returns the content of the user input field.\n\t * @memberof EditorOverlay\n\t * @instance\n\t * @return {string}\n\t */\n\tgetContent: function () {\n\t\treturn this.$content.val();\n\t},\n\n\t/**\n\t * @memberof EditorOverlay\n\t * @instance\n\t * @param {string} data\n\t * @return {string|false}\n\t */\n\t_parseBlockInfo: function ( data ) {\n\t\tvar blockInfo, expiry, reason,\n\t\t\tmoment = window.moment;\n\n\t\t// Workaround to parse a message parameter for mw.message, see T96885\n\t\tfunction jqueryMsgParse( wikitext ) {\n\t\t\tvar parser, ast;\n\t\t\t// eslint-disable-next-line new-cap\n\t\t\tparser = new mw.jqueryMsg.parser();\n\t\t\ttry {\n\t\t\t\tast = parser.wikiTextToAst( wikitext );\n\t\t\t\treturn parser.emitter.emit( ast ).html();\n\t\t\t} catch ( e ) {\n\t\t\t\t// Ignore error as it's probably the parser error. Usually this is because we\n\t\t\t\t// can't parse templates.\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tblockInfo = {\n\t\t\tpartial: data.blockinfo.blockpartial || false,\n\t\t\tuser: data.userinfo,\n\t\t\tcreator: {\n\t\t\t\tname: data.blockinfo.blockedby,\n\t\t\t\t// NS_USER === 2\n\t\t\t\turl: mw.util.getUrl(\n\t\t\t\t\tmw.config.get( 'wgFormattedNamespaces' )[2] + ':' +\n\t\t\t\t\tdata.blockinfo.blockedby\n\t\t\t\t)\n\t\t\t},\n\t\t\texpiry: null,\n\t\t\tduration: null,\n\t\t\treason: '',\n\t\t\tblockId: data.blockinfo.blockid\n\t\t};\n\n\t\texpiry = data.blockinfo.blockexpiry;\n\t\tif ( [ 'infinite', 'indefinite', 'infinity', 'never' ].indexOf( expiry ) === -1 ) {\n\t\t\tblockInfo.expiry = moment( expiry ).format( 'LLL' );\n\t\t\tblockInfo.duration = moment().to( expiry, true );\n\t\t}\n\n\t\treason = data.blockinfo.blockreason;\n\t\tif ( reason ) {\n\t\t\tblockInfo.reason = jqueryMsgParse( reason ) || mw.html.escape( reason );\n\t\t} else {\n\t\t\tblockInfo.reason = mw.message( 'mobile-frontend-editor-generic-block-reason' ).escaped();\n\t\t}\n\n\t\treturn blockInfo;\n\t},\n\n\t/**\n\t * Requests content from the API and reveals it in UI.\n\t * @memberof EditorOverlay\n\t * @instance\n\t * @private\n\t */\n\t_loadContent: function () {\n\t\tvar self = this,\n\t\t\t$el = this.$el;\n\n\t\tthis.$content.hide();\n\t\tthis.showSpinner();\n\t\t$el.addClass( 'overlay-loading' );\n\n\t\tthis.gateway.getContent()\n\t\t\t.then( function ( result ) {\n\t\t\t\tvar block, message,\n\t\t\t\t\tcontent = result.text;\n\n\t\t\t\tself.setContent( content );\n\t\t\t\t// check if user is blocked\n\t\t\t\tif ( result.blockinfo ) {\n\t\t\t\t\t// Lazy-load moment only if it's needed,\n\t\t\t\t\t// it's somewhat large (it is already used on\n\t\t\t\t\t// mobile by Echo's notifications panel, where it's also lazy-loaded)\n\t\t\t\t\tmw.loader.using( 'moment' ).then( function () {\n\t\t\t\t\t\tblock = self._parseBlockInfo( result );\n\t\t\t\t\t\tmessage = new BlockMessage( block );\n\t\t\t\t\t\tmessage.toggle();\n\t\t\t\t\t\tself.hide();\n\t\t\t\t\t\tself.hideSpinner();\n\t\t\t\t\t\t$el.removeClass( 'overlay-loading' );\n\t\t\t\t\t} );\n\t\t\t\t} else {\n\t\t\t\t\tself.hideSpinner();\n\t\t\t\t\t$el.removeClass( 'overlay-loading' );\n\t\t\t\t}\n\t\t\t}, function () {\n\t\t\t\tself.reportError( mw.msg( 'mobile-frontend-editor-error-loading' ) );\n\t\t\t\t$el.removeClass( 'overlay-loading' );\n\t\t\t} );\n\t},\n\n\t/**\n\t * Loads a {VisualEditorOverlay} and replaces the existing EditorOverlay with it\n\t * based on the current option values.\n\t * @memberof EditorOverlay\n\t * @instance\n\t * @private\n\t * @param {Object} options Object passed to the constructor\n\t */\n\t_switchToVisualEditor: function ( options ) {\n\t\tvar self = this;\n\t\tthis.log( {\n\t\t\taction: 'abort',\n\t\t\ttype: 'switchnochange',\n\t\t\tmechanism: 'navigate'\n\t\t} );\n\t\t// Save a user setting indicating that this user prefers using the VisualEditor\n\t\tmw.storage.set( 'preferredEditor', 'VisualEditor' );\n\t\t// Load the VisualEditor and replace the SourceEditor overlay with it\n\t\tthis.showSpinner();\n\t\tthis.$content.hide();\n\t\tmw.loader.using( 'ext.visualEditor.targetLoader' ).then( function () {\n\t\t\tmw.libs.ve.targetLoader.addPlugin( 'mobile.editor.ve' );\n\t\t\treturn mw.libs.ve.targetLoader.loadModules( 'visual' );\n\t\t} ).then(\n\t\t\tfunction () {\n\t\t\t\toptions.EditorOverlay = EditorOverlay;\n\t\t\t\toptions.switched = true;\n\t\t\t\tself.hideSpinner();\n\t\t\t\t// Unset classes from other editor\n\t\t\t\tdelete options.className;\n\t\t\t\tself.switching = true;\n\t\t\t\tself.overlayManager.replaceCurrent( new VisualEditorOverlay( options ) );\n\t\t\t\tself.switching = false;\n\t\t\t},\n\t\t\tfunction () {\n\t\t\t\tself.hideSpinner();\n\t\t\t\tself.$content.show();\n\t\t\t\t// FIXME: We should show an error notification, but right now toast\n\t\t\t\t// notifications are not dismissible when shown within the editor.\n\t\t\t}\n\t\t);\n\t},\n\n\t/**\n\t * Reveals an abuse filter panel inside the view.\n\t * @memberof EditorOverlay\n\t * @instance\n\t * @private\n\t * @param {string} type The type of alert, e.g. 'warning' or 'disallow'\n\t * @param {string} message Message to show in the AbuseFilter overlay\n\t */\n\t_showAbuseFilter: function ( type, message ) {\n\t\tthis.abuseFilterPanel.show( type, message );\n\t\tthis.showHidden( '.save-header' );\n\t\t// disable continue and save buttons, reenabled when user changes content\n\t\tthis.$el.find( '.continue, .submit' ).prop( 'disabled', this.abuseFilterPanel.isDisallowed );\n\t},\n\n\t/**\n\t * Executed when the editor clicks the save/publish button. Handles logging and submitting\n\t * the save action to the editor API.\n\t * @inheritdoc\n\t * @memberof EditorOverlay\n\t * @instance\n\t */\n\tonSaveBegin: function () {\n\t\tvar self = this,\n\t\t\toptions = {\n\t\t\t\tsummary: this.$el.find( '.summary' ).val()\n\t\t\t};\n\n\t\tif ( self.sectionLine !== '' ) {\n\t\t\toptions.summary = '/* ' + self.sectionLine + ' */' + options.summary;\n\t\t}\n\t\tEditorOverlayBase.prototype.onSaveBegin.apply( this, arguments );\n\t\tif ( this.confirmAborted ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( this.captchaId ) {\n\t\t\toptions.captchaId = this.captchaId;\n\t\t\toptions.captchaWord = this.$el.find( '.captcha-word' ).val();\n\t\t}\n\n\t\tthis.showHidden( '.saving-header' );\n\n\t\tthis.gateway.save( options )\n\t\t\t.then( function () {\n\t\t\t\tvar title = self.options.title;\n\t\t\t\t// Special case behaviour of main page\n\t\t\t\tif ( mw.config.get( 'wgIsMainPage' ) ) {\n\t\t\t\t\t// FIXME: Blocked on T189173\n\t\t\t\t\t// eslint-disable-next-line no-restricted-properties\n\t\t\t\t\twindow.location = mw.util.getUrl( title );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tself.onSaveComplete();\n\t\t\t}, function ( data ) {\n\t\t\t\tself.onSaveFailure( data );\n\t\t\t} );\n\t},\n\n\t/**\n\t * Executed when page save fails. Handles error display and bookkeeping,\n\t * passes logging duties to the parent.\n\t * @inheritdoc\n\t * @memberof EditorOverlay\n\t * @instance\n\t */\n\tonSaveFailure: function ( data ) {\n\t\tvar heading, msg;\n\n\t\tif ( data.type === 'captcha' ) {\n\t\t\tthis.captchaId = data.details.id;\n\t\t\tthis.handleCaptcha( data.details );\n\t\t} else if ( data.type === 'abusefilter' ) {\n\t\t\tthis._showAbuseFilter( data.details.type, data.details.message );\n\t\t} else {\n\t\t\tmsg = saveFailureMessage( data );\n\t\t\tif ( data.type === 'readonly' ) {\n\t\t\t\theading = mw.msg( 'apierror-readonly' );\n\t\t\t}\n\n\t\t\tif ( msg || heading ) {\n\t\t\t\tthis.reportError( msg, heading );\n\t\t\t\tthis.showHidden( '.save-header, .save-panel' );\n\t\t\t}\n\t\t}\n\n\t\tEditorOverlayBase.prototype.onSaveFailure.apply( this, arguments );\n\t},\n\n\t/**\n\t * Checks whether the existing content has changed.\n\t * @memberof EditorOverlay\n\t * @instance\n\t * @return {boolean}\n\t */\n\thasChanged: function () {\n\t\treturn this.gateway.hasChanged;\n\t}\n} );\n\nmodule.exports = EditorOverlay;\n","var Overlay = require( '../mobile.startup/Overlay' ),\n\tutil = require( '../mobile.startup/util' ),\n\tPageGateway = require( '../mobile.startup/PageGateway' ),\n\tIcon = require( '../mobile.startup/Icon' ),\n\ttoast = require( '../mobile.startup/toast' ),\n\tsaveFailureMessage = require( './saveFailureMessage' ),\n\tmfExtend = require( '../mobile.startup/mfExtend' ),\n\tMessageBox = require( '../mobile.startup/MessageBox' ),\n\tmwUser = mw.user;\n\n/**\n * 'Edit' button\n * @param {OO.ui.ToolGroup} toolGroup\n * @param {Object} config\n */\nfunction EditVeTool( toolGroup, config ) {\n\tconfig = config || {};\n\tconfig.classes = [ 'visual-editor' ];\n\tEditVeTool.super.call( this, toolGroup, config );\n}\nOO.inheritClass( EditVeTool, OO.ui.Tool );\n\nEditVeTool.static.name = 'editVe';\nEditVeTool.static.icon = 'edit';\nEditVeTool.static.group = 'editorSwitcher';\nEditVeTool.static.title = mw.msg( 'mobile-frontend-editor-switch-visual-editor' );\n/**\n * click handler\n * @memberof EditVeTool\n * @instance\n */\nEditVeTool.prototype.onSelect = function () {\n\t// will be overridden later\n};\n/**\n * Toolbar update state handler.\n * @memberof EditVeTool\n * @instance\n */\nEditVeTool.prototype.onUpdateState = function () {\n\t// do nothing\n};\n\n/**\n * Base class for EditorOverlay\n * @class EditorOverlayBase\n * @extends Overlay\n * @uses Icon\n * @uses user\n * @param {Object} params Configuration options\n * @param {number|null} params.editCount of user\n */\nfunction EditorOverlayBase( params ) {\n\tvar self = this,\n\t\toptions = util.extend(\n\t\t\ttrue,\n\t\t\t{\n\t\t\t\tclassName: 'overlay editor-overlay',\n\t\t\t\tisBorderBox: false\n\t\t\t},\n\t\t\tparams,\n\t\t\t{\n\t\t\t\tevents: util.extend(\n\t\t\t\t\t{\n\t\t\t\t\t\t'click .back': 'onClickBack',\n\t\t\t\t\t\t'click .continue': 'onClickContinue',\n\t\t\t\t\t\t'click .submit': 'onClickSubmit'\n\t\t\t\t\t},\n\t\t\t\t\tparams.events\n\t\t\t\t)\n\t\t\t}\n\t\t);\n\n\tif ( options.isNewPage ) {\n\t\toptions.placeholder = mw.msg( 'mobile-frontend-editor-placeholder-new-page', mwUser );\n\t}\n\t// change the message to request a summary when not in article namespace\n\tif ( mw.config.get( 'wgNamespaceNumber' ) !== 0 ) {\n\t\toptions.summaryRequestMsg = mw.msg( 'mobile-frontend-editor-summary' );\n\t}\n\tthis.pageGateway = new PageGateway( options.api );\n\tthis.editCount = options.editCount;\n\tthis.isNewPage = options.isNewPage;\n\tthis.isNewEditor = options.editCount === 0;\n\tthis.sectionId = options.sectionId;\n\t// FIXME: Pass this in via options rather than accessing mw.config\n\tthis.config = mw.config.get( 'wgMFEditorOptions' );\n\tthis.sessionId = options.sessionId;\n\tthis.overlayManager = options.overlayManager;\n\tthis.allowCloseWindow = mw.confirmCloseWindow( {\n\t\t// Returns true if content has changed\n\t\ttest: function () {\n\t\t\t// Check if content has changed\n\t\t\treturn self.hasChanged();\n\t\t},\n\n\t\t// Message to show the user, if content has changed\n\t\tmessage: mw.msg( 'mobile-frontend-editor-cancel-confirm' ),\n\t\t// Event namespace\n\t\tnamespace: 'editwarning'\n\t} );\n\n\tOverlay.call( this, options );\n}\n\nmfExtend( EditorOverlayBase, Overlay, {\n\t/**\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t * @mixes Overlay#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {OverlayManager} defaults.overlayManager instance\n\t * @property {mw.Api} defaults.api to interact with\n\t * @property {boolean} defaults.hasToolbar Whether the editor has a toolbar or not. When\n\t *  disabled a header will be show instead.\n\t * @property {string} defaults.continueMsg Caption for the next button on edit form\n\t * which takes you to the screen that shows a preview and license information.\n\t * @property {string} defaults.cancelMsg Caption for cancel button on edit form.\n\t * @property {string} defaults.closeMsg Caption for a button that takes you back to editing\n\t * from edit preview screen.\n\t * @property {string} defaults.summaryRequestMsg Header above edit summary input field\n\t * asking the user to summarize the changes they made to the page.\n\t * @property {string} defaults.summaryMsg A placeholder with examples for the summary input\n\t * field asking user what they changed.\n\t * @property {string} defaults.placeholder Placeholder text for empty sections.\n\t * @property {string} defaults.waitMsg Text that displays while a page edit is being saved.\n\t * @property {string} defaults.waitIcon HTML of the icon that displays while a page edit\n\t * is being saved.\n\t * @property {string} defaults.captchaMsg Placeholder for captcha input field.\n\t * @property {string} defaults.captchaTryAgainMsg A message shown when user enters\n\t * wrong CAPTCHA and a new one is displayed.\n\t * @property {string} defaults.switchMsg Label for button that allows the user\n\t * to switch between two different editing interfaces.\n\t * @property {string} defaults.licenseMsg Text and link of the license,\n\t * under which this contribution will be released to inform the user.\n\t */\n\tdefaults: util.extend( {}, Overlay.prototype.defaults, {\n\t\thasToolbar: false,\n\t\tcontinueMsg: mw.msg( 'mobile-frontend-editor-continue' ),\n\t\tcancelMsg: mw.msg( 'mobile-frontend-editor-cancel' ),\n\t\tcloseMsg: mw.msg( 'mobile-frontend-editor-keep-editing' ),\n\t\tsummaryRequestMsg: mw.msg( 'mobile-frontend-editor-summary-request' ),\n\t\tsummaryMsg: mw.msg( 'mobile-frontend-editor-summary-placeholder' ),\n\t\tplaceholder: mw.msg( 'mobile-frontend-editor-placeholder' ),\n\t\twaitMsg: mw.msg( 'mobile-frontend-editor-wait' ),\n\t\t// icons.spinner can't be used,\n\t\t// the spinner class changes to display:none in onStageChanges\n\t\twaitIcon: new Icon( {\n\t\t\tname: 'spinner',\n\t\t\tadditionalClassNames: 'savespinner loading'\n\t\t} ).toHtmlString(),\n\t\tcaptchaMsg: mw.msg( 'mobile-frontend-account-create-captcha-placeholder' ),\n\t\tcaptchaTryAgainMsg: mw.msg( 'mobile-frontend-editor-captcha-try-again' ),\n\t\tswitchMsg: mw.msg( 'mobile-frontend-editor-switch-editor' ),\n\t\tconfirmMsg: mw.msg( 'mobile-frontend-editor-cancel-confirm' ),\n\t\tlicenseMsg: undefined\n\t} ),\n\t/**\n\t * @inheritdoc\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t */\n\ttemplatePartials: util.extend( {}, Overlay.prototype.templatePartials, {\n\t\teditHeader: mw.template.get( 'mobile.editor.overlay', 'editHeader.hogan' ),\n\t\tpreviewHeader: mw.template.get( 'mobile.editor.overlay', 'previewHeader.hogan' ),\n\t\tsaveHeader: mw.template.get( 'mobile.editor.overlay', 'saveHeader.hogan' )\n\t} ),\n\t/**\n\t * @inheritdoc\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t */\n\ttemplate: mw.template.get( 'mobile.editor.overlay', 'EditorOverlayBase.hogan' ),\n\t/**\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t */\n\tsectionId: '',\n\t/**\n\t * Logs an event to http://meta.wikimedia.org/wiki/Schema:EditAttemptStep\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t * @param {Object} data\n\t */\n\tlog: function ( data ) {\n\t\tmw.track( 'mf.schemaEditAttemptStep', util.extend( data, {\n\t\t\t// eslint-disable-next-line camelcase\n\t\t\teditor_interface: this.editor,\n\t\t\t// eslint-disable-next-line camelcase\n\t\t\tediting_session_id: this.sessionId\n\t\t} ) );\n\t},\n\n\t/**\n\t * If this is a new article, require confirmation before saving.\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t * @return {boolean} The user confirmed saving\n\t */\n\tconfirmSave: function () {\n\t\tif ( this.isNewPage &&\n\t\t\t// TODO: Replace with an OOUI dialog\n\t\t\t!window.confirm( mw.msg( 'mobile-frontend-editor-new-page-confirm', mwUser ) )\n\t\t) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\treturn true;\n\t\t}\n\t},\n\t/**\n\t * Executed when page save is complete. Handles reloading the page, showing toast\n\t * messages.\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t */\n\tonSaveComplete: function () {\n\t\tvar msg,\n\t\t\t$window = util.getWindow(),\n\t\t\ttitle = this.options.title,\n\t\t\tself = this;\n\n\t\tthis.saved = true;\n\n\t\t// FIXME: use generic method for following 3 lines\n\t\tthis.pageGateway.invalidatePage( title );\n\n\t\tif ( this.isNewPage ) {\n\t\t\tmsg = mw.msg( 'mobile-frontend-editor-success-new-page' );\n\t\t} else if ( this.isNewEditor ) {\n\t\t\tmsg = mw.msg( 'mobile-frontend-editor-success-landmark-1' );\n\t\t} else {\n\t\t\tmsg = mw.msg( 'mobile-frontend-editor-success' );\n\t\t}\n\t\ttoast.showOnPageReload( msg, { type: 'success' } );\n\n\t\t// Ensure we don't lose this event when logging\n\t\tthis.log( {\n\t\t\taction: 'saveSuccess'\n\t\t} );\n\t\tif ( self.sectionId ) {\n\t\t\t// Ideally we'd want to do this via replaceState (see T189173)\n\t\t\t// eslint-disable-next-line no-restricted-properties\n\t\t\twindow.location.hash = '#' + self.sectionId;\n\t\t} else {\n\t\t\t// Cancel the hash fragment\n\t\t\t// otherwise clicking back after a save will take you back to the editor.\n\t\t\t// We avoid calling the hide method of the overlay here as this can be asynchronous\n\t\t\t// and may conflict with the window.reload call below.\n\t\t\t// eslint-disable-next-line no-restricted-properties\n\t\t\twindow.location.hash = '#';\n\t\t}\n\n\t\t$window.off( 'beforeunload.mfeditorwarning' );\n\n\t\t// Note the \"#\" may be in the URL.\n\t\t// If so, using window.location alone will not reload the page\n\t\t// we need to forcefully refresh\n\t\t// eslint-disable-next-line no-restricted-properties\n\t\twindow.location.reload();\n\t},\n\t/**\n\t * Executed when page save fails. Handles logging the error. Subclasses\n\t * should display error messages as appropriate.\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t * @param {Object} data Details about the failure, from EditorGateway.parseSaveError\n\t */\n\tonSaveFailure: function ( data ) {\n\t\tvar key = data && data.details && data.details.code,\n\t\t\ttypeMap = {\n\t\t\t\teditconflict: 'editConflict',\n\t\t\t\twasdeleted: 'editPageDeleted',\n\t\t\t\t'abusefilter-disallowed': 'extensionAbuseFilter',\n\t\t\t\tcaptcha: 'extensionCaptcha',\n\t\t\t\tspamprotectiontext: 'extensionSpamBlacklist',\n\t\t\t\t'titleblacklist-forbidden-edit': 'extensionTitleBlacklist'\n\t\t\t};\n\n\t\tif ( data.type === 'captcha' ) {\n\t\t\tkey = 'captcha';\n\t\t}\n\n\t\tthis.log( {\n\t\t\taction: 'saveFailure',\n\t\t\tmessage: saveFailureMessage( data ),\n\t\t\ttype: typeMap[key] || 'responseUnknown'\n\t\t} );\n\t},\n\t/**\n\t * Report load errors back to the user. Silently record the error using EventLogging.\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t * @param {string} text Text of message to display to user\n\t * @param {string} heading heading text to display to user\n\t */\n\treportError: function ( text, heading ) {\n\t\tvar errorNotice = new MessageBox( {\n\t\t\tclassName: 'errorbox',\n\t\t\tmsg: text,\n\t\t\theading: heading\n\t\t} );\n\t\tthis.$errorNoticeContainer.html( errorNotice.$el );\n\t},\n\thideErrorNotice: function () {\n\t\tthis.$errorNoticeContainer.empty();\n\t},\n\t/**\n\t * Prepares the penultimate screen before saving.\n\t * Expects to be overridden by child class.\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t */\n\tonStageChanges: function () {\n\t\tthis.showHidden( '.save-header, .save-panel' );\n\t\tthis.log( {\n\t\t\taction: 'saveIntent'\n\t\t} );\n\t\t// Scroll to the top of the page, so that the summary input is visible\n\t\t// (even if overlay was scrolled down when editing) and weird iOS header\n\t\t// problems are avoided (header position not updating to the top of the\n\t\t// screen, instead staying lower until a subsequent scroll event).\n\t\twindow.scrollTo( 0, 1 );\n\t},\n\t/**\n\t * Executed when the editor clicks the save button. Expects to be overridden by child\n\t * class. Checks if the save needs to be confirmed.\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t */\n\tonSaveBegin: function () {\n\t\tthis.confirmAborted = false;\n\t\tthis.hideErrorNotice();\n\t\t// Ask for confirmation in some cases\n\t\tif ( !this.confirmSave() ) {\n\t\t\tthis.confirmAborted = true;\n\t\t\treturn;\n\t\t}\n\t\tthis.log( {\n\t\t\taction: 'saveAttempt'\n\t\t} );\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t */\n\tpostRender: function () {\n\t\t// log edit attempt\n\t\t// TODO: if VE/NWE become the default, or even loadable-by-URL, this\n\t\t// logging needs to be moved into the individual overlays, because postRender\n\t\t// for VE still wouldn't technically be 'ready'.\n\t\tthis.log( {\n\t\t\taction: 'ready'\n\t\t} );\n\t\tthis.log( {\n\t\t\taction: 'loaded'\n\t\t} );\n\n\t\t// decide what happens, when the user clicks the continue button\n\t\tif ( this.config.skipPreview ) {\n\t\t\t// skip the preview and save the changes\n\t\t\tthis.nextStep = 'onSaveBegin';\n\t\t\tthis.$el.find( '.continue' ).text( this.defaults.saveMsg );\n\t\t} else {\n\t\t\t// default: show the preview step\n\t\t\tthis.nextStep = 'onStageChanges';\n\t\t}\n\t\tthis.$errorNoticeContainer = this.$el.find( '#error-notice-container' );\n\n\t\tOverlay.prototype.postRender.apply( this );\n\n\t\tthis.showHidden( '.initial-header' );\n\t},\n\tshow: function () {\n\t\tthis.saved = false;\n\t\tOverlay.prototype.show.call( this );\n\n\t\t// Inform other interested code that the editor has loaded\n\t\tmw.hook( 'mobileFrontend.editorOpened' ).fire( this.editor );\n\t},\n\t/**\n\t * Back button click handler\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t */\n\tonClickBack: function () {},\n\t/**\n\t * Submit button click handler\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t */\n\tonClickSubmit: function () {\n\t\tthis.onSaveBegin();\n\t},\n\t/**\n\t * Continue button click handler\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t */\n\tonClickContinue: function () {\n\t\tthis[this.nextStep]();\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t * @return {boolean|jQuery.Promise} Boolean, or promise resolving with a boolean\n\t */\n\thide: function () {\n\t\tvar windowManager,\n\t\t\tself = this;\n\t\tif ( this.hasChanged() ) {\n\t\t\twindowManager = OO.ui.getWindowManager();\n\t\t\twindowManager.addWindows( [ new mw.widgets.AbandonEditDialog() ] );\n\t\t\treturn windowManager.openWindow( 'abandonedit' )\n\t\t\t\t.closed.then( function ( data ) {\n\t\t\t\t\tif ( data && data.action === 'discard' ) {\n\t\t\t\t\t\t// log abandonment\n\t\t\t\t\t\tself.log( {\n\t\t\t\t\t\t\taction: 'abort',\n\t\t\t\t\t\t\tmechanism: 'cancel',\n\t\t\t\t\t\t\ttype: 'abandon'\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tself.allowCloseWindow.release();\n\t\t\t\t\t\tmw.hook( 'mobileFrontend.editorClosed' ).fire();\n\t\t\t\t\t\tOverlay.prototype.hide.call( self );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}\n\t\tif ( !this.switching && !this.saved ) {\n\t\t\t// log leaving without changes\n\t\t\tthis.log( {\n\t\t\t\taction: 'abort',\n\t\t\t\tmechanism: 'cancel',\n\t\t\t\t// if this is VE, hasChanged will be false because the Surface has\n\t\t\t\t// already been destroyed (which is good because it stops us\n\t\t\t\t// double-showing the abandon changes dialog above)... but we can\n\t\t\t\t// test whether there *were* changes for logging purposes by\n\t\t\t\t// examining the target:\n\t\t\t\ttype: ( this.target && this.target.edited ) ? 'abandon' : 'nochange'\n\t\t\t} );\n\t\t}\n\t\tthis.allowCloseWindow.release();\n\t\tmw.hook( 'mobileFrontend.editorClosed' ).fire();\n\t\treturn Overlay.prototype.hide.call( self );\n\t},\n\t/**\n\t * Check, if the user should be asked if they really want to leave the page.\n\t * Returns false, if he hasn't made changes, otherwise true.\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t * @param {boolean} [force] Whether this function should always return false\n\t * @return {boolean}\n\t */\n\tshouldConfirmLeave: function ( force ) {\n\t\tif ( force || !this.hasChanged() ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\n\t},\n\t/**\n\t * Checks whether the state of the thing being edited as changed. Expects to be\n\t * implemented by child class.\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t */\n\thasChanged: function () {},\n\t/**\n\t * Handles a failed save due to a CAPTCHA provided by ConfirmEdit extension.\n\t * @memberof EditorOverlayBase\n\t * @instance\n\t * @param {Object} details Details returned from the api.\n\t */\n\thandleCaptcha: function ( details ) {\n\t\tvar self = this,\n\t\t\t$input = this.$el.find( '.captcha-word' );\n\n\t\tif ( this.captchaShown ) {\n\t\t\t$input.val( '' );\n\t\t\t$input.attr( 'placeholder', this.options.captchaTryAgainMsg );\n\t\t\tsetTimeout( function () {\n\t\t\t\t$input.attr( 'placeholder', self.options.captchaMsg );\n\t\t\t}, 2000 );\n\t\t}\n\n\t\t// handle different mime types different\n\t\tif ( details.mime.indexOf( 'image/' ) === 0 ) {\n\t\t\t// image based CAPTCHA's like provided by FancyCaptcha, ReCaptcha or similar\n\t\t\tthis.$el.find( '.captcha-panel#question' ).detach();\n\t\t\tthis.$el.find( '.captcha-panel img' ).attr( 'src', details.url );\n\t\t} else {\n\t\t\t// not image based CAPTCHA.\n\t\t\tthis.$el.find( '.captcha-panel #image' ).detach();\n\t\t\tif ( details.mime.indexOf( 'text/html' ) === 0 ) {\n\t\t\t\t// handle mime type of HTML as HTML content (display as-is).\n\t\t\t\t// QuestyCaptcha now have default MIME type \"text/html\": see T147606\n\t\t\t\tthis.$el.find( '.captcha-panel #question' ).html( details.question );\n\t\t\t} else {\n\t\t\t\t// handle mime types\n\t\t\t\t// (other than image based ones and HTML based ones)\n\t\t\t\t// as plain text by default.\n\t\t\t\t// e.g. MathCaptcha (solve a math formula) or\n\t\t\t\t// SimpleCaptcha (simple math formula)\n\t\t\t\tthis.$el.find( '.captcha-panel #question' ).text( details.question );\n\t\t\t}\n\t\t}\n\n\t\tthis.showHidden( '.save-header, .captcha-panel' );\n\t\tthis.captchaShown = true;\n\t}\n} );\n\nmodule.exports = EditorOverlayBase;\n","/* global ve */\nvar EditorOverlayBase = require( './EditorOverlayBase' ),\n\tEditorGateway = require( './EditorGateway' ),\n\tmfExtend = require( '../mobile.startup/mfExtend' ),\n\tutil = require( '../mobile.startup/util' );\n\n/**\n * Overlay for VisualEditor view\n * @class VisualEditorOverlay\n * @extends EditorOverlayBase\n *\n * @param {Object} options Configuration options\n * @param {EditorOverlay} options.EditorOverlay Class to use for standard\n *  Wikitext editor. It must be passed in explicitly to avoid a cyclic\n *  dependency between VisualEdtiorOverlay and EditorOverlay\n */\nfunction VisualEditorOverlay( options ) {\n\tthis.applyHeaderOptions( options, true );\n\tEditorOverlayBase.call( this,\n\t\tutil.extend( {\n\t\t\tisBorderBox: false,\n\t\t\tclassName: 'overlay editor-overlay editor-overlay-ve'\n\t\t}, options )\n\t);\n\tthis.EditorOverlay = options.EditorOverlay;\n\tthis.isNewPage = options.isNewPage;\n\n\t// Gateway present for a few utility purposes; the VE articletarget\n\t// handles the actual API calls separately\n\tthis.gateway = new EditorGateway( {\n\t\tapi: options.api,\n\t\ttitle: options.title,\n\t\tsectionId: options.sectionId,\n\t\toldId: options.oldId,\n\t\tisNewPage: options.isNewPage\n\t} );\n}\n\nmfExtend( VisualEditorOverlay, EditorOverlayBase, {\n\t/**\n\t * @inheritdoc\n\t * @memberof VisualEditorOverlay\n\t * @instance\n\t */\n\ttemplatePartials: util.extend( {}, EditorOverlayBase.prototype.templatePartials, {\n\t\teditHeader: mw.template.get( 'mobile.editor.overlay', 'toolbarVE.hogan' ),\n\t\tcontent: mw.template.get( 'mobile.editor.overlay', 'contentVE.hogan' )\n\t} ),\n\t/**\n\t * @memberof VisualEditorOverlay\n\t * @instance\n\t */\n\teditor: 'visualeditor',\n\t/**\n\t * Set options that apply specifically to VisualEditorOverlay but not\n\t * EditorOverlay so that an EditorOverlay instance can be created effortlessly.\n\t * FIXME: Must be smarter way to do this.\n\t * @memberof VisualEditorOverlay\n\t * @instance\n\t * @param {Object} options Configuration options\n\t * @param {boolean} isVE whether the options are being generated for a VisualEditorOverlay\n\t *  or a EditorOverlay\n\t */\n\tapplyHeaderOptions: function ( options, isVE ) {\n\t\t// Set things that are known to be true.\n\t\toptions.hasToolbar = isVE;\n\t\toptions.isVisualEditor = isVE;\n\t},\n\t/**\n\t * Destroy the existing VisualEditor target.\n\t * @memberof VisualEditorOverlay\n\t * @instance\n\t */\n\tdestroyTarget: function () {\n\t\tif ( this.target ) {\n\t\t\tthis.target.destroy();\n\t\t\tthis.target = null;\n\t\t}\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof VisualEditorOverlay\n\t * @instance\n\t */\n\tshow: function () {\n\t\tEditorOverlayBase.prototype.show.apply( this, arguments );\n\n\t\t// We don't use the default spinner. Instead, rely on the progressbar from init/editor.js.\n\t\tif ( !this.options.switched ) {\n\t\t\tthis.hideSpinner();\n\t\t\tthis.$el.addClass( 'loading' );\n\t\t}\n\n\t\tthis.target = ve.init.mw.targetFactory.create( 'article', this, {\n\t\t\t$element: this.$el,\n\t\t\t// || null so that scrolling is not triggered for the lead (0) section\n\t\t\t// (which has no header to scroll to)\n\t\t\tsection: this.options.sectionId || null\n\t\t} );\n\t\tthis.target.once( 'surfaceReady', function () {\n\t\t\tthis.emit( 'editor-loaded' );\n\t\t\tthis.$el.removeClass( 'loading' );\n\t\t}.bind( this ) );\n\t\tthis.target.load( this.options.dataPromise );\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof VisualEditorOverlay\n\t * @instance\n\t */\n\thide: function () {\n\t\tvar overlay = this,\n\t\t\tretval = EditorOverlayBase.prototype.hide.apply( this, arguments );\n\t\tif ( retval === true ) {\n\t\t\tthis.destroyTarget();\n\t\t} else if ( retval && retval.then ) {\n\t\t\tretval.then( function ( hide ) {\n\t\t\t\tif ( hide ) {\n\t\t\t\t\toverlay.destroyTarget();\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t\treturn retval;\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof VisualEditorOverlay\n\t * @instance\n\t */\n\tonClickBack: function () {\n\t\tEditorOverlayBase.prototype.onClickBack.apply( this, arguments );\n\t\tthis.switchToEditor();\n\t},\n\n\t/**\n\t * Reveal the editing interface.\n\t * @memberof VisualEditorOverlay\n\t * @instance\n\t */\n\tswitchToEditor: function () {\n\t\tthis.showHidden( '.initial-header' );\n\t},\n\t/**\n\t * Loads an {EditorOverlay} and replaces the existing {VisualEditorOverlay}\n\t * @memberof VisualEditorOverlay\n\t * @instance\n\t */\n\tswitchToSourceEditor: function () {\n\t\tvar self = this,\n\t\t\tEditorOverlay = this.EditorOverlay;\n\t\tthis.log( {\n\t\t\taction: 'abort',\n\t\t\ttype: 'switchnochange',\n\t\t\tmechanism: 'navigate'\n\t\t} );\n\t\t// Save a user setting indicating that this user prefers using the SourceEditor\n\t\tmw.storage.set( 'preferredEditor', 'SourceEditor' );\n\t\tthis.showSpinner();\n\t\tthis.$el.find( '.surface' ).hide();\n\t\tself.hideSpinner();\n\t\tself.applyHeaderOptions( self.options, false );\n\t\t// Unset classes from other editor\n\t\tdelete self.options.className;\n\t\tself.switching = true;\n\t\tself.overlayManager.replaceCurrent( new EditorOverlay( self.options ) );\n\t\tself.switching = false;\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof VisualEditorOverlay\n\t * @instance\n\t */\n\tonSaveComplete: function () {\n\t\tEditorOverlayBase.prototype.onSaveComplete.apply( this, arguments );\n\t\tthis.destroyTarget();\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof VisualEditorOverlay\n\t * @instance\n\t */\n\thasChanged: function () {\n\t\treturn this.target &&\n\t\t\tthis.target.getSurface() &&\n\t\t\tthis.target.getSurface().getModel().hasBeenModified() &&\n\t\t\t// If we just saved, there's not really any changes, and the\n\t\t\t// target is going to be destroyed in one tick\n\t\t\t!this.saved;\n\t}\n} );\n\nmodule.exports = VisualEditorOverlay;\n","var m = require( './../mobile.startup/moduleLoaderSingleton' ),\n\tEditorOverlay = require( './EditorOverlay' ),\n\tVisualEditorOverlay = require( './VisualEditorOverlay' ),\n\tschemaEditAttemptStep = require( './schemaEditAttemptStep' );\n\n// Exposed for MobileFrontend mobile.init usage.\nm.define( 'mobile.editor.overlay/EditorOverlay', EditorOverlay );\nm.define( 'mobile.editor.overlay/VisualEditorOverlay', VisualEditorOverlay );\n// setup schema:edit logging\nschemaEditAttemptStep();\n","/**\n * Build a save failure message from the API response\n * @param {Object} data Details about the failure, from EditorGateway.parseSaveError\n * @return {string} message describing the failure for display to the user\n */\nmodule.exports = function saveFailureMessage( data ) {\n\tvar key = data && data.details && data.details.code,\n\t\t// When save failed with one of these error codes, the returned\n\t\t// message in response.error.info will be forwarded to the user.\n\t\t// FIXME: This shouldn't be needed when info texts are all localized.\n\t\twhitelistedErrorInfo = [\n\t\t\t'blocked',\n\t\t\t'autoblocked'\n\t\t];\n\tif ( data.type === 'readonly' ) {\n\t\treturn data.details.readonlyreason;\n\t}\n\tif ( key === 'editconflict' ) {\n\t\treturn mw.msg( 'mobile-frontend-editor-error-conflict' );\n\t} else if ( whitelistedErrorInfo.indexOf( key ) > -1 ) {\n\t\treturn data.error.info;\n\t}\n\treturn mw.msg( 'mobile-frontend-editor-error' );\n};\n","module.exports = function () {\n\tvar trackdebug = !!mw.util.getParamValue( 'trackdebug' );\n\n\tif ( mw.loader.getState( 'schema.EditAttemptStep' ) === null && !trackdebug ) {\n\t\treturn;\n\t}\n\n\tmw.loader.using( [ 'ext.eventLogging.subscriber' ] ).then( function () {\n\t\tvar // Schema provided by ext.eventLogging.subscriber class\n\t\t\tSchema = mw.eventLog.Schema,\n\t\t\tuser = mw.user,\n\t\t\tsampleRate = mw.config.get( 'wgWMESchemaEditAttemptStepSamplingRate' ),\n\t\t\tactionPrefixMap = {\n\t\t\t\tsaveIntent: 'save_intent',\n\t\t\t\tsaveAttempt: 'save_attempt',\n\t\t\t\tsaveSuccess: 'save_success',\n\t\t\t\tsaveFailure: 'save_failure'\n\t\t\t},\n\t\t\ttiming = {},\n\t\t\t/**\n\t\t\t * Edit schema\n\t\t\t * https://meta.wikimedia.org/wiki/Schema:EditAttemptStep\n\t\t\t */\n\t\t\t/* eslint-disable camelcase */\n\t\t\tschemaEditAttemptStep = new Schema(\n\t\t\t\t'EditAttemptStep',\n\t\t\t\tsampleRate,\n\t\t\t\t{\n\t\t\t\t\tpage_id: mw.config.get( 'wgArticleId' ),\n\t\t\t\t\trevision_id: mw.config.get( 'wgRevisionId' ),\n\t\t\t\t\tpage_title: mw.config.get( 'wgPageName' ),\n\t\t\t\t\tpage_ns: mw.config.get( 'wgNamespaceNumber' ),\n\t\t\t\t\tuser_id: user.getId(),\n\t\t\t\t\tuser_class: user.isAnon() ? 'IP' : undefined,\n\t\t\t\t\tuser_editcount: mw.config.get( 'wgUserEditCount', 0 ),\n\t\t\t\t\tmw_version: mw.config.get( 'wgVersion' ),\n\t\t\t\t\tplatform: 'phone',\n\t\t\t\t\tintegration: 'page',\n\t\t\t\t\tpage_token: user.getPageviewToken(),\n\t\t\t\t\tsession_token: user.sessionId(),\n\t\t\t\t\tversion: 1\n\t\t\t\t}\n\t\t\t);\n\t\t\t/* eslint-enable camelcase */\n\n\t\tfunction log() {\n\t\t\t// mw.log is a no-op unless resource loader is in debug mode, so\n\t\t\t// this allows trackdebug to work independently (T211698)\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log.apply( console, arguments );\n\t\t}\n\n\t\tfunction computeDuration( action, event, timeStamp ) {\n\t\t\t// This is duplicated from the VisualEditor extension\n\t\t\t// (ve.init.mw.trackSubscriber.js). Changes to this should be kept in\n\t\t\t// sync with that file, so the data remains consistent.\n\t\t\tif ( event.timing !== undefined ) {\n\t\t\t\treturn event.timing;\n\t\t\t}\n\n\t\t\tswitch ( action ) {\n\t\t\t\tcase 'ready':\n\t\t\t\t\treturn timeStamp - timing.init;\n\t\t\t\tcase 'loaded':\n\t\t\t\t\treturn timeStamp - timing.init;\n\t\t\t\tcase 'saveIntent':\n\t\t\t\t\treturn timeStamp - timing.ready;\n\t\t\t\tcase 'saveAttempt':\n\t\t\t\t\treturn timeStamp - timing.saveIntent;\n\t\t\t\tcase 'saveSuccess':\n\t\t\t\tcase 'saveFailure':\n\t\t\t\t\t// HERE BE DRAGONS: the caller must compute these themselves\n\t\t\t\t\t// for sensible results. Deliberately sabotage any attempts to\n\t\t\t\t\t// use the default by returning -1\n\t\t\t\t\tmw.log.warn( 'mf.schemaEditAttemptStep: Do not rely on default timing value for saveSuccess/saveFailure' );\n\t\t\t\t\treturn -1;\n\t\t\t\tcase 'abort':\n\t\t\t\t\tswitch ( event.abort_type ) {\n\t\t\t\t\t\tcase 'preinit':\n\t\t\t\t\t\t\treturn timeStamp - timing.init;\n\t\t\t\t\t\tcase 'nochange':\n\t\t\t\t\t\tcase 'switchwith':\n\t\t\t\t\t\tcase 'switchwithout':\n\t\t\t\t\t\tcase 'switchnochange':\n\t\t\t\t\t\tcase 'abandon':\n\t\t\t\t\t\t\treturn timeStamp - timing.ready;\n\t\t\t\t\t\tcase 'abandonMidsave':\n\t\t\t\t\t\t\treturn timeStamp - timing.saveAttempt;\n\t\t\t\t\t}\n\t\t\t\t\tmw.log.warn( 'mf.schemaEditAttemptStep: Unrecognized abort type', event.type );\n\t\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tmw.log.warn( 'mf.schemaEditAttemptStep: Unrecognized action', action );\n\t\t\treturn -1;\n\t\t}\n\n\t\tmw.trackSubscribe( 'mf.schemaEditAttemptStep', function ( topic, data, timeStamp ) {\n\t\t\tvar actionPrefix = actionPrefixMap[ data.action ] || data.action,\n\t\t\t\tduration = 0;\n\n\t\t\ttimeStamp = timeStamp || this.timeStamp; // I8e82acc12 back-compat\n\n\t\t\tdata[actionPrefix + '_type'] = data.type;\n\t\t\tdata[actionPrefix + '_mechanism'] = data.mechanism;\n\t\t\tif ( data.action !== 'init' ) {\n\t\t\t\tduration = Math.round( computeDuration( data.action, data, timeStamp ) );\n\t\t\t\tdata[actionPrefix + '_timing'] = duration;\n\t\t\t}\n\n\t\t\t// Remove renamed properties\n\t\t\tdelete data.type;\n\t\t\tdelete data.mechanism;\n\t\t\tdata[actionPrefix + '_message'] = data.message;\n\t\t\tdelete data.message;\n\t\t\t// eslint-disable-next-line camelcase\n\t\t\tdata.is_oversample =\n\t\t\t\t!mw.eventLog.inSample( 1 / sampleRate );\n\n\t\t\tif ( data.action === 'abort' && data.abort_type !== 'switchnochange' ) {\n\t\t\t\ttiming = {};\n\t\t\t} else {\n\t\t\t\ttiming[ data.action ] = timeStamp;\n\t\t\t}\n\n\t\t\t// Switching between visual and source produces a chain of\n\t\t\t// abort/ready events and no init event, so suppress them for\n\t\t\t// consistency with desktop VE's logging.\n\t\t\tif ( data.abort_type === 'switchnochange' ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( timing.abort && data.action === 'ready' ) {\n\t\t\t\tdelete timing.abort;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( trackdebug ) {\n\t\t\t\tlog( topic + '.' + data.action, duration + 'ms', data );\n\t\t\t} else {\n\t\t\t\tschemaEditAttemptStep.log( data, (\n\t\t\t\t\tmw.config.get( 'wgWMESchemaEditAttemptStepOversample' ) ||\n\t\t\t\t\tmw.config.get( 'wgMFSchemaEditAttemptStepOversample' ) === 'all' ||\n\t\t\t\t\t// wikitext / visualeditor\n\t\t\t\t\tdata.editor_interface === mw.config.get( 'wgMFSchemaEditAttemptStepOversample' )\n\t\t\t\t) ? 1 : sampleRate );\n\t\t\t}\n\t\t} );\n\n\t} );\n};\n"],"sourceRoot":""}