" )
- .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 );
}