mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-24 06:24:08 +00:00
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
This commit is contained in:
parent
e7ee9564e6
commit
6a068e7d83
|
@ -43,9 +43,9 @@ $messages['en'] = array(
|
|||
'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',
|
||||
|
@ -154,7 +154,7 @@ See also:
|
|||
'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.)',
|
||||
|
|
|
@ -373,6 +373,7 @@ $wgResourceModules += array(
|
|||
'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',
|
||||
|
@ -380,11 +381,11 @@ $wgResourceModules += array(
|
|||
'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/tools/ve.ui.ButtonTool.js',
|
||||
've/ui/tools/ve.ui.AnnotationButtonTool.js',
|
||||
|
@ -445,7 +446,8 @@ $wgResourceModules += array(
|
|||
'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',
|
||||
|
|
|
@ -254,16 +254,17 @@ $html = file_get_contents( $page );
|
|||
<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>
|
||||
|
|
|
@ -197,16 +197,17 @@
|
|||
<script src="../../ve/ui/widgets/ve.ui.MenuItemWidget.js"></script>
|
||||
<script src="../../ve/ui/widgets/ve.ui.MenuSectionItemWidget.js"></script>
|
||||
<script src="../../ve/ui/widgets/ve.ui.MenuWidget.js"></script>
|
||||
<script src="../../ve/ui/widgets/ve.ui.PendingInputWidget.js"></script>
|
||||
<script src="../../ve/ui/widgets/ve.ui.TextInputMenuWidget.js"></script>
|
||||
<script src="../../ve/ui/widgets/ve.ui.LinkTargetInputWidget.js"></script>
|
||||
<script src="../../ve/ui/widgets/ve.ui.MWLinkTargetInputWidget.js"></script>
|
||||
<script src="../../ve/ui/layouts/ve.ui.GridLayout.js"></script>
|
||||
<script src="../../ve/ui/layouts/ve.ui.PanelLayout.js"></script>
|
||||
<script src="../../ve/ui/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>
|
||||
|
|
|
@ -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 );
|
100
modules/ve/ui/dialogs/ve.ui.PagedDialog.js
Normal file
100
modules/ve/ui/dialogs/ve.ui.PagedDialog.js
Normal file
|
@ -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];
|
||||
};
|
|
@ -41,20 +41,29 @@ ve.ui.GroupElement.prototype.getItems = function () {
|
|||
* @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.addItems = function ( items ) {
|
|||
*/
|
||||
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];
|
||||
|
|
|
@ -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 @@ ve.ui.EditorPanelLayout = function VeUiEditorPanelLayout( config ) {
|
|||
// 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 @@ ve.ui.EditorPanelLayout = function VeUiEditorPanelLayout( config ) {
|
|||
|
||||
/* 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;
|
||||
};
|
|
@ -55,7 +55,7 @@ ve.ui.StackPanelLayout.prototype.addItems = function ( items ) {
|
|||
|
||||
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.clearItems = function () {
|
|||
ve.ui.StackPanelLayout.prototype.showItem = function ( item ) {
|
||||
this.$items.hide();
|
||||
item.$.show();
|
||||
this.currentItem = item;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
|
@ -117,6 +117,6 @@
|
|||
margin: 0.25em 0.25em;
|
||||
}
|
||||
|
||||
.ve-ui-metaDialog-outlinePanel {
|
||||
.ve-ui-pagedDialog-outlinePanel {
|
||||
border-right: solid 1px #ddd;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@ ve.ui.MWLinkTargetInputWidget = function VeUiMWLinkTargetInputWidget( config ) {
|
|||
|
||||
ve.inheritClass( ve.ui.MWLinkTargetInputWidget, ve.ui.LinkTargetInputWidget );
|
||||
|
||||
ve.mixinClass( ve.ui.MWLinkTargetInputWidget, ve.ui.PendingInputWidget );
|
||||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
|
@ -138,7 +140,7 @@ ve.ui.MWLinkTargetInputWidget.prototype.openMenu = function () {
|
|||
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 @@ ve.ui.MWLinkTargetInputWidget.prototype.populateMenu = function () {
|
|||
// 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 @@ ve.ui.MWLinkTargetInputWidget.prototype.populateMenu = function () {
|
|||
// 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 @@ ve.ui.MWLinkTargetInputWidget.prototype.populateMenu = function () {
|
|||
// 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(
|
||||
|
@ -215,30 +217,6 @@ ve.ui.MWLinkTargetInputWidget.prototype.populateMenu = function () {
|
|||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets an internal link annotation.
|
||||
*
|
||||
|
|
|
@ -34,7 +34,7 @@ ve.ui.MenuWidget = function VeUiMenuWidget( config ) {
|
|||
|
||||
// Initialization
|
||||
this.$.hide().addClass( 've-ui-menuWidget' );
|
||||
if ( !config.$input ) {
|
||||
if ( !config.input ) {
|
||||
this.$.append( this.$input );
|
||||
}
|
||||
};
|
||||
|
|
38
modules/ve/ui/widgets/ve.ui.PendingInputWidget.js
Normal file
38
modules/ve/ui/widgets/ve.ui.PendingInputWidget.js
Normal file
|
@ -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;
|
||||
};
|
|
@ -23,8 +23,9 @@ ve.ui.PopupWidget = function VeUiPopupWidget( config ) {
|
|||
|
||||
// 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,12 +36,21 @@ ve.ui.PopupWidget = function VeUiPopupWidget( config ) {
|
|||
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.inheritClass( ve.ui.PopupWidget, ve.ui.Widget );
|
|||
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.show = function () {
|
|||
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.
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue