wp/wp-admin/js/revisions.js
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
--- a/wp/wp-admin/js/revisions.js	Mon Jun 08 16:11:51 2015 +0000
+++ b/wp/wp-admin/js/revisions.js	Tue Jun 09 03:35:32 2015 +0200
@@ -1,19 +1,35 @@
+/* global isRtl */
+/**
+ * @file Revisions interface functions, Backbone classes and
+ * the revisions.php document.ready bootstrap.
+ *
+ */
+
 window.wp = window.wp || {};
 
 (function($) {
 	var revisions;
-
+	/**
+	 * Expose the module in window.wp.revisions.
+	 */
 	revisions = wp.revisions = { model: {}, view: {}, controller: {} };
 
-	// Link settings.
-	revisions.settings = _.isUndefined( _wpRevisionsSettings ) ? {} : _wpRevisionsSettings;
+	// Link post revisions data served from the back-end.
+	revisions.settings = window._wpRevisionsSettings || {};
 
 	// For debugging
 	revisions.debug = false;
 
+	/**
+	 * wp.revisions.log
+	 *
+	 * A debugging utility for revisions. Works only when a
+	 * debugĀ flag is on and the browser supports it.
+	 */
 	revisions.log = function() {
-		if ( window.console && revisions.debug )
-			console.log.apply( console, arguments );
+		if ( window.console && revisions.debug ) {
+			window.console.log.apply( window.console, arguments );
+		}
 	};
 
 	// Handy functions to help with positioning
@@ -33,16 +49,6 @@
 		});
 	};
 
-	// wp_localize_script transforms top-level numbers into strings. Undo that.
-	if ( revisions.settings.to )
-		revisions.settings.to = parseInt( revisions.settings.to, 10 );
-	if ( revisions.settings.from )
-		revisions.settings.from = parseInt( revisions.settings.from, 10 );
-
-	// wp_localize_script does not allow for top-level booleans. Fix that.
-	if ( revisions.settings.compareTwoMode )
-		revisions.settings.compareTwoMode = revisions.settings.compareTwoMode === '1';
-
 	/**
 	 * ========================================================================
 	 * MODELS
@@ -68,13 +74,13 @@
 			this.listenTo( this.frame, 'change:compareTwoMode', this.updateMode );
 
 			// Listen for internal changes
-			this.listenTo( this, 'change:from', this.handleLocalChanges );
-			this.listenTo( this, 'change:to', this.handleLocalChanges );
-			this.listenTo( this, 'change:compareTwoMode', this.updateSliderSettings );
-			this.listenTo( this, 'update:revisions', this.updateSliderSettings );
+			this.on( 'change:from', this.handleLocalChanges );
+			this.on( 'change:to', this.handleLocalChanges );
+			this.on( 'change:compareTwoMode', this.updateSliderSettings );
+			this.on( 'update:revisions', this.updateSliderSettings );
 
 			// Listen for changes to the hovered revision
-			this.listenTo( this, 'change:hoveredRevision', this.hoverRevision );
+			this.on( 'change:hoveredRevision', this.hoverRevision );
 
 			this.set({
 				max:   this.revisions.length - 1,
@@ -130,8 +136,9 @@
 		// Receives revisions changes from outside the model
 		receiveRevisions: function( from, to ) {
 			// Bail if nothing changed
-			if ( this.get('from') === from && this.get('to') === to )
+			if ( this.get('from') === from && this.get('to') === to ) {
 				return;
+			}
 
 			this.set({ from: from, to: to }, { silent: true });
 			this.trigger( 'update:revisions', from, to );
@@ -173,6 +180,11 @@
 
 	revisions.model.Revision = Backbone.Model.extend({});
 
+	/**
+	 * wp.revisions.model.Revisions
+	 *
+	 * A collection of post revisions.
+	 */
 	revisions.model.Revisions = Backbone.Collection.extend({
 		model: revisions.model.Revision,
 
@@ -183,15 +195,17 @@
 		next: function( revision ) {
 			var index = this.indexOf( revision );
 
-			if ( index !== -1 && index !== this.length - 1 )
+			if ( index !== -1 && index !== this.length - 1 ) {
 				return this.at( index + 1 );
+			}
 		},
 
 		prev: function( revision ) {
 			var index = this.indexOf( revision );
 
-			if ( index !== -1 && index !== 0 )
+			if ( index !== -1 && index !== 0 ) {
 				return this.at( index - 1 );
+			}
 		}
 	});
 
@@ -202,7 +216,7 @@
 	});
 
 	revisions.model.Diff = Backbone.Model.extend({
-		initialize: function( attributes, options ) {
+		initialize: function() {
 			var fields = this.get('fields');
 			this.unset('fields');
 
@@ -215,18 +229,19 @@
 			_.bindAll( this, 'getClosestUnloaded' );
 			this.loadAll = _.once( this._loadAll );
 			this.revisions = options.revisions;
+			this.postId = options.postId;
 			this.requests  = {};
 		},
 
 		model: revisions.model.Diff,
 
 		ensure: function( id, context ) {
-			var diff     = this.get( id );
-			var request  = this.requests[ id ];
-			var deferred = $.Deferred();
-			var ids      = {};
-			var from     = id.split(':')[0];
-			var to       = id.split(':')[1];
+			var diff     = this.get( id ),
+				request  = this.requests[ id ],
+				deferred = $.Deferred(),
+				ids      = {},
+				from     = id.split(':')[0],
+				to       = id.split(':')[1];
 			ids[id] = true;
 
 			wp.revisions.log( 'ensure', id );
@@ -239,11 +254,13 @@
 				this.trigger( 'ensure:load', ids, from, to, deferred.promise() );
 				_.each( ids, _.bind( function( id ) {
 					// Remove anything that has an ongoing request
-					if ( this.requests[ id ] )
+					if ( this.requests[ id ] ) {
 						delete ids[ id ];
+					}
 					// Remove anything we already have
-					if ( this.get( id ) )
+					if ( this.get( id ) ) {
 						delete ids[ id ];
+					}
 				}, this ) );
 				if ( ! request ) {
 					// Always include the ID that started this ensure
@@ -274,8 +291,8 @@
 		},
 
 		_loadAll: function( allRevisionIds, centerId, num ) {
-			var self = this, deferred = $.Deferred();
-			diffs = _.first( this.getClosestUnloaded( allRevisionIds, centerId ), num );
+			var self = this, deferred = $.Deferred(),
+				diffs = _.first( this.getClosestUnloaded( allRevisionIds, centerId ), num );
 			if ( _.size( diffs ) > 0 ) {
 				this.load( diffs ).done( function() {
 					self._loadAll( allRevisionIds, centerId, num ).done( function() {
@@ -299,7 +316,7 @@
 		load: function( comparisons ) {
 			wp.revisions.log( 'load', comparisons );
 			// Our collection should only ever grow, never shrink, so remove: false
-			return this.fetch({ data: { compare: comparisons }, remove: false }).done( function(){
+			return this.fetch({ data: { compare: comparisons }, remove: false }).done( function() {
 				wp.revisions.log( 'load:complete', comparisons );
 			});
 		},
@@ -310,11 +327,11 @@
 				options.context = this;
 				options.data = _.extend( options.data || {}, {
 					action: 'get-revision-diffs',
-					post_id: revisions.settings.postId
+					post_id: this.postId
 				});
 
-				var deferred = wp.ajax.send( options );
-				var requests = this.requests;
+				var deferred = wp.ajax.send( options ),
+					requests = this.requests;
 
 				// Record that we're requesting each diff.
 				if ( options.data.compare ) {
@@ -342,6 +359,17 @@
 	});
 
 
+	/**
+	 * wp.revisions.model.FrameState
+	 *
+	 * The frame state.
+	 *
+	 * @see wp.revisions.view.Frame
+	 *
+	 * @param {object}                    attributes        Model attributes - none are required.
+	 * @param {object}                    options           Options for the model.
+	 * @param {revisions.model.Revisions} options.revisions A collection of revisions.
+	 */
 	revisions.model.FrameState = Backbone.Model.extend({
 		defaults: {
 			loading: false,
@@ -350,16 +378,19 @@
 		},
 
 		initialize: function( attributes, options ) {
-			var properties = {};
-
+			var state = this.get( 'initialDiffState' );
 			_.bindAll( this, 'receiveDiff' );
 			this._debouncedEnsureDiff = _.debounce( this._ensureDiff, 200 );
 
 			this.revisions = options.revisions;
-			this.diffs = new revisions.model.Diffs( [], { revisions: this.revisions });
 
-			// Set the initial diffs collection provided through the settings
-			this.diffs.set( revisions.settings.diffData );
+			this.diffs = new revisions.model.Diffs( [], {
+				revisions: this.revisions,
+				postId: this.get( 'postId' )
+			} );
+
+			// Set the initial diffs collection.
+			this.diffs.set( this.get( 'diffData' ) );
 
 			// Set up internal listeners
 			this.listenTo( this, 'change:from', this.changeRevisionHandler );
@@ -369,12 +400,13 @@
 			this.listenTo( this.diffs, 'ensure:load', this.updateLoadingStatus );
 			this.listenTo( this, 'update:diff', this.updateLoadingStatus );
 
-			// Set the initial revisions, baseUrl, and mode as provided through settings
-			properties.to = this.revisions.get( revisions.settings.to );
-			properties.from = this.revisions.get( revisions.settings.from );
-			properties.compareTwoMode = revisions.settings.compareTwoMode;
-			properties.baseUrl = revisions.settings.baseUrl;
-			this.set( properties );
+			// Set the initial revisions, baseUrl, and mode as provided through attributes.
+
+			this.set( {
+				to : this.revisions.get( state.to ),
+				from : this.revisions.get( state.from ),
+				compareTwoMode : state.compareTwoMode
+			} );
 
 			// Start the router if browser supports History API
 			if ( window.history && window.history.pushState ) {
@@ -389,11 +421,23 @@
 		},
 
 		changeMode: function( model, value ) {
-			// If we were on the first revision before switching, we have to bump them over one
-			if ( value && 0 === this.revisions.indexOf( this.get('to') ) ) {
+			var toIndex = this.revisions.indexOf( this.get( 'to' ) );
+
+			// If we were on the first revision before switching to two-handled mode,
+			// bump the 'to' position over one
+			if ( value && 0 === toIndex ) {
 				this.set({
-					from: this.revisions.at(0),
-					to: this.revisions.at(1)
+					from: this.revisions.at( toIndex ),
+					to:   this.revisions.at( toIndex + 1 )
+				});
+			}
+
+			// When switching back to single-handled mode, reset 'from' model to
+			// one position before the 'to' model
+			if ( ! value && 0 !== toIndex ) { // '! value' means switching to single-handled mode
+				this.set({
+					from: this.revisions.at( toIndex - 1 ),
+					to:   this.revisions.at( toIndex )
 				});
 			}
 		},
@@ -423,8 +467,9 @@
 			diffId = ( from ? from.id : 0 ) + ':' + to.id;
 
 			// Check if we're actually changing the diff id.
-			if ( this._diffId === diffId )
+			if ( this._diffId === diffId ) {
 				return $.Deferred().reject().promise();
+			}
 
 			this._diffId = diffId;
 			this.trigger( 'update:revisions', from, to );
@@ -448,7 +493,7 @@
 
 		// A simple wrapper around `updateDiff` to prevent the change event's
 		// parameters from being passed through.
-		changeRevisionHandler: function( model, value, options ) {
+		changeRevisionHandler: function() {
 			this.updateDiff();
 		},
 
@@ -476,7 +521,14 @@
 	 * ========================================================================
 	 */
 
-	// The frame view. This contains the entire page.
+	/**
+	 * wp.revisions.view.Frame
+	 *
+	 * Top level frame that orchestrates the revisions experience.
+	 *
+	 * @param {object}                     options       The options hash for the view.
+	 * @param {revisions.model.FrameState} options.model The frame state model.
+	 */
 	revisions.view.Frame = wp.Backbone.View.extend({
 		className: 'revisions',
 		template: wp.template('revisions-frame'),
@@ -523,8 +575,13 @@
 		}
 	});
 
-	// The control view.
-	// This contains the revision slider, previous/next buttons, the meta info and the compare checkbox.
+	/**
+	 * wp.revisions.view.Controls
+	 *
+	 * The controls view.
+	 *
+	 * Contains the revision slider, previous/next buttons, the meta info and the compare checkbox.
+	 */
 	revisions.view.Controls = wp.Backbone.View.extend({
 		className: 'revisions-controls',
 
@@ -545,10 +602,10 @@
 			var slider = new revisions.model.Slider({
 				frame: this.model,
 				revisions: this.model.revisions
-			});
+			}),
 
 			// Prep the tooltip model
-			var tooltip = new revisions.model.Tooltip({
+			tooltip = new revisions.model.Tooltip({
 				frame: this.model,
 				revisions: this.model.revisions,
 				slider: slider
@@ -579,10 +636,10 @@
 			this.top = this.$el.offset().top;
 			this.window = $(window);
 			this.window.on( 'scroll.wp.revisions', {controls: this}, function(e) {
-				var controls = e.data.controls;
-				var container = controls.$el.parent();
-				var scrolled = controls.window.scrollTop();
-				var frame = controls.views.parent;
+				var controls  = e.data.controls,
+					container = controls.$el.parent(),
+					scrolled  = controls.window.scrollTop(),
+					frame     = controls.views.parent;
 
 				if ( scrolled >= controls.top ) {
 					if ( ! frame.$el.hasClass('pinned') ) {
@@ -724,8 +781,9 @@
 		},
 
 		ready: function() {
-			if ( this.model.revisions.length < 3 )
+			if ( this.model.revisions.length < 3 ) {
 				$('.revision-toggle-compare-mode').hide();
+			}
 		},
 
 		updateCompareTwoMode: function() {
@@ -733,7 +791,7 @@
 		},
 
 		// Toggle the compare two mode feature when the compare two checkbox is checked.
-		compareTwoToggle: function( event ) {
+		compareTwoToggle: function() {
 			// Activate compare two mode?
 			this.model.set({ compareTwoMode: $('.compare-two-revisions').prop('checked') });
 		}
@@ -745,23 +803,30 @@
 		className: 'revisions-tooltip',
 		template: wp.template('revisions-meta'),
 
-		initialize: function( options ) {
+		initialize: function() {
 			this.listenTo( this.model, 'change:offset', this.render );
 			this.listenTo( this.model, 'change:hovering', this.toggleVisibility );
 			this.listenTo( this.model, 'change:scrubbing', this.toggleVisibility );
 		},
 
 		prepare: function() {
-			if ( _.isNull( this.model.get('revision') ) )
+			if ( _.isNull( this.model.get('revision') ) ) {
 				return;
-			else
+			} else {
 				return _.extend( { type: 'tooltip' }, {
 					attributes: this.model.get('revision').toJSON()
 				});
+			}
 		},
 
 		render: function() {
-			var direction, directionVal, flipped, css = {}, position = this.model.revisions.indexOf( this.model.get('revision') ) + 1;
+			var otherDirection,
+				direction,
+				directionVal,
+				flipped,
+				css      = {},
+				position = this.model.revisions.indexOf( this.model.get('revision') ) + 1;
+
 			flipped = ( position / this.model.revisions.length ) > 0.5;
 			if ( isRtl ) {
 				direction = flipped ? 'left' : 'right';
@@ -781,11 +846,12 @@
 			return this.model.get( 'scrubbing' ) || this.model.get( 'hovering' );
 		},
 
-		toggleVisibility: function( options ) {
-			if ( this.visible() )
+		toggleVisibility: function() {
+			if ( this.visible() ) {
 				this.$el.stop().show().fadeTo( 100 - this.el.style.opacity * 100, 1 );
-			else
+			} else {
 				this.$el.stop().fadeTo( this.el.style.opacity * 300, 0, function(){ $(this).hide(); } );
+			}
 			return;
 		}
 	});
@@ -815,10 +881,11 @@
 				to: this.model.revisions.at( toIndex )
 			};
 			// If we're at the first revision, unset 'from'.
-			if ( toIndex )
+			if ( toIndex ) {
 				attributes.from = this.model.revisions.at( toIndex - 1 );
-			else
+			} else {
 				this.model.unset('from', { silent: true });
+			}
 
 			this.model.set( attributes );
 		},
@@ -837,11 +904,11 @@
 
 		// Check to see if the Previous or Next buttons need to be disabled or enabled.
 		disabledButtonCheck: function() {
-			var maxVal = this.model.revisions.length - 1,
-				minVal = 0,
-				next = $('.revisions-next .button'),
+			var maxVal   = this.model.revisions.length - 1,
+				minVal   = 0,
+				next     = $('.revisions-next .button'),
 				previous = $('.revisions-previous .button'),
-				val = this.model.revisions.indexOf( this.model.get('to') );
+				val      = this.model.revisions.indexOf( this.model.get('to') );
 
 			// Disable "Next" button if you're on the last node.
 			next.prop( 'disabled', ( maxVal === val ) );
@@ -884,19 +951,19 @@
 		},
 
 		mouseMove: function( e ) {
-			var zoneCount = this.model.revisions.length - 1, // One fewer zone than models
-				sliderFrom = this.$el.allOffsets()[this.direction], // "From" edge of slider
-				sliderWidth = this.$el.width(), // Width of slider
-				tickWidth = sliderWidth / zoneCount, // Calculated width of zone
-				actualX = isRtl? $(window).width() - e.pageX : e.pageX; // Flipped for RTL - sliderFrom;
-			actualX = actualX - sliderFrom; // Offset of mouse position in slider
-			var currentModelIndex = Math.floor( ( actualX + ( tickWidth / 2 )  ) / tickWidth ); // Calculate the model index
+			var zoneCount         = this.model.revisions.length - 1, // One fewer zone than models
+				sliderFrom        = this.$el.allOffsets()[this.direction], // "From" edge of slider
+				sliderWidth       = this.$el.width(), // Width of slider
+				tickWidth         = sliderWidth / zoneCount, // Calculated width of zone
+				actualX           = ( isRtl ? $(window).width() - e.pageX : e.pageX ) - sliderFrom, // Flipped for RTL - sliderFrom;
+				currentModelIndex = Math.floor( ( actualX  + ( tickWidth / 2 )  ) / tickWidth ); // Calculate the model index
 
 			// Ensure sane value for currentModelIndex.
-			if ( currentModelIndex < 0 )
+			if ( currentModelIndex < 0 ) {
 				currentModelIndex = 0;
-			else if ( currentModelIndex >= this.model.revisions.length )
+			} else if ( currentModelIndex >= this.model.revisions.length ) {
 				currentModelIndex = this.model.revisions.length - 1;
+			}
 
 			// Update the tooltip mode
 			this.model.set({ hoveredRevision: this.model.revisions.at( currentModelIndex ) });
@@ -933,19 +1000,20 @@
 			// Track the mouse position to enable smooth dragging,
 			// overrides default jQuery UI step behavior.
 			$( window ).on( 'mousemove.wp.revisions', { view: this }, function( e ) {
-				var view              = e.data.view,
-				    leftDragBoundary  = view.$el.offset().left,
-				    sliderOffset      = leftDragBoundary,
-				    sliderRightEdge   = leftDragBoundary + view.$el.width(),
-				    rightDragBoundary = sliderRightEdge,
-				    leftDragReset     = '0',
-				    rightDragReset    = '100%',
-				    handle            = $( ui.handle );
+				var handles,
+					view              = e.data.view,
+					leftDragBoundary  = view.$el.offset().left,
+					sliderOffset      = leftDragBoundary,
+					sliderRightEdge   = leftDragBoundary + view.$el.width(),
+					rightDragBoundary = sliderRightEdge,
+					leftDragReset     = '0',
+					rightDragReset    = '100%',
+					handle            = $( ui.handle );
 
 				// In two handle mode, ensure handles can't be dragged past each other.
 				// Adjust left/right boundaries and reset points.
 				if ( view.model.get('compareTwoMode') ) {
-					var handles = handle.parent().find('.ui-slider-handle');
+					handles = handle.parent().find('.ui-slider-handle');
 					if ( handle.is( handles.first() ) ) { // We're the left handle
 						rightDragBoundary = handles.last().offset().left;
 						rightDragReset    = rightDragBoundary - sliderOffset;
@@ -976,10 +1044,12 @@
 			// Compare two revisions mode
 			if ( this.model.get('compareTwoMode') ) {
 				// Prevent sliders from occupying same spot
-				if ( ui.values[1] === ui.values[0] )
+				if ( ui.values[1] === ui.values[0] ) {
 					return false;
-				if ( isRtl )
+				}
+				if ( isRtl ) {
 					ui.values.reverse();
+				}
 				attributes = {
 					from: this.model.revisions.at( this.getPosition( ui.values[0] ) ),
 					to: this.model.revisions.at( this.getPosition( ui.values[1] ) )
@@ -989,21 +1059,23 @@
 					to: this.model.revisions.at( this.getPosition( ui.value ) )
 				};
 				// If we're at the first revision, unset 'from'.
-				if ( this.getPosition( ui.value ) > 0 )
+				if ( this.getPosition( ui.value ) > 0 ) {
 					attributes.from = this.model.revisions.at( this.getPosition( ui.value ) - 1 );
-				else
+				} else {
 					attributes.from = undefined;
+				}
 			}
 			movedRevision = this.model.revisions.at( this.getPosition( ui.value ) );
 
 			// If we are scrubbing, a scrub to a revision is considered a hover
-			if ( this.model.get('scrubbing') )
+			if ( this.model.get('scrubbing') ) {
 				attributes.hoveredRevision = movedRevision;
+			}
 
 			this.model.set( attributes );
 		},
 
-		stop: function( event, ui ) {
+		stop: function() {
 			$( window ).off('mousemove.wp.revisions');
 			this.model.updateSliderSettings(); // To snap us back to a tick mark
 			this.model.set({ scrubbing: false });
@@ -1014,7 +1086,7 @@
 	// This is the view for the current active diff.
 	revisions.view.Diff = wp.Backbone.View.extend({
 		className: 'revisions-diff',
-		template: wp.template('revisions-diff'),
+		template:  wp.template('revisions-diff'),
 
 		// Generate the options to be passed to the template.
 		prepare: function() {
@@ -1022,15 +1094,12 @@
 		}
 	});
 
-	// The revisions router
-	// takes URLs with #hash fragments and routes them
+	// The revisions router.
+	// Maintains the URL routes so browser URL matches state.
 	revisions.Router = Backbone.Router.extend({
 		initialize: function( options ) {
 			this.model = options.model;
-			this.routes = _.object([
-				[ this.baseUrl( '?from=:from&to=:to' ), 'handleRoute' ],
-				[ this.baseUrl( '?from=:from&to=:to' ), 'handleRoute' ]
-			]);
+
 			// Maintain state and history when navigating
 			this.listenTo( this.model, 'update:diff', _.debounce( this.updateUrl, 250 ) );
 			this.listenTo( this.model, 'change:compareTwoMode', this.updateUrl );
@@ -1041,16 +1110,17 @@
 		},
 
 		updateUrl: function() {
-			var from = this.model.has('from') ? this.model.get('from').id : 0;
-			var to = this.model.get('to').id;
-			if ( this.model.get('compareTwoMode' ) )
-				this.navigate( this.baseUrl( '?from=' + from + '&to=' + to ) );
-			else
-				this.navigate( this.baseUrl( '?revision=' + to ) );
+			var from = this.model.has('from') ? this.model.get('from').id : 0,
+				to   = this.model.get('to').id;
+			if ( this.model.get('compareTwoMode' ) ) {
+				this.navigate( this.baseUrl( '?from=' + from + '&to=' + to ), { replace: true } );
+			} else {
+				this.navigate( this.baseUrl( '?revision=' + to ), { replace: true } );
+			}
 		},
 
 		handleRoute: function( a, b ) {
-			var from, to, compareTwo = _.isUndefined( b );
+			var compareTwo = _.isUndefined( b );
 
 			if ( ! compareTwo ) {
 				b = this.model.revisions.get( a );
@@ -1058,21 +1128,37 @@
 				b = b ? b.id : 0;
 				a = a ? a.id : 0;
 			}
-
-			this.model.set({
-				from: this.model.revisions.get( parseInt( a, 10 ) ),
-				to: this.model.revisions.get( parseInt( a, 10 ) ),
-				compareTwoMode: compareTwo
-			});
 		}
 	});
 
-	// Initialize the revisions UI.
+	/**
+	 * Initialize the revisions UI for revision.php.
+	 */
 	revisions.init = function() {
+		var state;
+
+		// Bail if the current page is not revision.php.
+		if ( ! window.adminpage || 'revision-php' !== window.adminpage ) {
+			return;
+		}
+
+		state = new revisions.model.FrameState({
+			initialDiffState: {
+				// wp_localize_script doesn't stringifies ints, so cast them.
+				to: parseInt( revisions.settings.to, 10 ),
+				from: parseInt( revisions.settings.from, 10 ),
+				// wp_localize_script does not allow for top-level booleans so do a comparator here.
+				compareTwoMode: ( revisions.settings.compareTwoMode === '1' )
+			},
+			diffData: revisions.settings.diffData,
+			baseUrl: revisions.settings.baseUrl,
+			postId: parseInt( revisions.settings.postId, 10 )
+		}, {
+			revisions: new revisions.model.Revisions( revisions.settings.revisionData )
+		});
+
 		revisions.view.frame = new revisions.view.Frame({
-			model: new revisions.model.FrameState({}, {
-				revisions: new revisions.model.Revisions( revisions.settings.revisionData )
-			})
+			model: state
 		}).render();
 	};