|
1 /* global isRtl */ |
|
2 /** |
|
3 * @file Revisions interface functions, Backbone classes and |
|
4 * the revisions.php document.ready bootstrap. |
|
5 * |
|
6 */ |
|
7 |
1 window.wp = window.wp || {}; |
8 window.wp = window.wp || {}; |
2 |
9 |
3 (function($) { |
10 (function($) { |
4 var revisions; |
11 var revisions; |
5 |
12 /** |
|
13 * Expose the module in window.wp.revisions. |
|
14 */ |
6 revisions = wp.revisions = { model: {}, view: {}, controller: {} }; |
15 revisions = wp.revisions = { model: {}, view: {}, controller: {} }; |
7 |
16 |
8 // Link settings. |
17 // Link post revisions data served from the back-end. |
9 revisions.settings = _.isUndefined( _wpRevisionsSettings ) ? {} : _wpRevisionsSettings; |
18 revisions.settings = window._wpRevisionsSettings || {}; |
10 |
19 |
11 // For debugging |
20 // For debugging |
12 revisions.debug = false; |
21 revisions.debug = false; |
13 |
22 |
|
23 /** |
|
24 * wp.revisions.log |
|
25 * |
|
26 * A debugging utility for revisions. Works only when a |
|
27 * debugĀ flag is on and the browser supports it. |
|
28 */ |
14 revisions.log = function() { |
29 revisions.log = function() { |
15 if ( window.console && revisions.debug ) |
30 if ( window.console && revisions.debug ) { |
16 console.log.apply( console, arguments ); |
31 window.console.log.apply( window.console, arguments ); |
|
32 } |
17 }; |
33 }; |
18 |
34 |
19 // Handy functions to help with positioning |
35 // Handy functions to help with positioning |
20 $.fn.allOffsets = function() { |
36 $.fn.allOffsets = function() { |
21 var offset = this.offset() || {top: 0, left: 0}, win = $(window); |
37 var offset = this.offset() || {top: 0, left: 0}, win = $(window); |
66 // Listen for changes to the revisions or mode from outside |
72 // Listen for changes to the revisions or mode from outside |
67 this.listenTo( this.frame, 'update:revisions', this.receiveRevisions ); |
73 this.listenTo( this.frame, 'update:revisions', this.receiveRevisions ); |
68 this.listenTo( this.frame, 'change:compareTwoMode', this.updateMode ); |
74 this.listenTo( this.frame, 'change:compareTwoMode', this.updateMode ); |
69 |
75 |
70 // Listen for internal changes |
76 // Listen for internal changes |
71 this.listenTo( this, 'change:from', this.handleLocalChanges ); |
77 this.on( 'change:from', this.handleLocalChanges ); |
72 this.listenTo( this, 'change:to', this.handleLocalChanges ); |
78 this.on( 'change:to', this.handleLocalChanges ); |
73 this.listenTo( this, 'change:compareTwoMode', this.updateSliderSettings ); |
79 this.on( 'change:compareTwoMode', this.updateSliderSettings ); |
74 this.listenTo( this, 'update:revisions', this.updateSliderSettings ); |
80 this.on( 'update:revisions', this.updateSliderSettings ); |
75 |
81 |
76 // Listen for changes to the hovered revision |
82 // Listen for changes to the hovered revision |
77 this.listenTo( this, 'change:hoveredRevision', this.hoverRevision ); |
83 this.on( 'change:hoveredRevision', this.hoverRevision ); |
78 |
84 |
79 this.set({ |
85 this.set({ |
80 max: this.revisions.length - 1, |
86 max: this.revisions.length - 1, |
81 compareTwoMode: this.frame.get('compareTwoMode'), |
87 compareTwoMode: this.frame.get('compareTwoMode'), |
82 from: this.frame.get('from'), |
88 from: this.frame.get('from'), |
171 } |
178 } |
172 }); |
179 }); |
173 |
180 |
174 revisions.model.Revision = Backbone.Model.extend({}); |
181 revisions.model.Revision = Backbone.Model.extend({}); |
175 |
182 |
|
183 /** |
|
184 * wp.revisions.model.Revisions |
|
185 * |
|
186 * A collection of post revisions. |
|
187 */ |
176 revisions.model.Revisions = Backbone.Collection.extend({ |
188 revisions.model.Revisions = Backbone.Collection.extend({ |
177 model: revisions.model.Revision, |
189 model: revisions.model.Revision, |
178 |
190 |
179 initialize: function() { |
191 initialize: function() { |
180 _.bindAll( this, 'next', 'prev' ); |
192 _.bindAll( this, 'next', 'prev' ); |
181 }, |
193 }, |
182 |
194 |
183 next: function( revision ) { |
195 next: function( revision ) { |
184 var index = this.indexOf( revision ); |
196 var index = this.indexOf( revision ); |
185 |
197 |
186 if ( index !== -1 && index !== this.length - 1 ) |
198 if ( index !== -1 && index !== this.length - 1 ) { |
187 return this.at( index + 1 ); |
199 return this.at( index + 1 ); |
|
200 } |
188 }, |
201 }, |
189 |
202 |
190 prev: function( revision ) { |
203 prev: function( revision ) { |
191 var index = this.indexOf( revision ); |
204 var index = this.indexOf( revision ); |
192 |
205 |
193 if ( index !== -1 && index !== 0 ) |
206 if ( index !== -1 && index !== 0 ) { |
194 return this.at( index - 1 ); |
207 return this.at( index - 1 ); |
|
208 } |
195 } |
209 } |
196 }); |
210 }); |
197 |
211 |
198 revisions.model.Field = Backbone.Model.extend({}); |
212 revisions.model.Field = Backbone.Model.extend({}); |
199 |
213 |
200 revisions.model.Fields = Backbone.Collection.extend({ |
214 revisions.model.Fields = Backbone.Collection.extend({ |
201 model: revisions.model.Field |
215 model: revisions.model.Field |
202 }); |
216 }); |
203 |
217 |
204 revisions.model.Diff = Backbone.Model.extend({ |
218 revisions.model.Diff = Backbone.Model.extend({ |
205 initialize: function( attributes, options ) { |
219 initialize: function() { |
206 var fields = this.get('fields'); |
220 var fields = this.get('fields'); |
207 this.unset('fields'); |
221 this.unset('fields'); |
208 |
222 |
209 this.fields = new revisions.model.Fields( fields ); |
223 this.fields = new revisions.model.Fields( fields ); |
210 } |
224 } |
213 revisions.model.Diffs = Backbone.Collection.extend({ |
227 revisions.model.Diffs = Backbone.Collection.extend({ |
214 initialize: function( models, options ) { |
228 initialize: function( models, options ) { |
215 _.bindAll( this, 'getClosestUnloaded' ); |
229 _.bindAll( this, 'getClosestUnloaded' ); |
216 this.loadAll = _.once( this._loadAll ); |
230 this.loadAll = _.once( this._loadAll ); |
217 this.revisions = options.revisions; |
231 this.revisions = options.revisions; |
|
232 this.postId = options.postId; |
218 this.requests = {}; |
233 this.requests = {}; |
219 }, |
234 }, |
220 |
235 |
221 model: revisions.model.Diff, |
236 model: revisions.model.Diff, |
222 |
237 |
223 ensure: function( id, context ) { |
238 ensure: function( id, context ) { |
224 var diff = this.get( id ); |
239 var diff = this.get( id ), |
225 var request = this.requests[ id ]; |
240 request = this.requests[ id ], |
226 var deferred = $.Deferred(); |
241 deferred = $.Deferred(), |
227 var ids = {}; |
242 ids = {}, |
228 var from = id.split(':')[0]; |
243 from = id.split(':')[0], |
229 var to = id.split(':')[1]; |
244 to = id.split(':')[1]; |
230 ids[id] = true; |
245 ids[id] = true; |
231 |
246 |
232 wp.revisions.log( 'ensure', id ); |
247 wp.revisions.log( 'ensure', id ); |
233 |
248 |
234 this.trigger( 'ensure', ids, from, to, deferred.promise() ); |
249 this.trigger( 'ensure', ids, from, to, deferred.promise() ); |
297 }, |
314 }, |
298 |
315 |
299 load: function( comparisons ) { |
316 load: function( comparisons ) { |
300 wp.revisions.log( 'load', comparisons ); |
317 wp.revisions.log( 'load', comparisons ); |
301 // Our collection should only ever grow, never shrink, so remove: false |
318 // Our collection should only ever grow, never shrink, so remove: false |
302 return this.fetch({ data: { compare: comparisons }, remove: false }).done( function(){ |
319 return this.fetch({ data: { compare: comparisons }, remove: false }).done( function() { |
303 wp.revisions.log( 'load:complete', comparisons ); |
320 wp.revisions.log( 'load:complete', comparisons ); |
304 }); |
321 }); |
305 }, |
322 }, |
306 |
323 |
307 sync: function( method, model, options ) { |
324 sync: function( method, model, options ) { |
308 if ( 'read' === method ) { |
325 if ( 'read' === method ) { |
309 options = options || {}; |
326 options = options || {}; |
310 options.context = this; |
327 options.context = this; |
311 options.data = _.extend( options.data || {}, { |
328 options.data = _.extend( options.data || {}, { |
312 action: 'get-revision-diffs', |
329 action: 'get-revision-diffs', |
313 post_id: revisions.settings.postId |
330 post_id: this.postId |
314 }); |
331 }); |
315 |
332 |
316 var deferred = wp.ajax.send( options ); |
333 var deferred = wp.ajax.send( options ), |
317 var requests = this.requests; |
334 requests = this.requests; |
318 |
335 |
319 // Record that we're requesting each diff. |
336 // Record that we're requesting each diff. |
320 if ( options.data.compare ) { |
337 if ( options.data.compare ) { |
321 _.each( options.data.compare, function( id ) { |
338 _.each( options.data.compare, function( id ) { |
322 requests[ id ] = deferred; |
339 requests[ id ] = deferred; |
340 } |
357 } |
341 } |
358 } |
342 }); |
359 }); |
343 |
360 |
344 |
361 |
|
362 /** |
|
363 * wp.revisions.model.FrameState |
|
364 * |
|
365 * The frame state. |
|
366 * |
|
367 * @see wp.revisions.view.Frame |
|
368 * |
|
369 * @param {object} attributes Model attributes - none are required. |
|
370 * @param {object} options Options for the model. |
|
371 * @param {revisions.model.Revisions} options.revisions A collection of revisions. |
|
372 */ |
345 revisions.model.FrameState = Backbone.Model.extend({ |
373 revisions.model.FrameState = Backbone.Model.extend({ |
346 defaults: { |
374 defaults: { |
347 loading: false, |
375 loading: false, |
348 error: false, |
376 error: false, |
349 compareTwoMode: false |
377 compareTwoMode: false |
350 }, |
378 }, |
351 |
379 |
352 initialize: function( attributes, options ) { |
380 initialize: function( attributes, options ) { |
353 var properties = {}; |
381 var state = this.get( 'initialDiffState' ); |
354 |
|
355 _.bindAll( this, 'receiveDiff' ); |
382 _.bindAll( this, 'receiveDiff' ); |
356 this._debouncedEnsureDiff = _.debounce( this._ensureDiff, 200 ); |
383 this._debouncedEnsureDiff = _.debounce( this._ensureDiff, 200 ); |
357 |
384 |
358 this.revisions = options.revisions; |
385 this.revisions = options.revisions; |
359 this.diffs = new revisions.model.Diffs( [], { revisions: this.revisions }); |
386 |
360 |
387 this.diffs = new revisions.model.Diffs( [], { |
361 // Set the initial diffs collection provided through the settings |
388 revisions: this.revisions, |
362 this.diffs.set( revisions.settings.diffData ); |
389 postId: this.get( 'postId' ) |
|
390 } ); |
|
391 |
|
392 // Set the initial diffs collection. |
|
393 this.diffs.set( this.get( 'diffData' ) ); |
363 |
394 |
364 // Set up internal listeners |
395 // Set up internal listeners |
365 this.listenTo( this, 'change:from', this.changeRevisionHandler ); |
396 this.listenTo( this, 'change:from', this.changeRevisionHandler ); |
366 this.listenTo( this, 'change:to', this.changeRevisionHandler ); |
397 this.listenTo( this, 'change:to', this.changeRevisionHandler ); |
367 this.listenTo( this, 'change:compareTwoMode', this.changeMode ); |
398 this.listenTo( this, 'change:compareTwoMode', this.changeMode ); |
368 this.listenTo( this, 'update:revisions', this.updatedRevisions ); |
399 this.listenTo( this, 'update:revisions', this.updatedRevisions ); |
369 this.listenTo( this.diffs, 'ensure:load', this.updateLoadingStatus ); |
400 this.listenTo( this.diffs, 'ensure:load', this.updateLoadingStatus ); |
370 this.listenTo( this, 'update:diff', this.updateLoadingStatus ); |
401 this.listenTo( this, 'update:diff', this.updateLoadingStatus ); |
371 |
402 |
372 // Set the initial revisions, baseUrl, and mode as provided through settings |
403 // Set the initial revisions, baseUrl, and mode as provided through attributes. |
373 properties.to = this.revisions.get( revisions.settings.to ); |
404 |
374 properties.from = this.revisions.get( revisions.settings.from ); |
405 this.set( { |
375 properties.compareTwoMode = revisions.settings.compareTwoMode; |
406 to : this.revisions.get( state.to ), |
376 properties.baseUrl = revisions.settings.baseUrl; |
407 from : this.revisions.get( state.from ), |
377 this.set( properties ); |
408 compareTwoMode : state.compareTwoMode |
|
409 } ); |
378 |
410 |
379 // Start the router if browser supports History API |
411 // Start the router if browser supports History API |
380 if ( window.history && window.history.pushState ) { |
412 if ( window.history && window.history.pushState ) { |
381 this.router = new revisions.Router({ model: this }); |
413 this.router = new revisions.Router({ model: this }); |
382 Backbone.history.start({ pushState: true }); |
414 Backbone.history.start({ pushState: true }); |
743 // Encapsulates the tooltip. |
801 // Encapsulates the tooltip. |
744 revisions.view.Tooltip = wp.Backbone.View.extend({ |
802 revisions.view.Tooltip = wp.Backbone.View.extend({ |
745 className: 'revisions-tooltip', |
803 className: 'revisions-tooltip', |
746 template: wp.template('revisions-meta'), |
804 template: wp.template('revisions-meta'), |
747 |
805 |
748 initialize: function( options ) { |
806 initialize: function() { |
749 this.listenTo( this.model, 'change:offset', this.render ); |
807 this.listenTo( this.model, 'change:offset', this.render ); |
750 this.listenTo( this.model, 'change:hovering', this.toggleVisibility ); |
808 this.listenTo( this.model, 'change:hovering', this.toggleVisibility ); |
751 this.listenTo( this.model, 'change:scrubbing', this.toggleVisibility ); |
809 this.listenTo( this.model, 'change:scrubbing', this.toggleVisibility ); |
752 }, |
810 }, |
753 |
811 |
754 prepare: function() { |
812 prepare: function() { |
755 if ( _.isNull( this.model.get('revision') ) ) |
813 if ( _.isNull( this.model.get('revision') ) ) { |
756 return; |
814 return; |
757 else |
815 } else { |
758 return _.extend( { type: 'tooltip' }, { |
816 return _.extend( { type: 'tooltip' }, { |
759 attributes: this.model.get('revision').toJSON() |
817 attributes: this.model.get('revision').toJSON() |
760 }); |
818 }); |
|
819 } |
761 }, |
820 }, |
762 |
821 |
763 render: function() { |
822 render: function() { |
764 var direction, directionVal, flipped, css = {}, position = this.model.revisions.indexOf( this.model.get('revision') ) + 1; |
823 var otherDirection, |
|
824 direction, |
|
825 directionVal, |
|
826 flipped, |
|
827 css = {}, |
|
828 position = this.model.revisions.indexOf( this.model.get('revision') ) + 1; |
|
829 |
765 flipped = ( position / this.model.revisions.length ) > 0.5; |
830 flipped = ( position / this.model.revisions.length ) > 0.5; |
766 if ( isRtl ) { |
831 if ( isRtl ) { |
767 direction = flipped ? 'left' : 'right'; |
832 direction = flipped ? 'left' : 'right'; |
768 directionVal = flipped ? 'leftPlusWidth' : direction; |
833 directionVal = flipped ? 'leftPlusWidth' : direction; |
769 } else { |
834 } else { |
882 |
949 |
883 this.applySliderSettings(); |
950 this.applySliderSettings(); |
884 }, |
951 }, |
885 |
952 |
886 mouseMove: function( e ) { |
953 mouseMove: function( e ) { |
887 var zoneCount = this.model.revisions.length - 1, // One fewer zone than models |
954 var zoneCount = this.model.revisions.length - 1, // One fewer zone than models |
888 sliderFrom = this.$el.allOffsets()[this.direction], // "From" edge of slider |
955 sliderFrom = this.$el.allOffsets()[this.direction], // "From" edge of slider |
889 sliderWidth = this.$el.width(), // Width of slider |
956 sliderWidth = this.$el.width(), // Width of slider |
890 tickWidth = sliderWidth / zoneCount, // Calculated width of zone |
957 tickWidth = sliderWidth / zoneCount, // Calculated width of zone |
891 actualX = isRtl? $(window).width() - e.pageX : e.pageX; // Flipped for RTL - sliderFrom; |
958 actualX = ( isRtl ? $(window).width() - e.pageX : e.pageX ) - sliderFrom, // Flipped for RTL - sliderFrom; |
892 actualX = actualX - sliderFrom; // Offset of mouse position in slider |
959 currentModelIndex = Math.floor( ( actualX + ( tickWidth / 2 ) ) / tickWidth ); // Calculate the model index |
893 var currentModelIndex = Math.floor( ( actualX + ( tickWidth / 2 ) ) / tickWidth ); // Calculate the model index |
|
894 |
960 |
895 // Ensure sane value for currentModelIndex. |
961 // Ensure sane value for currentModelIndex. |
896 if ( currentModelIndex < 0 ) |
962 if ( currentModelIndex < 0 ) { |
897 currentModelIndex = 0; |
963 currentModelIndex = 0; |
898 else if ( currentModelIndex >= this.model.revisions.length ) |
964 } else if ( currentModelIndex >= this.model.revisions.length ) { |
899 currentModelIndex = this.model.revisions.length - 1; |
965 currentModelIndex = this.model.revisions.length - 1; |
|
966 } |
900 |
967 |
901 // Update the tooltip mode |
968 // Update the tooltip mode |
902 this.model.set({ hoveredRevision: this.model.revisions.at( currentModelIndex ) }); |
969 this.model.set({ hoveredRevision: this.model.revisions.at( currentModelIndex ) }); |
903 }, |
970 }, |
904 |
971 |
931 this.model.set({ scrubbing: true }); |
998 this.model.set({ scrubbing: true }); |
932 |
999 |
933 // Track the mouse position to enable smooth dragging, |
1000 // Track the mouse position to enable smooth dragging, |
934 // overrides default jQuery UI step behavior. |
1001 // overrides default jQuery UI step behavior. |
935 $( window ).on( 'mousemove.wp.revisions', { view: this }, function( e ) { |
1002 $( window ).on( 'mousemove.wp.revisions', { view: this }, function( e ) { |
936 var view = e.data.view, |
1003 var handles, |
937 leftDragBoundary = view.$el.offset().left, |
1004 view = e.data.view, |
938 sliderOffset = leftDragBoundary, |
1005 leftDragBoundary = view.$el.offset().left, |
939 sliderRightEdge = leftDragBoundary + view.$el.width(), |
1006 sliderOffset = leftDragBoundary, |
940 rightDragBoundary = sliderRightEdge, |
1007 sliderRightEdge = leftDragBoundary + view.$el.width(), |
941 leftDragReset = '0', |
1008 rightDragBoundary = sliderRightEdge, |
942 rightDragReset = '100%', |
1009 leftDragReset = '0', |
943 handle = $( ui.handle ); |
1010 rightDragReset = '100%', |
|
1011 handle = $( ui.handle ); |
944 |
1012 |
945 // In two handle mode, ensure handles can't be dragged past each other. |
1013 // In two handle mode, ensure handles can't be dragged past each other. |
946 // Adjust left/right boundaries and reset points. |
1014 // Adjust left/right boundaries and reset points. |
947 if ( view.model.get('compareTwoMode') ) { |
1015 if ( view.model.get('compareTwoMode') ) { |
948 var handles = handle.parent().find('.ui-slider-handle'); |
1016 handles = handle.parent().find('.ui-slider-handle'); |
949 if ( handle.is( handles.first() ) ) { // We're the left handle |
1017 if ( handle.is( handles.first() ) ) { // We're the left handle |
950 rightDragBoundary = handles.last().offset().left; |
1018 rightDragBoundary = handles.last().offset().left; |
951 rightDragReset = rightDragBoundary - sliderOffset; |
1019 rightDragReset = rightDragBoundary - sliderOffset; |
952 } else { // We're the right handle |
1020 } else { // We're the right handle |
953 leftDragBoundary = handles.first().offset().left + handles.first().width(); |
1021 leftDragBoundary = handles.first().offset().left + handles.first().width(); |
974 slide: function( event, ui ) { |
1042 slide: function( event, ui ) { |
975 var attributes, movedRevision; |
1043 var attributes, movedRevision; |
976 // Compare two revisions mode |
1044 // Compare two revisions mode |
977 if ( this.model.get('compareTwoMode') ) { |
1045 if ( this.model.get('compareTwoMode') ) { |
978 // Prevent sliders from occupying same spot |
1046 // Prevent sliders from occupying same spot |
979 if ( ui.values[1] === ui.values[0] ) |
1047 if ( ui.values[1] === ui.values[0] ) { |
980 return false; |
1048 return false; |
981 if ( isRtl ) |
1049 } |
|
1050 if ( isRtl ) { |
982 ui.values.reverse(); |
1051 ui.values.reverse(); |
|
1052 } |
983 attributes = { |
1053 attributes = { |
984 from: this.model.revisions.at( this.getPosition( ui.values[0] ) ), |
1054 from: this.model.revisions.at( this.getPosition( ui.values[0] ) ), |
985 to: this.model.revisions.at( this.getPosition( ui.values[1] ) ) |
1055 to: this.model.revisions.at( this.getPosition( ui.values[1] ) ) |
986 }; |
1056 }; |
987 } else { |
1057 } else { |
988 attributes = { |
1058 attributes = { |
989 to: this.model.revisions.at( this.getPosition( ui.value ) ) |
1059 to: this.model.revisions.at( this.getPosition( ui.value ) ) |
990 }; |
1060 }; |
991 // If we're at the first revision, unset 'from'. |
1061 // If we're at the first revision, unset 'from'. |
992 if ( this.getPosition( ui.value ) > 0 ) |
1062 if ( this.getPosition( ui.value ) > 0 ) { |
993 attributes.from = this.model.revisions.at( this.getPosition( ui.value ) - 1 ); |
1063 attributes.from = this.model.revisions.at( this.getPosition( ui.value ) - 1 ); |
994 else |
1064 } else { |
995 attributes.from = undefined; |
1065 attributes.from = undefined; |
|
1066 } |
996 } |
1067 } |
997 movedRevision = this.model.revisions.at( this.getPosition( ui.value ) ); |
1068 movedRevision = this.model.revisions.at( this.getPosition( ui.value ) ); |
998 |
1069 |
999 // If we are scrubbing, a scrub to a revision is considered a hover |
1070 // If we are scrubbing, a scrub to a revision is considered a hover |
1000 if ( this.model.get('scrubbing') ) |
1071 if ( this.model.get('scrubbing') ) { |
1001 attributes.hoveredRevision = movedRevision; |
1072 attributes.hoveredRevision = movedRevision; |
|
1073 } |
1002 |
1074 |
1003 this.model.set( attributes ); |
1075 this.model.set( attributes ); |
1004 }, |
1076 }, |
1005 |
1077 |
1006 stop: function( event, ui ) { |
1078 stop: function() { |
1007 $( window ).off('mousemove.wp.revisions'); |
1079 $( window ).off('mousemove.wp.revisions'); |
1008 this.model.updateSliderSettings(); // To snap us back to a tick mark |
1080 this.model.updateSliderSettings(); // To snap us back to a tick mark |
1009 this.model.set({ scrubbing: false }); |
1081 this.model.set({ scrubbing: false }); |
1010 } |
1082 } |
1011 }); |
1083 }); |
1012 |
1084 |
1013 // The diff view. |
1085 // The diff view. |
1014 // This is the view for the current active diff. |
1086 // This is the view for the current active diff. |
1015 revisions.view.Diff = wp.Backbone.View.extend({ |
1087 revisions.view.Diff = wp.Backbone.View.extend({ |
1016 className: 'revisions-diff', |
1088 className: 'revisions-diff', |
1017 template: wp.template('revisions-diff'), |
1089 template: wp.template('revisions-diff'), |
1018 |
1090 |
1019 // Generate the options to be passed to the template. |
1091 // Generate the options to be passed to the template. |
1020 prepare: function() { |
1092 prepare: function() { |
1021 return _.extend({ fields: this.model.fields.toJSON() }, this.options ); |
1093 return _.extend({ fields: this.model.fields.toJSON() }, this.options ); |
1022 } |
1094 } |
1023 }); |
1095 }); |
1024 |
1096 |
1025 // The revisions router |
1097 // The revisions router. |
1026 // takes URLs with #hash fragments and routes them |
1098 // Maintains the URL routes so browser URL matches state. |
1027 revisions.Router = Backbone.Router.extend({ |
1099 revisions.Router = Backbone.Router.extend({ |
1028 initialize: function( options ) { |
1100 initialize: function( options ) { |
1029 this.model = options.model; |
1101 this.model = options.model; |
1030 this.routes = _.object([ |
1102 |
1031 [ this.baseUrl( '?from=:from&to=:to' ), 'handleRoute' ], |
|
1032 [ this.baseUrl( '?from=:from&to=:to' ), 'handleRoute' ] |
|
1033 ]); |
|
1034 // Maintain state and history when navigating |
1103 // Maintain state and history when navigating |
1035 this.listenTo( this.model, 'update:diff', _.debounce( this.updateUrl, 250 ) ); |
1104 this.listenTo( this.model, 'update:diff', _.debounce( this.updateUrl, 250 ) ); |
1036 this.listenTo( this.model, 'change:compareTwoMode', this.updateUrl ); |
1105 this.listenTo( this.model, 'change:compareTwoMode', this.updateUrl ); |
1037 }, |
1106 }, |
1038 |
1107 |
1039 baseUrl: function( url ) { |
1108 baseUrl: function( url ) { |
1040 return this.model.get('baseUrl') + url; |
1109 return this.model.get('baseUrl') + url; |
1041 }, |
1110 }, |
1042 |
1111 |
1043 updateUrl: function() { |
1112 updateUrl: function() { |
1044 var from = this.model.has('from') ? this.model.get('from').id : 0; |
1113 var from = this.model.has('from') ? this.model.get('from').id : 0, |
1045 var to = this.model.get('to').id; |
1114 to = this.model.get('to').id; |
1046 if ( this.model.get('compareTwoMode' ) ) |
1115 if ( this.model.get('compareTwoMode' ) ) { |
1047 this.navigate( this.baseUrl( '?from=' + from + '&to=' + to ) ); |
1116 this.navigate( this.baseUrl( '?from=' + from + '&to=' + to ), { replace: true } ); |
1048 else |
1117 } else { |
1049 this.navigate( this.baseUrl( '?revision=' + to ) ); |
1118 this.navigate( this.baseUrl( '?revision=' + to ), { replace: true } ); |
|
1119 } |
1050 }, |
1120 }, |
1051 |
1121 |
1052 handleRoute: function( a, b ) { |
1122 handleRoute: function( a, b ) { |
1053 var from, to, compareTwo = _.isUndefined( b ); |
1123 var compareTwo = _.isUndefined( b ); |
1054 |
1124 |
1055 if ( ! compareTwo ) { |
1125 if ( ! compareTwo ) { |
1056 b = this.model.revisions.get( a ); |
1126 b = this.model.revisions.get( a ); |
1057 a = this.model.revisions.prev( b ); |
1127 a = this.model.revisions.prev( b ); |
1058 b = b ? b.id : 0; |
1128 b = b ? b.id : 0; |
1059 a = a ? a.id : 0; |
1129 a = a ? a.id : 0; |
1060 } |
1130 } |
1061 |
1131 } |
1062 this.model.set({ |
1132 }); |
1063 from: this.model.revisions.get( parseInt( a, 10 ) ), |
1133 |
1064 to: this.model.revisions.get( parseInt( a, 10 ) ), |
1134 /** |
1065 compareTwoMode: compareTwo |
1135 * Initialize the revisions UI for revision.php. |
1066 }); |
1136 */ |
1067 } |
|
1068 }); |
|
1069 |
|
1070 // Initialize the revisions UI. |
|
1071 revisions.init = function() { |
1137 revisions.init = function() { |
|
1138 var state; |
|
1139 |
|
1140 // Bail if the current page is not revision.php. |
|
1141 if ( ! window.adminpage || 'revision-php' !== window.adminpage ) { |
|
1142 return; |
|
1143 } |
|
1144 |
|
1145 state = new revisions.model.FrameState({ |
|
1146 initialDiffState: { |
|
1147 // wp_localize_script doesn't stringifies ints, so cast them. |
|
1148 to: parseInt( revisions.settings.to, 10 ), |
|
1149 from: parseInt( revisions.settings.from, 10 ), |
|
1150 // wp_localize_script does not allow for top-level booleans so do a comparator here. |
|
1151 compareTwoMode: ( revisions.settings.compareTwoMode === '1' ) |
|
1152 }, |
|
1153 diffData: revisions.settings.diffData, |
|
1154 baseUrl: revisions.settings.baseUrl, |
|
1155 postId: parseInt( revisions.settings.postId, 10 ) |
|
1156 }, { |
|
1157 revisions: new revisions.model.Revisions( revisions.settings.revisionData ) |
|
1158 }); |
|
1159 |
1072 revisions.view.frame = new revisions.view.Frame({ |
1160 revisions.view.frame = new revisions.view.Frame({ |
1073 model: new revisions.model.FrameState({}, { |
1161 model: state |
1074 revisions: new revisions.model.Revisions( revisions.settings.revisionData ) |
|
1075 }) |
|
1076 }).render(); |
1162 }).render(); |
1077 }; |
1163 }; |
1078 |
1164 |
1079 $( revisions.init ); |
1165 $( revisions.init ); |
1080 }(jQuery)); |
1166 }(jQuery)); |