r105002 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r105001‎ | r105002 | r105003 >
Date:21:25, 2 December 2011
Author:tparscal
Status:deferred
Tags:
Comment:
Integrated menuView into format drop down tool
Modified paths:
  • /trunk/extensions/VisualEditor/modules/es/styles/es.ContextView.css (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/styles/es.MenuView.css (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/styles/es.ToolbarView.css (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/tools/es.DropdownTool.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/tools/es.FormatDropdownTool.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/views/es.ContextView.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/views/es.MenuView.js (modified) (history)

Diff [purge]

Index: trunk/extensions/VisualEditor/modules/es/tools/es.FormatDropdownTool.js
@@ -1,101 +1,123 @@
22 es.FormatDropdownTool = function( toolbar, name ) {
3 - es.DropdownTool.call( this, toolbar, name );
4 -
5 - this.formats = [
 3+ // Inheritance
 4+ es.DropdownTool.call( this, toolbar, name, [
65 {
7 - 'name': 'Paragraph',
 6+ 'name': 'paragraph',
 7+ 'label': 'Paragraph',
88 'type' : 'paragraph'
99 },
1010 {
11 - 'name': 'Heading Level 1',
 11+ 'name': 'heading-1',
 12+ 'label': 'Heading Level 1',
1213 'type' : 'heading',
1314 'attributes': { 'level': 1 }
1415 },
1516 {
16 - 'name': 'Heading Level 2',
 17+ 'name': 'heading-2',
 18+ 'label': 'Heading Level 2',
1719 'type' : 'heading',
1820 'attributes': { 'level': 2 }
1921 },
2022 {
21 - 'name': 'Heading Level 3',
 23+ 'name': 'heading-3',
 24+ 'label': 'Heading Level 3',
2225 'type' : 'heading',
2326 'attributes': { 'level': 3 }
2427 },
2528 {
26 - 'name': 'Heading Level 4',
 29+ 'name': 'heading-4',
 30+ 'label': 'Heading Level 4',
2731 'type' : 'heading',
2832 'attributes': { 'level': 4 }
2933 },
3034 {
31 - 'name': 'Heading Level 5',
 35+ 'name': 'heading-5',
 36+ 'label': 'Heading Level 5',
3237 'type' : 'heading',
3338 'attributes': { 'level': 5 }
3439 },
3540 {
36 - 'name': 'Heading Level 6',
 41+ 'name': 'heading-6',
 42+ 'label': 'Heading Level 6',
3743 'type' : 'heading',
3844 'attributes': { 'level': 6 }
3945 },
4046 {
41 - 'name': 'Preformatted',
 47+ 'name': 'pre',
 48+ 'label': 'Preformatted',
4249 'type' : 'pre'
4350 }
44 - ];
45 -
46 - this.$select.append( '<option>' );
 51+ ] );
4752
48 - for ( var i = 0; i < this.formats.length; i++ ) {
49 - $( '<option>' )
50 - .val( i )
51 - .html( this.formats[i].name )
52 - .appendTo( this.$select );
53 - }
 53+ var _this = this;
 54+ this.$.bind( {
 55+ 'mousedown': function( e ) {
 56+ if ( e.button === 0 ) {
 57+ e.preventDefault();
 58+ return false;
 59+ }
 60+ },
 61+ 'mouseup': function( e ) {
 62+ if ( e.button === 0 ) {
 63+ _this.menuView.setPosition( es.Position.newFromElementPagePosition( _this.$ ) );
 64+ _this.menuView.toggle();
 65+ }
 66+ }
 67+ } );
5468 };
5569
56 -es.FormatDropdownTool.prototype.onChange = function() {
57 - var index = this.$select.val();
58 - if ( index in this.formats ) {
59 - var txs = this.toolbar.surfaceView.model.getDocument().prepareLeafConversion(
60 - this.toolbar.surfaceView.currentSelection,
61 - this.formats[index].type,
62 - this.formats[index].attributes
63 - )
64 - for ( var i = 0; i < txs.length; i++ ) {
65 - this.toolbar.surfaceView.model.transact( txs[i] );
66 - }
 70+/* Methods */
 71+
 72+es.FormatDropdownTool.prototype.onSelect = function( item ) {
 73+ var txs = this.toolbar.surfaceView.model.getDocument().prepareLeafConversion(
 74+ this.toolbar.surfaceView.currentSelection,
 75+ item.type,
 76+ item.attributes
 77+ );
 78+ for ( var i = 0; i < txs.length; i++ ) {
 79+ this.toolbar.surfaceView.model.transact( txs[i] );
6780 }
6881 };
6982
7083 es.FormatDropdownTool.prototype.updateState = function( annotations, nodes ) {
71 - var format = {
72 - 'type': nodes[0].getElementType(),
73 - 'attributes': nodes[0].getElement().attributes
74 - };
75 -
76 - for( var i = 1; i < nodes.length; i++ ) {
77 - if ( format.type != nodes[i].getElementType()
78 - || !es.compareObjects( format.attributes, nodes[i].element.attributes ) ) {
 84+ // Get type and attributes of the first node
 85+ var i,
 86+ format = {
 87+ 'type': nodes[0].getElementType(),
 88+ 'attributes': nodes[0].getElement().attributes
 89+ };
 90+ // Look for mismatches, in which case format should be null
 91+ for ( i = 1; i < nodes.length; i++ ) {
 92+ if ( format.type != nodes[i].getElementType() ||
 93+ !es.compareObjects( format.attributes, nodes[i].element.attributes ) ) {
7994 format = null;
8095 break;
8196 }
8297 }
8398
8499 if ( format === null ) {
85 - this.$select.val( null );
 100+ this.$.text( '' );
86101 } else {
87 - for ( var i = 0; i < this.formats.length; i++ ) {
88 - if ( format.type === this.formats[i].type
89 - && es.compareObjects( format.attributes, this.formats[i].attributes ) ) {
90 - this.$select.val( i );
91 - break;
 102+ var items = this.menuView.getItems();
 103+ for ( i = 0; i < items.length; i++ ) {
 104+ if (
 105+ format.type === items[i].type &&
 106+ es.compareObjects( format.attributes, items[i].attributes )
 107+ ) {
 108+ this.$.text( items[i].label );
 109+ break;
92110 }
93111 }
94112 }
95113 };
96114
 115+/* Registration */
 116+
97117 es.Tool.tools.format = {
98 - constructor: es.FormatDropdownTool,
99 - name: 'format'
 118+ 'constructor': es.FormatDropdownTool,
 119+ 'name': 'format'
100120 };
101121
102 -es.extendClass( es.FormatDropdownTool, es.DropdownTool );
\ No newline at end of file
 122+/* Inheritance */
 123+
 124+es.extendClass( es.FormatDropdownTool, es.DropdownTool );
Index: trunk/extensions/VisualEditor/modules/es/tools/es.DropdownTool.js
@@ -1,28 +1,35 @@
2 -es.DropdownTool = function( toolbar, name ) {
 2+es.DropdownTool = function( toolbar, name, items ) {
 3+ // Inheritance
34 es.Tool.call( this, toolbar, name );
45
5 - // for es.extendClass
 6+ // Early exit when extending via es.extendClass
67 if ( !name ) {
78 return;
89 }
9 -
10 - this.$.addClass( 'es-toolbarDropdownTool' ).addClass( 'es-toolbarDropdownTool-' + name );
1110
12 - this.$select = $( '<select>' );
13 - this.$.append( this.$select );
14 -
 11+ // Properties
1512 var _this = this;
 13+ this.menuView = new es.MenuView( items, function( item ) {
 14+ _this.onSelect( item );
 15+ _this.$.text( item.label );
 16+ } );
1617
17 - this.$.bind( {
18 - 'change': function( e ) {
19 - _this.onChange( e );
 18+ $( document ).add( this.toolbar.surfaceView.$ ).mousedown( function( e ) {
 19+ if ( e.button === 0 ) {
 20+ _this.menuView.hide();
2021 }
2122 } );
2223
 24+ // DOM Changes
 25+ this.$.addClass( 'es-toolbarDropdownTool' ).addClass( 'es-toolbarDropdownTool-' + name );
2326 };
2427
25 -es.DropdownTool.prototype.onChange = function() {
26 - throw 'DropdownTool.onChange not implemented in this subclass:' + this.constructor;
 28+/* Methods */
 29+
 30+es.DropdownTool.prototype.onSelect = function( item ) {
 31+ throw 'DropdownTool.onSelect not implemented in this subclass:' + this.constructor;
2732 };
2833
29 -es.extendClass( es.DropdownTool, es.Tool );
\ No newline at end of file
 34+/* Inheritance */
 35+
 36+es.extendClass( es.DropdownTool, es.Tool );
Index: trunk/extensions/VisualEditor/modules/es/styles/es.ToolbarView.css
@@ -88,6 +88,19 @@
8989 background-image: url(../images/clear.png);
9090 }
9191 .es-toolbarDropdownTool {
 92+ border-color: #dddddd;
 93+ -webkit-border-radius: 0.25em;
 94+ -moz-border-radius: 0.25em;
 95+ -o-border-radius: 0.25em;
 96+ background-color: white;
 97+ font-size: 0.8em;
 98+ line-height: 24px;
 99+ padding-left: 0.75em;
 100+ padding-right: 24px;
 101+ background-image: url(../images/arrow-down.png);
 102+ background-position: 9em center;
 103+ background-repeat: no-repeat;
92104 }
93 -.es-toolbarDropdownTool-formatting {
94 -}
\ No newline at end of file
 105+.es-toolbarDropdownTool-format {
 106+ width: 8em;
 107+}
Index: trunk/extensions/VisualEditor/modules/es/styles/es.ContextView.css
@@ -19,6 +19,7 @@
2020 -webkit-box-shadow: 0 0.25em 1em 0 rgba(0,0,0,0.25);
2121 -moz-box-shadow: 0 0.25em 1em 0 rgba(0,0,0,0.25);
2222 box-shadow: 0 0.25em 1em 0 rgba(0,0,0,0.25);
 23+ z-index: 4;
2324 }
2425
2526 .es-contextView-position-start .es-contextView-icon {
Index: trunk/extensions/VisualEditor/modules/es/styles/es.MenuView.css
@@ -11,6 +11,7 @@
1212 -moz-box-shadow: 0 0.25em 1em 0 rgba(0,0,0,0.25);
1313 box-shadow: 0 0.25em 1em 0 rgba(0,0,0,0.25);
1414 padding: 0.33em 0;
 15+ z-index: 3;
1516 }
1617
1718 .es-menuView-item {
Index: trunk/extensions/VisualEditor/modules/es/views/es.ContextView.js
@@ -18,28 +18,30 @@
1919 this.surfaceView,
2020 [{ 'name': 'textStyle', 'items' : [ 'bold', 'italic', 'formatting', 'clear' ] }]
2121 );
22 - this.menu = new es.MenuView( [
23 - // Example menu items
24 - { 'name': 'tools', '$': this.$toolbar },
25 - '-',
26 - { 'name': 'link', 'label': 'Link to...', 'callback': function() {
27 - _this.menu.hide();
28 - _this.$panels
29 - .show()
30 - .find( '[rel="link"]' )
 22+ this.menuView = new es.MenuView( [
 23+ // Example menu items
 24+ { 'name': 'tools', '$': this.$toolbar },
 25+ '-',
 26+ { 'name': 'link', 'label': 'Link to...', 'callback': function( item ) {
 27+ _this.menuView.hide();
 28+ _this.$panels
3129 .show()
32 - .end()
33 - .find( '[rel="link"] input:first' )
34 - .focus();
35 - } },
36 - '-',
37 - { 'name': 'copy', 'label': 'Copy' },
38 - { 'name': 'cut', 'label': 'Cut' },
39 - { 'name': 'paste', 'label': 'Paste' }
40 - ] );
41 - this.$.append( this.menu.$ );
 30+ .find( '[rel="link"]' )
 31+ .show()
 32+ .end()
 33+ .find( '[rel="link"] input:first' )
 34+ .focus();
 35+ } },
 36+ '-',
 37+ { 'name': 'copy', 'label': 'Copy' },
 38+ { 'name': 'cut', 'label': 'Cut' },
 39+ { 'name': 'paste', 'label': 'Paste' }
 40+ ],
 41+ null,
 42+ this.$
 43+ );
4244 this.$icon = $( '<div class="es-contextView-icon"></div>' ).appendTo( this.$ );
43 -
 45+
4446 // Example panel
4547 this.$panels.append(
4648 '<div class="es-contextView-panel" rel="link">' +
@@ -52,8 +54,18 @@
5355 } );
5456
5557 // Events
56 - this.$icon.click( function() {
57 - _this.menu.toggle();
 58+ this.$icon.bind( {
 59+ 'mousedown': function( e ) {
 60+ if ( e.button === 0 ) {
 61+ e.preventDefault();
 62+ return false;
 63+ }
 64+ },
 65+ 'mouseup': function( e ) {
 66+ if ( e.button === 0 ) {
 67+ _this.menuView.toggle();
 68+ }
 69+ }
5870 } );
5971 };
6072
@@ -86,12 +98,13 @@
8799 }
88100 }
89101 if ( position ) {
90 - if ( position.left + this.menu.$.width() < $( 'body' ).width() ) {
 102+ if ( position.left + this.menuView.$.width() < $( 'body' ).width() ) {
91103 this.$.addClass( 'es-contextView-position-left' );
92104 } else {
93105 this.$.addClass( 'es-contextView-position-right' );
94106 }
95 - if ( position.top + this.menu.$.height() < $( window ).height() + $( window ).scrollTop() ) {
 107+ var $window = $( window );
 108+ if ( position.top + this.menuView.$.height() < $window.height() + $window.scrollTop() ) {
96109 this.$.addClass( 'es-contextView-position-below' );
97110 } else {
98111 this.$.addClass( 'es-contextView-position-above' );
@@ -104,5 +117,5 @@
105118 es.ContextView.prototype.clear = function() {
106119 this.$panels.hide().children().hide();
107120 this.$icon.hide();
108 - this.menu.hide();
 121+ this.menuView.hide();
109122 };
Index: trunk/extensions/VisualEditor/modules/es/views/es.MenuView.js
@@ -3,13 +3,16 @@
44 *
55 * @class
66 * @constructor
7 - * @param {jQuery} $overlay DOM selection to add nodes to
 7+ * @param {Object[]} items List of items to append initially
 8+ * @param {Function} callback Function to call if an item doesn't have it's own callback
 9+ * @param {jQuery} [$overlay=$( 'body' )] DOM selection to add nodes to
810 */
9 -es.MenuView = function( items, $overlay ) {
 11+es.MenuView = function( items, callback, $overlay ) {
1012 // Properties
1113 this.$ = $( '<div class="es-menuView"></div>' ).appendTo( $overlay || $( 'body' ) );
1214 this.items = [];
1315 this.autoNamedBreaks = 0;
 16+ this.callback = callback;
1417
1518 // Items
1619 if ( es.isArray( items ) ) {
@@ -91,6 +94,14 @@
9295 }
9396 };
9497
 98+es.MenuView.prototype.getItems = function() {
 99+ return this.items;
 100+};
 101+
 102+es.MenuView.prototype.setPosition = function( position ) {
 103+ return this.$.css( { 'top': position.top, 'left': position.left } );
 104+};
 105+
95106 es.MenuView.prototype.show = function() {
96107 this.$.show();
97108 };
@@ -105,7 +116,9 @@
106117
107118 es.MenuView.prototype.onSelect = function( item, event ) {
108119 if ( typeof item.callback === 'function' ) {
109 - item.callback();
 120+ item.callback( item );
 121+ } else if ( typeof this.callback === 'function' ) {
 122+ this.callback( item );
110123 }
111124 this.hide();
112125 };

Status & tagging log