Trevor Parscal has uploaded a new change for review.
https://gerrit.wikimedia.org/r/60700
Change subject: UI Refactor
......................................................................
UI Refactor
Changed:
VisualEditor.i18n.php
* Updated Link inspector i18n messages
ve.ui.MetaDialog.js -> ve.ui.PagedDialog
* Moved paging functionality into Paged dialog
ve.ui.EditorPanelLayout -> ve.ui.PagePanelLayout.js
* Renamed from EditorPanelLayout to work nicely with the concept of stacks and
pages
ve.ui.GroupElement.js
* Added addItem method and change addItems to use it
ve.ui.Dialog.css
* Updated classname as per refactor of meta dialog
ve.ui.StackPanelLayout.js
* Set currentItem property on showItem
* In addItems method, show currentItem with class method
** rather display block on element
ve.ui.Layout.css
* Make editorPanel layout 100% in width.
ve.ui.Widget.css
* Added CategoryWidget and CategoryPopup styles
* Other adjustments
ve.ui.PopupWidget.js
* Added auto-close on loss of focus
* Made friendly with being initialized inside a frame
ve.ui.MWLinkTargetInputWidget.js
* Mixin ve.ui.PendingInputWidget and remove pending methods
* Prevent querying on spaces
* Reintroduce i18n messages for menu sections
ve.ui.MenuWidget.js
* Update cases of $input config property to input
New:
ve.ui.PagedDialog.js
* Refactored base-class for mwMeta dialog (and probably other dialogs too)
* Abstracts adding and accessing pages
ve.ui.PendingInputWidget.js
* Moved pushPending and popPending methods into pending class
Change-Id: I29bcd92b7b5641941a4e98e65b2a56424a5263ff
---
M VisualEditor.i18n.php
M VisualEditor.php
M demos/ve/index.php
M modules/ve/test/index.php
D modules/ve/ui/dialogs/ve.ui.MetaDialog.js
A modules/ve/ui/dialogs/ve.ui.PagedDialog.js
M modules/ve/ui/elements/ve.ui.GroupElement.js
R modules/ve/ui/layouts/panels/ve.ui.PagePanelLayout.js
M modules/ve/ui/layouts/panels/ve.ui.StackPanelLayout.js
M modules/ve/ui/styles/ve.ui.Dialog.css
M modules/ve/ui/styles/ve.ui.Layout.css
M modules/ve/ui/styles/ve.ui.Widget.css
M modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js
M modules/ve/ui/widgets/ve.ui.MenuWidget.js
A modules/ve/ui/widgets/ve.ui.PendingInputWidget.js
M modules/ve/ui/widgets/ve.ui.PopupWidget.js
16 files changed, 252 insertions(+), 154 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor
refs/changes/00/60700/1
diff --git a/VisualEditor.i18n.php b/VisualEditor.i18n.php
index 8c491a0..1faeccd 100644
--- a/VisualEditor.i18n.php
+++ b/VisualEditor.i18n.php
@@ -43,9 +43,9 @@
'visualeditor-feedback-tool' => 'Leave feedback',
'visualeditor-window-title' => 'Inspect',
'visualeditor-linkinspector-title' => 'Hyperlink',
- 'visualeditor-linkinspector-suggest-existing-page' => 'Existing page',
+ 'visualeditor-linkinspector-suggest-matching-page' => 'Matching page',
'visualeditor-linkinspector-suggest-new-page' => 'New page',
- 'visualeditor-linkinspector-suggest-external-link' => 'Web link',
+ 'visualeditor-linkinspector-suggest-external-link' => 'External link',
'visualeditor-formatdropdown-title' => 'Change format',
'visualeditor-formatdropdown-format-paragraph' => 'Paragraph',
'visualeditor-formatdropdown-format-heading1' => 'Heading 1',
@@ -149,7 +149,7 @@
'visualeditor-window-title' => 'Title of an unnamed inspector',
'visualeditor-linkinspector-title' => 'Title of the link inspector
dialog.
{{Identical|Hyperlink}}',
- 'visualeditor-linkinspector-suggest-existing-page' => 'Label for
suggested existing pages in the link inspector',
+ 'visualeditor-linkinspector-suggest-matching-page' => 'Label for
suggested matching local wiki pages in the link inspector',
'visualeditor-linkinspector-suggest-new-page' => 'Label for a new page
in the link inspector',
'visualeditor-linkinspector-suggest-external-link' => 'Label for an
external (Web) link in the link inspector',
'visualeditor-formatdropdown-title' => 'This is a tooltip for the
drop-down box for choosing the formatting style of the selected text, such as
"Heading 1", "Heading 2" or "Plain text". (This is not related to "file format"
or "data format", such as "Wikitext", "HTML", "PDF" etc.)',
diff --git a/VisualEditor.php b/VisualEditor.php
index 2b5e928..7fb34fd 100644
--- a/VisualEditor.php
+++ b/VisualEditor.php
@@ -377,6 +377,7 @@
've/ui/widgets/ve.ui.MenuItemWidget.js',
've/ui/widgets/ve.ui.MenuSectionItemWidget.js',
've/ui/widgets/ve.ui.MenuWidget.js',
+ 've/ui/widgets/ve.ui.PendingInputWidget.js',
've/ui/widgets/ve.ui.TextInputMenuWidget.js',
've/ui/widgets/ve.ui.LinkTargetInputWidget.js',
've/ui/widgets/ve.ui.MWLinkTargetInputWidget.js',
@@ -384,11 +385,12 @@
've/ui/layouts/ve.ui.GridLayout.js',
've/ui/layouts/ve.ui.PanelLayout.js',
've/ui/layouts/panels/ve.ui.StackPanelLayout.js',
- 've/ui/layouts/panels/ve.ui.EditorPanelLayout.js',
+ 've/ui/layouts/panels/ve.ui.PagePanelLayout.js',
've/ui/dialogs/ve.ui.ContentDialog.js',
've/ui/dialogs/ve.ui.MediaDialog.js',
- 've/ui/dialogs/ve.ui.MetaDialog.js',
+ 've/ui/dialogs/ve.ui.PagedDialog.js',
+ 've/ui/dialogs/ve.ui.MWMetaDialog.js',
've/ui/tools/ve.ui.ButtonTool.js',
've/ui/tools/ve.ui.AnnotationButtonTool.js',
@@ -449,7 +451,8 @@
'visualeditor',
'visualeditor-inspector-title',
'visualeditor-linkinspector-title',
- 'visualeditor-linkinspector-suggest-existing-page',
+ 'visualeditor-linkinspector-label-pagetitle',
+ 'visualeditor-linkinspector-suggest-matching-page',
'visualeditor-linkinspector-suggest-new-page',
'visualeditor-linkinspector-suggest-external-link',
'visualeditor-formatdropdown-title',
diff --git a/demos/ve/index.php b/demos/ve/index.php
index b7c1e86..6a2b7ac 100644
--- a/demos/ve/index.php
+++ b/demos/ve/index.php
@@ -254,16 +254,17 @@
<script
src="../../modules/ve/ui/widgets/ve.ui.MenuItemWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.MenuSectionItemWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.MenuWidget.js"></script>
+ <script
src="../../modules/ve/ui/widgets/ve.ui.PendingInputWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.TextInputMenuWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.LinkTargetInputWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.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/layouts/panels/ve.ui.StackPanelLayout.js"></script>
- <script
src="../../modules/ve/ui/layouts/panels/ve.ui.EditorPanelLayout.js"></script>
+ <script
src="../../modules/ve/ui/layouts/panels/ve.ui.PagePanelLayout.js"></script>
<script
src="../../modules/ve/ui/dialogs/ve.ui.ContentDialog.js"></script>
<script
src="../../modules/ve/ui/dialogs/ve.ui.MediaDialog.js"></script>
- <script
src="../../modules/ve/ui/dialogs/ve.ui.MetaDialog.js"></script>
+ <script
src="../../modules/ve/ui/dialogs/ve.ui.PagedDialog.js"></script>
<script
src="../../modules/ve/ui/tools/ve.ui.ButtonTool.js"></script>
<script
src="../../modules/ve/ui/tools/ve.ui.AnnotationButtonTool.js"></script>
<script
src="../../modules/ve/ui/tools/ve.ui.DialogButtonTool.js"></script>
diff --git a/modules/ve/test/index.php b/modules/ve/test/index.php
index 273b863..c6930be 100644
--- a/modules/ve/test/index.php
+++ b/modules/ve/test/index.php
@@ -203,10 +203,10 @@
<script src="../../ve/ui/layouts/ve.ui.GridLayout.js"></script>
<script src="../../ve/ui/layouts/ve.ui.PanelLayout.js"></script>
<script
src="../../ve/ui/layouts/panels/ve.ui.StackPanelLayout.js"></script>
- <script
src="../../ve/ui/layouts/panels/ve.ui.EditorPanelLayout.js"></script>
+ <script
src="../../ve/ui/layouts/panels/ve.ui.PagePanelLayout.js"></script>
<script
src="../../ve/ui/dialogs/ve.ui.ContentDialog.js"></script>
<script src="../../ve/ui/dialogs/ve.ui.MediaDialog.js"></script>
- <script src="../../ve/ui/dialogs/ve.ui.MetaDialog.js"></script>
+ <script src="../../ve/ui/dialogs/ve.ui.PagedDialog.js"></script>
<script src="../../ve/ui/tools/ve.ui.ButtonTool.js"></script>
<script
src="../../ve/ui/tools/ve.ui.AnnotationButtonTool.js"></script>
<script
src="../../ve/ui/tools/ve.ui.DialogButtonTool.js"></script>
diff --git a/modules/ve/ui/dialogs/ve.ui.MetaDialog.js
b/modules/ve/ui/dialogs/ve.ui.MetaDialog.js
deleted file mode 100644
index 1751ce3..0000000
--- a/modules/ve/ui/dialogs/ve.ui.MetaDialog.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/*!
- * VisualEditor user interface MetaDialog class.
- *
- * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
- * @license The MIT License (MIT); see LICENSE.txt
- */
-
-/**
- * Document dialog.
- *
- * @class
- * @abstract
- * @extends ve.ui.Dialog
- *
- * @constructor
- * @param {ve.Surface} surface
- */
-ve.ui.MetaDialog = function VeUiMetaDialog( surface ) {
- // Parent constructor
- ve.ui.Dialog.call( this, surface );
-};
-
-/* Inheritance */
-
-ve.inheritClass( ve.ui.MetaDialog, ve.ui.Dialog );
-
-/* Static Properties */
-
-ve.ui.MetaDialog.static.titleMessage = 'visualeditor-dialog-meta-title';
-
-ve.ui.MetaDialog.static.icon = 'settings';
-
-/* Methods */
-
-/**
- * Handle frame ready events.
- *
- * @method
- */
-ve.ui.MetaDialog.prototype.initialize = function () {
- // Call parent method
- ve.ui.Dialog.prototype.initialize.call( this );
-
- // Properties
- this.outlinePanel = new ve.ui.PanelLayout( { '$$': this.$$, 'scroll':
true } );
- this.editorPanel = new ve.ui.StackPanelLayout( { '$$': this.$$ } );
- this.editorPanels = {
- 'categories': new ve.ui.EditorPanelLayout( {
- '$$': this.$$, 'icon': 'tag', 'label': 'Categories'
- } ),
- 'languages': new ve.ui.EditorPanelLayout( {
- '$$': this.$$, 'icon': 'language', 'label': 'Languages'
- } )
- };
- this.layout = new ve.ui.GridLayout(
- [this.outlinePanel, this.editorPanel],
- { '$$': this.$$, 'widths': [1, 2] }
- );
- this.editorPanel.addItems( ve.getObjectValues( this.editorPanels ) );
-
- // HACK
- this.outlineWidget = new ve.ui.OutlineWidget( { '$$': this.$$ } );
- this.outlineWidget.addItems( [
- new ve.ui.OutlineItemWidget(
- 'categories', { '$$': this.$$, 'icon': 'tag', 'label':
'Categories' }
- ),
- new ve.ui.OutlineItemWidget(
- 'languages', { '$$': this.$$, 'icon': 'language',
'label': 'Languages' }
- )
- ] );
- this.outlineWidget
- .on( 'select', ve.bind( function ( item ) {
- this.editorPanel.showItem(
this.editorPanels[item.getData()] );
- }, this ) )
- .selectItem( this.outlineWidget.getClosestSelectableItem( 0 ) );
-
- // Initialization
- this.outlinePanel.$.addClass( 've-ui-metaDialog-outlinePanel' );
- this.editorPanel.$.addClass( 've-ui-metaDialog-editorPanel' );
- this.$body.append( this.layout.$ );
- this.outlinePanel.$.append( this.outlineWidget.$ );
- this.layout.update();
-};
-
-/* Registration */
-
-ve.ui.dialogFactory.register( 'meta', ve.ui.MetaDialog );
diff --git a/modules/ve/ui/dialogs/ve.ui.PagedDialog.js
b/modules/ve/ui/dialogs/ve.ui.PagedDialog.js
new file mode 100644
index 0000000..f9a1c12
--- /dev/null
+++ b/modules/ve/ui/dialogs/ve.ui.PagedDialog.js
@@ -0,0 +1,100 @@
+/*!
+ * VisualEditor user interface PagedDialog class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * Paged dialog.
+ *
+ * A paged dialog has an outline in the left third, and a series of pages in
the right two-thirds.
+ * Pages can be added using the #addPage method, and later accessed using
`this.pages[name]` or
+ * through the #getPage method.
+ *
+ * @class
+ * @abstract
+ * @extends ve.ui.Dialog
+ *
+ * @constructor
+ * @param {ve.Surface} surface
+ */
+ve.ui.PagedDialog = function VeUiPagedDialog( surface ) {
+ // Parent constructor
+ ve.ui.Dialog.call( this, surface );
+
+ // Properties
+ this.pages = {};
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.ui.PagedDialog, ve.ui.Dialog );
+
+/* Methods */
+
+/**
+ * Handle frame ready events.
+ *
+ * @method
+ */
+ve.ui.PagedDialog.prototype.initialize = function () {
+ // Call parent method
+ ve.ui.Dialog.prototype.initialize.call( this );
+
+ // Properties
+ this.outlinePanel = new ve.ui.PanelLayout( { '$$': this.$$, 'scroll':
true } );
+ this.pagesPanel = new ve.ui.StackPanelLayout( { '$$': this.$$ } );
+ this.layout = new ve.ui.GridLayout(
+ [this.outlinePanel, this.pagesPanel], { '$$': this.$$,
'widths': [1, 2] }
+ );
+ this.outlineWidget = new ve.ui.OutlineWidget( { '$$': this.$$ } );
+
+ // Events
+ this.outlineWidget.on( 'select', ve.bind( function ( item ) {
+ if ( item ) {
+ this.pagesPanel.showItem( this.pages[item.getData()] );
+ }
+ }, this ) );
+
+ // Initialization
+ this.outlinePanel.$.append( this.outlineWidget.$ ).addClass(
've-ui-pagedDialog-outlinePanel' );
+ this.pagesPanel.$.addClass( 've-ui-pagedDialog-pagesPanel' );
+ this.$body.append( this.layout.$ );
+};
+
+/**
+ * Add a page to the dialog.
+ *
+ * @method
+ * @param {string} name Symbolic name of page
+ * @param {jQuery|string} [label] Page label
+ * @param {string} [icon] Symbolic name of icon
+ * @chainable
+ */
+ve.ui.PagedDialog.prototype.addPage = function ( name, label, icon ) {
+ var config = { '$$': this.$$, 'icon': icon, 'label': label || name };
+
+ // Create and add page panel and outline item
+ this.pages[name] = new ve.ui.PagePanelLayout( config );
+ this.pagesPanel.addItems( [this.pages[name]] );
+ this.outlineWidget.addItems( [ new ve.ui.OutlineItemWidget( name,
config ) ] );
+
+ // Auto-select first item when nothing is selected yet
+ if ( !this.outlineWidget.getSelectedItem() ) {
+ this.outlineWidget.selectItem(
this.outlineWidget.getClosestSelectableItem( 0 ) );
+ }
+
+ return this;
+};
+
+/**
+ * Get a page by name.
+ *
+ * @method
+ * @param {string} name Symbolic name of page
+ * @returns {ve.ui.PagePanelLayout|undefined} Page, if found
+ */
+ve.ui.PagedDialog.prototype.getPage = function ( name ) {
+ return this.pages[name];
+};
diff --git a/modules/ve/ui/elements/ve.ui.GroupElement.js
b/modules/ve/ui/elements/ve.ui.GroupElement.js
index 904a7f7..eec22df 100644
--- a/modules/ve/ui/elements/ve.ui.GroupElement.js
+++ b/modules/ve/ui/elements/ve.ui.GroupElement.js
@@ -41,20 +41,29 @@
* @chainable
*/
ve.ui.GroupElement.prototype.addItems = function ( items ) {
- var i, len, item;
-
+ var i, len;
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 );
- this.$group.append( item.$ );
- this.$items = this.$items.add( item.$ );
+ this.addItem( items[i] );
}
+ return this;
+};
+
+/**
+ * Add item.
+ *
+ * @method
+ * @param {ve.ui.Widget} item Item
+ * @chainable
+ */
+ve.ui.GroupElement.prototype.addItem = function ( item ) {
+ // 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 );
+ this.$.append( item.$ );
+ this.$items = this.$items.add( item.$ );
return this;
};
@@ -70,7 +79,6 @@
*/
ve.ui.GroupElement.prototype.removeItems = function ( items ) {
var i, len, item, index;
-
// Remove specific items
for ( i = 0, len = items.length; i < len; i++ ) {
item = items[i];
diff --git a/modules/ve/ui/layouts/panels/ve.ui.EditorPanelLayout.js
b/modules/ve/ui/layouts/panels/ve.ui.PagePanelLayout.js
similarity index 64%
rename from modules/ve/ui/layouts/panels/ve.ui.EditorPanelLayout.js
rename to modules/ve/ui/layouts/panels/ve.ui.PagePanelLayout.js
index 59cd3f7..c783b59 100644
--- a/modules/ve/ui/layouts/panels/ve.ui.EditorPanelLayout.js
+++ b/modules/ve/ui/layouts/panels/ve.ui.PagePanelLayout.js
@@ -1,12 +1,12 @@
/*!
- * VisualEditor UserInterface EditorPanelLayout class.
+ * VisualEditor UserInterface PagePanelLayout class.
*
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
- * Editor panel layout.
+ * Page panel layout.
*
* @class
* @extends ve.ui.PanelLayout
@@ -16,7 +16,7 @@
* @param {Object} [config] Config options
* @cfg {string} [icon=''] Symbolic icon name
*/
-ve.ui.EditorPanelLayout = function VeUiEditorPanelLayout( config ) {
+ve.ui.PagePanelLayout = function VeUiPagePanelLayout( config ) {
// Config initialization
config = ve.extendObject( config, { 'scroll': true } );
@@ -26,6 +26,9 @@
// Mixin constructors
ve.ui.LabeledElement.call( this, this.$$( '<div>' ), config );
+ // Properties
+ this.icon = config.icon;
+
// Initialization
this.$label.addClass( 've-ui-icon-' + config.icon + '-big' );
this.$.append( this.$label ).addClass( 've-ui-editorPanelLayout' );
@@ -33,6 +36,12 @@
/* Inheritance */
-ve.inheritClass( ve.ui.EditorPanelLayout, ve.ui.PanelLayout );
+ve.inheritClass( ve.ui.PagePanelLayout, ve.ui.PanelLayout );
-ve.mixinClass( ve.ui.EditorPanelLayout, ve.ui.LabeledElement );
+ve.mixinClass( ve.ui.PagePanelLayout, ve.ui.LabeledElement );
+
+/* Methods */
+
+ve.ui.PagePanelLayout.prototype.getIcon = function () {
+ return this.icon;
+};
diff --git a/modules/ve/ui/layouts/panels/ve.ui.StackPanelLayout.js
b/modules/ve/ui/layouts/panels/ve.ui.StackPanelLayout.js
index 51e432e..5bf34ac 100644
--- a/modules/ve/ui/layouts/panels/ve.ui.StackPanelLayout.js
+++ b/modules/ve/ui/layouts/panels/ve.ui.StackPanelLayout.js
@@ -55,7 +55,7 @@
for ( i = 0, len = items.length; i < len; i++ ) {
if ( !this.currentItem ) {
- items[i].$.show();
+ this.showItem( items[i] );
} else {
items[i].$.hide();
}
@@ -113,6 +113,7 @@
ve.ui.StackPanelLayout.prototype.showItem = function ( item ) {
this.$items.hide();
item.$.show();
+ this.currentItem = item;
return this;
};
diff --git a/modules/ve/ui/styles/ve.ui.Dialog.css
b/modules/ve/ui/styles/ve.ui.Dialog.css
index 4ed959c..26eea26 100644
--- a/modules/ve/ui/styles/ve.ui.Dialog.css
+++ b/modules/ve/ui/styles/ve.ui.Dialog.css
@@ -117,6 +117,6 @@
margin: 0.25em 0.25em;
}
-.ve-ui-metaDialog-outlinePanel {
+.ve-ui-pagedDialog-outlinePanel {
border-right: solid 1px #ddd;
}
diff --git a/modules/ve/ui/styles/ve.ui.Layout.css
b/modules/ve/ui/styles/ve.ui.Layout.css
index a7ca079..8e647c1 100644
--- a/modules/ve/ui/styles/ve.ui.Layout.css
+++ b/modules/ve/ui/styles/ve.ui.Layout.css
@@ -25,6 +25,7 @@
.ve-ui-editorPanelLayout {
padding: 1.5em;
+ width: 100%;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
diff --git a/modules/ve/ui/styles/ve.ui.Widget.css
b/modules/ve/ui/styles/ve.ui.Widget.css
index 562b01c..3ea4ca8 100644
--- a/modules/ve/ui/styles/ve.ui.Widget.css
+++ b/modules/ve/ui/styles/ve.ui.Widget.css
@@ -236,9 +236,8 @@
.ve-ui-menuWidget {
position: absolute;
- background: #FFFFFF;
+ background: #fff;
margin-top: -1px;
- font-size: 0.8em;
z-index: 101;
border: solid 1px #ccc;
border-radius: 0 0 0.25em 0.25em;
@@ -268,9 +267,9 @@
cursor: default;
}
-/* ve.ui.MWLinkTargetInputWidget */
+/* ve.ui.PendingInputWidget */
-.ve-ui-mwLinkTargetInputWidget-pending input {
+.ve-ui-pendingInputWidget input {
background-image: url(images/pending.gif);
}
@@ -279,6 +278,7 @@
.ve-ui-mwLinkTargetInputWidget-menu {
width: 20em;
margin-top: -7px;
+ font-size: 0.8em;
}
.ve-ui-mwLinkTargetInputWidget-menu .ve-ui-menuWidget-item {
@@ -331,3 +331,9 @@
-o-transition-timing-function: ease-in-out;
transition-timing-function: ease-in-out;
}
+
+.ve-ui-popupWidget-body:focus {
+ /* No outline. The body has a tabindex and is focused on show */
+ outline: none;
+}
+
diff --git a/modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js
b/modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js
index 956eab7..e044b65 100644
--- a/modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js
+++ b/modules/ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js
@@ -56,6 +56,8 @@
ve.inheritClass( ve.ui.MWLinkTargetInputWidget, ve.ui.LinkTargetInputWidget );
+ve.mixinClass( ve.ui.MWLinkTargetInputWidget, ve.ui.PendingInputWidget );
+
/* Methods */
/**
@@ -138,7 +140,7 @@
this.populateMenu();
this.queryPageExistence();
this.queryMatchingPages();
- if ( this.value.length && !this.menu.isVisible() ) {
+ if ( this.value.length && $.trim( this.value ) !== '' &&
!this.menu.isVisible() ) {
this.menu.show();
}
return this;
@@ -169,7 +171,7 @@
// External link
if ( ve.init.platform.getExternalLinkUrlProtocolsRegExp().test(
this.value ) ) {
items.push( new ve.ui.MenuSectionItemWidget(
- 'externalLink', { '$$': menu$$, 'label': 'External
link' }
+ 'externalLink', { '$$': menu$$, 'label': ve.msg(
'visualeditor-linkinspector-suggest-external-link' ) }
) );
items.push( new ve.ui.MenuItemWidget(
this.getExternalLinkAnnotationFromUrl( this.value ),
@@ -180,7 +182,7 @@
// Internal link
if ( !pageExists && ( !matchingPages || matchingPages.indexOf(
this.value ) === -1 ) ) {
items.push( new ve.ui.MenuSectionItemWidget(
- 'newPage', { '$$': menu$$, 'label': 'New page' }
+ 'newPage', { '$$': menu$$, 'label': ve.msg(
'visualeditor-linkinspector-suggest-new-page' ) }
) );
items.push( new ve.ui.MenuItemWidget(
this.getInternalLinkAnnotationFromTitle( this.value ),
@@ -191,7 +193,7 @@
// Matching pages
if ( matchingPages && matchingPages.length ) {
items.push( new ve.ui.MenuSectionItemWidget(
- 'matchingPages', { '$$': menu$$, 'label': 'Matching
page' }
+ 'matchingPages', { '$$': menu$$, 'label': ve.msg(
'visualeditor-linkinspector-suggest-matching-page' ) }
) );
for ( i = 0, len = matchingPages.length; i < len; i++ ) {
items.push( new ve.ui.MenuItemWidget(
@@ -212,30 +214,6 @@
}
this.menu.highlightItem( this.menu.getSelectedItem() );
- return this;
-};
-
-/**
- * Signals that an response is pending.
- *
- * @method
- * @chainable
- */
-ve.ui.MWLinkTargetInputWidget.prototype.pushPending = function () {
- this.pending++;
- this.$.addClass( 've-ui-mwLinkTargetInputWidget-pending' );
- return this;
-};
-
-/**
- * Signals that an response is complete.
- *
- * @method
- * @chainable
- */
-ve.ui.MWLinkTargetInputWidget.prototype.popPending = function () {
- this.pending--;
- this.$.removeClass( 've-ui-mwLinkTargetInputWidget-pending' );
return this;
};
diff --git a/modules/ve/ui/widgets/ve.ui.MenuWidget.js
b/modules/ve/ui/widgets/ve.ui.MenuWidget.js
index 91175bb..2be85d7 100644
--- a/modules/ve/ui/widgets/ve.ui.MenuWidget.js
+++ b/modules/ve/ui/widgets/ve.ui.MenuWidget.js
@@ -34,7 +34,7 @@
// Initialization
this.$.hide().addClass( 've-ui-menuWidget' );
- if ( !config.$input ) {
+ if ( !config.input ) {
this.$.append( this.$input );
}
};
diff --git a/modules/ve/ui/widgets/ve.ui.PendingInputWidget.js
b/modules/ve/ui/widgets/ve.ui.PendingInputWidget.js
new file mode 100644
index 0000000..7a47626
--- /dev/null
+++ b/modules/ve/ui/widgets/ve.ui.PendingInputWidget.js
@@ -0,0 +1,38 @@
+/*!
+ * VisualEditor UserInterface PendingInputWidget class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * Creates an ve.ui.PendingInputWidget object.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ */
+ve.ui.PendingInputWidget = function VeUiPendingInputWidget () {
+ this.pending = 0;
+};
+
+/* Methods */
+
+/**
+ * Adds a pending marker
+ */
+ve.ui.PendingInputWidget.prototype.pushPending = function () {
+ this.pending++;
+ this.$.addClass( 've-ui-pendingInputWidget' );
+ return this;
+};
+
+/**
+ * Removes a pending marker
+ */
+ve.ui.PendingInputWidget.prototype.popPending = function () {
+ this.pending--;
+ this.$.removeClass( 've-ui-pendingInputWidget' );
+ return this;
+};
diff --git a/modules/ve/ui/widgets/ve.ui.PopupWidget.js
b/modules/ve/ui/widgets/ve.ui.PopupWidget.js
index 56c0bee..2db41a3 100644
--- a/modules/ve/ui/widgets/ve.ui.PopupWidget.js
+++ b/modules/ve/ui/widgets/ve.ui.PopupWidget.js
@@ -23,8 +23,9 @@
// Properties
this.visible = false;
- this.$callout = $( '<div>' );
- this.$body = $( '<div>' );
+ this.$callout = this.$$( '<div>' );
+ // Tab index on body so that it may blur
+ this.$body = this.$$( '<div>' ).attr( 'tabindex', 1 );
this.transitionTimeout = null;
this.align = config.align || 'center';
@@ -35,11 +36,20 @@
this.$callout.addClass( 've-ui-popupWidget-callout' ),
this.$body.addClass( 've-ui-popupWidget-body' )
);
+
+ // Auto hide popup
+ this.$body.on( 'blur', ve.bind( this.onPopupBlur, this ) );
};
/* Inheritance */
ve.inheritClass( ve.ui.PopupWidget, ve.ui.Widget );
+
+/* Events */
+
+/**
+ * @event hide
+ */
/* Methods */
@@ -52,7 +62,8 @@
ve.ui.PopupWidget.prototype.show = function () {
this.$.show();
this.visible = true;
-
+ // Focus body so that it may blur.
+ this.$body.focus();
return this;
};
@@ -65,10 +76,39 @@
ve.ui.PopupWidget.prototype.hide = function () {
this.$.hide();
this.visible = false;
-
+ this.emit( 'hide' );
return this;
};
+ve.ui.PopupWidget.prototype.getFocusedChild = function () {
+ return this.$body.find( ':focus' );
+};
+
+ve.ui.PopupWidget.prototype.onPopupBlur = function () {
+ // Find out what is focused after blur
+ setTimeout( ve.bind( function () {
+ var $focused = this.getFocusedChild();
+ // Is there a focused child element?
+ if ( $focused.length > 0 ) {
+ // Bind a one off blur event to that focused child
element
+ $focused.one( 'blur', ve.bind( function () {
+ setTimeout( ve.bind( function () {
+ if ( this.getFocusedChild().length ===
0 ) {
+ // Be sure focus is not the
popup itself.
+ if ( this.$.find( ':focus'
).is( this.$body ) ){
+ return;
+ }
+ // Not a child and not the
popup itself, so hide.
+ this.hide();
+ }
+ }, this ), 0 );
+ }, this ) );
+ } else {
+ this.hide();
+ }
+ }, this ), 0 );
+};
+
/**
* Updates the position and size.
*
--
To view, visit https://gerrit.wikimedia.org/r/60700
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I29bcd92b7b5641941a4e98e65b2a56424a5263ff
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