From 3690db14f70a347b182c6f7a271e90ad23ca5789 Mon Sep 17 00:00:00 2001 From: "Dominik Schilling (ocean90)" Date: Wed, 3 Jul 2013 20:27:19 +0000 Subject: [PATCH] Revisions UI update: * Restore Compare two mode * Restore tooltips * RTL support * First pass for URL routing and history props adamsilverstein, see #24425. git-svn-id: https://develop.svn.wordpress.org/trunk@24549 602fd350-edb4-49c9-b593-d223f7449a82 --- wp-admin/css/colors-fresh.css | 4 +- wp-admin/css/wp-admin-rtl.css | 6 +- wp-admin/css/wp-admin.css | 52 ++-- wp-admin/js/revisions.js | 431 +++++++++++++++++++++++++++------- wp-admin/revision.php | 106 +++------ 5 files changed, 424 insertions(+), 175 deletions(-) diff --git a/wp-admin/css/colors-fresh.css b/wp-admin/css/colors-fresh.css index ddc73e932b..b92ab7a1aa 100644 --- a/wp-admin/css/colors-fresh.css +++ b/wp-admin/css/colors-fresh.css @@ -1379,8 +1379,8 @@ table.diff .diff-addedline ins { border: 1px solid #dfdfdf; } -#diff-slider .ui-slider-tooltip, -#diff-slider-ticks .ui-slider-tooltip { +.ui-slider-tooltip, +.ui-slider-tooltip { border-color: #d7d7d7; background-color: #fff; } diff --git a/wp-admin/css/wp-admin-rtl.css b/wp-admin/css/wp-admin-rtl.css index 24426c8ce0..40428571a9 100644 --- a/wp-admin/css/wp-admin-rtl.css +++ b/wp-admin/css/wp-admin-rtl.css @@ -975,17 +975,17 @@ th.sorted a span { left: 6px; } -#toggle-revision-compare-mode { +.revision-toggle-compare-mode { right: auto; left: 0; padding: 9px 0 0 9px; } -#diff-next-revision { +.revisions-next { float: left; } -#diff-previous-revision { +.revisions-previous { float: right; } diff --git a/wp-admin/css/wp-admin.css b/wp-admin/css/wp-admin.css index 668cf2c6c1..3bd9e32b4b 100644 --- a/wp-admin/css/wp-admin.css +++ b/wp-admin/css/wp-admin.css @@ -3498,10 +3498,14 @@ td.plugin-title p { .revisions-controls { height: 60px; padding: 40px 0 20px; - border-bottom: 1px solid #dfdfdf; + border-bottom: none; margin-bottom: 10px; } +.comparing-two-revisions .revisions-controls { + height: 90px; +} + .revisions-meta { margin-top: 15px; } @@ -3510,6 +3514,10 @@ td.plugin-title p { top: 0; right: 0; } +.comparing-two-revisions .revisions-previous, +.comparing-two-revisions .revisions-next { + display: none; +} .revisions-previous { float: left; @@ -3532,6 +3540,7 @@ td.plugin-title p { table.diff { width: 100%; + white-space: pre-wrap; } table.diff col.content { @@ -3590,18 +3599,11 @@ table.diff .diff-addedline ins { width: 95%; } -#diff-slider .ui-slider-tooltip, -#diff-slider-ticks .ui-slider-tooltip { - display: none; +.revisions .ui-slider-tooltip { position: absolute; - bottom: 21px; - margin-left: -74px; -} - -#diff-slider .ui-state-active .ui-slider-tooltip, -#diff-slider .ui-state-focus .ui-slider-tooltip, -#diff-slider .ui-state-hover .ui-slider-tooltip { - display: block; + bottom: 86px; + margin-left: -70px; + line-height: 28px; } #diff-title-to strong { @@ -3655,8 +3657,8 @@ table.diff .diff-addedline ins { margin-top: 20px; } -.comparing-two-revisions #diff-previous-revision, -.comparing-two-revisions #diff-next-revision, +#diff-previous-revision, +#diff-next-revision, #diff-header-from { display: none; } @@ -3668,6 +3670,9 @@ table.diff .diff-addedline ins { display: block; } +.comparing-two-revisions .revisions-tooltip div { + margin-bottom: 30px; +} .diff-slider-ticks-wrapper { margin: 0 auto; text-align: left; @@ -3740,7 +3745,9 @@ table.diff .diff-addedline ins { .ui-slider-tooltip img { float: left; margin-right: 5px; - margin-top: 5px; + margin-top: 2px; + padding: 0; + vertical-align: middle; } @@ -3748,7 +3755,7 @@ table.diff .diff-addedline ins { .ui-tooltip, .ui-slider-tooltip { - padding: 8px; + padding: 4px; position: absolute; z-index: 9999; max-width: 300px; @@ -3768,7 +3775,11 @@ body .ui-slider-tooltip { .ui-tooltip, .ui-slider-tooltip { - padding: 5px 10px; + padding: 4px 4px; +} + +.revisions-tooltip { + display: none; } .arrow { @@ -3776,10 +3787,10 @@ body .ui-slider-tooltip { height: 16px; overflow: hidden; position: absolute; - left: 50%; + left: 0; margin-left: -35px; - bottom: -16px; - z-index: 99999; + bottom: 71px; + z-index: 10000; } .arrow.top { @@ -3871,6 +3882,7 @@ body .ui-slider-tooltip { .wp-slider.ui-slider-horizontal { height: .8em; + z-index: 10001; } .wp-slider.ui-slider-horizontal .ui-slider-handle { diff --git a/wp-admin/js/revisions.js b/wp-admin/js/revisions.js index 67f7f80b8d..06d7dadf78 100644 --- a/wp-admin/js/revisions.js +++ b/wp-admin/js/revisions.js @@ -3,7 +3,7 @@ window.wp = window.wp || {}; (function($) { var revisions; - revisions = wp.revisions = { model: {}, view: {}, controller: {} }; + revisions = wp.revisions = { model: {}, view: {}, controller: {}, router: {} }; // Link settings. revisions.settings = typeof _wpRevisionsSettings === 'undefined' ? {} : _wpRevisionsSettings; @@ -30,7 +30,7 @@ window.wp = window.wp || {}; comparator: function( revision ) { return revision.id; - }, + } }); revisions.model.Field = Backbone.Model.extend({}); @@ -101,7 +101,6 @@ window.wp = window.wp || {}; return this.fetch({ data: { compare: comparisons }, remove: false }); }, -/**/ loadLast: function( num ) { num = num || 1; var ids = this.getProximalDiffIds(); @@ -194,14 +193,21 @@ window.wp = window.wp || {}; initialize: function( attributes, options ) { this.revisions = options.revisions; this.diffs = new revisions.model.Diffs( [], {revisions: this.revisions} ); - - this.listenTo( this, 'change:from change:to', this.updateDiffId ); + this.listenTo( this, 'change:from', this.updateDiffFrom ); + this.listenTo( this, 'change:to', this.updateDiffTo ); + this.revisionsRouter = new revisions.router.Router(); + this.revisionsRouter.model = this; }, - updateDiffId: function() { + updateDiffTo: function() { var from = this.get( 'from' ); var to = this.get( 'to' ); - this.set( 'diffId', (from ? from.id : '0') + ':' + to.id ); + this.set( 'diffId', (from ? from.id : '0' ) + ':' + to.id ); + }, + + updateDiffFrom: function() { + if ( this.get( 'compareTwoMode' ) ) + this.updateDiffTo(); } }); @@ -243,6 +249,7 @@ window.wp = window.wp || {}; this.model.diffs.loadAllBy( 50 ); }, this ) ); } + Backbone.history.start(); }, render: function() { @@ -266,17 +273,26 @@ window.wp = window.wp || {}; }); // The control view. - // This contains the revision slider, previous/next buttons, and the compare checkbox. + // This contains the revision slider, previous/next buttons, the meta info and the compare checkbox. revisions.view.Controls = wp.Backbone.View.extend({ tagName: 'div', className: 'revisions-controls', initialize: function() { // Add the button view - this.views.add( new revisions.view.Buttons({ + this.views.add( new revisions.view.Buttons({ model: this.model })); + // Add the checkbox view + this.views.add( new revisions.view.Checkbox({ + model: this.model + })); + + // Add the tooltip view + this.views.add( new revisions.view.Tooltip({ + model: this.model + })); // Add the Slider view this.views.add( new revisions.view.Slider({ model: this.model @@ -296,14 +312,14 @@ window.wp = window.wp || {}; className: 'revisions-meta', template: wp.template('revisions-meta'), - initialize: function() { - this.listenTo( this.model, 'change:diffId', this.updateMeta ); - }, - events: { 'click #restore-revision': 'restoreRevision' }, + initialize: function() { + this.listenTo( this.model, 'change:diffId', this.updateMeta ); + }, + restoreRevision: function() { var restoreUrl = this.model.get('to').attributes.restoreUrl.replace(/&/g, '&'); document.location = restoreUrl; @@ -312,99 +328,200 @@ window.wp = window.wp || {}; updateMeta: function() { this.$el.html( this.template( this.model.toJSON() ) ); if( this.model.get( 'to' ).attributes.current ) { - $( '#restore-revision' ).prop( 'disabled', true); + $( '#restore-revision' ).prop( 'disabled', true ); } else { - $( '#restore-revision' ).prop( 'disabled', false) + $( '#restore-revision' ).prop( 'disabled', false ); } } }); + // The checkbox view. + // Encapsulates all of the configuration for the compare checkbox. + revisions.view.Checkbox = wp.Backbone.View.extend({ + tagName: 'div', + className: 'revisions-checkbox', + template: wp.template( 'revisions-checkbox' ), + + events: { + 'click .compare-two-revisions': 'compareTwoToggle' + }, + + initialize: function() { + this.$el.html( this.template() ); + this.listenTo( this.model, 'change:compareTwoMode', this.updateCompareTwoMode ); + }, + + updateCompareTwoMode: function() { + if ( this.model.get( 'compareTwoMode' ) ) { + $( '.compare-two-revisions' ).parent().css('border', '1px solid #f00;').prop( 'checked', true ); + $( '.revisions-control-frame' ).addClass( 'comparing-two-revisions' ); + // in RTL mode the 'left handle' is the second in the slider, 'right' is first + $( '.wp-slider a.ui-slider-handle' ).first().addClass( isRtl ? 'right-handle' : 'left-handle' ); + $( '.wp-slider a.ui-slider-handle' ).last().addClass( isRtl ? 'left-handle' : 'right-handle' ); + } else { + $( '.compare-two-revisions' ).prop( 'checked', false ); + $( '.revisions-control-frame' ).removeClass( 'comparing-two-revisions' ); + $( '.wp-slider a.ui-slider-handle' ).removeClass( 'left-handle' ).removeClass( 'right-handle' ); + } + + }, + + // Toggle the compare two mode feature when the compare two checkbox is checked. + compareTwoToggle: function( event ) { + // Activate compare two mode? + if ( $( '.compare-two-revisions' ).is( ':checked' ) ) { + this.model.set( { compareTwoMode: true } ); + } else { + this.model.set( { compareTwoMode: false } ); + } + + // Update route + this.model.revisionsRouter.navigateRoute( this.model.get( 'to').id, this.model.get( 'from' ).id ); + }, + + ready: function() { + // Hide compare two mode toggle when fewer than three revisions. + if ( this.model.revisions.length < 3 ) + $( '.revision-toggle-compare-mode' ).hide(); + } + + }); + + // The tooltip view. + // Encapsulates the tooltip. + revisions.view.Tooltip = wp.Backbone.View.extend({ + tagName: 'div', + className: 'revisions-tooltip', + template: wp.template( 'revisions-tooltip' ), + + initialize: function() { + this.listenTo( this.model, 'change:sliderHovering', this.sliderHoveringChanged ); + this.listenTo( this.model, 'change:tooltipPosition', this.tooltipPositionChanged ); + }, + + ready: function() { + }, + + // Show or hide tooltip based on sliderHovering is true + sliderHoveringChanged: function() { + if ( this.model.get( 'sliderHovering' ) ) { + this.$el.show(); + } else { + this.$el.hide(); + } + }, + + tooltipPositionChanged: function() { + this.$el.html( this.template( this.model.revisions.at( this.model.get( 'hoveringAt') ).toJSON() ) ); + + this.setTooltip( this.model.get( 'tooltipPosition' ) ); + }, + + setTooltip: function( tooltipPosition ) { + var offset = $( '.revisions-buttons' ).offset().left, + calculatedX = tooltipPosition - offset; + + + this.$el.find( '.ui-slider-tooltip' ).css( 'left', calculatedX ); + this.$el.find( '.arrow' ).css( 'left', calculatedX ); + } + }); // The buttons view. - // Encapsulates all of the configuration for the previous/next buttons, and the compare checkbox. + // Encapsulates all of the configuration for the previous/next buttons. revisions.view.Buttons = wp.Backbone.View.extend({ tagName: 'div', className: 'revisions-buttons', - template: wp.template('revisions-controls'), - - initialize: function() { - this.$el.html( this.template() ) - }, + template: wp.template( 'revisions-buttons' ), events: { 'click #next': 'nextRevision', 'click #previous': 'previousRevision' }, - - gotoModel: function( toIndex ) { - var attributes = { - to: this.model.revisions.at( isRtl ? this.model.revisions.length - toIndex - 1 : toIndex ) // Reverse directions for Rtl - }; - // If we're at the first revision, unset 'from'. - if ( isRtl ? this.model.revisions.length - toIndex - 1 : toIndex ) // Reverse directions for Rtl - attributes.from = this.model.revisions.at( isRtl ? this.model.revisions.length - toIndex - 2 : toIndex - 1 ); - else - this.model.unset('from', { silent: true }); - this.model.set( attributes ); - }, - - nextRevision: function() { - var toIndex = this.model.revisions.indexOf( this.model.get( 'to' ) ); - toIndex = isRtl ? toIndex - 1 : toIndex + 1; - this.gotoModel( toIndex ); - }, - - previousRevision: function() { - var toIndex = this.model.revisions.indexOf( this.model.get('to') ); - toIndex = isRtl ? toIndex + 1 : toIndex - 1; - this.gotoModel( toIndex ); + initialize: function() { + this.$el.html( this.template() ); }, ready: function() { this.listenTo( this.model, 'change:diffId', this.disabledButtonCheck ); }, - // Check to see if the Previous or Next buttons need to be disabled or enabled - disabledButtonCheck: function() { - var maxVal = isRtl ? 0 : this.model.revisions.length - 1, - minVal = isRtl ? this.model.revisions.length - 1 : 0, - next = $( '.revisions-next .button' ), - previous = $( '.revisions-previous .button' ), - val = this.model.revisions.indexOf( this.model.get( 'to' ) ); + // Go to a specific modelindex, taking into account RTL mode. + gotoModel: function( toIndex ) { + var attributes = { + to: this.model.revisions.at( isRtl ? this.model.revisions.length - toIndex - 1 : toIndex ) // Reverse directions for RTL. + }; + // If we're at the first revision, unset 'from'. + if ( isRtl ? this.model.revisions.length - toIndex - 1 : toIndex ) // Reverse directions for RTL + attributes.from = this.model.revisions.at( isRtl ? this.model.revisions.length - toIndex - 2 : toIndex - 1 ); + else + this.model.unset('from', { silent: true }); - // Disable "Next" button if you're on the last node + this.model.set( attributes ); + + // Update route + this.model.revisionsRouter.navigateRoute( attributes.to.id, attributes.from ? attributes.from.id : 0 ); + }, + + // Go to the 'next' revision, direction takes into account RTL mode. + nextRevision: function() { + var toIndex = isRtl ? this.model.revisions.length - this.model.revisions.indexOf( this.model.get( 'to' ) ) - 1 : this.model.revisions.indexOf( this.model.get( 'to' ) ); + toIndex = isRtl ? toIndex - 1 : toIndex + 1; + this.gotoModel( toIndex ); + }, + + // Go to the 'previous' revision, direction takes into account RTL mode. + previousRevision: function() { + var toIndex = isRtl ? this.model.revisions.length - this.model.revisions.indexOf( this.model.get( 'to' ) ) - 1 : this.model.revisions.indexOf( this.model.get( 'to' ) ); + toIndex = isRtl ? toIndex + 1 : toIndex - 1; + this.gotoModel( toIndex ); + }, + + // Check to see if the Previous or Next buttons need to be disabled or enabled. + disabledButtonCheck: function() { + var maxVal = this.model.revisions.length - 1, + minVal = 0, + next = $( '.revisions-next .button' ), + previous = $( '.revisions-previous .button' ), + val = this.model.revisions.indexOf( this.model.get( 'to' ) ); + + // Disable "Next" button if you're on the last node. if ( maxVal === val ) next.prop( 'disabled', true ); else next.prop( 'disabled', false ); - // Disable "Previous" button if you're on the first node + // Disable "Previous" button if you're on the first node. if ( minVal === val ) previous.prop( 'disabled', true ); else previous.prop( 'disabled', false ); - }, - - + } }); + // The slider view. // Encapsulates all of the configuration for the jQuery UI slider into a view. revisions.view.Slider = wp.Backbone.View.extend({ tagName: 'div', className: 'wp-slider', + events: { + 'mousemove' : 'mousemove', + 'mouseenter' : 'mouseenter', + 'mouseleave' : 'mouseleave' + }, + initialize: function() { _.bindAll( this, 'start', 'slide', 'stop' ); // Create the slider model from the provided collection data. - // TODO: This should actually pull from the model's `to` key. var latestRevisionIndex = this.model.revisions.length - 1; // Find the initially selected revision var initiallySelectedRevisionIndex = - this.model.revisions.indexOf( + this.model.revisions.indexOf( this.model.revisions.findWhere( { id: Number( revisions.settings.selectedRevision ) } ) ); this.settings = new revisions.model.Slider({ @@ -418,57 +535,168 @@ window.wp = window.wp || {}; ready: function() { this.$el.slider( this.settings.toJSON() ); + + // Listen for changes in Compare Two Mode setting + this.listenTo( this.model, 'change:compareTwoMode', this.updateSliderSettings ); + this.settings.on( 'change', function( model, options ) { - // Apply changes to slider settings here. - this.$el.slider( { value: this.model.revisions.indexOf( this.model.get( 'to' ) ) } ); // Set handle to current to model + this.updateSliderSettings(); }, this ); - // Reset to the initially selected revision - this.slide( '', this.settings.attributes ); // Listen for changes in the diffId this.listenTo( this.model, 'change:diffId', this.diffIdChanged ); + // Reset to the initially selected revision + this.slide( '', this.settings.attributes ); + + }, + + mousemove: function( e ) { + var sliderLeft = Math.ceil( this.$el.offset().left ), + sliderWidth = Math.ceil( this.$el.width() ) + 2, + tickWidth = Math.ceil( ( sliderWidth ) / this.model.revisions.length ), + actualX = e.clientX - sliderLeft, + hoveringAt = Math.floor( actualX / tickWidth ); + + // Reverse direction in Rtl mode. + if ( isRtl ) + hoveringAt = this.model.revisions.length - hoveringAt - 1; + + // Ensure sane value for hoveringAt. + if ( hoveringAt < 0 ) + hoveringAt = 0; + else if ( hoveringAt >= this.model.revisions.length ) + hoveringAt = this.model.revisions.length - 1; + + // Update the model + this.model.set( 'hoveringAt', hoveringAt ); + this.model.set( 'tooltipPosition', e.clientX ); + + }, + + mouseenter: function( e ) { + this.model.set( 'sliderHovering', true ); + }, + + mouseleave: function( e ) { + this.model.set( 'sliderHovering', false ); + }, + + updateSliderSettings: function() { + if ( isRtl ) { + this.$el.slider( { // Order reversed in RTL mode + value: this.model.revisions.length - this.model.revisions.indexOf( this.model.get( 'to' ) ) - 1 + } ); + } else { + if ( this.model.get( 'compareTwoMode' ) ) { + this.$el.slider( { // Set handles to current from/to models + values: [ + this.model.revisions.indexOf( this.model.get( 'from' ) ), + this.model.revisions.indexOf( this.model.get( 'to' ) ) + ], + value: null, + range: true // Range mode ensures handles can't cross + } ); + } else { + this.$el.slider( { // Set handle to current to model + value: this.model.revisions.indexOf( this.model.get( 'to' ) ), + values: null, // Clear existing two handled values + range: false + } ); + } + } + if ( this.model.get( 'compareTwoMode' ) ){ + $( '.revisions' ).addClass( 'comparing-two-revisions' ); + + // in RTL mode the 'left handle' is the second in the slider, 'right' is first + $( 'a.ui-slider-handle', this.$el ) + .first() + .addClass( isRtl ? 'right-handle' : 'left-handle' ) + .removeClass( isRtl ? 'left-handle' : 'right-handle' ); + $( 'a.ui-slider-handle', this.$el ) + .last() + .addClass( isRtl ? 'left-handle' : 'right-handle' ) + .removeClass( isRtl ? 'right-handle' : 'left-handle' ); + } else { + $( '.revisions' ).removeClass( 'comparing-two-revisions' ); + } }, diffIdChanged: function() { // Reset the view settings when diffId is changed - this.settings.set( { 'value': this.model.revisions.indexOf( this.model.get( 'to' ) ) } ); + if ( this.model.get( 'compareTwoMode' ) ) { + this.settings.set( { 'values': [ + this.model.revisions.indexOf( this.model.get( 'from' ) ), + this.model.revisions.indexOf( this.model.get( 'to' ) ) + ] } ); + } else { + this.settings.set( { 'value': this.model.revisions.indexOf( this.model.get( 'to' ) ) } ); + } + }, + + getSliderPosition: function( ui ){ + return isRtl ? this.model.revisions.length - ui.value - 1 : ui.value; }, start: function( event, ui ) { - // Track the mouse position to enable smooth dragging, overrides default jquery ui step behaviour - $( window ).mousemove( function( e ) { - var sliderLeft = $( '.wp-slider' ).offset().left, - sliderRight = sliderLeft + $( '.wp-slider' ).width(); + if ( ! this.model.get( 'compareTwoMode' ) ) + return; - // Follow mouse movements, as long as handle remains inside slider + // Track the mouse position to enable smooth dragging, overrides default jquery ui step behaviour . + $( window ).mousemove( function( e ) { + var sliderLeft = this.$el.offset().left, + sliderRight = sliderLeft + this.$el.width(); + + // Follow mouse movements, as long as handle remains inside slider. if ( e.clientX < sliderLeft ) { - $( ui.handle ).css( 'left', 0 ); // Mouse to left of slider + $( ui.handle ).css( 'left', 0 ); // Mouse to left of slider. } else if ( e.clientX > sliderRight ) { - $( ui.handle ).css( 'left', sliderRight - sliderLeft); // Mouse to right of slider + $( ui.handle ).css( 'left', sliderRight - sliderLeft); // Mouse to right of slider. } else { - $( ui.handle ).css( 'left', e.clientX - sliderLeft ); // Mouse in slider + $( ui.handle ).css( 'left', e.clientX - sliderLeft ); // Mouse in slider. } - } ); // End mousemove + } ); // End mousemove. }, slide: function( event, ui ) { - var attributes = { - to: this.model.revisions.at( isRtl ? this.model.revisions.length - ui.value - 1 : ui.value ) // Reverse directions for Rtl - }; + var attributes; + // Compare two revisions mode + if ( 'undefined' !== typeof ui.values && this.model.get( 'compareTwoMode' ) ) { + // Prevent sliders from occupying same spot + if ( ui.values[1] === ui.values[0] ) + return false; - // If we're at the first revision, unset 'from'. - if ( isRtl ? this.model.revisions.length - ui.value - 1 : ui.value ) // Reverse directions for Rtl - attributes.from = this.model.revisions.at( isRtl ? this.model.revisions.length - ui.value - 2 : ui.value - 1 ); - else - this.model.unset('from', { silent: true }); + attributes = { + to: this.model.revisions.at( isRtl ? this.model.revisions.length - ui.values[1] - 1 : ui.values[1] ), // Reverse directions for RTL. + from: this.model.revisions.at( isRtl ? this.model.revisions.length - ui.values[0] - 1 : ui.values[0] ) // Reverse directions for RTL. + }; + } else { + // Compare single revision mode + var sliderPosition = this.getSliderPosition( ui ); + attributes = { + to: this.model.revisions.at( sliderPosition ) + }; + // If we're at the first revision, unset 'from'. + if ( sliderPosition ) // Reverse directions for RTL. + attributes.from = this.model.revisions.at( sliderPosition - 1 ); + else + this.model.unset('from', { silent: true }); + } this.model.set( attributes ); + + // Maintain state history when dragging + this.model.revisionsRouter.navigateRoute( attributes.to.id, ( attributes.from ? attributes.from.id : 0 ) ); }, stop: function( event, ui ) { - $( window ).unbind( 'mousemove' ); // Stop tracking the mouse - // Reset settings pops handle back to the step position + if ( ! this.model.get( 'compareTwoMode' ) ) + return; + + // Stop tracking the mouse. + $( window ).unbind( 'mousemove' ); + + // Reset settings pops handle back to the step position. this.settings.trigger( 'change' ); } }); @@ -486,6 +714,45 @@ window.wp = window.wp || {}; } }); + // The revisions router + // takes URLs with #hash fragments and routes them + revisions.router.Router = Backbone.Router.extend({ + model: null, + + routes: { + 'revision/from/:from/to/:to/handles/:handles': 'gotoRevisionId' + }, + + navigateRoute: function( to, from ) { + var navigateTo = '/revision/from/' + from + '/to/' + to + '/handles/'; + if ( this.model.get( 'compareTwoMode' ) ){ + navigateTo = navigateTo + '2'; + } else { + navigateTo = navigateTo + '1'; + } + this.navigate( navigateTo ); + }, + + gotoRevisionId: function( from, to, handles ) { + if ( '2' === handles ) { + this.model.set( { compareTwoMode: true } ); + } else { + this.model.set( { compareTwoMode: false } ); + } + + if ( 'undefined' !== typeof this.model ) { + var selectedToRevision = + this.model.revisions.findWhere( { 'id': Number( to ) } ), + selectedFromRevision = + this.model.revisions.findWhere( { 'id': Number( from ) } ); + + this.model.set( { + to: selectedToRevision, + from: selectedFromRevision } ); + } + } + }); + // Initialize the revisions UI. revisions.init = function() { revisions.view.frame = new revisions.view.Frame({ diff --git a/wp-admin/revision.php b/wp-admin/revision.php index 7c390989c6..036a116741 100644 --- a/wp-admin/revision.php +++ b/wp-admin/revision.php @@ -115,20 +115,11 @@ require_once( './admin-header.php' ); - + + + - - - - -