: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
onSelectChange: function(img, c) {
var sizer = imageEdit.hold.sizer;
selW.val( imageEdit.round(c.width / sizer) );
selH.val( imageEdit.round(c.height / sizer) );
selX.val( imageEdit.round(c.x1 / sizer) );
selY.val( imageEdit.round(c.y1 / sizer) );
* Stores the current crop selection.
* @param {number} postid The post ID.
* @param {Object} c The selection.
setCropSelection : function(postid, c) {
if ( !c || ( c.width < 3 && c.height < 3 ) ) {
this.setDisabled( $( '.imgedit-crop', '#imgedit-panel-' + postid ), 1 );
this.setDisabled( $( '#imgedit-crop-sel-' + postid ), 1 );
$('#imgedit-sel-width-' + postid).val('');
$('#imgedit-sel-height-' + postid).val('');
$('#imgedit-start-x-' + postid).val('0');
$('#imgedit-start-y-' + postid).val('0');
$('#imgedit-selection-' + postid).val('');
sel = { 'x': c.x1, 'y': c.y1, 'w': c.width, 'h': c.height };
this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 1);
$('#imgedit-selection-' + postid).val( JSON.stringify(sel) );
* Closes the image editor.
* @param {number} postid The post ID.
* @param {boolean} warn Warning message.
* @return {void|boolean} Returns false if there is a warning.
close : function(postid, warn) {
if ( warn && this.notsaved(postid) ) {
// If we've loaded the editor in the context of a Media Modal,
// then switch to the previous view, whatever that might have been.
// In case we are not accessing the image editor in the context of a View,
// close the editor the old-school way.
$('#image-editor-' + postid).fadeOut('fast', function() {
$( '#media-head-' + postid ).fadeIn( 'fast', function() {
// Move focus back to the Edit Image button. Runs also when saving.
$( '#imgedit-open-btn-' + postid ).trigger( 'focus' );
* Checks if the image edit history is saved.
* @param {number} postid The post ID.
* @return {boolean} Returns true if the history is not saved.
notsaved : function(postid) {
var h = $('#imgedit-history-' + postid).val(),
history = ( h !== '' ) ? JSON.parse(h) : [],
pop = this.intval( $('#imgedit-undone-' + postid).val() );
if ( pop < history.length ) {
if ( confirm( $('#imgedit-leaving-' + postid).text() ) ) {
* Adds an image edit action to the history.
* @param {Object} op The original position.
* @param {number} postid The post ID.
* @param {string} nonce The nonce.
addStep : function(op, postid, nonce) {
var t = this, elem = $('#imgedit-history-' + postid),
history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : [],
undone = $( '#imgedit-undone-' + postid ),
pop = t.intval( undone.val() );
elem.val( JSON.stringify(history) );
t.refreshEditor(postid, nonce, function() {
t.setDisabled($('#image-undo-' + postid), true);
t.setDisabled($('#image-redo-' + postid), false);
* @param {string} angle The angle the image is rotated with.
* @param {number} postid The post ID.
* @param {string} nonce The nonce.
* @param {Object} t The target element.
rotate : function(angle, postid, nonce, t) {
if ( $(t).hasClass('disabled') ) {
this.addStep({ 'r': { 'r': angle, 'fw': this.hold.h, 'fh': this.hold.w }}, postid, nonce);
* @param {number} axis The axle the image is flipped on.
* @param {number} postid The post ID.
* @param {string} nonce The nonce.
* @param {Object} t The target element.
flip : function (axis, postid, nonce, t) {
if ( $(t).hasClass('disabled') ) {
this.addStep({ 'f': { 'f': axis, 'fw': this.hold.w, 'fh': this.hold.h }}, postid, nonce);
* @param {number} postid The post ID.
* @param {string} nonce The nonce.
* @param {Object} t The target object.
* @return {void|boolean} Returns false if the crop button is disabled.
crop : function (postid, nonce, t) {
var sel = $('#imgedit-selection-' + postid).val(),
w = this.intval( $('#imgedit-sel-width-' + postid).val() ),
h = this.intval( $('#imgedit-sel-height-' + postid).val() );
if ( $(t).hasClass('disabled') || sel === '' ) {
if ( sel.w > 0 && sel.h > 0 && w > 0 && h > 0 ) {
this.addStep({ 'c': sel }, postid, nonce);
// Clear the selection fields after cropping.
$('#imgedit-sel-width-' + postid).val('');
$('#imgedit-sel-height-' + postid).val('');
$('#imgedit-start-x-' + postid).val('0');
$('#imgedit-start-y-' + postid).val('0');
* Undoes an image edit action.
* @param {number} postid The post ID.
* @param {string} nonce The nonce.
* @return {void|false} Returns false if the undo button is disabled.
undo : function (postid, nonce) {
var t = this, button = $('#image-undo-' + postid), elem = $('#imgedit-undone-' + postid),
pop = t.intval( elem.val() ) + 1;
if ( button.hasClass('disabled') ) {
t.refreshEditor(postid, nonce, function() {
var elem = $('#imgedit-history-' + postid),
history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : [];
t.setDisabled($('#image-redo-' + postid), true);
t.setDisabled(button, pop < history.length);
// When undo gets disabled, move focus to the redo button to avoid a focus loss.
if ( history.length === pop ) {
$( '#image-redo-' + postid ).trigger( 'focus' );
* @param {number} postid The post ID.
* @param {string} nonce The nonce.
redo : function(postid, nonce) {
var t = this, button = $('#image-redo-' + postid), elem = $('#imgedit-undone-' + postid),
pop = t.intval( elem.val() ) - 1;
if ( button.hasClass('disabled') ) {
t.refreshEditor(postid, nonce, function() {
t.setDisabled($('#image-undo-' + postid), true);
t.setDisabled(button, pop > 0);
// When redo gets disabled, move focus to the undo button to avoid a focus loss.
$( '#image-undo-' + postid ).trigger( 'focus' );
* Sets the selection for the height and width in pixels.
* @param {number} postid The post ID.
* @param {jQuery} el The element containing the values.
* @return {void|boolean} Returns false when the x or y value is lower than 1,
* void when the value is not numeric or when the operation
setNumSelection : function( postid, el ) {
var sel, elX = $('#imgedit-sel-width-' + postid), elY = $('#imgedit-sel-height-' + postid),
elX1 = $('#imgedit-start-x-' + postid), elY1 = $('#imgedit-start-y-' + postid),
xS = this.intval( elX1.val() ), yS = this.intval( elY1.val() ),
x = this.intval( elX.val() ), y = this.intval( elY.val() ),
img = $('#image-preview-' + postid), imgh = img.height(), imgw = img.width(),
sizer = this.hold.sizer, x1, y1, x2, y2, ias = this.iasapi;
if ( false === this.validateNumeric( el ) ) {
if ( ( ( x && y ) || ( xS && yS ) ) && ( sel = ias.getSelection() ) ) {
x2 = sel.x1 + Math.round( x * sizer );
y2 = sel.y1 + Math.round( y * sizer );
x1 = ( xS === sel.x1 ) ? sel.x1 : Math.round( xS * sizer );
y1 = ( yS === sel.y1 ) ? sel.y1 : Math.round( yS * sizer );
elX.val( Math.round( x2 / sizer ) );
elY.val( Math.round( y2 / sizer ) );
ias.setSelection( x1, y1, x2, y2 );
this.setCropSelection(postid, ias.getSelection());
* Rounds a number to a whole.
* @param {number} num The number.
* @return {number} The number rounded to a whole number.
if ( this.hold.sizer > 0.6 ) {
s = num.toString().slice(-1);
} else if ( '9' === s ) {
* Sets a locked aspect ratio for the selection.
* @param {number} postid The post ID.
* @param {number} n The ratio to set.
* @param {jQuery} el The element containing the values.
setRatioSelection : function(postid, n, el) {
var sel, r, x = this.intval( $('#imgedit-crop-width-' + postid).val() ),
y = this.intval( $('#imgedit-crop-height-' + postid).val() ),
h = $('#image-preview-' + postid).height();
if ( false === this.validateNumeric( el ) ) {
if ( sel = this.iasapi.getSelection(true) ) {
r = Math.ceil( sel.y1 + ( ( sel.x2 - sel.x1 ) / ( x / y ) ) );
var errorMessage = __( 'Selected crop ratio exceeds the boundaries of the image. Try a different ratio.' );
$( '#imgedit-crop-' + postid )
.prepend( '<div class="notice notice-error" tabindex="-1" role="alert"><p>' + errorMessage + '</p></div>' );
wp.a11y.speak( errorMessage, 'assertive' );
$('#imgedit-crop-height-' + postid).val( '' );
$('#imgedit-crop-width-' + postid).val( '');
var error = $( '#imgedit-crop-' + postid ).find( '.notice-error' );
if ( 'undefined' !== typeof( error ) ) {
this.iasapi.setSelection( sel.x1, sel.y1, sel.x2, r );
* Validates if a value in a jQuery.HTMLElement is numeric.
* @param {jQuery} el The html element.
* @return {void|boolean} Returns false if the value is not numeric,
validateNumeric: function( el ) {
if ( false === this.intval( $( el ).val() ) ) {