Robmoen has uploaded a new change for review.

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


Change subject: Introduce configurable target views.
......................................................................

Introduce configurable target views.

Major changes:

ve.init.Target.js
* Create abstract class methods for Target.

ve.init.sa.Target.js
* Create Standalone target view methods.

ve.init.mw.Target.js
* Added MW specific target view methods.
* Integration action buttons are now added to the edit
view in the toolbar.

ve.Surface.js
* Change toolbar config object to include views
* Tweak setupToolbars to incorporate view elements and contain
their configured tools.
* Each toolbar view has an actions container.

* Other changes include some documentation and code cleanup.

Change-Id: Iff39266bdd3052f34bda254ca407030dbbc81f26
---
M VisualEditor.php
M demos/ve/index.php
M modules/ve/init/mw/targets/ve.init.mw.ViewPageTarget.js
M modules/ve/init/mw/ve.init.mw.Platform.js
M modules/ve/init/mw/ve.init.mw.Target.js
M modules/ve/init/sa/styles/ve.init.sa.css
M modules/ve/init/sa/ve.init.sa.Platform.js
A modules/ve/init/sa/ve.init.sa.Target.js
M modules/ve/init/ve.init.Platform.js
A modules/ve/init/ve.init.Target.js
M modules/ve/ve.Surface.js
11 files changed, 262 insertions(+), 49 deletions(-)


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

diff --git a/VisualEditor.php b/VisualEditor.php
index 45a4e33..414bd63 100644
--- a/VisualEditor.php
+++ b/VisualEditor.php
@@ -175,6 +175,7 @@
                        've/ve.EventEmitter.js',
                        've/init/ve.init.js',
                        've/init/ve.init.Platform.js',
+                       've/init/ve.init.Target.js',
                ),
                'debugScripts' => array(
                        've/ve.debug.js',
diff --git a/demos/ve/index.php b/demos/ve/index.php
index 85295dd..23dbf40 100644
--- a/demos/ve/index.php
+++ b/demos/ve/index.php
@@ -59,7 +59,7 @@
                                </li>
                        <?php endforeach; ?>
                </ul>
-               <div class="ve-demo-content"></div>
+               <div class="ve-container"></div>
 
                <!-- Generated by maintenance/makeStaticLoader.php -->
                <!-- Dependencies -->
@@ -71,10 +71,12 @@
                <script src="../../modules/ve/ve.EventEmitter.js"></script>
                <script src="../../modules/ve/init/ve.init.js"></script>
                <script 
src="../../modules/ve/init/ve.init.Platform.js"></script>
+               <script src="../../modules/ve/init/ve.init.Target.js"></script>
                <script src="../../modules/ve/ve.debug.js"></script>
                <!-- Standalone Init -->
                <script src="../../modules/ve/init/sa/ve.init.sa.js"></script>
                <script 
src="../../modules/ve/init/sa/ve.init.sa.Platform.js"></script>
+               <script 
src="../../modules/ve/init/sa/ve.init.sa.Target.js"></script>
                <script>
                        <?php
                                require( 
'../../modules/../VisualEditor.i18n.php' );
@@ -212,12 +214,16 @@
                <script 
src="../../modules/ve/ui/inspectors/ve.ui.MWLinkInspector.js"></script>
                <!-- demo -->
                <script>
-                       $(document).ready( function () {
+                       $( document ).ready( function () {
+                               var target = new ve.init.sa.Target();
                                new ve.Surface(
-                                       $( '.ve-demo-content' ),
+                                       target.$,
                                        ve.createDocumentFromHTML( <?php echo 
json_encode( $html ) ?> )
+                                       target
                                );
                                $( '.ve-ce-documentNode' ).focus();
+                               //expose target for a sec.
+                               window.target = target;
                        } );
                </script>
 
diff --git a/modules/ve/init/mw/targets/ve.init.mw.ViewPageTarget.js 
b/modules/ve/init/mw/targets/ve.init.mw.ViewPageTarget.js
index 7fe0be8..8f6d102 100644
--- a/modules/ve/init/mw/targets/ve.init.mw.ViewPageTarget.js
+++ b/modules/ve/init/mw/targets/ve.init.mw.ViewPageTarget.js
@@ -57,13 +57,16 @@
                        'top': {
                                'float': !this.isMobileDevice,
                                // HACK: The toolbar configuration isn't very 
extendable, so this is mostly
-                               // copy-pasted from ve.Surface except using 
mwLink for the link tool
-                               'tools': [
-                                       { 'name': 'history', 'items' : ['undo', 
'redo'] },
-                                       { 'name': 'textStyle', 'items' : 
['format'] },
-                                       { 'name': 'textStyle', 'items' : 
['bold', 'italic', 'mwLink', 'clear'] },
-                                       { 'name': 'list', 'items' : ['number', 
'bullet', 'outdent', 'indent'] }
-                               ]
+                               'views': {
+                                       'edit': {
+                                               'groups': [
+                                                       { 'name': 'history', 
'items' : ['undo', 'redo'] },
+                                                       { 'name': 'textStyle', 
'items' : ['format'] },
+                                                       { 'name': 'textStyle', 
'items' : ['bold', 'italic', 'link', 'clear'] },
+                                                       { 'name': 'list', 
'items' : ['number', 'bullet', 'outdent', 'indent'] }
+                                               ]
+                                       }
+                               }
                        }
                },
                'commands': ['bold', 'italic', 'mwLink', 'undo', 'redo', 
'indent', 'outdent']
@@ -686,7 +689,7 @@
        // Store the HTML for reporting purposes
        this.originalHtml = doc.body.innerHTML; // TODO store entire document 
in the future
        // Initialize surface
-       this.surface = new ve.Surface( $( '#content' ), doc, 
this.surfaceOptions );
+       this.surface = new ve.Surface( this.$, doc, this, this.surfaceOptions );
        this.surface.getContext().hide();
        this.$document = this.surface.$.find( '.ve-ce-documentNode' );
        this.surface.getModel().on( 'transact', 
this.proxiedOnSurfaceModelTransact );
@@ -905,7 +908,7 @@
  * @method
  */
 ve.init.mw.ViewPageTarget.prototype.attachToolbarButtons = function () {
-       var $target = $( '.ve-ui-toolbar .ve-ui-actions' );
+       var $target = $( '.ve-ui-toolbar .ve-ui-toolbar-view-edit 
.ve-ui-actions' );
        $target.append( this.$toolbarFeedbackTool );
        if ( !ve.isEmptyObject( this.editNotices ) ) {
                $target.append( this.$toolbarEditNoticesTool );
@@ -1711,6 +1714,63 @@
        }
 };
 
+/**
+ * Adds an editor view to the target container.
+ *
+ * @method
+ * @param {string} view name of view.
+ * @param {object} config object of jQuery objects for the view.
+ */
+ve.init.mw.ViewPageTarget.prototype.addView = function ( view, config ) {
+       if( view in this.views ) {
+               throw new Error( 'View: ' + view + ' already registered!' );
+       }
+       this.views[view] = config;
+       // Add the view to the target container
+       if( config.$.length === 0 ) {
+               this.$.append( config.$ );
+       }
+       // Add the toolbar view to the toolbar.
+
+};
+
+/**
+ * Hides all registered views and shows given editor view & matching toolbar 
view.
+ *
+ * @method
+ * @param {string} view name of view.
+ */
+ve.init.mw.ViewPageTarget.prototype.showView = function ( view ) {
+       var name;
+       if ( !( view in this.views ) ) {
+               throw new Error( 'View: ' + view + ' not found!' );
+       }
+       // Hide all the views.
+       for( name in this.views ) {
+               this.hideView( name );
+       }
+       // Show view container.
+       this.views[view].$.show();
+       this.views[view].$toolbar.show();
+       // Show toolbar view container
+};
+
+
+/**
+ * Hide a view
+ *
+ * @method
+ * @param {string} view name of view.
+ */
+ve.init.mw.Target.prototype.hideView = function ( view ) {
+       if ( ! ( view in this.views ) ) {
+               throw new Error( 'View: ' + view + ' not found!' );
+       }
+       // Hide the view objects.
+       this.views[view].$.hide();
+       this.views[view].$toolbar.hide();
+};
+
 /* Initialization */
 
 ve.init.mw.targets.push( new ve.init.mw.ViewPageTarget() );
diff --git a/modules/ve/init/mw/ve.init.mw.Platform.js 
b/modules/ve/init/mw/ve.init.mw.Platform.js
index 5cb8c3f..1454d8b 100644
--- a/modules/ve/init/mw/ve.init.mw.Platform.js
+++ b/modules/ve/init/mw/ve.init.mw.Platform.js
@@ -1,5 +1,5 @@
 /*!
- * VisualEditor MediaWiki Initialization Target class.
+ * VisualEditor MediaWiki Initialization Platform class.
  *
  * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
  * @license The MIT License (MIT); see LICENSE.txt
diff --git a/modules/ve/init/mw/ve.init.mw.Target.js 
b/modules/ve/init/mw/ve.init.mw.Target.js
index 0f941b4..9ef116d 100644
--- a/modules/ve/init/mw/ve.init.mw.Target.js
+++ b/modules/ve/init/mw/ve.init.mw.Target.js
@@ -11,16 +11,17 @@
  * Initialization MediaWiki target.
  *
  * @class
- * @extends ve.EventEmitter
+ * @extends ve.init.Target
  * @constructor
  * @param {string} pageName Name of target page
  * @param {number} [revision] Revision ID
  */
 ve.init.mw.Target = function VeInitMwTarget( pageName, revision ) {
        // Parent constructor
-       ve.EventEmitter.call( this );
+       ve.init.Target.call( this );
 
        // Properties
+       this.$ = $( '#content' );
        this.pageName = pageName;
        this.pageExists = mw.config.get( 'wgArticleId', 0 ) !== 0;
        this.oldid = revision || '';
@@ -70,7 +71,7 @@
 
 /* Inheritance */
 
-ve.inheritClass( ve.init.mw.Target, ve.EventEmitter );
+ve.inheritClass( ve.init.mw.Target, ve.init.Target );
 
 /* Static Methods */
 
diff --git a/modules/ve/init/sa/styles/ve.init.sa.css 
b/modules/ve/init/sa/styles/ve.init.sa.css
index 0dc2c1e..fac7841 100644
--- a/modules/ve/init/sa/styles/ve.init.sa.css
+++ b/modules/ve/init/sa/styles/ve.init.sa.css
@@ -1,5 +1,5 @@
 /*!
- * VisualEditor Stand-alone Initialization styles.
+ * VisualEditor Standalone Initialization styles.
  *
  * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
  * @license The MIT License (MIT); see LICENSE.txt
diff --git a/modules/ve/init/sa/ve.init.sa.Platform.js 
b/modules/ve/init/sa/ve.init.sa.Platform.js
index 4daa93d..3b950ec 100644
--- a/modules/ve/init/sa/ve.init.sa.Platform.js
+++ b/modules/ve/init/sa/ve.init.sa.Platform.js
@@ -1,12 +1,12 @@
 /*!
- * VisualEditor stand-alone Initialization Target class.
+ * VisualEditor Standalone Initialization Platform class.
  *
  * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
  * @license The MIT License (MIT); see LICENSE.txt
  */
 
 /**
- * Initialization stand-alone platform.
+ * Initialization Standalone platform.
  *
  * @class
  * @extends ve.init.Platform
diff --git a/modules/ve/init/sa/ve.init.sa.Target.js 
b/modules/ve/init/sa/ve.init.sa.Target.js
new file mode 100644
index 0000000..c32c1de
--- /dev/null
+++ b/modules/ve/init/sa/ve.init.sa.Target.js
@@ -0,0 +1,72 @@
+/*!
+ * VisualEditor Standalone Initialization Target class.
+ *
+ * @copyright 2011-2012 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/*global mw */
+
+/**
+ * Initialization Standalone target.
+ *
+ * @class
+ * @extends ve.init.Target
+ * @constructor
+ */
+ve.init.sa.Target = function VeInitSaTarget() {
+       // Parent constructor
+       ve.init.Target.call( this );
+       this.$ = $( '.ve-container' );
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.init.sa.Target, ve.init.Target );
+
+/* Methods */
+
+/**
+ * Adds a view to the target.
+ *
+ * @method
+ * @param {string} message
+ */
+ve.init.sa.Target.prototype.addView = function ( view, config ) {
+       if( view in this.views ) {
+               throw new Error( 'View: ' + view + ' already registered!' );
+       }
+       this.views[view] = config;
+       // If not already present, add the dialog to the container.
+       if( config.$.length === 0 ) {
+               this.$.append( config.$ );
+       }
+};
+
+/**
+ * Show a view
+ *
+ * @method
+ * @param {string} view
+ */
+ve.init.sa.Target.prototype.showView = function ( view ) {
+       if ( ! ( view in this.views ) ) {
+               throw new Error( 'View: ' + view + ' not found!' );
+       }
+       // Show the dialog.
+       this.views[view].$.show();
+};
+
+/**
+ * Hide a view
+ *
+ * @method
+ * @param {string} view name of view.
+ */
+ve.init.sa.Target.prototype.hideView = function ( view ) {
+       if ( ! ( view in this.views ) ) {
+               throw new Error( 'View: ' + view + ' not found!' );
+       }
+       // Hide the dialog.
+       this.views[view].$.hide();
+};
diff --git a/modules/ve/init/ve.init.Platform.js 
b/modules/ve/init/ve.init.Platform.js
index b421370..afac259 100644
--- a/modules/ve/init/ve.init.Platform.js
+++ b/modules/ve/init/ve.init.Platform.js
@@ -1,5 +1,5 @@
 /*!
- * VisualEditor Initialization Target class.
+ * VisualEditor Initialization Platform class.
  *
  * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
  * @license The MIT License (MIT); see LICENSE.txt
diff --git a/modules/ve/init/ve.init.Target.js 
b/modules/ve/init/ve.init.Target.js
new file mode 100644
index 0000000..d178314
--- /dev/null
+++ b/modules/ve/init/ve.init.Target.js
@@ -0,0 +1,56 @@
+/*!
+ * VisualEditor Initialization Target class.
+ *
+ * @copyright 2011-2012 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * Generic Initialization target.
+ *
+ * @abstract
+ * @extends ve.EventEmitter
+ * @constructor
+ */
+ve.init.Target = function VeInitTarget() {
+       // Parent constructor
+       ve.EventEmitter.call( this );
+       // Map of target views
+       this.views = {};
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.init.Target, ve.EventEmitter );
+
+/* Abstract Methods */
+
+/**
+ * Adds a view to the target.
+ *
+ * @method
+ * @abstract
+ */
+ve.init.Target.prototype.addView = function () {
+       throw new Error( 've.init.Target.addView must be overridden in 
subclass' );
+};
+
+/**
+ * Show a view.
+ *
+ * @method
+ * @abstract
+ */
+ve.init.Target.prototype.showView = function () {
+       throw new Error( 've.init.Target.showView must be overridden in 
subclass' );
+};
+
+/**
+ * Hide a view.
+ *
+ * @method
+ * @abstract
+ */
+ve.init.Target.prototype.hideView = function () {
+       throw new Error( 've.init.Target.hideView must be overridden in 
subclass' );
+};
diff --git a/modules/ve/ve.Surface.js b/modules/ve/ve.Surface.js
index b777be1..0a41ee7 100644
--- a/modules/ve/ve.Surface.js
+++ b/modules/ve/ve.Surface.js
@@ -20,24 +20,24 @@
  * @constructor
  * @param {string} parent Selector of element to attach to
  * @param {HTMLDocument} doc HTML document to edit
+ * @param {Object} target Subclass of ve.init.Target
  * @param {Object} options Configuration options
  */
-ve.Surface = function VeSurface( parent, doc, options ) {
+ve.Surface = function VeSurface( parent, doc, target, options ) {
        // Properties
        this.$ = $( '<div>' );
        this.documentModel = new ve.dm.Document( 
ve.dm.converter.getDataFromDom( doc ) );
        this.options = ve.extendObject( true, ve.Surface.defaultOptions, 
options );
        this.model = new ve.dm.Surface( this.documentModel );
-       this.view = new ve.ce.Surface( this.$, this.model, this );
+       this.view =  new ve.ce.Surface( this.$, this.model, this );
        this.context = new ve.ui.Context( this );
+       this.target = target;
        this.toolbars = {};
        this.commands = {};
        this.enabled = true;
 
        // DOM Changes
-       this.$.addClass( 've-surface' );
-       $( parent ).append( this.$ );
-
+       $( parent ).append( this.$.addClass( 've-surface' ) );
        // Initialization
        // Propagate to each node information that it is live (attached to the 
live DOM)
        this.view.getDocument().getDocumentNode().setLive( true );
@@ -60,12 +60,16 @@
        'toolbars': {
                'top': {
                        'float': true,
-                       'tools': [
-                               { 'name': 'history', 'items' : ['undo', 'redo'] 
},
-                               { 'name': 'textStyle', 'items' : ['format'] },
-                               { 'name': 'textStyle', 'items' : ['bold', 
'italic', 'link', 'clear'] },
-                               { 'name': 'list', 'items' : ['number', 
'bullet', 'outdent', 'indent'] }
-                       ]
+                       'views': {
+                               'edit': {
+                                       'groups': [
+                                               { 'name': 'history', 'items' : 
['undo', 'redo'] },
+                                               { 'name': 'textStyle', 'items' 
: ['format'] },
+                                               { 'name': 'textStyle', 'items' 
: ['bold', 'italic', 'link', 'clear'] },
+                                               { 'name': 'list', 'items' : 
['number', 'bullet', 'outdent', 'indent'] }
+                                       ]
+                               }
+                       }
                }
        },
        // Items can either be symbolic names or objects with trigger and 
action properties
@@ -250,37 +254,50 @@
 };
 
 /**
- * Initialize the toolbar.
+ * Initialize all configured toolbars.
  *
  * This method uses {this.options} for its configuration.
  *
  * @method
  */
 ve.Surface.prototype.setupToolbars = function () {
-       var name, config, toolbar,
+       var name, config, toolbar, view, $toolbarView,
                toolbars = this.options.toolbars;
        for ( name in toolbars ) {
                config = toolbars[name];
                if ( ve.isPlainObject( config ) ) {
                        this.toolbars[name] = toolbar = { '$': $( '<div 
class="ve-ui-toolbar"></div>' ) };
-                       if ( name === 'top' ) {
+                       for( view in config.views ) {
+                               // Create a view element to place the tool 
groups in.
+                               $toolbarView = $( '<div 
class="ve-ui-toolbar-view-' + view + '">' )
+                                       .appendTo( toolbar.$ );
                                // Add extra sections to the toolbar
-                               toolbar.$.append(
-                                       '<div class="ve-ui-actions"></div>' +
-                                       '<div style="clear:both"></div>' +
-                                       '<div 
class="ve-ui-toolbar-shadow"></div>'
-                               );
-                               // Wrap toolbar for floating
-                               toolbar.$wrapper = $( '<div 
class="ve-ui-toolbar-wrapper"></div>' )
-                                       .append( this.toolbars[name].$ );
-                               // Add toolbar to surface
-                               this.$.before( toolbar.$wrapper );
-                               if ( 'float' in config && config.float === true 
) {
-                                       // Float top toolbar
-                                       this.floatTopToolbar();
-                               }
+                               $toolbarView.append( '<div 
class="ve-ui-actions"></div>' );
+                               // Create a new toolbar per configured view
+                               toolbar[view] = new ve.ui.Toolbar( 
$toolbarView, this, config.views[view].groups );
+                               // Register view.  If the view is the edit view,
+                               // use the Surface jQuery object.  Otherwise, 
attach an empty container.
+                               this.target.addView( view, {
+                                       '$': view === 'edit' ? this.$ : $( 
'<div>' ),
+                                       '$toolbar': $toolbarView
+                               } );
                        }
-                       toolbar.instance = new ve.ui.Toolbar( toolbar.$, this, 
config.tools );
+                       toolbar.$.append(
+                               '<div style="clear:both"></div>' +
+                               '<div class="ve-ui-toolbar-shadow"></div>'
+                       );
+               }
+               // Do special stuff to the top toolbar
+               if ( name === 'top' ) {
+                       // Wrap toolbar for floating
+                       toolbar.$wrapper = $( '<div 
class="ve-ui-toolbar-wrapper"></div>' )
+                               .append( toolbar.$ );
+                       // Add toolbar to surface
+                       this.$.before( toolbar.$wrapper );
+                       if ( 'float' in config && config.float === true ) {
+                               // Float top toolbar
+                               this.floatTopToolbar();
+                       }
                }
        }
 };

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iff39266bdd3052f34bda254ca407030dbbc81f26
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Robmoen <rm...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to