Ticket #23901: 23901.3.patch
File 23901.3.patch, 56.3 KB (added by , 12 years ago) |
---|
-
wp-admin/includes/ajax-actions.php
2092 2092 function wp_ajax_revisions_data() { 2093 2093 check_ajax_referer( 'revisions-ajax-nonce', 'nonce' ); 2094 2094 2095 $compare_to = isset( $_GET['compare_to'] ) ? absint( $_GET['compare_to'] ) : 0; 2096 $show_autosaves = isset( $_GET['show_autosaves'] ) ? $_GET['show_autosaves'] : ''; 2097 $show_split_view = isset( $_GET['show_split_view'] ) ? $_GET['show_split_view'] : ''; 2098 $post_id = isset( $_GET['post_id'] ) ? absint( $_GET['post_id'] ) : ''; 2099 $right_handle_at = isset( $_GET['right_handle_at'] ) ? $_GET['right_handle_at'] : 0; 2100 $left_handle_at = isset( $_GET['left_handle_at'] ) ? $_GET['left_handle_at'] : 0; 2101 $single_revision_id = isset( $_GET['single_revision_id'] ) ? $_GET['single_revision_id'] : 0; 2095 $compare_to = ! empty( $_GET['compare_to'] ) ? absint( $_GET['compare_to'] ) : 0; 2096 $show_autosaves = ! empty( $_GET['show_autosaves'] ); 2097 $show_split_view = ! empty( $_GET['show_split_view'] ); 2098 $post_id = ! empty( $_GET['post_id'] ) ? absint( $_GET['post_id'] ) : 0; 2099 $right_handle_at = ! empty( $_GET['right_handle_at'] ) ? $_GET['right_handle_at'] : 0; 2100 $left_handle_at = ! empty( $_GET['left_handle_at'] ) ? $_GET['left_handle_at'] : 0; 2101 $single_revision_id = ! empty( $_GET['single_revision_id'] ) ? $_GET['single_revision_id'] : 0; 2102 $compare_two_mode = (bool) $post_id; 2102 2103 2103 $compare_two_mode = ( '' == $post_id ) ? false : true;2104 2104 // 2105 2105 //TODO: currently code returns all possible comparisons for the indicated 'compare_to' revision 2106 2106 //however, the front end prevents users from pulling the right handle past the left or the left pass the right, 2107 2107 //so only the possible diffs need be generated 2108 2108 // 2109 2109 $alltherevisions = array(); 2110 if ( '' ==$post_id )2110 if ( ! $post_id ) 2111 2111 $post_id = $compare_to; 2112 2112 2113 2113 if ( ! current_user_can( 'read_post', $post_id ) ) … … 2116 2116 if ( ! $revisions = wp_get_post_revisions( $post_id ) ) 2117 2117 return; 2118 2118 2119 /* translators: revision date format, see http://php.net/date */2120 $datef = _x( 'j F, Y @ G:i:s', 'revision date format');2121 2122 2119 $left_revision = get_post( $compare_to ); 2123 2120 2124 2121 //single model fetch mode 2125 2122 //return the diff of a single revision comparison 2126 if ( 0 !=$single_revision_id ) {2123 if ( $single_revision_id ) { 2127 2124 $right_revision = get_post( $single_revision_id ); 2128 2125 2129 if ( 0 ==$compare_to )2126 if ( ! $compare_to ) 2130 2127 $left_revision = get_post( $post_id ); 2131 2128 2132 // make sure the right revision is the most recent2133 if ( $compare_two_mode && $right_revision->ID < $left_revision->ID ) {2134 $temp = $left_revision;2135 $left_revision = $right_revision;2136 $right_revision = $temp;2137 }2129 // make sure the right revision is the most recent 2130 if ( $compare_two_mode && $right_revision->ID < $left_revision->ID ) { 2131 $temp = $left_revision; 2132 $left_revision = $right_revision; 2133 $right_revision = $temp; 2134 } 2138 2135 2139 $linesadded=0; 2140 $linesdeleted=0; 2141 2142 // 2136 $linesadded = $linesdeleted = 0; 2137 $content = ''; 2143 2138 //compare from left to right, passed from application 2144 //2145 $content='';2146 2139 foreach ( array_keys( _wp_post_revision_fields() ) as $field ) { 2147 2140 $left_content = apply_filters( "_wp_post_revision_field_$field", $left_revision->$field, $field, $left_revision, 'left' ); 2148 2141 $right_content = apply_filters( "_wp_post_revision_field_$field", $right_revision->$field, $field, $right_revision, 'right' ); … … 2151 2144 2152 2145 $args = array(); 2153 2146 2154 if ( ! empty( $show_split_view ))2147 if ( $show_split_view ) 2155 2148 $args = array( 'show_split_view' => true ); 2156 2149 2157 2150 // compare_to == 0 means first revision, so compare to a blank field to show whats changed 2158 $diff = wp_text_diff_with_count( ( 0 == $compare_to ) ? '' : $left_content, $right_content, $args );2151 $diff = wp_text_diff_with_count( ( 0 == $compare_to ) ? '' : $left_content, $right_content, $args ); 2159 2152 2160 2153 if ( isset( $diff[ 'html' ] ) ) 2161 2154 $content .= $diff[ 'html' ]; … … 2165 2158 2166 2159 if ( isset( $diff[ 'linesdeleted' ] ) ) 2167 2160 $linesdeleted = $linesdeleted + $diff[ 'linesdeleted' ]; 2168 2169 2170 2161 } 2171 2162 $content = '' == $content ? __( 'No difference' ) : $content; 2172 2163 2173 2164 $alltherevisions = array ( 2174 ' revisiondiff'=> $content,2165 'diff' => $content, 2175 2166 'lines_deleted' => $linesdeleted, 2176 'lines_added' => $linesadded2167 'lines_added' => $linesadded 2177 2168 ); 2169 2178 2170 echo json_encode( $alltherevisions ); 2179 2171 exit(); 2180 2172 } //end single model fetch … … 2186 2178 2187 2179 $previous_revision_id = 0; 2188 2180 2181 /* translators: revision date format, see http://php.net/date */ 2182 $datef = _x( 'j F, Y @ G:i:s', 'revision date format'); 2183 2189 2184 foreach ( $revisions as $revision ) : 2190 //error_log( ( $show_autosaves )); 2191 if ( empty( $show_autosaves ) && wp_is_post_autosave( $revision ) ) 2192 continue; 2185 if ( $show_autosaves && wp_is_post_autosave( $revision ) ) 2186 continue; 2193 2187 2194 2188 $revision_from_date_author = ''; 2195 2189 $count++; … … 2230 2224 $date 2231 2225 ); 2232 2226 2233 $autosavef = _ _( '%1$s [Autosave]' );2234 $currentf = _ _( '%1$s [Current Revision]' );2227 $autosavef = _x( '%1$s [Autosave]', 'post revision title extra' ); 2228 $currentf = _x( '%1$s [Current Revision]', 'post revision title extra' ); 2235 2229 2236 if ( ! $post = get_post( $post_id ))2237 exit(); 2230 if ( ! $post = get_post( $post_id ) ) 2231 exit(); // Should that be `continue;` instead? 2238 2232 2239 2233 if ( $left_revision->post_modified === $post->post_modified ) 2240 2234 $revision_from_date_author = sprintf( $currentf, $revision_from_date_author ); … … 2246 2240 elseif ( wp_is_post_autosave( $revision ) ) 2247 2241 $revision_date_author = sprintf( $autosavef, $revision_date_author ); 2248 2242 2249 $date_short_format = __( 'j M @ G:i' ); 2243 /* translators: revision date short format, see http://php.net/date */ 2244 $date_short_format = _x( 'j M @ G:i', 'revision date short format'); 2250 2245 $date_short = date_i18n( $date_short_format, strtotime( $revision->post_modified ) ); 2251 2246 2252 2247 $revision_date_author_short = sprintf( … … 2256 2251 $date_short 2257 2252 ); 2258 2253 2259 $restore action= wp_nonce_url(2254 $restore_link = wp_nonce_url( 2260 2255 add_query_arg( 2261 2256 array( 'revision' => $revision->ID, 2262 2257 'action' => 'restore' ), … … 2264 2259 ), 2265 2260 "restore-post_{$revision->ID}" 2266 2261 ); 2262 2267 2263 // if this is a left handled calculation swap data 2268 2264 if ( 0 != $right_handle_at ) { 2269 2265 $tmp = $revision_from_date_author; 2270 2266 $revision_from_date_author = $revision_date_author; 2271 2267 $revision_date_author = $tmp; 2272 2268 } 2269 2273 2270 if ( ( $compare_two_mode || -1 !== $previous_revision_id ) ) { 2274 2271 $alltherevisions[] = array ( 2275 'ID' => $revision->ID,2276 ' revision_date_author'=> $revision_date_author,2277 ' revision_from_date_author'=> $revision_from_date_author,2278 ' revision_date_author_short'=> $revision_date_author_short,2279 'restore action' => urldecode( $restoreaction),2280 'revision_toload' => true,2272 'ID' => $revision->ID, 2273 'titleTo' => $revision_date_author, 2274 'titleFrom' => $revision_from_date_author, 2275 'titleTooltip' => $revision_date_author_short, 2276 'restoreLink' => urldecode( $restore_link ), 2277 'revision_toload' => true, 2281 2278 'previous_revision_id' => $previous_revision_id 2282 2279 ); 2283 2280 } -
wp-admin/js/revisions.js
1 1 window.wp = window.wp || {}; 2 2 3 3 (function($) { 4 wp.revisions = {4 var Revision, Revisions, Diff, l10n, revisions; 5 5 6 views: {}, 6 revisions = wp.revisions = function() { 7 Diff = revisions.Diff = new Diff(); 8 }; 7 9 8 Model: Backbone.Model.extend({ 9 idAttribute: 'ID', 10 urlRoot: ajaxurl + '?action=revisions-data' + 11 '&show_autosaves=true&show_split_view=true&nonce=' + wpRevisionsSettings.nonce, 12 defaults: { 13 ID: 0, 14 revision_date_author: '', 15 revision_date_author_short: '', 16 revisiondiff: '<div class="diff-loading"><div class="spinner"></div></div>', 17 restoreaction: '', 18 revision_from_date_author: '', 19 revision_toload: false, 20 lines_added: 0, 21 lines_deleted: 0, 22 scope_of_changes: 'none', 23 previous_revision_id: 0 24 }, 10 _.extend( revisions, { model: {}, view: {}, controller: {} } ); 25 11 26 url: function() { 27 if ( 1 === REVAPP._compareOneOrTwo ) { 28 return this.urlRoot + 29 '&single_revision_id=' + this.id + 30 '&compare_to=' + this.get( 'previous_revision_id' ) + 31 '&post_id=' + wpRevisionsSettings.post_id; 32 } else { 33 return this.urlRoot + 34 '&single_revision_id=' + this.id; 35 } 12 // Link any localized strings. 13 l10n = revisions.model.l10n = typeof wpRevisionsL10n === 'undefined' ? {} : wpRevisionsL10n; 36 14 37 } 15 // Link any settings. 16 revisions.model.settings = l10n.settings || {}; 17 delete l10n.settings; 38 18 39 }),40 19 41 app: _.extend({}, Backbone.Events), 20 /** 21 * ======================================================================== 22 * CONTROLLERS 23 * ======================================================================== 24 */ 42 25 43 App: Backbone.Router.extend({ 44 _revisions: null, 45 _leftHandleRevisions: null, 46 _rightHandleRevisions: null, 47 _revisionsInteractions: null, 48 _revisionsOptions: null, 49 _leftDiff: 1, 50 _rightDiff: 1, 51 _autosaves: true, 52 _showSplitView: true, 53 _compareOneOrTwo: 1, 54 _leftModelLoading: false, // keep track of model loads 55 _rightModelLoading: false, // disallow slider interaction, also repeat loads, while loading 56 _tickmarkView: null, // the slider tickmarks 26 /** 27 * wp.revisions.controller.Diff 28 * 29 * Controlls the diff 30 */ 31 Diff = revisions.controller.Diff = Backbone.Model.extend( { 32 rightDiff: 1, 33 leftDiff: 1, 34 revisions: null, 35 leftHandleRevisions: null, 36 rightHandleRevisions: null, 37 revisionsInteractions: null, 38 autosaves: true, 39 showSplitView: true, 40 singleRevision: true, 41 leftModelLoading: false, // keep track of model loads 42 rightModelLoading: false, // disallow slider interaction, also repeat loads, while loading 43 tickmarkView: null, // the slider tickmarks 44 slider: null, // the slider instance 57 45 58 routes: { 59 }, 46 constructor: function() { 47 this.slider = new revisions.view.Slider(); 48 if ( null === this.revisions ) { 49 this.revisions = new Revisions(); // set up collection 50 this.startRightModelLoading(); 60 51 61 reloadToLoadRevisions: function( model_collection, reverse_direction ) { 62 var self = this, 63 revisionsToLoad = model_collection.where( { revision_toload: true } ), 64 delay = 0; 65 // match slider to passed revision_id 66 _.each( revisionsToLoad, function( theModel ) { 67 if ( theModel.get( 'ID' ) == wpRevisionsSettings.revision_id ) { 68 self._rightDiff = self._revisions.indexOf( theModel ) + 1; 52 var self = this; 53 this.revisions.fetch({ // load revision data 54 success: function() { 55 self.stopRightModelLoading(); 56 self.completeApplicationSetup(); 69 57 } 70 71 58 }); 72 _.each( revisionsToLoad, function( theModel ) { 73 theModel.urlRoot = model_collection.url; 74 _.delay( function() { 75 theModel.fetch( { 76 update: true, 77 add: false, 78 remove: false, 79 success: function( model ) { 80 model.set( 'revision_toload', 'false' ); 59 } 60 }, 81 61 82 // stop spinner when all models are loaded 83 if ( 0 === model_collection.where( { revision_toload: true } ).length ) 84 self.stopModelLoadingSpinner(); 62 reloadToLoadRevisions: function( models, reverse_direction ) { 63 var self = this, 64 revisionsToLoad = models.where( { revision_toload: true } ), 65 delay = 0; 85 66 86 self._tickmarkView.render(); 67 // match slider to passed revision_id 68 _.each( revisionsToLoad, function( revision ) { 69 if ( revision.get( 'ID' ) == revisions.model.settings.revision_id ) 70 self.rightDiff = self.revisions.indexOf( revision ) + 1; 71 }); 87 72 88 var total_changes = model.get( 'lines_added' ) + model.get( 'lines_deleted'), 89 scope_of_changes = 'vsmall'; 73 _.each( revisionsToLoad, function( revision ) { 74 revision.urlRoot = models.url(); 75 _.delay( function() { 76 revision.fetch( { 77 update: true, 78 add: false, 79 remove: false, 80 success: function( model ) { 81 model.set( 'revision_toload', 'false' ); 90 82 91 // Note: hard coded scope of changes 92 // TODO change to dynamic based on range of values 93 if ( total_changes > 1 && total_changes <= 3 ) { 94 scope_of_changes = 'small'; 95 } else if(total_changes > 3 && total_changes <= 5 ) { 96 scope_of_changes = 'med'; 97 } else if(total_changes > 5 && total_changes <= 10 ) { 98 scope_of_changes = 'large'; 99 } else if(total_changes > 10 ) { 100 scope_of_changes = 'vlarge'; 101 } 102 model.set( 'scope_of_changes', scope_of_changes ); 103 if ( 0 !== self._rightDiff && 104 model.get( 'ID' ) === self._revisions.at( self._rightDiff - 1 ).get( 'ID' ) ) { 105 // reload if current model refreshed 106 self._revisionView.render(); 107 } 83 // stop spinner when all models are loaded 84 if ( 0 === models.where( { revision_toload: true } ).length ) 85 self.stopModelLoadingSpinner(); 108 86 109 } 110 } ); 111 }, delay ) ; 112 delay = delay + 150; // stagger model loads to avoid hammering server with requests 113 } 114 ); 115 }, 87 self.tickmarkView.render(); 116 88 117 startLeftModelLoading: function() { 118 this._leftModelLoading = true; 119 $('.revisiondiffcontainer').addClass('leftmodelloading'); 120 }, 89 var total_changes = model.get( 'lines_added' ) + model.get( 'lines_deleted'), 90 scope_of_changes = 'vsmall'; 121 91 122 stopLeftModelLoading: function() { 123 this._leftModelLoading = false; 124 }, 92 // Note: hard coded scope of changes 93 // TODO change to dynamic based on range of values 94 if ( total_changes > 1 && total_changes <= 3 ) { 95 scope_of_changes = 'small'; 96 } else if( total_changes > 3 && total_changes <= 5 ) { 97 scope_of_changes = 'med'; 98 } else if( total_changes > 5 && total_changes <= 10 ) { 99 scope_of_changes = 'large'; 100 } else if( total_changes > 10 ) { 101 scope_of_changes = 'vlarge'; 102 } 103 model.set( 'scope_of_changes', scope_of_changes ); 104 if ( 0 !== self.rightDiff && 105 model.get( 'ID' ) === self.revisions.at( self.rightDiff - 1 ).get( 'ID' ) ) { 106 // reload if current model refreshed 107 self.revisionView.render(); 108 } 125 109 126 startRightModelLoading: function() { 127 this._rightModelLoading = true; 128 $('.revisiondiffcontainer').addClass('rightmodelloading'); 129 }, 110 } 111 } ); 112 }, delay ) ; 113 delay = delay + 150; // stagger model loads to avoid hammering server with requests 114 } 115 ); 116 }, 130 117 131 stopRightModelLoading: function() { 132 this._rightModelLoading = false; 133 }, 118 startLeftModelLoading: function() { 119 this.leftModelLoading = true; 120 $('.revisiondiffcontainer').addClass('leftmodelloading'); 121 }, 134 122 135 stopModelLoadingSpinner: function() { 136 $('.revisiondiffcontainer').removeClass('rightmodelloading'); 137 $('.revisiondiffcontainer').removeClass('leftmodelloading'); 138 }, 123 stopLeftModelLoading: function() { 124 this.leftModelLoading = false; 125 }, 139 126 140 reloadModel: function() { 141 if ( 2 === this._compareOneOrTwo ) { 142 this.reloadLeftRight(); 143 } else { 144 this.reloadModelSingle(); 145 } 146 }, 127 startRightModelLoading: function() { 128 this.rightModelLoading = true; 129 $('.revisiondiffcontainer').addClass('rightmodelloading'); 130 }, 147 131 148 // load the models for the single handle mode 149 reloadModelSingle: function() { 150 var self = this; 151 self._revisions.url = ajaxurl + '?action=revisions-data&compare_to=' + wpRevisionsSettings.post_id + 152 '&show_autosaves=' + self._autosaves + 153 '&show_split_view=' + self._showSplitView + 154 '&nonce=' + wpRevisionsSettings.nonce; 155 self.startRightModelLoading(); 156 self._revisions.fetch({ // reload revision data 157 success: function() { 158 console.log('loaded'); 159 // self.stopRightModelLoading(); 160 // REVAPP._rightDiff -= 1; 161 var revisionCount = self._revisions.length; 162 self._revisionView.model = self._revisions; 163 self._revisionView.render(); 164 self.reloadToLoadRevisions( self._revisions ); 165 self._tickmarkView.model = self._revisions; 166 self._tickmarkView.render(); 167 $( '#slider' ).slider( 'option', 'max', revisionCount - 1 ); // TODO: test this, if autosave option changed 168 $( '#slider' ).slider( 'value', self._rightDiff - 1 ).trigger( 'slide' ); 132 stopRightModelLoading: function() { 133 this.rightModelLoading = false; 134 }, 169 135 170 }, 136 stopModelLoadingSpinner: function() { 137 $('.revisiondiffcontainer').removeClass('rightmodelloading'); 138 $('.revisiondiffcontainer').removeClass('leftmodelloading'); 139 }, 171 140 172 error: function() { 173 self.stopRightModelLoading(); 174 } 141 reloadModel: function() { 142 if ( this.singleRevision ) { 143 this.reloadModelSingle(); 144 } else { 145 this.reloadLeftRight(); 146 } 147 }, 175 148 176 }); 177 }, 149 // load the models for the single handle mode 150 reloadModelSingle: function() { 151 var self = this; 178 152 179 // load the models for the left handle180 reloadLeft: function(){181 var self = this;182 self.startLeftModelLoading();183 self._leftHandleRevisions = new wp.revisions.Collection();153 // TODO: Only updates the query args yet 154 self.revisions.reload({ 155 'showAutosaves': self.autosaves, 156 'showSplitView': self.showSplitView 157 }); 184 158 185 self._leftHandleRevisions.url = 186 ajaxurl + 187 '?action=revisions-data&compare_to=' + self._revisions.at( self._rightDiff - 1 ).get( 'ID' ) + 188 '&post_id=' + wpRevisionsSettings.post_id + 189 '&show_autosaves=' + REVAPP._autosaves + 190 '&show_split_view=' + REVAPP._showSplitView + 191 '&nonce=' + wpRevisionsSettings.nonce + 192 '&right_handle_at=' + ( self._rightDiff ); 159 self.startRightModelLoading(); 160 self.revisions.fetch({ // reload revision data 161 success: function() { 162 var revisionCount = self.revisions.length; 163 self.revisionView.model = self.revisions; 164 self.revisionView.render(); 165 self.reloadToLoadRevisions( self.revisions ); 166 self.tickmarkView.model = self.revisions; 167 self.tickmarkView.render(); 168 self.slider.refresh({ 169 'max': revisionCount - 1, 170 'value': self.rightDiff - 1 171 }, true); 172 }, 193 173 194 self._leftHandleRevisions.fetch({ 174 error: function() { 175 self.stopRightModelLoading(); 176 } 195 177 196 success: function(){ 197 self.stopLeftModelLoading(); 198 self.reloadToLoadRevisions( self._leftHandleRevisions ); 199 self._tickmarkView.model = self._leftHandleRevisions; 200 $( '#slider' ).slider( 'option', 'max', self._revisions.length ); 201 // ensure right handle not beyond length, in particular if viewing autosaves is switched from on to off 202 // the number of models in the collection might get shorter, this ensures right handle is not beyond last model 203 if ( self._rightDiff > self._revisions.length ) 204 self._rightDiff = self._revisions.length; 205 }, 178 }); 179 }, 206 180 207 error: function() { 208 self.stopLeftModelLoading(); 209 } 210 }); 211 }, 181 // load the models for the left handle 182 reloadLeft: function() { 183 var self = this; 184 self.startLeftModelLoading(); 185 self.leftHandleRevisions = new Revisions( {}, { 186 'compareTo': self.revisions.at( self.leftDiff ).get( 'ID' ), 187 'showAutosaves': self.autosaves, 188 'showSplitView': self.showSplitView, 189 'rightHandleAt': self.rightDiff 190 }); 212 191 213 // load the models for the right handle 214 reloadRight: function() { 215 var self = this; 216 self.startRightModelLoading(); 217 self._rightHandleRevisions = new wp.revisions.Collection(); 192 self.leftHandleRevisions.fetch({ 193 success: function(){ 194 self.stopLeftModelLoading(); 195 self.reloadToLoadRevisions( self.leftHandleRevisions ); 196 self.tickmarkView.model = self.leftHandleRevisions; 197 self.slider.refresh({ 198 'max': self.revisions.length 199 }); 200 // ensure right handle not beyond length, in particular if viewing autosaves is switched from on to off 201 // the number of models in the collection might get shorter, this ensures right handle is not beyond last model 202 if ( self.rightDiff > self.revisions.length ) 203 self.rightDiff = self.revisions.length; 204 }, 218 205 219 self._rightHandleRevisions.url = 220 ajaxurl + 221 '?action=revisions-data&compare_to=' + ( self._revisions.at( self._leftDiff ).get( 'ID' ) - 1 )+ 222 '&post_id=' + wpRevisionsSettings.post_id + 223 '&show_autosaves=' + REVAPP._autosaves + 224 '&show_split_view=' + REVAPP._showSplitView + 225 '&nonce=' + wpRevisionsSettings.nonce; 206 error: function() { 207 self.stopLeftModelLoading(); 208 } 209 }); 210 }, 226 211 227 self._rightHandleRevisions.fetch({ 212 // load the models for the right handle 213 reloadRight: function() { 214 var self = this; 215 self.startRightModelLoading(); 216 self.rightHandleRevisions = new Revisions( {}, { 217 'compareTo': self.revisions.at( self.leftDiff ).get( 'ID' ) - 1, 218 'showAutosaves': self.autosaves, 219 'showSplitView': self.showSplitView 220 }); 228 221 229 success: function(){ 230 self.stopRightModelLoading(); 231 self.reloadToLoadRevisions( self._rightHandleRevisions ); 232 self._tickmarkView.model = self._rightHandleRevisions; 233 $( '#slider' ).slider( 'option', 'max', self._revisions.length ); 234 $( '#slider' ).slider( 'values', [ REVAPP._leftDiff, REVAPP._rightDiff] ).trigger( 'slide' ); 222 self.rightHandleRevisions.fetch({ 223 success: function(){ 224 self.stopRightModelLoading(); 225 self.reloadToLoadRevisions( self.rightHandleRevisions ); 226 self.tickmarkView.model = self.rightHandleRevisions; 227 self.slider.refresh({ 228 'max': self.revisions.length, 229 'values': [ self.leftDiff, self.rightDiff] 230 }, true); 231 }, 235 232 236 // REVAPP._revisionView.render(); 233 error: function( response ) { 234 self.stopRightModelLoading(); 235 } 236 }); 237 237 238 238 }, 239 239 240 error: function( response ) { 241 self.stopRightModelLoading(); 242 } 243 }); 240 reloadLeftRight: function() { 241 this.startRightModelLoading(); 242 this.startLeftModelLoading(); 243 this.reloadLeft(); 244 this.reloadRight(); 245 }, 244 246 245 }, 247 completeApplicationSetup: function() { 248 this.revisionView = new revisions.view.Diff({ 249 model: this.revisions 250 }); 251 this.revisionView.render(); 246 252 247 reloadLeftRight: function() { 248 this.startRightModelLoading(); 249 this.startLeftModelLoading(); 250 this.reloadLeft(); 251 this.reloadRight(); 252 }, 253 this.reloadToLoadRevisions( this.revisions ); 253 254 254 /* 255 * initialize the revision application 256 */ 257 initialize: function( options ) { 258 var self = this; // store the application instance 259 if (this._revisions === null) { 260 self._revisions = new wp.revisions.Collection(); // set up collection 261 self.startRightModelLoading(); 262 self._revisions.fetch({ // load revision data 255 this.revisionsInteractions = new revisions.view.Interact({ 256 model: this.revisions 257 }); 258 this.revisionsInteractions.render(); 263 259 264 success: function() { 265 self.stopRightModelLoading(); 266 // self._rightHandleRevisions = self._revisions; 267 self.completeApplicationSetup(); 268 } 269 }); 270 } 271 return this; 272 }, 260 this.tickmarkView = new revisions.view.Tickmarks({ 261 model: this.revisions 262 }); 263 this.tickmarkView.render(); 264 this.tickmarkView.resetTicks(); 273 265 274 addTooltip: function( handle, message ) { 266 } 267 }); 275 268 276 handle.attr( 'title', '' ).tooltip({277 track: false,278 269 279 position: { 280 my: "left-30 top-66", 281 at: "top left", 282 using: function( position, feedback ) { 283 $( this ).css( position ); 284 $( "<div>" ) 285 .addClass( "arrow" ) 286 .addClass( feedback.vertical ) 287 .addClass( feedback.horizontal ) 288 .appendTo( $( this ) ); 289 } 290 }, 291 show: false, 292 hide: false, 293 content: function() { 294 return message; 295 } 270 /** 271 * ======================================================================== 272 * VIEWS 273 * ======================================================================== 274 */ 296 275 297 } ); 298 }, 299 /**/ 276 /** 277 * wp.revisions.view.Slider 278 * 279 * The slider 280 */ 281 revisions.view.Slider = Backbone.View.extend({ 282 el: $( '#slider' ), 283 singleRevision: true, 300 284 301 completeApplicationSetup: function() { 302 this._revisionView = new wp.revisions.views.View({ 303 model: this._revisions 304 }); 305 this._revisionView.render(); 306 $( '#slider' ).slider( 'option', 'max', this._revisions.length - 1 ); 285 initialize: function( options ) { 286 this.options = _.defaults( options || {}, { 287 value: 0, 288 min: 0, 289 max: 1, 290 step: 1 291 }); 292 }, 307 293 308 this.reloadToLoadRevisions( this._revisions ); 294 slide: function( event, ui ) { 295 if ( this.singleRevision ) { 296 Diff.rightDiff = ( ui.value + 1 ); 297 Diff.revisionView.render(); 298 } else { 299 if ( ui.values[0] === ui.values[1] ) // prevent compare to self 300 return false; 309 301 310 this._revisionsInteractions = new wp.revisions.views.Interact({ 311 model: this._revisions 312 }); 313 this._revisionsInteractions.render(); 302 var index = $( ui.handle ).index(); // 0 (left) or 2 (right) 303 switch ( index ) { 304 case 0: // left 305 if ( Diff.leftModelLoading ) // left model still loading, prevent sliding left handle 306 return false; 314 307 315 this._tickmarkView = new wp.revisions.views.Tickmarks({ 316 model: this._revisions 317 }); 318 this._tickmarkView.render(); 319 this._tickmarkView.resetTicks(); 308 Diff.leftDiff = ui.values[0]; 309 break; 320 310 311 case 2: // right 312 if ( Diff.rightModelLoading ) // right model still loading, prevent sliding right handle 313 return false; 321 314 322 /* 323 .on( 'mouseup', function( event ) { 324 REVAPP._keep_tooltip_open = false; 325 $( this ).find('.ui-slider-tooltip').hide(); 326 } ).on( 'mousedown', function( event ) { 327 REVAPP._keep_tooltip_open = true; 328 } ).on( 'mouseout', function( event ) { 329 if ( REVAPP._keep_tooltip_open) 330 event.stopImmediatePropagation(); 331 }); 332 */ 333 /* 334 // Options hidden for now, moving to screen options 335 this._revisionsOptions = new wp.revisions.views.Options({ 336 model: this._revisions 337 }); 338 this._revisionsOptions.render(); 339 */ 315 Diff.rightDiff = ui.values[1]; 316 break; 317 } 340 318 341 } 342 }) 343 }; 319 if ( 0 === Diff.leftDiff ) { 320 $( '.revisiondiffcontainer' ).addClass( 'currentversion' ); 321 } else { 322 $( '.revisiondiffcontainer' ).removeClass( 'currentversion' ); 323 } 344 324 345 wp.revisions.Collection = Backbone.Collection.extend({ 346 model: wp.revisions.Model, 347 url: ajaxurl + '?action=revisions-data&compare_to=' + wpRevisionsSettings.post_id + 348 '&show_autosaves=true&show_split_view=true&nonce=' + wpRevisionsSettings.nonce, 349 350 initialize: function() { 325 Diff.revisionView.render(); 351 326 } 352 } );327 }, 353 328 354 _.extend(wp.revisions.views, { 329 start: function( event, ui ) { 330 // Not needed in one mode 331 if ( this.singleRevision ) 332 return; 355 333 356 // Ticks inside slider view 357 Tickmarks: Backbone.View.extend({ 358 el: $('#diff-slider-ticks')[0], 359 tagName: 'diff-slider-ticks-view', 360 className: 'diff-slider-ticks-container', 361 template: wp.template('revision-ticks'), 362 model: wp.revisions.Model, 334 var index = $( ui.handle ).index(); // 0 (left) or 2 (right) 335 switch ( index ) { 336 case 0: // left handle drag 337 if ( Diff.leftModelLoading ) // left model still loading, prevent sliding left handle 338 return false; 363 339 364 resetTicks: function() { 365 var sliderMax = $( '#slider' ).slider( 'option', 'max'); 366 var sliderWidth = $( '#slider' ).width(); 367 var adjustMax = ( 2 === REVAPP._compareOneOrTwo ) ? 1 : 0; 368 var tickWidth = Math.floor( sliderWidth / ( sliderMax - adjustMax ) ); 340 Diff.revisionView.draggingLeft = true; 369 341 370 // TODO: adjust right margins for wider ticks so they stay centered on handle stop point 342 if ( Diff.revisionView.model !== Diff.leftHandleRevisions && 343 null !== Diff.leftHandleRevisions ) { 344 Diff.revisionView.model = Diff.leftHandleRevisions; 345 Diff.tickmarkView.model = Diff.leftHandleRevisions; 346 Diff.tickmarkView.render(); 347 } 371 348 372 // set minimum and maximum widths for tick marks 373 tickWidth = (tickWidth > 50 ) ? 50 : tickWidth; 374 tickWidth = (tickWidth < 10 ) ? 10 : tickWidth; 349 Diff.leftDiffStart = ui.values[ 0 ]; 350 break; 375 351 376 sliderWidth = tickWidth * (sliderMax - adjustMax ) + 1; 352 case 2: // right 353 if ( Diff.rightModelLoading || 0 === Diff.rightHandleRevisions.length) // right model still loading, prevent sliding right handle 354 return false; 377 355 378 $( '#slider' ).width( sliderWidth ); 379 $( '.diff-slider-ticks-wrapper' ).width( sliderWidth ); 380 $( '#diffslider' ).width( sliderWidth ); 381 $( '#diff-slider-ticks' ).width( sliderWidth ); 356 if ( Diff.revisionView.model !== Diff.rightHandleRevisions && 357 null !== Diff.rightHandleRevisions ) { 358 Diff.revisionView.model = Diff.rightHandleRevisions; 359 Diff.tickmarkView.model = Diff.rightHandleRevisions; 360 Diff.tickmarkView.render(); 361 } 382 362 383 var aTickWidth = $( '.revision-tick' ).width(); 363 Diff.revisionView.draggingLeft = false; 364 Diff.rightDiffStart = ui.values[1]; 365 break; 366 } 367 }, 384 368 385 if ( tickWidth !== aTickWidth ) { // is the width already set correctly?386 $( '.revision-tick' ).each( function( ) {387 $(this).css( 'margin-right', tickWidth - 1 + 'px'); // space the ticks out using right margin388 });369 stop: function( event, ui ) { 370 // Not needed in one mode 371 if ( this.singleRevision ) 372 return; 389 373 390 if( 2 === REVAPP._compareOneOrTwo ) { 391 $( '.revision-tick' ).first().remove(); // TODO - remove the check 392 } 393 $( '.revision-tick' ).last().css( 'margin-right', '0' ); // last tick gets no right margin 394 } 374 // calculate and generate a diff for comparing to the left handle 375 // and the right handle, swap out when dragging 376 var index = $( ui.handle ).index(); // 0 (left) or 1 (right) 395 377 396 }, 378 switch ( index ) { 379 case 1: // left 380 // left handle dragged & changed, reload right handle model 381 if ( Diff.leftDiffStart !== ui.values[0] ) 382 Diff.reloadRight(); 397 383 398 // render the tickmark view 399 render: function() { 400 var self = this; 384 break; 401 385 402 if ( null !== self.model ) { 403 var addHtml = ""; 404 _.each ( self.model.models, function( theModel ) { 405 addHtml = addHtml + self.template ( theModel.toJSON() ); 406 }); 407 self.$el.html( addHtml ); 386 case 2: // right 387 // right handle dragged & changed, reload left handle model if changed 388 if ( Diff.rightDiffStart !== ui.values[1] ) 389 Diff.reloadLeft(); 408 390 409 } 410 self.resetTicks(); 411 return self; 391 break; 412 392 } 413 } ),393 }, 414 394 415 // primary revision diff view 416 View: Backbone.View.extend({ 417 el: $('#backbonerevisionsdiff')[0], 418 tagName: 'revisionvview', 419 className: 'revisionview-container', 420 template: wp.template('revision'), 421 comparetwochecked: '', 422 draggingLeft: false, 395 addTooltip: function( handle, message ) { 423 396 424 // render the revisions 425 render: function() { 426 var addHtml = ''; 427 var thediff; 428 // compare two revisions mode? 397 handle.attr( 'title', '' ).tooltip({ 398 track: false, 429 399 430 if ( 2 === REVAPP._compareOneOrTwo ) { 431 432 this.comparetwochecked = 'checked'; 433 if ( this.draggingLeft ) { 434 thediff = REVAPP._leftDiff -1; 435 if ( this.model.at( thediff ) ) { 436 addHtml = this.template( _.extend( 437 this.model.at( thediff ).toJSON(), 438 { comparetwochecked: this.comparetwochecked } // keep the checkmark checked 439 ) ); 440 } 441 } else { // dragging right handle 442 thediff = REVAPP._rightDiff -1; 443 if ( this.model.at( thediff ) ) { 444 addHtml = this.template( _.extend( 445 this.model.at( thediff ).toJSON(), 446 { comparetwochecked: this.comparetwochecked } // keep the checkmark checked 447 ) ); 448 } 400 position: { 401 my: "left-30 top-66", 402 at: "top left", 403 using: function( position, feedback ) { 404 $( this ).css( position ); 405 $( "<div>" ) 406 .addClass( "arrow" ) 407 .addClass( feedback.vertical ) 408 .addClass( feedback.horizontal ) 409 .appendTo( $( this ) ); 449 410 } 450 } else { // end compare two revisions mode, eg only one slider handle 451 this.comparetwochecked = ''; 452 if ( this.model.at( REVAPP._rightDiff - 1 ) ) { 453 addHtml = this.template( _.extend( 454 this.model.at( REVAPP._rightDiff - 1 ).toJSON(), 455 { comparetwochecked: this.comparetwochecked } // keep the checkmark unchecked 456 ) ); 457 } 411 }, 412 show: false, 413 hide: false, 414 content: function() { 415 return message; 458 416 } 459 this.$el.html( addHtml );460 if ( this.model.length < 3 ) {461 $( 'div#comparetworevisions' ).hide(); // don't allow compare two if fewer than three revisions462 }463 if ( this.model.length < 2 ) {464 $( 'div#diffslider' ).hide(); // don't allow compare two if fewer than three revisions465 $( 'div.diff-slider-ticks-wrapper' ).hide();466 }467 417 468 // add tooltips to the handles 469 if ( 2 === REVAPP._compareOneOrTwo ) { 470 REVAPP.addTooltip ( $( 'a.ui-slider-handle.left-handle' ), 471 ( REVAPP._leftDiff < 0 ) ? '' : REVAPP._revisions.at( REVAPP._leftDiff - 1 ).get( 'revision_date_author_short' ) ); 472 REVAPP.addTooltip ( $( 'a.ui-slider-handle.right-handle' ), 473 ( REVAPP._rightDiff > REVAPP._revisions.length ) ? '' : REVAPP._revisions.at( REVAPP._rightDiff - 1 ).get( 'revision_date_author_short' ) ); 474 } else { 475 REVAPP.addTooltip ( $( 'a.ui-slider-handle' ), 476 ( REVAPP._rightDiff > REVAPP._revisions.length ) ? '' : REVAPP._revisions.at( REVAPP._rightDiff - 1 ).get( 'revision_date_author_short' ) ); 477 } 418 } ); 419 }, 478 420 479 // hide the restore button when on the last sport/current post data 480 if ( REVAPP._rightDiff === REVAPP._revisions.length ){ 481 $( '.restore-button' ).hide(); 482 } else { 483 $( '.restore-button' ).show(); 484 } 421 width: function() { 422 return $( '#slider' ).width(); 423 }, 485 424 486 return this; 487 }, 425 setWidth: function( width ) { 426 return $( '#slider' ).width( width ); 427 }, 488 428 489 // the compare two button is in this view, add the interaction here 490 events: { 491 'click #comparetwo': 'clickcomparetwo' 492 }, 429 refresh: function( options, slide ) { 430 $( '#slider' ).slider( 'option', options ); 493 431 494 // turn on/off the compare two mmode 495 clickcomparetwo: function(){ 496 self = this; 432 // Triggers the slide event 433 if ( slide ) 434 $( '#slider' ).trigger( 'slide' ); 435 }, 497 436 498 if ( $( 'input#comparetwo' ).is( ':checked' ) ) { // compare 2 mode 499 REVAPP._compareOneOrTwo = 2 ; 437 option: function( key ) { 438 return $( '#slider' ).slider( 'option', key ); 439 }, 500 440 501 if ( 1 === REVAPP._rightDiff ) 502 REVAPP._rightDiff = 2; 503 REVAPP._revisionView.draggingLeft = false; 441 render: function() { 442 var self = this; 443 // this.$el doesn't work, why? 444 $( '#slider' ).slider( { 445 slide: $.proxy( self.slide, self ), 446 start: $.proxy( self.start, self ), 447 stop: $.proxy( self.stop, self ) 448 } ); 504 449 505 wpRevisionsSettings.revision_id = ''; // reset passed revision id so switching back to one handle mode doesn't re-select revision 506 REVAPP.reloadLeftRight(); 507 REVAPP._revisionView.model = REVAPP._rightHandleRevisions; 450 // Set options 451 this.refresh( this.options ); 452 } 453 }); 508 454 509 } else { // compare one mode 510 REVAPP._compareOneOrTwo = 1 ; 511 REVAPP._revisionView.draggingLeft = false; 512 // REVAPP._leftDiff = 0; 513 // REVAPP._rightDiff = (REVAPP._revisions.length <= REVAPP._rightDiff ) ? REVAPP._rightDiff + 1 : REVAPP._rightDiff + 1; 514 REVAPP.reloadModelSingle(); 515 } 516 // REVAPP._revisionView.render(); 517 REVAPP._revisionsInteractions.render(); 518 REVAPP._tickmarkView.render(); 455 /** 456 * wp.revisions.view.Tickmarks 457 * 458 * The slider tickmarks. 459 */ 460 revisions.view.Tickmarks = Backbone.View.extend({ 461 el: $('#diff-slider-ticks'), 462 template: wp.template('revision-ticks'), 463 model: Revision, 519 464 520 } 521 }), 465 resetTicks: function() { 466 var sliderMax = Diff.slider.option( 'max' ); 467 var sliderWidth = Diff.slider.width(); 468 var adjustMax = Diff.singleRevision ? 0 : 1; 469 var tickWidth = Math.floor( sliderWidth / ( sliderMax - adjustMax ) ); 522 470 523 // options view for show autosaves and show split view options 524 /* DISABLED for now 525 Options: Backbone.View.extend({ 526 el: $('#backbonerevisionsoptions')[0], 527 tagName: 'revisionoptionsview', 528 className: 'revisionoptions-container', 529 template: wp.template('revisionoptions'), 471 // TODO: adjust right margins for wider ticks so they stay centered on handle stop point 530 472 531 // render the options view 532 render: function() { 533 var addHtml = this.template; 534 this.$el.html( addHtml ); 535 return this; 536 }, 473 // set minimum and maximum widths for tick marks 474 tickWidth = (tickWidth > 50 ) ? 50 : tickWidth; 475 tickWidth = (tickWidth < 10 ) ? 10 : tickWidth; 537 476 538 // add options interactions 539 events: { 540 'click #toggleshowautosaves': 'toggleshowautosaves', 541 'click #showsplitview': 'showsplitview' 542 }, 477 sliderWidth = tickWidth * (sliderMax - adjustMax ) + 1; 543 478 544 // toggle include autosaves 545 toggleshowautosaves: function() { 546 var self = this; 547 if ( $( '#toggleshowautosaves' ).is( ':checked' ) ) { 548 REVAPP._autosaves = true ; 549 } else { 550 REVAPP._autosaves = false ; 551 } 479 Diff.slider.setWidth( sliderWidth ); 480 $( '.diff-slider-ticks-wrapper' ).width( sliderWidth ); 481 $( '#diffslider' ).width( sliderWidth ); 482 $( '#diff-slider-ticks' ).width( sliderWidth ); 552 483 553 // refresh the model data 554 REVAPP.reloadModel(); 555 }, 484 var aTickWidth = $( '.revision-tick' ).width(); 556 485 557 // toggle showing the split diff view 558 showsplitview: function() { 559 var self = this; 486 if ( tickWidth !== aTickWidth ) { // is the width already set correctly? 487 $( '.revision-tick' ).each( function( ) { 488 $(this).css( 'margin-right', tickWidth - 1 + 'px'); // space the ticks out using right margin 489 }); 560 490 561 if ( $( 'input#showsplitview' ).is( ':checked' ) ) { 562 REVAPP._showSplitView = 'true'; 563 $('.revisiondiffcontainer').addClass('diffsplit'); 564 } else { 565 REVAPP._showSplitView = ''; 566 $('.revisiondiffcontainer').removeClass('diffsplit'); 491 if( ! Diff.singleRevision ) { 492 $( '.revision-tick' ).first().remove(); // TODO - remove the check 567 493 } 568 569 REVAPP.reloadModel(); 494 $( '.revision-tick' ).last().css( 'margin-right', '0' ); // last tick gets no right margin 570 495 } 571 }),572 */573 // main interactions view574 Interact: Backbone.View.extend({575 el: $('#backbonerevisionsinteract')[0],576 tagName: 'revisionvinteract',577 className: 'revisionvinteract-container',578 template: wp.template('revisionvinteract'),579 496 580 initialize: function() { 581 }, 497 }, 582 498 583 render: function() { 584 var self = this; 499 // render the tickmark view 500 render: function() { 501 var self = this; 585 502 586 var addHtml = this.template; 587 this.$el.html( addHtml ); 503 if ( null !== self.model ) { 504 var addHtml = ""; 505 _.each ( self.model.models, function( theModel ) { 506 addHtml = addHtml + self.template ( theModel.toJSON() ); 507 }); 508 self.$el.html( addHtml ); 588 509 589 var modelcount = REVAPP._revisions.length; 510 } 511 self.resetTicks(); 512 return self; 513 } 514 }); 590 515 591 slider = $( "#slider" ); 592 if ( 1 === REVAPP._compareOneOrTwo ) { 593 // set up the slider with a single handle 594 slider.slider({ 595 value: REVAPP._rightDiff - 1, 596 min: 0, 597 max: modelcount - 1, 598 step: 1, 516 /** 517 * wp.revisions.view.Interact 518 * 519 * Next/Prev buttons and the slider 520 */ 521 // TODO: Change Interact to something else. 522 revisions.view.Interact = Backbone.View.extend({ 523 el: $('#backbonerevisionsinteract'), 524 template: wp.template('revision-interact'), 599 525 526 // next and previous buttons, only available in compare one mode 527 events: { 528 'click #next': 'nextRevision', 529 'click #previous': 'previousRevision' 530 }, 600 531 601 // slide interactions for one handles slider602 slide: function( event, ui ) {532 render: function() { 533 var self = this; 603 534 604 REVAPP._rightDiff = ( ui.value + 1 ); 605 REVAPP._revisionView.render(); 606 /* 607 $( 'a.ui-slider-handle' ).tooltip( { 608 content: REVAPP._revisions.at( ui.value ).get( 'revision_date_author_short' ), 609 position: { 610 my: "top-65", 611 using: function( position, feedback ) { 612 $( this ).css( position ); 613 $( "<div>" ) 614 .addClass( "arrow" ) 615 .addClass( feedback.vertical ) 616 .addClass( feedback.horizontal ) 617 .appendTo( this ); 618 } 619 } 620 });// .trigger( 'close' ).trigger( 'open' ); 621 */ 622 } 623 }); 624 $( '.revisiondiffcontainer' ).removeClass( 'comparetwo' ); 535 var addHtml = this.template; 536 this.$el.html( addHtml ); 625 537 626 } else { // comparing more than one, eg 2 627 // set up the slider with two handles 628 slider.slider({ 629 values: [ REVAPP._leftDiff, REVAPP._rightDiff + 1 ], 630 min: 1, 631 max: modelcount + 1, 632 step: 1, 633 range: true, 538 var modelcount = Diff.revisions.length; 634 539 635 // in two handled mode when user starts dragging, swap in precalculated diff for handle 636 start: function(event, ui ) { 637 var index = $( ui.handle ).index(); // 0 (left) or 1 (right) 638 switch ( index ) { 639 case 1: // left handle drag 640 if ( REVAPP._leftModelLoading ) // left model still loading, prevent sliding left handle 641 return false; 540 Diff.slider.singleRevision = Diff.singleRevision; 541 Diff.slider.render(); 642 542 643 REVAPP._revisionView.draggingLeft = true; 543 if ( Diff.singleRevision ) { 544 Diff.slider.refresh({ 545 value: Diff.rightDiff - 1, 546 min: 0, 547 max: modelcount - 1 548 }); 644 549 645 if ( REVAPP._revisionView.model !== REVAPP._leftHandleRevisions && 646 null !== REVAPP._leftHandleRevisions ) { 647 REVAPP._revisionView.model = REVAPP._leftHandleRevisions; 648 REVAPP._tickmarkView.model = REVAPP._leftHandleRevisions; 649 REVAPP._tickmarkView.render(); 650 } 550 $( '.revisiondiffcontainer' ).removeClass( 'comparetwo' ); 651 551 652 REVAPP._leftDiffStart = ui.values[ 0 ]; 653 break; 552 } else { 553 Diff.slider.refresh({ 554 values: [ Diff.leftDiff, Diff.rightDiff + 1 ], 555 min: 1, 556 max: modelcount + 1, 557 range: true 558 }); 654 559 655 case 2: // right 656 if ( REVAPP._rightModelLoading || 0 === REVAPP._rightHandleRevisions.length) // right model still loading, prevent sliding right handle 657 return false; 560 $( '.revisiondiffcontainer' ).addClass( 'comparetwo' ); 561 $( '#diffslider a.ui-slider-handle' ).first().addClass( 'left-handle' ).next().addClass( 'right-handle' ); 658 562 659 if ( REVAPP._revisionView.model !== REVAPP._rightHandleRevisions && 660 null !== REVAPP._rightHandleRevisions ) { 661 REVAPP._revisionView.model = REVAPP._rightHandleRevisions; 662 REVAPP._tickmarkView.model = REVAPP._rightHandleRevisions; 663 REVAPP._tickmarkView.render(); 664 } 563 } 665 564 666 REVAPP._revisionView.draggingLeft = false; 667 REVAPP._rightDiffStart = ui.values[1]; 668 break; 669 } 670 }, 565 return this; 566 }, 671 567 672 // when sliding in two handled mode change appropriate value673 slide: function( event, ui) {674 if ( ui.values[0] === ui.values[1] ) // prevent compare to self675 return false;568 // go to the next revision 569 nextRevision: function() { 570 if ( Diff.rightDiff < this.model.length ) // unless at right boundry 571 Diff.rightDiff = Diff.rightDiff + 1 ; 676 572 677 var index = $( ui.handle ).index(); // 0 (left) or 1 (right)573 Diff.revisionView.render(); 678 574 679 switch ( index ){680 case 1: // left681 if ( REVAPP._leftModelLoading ) // left model still loading, prevent sliding left handle682 return false;575 Diff.slider.refresh({ 576 value: Diff.rightDiff - 1 577 }, true ); 578 }, 683 579 684 REVAPP._leftDiff = ui.values[0]; 685 break; 580 // go the the previous revision 581 previousRevision: function() { 582 if ( Diff.rightDiff > 1 ) // unless at left boundry 583 Diff.rightDiff = Diff.rightDiff - 1 ; 686 584 687 case 2: // right 688 if ( REVAPP._rightModelLoading ) // right model still loading, prevent sliding right handle 689 return false; 585 Diff.revisionView.render(); 690 586 691 REVAPP._rightDiff = ui.values[1]; 692 break; 693 } 587 Diff.slider.refresh({ 588 value: Diff.rightDiff - 1 589 }, true ); 590 } 591 }); 694 592 695 if ( 0 === REVAPP._leftDiff ) { 696 $( '.revisiondiffcontainer' ).addClass( 'currentversion' ); 593 /** 594 * wp.revisions.view.Diff 595 * 596 * Next/Prev buttons and the slider 597 */ 598 revisions.view.Diff = Backbone.View.extend({ 599 el: $('#backbonerevisionsdiff'), 600 template: wp.template('revision'), 601 draggingLeft: false, 697 602 698 } else { 699 $( '.revisiondiffcontainer' ).removeClass( 'currentversion' ); 700 } 603 // the compare two button is in this view, add the interaction here 604 events: { 605 'click #comparetwo': 'compareTwo', 606 'click #restore': 'restore' 607 }, 701 608 702 REVAPP._revisionView.render(); 609 // render the revisions 610 render: function() { 611 var addHtml = ''; 612 var thediff; 703 613 704 }, 614 // compare two revisions mode? 615 if ( ! Diff.singleRevision ) { 616 if ( this.draggingLeft ) { 617 thediff = Diff.leftDiff - 1; 618 if ( this.model.at( thediff ) ) { 619 addHtml = this.template( this.model.at( thediff ).toJSON() ); 620 } 621 } else { // dragging right handle 622 thediff = Diff.rightDiff -1; 623 if ( this.model.at( thediff ) ) { 624 addHtml = this.template( this.model.at( thediff ).toJSON() ); 625 } 626 } 627 } else { // end compare two revisions mode, eg only one slider handle 628 this.comparetwochecked = ''; 629 if ( this.model.at( Diff.rightDiff - 1 ) ) { 630 addHtml = this.template( this.model.at( Diff.rightDiff - 1 ).toJSON() ); 631 } 632 } 633 this.$el.html( addHtml ); 705 634 706 // when the user stops sliding in 2 handle mode, recalculate diffs 707 stop: function( event, ui ) { 708 if ( 2 === REVAPP._compareOneOrTwo ) { 709 // calculate and generate a diff for comparing to the left handle 710 // and the right handle, swap out when dragging 635 if ( this.model.length < 2 ) { 636 $( '#diffslider' ).hide(); // don't allow compare two if fewer than three revisions 637 $( '.diff-slider-ticks-wrapper' ).hide(); 638 } 711 639 712 var index = $( ui.handle ).index(); // 0 (left) or 1 (right) 640 // add tooltips to the handles 641 if ( ! Diff.singleRevision ) { 642 Diff.slider.addTooltip ( $( 'a.ui-slider-handle.left-handle' ), 643 ( Diff.leftDiff < 0 ) ? '' : Diff.revisions.at( Diff.leftDiff - 1 ).get( 'titleTooltip' ) ); 644 Diff.slider.addTooltip ( $( 'a.ui-slider-handle.right-handle' ), 645 ( Diff.rightDiff > Diff.revisions.length ) ? '' : Diff.revisions.at( Diff.rightDiff - 1 ).get( 'titleTooltip' ) ); 646 } else { 647 Diff.slider.addTooltip ( $( 'a.ui-slider-handle' ), 648 ( Diff.rightDiff > Diff.revisions.length ) ? '' : Diff.revisions.at( Diff.rightDiff - 1 ).get( 'titleTooltip' ) ); 649 } 713 650 714 switch ( index ) { 715 case 1: // left 651 this.toogleCompareTwoCheckbox(); 716 652 717 // left handle dragged & changed, reload right handle model 718 if ( REVAPP._leftDiffStart !== ui.values[0] ) 719 REVAPP.reloadRight(); 653 // hide the restore button when on the last sport/current post data 654 if ( Diff.rightDiff === Diff.revisions.length ){ 655 $( '#restore' ).hide(); 656 } else { 657 $( '#restore' ).show(); 658 } 720 659 721 break; 660 return this; 661 }, 722 662 723 case 2: // right 724 // REVAPP._rightDiff = ( 1 >= REVAPP._rightDiff ) ? 1 : REVAPP._rightDiff - 1; 725 // right handle dragged & changed, reload left handle model if changed 726 if ( REVAPP._rightDiffStart !== ui.values[1] ) 727 REVAPP.reloadLeft(); 663 toogleCompareTwoCheckbox: function() { 664 // don't allow compare two if fewer than three revisions 665 if ( this.model.length < 3 ) 666 $( '#comparetworevisions' ).hide(); 728 667 729 break; 730 } 731 } 732 } 733 }); 734 $( '.revisiondiffcontainer' ).addClass( 'comparetwo' ); 735 $( '#diffslider a.ui-slider-handle' ).first().addClass( 'left-handle' ).next().addClass( 'right-handle' ); 736 } 668 $( '#comparetwo' ).prop( 'checked', ! Diff.singleRevision ); 669 }, 737 670 738 return this; 739 }, 671 // turn on/off the compare two mode 672 compareTwo: function() { 673 if ( $( 'input#comparetwo' ).is( ':checked' ) ) { // compare 2 mode 674 Diff.singleRevision = false ; 740 675 741 // next and previous buttons, only available in compare one mode 742 events: { 743 'click #next': 'nextRevision', 744 'click #previous': 'previousRevision' 745 }, 676 if ( 1 === Diff.rightDiff ) 677 Diff.rightDiff = 2; 746 678 747 // go to the next revision 748 nextRevision: function() { 749 if ( REVAPP._rightDiff < this.model.length ) // unless at right boundry 750 REVAPP._rightDiff = REVAPP._rightDiff + 1 ; 679 Diff.revisionView.draggingLeft = false; 751 680 752 REVAPP._revisionView.render(); 681 revisions.model.settings.revision_id = ''; // reset passed revision id so switching back to one handle mode doesn't re-select revision 682 Diff.reloadLeftRight(); 683 Diff.revisionView.model = Diff.rightHandleRevisions; 753 684 754 $( '#slider' ).slider( 'value', REVAPP._rightDiff - 1 ).trigger( 'slide' ); 755 }, 685 } else { // compare one mode 686 Diff.singleRevision = true; 687 Diff.revisionView.draggingLeft = false; 688 Diff.reloadModelSingle(); 689 } 690 Diff.revisionsInteractions.render(); 691 Diff.tickmarkView.render(); 692 }, 756 693 757 // go the the previous revision758 previousRevision: function() {759 if ( REVAPP._rightDiff > 1 ) // unless at left boundry760 REVAPP._rightDiff = REVAPP._rightDiff - 1;694 restore: function() { 695 document.location = $( '#restore' ).data( 'restoreLink' ); 696 } 697 }); 761 698 762 REVAPP._revisionView.render();763 699 764 $( '#slider' ).slider( 'value', REVAPP._rightDiff - 1 ).trigger( 'slide' ); 700 /** 701 * ======================================================================== 702 * MODELS 703 * ======================================================================== 704 */ 705 706 /** 707 * wp.revisions.Revision 708 */ 709 Revision = revisions.model.Revision = Backbone.Model.extend({ 710 idAttribute: 'ID', 711 urlRoot: ajaxurl + '?action=revisions-data' + 712 '&show_autosaves=true&show_split_view=true&nonce=' + revisions.model.settings.nonce, 713 defaults: { 714 ID: 0, 715 titleTo: '', 716 titleTooltip: '', 717 titleFrom: '', 718 diff: '<div class="diff-loading"><div class="spinner"></div></div>', 719 restoreLink: '', 720 revision_toload: false, 721 lines_added: 0, 722 lines_deleted: 0, 723 scope_of_changes: 'none', 724 previous_revision_id: 0 725 }, 726 727 url: function() { 728 if ( Diff.singleRevision ) { 729 return this.urlRoot + 730 '&single_revision_id=' + this.id + 731 '&compare_to=' + this.get( 'previous_revision_id' ) + 732 '&post_id=' + revisions.model.settings.post_id; 733 } else { 734 return this.urlRoot + '&single_revision_id=' + this.id; 765 735 } 766 }) 736 737 } 767 738 }); 768 739 769 // instantiate Revision Application 770 REVAPP = new wp.revisions.App(); 740 /** 741 * wp.revisions.Revisions 742 */ 743 Revisions = revisions.Revisions = Backbone.Collection.extend({ 744 model: Revision, 745 urlRoot: ajaxurl + '?action=revisions-data', 771 746 747 initialize: function( models, options ) { 748 this.options = _.defaults( options || {}, { 749 'compareTo': revisions.model.settings.post_id, 750 'post_id': revisions.model.settings.post_id, 751 'showAutosaves': true, 752 'showSplitView': true, 753 'rightHandleAt': 0, 754 'nonce': revisions.model.settings.nonce 755 }); 756 }, 757 758 url: function() { 759 return this.urlRoot + 760 '&compare_to=' + this.options.compareTo + 761 '&post_id=' + this.options.post_id + 762 '&show_autosaves=' + this.options.showAutosaves + 763 '&show_split_view=' + this.options.showSplitView + 764 '&right_handle_at=' + this.options.rightHandleAt + 765 '&nonce=' + this.options.nonce; 766 }, 767 768 reload: function( options ) { 769 this.options = _.defaults( options || {}, this.options ); 770 771 // TODO 772 //this.fetch(); 773 } 774 775 } ); 776 777 $( wp.revisions ); 778 772 779 }(jQuery)); -
wp-admin/revision.php
79 79 80 80 require_once( './admin-header.php' ); 81 81 82 //TODO - Some of the translations below split things into multiple strings that are contextually related and this makes it pretty impossible for RTL translation. 83 //TODO can we pass the context in a better way 84 $wpRevisionsSettings = array( 'post_id' => $post->ID, 85 'nonce' => wp_create_nonce( 'revisions-ajax-nonce' ), 86 'revision_id' => $revision_id ); 87 wp_localize_script( 'revisions', 'wpRevisionsSettings', $wpRevisionsSettings ); 82 $strings = array( 83 'diffFromTitle' => _x( 'From: %s', 'revision from title' ), 84 'diffToTitle' => _x( 'To: %s', 'revision to title' ) 85 ); 88 86 87 $settings = array( 88 'post_id' => $post->ID, 89 'nonce' => wp_create_nonce( 'revisions-ajax-nonce' ), 90 'revision_id' => $revision_id 91 ); 92 93 $strings['settings'] = $settings; 94 95 wp_localize_script( 'revisions', 'wpRevisionsL10n', $strings ); 96 89 97 $comparetworevisionslink = get_edit_post_link( $revision->ID ); 90 98 ?> 91 99 … … 112 120 </div> 113 121 114 122 <script id="tmpl-revision" type="text/html"> 123 <div id="comparetworevisions"> 124 <label> 125 <input type="checkbox" id="comparetwo" /> 126 <?php esc_attr_e( 'Compare two revisions' ); ?> 127 </label> 128 </div> 129 115 130 <div id="diffsubheader" class="diff-left-hand-meta-row"> 116 131 <div id="diff_from_current_revision"> 117 132 <?php printf( '<b>%1$s</b> %2$s.' , __( 'From:' ), __( 'the current version' ) ); ?> 118 133 </div> 119 134 <div id="difftitlefrom"> 120 <div class="diff-from-title"><?php _e( 'From:' ); ?></div>{{{ data. revision_from_date_author}}}135 <div class="diff-from-title"><?php _e( 'From:' ); ?></div>{{{ data.titleFrom }}} 121 136 </div> 122 137 </div> 123 138 124 139 <div id="diffsubheader"> 125 140 <div id="difftitle"> 126 <div class="diff-to-title"><?php _e( 'To:' ); ?></div>{{{ data. revision_date_author}}}141 <div class="diff-to-title"><?php _e( 'To:' ); ?></div>{{{ data.titleTo }}} 127 142 </div> 128 143 <div id="diffrestore"> 129 <input class="button button-primary restore-button" onClick="document.location='{{{ data.restoreaction }}}'" type="submit" id="restore" value="<?php esc_attr_e( 'Restore This Revision' )?>" />144 <input class="button button-primary" data-restore-link="{{{ data.restoreLink }}}" type="button" id="restore" value="<?php esc_attr_e( 'Restore This Revision' )?>" /> 130 145 </div> 131 <div id="comparetworevisions">132 <input type="checkbox" id="comparetwo" value="comparetwo" {{{ data.comparetwochecked }}} name="comparetwo"/>133 <label for="comparetwo"><?php esc_attr_e( 'Compare two revisions' ); ?></a></label>134 </div>135 146 </div> 136 147 137 148 <div id="removedandadded"> 138 149 <div id="removed"><?php _e( 'Removed -' ); ?></div> 139 150 <div id="added"><?php _e( 'Added +' ); ?></div> 140 151 </div 141 <div>{{{ data. revisiondiff }}}</div>152 <div>{{{ data.diff }}}</div> 142 153 </script> 143 154 144 <script id="tmpl-revision vinteract" type="text/html">155 <script id="tmpl-revision-interact" type="text/html"> 145 156 <div id="diffheader"> 146 157 <div id="diffprevious"><input class="button" type="submit" id="previous" value="<?php esc_attr_e( 'Previous' ); ?>" /> 147 158 </div> … … 153 164 </div> 154 165 </div> 155 166 </script> 167 156 168 <script id="tmpl-revision-ticks" type="text/html"> 157 169 <div class="revision-tick revision-toload{{{ data.revision_toload }}} revision-scopeofchanges-{{{ data.scope_of_changes }}}"> 158 170 </div> 159 171 </script> 160 172 <?php 161 /* 162 TODO Convert these into screen options 163 <script id="tmpl-revisionoptions" type="text/html"> 164 <div id="revisionoptions"> 165 <div id="showsplitviewoption"> 166 <input type='checkbox' id="show_split_view" checked="checked" value="1" /> <?php _e( 'Show split diff view' ); ?> 167 </div> 168 <div id="toggleshowautosavesoption"> 169 <input type='checkbox' id="toggleshowautosaves" value="1" /> <?php _e( 'Show autosaves' ); ?> 170 </div> 171 </div> 172 </script> 173 */ 174 require_once( './admin-footer.php' ); 175 No newline at end of file 173 require_once( './admin-footer.php' );