r103976 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r103975‎ | r103976 | r103977 >
Date:22:59, 22 November 2011
Author:tparscal
Status:deferred
Tags:
Comment:
Rewrite of undo/redo - now completely implemented in es.SurfaceModel
Modified paths:
  • /trunk/extensions/VisualEditor/demo/index.html (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/models/es.HistoryModel.js (deleted) (history)
  • /trunk/extensions/VisualEditor/modules/es/models/es.HistoryStateModel.js (deleted) (history)
  • /trunk/extensions/VisualEditor/modules/es/models/es.SurfaceModel.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/views/es.SurfaceView.js (modified) (history)
  • /trunk/extensions/VisualEditor/tests/es/index.html (modified) (history)

Diff [purge]

Index: trunk/extensions/VisualEditor/tests/es/index.html
@@ -31,8 +31,6 @@
3232
3333 <!-- Models -->
3434 <script src="../../modules/es/models/es.DocumentModel.js"></script>
35 - <script src="../../modules/es/models/es.HistoryModel.js"></script>
36 - <script src="../../modules/es/models/es.HistoryStateModel.js"></script>
3735 <script src="../../modules/es/models/es.ListItemModel.js"></script>
3836 <script src="../../modules/es/models/es.ListModel.js"></script>
3937 <script src="../../modules/es/models/es.ParagraphModel.js"></script>
Index: trunk/extensions/VisualEditor/demo/index.html
@@ -82,8 +82,6 @@
8383 <!-- Models -->
8484 <script src="../modules/es/models/es.SurfaceModel.js"></script>
8585 <script src="../modules/es/models/es.DocumentModel.js"></script>
86 - <script src="../modules/es/models/es.HistoryModel.js"></script>
87 - <script src="../modules/es/models/es.HistoryStateModel.js"></script>
8886 <script src="../modules/es/models/es.ParagraphModel.js"></script>
8987 <script src="../modules/es/models/es.PreModel.js"></script>
9088 <script src="../modules/es/models/es.ListModel.js"></script>
Index: trunk/extensions/VisualEditor/modules/es/models/es.HistoryModel.js
@@ -1,190 +0,0 @@
2 -/**
3 - * Creates an es.HistoryModel object.
4 - *
5 - * @class
6 - * @constructor
7 - * @extends {es.EventEmitter}
8 - * @param {es.DocumentModel} doc Document being tracked and modified
9 - */
10 -es.HistoryModel = function( doc ) {
11 - // Inheritance
12 - es.EventEmitter.call( this );
13 -
14 - // Properties
15 - this.doc = doc;
16 - this.currentState = new es.HistoryStateModel();
17 - this.currentStateIndex = 0;
18 - this.states = [this.currentState];
19 - this.currentStateDiff = 0;
20 -
21 - // Configuration
22 - this.maxStateDiff = 24;
23 -};
24 -
25 -/* Methods */
26 -
27 -/**
28 - * Gets the index of the current state.
29 - *
30 - *
31 - */
32 -es.HistoryModel.prototype.getCurrentStateIndex = function() {
33 - return this.currentStateIndex;
34 -};
35 -
36 -/**
37 - * Gets the index of the current state.
38 - *
39 - *
40 - */
41 -es.HistoryModel.prototype.getCurrentStateSelection = function() {
42 - return this.currentState.getSelection();
43 -};
44 -
45 -/**
46 - * Gets the number of states available.
47 - *
48 - * @method
49 - */
50 -es.HistoryModel.prototype.getStateCount = function() {
51 - return this.states.length;
52 -};
53 -
54 -/**
55 - * Gets a copy of the list of states.
56 - *
57 - * @method
58 - * @param {Boolean} deep Whether to make a deep copy (can be slow)
59 - * @returns {Array[]} List of states, each a list of transactions
60 - */
61 -es.HistoryModel.prototype.getStates = function( deep ) {
62 - return deep ? es.copyArray( this.states ) : this.states.slice( 0 );
63 -};
64 -
65 -/**
66 - * Gets a copy of the list of transactions, which are not yet part of a state.
67 - *
68 - * @method
69 - * @param {Boolean} deep Whether to make a deep copy (can be slow)
70 - * @returns {es.TransactionModel[]} List of transactions
71 - */
72 -es.HistoryModel.prototype.getTransactions = function( deep ) {
73 - return deep ? es.copyArray( this.transactions ) : this.transactions.slice( 0 );
74 -};
75 -
76 -/**
77 - * Commits a transaction.
78 - *
79 - * Unless the accumulate option is used a state will be automatically pushed before committing
80 - * if the transaction is of a different type as the previous one in the transaction buffer, or if
81 - * the transaction would produce a content length difference beyond the configured maximum.
82 - *
83 - * @method
84 - * @param {es.TransactionModel} transaction Transaction to commit
85 - * @param {es.Range} [selection] Selection to use after the transaction has been applied
86 - * @param {Boolean} [accumulate] Prevent automatic state pushing
87 - */
88 -es.HistoryModel.prototype.commit = function( transaction, selection, accumulate ) {
89 - var transactionDiff = Math.abs( transaction.getLengthDiff() );
90 - // Unless we should intentionally accumulate transactions or this is the first one for this
91 - // state, automatically push state
92 - var transactionCount = this.currentState.getTransactionCount();
93 - if ( !accumulate && transactionCount ) {
94 - if (
95 - // If the transactions are of a different type
96 - this.currentState.getTransactions()[transactionCount - 1].type !== transaction.type ||
97 - // This transaction would make the state longer than the maximum length
98 - this.currentStateDiff + transactionDiff > this.maxStateDiff
99 - ) {
100 - this.pushState();
101 - }
102 - }
103 - this.currentState.pushTransaction( transaction );
104 - this.currentStateDiff += transactionDiff;
105 - // Apply transaction to the document
106 - this.doc.commit( transaction );
107 - // Emit a do event with the transaction that was just committed
108 - this.emit( 'do', transaction );
109 -};
110 -
111 -/**
112 - * Moves transactions in the buffer into a new state.
113 - *
114 - * @method
115 - */
116 -es.HistoryModel.prototype.pushState = function() {
117 - // If any transactions have been pushed since the last state push
118 - if ( this.currentState.getTransactionCount() ) {
119 - // If the current state is not the most recently added state
120 - if ( this.currentStateIndex < this.states.length - 1 ) {
121 - // Forget about states newer than the current one
122 - this.states.splice(
123 - this.currentStateIndex, this.states.length - this.currentStateIndex
124 - );
125 - }
126 - // Create a new current state
127 - this.currentState = new es.HistoryStateModel();
128 - // Add the new current state to the stack
129 - this.states.push( this.currentState );
130 - // Reset the state diff counter
131 - this.currentStateDiff = 0;
132 - // Move the current state index to the end (should be equivilant of ++)
133 - this.currentStateIndex = this.states.length - 1;
134 - }
135 - // Emit the completed
136 - this.emit( 'pushState', this.states[this.states.length - 1] );
137 -};
138 -
139 -/**
140 - *
141 - *
142 - * @method
143 - */
144 -es.HistoryModel.prototype.undo = function( steps ) {
145 - if ( steps === undefined ) {
146 - steps = 1;
147 - }
148 - // Stop undo just before the first state
149 - var previousStateIndex = this.currentStateIndex;
150 - this.currentStateIndex = Math.max( -1, this.currentStateIndex - steps );
151 - if ( previousStateIndex > this.currentStateIndex ) {
152 - for ( var i = previousStateIndex; i > this.currentStateIndex; i-- ) {
153 - // Apply transaction to the document
154 - var transactions = this.states[i].getTransactions();
155 - for ( var j = transactions.length - 1; j >= 0; j-- ) {
156 - this.doc.rollback( transactions[j] );
157 - }
158 - // Emit an undo event with the state to be rolled back
159 - this.emit( 'undo', this.states[i] );
160 - }
161 - }
162 -};
163 -
164 -/**
165 - *
166 - *
167 - * @method
168 - */
169 -es.HistoryModel.prototype.redo = function( steps ) {
170 - if ( steps === undefined ) {
171 - steps = 1;
172 - }
173 - // Stop redo at the last state
174 - var previousStateIndex = this.currentStateIndex;
175 - this.currentStateIndex = Math.min( this.states.length - 1, this.currentStateIndex + steps );
176 - if ( previousStateIndex < this.currentStateIndex ) {
177 - for ( var i = previousStateIndex + 1; i >= this.currentStateIndex; i++ ) {
178 - // Apply transaction to the document
179 - var transactions = this.states[i].getTransactions();
180 - for ( var j = 0; j < transactions.length; j++ ) {
181 - this.doc.commit( transactions[j] );
182 - }
183 - // Emit an undo event with the state to be rolled back
184 - this.emit( 'redo', this.states[i] );
185 - }
186 - }
187 -};
188 -
189 -/* Inheritance */
190 -
191 -es.extendClass( es.HistoryModel, es.EventEmitter );
Index: trunk/extensions/VisualEditor/modules/es/models/es.HistoryStateModel.js
@@ -1,31 +0,0 @@
2 -/**
3 - * Creates an es.HistoryStateModel object.
4 - *
5 - * @class
6 - * @constructor
7 - */
8 -es.HistoryStateModel = function() {
9 - this.transactions = [];
10 - this.selection = null;
11 -};
12 -
13 -/* Methods */
14 -
15 -es.HistoryStateModel.prototype.getSelection = function() {
16 - return this.selection;
17 -};
18 -
19 -es.HistoryStateModel.prototype.getTransactions = function() {
20 - return this.transactions;
21 -};
22 -
23 -es.HistoryStateModel.prototype.getTransactionCount = function() {
24 - return this.transactions.length;
25 -};
26 -
27 -es.HistoryStateModel.prototype.pushTransaction = function( transaction, selection ) {
28 - this.transactions.push( transaction );
29 - if ( selection !== undefined ) {
30 - this.selection = selection.clone();
31 - }
32 -};
Index: trunk/extensions/VisualEditor/modules/es/models/es.SurfaceModel.js
@@ -3,14 +3,207 @@
44 *
55 * @class
66 * @constructor
 7+ * @extends {es.EventEmitter}
78 * @param {es.DocumentModel} doc Document model to create surface for
89 */
910 es.SurfaceModel = function( doc ) {
 11+ // Inheritance
 12+ es.EventEmitter.call( this );
 13+
 14+ // Properties
1015 this.doc = doc;
 16+ this.selection = new es.Range();
 17+ this.states = [[]];
 18+ this.initializeState( this.states.length - 1 );
 19+
 20+ // Configuration
 21+ this.distanceLimit = 24;
 22+ this.lengthDifferenceLimit = 24;
1123 };
1224
1325 /* Methods */
1426
 27+es.SurfaceModel.prototype.initializeState = function( stateIndex ) {
 28+ if ( this.states[stateIndex] === undefined ) {
 29+ throw 'Invalid state index error. State index our of range: ' + stateIndex;
 30+ }
 31+ this.currentStateIndex = stateIndex;
 32+ this.currentState = this.states[stateIndex];
 33+ this.currentStateDistance = 0;
 34+ this.currentStateLengthDifference = 0;
 35+};
 36+
 37+/**
 38+ * Gets the document model of the surface.
 39+ *
 40+ * @method
 41+ * @returns {es.DocumentModel} Document model of the surface
 42+ */
1543 es.SurfaceModel.prototype.getDocument = function() {
1644 return this.doc;
1745 };
 46+
 47+/**
 48+ * Gets the selection for the current state.
 49+ *
 50+ * @method
 51+ * @returns {es.Range} Current state's selection
 52+ */
 53+es.SurfaceModel.prototype.getSelection = function() {
 54+ return this.selection;
 55+};
 56+
 57+/**
 58+ * Changes the selection.
 59+ *
 60+ * If changing the selection at a high frequency (such as while dragging) use the combine argument
 61+ * to avoid them being split up into multiple states.
 62+ *
 63+ * @method
 64+ * @param {es.Range} selection
 65+ * @param {Boolean} combine Whether to prevent this transaction from causing a state push
 66+ */
 67+es.SurfaceModel.prototype.select = function( selection, combine ) {
 68+ if ( !combine && this.shouldPushState( selection ) ) {
 69+ this.pushState();
 70+ }
 71+ var lastAction = this.states[this.states.length - 1];
 72+ if ( lastAction instanceof es.Range ) {
 73+ this.currentStateDistance += Math.abs(
 74+ selection.from - this.states[this.states.length - 1].from
 75+ );
 76+ }
 77+ this.selection = selection;
 78+ this.currentState.push( selection );
 79+ this.emit( 'select', selection );
 80+};
 81+
 82+/**
 83+ * Applies a series of transactions to the content data.
 84+ *
 85+ * If committing multiple transactions which are the result of a single user action and need to be
 86+ * part of a single state, use the combine argument for all but the last one to avoid them being
 87+ * split up into multple states.
 88+ *
 89+ * @method
 90+ * @param {es.TransactionModel} transactions Tranasction to apply to the document
 91+ * @param {Boolean} combine Whether to prevent this transaction from causing a state push
 92+ */
 93+es.SurfaceModel.prototype.transact = function( transaction, combine ) {
 94+ if ( !combine && this.shouldPushState( transaction ) ) {
 95+ this.pushState();
 96+ }
 97+ this.currentStateLengthDifference += transaction.getLengthDifference();
 98+ this.doc.commit( transaction );
 99+ this.currentState.push( transaction );
 100+ this.emit( 'transact', transaction );
 101+};
 102+
 103+/**
 104+ * Reverses one or more selections and transactions.
 105+ *
 106+ * @method
 107+ * @param {Integer} steps Number of steps to reverse
 108+ * @param {Boolean} soft Whether to consider selection states as steps
 109+ */
 110+es.SurfaceModel.prototype.undo = function( steps, soft ) {
 111+ // TODO: Implement me!
 112+ this.emit( 'undo'/*, transaction/selection*/ );
 113+};
 114+
 115+/**
 116+ * Repeats one or more selections and transactions.
 117+ *
 118+ * @method
 119+ * @param {Integer} steps Number of steps to repeat
 120+ * @param {Boolean} soft Whether to consider selection states as steps
 121+ */
 122+es.SurfaceModel.prototype.redo = function( steps, soft ) {
 123+ // TODO: Implement me!
 124+ this.emit( 'redo'/*, transaction/selection*/ );
 125+};
 126+
 127+/**
 128+ * Checks if it's an appropriate time to push the state.
 129+ *
 130+ * @method
 131+ * @returns {Boolean} Whether the state should be pushed
 132+ */
 133+es.SurfaceModel.prototype.shouldPushState = function( nextAction ) {
 134+ // Never push a new state if the current one is empty
 135+ if ( !this.currentState.length ) {
 136+ return false;
 137+ }
 138+ var lastAction = this.currentState[this.currentState.length - 1],
 139+ nextDirection,
 140+ lastDirection;
 141+ if (
 142+ // Check that types match
 143+ nextAction instanceof es.Range && lastAction instanceof es.Range
 144+ ) {
 145+ if (
 146+ // 2 or more select actions in a row are required to detect a direction
 147+ this.states.length >= 2 && this.states[this.states.length - 2] instanceof es.Range
 148+ ) {
 149+ // Check we haven't changed directions
 150+ lastDirection = this.states[this.states.length - 2].from - lastAction.from;
 151+ nextDirection = lastAction.from - nextAction.from;
 152+ if (
 153+ // Both movements are in the same direction
 154+ ( lastDirection < 0 && nextDirection < 0 ) ||
 155+ ( lastDirection > 0 && nextDirection > 0 )
 156+ ) {
 157+ // Check we are still within the distance threshold
 158+ if (
 159+ Math.abs( nextAction.from - lastAction.from ) + this.currentStateDistance <
 160+ this.distanceLimit
 161+ ) {
 162+ return false;
 163+ }
 164+ }
 165+ }
 166+ } else if (
 167+ // Check that types match
 168+ nextAction instanceof es.TransactionModel && lastAction instanceof es.TransactionModel
 169+ ) {
 170+ // Check if we've changed directions (insert vs remove)
 171+ lastLengthDifference = lastAction.getLengthDifference();
 172+ nextLengthDifference = nextAction.getLengthDifference();
 173+ if (
 174+ // Both movements are in the same direction
 175+ ( lastLengthDifference < 0 && nextLengthDifference < 0 ) ||
 176+ ( lastLengthDifference > 0 && nextLengthDifference > 0 )
 177+ ) {
 178+ // Check we are still within the length difference threshold
 179+ if (
 180+ nextLengthDifference + this.currentStateLengthDifference <
 181+ this.lengthDifferenceLimit
 182+ ) {
 183+ return false;
 184+ }
 185+ }
 186+ }
 187+ return true;
 188+};
 189+
 190+/**
 191+ * Removes any undone states and pushes a new state to the stack.
 192+ *
 193+ * @method
 194+ */
 195+es.SurfaceModel.prototype.pushState = function() {
 196+ // Automatically drop undone states - we are now moving in a new direction
 197+ if ( this.states[this.states.length - 1] !== this.currentState ) {
 198+ for ( var i = this.states.length - 1; i > this.currentStateIndex; i-- ) {
 199+ this.emit( 'popState', this.states.pop() );
 200+ }
 201+ }
 202+ // Push a new state to the stack
 203+ this.states.push( [] );
 204+ this.initializeState( this.states.length - 1 );
 205+ this.emit( 'pushState' );
 206+};
 207+
 208+/* Inheritance */
 209+
 210+es.extendClass( es.SurfaceModel, es.EventEmitter );
Index: trunk/extensions/VisualEditor/modules/es/views/es.SurfaceView.js
@@ -173,7 +173,7 @@
174174 } else if ( e.originalEvent.detail === 2 ) { // double click
175175 this.mouse.selectingMode = 2; // used in mouseMove handler
176176
177 - var wordRange = this.documentView.getModel().getWordBoundaries( offset );
 177+ var wordRange = this.model.getDocument().getWordBoundaries( offset );
178178 if( wordRange ) {
179179 this.selection = wordRange;
180180 this.mouse.selectedRange = this.selection.clone();
@@ -185,11 +185,11 @@
186186 var node = this.documentView.getNodeFromOffset( offset ),
187187 nodeOffset = this.documentView.getOffsetFromNode( node, false );
188188
189 - this.selection.from = this.documentView.getModel().getRelativeContentOffset(
 189+ this.selection.from = this.model.getDocument().getRelativeContentOffset(
190190 nodeOffset,
191191 1
192192 );
193 - this.selection.to = this.documentView.getModel().getRelativeContentOffset(
 193+ this.selection.to = this.model.getDocument().getRelativeContentOffset(
194194 nodeOffset + node.getElementLength(),
195195 -1
196196 );
@@ -220,7 +220,7 @@
221221 if ( this.mouse.selectingMode === 1 ) { // selection of chars
222222 this.selection.to = offset;
223223 } else if ( this.mouse.selectingMode === 2 ) { // selection of words
224 - var wordRange = this.documentView.getModel().getWordBoundaries( offset );
 224+ var wordRange = this.model.getDocument().getWordBoundaries( offset );
225225 if ( wordRange ) {
226226 if ( wordRange.to <= this.mouse.selectedRange.from ) {
227227 this.selection.from = wordRange.from;
@@ -238,14 +238,14 @@
239239 this.documentView.getNodeFromOffset( offset )
240240 );
241241 if ( nodeRange.to <= this.mouse.selectedRange.from ) {
242 - this.selection.from = this.documentView.getModel().getRelativeContentOffset(
 242+ this.selection.from = this.model.getDocument().getRelativeContentOffset(
243243 nodeRange.from,
244244 1
245245 );
246246 this.selection.to = this.mouse.selectedRange.to;
247247 } else {
248248 this.selection.from = this.mouse.selectedRange.from;
249 - this.selection.to = this.documentView.getModel().getRelativeContentOffset(
 249+ this.selection.to = this.model.getDocument().getRelativeContentOffset(
250250 nodeRange.to,
251251 -1
252252 );
@@ -408,12 +408,12 @@
409409 if ( this.selection.from === this.selection.to ) {
410410 if ( backspace ) {
411411 sourceOffset = this.selection.to;
412 - targetOffset = this.documentView.getModel().getRelativeContentOffset(
 412+ targetOffset = this.model.getDocument().getRelativeContentOffset(
413413 sourceOffset,
414414 -1
415415 );
416416 } else {
417 - sourceOffset = this.documentView.getModel().getRelativeContentOffset(
 417+ sourceOffset = this.model.getDocument().getRelativeContentOffset(
418418 this.selection.to,
419419 1
420420 );
@@ -427,22 +427,22 @@
428428 sourceSplitableNode = es.DocumentViewNode.getSplitableNode( sourceNode );
429429 targetSplitableNode = es.DocumentViewNode.getSplitableNode( targetNode );
430430 }
431 -
 431+
432432 this.selection.from = this.selection.to = targetOffset;
433433 this.showCursor();
434 -
 434+
435435 if ( sourceNode === targetNode ||
436436 ( typeof sourceSplitableNode !== 'undefined' &&
437437 sourceSplitableNode.getParent() === targetSplitableNode.getParent() ) ) {
438 - tx = this.documentView.getModel().prepareRemoval(
 438+ tx = this.model.getDocument().prepareRemoval(
439439 new es.Range( targetOffset, sourceOffset )
440440 );
441 - this.documentView.getModel().commit( tx );
 441+ this.model.transact( tx );
442442 } else {
443 - tx = this.documentView.getModel().prepareInsertion(
 443+ tx = this.model.getDocument().prepareInsertion(
444444 targetOffset, sourceNode.model.getContent()
445445 );
446 - this.documentView.getModel().commit( tx );
 446+ this.model.transact( tx );
447447
448448 var nodeToDelete = sourceNode;
449449 es.DocumentNode.traverseUpstream( nodeToDelete, function( node ) {
@@ -455,13 +455,13 @@
456456 var range = new es.Range();
457457 range.from = this.documentView.getOffsetFromNode( nodeToDelete, false );
458458 range.to = range.from + nodeToDelete.getElementLength();
459 - tx = this.documentView.getModel().prepareRemoval( range );
460 - this.documentView.getModel().commit( tx );
 459+ tx = this.model.getDocument().prepareRemoval( range );
 460+ this.model.transact( tx );
461461 }
462462 } else {
463463 // selection removal
464 - tx = this.documentView.getModel().prepareRemoval( this.selection );
465 - this.documentView.getModel().commit( tx );
 464+ tx = this.model.getDocument().prepareRemoval( this.selection );
 465+ this.model.transact( tx );
466466 this.documentView.clearSelection();
467467 this.selection.from = this.selection.to = this.selection.start;
468468 this.showCursor();
@@ -483,7 +483,7 @@
484484 nodeOffset + node.getElementLength(),
485485 [ { 'type': 'paragraph' }, { 'type': '/paragraph' } ]
486486 );
487 - this.documentView.getModel().commit( tx );
 487+ this.model.transact( tx );
488488 this.selection.from = this.selection.to = nodeOffset + node.getElementLength() + 1;
489489 this.showCursor();
490490 } else {
@@ -510,9 +510,9 @@
511511 splitable = es.DocumentView.splitRules[ elementType ].self;
512512 } );
513513 var tx = this.documentView.model.prepareInsertion( this.selection.to, stack );
514 - this.documentView.getModel().commit( tx );
 514+ this.model.transact( tx );
515515 this.selection.from = this.selection.to =
516 - this.documentView.getModel().getRelativeContentOffset( this.selection.to, 1 );
 516+ this.model.getDocument().getRelativeContentOffset( this.selection.to, 1 );
517517 this.showCursor();
518518 }
519519 };
@@ -523,14 +523,14 @@
524524 if ( val.length > 0 ) {
525525 var tx;
526526 if ( this.selection.from != this.selection.to ) {
527 - tx = this.documentView.getModel().prepareRemoval( this.selection );
528 - this.documentView.getModel().commit( tx );
 527+ tx = this.model.getDocument().prepareRemoval( this.selection );
 528+ this.model.transact( tx );
529529 this.documentView.clearSelection();
530530 this.selection.from = this.selection.to =
531531 Math.min( this.selection.from, this.selection.to );
532532 }
533 - tx = this.documentView.getModel().prepareInsertion( this.selection.from, val.split('') );
534 - this.documentView.getModel().commit( tx );
 533+ tx = this.model.getDocument().prepareInsertion( this.selection.from, val.split('') );
 534+ this.model.transact( tx );
535535 this.selection.from += val.length;
536536 this.selection.to += val.length;
537537 this.showCursor();
@@ -560,12 +560,12 @@
561561 } else {
562562 offset = direction === 'left' ? this.selection.start : this.selection.end;
563563 }
564 - to = this.documentView.getModel().getRelativeContentOffset(
 564+ to = this.model.getDocument().getRelativeContentOffset(
565565 offset,
566566 direction === 'left' ? -1 : 1
567567 );
568568 if ( unit === 'word' ) {
569 - var wordRange = this.documentView.getModel().getWordBoundaries(
 569+ var wordRange = this.model.getDocument().getWordBoundaries(
570570 direction === 'left' ? to : offset
571571 );
572572 if ( wordRange ) {
@@ -575,7 +575,7 @@
576576 break;
577577 case 'line':
578578 offset = this.cursor.initialBias ?
579 - this.documentView.getModel().getRelativeContentOffset(
 579+ this.model.getDocument().getRelativeContentOffset(
580580 this.selection.to,
581581 -1) :
582582 this.selection.to;
@@ -589,7 +589,7 @@
590590 switch ( unit ) {
591591 case 'unit':
592592 var toNode = null;
593 - this.documentView.getModel().traverseLeafNodes(
 593+ this.model.getDocument().traverseLeafNodes(
594594 function( node ) {
595595 if ( toNode === null) {
596596 toNode = node;
@@ -601,7 +601,7 @@
602602 this.documentView.getNodeFromOffset( this.selection.to, false ).getModel(),
603603 direction === 'up' ? true : false
604604 );
605 - to = this.documentView.getModel().getOffsetFromNode( toNode, false ) + 1;
 605+ to = this.model.getDocument().getOffsetFromNode( toNode, false ) + 1;
606606 break;
607607 case 'char':
608608 /*

Status & tagging log