https://www.mediawiki.org/wiki/Special:Code/MediaWiki/103517

Revision: 103517
Author:   tparscal
Date:     2011-11-17 22:44:11 +0000 (Thu, 17 Nov 2011)
Log Message:
-----------
Initial checkin of new es.HistoryModel (needs tests)

Modified Paths:
--------------
    trunk/extensions/VisualEditor/demo/index.html
    trunk/extensions/VisualEditor/tests/es/index.html

Added Paths:
-----------
    trunk/extensions/VisualEditor/modules/es/models/es.HistoryModel.js

Modified: trunk/extensions/VisualEditor/demo/index.html
===================================================================
--- trunk/extensions/VisualEditor/demo/index.html       2011-11-17 22:42:18 UTC 
(rev 103516)
+++ trunk/extensions/VisualEditor/demo/index.html       2011-11-17 22:44:11 UTC 
(rev 103517)
@@ -81,6 +81,7 @@
                <!-- Models -->
                <script src="../modules/es/models/es.SurfaceModel.js"></script>
                <script src="../modules/es/models/es.DocumentModel.js"></script>
+               <script src="../modules/es/models/es.HistoryModel.js"></script>
                <script 
src="../modules/es/models/es.ParagraphModel.js"></script>
                <script src="../modules/es/models/es.PreModel.js"></script>
                <script src="../modules/es/models/es.ListModel.js"></script>

Added: trunk/extensions/VisualEditor/modules/es/models/es.HistoryModel.js
===================================================================
--- trunk/extensions/VisualEditor/modules/es/models/es.HistoryModel.js          
                (rev 0)
