jenkins-bot has submitted this change and it was merged.
Change subject: Create base MobileView config and target refactor
......................................................................
Create base MobileView config and target refactor
Changes include:
* Target mobile for ve dependencies
* Create mobile view constructor
** Some tools like dialogs are excluded for now
* Refactor mw.target to permit code reuse
** Split out pageTarget view functionality from core init methods
Change-Id: I786b63ab57518fc6af7761501259ed66592f70e3
---
M VisualEditor.php
M VisualEditorDataModule.php
A modules/ve-mw/init/targets/ve.init.mw.MobileViewTarget.js
M modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
M modules/ve-mw/init/ve.init.mw.Target.js
5 files changed, 304 insertions(+), 92 deletions(-)
Approvals:
Catrope: Looks good to me, approved
jenkins-bot: Verified
diff --git a/VisualEditor.php b/VisualEditor.php
index eb902bd..c20246c 100644
--- a/VisualEditor.php
+++ b/VisualEditor.php
@@ -81,18 +81,21 @@
'rangy/rangy-position-1.3.js',
'rangy/rangy-export.js',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'jquery.visibleText' => $wgVisualEditorResourceTemplate + array(
'scripts' => array(
'jquery/jquery.visibleText.js',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'oojs' => $wgVisualEditorResourceTemplate + array(
'scripts' => array(
'oojs/oojs.js',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'oojs-ui' => $wgVisualEditorResourceTemplate + array(
@@ -114,7 +117,8 @@
),
'dependencies' => array(
'oojs'
- )
+ ),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'unicodejs.wordbreak' => $wgVisualEditorResourceTemplate + array(
@@ -126,6 +130,7 @@
'unicodejs/unicodejs.wordbreakproperties.js',
'unicodejs/unicodejs.wordbreak.js',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
// Alias for backwards compat, safe to remove after
@@ -139,12 +144,14 @@
'styles' => array(
've-mw/init/styles/ve.init.mw.ViewPageTarget.Icons-raster.css',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.viewPageTarget.icons-vector' =>
$wgVisualEditorResourceTemplate + array(
'styles' => array(
've-mw/init/styles/ve.init.mw.ViewPageTarget.Icons-vector.css',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.viewPageTarget.init' =>
$wgVisualEditorResourceTemplate + array(
@@ -197,20 +204,9 @@
'dependencies' => array(
'ext.visualEditor.base',
'ext.visualEditor.mediawiki',
- 'jquery.byteLength',
- 'jquery.byteLimit',
- 'jquery.client',
'jquery.placeholder',
- 'jquery.visibleText',
- 'mediawiki.api',
'mediawiki.feedback',
'mediawiki.jqueryMsg',
- 'mediawiki.notify',
- 'mediawiki.Title',
- 'mediawiki.Uri',
- 'mediawiki.user',
- 'user.options',
- 'user.tokens',
),
'messages' => array(
// MW core messages
@@ -228,6 +224,16 @@
'visualeditor-savedialog-identify-anon',
'visualeditor-savedialog-identify-user',
),
+ ),
+ 'ext.visualEditor.mobileViewTarget' => $wgVisualEditorResourceTemplate
+ array(
+ 'scripts' => array(
+ 've-mw/init/targets/ve.init.mw.MobileViewTarget.js',
+ ),
+ 'dependencies' => array(
+ 'ext.visualEditor.base',
+ 'ext.visualEditor.mediawiki',
+ ),
+ 'targets' => array( 'mobile' ),
),
'ext.visualEditor.base' => $wgVisualEditorResourceTemplate + array(
@@ -250,6 +256,7 @@
'unicodejs.wordbreak',
'mediawiki.util',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.mediawiki' => $wgVisualEditorResourceTemplate + array(
@@ -260,11 +267,20 @@
've-mw/init/ve.init.mw.Target.js',
),
'dependencies' => array(
+ 'jquery.visibleText',
'jquery.byteLength',
'jquery.client',
'mediawiki.Uri',
+ 'mediawiki.api',
+ 'mediawiki.notify',
+ 'mediawiki.Title',
+ 'mediawiki.Uri',
+ 'mediawiki.user',
+ 'user.options',
+ 'user.tokens',
'ext.visualEditor.base',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.standalone' => $wgVisualEditorResourceTemplate +
array(
@@ -280,7 +296,7 @@
),
'ext.visualEditor.data' => $wgVisualEditorResourceTemplate + array(
- 'class' => 'VisualEditorDataModule'
+ 'class' => 'VisualEditorDataModule',
),
'ext.visualEditor.core' => $wgVisualEditorResourceTemplate + array(
@@ -541,6 +557,7 @@
'mediawiki.action.history.diff',
'mediawiki.user',
'jquery.autoEllipsis',
+ 'jquery.byteLimit',
),
'messages' => array(
// VE messages for the editor (NOT experimental mode
messages)
@@ -682,6 +699,7 @@
'fancycaptcha-edit',
'colon-separator',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.language' => $wgVisualEditorResourceTemplate + array(
@@ -708,6 +726,7 @@
'visualeditor-languageinspector-block-tooltip-rtldirection',
'visualeditor-annotationbutton-language-tooltip',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.mwalienextension' => $wgVisualEditorResourceTemplate
+ array(
@@ -723,6 +742,7 @@
'messages' => array(
'visualeditor-mwalienextensioninspector-title',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.mwmath' => $wgVisualEditorResourceTemplate + array(
@@ -738,6 +758,7 @@
'messages' => array(
'visualeditor-mwmathinspector-title',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.mwhiero' => $wgVisualEditorResourceTemplate + array(
@@ -753,6 +774,7 @@
'messages' => array(
'visualeditor-mwhieroinspector-title',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.mwsyntaxHighlight' => $wgVisualEditorResourceTemplate
+ array(
@@ -776,6 +798,7 @@
'styles' => array(
'syntaxhighlight/styles/ve.ui.MWSyntaxHighlight.css',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.experimental' => array(
@@ -786,6 +809,7 @@
'ext.visualEditor.mwalienextension',
//'ext.visualEditor.mwsyntaxHighlight',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.icons-raster' => $wgVisualEditorResourceTemplate +
array(
@@ -793,12 +817,14 @@
've/ui/styles/ve.ui.Icons-raster.css',
've-mw/ui/styles/ve.ui.Icons-raster.css',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
'ext.visualEditor.icons-vector' => $wgVisualEditorResourceTemplate +
array(
'styles' => array(
've/ui/styles/ve.ui.Icons-vector.css',
've-mw/ui/styles/ve.ui.Icons-vector.css',
),
+ 'targets' => array( 'desktop', 'mobile' ),
),
);
diff --git a/VisualEditorDataModule.php b/VisualEditorDataModule.php
index 66f4727..f64ea58 100644
--- a/VisualEditorDataModule.php
+++ b/VisualEditorDataModule.php
@@ -15,6 +15,7 @@
protected $origin = self::ORIGIN_USER_SITEWIDE;
protected $gitInfo;
protected $gitHeadHash;
+ protected $targets = array( 'desktop', 'mobile' );
/* Methods */
diff --git a/modules/ve-mw/init/targets/ve.init.mw.MobileViewTarget.js
b/modules/ve-mw/init/targets/ve.init.mw.MobileViewTarget.js
new file mode 100644
index 0000000..d6904d2
--- /dev/null
+++ b/modules/ve-mw/init/targets/ve.init.mw.MobileViewTarget.js
@@ -0,0 +1,66 @@
+/*!
+ * VisualEditor MediaWiki Initialization MobileViewTarget class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/*global mw*/
+
+/**
+ *
+ * @class
+ * @extends ve.init.mw.Target
+ *
+ * @constructor
+ * @param {jQuery} $container Container to render target into
+ */
+ve.init.mw.MobileViewTarget = function VeInitMwMobileViewTarget( $el ) {
+ var currentUri = new mw.Uri();
+
+ // Parent constructor
+ ve.init.mw.Target.call(
+ this, $el, mw.config.get( 'wgRelevantPageName' ),
currentUri.query.oldid
+ );
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.init.mw.MobileViewTarget, ve.init.mw.Target );
+
+/* Static Properties */
+
+ve.init.mw.MobileViewTarget.static.toolbarGroups = [
+ { 'include': [ 'undo', 'redo' ] },
+ {
+ 'type': 'menu',
+ 'include': [ { 'group': 'format' } ],
+ 'promote': [ 'paragraph' ],
+ 'demote': [ 'preformatted', 'heading1' ]
+ },
+ { 'include': [ 'bold', 'italic', 'link', 'clear' ] },
+ { 'include': [ 'number', 'bullet', 'outdent', 'indent' ] },
+ { 'include': '*', 'exclude': [ { 'group': 'format' }, 'reference',
'referenceList', 'mediaEdit', 'mediaInsert', 'transclusion' ] }
+];
+
+ve.init.mw.MobileViewTarget.static.surfaceCommands = [
+ 'undo',
+ 'redo',
+ 'bold',
+ 'italic',
+ 'link',
+ 'clear',
+ 'underline',
+ 'subscript',
+ 'superscript',
+ 'indent',
+ 'outdent',
+ 'paragraph',
+ 'heading1',
+ 'heading2',
+ 'heading3',
+ 'heading4',
+ 'heading5',
+ 'heading6',
+ 'preformatted'
+];
diff --git a/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
b/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
index c8c7cb1..f5fda29 100644
--- a/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
+++ b/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js
@@ -37,10 +37,6 @@
this.timings = {};
this.active = false;
this.edited = false;
- this.sanityCheckFinished = false;
- this.sanityCheckVerified = false;
- this.activating = false;
- this.deactivating = false;
// If this is true then #transformPage / #restorePage will not call
pushState
// This is to avoid adding a new history entry for the url we just got
from onpopstate
// (which would mess up with the expected order of Back/Forwards
browsing)
@@ -70,16 +66,17 @@
// Events
this.connect( this, {
- 'load': 'onLoad',
'save': 'onSave',
'loadError': 'onLoadError',
+ 'surfaceReady': 'onSurfaceReady',
'tokenError': 'onTokenError',
'saveError': 'onSaveError',
'editConflict': 'onEditConflict',
'showChanges': 'onShowChanges',
'showChangesError': 'onShowChangesError',
'noChanges': 'onNoChanges',
- 'serializeError': 'onSerializeError'
+ 'serializeError': 'onSerializeError',
+ 'sanityCheckComplete': 'updateToolbarSaveButtonState'
} );
if ( !browserWhitelisted ) {
@@ -165,7 +162,7 @@
this.saveScrollPosition();
- this.load();
+ this.load( [ 'site', 'user' ] );
}
};
@@ -217,34 +214,6 @@
};
/**
- * Handle successful DOM load event.
- *
- * @method
- * @param {HTMLDocument} doc Parsed DOM from server
- */
-ve.init.mw.ViewPageTarget.prototype.onLoad = function ( doc ) {
- if ( this.activating ) {
- this.edited = false;
- this.doc = doc;
- this.setUpSurface( doc, ve.bind( function() {
- this.startSanityCheck();
- this.setupToolbarButtons();
- this.attachToolbarButtons();
- this.restoreScrollPosition();
- this.restoreEditSection();
- this.setupBeforeUnloadHandler();
- this.$document[0].focus();
- this.activating = false;
- if ( mw.config.get( 'wgVisualEditorConfig'
).showBetaWelcome ) {
- this.showBetaWelcome();
- }
- ve.track( 'performance.system.activation', {
'duration': ve.now() - this.timings.activationStart } );
- mw.hook( 've.activationComplete' ).fire();
- }, this ) );
- }
-};
-
-/**
* Handle failed DOM load event.
*
* @method
@@ -279,6 +248,36 @@
// User interface changes
this.deactivate( true );
}
+};
+
+/**
+ * Once surface is ready ready, init UI
+ *
+ * @method
+ */
+ve.init.mw.ViewPageTarget.prototype.onSurfaceReady = function () {
+ this.surface.getModel().getDocument().connect( this, {
+ 'transact': 'recordLastTransactionTime'
+ } );
+ this.surface.getModel().connect( this, {
+ 'documentUpdate': 'checkForWikitextWarning',
+ 'history': 'updateToolbarSaveButtonState'
+ } );
+ // Update UI
+ this.transformPageTitle();
+ this.changeDocumentTitle();
+ this.hidePageContent();
+ this.hideSpinner();
+ this.setupToolbarButtons();
+ this.attachToolbarButtons();
+ this.restoreScrollPosition();
+ this.restoreEditSection();
+ this.setupBeforeUnloadHandler();
+ if ( mw.config.get( 'wgVisualEditorConfig' ).showBetaWelcome ) {
+ this.showBetaWelcome();
+ }
+ ve.track( 'performance.system.activation', { 'duration': ve.now() -
this.timings.activationStart } );
+ mw.hook( 've.activationComplete' ).fire();
};
/**
@@ -1333,33 +1332,6 @@
.parent()
.data( 've.hideTableOfContents', true )
.slideUp();
-};
-
-/**
- * Show the toolbar.
- *
- * This also transplants the toolbar to a new location.
- *
- * @method
- */
-ve.init.mw.ViewPageTarget.prototype.setUpToolbar = function () {
- this.toolbar = new ve.ui.TargetToolbar( this, this.surface, { 'shadow':
true, 'actions': true } );
- this.toolbar.setup( this.constructor.static.toolbarGroups );
- this.surface.addCommands( this.constructor.static.surfaceCommands );
- if ( !this.isMobileDevice ) {
- this.toolbar.enableFloatable();
- }
- this.toolbar.$element
- .addClass( 've-init-mw-viewPageTarget-toolbar' )
- .insertBefore( '#firstHeading' );
- this.toolbar.$bar.slideDown( 'fast', ve.bind( function () {
- // Check the surface wasn't torn down while the toolbar was
animating
- if ( this.surface ) {
- this.toolbar.initialize();
- this.surface.emit( 'position' );
- this.surface.getContext().update();
- }
- }, this ) );
};
/**
diff --git a/modules/ve-mw/init/ve.init.mw.Target.js
b/modules/ve-mw/init/ve.init.mw.Target.js
index a7e8e5d..976235c 100644
--- a/modules/ve-mw/init/ve.init.mw.Target.js
+++ b/modules/ve-mw/init/ve.init.mw.Target.js
@@ -21,6 +21,7 @@
*/
ve.init.mw.Target = function VeInitMwTarget( $container, pageName, revisionId
) {
var i, len, prefName, prefValue, conf = mw.config.get(
'wgVisualEditorConfig' ),
+ // language, mwalienextension and mwhiero are commented out in
VisualEditorHooks::onGetBetaPreferences()
extraModules = [ 'experimental'/* , 'language'*//*,
'mwalienextension'*/, 'mwmath'/*, 'mwhiero'*/ ];
// Parent constructor
@@ -71,6 +72,10 @@
this.$checkboxes = null;
this.remoteNotices = [];
this.localNoticeMessages = [];
+ this.sanityCheckFinished = false;
+ this.sanityCheckVerified = false;
+ this.activating = false;
+ this.deactivating = false;
this.isMobileDevice = (
'ontouchstart' in window ||
( window.DocumentTouch && document instanceof
window.DocumentTouch )
@@ -78,8 +83,7 @@
};
/**
- * @event load
- * @param {HTMLDocument} dom
+ * @event surfaceReady
*/
/**
@@ -128,6 +132,10 @@
* @param {Mixed|null} error HTTP status text
*/
+/**
+ * @event sanityCheckComplete
+ */
+
/* Inheritance */
OO.inheritClass( ve.init.mw.Target, ve.init.Target );
@@ -160,8 +168,8 @@
* Handle response to a successful load request.
*
* This method is called within the context of a target instance. If
successful the DOM from the
- * server will be parsed, stored in {this.doc} and then
{ve.init.mw.Target.onReady} will be called once
- * the modules are ready.
+ * server will be parsed, stored in {this.doc} and then {this.onReady} will be
called once modules
+ * are ready.
*
* @static
* @method
@@ -207,17 +215,16 @@
this.startTimeStamp = data.starttimestamp;
this.revid = data.oldid;
// Everything worked, the page was loaded, continue as soon as
the modules are loaded
- this.modulesReady.done( ve.bind( ve.init.mw.Target.onReady,
this ) );
+ this.modulesReady.done( ve.bind( this.onReady, this ) );
}
};
/**
* Handle the edit notices being ready for rendering.
*
- * @static
* @method
*/
-ve.init.mw.Target.onNoticesReady = function () {
+ve.init.mw.Target.prototype.onNoticesReady = function () {
var i, len, noticeHtmls, tmp, el;
// Since we're going to parse them, we might as well save these nodes
@@ -261,18 +268,22 @@
/**
* Handle both DOM and modules being loaded and ready.
*
- * This method is called within the context of a target instance.
- *
- * @static
* @method
- * @fires load
+ * @fires surfaceReady
*/
-ve.init.mw.Target.onReady = function () {
+ve.init.mw.Target.prototype.onReady = function () {
// We need to wait until onReady as local notices may require special
messages
- ve.init.mw.Target.onNoticesReady.call( this );
-
+ this.onNoticesReady();
this.loading = false;
- this.emit( 'load', this.doc );
+ if ( this.activating ) {
+ this.edited = false;
+ this.setUpSurface( this.doc, ve.bind( function() {
+ this.startSanityCheck();
+ this.$document[0].focus();
+ this.activating = false;
+ this.emit( 'surfaceReady' );
+ }, this ) );
+ }
};
/**
@@ -510,9 +521,10 @@
* A side-effect of calling this method is that it requests {this.modules} be
loaded.
*
* @method
+ * @param {string[]} [additionalModules=[]] Resource loader modules
* @returns {boolean} Loading has been started
*/
-ve.init.mw.Target.prototype.load = function () {
+ve.init.mw.Target.prototype.load = function ( additionalModules ) {
var data, start;
// Prevent duplicate requests
if ( this.loading ) {
@@ -521,7 +533,7 @@
// Start loading the module immediately
mw.loader.using(
// Wait for site and user JS before running plugins
- this.modules.concat( [ 'site', 'user' ] ),
+ this.modules.concat( additionalModules || [] ),
ve.bind( ve.init.mw.Target.onModulesReady, this )
);
@@ -867,3 +879,138 @@
ve.init.mw.Target.prototype.getEditNotices = function () {
return this.editNotices;
};
+
+// FIXME: split out view specific functionality, emit to subclass
+
+/**
+ * Switch to editing mode.
+ *
+ * @method
+ * @param {HTMLDocument} doc HTML DOM to edit
+ * @param {Function} [callback] Callback to call when done
+ */
+ve.init.mw.Target.prototype.setUpSurface = function ( doc, callback ) {
+ var target = this;
+ setTimeout( function () {
+ // Build linmod
+ var store = new ve.dm.IndexValueStore(),
+ internalList = new ve.dm.InternalList(),
+ innerWhitespace = new Array( 2 ),
+ data = ve.dm.converter.getDataFromDom( doc, store,
internalList, innerWhitespace );
+ setTimeout( function () {
+ // Build DM tree
+ var dmDoc = new ve.dm.Document( data, doc, undefined,
internalList, innerWhitespace );
+ setTimeout( function () {
+ // Create ui.Surface (also creates ce.Surface
and dm.Surface and builds CE tree)
+ target.surface = new ve.ui.Surface( dmDoc,
target.surfaceOptions );
+ target.surface.$element.addClass(
've-init-mw-viewPageTarget-surface' );
+ setTimeout( function () {
+ // Initialize surface
+ target.surface.getContext().hide();
+ target.$document =
target.surface.$element.find( '.ve-ce-documentNode' );
+ target.$element.append(
target.surface.$element );
+ target.setUpToolbar();
+ target.$document.attr( {
+ 'lang': mw.config.get(
'wgVisualEditor' ).pageLanguageCode,
+ 'dir': mw.config.get(
'wgVisualEditor' ).pageLanguageDir
+ } );
+ // Add appropriately mw-content-ltr or
mw-content-rtl class
+ target.surface.view.$element.addClass(
+ 'mw-content-' + mw.config.get(
'wgVisualEditor' ).pageLanguageDir
+ );
+ target.active = true;
+ // Now that the surface is attached to
the document and ready,
+ // let it initialize itself
+ target.surface.initialize();
+ setTimeout( callback );
+ } );
+ } );
+ } );
+ } );
+};
+
+/**
+ * Show the toolbar.
+ *
+ * This also transplants the toolbar to a new location.
+ *
+ * @method
+ */
+ve.init.mw.Target.prototype.setUpToolbar = function () {
+ this.toolbar = new ve.ui.TargetToolbar( this, this.surface, { 'shadow':
true, 'actions': true } );
+ this.toolbar.setup( this.constructor.static.toolbarGroups );
+ this.surface.addCommands( this.constructor.static.surfaceCommands );
+ if ( !this.isMobileDevice ) {
+ this.toolbar.enableFloatable();
+ }
+ this.toolbar.$element
+ .addClass( 've-init-mw-viewPageTarget-toolbar' )
+ .insertBefore( $( '#firstHeading' ).length > 0 ?
'#firstHeading' : this.surface.$element );
+ this.toolbar.$bar.slideDown( 'fast', ve.bind( function () {
+ // Check the surface wasn't torn down while the toolbar was
animating
+ if ( this.surface ) {
+ this.toolbar.initialize();
+ this.surface.emit( 'position' );
+ this.surface.getContext().update();
+ }
+ }, this ) );
+};
+
+/**
+ * Fire off the sanity check. Must be called before the surface is activated.
+ *
+ * To access the result, check whether #sanityCheckPromise has been resolved
or rejected
+ * (it's asynchronous, so it may still be pending when you check).
+ *
+ * @method
+ * @fires sanityCheckComplete
+ */
+ve.init.mw.Target.prototype.startSanityCheck = function () {
+ // We have to get a copy of the data now, before we unlock the surface
and let the user edit,
+ // but we can defer the actual conversion and comparison
+ var viewPage = this,
+ doc = viewPage.surface.getModel().getDocument(),
+ data = new ve.dm.FlatLinearData( doc.getStore().clone(),
ve.copy( doc.getFullData() ) ),
+ oldDom = viewPage.doc,
+ d = $.Deferred();
+
+ // Reset
+ viewPage.sanityCheckFinished = false;
+ viewPage.sanityCheckVerified = false;
+
+ setTimeout( function () {
+ // We can't compare oldDom.body and newDom.body directly,
because the attributes on the
+ // <body> were ignored in the conversion. So compare each child
separately.
+ var i,
+ len = oldDom.body.childNodes.length,
+ newDoc = new ve.dm.Document( data, oldDom, undefined,
doc.getInternalList(), doc.getInnerWhitespace() ),
+ newDom = ve.dm.converter.getDomFromData(
newDoc.getFullData(), newDoc.getStore(), newDoc.getInternalList(),
newDoc.getInnerWhitespace() );
+
+ // Explicitly unlink our full copy of the original version of
the document data
+ data = undefined;
+
+ if ( len !== newDom.body.childNodes.length ) {
+ // Different number of children, so they're definitely
different
+ d.reject();
+ return;
+ }
+ for ( i = 0; i < len; i++ ) {
+ if ( !oldDom.body.childNodes[i].isEqualNode(
newDom.body.childNodes[i] ) ) {
+ d.reject();
+ return;
+ }
+ }
+ d.resolve();
+ } );
+
+ viewPage.sanityCheckPromise = d.promise()
+ .done( function () {
+ // If we detect no roundtrip errors,
+ // don't emphasize "review changes" to the user.
+ viewPage.sanityCheckVerified = true;
+ })
+ .always( function () {
+ viewPage.sanityCheckFinished = true;
+ viewPage.emit( 'sanityCheckComplete' );
+ } );
+};
--
To view, visit https://gerrit.wikimedia.org/r/93914
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I786b63ab57518fc6af7761501259ed66592f70e3
Gerrit-PatchSet: 25
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Robmoen <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: Kaldari <[email protected]>
Gerrit-Reviewer: Krinkle <[email protected]>
Gerrit-Reviewer: Robmoen <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits