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 : '
', 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));