Trevor Parscal has uploaded a new change for review.
https://gerrit.wikimedia.org/r/53901
Change subject: Basic classes for grid and panel layouts and outline widget
......................................................................
Basic classes for grid and panel layouts and outline widget
* Also corrects issues with several of the stand-alone files by fixing and
using makeStaticLoader.php
Change-Id: I6b92c0204e176c914c26eff8c03ea417578e080c
---
M .docs/categories.json
M VisualEditor.php
M demos/ve/index.php
M maintenance/makeStaticLoader.php
M modules/ve/test/index.php
A modules/ve/ui/layouts/ve.ui.GridLayout.js
A modules/ve/ui/layouts/ve.ui.PanelLayout.js
A modules/ve/ui/ve.ui.Element.js
A modules/ve/ui/ve.ui.Layout.js
M modules/ve/ui/ve.ui.Widget.js
A modules/ve/ui/widgets/ve.ui.OutlineItemWidget.js
A modules/ve/ui/widgets/ve.ui.OutlineWidget.js
12 files changed, 619 insertions(+), 37 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor
refs/changes/01/53901/1
diff --git a/.docs/categories.json b/.docs/categories.json
index 6900e4f..b03d8f0 100644
--- a/.docs/categories.json
+++ b/.docs/categories.json
@@ -13,7 +13,13 @@
"groups": [
{
"name": "General",
- "classes": ["ve.ce", "ve.ce.NodeFactory",
"ve.ce.Surface", "ve.ce.SurfaceObserver", "ve.ce.DomRange"]
+ "classes": [
+ "ve.ce",
+ "ve.ce.NodeFactory",
+ "ve.ce.Surface",
+ "ve.ce.SurfaceObserver",
+ "ve.ce.DomRange"
+ ]
},
{
"name": "Nodes",
@@ -73,7 +79,19 @@
"groups": [
{
"name": "General",
- "classes": ["ve.ui", "ve.ui.Context",
"ve.ui.Frame", "ve.ui.InspectorFactory", "ve.ui.Toolbar", "ve.ui.ToolFactory",
"ve.ui.Dialog"]
+ "classes": [
+ "ve.ui",
+ "ve.ui.Context",
+ "ve.ui.Frame",
+ "ve.ui.Toolbar",
+ "ve.ui.Element",
+ "ve.ui.Window",
+ "ve.ui.WindowSet"
+ ]
+ },
+ {
+ "name": "Factories",
+ "classes": ["ve.ui.*Factory"]
},
{
"name": "Tools",
@@ -86,6 +104,10 @@
{
"name": "Widgets",
"classes": ["ve.ui.*Widget"]
+ },
+ {
+ "name": "Layouts",
+ "classes": ["ve.ui.*Layout"]
},
{
"name": "Dialogs",
@@ -131,7 +153,9 @@
},
{
"name": "JavaScript",
- "classes": ["Array", "Boolean", "Date",
"Function", "Number", "Object", "RegExp", "String"]
+ "classes": [
+ "Array", "Boolean", "Date", "Function",
"Number", "Object", "RegExp", "String"
+ ]
}
]
}
diff --git a/VisualEditor.php b/VisualEditor.php
index cdca7b6..ba867ff 100644
--- a/VisualEditor.php
+++ b/VisualEditor.php
@@ -305,11 +305,16 @@
've/ui/ve.ui.InspectorFactory.js',
've/ui/ve.ui.Dialog.js',
've/ui/ve.ui.DialogFactory.js',
+ 've/ui/ve.ui.Element.js',
+ 've/ui/ve.ui.Layout.js',
've/ui/ve.ui.Widget.js',
've/ui/ve.ui.Tool.js',
've/ui/ve.ui.Toolbar.js',
've/ui/ve.ui.ToolFactory.js',
+ 've/ui/layouts/ve.ui.GridLayout.js',
+ 've/ui/layouts/ve.ui.PanelLayout.js',
+
've/ui/widgets/ve.ui.LabeledWidget.js',
've/ui/widgets/ve.ui.FlaggableWidget.js',
've/ui/widgets/ve.ui.ButtonWidget.js',
diff --git a/demos/ve/index.php b/demos/ve/index.php
index 9deb8b8..213e62d 100644
--- a/demos/ve/index.php
+++ b/demos/ve/index.php
@@ -23,9 +23,16 @@
<meta charset="UTF-8">
<title>VisualEditor Standalone Demo</title>
- <!-- Generated by maintenance/makeStaticLoader.php -->
+ <!-- Generated by makeStaticLoader.php -->
<!-- Standalone Init -->
<link rel=stylesheet
href="../../modules/ve/init/sa/styles/ve.init.sa.css">
+ <script>
+ if ( window.devicePixelRatio > 1 ) {
+ document.write( '<link rel="stylesheet"
href="../../modules/ve/ui/styles/ve.ui.Icons-vector.css">' );
+ } else {
+ document.write( '<link rel="stylesheet"
href="../../modules/ve/ui/styles/ve.ui.Icons-raster.css">' );
+ }
+ </script>
<!-- ext.visualEditor.core -->
<link rel=stylesheet
href="../../modules/ve/styles/ve.Surface.css">
<link rel=stylesheet
href="../../modules/ve/ce/styles/ve.ce.DocumentNode.css">
@@ -36,17 +43,9 @@
<link rel=stylesheet
href="../../modules/ve/ui/styles/ve.ui.Window.css">
<link rel=stylesheet
href="../../modules/ve/ui/styles/ve.ui.Dialog.css">
<link rel=stylesheet
href="../../modules/ve/ui/styles/ve.ui.Inspector.css">
- <link rel=stylesheet
href="../../modules/ve/ui/styles/ve.ui.Tool.css">
<link rel=stylesheet
href="../../modules/ve/ui/styles/ve.ui.Toolbar.css">
+ <link rel=stylesheet
href="../../modules/ve/ui/styles/ve.ui.Tool.css">
<link rel=stylesheet
href="../../modules/ve/ui/styles/ve.ui.Widget.css">
-
- <script>
- if ( window.devicePixelRatio > 1 ) {
- document.write( '<link rel="stylesheet"
href="../../modules/ve/ui/styles/ve.ui.Icons-vector.css">' );
- } else {
- document.write( '<link rel="stylesheet"
href="../../modules/ve/ui/styles/ve.ui.Icons-raster.css">' );
- }
- </script>
<!-- demo -->
<link rel="stylesheet" href="demo.css">
@@ -63,7 +62,7 @@
</ul>
<div class="ve-demo-editor"></div>
- <!-- Generated by maintenance/makeStaticLoader.php -->
+ <!-- Generated by makeStaticLoader.php -->
<!-- Dependencies -->
<script src="../../modules/jquery/jquery.js"></script>
<script src="../../modules/rangy/rangy-core.js"></script>
@@ -82,7 +81,7 @@
<script>
<?php
require(
'../../modules/../VisualEditor.i18n.php' );
- echo 've.init.platform.addMessages( ' .
json_encode( $messages['en'] ) . ');';
+ echo 've.init.platform.addMessages( ' .
json_encode( $messages['en'] ) . ');' . "\n";
?>
ve.init.platform.setModulesUrl( '../../modules/' );
</script>
@@ -137,8 +136,6 @@
<script
src="../../modules/ve/dm/nodes/ve.dm.ListItemNode.js"></script>
<script
src="../../modules/ve/dm/nodes/ve.dm.ListNode.js"></script>
<script
src="../../modules/ve/dm/nodes/ve.dm.MetaNode.js"></script>
- <script
src="../../modules/ve/dm/nodes/ve.dm.MWEntityNode.js"></script>
- <script
src="../../modules/ve/dm/nodes/ve.dm.MWMetaNode.js"></script>
<script
src="../../modules/ve/dm/nodes/ve.dm.ParagraphNode.js"></script>
<script
src="../../modules/ve/dm/nodes/ve.dm.PreformattedNode.js"></script>
<script
src="../../modules/ve/dm/nodes/ve.dm.TableCellNode.js"></script>
@@ -146,6 +143,10 @@
<script
src="../../modules/ve/dm/nodes/ve.dm.TableRowNode.js"></script>
<script
src="../../modules/ve/dm/nodes/ve.dm.TableSectionNode.js"></script>
<script
src="../../modules/ve/dm/nodes/ve.dm.TextNode.js"></script>
+ <script
src="../../modules/ve/dm/nodes/ve.dm.MWEntityNode.js"></script>
+ <script
src="../../modules/ve/dm/nodes/ve.dm.MWHeadingNode.js"></script>
+ <script
src="../../modules/ve/dm/nodes/ve.dm.MWMetaNode.js"></script>
+ <script
src="../../modules/ve/dm/nodes/ve.dm.MWPreformattedNode.js"></script>
<script
src="../../modules/ve/dm/annotations/ve.dm.LinkAnnotation.js"></script>
<script
src="../../modules/ve/dm/annotations/ve.dm.MWExternalLinkAnnotation.js"></script>
<script
src="../../modules/ve/dm/annotations/ve.dm.MWInternalLinkAnnotation.js"></script>
@@ -172,7 +173,6 @@
<script
src="../../modules/ve/ce/nodes/ve.ce.ImageNode.js"></script>
<script
src="../../modules/ve/ce/nodes/ve.ce.ListItemNode.js"></script>
<script
src="../../modules/ve/ce/nodes/ve.ce.ListNode.js"></script>
- <script
src="../../modules/ve/ce/nodes/ve.ce.MWEntityNode.js"></script>
<script
src="../../modules/ve/ce/nodes/ve.ce.ParagraphNode.js"></script>
<script
src="../../modules/ve/ce/nodes/ve.ce.PreformattedNode.js"></script>
<script
src="../../modules/ve/ce/nodes/ve.ce.TableCellNode.js"></script>
@@ -180,6 +180,9 @@
<script
src="../../modules/ve/ce/nodes/ve.ce.TableRowNode.js"></script>
<script
src="../../modules/ve/ce/nodes/ve.ce.TableSectionNode.js"></script>
<script
src="../../modules/ve/ce/nodes/ve.ce.TextNode.js"></script>
+ <script
src="../../modules/ve/ce/nodes/ve.ce.MWEntityNode.js"></script>
+ <script
src="../../modules/ve/ce/nodes/ve.ce.MWHeadingNode.js"></script>
+ <script
src="../../modules/ve/ce/nodes/ve.ce.MWPreformattedNode.js"></script>
<script src="../../modules/ve/ui/ve.ui.js"></script>
<script src="../../modules/ve/ui/ve.ui.Context.js"></script>
<script src="../../modules/ve/ui/ve.ui.Frame.js"></script>
@@ -189,10 +192,14 @@
<script
src="../../modules/ve/ui/ve.ui.InspectorFactory.js"></script>
<script src="../../modules/ve/ui/ve.ui.Dialog.js"></script>
<script
src="../../modules/ve/ui/ve.ui.DialogFactory.js"></script>
+ <script src="../../modules/ve/ui/ve.ui.Element.js"></script>
+ <script src="../../modules/ve/ui/ve.ui.Layout.js"></script>
<script src="../../modules/ve/ui/ve.ui.Widget.js"></script>
<script src="../../modules/ve/ui/ve.ui.Tool.js"></script>
<script src="../../modules/ve/ui/ve.ui.Toolbar.js"></script>
<script src="../../modules/ve/ui/ve.ui.ToolFactory.js"></script>
+ <script
src="../../modules/ve/ui/layouts/ve.ui.GridLayout.js"></script>
+ <script
src="../../modules/ve/ui/layouts/ve.ui.PanelLayout.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.LabeledWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.FlaggableWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.ButtonWidget.js"></script>
@@ -225,8 +232,10 @@
<script
src="../../modules/ve/ui/tools/buttons/ve.ui.RedoButtonTool.js"></script>
<script
src="../../modules/ve/ui/tools/buttons/ve.ui.UndoButtonTool.js"></script>
<script
src="../../modules/ve/ui/tools/dropdowns/ve.ui.FormatDropdownTool.js"></script>
+ <script
src="../../modules/ve/ui/tools/dropdowns/ve.ui.MWFormatDropdownTool.js"></script>
<script
src="../../modules/ve/ui/inspectors/ve.ui.LinkInspector.js"></script>
<script
src="../../modules/ve/ui/inspectors/ve.ui.MWLinkInspector.js"></script>
+
<!-- demo -->
<script>
$( document ).ready( function () {
diff --git a/maintenance/makeStaticLoader.php b/maintenance/makeStaticLoader.php
index 978f181..071e32c 100644
--- a/maintenance/makeStaticLoader.php
+++ b/maintenance/makeStaticLoader.php
@@ -52,6 +52,7 @@
'scripts' => array(
've/init/sa/ve.init.sa.js',
've/init/sa/ve.init.sa.Platform.js',
+ 've/init/sa/ve.init.sa.Target.js',
),
'headAdd' => '
<script>
diff --git a/modules/ve/test/index.php b/modules/ve/test/index.php
index 73c0f2a..62a7b1a 100644
--- a/modules/ve/test/index.php
+++ b/modules/ve/test/index.php
@@ -8,7 +8,7 @@
<link rel="stylesheet" href="../../qunit/qunit.css">
<script src="../../qunit/qunit.js"></script>
- <!-- Generated by maintenance/makeStaticLoader.php -->
+ <!-- Generated by makeStaticLoader.php -->
<!-- Dependencies -->
<script src="../../jquery/jquery.js"></script>
<script src="../../rangy/rangy-core.js"></script>
@@ -27,7 +27,7 @@
<script>
<?php
require( '../../../VisualEditor.i18n.php' );
- echo 've.init.platform.addMessages( ' .
json_encode( $messages['en'] ) . ');';
+ echo 've.init.platform.addMessages( ' .
json_encode( $messages['en'] ) . ');' . "\n";
?>
ve.init.platform.setModulesUrl( '../../' );
</script>
@@ -138,10 +138,14 @@
<script src="../../ve/ui/ve.ui.InspectorFactory.js"></script>
<script src="../../ve/ui/ve.ui.Dialog.js"></script>
<script src="../../ve/ui/ve.ui.DialogFactory.js"></script>
+ <script src="../../ve/ui/ve.ui.Element.js"></script>
+ <script src="../../ve/ui/ve.ui.Layout.js"></script>
<script src="../../ve/ui/ve.ui.Widget.js"></script>
<script src="../../ve/ui/ve.ui.Tool.js"></script>
<script src="../../ve/ui/ve.ui.Toolbar.js"></script>
<script src="../../ve/ui/ve.ui.ToolFactory.js"></script>
+ <script src="../../ve/ui/layouts/ve.ui.GridLayout.js"></script>
+ <script src="../../ve/ui/layouts/ve.ui.PanelLayout.js"></script>
<script
src="../../ve/ui/widgets/ve.ui.LabeledWidget.js"></script>
<script
src="../../ve/ui/widgets/ve.ui.FlaggableWidget.js"></script>
<script
src="../../ve/ui/widgets/ve.ui.ButtonWidget.js"></script>
diff --git a/modules/ve/ui/layouts/ve.ui.GridLayout.js
b/modules/ve/ui/layouts/ve.ui.GridLayout.js
new file mode 100644
index 0000000..cec0041
--- /dev/null
+++ b/modules/ve/ui/layouts/ve.ui.GridLayout.js
@@ -0,0 +1,141 @@
+/*!
+ * VisualEditor UserInterface GridLayout class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * Grid layout.
+ *
+ * @class
+ * @extends ve.ui.Layout
+ *
+ * @constructor
+ * @param {ve.ui.PanelLayout[]} panels Panels in the grid
+ * @param {Object} [config] Config options
+ * @cfg {number[]} [widths] Widths of columns as ratios
+ * @cfg {number[]} [heights] Heights of columns as ratios
+ */
+ve.ui.GridLayout = function VeUiGridLayout( panels, config ) {
+ var i, len;
+
+ // Parent constructor
+ ve.ui.Layout.call( this, config );
+
+ // Properties
+ this.panels = [];
+ this.widths = [];
+ this.heights = [];
+
+ // Initialization
+ this.$.addClass( 've-ui-gridLayout' );
+ for ( i = 0, len = panels.length; i < len; i++ ) {
+ this.panels.push( panels[i] );
+ this.$.append( panels[i].$ );
+ }
+ if ( config.widths || config.heights ) {
+ this.layout( config.widths || [], config.heights || [] );
+ } else {
+ // Arrange in columns by default
+ this.layout( new Array( this.panels.length ), [] );
+ }
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.ui.GridLayout, ve.ui.Layout );
+
+/* Events */
+
+/**
+ * @event layout
+ */
+
+/**
+ * @event update
+ */
+
+/* Static Properties */
+
+ve.ui.GridLayout.static.tagName = 'div';
+
+/* Methods */
+
+/**
+ * Set grid dimensions.
+ *
+ * @method
+ * @param {number[]} widths Widths of columns as ratios
+ * @param {number[]} heights Heights of rows as ratios
+ * @throws {Error} If grid is not large enough to fit all panels
+ */
+ve.ui.GridLayout.prototype.layout = function ( widths, heights ) {
+ var x, y, xd, yd,
+ cols = widths.length,
+ rows = heights.length;
+
+ // Verify grid is big enough to fit panels
+ if ( cols * rows < this.panels.length ) {
+ throw new Error( 'Grid is not large enough to fit ' +
this.panels.length + 'panels' );
+ }
+
+ // Sum up denominators
+ for ( x = 0; x < cols; x++ ) {
+ xd += widths[x];
+ }
+ for ( y = 0; y < rows; y++ ) {
+ yd += heights[yd];
+ }
+ // Store factors
+ this.widths = [];
+ this.heights = [];
+ for ( x = 0; x < cols; x++ ) {
+ this.widths[x] = widths[x] / xd;
+ }
+ for ( y = 0; y < rows; y++ ) {
+ this.heights[x] = heights[y] / yd;
+ }
+ // Synchronize view
+ this.update();
+ this.emit( 'layout' );
+};
+
+/**
+ * Update panel positions and sizes.
+ *
+ * @method
+ */
+ve.ui.GridLayout.prototype.update = function () {
+ var x, y, panel,
+ cols = this.widths.length,
+ rows = this.heights.length,
+ width = this.$.width(),
+ height = this.$.height(),
+ dim = { 'width': 0, 'height': 0, 'left': 0, 'top': 0 };
+
+ for ( x = 0; x < cols; x++ ) {
+ for ( y = 0; y < rows; y++ ) {
+ panel = this.panels[( x * cols ) + y];
+ dim.left += dim.width;
+ dim.top += dim.height;
+ dim.width = width * this.widths[x];
+ dim.height = height * this.heights[y];
+ panel.$.css( dim );
+ }
+ }
+ this.emit( 'update' );
+};
+
+/**
+ * Get a panel at a given position.
+ *
+ * The x and y position is affected by the current grid layout.
+ *
+ * @method
+ * @param {number} x Horizontal position
+ * @param {number} y Vertical position
+ */
+ve.ui.GridLayout.prototype.getPanel = function ( x, y ) {
+ return this.panels[( x * this.widths.length ) + y];
+};
diff --git a/modules/ve/ui/layouts/ve.ui.PanelLayout.js
b/modules/ve/ui/layouts/ve.ui.PanelLayout.js
new file mode 100644
index 0000000..bf41a57
--- /dev/null
+++ b/modules/ve/ui/layouts/ve.ui.PanelLayout.js
@@ -0,0 +1,31 @@
+/*!
+ * VisualEditor UserInterface PanelLayout class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * Panel layout.
+ *
+ * @class
+ * @extends ve.ui.Layout
+ *
+ * @constructor
+ * @param {Object} [config] Config options
+ * @cfg {boolean} [scroll] Allow vertical scrolling
+ */
+ve.ui.PanelLayout = function VeUiPanelLayout( config ) {
+ // Parent constructor
+ ve.ui.Layout.call( this, config );
+
+ // Initialization
+ this.$.addClass( 've-ui-panelLayout' );
+ if ( config.scroll ) {
+ this.$.css( 'overflow-x', 'auto' );
+ }
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.ui.PanelLayout, ve.ui.Layout );
diff --git a/modules/ve/ui/ve.ui.Element.js b/modules/ve/ui/ve.ui.Element.js
new file mode 100644
index 0000000..3d01262
--- /dev/null
+++ b/modules/ve/ui/ve.ui.Element.js
@@ -0,0 +1,44 @@
+/*!
+ * VisualEditor UserInterface Element class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * Creates an ve.ui.Element object.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {Object} [config] Config options
+ * @cfg {Function} [$$=$] jQuery for the frame the widget is in
+ */
+ve.ui.Element = function VeUiElement( config ) {
+ // Initialize config
+ config = ve.extendObject( { '$$': $ }, config );
+
+ // Properties
+ this.$$ = config.$$;
+ this.$ = this.$$( '<' + this.constructor.static.tagName + '>' );
+};
+
+/* Static Properties */
+
+/**
+ * @static
+ * @property
+ * @inheritable
+ */
+ve.ui.Element.static = {};
+
+/**
+ * HTML element name.
+ *
+ * @static
+ * @property
+ * @type {string}
+ * @inheritable
+ */
+ve.ui.Element.static.tagName = 'div';
diff --git a/modules/ve/ui/ve.ui.Layout.js b/modules/ve/ui/ve.ui.Layout.js
new file mode 100644
index 0000000..0d41037
--- /dev/null
+++ b/modules/ve/ui/ve.ui.Layout.js
@@ -0,0 +1,37 @@
+/*!
+ * VisualEditor UserInterface Layout class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * Creates an ve.ui.Layout object.
+ *
+ * @class
+ * @abstract
+ * @extends ve.ui.Element
+ * @mixin ve.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Config options
+ */
+ve.ui.Layout = function VeUiLayout( config ) {
+ // Initialize config
+ config = config || {};
+
+ // Parent constructor
+ ve.EventEmitter.call( this );
+
+ // Mixin constructors
+ ve.ui.Element.call( this, config );
+
+ // Initialization
+ this.$.addClass( 've-ui-layout' );
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.ui.Layout, ve.ui.Element );
+
+ve.mixinClass( ve.ui.Layout, ve.EventEmitter );
diff --git a/modules/ve/ui/ve.ui.Widget.js b/modules/ve/ui/ve.ui.Widget.js
index cfdfdc9..8bf0211 100644
--- a/modules/ve/ui/ve.ui.Widget.js
+++ b/modules/ve/ui/ve.ui.Widget.js
@@ -10,23 +10,24 @@
*
* @class
* @abstract
- * @extends ve.EventEmitter
+ * @extends ve.ui.Element
+ * @mixin ve.EventEmitter
*
* @constructor
* @param {Object} [config] Config options
- * @cfg {Function} [$$=$] jQuery for the frame the widget is in
* @cfg {boolean} [disabled=false] Disable
*/
ve.ui.Widget = function VeUiWidget( config ) {
// Initialize config
- config = ve.extendObject( { '$$': $, 'disabled': false }, config );
+ config = ve.extendObject( { 'disabled': false }, config );
// Parent constructor
ve.EventEmitter.call( this );
+ // Mixin constructors
+ ve.ui.Element.call( this, config );
+
// Properties
- this.$$ = config.$$;
- this.$ = this.$$( '<' + this.constructor.static.tagName + '>' );
this.disabled = config.disabled;
// Initialization
@@ -36,19 +37,9 @@
/* Inheritance */
-ve.inheritClass( ve.ui.Widget, ve.EventEmitter );
+ve.inheritClass( ve.ui.Widget, ve.ui.Element );
-/* Static Properties */
-
-/**
- * HTML element name.
- *
- * @static
- * @property
- * @type {string}
- * @inheritable
- */
-ve.ui.Widget.static.tagName = 'div';
+ve.mixinClass( ve.ui.Widget, ve.EventEmitter );
/* Methods */
diff --git a/modules/ve/ui/widgets/ve.ui.OutlineItemWidget.js
b/modules/ve/ui/widgets/ve.ui.OutlineItemWidget.js
new file mode 100644
index 0000000..29e5bc8
--- /dev/null
+++ b/modules/ve/ui/widgets/ve.ui.OutlineItemWidget.js
@@ -0,0 +1,113 @@
+/*!
+ * VisualEditor UserInterface OutlineItemWidget class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * Creates an ve.ui.OutlineItemWidget object.
+ *
+ * @class
+ * @extends ve.ui.Widget
+ * @mixins ve.ui.LabeledWidget
+ *
+ * @constructor
+ * @param {jQuery|string} label Item label
+ * @param {Mixed} data Item data
+ * @param {Object} [config] Config options
+ * @cfg {string} [rel] Value for `rel` attribute in DOM, allowing per-item
styling
+ * @cfg {boolean} [selected] Select item
+ */
+ve.ui.OutlineItemWidget = function VeUiOutlineItemWidget( label, data, config
) {
+ // Config intialization
+ config = ve.extendObject( { 'selected': false }, config );
+
+ // Parent constructor
+ ve.ui.Widget.call( this, config );
+
+ // Mixin constructors
+ ve.ui.LabeledWidget.call( this, this.$$( '<span>' ), config );
+
+ // Properties
+ this.label = label;
+ this.data = data;
+ this.selected = config.selected;
+
+ // Events
+ this.$.on( 'click', ve.bind( this.onClick, this ) );
+
+ // Initialization
+ this.setLabel( this.label );
+ this.$label.addClass( 've-ui-outlineItemWidget-label' );
+ this.$.addClass( 've-ui-outlineItemWidget' ).append( this.$label );
+ this.$.attr( 'rel', config.rel );
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.ui.OutlineItemWidget, ve.ui.Widget );
+
+ve.mixinClass( ve.ui.OutlineItemWidget, ve.ui.LabeledWidget );
+
+/* Events */
+
+/**
+ * @event select
+ */
+
+/* Static Properties */
+
+ve.ui.OutlineItemWidget.static.tagName = 'li';
+
+/* Methods */
+
+/**
+ * Handle mouse click events.
+ *
+ * @method
+ * @private
+ * @param {jQuery.Event} e Mouse click event
+ */
+ve.ui.OutlineItemWidget.prototype.onClick = function () {
+ this.setSelected( true );
+ return false;
+};
+
+/**
+ * Get item data.
+ *
+ * @method
+ * @returns {Mixed} Item data
+ */
+ve.ui.OutlineItemWidget.prototype.getData = function () {
+ return this.data;
+};
+
+/**
+ * Check if item is selected.
+ *
+ * @method
+ * @returns {boolean} Item is selected
+ */
+ve.ui.OutlineItemWidget.prototype.isSelected = function () {
+ return this.selected;
+};
+
+/**
+ * Set selected state.
+ *
+ * @method
+ * @param {boolean} [state=false] Select item
+ * @chainable
+ */
+ve.ui.OutlineItemWidget.prototype.setSelected = function ( state ) {
+ this.selected = !!state;
+ if ( this.selected ) {
+ this.emit( 'select' );
+ this.$.addClass( 've-ui-outlineItemWidget-selected' );
+ } else {
+ this.$.removeClass( 've-ui-outlineItemWidget-selected' );
+ }
+ return this;
+};
diff --git a/modules/ve/ui/widgets/ve.ui.OutlineWidget.js
b/modules/ve/ui/widgets/ve.ui.OutlineWidget.js
new file mode 100644
index 0000000..7e6cf20
--- /dev/null
+++ b/modules/ve/ui/widgets/ve.ui.OutlineWidget.js
@@ -0,0 +1,182 @@
+/*!
+ * VisualEditor UserInterface OutlineWidget class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * Create an ve.ui.OutlineWidget object.
+ *
+ * @class
+ * @extends ve.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Config options
+ */
+ve.ui.OutlineWidget = function VeUiOutlineWidget( config ) {
+ // Config intialization
+ config = config || {};
+
+ // Parent constructor
+ ve.ui.Widget.call( this, config );
+
+ // Properties
+ this.sequence = [];
+ this.$items = this.$$( '<ul>' ).addClass( 've-ui-outlineWidget-items' );
+
+ // Initialization
+ this.$.hide().addClass( 've-ui-outlineWidget' ).append( this.$items );
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.ui.OutlineWidget, ve.ui.Widget );
+
+/* Events */
+
+/**
+ * @event select
+ * @param {ve.ui.OutlineItemWidget} item Selected item
+ */
+
+/* Methods */
+
+/**
+ * Handle item select events.
+ *
+ * @method
+ * @private
+ * @param {ve.ui.OutlineItemWidget} item Selected item
+ */
+ve.ui.OutlineWidget.prototype.onItemSelect = function ( item ) {
+ var i, len;
+
+ if ( !this.disabled ) {
+ // Make selection mutually exclusive
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ if ( this.items[i] !== item ) {
+ this.items[i].setSelected( false );
+ }
+ }
+ this.emit( 'select', item );
+ }
+};
+
+/**
+ * Get items.
+ *
+ * @method
+ * @returns {ve.ui.OutlineItemWidget[]} Items
+ */
+ve.ui.OutlineWidget.prototype.getItems = function () {
+ return this.items.slice( 0 );
+};
+
+/**
+ * Get selected item.
+ *
+ * @method
+ * @returns {ve.ui.OutlineItemWidget|null} Selected item
+ */
+ve.ui.OutlineWidget.prototype.getSelectedItem = function () {
+ var i, len;
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ if ( this.items[i].isSelected() ) {
+ return this.items[i];
+ }
+ }
+ return null;
+};
+
+/**
+ * Select an item.
+ *
+ * @method
+ * @param {ve.ui.OutlineItemWidget} [item] Item to select, omit to deselect all
+ * @chainable
+ */
+ve.ui.OutlineWidget.prototype.selectItem = function ( item ) {
+ var i, len;
+
+ if ( item ) {
+ item.setSelected( true );
+ } else {
+ // Deselect all
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ this.items[i].setSelected( false );
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Add items.
+ *
+ * Adding an existing item (by value) will move it.
+ *
+ * @method
+ * @param {ve.ui.OutlineItemWidget[]} items Item
+ * @chainable
+ */
+ve.ui.OutlineWidget.prototype.addItems = function ( items ) {
+ var i, len, item;
+
+ for ( i = 0, len = items.length; i < len; i++ ) {
+ item = items[i];
+
+ // Check if item exists then remove it first, effectively
"moving" it
+ if ( this.items.indexOf( item ) !== -1 ) {
+ this.removeItems( [item] );
+ }
+ // Add the item
+ this.items.push( item );
+ item.on( 'select', ve.bind( this.onItemSelect, this, item ) );
+ }
+
+ return this;
+};
+
+/**
+ * Remove items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @param {ve.ui.OutlineItemWidget[]} items Items to remove
+ * @chainable
+ */
+ve.ui.OutlineWidget.prototype.removeItems = function ( items ) {
+ var i, len, item, index;
+
+ // Remove specific items
+ for ( i = 0, len = items.length; i < len; i++ ) {
+ item = items[i];
+ index = this.items.indexOf( item );
+ if ( index !== -1 ) {
+ this.items.splice( index, 1 );
+ item.$.detach();
+ item.removeAllListeners( 'select' );
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Clear all items.
+ *
+ * Items will be detached, not removed, so they can be used later.
+ *
+ * @method
+ * @chainable
+ */
+ve.ui.OutlineWidget.prototype.clearItems = function () {
+ // Remove all items, leaving empty groups
+ this.items = [];
+ this.$items.children().detach();
+
+ return this;
+};
--
To view, visit https://gerrit.wikimedia.org/r/53901
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I6b92c0204e176c914c26eff8c03ea417578e080c
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Trevor Parscal <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits