diff --git a/wp-admin/includes/ajax-actions.php b/wp-admin/includes/ajax-actions.php index b3d558209f..4878e4ad41 100644 --- a/wp-admin/includes/ajax-actions.php +++ b/wp-admin/includes/ajax-actions.php @@ -2092,22 +2092,22 @@ function wp_ajax_heartbeat() { function wp_ajax_revisions_data() { check_ajax_referer( 'revisions-ajax-nonce', 'nonce' ); - $compare_to = isset( $_GET['compare_to'] ) ? absint( $_GET['compare_to'] ) : 0; - $show_autosaves = isset( $_GET['show_autosaves'] ) ? $_GET['show_autosaves'] : ''; - $show_split_view = isset( $_GET['show_split_view'] ) ? $_GET['show_split_view'] : ''; - $post_id = isset( $_GET['post_id'] ) ? absint( $_GET['post_id'] ) : ''; - $right_handle_at = isset( $_GET['right_handle_at'] ) ? $_GET['right_handle_at'] : 0; - $left_handle_at = isset( $_GET['left_handle_at'] ) ? $_GET['left_handle_at'] : 0; - $single_revision_id = isset( $_GET['single_revision_id'] ) ? $_GET['single_revision_id'] : 0; + $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; - $compare_two_mode = ( '' == $post_id ) ? false : true; // //TODO: currently code returns all possible comparisons for the indicated 'compare_to' revision //however, the front end prevents users from pulling the right handle past the left or the left pass the right, //so only the possible diffs need be generated // - $alltherevisions = array(); - if ( '' == $post_id ) + $all_the_revisions = array(); + if ( ! $post_id ) $post_id = $compare_to; if ( ! current_user_can( 'read_post', $post_id ) ) @@ -2116,33 +2116,26 @@ function wp_ajax_revisions_data() { if ( ! $revisions = wp_get_post_revisions( $post_id ) ) return; - /* translators: revision date format, see http://php.net/date */ - $datef = _x( 'j F, Y @ G:i:s', 'revision date format'); - $left_revision = get_post( $compare_to ); //single model fetch mode //return the diff of a single revision comparison - if ( 0 != $single_revision_id ) { + if ( $single_revision_id ) { $right_revision = get_post( $single_revision_id ); - if ( 0 == $compare_to ) + if ( ! $compare_to ) $left_revision = get_post( $post_id ); - // make sure the right revision is the most recent - if ( $compare_two_mode && $right_revision->ID < $left_revision->ID ) { - $temp = $left_revision; - $left_revision = $right_revision; - $right_revision = $temp; - } + // make sure the right revision is the most recent + if ( $compare_two_mode && $right_revision->ID < $left_revision->ID ) { + $temp = $left_revision; + $left_revision = $right_revision; + $right_revision = $temp; + } - $linesadded=0; - $linesdeleted=0; - - // + $lines_added = $lines_deleted = 0; + $content = ''; //compare from left to right, passed from application - // - $content=''; foreach ( array_keys( _wp_post_revision_fields() ) as $field ) { $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' ); @@ -2151,31 +2144,30 @@ function wp_ajax_revisions_data() { $args = array(); - if ( ! empty( $show_split_view ) ) + 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 ); + $diff = wp_text_diff_with_count( ( 0 == $compare_to ) ? '' : $left_content, $right_content, $args ); if ( isset( $diff[ 'html' ] ) ) $content .= $diff[ 'html' ]; - if ( isset( $diff[ 'linesadded' ] ) ) - $linesadded = $linesadded + $diff[ 'linesadded' ]; - - if ( isset( $diff[ 'linesdeleted' ] ) ) - $linesdeleted = $linesdeleted + $diff[ 'linesdeleted' ]; - + 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; - $alltherevisions = array ( - 'revisiondiff' => $content, - 'lines_deleted' => $linesdeleted, - 'lines_added' => $linesadded + $all_the_revisions = array ( + 'diff' => $content, + 'lines_deleted' => $lines_deleted, + 'lines_added' => $lines_added ); - echo json_encode( $alltherevisions ); + + echo json_encode( $all_the_revisions ); exit(); } //end single model fetch @@ -2186,18 +2178,20 @@ function wp_ajax_revisions_data() { $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 ) : - //error_log( ( $show_autosaves )); - if ( empty( $show_autosaves ) && wp_is_post_autosave( $revision ) ) - continue; + if ( ! $show_autosaves && wp_is_post_autosave( $revision ) ) + continue; $revision_from_date_author = ''; $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) - if ( ( 0 != $left_handle_at && $count <= $left_handle_at ) || - ( 0 != $right_handle_at && $count > $right_handle_at )) { - $alltherevisions[] = array ( + 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; @@ -2230,11 +2224,11 @@ function wp_ajax_revisions_data() { $date ); - $autosavef = __( '%1$s [Autosave]' ); - $currentf = __( '%1$s [Current Revision]' ); + $autosavef = _x( '%1$s [Autosave]', 'post revision title extra' ); + $currentf = _x( '%1$s [Current Revision]', 'post revision title extra' ); - if ( ! $post = get_post( $post_id)) - exit(); + 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 ); @@ -2246,7 +2240,8 @@ function wp_ajax_revisions_data() { elseif ( wp_is_post_autosave( $revision ) ) $revision_date_author = sprintf( $autosavef, $revision_date_author ); - $date_short_format = __( 'j M @ G:i' ); + /* 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( @@ -2256,7 +2251,7 @@ function wp_ajax_revisions_data() { $date_short ); - $restoreaction = wp_nonce_url( + $restore_link = wp_nonce_url( add_query_arg( array( 'revision' => $revision->ID, 'action' => 'restore' ), @@ -2264,20 +2259,22 @@ function wp_ajax_revisions_data() { ), "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 ) ) { - $alltherevisions[] = array ( - 'ID' => $revision->ID, - 'revision_date_author' => $revision_date_author, - 'revision_from_date_author' => $revision_from_date_author, - 'revision_date_author_short' => $revision_date_author_short, - 'restoreaction' => urldecode( $restoreaction ), - 'revision_toload' => true, + $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 ), + 'revision_toload' => true, 'previous_revision_id' => $previous_revision_id ); } @@ -2285,6 +2282,6 @@ function wp_ajax_revisions_data() { endforeach; - echo json_encode( $alltherevisions ); + echo json_encode( $all_the_revisions ); exit(); } diff --git a/wp-admin/js/revisions.js b/wp-admin/js/revisions.js index 305919869e..34b7190e52 100644 --- a/wp-admin/js/revisions.js +++ b/wp-admin/js/revisions.js @@ -1,772 +1,769 @@ window.wp = window.wp || {}; (function($) { - wp.revisions = { + var Revision, Revisions, Diff, l10n, revisions; - views: {}, - - Model: Backbone.Model.extend({ - idAttribute: 'ID', - urlRoot: ajaxurl + '?action=revisions-data' + - '&show_autosaves=true&show_split_view=true&nonce=' + wpRevisionsSettings.nonce, - defaults: { - ID: 0, - revision_date_author: '', - revision_date_author_short: '', - revisiondiff: '
', - restoreaction: '', - revision_from_date_author: '', - revision_toload: false, - lines_added: 0, - lines_deleted: 0, - scope_of_changes: 'none', - previous_revision_id: 0 - }, - - url: function() { - if ( 1 === REVAPP._compareOneOrTwo ) { - return this.urlRoot + - '&single_revision_id=' + this.id + - '&compare_to=' + this.get( 'previous_revision_id' ) + - '&post_id=' + wpRevisionsSettings.post_id; - } else { - return this.urlRoot + - '&single_revision_id=' + this.id; - } - - } - - }), - - app: _.extend({}, Backbone.Events), - - App: Backbone.Router.extend({ - _revisions: null, - _leftHandleRevisions: null, - _rightHandleRevisions: null, - _revisionsInteractions: null, - _revisionsOptions: null, - _leftDiff: 1, - _rightDiff: 1, - _autosaves: true, - _showSplitView: true, - _compareOneOrTwo: 1, - _leftModelLoading: false, // keep track of model loads - _rightModelLoading: false, // disallow slider interaction, also repeat loads, while loading - _tickmarkView: null, // the slider tickmarks - - routes: { - }, - - reloadToLoadRevisions: function( model_collection, reverse_direction ) { - var self = this, - revisionsToLoad = model_collection.where( { revision_toload: true } ), - delay = 0; - // match slider to passed revision_id - _.each( revisionsToLoad, function( theModel ) { - if ( theModel.get( 'ID' ) == wpRevisionsSettings.revision_id ) { - self._rightDiff = self._revisions.indexOf( theModel ) + 1; - } - - }); - _.each( revisionsToLoad, function( theModel ) { - theModel.urlRoot = model_collection.url; - _.delay( function() { - theModel.fetch( { - update: true, - add: false, - remove: false, - success: function( model ) { - model.set( 'revision_toload', 'false' ); - - // stop spinner when all models are loaded - if ( 0 === model_collection.where( { revision_toload: true } ).length ) - self.stopModelLoadingSpinner(); - - self._tickmarkView.render(); - - var total_changes = model.get( 'lines_added' ) + model.get( 'lines_deleted'), - scope_of_changes = 'vsmall'; - - // Note: hard coded scope of changes - // TODO change to dynamic based on range of values - if ( total_changes > 1 && total_changes <= 3 ) { - scope_of_changes = 'small'; - } else if(total_changes > 3 && total_changes <= 5 ) { - scope_of_changes = 'med'; - } else if(total_changes > 5 && total_changes <= 10 ) { - scope_of_changes = 'large'; - } else if(total_changes > 10 ) { - scope_of_changes = 'vlarge'; - } - model.set( 'scope_of_changes', scope_of_changes ); - if ( 0 !== self._rightDiff && - model.get( 'ID' ) === self._revisions.at( self._rightDiff - 1 ).get( 'ID' ) ) { - // reload if current model refreshed - self._revisionView.render(); - } - - } - } ); - }, delay ) ; - delay = delay + 150; // stagger model loads to avoid hammering server with requests - } - ); - }, - - startLeftModelLoading: function() { - this._leftModelLoading = true; - $('.revisiondiffcontainer').addClass('leftmodelloading'); - }, - - stopLeftModelLoading: function() { - this._leftModelLoading = false; - }, - - startRightModelLoading: function() { - this._rightModelLoading = true; - $('.revisiondiffcontainer').addClass('rightmodelloading'); - }, - - stopRightModelLoading: function() { - this._rightModelLoading = false; - }, - - stopModelLoadingSpinner: function() { - $('.revisiondiffcontainer').removeClass('rightmodelloading'); - $('.revisiondiffcontainer').removeClass('leftmodelloading'); - }, - - reloadModel: function() { - if ( 2 === this._compareOneOrTwo ) { - this.reloadLeftRight(); - } else { - this.reloadModelSingle(); - } - }, - - // load the models for the single handle mode - reloadModelSingle: function() { - var self = this; - self._revisions.url = ajaxurl + '?action=revisions-data&compare_to=' + wpRevisionsSettings.post_id + - '&show_autosaves=' + self._autosaves + - '&show_split_view=' + self._showSplitView + - '&nonce=' + wpRevisionsSettings.nonce; - self.startRightModelLoading(); - self._revisions.fetch({ // reload revision data - success: function() { - console.log('loaded'); - // self.stopRightModelLoading(); - // REVAPP._rightDiff -= 1; - var revisionCount = self._revisions.length; - self._revisionView.model = self._revisions; - self._revisionView.render(); - self.reloadToLoadRevisions( self._revisions ); - self._tickmarkView.model = self._revisions; - self._tickmarkView.render(); - $( '#slider' ).slider( 'option', 'max', revisionCount - 1 ); // TODO: test this, if autosave option changed - $( '#slider' ).slider( 'value', self._rightDiff - 1 ).trigger( 'slide' ); - - }, - - error: function() { - self.stopRightModelLoading(); - } - - }); - }, - - // load the models for the left handle - reloadLeft: function() { - var self = this; - self.startLeftModelLoading(); - self._leftHandleRevisions = new wp.revisions.Collection(); - - self._leftHandleRevisions.url = - ajaxurl + - '?action=revisions-data&compare_to=' + self._revisions.at( self._rightDiff - 1 ).get( 'ID' ) + - '&post_id=' + wpRevisionsSettings.post_id + - '&show_autosaves=' + REVAPP._autosaves + - '&show_split_view=' + REVAPP._showSplitView + - '&nonce=' + wpRevisionsSettings.nonce + - '&right_handle_at=' + ( self._rightDiff ); - - self._leftHandleRevisions.fetch({ - - success: function(){ - self.stopLeftModelLoading(); - self.reloadToLoadRevisions( self._leftHandleRevisions ); - self._tickmarkView.model = self._leftHandleRevisions; - $( '#slider' ).slider( 'option', 'max', self._revisions.length ); - // ensure right handle not beyond length, in particular if viewing autosaves is switched from on to off - // the number of models in the collection might get shorter, this ensures right handle is not beyond last model - if ( self._rightDiff > self._revisions.length ) - self._rightDiff = self._revisions.length; - }, - - error: function() { - self.stopLeftModelLoading(); - } - }); - }, - - // load the models for the right handle - reloadRight: function() { - var self = this; - self.startRightModelLoading(); - self._rightHandleRevisions = new wp.revisions.Collection(); - - self._rightHandleRevisions.url = - ajaxurl + - '?action=revisions-data&compare_to=' + ( self._revisions.at( self._leftDiff ).get( 'ID' ) - 1 )+ - '&post_id=' + wpRevisionsSettings.post_id + - '&show_autosaves=' + REVAPP._autosaves + - '&show_split_view=' + REVAPP._showSplitView + - '&nonce=' + wpRevisionsSettings.nonce; - - self._rightHandleRevisions.fetch({ - - success: function(){ - self.stopRightModelLoading(); - self.reloadToLoadRevisions( self._rightHandleRevisions ); - self._tickmarkView.model = self._rightHandleRevisions; - $( '#slider' ).slider( 'option', 'max', self._revisions.length ); - $( '#slider' ).slider( 'values', [ REVAPP._leftDiff, REVAPP._rightDiff] ).trigger( 'slide' ); - - // REVAPP._revisionView.render(); - - }, - - error: function( response ) { - self.stopRightModelLoading(); - } - }); - - }, - - reloadLeftRight: function() { - this.startRightModelLoading(); - this.startLeftModelLoading(); - this.reloadLeft(); - this.reloadRight(); - }, - - /* - * initialize the revision application - */ - initialize: function( options ) { - var self = this; // store the application instance - if (this._revisions === null) { - self._revisions = new wp.revisions.Collection(); // set up collection - self.startRightModelLoading(); - self._revisions.fetch({ // load revision data - - success: function() { - self.stopRightModelLoading(); - // self._rightHandleRevisions = self._revisions; - self.completeApplicationSetup(); - } - }); - } - return this; - }, - - addTooltip: function( handle, message ) { - - handle.attr( 'title', '' ).tooltip({ - track: false, - - position: { - my: "left-30 top-66", - at: "top left", - using: function( position, feedback ) { - $( this ).css( position ); - $( "
" ) - .addClass( "arrow" ) - .addClass( feedback.vertical ) - .addClass( feedback.horizontal ) - .appendTo( $( this ) ); - } - }, - show: false, - hide: false, - content: function() { - return message; - } - - } ); - }, -/**/ - - completeApplicationSetup: function() { - this._revisionView = new wp.revisions.views.View({ - model: this._revisions - }); - this._revisionView.render(); - $( '#slider' ).slider( 'option', 'max', this._revisions.length - 1 ); - - this.reloadToLoadRevisions( this._revisions ); - - this._revisionsInteractions = new wp.revisions.views.Interact({ - model: this._revisions - }); - this._revisionsInteractions.render(); - - this._tickmarkView = new wp.revisions.views.Tickmarks({ - model: this._revisions - }); - this._tickmarkView.render(); - this._tickmarkView.resetTicks(); - - - /* - .on( 'mouseup', function( event ) { - REVAPP._keep_tooltip_open = false; - $( this ).find('.ui-slider-tooltip').hide(); - } ).on( 'mousedown', function( event ) { - REVAPP._keep_tooltip_open = true; - } ).on( 'mouseout', function( event ) { - if ( REVAPP._keep_tooltip_open) - event.stopImmediatePropagation(); - }); - */ - /* - // Options hidden for now, moving to screen options - this._revisionsOptions = new wp.revisions.views.Options({ - model: this._revisions - }); - this._revisionsOptions.render(); - */ - - } - }) + revisions = wp.revisions = function() { + Diff = revisions.Diff = new Diff(); }; - wp.revisions.Collection = Backbone.Collection.extend({ - model: wp.revisions.Model, - url: ajaxurl + '?action=revisions-data&compare_to=' + wpRevisionsSettings.post_id + - '&show_autosaves=true&show_split_view=true&nonce=' + wpRevisionsSettings.nonce, + _.extend( revisions, { model: {}, view: {}, controller: {} } ); - initialize: function() { - } - } ); + // Link any localized strings. + l10n = revisions.model.l10n = typeof wpRevisionsL10n === 'undefined' ? {} : wpRevisionsL10n; - _.extend(wp.revisions.views, { + // Link any settings. + revisions.model.settings = l10n.settings || {}; + delete l10n.settings; - // Ticks inside slider view - Tickmarks: Backbone.View.extend({ - el: $('#diff-slider-ticks')[0], - tagName: 'diff-slider-ticks-view', - className: 'diff-slider-ticks-container', - template: wp.template('revision-ticks'), - model: wp.revisions.Model, - resetTicks: function() { - var sliderMax = $( '#slider' ).slider( 'option', 'max'); - var sliderWidth = $( '#slider' ).width(); - var adjustMax = ( 2 === REVAPP._compareOneOrTwo ) ? 1 : 0; - var tickWidth = Math.floor( sliderWidth / ( sliderMax - adjustMax ) ); + /** + * ======================================================================== + * CONTROLLERS + * ======================================================================== + */ - // TODO: adjust right margins for wider ticks so they stay centered on handle stop point + /** + * 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 - // set minimum and maximum widths for tick marks - tickWidth = (tickWidth > 50 ) ? 50 : tickWidth; - tickWidth = (tickWidth < 10 ) ? 10 : tickWidth; + constructor: function() { + this.slider = new revisions.view.Slider(); + if ( null === this.revisions ) { + this.revisions = new Revisions(); // set up collection + this.startRightModelLoading(); - sliderWidth = tickWidth * (sliderMax - adjustMax ) + 1; - - $( '#slider' ).width( sliderWidth ); - $( '.diff-slider-ticks-wrapper' ).width( sliderWidth ); - $( '#diffslider' ).width( sliderWidth ); - $( '#diff-slider-ticks' ).width( sliderWidth ); - - var aTickWidth = $( '.revision-tick' ).width(); - - if ( tickWidth !== aTickWidth ) { // is the width already set correctly? - $( '.revision-tick' ).each( function( ) { - $(this).css( 'margin-right', tickWidth - 1 + 'px'); // space the ticks out using right margin - }); - - if( 2 === REVAPP._compareOneOrTwo ) { - $( '.revision-tick' ).first().remove(); // TODO - remove the check - } - $( '.revision-tick' ).last().css( 'margin-right', '0' ); // last tick gets no right margin - } - - }, - - // render the tickmark view - render: function() { var self = this; - - if ( null !== self.model ) { - var addHtml = ""; - _.each ( self.model.models, function( theModel ) { - addHtml = addHtml + self.template ( theModel.toJSON() ); - }); - self.$el.html( addHtml ); - - } - self.resetTicks(); - return self; - } - }), - - // primary revision diff view - View: Backbone.View.extend({ - el: $('#backbonerevisionsdiff')[0], - tagName: 'revisionvview', - className: 'revisionview-container', - template: wp.template('revision'), - comparetwochecked: '', - draggingLeft: false, - - // render the revisions - render: function() { - var addHtml = ''; - var thediff; - // compare two revisions mode? - - if ( 2 === REVAPP._compareOneOrTwo ) { - - this.comparetwochecked = 'checked'; - if ( this.draggingLeft ) { - thediff = REVAPP._leftDiff -1; - if ( this.model.at( thediff ) ) { - addHtml = this.template( _.extend( - this.model.at( thediff ).toJSON(), - { comparetwochecked: this.comparetwochecked } // keep the checkmark checked - ) ); - } - } else { // dragging right handle - thediff = REVAPP._rightDiff -1; - if ( this.model.at( thediff ) ) { - addHtml = this.template( _.extend( - this.model.at( thediff ).toJSON(), - { comparetwochecked: this.comparetwochecked } // keep the checkmark checked - ) ); - } + this.revisions.fetch({ // load revision data + success: function() { + self.stopRightModelLoading(); + self.completeApplicationSetup(); } - } else { // end compare two revisions mode, eg only one slider handle - this.comparetwochecked = ''; - if ( this.model.at( REVAPP._rightDiff - 1 ) ) { - addHtml = this.template( _.extend( - this.model.at( REVAPP._rightDiff - 1 ).toJSON(), - { comparetwochecked: this.comparetwochecked } // keep the checkmark unchecked - ) ); - } - } - this.$el.html( addHtml ); - if ( this.model.length < 3 ) { - $( 'div#comparetworevisions' ).hide(); // don't allow compare two if fewer than three revisions - } - if ( this.model.length < 2 ) { - $( 'div#diffslider' ).hide(); // don't allow compare two if fewer than three revisions - $( 'div.diff-slider-ticks-wrapper' ).hide(); - } - - // add tooltips to the handles - if ( 2 === REVAPP._compareOneOrTwo ) { - REVAPP.addTooltip ( $( 'a.ui-slider-handle.left-handle' ), - ( REVAPP._leftDiff < 0 ) ? '' : REVAPP._revisions.at( REVAPP._leftDiff - 1 ).get( 'revision_date_author_short' ) ); - REVAPP.addTooltip ( $( 'a.ui-slider-handle.right-handle' ), - ( REVAPP._rightDiff > REVAPP._revisions.length ) ? '' : REVAPP._revisions.at( REVAPP._rightDiff - 1 ).get( 'revision_date_author_short' ) ); - } else { - REVAPP.addTooltip ( $( 'a.ui-slider-handle' ), - ( REVAPP._rightDiff > REVAPP._revisions.length ) ? '' : REVAPP._revisions.at( REVAPP._rightDiff - 1 ).get( 'revision_date_author_short' ) ); - } - - // hide the restore button when on the last sport/current post data - if ( REVAPP._rightDiff === REVAPP._revisions.length ){ - $( '.restore-button' ).hide(); - } else { - $( '.restore-button' ).show(); - } - - return this; - }, - - // the compare two button is in this view, add the interaction here - events: { - 'click #comparetwo': 'clickcomparetwo' - }, - - // turn on/off the compare two mmode - clickcomparetwo: function(){ - self = this; - - if ( $( 'input#comparetwo' ).is( ':checked' ) ) { // compare 2 mode - REVAPP._compareOneOrTwo = 2 ; - - if ( 1 === REVAPP._rightDiff ) - REVAPP._rightDiff = 2; - REVAPP._revisionView.draggingLeft = false; - - wpRevisionsSettings.revision_id = ''; // reset passed revision id so switching back to one handle mode doesn't re-select revision - REVAPP.reloadLeftRight(); - REVAPP._revisionView.model = REVAPP._rightHandleRevisions; - - } else { // compare one mode - REVAPP._compareOneOrTwo = 1 ; - REVAPP._revisionView.draggingLeft = false; - // REVAPP._leftDiff = 0; - // REVAPP._rightDiff = (REVAPP._revisions.length <= REVAPP._rightDiff ) ? REVAPP._rightDiff + 1 : REVAPP._rightDiff + 1; - REVAPP.reloadModelSingle(); - } - // REVAPP._revisionView.render(); - REVAPP._revisionsInteractions.render(); - REVAPP._tickmarkView.render(); - + }); } - }), + }, - // options view for show autosaves and show split view options - /* DISABLED for now - Options: Backbone.View.extend({ - el: $('#backbonerevisionsoptions')[0], - tagName: 'revisionoptionsview', - className: 'revisionoptions-container', - template: wp.template('revisionoptions'), + reloadToLoadRevisions: function( models, reverse_direction ) { + var self = this, + revisionsToLoad = models.where( { revision_toload: true } ), + delay = 0; - // render the options view - render: function() { - var addHtml = this.template; - this.$el.html( addHtml ); - return this; - }, + // 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; + }); - // add options interactions - events: { - 'click #toggleshowautosaves': 'toggleshowautosaves', - 'click #showsplitview': 'showsplitview' - }, + _.each( revisionsToLoad, function( revision ) { + _.delay( function() { + revision.fetch( { + update: true, + add: false, + remove: false, + success: function( model ) { + model.set( 'revision_toload', 'false' ); - // toggle include autosaves - toggleshowautosaves: function() { - var self = this; - if ( $( '#toggleshowautosaves' ).is( ':checked' ) ) { - REVAPP._autosaves = true ; - } else { - REVAPP._autosaves = false ; - } + // stop spinner when all models are loaded + if ( 0 === models.where( { revision_toload: true } ).length ) + self.stopModelLoadingSpinner(); - // refresh the model data - REVAPP.reloadModel(); - }, + self.tickmarkView.render(); - // toggle showing the split diff view - showsplitview: function() { - var self = this; + var total_changes = model.get( 'lines_added' ) + model.get( 'lines_deleted'), + scope_of_changes = 'vsmall'; - if ( $( 'input#showsplitview' ).is( ':checked' ) ) { - REVAPP._showSplitView = 'true'; - $('.revisiondiffcontainer').addClass('diffsplit'); - } else { - REVAPP._showSplitView = ''; - $('.revisiondiffcontainer').removeClass('diffsplit'); - } - - REVAPP.reloadModel(); - } - }), - */ - // main interactions view - Interact: Backbone.View.extend({ - el: $('#backbonerevisionsinteract')[0], - tagName: 'revisionvinteract', - className: 'revisionvinteract-container', - template: wp.template('revisionvinteract'), - - initialize: function() { - }, - - render: function() { - var self = this; - - var addHtml = this.template; - this.$el.html( addHtml ); - - var modelcount = REVAPP._revisions.length; - - slider = $( "#slider" ); - if ( 1 === REVAPP._compareOneOrTwo ) { - // set up the slider with a single handle - slider.slider({ - value: REVAPP._rightDiff - 1, - min: 0, - max: modelcount - 1, - step: 1, - - - // slide interactions for one handles slider - slide: function( event, ui ) { - - REVAPP._rightDiff = ( ui.value + 1 ); - REVAPP._revisionView.render(); - /* - $( 'a.ui-slider-handle' ).tooltip( { - content: REVAPP._revisions.at( ui.value ).get( 'revision_date_author_short' ), - position: { - my: "top-65", - using: function( position, feedback ) { - $( this ).css( position ); - $( "
" ) - .addClass( "arrow" ) - .addClass( feedback.vertical ) - .addClass( feedback.horizontal ) - .appendTo( this ); - } + // Note: hard coded scope of changes + // TODO change to dynamic based on range of values + if ( total_changes > 1 && total_changes <= 3 ) { + scope_of_changes = 'small'; + } else if( total_changes > 3 && total_changes <= 5 ) { + scope_of_changes = 'med'; + } else if( total_changes > 5 && total_changes <= 10 ) { + scope_of_changes = 'large'; + } else if( total_changes > 10 ) { + scope_of_changes = 'vlarge'; } - });// .trigger( 'close' ).trigger( 'open' ); -*/ - } - }); - $( '.revisiondiffcontainer' ).removeClass( 'comparetwo' ); - - } else { // comparing more than one, eg 2 - // set up the slider with two handles - slider.slider({ - values: [ REVAPP._leftDiff, REVAPP._rightDiff + 1 ], - min: 1, - max: modelcount + 1, - step: 1, - range: true, - - // in two handled mode when user starts dragging, swap in precalculated diff for handle - start: function(event, ui ) { - var index = $( ui.handle ).index(); // 0 (left) or 1 (right) - switch ( index ) { - case 1: // left handle drag - if ( REVAPP._leftModelLoading ) // left model still loading, prevent sliding left handle - return false; - - REVAPP._revisionView.draggingLeft = true; - - if ( REVAPP._revisionView.model !== REVAPP._leftHandleRevisions && - null !== REVAPP._leftHandleRevisions ) { - REVAPP._revisionView.model = REVAPP._leftHandleRevisions; - REVAPP._tickmarkView.model = REVAPP._leftHandleRevisions; - REVAPP._tickmarkView.render(); - } - - REVAPP._leftDiffStart = ui.values[ 0 ]; - break; - - case 2: // right - if ( REVAPP._rightModelLoading || 0 === REVAPP._rightHandleRevisions.length) // right model still loading, prevent sliding right handle - return false; - - if ( REVAPP._revisionView.model !== REVAPP._rightHandleRevisions && - null !== REVAPP._rightHandleRevisions ) { - REVAPP._revisionView.model = REVAPP._rightHandleRevisions; - REVAPP._tickmarkView.model = REVAPP._rightHandleRevisions; - REVAPP._tickmarkView.render(); - } - - REVAPP._revisionView.draggingLeft = false; - REVAPP._rightDiffStart = ui.values[1]; - break; - } - }, - - // when sliding in two handled mode change appropriate value - slide: function( event, ui ) { - if ( ui.values[0] === ui.values[1] ) // prevent compare to self - return false; - - var index = $( ui.handle ).index(); // 0 (left) or 1 (right) - - switch ( index ) { - case 1: // left - if ( REVAPP._leftModelLoading ) // left model still loading, prevent sliding left handle - return false; - - REVAPP._leftDiff = ui.values[0]; - break; - - case 2: // right - if ( REVAPP._rightModelLoading ) // right model still loading, prevent sliding right handle - return false; - - REVAPP._rightDiff = ui.values[1]; - break; - } - - if ( 0 === REVAPP._leftDiff ) { - $( '.revisiondiffcontainer' ).addClass( 'currentversion' ); - - } else { - $( '.revisiondiffcontainer' ).removeClass( 'currentversion' ); - } - - REVAPP._revisionView.render(); - - }, - - // when the user stops sliding in 2 handle mode, recalculate diffs - stop: function( event, ui ) { - if ( 2 === REVAPP._compareOneOrTwo ) { - // calculate and generate a diff for comparing to the left handle - // and the right handle, swap out when dragging - - var index = $( ui.handle ).index(); // 0 (left) or 1 (right) - - switch ( index ) { - case 1: // left - - // left handle dragged & changed, reload right handle model - if ( REVAPP._leftDiffStart !== ui.values[0] ) - REVAPP.reloadRight(); - - break; - - case 2: // right - // REVAPP._rightDiff = ( 1 >= REVAPP._rightDiff ) ? 1 : REVAPP._rightDiff - 1; - // right handle dragged & changed, reload left handle model if changed - if ( REVAPP._rightDiffStart !== ui.values[1] ) - REVAPP.reloadLeft(); - - break; + model.set( 'scope_of_changes', scope_of_changes ); + if ( 0 !== self.rightDiff && + model.get( 'ID' ) === self.revisions.at( self.rightDiff - 1 ).get( 'ID' ) ) { + // reload if current model refreshed + self.revisionView.render(); } + } - } - }); - $( '.revisiondiffcontainer' ).addClass( 'comparetwo' ); - $( '#diffslider a.ui-slider-handle' ).first().addClass( 'left-handle' ).next().addClass( 'right-handle' ); + } ); + }, delay ) ; + delay = delay + 150; // stagger model loads to avoid hammering server with requests + } + ); + }, + + startLeftModelLoading: function() { + this.leftModelLoading = true; + $('.revisiondiffcontainer').addClass('leftmodelloading'); + }, + + stopLeftModelLoading: function() { + this.leftModelLoading = false; + }, + + startRightModelLoading: function() { + this.rightModelLoading = true; + $('.revisiondiffcontainer').addClass('rightmodelloading'); + }, + + stopRightModelLoading: function() { + this.rightModelLoading = false; + }, + + stopModelLoadingSpinner: function() { + $('.revisiondiffcontainer').removeClass('rightmodelloading'); + $('.revisiondiffcontainer').removeClass('leftmodelloading'); + }, + + reloadModel: function() { + if ( this.singleRevision ) { + this.reloadModelSingle(); + } else { + this.reloadLeftRight(); + } + }, + + // load the models for the single handle mode + reloadModelSingle: function() { + var self = this; + + // TODO: Only updates the query args yet + self.revisions.reload({ + 'showAutosaves': self.autosaves, + 'showSplitView': self.showSplitView + }); + + self.startRightModelLoading(); + self.revisions.fetch({ // reload revision data + success: function() { + var revisionCount = self.revisions.length; + self.revisionView.model = self.revisions; + self.revisionView.render(); + self.reloadToLoadRevisions( self.revisions ); + self.tickmarkView.model = self.revisions; + self.tickmarkView.render(); + self.slider.refresh({ + 'max': revisionCount - 1, + 'value': self.rightDiff - 1 + }, true); + }, + + error: function() { + self.stopRightModelLoading(); } - return this; - }, + }); + }, - // next and previous buttons, only available in compare one mode - events: { - 'click #next': 'nextRevision', - 'click #previous': 'previousRevision' - }, + // load the models for the left handle + reloadLeft: function() { + var self = this; + self.startLeftModelLoading(); + self.leftHandleRevisions = new Revisions( {}, { + 'compareTo': self.revisions.at( self.rightDiff - 1 ).get( 'ID' ), + 'showAutosaves': self.autosaves, + 'showSplitView': self.showSplitView, + 'rightHandleAt': self.rightDiff + }); - // go to the next revision - nextRevision: function() { - if ( REVAPP._rightDiff < this.model.length ) // unless at right boundry - REVAPP._rightDiff = REVAPP._rightDiff + 1 ; + self.leftHandleRevisions.fetch({ + success: function(){ + self.stopLeftModelLoading(); + self.reloadToLoadRevisions( self.leftHandleRevisions ); + self.tickmarkView.model = self.leftHandleRevisions; + self.slider.refresh({ + 'max': self.revisions.length + }); + // ensure right handle not beyond length, in particular if viewing autosaves is switched from on to off + // the number of models in the collection might get shorter, this ensures right handle is not beyond last model + if ( self.rightDiff > self.revisions.length ) + self.rightDiff = self.revisions.length; + }, - REVAPP._revisionView.render(); + error: function() { + self.stopLeftModelLoading(); + } + }); + }, - $( '#slider' ).slider( 'value', REVAPP._rightDiff - 1 ).trigger( 'slide' ); - }, + // load the models for the right handle + reloadRight: function() { + var self = this; + self.startRightModelLoading(); + self.rightHandleRevisions = new Revisions( {}, { + 'compareTo': self.revisions.at( self.leftDiff ).get( 'ID' ) - 1, + 'showAutosaves': self.autosaves, + 'showSplitView': self.showSplitView, + 'leftHandleAt': self.leftDiff + }); - // go the the previous revision - previousRevision: function() { - if ( REVAPP._rightDiff > 1 ) // unless at left boundry - REVAPP._rightDiff = REVAPP._rightDiff - 1 ; + self.rightHandleRevisions.fetch({ + success: function(){ + self.stopRightModelLoading(); + self.reloadToLoadRevisions( self.rightHandleRevisions ); + self.tickmarkView.model = self.rightHandleRevisions; + self.slider.refresh({ + 'max': self.revisions.length, + 'values': [ self.leftDiff, self.rightDiff] + }, true); + }, - REVAPP._revisionView.render(); + error: function( response ) { + self.stopRightModelLoading(); + } + }); - $( '#slider' ).slider( 'value', REVAPP._rightDiff - 1 ).trigger( 'slide' ); - } - }) + }, + + reloadLeftRight: function() { + this.startRightModelLoading(); + this.startLeftModelLoading(); + this.reloadLeft(); + this.reloadRight(); + }, + + completeApplicationSetup: function() { + this.revisionView = new revisions.view.Diff({ + model: this.revisions + }); + this.revisionView.render(); + + this.reloadToLoadRevisions( this.revisions ); + + this.revisionsInteractions = new revisions.view.Interact({ + model: this.revisions + }); + this.revisionsInteractions.render(); + + this.tickmarkView = new revisions.view.Tickmarks({ + model: this.revisions + }); + this.tickmarkView.render(); + this.tickmarkView.resetTicks(); + + } }); - // instantiate Revision Application - REVAPP = new wp.revisions.App(); + + /** + * ======================================================================== + * VIEWS + * ======================================================================== + */ + + /** + * wp.revisions.view.Slider + * + * The slider + */ + revisions.view.Slider = Backbone.View.extend({ + el: $( '#slider' ), + singleRevision: true, + + initialize: function( options ) { + this.options = _.defaults( options || {}, { + value: 0, + min: 0, + max: 1, + step: 1 + }); + }, + + slide: function( event, ui ) { + if ( this.singleRevision ) { + Diff.rightDiff = ( ui.value + 1 ); + Diff.revisionView.render(); + } else { + if ( ui.values[0] === ui.values[1] ) // prevent compare to self + return false; + + if ( $( ui.handle ).hasClass( 'left-handle' ) ) { + // Left handler + if ( Diff.leftModelLoading ) // left model still loading, prevent sliding left handle + return false; + + Diff.leftDiff = ui.values[0]; + } else { + // Right handler + if ( Diff.rightModelLoading ) // right model still loading, prevent sliding right handle + return false; + + Diff.rightDiff = ui.values[1]; + } + + if ( 0 === Diff.leftDiff ) { + $( '.revisiondiffcontainer' ).addClass( 'currentversion' ); + } else { + $( '.revisiondiffcontainer' ).removeClass( 'currentversion' ); + } + + Diff.revisionView.render(); + } + }, + + start: function( event, ui ) { + // Not needed in one mode + if ( this.singleRevision ) + return; + + if ( $( ui.handle ).hasClass( 'left-handle' ) ) { + // Left handler + if ( Diff.leftModelLoading ) // left model still loading, prevent sliding left handle + return false; + + Diff.revisionView.draggingLeft = true; + + if ( Diff.revisionView.model !== Diff.leftHandleRevisions && + null !== Diff.leftHandleRevisions ) { + Diff.revisionView.model = Diff.leftHandleRevisions; + Diff.tickmarkView.model = Diff.leftHandleRevisions; + Diff.tickmarkView.render(); + } + + Diff.leftDiffStart = ui.values[ 0 ]; + + } else { + // Right handler + if ( Diff.rightModelLoading || 0 === Diff.rightHandleRevisions.length) // right model still loading, prevent sliding right handle + return false; + + if ( Diff.revisionView.model !== Diff.rightHandleRevisions && + null !== Diff.rightHandleRevisions ) { + Diff.revisionView.model = Diff.rightHandleRevisions; + Diff.tickmarkView.model = Diff.rightHandleRevisions; + Diff.tickmarkView.render(); + } + + Diff.revisionView.draggingLeft = false; + Diff.rightDiffStart = ui.values[1]; + } + }, + + stop: function( event, ui ) { + // Not needed in one mode + if ( this.singleRevision ) + return; + + // 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 hadnler + if ( Diff.leftDiffStart !== ui.values[0] ) + Diff.reloadRight(); + } else { + // Right handler + if ( Diff.rightDiffStart !== ui.values[1] ) + Diff.reloadLeft(); + } + }, + + addTooltip: function( handle, message ) { + + handle.attr( 'title', '' ).tooltip({ + track: false, + + position: { + my: "left-30 top-66", + at: "top left", + using: function( position, feedback ) { + $( this ).css( position ); + $( "
" ) + .addClass( "arrow" ) + .addClass( feedback.vertical ) + .addClass( feedback.horizontal ) + .appendTo( $( this ) ); + } + }, + show: false, + hide: false, + content: function() { + return message; + } + + } ); + }, + + width: function() { + return $( '#slider' ).width(); + }, + + setWidth: function( width ) { + return $( '#slider' ).width( width ); + }, + + refresh: function( options, slide ) { + $( '#slider' ).slider( 'option', options ); + + // Triggers the slide event + if ( slide ) + $( '#slider' ).trigger( 'slide' ); + }, + + option: function( key ) { + return $( '#slider' ).slider( 'option', key ); + }, + + render: function() { + var self = this; + // this.$el doesn't work, why? + $( '#slider' ).slider( { + slide: $.proxy( self.slide, self ), + start: $.proxy( self.start, self ), + stop: $.proxy( self.stop, self ) + } ); + + // Set options + this.refresh( this.options ); + } + }); + + /** + * 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 = Diff.slider.option( 'max' ); + var sliderWidth = Diff.slider.width(); + var adjustMax = Diff.singleRevision ? 0 : 1; + var tickWidth = Math.floor( sliderWidth / ( sliderMax - adjustMax ) ); + + // TODO: adjust right margins for wider ticks so they stay centered on handle stop point + + // set minimum and maximum widths for tick marks + tickWidth = (tickWidth > 50 ) ? 50 : tickWidth; + tickWidth = (tickWidth < 10 ) ? 10 : tickWidth; + + sliderWidth = tickWidth * (sliderMax - adjustMax ) + 1; + + Diff.slider.setWidth( sliderWidth ); + $( '.diff-slider-ticks-wrapper' ).width( sliderWidth ); + $( '#diffslider' ).width( sliderWidth ); + $( '#diff-slider-ticks' ).width( sliderWidth ); + + var aTickWidth = $( '.revision-tick' ).width(); + + if ( tickWidth !== aTickWidth ) { // is the width already set correctly? + $( '.revision-tick' ).each( function( ) { + $(this).css( 'margin-right', tickWidth - 1 + 'px'); // space the ticks out using right margin + }); + + if( ! Diff.singleRevision ) { + $( '.revision-tick' ).first().remove(); // TODO - remove the check + } + $( '.revision-tick' ).last().css( 'margin-right', '0' ); // last tick gets no right margin + } + + }, + + // render the tickmark view + render: function() { + var self = this; + + if ( null !== self.model ) { + var 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 + */ + // TODO: Change Interact to something else. + revisions.view.Interact = Backbone.View.extend({ + el: $('#backbonerevisionsinteract'), + template: wp.template('revision-interact'), + + // next and previous buttons, only available in compare one mode + events: { + 'click #next': 'nextRevision', + 'click #previous': 'previousRevision' + }, + + render: function() { + var self = this; + + var addHtml = this.template; + this.$el.html( addHtml ); + + var modelcount = Diff.revisions.length; + + Diff.slider.singleRevision = Diff.singleRevision; + Diff.slider.render(); + + if ( Diff.singleRevision ) { + Diff.slider.refresh({ + value: Diff.rightDiff - 1, + min: 0, + max: modelcount - 1 + }); + + $( '.revisiondiffcontainer' ).removeClass( 'comparetwo' ); + + } else { + Diff.slider.refresh({ + values: [ Diff.leftDiff, Diff.rightDiff + 1 ], + min: 1, + max: modelcount + 1, + range: true + }); + + $( '.revisiondiffcontainer' ).addClass( 'comparetwo' ); + $( '#diffslider a.ui-slider-handle' ).first().addClass( 'left-handle' ); + $( '#diffslider a.ui-slider-handle' ).last().addClass( 'right-handle' ); + + } + + return this; + }, + + // go to the next revision + nextRevision: function() { + if ( Diff.rightDiff < this.model.length ) // unless at right boundry + Diff.rightDiff = Diff.rightDiff + 1 ; + + Diff.revisionView.render(); + + Diff.slider.refresh({ + value: Diff.rightDiff - 1 + }, true ); + }, + + // go the 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 + * + * Next/Prev buttons and the slider + */ + revisions.view.Diff = Backbone.View.extend({ + el: $('#backbonerevisionsdiff'), + template: wp.template('revision'), + draggingLeft: false, + + // the compare two button is in this view, add the interaction here + events: { + 'click #comparetwo': 'compareTwo', + 'click #restore': 'restore' + }, + + // render the revisions + render: function() { + var addHtml = ''; + var thediff; + + // compare two revisions mode? + if ( ! Diff.singleRevision ) { + if ( this.draggingLeft ) { + thediff = Diff.leftDiff - 1; + if ( this.model.at( thediff ) ) { + addHtml = this.template( this.model.at( thediff ).toJSON() ); + } + } else { // dragging right handle + thediff = Diff.rightDiff -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 + this.comparetwochecked = ''; + if ( this.model.at( Diff.rightDiff - 1 ) ) { + addHtml = this.template( this.model.at( Diff.rightDiff - 1 ).toJSON() ); + } + } + this.$el.html( addHtml ); + + if ( this.model.length < 2 ) { + $( '#diffslider' ).hide(); // don't allow compare two if fewer than three revisions + $( '.diff-slider-ticks-wrapper' ).hide(); + } + + // add tooltips to the handles + if ( ! Diff.singleRevision ) { + Diff.slider.addTooltip ( $( 'a.ui-slider-handle.left-handle' ), + ( Diff.leftDiff < 0 ) ? '' : Diff.revisions.at( Diff.leftDiff - 1 ).get( 'titleTooltip' ) ); + Diff.slider.addTooltip ( $( 'a.ui-slider-handle.right-handle' ), + ( Diff.rightDiff > Diff.revisions.length ) ? '' : Diff.revisions.at( Diff.rightDiff - 1 ).get( 'titleTooltip' ) ); + } else { + Diff.slider.addTooltip ( $( 'a.ui-slider-handle' ), + ( Diff.rightDiff > Diff.revisions.length ) ? '' : Diff.revisions.at( Diff.rightDiff - 1 ).get( 'titleTooltip' ) ); + } + + this.toogleCompareTwoCheckbox(); + + // hide the restore button when on the last sport/current post data + if ( Diff.rightDiff === Diff.revisions.length ){ + $( '#restore' ).hide(); + } else { + $( '#restore' ).show(); + } + + return this; + }, + + toogleCompareTwoCheckbox: function() { + // don't allow compare two if fewer than three revisions + if ( this.model.length < 3 ) + $( '#comparetworevisions' ).hide(); + + $( '#comparetwo' ).prop( 'checked', ! Diff.singleRevision ); + }, + + // turn on/off the compare two mode + compareTwo: function() { + if ( $( 'input#comparetwo' ).is( ':checked' ) ) { // compare 2 mode + Diff.singleRevision = false ; + + if ( 1 === Diff.rightDiff ) + Diff.rightDiff = 2; + + Diff.revisionView.draggingLeft = false; + + revisions.model.settings.revision_id = ''; // reset passed revision id so switching back to one handle mode doesn't re-select revision + Diff.reloadLeftRight(); + Diff.revisionView.model = Diff.rightHandleRevisions; + + } else { // compare one mode + Diff.singleRevision = true; + Diff.revisionView.draggingLeft = false; + Diff.reloadModelSingle(); + } + Diff.revisionsInteractions.render(); + Diff.tickmarkView.render(); + }, + + restore: function() { + document.location = $( '#restore' ).data( 'restoreLink' ); + } + }); + + + /** + * ======================================================================== + * MODELS + * ======================================================================== + */ + + /** + * wp.revisions.Revision + */ + Revision = revisions.model.Revision = Backbone.Model.extend({ + idAttribute: 'ID', + urlRoot: ajaxurl + '?action=revisions-data' + + '&show_autosaves=true&show_split_view=true&nonce=' + revisions.model.settings.nonce, + defaults: { + ID: 0, + titleTo: '', + titleTooltip: '', + titleFrom: '', + diff: '
', + restoreLink: '', + revision_toload: false, + lines_added: 0, + lines_deleted: 0, + scope_of_changes: 'none', + previous_revision_id: 0 + }, + + url: function() { + if ( Diff.singleRevision ) { + return this.urlRoot + + '&single_revision_id=' + this.id + + '&compare_to=' + this.get( 'previous_revision_id' ) + + '&post_id=' + revisions.model.settings.post_id; + } else { + return this.collection.url() + '&single_revision_id=' + this.id; + } + + } + }); + + /** + * wp.revisions.Revisions + */ + Revisions = revisions.Revisions = Backbone.Collection.extend({ + model: Revision, + urlRoot: ajaxurl + '?action=revisions-data', + + 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 this.urlRoot + + '&compare_to=' + this.options.compareTo + + '&post_id=' + this.options.post_id + + '&show_autosaves=' + this.options.showAutosaves + + '&show_split_view=' + this.options.showSplitView + + '&right_handle_at=' + this.options.rightHandleAt + + '&left_handle_at=' + this.options.leftHandleAt + + '&nonce=' + this.options.nonce; + }, + + reload: function( options ) { + this.options = _.defaults( options || {}, this.options ); + + // TODO + //this.fetch(); + } + + } ); + + $( wp.revisions ); }(jQuery)); diff --git a/wp-admin/revision.php b/wp-admin/revision.php index 1acb5df6f5..44cf4e3313 100644 --- a/wp-admin/revision.php +++ b/wp-admin/revision.php @@ -79,12 +79,20 @@ wp_enqueue_script( 'revisions' ); require_once( './admin-header.php' ); -//TODO - Some of the translations below split things into multiple strings that are contextually related and this makes it pretty impossible for RTL translation. -//TODO can we pass the context in a better way -$wpRevisionsSettings = array( 'post_id' => $post->ID, - 'nonce' => wp_create_nonce( 'revisions-ajax-nonce' ), - 'revision_id' => $revision_id ); -wp_localize_script( 'revisions', 'wpRevisionsSettings', $wpRevisionsSettings ); +$strings = array( + 'diffFromTitle' => _x( 'From: %s', 'revision from title' ), + 'diffToTitle' => _x( 'To: %s', 'revision to title' ) +); + +$settings = array( + 'post_id' => $post->ID, + 'nonce' => wp_create_nonce( 'revisions-ajax-nonce' ), + 'revision_id' => $revision_id +); + +$strings['settings'] = $settings; + +wp_localize_script( 'revisions', 'wpRevisionsL10n', $strings ); $comparetworevisionslink = get_edit_post_link( $revision->ID ); ?> @@ -112,25 +120,28 @@ $comparetworevisionslink = get_edit_post_link( $revision->ID );
- + -
-
- -
-
- -
-
- -*/ -require_once( './admin-footer.php' ); \ No newline at end of file +require_once( './admin-footer.php' ); diff --git a/wp-includes/revision.php b/wp-includes/revision.php index 2f46abdab5..0cddf445f6 100644 --- a/wp-includes/revision.php +++ b/wp-includes/revision.php @@ -675,7 +675,7 @@ 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' ) ) + if ( ! class_exists( 'WP_Text_Diff_Renderer_Table' ) ) require( ABSPATH . WPINC . '/wp-diff.php' ); $left_string = normalize_whitespace( $left_string ); @@ -685,8 +685,8 @@ function wp_text_diff_with_count( $left_string, $right_string, $args = null ) { $right_lines = explode( "\n", $right_string) ; $text_diff = new Text_Diff($left_lines, $right_lines ); - $linesadded = $text_diff->countAddedLines(); - $linesdeleted = $text_diff->countDeletedLines(); + $lines_added = $text_diff->countAddedLines(); + $lines_deleted = $text_diff->countDeletedLines(); $renderer = new WP_Text_Diff_Renderer_Table(); $diff = $renderer->render( $text_diff ); @@ -718,5 +718,5 @@ function wp_text_diff_with_count( $left_string, $right_string, $args = null ) { $r .= "\n$diff\n\n"; $r .= ""; - return array( 'html' => $r, 'linesadded' => $linesadded, 'linesdeleted' => $linesdeleted ); + return array( 'html' => $r, 'lines_added' => $lines_added, 'lines_deleted' => $lines_deleted ); }