Index: trunk/extensions/VisualEditor/modules/es/tools/es.AnnotationButtonTool.js |
— | — | @@ -14,36 +14,23 @@ |
15 | 15 | |
16 | 16 | // Properties |
17 | 17 | this.annotation = data; |
| 18 | + this.active = false; |
18 | 19 | }; |
19 | 20 | |
20 | 21 | /* Methods */ |
21 | 22 | |
22 | 23 | es.AnnotationButtonTool.prototype.onClick = function() { |
23 | | - var method; |
24 | | - if ( this.$.hasClass( 'es-toolbarButtonTool-down' ) ) { |
25 | | - method = 'clear'; |
26 | | - this.toolbar.surfaceView.removeInsertionAnnotation( this.annotation ); |
27 | | - } else { |
28 | | - method = 'set'; |
29 | | - this.toolbar.surfaceView.addInsertionAnnotation( this.annotation ); |
30 | | - } |
31 | | - |
32 | | - var tx = this.toolbar.surfaceView.model.getDocument().prepareContentAnnotation( |
33 | | - this.toolbar.surfaceView.currentSelection, |
34 | | - method, |
35 | | - this.annotation |
36 | | - ); |
37 | | - this.toolbar.surfaceView.model.transact( tx ); |
| 24 | + this.toolbar.getSurfaceView().annotate( this.active ? 'clear' : 'set', this.annotation ); |
38 | 25 | }; |
39 | 26 | |
40 | | -es.AnnotationButtonTool.prototype.updateState = function( annotations ) { |
41 | | - for ( var i = 0; i < annotations.full.length; i++ ) { |
42 | | - if ( annotations.full[i].type === this.annotation.type ) { |
43 | | - this.$.addClass( 'es-toolbarButtonTool-down' ); |
44 | | - return; |
45 | | - } |
| 27 | +es.AnnotationButtonTool.prototype.updateState = function( annotations, nodes ) { |
| 28 | + if ( es.DocumentModel.getIndexOfAnnotation( annotations.full, this.annotation ) !== -1 ) { |
| 29 | + this.$.addClass( 'es-toolbarButtonTool-down' ); |
| 30 | + this.active = true; |
| 31 | + return; |
46 | 32 | } |
47 | 33 | this.$.removeClass( 'es-toolbarButtonTool-down' ); |
| 34 | + this.active = false; |
48 | 35 | }; |
49 | 36 | |
50 | 37 | /* Registration */ |
Index: trunk/extensions/VisualEditor/modules/es/models/es.DocumentModel.js |
— | — | @@ -173,7 +173,7 @@ |
174 | 174 | if ( typeof annotations[i] === 'string' ) { |
175 | 175 | continue; |
176 | 176 | } |
177 | | - if ( annotations[i].hash === annotation.hash ) { |
| 177 | + if ( annotations[i].hash === ( annotation.hash || es.DocumentModel.getHash( annotation ) ) ) { |
178 | 178 | return i; |
179 | 179 | } |
180 | 180 | } |
Index: trunk/extensions/VisualEditor/modules/es/views/es.SurfaceView.js |
— | — | @@ -153,26 +153,52 @@ |
154 | 154 | }; |
155 | 155 | |
156 | 156 | /* Methods */ |
| 157 | + |
| 158 | +es.SurfaceView.prototype.annotate = function( method, annotation ) { |
| 159 | + if ( method === 'toggle' ) { |
| 160 | + var annotations = this.getAnnotations(); |
| 161 | + if ( es.DocumentModel.getIndexOfAnnotation( annotations.full, annotation ) !== -1 ) { |
| 162 | + method = 'clear'; |
| 163 | + } else { |
| 164 | + method = 'set'; |
| 165 | + } |
| 166 | + } |
| 167 | + if ( this.currentSelection.getLength() ) { |
| 168 | + var tx = this.model.getDocument().prepareContentAnnotation( |
| 169 | + this.currentSelection, method, annotation |
| 170 | + ); |
| 171 | + this.model.transact( tx ); |
| 172 | + } else { |
| 173 | + if ( method === 'set' ) { |
| 174 | + this.addInsertionAnnotation( annotation ); |
| 175 | + } else if ( method === 'clear' ) { |
| 176 | + this.removeInsertionAnnotation( annotation ); |
| 177 | + } |
| 178 | + } |
| 179 | +}; |
| 180 | + |
| 181 | +es.SurfaceView.prototype.getAnnotations = function() { |
| 182 | + return this.currentSelection.getLength() ? |
| 183 | + this.model.getDocument().getAnnotationsFromRange( this.currentSelection ) : |
| 184 | + { |
| 185 | + 'full': this.insertionAnnotations, |
| 186 | + 'partial': [], |
| 187 | + 'all': this.insertionAnnotations |
| 188 | + }; |
| 189 | +}; |
| 190 | + |
157 | 191 | es.SurfaceView.prototype.emitCursor = function() { |
158 | 192 | if ( this.emitCursorTimeout ) { |
159 | 193 | clearTimeout( this.emitCursorTimeout ); |
160 | 194 | } |
161 | 195 | var _this = this; |
162 | 196 | this.emitCursorTimeout = setTimeout( function() { |
163 | | - var annotations, |
| 197 | + var annotations = _this.getAnnotations(), |
164 | 198 | nodes = [], |
165 | 199 | model = _this.documentView.model; |
166 | | - |
167 | | - if( _this.currentSelection.from === _this.currentSelection.to ) { |
168 | | - var insertionAnnotations = _this.getInsertionAnnotations(); |
169 | | - annotations = { |
170 | | - 'full': insertionAnnotations, |
171 | | - 'partial': [], |
172 | | - 'all': insertionAnnotations |
173 | | - }; |
| 200 | + if ( _this.currentSelection.from === _this.currentSelection.to ) { |
174 | 201 | nodes.push( model.getNodeFromOffset( _this.currentSelection.from ) ); |
175 | 202 | } else { |
176 | | - annotations = model.getAnnotationsFromRange( _this.currentSelection ); |
177 | 203 | var startNode = model.getNodeFromOffset( _this.currentSelection.start ), |
178 | 204 | endNode = model.getNodeFromOffset( _this.currentSelection.end ); |
179 | 205 | if ( startNode === endNode ) { |
— | — | @@ -496,52 +522,52 @@ |
497 | 523 | this.handleEnter(); |
498 | 524 | e.preventDefault(); |
499 | 525 | break; |
500 | | - // Z (undo/redo) |
501 | | - case 90: |
| 526 | + // Insert content (maybe) |
| 527 | + default: |
| 528 | + // Control/command + character combos |
502 | 529 | if ( e.metaKey || e.ctrlKey ) { |
503 | | - if ( this.keyboard.keys.shift ) { |
504 | | - this.model.redo( 1 ); |
505 | | - } else { |
506 | | - this.model.undo( 1 ); |
| 530 | + switch ( e.keyCode ) { |
| 531 | + // z (undo/redo) |
| 532 | + case 90: |
| 533 | + if ( this.keyboard.keys.shift ) { |
| 534 | + this.model.redo( 1 ); |
| 535 | + } else { |
| 536 | + this.model.undo( 1 ); |
| 537 | + } |
| 538 | + return false; |
| 539 | + // a (select all) |
| 540 | + case 65: |
| 541 | + this.model.select( new es.Range( |
| 542 | + this.model.getDocument().getRelativeContentOffset( 0, 1 ), |
| 543 | + this.model.getDocument().getRelativeContentOffset( |
| 544 | + this.model.getDocument().getContentLength(), -1 |
| 545 | + ) |
| 546 | + ), true ); |
| 547 | + return false; |
| 548 | + // b (bold) |
| 549 | + case 66: |
| 550 | + this.annotate( 'toggle', {'type': 'textStyle/bold' } ); |
| 551 | + return false; |
| 552 | + // i (italic) |
| 553 | + case 73: |
| 554 | + this.annotate( 'toggle', {'type': 'textStyle/italic' } ); |
| 555 | + return false; |
507 | 556 | } |
508 | | - return false; |
509 | 557 | } |
| 558 | + // Regular text insertion |
510 | 559 | handleInsert(); |
511 | 560 | break; |
512 | | - |
513 | | - // a (select all) |
514 | | - case 65: |
515 | | - if ( e.metaKey || e.ctrlKey ) { |
516 | | - this.model.select( new es.Range( |
517 | | - this.model.getDocument().getRelativeContentOffset( 0, 1 ), |
518 | | - this.model.getDocument().getRelativeContentOffset( |
519 | | - this.model.getDocument().getContentLength(), -1 |
520 | | - ) |
521 | | - ), true ); |
522 | | - break; |
523 | | - } |
524 | | - // Insert content (maybe) |
525 | | - default: |
526 | | - if ( !e.ctrlKey || ( e.ctrlKey && e.keyCode === 86 ) ) { |
527 | | - handleInsert(); |
528 | | - } |
529 | | - break; |
530 | 561 | } |
531 | 562 | return true; |
532 | 563 | }; |
533 | 564 | |
534 | 565 | es.SurfaceView.prototype.onKeyUp = function( e ) { |
535 | | - switch ( e.keyCode ) { |
536 | | - case 16: // Shift |
537 | | - this.keyboard.keys.shift = false; |
538 | | - if ( this.keyboard.selecting ) { |
539 | | - this.keyboard.selecting = false; |
540 | | - } |
541 | | - break; |
542 | | - default: |
543 | | - break; |
| 566 | + if ( e.keyCode === 16 ) { |
| 567 | + this.keyboard.keys.shift = false; |
| 568 | + if ( this.keyboard.selecting ) { |
| 569 | + this.keyboard.selecting = false; |
| 570 | + } |
544 | 571 | } |
545 | | - return true; |
546 | 572 | }; |
547 | 573 | |
548 | 574 | es.SurfaceView.prototype.handleDelete = function( backspace, isPartial ) { |
— | — | @@ -815,12 +841,10 @@ |
816 | 842 | break; |
817 | 843 | default: |
818 | 844 | throw new Error( 'unrecognized cursor movement unit' ); |
819 | | - break; |
820 | 845 | } |
821 | 846 | break; |
822 | 847 | default: |
823 | 848 | throw new Error( 'unrecognized cursor direction' ); |
824 | | - break; |
825 | 849 | } |
826 | 850 | |
827 | 851 | if( direction != 'up' && direction != 'down' ) { |
Index: trunk/extensions/VisualEditor/modules/es/views/es.ToolbarView.js |
— | — | @@ -56,6 +56,12 @@ |
57 | 57 | this.setup(); |
58 | 58 | }; |
59 | 59 | |
| 60 | +/* Methods */ |
| 61 | + |
| 62 | +es.ToolbarView.prototype.getSurfaceView = function() { |
| 63 | + return this.surfaceView; |
| 64 | +}; |
| 65 | + |
60 | 66 | es.ToolbarView.prototype.setup = function() { |
61 | 67 | for ( var i = 0; i < this.config.length; i++ ) { |
62 | 68 | var $group = $( '<div>' ) |