mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-09-26 19:56:49 +00:00
Single-click insertion
Objectives: * Reduce the number of clicks and mouse maneuvers required to insert media, references or template parameters * Make use of highlighting with mouse movement or arrow key presses, similar to menus, to suggest action when clicked * Improve the way media search results look and feel Changes: ve.ui.SelectWidget.js * Add mouseleave handler to un-highlight when the mouse exits the widget * Document highlight events (already being emitted) ve.ui.SearchWidget.js * Propagate both select and highlight events from results widget * Make arrow keys change highlight instead of selection * Get rid of enter event, make enter key select highlighted item instead * Provide direct access to results widget through getResults method ve.ui.MenuWidget.js * Use the selected item as a starting point if nothing is currently highlighted when adjusting the highlight position ve.ui.Dialog.js * Add footless option to hide the foot element and make the body extend all the way down to the bottom * Remove applyButton, which only some dialogs need, and should be creating themselves, along with other buttons as needed ve.ui.Widget.css * Change highlight and selected colors of option widgets to match other selection colors used elsewhere * Leave selected and highlighted widget looking selected ve.ui.Frame.css * Add background color to combat any color that might have been applied to the frame body in the imported CSS from the parent frame ve.ui.Dialog.css * Add rules for footless mode ve.ui.MWReferenceResultWidget.js, ve.ui.MWParameterResultWidget.js, ve.ui.MWMediaResultWidget.js * Allow highlighting ve.ui.MWParamterSearchWidget.js * Switch from selecting the first item when filtering to highlighting ve-mw/ve.ui.Widget.js * Adjust media result widget styling to better match other elements ve.ui.MWTransclusionDialog.js, ve.ui.MWReferenceListDialog.js, ve.ui.MWReferenceEditDialog.js, ve.ui.MWMetaDialog.js ve.ui.MWMediaEditDialog.js * Add apply button, as per it being removed from parent class ve.ui.MWTransclusionDialog.js, ve.ui.MWReferenceInsertDialog.js, ve.ui.MWMediaInsertDialog.js * Insert parameter/reference/media on select, instead of clicking an insert button * Use 'insert' instead of 'apply' as argument for close method Bug: 50774 Bug: 51143 Change-Id: Ia18e79f1f8df2540f465468edb01f5ce989bf843
This commit is contained in:
parent
3d214d97b3
commit
130e446e52
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Document dialog.
|
||||
* Dialog for editing MediaWiki media objects.
|
||||
*
|
||||
* @class
|
||||
* @extends ve.ui.MWDialog
|
||||
|
@ -54,10 +54,17 @@ ve.ui.MWMediaEditDialog.prototype.initialize = function () {
|
|||
'label': ve.msg( 'visualeditor-dialog-media-content-section' ),
|
||||
'icon': 'parameter'
|
||||
} );
|
||||
this.applyButton = new ve.ui.ButtonWidget( {
|
||||
'$$': this.$$, 'label': ve.msg( 'visualeditor-dialog-action-apply' ), 'flags': ['primary']
|
||||
} );
|
||||
|
||||
// Events
|
||||
this.applyButton.connect( this, { 'click': [ 'close', 'apply' ] } );
|
||||
|
||||
// Initialization
|
||||
this.$body.addClass( 've-ui-mwMediaEditDialog-body' );
|
||||
this.$body.append( this.contentFieldset.$ );
|
||||
this.$foot.append( this.applyButton.$ );
|
||||
};
|
||||
|
||||
ve.ui.MWMediaEditDialog.prototype.onOpen = function () {
|
||||
|
|
|
@ -5,11 +5,10 @@
|
|||
* @license The MIT License (MIT); see LICENSE.txt
|
||||
*/
|
||||
|
||||
/*global mw */
|
||||
|
||||
/**
|
||||
* Dialog for inserting MediaWiki media objects.
|
||||
*
|
||||
* @class
|
||||
* @abstract
|
||||
* @extends ve.ui.MWDialog
|
||||
*
|
||||
* @constructor
|
||||
|
@ -17,6 +16,9 @@
|
|||
* @param {Object} [config] Config options
|
||||
*/
|
||||
ve.ui.MWMediaInsertDialog = function VeUiMWMediaInsertDialog( surface, config ) {
|
||||
// Configuration initialization
|
||||
config = ve.extendObject( {}, config, { 'footless': true } );
|
||||
|
||||
// Parent constructor
|
||||
ve.ui.MWDialog.call( this, surface, config );
|
||||
|
||||
|
@ -36,9 +38,11 @@ ve.ui.MWMediaInsertDialog.static.icon = 'picture';
|
|||
|
||||
/* Methods */
|
||||
|
||||
ve.ui.MWMediaInsertDialog.prototype.onSelect = function ( item ) {
|
||||
ve.ui.MWMediaInsertDialog.prototype.onSearchSelect = function ( item ) {
|
||||
this.item = item;
|
||||
this.applyButton.setDisabled( item === null );
|
||||
if ( item ) {
|
||||
this.close( 'insert' );
|
||||
}
|
||||
};
|
||||
|
||||
ve.ui.MWMediaInsertDialog.prototype.onOpen = function () {
|
||||
|
@ -47,6 +51,8 @@ ve.ui.MWMediaInsertDialog.prototype.onOpen = function () {
|
|||
|
||||
// Initialization
|
||||
this.search.getQuery().$input.focus().select();
|
||||
this.search.getResults().selectItem();
|
||||
this.search.getResults().highlightItem();
|
||||
};
|
||||
|
||||
ve.ui.MWMediaInsertDialog.prototype.onClose = function ( action ) {
|
||||
|
@ -55,7 +61,7 @@ ve.ui.MWMediaInsertDialog.prototype.onClose = function ( action ) {
|
|||
// Parent method
|
||||
ve.ui.MWDialog.prototype.onClose.call( this );
|
||||
|
||||
if ( action === 'apply' ) {
|
||||
if ( action === 'insert' ) {
|
||||
info = this.item.imageinfo[0];
|
||||
this.surface.getModel().getFragment().insertContent( [
|
||||
{
|
||||
|
@ -86,12 +92,9 @@ ve.ui.MWMediaInsertDialog.prototype.initialize = function () {
|
|||
this.search = new ve.ui.MWMediaSearchWidget( { '$$': this.frame.$$ } );
|
||||
|
||||
// Events
|
||||
this.search.connect( this, { 'select': 'onSelect' } );
|
||||
this.search.connect( this, { 'select': 'onSearchSelect' } );
|
||||
|
||||
// Initialization
|
||||
this.applyButton.setDisabled( true ).setLabel(
|
||||
mw.msg( 'visualeditor-dialog-media-insert-button' )
|
||||
);
|
||||
this.search.$.addClass( 've-ui-mwMediaInsertDialog-select' );
|
||||
this.$body.append( this.search.$ );
|
||||
};
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
/*global mw*/
|
||||
|
||||
/**
|
||||
* Dialog for editing MediaWiki page meta information.
|
||||
*
|
||||
* @class
|
||||
* @extends ve.ui.MWDialog
|
||||
* @mixins ve.ui.PagedDialog
|
||||
|
@ -85,6 +87,9 @@ ve.ui.MWMetaDialog.prototype.initialize = function () {
|
|||
'label': ve.msg( 'visualeditor-dialog-meta-languages-label' ),
|
||||
'icon': 'language'
|
||||
} );
|
||||
this.applyButton = new ve.ui.ButtonWidget( {
|
||||
'$$': this.$$, 'label': ve.msg( 'visualeditor-dialog-action-apply' ), 'flags': ['primary']
|
||||
} );
|
||||
|
||||
// Events
|
||||
this.categoryWidget.connect( this, {
|
||||
|
@ -94,6 +99,7 @@ ve.ui.MWMetaDialog.prototype.initialize = function () {
|
|||
this.defaultSortInput.connect( this, {
|
||||
'change': 'onDefaultSortChange'
|
||||
} );
|
||||
this.applyButton.connect( this, { 'click': [ 'close', 'apply' ] } );
|
||||
|
||||
// Initialization
|
||||
this.categoryWidget.addItems( this.getCategoryItems() );
|
||||
|
@ -108,6 +114,7 @@ ve.ui.MWMetaDialog.prototype.initialize = function () {
|
|||
this.pages.categories.$.append( this.categoriesFieldset.$, this.categoryOptionsFieldset.$ );
|
||||
this.categoriesFieldset.$.append( this.categoryWidget.$ );
|
||||
this.categoryOptionsFieldset.$.append( this.defaultSortLabel.$, this.defaultSortInput.$ );
|
||||
this.$foot.append( this.applyButton.$ );
|
||||
|
||||
this.pages.languages.$.append( this.languagesFieldset.$ );
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Dialog for a MediaWiki reference.
|
||||
* Dialog for editing MediaWiki references.
|
||||
*
|
||||
* @class
|
||||
* @extends ve.ui.MWDialog
|
||||
|
@ -68,6 +68,13 @@ ve.ui.MWReferenceEditDialog.prototype.initialize = function () {
|
|||
'label': ve.msg( 'visualeditor-dialog-reference-options-group-label' )
|
||||
} );
|
||||
|
||||
this.applyButton = new ve.ui.ButtonWidget( {
|
||||
'$$': this.$$, 'label': ve.msg( 'visualeditor-dialog-action-apply' ), 'flags': ['primary']
|
||||
} );
|
||||
|
||||
// Events
|
||||
this.applyButton.connect( this, { 'click': [ 'close', 'apply' ] } );
|
||||
|
||||
// Initialization
|
||||
this.optionsFieldset.$.append(
|
||||
this.groupLabel.$,
|
||||
|
@ -76,6 +83,7 @@ ve.ui.MWReferenceEditDialog.prototype.initialize = function () {
|
|||
this.$body
|
||||
.append( this.contentFieldset.$, this.optionsFieldset.$ )
|
||||
.addClass( 've-ui-mwReferenceEditDialog-body' );
|
||||
this.$foot.append( this.applyButton.$ );
|
||||
};
|
||||
|
||||
ve.ui.MWReferenceEditDialog.prototype.onOpen = function () {
|
||||
|
|
|
@ -5,11 +5,10 @@
|
|||
* @license The MIT License (MIT); see LICENSE.txt
|
||||
*/
|
||||
|
||||
/*global mw */
|
||||
|
||||
/**
|
||||
* Dialog for inserting MediaWiki references.
|
||||
*
|
||||
* @class
|
||||
* @abstract
|
||||
* @extends ve.ui.MWDialog
|
||||
*
|
||||
* @constructor
|
||||
|
@ -17,6 +16,9 @@
|
|||
* @param {Object} [config] Config options
|
||||
*/
|
||||
ve.ui.MWReferenceInsertDialog = function VeUiMWReferenceInsertDialog( surface, config ) {
|
||||
// Configuration initialization
|
||||
config = ve.extendObject( {}, config, { 'footless': true } );
|
||||
|
||||
// Parent constructor
|
||||
ve.ui.MWDialog.call( this, surface, config );
|
||||
|
||||
|
@ -43,9 +45,11 @@ ve.ui.MWReferenceInsertDialog.static.icon = 'reference';
|
|||
* @param {string|Object|null} result Command string, reference attributes object, or null if
|
||||
* nothing is selected
|
||||
*/
|
||||
ve.ui.MWReferenceInsertDialog.prototype.onSelect = function ( result ) {
|
||||
ve.ui.MWReferenceInsertDialog.prototype.onSearchSelect = function ( result ) {
|
||||
this.result = result;
|
||||
this.applyButton.setDisabled( result === null );
|
||||
if ( result ) {
|
||||
this.close( 'insert' );
|
||||
}
|
||||
};
|
||||
|
||||
ve.ui.MWReferenceInsertDialog.prototype.onOpen = function () {
|
||||
|
@ -66,7 +70,7 @@ ve.ui.MWReferenceInsertDialog.prototype.onClose = function ( action ) {
|
|||
// Parent method
|
||||
ve.ui.MWDialog.prototype.onClose.call( this );
|
||||
|
||||
if ( action === 'apply' ) {
|
||||
if ( action === 'insert' ) {
|
||||
doc = surfaceModel.getDocument(),
|
||||
internalList = doc.getInternalList();
|
||||
if ( create ) {
|
||||
|
@ -132,12 +136,9 @@ ve.ui.MWReferenceInsertDialog.prototype.initialize = function () {
|
|||
this.search = new ve.ui.MWReferenceSearchWidget( this.surface, { '$$': this.frame.$$ } );
|
||||
|
||||
// Events
|
||||
this.search.connect( this, { 'select': 'onSelect' } );
|
||||
this.search.connect( this, { 'select': 'onSearchSelect' } );
|
||||
|
||||
// Initialization
|
||||
this.applyButton.setDisabled( true ).setLabel(
|
||||
mw.msg( 'visualeditor-dialog-reference-insert-button' )
|
||||
);
|
||||
this.search.$.addClass( 've-ui-mwReferenceInsertDialog-select' );
|
||||
this.$body.append( this.search.$ );
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Dialog for a MediaWiki references list.
|
||||
* Dialog for inserting and editing MediaWiki reference lists.
|
||||
*
|
||||
* @class
|
||||
* @extends ve.ui.MWDialog
|
||||
|
@ -50,11 +50,19 @@ ve.ui.MWReferenceListDialog.prototype.initialize = function () {
|
|||
'label': ve.msg( 'visualeditor-dialog-reference-options-group-label' )
|
||||
} );
|
||||
|
||||
this.applyButton = new ve.ui.ButtonWidget( {
|
||||
'$$': this.$$, 'label': ve.msg( 'visualeditor-dialog-action-apply' ), 'flags': ['primary']
|
||||
} );
|
||||
|
||||
// Events
|
||||
this.applyButton.connect( this, { 'click': [ 'close', 'apply' ] } );
|
||||
|
||||
// Initialization
|
||||
this.optionsFieldset.$.append( this.groupLabel.$, this.groupInput.$ );
|
||||
this.$body
|
||||
.append( this.optionsFieldset.$ )
|
||||
.addClass( 've-ui-mwReferenceListDialog-body' );
|
||||
this.$foot.append( this.applyButton.$ );
|
||||
};
|
||||
|
||||
ve.ui.MWReferenceListDialog.prototype.onOpen = function () {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* Dialog for editing a MediaWiki transclusion.
|
||||
* Dialog for inserting and editing MediaWiki transclusions.
|
||||
*
|
||||
* See https://raw.github.com/wikimedia/mediawiki-extensions-TemplateData/master/spec.templatedata.json
|
||||
* for the latest version of the TemplateData specification.
|
||||
|
@ -70,11 +70,20 @@ ve.ui.MWTransclusionDialog.prototype.initialize = function () {
|
|||
// Setup for PagedDialog
|
||||
this.initializePages();
|
||||
|
||||
// Properties
|
||||
this.applyButton = new ve.ui.ButtonWidget( {
|
||||
'$$': this.$$, 'label': ve.msg( 'visualeditor-dialog-action-apply' ), 'flags': ['primary']
|
||||
} );
|
||||
|
||||
// Events
|
||||
this.outlineControlsWidget.connect( this, {
|
||||
'move': 'onOutlineControlsMove',
|
||||
'add': 'onOutlineControlsAdd'
|
||||
} );
|
||||
this.applyButton.connect( this, { 'click': [ 'close', 'apply' ] } );
|
||||
|
||||
// Initialization
|
||||
this.$foot.append( this.applyButton.$ );
|
||||
};
|
||||
|
||||
ve.ui.MWTransclusionDialog.prototype.onOpen = function () {
|
||||
|
@ -394,18 +403,15 @@ ve.ui.MWTransclusionDialog.prototype.getContentPage = function ( content ) {
|
|||
* @param {ve.dm.MWTemplateModel} template Template model
|
||||
*/
|
||||
ve.ui.MWTransclusionDialog.prototype.getTemplatePage = function ( template ) {
|
||||
var infoFieldset, addParameterFieldset, addParameterSearch, addParameterButton, optionsFieldset,
|
||||
var infoFieldset, addParameterFieldset, addParameterSearch, optionsFieldset,
|
||||
removeButton,
|
||||
spec = template.getSpec(),
|
||||
label = spec.getLabel(),
|
||||
description = spec.getDescription();
|
||||
|
||||
function addParameter() {
|
||||
var data, name, param,
|
||||
item = addParameterSearch.results.getSelectedItem();
|
||||
function addParameter( name ) {
|
||||
var param;
|
||||
|
||||
data = item && item.getData();
|
||||
name = data && data.name;
|
||||
if ( name ) {
|
||||
param = new ve.dm.MWTemplateParameterModel( template, name );
|
||||
template.addParameter( param );
|
||||
|
@ -431,20 +437,8 @@ ve.ui.MWTransclusionDialog.prototype.getTemplatePage = function ( template ) {
|
|||
} );
|
||||
addParameterFieldset.$.addClass( 've-ui-mwTransclusionDialog-addParameterFieldset' );
|
||||
addParameterSearch = new ve.ui.MWParameterSearchWidget( template, { '$$': this.frame.$$ } );
|
||||
addParameterButton = new ve.ui.ButtonWidget( {
|
||||
'$$': this.frame.$$,
|
||||
'label': ve.msg( 'visualeditor-dialog-transclusion-add-param' ),
|
||||
'disabled': true
|
||||
} );
|
||||
addParameterButton.connect( this, { 'click': addParameter } );
|
||||
addParameterSearch.connect( this, {
|
||||
'enter': addParameter,
|
||||
'select': function ( name ) {
|
||||
var names = template.getParameterNames();
|
||||
addParameterButton.setDisabled( !name || names.indexOf( name ) !== -1 );
|
||||
}
|
||||
} );
|
||||
addParameterFieldset.$.append( addParameterSearch.$, addParameterButton.$ );
|
||||
addParameterSearch.connect( this, { 'select': addParameter } );
|
||||
addParameterFieldset.$.append( addParameterSearch.$ );
|
||||
|
||||
optionsFieldset = new ve.ui.FieldsetLayout( {
|
||||
'$$': this.frame.$$,
|
||||
|
|
|
@ -221,10 +221,20 @@
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
box-shadow: inset 0 0 0 1px #ccc;
|
||||
}
|
||||
|
||||
.ve-ui-optionWidget-highlighted .ve-ui-mwMediaResultWidget-overlay,
|
||||
.ve-ui-optionWidget-selected .ve-ui-mwMediaResultWidget-overlay {
|
||||
box-shadow: inset 0 0 0 1px rgba(0,0,0,0.5), inset 0 0 0 2px rgba(255,255,255,0.5);
|
||||
box-shadow: inset 0 0 0 1px #a7dcff;
|
||||
}
|
||||
|
||||
.ve-ui-mwMediaResultWidget.ve-ui-optionWidget-highlighted {
|
||||
box-shadow: 0 0 0.3em #a7dcff, 0 0 0 white;
|
||||
}
|
||||
|
||||
.ve-ui-mwMediaResultWidget.ve-ui-optionWidget-selected {
|
||||
box-shadow: 0 0 0.3em #a7dcff, 0 0 0 white;
|
||||
}
|
||||
|
||||
.ve-ui-mwMediaResultWidget-error .ve-ui-mwMediaResultWidget-thumbnail {
|
||||
|
@ -249,6 +259,14 @@
|
|||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ve-ui-mwMediaResultWidget.ve-ui-optionWidget-highlighted .ve-ui-labeledElement-label {
|
||||
background-color: rgba(0,0,0,0.75);
|
||||
}
|
||||
|
||||
.ve-ui-mwMediaResultWidget.ve-ui-optionWidget-selected .ve-ui-labeledElement-label {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
/* ve.ui.MWReferenceSearchWidget */
|
||||
|
||||
.ve-ui-mwReferenceSearchWidget-citation {
|
||||
|
|
|
@ -43,10 +43,6 @@ ve.ui.MWMediaResultWidget = function VeUiMWMediaResultWidget( data, config ) {
|
|||
|
||||
ve.inheritClass( ve.ui.MWMediaResultWidget, ve.ui.OptionWidget );
|
||||
|
||||
/* Static Properties */
|
||||
|
||||
ve.ui.MWMediaResultWidget.static.highlightable = false;
|
||||
|
||||
/* Methods */
|
||||
|
||||
ve.ui.MWMediaResultWidget.prototype.onThumbnailLoad = function () {
|
||||
|
|
|
@ -36,10 +36,6 @@ ve.ui.MWParameterResultWidget = function VeUiMWParameterResultWidget( data, conf
|
|||
|
||||
ve.inheritClass( ve.ui.MWParameterResultWidget, ve.ui.OptionWidget );
|
||||
|
||||
/* Static Properties */
|
||||
|
||||
ve.ui.MWParameterResultWidget.static.highlightable = false;
|
||||
|
||||
/* Methods */
|
||||
|
||||
ve.ui.MWParameterResultWidget.prototype.buildLabel = function () {
|
||||
|
|
|
@ -153,6 +153,6 @@ ve.ui.MWParameterSearchWidget.prototype.addResults = function () {
|
|||
|
||||
this.results.addItems( items );
|
||||
if ( query.length ) {
|
||||
this.results.selectItem( this.results.getFirstSelectableItem() );
|
||||
this.results.highlightItem( this.results.getFirstSelectableItem() );
|
||||
}
|
||||
};
|
||||
|
|
|
@ -40,7 +40,3 @@ ve.ui.MWReferenceResultWidget = function VeUiMWReferenceResultWidget( data, conf
|
|||
/* Inheritance */
|
||||
|
||||
ve.inheritClass( ve.ui.MWReferenceResultWidget, ve.ui.OptionWidget );
|
||||
|
||||
/* Static Properties */
|
||||
|
||||
ve.ui.MWReferenceResultWidget.static.highlightable = false;
|
||||
|
|
|
@ -95,6 +95,14 @@
|
|||
bottom: 4.8em;
|
||||
}
|
||||
|
||||
.ve-ui-dialog-content-footless .ve-ui-window-body {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.ve-ui-dialog-content-footless .ve-ui-window-foot {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ve-ui-dialog-content .ve-ui-window-icon {
|
||||
width: 2.4em;
|
||||
height: 2.8em;
|
||||
|
|
|
@ -176,9 +176,12 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ve-ui-optionWidget-highlighted,
|
||||
.ve-ui-optionWidget-highlighted {
|
||||
background-color: #e1f3ff;
|
||||
}
|
||||
|
||||
.ve-ui-optionWidget-selected {
|
||||
background-color: #b3d6f6;
|
||||
background-color: #a7dcff;
|
||||
}
|
||||
|
||||
.ve-ui-optionWidget.ve-ui-widget-disabled {
|
||||
|
@ -386,10 +389,6 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.ve-ui-menuItemWidget.ve-ui-optionWidget-selected:not(.ve-ui-optionWidget-highlighted) {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.ve-ui-menuItemWidget .ve-ui-optionWidget-icon {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -15,19 +15,26 @@
|
|||
* @constructor
|
||||
* @param {ve.ui.Surface} surface
|
||||
* @param {Object} [config] Config options
|
||||
* @cfg {boolean} [footless] Hide foot
|
||||
*/
|
||||
ve.ui.Dialog = function VeUiDialog( surface, config ) {
|
||||
// Configuration initialization
|
||||
config = config || {};
|
||||
|
||||
// Parent constructor
|
||||
ve.ui.Window.call( this, surface, config );
|
||||
|
||||
// Properties
|
||||
this.visible = false;
|
||||
this.footless = !!config.footless;
|
||||
this.onWindowMouseWheelHandler = ve.bind( this.onWindowMouseWheel, this );
|
||||
this.onDocumentKeyDownHandler = ve.bind( this.onDocumentKeyDown, this );
|
||||
|
||||
// Events
|
||||
this.$.on( 'mousedown', false );
|
||||
|
||||
// Initialization
|
||||
this.$.addClass( 've-ui-dialog' );
|
||||
this.$.on( 'mousedown', false );
|
||||
};
|
||||
|
||||
/* Inheritance */
|
||||
|
@ -45,15 +52,6 @@ ve.ui.Dialog.prototype.onCloseButtonClick = function () {
|
|||
this.close( 'cancel' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle apply button click events.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.ui.Dialog.prototype.onApplyButtonClick = function () {
|
||||
this.close( 'apply' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle window mouse wheel events.
|
||||
*
|
||||
|
@ -142,22 +140,19 @@ ve.ui.Dialog.prototype.initialize = function () {
|
|||
ve.ui.Window.prototype.initialize.call( this );
|
||||
|
||||
// Properties
|
||||
this.applyButton = new ve.ui.ButtonWidget( {
|
||||
'$$': this.$$, 'label': ve.msg( 'visualeditor-dialog-action-apply' ), 'flags': ['primary']
|
||||
} );
|
||||
this.closeButton = new ve.ui.IconButtonWidget( {
|
||||
'$$': this.$$, 'title': ve.msg( 'visualeditor-dialog-action-close' ), 'icon': 'close'
|
||||
} );
|
||||
|
||||
// Events
|
||||
this.closeButton.connect( this, { 'click': 'onCloseButtonClick' } );
|
||||
this.applyButton.connect( this, { 'click': 'onApplyButtonClick' } );
|
||||
this.frame.$document.on( 'keydown', ve.bind( this.onFrameDocumentKeyDown, this ) );
|
||||
|
||||
// Initialization
|
||||
this.frame.$content.addClass( 've-ui-dialog-content' );
|
||||
if ( this.footless ) {
|
||||
this.frame.$content.addClass( 've-ui-dialog-content-footless' );
|
||||
}
|
||||
this.closeButton.$.addClass( 've-ui-window-closeButton' );
|
||||
this.applyButton.$.addClass( 've-ui-window-applyButton' );
|
||||
this.$head.append( this.closeButton.$ );
|
||||
this.$foot.append( this.applyButton.$ );
|
||||
};
|
||||
|
|
|
@ -51,6 +51,9 @@ ve.ui.MenuWidget.prototype.onKeyDown = function ( e ) {
|
|||
highlightItem = this.getHighlightedItem();
|
||||
|
||||
if ( !this.disabled && this.visible ) {
|
||||
if ( !highlightItem ) {
|
||||
highlightItem = this.getSelectedItem();
|
||||
}
|
||||
switch ( e.keyCode ) {
|
||||
case ve.Keys.ENTER:
|
||||
this.selectItem( highlightItem );
|
||||
|
|
|
@ -35,9 +35,15 @@ ve.ui.SearchWidget = function VeUiSearchWidget( config ) {
|
|||
this.$results = this.$$( '<div>' );
|
||||
|
||||
// Events
|
||||
this.query.connect( this, { 'change': 'onQueryChange', 'enter': [ 'emit', 'enter' ] } );
|
||||
this.results.connect( this, { 'select': 'onResultsSelect' } );
|
||||
this.query.$.on( 'keydown', ve.bind( this.onQueryKeydown, this ) );
|
||||
this.query.connect( this, {
|
||||
'change': 'onQueryChange',
|
||||
'enter': 'onQueryEnter'
|
||||
} );
|
||||
this.results.connect( this, {
|
||||
'highlight': 'onResultsHighlight',
|
||||
'select': 'onResultsSelect'
|
||||
} );
|
||||
this.query.$input.on( 'keydown', ve.bind( this.onQueryKeydown, this ) );
|
||||
|
||||
// Initialization
|
||||
this.$query
|
||||
|
@ -58,12 +64,13 @@ ve.inheritClass( ve.ui.SearchWidget, ve.ui.Widget );
|
|||
/* Events */
|
||||
|
||||
/**
|
||||
* @event select
|
||||
* @param {Object|null} item Item data or null if no item is selected
|
||||
* @event highlight
|
||||
* @param {Object|null} item Item data or null if no item is highlighted
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event enter
|
||||
* @event select
|
||||
* @param {Object|null} item Item data or null if no item is selected
|
||||
*/
|
||||
|
||||
/* Methods */
|
||||
|
@ -75,12 +82,15 @@ ve.inheritClass( ve.ui.SearchWidget, ve.ui.Widget );
|
|||
* @param {jQuery.Event} e Key down event
|
||||
*/
|
||||
ve.ui.SearchWidget.prototype.onQueryKeydown = function ( e ) {
|
||||
var selectedItem,
|
||||
var highlightedItem,
|
||||
dir = e.which === ve.Keys.DOWN ? 1 : ( e.which === ve.Keys.UP ? -1 : 0 );
|
||||
|
||||
if ( dir ) {
|
||||
selectedItem = this.results.getSelectedItem();
|
||||
this.results.selectItem( this.results.getRelativeSelectableItem( selectedItem, dir ) );
|
||||
highlightedItem = this.results.getHighlightedItem();
|
||||
if ( !highlightedItem ) {
|
||||
highlightedItem = this.results.getSelectedItem();
|
||||
}
|
||||
this.results.highlightItem( this.results.getRelativeSelectableItem( highlightedItem, dir ) );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -97,6 +107,30 @@ ve.ui.SearchWidget.prototype.onQueryChange = function () {
|
|||
this.results.clearItems();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle select widget enter key events.
|
||||
*
|
||||
* Selects highlighted item.
|
||||
*
|
||||
* @method
|
||||
* @param {string} value New value
|
||||
*/
|
||||
ve.ui.SearchWidget.prototype.onQueryEnter = function () {
|
||||
// Reset
|
||||
this.results.selectItem( this.results.getHighlightedItem() );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle select widget highlight events.
|
||||
*
|
||||
* @method
|
||||
* @param {ve.ui.OptionWidget} item Highlighted item
|
||||
* @emits highlight
|
||||
*/
|
||||
ve.ui.SearchWidget.prototype.onResultsHighlight = function ( item ) {
|
||||
this.emit( 'highlight', item ? item.getData() : null );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle select widget select events.
|
||||
*
|
||||
|
@ -117,3 +151,13 @@ ve.ui.SearchWidget.prototype.onResultsSelect = function ( item ) {
|
|||
ve.ui.SearchWidget.prototype.getQuery = function () {
|
||||
return this.query;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the results list.
|
||||
*
|
||||
* @method
|
||||
* @returns {ve.ui.SelectWidget} Select list
|
||||
*/
|
||||
ve.ui.SearchWidget.prototype.getResults = function () {
|
||||
return this.results;
|
||||
};
|
||||
|
|
|
@ -36,7 +36,8 @@ ve.ui.SelectWidget = function VeUiSelectWidget( config ) {
|
|||
'mousedown': ve.bind( this.onMouseDown, this ),
|
||||
'mouseup': ve.bind( this.onMouseUp, this ),
|
||||
'mousemove': ve.bind( this.onMouseMove, this ),
|
||||
'mouseover': ve.bind( this.onMouseOver, this )
|
||||
'mouseover': ve.bind( this.onMouseOver, this ),
|
||||
'mouseleave': ve.bind( this.onMouseLeave, this )
|
||||
} );
|
||||
|
||||
// Initialization
|
||||
|
@ -51,6 +52,11 @@ ve.mixinClass( ve.ui.SelectWidget, ve.ui.GroupElement );
|
|||
|
||||
/* Events */
|
||||
|
||||
/**
|
||||
* @event highlight
|
||||
* @param {ve.ui.OptionWidget|null} item Highlighted item or null if no item is highlighted
|
||||
*/
|
||||
|
||||
/**
|
||||
* @event select
|
||||
* @param {ve.ui.OptionWidget|null} item Selected item or null if no item is selected
|
||||
|
@ -150,6 +156,20 @@ ve.ui.SelectWidget.prototype.onMouseOver = function ( e ) {
|
|||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle mouse leave events.
|
||||
*
|
||||
* @method
|
||||
* @private
|
||||
* @param {jQuery.Event} e Mouse over event
|
||||
*/
|
||||
ve.ui.SelectWidget.prototype.onMouseLeave = function () {
|
||||
if ( !this.disabled ) {
|
||||
this.highlightItem();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the closest item to a jQuery.Event.
|
||||
*
|
||||
|
@ -225,6 +245,7 @@ ve.ui.SelectWidget.prototype.getItemFromData = function ( data ) {
|
|||
* @method
|
||||
* @param {ve.ui.OptionWidget} [item] Item to highlight, omit to deselect all
|
||||
* @param {boolean} [silent=false] Update UI only, do not emit `highlight` event
|
||||
* @emits highlight
|
||||
* @chainable
|
||||
*/
|
||||
ve.ui.SelectWidget.prototype.highlightItem = function ( item, silent ) {
|
||||
|
@ -252,6 +273,7 @@ ve.ui.SelectWidget.prototype.highlightItem = function ( item, silent ) {
|
|||
* @method
|
||||
* @param {ve.ui.OptionWidget} [item] Item to select, omit to deselect all
|
||||
* @param {boolean} [silent=false] Update UI only, do not emit `select` event
|
||||
* @emits select
|
||||
* @chainable
|
||||
*/
|
||||
ve.ui.SelectWidget.prototype.selectItem = function ( item, silent ) {
|
||||
|
@ -334,6 +356,7 @@ ve.ui.SelectWidget.prototype.getFirstSelectableItem = function () {
|
|||
* @method
|
||||
* @param {ve.ui.OptionWidget[]} items Items to add
|
||||
* @param {number} [index] Index to insert items after
|
||||
* @emits add
|
||||
* @chainable
|
||||
*/
|
||||
ve.ui.SelectWidget.prototype.addItems = function ( items, index ) {
|
||||
|
@ -365,6 +388,7 @@ ve.ui.SelectWidget.prototype.addItems = function ( items, index ) {
|
|||
*
|
||||
* @method
|
||||
* @param {ve.ui.OptionWidget[]} items Items to remove
|
||||
* @emits remove
|
||||
* @chainable
|
||||
*/
|
||||
ve.ui.SelectWidget.prototype.removeItems = function ( items ) {
|
||||
|
@ -394,6 +418,7 @@ ve.ui.SelectWidget.prototype.removeItems = function ( items ) {
|
|||
* Items will be detached, not removed, so they can be used later.
|
||||
*
|
||||
* @method
|
||||
* @emits remove
|
||||
* @chainable
|
||||
*/
|
||||
ve.ui.SelectWidget.prototype.clearItems = function () {
|
||||
|
|
Loading…
Reference in a new issue