Make WordPress Core

Ticket #24425: 24425.draft.diff

File 24425.draft.diff, 31.9 KB (added by koopersmith, 9 years ago)
  • wp-admin/css/wp-admin.css

    td.plugin-title p { 
    35283528/*------------------------------------------------------------------------------
    35293529  11.2 - Post Revisions
    35303530------------------------------------------------------------------------------*/
     3531.revisions .spinner {
     3532        float: none;
     3533        margin: 100px auto;
     3534}
     3535
     3536.revisions.loading .spinner {
     3537        display: block;
     3538}
     3539
     3540.revisions-control-frame,
     3541.revisions-diff-frame {
     3542        position: relative;
     3543}
     3544
     3545.revisions-controls {
     3546        height: 20px;
     3547        padding: 40px 0 20px;
     3548        border-bottom: 1px solid #dfdfdf;
     3549        margin-bottom: 10px;
     3550}
     3551
     3552.revision-toggle-compare-mode {
     3553        position: absolute;
     3554        top: 0;
     3555        right: 0;
     3556}
     3557
     3558.revisions-previous {
     3559        float: left;
     3560}
     3561
     3562.revisions-next {
     3563        float: right;
     3564}
     3565
     3566.revisions-slider {
     3567        width: 70%;
     3568        margin: 6px auto 0;
     3569}
    35313570
    35323571/* Revision meta box */
    35333572.post-revisions li img,
    table.diff .diff-addedline ins { 
    35743613        position: relative;
    35753614}
    35763615
    3577 #toggle-revision-compare-mode {
    3578         position: absolute;
    3579         top: 0;
    3580         right: 0;
    3581         padding: 9px 9px 0 0;
    3582 }
    3583 
    35843616#loading-status {
    35853617        display: none;
    35863618        position: absolute;
    table.diff .diff-addedline ins { 
    35983630        padding: 20px 0;
    35993631}
    36003632
    3601 #diff-next-revision,
    3602 #diff-previous-revision {
    3603         margin-top: -.4em; /* Same line as the slider (height: .8em) */
    3604 }
    3605 
    3606 #diff-next-revision {
    3607         float: right;
    3608 }
    3609 
    3610 #diff-previous-revision {
    3611         float: left;
    3612 }
    3613 
    3614 #diff-slider {
    3615         width: 70%;
    3616         margin: 0 auto;
    3617 }
    3618 
    36193633.comparetwo #diff-slider {
    36203634        width: 95%;
    36213635}
  • wp-admin/js/revisions.js

     
    11window.wp = window.wp || {};
    22
    33(function($) {
    4         var Revision, Revisions, Diff, revisions;
     4        var revisions;
    55
    6         revisions = wp.revisions = function() {
    7                 Diff = revisions.Diff = new Diff();
    8         };
    9 
    10         _.extend( revisions, { model: {}, view: {}, controller: {} } );
     6        revisions = wp.revisions = { model: {}, view: {}, controller: {} };
    117
    128        // Link settings.
    13         revisions.model.settings = typeof wpRevisionsSettings === 'undefined' ? {} : wpRevisionsSettings;
     9        revisions.settings = typeof _wpRevisionsSettings === 'undefined' ? {} : _wpRevisionsSettings;
    1410
    1511
    1612        /**
    1713         * ========================================================================
    18          * CONTROLLERS
     14         * MODELS
    1915         * ========================================================================
    2016         */
    21 
    22         /**
    23          * wp.revisions.controller.Diff
    24          *
    25          * Controlls the diff
    26          */
    27         Diff = revisions.controller.Diff = Backbone.Model.extend( {
    28                 rightDiff: 1,
    29                 leftDiff: 1,
    30                 revisions: null,
    31                 leftHandleRevisions: null,
    32                 rightHandleRevisions: null,
    33                 revisionsInteractions: null,
    34                 autosaves: true,
    35                 showSplitView: true,
    36                 singleRevision: true,
    37                 leftModelLoading: false,        // keep track of model loads
    38                 rightModelLoading: false,       // disallow slider interaction, also repeat loads, while loading
    39                 tickmarkView: null, // the slider tickmarks
    40                 slider: null, // the slider instance
    41 
    42                 constructor: function() {
    43                         var self    = this;
    44                         this.slider = new revisions.view.Slider();
    45 
    46                         if ( null === this.revisions ) {
    47                                 this.revisions = new Revisions(); // set up collection
    48                                 this.startRightModelLoading();
    49 
    50                                 this.revisions.fetch({ // load revision data
    51                                         success: function() {
    52                                                 self.stopRightModelLoading();
    53                                                 self.completeApplicationSetup();
    54                                         }
    55                                 });
    56                         }
    57                 },
    58 
    59                 loadDiffs: function( models ) {
    60                         var self = this,
    61                                 revisionsToLoad = models.where( { completed: false } ),
    62                                 delay = 0,
    63                                 totalChanges;
    64 
    65                         // match slider to passed revision_id
    66                         _.each( revisionsToLoad, function( revision ) {
    67                                 if ( revision.get( 'ID' ) == revisions.model.settings.revision_id )
    68                                         self.rightDiff = self.revisions.indexOf( revision ) + 1;
    69                         });
    70 
    71                         _.each( revisionsToLoad, function( revision ) {
    72                                         _.delay( function() {
    73                                                 revision.fetch( {
    74                                                         update: true,
    75                                                         add: false,
    76                                                         remove: false,
    77                                                         success: function( model ) {
    78                                                                 model.set( 'completed', true );
    79 
    80                                                                 // stop spinner when all models are loaded
    81                                                                 if ( 0 === models.where( { completed: false } ).length )
    82                                                                         self.stopModelLoadingSpinner();
    83 
    84                                                                 totalChanges = model.get( 'linesAdded' ) + model.get( 'linesDeleted' ),
    85                                                                         scopeOfChanges = 'vsmall';
    86 
    87                                                                 // Note: hard coded scope of changes
    88                                                                 // TODO change to dynamic based on range of values
    89                                                                 if ( totalChanges > 1 && totalChanges <= 3 ) {
    90                                                                         scopeOfChanges = 'small';
    91                                                                 } else if ( totalChanges > 3 && totalChanges <= 5 ) {
    92                                                                         scopeOfChanges = 'med';
    93                                                                 } else if ( totalChanges > 5 && totalChanges <= 10 ) {
    94                                                                         scopeOfChanges = 'large';
    95                                                                 } else if ( totalChanges > 10 ) {
    96                                                                         scopeOfChanges = 'vlarge';
    97                                                                 }
    98                                                                 model.set( 'scopeOfChanges', scopeOfChanges );
    99                                                                 if ( 0 !== self.rightDiff &&
    100                                                                         model.get( 'ID' ) === self.revisions.at( self.rightDiff - 1 ).get( 'ID' ) ) {
    101                                                                         // reload if current model refreshed
    102                                                                         self.revisionView.render();
    103                                                                 }
    104                                                                 self.tickmarkView.render();
    105                                                         }
    106                                         } );
    107                                         }, delay ) ;
    108                                         delay = delay + 150; // stagger model loads to avoid hammering server with requests
    109                                 }
    110                         );
    111                 },
    112 
    113                 startLeftModelLoading: function() {
    114                         this.leftModelLoading = true;
    115                         $('#revision-diff-container').addClass('left-model-loading');
    116                 },
    117 
    118                 stopLeftModelLoading: function() {
    119                         this.leftModelLoading = false;
    120                 },
    121 
    122                 startRightModelLoading: function() {
    123                         this.rightModelLoading = true;
    124                         $('#revision-diff-container').addClass('right-model-loading');
    125                 },
    126 
    127                 stopRightModelLoading: function() {
    128                         this.rightModelLoading = false;
    129                 },
    130 
    131                 stopModelLoadingSpinner: function() {
    132                         $('#revision-diff-container').removeClass('right-model-loading');
    133                         $('#revision-diff-container').removeClass('left-model-loading');
    134                 },
    135 
    136                 reloadModel: function() {
    137                         if ( this.singleRevision ) {
    138                                 this.reloadModelSingle();
    139                         } else {
    140                                 this.reloadLeftRight();
    141                         }
    142                 },
    143 
    144                 // load the models for the single handle mode
    145                 reloadModelSingle: function() {
    146                         var self = this;
    147 
    148                         self.startRightModelLoading();
    149 
    150                         self.revisions.reload({
    151                                 options: {
    152                                 'showAutosaves': self.autosaves,
    153                                 'showSplitView': self.showSplitView
    154                                 },
    155 
    156                                 success: function() {
    157                                         var revisionCount = self.revisions.length;
    158                                         self.revisionView.model = self.revisions;
    159                                         self.revisionView.render();
    160                                         self.loadDiffs( self.revisions );
    161                                         self.tickmarkView.model = self.revisions;
    162                                         self.tickmarkView.render();
    163                                         self.slider.refresh({
    164                                                 'max': revisionCount - 1, // slider starts at 0 in single handle mode
    165                                                 'value': self.rightDiff - 1 // slider starts at 0 in single handle mode
    166                                         }, true);
    167                                 },
    168 
    169                                 error: function() {
    170                                         self.stopRightModelLoading();
    171                                 }
    172                         });
    173                 },
    174 
    175                 // load the models for the left handle (the right handler has moved)
    176                 reloadLeft: function() {
    177                         var self = this;
    178                         self.startLeftModelLoading();
    179                         self.leftHandleRevisions = new Revisions( {}, {
    180                                 'compareTo': self.revisions.at( self.rightDiff - 1 ).get( 'ID' ), // diff and model count off by 1
    181                                 'showAutosaves': self.autosaves,
    182                                 'showSplitView': self.showSplitView,
    183                                 'rightHandleAt': self.rightDiff
    184                         });
    185 
    186                         self.leftHandleRevisions.fetch({
    187                                 success: function(){
    188                                         self.stopLeftModelLoading();
    189                                         self.loadDiffs( self.leftHandleRevisions );
    190                                         self.tickmarkView.model = self.leftHandleRevisions;
    191                                         self.slider.refresh({
    192                                                 'max': self.revisions.length
    193                                         });
    194                                         // ensure right handle not beyond length
    195                                         if ( self.rightDiff > self.revisions.length )
    196                                                 self.rightDiff = self.revisions.length;
    197                                         },
    198 
    199                                 error: function() {
    200                                         self.stopLeftModelLoading();
    201                                 }
    202                         });
    203                 },
    204 
    205                 // load the models for the right handle (the left handle has moved)
    206                 reloadRight: function() {
    207                         var self = this;
    208                         self.startRightModelLoading();
    209                         self.rightHandleRevisions = new Revisions( {}, {
    210                                 'compareTo': self.revisions.at( self.leftDiff - 1 ).get( 'ID' ), // diff and model count off by 1
    211                                 'showAutosaves': self.autosaves,
    212                                 'showSplitView': self.showSplitView,
    213                                 'leftHandleAt': self.leftDiff
    214                         });
    215 
    216                         self.rightHandleRevisions.fetch({
    217                                 success: function(){
    218                                         self.stopRightModelLoading();
    219                                         self.loadDiffs( self.rightHandleRevisions );
    220                                         self.tickmarkView.model = self.rightHandleRevisions;
    221                                         self.slider.refresh({
    222                                                 'max': self.revisions.length
    223                                         }, true);
    224                                 },
    225 
    226                                 error: function( response ) {
    227                                         self.stopRightModelLoading();
    228                                 }
    229                         });
    230 
    231                 },
    232 
    233                 /**
    234                  * reloadLeftRight reload models for both the left and right handles
    235                  */
    236                 reloadLeftRight: function() {
    237                         this.startRightModelLoading();
    238                         this.startLeftModelLoading();
    239                         this.reloadLeft();
    240                         this.reloadRight();
    241                 },
    242 
    243                 disabledButtonCheck: function( val ) {
    244                         var maxVal = this.revisions.length - 1,
    245                                 next = ! isRtl ? $( '#next' ) : $( '#previous' ),
    246                                 prev = ! isRtl ? $( '#previous' ) : $( '#next' );
    247 
    248                         // Disable "Next" button if you're on the last node
    249                         if ( maxVal === val )
    250                                 next.prop( 'disabled', true );
    251                         else
    252                                 next.prop( 'disabled', false );
    253 
    254                         // Disable "Previous" button if you're on the 0 node
    255                         if ( 0 === val )
    256                                 prev.prop( 'disabled', true );
    257                         else
    258                                 prev.prop( 'disabled', false );
    259                 },
    260 
    261                 /**
    262                  * completeApplicationSetup finishes loading all views once the initial model load is complete
    263                  */
    264                 completeApplicationSetup: function() {
    265                         this.revisionView = new revisions.view.Diff({
    266                                 model: this.revisions
    267                         });
    268                         this.revisionView.render(); // render the revision view
    269 
    270                         this.loadDiffs( this.revisions ); // get the actual revisions data
    271 
    272                         this.revisionsInteractions = new revisions.view.Interact({
    273                                 model: this.revisions
    274                         });
    275                         this.revisionsInteractions.render(); // render the interaction view
    276 
    277                         this.tickmarkView = new revisions.view.Tickmarks({
    278                                 model: this.revisions
    279                         });
    280                         this.tickmarkView.render(); // render the tickmark view
     17        revisions.model.Slider = Backbone.Model.extend({
     18                defaults: {
     19                        value: 0,
     20                        min: 0,
     21                        max: 1,
     22                        step: 1
    28123                }
    28224        });
    28325
    284 
    28526        /**
    28627         * ========================================================================
    28728         * VIEWS
    28829         * ========================================================================
    28930         */
    29031
    291         /**
    292          * wp.revisions.view.Slider
    293          *
    294          * The slider
    295          */
    296         revisions.view.Slider = Backbone.View.extend({
    297                 el: $( '#diff-slider' ),
    298                 singleRevision: true,
    299 
    300                 initialize: function( options ) {
    301                         this.options = _.defaults( options || {}, {
    302                                 value: 0,
    303                                 min: 0,
    304                                 max: 1,
    305                                 step: 1
    306                         });
    307                 },
    308 
    309                 /**
    310                  * respond to slider slide events
    311                  * Note: in one handle mode, jQuery UI reports leftmost position as 0
    312                  * in two handle mode, jQuery UI Slider reports leftmost position as 1
    313                  */
    314                 slide: function( event, ui ) {
    315                         if ( this.singleRevision ) {
    316                                 Diff.rightDiff = ( ui.value + 1 );
    317                                 Diff.revisionView.render();
    318                                 Diff.disabledButtonCheck( ui.value );
    319                         } else {
    320                                 if ( ui.values[0] === ui.values[1] ) // prevent compare to self
    321                                         return false;
    322 
    323                                 if ( $( ui.handle ).hasClass( 'left-handle' ) ) {
    324                                         // Left handler
    325                                         if ( Diff.leftModelLoading ) // left model still loading, prevent sliding left handle
    326                                                 return false;
    327 
    328                                         Diff.leftDiff = isRtl ? ui.values[1] : ui.values[0]; // handles are reversed in RTL mode
    329                                 } else {
    330                                         // Right handler
    331                                         if ( Diff.rightModelLoading ) // right model still loading, prevent sliding right handle
    332                                                 return false;
    333 
    334                                         Diff.rightDiff = isRtl ? ui.values[0] : ui.values[1]; // handles are reversed in RTL mode
    335                                 }
    336 
    337                                 Diff.revisionView.render();
    338                         }
    339                 },
    340 
    341                 /**
    342                  * responds to slider start sliding events
    343                  * in two handle mode stores start position, so if unchanged at stop event no need to reload diffs
    344                  * also swaps in the appropriate models - left handled or right handled
    345                  */
    346                 start: function( event, ui ) {
    347                         // Not needed in one mode
    348                         if ( this.singleRevision )
    349                                 return;
    350 
    351                         if ( $( ui.handle ).hasClass( 'left-handle' ) ) {
    352                                 // Left handler
    353                                 if ( Diff.leftModelLoading ) // left model still loading, prevent sliding left handle
    354                                         return false;
    355 
    356                                 Diff.revisionView.draggingLeft = true;
    357 
    358                                 if ( Diff.revisionView.model !== Diff.leftHandleRevisions &&
    359                                                 null !== Diff.leftHandleRevisions ) {
    360                                         Diff.revisionView.model = Diff.leftHandleRevisions; // use the left handle models
    361                                         Diff.tickmarkView.model = Diff.leftHandleRevisions;
    362                                         Diff.tickmarkView.render();
    363                                 }
    364 
    365                                 Diff.leftDiffStart = isRtl ? ui.values[1] : ui.values[0]; // in RTL mode the 'left handle' is the second in the slider, 'right' is first
    366 
    367                         } else {
    368                                 // Right handler
    369                                 if ( Diff.rightModelLoading || 0 === Diff.rightHandleRevisions.length) // right model still loading, prevent sliding right handle
    370                                         return false;
    371 
    372                                 if ( Diff.revisionView.model !== Diff.rightHandleRevisions &&
    373                                                 null !== Diff.rightHandleRevisions ) {
    374                                         Diff.revisionView.model = Diff.rightHandleRevisions; // use the right handle models
    375                                         Diff.tickmarkView.model = Diff.rightHandleRevisions;
    376                                         Diff.tickmarkView.render();
    377                                 }
    378 
    379                                 Diff.revisionView.draggingLeft = false;
    380                                 Diff.rightDiffStart = isRtl ? ui.values[0] : ui.values[1]; // in RTL mode the 'left handle' is the second in the slider, 'right' is first
    381                         }
    382                 },
    383 
    384                 /**
    385                  * responds to slider stop events
    386                  * in two handled mode, if the handle that stopped has moved, reload the diffs for the other handle
    387                  * the other handle compares to this handle's position, so if it changes they need to be recalculated
    388                  */
    389                 stop: function( event, ui ) {
    390                         // Not needed in one mode
    391                         if ( this.singleRevision )
    392                                 return;
    393 
    394                         // calculate and generate a diff for comparing to the left handle
    395                         // and the right handle, swap out when dragging
    396                         if ( $( ui.handle ).hasClass( 'left-handle' ) ) {
    397                                 // Left handler
    398                                 if ( Diff.leftDiffStart !== isRtl ? ui.values[1] : ui.values[0] ) // in RTL mode the 'left handle' is the second in the slider, 'right' is first
    399                                         Diff.reloadRight();
    400                         } else {
    401                                 // Right handler
    402                                 if ( Diff.rightDiffStart !== isRtl ? ui.values[0] : ui.values[1] ) // in RTL mode the 'left handle' is the second in the slider, 'right' is first
    403                                         Diff.reloadLeft();
    404                         }
    405                 },
    406 
    407                 addTooltip: function( handle, message ) {
    408                         handle.find( '.ui-slider-tooltip' ).html( message );
    409                 },
    410 
    411                 width: function() {
    412                         return $( '#diff-slider' ).width();
    413                 },
    414 
    415                 setWidth: function( width ) {
    416                         $( '#diff-slider' ).width( width );
    417                 },
    418 
    419                 refresh: function( options, slide ) {
    420                         $( '#diff-slider' ).slider( 'option', options );
     32        // The frame view. This contains the entire page.
     33        revisions.view.Frame = wp.Backbone.View.extend({
     34                tagName: 'div',
     35                className: 'revisions',
     36                template: wp.template('revisions-frame'),
    42137
    422                         // Triggers the slide event
    423                         if ( slide )
    424                                 $( '#diff-slider' ).trigger( 'slide' );
    425 
    426                         Diff.disabledButtonCheck( options.value );
    427                 },
    428 
    429                 option: function( key ) {
    430                         return $( '#diff-slider' ).slider( 'option', key );
    431                 },
    432 
    433                 render: function() {
    434                         var self = this;
    435                         // this.$el doesn't work, why?
    436                         $( '#diff-slider' ).slider( {
    437                                 slide: $.proxy( self.slide, self ),
    438                                 start: $.proxy( self.start, self ),
    439                                 stop:  $.proxy( self.stop, self )
    440                         } );
    441 
    442                         // Set options
    443                         this.refresh( this.options );
     38                initialize: function() {
     39                        this.views.set( '.revisions-control-frame', new revisions.view.Controls() );
     40                        this.views.set( '.revisions-diff-frame', new revisions.view.Diff() );
    44441                }
    44542        });
    44643
    447         /**
    448          * wp.revisions.view.Tickmarks
    449          *
    450          * The slider tickmarks.
    451          */
    452         revisions.view.Tickmarks = Backbone.View.extend({
    453                 el: $('#diff-slider-ticks'),
    454                 template: wp.template('revision-ticks'),
    455                 model: Revision,
    456 
    457                 resetTicks: function() {
    458                         var sliderMax, sliderWidth, adjustMax, tickWidth, tickCount = 0, aTickWidth, tickMargin, self = this, firstTick, lastTick;
    459                         sliderMax   = Diff.slider.option( 'max' );
    460                         sliderWidth = Diff.slider.width();
    461                         adjustMax   = Diff.singleRevision ? 0 : 1;
    462                         tickWidth   = Math.floor( sliderWidth / ( sliderMax - adjustMax ) );
    463                         tickWidth   = ( tickWidth > 50 ) ? 50 : tickWidth; // set minimum and maximum widths for tick marks
    464                         tickWidth   = ( tickWidth < 6 ) ? 6 : tickWidth;
    465                         sliderWidth = tickWidth * ( sliderMax - adjustMax ); // calculate the slider width
    466                         aTickWidth  = $( '.revision-tick' ).width();
    467 
    468                         if ( tickWidth !== aTickWidth ) { // is the width already set correctly?
    469                                 $( '.revision-tick' ).each( function() {
    470                                         tickMargin = Math.floor( ( tickWidth - $( this ).width() ) / 2 ) + 1;
    471                                         $( this ).css( 'border-left', tickMargin + 'px solid #f7f7f7'); // space the ticks out using margins
    472                                         $( this ).css( 'border-right', ( tickWidth - tickMargin - $( this ).width() ) + 'px solid #f7f7f7'); // space the ticks out using margins
    473                                 });
    474                                 firstTick = $( '.revision-tick' ).first(); //cache selectors for optimization
    475                                 lastTick = $( '.revision-tick' ).last();
    476 
    477                                 sliderWidth = sliderWidth + Math.ceil( ( tickWidth - ( lastTick.outerWidth() - lastTick.innerWidth() ) ) / 2 ); // room for the last tick
    478                                 sliderWidth = sliderWidth + Math.ceil( ( tickWidth - ( firstTick.outerWidth() - firstTick.innerWidth() ) ) / 2 ); // room for the first tick
    479                                 firstTick.css( 'border-left', 'none' ); // first tick gets no left border
    480                                 lastTick.css( 'border-right', 'none' ); // last tick gets no right border
    481                         }
     44        // The control view.
     45        // This contains the revision slider, previous/next buttons, and the compare checkbox.
     46        revisions.view.Controls = wp.Backbone.View.extend({
     47                tagName: 'div',
     48                className: 'revisions-controls',
     49                template: wp.template('revisions-controls'),
    48250
    483                         /**
    484                          * reset the slider width
    485                          */
    486                         Diff.slider.setWidth( sliderWidth );
    487                         $( '.diff-slider-ticks-wrapper' ).width( sliderWidth );
    488                         $( '#diff-slider-ticks' ).width( sliderWidth );
    489 
    490                         /**
    491                          * go through all ticks, add hover and click interactions
    492                          */
    493                         $( '.revision-tick' ).each( function() {
    494                                 Diff.slider.addTooltip ( $( this ), Diff.revisions.at( tickCount++ ).get( 'titleTooltip' ) );
    495                                 $( this ).hover(
    496                                         function() {
    497                                                 $( this ).find( '.ui-slider-tooltip' ).show().append('<div class="arrow"></div>');
    498                                         },
    499                                         function() {
    500                                                 $( this ).find( '.ui-slider-tooltip' ).hide().find( '.arrow' ).remove();
    501                                         }
    502                                 );
    503 
    504                                 /**
    505                                  * move the slider handle when the tick marks are clicked
    506                                  */
    507                                 $( this ).on( 'click',
    508                                         { tickCount: tickCount }, // pass the tick through so we know where to move the handle
    509                                         function( event ) {
    510                                                 if ( Diff.slider.singleRevision ) { // single handle mode
    511                                                         Diff.rightDiff = event.data.tickCount; // reposition the right handle
    512                                                         Diff.slider.refresh({
    513                                                                 value: Diff.rightDiff - 1
    514                                                         } );
    515                                                 } else { //compare two mode
    516                                                         if ( isRtl ) {
    517                                                                 if ( event.data.tickCount < Diff.leftDiff ) { // click was on the 'left' side
    518                                                                                 Diff.rightDiff = event.data.tickCount; // set the 'right' handle location
    519                                                                                 Diff.reloadLeft(); // reload the left handle comparison models
    520                                                                 } else { // middle or 'right' clicks
    521                                                                         Diff.leftDiff = event.data.tickCount; // set the 'left' handle location
    522                                                                         Diff.reloadRight(); // reload right handle models
    523                                                                 }
    524                                                         } else {
    525                                                                 if ( event.data.tickCount < Diff.leftDiff ) { // click was on the 'left' side
    526                                                                                 Diff.leftDiff = event.data.tickCount; // set the left handle location
    527                                                                                 Diff.reloadRight(); // reload the right handle comparison models
    528                                                                 } else { // middle or 'right' clicks
    529                                                                         Diff.rightDiff = event.data.tickCount; // set the right handle location
    530                                                                         Diff.reloadLeft(); // reload left handle models
    531                                                                 }
    532                                                         }
    533                                                         Diff.slider.refresh( { // set the slider handle positions
    534                                                                 values: [ isRtl ? Diff.rightDiff : Diff.leftDiff, isRtl ? Diff.leftDiff : Diff.rightDiff ]
    535                                                         } );
    536                                                 }
    537                                                 Diff.revisionView.render(); // render the main view
    538                                         } );
    539                         } );
     51                initialize: function() {
     52                        this.views.set( new revisions.view.Slider() );
    54053                },
    54154
    542                 // render the tick mark view
    54355                render: function() {
    544                         var self = this, addHtml;
     56                        wp.Backbone.View.prototype.render.apply( this, arguments );
    54557
    546                         if ( null !== self.model ) {
    547                                 addHtml = "";
    548                                 _.each ( self.model.models, function( theModel ) {
    549                                         addHtml = addHtml + self.template ( theModel.toJSON() );
    550                                 });
    551                                 self.$el.html( addHtml );
    552 
    553                         }
    554                         self.resetTicks();
    555                         return self;
    556                 }
    557         } );
    558 
    559         /**
    560          * wp.revisions.view.Interact
    561          *
    562          * Next/Prev buttons and the slider
    563          */
    564         revisions.view.Interact = Backbone.View.extend({
    565                 el: $( '#revision-interact' ),
    566                 template: wp.template( 'revision-interact' ),
    567 
    568                 // next and previous buttons, only available in compare one mode
    569                 events: {
    570                         'click #next':     ! isRtl ? 'nextRevision' : 'previousRevision',
    571                         'click #previous': ! isRtl ? 'previousRevision' : 'nextRevision'
    572                 },
    573 
    574                 render: function() {
    575                         var modelcount;
    576                         this.$el.html( this.template );
    577 
    578                         modelcount = Diff.revisions.length;
    579 
    580                         Diff.slider.singleRevision = Diff.singleRevision;
    581                         Diff.slider.render();
    582 
    583                         if ( Diff.singleRevision ) {
    584                                 Diff.slider.refresh({
    585                                         value: Diff.rightDiff - 1, // rightDiff value is off model index by 1
    586                                         min: 0,
    587                                         max: modelcount - 1
    588                                 });
    589 
    590                                 $( '#revision-diff-container' ).removeClass( 'comparing-two-revisions' );
    591 
    592                         } else {
    593                                 Diff.slider.refresh({
    594                                         // in RTL mode the 'left handle' is the second in the slider, 'right' is first
    595                                         values: [ isRtl ? Diff.rightDiff : Diff.leftDiff, isRtl ? Diff.leftDiff : Diff.rightDiff ],
    596                                         min: 1,
    597                                         max: modelcount + 1,
    598                                         range: true
    599                                 });
    600 
    601                                 $( '#revision-diff-container' ).addClass( 'comparing-two-revisions' );
    602                                 // in RTL mode the 'left handle' is the second in the slider, 'right' is first
    603                                 $( '#diff-slider a.ui-slider-handle' ).first().addClass( isRtl ? 'right-handle' : 'left-handle' );
    604                                 $( '#diff-slider a.ui-slider-handle' ).last().addClass( isRtl ? 'left-handle' : 'right-handle' );
    605 
    606                         }
     58                        $('#wpbody-content .wrap').append( this.el );
     59                        this.views.ready();
    60760
    60861                        return this;
    609                 },
    610 
    611                 // go to the next revision
    612                 nextRevision: function() {
    613                         if ( Diff.rightDiff < this.model.length ) // unless at right boundry
    614                                 Diff.rightDiff = Diff.rightDiff + 1 ;
    615 
    616                         Diff.revisionView.render();
    617 
    618                         Diff.slider.refresh({
    619                                 value: Diff.rightDiff - 1
    620                         }, true );
    621                 },
    622 
    623                 // go to the previous revision
    624                 previousRevision: function() {
    625                         if ( Diff.rightDiff > 1 ) // unless at left boundry
    626                                 Diff.rightDiff = Diff.rightDiff - 1 ;
    627 
    628                         Diff.revisionView.render();
    629 
    630                         Diff.slider.refresh({
    631                                 value: Diff.rightDiff - 1
    632                         }, true );
    63362                }
    63463        });
    63564
    636         /**
    637          * wp.revisions.view.Diff
    638          *
    639          * Diff, compare two checkbox and restore button
    640          */
    641         revisions.view.Diff = Backbone.View.extend({
    642                 el: $( '#revisions-diff' ),
    643                 template: wp.template( 'revisions-diff' ),
    644                 draggingLeft: false,
    645 
    646                 // the compare two button is in this view, add the interaction here
    647                 events: {
    648                         'click #compare-two-revisions': 'compareTwo',
    649                         'click #restore-revision':      'restore'
    650                 },
    651 
    652                 // render the revisions
    653                 render: function() {
    654                         var addHtml = '', thediff;
    655 
    656                         // compare two revisions mode?
    657                         if ( ! Diff.singleRevision ) {
    658                                 if ( this.draggingLeft ) {
    659                                         thediff = Diff.leftDiff - 1; //leftDiff value is off model index by 1
    660                                         if ( this.model.at( thediff ) ) {
    661                                                 addHtml = this.template( this.model.at( thediff ).toJSON() );
    662                                         }
    663                                 } else { // dragging right handle
    664                                         thediff = Diff.rightDiff - 1; // rightDiff value is off model index by 1
    665                                         if ( this.model.at( thediff ) ) {
    666                                                 addHtml = this.template( this.model.at( thediff ).toJSON() );
    667                                         }
    668                                 }
    669                         } else { // end compare two revisions mode, eg only one slider handle
    670                                 if ( this.model.at( Diff.rightDiff - 1 ) ) { // rightDiff value is off model index by 1
    671                                         addHtml = this.template( this.model.at( Diff.rightDiff - 1 ).toJSON() );
    672                                 }
    673                         }
    674                         this.$el.html( addHtml );
    675 
    676                         if ( this.model.length < 2 ) {
    677                                 $( '#diff-slider' ).hide(); // don't allow compare two if fewer than three revisions
    678                                 $( '.diff-slider-ticks-wrapper' ).hide();
    679                         }
    680 
    681                         this.toggleCompareTwoCheckbox();
    682 
    683                         // hide the restore button when on the last sport/current post data
    684                         $( '#restore-revision' ).toggle( ! Diff.revisions.at( Diff.rightDiff - 1 ).get( 'isCurrent' ) );
    685 
    686                         return this;
     65        // The slider view.
     66        // Encapsulates all of the configuration for the jQuery UI slider into a view.
     67        revisions.view.Slider = wp.Backbone.View.extend({
     68                tagName: 'div',
     69                className: 'wp-slider',
     70
     71                initialize: function() {
     72                        // Create the slider model.
     73                        if ( ! this.model )
     74                                this.model = new revisions.model.Slider();
     75
     76                        // Attach the start, slide, and stop methods to the model.
     77                        _.bindAll( this, 'start', 'slide', 'stop' );
     78                        this.model.set({
     79                                start: this.start,
     80                                slide: this.slide,
     81                                stop: this.stop
     82                        });
    68783                },
    68884
    689                 toggleCompareTwoCheckbox: function() {
    690                         // don't allow compare two if fewer than three revisions
    691                         if ( this.model.length < 3 )
    692                                 $( '#toggle-revision-compare-mode' ).hide();
    693 
    694                         $( '#compare-two-revisions' ).prop( 'checked', ! Diff.singleRevision );
     85                ready: function() {
     86                        this.$el.slider( this.model.toJSON() );
     87                        this.model.on( 'change', function( model, options ) {
     88                                // Apply changes to slider here.
     89                        }, this );
    69590                },
    69691
    697                 // turn on/off the compare two mode
    698                 compareTwo: function() {
    699                         if ( $( '#compare-two-revisions' ).is( ':checked' ) ) { // compare 2 mode
    700                                 Diff.singleRevision = false ;
    701 
    702                                 // in RTL mode handles are swapped, so boundary checks are different;
    703                                 if ( isRtl ){
    704                                         Diff.leftDiff = Diff.revisions.length; // put the left handle at the rightmost position, representing current revision
    705 
    706                                         if ( Diff.revisions.length === Diff.rightDiff ) // make sure 'left' handle not in rightmost slot
    707                                                 Diff.rightDiff = Diff.rightDiff - 1;
    708                                 } else {
    709                                         if ( 1 === Diff.rightDiff ) // make sure right handle not in leftmost slot
    710                                                 Diff.rightDiff = 2;
    711                                 }
    712 
    713                                 Diff.revisionView.draggingLeft = false;
    714 
    715                                 revisions.model.settings.revision_id = ''; // reset passed revision id so switching back to one handle mode doesn't re-select revision
    716                                 Diff.reloadLeftRight(); // load diffs for left and right handles
    717                                 Diff.revisionView.model = Diff.rightHandleRevisions;
     92                start: function() {
    71893
    719                         } else { // compare one mode
    720                                 Diff.singleRevision = true;
    721                                 Diff.revisionView.draggingLeft = false;
    722                                 Diff.reloadModelSingle();
    723                         }
    724                         Diff.revisionsInteractions.render();
    725                         Diff.tickmarkView.render();
    72694                },
    72795
    728                 restore: function() {
    729                         document.location = $( '#restore-revision' ).data( 'restoreLink' );
    730                 }
    731         });
    732 
    733 
    734         /**
    735          * ========================================================================
    736          * MODELS
    737          * ========================================================================
    738          */
    739 
    740         /**
    741          * wp.revisions.Revision
    742          */
    743         Revision = revisions.model.Revision = Backbone.Model.extend({
    744                 idAttribute: 'ID',
     96                slide: function() {
    74597
    746                 defaults: {
    747                         ID: 0,
    748                         titleTo: '',
    749                         titleTooltip: '',
    750                         titleFrom: '',
    751                         diff: '<div class="diff-loading"><div class="spinner"></div></div>',
    752                         restoreLink: '',
    753                         completed: false,
    754                         linesAdded: 0,
    755                         linesDeleted: 0,
    756                         scopeOfChanges: 'none',
    757                         previousID: 0,
    758                         isCurrent: false
    75998                },
    76099
    761                 url: function() {
    762                         if ( Diff.singleRevision ) {
    763                                 return ajaxurl +
    764                                         '?action=revisions-data' +
    765                                         '&show_autosaves=true' +
    766                                         '&show_split_view=true' +
    767                                         '&nonce=' + revisions.model.settings.nonce +
    768                                         '&single_revision_id=' + this.id +
    769                                         '&compare_to=' + this.get( 'previousID' ) +
    770                                         '&post_id=' + revisions.model.settings.post_id;
    771                         } else {
    772                                 return this.collection.url() + '&single_revision_id=' + this.id;
    773                         }
     100                stop: function() {
    774101
    775102                }
    776103        });
    777104
    778         /**
    779          * wp.revisions.Revisions
    780          */
    781         Revisions = revisions.Revisions = Backbone.Collection.extend({
    782                 model: Revision,
    783 
    784                 initialize: function( models, options ) {
    785                         this.options = _.defaults( options || {}, {
    786                                 'compareTo': revisions.model.settings.post_id,
    787                                 'post_id': revisions.model.settings.post_id,
    788                                 'showAutosaves': true,
    789                                 'showSplitView': true,
    790                                 'rightHandleAt': 0,
    791                                 'leftHandleAt': 0,
    792                                 'nonce': revisions.model.settings.nonce
    793                         });
    794                 },
    795 
    796                 url: function() {
    797                         return ajaxurl +
    798                                 '?action=revisions-data' +
    799                                 '&compare_to=' + this.options.compareTo + // revision are we comparing to
    800                                 '&post_id=' + this.options.post_id + // the post id
    801                                 '&show_autosaves=' + this.options.showAutosaves + // show or hide autosaves
    802                                 '&show_split_view=' + this.options.showSplitView + // show in split view or single column view
    803                                 '&right_handle_at=' + this.options.rightHandleAt + // mark point for comparison list
    804                                 '&left_handle_at=' + this.options.leftHandleAt + // mark point for comparison list
    805                                 '&nonce=' + this.options.nonce;
    806                 },
    807 
    808                 reload: function( options ) {
    809                         this.options = _.defaults( options.options || {}, this.options );
    810 
    811                         this.fetch({
    812                                 success: options.success || null,
    813                                 error: options.error || null
    814                         });
    815                 }
    816 
    817         } );
     105        // The diff view.
     106        // This is the view for the current active diff.
     107        revisions.view.Diff = wp.Backbone.View.extend({
     108                tagName: 'div',
     109                className: 'revisions-diff',
     110                template: wp.template('revisions-diff')
     111        });
    818112
    819         $( wp.revisions );
     113        // Initialize the revisions UI.
     114        revisions.init = function() {
     115                new revisions.view.Frame().render();
     116        };
    820117
     118        $( revisions.init );
    821119}(jQuery));
  • wp-admin/revision.php

    $settings = array( 
    8585        'revision_id' => $revision_id
    8686);
    8787
    88 wp_localize_script( 'revisions', 'wpRevisionsSettings', $settings );
     88wp_localize_script( 'revisions', '_wpRevisionsSettings', $settings );
    8989
    9090/* Revisions Help Tab */
    9191
    require_once( './admin-header.php' ); 
    114114
    115115<div class="wrap">
    116116        <?php screen_icon(); ?>
    117         <div id="revision-diff-container" class="current-version right-model-loading">
    118                 <h2 class="long-header"><?php echo $h2; ?></h2>
     117        <h2 class="long-header"><?php echo $h2; ?></h2>
     118</div>
    119119
    120                 <div id="loading-status" class="updated message">
    121                         <p><span class="spinner" ></span></p>
    122                 </div>
     120<script id="tmpl-revisions-frame" type="text/html">
     121        <span class="spinner"></span>
     122        <div class="revisions-control-frame"></div>
     123        <div class="revisions-diff-frame"></div>
     124</script>
    123125
    124                 <div class="diff-slider-ticks-wrapper">
    125                         <div id="diff-slider-ticks"></div>
    126                 </div>
     126<script id="tmpl-revisions-controls" type="text/html">
     127        <div class="revision-toggle-compare-mode">
     128                <label>
     129                        <input type="checkbox" class="compare-two-revisions" />
     130                        <?php esc_attr_e( 'Compare two revisions' ); ?>
     131                </label>
     132        </div>
    127133
    128                 <div id="revision-interact"></div>
     134        <div class="revisions-previous">
     135                <input class="button" type="button" id="previous" value="<?php echo esc_attr_x( 'Previous', 'Button label for a previous revision' ); ?>" />
     136        </div>
    129137
    130                 <div id="revisions-diff"></div>
     138        <div class="revisions-next">
     139                <input class="button" type="button" id="next" value="<?php echo esc_attr_x( 'Next', 'Button label for a next revision' ); ?>" />
    131140        </div>
    132 </div>
     141
     142        <div class="revisions-slider"></div>
     143</script>
    133144
    134145<script id="tmpl-revisions-diff" type="text/html">
     146        DIFF
     147</script>
     148
     149<script id="tmpl-revisions-diff-old" type="text/html">
    135150        <div id="toggle-revision-compare-mode">
    136151                <label>
    137152                        <input type="checkbox" id="compare-two-revisions" />
    require_once( './admin-header.php' ); 
    157172                </div>
    158173        </div>
    159174
    160         </div>
    161 
    162175        <div id="diff-table">{{{ data.diff }}}</div>
    163176</script>
    164177