mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-15 02:23:58 +00:00
Integrated menuView into format drop down tool
This commit is contained in:
parent
01180e4f8f
commit
3d678ea3bd
|
@ -19,6 +19,7 @@
|
|||
-webkit-box-shadow: 0 0.25em 1em 0 rgba(0,0,0,0.25);
|
||||
-moz-box-shadow: 0 0.25em 1em 0 rgba(0,0,0,0.25);
|
||||
box-shadow: 0 0.25em 1em 0 rgba(0,0,0,0.25);
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.es-contextView-position-start .es-contextView-icon {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
-moz-box-shadow: 0 0.25em 1em 0 rgba(0,0,0,0.25);
|
||||
box-shadow: 0 0.25em 1em 0 rgba(0,0,0,0.25);
|
||||
padding: 0.33em 0;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.es-menuView-item {
|
||||
|
|
|
@ -88,6 +88,19 @@
|
|||
background-image: url(../images/clear.png);
|
||||
}
|
||||
.es-toolbarDropdownTool {
|
||||
border-color: #dddddd;
|
||||
-webkit-border-radius: 0.25em;
|
||||
-moz-border-radius: 0.25em;
|
||||
-o-border-radius: 0.25em;
|
||||
background-color: white;
|
||||
font-size: 0.8em;
|
||||
line-height: 24px;
|
||||
padding-left: 0.75em;
|
||||
padding-right: 24px;
|
||||
background-image: url(../images/arrow-down.png);
|
||||
background-position: 9em center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.es-toolbarDropdownTool-format {
|
||||
width: 8em;
|
||||
}
|
||||
.es-toolbarDropdownTool-formatting {
|
||||
}
|
|
@ -1,28 +1,35 @@
|
|||
es.DropdownTool = function( toolbar, name ) {
|
||||
es.DropdownTool = function( toolbar, name, items ) {
|
||||
// Inheritance
|
||||
es.Tool.call( this, toolbar, name );
|
||||
|
||||
// for es.extendClass
|
||||
// Early exit when extending via es.extendClass
|
||||
if ( !name ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$.addClass( 'es-toolbarDropdownTool' ).addClass( 'es-toolbarDropdownTool-' + name );
|
||||
|
||||
this.$select = $( '<select>' );
|
||||
this.$.append( this.$select );
|
||||
|
||||
// Properties
|
||||
var _this = this;
|
||||
this.menuView = new es.MenuView( items, function( item ) {
|
||||
_this.onSelect( item );
|
||||
_this.$.text( item.label );
|
||||
} );
|
||||
|
||||
this.$.bind( {
|
||||
'change': function( e ) {
|
||||
_this.onChange( e );
|
||||
$( document ).add( this.toolbar.surfaceView.$ ).mousedown( function( e ) {
|
||||
if ( e.button === 0 ) {
|
||||
_this.menuView.hide();
|
||||
}
|
||||
} );
|
||||
|
||||
// DOM Changes
|
||||
this.$.addClass( 'es-toolbarDropdownTool' ).addClass( 'es-toolbarDropdownTool-' + name );
|
||||
};
|
||||
|
||||
es.DropdownTool.prototype.onChange = function() {
|
||||
throw 'DropdownTool.onChange not implemented in this subclass:' + this.constructor;
|
||||
/* Methods */
|
||||
|
||||
es.DropdownTool.prototype.onSelect = function( item ) {
|
||||
throw 'DropdownTool.onSelect not implemented in this subclass:' + this.constructor;
|
||||
};
|
||||
|
||||
es.extendClass( es.DropdownTool, es.Tool );
|
||||
/* Inheritance */
|
||||
|
||||
es.extendClass( es.DropdownTool, es.Tool );
|
||||
|
|
|
@ -1,101 +1,123 @@
|
|||
es.FormatDropdownTool = function( toolbar, name ) {
|
||||
es.DropdownTool.call( this, toolbar, name );
|
||||
|
||||
this.formats = [
|
||||
// Inheritance
|
||||
es.DropdownTool.call( this, toolbar, name, [
|
||||
{
|
||||
'name': 'Paragraph',
|
||||
'name': 'paragraph',
|
||||
'label': 'Paragraph',
|
||||
'type' : 'paragraph'
|
||||
},
|
||||
{
|
||||
'name': 'Heading Level 1',
|
||||
'name': 'heading-1',
|
||||
'label': 'Heading Level 1',
|
||||
'type' : 'heading',
|
||||
'attributes': { 'level': 1 }
|
||||
},
|
||||
{
|
||||
'name': 'Heading Level 2',
|
||||
'name': 'heading-2',
|
||||
'label': 'Heading Level 2',
|
||||
'type' : 'heading',
|
||||
'attributes': { 'level': 2 }
|
||||
},
|
||||
{
|
||||
'name': 'Heading Level 3',
|
||||
'name': 'heading-3',
|
||||
'label': 'Heading Level 3',
|
||||
'type' : 'heading',
|
||||
'attributes': { 'level': 3 }
|
||||
},
|
||||
{
|
||||
'name': 'Heading Level 4',
|
||||
'name': 'heading-4',
|
||||
'label': 'Heading Level 4',
|
||||
'type' : 'heading',
|
||||
'attributes': { 'level': 4 }
|
||||
},
|
||||
{
|
||||
'name': 'Heading Level 5',
|
||||
'name': 'heading-5',
|
||||
'label': 'Heading Level 5',
|
||||
'type' : 'heading',
|
||||
'attributes': { 'level': 5 }
|
||||
},
|
||||
{
|
||||
'name': 'Heading Level 6',
|
||||
'name': 'heading-6',
|
||||
'label': 'Heading Level 6',
|
||||
'type' : 'heading',
|
||||
'attributes': { 'level': 6 }
|
||||
},
|
||||
{
|
||||
'name': 'Preformatted',
|
||||
'name': 'pre',
|
||||
'label': 'Preformatted',
|
||||
'type' : 'pre'
|
||||
}
|
||||
];
|
||||
|
||||
this.$select.append( '<option>' );
|
||||
] );
|
||||
|
||||
for ( var i = 0; i < this.formats.length; i++ ) {
|
||||
$( '<option>' )
|
||||
.val( i )
|
||||
.html( this.formats[i].name )
|
||||
.appendTo( this.$select );
|
||||
}
|
||||
var _this = this;
|
||||
this.$.bind( {
|
||||
'mousedown': function( e ) {
|
||||
if ( e.button === 0 ) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
},
|
||||
'mouseup': function( e ) {
|
||||
if ( e.button === 0 ) {
|
||||
_this.menuView.setPosition( es.Position.newFromElementPagePosition( _this.$ ) );
|
||||
_this.menuView.toggle();
|
||||
}
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
es.FormatDropdownTool.prototype.onChange = function() {
|
||||
var index = this.$select.val();
|
||||
if ( index in this.formats ) {
|
||||
var txs = this.toolbar.surfaceView.model.getDocument().prepareLeafConversion(
|
||||
this.toolbar.surfaceView.currentSelection,
|
||||
this.formats[index].type,
|
||||
this.formats[index].attributes
|
||||
)
|
||||
for ( var i = 0; i < txs.length; i++ ) {
|
||||
this.toolbar.surfaceView.model.transact( txs[i] );
|
||||
}
|
||||
/* Methods */
|
||||
|
||||
es.FormatDropdownTool.prototype.onSelect = function( item ) {
|
||||
var txs = this.toolbar.surfaceView.model.getDocument().prepareLeafConversion(
|
||||
this.toolbar.surfaceView.currentSelection,
|
||||
item.type,
|
||||
item.attributes
|
||||
);
|
||||
for ( var i = 0; i < txs.length; i++ ) {
|
||||
this.toolbar.surfaceView.model.transact( txs[i] );
|
||||
}
|
||||
};
|
||||
|
||||
es.FormatDropdownTool.prototype.updateState = function( annotations, nodes ) {
|
||||
var format = {
|
||||
'type': nodes[0].getElementType(),
|
||||
'attributes': nodes[0].getElement().attributes
|
||||
};
|
||||
|
||||
for( var i = 1; i < nodes.length; i++ ) {
|
||||
if ( format.type != nodes[i].getElementType()
|
||||
|| !es.compareObjects( format.attributes, nodes[i].element.attributes ) ) {
|
||||
// Get type and attributes of the first node
|
||||
var i,
|
||||
format = {
|
||||
'type': nodes[0].getElementType(),
|
||||
'attributes': nodes[0].getElement().attributes
|
||||
};
|
||||
// Look for mismatches, in which case format should be null
|
||||
for ( i = 1; i < nodes.length; i++ ) {
|
||||
if ( format.type != nodes[i].getElementType() ||
|
||||
!es.compareObjects( format.attributes, nodes[i].element.attributes ) ) {
|
||||
format = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( format === null ) {
|
||||
this.$select.val( null );
|
||||
this.$.text( '' );
|
||||
} else {
|
||||
for ( var i = 0; i < this.formats.length; i++ ) {
|
||||
if ( format.type === this.formats[i].type
|
||||
&& es.compareObjects( format.attributes, this.formats[i].attributes ) ) {
|
||||
this.$select.val( i );
|
||||
break;
|
||||
var items = this.menuView.getItems();
|
||||
for ( i = 0; i < items.length; i++ ) {
|
||||
if (
|
||||
format.type === items[i].type &&
|
||||
es.compareObjects( format.attributes, items[i].attributes )
|
||||
) {
|
||||
this.$.text( items[i].label );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Registration */
|
||||
|
||||
es.Tool.tools.format = {
|
||||
constructor: es.FormatDropdownTool,
|
||||
name: 'format'
|
||||
'constructor': es.FormatDropdownTool,
|
||||
'name': 'format'
|
||||
};
|
||||
|
||||
es.extendClass( es.FormatDropdownTool, es.DropdownTool );
|
||||
/* Inheritance */
|
||||
|
||||
es.extendClass( es.FormatDropdownTool, es.DropdownTool );
|
||||
|
|
|
@ -18,28 +18,30 @@ es.ContextView = function( surfaceView, $overlay ) {
|
|||
this.surfaceView,
|
||||
[{ 'name': 'textStyle', 'items' : [ 'bold', 'italic', 'formatting', 'clear' ] }]
|
||||
);
|
||||
this.menu = new es.MenuView( [
|
||||
// Example menu items
|
||||
{ 'name': 'tools', '$': this.$toolbar },
|
||||
'-',
|
||||
{ 'name': 'link', 'label': 'Link to...', 'callback': function() {
|
||||
_this.menu.hide();
|
||||
_this.$panels
|
||||
.show()
|
||||
.find( '[rel="link"]' )
|
||||
this.menuView = new es.MenuView( [
|
||||
// Example menu items
|
||||
{ 'name': 'tools', '$': this.$toolbar },
|
||||
'-',
|
||||
{ 'name': 'link', 'label': 'Link to...', 'callback': function( item ) {
|
||||
_this.menuView.hide();
|
||||
_this.$panels
|
||||
.show()
|
||||
.end()
|
||||
.find( '[rel="link"] input:first' )
|
||||
.focus();
|
||||
} },
|
||||
'-',
|
||||
{ 'name': 'copy', 'label': 'Copy' },
|
||||
{ 'name': 'cut', 'label': 'Cut' },
|
||||
{ 'name': 'paste', 'label': 'Paste' }
|
||||
] );
|
||||
this.$.append( this.menu.$ );
|
||||
.find( '[rel="link"]' )
|
||||
.show()
|
||||
.end()
|
||||
.find( '[rel="link"] input:first' )
|
||||
.focus();
|
||||
} },
|
||||
'-',
|
||||
{ 'name': 'copy', 'label': 'Copy' },
|
||||
{ 'name': 'cut', 'label': 'Cut' },
|
||||
{ 'name': 'paste', 'label': 'Paste' }
|
||||
],
|
||||
null,
|
||||
this.$
|
||||
);
|
||||
this.$icon = $( '<div class="es-contextView-icon"></div>' ).appendTo( this.$ );
|
||||
|
||||
|
||||
// Example panel
|
||||
this.$panels.append(
|
||||
'<div class="es-contextView-panel" rel="link">' +
|
||||
|
@ -52,8 +54,18 @@ es.ContextView = function( surfaceView, $overlay ) {
|
|||
} );
|
||||
|
||||
// Events
|
||||
this.$icon.click( function() {
|
||||
_this.menu.toggle();
|
||||
this.$icon.bind( {
|
||||
'mousedown': function( e ) {
|
||||
if ( e.button === 0 ) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
},
|
||||
'mouseup': function( e ) {
|
||||
if ( e.button === 0 ) {
|
||||
_this.menuView.toggle();
|
||||
}
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
|
@ -86,12 +98,13 @@ es.ContextView.prototype.set = function() {
|
|||
}
|
||||
}
|
||||
if ( position ) {
|
||||
if ( position.left + this.menu.$.width() < $( 'body' ).width() ) {
|
||||
if ( position.left + this.menuView.$.width() < $( 'body' ).width() ) {
|
||||
this.$.addClass( 'es-contextView-position-left' );
|
||||
} else {
|
||||
this.$.addClass( 'es-contextView-position-right' );
|
||||
}
|
||||
if ( position.top + this.menu.$.height() < $( window ).height() + $( window ).scrollTop() ) {
|
||||
var $window = $( window );
|
||||
if ( position.top + this.menuView.$.height() < $window.height() + $window.scrollTop() ) {
|
||||
this.$.addClass( 'es-contextView-position-below' );
|
||||
} else {
|
||||
this.$.addClass( 'es-contextView-position-above' );
|
||||
|
@ -104,5 +117,5 @@ es.ContextView.prototype.set = function() {
|
|||
es.ContextView.prototype.clear = function() {
|
||||
this.$panels.hide().children().hide();
|
||||
this.$icon.hide();
|
||||
this.menu.hide();
|
||||
this.menuView.hide();
|
||||
};
|
||||
|
|
|
@ -3,13 +3,16 @@
|
|||
*
|
||||
* @class
|
||||
* @constructor
|
||||
* @param {jQuery} $overlay DOM selection to add nodes to
|
||||
* @param {Object[]} items List of items to append initially
|
||||
* @param {Function} callback Function to call if an item doesn't have it's own callback
|
||||
* @param {jQuery} [$overlay=$( 'body' )] DOM selection to add nodes to
|
||||
*/
|
||||
es.MenuView = function( items, $overlay ) {
|
||||
es.MenuView = function( items, callback, $overlay ) {
|
||||
// Properties
|
||||
this.$ = $( '<div class="es-menuView"></div>' ).appendTo( $overlay || $( 'body' ) );
|
||||
this.items = [];
|
||||
this.autoNamedBreaks = 0;
|
||||
this.callback = callback;
|
||||
|
||||
// Items
|
||||
if ( es.isArray( items ) ) {
|
||||
|
@ -91,6 +94,14 @@ es.MenuView.prototype.removeItem = function( name ) {
|
|||
}
|
||||
};
|
||||
|
||||
es.MenuView.prototype.getItems = function() {
|
||||
return this.items;
|
||||
};
|
||||
|
||||
es.MenuView.prototype.setPosition = function( position ) {
|
||||
return this.$.css( { 'top': position.top, 'left': position.left } );
|
||||
};
|
||||
|
||||
es.MenuView.prototype.show = function() {
|
||||
this.$.show();
|
||||
};
|
||||
|
@ -105,7 +116,9 @@ es.MenuView.prototype.hide = function() {
|
|||
|
||||
es.MenuView.prototype.onSelect = function( item, event ) {
|
||||
if ( typeof item.callback === 'function' ) {
|
||||
item.callback();
|
||||
item.callback( item );
|
||||
} else if ( typeof this.callback === 'function' ) {
|
||||
this.callback( item );
|
||||
}
|
||||
this.hide();
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue