Index: wp-includes/revision.php
===================================================================
--- wp-includes/revision.php	(revision 24458)
+++ wp-includes/revision.php	(working copy)
@@ -597,68 +597,3 @@
 
 	return true;
 }
-
-/**
- * Displays a human readable HTML representation of the difference between two strings.
- * similar to wp_text_diff, but tracks and returns could of lines added and removed
- *
- * @since 3.6.0
- *
- * @see wp_parse_args() Used to change defaults to user defined settings.
- * @uses Text_Diff
- * @uses WP_Text_Diff_Renderer_Table
- *
- * @param string $left_string "old" (left) version of string
- * @param string $right_string "new" (right) version of string
- * @param string|array $args Optional. Change 'title', 'title_left', and 'title_right' defaults.
- * @return array contains html, linesadded & linesdeletd, empty string if strings are equivalent.
- */
-function wp_text_diff_with_count( $left_string, $right_string, $args = null ) {
-	$defaults = array( 'title' => '', 'title_left' => '', 'title_right' => '' );
-	$args = wp_parse_args( $args, $defaults );
-
-	if ( ! class_exists( 'WP_Text_Diff_Renderer_Table' ) )
-			require( ABSPATH . WPINC . '/wp-diff.php' );
-
-	$left_string  = normalize_whitespace( $left_string );
-	$right_string = normalize_whitespace( $right_string );
-
-	$left_lines  = explode( "\n", $left_string );
-	$right_lines = explode( "\n", $right_string) ;
-
-	$text_diff = new Text_Diff($left_lines, $right_lines  );
-	$lines_added = $text_diff->countAddedLines();
-	$lines_deleted = $text_diff->countDeletedLines();
-
-	$renderer  = new WP_Text_Diff_Renderer_Table();
-	$diff = $renderer->render( $text_diff );
-
-	if ( !$diff )
-			return '';
-
-		$r  = "<table class='diff'>\n";
-
-	if ( ! empty( $args[ 'show_split_view' ] ) ) {
-		$r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />";
-	} else {
-		$r .= "<col class='content' />";
-	}
-
-	if ( $args['title'] || $args['title_left'] || $args['title_right'] )
-		$r .= "<thead>";
-	if ( $args['title'] )
-		$r .= "<tr class='diff-title'><th colspan='4'>$args[title]</th></tr>\n";
-	if ( $args['title_left'] || $args['title_right'] ) {
-		$r .= "<tr class='diff-sub-title'>\n";
-		$r .= "\t<td></td><th>$args[title_left]</th>\n";
-		$r .= "\t<td></td><th>$args[title_right]</th>\n";
-		$r .= "</tr>\n";
-	}
-	if ( $args['title'] || $args['title_left'] || $args['title_right'] )
-		$r .= "</thead>\n";
-
-	$r .= "<tbody>\n$diff\n</tbody>\n";
-	$r .= "</table>";
-
-	return array( 'html' => $r, 'lines_added' => $lines_added, 'lines_deleted' => $lines_deleted );
-}
Index: wp-admin/admin-ajax.php
===================================================================
--- wp-admin/admin-ajax.php	(revision 24458)
+++ wp-admin/admin-ajax.php	(working copy)
@@ -42,7 +42,7 @@
 
 $core_actions_get = array(
 	'fetch-list', 'ajax-tag-search', 'wp-compression-test', 'imgedit-preview', 'oembed-cache',
-	'autocomplete-user', 'dashboard-widgets', 'logged-in', 'revisions-data'
+	'autocomplete-user', 'dashboard-widgets', 'logged-in',
 );
 
 $core_actions_post = array(
@@ -56,7 +56,7 @@
 	'save-widget', 'set-post-thumbnail', 'date_format', 'time_format', 'wp-fullscreen-save-post',
 	'wp-remove-post-lock', 'dismiss-wp-pointer', 'upload-attachment', 'get-attachment',
 	'query-attachments', 'save-attachment', 'save-attachment-compat', 'send-link-to-editor',
-	'send-attachment-to-editor', 'save-attachment-order', 'heartbeat',
+	'send-attachment-to-editor', 'save-attachment-order', 'heartbeat', 'get-revision-diffs',
 );
 
 // Register core Ajax calls.
Index: wp-admin/includes/ajax-actions.php
===================================================================
--- wp-admin/includes/ajax-actions.php	(revision 24458)
+++ wp-admin/includes/ajax-actions.php	(working copy)
@@ -2082,219 +2082,31 @@
 	wp_send_json($response);
 }
 
-function wp_ajax_revisions_data() {
-	check_ajax_referer( 'revisions-ajax-nonce', 'nonce' );
+function wp_ajax_get_revision_diffs() {
+	require ABSPATH . 'wp-admin/includes/revision.php';
 
-	$compare_to = ! empty( $_GET['compare_to'] ) ? absint( $_GET['compare_to'] ) : 0;
-	$show_autosaves = ! empty( $_GET['show_autosaves'] );
-	$show_split_view = ! empty( $_GET['show_split_view'] );
-	$post_id = ! empty( $_GET['post_id'] ) ? absint( $_GET['post_id'] ) : 0;
-	$right_handle_at = ! empty( $_GET['right_handle_at'] ) ? (int) $_GET['right_handle_at'] : 0;
-	$left_handle_at = ! empty( $_GET['left_handle_at'] ) ? (int) $_GET['left_handle_at'] : 0;
-	$single_revision_id = ! empty( $_GET['single_revision_id'] ) ? absint( $_GET['single_revision_id'] ) : 0;
-	$compare_two_mode = (bool) $post_id;
+	// check_ajax_referer( 'revisions-ajax-nonce', 'nonce' );
 
-	$all_the_revisions = array();
-	if ( ! $post_id )
-		$post_id = $compare_to;
+	if ( ! $post = get_post( (int) $_REQUEST['post_id'] ) )
+		wp_send_json_error();
 
-	if ( ! current_user_can( 'read_post', $post_id ) )
-		continue;
+	if ( ! current_user_can( 'read_post', $post->ID ) )
+		wp_send_json_error();
 
-	if ( ! $revisions = wp_get_post_revisions( $post_id ) )
-		return;
+	// Really just pre-loading the cache here.
+	if ( ! $revisions = wp_get_post_revisions( $post->ID ) )
+		wp_send_json_error();
 
-	$left_revision = get_post( $compare_to );
+	$return = array();
+	@set_time_limit( count( $_REQUEST['compare'] ) );
 
-	// single model fetch mode
-	// return the diff of a single revision comparison
-	if ( $single_revision_id ) {
-		$right_revision = get_post( $single_revision_id );
+	foreach ( $_REQUEST['compare'] as $compare_key ) {
+		list( $compare_from, $compare_to ) = explode( ':', $compare_key ); // from:to
 
-		if ( ! $compare_to )
-			$left_revision = get_post( $post_id );
-
-		// make sure the right revision is the most recent, except on oldest revision
-		if ( $compare_to && $right_revision->post_date < $left_revision->post_date ) {
-			$temp = $left_revision;
-			$left_revision = $right_revision;
-			$right_revision = $temp;
-		}
-
-		$lines_added = $lines_deleted = 0;
-		$content = '';
-		// compare from left to right, passed from application
-		foreach ( _wp_post_revision_fields() as $field => $field_value ) {
-			$left_content = apply_filters( "_wp_post_revision_field_$field", $left_revision->$field, $field, $left_revision, 'left' );
-			$right_content = apply_filters( "_wp_post_revision_field_$field", $right_revision->$field, $field, $right_revision, 'right' );
-
-			add_filter( "_wp_post_revision_field_$field", 'htmlspecialchars' );
-
-			$args = array();
-
-			if ( $show_split_view )
-				 $args = array( 'show_split_view' => true );
-
-			// compare_to == 0 means first revision, so compare to a blank field to show whats changed
-			$diff = wp_text_diff_with_count( ( 0 == $compare_to ) ? '' : $left_content, $right_content, $args );
-
-			if ( isset( $diff[ 'html' ] ) ) {
-				$content .= sprintf( '<div class="diff-label">%s</div>', $field_value );
-				$content .= $diff[ 'html' ];
-			}
-
-			if ( isset( $diff[ 'lines_added' ] ) )
-				$lines_added = $lines_added + $diff[ 'lines_added' ];
-
-			if ( isset( $diff[ 'lines_deleted' ] ) )
-				$lines_deleted = $lines_deleted + $diff[ 'lines_deleted' ];
-		}
-		$content = '' == $content ? __( 'No difference' ) : $content;
-
-		$all_the_revisions = array (
-			'diff'         => $content,
-			'linesDeleted' => $lines_deleted,
-			'linesAdded'   => $lines_added
+		$return[] = array(
+			'id' => $compare_key,
+			'fields' => wp_get_revision_ui_diff( $post, $compare_from, $compare_to ),
 		);
-
-		echo json_encode( $all_the_revisions );
-		exit();
-	} // end single model fetch
-
-	$count = -1;
-
-	// reverse the list to start with oldest revision
-	$revisions = array_reverse( $revisions );
-
-	$previous_revision_id = 0;
-
-	/* translators: revision date format, see http://php.net/date */
-	$datef = _x( 'j F, Y @ G:i:s', 'revision date format');
-
-	foreach ( $revisions as $revision ) :
-		if ( ! $show_autosaves && wp_is_post_autosave( $revision ) )
-			continue;
-
-		$revision_from_date_author = '';
-		$is_current_revision = false;
-		$count++;
-
-		/**
-		* return blank data for diffs to the left of the left handle (for right handel model)
-		* or to the right of the right handle (for left handel model)
-		* and visa versa in RTL mode
-		*/
-		if( ! is_rtl() ) {
-			if ( ( ( 0 != $left_handle_at && $count < $left_handle_at ) ||
-				 ( 0 != $right_handle_at && $count > ( $right_handle_at - 2 ) ) ) ) {
-				$all_the_revisions[] = array (
-					'ID' => $revision->ID,
-				);
-				continue;
-			}
-		} else { // is_rtl
-			if ( ( 0 != $left_handle_at && $count > ( $left_handle_at - 1 ) ||
-				 ( 0 != $left_handle_at && $count < $right_handle_at ) ) ) {
-				$all_the_revisions[] = array (
-					'ID' => $revision->ID,
-				);
-				continue;
-			}
-		}
-
-		if ( $compare_two_mode ) {
-			$compare_to_gravatar = get_avatar( $left_revision->post_author, 24 );
-			$compare_to_author = get_the_author_meta( 'display_name', $left_revision->post_author );
-			$compare_to_date = date_i18n( $datef, strtotime( $left_revision->post_modified ) );
-
-			$revision_from_date_author = sprintf(
-				/* translators: post revision title: 1: author avatar, 2: author name, 3: time ago, 4: date */
-				_x( '%1$s %2$s, %3$s ago (%4$s)', 'post revision title' ),
-				$compare_to_gravatar,
-				$compare_to_author,
-				human_time_diff( strtotime( $left_revision->post_modified ), current_time( 'timestamp' ) ),
-				$compare_to_date
-			);
-		}
-
-		$gravatar = get_avatar( $revision->post_author, 24 );
-		$author = get_the_author_meta( 'display_name', $revision->post_author );
-		$date = date_i18n( $datef, strtotime( $revision->post_modified ) );
-		$revision_date_author = sprintf(
-			/* translators: post revision title: 1: author avatar, 2: author name, 3: time ago, 4: date */
-			_x( '%1$s %2$s, %3$s ago (%4$s)', 'post revision title' ),
-			$gravatar,
-			$author,
-			human_time_diff( strtotime( $revision->post_modified ), current_time( 'timestamp' ) ),
-			$date
-		);
-
-		/* translators: 1: date */
-		$autosavef = _x( '%1$s [Autosave]', 'post revision title extra' );
-		/* translators: 1: date */
-		$currentf  = _x( '%1$s [Current Revision]', 'post revision title extra' );
-
-		if ( ! $post = get_post( $post_id ) )
-			continue;
-
-		if ( $left_revision->post_modified === $post->post_modified )
-			$revision_from_date_author = sprintf( $currentf, $revision_from_date_author );
-		elseif ( wp_is_post_autosave( $left_revision ) )
-			$revision_from_date_author = sprintf( $autosavef, $revision_from_date_author );
-
-		if ( $revision->post_modified === $post->post_modified ) {
-			$revision_date_author = sprintf( $currentf, $revision_date_author );
-			$is_current_revision = true;
-		} elseif ( wp_is_post_autosave( $revision ) ) {
-			$revision_date_author = sprintf( $autosavef, $revision_date_author );
-		}
-
-		/* translators: revision date short format, see http://php.net/date */
-		$date_short_format = _x( 'j M @ G:i', 'revision date short format');
-		$date_short = date_i18n( $date_short_format, strtotime( $revision->post_modified ) );
-
-		$revision_date_author_short = sprintf(
-			'%s <strong>%s</strong><br />%s',
-			$gravatar,
-			$author,
-			$date_short
-		);
-
-		$restore_link = wp_nonce_url(
-			add_query_arg(
-				array( 'revision' => $revision->ID,
-					'action' => 'restore' ),
-					admin_url( 'revision.php' )
-			),
-			"restore-post_{$revision->ID}"
-		);
-
-		// if this is a left handled calculation swap data
-		if ( 0 != $right_handle_at ) {
-			$tmp = $revision_from_date_author;
-			$revision_from_date_author = $revision_date_author;
-			$revision_date_author = $tmp;
-		}
-
-		if ( ( $compare_two_mode || -1 !== $previous_revision_id ) ) {
-			$all_the_revisions[] = array (
-				'ID'           => $revision->ID,
-				'titleTo'      => $revision_date_author,
-				'titleFrom'    => $revision_from_date_author,
-				'titleTooltip' => $revision_date_author_short,
-				'restoreLink'  => urldecode( $restore_link ),
-				'previousID'   => $previous_revision_id,
-				'isCurrent'    => $is_current_revision,
-			);
-		}
-		$previous_revision_id = $revision->ID;
-
-	endforeach;
-
-	// in RTL + single handle mode, reverse the revision direction
-	if ( is_rtl() && $compare_two_mode )
-		$all_the_revisions = array_reverse( $all_the_revisions );
-
-	echo json_encode( $all_the_revisions );
-	exit();
+	}
+	wp_send_json_success( $return );
 }
Index: wp-admin/includes/revision.php
===================================================================
--- wp-admin/includes/revision.php	(revision 0)
+++ wp-admin/includes/revision.php	(revision 0)
@@ -0,0 +1,100 @@
+<?php
+
+function wp_get_revision_ui_diff( $post, $compare_from, $compare_to ) {
+	if ( ! $post = get_post( $post ) )
+		return false;
+
+	if ( $compare_from ) {
+		if ( ! $compare_from = get_post( $compare_from ) )
+			return false;
+	} else {
+		// If we're dealing with the first revision...
+		$compare_from = false;
+	}
+
+	if ( ! $compare_to = get_post( $compare_to ) )
+		return false;
+
+	// If comparing revisions, make sure we're dealing with the right post parent.
+	if ( $compare_from && $compare_from->post_parent !== $post->ID )
+		return false;
+	if ( $compare_to->post_parent !== $post->ID )
+		return false;
+
+	if ( $compare_from && strtotime( $compare_from->post_date_gmt ) > strtotime( $compare_to->post_date_gmt ) ) {
+		$temp = $compare_from;
+		$compare_from = $compare_to;
+		$compare_to = $temp;
+	}
+
+	$return = array();
+
+	foreach ( _wp_post_revision_fields() as $field => $name ) {
+		$content_from = $compare_from ? apply_filters( "_wp_post_revision_field_$field", $compare_from->$field, $field, $compare_from, 'left' ) : '';
+		$content_to = apply_filters( "_wp_post_revision_field_$field", $compare_to->$field, $field, $compare_to, 'right' );
+
+		$diff = wp_text_diff( $content_from, $content_to, array( 'show_split_view' => true ) );
+
+		if ( ! $diff && 'post_title' === $field ) {
+			// It's a better user experience to still show the Title, even if it didn't change.
+			// No, you didn't see this.
+			$diff = "<table class='diff'><col class='ltype' /><col class='content' /><col class='ltype' /><col class='content' /><tbody><tr>";
+			$diff .= '<td>' . esc_html( $compare_from->post_title ) . '</td><td></td><td>' . esc_html( $compare_to->post_title ) . '</td>';
+			$diff .= '</tr></tbody>';
+			$diff .= '</table>';
+		}
+
+		if ( $diff ) {
+			$return[] = array(
+				'id' => $field,
+				'name' => $name,
+				'diff' => $diff,
+			);
+		}
+	}
+	return $return;
+}
+
+function wp_prepare_revisions_for_js( $post, $selected_revision_id ) {
+	$post = get_post( $post );
+	$revisions = array();
+	$current = current_time( 'timestamp' );
+
+	$revisions = wp_get_post_revisions( $post->ID );
+
+	cache_users( wp_list_pluck( $revisions, 'post_author' ) );
+
+	foreach ( $revisions as $revision ) {
+		$modified_gmt = strtotime( $revision->post_modified_gmt );
+		$restore_link = wp_nonce_url(
+			add_query_arg(
+				array( 'revision' => $revision->ID,
+					'action' => 'restore' ),
+					admin_url( 'revision.php' )
+			),
+			"restore-post_{$revision->ID}"
+		);
+		$revisions[ $revision->ID ] = array(
+			'id'           => $revision->ID,
+			'title'        => get_the_title( $post->ID ),
+			'author' => array(
+				'id'     => (int) $revision->post_author,
+				'avatar' => get_avatar( $revision->post_author, 24 ),
+				'name'   => get_the_author_meta( 'display_name', $revision->post_author ),
+			),
+			'date'         => date_i18n( __( 'M j, Y @ G:i' ), $modified_gmt ),
+			'dateShort'    => date_i18n( _x( 'j M @ G:i', 'revision date short format' ), $modified_gmt ),
+			'timeAgo'      => human_time_diff( $modified_gmt, $current ),
+			'autosave'     => wp_is_post_autosave( $revision ),
+			'current'      => $revision->post_modified_gmt === $post->post_modified_gmt,
+			'restoreUrl'   => urldecode( $restore_link ),
+		);
+	}
+
+	return array(
+		'postId'           => $post->ID,
+		'nonce'            => wp_create_nonce( 'revisions-ajax-nonce' ),
+		'revisionData'     => array_values( $revisions ),
+		'selectedRevision' => $selected_revision_id,
+	);
+}
\ No newline at end of file
Index: wp-admin/js/revisions.js
===================================================================
--- wp-admin/js/revisions.js	(revision 24458)
+++ wp-admin/js/revisions.js	(working copy)
@@ -1,283 +1,207 @@
 window.wp = window.wp || {};
 
 (function($) {
-	var Revision, Revisions, Diff, revisions;
+	var revisions;
 
-	revisions = wp.revisions = function() {
-		Diff = revisions.Diff = new Diff();
-	};
+	revisions = wp.revisions = { model: {}, view: {}, controller: {} };
 
-	_.extend( revisions, { model: {}, view: {}, controller: {} } );
-
 	// Link settings.
-	revisions.model.settings = typeof wpRevisionsSettings === 'undefined' ? {} : wpRevisionsSettings;
+	revisions.settings = typeof _wpRevisionsSettings === 'undefined' ? {} : _wpRevisionsSettings;
 
 
 	/**
 	 * ========================================================================
-	 * CONTROLLERS
+	 * MODELS
 	 * ========================================================================
 	 */
+	revisions.model.Slider = Backbone.Model.extend({
+		defaults: {
+			value: 0,
+			min: 0,
+			max: 1,
+			step: 1
+		}
+	});
 
-	/**
-	 * wp.revisions.controller.Diff
-	 *
-	 * Controlls the diff
-	 */
-	Diff = revisions.controller.Diff = Backbone.Model.extend( {
-		rightDiff: 1,
-		leftDiff: 1,
-		revisions: null,
-		leftHandleRevisions: null,
-		rightHandleRevisions: null,
-		revisionsInteractions: null,
-		autosaves: true,
-		showSplitView: true,
-		singleRevision: true,
-		leftModelLoading: false,	// keep track of model loads
-		rightModelLoading: false,	// disallow slider interaction, also repeat loads, while loading
-		tickmarkView: null, // the slider tickmarks
-		slider: null, // the slider instance
+	revisions.model.Revision = Backbone.Model.extend({});
 
-		constructor: function() {
-			var self    = this;
-			this.slider = new revisions.view.Slider();
+	revisions.model.Revisions = Backbone.Collection.extend({
+		model: revisions.model.Revision,
 
-			if ( null === this.revisions ) {
-				this.revisions = new Revisions(); // set up collection
-				this.startRightModelLoading();
-
-				this.revisions.fetch({ // load revision data
-					success: function() {
-						self.stopRightModelLoading();
-						self.completeApplicationSetup();
-					}
-				});
-			}
+		comparator: function( revision ) {
+			return revision.id;
 		},
+	});
 
-		loadDiffs: function( models ) {
-			var self = this,
-				revisionsToLoad = models.where( { completed: false } ),
-				delay = 0,
-				totalChanges;
+	revisions.model.Field = Backbone.Model.extend({});
 
-			// match slider to passed revision_id
-			_.each( revisionsToLoad, function( revision ) {
-				if ( revision.get( 'ID' ) == revisions.model.settings.revision_id )
-					self.rightDiff = self.revisions.indexOf( revision ) + 1;
-			});
+	revisions.model.Fields = Backbone.Collection.extend({
+		model: revisions.model.Field
+	});
 
-			_.each( revisionsToLoad, function( revision ) {
-					_.delay( function() {
-						revision.fetch( {
-							update: true,
-							add: false,
-							remove: false,
-							success: function( model ) {
-								model.set( 'completed', true );
+	revisions.model.Diff = Backbone.Model.extend({
+		initialize: function(attributes, options) {
+			var fields = this.get('fields');
+			this.unset('fields');
 
-								// stop spinner when all models are loaded
-								if ( 0 === models.where( { completed: false } ).length )
-									self.stopModelLoadingSpinner();
+			this.fields = new revisions.model.Fields( fields );
+		}
+	});
 
-								totalChanges = model.get( 'linesAdded' ) + model.get( 'linesDeleted' ),
-									scopeOfChanges = 'vsmall';
+	revisions.model.Diffs = Backbone.Collection.extend({
+		initialize: function(models, options) {
+			this.revisions = options.revisions;
+			this.requests  = {};
+		},
 
-								// Note: hard coded scope of changes
-								// TODO change to dynamic based on range of values
-								if ( totalChanges > 1 && totalChanges <= 3 ) {
-									scopeOfChanges = 'small';
-								} else if ( totalChanges > 3 && totalChanges <= 5 ) {
-									scopeOfChanges = 'med';
-								} else if ( totalChanges > 5 && totalChanges <= 10 ) {
-									scopeOfChanges = 'large';
-								} else if ( totalChanges > 10 ) {
-									scopeOfChanges = 'vlarge';
-								}
-								model.set( 'scopeOfChanges', scopeOfChanges );
-								if ( 0 !== self.rightDiff &&
-									model.get( 'ID' ) === self.revisions.at( self.rightDiff - 1 ).get( 'ID' ) ) {
-									// reload if current model refreshed
-									self.revisionView.render();
-								}
-								self.tickmarkView.render();
-							}
-					} );
-					}, delay ) ;
-					delay = delay + 150; // stagger model loads to avoid hammering server with requests
+		model: revisions.model.Diff,
+
+		ensure: function( id, context ) {
+			var diff     = this.get( id );
+			var request  = this.requests[ id ];
+			var deferred = $.Deferred();
+			var ids      = {};
+
+			if ( diff ) {
+				deferred.resolveWith( context, [ diff ] );
+			} else {
+				this.trigger( 'ensure:load', ids );
+				_.each( ids, _.bind( function(id) {
+					// Remove anything that has an ongoing request
+					if ( this.requests[ id ] )
+						delete ids[ id ];
+				}, this ) );
+				if ( ! request ) {
+					// Always include the ID that started this ensure
+					ids[ id ] = true;
+					request   = this.load( _.keys( ids ) );
 				}
-			);
-		},
 
-		startLeftModelLoading: function() {
-			this.leftModelLoading = true;
-			$('#revision-diff-container').addClass('left-model-loading');
-		},
+				request.done( _.bind( function() {
+					deferred.resolveWith( context, [ this.get( id ) ] );
+				}, this ) );
+			}
 
-		stopLeftModelLoading: function() {
-			this.leftModelLoading = false;
+			return deferred.promise();
 		},
 
-		startRightModelLoading: function() {
-			this.rightModelLoading = true;
-			$('#revision-diff-container').addClass('right-model-loading');
+		loadNew: function( comparisons ) {
+			comparisons = _.object( comparisons, comparisons );
+			_.each( comparisons, _.bind( function( id ) {
+				// Exists
+				if ( this.get( id ) )
+					delete comparisons[ id ];
+			}, this ) );
+			comparisons = _.toArray( comparisons );
+			return this.load( comparisons );
 		},
 
-		stopRightModelLoading: function() {
-			this.rightModelLoading = false;
+		load: function( comparisons ) {
+			// Our collection should only ever grow, never shrink, so remove: false
+			return this.fetch({ data: { compare: comparisons }, remove: false });
 		},
 
-		stopModelLoadingSpinner: function() {
-			$('#revision-diff-container').removeClass('right-model-loading');
-			$('#revision-diff-container').removeClass('left-model-loading');
-		},
+/**/
+		loadLast: function( num ) {
+			num     = num || 1;
+			var ids = this.getProximalDiffIds();
+			ids     = _.last( ids, num );
 
-		reloadModel: function() {
-			if ( this.singleRevision ) {
-				this.reloadModelSingle();
-			} else {
-				this.reloadLeftRight();
+			if ( ids.length ) {
+				return this.loadNew( ids );
 			}
 		},
 
-		// load the models for the single handle mode
-		reloadModelSingle: function() {
-			var self = this;
+		loadLastUnloaded: function( num ) {
+			num     = num || 1;
+			var ids = this.getUnloadedProximalDiffIds();
+			ids     = _.last( ids, num );
 
-			self.startRightModelLoading();
+			if ( ids.length ) {
+				return this.loadNew( ids );
+			}
+		},
 
-			self.revisions.reload({
-				options: {
-				'showAutosaves': self.autosaves,
-				'showSplitView': self.showSplitView
-				},
+		getProximalDiffIds: function() {
+			var previous = 0, ids = [];
+			this.revisions.each( _.bind( function(revision) {
+				ids.push( previous + ':' + revision.id );
+				previous = revision.id;
+			}, this ) );
+			return ids;
+		},
 
-				success: function() {
-					var revisionCount = self.revisions.length;
-					self.revisionView.model = self.revisions;
-					self.revisionView.render();
-					self.loadDiffs( self.revisions );
-					self.tickmarkView.model = self.revisions;
-					self.tickmarkView.render();
-					self.slider.refresh({
-						'max': revisionCount - 1, // slider starts at 0 in single handle mode
-						'value': self.rightDiff - 1 // slider starts at 0 in single handle mode
-					}, true);
-				},
-
-				error: function() {
-					self.stopRightModelLoading();
-				}
-			});
+		getUnloadedProximalDiffIds: function() {
+			var comparisons = this.getProximalDiffIds();
+			comparisons     = _.object( comparisons, comparisons );
+			_.each( comparisons, _.bind( function( id ) {
+				// Exists
+				if ( this.get( id ) )
+					delete comparisons[ id ];
+			}, this ) );
+			return _.toArray( comparisons );
 		},
 
-		// load the models for the left handle (the right handler has moved)
-		reloadLeft: function() {
-			var self = this;
-			self.startLeftModelLoading();
-			self.leftHandleRevisions = new Revisions( {}, {
-				'compareTo': self.revisions.at( self.rightDiff - 1 ).get( 'ID' ), // diff and model count off by 1
-				'showAutosaves': self.autosaves,
-				'showSplitView': self.showSplitView,
-				'rightHandleAt': self.rightDiff
-			});
-
-			self.leftHandleRevisions.fetch({
-				success: function(){
-					self.stopLeftModelLoading();
-					self.loadDiffs( self.leftHandleRevisions );
-					self.tickmarkView.model = self.leftHandleRevisions;
-					self.slider.refresh({
-						'max': self.revisions.length
-					});
-					// ensure right handle not beyond length
-					if ( self.rightDiff > self.revisions.length )
-						self.rightDiff = self.revisions.length;
-					},
-
-				error: function() {
-					self.stopLeftModelLoading();
-				}
-			});
+		loadAllBy: function( chunkSize ) {
+			chunkSize    = chunkSize || 20;
+			var unloaded = this.getUnloadedProximalDiffIds();
+			if ( unloaded.length ) {
+				return this.loadLastUnloaded( chunkSize ).always( _.bind( function() {
+					this.loadAllBy( chunkSize );
+				}, this ) );
+			}
 		},
 
-		// load the models for the right handle (the left handle has moved)
-		reloadRight: function() {
-			var self = this;
-			self.startRightModelLoading();
-			self.rightHandleRevisions = new Revisions( {}, {
-				'compareTo': self.revisions.at( self.leftDiff - 1 ).get( 'ID' ), // diff and model count off by 1
-				'showAutosaves': self.autosaves,
-				'showSplitView': self.showSplitView,
-				'leftHandleAt': self.leftDiff
-			});
+		sync: function( method, model, options ) {
+			if ( 'read' === method ) {
+				options         = options || {};
+				options.context = this;
+				options.data    = _.extend( options.data || {}, {
+					action: 'get-revision-diffs',
+					post_id: revisions.settings.postId
+				});
 
-			self.rightHandleRevisions.fetch({
-				success: function(){
-					self.stopRightModelLoading();
-					self.loadDiffs( self.rightHandleRevisions );
-					self.tickmarkView.model = self.rightHandleRevisions;
-					self.slider.refresh({
-						'max': self.revisions.length
-					}, true);
-				},
+				var deferred = wp.xhr.send( options );
+				var requests = this.requests;
 
-				error: function( response ) {
-					self.stopRightModelLoading();
+				// Record that we're requesting each diff.
+				if ( options.data.compare ) {
+					_.each( options.data.compare, function( id ) {
+						requests[ id ] = deferred;
+					});
 				}
-			});
 
-		},
+				// When the request completes, clear the stored request.
+				deferred.always( function() {
+					if ( options.data.compare ) {
+						_.each( options.data.compare, function( id ) {
+							delete requests[ id ];
+						});
+					}
+				});
 
-		/**
-		 * reloadLeftRight reload models for both the left and right handles
-		 */
-		reloadLeftRight: function() {
-			this.startRightModelLoading();
-			this.startLeftModelLoading();
-			this.reloadLeft();
-			this.reloadRight();
-		},
+				return deferred;
 
-		disabledButtonCheck: function( val ) {
-			var maxVal = this.revisions.length - 1,
-				next = ! isRtl ? $( '#next' ) : $( '#previous' ),
-				prev = ! isRtl ? $( '#previous' ) : $( '#next' );
+			// Otherwise, fall back to `Backbone.sync()`.
+			} else {
+				return Backbone.Model.prototype.sync.apply( this, arguments );
+			}
+		}
+	});
 
-			// Disable "Next" button if you're on the last node
-			if ( maxVal === val )
-				next.prop( 'disabled', true );
-			else
-				next.prop( 'disabled', false );
 
-			// Disable "Previous" button if you're on the 0 node
-			if ( 0 === val )
-				prev.prop( 'disabled', true );
-			else
-				prev.prop( 'disabled', false );
+	revisions.model.FrameState = Backbone.Model.extend({
+		initialize: function( attributes, options ) {
+			this.revisions = options.revisions;
+			this.diffs     = new revisions.model.Diffs( [], {revisions: this.revisions} );
+
+			this.listenTo( this, 'change:from change:to', this.updateDiffId );
 		},
 
-		/**
-		 * completeApplicationSetup finishes loading all views once the initial model load is complete
-		 */
-		completeApplicationSetup: function() {
-			this.revisionView = new revisions.view.Diff({
-				model: this.revisions
-			});
-			this.revisionView.render(); // render the revision view
-
-			this.loadDiffs( this.revisions ); // get the actual revisions data
-
-			this.revisionsInteractions = new revisions.view.Interact({
-				model: this.revisions
-			});
-			this.revisionsInteractions.render(); // render the interaction view
-
-			this.tickmarkView = new revisions.view.Tickmarks({
-				model: this.revisions
-			});
-			this.tickmarkView.render(); // render the tickmark view
+		updateDiffId: function() {
+			var from = this.get( 'from' );
+			var to   = this.get( 'to' );
+			this.set( 'diffId', (from ? from.id : '0') + ':' + to.id );
 		}
 	});
 
@@ -288,534 +212,273 @@
 	 * ========================================================================
 	 */
 
-	/**
-	 * wp.revisions.view.Slider
-	 *
-	 * The slider
-	 */
-	revisions.view.Slider = Backbone.View.extend({
-		el: $( '#diff-slider' ),
-		singleRevision: true,
+	// The frame view. This contains the entire page.
+	revisions.view.Frame = wp.Backbone.View.extend({
+		tagName: 'div',
+		className: 'revisions',
+		template: wp.template('revisions-frame'),
 
-		initialize: function( options ) {
-			this.options = _.defaults( options || {}, {
-				value: 0,
-				min: 0,
-				max: 1,
-				step: 1
+		initialize: function() {
+			this.model = new revisions.model.FrameState({}, {
+				revisions: this.collection
 			});
-		},
 
-		/**
-		 * respond to slider slide events
-		 * Note: in one handle mode, jQuery UI reports leftmost position as 0
-		 * in two handle mode, jQuery UI Slider reports leftmost position as 1
-		 */
-		slide: function( event, ui ) {
-			if ( this.singleRevision ) {
-				Diff.rightDiff = ( ui.value + 1 );
-				Diff.revisionView.render();
-				Diff.disabledButtonCheck( ui.value );
-			} else {
-				if ( ui.values[0] === ui.values[1] ) // prevent compare to self
-					return false;
+			this.listenTo( this.model, 'change:diffId', this.updateDiff );
 
-				if ( $( ui.handle ).hasClass( 'left-handle' ) ) {
-					// Left handler
-					if ( Diff.leftModelLoading ) // left model still loading, prevent sliding left handle
-						return false;
+			this.views.set( '.revisions-control-frame', new revisions.view.Controls({
+				model: this.model
+			}) );
 
-					Diff.leftDiff = isRtl ? ui.values[1] : ui.values[0]; // handles are reversed in RTL mode
-				} else {
-					// Right handler
-					if ( Diff.rightModelLoading ) // right model still loading, prevent sliding right handle
-						return false;
+			if ( this.model.revisions.length ) {
+				var last = this.model.revisions.last(2);
+				var attributes = { to: last.pop() };
 
-					Diff.rightDiff = isRtl ? ui.values[0] : ui.values[1]; // handles are reversed in RTL mode
-				}
+				if ( last.length )
+					attributes.from = last.pop();
 
-				Diff.revisionView.render();
+				this.model.set( attributes );
+
+				// Load the rest: first 10, then the rest by 50
+				this.model.diffs.loadLastUnloaded( 10 ).always( _.bind( function() {
+					this.model.diffs.loadAllBy( 50 );
+				}, this ) );
 			}
 		},
 
-		/**
-		 * responds to slider start sliding events
-		 * in two handle mode stores start position, so if unchanged at stop event no need to reload diffs
-		 * also swaps in the appropriate models - left handled or right handled
-		 */
-		start: function( event, ui ) {
-			// Not needed in one mode
-			if ( this.singleRevision )
-				return;
+		render: function() {
+			wp.Backbone.View.prototype.render.apply( this, arguments );
 
-			if ( $( ui.handle ).hasClass( 'left-handle' ) ) {
-				// Left handler
-				if ( Diff.leftModelLoading ) // left model still loading, prevent sliding left handle
-					return false;
+			$('#wpbody-content .wrap').append( this.el );
+			this.views.ready();
 
-				Diff.revisionView.draggingLeft = true;
+			return this;
+		},
 
-				if ( Diff.revisionView.model !== Diff.leftHandleRevisions &&
-						null !== Diff.leftHandleRevisions ) {
-					Diff.revisionView.model = Diff.leftHandleRevisions; // use the left handle models
-					Diff.tickmarkView.model = Diff.leftHandleRevisions;
-					Diff.tickmarkView.render();
-				}
+		updateDiff: function() {
+			this.model.diffs.ensure( this.model.get('diffId'), this ).done( function( diff ) {
+				if ( this.model.get('diffId') !== diff.id )
+					return;
+				this.views.set( '.revisions-diff-frame', new revisions.view.Diff({
+					model: diff
+				}));
+			});
+		}
+	});
 
-				Diff.leftDiffStart = isRtl ? ui.values[1] : ui.values[0]; // in RTL mode the 'left handle' is the second in the slider, 'right' is first
+	// The control view.
+	// This contains the revision slider, previous/next buttons, and the compare checkbox.
+	revisions.view.Controls = wp.Backbone.View.extend({
+		tagName: 'div',
+		className: 'revisions-controls',
 
-			} else {
-				// Right handler
-				if ( Diff.rightModelLoading || 0 === Diff.rightHandleRevisions.length) // right model still loading, prevent sliding right handle
-					return false;
+		initialize: function() {
+			// Add the button view
+			this.views.add( new revisions.view.Buttons({ 
+				model: this.model
+			}));
 
-				if ( Diff.revisionView.model !== Diff.rightHandleRevisions &&
-						null !== Diff.rightHandleRevisions ) {
-					Diff.revisionView.model = Diff.rightHandleRevisions; // use the right handle models
-					Diff.tickmarkView.model = Diff.rightHandleRevisions;
-					Diff.tickmarkView.render();
-				}
+			// Add the Slider view
+			this.views.add( new revisions.view.Slider({
+				model: this.model
+			}) );
 
-				Diff.revisionView.draggingLeft = false;
-				Diff.rightDiffStart = isRtl ? ui.values[0] : ui.values[1]; // in RTL mode the 'left handle' is the second in the slider, 'right' is first
-			}
-		},
+			// Add the Meta view
+			this.views.add( new revisions.view.Meta({
+				model: this.model
+			}) );
+		}
+	});
 
-		/**
-		 * responds to slider stop events
-		 * in two handled mode, if the handle that stopped has moved, reload the diffs for the other handle
-		 * the other handle compares to this handle's position, so if it changes they need to be recalculated
-		 */
-		stop: function( event, ui ) {
-			// Not needed in one mode
-			if ( this.singleRevision )
-				return;
+	// The meta view.
+	// This contains the revision meta, and the restore button.
+	revisions.view.Meta = wp.Backbone.View.extend({
+		tagName: 'div',
+		className: 'revisions-meta',
+		template: wp.template('revisions-meta'),
 
-			// calculate and generate a diff for comparing to the left handle
-			// and the right handle, swap out when dragging
-			if ( $( ui.handle ).hasClass( 'left-handle' ) ) {
-				// Left handler
-				if ( Diff.leftDiffStart !== isRtl ? ui.values[1] : ui.values[0] ) // in RTL mode the 'left handle' is the second in the slider, 'right' is first
-					Diff.reloadRight();
-			} else {
-				// Right handler
-				if ( Diff.rightDiffStart !== isRtl ? ui.values[0] : ui.values[1] ) // in RTL mode the 'left handle' is the second in the slider, 'right' is first
-					Diff.reloadLeft();
-			}
+		initialize: function() {
+			this.listenTo( this.model, 'change:diffId', this.updateMeta );
 		},
 
-		addTooltip: function( handle, message ) {
-			handle.find( '.ui-slider-tooltip' ).html( message );
+		events: {
+			'click #restore-revision': 'restoreRevision'
 		},
 
-		width: function() {
-			return $( '#diff-slider' ).width();
+		restoreRevision: function() {
+			var restoreUrl    = this.model.get('to').attributes.restoreUrl.replace(/&amp;/g, '&');
+			document.location = restoreUrl;
 		},
 
-		setWidth: function( width ) {
-			$( '#diff-slider' ).width( width );
-		},
-
-		refresh: function( options, slide ) {
-			$( '#diff-slider' ).slider( 'option', options );
-
-			// Triggers the slide event
-			if ( slide )
-				$( '#diff-slider' ).trigger( 'slide' );
-
-			Diff.disabledButtonCheck( options.value );
-		},
-
-		option: function( key ) {
-			return $( '#diff-slider' ).slider( 'option', key );
-		},
-
-		render: function() {
-			var self = this;
-			// this.$el doesn't work, why?
-			$( '#diff-slider' ).slider( {
-				slide: $.proxy( self.slide, self ),
-				start: $.proxy( self.start, self ),
-				stop:  $.proxy( self.stop, self )
-			} );
-
-			// Set options
-			this.refresh( this.options );
+		updateMeta: function() {
+			this.$el.html( this.template( this.model.toJSON() ) );
+			if( this.model.get( 'to' ).attributes.current ) {
+				$( '#restore-revision' ).prop( 'disabled', true);
+			} else {
+				$( '#restore-revision' ).prop( 'disabled', false)
+			}
 		}
 	});
 
-	/**
-	 * wp.revisions.view.Tickmarks
-	 *
-	 * The slider tickmarks.
-	 */
-	revisions.view.Tickmarks = Backbone.View.extend({
-		el: $('#diff-slider-ticks'),
-		template: wp.template('revision-ticks'),
-		model: Revision,
 
-		resetTicks: function() {
-			var sliderMax, sliderWidth, adjustMax, tickWidth, tickCount = 0, aTickWidth, tickMargin, self = this, firstTick, lastTick;
-			sliderMax   = Diff.slider.option( 'max' );
-			sliderWidth = Diff.slider.width();
-			adjustMax   = Diff.singleRevision ? 0 : 1;
-			tickWidth   = Math.floor( sliderWidth / ( sliderMax - adjustMax ) );
-			tickWidth   = ( tickWidth > 50 ) ? 50 : tickWidth; // set minimum and maximum widths for tick marks
-			tickWidth   = ( tickWidth < 6 ) ? 6 : tickWidth;
-			sliderWidth = tickWidth * ( sliderMax - adjustMax ); // calculate the slider width
-			aTickWidth  = $( '.revision-tick' ).width();
+	// The buttons view.
+	// Encapsulates all of the configuration for the previous/next buttons, and the compare checkbox.
+	revisions.view.Buttons = wp.Backbone.View.extend({
+		tagName: 'div',
+		className: 'revisions-buttons',
+		template: wp.template('revisions-controls'),
 
-			if ( tickWidth !== aTickWidth ) { // is the width already set correctly?
-				$( '.revision-tick' ).each( function() {
-					tickMargin = Math.floor( ( tickWidth - $( this ).width() ) / 2 ) + 1;
-					$( this ).css( 'border-left', tickMargin + 'px solid #f7f7f7'); // space the ticks out using margins
-					$( this ).css( 'border-right', ( tickWidth - tickMargin - $( this ).width() ) + 'px solid #f7f7f7'); // space the ticks out using margins
-				});
-				firstTick = $( '.revision-tick' ).first(); //cache selectors for optimization
-				lastTick = $( '.revision-tick' ).last();
-
-				sliderWidth = sliderWidth + Math.ceil( ( tickWidth - ( lastTick.outerWidth() - lastTick.innerWidth() ) ) / 2 ); // room for the last tick
-				sliderWidth = sliderWidth + Math.ceil( ( tickWidth - ( firstTick.outerWidth() - firstTick.innerWidth() ) ) / 2 ); // room for the first tick
-				firstTick.css( 'border-left', 'none' ); // first tick gets no left border
-				lastTick.css( 'border-right', 'none' ); // last tick gets no right border
-			}
-
-			/**
-			 * reset the slider width
-			 */
-			Diff.slider.setWidth( sliderWidth );
-			$( '.diff-slider-ticks-wrapper' ).width( sliderWidth );
-			$( '#diff-slider-ticks' ).width( sliderWidth );
-
-			/**
-			 * go through all ticks, add hover and click interactions
-			 */
-			$( '.revision-tick' ).each( function() {
-				Diff.slider.addTooltip ( $( this ), Diff.revisions.at( tickCount++ ).get( 'titleTooltip' ) );
-				$( this ).hover(
-					function() {
-						$( this ).find( '.ui-slider-tooltip' ).show().append('<div class="arrow"></div>');
-					},
-					function() {
-						$( this ).find( '.ui-slider-tooltip' ).hide().find( '.arrow' ).remove();
-					}
-				);
-
-				/**
-				 * move the slider handle when the tick marks are clicked
-				 */
-				$( this ).on( 'click',
-					{ tickCount: tickCount }, // pass the tick through so we know where to move the handle
-					function( event ) {
-						if ( Diff.slider.singleRevision ) { // single handle mode
-							Diff.rightDiff = event.data.tickCount; // reposition the right handle
-							Diff.slider.refresh({
-								value: Diff.rightDiff - 1
-							} );
-						} else { //compare two mode
-							if ( isRtl ) {
-								if ( event.data.tickCount < Diff.leftDiff ) { // click was on the 'left' side
-										Diff.rightDiff = event.data.tickCount; // set the 'right' handle location
-										Diff.reloadLeft(); // reload the left handle comparison models
-								} else { // middle or 'right' clicks
-									Diff.leftDiff = event.data.tickCount; // set the 'left' handle location
-									Diff.reloadRight(); // reload right handle models
-								}
-							} else {
-								if ( event.data.tickCount < Diff.leftDiff ) { // click was on the 'left' side
-										Diff.leftDiff = event.data.tickCount; // set the left handle location
-										Diff.reloadRight(); // reload the right handle comparison models
-								} else { // middle or 'right' clicks
-									Diff.rightDiff = event.data.tickCount; // set the right handle location
-									Diff.reloadLeft(); // reload left handle models
-								}
-							}
-							Diff.slider.refresh( { // set the slider handle positions
-								values: [ isRtl ? Diff.rightDiff : Diff.leftDiff, isRtl ? Diff.leftDiff : Diff.rightDiff ]
-							} );
-						}
-						Diff.revisionView.render(); // render the main view
-					} );
-			} );
+		initialize: function() {
+			this.$el.html( this.template() )
 		},
 
-		// render the tick mark view
-		render: function() {
-			var self = this, addHtml;
-
-			if ( null !== self.model ) {
-				addHtml = "";
-				_.each ( self.model.models, function( theModel ) {
-					addHtml = addHtml + self.template ( theModel.toJSON() );
-				});
-				self.$el.html( addHtml );
-
-			}
-			self.resetTicks();
-			return self;
-		}
-	} );
-
-	/**
-	 * wp.revisions.view.Interact
-	 *
-	 * Next/Prev buttons and the slider
-	 */
-	revisions.view.Interact = Backbone.View.extend({
-		el: $( '#revision-interact' ),
-		template: wp.template( 'revision-interact' ),
-
-		// next and previous buttons, only available in compare one mode
 		events: {
-			'click #next':     ! isRtl ? 'nextRevision' : 'previousRevision',
-			'click #previous': ! isRtl ? 'previousRevision' : 'nextRevision'
+			'click #next': 'nextRevision',
+			'click #previous': 'previousRevision'
 		},
+		
+		nextRevision: function() {
+			var toIndex = this.model.revisions.indexOf( this.model.get( 'to' ) );
+			toIndex     = isRtl ? toIndex - 1 : toIndex + 1;
+			this.model.set( { 'to': this.model.revisions.at( toIndex ) } );
+		},
+		
+		previousRevision: function() {
+			var toIndex = this.model.revisions.indexOf( this.model.get('to') );
+			toIndex     = isRtl ? toIndex + 1 : toIndex - 1;
+			this.model.set( { 'to': this.model.revisions.at( toIndex ) } );
+		},
 
-		render: function() {
-			var modelcount;
-			this.$el.html( this.template );
-
-			modelcount = Diff.revisions.length;
-
-			Diff.slider.singleRevision = Diff.singleRevision;
-			Diff.slider.render();
-
-			if ( Diff.singleRevision ) {
-				Diff.slider.refresh({
-					value: Diff.rightDiff - 1, // rightDiff value is off model index by 1
-					min: 0,
-					max: modelcount - 1
-				});
-
-				$( '#revision-diff-container' ).removeClass( 'comparing-two-revisions' );
-
-			} else {
-				Diff.slider.refresh({
-					// in RTL mode the 'left handle' is the second in the slider, 'right' is first
-					values: [ isRtl ? Diff.rightDiff : Diff.leftDiff, isRtl ? Diff.leftDiff : Diff.rightDiff ],
-					min: 1,
-					max: modelcount + 1,
-					range: true
-				});
-
-				$( '#revision-diff-container' ).addClass( 'comparing-two-revisions' );
-				// in RTL mode the 'left handle' is the second in the slider, 'right' is first
-				$( '#diff-slider a.ui-slider-handle' ).first().addClass( isRtl ? 'right-handle' : 'left-handle' );
-				$( '#diff-slider a.ui-slider-handle' ).last().addClass( isRtl ? 'left-handle' : 'right-handle' );
-
-			}
-
-			return this;
+		ready: function() {
+			this.listenTo( this.model, 'change:diffId', this.disabledButtonCheck );
 		},
 
-		// go to the next revision
-		nextRevision: function() {
-			if ( Diff.rightDiff < this.model.length ) // unless at right boundry
-				Diff.rightDiff = Diff.rightDiff + 1 ;
+		// Check to see if the Previous or Next buttons need to be disabled or enabled
+		disabledButtonCheck: function() {
+			var maxVal   = isRtl ? 0 : this.model.revisions.length - 1,
+				minVal   = isRtl ? this.model.revisions.length - 1 : 0,
+				next     = $( '.revisions-next .button' ),
+				previous = $( '.revisions-previous .button' ),
+				val      = this.model.revisions.indexOf( this.model.get( 'to' ) );
 
-			Diff.revisionView.render();
+			// Disable "Next" button if you're on the last node
+			if ( maxVal === val )
+				next.prop( 'disabled', true );
+			else
+				next.prop( 'disabled', false );
 
-			Diff.slider.refresh({
-				value: Diff.rightDiff - 1
-			}, true );
+			// Disable "Previous" button if you're on the first node
+			if ( minVal === val )
+				previous.prop( 'disabled', true );
+			else
+				previous.prop( 'disabled', false );
 		},
 
-		// go to the previous revision
-		previousRevision: function() {
-			if ( Diff.rightDiff > 1 ) // unless at left boundry
-				Diff.rightDiff = Diff.rightDiff - 1 ;
 
-			Diff.revisionView.render();
-
-			Diff.slider.refresh({
-				value: Diff.rightDiff - 1
-			}, true );
-		}
 	});
 
-	/**
-	 * wp.revisions.view.Diff
-	 *
-	 * Diff, compare two checkbox and restore button
-	 */
-	revisions.view.Diff = Backbone.View.extend({
-		el: $( '#revisions-diff' ),
-		template: wp.template( 'revisions-diff' ),
-		draggingLeft: false,
+	// The slider view.
+	// Encapsulates all of the configuration for the jQuery UI slider into a view.
+	revisions.view.Slider = wp.Backbone.View.extend({
+		tagName: 'div',
+		className: 'wp-slider',
 
-		// the compare two button is in this view, add the interaction here
-		events: {
-			'click #compare-two-revisions': 'compareTwo',
-			'click #restore-revision':      'restore'
-		},
+		initialize: function() {
+			_.bindAll( this, 'start', 'slide', 'stop' );
 
-		// render the revisions
-		render: function() {
-			var addHtml = '', thediff;
+			// Create the slider model from the provided collection data.
+			// TODO: This should actually pull from the model's `to` key.
+			var latestRevisionIndex = this.model.revisions.length - 1;
 
-			// compare two revisions mode?
-			if ( ! Diff.singleRevision ) {
-				if ( this.draggingLeft ) {
-					thediff = Diff.leftDiff - 1; //leftDiff value is off model index by 1
-					if ( this.model.at( thediff ) ) {
-						addHtml = this.template( this.model.at( thediff ).toJSON() );
-					}
-				} else { // dragging right handle
-					thediff = Diff.rightDiff - 1; // rightDiff value is off model index by 1
-					if ( this.model.at( thediff ) ) {
-						addHtml = this.template( this.model.at( thediff ).toJSON() );
-					}
-				}
-			} else { // end compare two revisions mode, eg only one slider handle
-				if ( this.model.at( Diff.rightDiff - 1 ) ) { // rightDiff value is off model index by 1
-					addHtml = this.template( this.model.at( Diff.rightDiff - 1 ).toJSON() );
-				}
-			}
-			this.$el.html( addHtml );
+			// Find the initially selected revision
+			var initiallySelectedRevisionIndex =
+				this.model.revisions.indexOf( 
+					this.model.revisions.findWhere(  { id: Number( revisions.settings.selectedRevision ) } ) );
 
-			if ( this.model.length < 2 ) {
-				$( '#diff-slider' ).hide(); // don't allow compare two if fewer than three revisions
-				$( '.diff-slider-ticks-wrapper' ).hide();
-			}
+			this.settings = new revisions.model.Slider({
+				max:   latestRevisionIndex,
+				value: initiallySelectedRevisionIndex,
+				start: this.start,
+				slide: this.slide,
+				stop:  this.stop
+			});
+		},
 
-			this.toggleCompareTwoCheckbox();
+		ready: function() {
+			this.$el.slider( this.settings.toJSON() );
+			this.settings.on( 'change', function( model, options ) {
+				// Apply changes to slider settings here.
+ 				this.$el.slider( { value: this.model.revisions.indexOf( this.model.get( 'to' ) ) } ); // Set handle to current to model
+			}, this );
+			// Reset to the initially selected revision
+			this.slide( '', this.settings.attributes );
 
-			// hide the restore button when on the last sport/current post data
-			$( '#restore-revision' ).toggle( ! Diff.revisions.at( Diff.rightDiff - 1 ).get( 'isCurrent' ) );
+			// Listen for changes in the diffId
+			this.listenTo( this.model, 'change:diffId', this.diffIdChanged );
 
-			return this;
 		},
 
-		toggleCompareTwoCheckbox: function() {
-			// don't allow compare two if fewer than three revisions
-			if ( this.model.length < 3 )
-				$( '#toggle-revision-compare-mode' ).hide();
-
-			$( '#compare-two-revisions' ).prop( 'checked', ! Diff.singleRevision );
+		diffIdChanged: function() {
+			// Reset the view settings when diffId is changed
+			this.settings.set( { 'value': this.model.revisions.indexOf( this.model.get( 'to' ) ) } );
 		},
 
-		// turn on/off the compare two mode
-		compareTwo: function() {
-			if ( $( '#compare-two-revisions' ).is( ':checked' ) ) { // compare 2 mode
-				Diff.singleRevision = false ;
+		start: function( event, ui ) {
+			// Track the mouse position to enable smooth dragging, overrides default jquery ui step behaviour 
+			$( window ).mousemove( function( e ) { 
+				var sliderLeft  = $( '.wp-slider' ).offset().left,
+					sliderRight = sliderLeft + $( '.wp-slider' ).width();
 
-				// in RTL mode handles are swapped, so boundary checks are different;
-				if ( isRtl ){
-					Diff.leftDiff = Diff.revisions.length; // put the left handle at the rightmost position, representing current revision
-
-					if ( Diff.revisions.length === Diff.rightDiff ) // make sure 'left' handle not in rightmost slot
-						Diff.rightDiff = Diff.rightDiff - 1;
+				// Follow mouse movements, as long as handle remains inside slider
+				if ( e.clientX < sliderLeft ) {
+					$( ui.handle ).css( 'left', 0 ); // Mouse to left of slider
+				} else if ( e.clientX > sliderRight ) {
+					$( ui.handle ).css( 'left', sliderRight - sliderLeft); // Mouse to right of slider
 				} else {
-					if ( 1 === Diff.rightDiff ) // make sure right handle not in leftmost slot
-						Diff.rightDiff = 2;
+					$( ui.handle ).css( 'left', e.clientX - sliderLeft ); // Mouse in slider
 				}
+			} ); // End mousemove 
+		},
 
-				Diff.revisionView.draggingLeft = false;
+		slide: function( event, ui ) {
+			var attributes = {
+				to: this.model.revisions.at( ui.value )
+			};
 
-				revisions.model.settings.revision_id = ''; // reset passed revision id so switching back to one handle mode doesn't re-select revision
-				Diff.reloadLeftRight(); // load diffs for left and right handles
-				Diff.revisionView.model = Diff.rightHandleRevisions;
+			// If we're at the first revision, unset 'from'.
+			if ( ui.value )
+				attributes.from = this.model.revisions.at( ui.value - 1 );
+			else
+				this.model.unset('from', { silent: true });
 
-			} else { // compare one mode
-				Diff.singleRevision = true;
-				Diff.revisionView.draggingLeft = false;
-				Diff.reloadModelSingle();
-			}
-			Diff.revisionsInteractions.render();
-			Diff.tickmarkView.render();
+			this.model.set( attributes );
 		},
 
-		restore: function() {
-			document.location = $( '#restore-revision' ).data( 'restoreLink' );
+		stop: function( event, ui ) {
+			$( window ).unbind( 'mousemove' ); // Stop tracking the mouse
+			// Reset settings pops handle back to the step position
+			this.settings.trigger( 'change' );
 		}
 	});
 
+	// The diff view.
+	// This is the view for the current active diff.
+	revisions.view.Diff = wp.Backbone.View.extend({
+		tagName: 'div',
+		className: 'revisions-diff',
+		template: wp.template('revisions-diff'),
 
-	/**
-	 * ========================================================================
-	 * MODELS
-	 * ========================================================================
-	 */
-
-	/**
-	 * wp.revisions.Revision
-	 */
-	Revision = revisions.model.Revision = Backbone.Model.extend({
-		idAttribute: 'ID',
-
-		defaults: {
-			ID: 0,
-			titleTo: '',
-			titleTooltip: '',
-			titleFrom: '',
-			diff: '<div class="diff-loading"><div class="spinner"></div></div>',
-			restoreLink: '',
-			completed: false,
-			linesAdded: 0,
-			linesDeleted: 0,
-			scopeOfChanges: 'none',
-			previousID: 0,
-			isCurrent: false
-		},
-
-		url: function() {
-			if ( Diff.singleRevision ) {
-				return ajaxurl +
-					'?action=revisions-data' +
-					'&show_autosaves=true' +
-					'&show_split_view=true' +
-					'&nonce=' + revisions.model.settings.nonce +
-					'&single_revision_id=' + this.id +
-					'&compare_to=' + this.get( 'previousID' ) +
-					'&post_id=' + revisions.model.settings.post_id;
-			} else {
-				return this.collection.url() + '&single_revision_id=' + this.id;
-			}
-
+		// Generate the options to be passed to the template.
+		prepare: function() {
+			return _.extend({ fields: this.model.fields.toJSON() }, this.options );
 		}
 	});
 
-	/**
-	 * wp.revisions.Revisions
-	 */
-	Revisions = revisions.Revisions = Backbone.Collection.extend({
-		model: Revision,
+	// Initialize the revisions UI.
+	revisions.init = function() {
+		revisions.view.frame = new revisions.view.Frame({
+			collection: new revisions.model.Revisions( revisions.settings.revisionData )
+		}).render();
+	};
 
-		initialize: function( models, options ) {
-			this.options = _.defaults( options || {}, {
-				'compareTo': revisions.model.settings.post_id,
-				'post_id': revisions.model.settings.post_id,
-				'showAutosaves': true,
-				'showSplitView': true,
-				'rightHandleAt': 0,
-				'leftHandleAt': 0,
-				'nonce': revisions.model.settings.nonce
-			});
-		},
-
-		url: function() {
-			return ajaxurl +
-				'?action=revisions-data' +
-				'&compare_to=' + this.options.compareTo + // revision are we comparing to
-				'&post_id=' + this.options.post_id + // the post id
-				'&show_autosaves=' + this.options.showAutosaves + // show or hide autosaves
-				'&show_split_view=' + this.options.showSplitView + // show in split view or single column view
-				'&right_handle_at=' + this.options.rightHandleAt + // mark point for comparison list
-				'&left_handle_at=' + this.options.leftHandleAt + // mark point for comparison list
-				'&nonce=' + this.options.nonce;
-		},
-
-		reload: function( options ) {
-			this.options = _.defaults( options.options || {}, this.options );
-
-			this.fetch({
-				success: options.success || null,
-				error: options.error || null
-			});
-		}
-
-	} );
-
-	$( wp.revisions );
-
+	$( revisions.init );
 }(jQuery));
Index: wp-admin/revision.php
===================================================================
--- wp-admin/revision.php	(revision 24458)
+++ wp-admin/revision.php	(working copy)
@@ -8,6 +8,12 @@
 
 /** WordPress Administration Bootstrap */
 require_once('./admin.php');
+
+require ABSPATH . 'wp-admin/includes/revision.php';
+
+// wp_get_revision_ui_diff( $post, $compare_from, $compare_to )
+// wp_prepare_revisions_for_js( $post )
+
 wp_reset_vars( array( 'revision', 'action' ) );
 
 $revision_id = absint( $revision );
@@ -21,7 +27,6 @@
 	if ( ! current_user_can( 'edit_post', $revision->post_parent ) )
 		break;
 
-
 	if ( ! $post = get_post( $revision->post_parent ) )
 		break;
 
@@ -77,16 +82,8 @@
 	$parent_file = $submenu_file = 'edit.php';
 
 wp_enqueue_script( 'revisions' );
+wp_localize_script( 'revisions', '_wpRevisionsSettings', wp_prepare_revisions_for_js( $post, $revision_id ) );
 
-
-$settings = array(
-	'post_id'     => $post->ID,
-	'nonce'       => wp_create_nonce( 'revisions-ajax-nonce' ),
-	'revision_id' => $revision_id
-);
-
-wp_localize_script( 'revisions', 'wpRevisionsSettings', $settings );
-
 /* Revisions Help Tab */
 
 $revisions_overview  = '<p>' . __( 'This screen is used for managing your content revisions.' ) . '</p>';
@@ -114,24 +111,73 @@
 
 <div class="wrap">
 	<?php screen_icon(); ?>
-	<div id="revision-diff-container" class="current-version right-model-loading">
-		<h2 class="long-header"><?php echo $h2; ?></h2>
+	<h2 class="long-header"><?php echo $h2; ?></h2>
+</div>
 
-		<div id="loading-status" class="updated message">
-			<p><span class="spinner" ></span></p>
+<script id="tmpl-revisions-frame" type="text/html">
+	<span class="spinner"></span>
+	<div class="revisions-control-frame"></div>
+	<div class="revisions-diff-frame"></div>
+</script>
+
+<script id="tmpl-revisions-controls" type="text/html">
+
+	<div class="revision-toggle-compare-mode">
+		<label>
+			<input type="checkbox" class="compare-two-revisions" />
+			<?php esc_attr_e( 'Compare two revisions' ); ?>
+		</label>
+	</div>
+
+	<div class="revisions-previous">
+		<input class="button" type="button" id="previous" value="<?php echo esc_attr_x( 'Previous', 'Button label for a previous revision' ); ?>" />
+	</div>
+
+	<div class="revisions-next">
+		<input class="button" type="button" id="next" value="<?php echo esc_attr_x( 'Next', 'Button label for a next revision' ); ?>" />
+	</div>
+</script>
+
+
+<script id="tmpl-revisions-meta" type="text/html">
+	<div id="diff-header">
+		<div id="diff-header-from" class="diff-header">
+			<div id="diff-title-from" class="diff-title">
+				<strong>
+				<?php _ex( 'From:', 'Followed by post revision info' ); ?></strong>
+					<# if ( 'undefined' !== typeof data.from ) { #>
+						{{{ data.from.attributes.author.avatar }}} {{{ data.from.attributes.author.name }}},
+						{{{ data.from.attributes.timeAgo }}} <?php _e( 'ago' ); ?>
+						({{{ data.from.attributes.dateShort }}})
+					<# } #>
+
+			</div>
+			<div class="clear"></div>
 		</div>
 
-		<div class="diff-slider-ticks-wrapper">
-			<div id="diff-slider-ticks"></div>
+		<div id="diff-header-to" class="diff-header">
+			<div id="diff-title-to" class="diff-title">
+				<strong><?php _ex( 'To:', 'Followed by post revision info' ); ?></strong>
+					<# if ( 'undefined' !== typeof data.to ) { #>
+						{{{ data.to.attributes.author.avatar }}} {{{ data.to.attributes.author.name }}},
+						{{{ data.to.attributes.timeAgo }}} <?php _e( 'ago' ); ?>
+						({{{ data.to.attributes.dateShort }}})
+					<# } #>
 		</div>
 
-		<div id="revision-interact"></div>
-
-		<div id="revisions-diff"></div>
+			<input type="button" id="restore-revision" class="button button-primary" data-restore-link="{{{ data.restoreLink }}}" value="<?php esc_attr_e( 'Restore This Revision' )?>" />
+		</div>
 	</div>
-</div>
+</script>
 
 <script id="tmpl-revisions-diff" type="text/html">
+	<# _.each( data.fields, function( field ) { #>
+		<h3>{{{ field.name }}}</h3>
+		{{{ field.diff }}}
+	<# }); #>
+</script>
+
+<script id="tmpl-revisions-diff-old" type="text/html">
 	<div id="toggle-revision-compare-mode">
 		<label>
 			<input type="checkbox" id="compare-two-revisions" />
@@ -157,12 +203,10 @@
 		</div>
 	</div>
 
-	</div>
-
 	<div id="diff-table">{{{ data.diff }}}</div>
 </script>
 
-<script id="tmpl-revision-interact" type="text/html">
+<script id="tmpl-revision-interact-old" type="text/html">
 	<div id="diff-previous-revision">
 		<input class="button" type="button" id="previous" value="<?php echo esc_attr_x( 'Previous', 'Button label for a previous revision' ); ?>" />
 	</div>
@@ -171,7 +215,6 @@
 		<input class="button" type="button" id="next" value="<?php echo esc_attr_x( 'Next', 'Button label for a next revision' ); ?>" />
 	</div>
 
-	<div id="diff-slider" class="wp-slider"></div>
 </script>
 
 <script id="tmpl-revision-ticks" type="text/html">
Index: wp-admin/css/wp-admin.css
===================================================================
--- wp-admin/css/wp-admin.css	(revision 24458)
+++ wp-admin/css/wp-admin.css	(working copy)
@@ -3481,7 +3481,49 @@
 /*------------------------------------------------------------------------------
   11.2 - Post Revisions
 ------------------------------------------------------------------------------*/
+.revisions .spinner {
+	float: none;
+	margin: 100px auto;
+}
 
+.revisions.loading .spinner {
+	display: block;
+}
+
+.revisions-control-frame,
+.revisions-diff-frame {
+	position: relative;
+}
+
+.revisions-controls {
+	height: 60px;
+	padding: 40px 0 20px;
+	border-bottom: 1px solid #dfdfdf;
+	margin-bottom: 10px;
+}
+
+.revisions-meta {
+	margin-top: 15px;
+}
+.revision-toggle-compare-mode {
+	position: absolute;
+	top: 0;
+	right: 0;
+}
+
+.revisions-previous {
+	float: left;
+}
+
+.revisions-next {
+	float: right;
+}
+
+.wp-slider {
+	width: 70%;
+	margin: 6px auto 0;
+}
+
 /* Revision meta box */
 .post-revisions li img,
 #revisions-meta-restored img {
@@ -3527,13 +3569,6 @@
 	position: relative;
 }
 
-#toggle-revision-compare-mode {
-	position: absolute;
-	top: 0;
-	right: 0;
-	padding: 9px 9px 0 0;
-}
-
 #loading-status {
 	display: none;
 	position: absolute;
@@ -3551,24 +3586,6 @@
 	padding: 20px 0;
 }
 
-#diff-next-revision,
-#diff-previous-revision {
-	margin-top: -.4em; /* Same line as the slider (height: .8em) */
-}
-
-#diff-next-revision {
-	float: right;
-}
-
-#diff-previous-revision {
-	float: left;
-}
-
-#diff-slider {
-	width: 70%;
-	margin: 0 auto;
-}
-
 .comparetwo #diff-slider {
 	width: 95%;
 }
@@ -3588,7 +3605,7 @@
 }
 
 #diff-title-to strong {
-	display: none;
+	display: inline;
 }
 
 .comparing-two-revisions #diff-title-to strong {
@@ -3605,6 +3622,7 @@
 	-webkit-border-radius: 3px;
 	border-radius: 3px;
 	padding: 5px 200px 5px 5px;
+	clear: both;
 }
 
 .diff-header {
