r103517 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r103516‎ | r103517 | r103518 >
Date:22:44, 17 November 2011
Author:tparscal
Status:deferred
Tags:
Comment:
Initial checkin of new es.HistoryModel (needs tests)
Modified paths:
  • /trunk/extensions/VisualEditor/demo/index.html (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/models/es.HistoryModel.js (added) (history)
  • /trunk/extensions/VisualEditor/tests/es/index.html (modified) (history)

Diff [purge]

Index: trunk/extensions/VisualEditor/tests/es/index.html
@@ -31,6 +31,7 @@
3232
3333 <!-- Models -->
3434 <script src="../../modules/es/models/es.DocumentModel.js"></script>
 35+ <script src="../../modules/es/models/es.HistoryModel.js"></script>
3536 <script src="../../modules/es/models/es.ListItemModel.js"></script>
3637 <script src="../../modules/es/models/es.ListModel.js"></script>
3738 <script src="../../modules/es/models/es.ParagraphModel.js"></script>
Index: trunk/extensions/VisualEditor/demo/index.html
@@ -81,6 +81,7 @@
8282 <!-- Models -->
8383 <script src="../modules/es/models/es.SurfaceModel.js"></script>
8484 <script src="../modules/es/models/es.DocumentModel.js"></script>
 85+ <script src="../modules/es/models/es.HistoryModel.js"></script>
8586 <script src="../modules/es/models/es.ParagraphModel.js"></script>
8687 <script src="../modules/es/models/es.PreModel.js"></script>
8788 <script src="../modules/es/models/es.ListModel.js"></script>
Index: trunk/extensions/VisualEditor/modules/es/models/es.HistoryModel.js
@@ -0,0 +1,170 @@
 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.states = [];
 17+ this.currentStateIndex = -1;
 18+ this.transactions = [];
 19+ this.transactionsDiff = 0;
 20+
 21+ // Configuration
 22+ this.maxTransactionsDiff = 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 number of states available.
 38+ *
 39+ * @method
 40+ */
 41+es.HistoryModel.prototype.getStateCount = function() {
 42+ return this.states.length;
 43+};
 44+
 45+/**
 46+ * Gets a copy of the list of states.
 47+ *
 48+ * @method
 49+ * @param {Boolean} deep Whether to make a deep copy (can be slow)
 50+ * @returns {Array[]} List of states, each a list of transactions
 51+ */
 52+es.HistoryModel.prototype.getStates = function( deep ) {
 53+ return deep ? es.copyArray( this.states ) : this.states.slice( 0 );
 54+};
 55+
 56+/**
 57+ * Gets a copy of the list of transactions, which are not yet part of a state.
 58+ *
 59+ * @method
 60+ * @param {Boolean} deep Whether to make a deep copy (can be slow)
 61+ * @returns {es.TransactionModel[]} List of transactions
 62+ */
 63+es.HistoryModel.prototype.getTransactions = function( deep ) {
 64+ return deep ? es.copyArray( this.transactions ) : this.transactions.slice( 0 );
 65+};
 66+
 67+/**
 68+ * Commits a transaction.
 69+ *
 70+ * Unless the accumulate option is used a state will be automatically pushed before committing
 71+ * if the transaction is of a different type as the previous one in the transaction buffer, or if
 72+ * the transaction would produce a content length difference beyond the configured maximum.
 73+ *
 74+ * @method
 75+ * @param {es.TransactionModel} transaction Transaction to commit
 76+ * @param {Boolean} accumulate Prevent automatic state pushing
 77+ */
 78+es.HistoryModel.prototype.commit = function( transaction, accumulate ) {
 79+ var absLengthDiff = Math.abs( transaction.getLengthDiff() );
 80+ // Unless we should intentionally accumulate transactions or this is the first one for this
 81+ // state, automatically push state
 82+ if ( !accumulate && !this.transactions.length ) {
 83+ if (
 84+ // If the transactions are of a different type
 85+ this.transactions[this.transactions.length].type !== transaction.type ||
 86+ // This transaction would make the state longer than the maximum length
 87+ this.transactionsDiff + absLengthDiff > this.maxTransactionsDiff
 88+ ) {
 89+ this.pushState();
 90+ }
 91+ }
 92+ this.transactions.push( transaction );
 93+ this.transactionsDiff += absLengthDiff;
 94+ // Apply transaction to the document
 95+ this.doc.commit( transaction );
 96+ // Emit a do event with the transaction that was just committed
 97+ this.emit( 'do', transaction );
 98+};
 99+
 100+/**
 101+ * Moves transactions in the buffer into a new state.
 102+ *
 103+ * @method
 104+ */
 105+es.HistoryModel.prototype.pushState = function() {
 106+ // If any transactions have been pushed since the last state push
 107+ if ( this.transactions.length ) {
 108+ // If the current state is not the most recently added state
 109+ if ( this.currentStateIndex < this.states.length - 1 ) {
 110+ // Forget about states newer than the current one
 111+ this.states.splice(
 112+ this.currentStateIndex, this.states.length - this.currentStateIndex
 113+ );
 114+ }
 115+ // Add accumulated transactions as a state
 116+ this.states.push( this.transactions );
 117+ // Clear the transaction buffer
 118+ this.transactions = [];
 119+ this.transactionsDiff = 0;
 120+ // Move the current state forward
 121+ this.currentStateIndex++;
 122+ }
 123+};
 124+
 125+/**
 126+ *
 127+ *
 128+ * @method
 129+ */
 130+es.HistoryModel.prototype.undo = function( steps ) {
 131+ if ( steps === undefined ) {
 132+ steps = 1;
 133+ }
 134+ // Apply transactions in the buffer
 135+ this.pushState();
 136+ // Stop undo just before the first state
 137+ var previousStateIndex = this.currentStateIndex;
 138+ this.currentStateIndex = Math.max( -1, this.currentStateIndex - steps );
 139+ if ( previousStateIndex > this.currentStateIndex ) {
 140+ for ( var i = previousStateIndex; i > this.currentStateIndex; i-- ) {
 141+ // Apply transaction to the document
 142+ this.doc.rollback( this.states[i] );
 143+ // Emit an undo event with the state to be rolled back
 144+ this.emit( 'undo', this.states[i] );
 145+ }
 146+ }
 147+};
 148+
 149+/**
 150+ *
 151+ *
 152+ * @method
 153+ */
 154+es.HistoryModel.prototype.redo = function( steps ) {
 155+ if ( steps === undefined ) {
 156+ steps = 1;
 157+ }
 158+ // Apply transactions in the buffer
 159+ this.pushState();
 160+ // Stop redo at the last state
 161+ var previousStateIndex = this.currentStateIndex;
 162+ this.currentStateIndex = Math.min( this.states.length - 1, this.currentStateIndex + steps );
 163+ if ( previousStateIndex < this.currentStateIndex ) {
 164+ for ( var i = previousStateIndex + 1; i >= this.currentStateIndex; i++ ) {
 165+ // Apply transaction to the document
 166+ this.doc.rollback( this.states[i] );
 167+ // Emit an undo event with the state to be rolled back
 168+ this.emit( 'redo', this.states[i] );
 169+ }
 170+ }
 171+};

Status & tagging log