Jiabao has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/85638


Change subject: MathJax Live Preview III
......................................................................

MathJax Live Preview III

Change-Id: I623eef48e40d480cc98766cf7daf75dacd0bde19
---
M modules/ve-mw/ce/nodes/ve.ce.MWMathNode.js
M modules/ve-mw/dm/nodes/ve.dm.MWMathNode.js
M modules/ve-mw/ui/inspectors/ve.ui.MWMathInspector.js
3 files changed, 234 insertions(+), 25 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor 
refs/changes/38/85638/1

diff --git a/modules/ve-mw/ce/nodes/ve.ce.MWMathNode.js 
b/modules/ve-mw/ce/nodes/ve.ce.MWMathNode.js
index 0c19877..a54878d 100644
--- a/modules/ve-mw/ce/nodes/ve.ce.MWMathNode.js
+++ b/modules/ve-mw/ce/nodes/ve.ce.MWMathNode.js
@@ -5,51 +5,130 @@
  * @license The MIT License (MIT); see LICENSE.txt
  */
 
-/*global MathJax */
+/*global mw, MathJax */
 
 /**
  * ContentEditable MediaWiki math node.
  *
  * @class
- * @extends ve.ce.MWExtensionNode
+ * @extends ve.ce.LeafNode
+ * @mixins ve.ce.FocusableNode
+ * @mixins ve.ce.ProtectedNode
+ * @mixins ve.ce.GeneratedContentNode
  *
  * @constructor
  * @param {ve.dm.MWMathNode} model Model to observe
  * @param {Object} [config] Config options
  */
 ve.ce.MWMathNode = function VeCeMWMathNode( model, config ) {
-       // Parent constructor
-       ve.ce.MWExtensionNode.call( this, model, config );
 
-       // DOM changes
+       // Parent constructor
+       ve.ce.LeafNode.call( this, model, config );
+
+       // Mixin constructors
+       ve.ce.FocusableNode.call( this );
+       ve.ce.ProtectedNode.call( this );
+       ve.ce.GeneratedContentNode.call( this );
+
+       // Events
+       this.$.on( 'click', ve.bind( this.onClick, this ) );
+
+       // DOM Changes
        this.$.addClass( 've-ce-mwMathNode' );
 };
 
 /* Inheritance */
 
-ve.inheritClass( ve.ce.MWMathNode, ve.ce.MWExtensionNode );
+ve.inheritClass( ve.ce.MWMathNode, ve.ce.LeafNode );
+
+ve.mixinClass( ve.ce.MWMathNode, ve.ce.FocusableNode );
+ve.mixinClass( ve.ce.MWMathNode, ve.ce.ProtectedNode );
+ve.mixinClass( ve.ce.MWMathNode, ve.ce.GeneratedContentNode );
 
 /* Static Properties */
 
 ve.ce.MWMathNode.static.name = 'mwMath';
 
+ve.ce.MWMathNode.static.tagName = 'span';
+
 /* Methods */
 
 /** */
