Trevor Parscal has uploaded a new change for review. https://gerrit.wikimedia.org/r/192738
Change subject: Context refactor ...................................................................... Context refactor * Context items are no longer options in a select * Context is now a group element, it's items are the context items * Context items are registered with the context item factory * ModeledFactory is a new mixin for factories of things that have static modelClasses properties * If a selected model doesn't have a context item for it, the tool factory is queried for matching tools and then ToolContextItem objects are created to provide a fallback * A context subclass can be configured to display context item descriptions instead of bodies, and the mobile context does so Change-Id: Ibca8cf5cb8ee2f0a8f520461cef3af6fa6f2ac4d --- M .docs/eg-iframe.html M build/modules.json M demos/ve/desktop.html M demos/ve/mobile.html A src/ui/contextitems/ve.ui.CommentContextItem.js A src/ui/contextitems/ve.ui.LanguageContextItem.js A src/ui/contextitems/ve.ui.LinkContextItem.js A src/ui/contextitems/ve.ui.ToolContextItem.js A src/ui/styles/contextitems/ve.ui.CommentContextItem.css A src/ui/styles/contextitems/ve.ui.LanguageContextItem.css A src/ui/styles/contextitems/ve.ui.LinkContextItem.css A src/ui/styles/contextitems/ve.ui.ToolContextItem.css M src/ui/styles/ve.ui.Context.css A src/ui/styles/ve.ui.ContextItem.css M src/ui/styles/ve.ui.DesktopContext.css A src/ui/styles/ve.ui.MobileContext.css D src/ui/styles/widgets/ve.ui.ContextOptionWidget.css D src/ui/styles/widgets/ve.ui.ContextSelectWidget.css D src/ui/styles/widgets/ve.ui.MobileContextOptionWidget.css M src/ui/ve.ui.Context.js A src/ui/ve.ui.ContextItem.js A src/ui/ve.ui.ContextItemFactory.js M src/ui/ve.ui.DesktopContext.js M src/ui/ve.ui.MobileContext.js A src/ui/ve.ui.ModeledFactory.js M src/ui/ve.ui.TableContext.js M src/ui/ve.ui.ToolFactory.js M src/ui/ve.ui.js D src/ui/widgets/ve.ui.ContextOptionWidget.js D src/ui/widgets/ve.ui.ContextSelectWidget.js D src/ui/widgets/ve.ui.MobileContextOptionWidget.js M tests/index.html 32 files changed, 940 insertions(+), 433 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/38/192738/1 diff --git a/.docs/eg-iframe.html b/.docs/eg-iframe.html index c95f847..418aac0 100644 --- a/.docs/eg-iframe.html +++ b/.docs/eg-iframe.html @@ -28,8 +28,6 @@ <link rel=stylesheet href="../src/ui/styles/tools/ve.ui.FormatTool.css" class="stylesheet-ve"> <link rel=stylesheet href="../src/ui/styles/widgets/ve.ui.LanguageInputWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../src/ui/styles/widgets/ve.ui.LanguageSearchWidget.css" class="stylesheet-ve"> - <link rel=stylesheet href="../src/ui/styles/widgets/ve.ui.ContextOptionWidget.css" class="stylesheet-ve"> - <link rel=stylesheet href="../src/ui/styles/widgets/ve.ui.ContextSelectWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../src/ui/styles/widgets/ve.ui.DimensionsWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../src/ui/styles/widgets/ve.ui.MediaSizeWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../src/ui/styles/inspectors/ve.ui.CommentInspector.css" class="stylesheet-ve"> @@ -37,6 +35,11 @@ <link rel=stylesheet href="../src/ui/styles/inspectors/ve.ui.LinkInspector.css" class="stylesheet-ve"> <link rel=stylesheet href="../src/ui/styles/inspectors/ve.ui.SpecialCharacterInspector.css" class="stylesheet-ve"> <link rel=stylesheet href="../src/ui/styles/ve.ui.Context.css" class="stylesheet-ve"> + <link rel=stylesheet href="../src/ui/styles/ve.ui.ContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../src/ui/styles/contextitems/ve.ui.CommentContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../src/ui/styles/contextitems/ve.ui.LanguageContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../src/ui/styles/contextitems/ve.ui.LinkContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../src/ui/styles/contextitems/ve.ui.ToolContextItem.css" class="stylesheet-ve"> <link rel=stylesheet href="../src/ui/styles/ve.ui.Overlay.css" class="stylesheet-ve"> <link rel=stylesheet href="../src/ui/styles/ve.ui.Surface.css" class="stylesheet-ve"> <link rel=stylesheet href="../src/ui/styles/widgets/ve.ui.SurfaceWidget.css" class="stylesheet-ve"> @@ -290,6 +293,13 @@ <script src="../src/ui/ve.ui.Overlay.js"></script> <script src="../src/ui/ve.ui.Surface.js"></script> <script src="../src/ui/ve.ui.Context.js"></script> + <script src="../src/ui/ve.ui.ModeledFactory.js"></script> + <script src="../src/ui/ve.ui.ContextItem.js"></script> + <script src="../src/ui/ve.ui.ContextItemFactory.js"></script> + <script src="../src/ui/contextitems/ve.ui.CommentContextItem.js"></script> + <script src="../src/ui/contextitems/ve.ui.LanguageContextItem.js"></script> + <script src="../src/ui/contextitems/ve.ui.LinkContextItem.js"></script> + <script src="../src/ui/contextitems/ve.ui.ToolContextItem.js"></script> <script src="../src/ui/ve.ui.TableContext.js"></script> <script src="../src/ui/ve.ui.Tool.js"></script> <script src="../src/ui/ve.ui.Toolbar.js"></script> @@ -340,8 +350,6 @@ <script src="../src/ui/widgets/ve.ui.LanguageInputWidget.js"></script> <script src="../src/ui/widgets/ve.ui.SurfaceWidget.js"></script> <script src="../src/ui/widgets/ve.ui.LinkTargetInputWidget.js"></script> - <script src="../src/ui/widgets/ve.ui.ContextSelectWidget.js"></script> - <script src="../src/ui/widgets/ve.ui.ContextOptionWidget.js"></script> <script src="../src/ui/widgets/ve.ui.DimensionsWidget.js"></script> <script src="../src/ui/widgets/ve.ui.MediaSizeWidget.js"></script> <script src="../src/ui/widgets/ve.ui.WhitespacePreservingTextInputWidget.js"></script> diff --git a/build/modules.json b/build/modules.json index 9b7126b..383a024 100644 --- a/build/modules.json +++ b/build/modules.json @@ -317,6 +317,13 @@ "src/ui/ve.ui.Overlay.js", "src/ui/ve.ui.Surface.js", "src/ui/ve.ui.Context.js", + "src/ui/ve.ui.ModeledFactory.js", + "src/ui/ve.ui.ContextItem.js", + "src/ui/ve.ui.ContextItemFactory.js", + "src/ui/contextitems/ve.ui.CommentContextItem.js", + "src/ui/contextitems/ve.ui.LanguageContextItem.js", + "src/ui/contextitems/ve.ui.LinkContextItem.js", + "src/ui/contextitems/ve.ui.ToolContextItem.js", "src/ui/ve.ui.TableContext.js", "src/ui/ve.ui.Tool.js", "src/ui/ve.ui.Toolbar.js", @@ -368,8 +375,6 @@ "src/ui/widgets/ve.ui.LanguageInputWidget.js", "src/ui/widgets/ve.ui.SurfaceWidget.js", "src/ui/widgets/ve.ui.LinkTargetInputWidget.js", - "src/ui/widgets/ve.ui.ContextSelectWidget.js", - "src/ui/widgets/ve.ui.ContextOptionWidget.js", "src/ui/widgets/ve.ui.DimensionsWidget.js", "src/ui/widgets/ve.ui.MediaSizeWidget.js", "src/ui/widgets/ve.ui.WhitespacePreservingTextInputWidget.js", @@ -412,8 +417,6 @@ "src/ui/styles/tools/ve.ui.FormatTool.css", "src/ui/styles/widgets/ve.ui.LanguageInputWidget.css", "src/ui/styles/widgets/ve.ui.LanguageSearchWidget.css", - "src/ui/styles/widgets/ve.ui.ContextOptionWidget.css", - "src/ui/styles/widgets/ve.ui.ContextSelectWidget.css", "src/ui/styles/widgets/ve.ui.DimensionsWidget.css", "src/ui/styles/widgets/ve.ui.MediaSizeWidget.css", "src/ui/styles/inspectors/ve.ui.CommentInspector.css", @@ -421,6 +424,11 @@ "src/ui/styles/inspectors/ve.ui.LinkInspector.css", "src/ui/styles/inspectors/ve.ui.SpecialCharacterInspector.css", "src/ui/styles/ve.ui.Context.css", + "src/ui/styles/ve.ui.ContextItem.css", + "src/ui/styles/contextitems/ve.ui.CommentContextItem.css", + "src/ui/styles/contextitems/ve.ui.LanguageContextItem.css", + "src/ui/styles/contextitems/ve.ui.LinkContextItem.css", + "src/ui/styles/contextitems/ve.ui.ToolContextItem.css", "src/ui/styles/ve.ui.Overlay.css", "src/ui/styles/ve.ui.Surface.css", "src/ui/styles/widgets/ve.ui.SurfaceWidget.css", @@ -561,12 +569,11 @@ "scripts": [ "src/ui/ve.ui.MobileSurface.js", "src/ui/ve.ui.MobileContext.js", - "src/ui/windowmanagers/ve.ui.MobileWindowManager.js", - "src/ui/widgets/ve.ui.MobileContextOptionWidget.js" + "src/ui/windowmanagers/ve.ui.MobileWindowManager.js" ], "styles": [ - "src/ui/styles/ve.ui.MobileSurface.css", - "src/ui/styles/widgets/ve.ui.MobileContextOptionWidget.css" + "src/ui/styles/ve.ui.MobileContext.css", + "src/ui/styles/ve.ui.MobileSurface.css" ], "dependencies": [ "visualEditor.core.build" diff --git a/demos/ve/desktop.html b/demos/ve/desktop.html index 0b686e8..6d52fd2 100644 --- a/demos/ve/desktop.html +++ b/demos/ve/desktop.html @@ -42,8 +42,6 @@ <link rel=stylesheet href="../../src/ui/styles/tools/ve.ui.FormatTool.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.LanguageInputWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.LanguageSearchWidget.css" class="stylesheet-ve"> - <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.ContextOptionWidget.css" class="stylesheet-ve"> - <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.ContextSelectWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.DimensionsWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.MediaSizeWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/inspectors/ve.ui.CommentInspector.css" class="stylesheet-ve"> @@ -51,6 +49,11 @@ <link rel=stylesheet href="../../src/ui/styles/inspectors/ve.ui.LinkInspector.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/inspectors/ve.ui.SpecialCharacterInspector.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/ve.ui.Context.css" class="stylesheet-ve"> + <link rel=stylesheet href="../../src/ui/styles/ve.ui.ContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../../src/ui/styles/contextitems/ve.ui.CommentContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../../src/ui/styles/contextitems/ve.ui.LanguageContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../../src/ui/styles/contextitems/ve.ui.LinkContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../../src/ui/styles/contextitems/ve.ui.ToolContextItem.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/ve.ui.Overlay.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/ve.ui.Surface.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.SurfaceWidget.css" class="stylesheet-ve"> @@ -307,6 +310,13 @@ <script src="../../src/ui/ve.ui.Overlay.js"></script> <script src="../../src/ui/ve.ui.Surface.js"></script> <script src="../../src/ui/ve.ui.Context.js"></script> + <script src="../../src/ui/ve.ui.ModeledFactory.js"></script> + <script src="../../src/ui/ve.ui.ContextItem.js"></script> + <script src="../../src/ui/ve.ui.ContextItemFactory.js"></script> + <script src="../../src/ui/contextitems/ve.ui.CommentContextItem.js"></script> + <script src="../../src/ui/contextitems/ve.ui.LanguageContextItem.js"></script> + <script src="../../src/ui/contextitems/ve.ui.LinkContextItem.js"></script> + <script src="../../src/ui/contextitems/ve.ui.ToolContextItem.js"></script> <script src="../../src/ui/ve.ui.TableContext.js"></script> <script src="../../src/ui/ve.ui.Tool.js"></script> <script src="../../src/ui/ve.ui.Toolbar.js"></script> @@ -358,8 +368,6 @@ <script src="../../src/ui/widgets/ve.ui.LanguageInputWidget.js"></script> <script src="../../src/ui/widgets/ve.ui.SurfaceWidget.js"></script> <script src="../../src/ui/widgets/ve.ui.LinkTargetInputWidget.js"></script> - <script src="../../src/ui/widgets/ve.ui.ContextSelectWidget.js"></script> - <script src="../../src/ui/widgets/ve.ui.ContextOptionWidget.js"></script> <script src="../../src/ui/widgets/ve.ui.DimensionsWidget.js"></script> <script src="../../src/ui/widgets/ve.ui.MediaSizeWidget.js"></script> <script src="../../src/ui/widgets/ve.ui.WhitespacePreservingTextInputWidget.js"></script> diff --git a/demos/ve/mobile.html b/demos/ve/mobile.html index ec72fa0..288f1a8 100644 --- a/demos/ve/mobile.html +++ b/demos/ve/mobile.html @@ -42,8 +42,6 @@ <link rel=stylesheet href="../../src/ui/styles/tools/ve.ui.FormatTool.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.LanguageInputWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.LanguageSearchWidget.css" class="stylesheet-ve"> - <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.ContextOptionWidget.css" class="stylesheet-ve"> - <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.ContextSelectWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.DimensionsWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.MediaSizeWidget.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/inspectors/ve.ui.CommentInspector.css" class="stylesheet-ve"> @@ -51,6 +49,11 @@ <link rel=stylesheet href="../../src/ui/styles/inspectors/ve.ui.LinkInspector.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/inspectors/ve.ui.SpecialCharacterInspector.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/ve.ui.Context.css" class="stylesheet-ve"> + <link rel=stylesheet href="../../src/ui/styles/ve.ui.ContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../../src/ui/styles/contextitems/ve.ui.CommentContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../../src/ui/styles/contextitems/ve.ui.LanguageContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../../src/ui/styles/contextitems/ve.ui.LinkContextItem.css" class="stylesheet-ve"> + <link rel=stylesheet href="../../src/ui/styles/contextitems/ve.ui.ToolContextItem.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/ve.ui.Overlay.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/ve.ui.Surface.css" class="stylesheet-ve"> <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.SurfaceWidget.css" class="stylesheet-ve"> @@ -59,8 +62,8 @@ <link rel=stylesheet href="../../src/ui/styles/ve.ui.Icons.css" class="stylesheet-ve"> <!-- visualEditor.mobile.build --> + <link rel=stylesheet href="../../src/ui/styles/ve.ui.MobileContext.css"> <link rel=stylesheet href="../../src/ui/styles/ve.ui.MobileSurface.css"> - <link rel=stylesheet href="../../src/ui/styles/widgets/ve.ui.MobileContextOptionWidget.css"> <!-- visualEditor.theme.mediawiki --> <link rel=stylesheet href="../../src/themes/mediawiki/dialogs.css"> @@ -308,6 +311,13 @@ <script src="../../src/ui/ve.ui.Overlay.js"></script> <script src="../../src/ui/ve.ui.Surface.js"></script> <script src="../../src/ui/ve.ui.Context.js"></script> + <script src="../../src/ui/ve.ui.ModeledFactory.js"></script> + <script src="../../src/ui/ve.ui.ContextItem.js"></script> + <script src="../../src/ui/ve.ui.ContextItemFactory.js"></script> + <script src="../../src/ui/contextitems/ve.ui.CommentContextItem.js"></script> + <script src="../../src/ui/contextitems/ve.ui.LanguageContextItem.js"></script> + <script src="../../src/ui/contextitems/ve.ui.LinkContextItem.js"></script> + <script src="../../src/ui/contextitems/ve.ui.ToolContextItem.js"></script> <script src="../../src/ui/ve.ui.TableContext.js"></script> <script src="../../src/ui/ve.ui.Tool.js"></script> <script src="../../src/ui/ve.ui.Toolbar.js"></script> @@ -359,8 +369,6 @@ <script src="../../src/ui/widgets/ve.ui.LanguageInputWidget.js"></script> <script src="../../src/ui/widgets/ve.ui.SurfaceWidget.js"></script> <script src="../../src/ui/widgets/ve.ui.LinkTargetInputWidget.js"></script> - <script src="../../src/ui/widgets/ve.ui.ContextSelectWidget.js"></script> - <script src="../../src/ui/widgets/ve.ui.ContextOptionWidget.js"></script> <script src="../../src/ui/widgets/ve.ui.DimensionsWidget.js"></script> <script src="../../src/ui/widgets/ve.ui.MediaSizeWidget.js"></script> <script src="../../src/ui/widgets/ve.ui.WhitespacePreservingTextInputWidget.js"></script> @@ -387,7 +395,6 @@ <script src="../../src/ui/ve.ui.MobileSurface.js"></script> <script src="../../src/ui/ve.ui.MobileContext.js"></script> <script src="../../src/ui/windowmanagers/ve.ui.MobileWindowManager.js"></script> - <script src="../../src/ui/widgets/ve.ui.MobileContextOptionWidget.js"></script> <!-- visualEditor.standalone.demo --> <script src="../../demos/ve/demo.js"></script> diff --git a/src/ui/contextitems/ve.ui.CommentContextItem.js b/src/ui/contextitems/ve.ui.CommentContextItem.js new file mode 100644 index 0000000..9567411 --- /dev/null +++ b/src/ui/contextitems/ve.ui.CommentContextItem.js @@ -0,0 +1,54 @@ + +/** + * @inheritdoc + *//*! + * VisualEditor CommentContextItem class. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/** + * Context item for a comment. + * + * @param {ve.ui.Context} context Context item is in + * @param {ve.dm.Model} model Model item is related to + * @param {Object} config Configuration options + */ +ve.ui.CommentContextItem = function VeCommentContextItem( context, model, config ) { + // Parent constructor + ve.ui.CommentContextItem.super.call( this, context, model, config ); + + // Initialization + this.$element.addClass( 've-ui-commentContextItem' ); +}; + +/* Inheritance */ + +OO.inheritClass( ve.ui.CommentContextItem, ve.ui.ContextItem ); + +/* Static Properties */ + +ve.ui.CommentContextItem.static.name = 'comment'; + +ve.ui.CommentContextItem.static.icon = 'comment'; + +ve.ui.CommentContextItem.static.label = OO.ui.deferMsg( 'visualeditor-commentinspector-title' ); + +ve.ui.CommentContextItem.static.modelClasses = [ ve.dm.CommentNode ]; + +ve.ui.CommentContextItem.static.embeddable = false; + +ve.ui.CommentContextItem.static.commandName = 'comment'; + +/* Methods */ + +/** + * @inheritdoc + */ +ve.ui.CommentContextItem.prototype.getDescription = function () { + return this.model.getAttribute( 'text' ).trim(); +}; + +/* Registration */ + +ve.ui.contextItemFactory.register( ve.ui.CommentContextItem ); diff --git a/src/ui/contextitems/ve.ui.LanguageContextItem.js b/src/ui/contextitems/ve.ui.LanguageContextItem.js new file mode 100644 index 0000000..64eae2d --- /dev/null +++ b/src/ui/contextitems/ve.ui.LanguageContextItem.js @@ -0,0 +1,51 @@ +/*! + * VisualEditor LanguageContextItem class. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/** + * Context item for a language. + * + * @param {ve.ui.Context} context Context item is in + * @param {ve.dm.Model} model Model item is related to + * @param {Object} config Configuration options + */ +ve.ui.LanguageContextItem = function VeLanguageContextItem( context, model, config ) { + // Parent constructor + ve.ui.LanguageContextItem.super.call( this, context, model, config ); + + // Initialization + this.$element.addClass( 've-ui-languageContextItem' ); +}; + +/* Inheritance */ + +OO.inheritClass( ve.ui.LanguageContextItem, ve.ui.ContextItem ); + +/* Static Properties */ + +ve.ui.LanguageContextItem.static.name = 'language'; + +ve.ui.LanguageContextItem.static.icon = 'language'; + +ve.ui.LanguageContextItem.static.label = OO.ui.deferMsg( 'visualeditor-languageinspector-title' ); + +ve.ui.LanguageContextItem.static.modelClasses = [ ve.dm.LanguageAnnotation ]; + +ve.ui.LanguageContextItem.static.embeddable = false; + +ve.ui.LanguageContextItem.static.commandName = 'language'; + +/* Methods */ + +/** + * @inheritdoc + */ +ve.ui.LanguageContextItem.prototype.getDescription = function () { + return ve.ce.LanguageAnnotation.static.getDescription( this.model ); +}; + +/* Registration */ + +ve.ui.contextItemFactory.register( ve.ui.LanguageContextItem ); diff --git a/src/ui/contextitems/ve.ui.LinkContextItem.js b/src/ui/contextitems/ve.ui.LinkContextItem.js new file mode 100644 index 0000000..df28117 --- /dev/null +++ b/src/ui/contextitems/ve.ui.LinkContextItem.js @@ -0,0 +1,65 @@ +/*! + * VisualEditor LinkContextItem class. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/** + * Context item for a link. + * + * @param {ve.ui.Context} context Context item is in + * @param {ve.dm.Model} model Model item is related to + * @param {Object} config Configuration options + */ +ve.ui.LinkContextItem = function VeLinkContextItem( context, model, config ) { + // Parent constructor + ve.ui.LinkContextItem.super.call( this, context, model, config ); + + // Initialization + this.$element.addClass( 've-ui-linkContextItem' ); +}; + +/* Inheritance */ + +OO.inheritClass( ve.ui.LinkContextItem, ve.ui.ContextItem ); + +/* Static Properties */ + +ve.ui.LinkContextItem.static.name = 'link'; + +ve.ui.LinkContextItem.static.icon = 'link'; + +ve.ui.LinkContextItem.static.label = OO.ui.deferMsg( 'visualeditor-linkinspector-title' ); + +ve.ui.LinkContextItem.static.modelClasses = [ ve.dm.LinkAnnotation ]; + +ve.ui.LinkContextItem.static.embeddable = false; + +ve.ui.LinkContextItem.static.commandName = 'link'; + +/* Methods */ + +/** + * @inheritdoc + */ +ve.ui.LinkContextItem.prototype.getDescription = function () { + return this.model.getHref(); +}; + +/** + * @inheritdoc + */ +ve.ui.LinkContextItem.prototype.renderBody = function () { + this.$body.empty().append( + $( '<a>' ) + .text( this.getDescription() ) + .attr( { + href: this.model.getHref(), + target: '_blank' + } ) + ); +}; + +/* Registration */ + +ve.ui.contextItemFactory.register( ve.ui.LinkContextItem ); diff --git a/src/ui/contextitems/ve.ui.ToolContextItem.js b/src/ui/contextitems/ve.ui.ToolContextItem.js new file mode 100644 index 0000000..2d0bff7 --- /dev/null +++ b/src/ui/contextitems/ve.ui.ToolContextItem.js @@ -0,0 +1,59 @@ +/*! + * VisualEditor ToolContextItem class. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/** + * Context item for a tool. + * + * @param {ve.ui.Context} context Context item is in + * @param {ve.dm.Model} model Model the item is related to + * @param {Function} tool Tool class the item is based on + * @param {Object} config Configuration options + */ +ve.ui.ToolContextItem = function VeToolContextItem( context, model, tool, config ) { + // Parent constructor + ve.ui.ToolContextItem.super.call( this, context, model, config ); + + // Properties + this.tool = tool; + + // Initialization + this.setIcon( tool.static.icon ); + this.setLabel( tool.static.title ); + this.$element.addClass( 've-ui-toolContextItem' ); +}; + +/* Inheritance */ + +OO.inheritClass( ve.ui.ToolContextItem, ve.ui.ContextItem ); + +/* Methods */ + +/** + * @inheritdoc + */ +ve.ui.ToolContextItem.prototype.getCommand = function () { + return ve.ui.commandRegistry.lookup( this.tool.static.commandName ); +}; + +/** + * Get a description of the model. + * + * @return {string} Description of model + */ +ve.ui.ToolContextItem.prototype.getDescription = function () { + var description; + + if ( this.model instanceof ve.dm.Annotation ) { + description = ve.ce.annotationFactory.getDescription( this.model ); + } else if ( this.model instanceof ve.dm.Node ) { + description = ve.ce.nodeFactory.getDescription( this.model ); + } + if ( !description ) { + description = this.tool.static.title; + } + + return description; +}; diff --git a/src/ui/styles/contextitems/ve.ui.CommentContextItem.css b/src/ui/styles/contextitems/ve.ui.CommentContextItem.css new file mode 100644 index 0000000..ec60d2b --- /dev/null +++ b/src/ui/styles/contextitems/ve.ui.CommentContextItem.css @@ -0,0 +1,13 @@ +/*! + * VisualEditor UserInterface CommentContextItem styles. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +.ve-ui-commentContextItem .ve-ui-contextItem-body { + padding: 0.5em 1.5em 1.5em 1.5em; + font-family: 'Courier New', 'Courier', monospace; + white-space: pre-wrap; + line-height: 1em; + color: #555; +} diff --git a/src/ui/styles/contextitems/ve.ui.LanguageContextItem.css b/src/ui/styles/contextitems/ve.ui.LanguageContextItem.css new file mode 100644 index 0000000..e939399 --- /dev/null +++ b/src/ui/styles/contextitems/ve.ui.LanguageContextItem.css @@ -0,0 +1,13 @@ +/*! + * VisualEditor UserInterface LanguageContextItem styles. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +.ve-ui-languageContextItem .ve-ui-contextItem-body { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 1.2em; + color: #555; +} diff --git a/src/ui/styles/contextitems/ve.ui.LinkContextItem.css b/src/ui/styles/contextitems/ve.ui.LinkContextItem.css new file mode 100644 index 0000000..edb4c21 --- /dev/null +++ b/src/ui/styles/contextitems/ve.ui.LinkContextItem.css @@ -0,0 +1,12 @@ +/*! + * VisualEditor UserInterface LinkContextItem styles. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +.ve-ui-linkContextItem .ve-ui-contextItem-body { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 1.2em; +} diff --git a/src/ui/styles/contextitems/ve.ui.ToolContextItem.css b/src/ui/styles/contextitems/ve.ui.ToolContextItem.css new file mode 100644 index 0000000..848e52c --- /dev/null +++ b/src/ui/styles/contextitems/ve.ui.ToolContextItem.css @@ -0,0 +1,12 @@ +/*! + * VisualEditor UserInterface ToolContextItem styles. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +.ve-ui-toolContextItem .ve-ui-contextItem-body { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 1.2em; +} diff --git a/src/ui/styles/ve.ui.Context.css b/src/ui/styles/ve.ui.Context.css index eebe9c2..7467016 100644 --- a/src/ui/styles/ve.ui.Context.css +++ b/src/ui/styles/ve.ui.Context.css @@ -6,5 +6,4 @@ /* Hide context by default, only show programmatically */ .ve-ui-context { - visibility: hidden; } \ No newline at end of file diff --git a/src/ui/styles/ve.ui.ContextItem.css b/src/ui/styles/ve.ui.ContextItem.css new file mode 100644 index 0000000..288d39c --- /dev/null +++ b/src/ui/styles/ve.ui.ContextItem.css @@ -0,0 +1,83 @@ +/*! + * VisualEditor UserInterface ContextItem styles. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +.ve-ui-contextItem { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} + +.ve-ui-contextItem-head { + display: table; + width: 100%; +} + +.ve-ui-contextItem-title { + display: table-cell; + width: 1%; + text-align: left; + padding: 0.5em 1em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.ve-ui-contextItem-icon { + display: inline-block; + vertical-align: middle; + width: 2em; + height: 2em; + background-position: center center; + background-repeat: no-repeat; +} + +.ve-ui-contextItem-label { + min-width: 4em; + display: inline-block; + vertical-align: middle; + margin-left: 0.5em; +} + +.ve-ui-contextItem-info { + display: table-cell; + position: relative; + width: 99%; +} + +.ve-ui-contextItem-description { + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + line-height: 3.6em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: #888; +} + +.ve-ui-contextItem-actions { + display: table-cell; + width: 1%; + text-align: right; + padding: 0.5em; +} + +.ve-ui-contextItem-editButton { + display: inline-block; + vertical-align: middle; +} + +.ve-ui-contextItem-body { + padding: 0 1em 0.5em 1em; +} + +.ve-ui-contextItem + .ve-ui-contextItem { + border-top: solid 1px #eee; +} diff --git a/src/ui/styles/ve.ui.DesktopContext.css b/src/ui/styles/ve.ui.DesktopContext.css index 6fc0a1d..0af77bc 100644 --- a/src/ui/styles/ve.ui.DesktopContext.css +++ b/src/ui/styles/ve.ui.DesktopContext.css @@ -8,9 +8,14 @@ position: absolute; } +.ve-ui-desktopContext .ve-ui-contextItem-description { + display: none; +} + .ve-ui-desktopContext-menu { position: absolute; font-size: 0.8em; + width: 300px; } .ve-ui-desktopContext-menu .oo-ui-toolbar-bar { diff --git a/src/ui/styles/ve.ui.MobileContext.css b/src/ui/styles/ve.ui.MobileContext.css new file mode 100644 index 0000000..cfd479f --- /dev/null +++ b/src/ui/styles/ve.ui.MobileContext.css @@ -0,0 +1,17 @@ +/*! + * VisualEditor UserInterface MobileSurface styles. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +.ve-ui-mobileContext { + font-size: 0.875em; +} + +.ve-ui-mobileContext .ve-ui-contextItem-body { + display: none; +} + +.ve-ui-mobileContext-menu { + border-top: solid 1px #eee; +} \ No newline at end of file diff --git a/src/ui/styles/widgets/ve.ui.ContextOptionWidget.css b/src/ui/styles/widgets/ve.ui.ContextOptionWidget.css deleted file mode 100644 index 151c7a5..0000000 --- a/src/ui/styles/widgets/ve.ui.ContextOptionWidget.css +++ /dev/null @@ -1,31 +0,0 @@ -/*! - * VisualEditor UserInterface ContextOptionWidget styles. - * - * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org - */ - -.ve-ui-contextOptionWidget { - padding: 0.5em 1em 0.5em 3em; -} - -.ve-ui-contextOptionWidget .oo-ui-labelElement-label { - color: #666; - /* Size required to match menu and inspector widths */ - max-width: 19.4em; - text-overflow: ellipsis; - overflow: hidden; -} - -.ve-ui-contextOptionWidget .oo-ui-iconElement-icon { - opacity: 0.8; -} - -.ve-ui-contextOptionWidget.oo-ui-optionWidget-highlighted, -.ve-ui-contextOptionWidget.oo-ui-optionWidget-selected, -.ve-ui-contextOptionWidget.oo-ui-optionWidget-pressed { - background-color: transparent; -} - -.ve-ui-contextOptionWidget.oo-ui-optionWidget-highlighted .oo-ui-iconElement-icon { - opacity: 1; -} diff --git a/src/ui/styles/widgets/ve.ui.ContextSelectWidget.css b/src/ui/styles/widgets/ve.ui.ContextSelectWidget.css deleted file mode 100644 index 679f6fc..0000000 --- a/src/ui/styles/widgets/ve.ui.ContextSelectWidget.css +++ /dev/null @@ -1,9 +0,0 @@ -/*! - * VisualEditor UserInterface ContextSelectWidget styles. - * - * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org - */ - -.ve-ui-contextSelectWidget { - padding: 0; -} diff --git a/src/ui/styles/widgets/ve.ui.MobileContextOptionWidget.css b/src/ui/styles/widgets/ve.ui.MobileContextOptionWidget.css deleted file mode 100644 index 488410c..0000000 --- a/src/ui/styles/widgets/ve.ui.MobileContextOptionWidget.css +++ /dev/null @@ -1,22 +0,0 @@ -/*! - * VisualEditor UserInterface MobileContextOptionWidget styles. - * - * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org - */ - -.ve-ui-mobileContextOptionWidget .oo-ui-labelElement-label { - max-width: none; - text-overflow: clip; -} - -.ve-ui-mobileContextOptionWidget-label-primary { - display: block; - text-overflow: ellipsis; - overflow: hidden; -} - -.ve-ui-mobileContextOptionWidget-label-secondary { - float: right; - margin-left: 1em; - color: #347bff; -} diff --git a/src/ui/ve.ui.Context.js b/src/ui/ve.ui.Context.js index 15c8276..ac14982 100644 --- a/src/ui/ve.ui.Context.js +++ b/src/ui/ve.ui.Context.js @@ -10,6 +10,7 @@ * @class * @abstract * @extends OO.ui.Element + * @mixins OO.ui.GroupElement * * @constructor * @param {ve.ui.Surface} surface @@ -17,14 +18,17 @@ */ ve.ui.Context = function VeUiContext( surface, config ) { // Parent constructor - OO.ui.Element.call( this, config ); + ve.ui.Context.super.call( this, config ); + + // Mixin constructors + OO.ui.GroupElement.call( this, config ); // Properties this.surface = surface; this.visible = false; + this.choosing = false; this.inspector = null; this.inspectors = this.createInspectorWindowManager(); - this.menu = new ve.ui.ContextSelectWidget( { $: this.$ } ); this.lastSelectedNode = null; this.afterContextChangeTimeout = null; this.afterContextChangeHandler = this.afterContextChange.bind( this ); @@ -33,22 +37,38 @@ // Events this.surface.getModel().connect( this, { contextChange: 'onContextChange' } ); this.inspectors.connect( this, { opening: 'onInspectorOpening' } ); - this.menu.connect( this, { choose: 'onContextItemChoose' } ); // Initialization // Hide element using a class, not this.toggle, as child implementations // of toggle may require the instance to be fully constructed before running. + this.$group.addClass( 've-ui-context-menu' ); this.$element - .addClass( 've-ui-context oo-ui-element-hidden' ); - this.menu.toggle( false ); + .addClass( 've-ui-context oo-ui-element-hidden' ) + .append( this.$group ); this.inspectors.$element.addClass( 've-ui-context-inspectors' ); }; /* Inheritance */ OO.inheritClass( ve.ui.Context, OO.ui.Element ); +OO.mixinClass( ve.ui.Context, OO.ui.GroupElement ); + +/* Static Property */ + +/** + * Instruct items to provide only a basic rendering. + * + * @static + * @inhertable + * @property {boolean} + */ +ve.ui.Context.static.basicRendering = false; /* Methods */ + +ve.ui.Context.prototype.shouldUseBasicRendering = function () { + return this.constructor.static.basicRendering; +}; /** * Handle context change event. @@ -75,8 +95,8 @@ this.afterContextChangeTimeout = setTimeout( this.afterContextChangeHandler ); } } - // Purge available tools cache - this.availableTools = null; + // Purge related items cache + this.relatedSources = null; }; /** @@ -89,17 +109,21 @@ this.afterContextChangeTimeout = null; if ( this.isVisible() ) { - if ( this.menu.isVisible() ) { + if ( !this.isEmpty() ) { if ( this.isInspectable() ) { // Change state: menu -> menu - this.populateMenu(); + this.teardownMenuItems(); + this.setupMenuItems(); this.updateDimensionsDebounced(); } else { // Change state: menu -> closed - this.menu.toggle( false ); + this.toggleMenu( false ); this.toggle( false ); } - } else if ( this.inspector && ( !selectedNode || ( selectedNode !== this.lastSelectedNode ) ) ) { + } else if ( + this.inspector && + ( !selectedNode || ( selectedNode !== this.lastSelectedNode ) ) + ) { // Change state: inspector -> (closed|menu) // Unless there is a selectedNode that hasn't changed (e.g. your inspector is editing a node) this.inspector.close(); @@ -107,8 +131,7 @@ } else { if ( this.isInspectable() ) { // Change state: closed -> menu - this.menu.toggle( true ); - this.populateMenu(); + this.toggleMenu( true ); this.toggle( true ); } } @@ -139,9 +162,9 @@ opening .progress( function ( data ) { if ( data.state === 'setup' ) { - if ( context.menu.isVisible() ) { + if ( !context.isEmpty() ) { // Change state: menu -> inspector - context.menu.toggle( false ); + context.toggleMenu( false ); } else if ( !context.isVisible() ) { // Change state: closed -> inspector context.toggle( true ); @@ -152,7 +175,7 @@ .always( function ( opened ) { opened.always( function ( closed ) { closed.always( function () { - var inspectable = !!context.getAvailableTools().length; + var inspectable = context.isInspectable(); context.inspector = null; @@ -161,8 +184,7 @@ if ( inspectable ) { // Change state: inspector -> menu - context.menu.toggle( true ); - context.populateMenu(); + context.toggleMenu( true ); context.updateDimensionsDebounced(); } else { // Change state: inspector -> closed @@ -176,17 +198,6 @@ } ); } ); } ); -}; - -/** - * Handle context item choose events. - * - * @param {ve.ui.ContextOptionWidget} item Chosen item - */ -ve.ui.Context.prototype.onContextItemChoose = function ( item ) { - if ( item ) { - item.getCommand().execute( this.surface ); - } }; /** @@ -204,7 +215,7 @@ * @return {boolean} Content is inspectable */ ve.ui.Context.prototype.isInspectable = function () { - return !!this.getAvailableTools().length; + return !!this.getRelatedSources().length; }; /** @@ -212,35 +223,63 @@ * * @return {boolean} Content is inspectable */ -ve.ui.Context.prototype.hasInspector = function () { - var i, availableTools = this.getAvailableTools(); - for ( i = availableTools.length - 1; i >= 0; i-- ) { - if ( availableTools[i].tool.prototype instanceof ve.ui.InspectorTool ) { - return true; +ve.ui.Context.prototype.isEmbeddable = function () { + var i, len, + sources = this.getRelatedSources(); + + for ( i = 0, len = sources.length; i < len; i++ ) { + if ( !sources[i].embedable ) { + return false; } } - return false; + + return true; }; /** - * Get available tools. + * Get related item sources. * * Result is cached, and cleared when the model or selection changes. * - * @returns {Object[]} List of objects containing `tool` and `model` properties, representing each - * compatible tool and the node or annotation it is compatible with + * @returns {Object[]} List of objects containing `type`, `name` and `model` properties, + * representing each compatible type (either `item` or `tool`), symbolic name of the item or tool + * and the model the item or tool is compatible with */ -ve.ui.Context.prototype.getAvailableTools = function () { - if ( !this.availableTools ) { +ve.ui.Context.prototype.getRelatedSources = function () { + var i, len, toolClass, items, tools, models, + selectedModels = this.surface.getModel().getFragment().getSelectedModels(); + + if ( !this.relatedSources ) { + this.relatedSources = []; if ( this.surface.getModel().getSelection() instanceof ve.dm.LinearSelection ) { - this.availableTools = ve.ui.toolFactory.getToolsForFragment( - this.surface.getModel().getFragment() - ); - } else { - this.availableTools = []; + models = []; + items = ve.ui.contextItemFactory.getRelatedItems( selectedModels ); + for ( i = 0, len = items.length; i < len; i++ ) { + models.push( items[i].model ); + this.relatedSources.push( { + type: 'item', + embedable: ve.ui.contextItemFactory.isEmbeddable( items[i].name ), + name: items[i].name, + model: items[i].model + } ); + } + tools = ve.ui.toolFactory.getRelatedItems( selectedModels ); + for ( i = 0, len = tools.length; i < len; i++ ) { + if ( models.indexOf( tools[i].model ) === -1 ) { + toolClass = ve.ui.toolFactory.lookup( tools[i].name ); + this.relatedSources.push( { + type: 'tool', + embedable: !toolClass || + !( toolClass.prototype instanceof ve.ui.InspectorTool ), + name: tools[i].name, + model: tools[i].model + } ); + } + } } } - return this.availableTools; + + return this.relatedSources; }; /** @@ -262,15 +301,6 @@ }; /** - * Get context menu. - * - * @return {ve.ui.ContextSelectWidget} - */ -ve.ui.Context.prototype.getMenu = function () { - return this.menu; -}; - -/** * Create a inspector window manager. * * @method @@ -283,34 +313,72 @@ }; /** - * Create a context item widget + * Toggle the menu. * - * @param {Object} tool Object containing tool and model properties. - * @return {ve.ui.ContextOptionWidget} Context item widget + * @param {boolean} [show] Show the menu, omit to toggle + * @chainable */ -ve.ui.Context.prototype.createItem = function ( tool ) { - return new ve.ui.ContextOptionWidget( - tool.tool, tool.model, { $: this.$, data: tool.tool.static.name } - ); +ve.ui.Context.prototype.toggleMenu = function ( show ) { + show = show === undefined ? !this.choosing : !!show; + + if ( show !== this.choosing ) { + this.choosing = show; + this.$element.toggleClass( 've-ui-context-choosing', show ); + if ( show ) { + this.setupMenuItems(); + } else { + this.teardownMenuItems(); + } + } + + return this; }; /** - * Update the contents of the menu. + * Setup menu items. * + * @protected * @chainable */ -ve.ui.Context.prototype.populateMenu = function () { - var i, len, - items = [], - tools = this.getAvailableTools(); +ve.ui.Context.prototype.setupMenuItems = function () { + var i, len, source, + sources = this.getRelatedSources(), + items = []; - this.menu.clearItems(); - if ( tools.length ) { - for ( i = 0, len = tools.length; i < len; i++ ) { - items.push( this.createItem( tools[i] ) ); + for ( i = 0, len = sources.length; i < len; i++ ) { + source = sources[i]; + if ( source.type === 'item' ) { + items.push( ve.ui.contextItemFactory.create( + sources[i].name, this, sources[i].model, { $: this.$ } + ) ); + } else if ( source.type === 'tool' ) { + items.push( new ve.ui.ToolContextItem( + this, sources[i].model, ve.ui.toolFactory.lookup( sources[i].name ), { $: this.$ } + ) ); } - this.menu.addItems( items ); } + + this.addItems( items ); + for ( i = 0, len = items.length; i < len; i++ ) { + items[i].setup(); + } + + return this; +}; + +/** + * Teardown menu items. + * + * @protected + * @chainable + */ +ve.ui.Context.prototype.teardownMenuItems = function () { + var i, len; + + for ( i = 0, len = this.items.length; i < len; i++ ) { + this.items[i].teardown(); + } + this.clearItems(); return this; }; @@ -347,7 +415,6 @@ // Disconnect events this.surface.getModel().disconnect( this ); this.inspectors.disconnect( this ); - this.menu.disconnect( this ); // Destroy inspectors WindowManager this.inspectors.destroy(); diff --git a/src/ui/ve.ui.ContextItem.js b/src/ui/ve.ui.ContextItem.js new file mode 100644 index 0000000..be3228f --- /dev/null +++ b/src/ui/ve.ui.ContextItem.js @@ -0,0 +1,179 @@ +/*! + * VisualEditor UserInterface ContextItem class. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/** + * Item in a context. + * + * @extends OO.ui.Widget + * @mixins OO.ui.IconElement + * @mixins OO.ui.LabelElement + * @mixins OO.ui.PendingElement + * + * @param {ve.ui.Context} context Context item is in + * @param {ve.dm.Model} model Model item is related to + * @param {Object} config Configuration options + * @cfg {boolean} [basic] Render only basic information + */ +ve.ui.ContextItem = function ( context, model, config ) { + // Parent constructor + ve.ui.ContextItem.super.call( this, config ); + + // Mixin constructors + OO.ui.IconElement.call( this, config ); + OO.ui.LabelElement.call( this, config ); + OO.ui.PendingElement.call( this, config ); + + // Properties + this.context = context; + this.model = model; + this.$head = $( '<div>' ); + this.$title = $( '<div>' ); + this.$actions = $( '<div>' ); + this.$body = $( '<div>' ); + this.$info = $( '<div>' ); + this.$description = $( '<div>' ); + this.editButton = new OO.ui.ButtonWidget( { + label: 'Edit', + flags: [ 'progressive' ], + classes: [ 've-ui-contextItem-editButton' ] + } ); + + // Events + this.editButton.connect( this, { click: 'onEditButtonClick' } ); + this.$element.on( 'mousedown', false ); + + // Initialization + this.$label.addClass( 've-ui-contextItem-label' ); + this.$icon.addClass( 've-ui-contextItem-icon' ); + this.$description.addClass( 've-ui-contextItem-description' ); + this.$info + .addClass( 've-ui-contextItem-info' ) + .append( this.$description ); + this.$title + .addClass( 've-ui-contextItem-title' ) + .append( this.$icon, this.$label ); + this.$actions + .addClass( 've-ui-contextItem-actions' ) + .append( this.editButton.$element ); + this.$head + .addClass( 've-ui-contextItem-head' ) + .append( this.$title, this.$info, this.$actions ); + this.$body.addClass( 've-ui-contextItem-body' ); + this.$element + .addClass( 've-ui-contextItem' ) + .toggleClass( 've-ui-contextItem-basic', this.context.shouldUseBasicRendering() ) + .append( this.$head, this.$body ); +}; + +OO.inheritClass( ve.ui.ContextItem, OO.ui.Widget ); +OO.mixinClass( ve.ui.ContextItem, OO.ui.IconElement ); +OO.mixinClass( ve.ui.ContextItem, OO.ui.LabelElement ); +OO.mixinClass( ve.ui.ContextItem, OO.ui.PendingElement ); + +/* Static Properties */ + +ve.ui.ContextItem.static.editable = true; + +ve.ui.ContextItem.static.embeddable = true; + +ve.ui.ContextItem.static.commandName = null; + +/* Methods */ + +/** + * Handle edit button click events. + * + * @localdoc Executes the command related to #static-commandName on the context's surface + * + * @protected + */ +ve.ui.ContextItem.prototype.onEditButtonClick = function () { + var command = this.getCommand(); + + if ( command ) { + command.execute( this.context.getSurface() ); + } +}; + +/** + * Check if item is editable. + * + * @return {boolean} Item is editable + */ +ve.ui.ContextItem.prototype.isEditable = function () { + return this.constructor.static.editable; +}; + +/** + * Get the command for this item. + * + * @return {ve.ui.Command} Command + */ +ve.ui.ContextItem.prototype.getCommand = function () { + return ve.ui.commandRegistry.lookup( this.constructor.static.commandName ); +}; + +/** + * Get the description. + * + * @localdoc Override for custom description content + * @return {string} Item description + */ +ve.ui.ContextItem.prototype.getDescription = function () { + return ''; +}; + +/** + * Render the body. + * + * @localdoc Renders the result of #getDescription + * @localdoc Override for custom body rendering + */ +ve.ui.ContextItem.prototype.renderBody = function () { + this.$body.text( this.getDescription() ); +}; + +/** + * Render the description. + * + * @localdoc Renders the result of #getDescription + * @localdoc Override for custom description rendering + */ +ve.ui.ContextItem.prototype.renderDescription = function () { + this.$description.text( this.getDescription() ); +}; + +/** + * Setup the item. + * + * @localdoc Calls #renderDescription if the context suggests basic rendering or #renderBody if not + * @localdoc Override to start any async rendering common to the body and description + * @chainable + */ +ve.ui.ContextItem.prototype.setup = function () { + this.editButton.toggle( this.isEditable() ); + + if ( this.context.shouldUseBasicRendering() ) { + this.renderDescription(); + } else { + this.renderBody(); + } + + return this; +}; + +/** + * Teardown the item. + * + * @localdoc Empties the description and body + * @localdox Override to abort any async rendering + * @chainable + */ +ve.ui.ContextItem.prototype.teardown = function () { + this.$description.empty(); + this.$body.empty(); + return this; +}; diff --git a/src/ui/ve.ui.ContextItemFactory.js b/src/ui/ve.ui.ContextItemFactory.js new file mode 100644 index 0000000..0761b87 --- /dev/null +++ b/src/ui/ve.ui.ContextItemFactory.js @@ -0,0 +1,46 @@ +/*! + * VisualEditor UserInterface ContextItemFactory class. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/** + * Factory for context items. + * + * @class + * @extends OO.Factory + * @mixins ve.ui.ModeledFactory + * + * @constructor + */ +ve.ui.ContextItemFactory = function VeUiContextItemFactory() { + // Parent constructor + ve.ui.ContextItemFactory.super.call( this ); + + // Mixin constructors + ve.ui.ModeledFactory.call( this ); +}; + +/* Inheritance */ + +OO.inheritClass( ve.ui.ContextItemFactory, OO.Factory ); +OO.mixinClass( ve.ui.ContextItemFactory, ve.ui.ModeledFactory ); + +/* Methods */ + +/** + * Check if an item is embeddable. + * + * @param {string} name Symbolic item name + * @return {boolean} Item is embeddable + */ +ve.ui.ContextItemFactory.prototype.isEmbeddable = function ( name ) { + if ( Object.prototype.hasOwnProperty.call( this.registry, name ) ) { + return !!this.registry[name].static.embeddable; + } + throw new Error( 'Unrecognized symbolic name: ' + name ); +}; + +/* Initialization */ + +ve.ui.contextItemFactory = new ve.ui.ContextItemFactory(); diff --git a/src/ui/ve.ui.DesktopContext.js b/src/ui/ve.ui.DesktopContext.js index 004b58e..6afee74 100644 --- a/src/ui/ve.ui.DesktopContext.js +++ b/src/ui/ve.ui.DesktopContext.js @@ -45,16 +45,9 @@ this.$element .addClass( 've-ui-desktopContext' ) .append( this.popup.$element ); - this.menu.$element.addClass( 've-ui-desktopContext-menu' ); + this.$group.addClass( 've-ui-desktopContext-menu' ); this.inspectors.$element.addClass( 've-ui-desktopContext-inspectors' ); - this.popup.$body.append( this.menu.$element, this.inspectors.$element ); - - // HACK: hide the popup with visibility: hidden; rather than display: none;, because - // the popup contains inspector iframes, and applying display: none; to those causes them to - // not load in Firefox - this.popup.$element - .css( { visibility: 'hidden' } ) - .removeClass( 'oo-ui-element-hidden' ); + this.popup.$body.append( this.$group, this.inspectors.$element ); }; /* Inheritance */ @@ -81,11 +74,10 @@ */ ve.ui.DesktopContext.prototype.onSuppress = function () { this.suppressed = true; - if ( this.isVisible() ) { - if ( this.menu.isVisible() ) { + if ( !this.isEmpty() ) { // Change state: menu -> closed - this.menu.toggle( false ); + this.toggleMenu( false ); this.toggle( false ); } else if ( this.inspector ) { // Change state: inspector -> closed @@ -98,14 +90,11 @@ * Handle context unsuppression event. */ ve.ui.DesktopContext.prototype.onUnsuppress = function () { - var inspectable = !!this.getAvailableTools().length; - this.suppressed = false; - if ( inspectable ) { + if ( this.isInspectable() ) { // Change state: closed -> menu - this.menu.toggle( true ); - this.populateMenu(); + this.toggleMenu( true ); this.toggle( true ); } }; @@ -166,19 +155,13 @@ return $.Deferred().resolve().promise(); } - this.visible = show; this.transitioning = $.Deferred(); promise = this.transitioning.promise(); this.popup.toggle( show ); - // HACK: make the context and popup visibility: hidden; instead of display: none; because - // they contain inspector iframes, and applying display: none; to those causes them to - // not load in Firefox - this.$element.add( this.popup.$element ) - .removeClass( 'oo-ui-element-hidden' ) - .css( { - visibility: show ? 'visible' : 'hidden' - } ); + + // Parent method + ve.ui.DesktopContext.super.prototype.toggle.call( this, show ); this.transitioning.resolve(); this.transitioning = null; @@ -216,9 +199,9 @@ this.popup.toggleAnchor( true ); this.popup.align = 'center'; } else if ( focusedNode && !focusedNode.isContent() ) { - embeddable = !this.hasInspector() && - boundingRect.height > this.menu.$element.outerHeight() + 5 && - boundingRect.width > this.menu.$element.outerWidth() + 10; + embeddable = this.isEmbeddable() && + boundingRect.height > this.$group.outerHeight() + 5 && + boundingRect.width > this.$group.outerWidth() + 10; this.popup.toggleAnchor( !embeddable ); if ( embeddable ) { // Embedded context position depends on directionality @@ -278,7 +261,7 @@ * Resize the popup to match the size of its contents (menu or inspector). */ ve.ui.DesktopContext.prototype.setPopupSize = function () { - var $container = this.inspector ? this.inspector.$frame : this.menu.$element; + var $container = this.inspector ? this.inspector.$frame : this.$group; // PopupWidget normally is clippable, suppress that to be able to resize and scroll it into view. // Needs to be repeated before every call, as it resets itself when the popup is shown or hidden. diff --git a/src/ui/ve.ui.MobileContext.js b/src/ui/ve.ui.MobileContext.js index 3f9cbdf..7db990c 100644 --- a/src/ui/ve.ui.MobileContext.js +++ b/src/ui/ve.ui.MobileContext.js @@ -28,11 +28,8 @@ } ); // Initialization - this.$element - .addClass( 've-ui-mobileContext' ) - .append( this.menu.$element ); - this.toggle( true ); - this.menu.$element.addClass( 've-ui-mobileContext-menu' ); + this.$element.addClass( 've-ui-mobileContext' ); + this.$group.addClass( 've-ui-mobileContext-menu' ); this.inspectors.$element.addClass( 've-ui-mobileContext-inspectors' ); this.surface.getGlobalOverlay().$element.append( this.inspectors.$element ); }; @@ -40,6 +37,10 @@ /* Inheritance */ OO.inheritClass( ve.ui.MobileContext, ve.ui.Context ); + +/* Static Properties */ + +ve.ui.MobileContext.static.basicRendering = true; /* Methods */ @@ -56,23 +57,13 @@ /** * @inheritdoc */ -ve.ui.MobileContext.prototype.createItem = function ( tool ) { - return new ve.ui.MobileContextOptionWidget( - tool.tool, tool.model, { $: this.$, data: tool.tool.static.name } - ); -}; - -/** - * @inheritdoc - */ ve.ui.MobileContext.prototype.toggle = function ( show ) { var deferred = $.Deferred(); show = show === undefined ? !this.visible : !!show; if ( show !== this.visible ) { this.visible = show; - this.$element - .toggleClass( 'oo-ui-element-hidden', !show ); + this.$element.toggleClass( 'oo-ui-element-hidden', !show ); setTimeout( function () { deferred.resolve(); }, 300 ); diff --git a/src/ui/ve.ui.ModeledFactory.js b/src/ui/ve.ui.ModeledFactory.js new file mode 100644 index 0000000..4f79aef --- /dev/null +++ b/src/ui/ve.ui.ModeledFactory.js @@ -0,0 +1,90 @@ +/*! + * VisualEditor UserInterface ModeledFactory class. + * + * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/** + * Mixin for factories that relate to models. + * + * @class + * @extends OO.ui.ModeledFactory + * + * @constructor + */ +ve.ui.ModeledFactory = function VeUiModeledFactory() { + // +}; + +/* Inheritance */ + +OO.initClass( ve.ui.ModeledFactory ); + +/* Methods */ + +/** + * Get a list of symbolic names for classes related to a list of models. + * + * The lowest compatible item in each inheritance chain will be used. + * + * @param {ve.dm.Model[]} models Models to find relationships with + * @returns {Object[]} List of objects containing `name` and `model` properties, representing + * each compatible class's symbolic name and the model it is compatible with + */ +ve.ui.ModeledFactory.prototype.getRelatedItems = function ( models ) { + var i, iLen, j, jLen, name, classes, model, + registry = this.registry, + names = {}, + matches = []; + + /** + * Collect the most specific compatible classes for a model. + * + * @private + * @param {ve.dm.Model} model Model to find compatability with + * @returns {Function[]} List of compatible classes + */ + function collect( model ) { + var i, len, name, candidate, add, modelClasses, + candidates = []; + + for ( name in registry ) { + candidate = registry[name]; + modelClasses = candidate.static.modelClasses; + if ( modelClasses && ve.isInstanceOfAny( model, modelClasses ) ) { + add = true; + for ( i = 0, len = candidates.length; i < len; i++ ) { + if ( candidate.prototype instanceof candidates[i] ) { + candidates.splice( i, 1, candidate ); + add = false; + break; + } else if ( candidates[i].prototype instanceof candidate ) { + add = false; + break; + } + } + if ( add ) { + candidates.push( candidate ); + } + } + } + + return candidates; + } + + // Collect compatible classes and the models they are specifically compatible with, + // discarding class's with duplicate symbolic names + for ( i = 0, iLen = models.length; i < iLen; i++ ) { + model = models[i]; + classes = collect( model ); + for ( j = 0, jLen = classes.length; j < jLen; j++ ) { + name = classes[j].static.name; + if ( !names[name] ) { + matches.push( { name: name, model: model } ); + } + names[name] = true; + } + } + + return matches; +}; diff --git a/src/ui/ve.ui.TableContext.js b/src/ui/ve.ui.TableContext.js index 9943aae..657a0bb 100644 --- a/src/ui/ve.ui.TableContext.js +++ b/src/ui/ve.ui.TableContext.js @@ -11,6 +11,7 @@ * * @class * @extends OO.ui.Element + * @mixins OO.ui.GroupElement * * @constructor * @param {ve.ce.TableNode} tableNode @@ -24,6 +25,9 @@ // Parent constructor ve.ui.TableContext.super.call( this, config ); + // Mixin constructors + OO.ui.GroupElement.call( this, config ); + // Properties this.tableNode = tableNode; this.toolGroup = toolGroup; @@ -34,7 +38,6 @@ classes: ['ve-ui-tableContext-indicator'], indicator: config.indicator } ); - this.menu = new ve.ui.ContextSelectWidget( { $: this.$ } ); this.popup = new OO.ui.PopupWidget( { $: this.$, $container: this.surface.$element, @@ -43,38 +46,40 @@ // Events this.indicator.$element.on( 'mousedown', this.onIndicatorMouseDown.bind( this ) ); - this.menu.connect( this, { choose: 'onContextItemChoose' } ); this.onDocumentMouseDownHandler = this.onDocumentMouseDown.bind( this ); // Initialization - this.populateMenu(); - this.menu.$element.addClass( 've-ui-tableContext-menu' ); - this.popup.$body.append( this.menu.$element ); + this.toggleMenu( true ); + this.$group.addClass( 've-ui-tableContext-menu' ); + this.popup.$body.append( this.$group ); this.$element.addClass( 've-ui-tableContext' ).append( this.indicator.$element, this.popup.$element ); }; /* Inheritance */ OO.inheritClass( ve.ui.TableContext, OO.ui.Element ); +OO.mixinClass( ve.ui.TableContext, OO.ui.GroupElement ); /* Methods */ /** * Populate menu items. */ -ve.ui.TableContext.prototype.populateMenu = function () { +ve.ui.TableContext.prototype.toggleMenu = function () { + /* var i, l, tool, items = [], toolList = ve.ui.toolFactory.getTools( [ { group: this.toolGroup } ] ); - this.menu.clearItems(); + this.clearItems(); for ( i = 0, l = toolList.length; i < l; i++ ) { tool = ve.ui.toolFactory.lookup( toolList[i] ); items.push( new ve.ui.ContextOptionWidget( tool, this.tableNode.getModel(), { $: this.$, data: tool.static.name } ) ); } - this.menu.addItems( items ); + this.addItems( items ); + */ }; /** diff --git a/src/ui/ve.ui.ToolFactory.js b/src/ui/ve.ui.ToolFactory.js index dd00a43..71c345a 100644 --- a/src/ui/ve.ui.ToolFactory.js +++ b/src/ui/ve.ui.ToolFactory.js @@ -9,84 +9,22 @@ * * @class * @extends OO.ui.ToolFactory + * @mixins ve.ui.ModeledFactory * * @constructor */ -ve.ui.ToolFactory = function OoUiToolFactory() { +ve.ui.ToolFactory = function VeUiToolFactory() { // Parent constructor - OO.ui.ToolFactory.call( this ); + ve.ui.ToolFactory.super.call( this ); + + // Mixin constructors + ve.ui.ModeledFactory.call( this ); }; /* Inheritance */ OO.inheritClass( ve.ui.ToolFactory, OO.ui.ToolFactory ); - -/* Methods */ - -/** - * Get a list of tools for a fragment. - * - * The lowest compatible item in each inheritance chain will be used. - * - * @method - * @param {ve.dm.SurfaceFragment} fragment Fragment to find compatible tools for - * @returns {Object[]} List of objects containing `tool` and `model` properties, representing each - * compatible tool and the node or annotation it is compatible with - */ -ve.ui.ToolFactory.prototype.getToolsForFragment = function ( fragment ) { - var i, iLen, j, jLen, name, tools, model, - models = fragment.getSelectedModels(), - names = {}, - matches = []; - - // Collect tool/model pairs, unique by tool name - for ( i = 0, iLen = models.length; i < iLen; i++ ) { - model = models[i]; - tools = this.collectCompatibleTools( model ); - for ( j = 0, jLen = tools.length; j < jLen; j++ ) { - name = tools[j].static.name; - if ( !names[name] ) { - matches.push( { tool: tools[j], model: model } ); - } - names[name] = true; - } - } - - return matches; -}; - -/** - * Collect the most specific compatible tools for an annotation or node. - * - * @param {ve.dm.Annotation|ve.dm.Node} model Annotation or node - * @returns {Function[]} List of compatible tools - */ -ve.ui.ToolFactory.prototype.collectCompatibleTools = function ( model ) { - var i, len, name, candidate, add, - candidates = []; - - for ( name in this.registry ) { - candidate = this.registry[name]; - if ( candidate.static.isCompatibleWith( model ) ) { - add = true; - for ( i = 0, len = candidates.length; i < len; i++ ) { - if ( candidate.prototype instanceof candidates[i] ) { - candidates.splice( i, 1, candidate ); - add = false; - break; - } else if ( candidates[i].prototype instanceof candidate ) { - add = false; - break; - } - } - if ( add ) { - candidates.push( candidate ); - } - } - } - - return candidates; -}; +OO.mixinClass( ve.ui.ToolFactory, ve.ui.ModeledFactory ); /* Initialization */ diff --git a/src/ui/ve.ui.js b/src/ui/ve.ui.js index 26bfad1..d06b4c3 100644 --- a/src/ui/ve.ui.js +++ b/src/ui/ve.ui.js @@ -15,6 +15,7 @@ // 'commandRegistry' instantiated in ve.ui.CommandRegistry.js // 'triggerRegistry' instantiated in ve.ui.TriggerRegistry.js // 'toolFactory' instantiated in ve.ui.ToolFactory.js + // 'contextItemFactory' instantiated in ve.ui.ContextItemFactory.js // 'dataTransferHandlerFactory' instantiated in ve.ui.DataTransferHandlerFactory.js windowFactory: new OO.Factory() }; diff --git a/src/ui/widgets/ve.ui.ContextOptionWidget.js b/src/ui/widgets/ve.ui.ContextOptionWidget.js deleted file mode 100644 index 0175076..0000000 --- a/src/ui/widgets/ve.ui.ContextOptionWidget.js +++ /dev/null @@ -1,71 +0,0 @@ -/*! - * VisualEditor Context Item widget class. - * - * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org - */ - -/** - * Proxy for a tool, displaying information about the current context. - * - * Use with ve.ui.ContextSelectWidget. - * - * @class - * @extends OO.ui.DecoratedOptionWidget - * - * @constructor - * @param {Function} tool Tool item is a proxy for - * @param {ve.dm.Node|ve.dm.Annotation} model Node or annotation item is related to - * @param {Object} [config] Configuration options - */ -ve.ui.ContextOptionWidget = function VeUiContextOptionWidget( tool, model, config ) { - // Config initialization - config = config || {}; - - // Parent constructor - ve.ui.ContextOptionWidget.super.call( this, config ); - - // Properties - this.tool = tool; - this.model = model; - - // Initialization - this.$element.addClass( 've-ui-contextOptionWidget' ); - this.setIcon( this.tool.static.icon ); - - this.setLabel( this.getDescription() ); -}; - -/* Setup */ - -OO.inheritClass( ve.ui.ContextOptionWidget, OO.ui.DecoratedOptionWidget ); - -/* Methods */ - -/** - * Get a description of the model. - * - * @return {string} Description of model - */ -ve.ui.ContextOptionWidget.prototype.getDescription = function () { - var description; - - if ( this.model instanceof ve.dm.Annotation ) { - description = ve.ce.annotationFactory.getDescription( this.model ); - } else if ( this.model instanceof ve.dm.Node ) { - description = ve.ce.nodeFactory.getDescription( this.model ); - } - if ( !description ) { - description = this.tool.static.title; - } - - return description; -}; - -/** - * Get the command for this item. - * - * @return {ve.ui.Command} Command - */ -ve.ui.ContextOptionWidget.prototype.getCommand = function () { - return ve.ui.commandRegistry.lookup( this.tool.static.commandName ); -}; diff --git a/src/ui/widgets/ve.ui.ContextSelectWidget.js b/src/ui/widgets/ve.ui.ContextSelectWidget.js deleted file mode 100644 index 98b5960..0000000 --- a/src/ui/widgets/ve.ui.ContextSelectWidget.js +++ /dev/null @@ -1,43 +0,0 @@ -/*! - * VisualEditor Context Menu widget class. - * - * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org - */ - -/** - * Menu of items, each an inspectable attribute of the current context. - * - * Use with ve.ui.ContextOptionWidget. - * - * @class - * @extends OO.ui.SelectWidget - * - * @constructor - * @param {Object} [config] Configuration options - */ -ve.ui.ContextSelectWidget = function VeUiContextSelectWidget( config ) { - // Config initialization - config = config || {}; - - // Parent constructor - ve.ui.ContextSelectWidget.super.call( this, config ); - - this.connect( this, { choose: 'onChooseItem' } ); - - // Initialization - this.$element.addClass( 've-ui-contextSelectWidget' ); -}; - -/* Setup */ - -OO.inheritClass( ve.ui.ContextSelectWidget, OO.ui.SelectWidget ); - -/* Methods */ - -/** - * Handle choose item events. - */ -ve.ui.ContextSelectWidget.prototype.onChooseItem = function () { - // Auto-deselect - this.selectItem( null ); -}; diff --git a/src/ui/widgets/ve.ui.MobileContextOptionWidget.js b/src/ui/widgets/ve.ui.MobileContextOptionWidget.js deleted file mode 100644 index 3b3eee5..0000000 --- a/src/ui/widgets/ve.ui.MobileContextOptionWidget.js +++ /dev/null @@ -1,35 +0,0 @@ -/*! - * VisualEditor Mobile Context Item widget class. - * - * @copyright 2011-2015 VisualEditor Team and others; see http://ve.mit-license.org - */ - -/** - * Mobile version of context item widget - * - * @class - * @extends ve.ui.ContextOptionWidget - * - * @constructor - * @param {Function} tool - * @param {ve.dm.Node|ve.dm.Annotation} model - * @param {Object} [config] - */ -ve.ui.MobileContextOptionWidget = function VeUiContextOptionWidget() { - // Parent constructor - ve.ui.MobileContextOptionWidget.super.apply( this, arguments ); - - this.$element.addClass( 've-ui-mobileContextOptionWidget' ); - this.setLabel( - this.$( '<span>' ).addClass( 've-ui-mobileContextOptionWidget-label-secondary' ) - .text( ve.msg( 'visualeditor-contextitemwidget-label-secondary' ) ) - .add( - this.$( '<span>' ).addClass( 've-ui-mobileContextOptionWidget-label-primary' ) - .text( this.getDescription() ) - ) - ); -}; - -/* Setup */ - -OO.inheritClass( ve.ui.MobileContextOptionWidget, ve.ui.ContextOptionWidget ); diff --git a/tests/index.html b/tests/index.html index 563f554..b028791 100644 --- a/tests/index.html +++ b/tests/index.html @@ -249,6 +249,13 @@ <script src="../src/ui/ve.ui.Overlay.js"></script> <script src="../src/ui/ve.ui.Surface.js"></script> <script src="../src/ui/ve.ui.Context.js"></script> + <script src="../src/ui/ve.ui.ModeledFactory.js"></script> + <script src="../src/ui/ve.ui.ContextItem.js"></script> + <script src="../src/ui/ve.ui.ContextItemFactory.js"></script> + <script src="../src/ui/contextitems/ve.ui.CommentContextItem.js"></script> + <script src="../src/ui/contextitems/ve.ui.LanguageContextItem.js"></script> + <script src="../src/ui/contextitems/ve.ui.LinkContextItem.js"></script> + <script src="../src/ui/contextitems/ve.ui.ToolContextItem.js"></script> <script src="../src/ui/ve.ui.TableContext.js"></script> <script src="../src/ui/ve.ui.Tool.js"></script> <script src="../src/ui/ve.ui.Toolbar.js"></script> @@ -299,8 +306,6 @@ <script src="../src/ui/widgets/ve.ui.LanguageInputWidget.js"></script> <script src="../src/ui/widgets/ve.ui.SurfaceWidget.js"></script> <script src="../src/ui/widgets/ve.ui.LinkTargetInputWidget.js"></script> - <script src="../src/ui/widgets/ve.ui.ContextSelectWidget.js"></script> - <script src="../src/ui/widgets/ve.ui.ContextOptionWidget.js"></script> <script src="../src/ui/widgets/ve.ui.DimensionsWidget.js"></script> <script src="../src/ui/widgets/ve.ui.MediaSizeWidget.js"></script> <script src="../src/ui/widgets/ve.ui.WhitespacePreservingTextInputWidget.js"></script> -- To view, visit https://gerrit.wikimedia.org/r/192738 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ibca8cf5cb8ee2f0a8f520461cef3af6fa6f2ac4d Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Trevor Parscal <tpars...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits