mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-09-25 11:16:51 +00:00
Added es.MenuView
This commit is contained in:
parent
874e8aa40a
commit
8a58fb5189
|
@ -93,6 +93,7 @@ $wgResourceModules += array(
|
|||
'es/views/es.HeadingView.js',
|
||||
'es/views/es.ListItemView.js',
|
||||
'es/views/es.ListView.js',
|
||||
'es/views/es.MenuView.js',
|
||||
'es/views/es.ParagraphView.js',
|
||||
'es/views/es.PreView.js',
|
||||
'es/views/es.SurfaceView.js',
|
||||
|
@ -115,6 +116,7 @@ $wgResourceModules += array(
|
|||
'es/styles/es.ContentView.css',
|
||||
'es/styles/es.DocumentView.css',
|
||||
'es/styles/es.ToolbarView.css',
|
||||
'es/styles/es.MenuView.css',
|
||||
),
|
||||
'dependencies' => array(
|
||||
'jquery',
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<link rel="stylesheet" href="../modules/es/styles/es.ContentView.css">
|
||||
<link rel="stylesheet" href="../modules/es/styles/es.DocumentView.css">
|
||||
<link rel="stylesheet" href="../modules/es/styles/es.ToolbarView.css">
|
||||
<link rel="stylesheet" href="../modules/es/styles/es.MenuView.css">
|
||||
<link rel="stylesheet" href="../modules/sandbox/sandbox.css">
|
||||
<style>
|
||||
body {
|
||||
|
@ -126,6 +127,7 @@
|
|||
<script src="../modules/es/views/es.ParagraphView.js"></script>
|
||||
<script src="../modules/es/views/es.PreView.js"></script>
|
||||
<script src="../modules/es/views/es.ListView.js"></script>
|
||||
<script src="../modules/es/views/es.MenuView.js"></script>
|
||||
<script src="../modules/es/views/es.ListItemView.js"></script>
|
||||
<script src="../modules/es/views/es.TableView.js"></script>
|
||||
<script src="../modules/es/views/es.TableRowView.js"></script>
|
||||
|
|
|
@ -45,7 +45,23 @@
|
|||
border-color: #b3d6f6;
|
||||
}
|
||||
|
||||
.es-contextView-container {
|
||||
.es-contextView-position-above .es-contextView-menu {
|
||||
bottom: -4px;
|
||||
}
|
||||
|
||||
.es-contextView-position-below .es-contextView-menu {
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
.es-contextView-position-left .es-contextView-menu {
|
||||
left: -1px;
|
||||
}
|
||||
|
||||
.es-contextView-position-right .es-contextView-menu {
|
||||
right: -1px;
|
||||
}
|
||||
|
||||
.es-contextView-panels {
|
||||
position: absolute;
|
||||
border: solid 1px #cccccc;
|
||||
-webkit-border-radius: 0.25em;
|
||||
|
@ -59,50 +75,12 @@
|
|||
padding: 0.33em 0;
|
||||
}
|
||||
|
||||
.es-contextView-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.es-contextView-position-above .es-contextView-container {
|
||||
bottom: -4px;
|
||||
}
|
||||
|
||||
.es-contextView-position-below .es-contextView-container {
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
.es-contextView-position-left .es-contextView-container {
|
||||
left: -1px;
|
||||
}
|
||||
|
||||
.es-contextView-position-right .es-contextView-container {
|
||||
right: -1px;
|
||||
}
|
||||
|
||||
.es-contextView-menuItem {
|
||||
padding: 0.33em 1em;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.es-contextView-menuSection {
|
||||
padding: 0.33em 0.66em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.es-contextView-menuItem-break {
|
||||
margin: 0.33em 0;
|
||||
border-top: solid 1px #dddddd;
|
||||
}
|
||||
|
||||
.es-contextView-menuItem:hover {
|
||||
background-color: #b3d6f6;
|
||||
}
|
||||
|
||||
.es-contextView-panels {
|
||||
}
|
||||
|
||||
.es-contextView-panel {
|
||||
display: none;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.es-contextView-toolbar {
|
||||
padding: 0.33em 0.66em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
|
29
modules/es/styles/es.MenuView.css
Normal file
29
modules/es/styles/es.MenuView.css
Normal file
|
@ -0,0 +1,29 @@
|
|||
.es-menuView {
|
||||
display: none;
|
||||
position: absolute;
|
||||
border: solid 1px #cccccc;
|
||||
-webkit-border-radius: 0.25em;
|
||||
-moz-border-radius: 0.25em;
|
||||
-o-border-radius: 0.25em;
|
||||
border-radius: 0.25em;
|
||||
background-color: rgba(255,255,255,0.95);
|
||||
-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);
|
||||
padding: 0.33em 0;
|
||||
}
|
||||
|
||||
.es-menuView-item {
|
||||
padding: 0.33em 1em;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.es-menuView-item:hover {
|
||||
background-color: #b3d6f6;
|
||||
}
|
||||
|
||||
.es-menuView-break {
|
||||
margin: 0.33em 0;
|
||||
border-top: solid 1px #dddddd;
|
||||
}
|
|
@ -6,65 +6,55 @@
|
|||
* @param {jQuery} $overlay DOM selection to add nodes to
|
||||
*/
|
||||
es.ContextView = function( surfaceView, $overlay ) {
|
||||
var _this = this;
|
||||
|
||||
// Properties
|
||||
this.surfaceView = surfaceView;
|
||||
this.$ = $( '<div class="es-contextView"></div>' ).appendTo( $overlay || $( 'body' ) );
|
||||
this.$toolbar = $( '<div class="es-contextView-menuSection"></div>' );
|
||||
this.$container = $( '<div class="es-contextView-container"></div>' )
|
||||
.appendTo( this.$ );
|
||||
this.$menu = $( '<div class="es-contextView-menu"></div>' )
|
||||
.append( this.$toolbar )
|
||||
.appendTo( this.$container );
|
||||
this.$panels = $( '<div class="es-contextView-panels"></div>' )
|
||||
.appendTo( this.$container );
|
||||
this.$icon = $( '<div class="es-contextView-icon"></div>' )
|
||||
.appendTo( this.$ );
|
||||
this.$panels = $( '<div class="es-contextView-panels"></div>' ).appendTo( this.$ );
|
||||
this.$toolbar = $( '<div class="es-contextView-toolbar"></div>' );
|
||||
this.toolbarView = new es.ToolbarView(
|
||||
this.$toolbar,
|
||||
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.find( '[rel="link"]' ).show();
|
||||
_this.$panels.find( '[rel="link"] input:first' ).focus();
|
||||
} },
|
||||
'-',
|
||||
{ 'name': 'copy', 'label': 'Copy' },
|
||||
{ 'name': 'cut', 'label': 'Cut' },
|
||||
{ 'name': 'paste', 'label': 'Paste' }
|
||||
] );
|
||||
this.$.append( this.menu.$ );
|
||||
this.$icon = $( '<div class="es-contextView-icon"></div>' ).appendTo( this.$ );
|
||||
|
||||
// Example menu items
|
||||
this.$menu.append(
|
||||
'<div class="es-contextView-menuItem-break"></div>' +
|
||||
'<div class="es-contextView-menuItem" rel="link">Link to...</div>' +
|
||||
'<div class="es-contextView-menuItem-break"></div>' +
|
||||
'<div class="es-contextView-menuItem">Copy</div>' +
|
||||
'<div class="es-contextView-menuItem">Cut</div>' +
|
||||
'<div class="es-contextView-menuItem">Paste</div>'
|
||||
);
|
||||
|
||||
// Example panel
|
||||
this.$panels.append(
|
||||
'<div class="es-contextView-panel" rel="link">' +
|
||||
'<div><label>Page title or URL <input type="text"></label></div>' +
|
||||
'<div><a href="#cancel">Cancel</a> <button>Change</button></div>' +
|
||||
'</div>'
|
||||
);
|
||||
this.$panels.find( '[href="#cancel"]' ).click( function() {
|
||||
_this.$panels.children().hide();
|
||||
} );
|
||||
|
||||
// Events
|
||||
var _this = this;
|
||||
this.$icon.click( function() {
|
||||
_this.$container.toggle();
|
||||
} );
|
||||
|
||||
this.$menu.find( '[rel="link"]' ).click( function() {
|
||||
_this.$menu.hide();
|
||||
_this.$panels.find( '[rel="link"]' ).show();
|
||||
_this.$panels.find( '[rel="link"] input:first' ).focus();
|
||||
} );
|
||||
this.$panels.find( 'button, [href="#cancel"]' ).click( function() {
|
||||
_this.$menu.show();
|
||||
_this.$panels.children().hide();
|
||||
_this.$container.toggle();
|
||||
_this.surfaceView.$input.focus();
|
||||
return false;
|
||||
_this.menu.toggle();
|
||||
} );
|
||||
};
|
||||
|
||||
/* Methods */
|
||||
|
||||
es.ContextView.prototype.set = function() {
|
||||
|
||||
this.$.removeClass(
|
||||
'es-contextView-position-below es-contextView-position-above ' +
|
||||
'es-contextView-position-left es-contextView-position-right ' +
|
||||
|
@ -91,12 +81,12 @@ es.ContextView.prototype.set = function() {
|
|||
}
|
||||
}
|
||||
if ( position ) {
|
||||
if ( position.left + this.$container.width() < $( 'body' ).width() ) {
|
||||
if ( position.left + this.menu.$.width() < $( 'body' ).width() ) {
|
||||
this.$.addClass( 'es-contextView-position-left' );
|
||||
} else {
|
||||
this.$.addClass( 'es-contextView-position-right' );
|
||||
}
|
||||
if ( position.top + this.$container.height() < $( window ).height() + $( window ).scrollTop() ) {
|
||||
if ( position.top + this.menu.$.height() < $( window ).height() + $( window ).scrollTop() ) {
|
||||
this.$.addClass( 'es-contextView-position-below' );
|
||||
} else {
|
||||
this.$.addClass( 'es-contextView-position-above' );
|
||||
|
@ -107,6 +97,7 @@ es.ContextView.prototype.set = function() {
|
|||
};
|
||||
|
||||
es.ContextView.prototype.clear = function() {
|
||||
this.$panels.hide().children().hide();
|
||||
this.$icon.hide();
|
||||
this.$container.hide();
|
||||
this.menu.hide();
|
||||
};
|
||||
|
|
111
modules/es/views/es.MenuView.js
Normal file
111
modules/es/views/es.MenuView.js
Normal file
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* Creates an es.MenuView object.
|
||||
*
|
||||
* @class
|
||||
* @constructor
|
||||
* @param {jQuery} $overlay DOM selection to add nodes to
|
||||
*/
|
||||
es.MenuView = function( items, $overlay ) {
|
||||
// Properties
|
||||
this.$ = $( '<div class="es-menuView"></div>' ).appendTo( $overlay || $( 'body' ) );
|
||||
this.items = [];
|
||||
this.autoNamedBreaks = 0;
|
||||
|
||||
// Items
|
||||
if ( es.isArray( items ) ) {
|
||||
for ( var i = 0; i < items.length; i++ ) {
|
||||
this.addItem( items[i] );
|
||||
}
|
||||
}
|
||||
|
||||
// Events
|
||||
var _this = this;
|
||||
this.$.bind( {
|
||||
'mousedown': function( e ) {
|
||||
if ( e.button === 0 ) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
},
|
||||
'mouseup': function( e ) {
|
||||
if ( e.button === 0 ) {
|
||||
var $item = $( e.target ).closest( '.es-menuView-item' );
|
||||
if ( $item.length ) {
|
||||
var name = $item.attr( 'rel' );
|
||||
for ( var i = 0; i < _this.items.length; i++ ) {
|
||||
if ( _this.items[i].name === name ) {
|
||||
_this.onSelect( _this.items[i], e );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
/* Methods */
|
||||
|
||||
es.MenuView.prototype.addItem = function( item, before ) {
|
||||
if ( item === '-' ) {
|
||||
item = {
|
||||
'name': 'break-' + this.autoNamedBreaks++
|
||||
};
|
||||
}
|
||||
// Items that don't have custom DOM elements will be auto-created
|
||||
if ( !item.$ ) {
|
||||
if ( !item.name ) {
|
||||
throw 'Invalid menu item error. Items must have a name property.';
|
||||
}
|
||||
if ( item.label ) {
|
||||
item.$ = $( '<div class="es-menuView-item"></div>' )
|
||||
.attr( 'rel', item.name )
|
||||
// TODO: i18n time!
|
||||
.text( item.label );
|
||||
} else {
|
||||
// No label, must be a break
|
||||
item.$ = $( '<div class="es-menuView-break"></div>' )
|
||||
.attr( 'rel', item.name );
|
||||
}
|
||||
// TODO: Keyboard shortcut (and icons for them), support for keyboard accelerators, etc.
|
||||
}
|
||||
if ( before ) {
|
||||
for ( var i = 0; i < this.items.length; i++ ) {
|
||||
if ( this.items[i].name === before ) {
|
||||
this.items.splice( i, 0, item );
|
||||
this.items[i].$.before( item.$ );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.items.push( item );
|
||||
this.$.append( item.$ );
|
||||
};
|
||||
|
||||
es.MenuView.prototype.removeItem = function( name ) {
|
||||
for ( var i = 0; i < this.items.length; i++ ) {
|
||||
if ( this.items[i].name === name ) {
|
||||
this.items.splice( i, 1 );
|
||||
i--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
es.MenuView.prototype.show = function() {
|
||||
this.$.show();
|
||||
};
|
||||
|
||||
es.MenuView.prototype.toggle = function() {
|
||||
this.$.toggle();
|
||||
};
|
||||
|
||||
es.MenuView.prototype.hide = function() {
|
||||
this.$.hide();
|
||||
};
|
||||
|
||||
es.MenuView.prototype.onSelect = function( item, event ) {
|
||||
if ( typeof item.callback === 'function' ) {
|
||||
item.callback();
|
||||
}
|
||||
this.hide();
|
||||
};
|
Loading…
Reference in a new issue