Wordpress/wp-admin/js/revisions.js
Peter Westwood ae4522b5f1 Revisions: Updates to the new Revisions UI.
Various Updates including:
 * i18n fixes
 * Added tracking of what revision ID was restored
 * async fetching of diffs so that slider works sooner even with many revisions

See #23497 props adamsilverstein, ethitter


git-svn-id: https://develop.svn.wordpress.org/trunk@23639 602fd350-edb4-49c9-b593-d223f7449a82
2013-03-07 15:32:26 +00:00

599 lines
18 KiB
JavaScript

window.wp = window.wp || {};
(function($) {
wp.revisions = {
views : {},
Model : Backbone.Model.extend({
idAttribute : 'ID',
urlRoot : ajaxurl + '?action=revisions-data&compare_to=' + wpRevisionsSettings.post_id +
'&show_autosaves=false&show_split_view=true&nonce=' + wpRevisionsSettings.nonce,
defaults: {
ID : 0,
revision_date_author : '',
revisiondiff : '<div class="diff-loading"><div class="spinner"></div></div>',
restoreaction : '',
revision_from_date_author : '',
revision_toload : false
},
url : function() {
return this.urlRoot + '&single_revision_id=' + this.id;
}
}),
app: _.extend({}, Backbone.Events),
App : Backbone.Router.extend({
_revisionDifflView : null,
_revisions : null,
_left_handle_revisions : null,
_right_handle_revisions : null,
_revisionsInteractions : null,
_revisionsOptions : null,
_left_diff : 0,
_right_diff : 1,
_autosaves : false,
_show_split_view : true,
_compareoneortwo : 1,
_left_model_loading : false, //keep track of model loads
_right_model_loading : false, //disallow slider interaction, also repeat loads, while loading
//TODO add ability to arrive on specific revision
routes : {
},
viewrevision : function( revision ) {
//coming soon
},
reload_toload_revisions : function( model_collection, reverse_direction ) {
var self = this;
var revisions_to_load = model_collection.where( { revision_toload : true } );
//console.log(revisions_to_load);
var delay=0;
_.each(revisions_to_load, function( the_model ) {
the_model.urlRoot = model_collection.url;
_.delay( function() {
the_model.fetch( {
update : true,
add : false,
remove : false,
//async : false,
success : function( model ) {
//console.log(model.get( 'ID' ) +'-'+self._revisions.at( self._right_diff ).get( 'ID' ));
if ( model.get( 'ID' ) === self._revisions.at( self._right_diff - 1 ).get( 'ID' ) ) { //reload if current model refreshed
//console.log('render');
self._revisionView.render();
}
}
} );
}, delay ) ;
delay = delay + 200; //stagger model loads by 200 ms to avoid hammering server with requests
}
);
},
start_left_model_loading : function() {
this._left_model_loading = true;
$('.revisiondiffcontainer').addClass('leftmodelloading');
},
stop_left_model_loading : function() {
this._left_model_loading = false;
$('.revisiondiffcontainer').removeClass('leftmodelloading');
},
start_right_model_loading : function() {
this._right_model_loading = true;
$('.revisiondiffcontainer').addClass('rightmodelloading');
},
stop_right_model_loading : function() {
this._right_model_loading = false;
$('.revisiondiffcontainer').removeClass('rightmodelloading');
},
reloadmodel : function() {
if ( 2 === this._compareoneortwo ) {
this.reloadleftright();
} else {
this.reloadmodelsingle();
}
},
reloadmodelsingle : function() {
var self = this;
self._revisions.url = ajaxurl + '?action=revisions-data&compare_to=' + wpRevisionsSettings.post_id +
'&show_autosaves=' + self._autosaves +
'&show_split_view=' + REVAPP._show_split_view +
'&nonce=' + wpRevisionsSettings.nonce;
self.start_right_model_loading();
this._revisions.fetch({ //reload revision data
success : function() {
self.stop_right_model_loading();
var revisioncount = self._revisions.length;
if ( self._right_diff > revisioncount ) //if right handle past rightmost, move
self._right_diff = revisioncount;
self._revisionView.render();
self.reload_toload_revisions( self._revisions );
$( '#slider' ).slider( 'option', 'max', revisioncount-1 ); //TODO test this, autsaves changed
},
error : function () {
self.stop_right_model_loading();
//console.log( 'Error loading revision data' );
}
});
},
reloadleft : function() {
var self = this;
self.start_left_model_loading();
self._left_handle_revisions = new wp.revisions.Collection();
self._left_handle_revisions.url =
ajaxurl +
'?action=revisions-data&compare_to=' + self._revisions.at( self._right_diff - 1 ).get( 'ID' ) +
'&post_id=' + wpRevisionsSettings.post_id +
'&show_autosaves=' + self._autosaves +
'&show_split_view=' + self._show_split_view +
'&nonce=' + wpRevisionsSettings.nonce +
'&right_handle_at=' + ( self._right_diff );
self._left_handle_revisions.fetch({
success : function(){
self.stop_left_model_loading();
self.reload_toload_revisions( self._left_handle_revisions );
},
error : function () {
//console.log( 'Error loading revision data' );
self.stop_left_model_loading();
}
});
},
reloadright : function() {
var self = this;
self.start_right_model_loading();
self._right_handle_revisions = new wp.revisions.Collection();
if ( 0 === self._left_diff ) {
self._right_handle_revisions.url =
ajaxurl +
'?action=revisions-data&compare_to=' + wpRevisionsSettings.post_id +
'&post_id=' + wpRevisionsSettings.post_id +
'&show_autosaves=' + self._autosaves +
'&show_split_view=' + self._show_split_view +
'&nonce=' + wpRevisionsSettings.nonce;
} else {
self._right_handle_revisions.url =
ajaxurl +
'?action=revisions-data&compare_to=' + self._revisions.at( self._left_diff - 1 ).get( 'ID' ) +
'&post_id=' + wpRevisionsSettings.post_id +
'&show_autosaves=' + self._autosaves +
'&show_split_view=' + self._show_split_view +
'&nonce=' + wpRevisionsSettings.nonce +
'&left_handle_at=' + (self._left_diff ) ;
}
self._right_handle_revisions.fetch({
success : function(){
self.stop_right_model_loading();
self.reload_toload_revisions( self._right_handle_revisions );
},
error : function ( response ) {
//console.log( 'Error loading revision data - ' + response.toSource() );
self.stop_right_model_loading();
}
});
},
reloadleftright : function() {
this.reloadleft();
this.reloadright();
},
/*
* initialize the revision application
*/
initialize : function( options ) {
var self = this; //store the application instance
if (this._revisions === null) {
self._autosaves = '';
self._revisions = new wp.revisions.Collection(); //set up collection
self.start_right_model_loading();
self._revisions.fetch({ //load revision data
success : function() {
self.stop_right_model_loading();
self.revisionDiffSetup();
}
});
}
return this;
},
revisionDiffSetup : function() {
this._revisionView = new wp.revisions.views.View({
model : this._revisions
});
this._revisionView.render();
$( '#diff_max, #diff_maxof' ).html( this._revisions.length );
$( '#diff_count' ).html( REVAPP._right_diff );
$( '#slider' ).slider( 'option', 'max', this._revisions.length - 1 );
this.reload_toload_revisions( this._revisions );
this._revisionsInteractions = new wp.revisions.views.Interact({
model : this._revisions
});
this._revisionsInteractions.render();
/*
//Options hidden for now, moving to screen options
this._revisionsOptions = new wp.revisions.views.Options({
model : this._revisions
});
this._revisionsOptions.render();
*/
}
})
};
wp.revisions.Collection = Backbone.Collection.extend({
model : wp.revisions.Model,
url : ajaxurl + '?action=revisions-data&compare_to=' + wpRevisionsSettings.post_id +
'&show_autosaves=false&show_split_view=true&nonce=' + wpRevisionsSettings.nonce,
initialize : function() {
}
} );
_.extend(wp.revisions.views, {
//
//primary revision diff view
//
View : Backbone.View.extend({
el : $('#backbonerevisionsdiff')[0],
tagName : 'revisionvview',
className : 'revisionview-container',
template : wp.template('revision'),
revvapp : null,
comparetwochecked : '',
draggingleft : false,
initialize : function(){
},
//
//render the revisions
//
render : function() {
var addhtml = '';
//compare two revisions mode?
if ( 2 === REVAPP._compareoneortwo ) {
this.comparetwochecked = 'checked';
if ( this.draggingleft ) {
if ( this.model.at( REVAPP._left_diff ) ) {
addhtml = this.template( _.extend(
this.model.at( REVAPP._left_diff ).toJSON(),
{ comparetwochecked : this.comparetwochecked } //keep the checkmark checked
) );
}
} else { //dragging right handle
var thediff = REVAPP._right_diff;
if ( this.model.at( thediff ) ) {
addhtml = this.template( _.extend(
this.model.at( thediff ).toJSON(),
{ comparetwochecked : this.comparetwochecked } //keep the checkmark checked
) );
}
}
} else { //end compare two revisions mode, eg only one slider handle
this.comparetwochecked = '';
if ( this.model.at( REVAPP._right_diff - 1 ) ) {
addhtml = this.template( _.extend(
this.model.at( REVAPP._right_diff - 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
}
//console.log ( (this.model.at( REVAPP._right_diff - 1 )).url());
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' ) ) {
REVAPP._compareoneortwo = 2 ;
REVAPP.reloadleftright();
} else {
REVAPP._compareoneortwo = 1 ;
REVAPP._revisionView.draggingleft = false;
REVAPP._left_diff = 0;
REVAPP.reloadmodelsingle();
}
REVAPP._revisionsInteractions.render();
}
}),
//
//options view for show autosaves and show split view options
//
Options : Backbone.View.extend({
el : $('#backbonerevisionsoptions')[0],
tagName : 'revisionoptionsview',
className : 'revisionoptions-container',
template : wp.template('revisionoptions'),
initialize : function() {
},
//render the options view
render : function() {
var addhtml = this.template;
this.$el.html( addhtml );
return this;
},
//add options interactions
events : {
'click #toggleshowautosaves' : 'toggleshowautosaves',
'click #showsplitview' : 'showsplitview'
},
//
//toggle include autosaves
//
toggleshowautosaves : function() {
var self = this;
if ( $( '#toggleshowautosaves' ).is( ':checked' ) ) {
REVAPP._autosaves = true ;
} else {
REVAPP._autosaves = false ;
}
//refresh the model data
REVAPP.reloadmodel();
},
//
//toggle showing the split diff view
//
showsplitview : function() {
var self = this;
if ( $( 'input#showsplitview' ).is( ':checked' ) ) {
REVAPP._show_split_view = 'true';
$('.revisiondiffcontainer').addClass('diffsplit');
} else {
REVAPP._show_split_view = '';
$('.revisiondiffcontainer').removeClass('diffsplit');
}
REVAPP.reloadmodel();
}
}),
//
//main interactions view
//
Interact : Backbone.View.extend({
el : $('#backbonerevisionsinteract')[0],
tagName : 'revisionvinteract',
className : 'revisionvinteract-container',
template : wp.template('revisionvinteract'),
_restoreword : '',
initialize : function() {
this._restoreword = $( 'input#restore' ).attr( 'value' );
},
reset_restore_button : function() {
$( 'input#restore' ).attr( 'value', this._restoreword + ' ' + REVAPP._revisions.at( REVAPP._right_diff - 1 ).get( 'ID' ) );
},
render : function() {
var self = this;
var addhtml = this.template;
this.$el.html( addhtml );
$( '#diff_max, #diff_maxof' ).html( this.model.length );
$( '#diff_count' ).html( REVAPP._right_diff );
$( '#diff_left_count_inner' ).html( 0 === REVAPP._left_diff ? '' : 'revision' + REVAPP._left_diff );
self.reset_restore_button();
var modelcount = REVAPP._revisions.length;
slider = $( "#slider" );
if ( 1 === REVAPP._compareoneortwo ) {
//set up the slider with a single handle
slider.slider({
value : REVAPP._right_diff-1,
min : 0,
max : modelcount-1,
step : 1,
//slide interactions for one handles slider
slide : function( event, ui ) {
if ( REVAPP._right_model_loading ) //left model stoll loading, prevent sliding left handle
return false;
REVAPP._right_diff =( ui.value+1 );
$( '#diff_count' ).html( REVAPP._right_diff );
REVAPP._revisionView.render();
self.reset_restore_button();
}
});
$( '.revisiondiffcontainer' ).removeClass( 'comparetwo' );
} else { //comparing more than one, eg 2
//set up the slider with two handles
slider.slider({
values : [ REVAPP._left_diff, REVAPP._right_diff + 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._left_model_loading ) //left model stoll loading, prevent sliding left handle
return false;
if ( REVAPP._revisionView.model !== REVAPP._left_handle_revisions &&
null !== REVAPP._left_handle_revisions )
REVAPP._revisionView.model = REVAPP._left_handle_revisions;
REVAPP._revisionView.draggingleft = true;
REVAPP._left_diff_start = ui.values[ 0 ];
break;
case 2: //right
if ( REVAPP._right_model_loading ) //right model stoll loading, prevent sliding right handle
return false;
//one extra spot at left end when comparing two
if ( REVAPP._revisionView.model !== REVAPP._right_handle_revisions &&
null !== REVAPP._right_handle_revisions )
REVAPP._revisionView.model = REVAPP._right_handle_revisions;
REVAPP._revisionView.draggingleft = false;
REVAPP._right_diff_start = 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._left_model_loading ) //left model still loading, prevent sliding left handle
return false;
REVAPP._left_diff = ui.values[ 0 ] - 1; //one extra spot at left end when comparing two
break;
case 2: //right
if ( REVAPP._right_model_loading ) //right model still loading, prevent sliding right handle
return false;
REVAPP._right_diff = ui.values[ 1 ] - 1 ;
break;
}
$( '#diff_count' ).html( REVAPP._right_diff );
if ( 0 === REVAPP._left_diff ) {
$( '.revisiondiffcontainer' ).addClass( 'currentversion' );
} else {
$( '.revisiondiffcontainer' ).removeClass( 'currentversion' );
$( '#diff_left_count_inner' ).html( REVAPP._left_diff );
}
REVAPP._revisionView.render(); //render the diff view
self.reset_restore_button();
},
//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._left_diff_start === ui.values[ 0 ] || REVAPP._left_model_loading ) )
REVAPP.reloadright();
break;
case 2: //right
//right handle dragged & changed, reload left handle model if changed
if ( ! ( REVAPP._right_diff_start === ui.values[ 1 ] || REVAPP._right_model_loading ) ) {
REVAPP.reloadleft();
}
break;
}
}
}
});
$( '.revisiondiffcontainer' ).addClass( 'comparetwo' );
}
return this;
},
//next and previous buttons, only available in compare one mode
events : {
'click #next' : 'nextrevision',
'click #previous' : 'previousrevision'
},
//go to the next revision
nextrevision : function() {
if ( REVAPP._right_diff < this.model.length ) //unless at right boundry
REVAPP._right_diff = REVAPP._right_diff + 1 ;
REVAPP._revisionView.render();
$( '#diff_count' ).html( REVAPP._right_diff );
$( '#slider' ).slider( 'value', REVAPP._right_diff - 1 ).trigger( 'slide' );
this.reset_restore_button();
},
//go the the previous revision
previousrevision : function() {
if ( REVAPP._right_diff > 1 ) //unless at left boundry
REVAPP._right_diff = REVAPP._right_diff - 1 ;
REVAPP._revisionView.render();
$( '#diff_count' ).html( REVAPP._right_diff );
$( '#slider' ).slider( 'value', REVAPP._right_diff - 1 ).trigger( 'slide' );
this.reset_restore_button();
}
})
});
//instantiate Revision Application
REVAPP = new wp.revisions.App();
//TODO consider enable back button to step back thru states?
//Backbone.history.start({pushState: true});
}(jQuery));