Revisions: First pass an implementing a new UI/UX for reviewing the revisions of posts. See #23497 props adamsilverstein for the initial patch.

This implements a new revisions ui using Backbone and preserves all the old methods of "integration" so the change should be transparent to plugins using revisi
ons with CPTs.

This is the first pass and so there are a number of things still to be resolved, more details in the ticket. Feedback welcomed.


git-svn-id: http://core.svn.wordpress.org/trunk@23506 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Peter Westwood 2013-02-28 15:14:34 +00:00
parent 766d96db5d
commit 9bd192fab3
18 changed files with 1642 additions and 173 deletions

View File

@ -42,7 +42,7 @@ do_action( 'admin_init' );
$core_actions_get = array(
'fetch-list', 'ajax-tag-search', 'wp-compression-test', 'imgedit-preview', 'oembed-cache',
'autocomplete-user', 'dashboard-widgets', 'logged-in',
'autocomplete-user', 'dashboard-widgets', 'logged-in', 'revisions-data'
);
$core_actions_post = array(
@ -56,7 +56,7 @@ $core_actions_post = array(
'save-widget', 'set-post-thumbnail', 'date_format', 'time_format', 'wp-fullscreen-save-post',
'wp-remove-post-lock', 'dismiss-wp-pointer', 'upload-attachment', 'get-attachment',
'query-attachments', 'save-attachment', 'save-attachment-compat', 'send-link-to-editor',
'send-attachment-to-editor', 'save-attachment-order', 'heartbeat',
'send-attachment-to-editor', 'save-attachment-order', 'heartbeat'
);
// Register core Ajax calls.

View File

@ -1351,15 +1351,26 @@ div.wp-menu-image {
/* Diff */
table.diff .diff-deletedline {
background-color: #fdd;
background-color: #ffe5e6;
color: #f2001f;
text-decoration: line-through;
}
table.diff .diff-deletedline del {
background-color: #f99;
}
table.diff .diff-deletedline-symbol {
color: #f2001f;
}
table.diff .diff-addedline {
background-color: #dfd;
background-color: #e9f6ea;
color: #00a500;
}
table.diff .diff-addedline-symbol {
color: #00a500;
}
table.diff .diff-addedline ins {

213
wp-admin/css/revisions.css Normal file
View File

@ -0,0 +1,213 @@
/* Styles for the revision screen */
.revisiondiffcontainer {
width: 96%;
}
.revisiondiffcontainer input.button {
margin: 2px;
}
#diffrestore, #diffnext, #diffcancel {
float: right;
margin-right: 5px;
}
#diffprevious, #difftitle, #difftitlefrom, #diff_from_current_revision {
float: left;
margin-left: 5px;
height: 35px;
}
#diffprevious, #diffnext {
margin-top: 7px;
height: 30px;
}
#diffheader, #diffsubheader {
clear: both;
width: 100%;
}
#diffheader {
border-bottom: 2px solid #999;
width: 100%;
height: 45px;
line-height: 45px;
padding-top: 10px;
}
#diffsubheader {
background-color: #eee;
border-bottom: 2px solid #999;
width: 100%;
height:35px;
line-height: 35px;
}
#diffslider {
width: 70%;
margin-left: auto;
margin-right: auto;
text-align: center;
height: 3.5em;
}
#revisioncount {
width: 50%;
margin-left: auto;
margin-right: auto;
margin-top: 0;
line-height: 1em;
height: 1em;
text-align: center;
clear: none;
padding: 5px;
}
.revisiondiffcontainer {
margin-top: 10px;
}
#diffsliderwrap {
width: 80%;
margin-left: auto;
margin-right: auto;
}
#diffsliderwrap #sliderinner {
position: relative;
top: 47px;
}
#removedandadded {
width: 100%
padding-bottom: 30px;
padding-top: 3px;
font-size: 16px;
}
#removed, #added {
width: auto;
text-align: left;
padding-left: 5px;
padding-right: 5px;
padding-top: 5px;
padding-bottom: 5px;
float: left;
}
.diffsplit #added {
float: right;
width: 47%;
text-align: left;
}
.diffsplit #removedandadded {
width: 100%;
}
#added {
padding-left: 10px;
}
#removed {
padding-left: 0px;
}
#removed {
color: #d2281f;
}
#added {
color: #00a100;
}
#comparetworevisions {
float: right;
line-height: 35px;
padding-right: 5px;
}
#comparetworevisions input{
margin-right: 2px;
}
#difftitle img, #difftitlefrom img {
vertical-align: middle;
margin-left: 5px;
}
#showsplitviewoption, #toggleshowautosavesoption {
float: right;
padding-left: 10px;
padding-right: 10px;
}
#revisionoptions {
margin-top: 0px;
line-height: 40px;
clear: both;
width: 100%;
}
.comparetwo #diffprevious, .comparetwo #diffnext {
display: none;
}
.comparetwo #diffslider {
width: 95%;
}
.currentversion span#diff_left_current_revision {
display: inline;
}
span#diff_left_current_revision, span#diff_from_current_revision {
display: none;
}
span#diff_left_count, span#diff_left_count_inner {
display: inline;
}
.currentversion span#diff_left_count,
.currentversion span#diff_left_count_inner,
.currentversion #difftitlefrom {
display: none;
}
#difftitlefrom {
float: left;
display: none;
}
.comparetwo #difftitlefrom, .comparetwo.currentversion span#diff_from_current_revision {
display: inline;
}
.comparetwo.currentversion #difftitlefrom {
display: none;
}
#modelsloading {
float: right;
line-height: 30px;
display: none;
clear: none;
margin: 0;
margin-top: -40px;
}
#modelsloading .spinner {
float: left;
}
.leftmodelloading #modelsloading,
.rightmodelloading #modelsloading,
.leftmodelloading #modelsloading .spinner,
.rightmodelloading #modelsloading .spinner {
display: inline;
}

0
wp-admin/css/revisions.min.css vendored Normal file
View File

View File

@ -3504,7 +3504,19 @@ table.diff {
}
table.diff col.content {
width: 50%;
width: auto;
}
table.diff col.content.diffsplit {
width: 48%;
}
table.diff col.diffsplit.middle {
width: 4%;
}
table.diff col.ltype {
width: 30px;
}
table.diff tr {
@ -8808,3 +8820,17 @@ a.widget-control-edit {
.locale-lt-lt .inline-edit-row fieldset label span.input-text-wrap {
margin-left: 8em;
}
#revisions-meta-mostrecent,
#revisions-meta-stored,
#revisions-meta-oldest,
#revisions-meta-link {
line-height: 30px;
height: 30px;
vertical-align: middle;
padding-right: 10px;
}
#revisions-meta-mostrecent img,
#revisions-meta-oldest img {
vertical-align: middle;
}

View File

@ -168,7 +168,8 @@ if ( post_type_supports($post_type, 'author') ) {
add_meta_box('authordiv', __('Author'), 'post_author_meta_box', null, 'normal', 'core');
}
if ( post_type_supports($post_type, 'revisions') && 0 < $post_ID && wp_get_post_revisions( $post_ID ) )
// TODO review this count() - why do we need to add it?
if ( post_type_supports($post_type, 'revisions') && 0 < $post_ID && count ( wp_get_post_revisions( $post_ID ) ) > 1 )
add_meta_box('revisionsdiv', __('Revisions'), 'post_revisions_meta_box', null, 'normal', 'core');
do_action('add_meta_boxes', $post_type, $post);

View File

@ -1379,7 +1379,7 @@ function wp_ajax_inline_save_tax() {
global $wp_list_table;
check_ajax_referer( 'taxinlineeditnonce', '_inline_edit' );
$post_data = wp_unslash( $_POST );
$taxonomy = sanitize_key( $post_data['taxonomy'] );
@ -2134,3 +2134,138 @@ function wp_ajax_nopriv_heartbeat() {
wp_send_json($response);
}
function wp_ajax_revisions_data() {
check_ajax_referer( 'revisions-ajax-nonce', 'nonce' );
$compareto = isset( $_GET['compareto'] ) ? absint( $_GET['compareto'] ) : 0;
$showautosaves = isset( $_GET['showautosaves'] ) ? $_GET['showautosaves'] : '';
$show_split_view = isset( $_GET['show_split_view'] ) ? $_GET['show_split_view'] : '';
$postid = isset( $_GET['postid'] ) ? absint( $_GET['postid'] ) : '';
$comparetwomode = ( '' == $postid ) ? false : true;
//
//TODO: currently code returns all possible comparisons for the indicated 'compareto' revision
//however, the front end prevents users from pulling the right handle past the left or the left pass the right,
//so only the possible diffs need be generated
//
$alltherevisions = array();
if ( '' == $postid )
$postid = $compareto;
if ( ! current_user_can( 'read_post', $postid ) )
continue;
if ( ! $revisions = wp_get_post_revisions( $postid ) )
return;
//if we are comparing two revisions, the first 'revision' represented by the leftmost
//slider position is the current revision, prepend a comparison to this revision
if ( $comparetwomode )
array_unshift( $revisions, get_post( $postid ) );
$count = 1;
foreach ( $revisions as $revision ) :
if ( 'true' != $showautosaves && wp_is_post_autosave( $revision ) )
continue;
$revision_from_date_author = '';
$left_revision = get_post( $compareto );
$right_revision = get_post( $revision );
$author = get_the_author_meta( 'display_name', $revision->post_author );
/* translators: revision date format, see http://php.net/date */
$datef = _x( 'j F, Y @ G:i:s', 'revision date format');
$gravatar = get_avatar( $revision->post_author, 18 );
$date = date_i18n( $datef, strtotime( $revision->post_modified ) );
$revision_date_author = sprintf(
'%s %s, %s %s (%s)',
$gravatar,
$author,
human_time_diff( strtotime( $revision->post_modified ), current_time( 'timestamp' ) ),
__( ' ago ' ),
$date
);
if ( $comparetwomode ) {
$compareto_gravatar = get_avatar( $left_revision->post_author, 18 );
$compareto_author = get_the_author_meta( 'display_name', $left_revision->post_author );
$compareto_date = date_i18n( $datef, strtotime( $left_revision->post_modified ) );
$revision_from_date_author = sprintf(
'%s %s, %s %s (%s)',
$compareto_gravatar,
$compareto_author,
human_time_diff( strtotime( $left_revision->post_modified ), current_time( 'timestamp' ) ),
__( ' ago ' ),
$compareto_date
);
}
$restoreaction = wp_nonce_url(
add_query_arg(
array( 'revision' => $revision->ID,
'action' => 'restore' ),
'/wp-admin/revision.php'
),
"restore-post_{$compareto}|{$revision->ID}"
);
//
//make sure the left revision is the most recent
//
if ( strtotime( $right_revision->post_modified_gmt ) < strtotime( $left_revision->post_modified_gmt ) ) {
$temp = $left_revision;
$left_revision = $right_revision;
$right_revision = $temp;
}
//
//compare from left to right, passed from application
//
$content='';
foreach ( array_keys( _wp_post_revision_fields() ) as $field ) {
$left_content = apply_filters( "_wp_post_revision_field_$field", $left_revision->$field, $field, $left_revision, 'left' );
$right_content = apply_filters( "_wp_post_revision_field_$field", $right_revision->$field, $field, $right_revision, 'right' );
add_filter( "_wp_post_revision_field_$field", 'wp_kses_post' );
$args = array();
if ( 'true' == $show_split_view )
$args = array( 'show_split_view' => 'true' );
$content .= wp_text_diff( $left_content, $right_content, $args );
}
//if we are comparing two revisions
//and we are on the matching revision
//add an error revision indicating unable to compare to self
if ( $comparetwomode && $compareto == $revision->ID )
$alltherevisions[] = array (
'ID' => $revision->ID,
'revision_date_author' => $revision_date_author,
'revisiondiff' => sprintf('<div id="selfcomparisonerror">%s</div>', __( 'Cannot compare revision to itself' ) ),
'restoreaction' => urldecode( $restoreaction ),
'revision_from_date_author' => ''
);
//add to the return data only if there is a difference
if ( '' != $content )
$alltherevisions[] = array (
'ID' => $revision->ID,
'revision_date_author' => $revision_date_author,
'revisiondiff' => $content,
'restoreaction' => urldecode( $restoreaction ),
'revision_from_date_author' => $revision_from_date_author
);
endforeach;
echo json_encode( $alltherevisions );
exit();
}

530
wp-admin/js/revisions.js Normal file
View File

@ -0,0 +1,530 @@
window.wp = window.wp || {};
(function($) {
wp.revisions = {
views : {},
Model : Backbone.Model.extend({
defaults: {
ID : 0,
revision_date_author : '',
revisiondiff : '',
restoreaction: '',
diff_max : 0,
diff_count : 0,
diff_revision_to : 0,
revision_from_date_author : '',
}
}),
app: _.extend({}, Backbone.Events),
App : Backbone.Router.extend({
_revisionDifflView : null,
_revisions : null,
_left_handle_revisions : null,
_right_handle_revisions : null,
_revisionsInteractions : null,
_revisionsOptions : null,
_left_diff : 0,
_right_diff : 1,
_autosaves : false,
_showsplitview : true,
_compareoneortwo : 1,
left_model_loading : false, //keep track of model loads
right_model_loading : false, //disallow slider interaction, also repeat loads, while loading
//TODO add ability to arrive on specific revision
routes : {
"viewrevision/:revision": "viewrevision",
},
viewrevision : function( revision ) {
//coming soon
},
start_left_model_loading : function() {
this.left_model_loading = true;
$('.revisiondiffcontainer').addClass('leftmodelloading');
},
stop_left_model_loading : function() {
this.left_model_loading = false;
$('.revisiondiffcontainer').removeClass('leftmodelloading');
},
start_right_model_loading : function() {
this.right_model_loading = true;
$('.revisiondiffcontainer').addClass('rightmodelloading');
},
stop_right_model_loading : function() {
this.right_model_loading = false;
$('.revisiondiffcontainer').removeClass('rightmodelloading');
},
reloadmodel : function() {
if ( 2 == this._compareoneortwo ) {
this.reloadleftright();
} else {
this.reloadmodelsingle();
}
},
reloadmodelsingle : function() {
var self = this;
self._revisions.url = ajaxurl + '?action=revisions-data&compareto=' + wpRevisionsSettings.post_id +
'&showautosaves=' + self.self_autosaves +
'&showsplitview=' + REVAPP._showsplitview +
'&nonce=' + wpRevisionsSettings.nonce;
self.start_right_model_loading();
this._revisions.fetch({ //reload revision data
success : function() {
self.stop_right_model_loading();
var revisioncount = self._revisions.length;
if ( self._right_diff > revisioncount ) //if right handle past rightmost, move
self._right_diff = revisioncount;
//TODO add a test for matchind left revision and push left, testing
//also reset the slider values here
self._revisionView.render();
$( '#slider' ).slider( 'option', 'max', revisioncount-1 ); //TODO test this
},
error : function () {
self.stop_right_model_loading();
window.console && console.log( 'Error loading revision data' );
}
});
},
reloadleftright : function() {
var self = this;
self.start_left_model_loading();
self.start_right_model_loading();
self._left_handle_revisions = new wp.revisions.Collection();
self._right_handle_revisions = new wp.revisions.Collection();
if ( 0 == self._left_diff ) {
self._right_handle_revisions.url =
ajaxurl +
'?action=revisions-data&compareto=' + wpRevisionsSettings.post_id +
'&wpRevisionsSettings.post_id=' + wpRevisionsSettings.post_id +
'&showautosaves=' + self._autosaves +
'&showsplitview=' + self._showsplitview +
'&nonce=' + wpRevisionsSettings.nonce;
} else {
self._right_handle_revisions.url =
ajaxurl +
'?action=revisions-data&compareto=' + self._revisions.at( self._left_diff - 1 ).get( 'ID' ) +
'&wpRevisionsSettings.post_id=' + wpRevisionsSettings.post_id +
'&showautosaves=' + self._autosaves +
'&showsplitview=' + self._showsplitview +
'&nonce=' + wpRevisionsSettings.nonce;
}
self._left_handle_revisions.url =
ajaxurl +
'?action=revisions-data&compareto=' + self._revisions.at( self._right_diff - 1 ).get( 'ID' ) +
'&wpRevisionsSettings.post_id=' + wpRevisionsSettings.post_id +
'&showautosaves=' + self._autosaves +
'&showsplitview=' + self._showsplitview +
'&nonce=' + wpRevisionsSettings.nonce;
self._left_handle_revisions.fetch({
xhr: function() {
var xhr = $.ajaxSettings.xhr();
xhr.onprogress = self.handleProgress;
return xhr;
},
handleProgress: function(evt){
var percentComplete = 0;
if (evt.lengthComputable) {
percentComplete = evt.loaded / evt.total;
window.console && console.log( Math.round( percentComplete * 100) + "%" );
}
},
success : function(){
self.stop_left_model_loading();
},
error : function () {
window.console && console.log( 'Error loading revision data' );
self.stop_left_model_loading();
}
});
self._right_handle_revisions.fetch({
success : function(){
self.stop_right_model_loading();
},
error : function () {
window.console && console.log( 'Error loading revision data' );
self.stop_right_model_loading();
}
});
},
/*
* initialize the revision appl;ication
*/
initialize : function( options ) {
var self = this; //store the application instance
if (this._revisions === null) {
self._autosaves = '';
self._revisions = new wp.revisions.Collection(); //set up collection
self.start_right_model_loading();
self._revisions.fetch({ //load revision data
success : function() {
self.stop_right_model_loading();
self.revisionDiffSetup();
}
});
}
return this;
},
revisionDiffSetup : function() {
var self = this, slider;
this._revisionView = new wp.revisions.views.View({
model : this._revisions
});
this._revisionView.render();
this._revisionsInteractions = new wp.revisions.views.Interact({
model : this._revisions
});
this._revisionsInteractions.render();
this._revisionsOptions = new wp.revisions.views.Options({
model : this._revisions
});
this._revisionsOptions.render();
}
})
};
wp.revisions.Collection = Backbone.Collection.extend({
model : wp.revisions.Model,
url : ajaxurl + '?action=revisions-data&compareto=' + wpRevisionsSettings.post_id + '&showautosaves=false&showsplitview=true&nonce=' + wpRevisionsSettings.nonce
});
_.extend(wp.revisions.views, {
//
//primary revision diff view
//
View : Backbone.View.extend({
el : $('#backbonerevisionsdiff')[0],
tagName : 'revisionvview',
className : 'revisionview-container',
template : wp.template('revision'),
revvapp : null,
comparetwochecked : '',
draggingleft : false,
initialize : function(){
},
//
//render the revisions
//
render : function() {
var addhtml = '';
//compare two revisions mode?
if ( 2 == REVAPP._compareoneortwo ) {
this.comparetwochecked = 'checked';
if ( this.draggingleft ) {
if ( this.model.at( REVAPP._left_diff ) ) {
addhtml = this.template( _.extend(
this.model.at( REVAPP._left_diff ).toJSON(),
{ comparetwochecked : this.comparetwochecked } //keep the checkmark checked
) );
}
} else { //dragging right handle
var thediff = REVAPP._right_diff;
if ( this.model.at( thediff ) ) {
addhtml = this.template( _.extend(
this.model.at( thediff ).toJSON(),
{ comparetwochecked : this.comparetwochecked } //keep the checkmark checked
) );
}
}
} else { //end compare two revisions mode, eg only one slider handel
this.comparetwochecked = '';
if ( this.model.at( REVAPP._right_diff - 1 ) ) {
addhtml = this.template( _.extend(
this.model.at( REVAPP._right_diff-1 ).toJSON(),
{ comparetwochecked : this.comparetwochecked } //keep the checkmark checked
) );
}
}
this.$el.html( addhtml );
return this;
},
//the compare two button is in this view, add the interaction here
events : {
'click #comparetwo' : 'clickcomparetwo'
},
//
//turn on/off the compare two mmode
//
clickcomparetwo : function(){
self = this;
if ( $( 'input#comparetwo' ).is( ':checked' ) ) {
REVAPP._compareoneortwo = 2 ;
REVAPP.reloadleftright();
} else {
REVAPP._compareoneortwo = 1 ;
REVAPP._revisionView.draggingleft = false;
REVAPP._left_diff = 0;
REVAPP.reloadmodelsingle();
}
REVAPP._revisionsInteractions.render();
}
}),
//
//options view for show autosaves and show split view options
//
Options : Backbone.View.extend({
el : $('#backbonerevisionsoptions')[0],
tagName : 'revisionoptionsview',
className : 'revisionoptions-container',
template : wp.template('revisionoptions'),
initialize : function() {
},
//render the options view
render : function() {
var addhtml = this.template;
this.$el.html( addhtml );
return this;
},
//add options interactions
events : {
'click #toggleshowautosaves' : 'toggleshowautosaves',
'click #showsplitview' : 'showsplitview'
},
//
//toggle include autosaves
//
toggleshowautosaves : function() {
var self = this;
if ( $( '#toggleshowautosaves' ).is( ':checked' ) ) {
REVAPP._autosaves = true ;
} else {
REVAPP._autosaves = false ;
}
//refresh the model data
REVAPP.reloadmodel();
//TODO check for two handle mode
},
//
//toggle showing the split diff view
//
showsplitview : function() {
var self = this;
if ( $( 'input#showsplitview' ).is( ':checked' ) ) {
REVAPP._showsplitview = 'true';
$('.revisiondiffcontainer').addClass('diffsplit');
} else {
REVAPP._showsplitview = '';
$('.revisiondiffcontainer').removeClass('diffsplit');
}
REVAPP.reloadmodel();
}
}),
//
//main interactions view
//
Interact : Backbone.View.extend({
el : $('#backbonerevisionsinteract')[0],
tagName : 'revisionvinteract',
className : 'revisionvinteract-container',
template : wp.template('revisionvinteract'),
initialize : function() {
},
render : function() {
var self = this;
var addhtml = this.template;
this.$el.html( addhtml );
$( '#diff_max, #diff_maxof' ).html( this.model.length );
$( '#diff_count' ).html( REVAPP._right_diff );
$( '#diff_left_count_inner' ).html( 0 == REVAPP._left_diff ? '' : 'revision' + REVAPP._left_diff );
var modelcount = REVAPP._revisions.length;
slider = $("#slider");
if ( 1 == REVAPP._compareoneortwo ) {
//set up the slider with a single handle
slider.slider({
value : REVAPP._right_diff-1,
min : 0,
max : modelcount-1,
step : 1,
//slide interactions for one handles slider
slide : function( event, ui ) {
if ( REVAPP.right_model_loading ) //left model stoll loading, prevent sliding left handle
return false;
REVAPP._right_diff =( ui.value+1 );
$( '#diff_count' ).html( REVAPP._right_diff );
REVAPP._revisionView.render();
}
});
$( '.revisiondiffcontainer' ).removeClass( 'comparetwo' );
} else { //comparing more than one, eg 2
//set up the slider with two handles
slider.slider({
values : [ REVAPP._left_diff, REVAPP._right_diff + 1 ],
min : 1,
max : modelcount+1,
step : 1,
range: true,
//in two handled mode when user starts dragging, swap in precalculated diff for handle
start : function (event, ui ) {
var index = $( ui.handle ).index(); //0 (left) or 1 (right)
switch ( index ) {
case 1: //left handle drag
if ( REVAPP.left_model_loading ) //left model stoll loading, prevent sliding left handle
return false;
if ( REVAPP._revisionView.model !== REVAPP._left_handle_revisions &&
null != REVAPP._left_handle_revisions )
REVAPP._revisionView.model = REVAPP._left_handle_revisions;
REVAPP._revisionView.draggingleft = true;
break;
case 2: //right
if ( REVAPP.right_model_loading ) //right model stoll loading, prevent sliding right handle
return false;
//one extra spot at left end when comparing two
if ( REVAPP._revisionView.model !== REVAPP._right_handle_revisions &&
null != REVAPP._right_handle_revisions )
REVAPP._revisionView.model = REVAPP._right_handle_revisions;
REVAPP._revisionView.draggingleft = false;
REVAPP._right_diff = ui.values[1] - 1 ;
break;
}
},
//when sliding in two handled mode change appropriate value
slide : function( event, ui ) {
if ( ui.values[0] == ui.values[1] ) //prevent compare to self
return false;
var index = $( ui.handle ).index(); //0 (left) or 1 (right)
switch ( index ) {
case 1: //left
if ( REVAPP.left_model_loading ) //left model stoll loading, prevent sliding left handle
return false;
REVAPP._left_diff = ui.values[0] - 1; //one extra spot at left end when comparing two
break;
case 2: //right
if ( REVAPP.right_model_loading ) //right model stoll loading, prevent sliding right handle
return false;
REVAPP._right_diff = ui.values[1] - 1 ;
break;
}
$( '#diff_count' ).html( REVAPP._right_diff );
if ( 0 == REVAPP._left_diff ) {
$( '.revisiondiffcontainer' ).addClass( 'currentversion' );
} else {
$( '.revisiondiffcontainer' ).removeClass( 'currentversion' );
$( '#diff_left_count_inner' ).html( REVAPP._left_diff );
}
REVAPP._revisionView.render(); //render the diff view
},
//when the user stops sliding in 2 handle mode, recalculate diffs
stop : function( event, ui ) {
if ( 2 == REVAPP._compareoneortwo ) {
//calculate and generate a diff for comparing to the left handle
//and the right handle, swap out when dragging
if ( ! (REVAPP.left_model_loading && REVAPP.right_model.loading ) ) {
REVAPP.reloadleftright();
}
}
}
});
$( '.revisiondiffcontainer' ).addClass( 'comparetwo' );
}
return this;
},
//next and previous buttons, only available in compare one mode
events : {
'click #next' : 'nextrevision',
'click #previous' : 'previousrevision'
},
//go to the next revision
nextrevision : function() {
if ( REVAPP._right_diff < this.model.length ) //unless at right boundry
REVAPP._right_diff = REVAPP._right_diff + 1 ;
REVAPP._revisionView.render();
$( '#diff_count' ).html( REVAPP._right_diff );
$( '#slider' ).slider( 'value', REVAPP._right_diff - 1 ).trigger( 'slide' );
},
//go the the previous revision
previousrevision : function() {
if ( REVAPP._right_diff > 1 ) //unless at left boundry
REVAPP._right_diff = REVAPP._right_diff - 1 ;
REVAPP._revisionView.render();
$( '#diff_count' ).html( REVAPP._right_diff );
$( '#slider' ).slider( 'value', REVAPP._right_diff - 1 ).trigger( 'slide' );
}
})
});
//instantiate Revision Application
REVAPP = new wp.revisions.App();
//TODO consider enable back button to step back thru states?
Backbone.history.start();
}(jQuery));

0
wp-admin/js/revisions.min.js vendored Normal file
View File

View File

@ -8,15 +8,9 @@
/** WordPress Administration Bootstrap */
require_once('./admin.php');
wp_enqueue_script('list-revisions');
wp_reset_vars(array('revision', 'left', 'right', 'action'));
wp_reset_vars( array( 'revision', 'action' ) );
$revision_id = absint($revision);
$left = absint($left);
$right = absint($right);
$redirect = 'edit.php';
switch ( $action ) :
@ -33,75 +27,13 @@ case 'restore' :
$redirect = 'edit.php?post_type=' . $post->post_type;
break;
}
check_admin_referer( "restore-post_$post->ID|$revision->ID" );
check_admin_referer( "restore-post_{$post->ID}|{$revision->ID}" );
wp_restore_post_revision( $revision->ID );
$redirect = add_query_arg( array( 'message' => 5, 'revision' => $revision->ID ), get_edit_post_link( $post->ID, 'url' ) );
break;
case 'diff' :
if ( !$left_revision = get_post( $left ) )
break;
if ( !$right_revision = get_post( $right ) )
break;
if ( !current_user_can( 'read_post', $left_revision->ID ) || !current_user_can( 'read_post', $right_revision->ID ) )
break;
// If we're comparing a revision to itself, redirect to the 'view' page for that revision or the edit page for that post
if ( $left_revision->ID == $right_revision->ID ) {
$redirect = get_edit_post_link( $left_revision->ID );
include( './js/revisions-js.php' );
break;
}
// Don't allow reverse diffs?
if ( strtotime($right_revision->post_modified_gmt) < strtotime($left_revision->post_modified_gmt) ) {
$redirect = add_query_arg( array( 'left' => $right, 'right' => $left ) );
break;
}
if ( $left_revision->ID == $right_revision->post_parent ) // right is a revision of left
$post =& $left_revision;
elseif ( $left_revision->post_parent == $right_revision->ID ) // left is a revision of right
$post =& $right_revision;
elseif ( $left_revision->post_parent == $right_revision->post_parent ) // both are revisions of common parent
$post = get_post( $left_revision->post_parent );
else
break; // Don't diff two unrelated revisions
if ( ! WP_POST_REVISIONS || !post_type_supports($post->post_type, 'revisions') ) { // Revisions disabled
if (
// we're not looking at an autosave
( !wp_is_post_autosave( $left_revision ) && !wp_is_post_autosave( $right_revision ) )
||
// we're not comparing an autosave to the current post
( $post->ID !== $left_revision->ID && $post->ID !== $right_revision->ID )
) {
$redirect = 'edit.php?post_type=' . $post->post_type;
break;
}
}
if (
// They're the same
$left_revision->ID == $right_revision->ID
||
// Neither is a revision
( !wp_get_post_revision( $left_revision->ID ) && !wp_get_post_revision( $right_revision->ID ) )
)
break;
$post_title = '<a href="' . get_edit_post_link() . '">' . get_the_title() . '</a>';
$h2 = sprintf( __( 'Compare Revisions of &#8220;%1$s&#8221;' ), $post_title );
$title = __( 'Revisions' );
$left = $left_revision->ID;
$right = $right_revision->ID;
$redirect = false;
break;
case 'view' :
case 'edit' :
default :
if ( !$revision = wp_get_post_revision( $revision_id ) )
break;
@ -119,13 +51,9 @@ default :
$post_title = '<a href="' . get_edit_post_link() . '">' . get_the_title() . '</a>';
$revision_title = wp_post_revision_title( $revision, false );
$h2 = sprintf( __( 'Revision for &#8220;%1$s&#8221; created on %2$s' ), $post_title, $revision_title );
$h2 = sprintf( __( 'Compare Revisions of &#8220;%1$s&#8221;' ), $post_title );
$title = __( 'Revisions' );
// Sets up the diff radio buttons
$left = $revision->ID;
$right = $post->ID;
$redirect = false;
break;
endswitch;
@ -145,79 +73,83 @@ if ( !empty($post->post_type) && 'post' != $post->post_type )
else
$parent_file = $submenu_file = 'edit.php';
wp_enqueue_style( 'revisions' );
wp_enqueue_script( 'revisions' );
require_once( './admin-header.php' );
//TODO - Some of the translations below split things into multiple strings that are contextually related and this makes it pretty impossible for RTL translation.
//TODO can we pass the context in a better way
?>
<script type="text/javascript">
var wpRevisionsSettings = <?php echo json_encode( array( 'post_id' => $post->ID, 'nonce' => wp_create_nonce( 'revisions-ajax-nonce' ) ) ); ?>;
</script>
<div id="backbonerevisionsoptions"></div>
<br class="clear"/>
<div class="wrap">
<h2 class="long-header"><?php echo $h2; ?></h2>
<table class="form-table ie-fixed">
<col class="th" />
<?php if ( 'diff' == $action ) : ?>
<tr id="revision">
<th scope="row"></th>
<th scope="col" class="th-full">
<span class="alignleft"><?php printf( __('Older: %s'), wp_post_revision_title( $left_revision ) ); ?></span>
<span class="alignright"><?php printf( __('Newer: %s'), wp_post_revision_title( $right_revision ) ); ?></span>
</th>
</tr>
<?php endif;
// use get_post_to_edit filters?
$identical = true;
foreach ( _wp_post_revision_fields() as $field => $field_title ) :
if ( 'diff' == $action ) {
$left_content = apply_filters( "_wp_post_revision_field_$field", $left_revision->$field, $field, $left_revision, 'left' );
$right_content = apply_filters( "_wp_post_revision_field_$field", $right_revision->$field, $field, $right_revision, 'right' );
if ( !$content = wp_text_diff( $left_content, $right_content ) )
continue; // There is no difference between left and right
$identical = false;
} else {
add_filter( "_wp_post_revision_field_$field", 'htmlspecialchars' );
$content = apply_filters( "_wp_post_revision_field_$field", $revision->$field, $field, $revision, '' );
}
?>
<tr id="revision-field-<?php echo $field; ?>">
<th scope="row"><?php echo esc_html( $field_title ); ?></th>
<td><div class="pre"><?php echo $content; ?></div></td>
</tr>
<?php
endforeach;
if ( 'diff' == $action && $identical ) :
?>
<tr><td colspan="2"><div class="updated"><p><?php _e( 'These revisions are identical.' ); ?></p></div></td></tr>
<?php
endif;
?>
</table>
<br class="clear" />
<h3><?php echo $title; ?></h3>
<div class="icon32 icon32-posts-post" id="icon-edit"><br></div>
<div class="revisiondiffcontainer diffsplit currentversion rightmodelloading">
<div id="modelsloading" class="updated message"><span class="spinner" ></span> <?php _e( 'Calculating revision diffs' ); ?></div>
<h2 class="long-header"><?php echo $h2; ?></h2>
<div id="backbonerevisionsinteract"></div>
<div id="backbonerevisionsdiff"></div>
<hr />
<?php
$args = array( 'format' => 'form-table', 'parent' => true, 'right' => $right, 'left' => $left );
if ( ! WP_POST_REVISIONS || !post_type_supports($post->post_type, 'revisions') )
$args['type'] = 'autosave';
wp_list_post_revisions( $post, $args );
$comparetworevisionslink = get_edit_post_link( $revision->ID );
?>
</div>
</div>
<script id="tmpl-revision" type="text/html">
<div id="diffsubheader">
<span id="diff_from_current_revision"><?php _e( 'Current version' ); ?><?php _e( '- compared to -' ); ?></span>
<div id="difftitlefrom">{{{ data.revision_from_date_author }}} <?php _e( '- compared to -' ); ?></div>
<div id="difftitle">{{{ data.revision_date_author }}}</div>
<div id="diffcancel"><input class="button" onClick="document.location='<?php echo get_edit_post_link( $post->ID ); ?>'" type="submit" id="cancel" value="<?php esc_attr_e( 'Cancel' )?>" /></div>
<div id="diffrestore"><input class="button button-primary" onClick="document.location='{{{ data.restoreaction }}}'" type="submit" id="restore" value="<?php esc_attr_e( 'Restore' )?>" /></div>
<div id="comparetworevisions"><input type="checkbox" id="comparetwo" value="comparetwo" {{{ data.comparetwochecked }}} name="comparetwo"/> <?php esc_attr_e( 'Compare two revisions' )?></div>
</div>
<div id="removedandadded">
<div id="removed"><?php _e( 'Removed -' ); ?></div>
<div id="added"><?php _e( 'Added +' ); ?></div>
</div
<div>{{{ data.revisiondiff }}}</div>
</script>
<script id="tmpl-revisionvinteract" type="text/html">
<div id="diffheader">
<div id="diffprevious"><input class="button" type="submit" id="previous" value="Previous" /></div>
<div id="diffnext"><input class="button" type="submit" id="next" value="Next" /></div>
<div id="diffslider">
<div id="revisioncount">
<?php _e( 'Comparing' ); ?>
<span id="diff_left_count"> <?php _e( 'revision' ); ?></span> <span id="diff_left_count_inner"></span>
<span id="diff_left_current_revision"><?php _e( 'current version' ); ?></span>
<span id="diff_revision_from">{{{ data.diff_revision_from }}}</span>
<?php _e( ' to revision' ); ?>
<span id="diff_count">{{{ data.current_diff }}}</span>
<?php _e( ' of ' ); ?>
<span id="diff_max" ></span>
</div>
<div id="slider"></div>
</div>
</div>
</script>
<?php
require_once( './admin-footer.php' );
/*
TODO Convert these into screen options
<script id="tmpl-revisionoptions" type="text/html">
<div id="revisionoptions">
<div id="showsplitviewoption">
<input type='checkbox' id="show_split_view" checked="checked" value="1" /> <?php _e( 'Show split diff view' ); ?>
</div>
<div id="toggleshowautosavesoption">
<input type='checkbox' id="toggleshowautosaves" value="1" /> <?php _e( 'Show autosaves' ); ?>
</div>
</div>
</script>
*/
require_once( './admin-footer.php' );

View File

@ -0,0 +1,544 @@
/*! jQuery UI - v1.10.1 - 2013-02-15
* http://jqueryui.com
* Includes: jquery.ui.core.css, jquery.ui.slider.css
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
* Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */
/* Layout helpers
----------------------------------*/
.ui-helper-hidden {
display: none;
}
.ui-helper-hidden-accessible {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.ui-helper-reset {
margin: 0;
padding: 0;
border: 0;
outline: 0;
line-height: 1.3;
text-decoration: none;
font-size: 100%;
list-style: none;
}
.ui-helper-clearfix:before,
.ui-helper-clearfix:after {
content: "";
display: table;
border-collapse: collapse;
}
.ui-helper-clearfix:after {
clear: both;
}
.ui-helper-clearfix {
min-height: 0; /* support: IE7 */
}
.ui-helper-zfix {
width: 100%;
height: 100%;
top: 0;
left: 0;
position: absolute;
opacity: 0;
filter:Alpha(Opacity=0);
}
.ui-front {
z-index: 100;
}
/* Interaction Cues
----------------------------------*/
.ui-state-disabled {
cursor: default !important;
}
/* Icons
----------------------------------*/
/* states and images */
.ui-icon {
display: block;
text-indent: -99999px;
overflow: hidden;
background-repeat: no-repeat;
}
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.ui-slider {
position: relative;
text-align: left;
}
.ui-slider .ui-slider-handle {
position: absolute;
z-index: 2;
width: 1.2em;
height: 1.2em;
cursor: default;
}
.ui-slider .ui-slider-range {
position: absolute;
z-index: 1;
font-size: .7em;
display: block;
border: 0;
background-position: 0 0;
}
/* For IE8 - See #6727 */
.ui-slider.ui-state-disabled .ui-slider-handle,
.ui-slider.ui-state-disabled .ui-slider-range {
filter: inherit;
}
.ui-slider-horizontal {
height: .8em;
}
.ui-slider-horizontal .ui-slider-handle {
top: -.3em;
margin-left: -.6em;
}
.ui-slider-horizontal .ui-slider-range {
top: 0;
height: 100%;
}
.ui-slider-horizontal .ui-slider-range-min {
left: 0;
}
.ui-slider-horizontal .ui-slider-range-max {
right: 0;
}
.ui-slider-vertical {
width: .8em;
height: 100px;
}
.ui-slider-vertical .ui-slider-handle {
left: -.3em;
margin-left: 0;
margin-bottom: -.6em;
}
.ui-slider-vertical .ui-slider-range {
left: 0;
width: 100%;
}
.ui-slider-vertical .ui-slider-range-min {
bottom: 0;
}
.ui-slider-vertical .ui-slider-range-max {
top: 0;
}
/* Component containers
----------------------------------*/
.ui-widget {
font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;
font-size: 1.1em;
}
.ui-widget .ui-widget {
font-size: 1em;
}
.ui-widget input,
.ui-widget select,
.ui-widget textarea,
.ui-widget button {
font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;
font-size: 1em;
}
.ui-widget-content {
border: 1px solid #dddddd;
background: #eeeeee url(../images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x;
color: #333333;
}
.ui-widget-content a {
color: #333333;
}
.ui-widget-header {
border: 1px solid #e78f08;
background: #f6a828 url(../images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x;
color: #ffffff;
font-weight: bold;
}
.ui-widget-header a {
color: #ffffff;
}
/* Interaction states
----------------------------------*/
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default {
border: 1px solid #cccccc;
background: #f6f6f6 url(../images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x;
font-weight: bold;
color: #1c94c4;
}
.ui-state-default a,
.ui-state-default a:link,
.ui-state-default a:visited {
color: #1c94c4;
text-decoration: none;
}
.ui-state-hover,
.ui-widget-content .ui-state-hover,
.ui-widget-header .ui-state-hover,
.ui-state-focus,
.ui-widget-content .ui-state-focus,
.ui-widget-header .ui-state-focus {
border: 1px solid #fbcb09;
background: #fdf5ce url(../images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x;
font-weight: bold;
color: #c77405;
}
.ui-state-hover a,
.ui-state-hover a:hover,
.ui-state-hover a:link,
.ui-state-hover a:visited {
color: #c77405;
text-decoration: none;
}
.ui-state-active,
.ui-widget-content .ui-state-active,
.ui-widget-header .ui-state-active {
border: 1px solid #fbd850;
background: #ffffff url(../images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;
font-weight: bold;
color: #eb8f00;
}
.ui-state-active a,
.ui-state-active a:link,
.ui-state-active a:visited {
color: #eb8f00;
text-decoration: none;
}
/* Interaction Cues
----------------------------------*/
.ui-state-highlight,
.ui-widget-content .ui-state-highlight,
.ui-widget-header .ui-state-highlight {
border: 1px solid #fed22f;
background: #ffe45c url(../images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x;
color: #363636;
}
.ui-state-highlight a,
.ui-widget-content .ui-state-highlight a,
.ui-widget-header .ui-state-highlight a {
color: #363636;
}
.ui-state-error,
.ui-widget-content .ui-state-error,
.ui-widget-header .ui-state-error {
border: 1px solid #cd0a0a;
background: #b81900 url(../images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat;
color: #ffffff;
}
.ui-state-error a,
.ui-widget-content .ui-state-error a,
.ui-widget-header .ui-state-error a {
color: #ffffff;
}
.ui-state-error-text,
.ui-widget-content .ui-state-error-text,
.ui-widget-header .ui-state-error-text {
color: #ffffff;
}
.ui-priority-primary,
.ui-widget-content .ui-priority-primary,
.ui-widget-header .ui-priority-primary {
font-weight: bold;
}
.ui-priority-secondary,
.ui-widget-content .ui-priority-secondary,
.ui-widget-header .ui-priority-secondary {
opacity: .7;
filter:Alpha(Opacity=70);
font-weight: normal;
}
.ui-state-disabled,
.ui-widget-content .ui-state-disabled,
.ui-widget-header .ui-state-disabled {
opacity: .35;
filter:Alpha(Opacity=35);
background-image: none;
}
.ui-state-disabled .ui-icon {
filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
}
/* Icons
----------------------------------*/
/* states and images */
.ui-icon {
width: 16px;
height: 16px;
background-position: 16px 16px;
}
.ui-icon,
.ui-widget-content .ui-icon {
background-image: url(../images/ui-icons_222222_256x240.png);
}
.ui-widget-header .ui-icon {
background-image: url(../images/ui-icons_ffffff_256x240.png);
}
.ui-state-default .ui-icon {
background-image: url(../images/ui-icons_ef8c08_256x240.png);
}
.ui-state-hover .ui-icon,
.ui-state-focus .ui-icon {
background-image: url(../images/ui-icons_ef8c08_256x240.png);
}
.ui-state-active .ui-icon {
background-image: url(../images/ui-icons_ef8c08_256x240.png);
}
.ui-state-highlight .ui-icon {
background-image: url(../images/ui-icons_228ef1_256x240.png);
}
.ui-state-error .ui-icon,
.ui-state-error-text .ui-icon {
background-image: url(../images/ui-icons_ffd27a_256x240.png);
}
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-on { background-position: -96px -144px; }
.ui-icon-radio-off { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all,
.ui-corner-top,
.ui-corner-left,
.ui-corner-tl {
border-top-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-top,
.ui-corner-right,
.ui-corner-tr {
border-top-right-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-left,
.ui-corner-bl {
border-bottom-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-right,
.ui-corner-br {
border-bottom-right-radius: 4px;
}
/* Overlays */
.ui-widget-overlay {
background: #666666 url(../images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat;
opacity: .5;
filter: Alpha(Opacity=50);
}
.ui-widget-shadow {
margin: -5px 0 0 -5px;
padding: 5px;
background: #000000 url(../images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x;
opacity: .2;
filter: Alpha(Opacity=20);
border-radius: 5px;
}

View File

View File

@ -0,0 +1,29 @@
window.wp = window.wp || {};
(function ($) {
var template;
/**
* wp.template( id )
*
* Fetches a template by id.
*
* @param {string} id A string that corresponds to a DOM element with an id prefixed with "tmpl-".
* For example, "attachment" maps to "tmpl-attachment".
* @return {function} A function that lazily-compiles the template requested.
*/
template = wp.template = _.memoize(function ( id ) {
var compiled,
options = {
evaluate: /<#([\s\S]+?)#>/g,
interpolate: /\{\{\{([\s\S]+?)\}\}\}/g,
escape: /\{\{([^\}]+?)\}\}(?!\})/g,
variable: 'data'
};
return function ( data ) {
compiled = compiled || _.template( $( '#tmpl-' + id ).html(), null, options );
return compiled( data );
};
});
}(jQuery));

0
wp-includes/js/template.min.js vendored Normal file
View File

View File

@ -1713,16 +1713,20 @@ function wp_text_diff( $left_string, $right_string, $args = null ) {
$left_lines = explode("\n", $left_string);
$right_lines = explode("\n", $right_string);
$text_diff = new Text_Diff($left_lines, $right_lines);
$renderer = new WP_Text_Diff_Renderer_Table();
$renderer = new WP_Text_Diff_Renderer_Table( $args );
$diff = $renderer->render($text_diff);
if ( !$diff )
return '';
$r = "<table class='diff'>\n";
$r .= "<col class='ltype' /><col class='content' /><col class='ltype' /><col class='content' />";
if ( isset( $args[ 'showsplitview' ] ) && 'true' == $args[ 'showsplitview' ] ) {
$r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />";
} else {
$r .= "<col class='content' />";
}
if ( $args['title'] || $args['title_left'] || $args['title_right'] )
$r .= "<thead>";

View File

@ -1300,23 +1300,34 @@ function wp_post_revision_title( $revision, $link = true ) {
if ( !in_array( $revision->post_type, array( 'post', 'page', 'revision' ) ) )
return false;
$author = get_the_author_meta( 'display_name', $revision->post_author );
/* translators: revision date format, see http://php.net/date */
$datef = _x( 'j F, Y @ G:i', 'revision date format');
/* translators: 1: date */
$autosavef = __( '%1$s [Autosave]' );
/* translators: 1: date */
$currentf = __( '%1$s [Current Revision]' );
$datef = _x( 'j F, Y @ G:i:s', 'revision date format');
$gravatar = get_avatar( $revision->post_author, 18 );
$date = date_i18n( $datef, strtotime( $revision->post_modified ) );
if ( $link && current_user_can( 'edit_post', $revision->ID ) && $link = get_edit_post_link( $revision->ID ) )
$date = "<a href='$link'>$date</a>";
$revision_date_author = sprintf(
'%s %s, %s %s (%s)',
$gravatar,
$author,
human_time_diff( strtotime( $revision->post_modified ), current_time( 'timestamp' ) ),
__( 'ago' ),
$date
);
$autosavef = __( '%1$s [Autosave]' );
$currentf = __( '%1$s [Current Revision]' );
if ( !wp_is_post_revision( $revision ) )
$date = sprintf( $currentf, $date );
$revision_date_author = sprintf( $currentf, $revision_date_author );
elseif ( wp_is_post_autosave( $revision ) )
$date = sprintf( $autosavef, $date );
$revision_date_author = sprintf( $autosavef, $revision_date_author );
return $date;
return $revision_date_author;
}
/**

View File

@ -270,7 +270,10 @@ function wp_default_scripts( &$scripts ) {
$scripts->add( 'json2', "/wp-includes/js/json2$suffix.js", array(), '2011-02-23');
$scripts->add( 'underscore', '/wp-includes/js/underscore.min.js', array(), '1.4.4', 1 );
$scripts->add( 'backbone', '/wp-includes/js/backbone.min.js', array('underscore','jquery'), '0.9.2', 1 );
$scripts->add( 'template', "/wp-includes/js/template$suffix.js", array('underscore'), '1.4.4', 1 );
$scripts->add( 'backbone', '/wp-includes/js/backbone.min.js', array('underscore','jquery', 'template'), '0.9.2', 1 );
$scripts->add( 'revisions', "/wp-admin/js/revisions$suffix.js", array( 'backbone', 'jquery-ui-slider' ), false, 1 );
$scripts->add( 'imgareaselect', "/wp-includes/js/imgareaselect/jquery.imgareaselect$suffix.js", array('jquery'), '0.9.8', 1 );
@ -539,6 +542,8 @@ function wp_default_styles( &$styles ) {
$styles->add( 'customize-controls', "/wp-admin/css/customize-controls$suffix.css", array( 'wp-admin', 'colors', 'ie' ) );
$styles->add( 'media-views', "/wp-includes/css/media-views$suffix.css", array( 'buttons' ) );
$styles->add( 'buttons', "/wp-includes/css/buttons$suffix.css" );
$styles->add( 'wp-jquery-ui-slider', "/wp-includes/css/jquery-ui-slider$suffix.css" );
$styles->add( 'revisions', "/wp-admin/css/revisions$suffix.css", array( 'wp-jquery-ui-slider' ) );
foreach ( $rtl_styles as $rtl_style ) {
$styles->add_data( $rtl_style, 'rtl', true );

View File

@ -59,6 +59,15 @@ class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
*/
var $inline_diff_renderer = 'WP_Text_Diff_Renderer_inline';
/**
* Should we show the split view or not
*
* @var string
* @access protected
* @since 3.6.0
*/
var $_show_split_view = true;
/**
* Constructor - Call parent constructor with params array.
*
@ -70,6 +79,8 @@ class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
*/
function __construct( $params = array() ) {
parent::__construct( $params );
if ( isset( $params[ 'show_split_view' ] ) )
$this->_show_split_view = $params[ 'show_split_view' ];
}
/**
@ -98,7 +109,8 @@ class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
* @return string
*/
function addedLine( $line ) {
return "<td>+</td><td class='diff-addedline'>{$line}</td>";
return "<td class='diff-addedline'>{$line}</td>";
}
/**
@ -108,7 +120,7 @@ class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
* @return string
*/
function deletedLine( $line ) {
return "<td>-</td><td class='diff-deletedline'>{$line}</td>";
return "<td class='diff-deletedline'>{$line}</td>";
}
/**
@ -118,7 +130,7 @@ class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
* @return string
*/
function contextLine( $line ) {
return "<td> </td><td class='diff-context'>{$line}</td>";
return "<td class='diff-context'>{$line}</td>";
}
/**
@ -127,7 +139,7 @@ class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
* @return string
*/
function emptyLine() {
return '<td colspan="2">&nbsp;</td>';
return '<td>&nbsp;</td>';
}
/**
@ -142,8 +154,12 @@ class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
$r = '';
foreach ($lines as $line) {
if ( $encode )
$line = htmlspecialchars( $line );
$r .= '<tr>' . $this->emptyLine() . $this->addedLine( $line ) . "</tr>\n";
$line = wp_kses_post( $line );
if ( $this->_show_split_view ) {
$r .= '<tr>' . $this->emptyLine() . $this->emptyLine() . $this->addedLine( $line ) . "</tr>\n";
} else {
$r .= '<tr>' . $this->addedLine( $line ) . "</tr>\n";
}
}
return $r;
}
@ -160,8 +176,13 @@ class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
$r = '';
foreach ($lines as $line) {
if ( $encode )
$line = htmlspecialchars( $line );
$r .= '<tr>' . $this->deletedLine( $line ) . $this->emptyLine() . "</tr>\n";
$line = wp_kses_post( $line );
if ( $this->_show_split_view ) {
$r .= '<tr>' . $this->deletedLine( $line ) . $this->emptyLine() . $this->emptyLine() . "</tr>\n";
} else {
$r .= '<tr>' . $this->deletedLine( $line ) . "</tr>\n";
}
}
return $r;
}
@ -178,9 +199,12 @@ class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
$r = '';
foreach ($lines as $line) {
if ( $encode )
$line = htmlspecialchars( $line );
$r .= '<tr>' .
$this->contextLine( $line ) . $this->contextLine( $line ) . "</tr>\n";
$line = wp_kses_post( $line );
if ( $this->_show_split_view ) {
$r .= '<tr>' . $this->contextLine( $line ) . $this->emptyLine() . $this->contextLine( $line ) . "</tr>\n";
} else {
$r .= '<tr>' . $this->contextLine( $line ) . "</tr>\n";
}
}
return $r;
}
@ -264,7 +288,11 @@ class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
} elseif ( $final_rows[$row] < 0 ) { // Final is blank. This is really a deleted row.
$r .= $this->_deleted( array($orig_line), false );
} else { // A true changed row.
$r .= '<tr>' . $this->deletedLine( $orig_line ) . $this->addedLine( $final_line ) . "</tr>\n";
if ( $this->_show_split_view ) {
$r .= '<tr>' . $this->deletedLine( $orig_line ) . $this->emptyLine() . $this->addedLine( $final_line ) . "</tr>\n";
} else {
$r .= '<tr>' . $this->deletedLine( $orig_line ) . "</tr><tr>" . $this->addedLine( $final_line ) . "</tr>\n";
}
}
}