+ve.ce.MWMathNode.prototype.generateContents = function ( config ) {
+       var xhr, promise, deferred = $.Deferred(),
+               wikitext = this.model.getAttribute( 'mw' ).body.extsrc;
+
+       if (config) {
+               wikitext = config.wikitext;
+       }
+       xhr = $.ajax( {
+               'url': mw.util.wikiScript( 'api' ),
+               'data': {
+                       'action': 'visualeditor',
+                       'paction': 'parsefragment',
+                       'page': mw.config.get( 'wgRelevantPageName' ),
+                       'wikitext': '<math>' + wikitext + '</math>',
+                       'token': mw.user.tokens.get( 'editToken' ),
+                       'format': 'json'
+               },
+               'dataType': 'json',
+               'type': 'POST',
+               // Wait up to 100 seconds before giving up
+               'timeout': 100000,
+               'cache': 'false',
+               'success': ve.bind( this.onParseSuccess, this, deferred ),
+               'error': ve.bind( this.onParseError, this, deferred )
+       } );
+       promise = deferred.promise();
+       promise.abort = function () {
+               xhr.abort();
+       };
+       return promise;
+};
+
+/**
+ * Handle a successful response from the parser for the wikitext fragment.
+ *
+ * @param {jQuery.Deferred} deferred The Deferred object created by 
generateContents
+ * @param {Object} response Response data
+ */
 ve.ce.MWMathNode.prototype.onParseSuccess = function ( deferred, response ) {
-       var data = response.visualeditor, contentNodes = $( data.content 
).get();
-       // HACK: unwrap paragraph from PHP parser
+       var data = response.visualeditor, contentNodes = $( data.content 
).get();//, self = this;
        contentNodes = Array.prototype.slice.apply( contentNodes[0].childNodes 
);
        deferred.resolve( contentNodes );
-       if ( $( contentNodes ).is( 'span.tex' ) ) {
-               // MathJax
-               MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub ] );
-       } else {
-               // Rerender after image load
-               this.$.find( 'img' ).on( 'load', ve.bind( function () {
-                       this.emit( 'rerender' );
-               }, this ) );
-       }
+
+       MathJax.Hub.Queue( [ 'Typeset', MathJax.Hub, this.$[0] ] );
+};
+
+
+/**
+ * Handle an unsuccessful response from the parser for the wikitext fragment.
+ *
+ * @param {jQuery.Deferred} deferred The promise object created by 
generateContents
+ * @param {Object} response Response data
+ */
+ve.ce.MWMathNode.prototype.onParseError = function ( deferred ) {
+       deferred.reject();
+};
+
+/**
+ * Handle the mouse click.
+ *
+ * @method
+ * @param {jQuery.Event} e Click event
+ */
+ve.ce.MWMathNode.prototype.onClick = function ( e ) {
+       var surfaceModel = this.getRoot().getSurface().getModel(),
+               selectionRange = surfaceModel.getSelection(),
+               nodeRange = this.model.getOuterRange();
+
+       surfaceModel.getFragment(
+               e.shiftKey ?
+                       ve.Range.newCoveringRange(
+                               [ selectionRange, nodeRange ], 
selectionRange.from > nodeRange.from
+                       ) :
+                       nodeRange
+       ).select();
 };
 
 /* Registration */
diff --git a/modules/ve-mw/dm/nodes/ve.dm.MWMathNode.js 
b/modules/ve-mw/dm/nodes/ve.dm.MWMathNode.js
index 622f13a..7588df9 100644
--- a/modules/ve-mw/dm/nodes/ve.dm.MWMathNode.js
+++ b/modules/ve-mw/dm/nodes/ve.dm.MWMathNode.js
@@ -9,26 +9,83 @@
  * DataModel MediaWiki math node.
  *
  * @class
- * @extends ve.dm.MWExtensionNode
+ * @extends ve.dm.LeafNode
+ * @mixins ve.dm.GeneratedContentNode
  *
  * @constructor
  */
 ve.dm.MWMathNode = function VeDmMWMathNode( length, element ) {
        // Parent constructor
-       ve.dm.MWExtensionNode.call( this, 0, element );
+       ve.dm.LeafNode.call( this, 0, element );
+
+       // Mixin constructors
+       ve.dm.GeneratedContentNode.call( this );
 };
 
 /* Inheritance */
 
-ve.inheritClass( ve.dm.MWMathNode, ve.dm.MWExtensionNode );
+ve.inheritClass( ve.dm.MWMathNode, ve.dm.LeafNode );
+
+ve.mixinClass( ve.dm.MWMathNode, ve.dm.GeneratedContentNode );
 
 /* Static members */
 
 ve.dm.MWMathNode.static.name = 'mwMath';
 
-ve.dm.MWMathNode.static.tagName = 'img';
+ve.dm.MWMathNode.static.enableAboutGrouping = true;
 
-ve.dm.MWMathNode.static.extensionName = 'math';
+ve.dm.MWMathNode.static.matchTagNames = null;
+
+ve.dm.MWMathNode.static.matchRdfaTypes = [ 'mw:Extension/math' ];
+
+ve.dm.MWMathNode.static.isContent = true;
+
+ve.dm.MWMathNode.static.toDataElement = function ( domElements, converter ) {
+       var dataElement, index,
+               mwDataJSON = domElements[0].getAttribute( 'data-mw' ),
+               mwData = mwDataJSON ? JSON.parse( mwDataJSON ) : {};
+
+       dataElement = {
+               'type': 'mwMath',
+               'attributes': {
+                       'mw': mwData,
+                       'originalDomElements':  [ domElements[0] ],
+                       'originalMw': mwDataJSON
+               }
+       };
+
+       index = this.storeDomElements( dataElement, domElements, 
converter.getStore() );
+       dataElement.attributes.originalIndex = index;
+       return dataElement;
+};
+
+ve.dm.MWMathNode.static.toDomElements = function ( dataElement, doc, converter 
) {
+       var el,
+               index = converter.getStore().indexOfHash( ve.getHash( 
this.getHashObject( dataElement ) ) ),
+               originalMw = dataElement.attributes.originalMw;
+
+       // If the transclusion is unchanged just send back the
+       // original DOM elements so selser can skip over it
+       if (
+               index === dataElement.attributes.originalIndex ||
+               ( originalMw && ve.compare( dataElement.attributes.mw, 
JSON.parse( originalMw ) ) )
+       ) {
+               // The object in the store is also used for CE rendering so 
return a copy
+               return ve.copyDomElements( 
dataElement.attributes.originalDomElements, doc );
+       } else {
+               el = doc.createElement( 'img' );
+               el.setAttribute( 'typeof', 'mw:Extension/Math' );
+               el.setAttribute( 'data-mw', JSON.stringify( 
dataElement.attributes.mw ) );
+               return [ el ];
+       }
+};
+
+ve.dm.MWMathNode.static.getHashObject = function ( dataElement ) {
+       return {
+               type: dataElement.type,
+               mw: dataElement.attributes.mw
+       };
+};
 
 /* Registration */
 
