: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
/* global wp_smush_msgs */
* @since 2.9.0 Moved from admin.js
cacheUpsellErrorCodes: [],
* Convert bytes to human-readable form.
* @param {number} a Bytes
* @param {number} b Number of digits
* @return {*} Formatted Bytes
formatBytes: ( a, b ) => {
units = [ 'KB', 'MB', 'GB', 'TB', 'PB' ];
if ( Math.abs( a ) < thresh ) {
} while ( Math.abs( a ) >= thresh && u < units.length - 1 );
return a.toFixed( b ) + ' ' + units[ u ];
* Get size from a string.
* @param {string} formattedSize Formatter string
* @return {*} Formatted Bytes
getSizeFromString: ( formattedSize ) => {
return formattedSize.replace( /[a-zA-Z]/g, '' ).trim();
* Get type from formatted string.
* @param {string} formattedSize Formatted string
* @return {*} Formatted Bytes
getFormatFromString: ( formattedSize ) => {
return formattedSize.replace( /[0-9.]/g, '' ).trim();
* Stackoverflow: http://stackoverflow.com/questions/1726630/formatting-a-number-with-exactly-two-decimals-in-javascript
* @param {number} decimals
* @return {number} Number
precise_round: ( num, decimals ) => {
const sign = num >= 0 ? 1 : -1;
// Keep the percentage below 100.
num = num > 100 ? 100 : num;
Math.round( num * Math.pow( 10, decimals ) + sign * 0.001 ) /
* Displays a floating error message using the #wp-smush-ajax-notice container.
* @param {string} message
showErrorNotice: ( message ) => {
if ( 'undefined' === typeof message ) {
const noticeMessage = `<p>${ message }</p>`,
SUI.openNotice( 'wp-smush-ajax-notice', noticeMessage, noticeOptions );
const loadingButton = document.querySelector( '.sui-button-onload' );
loadingButton.classList.remove( 'sui-button-onload' );
const _nonce = document.getElementById( 'wp_smush_reset' );
const xhr = new XMLHttpRequest();
xhr.open( 'POST', ajaxurl + '?action=reset_settings', true );
'application/x-www-form-urlencoded'
if ( 200 === xhr.status ) {
const res = JSON.parse( xhr.response );
if ( 'undefined' !== typeof res.success && res.success ) {
window.location.href = wp_smush_msgs.smush_url;
'Request failed. Returned status of ' + xhr.status
xhr.send( '_ajax_nonce=' + _nonce.value );
* Prepare error row. Will only allow to hide errors for WP media attachments (not nextgen).
* @since 3.12.0 Moved from Smush.
* @param {string} errorMsg Error message.
* @param {string} fileName File name.
* @param {string} thumbnail Thumbnail for image (if available).
* @param {number} id Image ID.
* @param {string} type Smush type: media or netxgen.
* @param {string} errorCode Error code.
* @return {string} Row with error.
prepareBulkSmushErrorRow: (errorMsg, fileName, thumbnail, id, type, errorCode) => {
thumbnail && 'undefined' !== typeof thumbnail ?
`<img class="attachment-thumbnail" src="${thumbnail}" />` :
'<i class="sui-icon-photo-picture" aria-hidden="true"></i>';
const editLink = window.wp_smush_msgs.edit_link.replace('{{id}}', id);
'undefined' === fileName || 'undefined' === typeof fileName ?
`<div class="smush-bulk-error-row" data-error-code="${errorCode}">
<div class="smush-bulk-image-data">
<div class="smush-bulk-image-title">
<span class="smush-image-name">
<a href="${editLink}">${fileName}</a>
<div class="smush-image-error">
`<div class="smush-bulk-image-actions">
<a href="javascript:void(0)" class="sui-tooltip sui-tooltip-constrained sui-tooltip-left smush-ignore-image" data-tooltip="${window.wp_smush_msgs.error_ignore}" data-id="${id}">
${window.wp_smush_msgs.btn_ignore}
<a class="smush-link-detail" href="${editLink}">
${window.wp_smush_msgs.view_detail}
tableDiv += WP_Smush.helpers.upsellWithError( errorCode );
cacheUpsellErrorCode( errorCode ) {
this.cacheUpsellErrorCodes.push( errorCode );
* Get upsell base on error code.
* @param {string} errorCode Error code.
upsellWithError(errorCode) {
|| !window.wp_smush_msgs['error_' + errorCode]
|| this.isUpsellRendered( errorCode )
this.cacheRenderedUpsell( errorCode );
return '<div class="smush-bulk-error-row smush-error-upsell">' +
'<div class="smush-bulk-image-title">' +
'<span class="smush-image-error">' +
window.wp_smush_msgs['error_' + errorCode] +
// Do not use arrow function to use `this`.
isUpsellRendered( errorCode ) {
return this.cacheUpsellErrorCodes.includes( errorCode );
// Do not use arrow function to use `this`.
cacheRenderedUpsell( errorCode ) {
this.cacheUpsellErrorCodes.push( errorCode );
* Get error message from Ajax response or Error.
getErrorMessage: ( resp ) => {
return resp.message || resp.data && resp.data.message ||
resp.responseJSON && resp.responseJSON.data && resp.responseJSON.data.message ||
window.wp_smush_msgs.generic_ajax_error ||
resp.status && 'Request failed. Returned status of ' + resp.status
* Displays a floating message from response,
* using the #wp-smush-ajax-notice container.
* @param {Object|string} notice
* @param {Object} noticeOptions
showNotice: function( notice, noticeOptions ) {
if ( 'object' === typeof notice ) {
message = this.getErrorMessage( notice );
noticeOptions = noticeOptions || {};
noticeOptions = Object.assign({
type: noticeOptions.type || 'error',
icon: noticeOptions.icon || ( 'success' === noticeOptions.type ? 'check-tick' : 'info' ),
show: noticeOptions.showdismiss,
label: window.wp_smush_msgs.noticeDismiss,
tooltip: window.wp_smush_msgs.noticeDismissTooltip,
show: noticeOptions.autoclose
const noticeMessage = `<p>${ message }</p>`;
SUI.openNotice( 'wp-smush-ajax-notice', noticeMessage, noticeOptions );
return Promise.resolve( '#wp-smush-ajax-notice' );
window.SUI.closeNotice( 'wp-smush-ajax-notice' );
renderActivationCDNNotice: function( noticeMessage ) {
const animatedNotice = document.getElementById('wp-smush-animated-upsell-notice');
const upsellHtml = `<div class="sui-notice sui-notice-info sui-margin-top" id="wp-smush-animated-upsell-notice">
<div class="sui-notice-content">
<div class="sui-notice-message">
<i class="sui-notice-icon sui-icon-info" aria-hidden="true"></i>
document.querySelector( '#smush-box-bulk .wp-smush-bulk-wrapper' ).outerHTML += upsellHtml;
page = `page=smush-${page}`;
if ( window.location.href.includes( page ) ) {
window.location.reload();
window.location.search = page;
const focusAfterClosed = 'wpbody-content',
focusWhenOpen = undefined,