+++ trunk/extensions/VisualEditor/modules/es/models/es.HistoryModel.js  
2011-11-17 22:44:11 UTC (rev 103517)
@@ -0,0 +1,170 @@
+/**
+ * Creates an es.HistoryModel object.
+ * 
+ * @class
+ * @constructor
+ * @extends {es.EventEmitter}
+ * @param {es.DocumentModel} doc Document being tracked and modified
+ */
+es.HistoryModel = function( doc ) {
+       // Inheritance
+       es.EventEmitter.call( this );
+
+       // Properties
+       this.doc = doc;
+       this.states = [];
+       this.currentStateIndex = -1;
+       this.transactions = [];
+       this.transactionsDiff = 0;
+
+       // Configuration
+       this.maxTransactionsDiff = 24;
+};
+
+/* Methods */
+
+/**
+ * Gets the index of the current state.
+ * 
+ * 
+ */
+es.HistoryModel.prototype.getCurrentStateIndex = function() {
+       return this.currentStateIndex;
+};
+
+/**
+ * Gets the number of states available.
+ * 
+ * @method
+ */
+es.HistoryModel.prototype.getStateCount = function() {
+       return this.states.length;
+};
+
+/**
+ * Gets a copy of the list of states.
+ * 
+ * @method
+ * @param {Boolean} deep Whether to make a deep copy (can be slow)
+ * @returns {Array[]} List of states, each a list of transactions
+ */
+es.HistoryModel.prototype.getStates = function( deep ) {
+       return deep ? es.copyArray( this.states ) : this.states.slice( 0 );
+};
+
+/**
+ * Gets a copy of the list of transactions, which are not yet part of a state.
+ * 
+ * @method
+ * @param {Boolean} deep Whether to make a deep copy (can be slow)
+ * @returns {es.TransactionModel[]} List of transactions
+ */
+es.HistoryModel.prototype.getTransactions = function( deep ) {
+       return deep ? es.copyArray( this.transactions ) : 
this.transactions.slice( 0 );
+};
+
+/**
+ * Commits a transaction.
+ * 
+ * Unless the accumulate option is used a state will be automatically pushed 
before committing
+ * if the transaction is of a different type as the previous one in the 
transaction buffer, or if
+ * the transaction would produce a content length difference beyond the 
configured maximum.
+ * 
+ * @method
+ * @param {es.TransactionModel} transaction Transaction to commit
+ * @param {Boolean} accumulate Prevent automatic state pushing
+ */
+es.HistoryModel.prototype.commit = function( transaction, accumulate ) {
+       var absLengthDiff = Math.abs( transaction.getLengthDiff() );
+       // Unless we should intentionally accumulate transactions or this is 
the first one for this
+       // state, automatically push state
+       if ( !accumulate && !this.transactions.length ) {
+               if (
+                       // If the transactions are of a different type
+                       this.transactions[this.transactions.length].type !== 
transaction.type ||
+                       // This transaction would make the state longer than 
the maximum length
+                       this.transactionsDiff + absLengthDiff > 
this.maxTransactionsDiff
+               ) {
+                       this.pushState();
+               }
+       }
+       this.transactions.push( transaction );
+       this.transactionsDiff += absLengthDiff;
+       // Apply transaction to the document
+       this.doc.commit( transaction );
+       // Emit a do event with the transaction that was just committed
+       this.emit( 'do', transaction );
+};
+
+/**
+ * Moves transactions in the buffer into a new state.
+ * 
+ * @method
+ */
+es.HistoryModel.prototype.pushState = function() {
+       // If any transactions have been pushed since the last state push
+       if ( this.transactions.length ) {
+               // If the current state is not the most recently added state
+               if ( this.currentStateIndex < this.states.length - 1 ) {
+                       // Forget about states newer than the current one
+                       this.states.splice(
+                               this.currentStateIndex, this.states.length - 
this.currentStateIndex
+                       );
+               }
+               // Add accumulated transactions as a state
+               this.states.push( this.transactions );
+               // Clear the transaction buffer
+               this.transactions = [];
+               this.transactionsDiff = 0;
+               // Move the current state forward
+               this.currentStateIndex++;
+       }
+};
+
+/**
+ * 
+ * 
+ * @method
+ */
+es.HistoryModel.prototype.undo = function( steps ) {
+       if ( steps === undefined ) {
+               steps = 1; 
+       }
+       // Apply transactions in the buffer
+       this.pushState();
+       // Stop undo just before the first state
+       var previousStateIndex = this.currentStateIndex;
+       this.currentStateIndex = Math.max( -1, this.currentStateIndex - steps );
+       if ( previousStateIndex > this.currentStateIndex ) {
+               for ( var i = previousStateIndex; i > this.currentStateIndex; 
i-- ) {
+                       // Apply transaction to the document
+                       this.doc.rollback( this.states[i] );
+                       // Emit an undo event with the state to be rolled back
+                       this.emit( 'undo', this.states[i] );
+               }
+       }
+};
+
+/**
+ * 
+ * 
+ * @method
+ */
+es.HistoryModel.prototype.redo = function( steps ) {
+       if ( steps === undefined ) {
+               steps = 1; 
+       }
+       // Apply transactions in the buffer
+       this.pushState();
+       // Stop redo at the last state
+       var previousStateIndex = this.currentStateIndex;
+       this.currentStateIndex = Math.min( this.states.length - 1, 
this.currentStateIndex + steps );
+       if ( previousStateIndex < this.currentStateIndex ) {
+               for ( var i = previousStateIndex + 1; i >= 
this.currentStateIndex; i++ ) {
+                       // Apply transaction to the document
+                       this.doc.rollback( this.states[i] );
+                       // Emit an undo event with the state to be rolled back
+                       this.emit( 'redo', this.states[i] );
+               }
+       }
+};

Modified: trunk/extensions/VisualEditor/tests/es/index.html
===================================================================
--- trunk/extensions/VisualEditor/tests/es/index.html   2011-11-17 22:42:18 UTC 
(rev 103516)
+++ trunk/extensions/VisualEditor/tests/es/index.html   2011-11-17 22:44:11 UTC 
(rev 103517)
@@ -31,6 +31,7 @@
 
                <!-- Models -->
                <script 
src="../../modules/es/models/es.DocumentModel.js"></script>
+               <script 
src="../../modules/es/models/es.HistoryModel.js"></script>
                <script 
src="../../modules/es/models/es.ListItemModel.js"></script>
                <script src="../../modules/es/models/es.ListModel.js"></script>
                <script 
src="../../modules/es/models/es.ParagraphModel.js"></script>


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to