diff --git a/modules/ve-mw/ui/inspectors/ve.ui.MWMathInspector.js 
b/modules/ve-mw/ui/inspectors/ve.ui.MWMathInspector.js
index 177177f..af73629 100644
--- a/modules/ve-mw/ui/inspectors/ve.ui.MWMathInspector.js
+++ b/modules/ve-mw/ui/inspectors/ve.ui.MWMathInspector.js
@@ -36,14 +36,87 @@
 
 ve.ui.MWMathInspector.static.nodeModel = ve.dm.MWMathNode;
 
+ve.ui.MWMathInspector.static.TextInputWidget = ve.ui.TextInputWidget;
+
 /* Methods */
 
-/** */
+/**
+ * Handle frame ready events.
+ *
+ * @method
+ */
 ve.ui.MWMathInspector.prototype.initialize = function () {
        // Parent method
-       ve.ui.MWExtensionInspector.prototype.initialize.call( this );
+       ve.ui.Inspector.prototype.initialize.call( this );
 
-       this.input.$.addClass( 've-ui-mwMathInspector-input' );
+       this.input = new this.constructor.static.TextInputWidget( {
+               '$$': this.frame.$$, 'overlay': this.surface.$localOverlay
+       } );
+
+       this.changed = false;
+
+       this.input.on( 'change', ve.bind( this.livePreview, this ) );
+
+       // Initialization
+       this.$form.append( this.input.$ );
+};
+
+ve.ui.MWMathInspector.prototype.livePreview = function () {
+
+       var newsrc = this.input.getValue(),
+               mw = this.mathNode.getModel().getAttribute( 'mw' );
+
+       if ( mw.body.extsrc !== newsrc ) {
+               this.mathNode.forceUpdate({ 'wikitext': newsrc });
+       }
+};
+
+/**
+ * Handle the inspector being opened.
+ */
+ve.ui.MWMathInspector.prototype.onOpen = function () {
+
+       // Parent method
+       ve.ui.Inspector.prototype.onOpen.call( this );
+
+       this.mathNode = this.surface.getView().getFocusedNode();
+
+       var src = this.mathNode.getModel().getAttribute( 'mw' ).body.extsrc;
+
+       // Wait for animation to complete
+       setTimeout( ve.bind( function () {
+               // Setup input text
+               this.input.setValue( src );
+               this.input.$input.focus().select();
+       }, this ), 200 );
+};
+
+/**
+ * Handle the inspector being closed.
+ *
+ * @param {string} action Action that caused the window to be closed
+ */
+ve.ui.MWMathInspector.prototype.onClose = function ( action ) {
+
+       var newsrc = this.input.getValue(),
+               surfaceModel = this.surface.getModel(),
+               mw = this.mathNode.getModel().getAttribute( 'mw' );
+
+       // Parent method
+       ve.ui.Inspector.prototype.onClose.call( this, action );
+
+       // If change is called with no change it will unrender the mathnode
+       // If the input box is empty when closed it errors if change is called 
in the onParseSuccess function
+       if ( newsrc !== '' ) {
+               if ( mw.body.extsrc !== newsrc ) {
+                       mw.body.extsrc = this.input.getValue();
+                       surfaceModel.change(
+                               ve.dm.Transaction.newFromAttributeChanges(
+                                       surfaceModel.getDocument(), 
this.mathNode.getOuterRange().start, { 'mw': mw }
+                               )
+                       );
+               }
+       }
 };
 
 /* Registration */

-- 
To view, visit https://gerrit.wikimedia.org/r/85638
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I623eef48e40d480cc98766cf7daf75dacd0bde19
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Jiabao <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to