Index: trunk/extensions/VisualEditor/modules/ve/ui/tools/ve.ui.ListButtonTool.js |
— | — | @@ -78,21 +78,19 @@ |
79 | 79 | } |
80 | 80 | } |
81 | 81 | |
82 | | - for( i = 0; i < listItems.length; i++ ) { |
| 82 | + for ( i = 0; i < listItems.length; i++ ) { |
83 | 83 | styles = listItems[i].getElementAttribute( 'styles' ); |
84 | 84 | if ( styles[styles.length - 1] !== style ) { |
85 | | - styles.splice( styles.length - 1, 1, style ); |
86 | 85 | tx = surface.model.getDocument().prepareElementAttributeChange( |
87 | 86 | surface.documentView.model.getOffsetFromNode( listItems[i], false ), |
88 | | - 'set', |
89 | 87 | 'styles', |
90 | | - styles |
| 88 | + styles.slice( 0, styles.length - 1 ).concat( style ) |
91 | 89 | ); |
92 | 90 | surface.model.transact( tx ); |
93 | 91 | } |
94 | 92 | } |
95 | 93 | |
96 | | - for( i = 0; i < stacks.length; i++ ) { |
| 94 | + for ( i = 0; i < stacks.length; i++ ) { |
97 | 95 | removeLength = 0; |
98 | 96 | insertAt = surface.documentView.model.getOffsetFromNode( stacks[i][0], false ); |
99 | 97 | |
Index: trunk/extensions/VisualEditor/modules/ve/ui/tools/ve.ui.IndentationButtonTool.js |
— | — | @@ -45,12 +45,10 @@ |
46 | 46 | for ( i = 0; i < listItems.length; i++ ) { |
47 | 47 | styles = listItems[i].getElementAttribute( 'styles' ); |
48 | 48 | if ( styles.length < 6 ) { |
49 | | - styles.push( styles[styles.length - 1] ); |
50 | 49 | tx = surface.model.getDocument().prepareElementAttributeChange( |
51 | 50 | surface.documentView.model.getOffsetFromNode( listItems[i], false ), |
52 | | - 'set', |
53 | 51 | 'styles', |
54 | | - styles |
| 52 | + styles.concat( styles[styles.length - 1] ) |
55 | 53 | ); |
56 | 54 | surface.model.transact( tx ); |
57 | 55 | } |
— | — | @@ -66,12 +64,10 @@ |
67 | 65 | for ( i = 0; i < listItems.length; i++ ) { |
68 | 66 | styles = listItems[i].getElementAttribute( 'styles' ); |
69 | 67 | if ( styles.length > 1 ) { |
70 | | - styles.splice( styles.length - 1, 1); |
71 | 68 | tx = surface.model.getDocument().prepareElementAttributeChange( |
72 | 69 | surface.documentView.model.getOffsetFromNode( listItems[i], false ), |
73 | | - 'set', |
74 | 70 | 'styles', |
75 | | - styles |
| 71 | + styles.slice( 0, styles.length - 1 ) |
76 | 72 | ); |
77 | 73 | surface.model.transact( tx ); |
78 | 74 | } |
Index: trunk/extensions/VisualEditor/modules/ve/dm/nodes/ve.dm.DocumentNode.js |
— | — | @@ -1175,7 +1175,7 @@ |
1176 | 1176 | * @method |
1177 | 1177 | * @returns {ve.dm.Transaction} |
1178 | 1178 | */ |
1179 | | -ve.dm.DocumentNode.prototype.prepareElementAttributeChange = function( offset, method, key, value ) { |
| 1179 | +ve.dm.DocumentNode.prototype.prepareElementAttributeChange = function( offset, key, to ) { |
1180 | 1180 | var tx = new ve.dm.Transaction(); |
1181 | 1181 | if ( offset ) { |
1182 | 1182 | tx.pushRetain( offset ); |
— | — | @@ -1186,7 +1186,8 @@ |
1187 | 1187 | if ( this.data[offset].type[0] === '/' ) { |
1188 | 1188 | throw 'Invalid element offset error. Can not set attributes on closing element.'; |
1189 | 1189 | } |
1190 | | - tx.pushChangeElementAttribute( method, key, value ); |
| 1190 | + var from = 'attributes' in this.data[offset] ? this.data[offset].attributes[key] : undefined; |
| 1191 | + tx.pushReplaceElementAttribute( key, from, to ); |
1191 | 1192 | if ( offset < this.data.length ) { |
1192 | 1193 | tx.pushRetain( this.data.length - offset ); |
1193 | 1194 | } |
Index: trunk/extensions/VisualEditor/modules/ve/dm/ve.dm.Transaction.js |
— | — | @@ -94,14 +94,15 @@ |
95 | 95 | * @method |
96 | 96 | * @param {String} method Method to use, either "set" or "clear" |
97 | 97 | * @param {String} key Name of attribute to change |
98 | | - * @param {Mixed} value Value to set attribute to, or value of attribute being cleared |
| 98 | + * @param {Mixed} from Value change attribute from |
| 99 | + * @param {Mixed} to Value to change attribute to |
99 | 100 | */ |
100 | | -ve.dm.Transaction.prototype.pushChangeElementAttribute = function( method, key, value ) { |
| 101 | +ve.dm.Transaction.prototype.pushReplaceElementAttribute = function( key, from, to ) { |
101 | 102 | this.operations.push( { |
102 | 103 | 'type': 'attribute', |
103 | | - 'method': method, |
104 | 104 | 'key': key, |
105 | | - 'value': value |
| 105 | + 'from': from, |
| 106 | + 'to': to |
106 | 107 | } ); |
107 | 108 | }; |
108 | 109 | |
Index: trunk/extensions/VisualEditor/modules/ve/dm/ve.dm.TransactionProcessor.js |
— | — | @@ -450,13 +450,9 @@ |
451 | 451 | if ( element.type === undefined ) { |
452 | 452 | throw 'Invalid element error. Can not set attributes on non-element data.'; |
453 | 453 | } |
454 | | - if ( ( op.method === 'set' && !invert ) || ( op.method === 'clear' && invert ) ) { |
455 | | - // Automatically initialize attributes object |
456 | | - if ( !element.attributes ) { |
457 | | - element.attributes = {}; |
458 | | - } |
459 | | - element.attributes[op.key] = op.value; |
460 | | - } else if ( ( op.method === 'clear' && !invert ) || ( op.method === 'set' && invert ) ) { |
| 454 | + var to = invert ? op.from : op.to; |
| 455 | + if ( to === undefined ) { |
| 456 | + // Clear |
461 | 457 | if ( element.attributes ) { |
462 | 458 | delete element.attributes[op.key]; |
463 | 459 | } |
— | — | @@ -470,7 +466,12 @@ |
471 | 467 | delete element.attributes; |
472 | 468 | } |
473 | 469 | } else { |
474 | | - throw 'Invalid method error. Can not operate attributes this way: ' + method; |
| 470 | + // Automatically initialize attributes object |
| 471 | + if ( !element.attributes ) { |
| 472 | + element.attributes = {}; |
| 473 | + } |
| 474 | + // Set |
| 475 | + element.attributes[op.key] = to; |
475 | 476 | } |
476 | 477 | var node = this.model.getNodeFromOffset( this.cursor + 1 ); |
477 | 478 | if ( node.hasChildren() ) { |