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