Merged in feature/from-pantheon (pull request #16)
code from pantheon * code from pantheon
This commit is contained in:
37
wp/wp-content/plugins/imagify/assets/js/admin-bar.js
Normal file
37
wp/wp-content/plugins/imagify/assets/js/admin-bar.js
Normal file
@@ -0,0 +1,37 @@
|
||||
// Admin bar =======================================================================================
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
var busy = false;
|
||||
|
||||
$( d ).on( 'mouseenter', '#wp-admin-bar-imagify', function() {
|
||||
var $adminBarProfile, url;
|
||||
|
||||
if ( true === busy ) {
|
||||
return;
|
||||
}
|
||||
|
||||
busy = true;
|
||||
|
||||
$adminBarProfile = $( '#wp-admin-bar-imagify-profile-content' );
|
||||
|
||||
if ( ! $adminBarProfile.is( ':empty' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( w.ajaxurl ) {
|
||||
url = w.ajaxurl;
|
||||
} else {
|
||||
url = w.imagifyAdminBar.ajaxurl;
|
||||
}
|
||||
|
||||
url += url.indexOf( '?' ) > 0 ? '&' : '?';
|
||||
|
||||
$.get( url + 'action=imagify_get_admin_bar_profile&imagifygetadminbarprofilenonce=' + $( '#imagifygetadminbarprofilenonce' ).val() )
|
||||
.done( function( response ) {
|
||||
$adminBarProfile.html( response.data );
|
||||
$( '#wp-admin-bar-imagify-profile-loading' ).remove();
|
||||
busy = false;
|
||||
} );
|
||||
} );
|
||||
|
||||
} )(jQuery, document, window);
|
||||
1
wp/wp-content/plugins/imagify/assets/js/admin-bar.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/admin-bar.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(n,i,e){var m=!1;n(i).on("mouseenter","#wp-admin-bar-imagify",function(){var a,i;!0!==m&&(m=!0,(a=n("#wp-admin-bar-imagify-profile-content")).is(":empty"))&&(i=e.ajaxurl||e.imagifyAdminBar.ajaxurl,i+=0<i.indexOf("?")?"&":"?",n.get(i+"action=imagify_get_admin_bar_profile&imagifygetadminbarprofilenonce="+n("#imagifygetadminbarprofilenonce").val()).done(function(i){a.html(i.data),n("#wp-admin-bar-imagify-profile-loading").remove(),m=!1}))})}(jQuery,document,window);
|
||||
103
wp/wp-content/plugins/imagify/assets/js/admin.js
Normal file
103
wp/wp-content/plugins/imagify/assets/js/admin.js
Normal file
@@ -0,0 +1,103 @@
|
||||
window.imagify = window.imagify || {};
|
||||
|
||||
jQuery.extend( window.imagify, {
|
||||
concat: ajaxurl.indexOf( '?' ) > 0 ? '&' : '?',
|
||||
log: function( content ) {
|
||||
if ( undefined !== console ) {
|
||||
console.log( content ); // eslint-disable-line no-console
|
||||
}
|
||||
},
|
||||
info: function( content ) {
|
||||
if ( undefined !== console ) {
|
||||
console.info( content ); // eslint-disable-line no-console
|
||||
}
|
||||
},
|
||||
openModal: function( $link ) {
|
||||
var target = $link.data( 'target' ) || $link.attr( 'href' );
|
||||
|
||||
jQuery( target ).css( 'display', 'flex' ).hide().fadeIn( 400 ).attr( {
|
||||
'aria-hidden': 'false',
|
||||
'tabindex': '0'
|
||||
} ).trigger('focus').removeAttr( 'tabindex' ).addClass( 'modal-is-open' );
|
||||
|
||||
jQuery( 'body' ).addClass( 'imagify-modal-is-open' );
|
||||
},
|
||||
template: function( id ) {
|
||||
if ( undefined === _ ) {
|
||||
// No need to load underscore everywhere if we don't use it.
|
||||
return '';
|
||||
}
|
||||
|
||||
return _.memoize( function( data ) {
|
||||
var compiled,
|
||||
options = {
|
||||
evaluate: /<#([\s\S]+?)#>/g,
|
||||
interpolate: /\{\{\{([\s\S]+?)\}\}\}/g,
|
||||
escape: /\{\{([^}]+?)\}\}(?!\})/g,
|
||||
variable: 'data'
|
||||
};
|
||||
|
||||
return function() {
|
||||
compiled = compiled || _.template( jQuery( '#tmpl-' + id ).html(), null, options );
|
||||
data = data || {};
|
||||
return compiled( data );
|
||||
};
|
||||
} );
|
||||
},
|
||||
humanSize: function( bytes ) {
|
||||
var sizes = ['B', 'kB', 'MB'],
|
||||
i;
|
||||
|
||||
if ( 0 === bytes ) {
|
||||
return '0\xA0kB';
|
||||
}
|
||||
|
||||
i = parseInt( Math.floor( Math.log( bytes ) / Math.log( 1024 ) ), 10 );
|
||||
|
||||
return ( bytes / Math.pow( 1024, i ) ).toFixed( 2 ) + '\xA0' + sizes[ i ];
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
// Imagify light modal =============================================================================
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
// Accessibility.
|
||||
$( '.imagify-modal' ).attr( 'aria-hidden', 'true' );
|
||||
|
||||
$( d )
|
||||
// On click on modal trigger, open modal.
|
||||
.on( 'click.imagify', '.imagify-modal-trigger', function( e ) {
|
||||
e.preventDefault();
|
||||
w.imagify.openModal( $( this ) );
|
||||
} )
|
||||
// On click on close button, close modal.
|
||||
.on( 'click.imagify', '.imagify-modal .close-btn', function() {
|
||||
var $modal = $( this ).closest( '.imagify-modal' );
|
||||
|
||||
$modal.fadeOut( 400 ).attr( 'aria-hidden', 'true' ).removeClass( 'modal-is-open' ).trigger( 'modalClosed.imagify' );
|
||||
|
||||
$( 'body' ).removeClass( 'imagify-modal-is-open' );
|
||||
} )
|
||||
// On close button blur, improve accessibility.
|
||||
.on( 'blur.imagify', '.imagify-modal .close-btn', function() {
|
||||
var $modal = $( this ).closest( '.imagify-modal' );
|
||||
|
||||
if ( $modal.attr( 'aria-hidden' ) === 'false' ) {
|
||||
$modal.attr( 'tabindex', '0' ).trigger('focus').removeAttr( 'tabindex' );
|
||||
}
|
||||
} )
|
||||
// On click on dropped layer of modal, close modal.
|
||||
.on( 'click.imagify', '.imagify-modal', function( e ) {
|
||||
$( e.target ).filter( '.modal-is-open' ).find( '.close-btn' ).trigger( 'click.imagify' );
|
||||
} )
|
||||
// `Esc` key binding, close modal.
|
||||
.on( 'keydown.imagify', function( e ) {
|
||||
if ( 27 === e.keyCode && $( '.imagify-modal.modal-is-open' ).length > 0 ) {
|
||||
e.preventDefault();
|
||||
// Trigger the event.
|
||||
$( '.imagify-modal.modal-is-open' ).find( '.close-btn' ).trigger( 'click.imagify' );
|
||||
}
|
||||
} );
|
||||
|
||||
} )(jQuery, document, window);
|
||||
1
wp/wp-content/plugins/imagify/assets/js/admin.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/admin.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
window.imagify=window.imagify||{},jQuery.extend(window.imagify,{concat:0<ajaxurl.indexOf("?")?"&":"?",log:function(i){void 0!==console&&console.log(i)},info:function(i){void 0!==console&&console.info(i)},openModal:function(i){i=i.data("target")||i.attr("href");jQuery(i).css("display","flex").hide().fadeIn(400).attr({"aria-hidden":"false",tabindex:"0"}).trigger("focus").removeAttr("tabindex").addClass("modal-is-open"),jQuery("body").addClass("imagify-modal-is-open")},template:function(o){return void 0===_?"":_.memoize(function(i){var a,e={evaluate:/<#([\s\S]+?)#>/g,interpolate:/\{\{\{([\s\S]+?)\}\}\}/g,escape:/\{\{([^}]+?)\}\}(?!\})/g,variable:"data"};return function(){return(a=a||_.template(jQuery("#tmpl-"+o).html(),null,e))(i=i||{})}})},humanSize:function(i){var a;return 0===i?"0 kB":(a=parseInt(Math.floor(Math.log(i)/Math.log(1024)),10),(i/Math.pow(1024,a)).toFixed(2)+" "+["B","kB","MB"][a])}}),function(a,i,e){a(".imagify-modal").attr("aria-hidden","true"),a(i).on("click.imagify",".imagify-modal-trigger",function(i){i.preventDefault(),e.imagify.openModal(a(this))}).on("click.imagify",".imagify-modal .close-btn",function(){a(this).closest(".imagify-modal").fadeOut(400).attr("aria-hidden","true").removeClass("modal-is-open").trigger("modalClosed.imagify"),a("body").removeClass("imagify-modal-is-open")}).on("blur.imagify",".imagify-modal .close-btn",function(){var i=a(this).closest(".imagify-modal");"false"===i.attr("aria-hidden")&&i.attr("tabindex","0").trigger("focus").removeAttr("tabindex")}).on("click.imagify",".imagify-modal",function(i){a(i.target).filter(".modal-is-open").find(".close-btn").trigger("click.imagify")}).on("keydown.imagify",function(i){27===i.keyCode&&0<a(".imagify-modal.modal-is-open").length&&(i.preventDefault(),a(".imagify-modal.modal-is-open").find(".close-btn").trigger("click.imagify"))})}(jQuery,document,window);
|
||||
872
wp/wp-content/plugins/imagify/assets/js/beat.js
Normal file
872
wp/wp-content/plugins/imagify/assets/js/beat.js
Normal file
@@ -0,0 +1,872 @@
|
||||
/**
|
||||
* Imagify beat API
|
||||
*
|
||||
* This is a modified version of WordPress’ Heartbeat (WP 5.2.1).
|
||||
* The main difference is that it allows to prevent suspension entirely.
|
||||
* It uses the var imagifybeatSettings on init.
|
||||
*
|
||||
* Custom jQuery events:
|
||||
* - imagifybeat-send
|
||||
* - imagifybeat-tick
|
||||
* - imagifybeat-error
|
||||
* - imagifybeat-connection-lost
|
||||
* - imagifybeat-connection-restored
|
||||
* - imagifybeat-nonces-expired
|
||||
*
|
||||
* @since 1.9.3
|
||||
*/
|
||||
|
||||
window.imagify = window.imagify || {};
|
||||
|
||||
/* eslint-disable no-use-before-define */
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
/**
|
||||
* Constructs the Imagifybeat API.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @constructor
|
||||
*
|
||||
* @return {Imagifybeat} An instance of the Imagifybeat class.
|
||||
*/
|
||||
var Imagifybeat = function() {
|
||||
var $document = $( d ),
|
||||
settings = {
|
||||
// Suspend/resume.
|
||||
suspend: false,
|
||||
|
||||
// Whether suspending is enabled.
|
||||
suspendEnabled: true,
|
||||
|
||||
// Current screen id, defaults to the JS global 'pagenow' when present
|
||||
// (in the admin) or 'front'.
|
||||
screenId: '',
|
||||
|
||||
// XHR request URL, defaults to the JS global 'ajaxurl' when present.
|
||||
url: '',
|
||||
|
||||
// Timestamp, start of the last connection request.
|
||||
lastTick: 0,
|
||||
|
||||
// Container for the enqueued items.
|
||||
queue: {},
|
||||
|
||||
// Connect interval (in seconds).
|
||||
mainInterval: 60,
|
||||
|
||||
// Used when the interval is set to 5 sec. temporarily.
|
||||
tempInterval: 0,
|
||||
|
||||
// Used when the interval is reset.
|
||||
originalInterval: 0,
|
||||
|
||||
// Used to limit the number of AJAX requests.
|
||||
minimalInterval: 0,
|
||||
|
||||
// Used together with tempInterval.
|
||||
countdown: 0,
|
||||
|
||||
// Whether a connection is currently in progress.
|
||||
connecting: false,
|
||||
|
||||
// Whether a connection error occurred.
|
||||
connectionError: false,
|
||||
|
||||
// Used to track non-critical errors.
|
||||
errorcount: 0,
|
||||
|
||||
// Whether at least one connection has been completed successfully.
|
||||
hasConnected: false,
|
||||
|
||||
// Whether the current browser w is in focus and the user is active.
|
||||
hasFocus: true,
|
||||
|
||||
// Timestamp, last time the user was active. Checked every 30 sec.
|
||||
userActivity: 0,
|
||||
|
||||
// Flag whether events tracking user activity were set.
|
||||
userActivityEvents: false,
|
||||
|
||||
// Timer that keeps track of how long a user has focus.
|
||||
checkFocusTimer: 0,
|
||||
|
||||
// Timer that keeps track of how long needs to be waited before connecting to
|
||||
// the server again.
|
||||
beatTimer: 0
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets local variables and events, then starts the beat.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function initialize() {
|
||||
var options, hidden, visibilityState, visibilitychange;
|
||||
|
||||
if ( typeof w.pagenow === 'string' ) {
|
||||
settings.screenId = w.pagenow;
|
||||
}
|
||||
|
||||
if ( typeof w.ajaxurl === 'string' ) {
|
||||
settings.url = w.ajaxurl;
|
||||
}
|
||||
|
||||
// Pull in options passed from PHP.
|
||||
if ( typeof w.imagifybeatSettings === 'object' ) {
|
||||
options = w.imagifybeatSettings;
|
||||
|
||||
// The XHR URL can be passed as option when w.ajaxurl is not set.
|
||||
if ( ! settings.url && options.ajaxurl ) {
|
||||
settings.url = options.ajaxurl;
|
||||
}
|
||||
|
||||
/*
|
||||
* The interval can be from 15 to 120 sec. and can be set temporarily to 5 sec.
|
||||
* It can be set in the initial options or changed later through JS and/or
|
||||
* through PHP.
|
||||
*/
|
||||
if ( options.interval ) {
|
||||
settings.mainInterval = options.interval;
|
||||
|
||||
if ( settings.mainInterval < 15 ) {
|
||||
settings.mainInterval = 15;
|
||||
} else if ( settings.mainInterval > 120 ) {
|
||||
settings.mainInterval = 120;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to limit the number of AJAX requests. Overrides all other intervals if
|
||||
* they are shorter. Needed for some hosts that cannot handle frequent requests
|
||||
* and the user may exceed the allocated server CPU time, etc. The minimal
|
||||
* interval can be up to 600 sec. however setting it to longer than 120 sec.
|
||||
* will limit or disable some of the functionality (like post locks). Once set
|
||||
* at initialization, minimalInterval cannot be changed/overridden.
|
||||
*/
|
||||
if ( options.minimalInterval ) {
|
||||
options.minimalInterval = parseInt( options.minimalInterval, 10 );
|
||||
settings.minimalInterval = options.minimalInterval > 0 && options.minimalInterval <= 600 ? options.minimalInterval * 1000 : 0;
|
||||
}
|
||||
|
||||
if ( settings.minimalInterval && settings.mainInterval < settings.minimalInterval ) {
|
||||
settings.mainInterval = settings.minimalInterval;
|
||||
}
|
||||
|
||||
// 'screenId' can be added from settings on the front end where the JS global
|
||||
// 'pagenow' is not set.
|
||||
if ( ! settings.screenId ) {
|
||||
settings.screenId = options.screenId || 'front';
|
||||
}
|
||||
|
||||
if ( 'disable' === options.suspension ) {
|
||||
disableSuspend();
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to milliseconds.
|
||||
settings.mainInterval = settings.mainInterval * 1000;
|
||||
settings.originalInterval = settings.mainInterval;
|
||||
|
||||
/*
|
||||
* Switch the interval to 120 seconds by using the Page Visibility API.
|
||||
* If the browser doesn't support it (Safari < 7, Android < 4.4, IE < 10), the
|
||||
* interval will be increased to 120 seconds after 5 minutes of mouse and keyboard
|
||||
* inactivity.
|
||||
*/
|
||||
if ( typeof document.hidden !== 'undefined' ) {
|
||||
hidden = 'hidden';
|
||||
visibilitychange = 'visibilitychange';
|
||||
visibilityState = 'visibilityState';
|
||||
} else if ( typeof document.msHidden !== 'undefined' ) { // IE10
|
||||
hidden = 'msHidden';
|
||||
visibilitychange = 'msvisibilitychange';
|
||||
visibilityState = 'msVisibilityState';
|
||||
} else if ( typeof document.webkitHidden !== 'undefined' ) { // Android
|
||||
hidden = 'webkitHidden';
|
||||
visibilitychange = 'webkitvisibilitychange';
|
||||
visibilityState = 'webkitVisibilityState';
|
||||
}
|
||||
|
||||
if ( hidden ) {
|
||||
if ( document[ hidden ] ) {
|
||||
settings.hasFocus = false;
|
||||
}
|
||||
|
||||
$document.on( visibilitychange + '.imagifybeat', function() {
|
||||
if ( 'hidden' === document[ visibilityState ] ) {
|
||||
blurred();
|
||||
w.clearInterval( settings.checkFocusTimer );
|
||||
} else {
|
||||
focused();
|
||||
if ( document.hasFocus ) {
|
||||
settings.checkFocusTimer = w.setInterval( checkFocus, 10000 );
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Use document.hasFocus() if available.
|
||||
if ( document.hasFocus ) {
|
||||
settings.checkFocusTimer = w.setInterval( checkFocus, 10000 );
|
||||
}
|
||||
|
||||
$( w ).on( 'unload.imagifybeat', function() {
|
||||
// Don't connect anymore.
|
||||
settings.suspend = true;
|
||||
|
||||
// Abort the last request if not completed.
|
||||
if ( settings.xhr && 4 !== settings.xhr.readyState ) {
|
||||
settings.xhr.abort();
|
||||
}
|
||||
} );
|
||||
|
||||
// Check for user activity every 30 seconds.
|
||||
w.setInterval( checkUserActivity, 30000 );
|
||||
|
||||
// Start one tick after DOM ready.
|
||||
$document.ready( function() {
|
||||
settings.lastTick = time();
|
||||
scheduleNextTick();
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current time according to the browser.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @return {int} Returns the current time.
|
||||
*/
|
||||
function time() {
|
||||
return (new Date()).getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the iframe is from the same origin.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @return {bool} Returns whether or not the iframe is from the same origin.
|
||||
*/
|
||||
function isLocalFrame( frame ) {
|
||||
var origin, src = frame.src; // eslint-disable-line no-shadow
|
||||
|
||||
/*
|
||||
* Need to compare strings as WebKit doesn't throw JS errors when iframes have different origin. It throws uncatchable exceptions.
|
||||
*/
|
||||
if ( src && /^https?:\/\//.test( src ) ) {
|
||||
origin = w.location.origin ? w.location.origin : w.location.protocol + '//' + w.location.host;
|
||||
|
||||
if ( src.indexOf( origin ) !== 0 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if ( frame.contentWindow.document ) {
|
||||
return true;
|
||||
}
|
||||
} catch ( e ) {} // eslint-disable-line no-empty
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the document's focus has changed.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function checkFocus() {
|
||||
if ( settings.hasFocus && ! document.hasFocus() ) {
|
||||
blurred();
|
||||
} else if ( ! settings.hasFocus && document.hasFocus() ) {
|
||||
focused();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets error state and fires an event on XHR errors or timeout.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @param {string} error The error type passed from the XHR.
|
||||
* @param {int} httpStatus The HTTP status code passed from jqXHR (200, 404, 500, etc.).
|
||||
* @return {void}
|
||||
*/
|
||||
function setErrorState( error, httpStatus ) {
|
||||
var trigger;
|
||||
|
||||
if ( error ) {
|
||||
switch ( error ) {
|
||||
case 'abort':
|
||||
// Do nothing.
|
||||
break;
|
||||
case 'timeout':
|
||||
// No response for 30 sec.
|
||||
trigger = true;
|
||||
break;
|
||||
case 'error':
|
||||
if ( 503 === httpStatus && settings.hasConnected ) {
|
||||
trigger = true;
|
||||
break;
|
||||
}
|
||||
/* falls through */
|
||||
case 'parsererror':
|
||||
case 'empty':
|
||||
case 'unknown':
|
||||
settings.errorcount++;
|
||||
|
||||
if ( settings.errorcount > 2 && settings.hasConnected ) {
|
||||
trigger = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ( trigger && ! hasConnectionError() ) {
|
||||
settings.connectionError = true;
|
||||
$document.trigger( 'imagifybeat-connection-lost', [ error, httpStatus ] );
|
||||
|
||||
if ( w.wp.hooks ) {
|
||||
w.wp.hooks.doAction( 'imagifybeat.connection-lost', error, httpStatus );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the error state and fires an event if there is a connection error.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function clearErrorState() {
|
||||
// Has connected successfully.
|
||||
settings.hasConnected = true;
|
||||
|
||||
if ( hasConnectionError() ) {
|
||||
settings.errorcount = 0;
|
||||
settings.connectionError = false;
|
||||
$document.trigger( 'imagifybeat-connection-restored' );
|
||||
|
||||
if ( w.wp.hooks ) {
|
||||
w.wp.hooks.doAction( 'imagifybeat.connection-restored' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gathers the data and connects to the server.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function connect() {
|
||||
var ajaxData, imagifybeatData;
|
||||
|
||||
// If the connection to the server is slower than the interval,
|
||||
// imagifybeat connects as soon as the previous connection's response is received.
|
||||
if ( settings.connecting || settings.suspend ) {
|
||||
return;
|
||||
}
|
||||
|
||||
settings.lastTick = time();
|
||||
|
||||
imagifybeatData = $.extend( {}, settings.queue );
|
||||
// Clear the data queue. Anything added after this point will be sent on the next tick.
|
||||
settings.queue = {};
|
||||
|
||||
$document.trigger( 'imagifybeat-send', [ imagifybeatData ] );
|
||||
|
||||
if ( w.wp.hooks ) {
|
||||
w.wp.hooks.doAction( 'imagifybeat.send', imagifybeatData );
|
||||
}
|
||||
|
||||
ajaxData = {
|
||||
data: imagifybeatData,
|
||||
interval: settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000,
|
||||
_nonce: typeof w.imagifybeatSettings === 'object' ? w.imagifybeatSettings.nonce : '',
|
||||
action: 'imagifybeat',
|
||||
screen_id: settings.screenId,
|
||||
has_focus: settings.hasFocus
|
||||
};
|
||||
|
||||
if ( 'customize' === settings.screenId ) {
|
||||
ajaxData.wp_customize = 'on';
|
||||
}
|
||||
|
||||
settings.connecting = true;
|
||||
settings.xhr = $.ajax( {
|
||||
url: settings.url,
|
||||
type: 'post',
|
||||
timeout: 60000, // Throw an error if not completed after 60 sec.
|
||||
data: ajaxData,
|
||||
dataType: 'json'
|
||||
} ).always( function() {
|
||||
settings.connecting = false;
|
||||
scheduleNextTick();
|
||||
} ).done( function( response, textStatus, jqXHR ) {
|
||||
var newInterval;
|
||||
|
||||
if ( ! response ) {
|
||||
setErrorState( 'empty' );
|
||||
return;
|
||||
}
|
||||
|
||||
clearErrorState();
|
||||
|
||||
if ( response.nonces_expired ) {
|
||||
$document.trigger( 'imagifybeat-nonces-expired' );
|
||||
|
||||
if ( w.wp.hooks ) {
|
||||
w.wp.hooks.doAction( 'imagifybeat.nonces-expired' );
|
||||
}
|
||||
}
|
||||
|
||||
// Change the interval from PHP
|
||||
if ( response.imagifybeat_interval ) {
|
||||
newInterval = response.imagifybeat_interval;
|
||||
delete response.imagifybeat_interval;
|
||||
}
|
||||
|
||||
// Update the imagifybeat nonce if set.
|
||||
if ( response.imagifybeat_nonce && typeof w.imagifybeatSettings === 'object' ) {
|
||||
w.imagifybeatSettings.nonce = response.imagifybeat_nonce;
|
||||
delete response.imagifybeat_nonce;
|
||||
}
|
||||
|
||||
$document.trigger( 'imagifybeat-tick', [ response, textStatus, jqXHR ] );
|
||||
|
||||
if ( w.wp.hooks ) {
|
||||
w.wp.hooks.doAction( 'imagifybeat.tick', response, textStatus, jqXHR );
|
||||
}
|
||||
|
||||
// Do this last. Can trigger the next XHR if connection time > 5 sec. and newInterval == 'fast'.
|
||||
if ( newInterval ) {
|
||||
interval( newInterval );
|
||||
}
|
||||
} ).fail( function( jqXHR, textStatus, error ) {
|
||||
setErrorState( textStatus || 'unknown', jqXHR.status );
|
||||
$document.trigger( 'imagifybeat-error', [ jqXHR, textStatus, error ] );
|
||||
|
||||
if ( w.wp.hooks ) {
|
||||
w.wp.hooks.doAction( 'imagifybeat.error', jqXHR, textStatus, error );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the next connection.
|
||||
*
|
||||
* Fires immediately if the connection time is longer than the interval.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function scheduleNextTick() {
|
||||
var delta = time() - settings.lastTick,
|
||||
interv = settings.mainInterval;
|
||||
|
||||
if ( settings.suspend ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! settings.hasFocus && settings.suspendEnabled ) {
|
||||
// When no user activity or the window lost focus, increase polling interval to 120 seconds, but only if suspend is enabled.
|
||||
interv = 120000; // 120 sec.
|
||||
} else if ( settings.countdown > 0 && settings.tempInterval ) {
|
||||
interv = settings.tempInterval;
|
||||
settings.countdown--;
|
||||
|
||||
if ( settings.countdown < 1 ) {
|
||||
settings.tempInterval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( settings.minimalInterval && interv < settings.minimalInterval ) {
|
||||
interv = settings.minimalInterval;
|
||||
}
|
||||
|
||||
w.clearTimeout( settings.beatTimer );
|
||||
|
||||
if ( delta < interv ) {
|
||||
settings.beatTimer = w.setTimeout(
|
||||
function() {
|
||||
connect();
|
||||
},
|
||||
interv - delta
|
||||
);
|
||||
} else {
|
||||
connect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal state when the browser w becomes hidden or loses focus.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function blurred() {
|
||||
settings.hasFocus = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal state when the browser w becomes visible or is in focus.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function focused() {
|
||||
settings.userActivity = time();
|
||||
|
||||
// Resume if suspended
|
||||
settings.suspend = false;
|
||||
|
||||
if ( ! settings.hasFocus ) {
|
||||
settings.hasFocus = true;
|
||||
scheduleNextTick();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs when the user becomes active after a period of inactivity.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function userIsActive() {
|
||||
settings.userActivityEvents = false;
|
||||
$document.off( '.imagifybeat-active' );
|
||||
|
||||
$( 'iframe' ).each( function( i, frame ) {
|
||||
if ( isLocalFrame( frame ) ) {
|
||||
$( frame.contentWindow ).off( '.imagifybeat-active' );
|
||||
}
|
||||
} );
|
||||
|
||||
focused();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for user activity.
|
||||
*
|
||||
* Runs every 30 sec. Sets 'hasFocus = true' if user is active and the w is
|
||||
* in the background. Sets 'hasFocus = false' if the user has been inactive
|
||||
* (no mouse or keyboard activity) for 5 min. even when the w has focus.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @access private
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function checkUserActivity() {
|
||||
var lastActive = settings.userActivity ? time() - settings.userActivity : 0;
|
||||
|
||||
// Set hasFocus to false when no mouse or keyboard activity for 5 min.
|
||||
if ( lastActive > 300000 && settings.hasFocus ) {
|
||||
blurred();
|
||||
}
|
||||
|
||||
// Suspend after 10 min. of inactivity.
|
||||
if ( settings.suspendEnabled && lastActive > 600000 ) {
|
||||
settings.suspend = true;
|
||||
}
|
||||
|
||||
if ( ! settings.userActivityEvents ) {
|
||||
$document.on( 'mouseover.imagifybeat-active keyup.imagifybeat-active touchend.imagifybeat-active', function() {
|
||||
userIsActive();
|
||||
} );
|
||||
|
||||
$( 'iframe' ).each( function( i, frame ) {
|
||||
if ( isLocalFrame( frame ) ) {
|
||||
$( frame.contentWindow ).on( 'mouseover.imagifybeat-active keyup.imagifybeat-active touchend.imagifybeat-active', function() {
|
||||
userIsActive();
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
settings.userActivityEvents = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Public methods.
|
||||
|
||||
/**
|
||||
* Checks whether the w (or any local iframe in it) has focus, or the user
|
||||
* is active.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @memberOf imagify.beat.prototype
|
||||
*
|
||||
* @return {bool} True if the w or the user is active.
|
||||
*/
|
||||
function hasFocus() {
|
||||
return settings.hasFocus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there is a connection error.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @memberOf imagify.beat.prototype
|
||||
*
|
||||
* @return {bool} True if a connection error was found.
|
||||
*/
|
||||
function hasConnectionError() {
|
||||
return settings.connectionError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects as soon as possible regardless of 'hasFocus' state.
|
||||
*
|
||||
* Will not open two concurrent connections. If a connection is in progress,
|
||||
* will connect again immediately after the current connection completes.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @memberOf imagify.beat.prototype
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function connectNow() {
|
||||
settings.lastTick = 0;
|
||||
scheduleNextTick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables suspending.
|
||||
*
|
||||
* Should be used only when Imagifybeat is performing critical tasks like
|
||||
* autosave, post-locking, etc. Using this on many screens may overload the
|
||||
* user's hosting account if several browser ws/tabs are left open for a
|
||||
* long time.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @memberOf imagify.beat.prototype
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function disableSuspend() {
|
||||
settings.suspendEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables suspending.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @memberOf imagify.beat.prototype
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function enableSuspend() {
|
||||
settings.suspendEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets/Sets the interval.
|
||||
*
|
||||
* When setting to 'fast' or 5, the interval is 5 seconds for the next 30 ticks
|
||||
* (for 2 minutes and 30 seconds) by default. In this case the number of 'ticks'
|
||||
* can be passed as second argument. If the window doesn't have focus, the
|
||||
* interval slows down to 2 min.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @memberOf imagify.beat.prototype
|
||||
*
|
||||
* @param {string|int} speed Interval: 'fast' or 5, 15, 30, 60, 120. Fast equals 5.
|
||||
* @param {string} ticks Tells how many ticks before the interval reverts back. Used with speed = 'fast' or 5.
|
||||
* @return {int} Current interval in seconds.
|
||||
*/
|
||||
function interval( speed, ticks ) {
|
||||
var newInterval,
|
||||
oldInterval = settings.tempInterval ? settings.tempInterval : settings.mainInterval;
|
||||
|
||||
if ( speed ) {
|
||||
switch ( speed ) {
|
||||
case 'fast':
|
||||
case 5:
|
||||
newInterval = 5000;
|
||||
break;
|
||||
case 15:
|
||||
newInterval = 15000;
|
||||
break;
|
||||
case 30:
|
||||
newInterval = 30000;
|
||||
break;
|
||||
case 60:
|
||||
newInterval = 60000;
|
||||
break;
|
||||
case 120:
|
||||
newInterval = 120000;
|
||||
break;
|
||||
case 'long-polling':
|
||||
// Allow long polling, (experimental)
|
||||
settings.mainInterval = 0;
|
||||
return 0;
|
||||
default:
|
||||
newInterval = settings.originalInterval;
|
||||
}
|
||||
|
||||
if ( settings.minimalInterval && newInterval < settings.minimalInterval ) {
|
||||
newInterval = settings.minimalInterval;
|
||||
}
|
||||
|
||||
if ( 5000 === newInterval ) {
|
||||
ticks = parseInt( ticks, 10 ) || 30;
|
||||
ticks = ticks < 1 || ticks > 30 ? 30 : ticks;
|
||||
|
||||
settings.countdown = ticks;
|
||||
settings.tempInterval = newInterval;
|
||||
} else {
|
||||
settings.countdown = 0;
|
||||
settings.tempInterval = 0;
|
||||
settings.mainInterval = newInterval;
|
||||
}
|
||||
|
||||
// Change the next connection time if new interval has been set.
|
||||
// Will connect immediately if the time since the last connection
|
||||
// is greater than the new interval.
|
||||
if ( newInterval !== oldInterval ) {
|
||||
scheduleNextTick();
|
||||
}
|
||||
}
|
||||
|
||||
return settings.tempInterval ? settings.tempInterval / 1000 : settings.mainInterval / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the interval.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @memberOf imagify.beat.prototype
|
||||
*
|
||||
* @return {int} Current interval in seconds.
|
||||
*/
|
||||
function resetInterval() {
|
||||
return interval( settings.originalInterval );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues data to send with the next XHR.
|
||||
*
|
||||
* As the data is send asynchronously, this function doesn't return the XHR
|
||||
* response. To see the response, use the custom jQuery event 'imagifybeat-tick'
|
||||
* on the document, example:
|
||||
* $(document).on( 'imagifybeat-tick.myname', function( event, data, textStatus, jqXHR ) {
|
||||
* // code
|
||||
* });
|
||||
* If the same 'handle' is used more than once, the data is not overwritten when
|
||||
* the third argument is 'true'. Use `imagify.beat.isQueued('handle')` to see if
|
||||
* any data is already queued for that handle.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @memberOf imagify.beat.prototype
|
||||
*
|
||||
* @param {string} handle Unique handle for the data, used in PHP to receive the data.
|
||||
* @param {mixed} data The data to send.
|
||||
* @param {bool} noOverwrite Whether to overwrite existing data in the queue.
|
||||
* @return {bool} True if the data was queued.
|
||||
*/
|
||||
function enqueue( handle, data, noOverwrite ) {
|
||||
if ( handle ) {
|
||||
if ( noOverwrite && this.isQueued( handle ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
settings.queue[handle] = data;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if data with a particular handle is queued.
|
||||
*
|
||||
* @since 1.9.3
|
||||
*
|
||||
* @param {string} handle The handle for the data.
|
||||
* @return {bool} True if the data is queued with this handle.
|
||||
*/
|
||||
function isQueued( handle ) {
|
||||
if ( handle ) {
|
||||
return Object.prototype.hasOwnProperty.call( settings.queue, handle );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes data with a particular handle from the queue.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @memberOf imagify.beat.prototype
|
||||
*
|
||||
* @param {string} handle The handle for the data.
|
||||
*/
|
||||
function dequeue( handle ) {
|
||||
if ( handle ) {
|
||||
delete settings.queue[handle];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data that was enqueued with a particular handle.
|
||||
*
|
||||
* @since 1.9.3
|
||||
* @memberOf imagify.beat.prototype
|
||||
*
|
||||
* @param {string} handle The handle for the data.
|
||||
* @return {mixed} The data or undefined.
|
||||
*/
|
||||
function getQueuedItem( handle ) {
|
||||
if ( handle ) {
|
||||
return this.isQueued( handle ) ? settings.queue[ handle ] : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
initialize();
|
||||
|
||||
// Expose public methods.
|
||||
return {
|
||||
hasFocus: hasFocus,
|
||||
connectNow: connectNow,
|
||||
disableSuspend: disableSuspend,
|
||||
enableSuspend: enableSuspend,
|
||||
interval: interval,
|
||||
resetInterval: resetInterval,
|
||||
hasConnectionError: hasConnectionError,
|
||||
enqueue: enqueue,
|
||||
dequeue: dequeue,
|
||||
isQueued: isQueued,
|
||||
getQueuedItem: getQueuedItem
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains the Imagifybeat API.
|
||||
*
|
||||
* @namespace imagify.beat
|
||||
* @type {Imagifybeat}
|
||||
*/
|
||||
w.imagify.beat = new Imagifybeat();
|
||||
|
||||
} )( jQuery, document, window );
|
||||
1
wp/wp-content/plugins/imagify/assets/js/beat.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/beat.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1158
wp/wp-content/plugins/imagify/assets/js/es6-promise.auto.js
Normal file
1158
wp/wp-content/plugins/imagify/assets/js/es6-promise.auto.js
Normal file
File diff suppressed because it is too large
Load Diff
1
wp/wp-content/plugins/imagify/assets/js/es6-promise.auto.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/es6-promise.auto.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
457
wp/wp-content/plugins/imagify/assets/js/files-list.js
Normal file
457
wp/wp-content/plugins/imagify/assets/js/files-list.js
Normal file
@@ -0,0 +1,457 @@
|
||||
/**
|
||||
* Mini chart.
|
||||
*
|
||||
* @param {element} canvas The canvas element.
|
||||
*/
|
||||
window.imagify.drawMeAChart = function( canvas ) {
|
||||
canvas.each( function() {
|
||||
var value = parseInt( jQuery( this ).closest( '.imagify-chart' ).next( '.imagify-chart-value' ).text(), 10 );
|
||||
|
||||
new window.imagify.Chart( this, { // eslint-disable-line no-new
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
datasets: [ {
|
||||
data: [ value, 100 - value ],
|
||||
backgroundColor: [ '#00B3D3', '#D8D8D8' ],
|
||||
borderColor: '#fff',
|
||||
borderWidth: 1
|
||||
} ]
|
||||
},
|
||||
options: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
events: [],
|
||||
animation: {
|
||||
easing: 'easeOutBounce'
|
||||
},
|
||||
tooltips: {
|
||||
enabled: false
|
||||
},
|
||||
responsive: false
|
||||
}
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
w.imagify.filesList = {
|
||||
|
||||
working: [],
|
||||
|
||||
/*
|
||||
* Init.
|
||||
*/
|
||||
init: function () {
|
||||
var $document = $( d ),
|
||||
$processing;
|
||||
|
||||
// Update the chart in the media modal when a media is selected, and the ones already printed.
|
||||
$( w ).on( 'canvasprinted.imagify', this.updateChart ).trigger( 'canvasprinted.imagify' );
|
||||
|
||||
// Handle bulk actions.
|
||||
this.insertBulkActionTags();
|
||||
|
||||
$( '#doaction, #doaction2' ).on( 'click.imagify', this.processBulkAction );
|
||||
|
||||
// Optimize, restore, etc.
|
||||
$document.on( 'click.imagify', '.button-imagify-optimize, .button-imagify-manual-reoptimize, .button-imagify-generate-webp, .button-imagify-delete-webp, .button-imagify-restore, .button-imagify-refresh-status', this.processOptimization );
|
||||
|
||||
$document.on( 'imagifybeat-send', this.addToImagifybeat );
|
||||
$document.on( 'imagifybeat-tick', this.processImagifybeat );
|
||||
|
||||
// Some items may be processed in background on page load.
|
||||
$processing = $( '.wp-list-table.imagify-files .button-imagify-processing' );
|
||||
|
||||
if ( $processing.length ) {
|
||||
// Some media are already being processed.
|
||||
// Lock the items, so we can check their status with Imagifybeat.
|
||||
$processing.closest( 'tr' ).find( '.check-column [name="bulk_select[]"]' ).each( function() {
|
||||
var id = w.imagify.filesList.sanitizeId( this.value );
|
||||
|
||||
w.imagify.filesList.lockItem( w.imagifyFiles.context, id );
|
||||
} );
|
||||
|
||||
// Fasten Imagifybeat.
|
||||
w.imagify.beat.interval( 15 );
|
||||
}
|
||||
},
|
||||
|
||||
// Charts ==================================================================================
|
||||
|
||||
/**
|
||||
* Update the chart in the media modal when a media is selected, and the ones already printed.
|
||||
*
|
||||
* @param {object} e Event.
|
||||
* @param {string} selector A CSS selector.
|
||||
*/
|
||||
updateChart: function( e, selector ) {
|
||||
var $canvas;
|
||||
|
||||
selector = selector || '.imagify-consumption-chart';
|
||||
$canvas = $( selector );
|
||||
|
||||
w.imagify.drawMeAChart( $canvas );
|
||||
|
||||
$canvas.closest( '.imagify-datas-list' ).siblings( '.imagify-datas-details' ).hide();
|
||||
},
|
||||
|
||||
// Bulk optimization =======================================================================
|
||||
|
||||
/**
|
||||
* Insert the bulk actions in the <select> tag.
|
||||
*/
|
||||
insertBulkActionTags: function() {
|
||||
var bulkActions = '<option value="imagify-bulk-optimize">' + w.imagifyFiles.labels.bulkActionsOptimize + '</option>';
|
||||
|
||||
if ( w.imagifyFiles.backupOption || $( '.file-has-backup' ).length ) {
|
||||
// If the backup option is enabled, or if we have items that can be restored.
|
||||
bulkActions += '<option value="imagify-bulk-restore">' + w.imagifyFiles.labels.bulkActionsRestore + '</option>';
|
||||
}
|
||||
|
||||
$( '.bulkactions select[name="action"] option:first-child, .bulkactions select[name="action2"] option:first-child' ).after( bulkActions );
|
||||
},
|
||||
|
||||
/**
|
||||
* Process one of these actions: bulk restore, bulk optimize, or bulk refresh-status.
|
||||
*
|
||||
* @param {object} e Event.
|
||||
*/
|
||||
processBulkAction: function( e ) {
|
||||
var value = $( this ).prev( 'select' ).val(),
|
||||
action;
|
||||
|
||||
if ( 'imagify-bulk-optimize' !== value && 'imagify-bulk-restore' !== value && 'imagify-bulk-refresh-status' !== value ) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
action = value.replace( 'imagify-bulk-', '' );
|
||||
|
||||
$( 'input[name="bulk_select[]"]:checked' ).closest( 'tr' ).find( '.button-imagify-' + action ).each( function ( index, el ) {
|
||||
setTimeout( function() {
|
||||
$( el ).trigger( 'click.imagify' );
|
||||
}, index * 500 );
|
||||
} );
|
||||
},
|
||||
|
||||
// Optimization ============================================================================
|
||||
|
||||
/**
|
||||
* Process one of these actions: optimize, re-optimize, restore, or refresh-status.
|
||||
*
|
||||
* @param {object} e Event.
|
||||
*/
|
||||
processOptimization: function( e ) {
|
||||
var $button = $( this ),
|
||||
$row = $button.closest( 'tr' ),
|
||||
$checkbox = $row.find( '.check-column [type="checkbox"]' ),
|
||||
id = imagify.filesList.sanitizeId( $checkbox.val() ),
|
||||
context = w.imagifyFiles.context,
|
||||
$parent, href, processingTemplate;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if ( imagify.filesList.isItemLocked( context, id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
imagify.filesList.lockItem( context, id );
|
||||
|
||||
href = $button.attr( 'href' );
|
||||
processingTemplate = w.imagify.template( 'imagify-button-processing' );
|
||||
$parent = $button.closest( '.column-actions, .column-status' );
|
||||
|
||||
$parent.html( processingTemplate( {
|
||||
label: $button.data( 'processing-label' )
|
||||
} ) );
|
||||
|
||||
$.get( href.replace( 'admin-post.php', 'admin-ajax.php' ) )
|
||||
.done( function( r ) {
|
||||
if ( ! r.success ) {
|
||||
if ( r.data && r.data.row ) {
|
||||
$row.html( '<td class="colspanchange" colspan="' + $row.children().length + '">' + r.data.row + '</td>' );
|
||||
} else {
|
||||
$parent.html( r.data );
|
||||
}
|
||||
|
||||
$row.find( '.check-column [type="checkbox"]' ).prop( 'checked', false );
|
||||
|
||||
imagify.filesList.unlockItem( context, id );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( r.data && r.data.columns ) {
|
||||
// The work is done.
|
||||
w.imagify.filesList.displayProcessResult( context, id, r.data.columns );
|
||||
} else {
|
||||
// Still processing in background: we're waiting for the result by poking Imagifybeat.
|
||||
// Set the Imagifybeat interval to 15 seconds.
|
||||
w.imagify.beat.interval( 15 );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
// Imagifybeat =============================================================================
|
||||
|
||||
/**
|
||||
* Send the media IDs and their status to Imagifybeat.
|
||||
*
|
||||
* @param {object} e Event object.
|
||||
* @param {object} data Object containing all Imagifybeat IDs.
|
||||
*/
|
||||
addToImagifybeat: function ( e, data ) {
|
||||
var $boxes = $( '.wp-list-table.imagify-files .check-column [name="bulk_select[]"]' );
|
||||
|
||||
if ( ! $boxes.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
data[ w.imagifyFiles.imagifybeatID ] = {};
|
||||
|
||||
$boxes.each( function() {
|
||||
var id = w.imagify.filesList.sanitizeId( this.value ),
|
||||
context = w.imagifyFiles.context,
|
||||
locked = w.imagify.filesList.isItemLocked( context, id ) ? 1 : 0;
|
||||
|
||||
data[ w.imagifyFiles.imagifybeatID ][ context ] = data[ w.imagifyFiles.imagifybeatID ][ context ] || {};
|
||||
data[ w.imagifyFiles.imagifybeatID ][ context ][ '_' + id ] = locked;
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Listen for the custom event "imagifybeat-tick" on $(document).
|
||||
*
|
||||
* @param {object} e Event object.
|
||||
* @param {object} data Object containing all Imagifybeat IDs.
|
||||
*/
|
||||
processImagifybeat: function ( e, data ) {
|
||||
if ( typeof data[ w.imagifyFiles.imagifybeatID ] === 'undefined' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.each( data[ w.imagifyFiles.imagifybeatID ], function( contextId, columns ) {
|
||||
var context, id;
|
||||
|
||||
context = $.trim( contextId ).match( /^(.+)_(\d+)$/ );
|
||||
|
||||
if ( ! context ) {
|
||||
return;
|
||||
}
|
||||
|
||||
id = w.imagify.filesList.sanitizeId( context[2] );
|
||||
context = w.imagify.filesList.sanitizeContext( context[1] );
|
||||
|
||||
if ( context !== w.imagifyFiles.context ) {
|
||||
return;
|
||||
}
|
||||
|
||||
w.imagify.filesList.displayProcessResult( context, id, columns );
|
||||
} );
|
||||
},
|
||||
|
||||
// DOM manipulation tools ==================================================================
|
||||
|
||||
/**
|
||||
* Display a successful process result.
|
||||
*
|
||||
* @param {string} context The media context.
|
||||
* @param {int} id The media ID.
|
||||
* @param {string} columns A list of HTML, keyed by column name.
|
||||
*/
|
||||
displayProcessResult: function( context, id, columns ) {
|
||||
var $row = w.imagify.filesList.getContainers( id );
|
||||
|
||||
$.each( columns, function( k, v ) {
|
||||
$row.children( '.column-' + k ).html( v );
|
||||
} );
|
||||
|
||||
$row.find( '.check-column [type="checkbox"]' ).prop( 'checked', false );
|
||||
|
||||
w.imagify.filesList.unlockItem( context, id );
|
||||
|
||||
if ( ! w.imagify.filesList.working.length ) {
|
||||
// Work is done.
|
||||
// Reset Imagifybeat interval.
|
||||
w.imagify.beat.resetInterval();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all containers matching the given id.
|
||||
*
|
||||
* @param {int} id The media ID.
|
||||
* @return {object} A jQuery collection.
|
||||
*/
|
||||
getContainers: function( id ) {
|
||||
return $( '.wp-list-table.imagify-files .check-column [name="bulk_select[]"][value="' + id + '"]' ).closest( 'tr' );
|
||||
},
|
||||
|
||||
// Sanitization ============================================================================
|
||||
|
||||
/**
|
||||
* Sanitize a media ID.
|
||||
*
|
||||
* @param {int|string} id A media ID.
|
||||
* @return {int}
|
||||
*/
|
||||
sanitizeId: function( id ) {
|
||||
return parseInt( id, 10 );
|
||||
},
|
||||
|
||||
/**
|
||||
* Sanitize a media context.
|
||||
*
|
||||
* @param {string} context A media context.
|
||||
* @return {string}
|
||||
*/
|
||||
sanitizeContext: function( context ) {
|
||||
context = context.replace( '/[^a-z0-9_-]/gi', '' ).toLowerCase();
|
||||
return context ? context : 'wp';
|
||||
},
|
||||
|
||||
// Locks ===================================================================================
|
||||
|
||||
/**
|
||||
* Lock an item.
|
||||
*
|
||||
* @param {string} context The media context.
|
||||
* @param {int} id The media ID.
|
||||
*/
|
||||
lockItem: function( context, id ) {
|
||||
if ( ! this.isItemLocked( context, id ) ) {
|
||||
this.working.push( context + '_' + id );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Unlock an item.
|
||||
*
|
||||
* @param {string} context The media context.
|
||||
* @param {int} id The media ID.
|
||||
*/
|
||||
unlockItem: function( context, id ) {
|
||||
var name = context + '_' + id,
|
||||
i = _.indexOf( this.working, name );
|
||||
|
||||
if ( i > -1 ) {
|
||||
this.working.splice( i, 1 );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Tell if an item is locked.
|
||||
*
|
||||
* @param {string} context The media context.
|
||||
* @param {int} id The media ID.
|
||||
* @return {bool}
|
||||
*/
|
||||
isItemLocked: function( context, id ) {
|
||||
return _.indexOf( this.working, context + '_' + id ) > -1;
|
||||
}
|
||||
};
|
||||
|
||||
w.imagify.filesList.init();
|
||||
|
||||
} )(jQuery, document, window);
|
||||
|
||||
|
||||
(function(w) { // eslint-disable-line no-shadow, no-shadow-restricted-names
|
||||
|
||||
/**
|
||||
* requestAnimationFrame polyfill by Erik Möller.
|
||||
* Fixes from Paul Irish and Tino Zijdel.
|
||||
* MIT license - http://paulirish.com/2011/requestanimationframe-for-smart-animating/ - http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating.
|
||||
*/
|
||||
var lastTime = 0,
|
||||
vendors = ['ms', 'moz', 'webkit', 'o'];
|
||||
|
||||
for ( var x = 0; x < vendors.length && ! w.requestAnimationFrame; ++x ) {
|
||||
w.requestAnimationFrame = w[vendors[x] + 'RequestAnimationFrame'];
|
||||
w.cancelAnimationFrame = w[vendors[x] + 'CancelAnimationFrame'] || w[vendors[x] + 'CancelRequestAnimationFrame'];
|
||||
}
|
||||
|
||||
if ( ! w.requestAnimationFrame ) {
|
||||
w.requestAnimationFrame = function( callback ) {
|
||||
var currTime = new Date().getTime(),
|
||||
timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) ),
|
||||
id = setTimeout( function() {
|
||||
callback( currTime + timeToCall );
|
||||
}, timeToCall );
|
||||
|
||||
lastTime = currTime + timeToCall;
|
||||
return id;
|
||||
};
|
||||
}
|
||||
|
||||
if ( ! w.cancelAnimationFrame ) {
|
||||
w.cancelAnimationFrame = function( id ) {
|
||||
clearTimeout( id );
|
||||
};
|
||||
}
|
||||
|
||||
})(window);
|
||||
|
||||
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
/**
|
||||
* LazyLoad images in the list.
|
||||
*/
|
||||
var lazyImages = $( '#imagify-files-list-form' ).find( '[data-lazy-src]' ),
|
||||
lazyTimer;
|
||||
|
||||
function lazyLoadThumbnails() {
|
||||
w.cancelAnimationFrame( lazyTimer );
|
||||
lazyTimer = w.requestAnimationFrame( lazyLoadThumbnailsCallback ); // eslint-disable-line no-use-before-define
|
||||
}
|
||||
|
||||
function lazyLoadThumbnailsCallback() {
|
||||
var $w = $( w ),
|
||||
winScroll = $w.scrollTop(),
|
||||
winHeight = $w.outerHeight();
|
||||
|
||||
$.each( lazyImages, function() {
|
||||
var $image = $( this ),
|
||||
imgTop = $image.offset().top,
|
||||
imgBottom = imgTop + $image.outerHeight(),
|
||||
screenTopThresholded = winScroll - 150,
|
||||
screenBottomThresholded = winScroll + winHeight + 150,
|
||||
src;
|
||||
|
||||
lazyImages = lazyImages.not( $image );
|
||||
|
||||
if ( ! lazyImages.length ) {
|
||||
$w.off( 'scroll resize orientationchange', lazyLoadThumbnails );
|
||||
}
|
||||
|
||||
/**
|
||||
* Hidden images that are above the fold and below the top, are reported as:
|
||||
* - offset: window scroll,
|
||||
* - height: 0,
|
||||
* (at least in Firefox).
|
||||
* That's why I use <= and >=.
|
||||
*
|
||||
* 150 is the threshold.
|
||||
*/
|
||||
if ( imgBottom >= screenTopThresholded && imgTop <= screenBottomThresholded ) {
|
||||
src = $image.attr( 'data-lazy-src' );
|
||||
|
||||
if ( undefined !== src && src ) {
|
||||
$image.attr( 'src', src ).removeAttr( 'data-lazy-src' );
|
||||
}
|
||||
|
||||
$image.next( 'noscript' ).remove();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
if ( lazyImages.length ) {
|
||||
$( w ).on( 'scroll resize orientationchange', lazyLoadThumbnails );
|
||||
lazyLoadThumbnailsCallback();
|
||||
}
|
||||
|
||||
} )(jQuery, document, window);
|
||||
1
wp/wp-content/plugins/imagify/assets/js/files-list.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/files-list.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
400
wp/wp-content/plugins/imagify/assets/js/imagify-gulp.js
Normal file
400
wp/wp-content/plugins/imagify/assets/js/imagify-gulp.js
Normal file
@@ -0,0 +1,400 @@
|
||||
/**
|
||||
* Library that handles the bulk optimization processes.
|
||||
*
|
||||
* @requires jQuery
|
||||
*/
|
||||
window.imagify = window.imagify || {};
|
||||
|
||||
/* eslint-disable no-underscore-dangle, consistent-this */
|
||||
(function($, d, w) {
|
||||
|
||||
/**
|
||||
* Construct the optimizer.
|
||||
*
|
||||
* @param {object} settings {
|
||||
* Optimizer settings:
|
||||
*
|
||||
* @type {string} groupID Group ID, like 'library' or 'custom-folders'.
|
||||
* @type {string} context Context within this group, like 'wp' or 'custom-folders' (yes, again).
|
||||
* @type {int} level Optimization level: 0 to 2.
|
||||
* @type {int} bufferSize Number of parallel optimizations: usually 4.
|
||||
* @type {string} ajaxUrl URL to request to optimize.
|
||||
* @type {object} files Files to optimize: media ID as key (prefixed with an underscore), file URL as value.
|
||||
* @type {string} defaultThumb A default thumbnail URL.
|
||||
* @type {string} doneEvent Name of the event to listen to know when optimizations end.
|
||||
* @type {array} imageExtensions A list of supported image extensions (only images).
|
||||
* }
|
||||
*/
|
||||
w.imagify.Optimizer = function ( settings ) {
|
||||
// Settings.
|
||||
this.groupID = settings.groupID;
|
||||
this.context = settings.context;
|
||||
this.level = settings.level;
|
||||
this.bufferSize = settings.bufferSize || 1;
|
||||
this.ajaxUrl = settings.ajaxUrl;
|
||||
this.files = settings.files;
|
||||
this.defaultThumb = settings.defaultThumb;
|
||||
this.doneEvent = settings.doneEvent;
|
||||
|
||||
if ( settings.imageExtensions ) {
|
||||
this.imageExtensions = settings.imageExtensions;
|
||||
} else {
|
||||
this.imageExtensions = [ 'jpg', 'jpeg', 'jpe', 'png', 'gif' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of media IDs (prefixed with an underscore).
|
||||
*/
|
||||
this.prefixedMediaIDs = Object.keys( this.files );
|
||||
/**
|
||||
* An array of medias currently being optimized: {
|
||||
* @type {int} mediaID The media ID.
|
||||
* @type {string} filename The file name.
|
||||
* @type {string} thumbnail The file thumbnail URL.
|
||||
* }
|
||||
*/
|
||||
this.currentItems = [];
|
||||
|
||||
// Internal counters.
|
||||
this.totalMedia = this.prefixedMediaIDs.length;
|
||||
this.processedMedia = 0;
|
||||
|
||||
// Global stats.
|
||||
this.globalOriginalSize = 0;
|
||||
this.globalOptimizedSize = 0;
|
||||
this.globalGain = 0;
|
||||
this.globalPercent = 0;
|
||||
|
||||
// Callbacks.
|
||||
this._before = function () {};
|
||||
this._each = function () {};
|
||||
this._done = function () {};
|
||||
|
||||
// Listen to the "optimization done" event.
|
||||
if ( this.totalMedia && this.doneEvent ) {
|
||||
$( w ).on( this.doneEvent, { _this: this }, this.processedCallback );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to trigger before each media optimization.
|
||||
*
|
||||
* @param {callable} fnc A callback.
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.before = function( fnc ) {
|
||||
this._before = fnc;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to trigger after each media optimization.
|
||||
*
|
||||
* @param {callable} fnc A callback.
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.each = function( fnc ) {
|
||||
this._each = fnc;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to trigger all media optimizations have been done.
|
||||
*
|
||||
* @param {callable} fnc A callback.
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.done = function( fnc ) {
|
||||
this._done = fnc;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch optimizations.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.run = function() {
|
||||
var chunkLength = this.prefixedMediaIDs.length > this.bufferSize ? this.bufferSize : this.prefixedMediaIDs.length,
|
||||
i;
|
||||
|
||||
for ( i = 0; i < chunkLength; i++ ) {
|
||||
this.processNext();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch next optimization.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.processNext = function() {
|
||||
if ( this.prefixedMediaIDs.length ) {
|
||||
this.process( this.prefixedMediaIDs.shift() );
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch an optimization.
|
||||
*
|
||||
* @param {string} prefixedId A media ID, prefixed with an underscore.
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.process = function( prefixedId ) {
|
||||
var _this = this,
|
||||
fileURL = this.files[ prefixedId ],
|
||||
data = {
|
||||
mediaID: parseInt( prefixedId.toString().substr( 1 ), 10 ),
|
||||
filename: this.files[ prefixedId ].split( '/' ).pop(),
|
||||
thumbnail: this.defaultThumb
|
||||
},
|
||||
extension = data.filename.split( '.' ).pop().toLowerCase(),
|
||||
regexp = new RegExp( '^' + this.imageExtensions.join( '|' ).toLowerCase() + '$' ),
|
||||
image;
|
||||
|
||||
if ( ! extension.match( regexp ) ) {
|
||||
// Not an image.
|
||||
this.currentItems.push( data );
|
||||
this._before( data );
|
||||
this.send( data );
|
||||
return this;
|
||||
}
|
||||
|
||||
// Create a thumbnail and send the ajax request.
|
||||
image = new Image();
|
||||
|
||||
image.onerror = function () {
|
||||
_this.currentItems.push( data );
|
||||
_this._before( data );
|
||||
_this.send( data );
|
||||
};
|
||||
|
||||
image.onload = function () {
|
||||
var maxWidth = 33,
|
||||
maxHeight = 33,
|
||||
imageWidth = image.width,
|
||||
imageHeight = image.height,
|
||||
newHeight = 0,
|
||||
newWidth = 0,
|
||||
topOffset = 0,
|
||||
leftOffset = 0,
|
||||
canvas = null,
|
||||
ctx = null;
|
||||
|
||||
if ( imageWidth < imageHeight ) {
|
||||
// Portrait.
|
||||
newWidth = maxWidth;
|
||||
newHeight = newWidth * imageHeight / imageWidth;
|
||||
topOffset = ( maxHeight - newHeight ) / 2;
|
||||
} else {
|
||||
// Landscape.
|
||||
newHeight = maxHeight;
|
||||
newWidth = newHeight * imageWidth / imageHeight;
|
||||
leftOffset = ( maxWidth - newWidth ) / 2;
|
||||
}
|
||||
|
||||
canvas = d.createElement( 'canvas' );
|
||||
|
||||
canvas.width = maxWidth;
|
||||
canvas.height = maxHeight;
|
||||
|
||||
ctx = canvas.getContext( '2d' );
|
||||
ctx.drawImage( this, leftOffset, topOffset, newWidth, newHeight );
|
||||
|
||||
try {
|
||||
data.thumbnail = canvas.toDataURL( 'image/jpeg' );
|
||||
} catch ( e ) {
|
||||
data.thumbnail = _this.defaultThumb;
|
||||
}
|
||||
|
||||
canvas = null;
|
||||
ctx = null;
|
||||
image = null;
|
||||
|
||||
_this.currentItems.push( data );
|
||||
_this._before( data );
|
||||
_this.send( data );
|
||||
};
|
||||
|
||||
image.src = fileURL;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Do the ajax request.
|
||||
*
|
||||
* @param {object} data {
|
||||
* The data:
|
||||
*
|
||||
* @type {int} mediaID The media ID.
|
||||
* @type {string} filename The file name.
|
||||
* @type {string} thumbnail The file thumbnail URL.
|
||||
* }
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.send = function( data ) {
|
||||
var _this = this,
|
||||
defaultResponse = {
|
||||
success: false,
|
||||
mediaID: data.mediaID,
|
||||
groupID: this.groupID,
|
||||
context: this.context,
|
||||
filename: data.filename,
|
||||
thumbnail: data.thumbnail,
|
||||
status: 'error',
|
||||
error: ''
|
||||
};
|
||||
|
||||
$.post( {
|
||||
url: this.ajaxUrl,
|
||||
data: {
|
||||
media_id: data.mediaID,
|
||||
context: this.context,
|
||||
optimization_level: this.level
|
||||
},
|
||||
dataType: 'json'
|
||||
} )
|
||||
.done( function( response ) {
|
||||
if ( response.success ) {
|
||||
return;
|
||||
}
|
||||
|
||||
defaultResponse.error = response.data.error;
|
||||
|
||||
_this.processed( defaultResponse );
|
||||
} )
|
||||
.fail( function( jqXHR ) {
|
||||
if ( 200 === jqXHR.status ) {
|
||||
defaultResponse.error = jqXHR.responseText.replace( /<h1>.*<\/h1>\n*/, '' );
|
||||
} else {
|
||||
defaultResponse.error = jqXHR.statusText;
|
||||
}
|
||||
|
||||
_this.processed( defaultResponse );
|
||||
} );
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback triggered when an optimization is complete.
|
||||
*
|
||||
* @param {object} e jQuery's Event object.
|
||||
* @param {object} item {
|
||||
* The response:
|
||||
*
|
||||
* @type {int} mediaID The media ID.
|
||||
* @type {string} context The context.
|
||||
* }
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.processedCallback = function( e, item ) {
|
||||
var _this = e.data._this;
|
||||
|
||||
if ( item.context !== _this.context ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! item.mediaID || typeof _this.files[ '_' + item.mediaID ] === 'undefined' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
item.groupID = _this.groupID;
|
||||
|
||||
if ( ! _this.currentItems.length ) {
|
||||
// Trouble.
|
||||
_this.processed( item );
|
||||
return;
|
||||
}
|
||||
|
||||
$.each( _this.currentItems, function( i, mediaData ) {
|
||||
if ( item.mediaID === mediaData.mediaID ) {
|
||||
item.filename = mediaData.filename;
|
||||
item.thumbnail = mediaData.thumbnail;
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
|
||||
_this.processed( item );
|
||||
};
|
||||
|
||||
/**
|
||||
* After a media has been processed.
|
||||
*
|
||||
* @param {object} response {
|
||||
* The response:
|
||||
*
|
||||
* @type {bool} success Whether the optimization succeeded or not ("already optimized" is a success).
|
||||
* @type {int} mediaID The media ID.
|
||||
* @type {string} groupID The group ID.
|
||||
* @type {string} context The context.
|
||||
* @type {string} filename The file name.
|
||||
* @type {string} thumbnail The file thumbnail URL.
|
||||
* @type {string} status The status, like 'optimized', 'already-optimized', 'over-quota', 'error'.
|
||||
* @type {string} error The error message.
|
||||
* }
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.processed = function( response ) {
|
||||
var currentItems = this.currentItems;
|
||||
|
||||
if ( currentItems.length ) {
|
||||
// Remove this media from the "current" list.
|
||||
$.each( currentItems, function( i, mediaData ) {
|
||||
if ( response.mediaID === mediaData.mediaID ) {
|
||||
currentItems.splice( i, 1 );
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
|
||||
this.currentItems = currentItems;
|
||||
}
|
||||
|
||||
// Update stats.
|
||||
if ( response.success && 'already-optimized' !== response.status ) {
|
||||
this.globalOriginalSize += response.originalOverallSize;
|
||||
this.globalOptimizedSize += response.newOverallSize;
|
||||
this.globalGain += response.overallSaving;
|
||||
this.globalPercent = ( 100 - this.globalOptimizedSize / this.globalOptimizedSize * 100 ).toFixed( 2 );
|
||||
}
|
||||
|
||||
++this.processedMedia;
|
||||
response.progress = Math.floor( this.processedMedia / this.totalMedia * 100 );
|
||||
|
||||
this._each( response );
|
||||
|
||||
if ( this.prefixedMediaIDs.length ) {
|
||||
this.processNext();
|
||||
} else if ( this.totalMedia === this.processedMedia ) {
|
||||
this._done( {
|
||||
globalOriginalSize: this.globalOriginalSize,
|
||||
globalOptimizedSize: this.globalOptimizedSize,
|
||||
globalGain: this.globalGain
|
||||
} );
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop the process.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.stopProcess = function() {
|
||||
this.files = {};
|
||||
this.prefixedMediaIDs = [];
|
||||
this.currentItems = [];
|
||||
|
||||
if ( this.doneEvent ) {
|
||||
$( w ).off( this.doneEvent, this.processedCallback );
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
} )(jQuery, document, window);
|
||||
396
wp/wp-content/plugins/imagify/assets/js/imagify-gulp.min.js
vendored
Normal file
396
wp/wp-content/plugins/imagify/assets/js/imagify-gulp.min.js
vendored
Normal file
@@ -0,0 +1,396 @@
|
||||
/**
|
||||
* Library that handles the bulk optimization processes.
|
||||
*
|
||||
* @requires jQuery
|
||||
*/
|
||||
window.imagify = window.imagify || {};
|
||||
|
||||
/* eslint-disable no-underscore-dangle, consistent-this */
|
||||
(function($, d, w) {
|
||||
|
||||
/**
|
||||
* Construct the optimizer.
|
||||
*
|
||||
* @param {object} settings {
|
||||
* Optimizer settings:
|
||||
*
|
||||
* @type {string} groupID Group ID, like 'library' or 'custom-folders'.
|
||||
* @type {string} context Context within this group, like 'wp' or 'custom-folders' (yes, again).
|
||||
* @type {int} level Optimization level: 0 to 2.
|
||||
* @type {int} bufferSize Number of parallel optimizations: usually 4.
|
||||
* @type {string} ajaxUrl URL to request to optimize.
|
||||
* @type {object} files Files to optimize: media ID as key (prefixed with an underscore), file URL as value.
|
||||
* @type {string} defaultThumb A default thumbnail URL.
|
||||
* @type {string} doneEvent Name of the event to listen to know when optimizations end.
|
||||
* @type {array} imageExtensions A list of supported image extensions (only images).
|
||||
* }
|
||||
*/
|
||||
w.imagify.Optimizer = function ( settings ) {
|
||||
// Settings.
|
||||
this.groupID = settings.groupID;
|
||||
this.context = settings.context;
|
||||
this.level = settings.level;
|
||||
this.bufferSize = settings.bufferSize || 1;
|
||||
this.ajaxUrl = settings.ajaxUrl;
|
||||
this.files = settings.files;
|
||||
this.defaultThumb = settings.defaultThumb;
|
||||
this.doneEvent = settings.doneEvent;
|
||||
|
||||
if ( settings.imageExtensions ) {
|
||||
this.imageExtensions = settings.imageExtensions;
|
||||
} else {
|
||||
this.imageExtensions = [ 'jpg', 'jpeg', 'jpe', 'png', 'gif' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of media IDs (prefixed with an underscore).
|
||||
*/
|
||||
this.prefixedMediaIDs = Object.keys( this.files );
|
||||
/**
|
||||
* An array of medias currently being optimized: {
|
||||
* @type {int} mediaID The media ID.
|
||||
* @type {string} filename The file name.
|
||||
* @type {string} thumbnail The file thumbnail URL.
|
||||
* }
|
||||
*/
|
||||
this.currentItems = [];
|
||||
|
||||
// Internal counters.
|
||||
this.totalMedia = this.prefixedMediaIDs.length;
|
||||
this.processedMedia = 0;
|
||||
|
||||
// Global stats.
|
||||
this.globalOriginalSize = 0;
|
||||
this.globalOptimizedSize = 0;
|
||||
this.globalGain = 0;
|
||||
this.globalPercent = 0;
|
||||
|
||||
// Callbacks.
|
||||
this._before = function () {};
|
||||
this._each = function () {};
|
||||
this._done = function () {};
|
||||
|
||||
// Listen to the "optimization done" event.
|
||||
if ( this.totalMedia && this.doneEvent ) {
|
||||
$( w ).on( this.doneEvent, { _this: this }, this.processedCallback );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to trigger before each media optimization.
|
||||
*
|
||||
* @param {callable} fnc A callback.
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.before = function( fnc ) {
|
||||
this._before = fnc;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to trigger after each media optimization.
|
||||
*
|
||||
* @param {callable} fnc A callback.
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.each = function( fnc ) {
|
||||
this._each = fnc;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback to trigger all media optimizations have been done.
|
||||
*
|
||||
* @param {callable} fnc A callback.
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.done = function( fnc ) {
|
||||
this._done = fnc;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch optimizations.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.run = function() {
|
||||
var chunkLength = this.prefixedMediaIDs.length > this.bufferSize ? this.bufferSize : this.prefixedMediaIDs.length,
|
||||
i;
|
||||
|
||||
for ( i = 0; i < chunkLength; i++ ) {
|
||||
this.processNext();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch next optimization.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.processNext = function() {
|
||||
if ( this.prefixedMediaIDs.length ) {
|
||||
this.process( this.prefixedMediaIDs.shift() );
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch an optimization.
|
||||
*
|
||||
* @param {string} prefixedId A media ID, prefixed with an underscore.
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.process = function( prefixedId ) {
|
||||
var _this = this,
|
||||
fileURL = this.files[ prefixedId ],
|
||||
data = {
|
||||
mediaID: parseInt( prefixedId.toString().substr( 1 ), 10 ),
|
||||
filename: this.files[ prefixedId ].split( '/' ).pop(),
|
||||
thumbnail: this.defaultThumb
|
||||
},
|
||||
extension = data.filename.split( '.' ).pop().toLowerCase(),
|
||||
regexp = new RegExp( '^' + this.imageExtensions.join( '|' ).toLowerCase() + '$' ),
|
||||
image;
|
||||
|
||||
if ( ! extension.match( regexp ) ) {
|
||||
// Not an image.
|
||||
this.currentItems.push( data );
|
||||
this._before( data );
|
||||
this.send( data );
|
||||
return this;
|
||||
}
|
||||
|
||||
// Create a thumbnail and send the ajax request.
|
||||
image = new Image();
|
||||
|
||||
image.onerror = function () {
|
||||
_this.currentItems.push( data );
|
||||
_this._before( data );
|
||||
_this.send( data );
|
||||
};
|
||||
|
||||
image.onload = function () {
|
||||
var maxWidth = 33,
|
||||
maxHeight = 33,
|
||||
imageWidth = image.width,
|
||||
imageHeight = image.height,
|
||||
newHeight = 0,
|
||||
newWidth = 0,
|
||||
topOffset = 0,
|
||||
leftOffset = 0,
|
||||
canvas = null,
|
||||
ctx = null;
|
||||
|
||||
if ( imageWidth < imageHeight ) {
|
||||
// Portrait.
|
||||
newWidth = maxWidth;
|
||||
newHeight = newWidth * imageHeight / imageWidth;
|
||||
topOffset = ( maxHeight - newHeight ) / 2;
|
||||
} else {
|
||||
// Landscape.
|
||||
newHeight = maxHeight;
|
||||
newWidth = newHeight * imageWidth / imageHeight;
|
||||
leftOffset = ( maxWidth - newWidth ) / 2;
|
||||
}
|
||||
|
||||
canvas = d.createElement( 'canvas' );
|
||||
|
||||
canvas.width = maxWidth;
|
||||
canvas.height = maxHeight;
|
||||
|
||||
ctx = canvas.getContext( '2d' );
|
||||
ctx.drawImage( this, leftOffset, topOffset, newWidth, newHeight );
|
||||
|
||||
try {
|
||||
data.thumbnail = canvas.toDataURL( 'image/jpeg' );
|
||||
} catch ( e ) {
|
||||
data.thumbnail = _this.defaultThumb;
|
||||
}
|
||||
|
||||
canvas = null;
|
||||
ctx = null;
|
||||
image = null;
|
||||
|
||||
_this.currentItems.push( data );
|
||||
_this._before( data );
|
||||
_this.send( data );
|
||||
};
|
||||
|
||||
image.src = fileURL;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Do the ajax request.
|
||||
*
|
||||
* @param {object} data {
|
||||
* The data:
|
||||
*
|
||||
* @type {int} mediaID The media ID.
|
||||
* @type {string} filename The file name.
|
||||
* @type {string} thumbnail The file thumbnail URL.
|
||||
* }
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.send = function( data ) {
|
||||
var _this = this,
|
||||
defaultResponse = {
|
||||
success: false,
|
||||
mediaID: data.mediaID,
|
||||
groupID: this.groupID,
|
||||
context: this.context,
|
||||
filename: data.filename,
|
||||
thumbnail: data.thumbnail,
|
||||
status: 'error',
|
||||
error: ''
|
||||
};
|
||||
|
||||
$.post( {
|
||||
url: this.ajaxUrl,
|
||||
data: {
|
||||
media_id: data.mediaID,
|
||||
context: this.context,
|
||||
optimization_level: this.level
|
||||
},
|
||||
dataType: 'json'
|
||||
} )
|
||||
.done( function( response ) {
|
||||
if ( response.success ) {
|
||||
return;
|
||||
}
|
||||
|
||||
defaultResponse.error = response.data.error;
|
||||
|
||||
_this.processed( defaultResponse );
|
||||
} )
|
||||
.fail( function( jqXHR ) {
|
||||
defaultResponse.error = jqXHR.statusText;
|
||||
|
||||
_this.processed( defaultResponse );
|
||||
} );
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback triggered when an optimization is complete.
|
||||
*
|
||||
* @param {object} e jQuery's Event object.
|
||||
* @param {object} item {
|
||||
* The response:
|
||||
*
|
||||
* @type {int} mediaID The media ID.
|
||||
* @type {string} context The context.
|
||||
* }
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.processedCallback = function( e, item ) {
|
||||
var _this = e.data._this;
|
||||
|
||||
if ( item.context !== _this.context ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! item.mediaID || typeof _this.files[ '_' + item.mediaID ] === 'undefined' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
item.groupID = _this.groupID;
|
||||
|
||||
if ( ! _this.currentItems.length ) {
|
||||
// Trouble.
|
||||
_this.processed( item );
|
||||
return;
|
||||
}
|
||||
|
||||
$.each( _this.currentItems, function( i, mediaData ) {
|
||||
if ( item.mediaID === mediaData.mediaID ) {
|
||||
item.filename = mediaData.filename;
|
||||
item.thumbnail = mediaData.thumbnail;
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
|
||||
_this.processed( item );
|
||||
};
|
||||
|
||||
/**
|
||||
* After a media has been processed.
|
||||
*
|
||||
* @param {object} response {
|
||||
* The response:
|
||||
*
|
||||
* @type {bool} success Whether the optimization succeeded or not ("already optimized" is a success).
|
||||
* @type {int} mediaID The media ID.
|
||||
* @type {string} groupID The group ID.
|
||||
* @type {string} context The context.
|
||||
* @type {string} filename The file name.
|
||||
* @type {string} thumbnail The file thumbnail URL.
|
||||
* @type {string} status The status, like 'optimized', 'already-optimized', 'over-quota', 'error'.
|
||||
* @type {string} error The error message.
|
||||
* }
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.processed = function( response ) {
|
||||
var currentItems = this.currentItems;
|
||||
|
||||
if ( currentItems.length ) {
|
||||
// Remove this media from the "current" list.
|
||||
$.each( currentItems, function( i, mediaData ) {
|
||||
if ( response.mediaID === mediaData.mediaID ) {
|
||||
currentItems.splice( i, 1 );
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
|
||||
this.currentItems = currentItems;
|
||||
}
|
||||
|
||||
// Update stats.
|
||||
if ( response.success && 'already-optimized' !== response.status ) {
|
||||
this.globalOriginalSize += response.originalOverallSize;
|
||||
this.globalOptimizedSize += response.newOverallSize;
|
||||
this.globalGain += response.overallSaving;
|
||||
this.globalPercent = ( 100 - this.globalOptimizedSize / this.globalOptimizedSize * 100 ).toFixed( 2 );
|
||||
}
|
||||
|
||||
++this.processedMedia;
|
||||
response.progress = Math.floor( this.processedMedia / this.totalMedia * 100 );
|
||||
|
||||
this._each( response );
|
||||
|
||||
if ( this.prefixedMediaIDs.length ) {
|
||||
this.processNext();
|
||||
} else if ( this.totalMedia === this.processedMedia ) {
|
||||
this._done( {
|
||||
globalOriginalSize: this.globalOriginalSize,
|
||||
globalOptimizedSize: this.globalOptimizedSize,
|
||||
globalGain: this.globalGain
|
||||
} );
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop the process.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
w.imagify.Optimizer.prototype.stopProcess = function() {
|
||||
this.files = {};
|
||||
this.prefixedMediaIDs = [];
|
||||
this.currentItems = [];
|
||||
|
||||
if ( this.doneEvent ) {
|
||||
$( w ).off( this.doneEvent, this.processedCallback );
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
} )(jQuery, document, window);
|
||||
584
wp/wp-content/plugins/imagify/assets/js/jquery.event.move.js
Normal file
584
wp/wp-content/plugins/imagify/assets/js/jquery.event.move.js
Normal file
@@ -0,0 +1,584 @@
|
||||
// DOM.event.move
|
||||
//
|
||||
// 2.0.1
|
||||
//
|
||||
// Stephen Band
|
||||
//
|
||||
// Triggers 'movestart', 'move' and 'moveend' events after
|
||||
// mousemoves following a mousedown cross a distance threshold,
|
||||
// similar to the native 'dragstart', 'drag' and 'dragend' events.
|
||||
// Move events are throttled to animation frames. Move event objects
|
||||
// have the properties:
|
||||
//
|
||||
// pageX:
|
||||
// pageY: Page coordinates of pointer.
|
||||
// startX:
|
||||
// startY: Page coordinates of pointer at movestart.
|
||||
// distX:
|
||||
// distY: Distance the pointer has moved since movestart.
|
||||
// deltaX:
|
||||
// deltaY: Distance the finger has moved since last event.
|
||||
// velocityX:
|
||||
// velocityY: Average velocity over last few events.
|
||||
|
||||
|
||||
(function(fn) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define([], fn);
|
||||
} else if ((typeof module !== "undefined" && module !== null) && module.exports) {
|
||||
module.exports = fn;
|
||||
} else {
|
||||
fn();
|
||||
}
|
||||
})(function(){
|
||||
var assign = Object.assign || window.jQuery && jQuery.extend;
|
||||
|
||||
// Number of pixels a pressed pointer travels before movestart
|
||||
// event is fired.
|
||||
var threshold = 8;
|
||||
|
||||
// Shim for requestAnimationFrame, falling back to timer. See:
|
||||
// see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
|
||||
var requestFrame = (function(){
|
||||
return (
|
||||
window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function(fn, element){
|
||||
return window.setTimeout(function(){
|
||||
fn();
|
||||
}, 25);
|
||||
}
|
||||
);
|
||||
})();
|
||||
|
||||
var ignoreTags = {
|
||||
textarea: true,
|
||||
input: true,
|
||||
select: true,
|
||||
button: true
|
||||
};
|
||||
|
||||
var mouseevents = {
|
||||
move: 'mousemove',
|
||||
cancel: 'mouseup dragstart',
|
||||
end: 'mouseup'
|
||||
};
|
||||
|
||||
var touchevents = {
|
||||
move: 'touchmove',
|
||||
cancel: 'touchend',
|
||||
end: 'touchend'
|
||||
};
|
||||
|
||||
var rspaces = /\s+/;
|
||||
|
||||
|
||||
// DOM Events
|
||||
|
||||
var eventOptions = { bubbles: true, cancelable: true };
|
||||
|
||||
var eventsSymbol = Symbol('events');
|
||||
|
||||
function createEvent(type) {
|
||||
return new CustomEvent(type, eventOptions);
|
||||
}
|
||||
|
||||
function getEvents(node) {
|
||||
return node[eventsSymbol] || (node[eventsSymbol] = {});
|
||||
}
|
||||
|
||||
function on(node, types, fn, data, selector) {
|
||||
types = types.split(rspaces);
|
||||
|
||||
var events = getEvents(node);
|
||||
var i = types.length;
|
||||
var handlers, type;
|
||||
|
||||
function handler(e) { fn(e, data); }
|
||||
|
||||
while (i--) {
|
||||
type = types[i];
|
||||
handlers = events[type] || (events[type] = []);
|
||||
handlers.push([fn, handler]);
|
||||
node.addEventListener(type, handler);
|
||||
}
|
||||
}
|
||||
|
||||
function off(node, types, fn, selector) {
|
||||
types = types.split(rspaces);
|
||||
|
||||
var events = getEvents(node);
|
||||
var i = types.length;
|
||||
var type, handlers, k;
|
||||
|
||||
if (!events) { return; }
|
||||
|
||||
while (i--) {
|
||||
type = types[i];
|
||||
handlers = events[type];
|
||||
if (!handlers) { continue; }
|
||||
k = handlers.length;
|
||||
while (k--) {
|
||||
if (handlers[k][0] === fn) {
|
||||
node.removeEventListener(type, handlers[k][1]);
|
||||
handlers.splice(k, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function trigger(node, type, properties) {
|
||||
// Don't cache events. It prevents you from triggering an event of a
|
||||
// given type from inside the handler of another event of that type.
|
||||
var event = createEvent(type);
|
||||
if (properties) { assign(event, properties); }
|
||||
node.dispatchEvent(event);
|
||||
}
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
function Timer(fn){
|
||||
var callback = fn,
|
||||
active = false,
|
||||
running = false;
|
||||
|
||||
function trigger(time) {
|
||||
if (active){
|
||||
callback();
|
||||
requestFrame(trigger);
|
||||
running = true;
|
||||
active = false;
|
||||
}
|
||||
else {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
this.kick = function(fn) {
|
||||
active = true;
|
||||
if (!running) { trigger(); }
|
||||
};
|
||||
|
||||
this.end = function(fn) {
|
||||
var cb = callback;
|
||||
|
||||
if (!fn) { return; }
|
||||
|
||||
// If the timer is not running, simply call the end callback.
|
||||
if (!running) {
|
||||
fn();
|
||||
}
|
||||
// If the timer is running, and has been kicked lately, then
|
||||
// queue up the current callback and the end callback, otherwise
|
||||
// just the end callback.
|
||||
else {
|
||||
callback = active ?
|
||||
function(){ cb(); fn(); } :
|
||||
fn ;
|
||||
|
||||
active = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Functions
|
||||
|
||||
function noop() {}
|
||||
|
||||
function preventDefault(e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function isIgnoreTag(e) {
|
||||
return !!ignoreTags[e.target.tagName.toLowerCase()];
|
||||
}
|
||||
|
||||
function isPrimaryButton(e) {
|
||||
// Ignore mousedowns on any button other than the left (or primary)
|
||||
// mouse button, or when a modifier key is pressed.
|
||||
return (e.which === 1 && !e.ctrlKey && !e.altKey);
|
||||
}
|
||||
|
||||
function identifiedTouch(touchList, id) {
|
||||
var i, l;
|
||||
|
||||
if (touchList.identifiedTouch) {
|
||||
return touchList.identifiedTouch(id);
|
||||
}
|
||||
|
||||
// touchList.identifiedTouch() does not exist in
|
||||
// webkit yet… we must do the search ourselves...
|
||||
|
||||
i = -1;
|
||||
l = touchList.length;
|
||||
|
||||
while (++i < l) {
|
||||
if (touchList[i].identifier === id) {
|
||||
return touchList[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function changedTouch(e, data) {
|
||||
var touch = identifiedTouch(e.changedTouches, data.identifier);
|
||||
|
||||
// This isn't the touch you're looking for.
|
||||
if (!touch) { return; }
|
||||
|
||||
// Chrome Android (at least) includes touches that have not
|
||||
// changed in e.changedTouches. That's a bit annoying. Check
|
||||
// that this touch has changed.
|
||||
if (touch.pageX === data.pageX && touch.pageY === data.pageY) { return; }
|
||||
|
||||
return touch;
|
||||
}
|
||||
|
||||
|
||||
// Handlers that decide when the first movestart is triggered
|
||||
|
||||
function mousedown(e){
|
||||
// Ignore non-primary buttons
|
||||
if (!isPrimaryButton(e)) { return; }
|
||||
|
||||
// Ignore form and interactive elements
|
||||
if (isIgnoreTag(e)) { return; }
|
||||
|
||||
on(document, mouseevents.move, mousemove, e);
|
||||
on(document, mouseevents.cancel, mouseend, e);
|
||||
}
|
||||
|
||||
function mousemove(e, data){
|
||||
checkThreshold(e, data, e, removeMouse);
|
||||
}
|
||||
|
||||
function mouseend(e, data) {
|
||||
removeMouse();
|
||||
}
|
||||
|
||||
function removeMouse() {
|
||||
off(document, mouseevents.move, mousemove);
|
||||
off(document, mouseevents.cancel, mouseend);
|
||||
}
|
||||
|
||||
function touchstart(e) {
|
||||
// Don't get in the way of interaction with form elements
|
||||
if (ignoreTags[e.target.tagName.toLowerCase()]) { return; }
|
||||
|
||||
var touch = e.changedTouches[0];
|
||||
|
||||
// iOS live updates the touch objects whereas Android gives us copies.
|
||||
// That means we can't trust the touchstart object to stay the same,
|
||||
// so we must copy the data. This object acts as a template for
|
||||
// movestart, move and moveend event objects.
|
||||
var data = {
|
||||
target: touch.target,
|
||||
pageX: touch.pageX,
|
||||
pageY: touch.pageY,
|
||||
identifier: touch.identifier,
|
||||
|
||||
// The only way to make handlers individually unbindable is by
|
||||
// making them unique.
|
||||
touchmove: function(e, data) { touchmove(e, data); },
|
||||
touchend: function(e, data) { touchend(e, data); }
|
||||
};
|
||||
|
||||
on(document, touchevents.move, data.touchmove, data);
|
||||
on(document, touchevents.cancel, data.touchend, data);
|
||||
}
|
||||
|
||||
function touchmove(e, data) {
|
||||
var touch = changedTouch(e, data);
|
||||
if (!touch) { return; }
|
||||
checkThreshold(e, data, touch, removeTouch);
|
||||
}
|
||||
|
||||
function touchend(e, data) {
|
||||
var touch = identifiedTouch(e.changedTouches, data.identifier);
|
||||
if (!touch) { return; }
|
||||
removeTouch(data);
|
||||
}
|
||||
|
||||
function removeTouch(data) {
|
||||
off(document, touchevents.move, data.touchmove);
|
||||
off(document, touchevents.cancel, data.touchend);
|
||||
}
|
||||
|
||||
function checkThreshold(e, data, touch, fn) {
|
||||
var distX = touch.pageX - data.pageX;
|
||||
var distY = touch.pageY - data.pageY;
|
||||
|
||||
// Do nothing if the threshold has not been crossed.
|
||||
if ((distX * distX) + (distY * distY) < (threshold * threshold)) { return; }
|
||||
|
||||
triggerStart(e, data, touch, distX, distY, fn);
|
||||
}
|
||||
|
||||
function triggerStart(e, data, touch, distX, distY, fn) {
|
||||
var touches = e.targetTouches;
|
||||
var time = e.timeStamp - data.timeStamp;
|
||||
|
||||
// Create a movestart object with some special properties that
|
||||
// are passed only to the movestart handlers.
|
||||
var template = {
|
||||
altKey: e.altKey,
|
||||
ctrlKey: e.ctrlKey,
|
||||
shiftKey: e.shiftKey,
|
||||
startX: data.pageX,
|
||||
startY: data.pageY,
|
||||
distX: distX,
|
||||
distY: distY,
|
||||
deltaX: distX,
|
||||
deltaY: distY,
|
||||
pageX: touch.pageX,
|
||||
pageY: touch.pageY,
|
||||
velocityX: distX / time,
|
||||
velocityY: distY / time,
|
||||
identifier: data.identifier,
|
||||
targetTouches: touches,
|
||||
finger: touches ? touches.length : 1,
|
||||
enableMove: function() {
|
||||
this.moveEnabled = true;
|
||||
this.enableMove = noop;
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
// Trigger the movestart event.
|
||||
trigger(data.target, 'movestart', template);
|
||||
|
||||
// Unbind handlers that tracked the touch or mouse up till now.
|
||||
fn(data);
|
||||
}
|
||||
|
||||
|
||||
// Handlers that control what happens following a movestart
|
||||
|
||||
function activeMousemove(e, data) {
|
||||
var timer = data.timer;
|
||||
|
||||
data.touch = e;
|
||||
data.timeStamp = e.timeStamp;
|
||||
timer.kick();
|
||||
}
|
||||
|
||||
function activeMouseend(e, data) {
|
||||
var target = data.target;
|
||||
var event = data.event;
|
||||
var timer = data.timer;
|
||||
|
||||
removeActiveMouse();
|
||||
|
||||
endEvent(target, event, timer, function() {
|
||||
// Unbind the click suppressor, waiting until after mouseup
|
||||
// has been handled.
|
||||
setTimeout(function(){
|
||||
off(target, 'click', preventDefault);
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
function removeActiveMouse() {
|
||||
off(document, mouseevents.move, activeMousemove);
|
||||
off(document, mouseevents.end, activeMouseend);
|
||||
}
|
||||
|
||||
function activeTouchmove(e, data) {
|
||||
var event = data.event;
|
||||
var timer = data.timer;
|
||||
var touch = changedTouch(e, event);
|
||||
|
||||
if (!touch) { return; }
|
||||
|
||||
// Stop the interface from gesturing
|
||||
e.preventDefault();
|
||||
|
||||
event.targetTouches = e.targetTouches;
|
||||
data.touch = touch;
|
||||
data.timeStamp = e.timeStamp;
|
||||
|
||||
timer.kick();
|
||||
}
|
||||
|
||||
function activeTouchend(e, data) {
|
||||
var target = data.target;
|
||||
var event = data.event;
|
||||
var timer = data.timer;
|
||||
var touch = identifiedTouch(e.changedTouches, event.identifier);
|
||||
|
||||
// This isn't the touch you're looking for.
|
||||
if (!touch) { return; }
|
||||
|
||||
removeActiveTouch(data);
|
||||
endEvent(target, event, timer);
|
||||
}
|
||||
|
||||
function removeActiveTouch(data) {
|
||||
off(document, touchevents.move, data.activeTouchmove);
|
||||
off(document, touchevents.end, data.activeTouchend);
|
||||
}
|
||||
|
||||
|
||||
// Logic for triggering move and moveend events
|
||||
|
||||
function updateEvent(event, touch, timeStamp) {
|
||||
var time = timeStamp - event.timeStamp;
|
||||
|
||||
event.distX = touch.pageX - event.startX;
|
||||
event.distY = touch.pageY - event.startY;
|
||||
event.deltaX = touch.pageX - event.pageX;
|
||||
event.deltaY = touch.pageY - event.pageY;
|
||||
|
||||
// Average the velocity of the last few events using a decay
|
||||
// curve to even out spurious jumps in values.
|
||||
event.velocityX = 0.3 * event.velocityX + 0.7 * event.deltaX / time;
|
||||
event.velocityY = 0.3 * event.velocityY + 0.7 * event.deltaY / time;
|
||||
event.pageX = touch.pageX;
|
||||
event.pageY = touch.pageY;
|
||||
}
|
||||
|
||||
function endEvent(target, event, timer, fn) {
|
||||
timer.end(function(){
|
||||
trigger(target, 'moveend', event);
|
||||
return fn && fn();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Set up the DOM
|
||||
|
||||
function movestart(e) {
|
||||
if (e.defaultPrevented) { return; }
|
||||
if (!e.moveEnabled) { return; }
|
||||
|
||||
var event = {
|
||||
startX: e.startX,
|
||||
startY: e.startY,
|
||||
pageX: e.pageX,
|
||||
pageY: e.pageY,
|
||||
distX: e.distX,
|
||||
distY: e.distY,
|
||||
deltaX: e.deltaX,
|
||||
deltaY: e.deltaY,
|
||||
velocityX: e.velocityX,
|
||||
velocityY: e.velocityY,
|
||||
identifier: e.identifier,
|
||||
targetTouches: e.targetTouches,
|
||||
finger: e.finger
|
||||
};
|
||||
|
||||
var data = {
|
||||
target: e.target,
|
||||
event: event,
|
||||
timer: new Timer(update),
|
||||
touch: undefined,
|
||||
timeStamp: e.timeStamp
|
||||
};
|
||||
|
||||
function update(time) {
|
||||
updateEvent(event, data.touch, data.timeStamp);
|
||||
trigger(data.target, 'move', event);
|
||||
}
|
||||
|
||||
if (e.identifier === undefined) {
|
||||
// We're dealing with a mouse event.
|
||||
// Stop clicks from propagating during a move
|
||||
on(e.target, 'click', preventDefault);
|
||||
on(document, mouseevents.move, activeMousemove, data);
|
||||
on(document, mouseevents.end, activeMouseend, data);
|
||||
}
|
||||
else {
|
||||
// In order to unbind correct handlers they have to be unique
|
||||
data.activeTouchmove = function(e, data) { activeTouchmove(e, data); };
|
||||
data.activeTouchend = function(e, data) { activeTouchend(e, data); };
|
||||
|
||||
// We're dealing with a touch.
|
||||
on(document, touchevents.move, data.activeTouchmove, data);
|
||||
on(document, touchevents.end, data.activeTouchend, data);
|
||||
}
|
||||
}
|
||||
|
||||
on(document, 'mousedown', mousedown);
|
||||
on(document, 'touchstart', touchstart);
|
||||
on(document, 'movestart', movestart);
|
||||
|
||||
|
||||
// jQuery special events
|
||||
//
|
||||
// jQuery event objects are copies of DOM event objects. They need
|
||||
// a little help copying the move properties across.
|
||||
|
||||
if (!window.jQuery) { return; }
|
||||
|
||||
var properties = ("startX startY pageX pageY distX distY deltaX deltaY velocityX velocityY").split(' ');
|
||||
|
||||
function enableMove1(e) { e.enableMove(); }
|
||||
function enableMove2(e) { e.enableMove(); }
|
||||
function enableMove3(e) { e.enableMove(); }
|
||||
|
||||
function add(handleObj) {
|
||||
var handler = handleObj.handler;
|
||||
|
||||
handleObj.handler = function(e) {
|
||||
// Copy move properties across from originalEvent
|
||||
var i = properties.length;
|
||||
var property;
|
||||
|
||||
while(i--) {
|
||||
property = properties[i];
|
||||
e[property] = e.originalEvent[property];
|
||||
}
|
||||
|
||||
handler.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
jQuery.event.special.movestart = {
|
||||
setup: function() {
|
||||
// Movestart must be enabled to allow other move events
|
||||
on(this, 'movestart', enableMove1);
|
||||
|
||||
// Do listen to DOM events
|
||||
return false;
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
off(this, 'movestart', enableMove1);
|
||||
return false;
|
||||
},
|
||||
|
||||
add: add
|
||||
};
|
||||
|
||||
jQuery.event.special.move = {
|
||||
setup: function() {
|
||||
on(this, 'movestart', enableMove2);
|
||||
return false;
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
off(this, 'movestart', enableMove2);
|
||||
return false;
|
||||
},
|
||||
|
||||
add: add
|
||||
};
|
||||
|
||||
jQuery.event.special.moveend = {
|
||||
setup: function() {
|
||||
on(this, 'movestart', enableMove3);
|
||||
return false;
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
off(this, 'movestart', enableMove3);
|
||||
return false;
|
||||
},
|
||||
|
||||
add: add
|
||||
};
|
||||
});
|
||||
1
wp/wp-content/plugins/imagify/assets/js/jquery.event.move.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/jquery.event.move.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
708
wp/wp-content/plugins/imagify/assets/js/jquery.twentytwenty.js
Normal file
708
wp/wp-content/plugins/imagify/assets/js/jquery.twentytwenty.js
Normal file
@@ -0,0 +1,708 @@
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
$.fn.twentytwenty = function( options, callback ) {
|
||||
options = $.extend( {
|
||||
handlePosition: 0.5,
|
||||
orientation: 'horizontal',
|
||||
labelBefore: 'Before',
|
||||
labelAfter: 'After'
|
||||
}, options );
|
||||
|
||||
return this.each( function() {
|
||||
var sliderPct = options.handlePosition,
|
||||
$container = $( this ),
|
||||
sliderOrientation = options.orientation,
|
||||
beforeDirection = ( 'vertical' === sliderOrientation ) ? 'down' : 'left',
|
||||
afterDirection = ( 'vertical' === sliderOrientation ) ? 'up' : 'right',
|
||||
$beforeImg = $container.find( 'img:first' ),
|
||||
$afterImg = $container.find( 'img:last' ),
|
||||
offsetX = 0,
|
||||
offsetY = 0,
|
||||
imgWidth = 0,
|
||||
imgHeight = 0,
|
||||
$slider, $overlay,
|
||||
calcOffset = function( dimensionPct ) {
|
||||
var width = parseInt( $beforeImg.width(), 10 ),
|
||||
height = parseInt( $beforeImg.height(), 10 );
|
||||
|
||||
if ( ! width || ! height ) {
|
||||
width = parseInt( $beforeImg.attr( 'width' ), 10 );
|
||||
height = parseInt( $beforeImg.attr( 'height' ), 10 );
|
||||
}
|
||||
|
||||
return {
|
||||
w: width + "px",
|
||||
h: height + "px",
|
||||
cw: ( dimensionPct * width ) + "px",
|
||||
ch: ( dimensionPct * height ) + "px"
|
||||
};
|
||||
},
|
||||
adjustContainer = function( offset ) {
|
||||
// Make it dynamic, in case the "before" image changes.
|
||||
var $beforeImage = $container.find( '.twentytwenty-before' );
|
||||
|
||||
if ( 'vertical' === sliderOrientation ) {
|
||||
$beforeImage.css( 'clip', 'rect(0,' + offset.w + ',' + offset.ch + ',0)' );
|
||||
} else {
|
||||
$beforeImage.css( 'clip', 'rect(0,' + offset.cw + ',' + offset.h + ',0)' );
|
||||
}
|
||||
|
||||
$container.css( 'height', offset.h );
|
||||
|
||||
if ( typeof callback === 'function' ) {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
adjustSlider = function( pct ) {
|
||||
var offset = calcOffset( pct );
|
||||
|
||||
if ( 'vertical' === sliderOrientation ) {
|
||||
$slider.css( 'top', offset.ch );
|
||||
} else {
|
||||
$slider.css( 'left', offset.cw );
|
||||
}
|
||||
|
||||
adjustContainer( offset );
|
||||
};
|
||||
|
||||
|
||||
if ( $container.parent( '.twentytwenty-wrapper' ).length ) {
|
||||
$container.unwrap();
|
||||
}
|
||||
$container.wrap( '<div class="twentytwenty-wrapper twentytwenty-' + sliderOrientation + '"></div>' );
|
||||
|
||||
$container.children( '.twentytwenty-overlay, .twentytwenty-handle' ).remove();
|
||||
$container.append( '<div class="twentytwenty-overlay"></div>' );
|
||||
$container.append( '<div class="twentytwenty-handle"></div>' );
|
||||
|
||||
$slider = $container.find( '.twentytwenty-handle' );
|
||||
|
||||
$slider.append( '<span class="twentytwenty-' + beforeDirection + '-arrow"></span>' );
|
||||
$slider.append( '<span class="twentytwenty-' + afterDirection + '-arrow"></span>' );
|
||||
$container.addClass( 'twentytwenty-container' );
|
||||
$beforeImg.addClass( 'twentytwenty-before' );
|
||||
$afterImg.addClass( 'twentytwenty-after' );
|
||||
|
||||
$overlay = $container.find( '.twentytwenty-overlay' );
|
||||
|
||||
$overlay.append( '<div class="twentytwenty-labels twentytwenty-before-label"><span class="twentytwenty-label-content">' + options.labelBefore + '</span></div>' );
|
||||
$overlay.append( '<div class="twentytwenty-labels twentytwenty-after-label"><span class="twentytwenty-label-content">' + options.labelAfter + '</span></div>' );
|
||||
|
||||
$( w ).on( 'resize.twentytwenty', function() {
|
||||
adjustSlider( sliderPct );
|
||||
} );
|
||||
|
||||
$slider.on( 'movestart', function( e ) {
|
||||
if ( 'vertical' !== sliderOrientation && ( ( e.distX > e.distY && e.distX < -e.distY ) || ( e.distX < e.distY && e.distX > -e.distY ) ) ) {
|
||||
e.preventDefault();
|
||||
} else if ( 'vertical' === sliderOrientation && ( ( e.distX < e.distY && e.distX < -e.distY ) || ( e.distX > e.distY && e.distX > -e.distY ) ) ) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
$container.addClass( 'active' );
|
||||
|
||||
offsetX = $container.offset().left;
|
||||
offsetY = $container.offset().top;
|
||||
imgWidth = $beforeImg.width();
|
||||
imgHeight = $beforeImg.height();
|
||||
} );
|
||||
|
||||
$slider.on( 'moveend', function() {
|
||||
$container.removeClass( 'active' );
|
||||
} );
|
||||
|
||||
$slider.on( 'move', function( e ) {
|
||||
if ( $container.hasClass('active') ) {
|
||||
sliderPct = 'vertical' === sliderOrientation ? ( e.pageY - offsetY ) / imgHeight : ( e.pageX - offsetX ) / imgWidth;
|
||||
|
||||
if ( sliderPct < 0 ) {
|
||||
sliderPct = 0;
|
||||
} else if ( sliderPct > 1 ) {
|
||||
sliderPct = 1;
|
||||
}
|
||||
|
||||
adjustSlider( sliderPct );
|
||||
}
|
||||
} );
|
||||
|
||||
$container.find( 'img' ).on( 'mousedown', function( e ) {
|
||||
e.preventDefault();
|
||||
} );
|
||||
|
||||
$( w ).trigger( 'resize.twentytwenty' );
|
||||
} );
|
||||
};
|
||||
|
||||
} )(jQuery, document, window);
|
||||
|
||||
/**
|
||||
* Twentytwenty Imagify Init
|
||||
*/
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
/*
|
||||
* Mini chart
|
||||
*
|
||||
* @param {element} canvas
|
||||
*/
|
||||
var drawMeAChart = function ( canvas ) {
|
||||
canvas.each( function() {
|
||||
var value = parseInt( $( this ).closest( '.imagify-chart' ).next( '.imagify-chart-value' ).text(), 10 );
|
||||
|
||||
new w.imagify.Chart( this, { // eslint-disable-line no-new
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: [ value, 100 - value ],
|
||||
backgroundColor: [ '#00B3D3', '#D8D8D8' ],
|
||||
borderColor: '#2A2E3C',
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
events: [],
|
||||
animation: {
|
||||
easing: 'easeOutBounce'
|
||||
},
|
||||
tooltips: {
|
||||
enabled: false
|
||||
},
|
||||
responsive: false,
|
||||
cutoutPercentage: 60
|
||||
}
|
||||
} );
|
||||
} );
|
||||
},
|
||||
/**
|
||||
* Dynamic modal
|
||||
*
|
||||
* @param {object} Parameters to build modal with datas
|
||||
*/
|
||||
imagifyTwentyModal = function( options ) {
|
||||
var defaults = {
|
||||
width: 0, //px
|
||||
height: 0, //px
|
||||
originalUrl: '', //url
|
||||
optimizedUrl: '', //url
|
||||
originalSize: 0, //mb
|
||||
optimizedSize: 0, // mb
|
||||
saving: 0, //percent
|
||||
modalAppendTo: $( 'body' ), // jQuery element
|
||||
trigger: $( '[data-target="imagify-visual-comparison"]' ), // jQuery element (button, link) with data-target="modalId"
|
||||
modalId: 'imagify-visual-comparison', // should be dynamic if multiple modals
|
||||
openModal: false
|
||||
},
|
||||
settings = $.extend( {}, defaults, options ),
|
||||
modalHtml;
|
||||
|
||||
if ( 0 === settings.width || 0 === settings.height || '' === settings.originalUrl || '' === settings.optimizedUrl || 0 === settings.originalSize || 0 === settings.optimizedSize || 0 === settings.saving ) {
|
||||
return 'error';
|
||||
}
|
||||
|
||||
// create modal box
|
||||
modalHtml = '<div id="' + settings.modalId + '" class="imagify-modal imagify-visual-comparison" aria-hidden="true">';
|
||||
/* eslint-disable indent */
|
||||
modalHtml += '<div class="imagify-modal-content loading">';
|
||||
modalHtml += '<div class="twentytwenty-container">';
|
||||
modalHtml += '<img class="imagify-img-before" alt="" width="' + settings.width + '" height="' + settings.height + '">';
|
||||
modalHtml += '<img class="imagify-img-after" alt="" width="' + settings.width + '" height="' + settings.height + '">';
|
||||
modalHtml += '</div>';
|
||||
modalHtml += '<div class="imagify-comparison-levels">';
|
||||
modalHtml += '<div class="imagify-c-level imagify-level-original go-left">';
|
||||
modalHtml += '<p class="imagify-c-level-row">';
|
||||
modalHtml += '<span class="label">' + imagifyTTT.labels.filesize + '</span>';
|
||||
modalHtml += '<span class="value level">' + settings.originalSize + '</span>';
|
||||
modalHtml += '</p>';
|
||||
modalHtml += '</div>';
|
||||
modalHtml += '<div class="imagify-c-level imagify-level-optimized go-right">';
|
||||
modalHtml += '<p class="imagify-c-level-row">';
|
||||
modalHtml += '<span class="label">' + imagifyTTT.labels.filesize + '</span>';
|
||||
modalHtml += '<span class="value level">' + settings.optimizedSize + '</span>';
|
||||
modalHtml += '</p>';
|
||||
modalHtml += '<p class="imagify-c-level-row">';
|
||||
modalHtml += '<span class="label">' + imagifyTTT.labels.saving + '</span>';
|
||||
modalHtml += '<span class="value"><span class="imagify-chart"><span class="imagify-chart-container"><canvas id="imagify-consumption-chart-normal" width="15" height="15"></canvas></span></span><span class="imagify-chart-value">' + settings.saving + '</span>%</span>';
|
||||
modalHtml += '</p>';
|
||||
modalHtml += '</div>';
|
||||
modalHtml += '</div>';
|
||||
modalHtml += '<button class="close-btn absolute" type="button"><i aria-hidden="true" class="dashicons dashicons-no-alt"></i><span class="screen-reader-text">' + imagifyTTT.labels.close + '</span></button>';
|
||||
modalHtml += '</div>';
|
||||
/* eslint-enable indent */
|
||||
modalHtml += '</div>';
|
||||
|
||||
settings.modalAppendTo.append( modalHtml );
|
||||
|
||||
settings.trigger.on( 'click.imagify', function( e ) {
|
||||
var $modal = $( $( this ).data( 'target' ) ),
|
||||
imgsLoaded = 0,
|
||||
$tt, checkLoad;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if ( settings.openModal ) {
|
||||
w.imagify.openModal( $( this ) );
|
||||
}
|
||||
|
||||
$modal.find( '.imagify-modal-content' ).css( {
|
||||
'width': ( $( w ).outerWidth() * 0.85 ) + 'px',
|
||||
'max-width': settings.width
|
||||
} );
|
||||
|
||||
// Load before img.
|
||||
$modal.find( '.imagify-img-before' ).on( 'load', function() {
|
||||
imgsLoaded++;
|
||||
} ).attr( 'src', settings.originalUrl );
|
||||
|
||||
// Load after img.
|
||||
$modal.find( '.imagify-img-after' ).on( 'load', function() {
|
||||
imgsLoaded++;
|
||||
} ).attr( 'src', settings.optimizedUrl + ( settings.optimizedUrl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'v=' + Date.now() );
|
||||
|
||||
$tt = $modal.find( '.twentytwenty-container' );
|
||||
checkLoad = setInterval( function() {
|
||||
if ( 2 !== imgsLoaded ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tt.twentytwenty( {
|
||||
handlePosition: 0.3,
|
||||
orientation: 'horizontal',
|
||||
labelBefore: imagifyTTT.labels.originalL,
|
||||
labelAfter: imagifyTTT.labels.optimizedL
|
||||
}, function() {
|
||||
var windowH = $( w ).height(),
|
||||
ttH = $modal.find( '.twentytwenty-container' ).height(),
|
||||
ttTop = $modal.find( '.twentytwenty-wrapper' ).position().top,
|
||||
$handle, $labels, $datas, datasH, handlePos, labelsPos;
|
||||
|
||||
if ( ! $tt.closest( '.imagify-modal-content' ).hasClass( 'loaded' ) ) {
|
||||
$tt.closest( '.imagify-modal-content' ).removeClass( 'loading' ).addClass( 'loaded' );
|
||||
drawMeAChart( $modal.find( '.imagify-level-optimized .imagify-chart canvas' ) );
|
||||
}
|
||||
|
||||
// Check if image height is to big.
|
||||
if ( windowH < ttH && ! $modal.hasClass( 'modal-is-too-high' ) ) {
|
||||
$modal.addClass( 'modal-is-too-high' );
|
||||
|
||||
$handle = $modal.find( '.twentytwenty-handle' );
|
||||
$labels = $modal.find( '.twentytwenty-label-content' );
|
||||
$datas = $modal.find( '.imagify-comparison-levels' );
|
||||
datasH = $datas.outerHeight();
|
||||
handlePos = ( windowH - ttTop - $handle.height() ) / 2;
|
||||
labelsPos = ( windowH - ttTop * 3 - datasH );
|
||||
|
||||
$handle.css( {
|
||||
top: handlePos
|
||||
} );
|
||||
$labels.css( {
|
||||
top: labelsPos,
|
||||
bottom: 'auto'
|
||||
} );
|
||||
$modal.find( '.twentytwenty-wrapper' ).css( {
|
||||
paddingBottom: datasH
|
||||
} );
|
||||
$modal.find( '.imagify-modal-content' ).on( 'scroll.imagify', function() {
|
||||
var scrollTop = $( this ).scrollTop();
|
||||
|
||||
$handle.css( {
|
||||
top: handlePos + scrollTop
|
||||
} );
|
||||
$labels.css( {
|
||||
top: labelsPos + scrollTop
|
||||
} );
|
||||
$datas.css( {
|
||||
bottom: -scrollTop
|
||||
} );
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
clearInterval( checkLoad );
|
||||
checkLoad = null;
|
||||
return 'done';
|
||||
}, 75 );
|
||||
} );
|
||||
}; // imagifyTwentyModal( options );
|
||||
|
||||
|
||||
/**
|
||||
* The complexe visual comparison
|
||||
*/
|
||||
$( '.imagify-visual-comparison-btn' ).on( 'click', function() {
|
||||
var $tt, imgsLoaded, loader,
|
||||
labelOriginal, labelNormal, labelAggressive, labelUltra,
|
||||
originalLabel, originalAlt, originalSrc, originalDim,
|
||||
normalAlt, normalSrc, normalDim,
|
||||
aggressiveAlt, aggressiveSrc, aggressiveDim,
|
||||
ultraLabel, ultraAlt, ultraSrc, ultraDim,
|
||||
ttBeforeButtons, ttAfterButtons, image50, twentyMe;
|
||||
|
||||
if ( $( '.twentytwenty-wrapper' ).length === 1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$( $( this ).data( 'target' ) ).find( '.imagify-modal-content' ).css( 'width', ( $( w ).outerWidth() * 0.95 ) + 'px' );
|
||||
|
||||
if ( $( '.twentytwenty-container' ).length > 0 && $( w ).outerWidth() <= 800 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tt = $( '.twentytwenty-container' );
|
||||
imgsLoaded = 0;
|
||||
loader = $tt.data( 'loader' );
|
||||
labelOriginal = $tt.data( 'label-original' );
|
||||
labelNormal = $tt.data( 'label-normal' );
|
||||
labelAggressive = $tt.data( 'label-aggressive' );
|
||||
labelUltra = $tt.data( 'label-ultra' );
|
||||
|
||||
originalLabel = $tt.data( 'original-label' ).replace( /\*\*/, '<strong>' ).replace( /\*\*/, '</strong>' );
|
||||
originalAlt = $tt.data( 'original-alt' );
|
||||
originalSrc = $tt.data( 'original-img' );
|
||||
originalDim = $tt.data( 'original-dim' ).split( 'x' );
|
||||
|
||||
normalAlt = $tt.data( 'normal-alt' );
|
||||
normalSrc = $tt.data( 'normal-img' );
|
||||
normalDim = $tt.data( 'normal-dim' ).split( 'x' );
|
||||
|
||||
aggressiveAlt = $tt.data( 'aggressive-alt' );
|
||||
aggressiveSrc = $tt.data( 'aggressive-img' );
|
||||
aggressiveDim = $tt.data( 'aggressive-dim' ).split( 'x' );
|
||||
|
||||
ultraLabel = $tt.data( 'ultra-label' ).replace( /\*\*/, '<strong>' ).replace( /\*\*/, '</strong>' );
|
||||
ultraAlt = $tt.data( 'ultra-alt' );
|
||||
ultraSrc = $tt.data( 'ultra-img' );
|
||||
ultraDim = $tt.data( 'ultra-dim' ).split( 'x' );
|
||||
|
||||
ttBeforeButtons = '<span class="twentytwenty-duo-buttons twentytwenty-duo-left">';
|
||||
/* eslint-disable indent */
|
||||
ttBeforeButtons += '<button type="button" class="imagify-comparison-original selected" data-img="original">' + labelOriginal + '</button>';
|
||||
ttBeforeButtons += '<button type="button" class="imagify-comparison-normal" data-img="normal">' + labelNormal + '</button>';
|
||||
ttBeforeButtons += '<button type="button" class="imagify-comparison-aggressive" data-img="aggressive">' + labelAggressive + '</button>';
|
||||
/* eslint-enable indent */
|
||||
ttBeforeButtons += '</span>';
|
||||
ttAfterButtons = '<span class="twentytwenty-duo-buttons twentytwenty-duo-right">';
|
||||
/* eslint-disable indent */
|
||||
ttAfterButtons += '<button type="button" class="imagify-comparison-normal" data-img="normal">' + labelNormal + '</button>';
|
||||
ttAfterButtons += '<button type="button" class="imagify-comparison-aggressive" data-img="aggressive">' + labelAggressive + '</button>';
|
||||
ttAfterButtons += '<button type="button" class="imagify-comparison-ultra selected" data-img="ultra">' + labelUltra + '</button>';
|
||||
/* eslint-enable indent */
|
||||
ttAfterButtons += '</span>';
|
||||
|
||||
// Loader.
|
||||
$tt.before( '<img class="loader" src="' + loader + '" alt="Loading…" width="64" height="64">' );
|
||||
|
||||
// Should be more locally integrated...
|
||||
$( '.twentytwenty-left-buttons' ).append( ttBeforeButtons );
|
||||
$( '.twentytwenty-right-buttons' ).append( ttAfterButtons );
|
||||
|
||||
image50 = '<img class="img-original" alt="' + originalAlt + '" width="' + originalDim[0] + '" height="' + originalDim[1] + '">';
|
||||
image50 += '<img class="img-normal" alt="' + normalAlt + '" width="' + normalDim[0] + '" height="' + normalDim[1] + '">';
|
||||
image50 += '<img class="img-aggressive" alt="' + aggressiveAlt + '" width="' + aggressiveDim[0] + '" height="' + aggressiveDim[1] + '">';
|
||||
image50 += '<img class="img-ultra" alt="' + ultraAlt + '" width="' + ultraDim[0] + '" height="' + ultraDim[1] + '">';
|
||||
// Add switchers button only if needed.
|
||||
// Should be more locally integrated...
|
||||
image50 += $( '.twentytwenty-left-buttons' ).lenght ? ttBeforeButtons + ttAfterButtons : '';
|
||||
|
||||
// Add images to 50/50 area.
|
||||
$tt.closest( '.imagify-modal-content' ).addClass( 'loading' ).find( '.twentytwenty-container' ).append( image50 );
|
||||
|
||||
// Load image original.
|
||||
$( '.img-original' ).on( 'load', function() {
|
||||
imgsLoaded++;
|
||||
} ).attr( 'src', originalSrc );
|
||||
|
||||
// Load image normal.
|
||||
$( '.img-normal' ).on( 'load', function() {
|
||||
imgsLoaded++;
|
||||
} ).attr( 'src', normalSrc );
|
||||
|
||||
// Load image aggressive.
|
||||
$( '.img-aggressive' ).on( 'load', function() {
|
||||
imgsLoaded++;
|
||||
} ).attr( 'src', aggressiveSrc );
|
||||
|
||||
// Load image ultra.
|
||||
$( '.img-ultra' ).on( 'load', function() {
|
||||
imgsLoaded++;
|
||||
} ).attr( 'src', ultraSrc );
|
||||
|
||||
twentyMe = setInterval( function() {
|
||||
if ( 4 !== imgsLoaded ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tt.twentytwenty({
|
||||
handlePosition: 0.6,
|
||||
orientation: 'horizontal',
|
||||
labelBefore: originalLabel,
|
||||
labelAfter: ultraLabel
|
||||
}, function() {
|
||||
// Fires on initialisation & each time the handle is moving.
|
||||
if ( ! $tt.closest( '.imagify-modal-content' ).hasClass( 'loaded' ) ) {
|
||||
$tt.closest( '.imagify-modal-content' ).removeClass( 'loading' ).addClass( 'loaded' );
|
||||
drawMeAChart( $( '.imagify-level-ultra .imagify-chart canvas' ) );
|
||||
}
|
||||
} );
|
||||
|
||||
clearInterval( twentyMe );
|
||||
twentyMe = null;
|
||||
}, 75);
|
||||
|
||||
// On click on button choices.
|
||||
$( '.imagify-comparison-title' ).on( 'click', '.twentytwenty-duo-buttons button:not(.selected)', function( e ) {
|
||||
var $this = $( this ),
|
||||
$container = $this.closest( '.imagify-comparison-title' ).nextAll( '.twentytwenty-wrapper' ).find( '.twentytwenty-container' ),
|
||||
side = $this.closest( '.twentytwenty-duo-buttons' ).hasClass( 'twentytwenty-duo-left' ) ? 'left' : 'right',
|
||||
$otherSide = 'left' === side ? $this.closest( '.imagify-comparison-title' ).find( '.twentytwenty-duo-right' ) : $this.closest( '.imagify-comparison-title' ).find( '.twentytwenty-duo-left' ),
|
||||
$duo = $this.closest( '.twentytwenty-duo-buttons' ).find( 'button' ),
|
||||
$imgBefore = $container.find( '.twentytwenty-before' ),
|
||||
$imgAfter = $container.find( '.twentytwenty-after' ),
|
||||
image = $this.data( 'img' ),
|
||||
clipStyles;
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
// Button coloration.
|
||||
$duo.removeClass( 'selected' );
|
||||
$this.addClass( 'selected' );
|
||||
|
||||
// Other side action (to not compare same images).
|
||||
if ( $otherSide.find( '.selected' ).data( 'img' ) === image ) {
|
||||
$otherSide.find( 'button:not(.selected)' ).eq( 0 ).trigger( 'click' );
|
||||
}
|
||||
|
||||
// Left buttons.
|
||||
if ( 'left' === side ) {
|
||||
clipStyles = $imgBefore.css( 'clip' );
|
||||
$imgBefore.attr( 'style', '' );
|
||||
$imgBefore.removeClass( 'twentytwenty-before' );
|
||||
$container.find( '.img-' + image ).addClass( 'twentytwenty-before' ).css( 'clip', clipStyles );
|
||||
$( '.twentytwenty-before-label .twentytwenty-label-content' ).text( $container.data( image + '-label' ) );
|
||||
$( '.imagify-c-level.go-left' ).attr( 'aria-hidden', 'true' ).removeClass( 'go-left go-right' );
|
||||
$( '.imagify-level-' + image ).attr( 'aria-hidden', 'false' ).addClass( 'go-left' );
|
||||
}
|
||||
|
||||
// Right buttons.
|
||||
if ( 'right' === side ) {
|
||||
$imgAfter.removeClass( 'twentytwenty-after' );
|
||||
$container.find( '.img-' + image ).addClass( 'twentytwenty-after' );
|
||||
$( '.twentytwenty-after-label .twentytwenty-label-content' ).text( $container.data( image + '-label' ) );
|
||||
$( '.imagify-c-level.go-right' ).attr( 'aria-hidden', 'true' ).removeClass( 'go-left go-right' );
|
||||
$( '.imagify-level-' + image ).attr( 'aria-hidden', 'false' ).addClass( 'go-right' );
|
||||
}
|
||||
|
||||
drawMeAChart( $( '.imagify-level-' + image + ' .imagify-chart canvas' ) );
|
||||
} );
|
||||
} );
|
||||
|
||||
|
||||
/**
|
||||
* Imagify comparison inside Media post edition.
|
||||
*/
|
||||
if ( imagifyTTT.imageWidth && $( '.post-php .wp_attachment_image .thumbnail' ).length > 0 ) {
|
||||
|
||||
var $oriParent = $( '.post-php .wp_attachment_image' ),
|
||||
oriSource = { src: $( '#imagify-full-original' ).val(), size: $( '#imagify-full-original-size' ).val() },
|
||||
$optimizeBtn = $( '#misc-publishing-actions' ).find( '.misc-pub-imagify .button-primary' ),
|
||||
filesize, saving;
|
||||
|
||||
imagifyTTT.widthLimit = parseInt( imagifyTTT.widthLimit, 10 );
|
||||
|
||||
// If shown image > 360, use twentytwenty.
|
||||
if ( imagifyTTT.imageWidth > imagifyTTT.widthLimit && oriSource.src ) {
|
||||
|
||||
filesize = $( '.misc-pub-filesize strong' ).text();
|
||||
saving = $( '.imagify-data-item .imagify-chart-value' ).text();
|
||||
|
||||
// Create button to trigger.
|
||||
$( '[id^="imgedit-open-btn-"]' ).before( '<button type="button" class="imagify-button-primary button-primary imagify-modal-trigger" data-target="#imagify-visual-comparison" id="imagify-start-comparison">' + imagifyTTT.labels.compare + '</button>' );
|
||||
|
||||
// Modal and trigger event creation.
|
||||
imagifyTwentyModal( {
|
||||
width: parseInt( imagifyTTT.imageWidth, 10 ),
|
||||
height: parseInt( imagifyTTT.imageHeight, 10 ),
|
||||
originalUrl: oriSource.src,
|
||||
optimizedUrl: imagifyTTT.imageSrc,
|
||||
originalSize: oriSource.size,
|
||||
optimizedSize: filesize,
|
||||
saving: saving,
|
||||
modalAppendTo: $oriParent,
|
||||
trigger: $( '#imagify-start-comparison' ),
|
||||
modalId: 'imagify-visual-comparison'
|
||||
} );
|
||||
}
|
||||
// Else put images next to next.
|
||||
else if ( imagifyTTT.imageWidth < imagifyTTT.widthLimit && oriSource.src ) {
|
||||
// TODO
|
||||
}
|
||||
// If image has no backup.
|
||||
else if ( $( '#imagify-full-original' ).length > 0 && '' === oriSource.src ) {
|
||||
// do nothing ?
|
||||
}
|
||||
// In case image is not optimized.
|
||||
else {
|
||||
// If is not in optimizing process, propose the Optimize button trigger.
|
||||
if ( $( '#misc-publishing-actions' ).find( '.misc-pub-imagify .button-primary' ).length === 1 ) {
|
||||
$( '[id^="imgedit-open-btn-"]' ).before( '<span class="spinner imagify-hidden"></span><a class="imagify-button-primary button-primary imagify-optimize-trigger" id="imagify-optimize-trigger" href="' + $optimizeBtn.attr( 'href' ) + '">' + imagifyTTT.labels.optimize + '</a>' );
|
||||
|
||||
$( '#imagify-optimize-trigger' ).on( 'click', function() {
|
||||
$( this ).prev( '.spinner' ).removeClass( 'imagify-hidden' ).addClass( 'is-active' );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Images comparison in attachments list page (upload.php).
|
||||
*/
|
||||
if ( $( '.upload-php .imagify-compare-images' ).length > 0 ) {
|
||||
|
||||
$( '.imagify-compare-images' ).each( function() {
|
||||
var $this = $( this ),
|
||||
id = $this.data( 'id' ),
|
||||
$datas = $this.closest( '#post-' + id ).find( '.column-imagify_optimized_file' );
|
||||
|
||||
// Modal and trigger event creation.
|
||||
imagifyTwentyModal( {
|
||||
width: parseInt( $this.data( 'full-width' ), 10 ),
|
||||
height: parseInt( $this.data( 'full-height' ), 10 ),
|
||||
originalUrl: $this.data( 'backup-src' ),
|
||||
optimizedUrl: $this.data( 'full-src' ),
|
||||
originalSize: $datas.find( '.original' ).text(),
|
||||
optimizedSize: $datas.find( '.imagify-data-item .big' ).text(),
|
||||
saving: $datas.find( '.imagify-chart-value' ).text(),
|
||||
modalAppendTo: $this.closest( '.column-primary' ),
|
||||
trigger: $this,
|
||||
modalId: 'imagify-comparison-' + id
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Images Comparison in Grid View modal.
|
||||
*/
|
||||
if ( $( '.upload-php' ).length > 0 ) {
|
||||
|
||||
var getVar = function( param ) {
|
||||
var vars = {};
|
||||
|
||||
w.location.href.replace(
|
||||
/[?&]+([^=&]+)=?([^&]*)?/gi,
|
||||
function( m, key, value ) {
|
||||
vars[ key ] = undefined !== value ? value : '';
|
||||
}
|
||||
);
|
||||
|
||||
if ( param ) {
|
||||
return vars[ param ] ? vars[ param ] : null;
|
||||
}
|
||||
return vars;
|
||||
},
|
||||
imagifyContentInModal = function() {
|
||||
var tempTimer = setInterval( function() {
|
||||
var $datas, originalSrc, $actions;
|
||||
|
||||
if ( ! $( '.media-modal .imagify-datas-details' ).length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
originalSrc = $( '#imagify-original-src' ).val();
|
||||
|
||||
if ( originalSrc ) {
|
||||
// Trigger creation.
|
||||
$actions = $( '.media-frame-content .attachment-actions' );
|
||||
|
||||
$actions.find( '#imagify-media-frame-comparison-btn' ).remove();
|
||||
$actions.prepend( '<button type="button" class="imagify-button-primary button-primary imagify-modal-trigger" data-target="#imagify-comparison-modal" id="imagify-media-frame-comparison-btn">' + imagifyTTT.labels.compare + '</button>' );
|
||||
|
||||
// Get datas.
|
||||
$datas = $( '.media-frame-content .compat-field-imagify' );
|
||||
|
||||
// Modal and trigger event creation.
|
||||
imagifyTwentyModal( {
|
||||
width: parseInt( $( '#imagify-full-width' ).val(), 10 ),
|
||||
height: parseInt( $( '#imagify-full-height' ).val(), 10 ),
|
||||
originalUrl: originalSrc,
|
||||
optimizedUrl: $( '#imagify-full-src' ).val(),
|
||||
originalSize: $( '#imagify-original-size' ).val(),
|
||||
optimizedSize: $datas.find( '.imagify-data-item .big' ).text(),
|
||||
saving: $datas.find( '.imagify-chart-value' ).text(),
|
||||
modalAppendTo: $( '.media-frame-content .thumbnail-image' ),
|
||||
trigger: $( '#imagify-media-frame-comparison-btn' ),
|
||||
modalId: 'imagify-comparison-modal',
|
||||
openModal: true
|
||||
} );
|
||||
}
|
||||
|
||||
clearInterval( tempTimer );
|
||||
tempTimer = null;
|
||||
}, 20 );
|
||||
};
|
||||
|
||||
// If attachment is clicked, or the "Previous" and "Next" buttons, build the modal inside the modal.
|
||||
$( '.upload-php' ).on( 'click', '.media-frame.mode-grid .attachment, .edit-media-header .left, .edit-media-header .right', function() {
|
||||
imagifyContentInModal();
|
||||
} );
|
||||
|
||||
// If attachment is mentionned in URL, build the modal inside the modal.
|
||||
if ( getVar( 'item' ) ) {
|
||||
imagifyContentInModal();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Images comparison in custom folders list page.
|
||||
*/
|
||||
if ( $( '#imagify-files-list-form' ).length > 0 ) {
|
||||
|
||||
var buildComparisonModal = function( $buttons ) {
|
||||
$buttons.each( function() {
|
||||
var $this = $( this ),
|
||||
id = $this.data( 'id' ),
|
||||
$datas = $this.closest( 'tr' ).find( '.column-optimization .imagify-data-item' );
|
||||
|
||||
$( '#imagify-comparison-' + id ).remove();
|
||||
|
||||
// Modal and trigger event creation.
|
||||
imagifyTwentyModal( {
|
||||
width: parseInt( $this.data( 'full-width' ), 10 ),
|
||||
height: parseInt( $this.data( 'full-height' ), 10 ),
|
||||
originalUrl: $this.data( 'backup-src' ),
|
||||
optimizedUrl: $this.data( 'full-src' ),
|
||||
originalSize: $datas.find( '.original' ).text(),
|
||||
optimizedSize: $datas.find( '.optimized' ).text(),
|
||||
saving: $datas.find( '.imagify-chart-value' ).text(),
|
||||
modalAppendTo: $this.closest( '.column-primary' ),
|
||||
trigger: $this,
|
||||
modalId: 'imagify-comparison-' + id
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the comparison tool window when a file row is updated via ajax, and the ones already printed.
|
||||
*/
|
||||
$( w ).on( 'comparisonprinted.imagify', function( e, id ) {
|
||||
var $buttons;
|
||||
|
||||
id = id || 0;
|
||||
|
||||
if ( id ) {
|
||||
$buttons = $( '#imagify-files-list-form' ).find( '.imagify-compare-images[data-id="' + id + '"]' );
|
||||
} else {
|
||||
$buttons = $( '#imagify-files-list-form' ).find( '.imagify-compare-images' );
|
||||
}
|
||||
|
||||
if ( $buttons.length ) {
|
||||
buildComparisonModal( $buttons );
|
||||
}
|
||||
} )
|
||||
.trigger( 'comparisonprinted.imagify' );
|
||||
}
|
||||
|
||||
} )(jQuery, document, window);
|
||||
1
wp/wp-content/plugins/imagify/assets/js/jquery.twentytwenty.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/jquery.twentytwenty.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
51
wp/wp-content/plugins/imagify/assets/js/library.js
Normal file
51
wp/wp-content/plugins/imagify/assets/js/library.js
Normal file
@@ -0,0 +1,51 @@
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
var bulkOpt;
|
||||
/**
|
||||
* Add a "Imagify'em all" in the select list.
|
||||
*/
|
||||
bulkOpt = '<option value="imagify-bulk|optimize">' + imagifyLibrary.labels.bulkActionsOptimize + '</option>';
|
||||
|
||||
if ( $( '.button-imagify-optimize-missing-sizes' ).length ) {
|
||||
// If we have items that have missing sizes.
|
||||
bulkOpt += '<option value="imagify-bulk|optimize_missing_sizes">' + imagifyLibrary.labels.bulkActionsOptimizeMissingSizes + '</option>';
|
||||
}
|
||||
|
||||
if ( imagifyLibrary.backupOption || $( '.attachment-has-backup' ).length ) {
|
||||
// If the backup option is enabled, or if we have items that can be restored.
|
||||
bulkOpt += '<option value="imagify-bulk|restore">' + imagifyLibrary.labels.bulkActionsRestore + '</option>';
|
||||
}
|
||||
|
||||
$( '.bulkactions select[name="action"] option:last-child' ).before( bulkOpt );
|
||||
$( '.bulkactions select[name="action2"] option:last-child' ).before( bulkOpt );
|
||||
$( '#bulkaction option:last-child' ).after( bulkOpt );
|
||||
|
||||
/**
|
||||
* Process optimization for all selected images.
|
||||
*/
|
||||
$( '#doaction' )
|
||||
.add( '#doaction2' )
|
||||
.add( '#bulkaction + [name="showThickbox"]' )
|
||||
.on( 'click', function( e ) {
|
||||
var value = $( this ).prev( 'select' ).val().split( '|' ),
|
||||
action, ids;
|
||||
|
||||
if ( 'imagify-bulk' !== value[0] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
action = value[1];
|
||||
ids = $( 'input[name^="media"]:checked, input[name^="doaction"]:checked' ).map( function() {
|
||||
return this.value;
|
||||
} ).get();
|
||||
|
||||
ids.forEach( function( id, index ) {
|
||||
setTimeout( function() {
|
||||
$( 'table .imagify-data-actions-container[data-id="' + id + '"] .button-imagify-' + action ).first().trigger( 'click' );
|
||||
}, index * 300 );
|
||||
} );
|
||||
} );
|
||||
|
||||
} )(jQuery, document, window);
|
||||
1
wp/wp-content/plugins/imagify/assets/js/library.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/library.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(o){var i='<option value="imagify-bulk|optimize">'+imagifyLibrary.labels.bulkActionsOptimize+"</option>";o(".button-imagify-optimize-missing-sizes").length&&(i+='<option value="imagify-bulk|optimize_missing_sizes">'+imagifyLibrary.labels.bulkActionsOptimizeMissingSizes+"</option>"),(imagifyLibrary.backupOption||o(".attachment-has-backup").length)&&(i+='<option value="imagify-bulk|restore">'+imagifyLibrary.labels.bulkActionsRestore+"</option>"),o('.bulkactions select[name="action"] option:last-child').before(i),o('.bulkactions select[name="action2"] option:last-child').before(i),o("#bulkaction option:last-child").after(i),o("#doaction").add("#doaction2").add('#bulkaction + [name="showThickbox"]').on("click",function(i){var a,t=o(this).prev("select").val().split("|");"imagify-bulk"===t[0]&&(i.preventDefault(),a=t[1],o('input[name^="media"]:checked, input[name^="doaction"]:checked').map(function(){return this.value}).get().forEach(function(i,t){setTimeout(function(){o('table .imagify-data-actions-container[data-id="'+i+'"] .button-imagify-'+a).first().trigger("click")},300*t)}))})}(jQuery,(document,window));
|
||||
334
wp/wp-content/plugins/imagify/assets/js/media-modal.js
Normal file
334
wp/wp-content/plugins/imagify/assets/js/media-modal.js
Normal file
@@ -0,0 +1,334 @@
|
||||
/**
|
||||
* Mini chart.
|
||||
*
|
||||
* @param {element} canvas The canvas element.
|
||||
*/
|
||||
window.imagify.drawMeAChart = function( canvas ) {
|
||||
canvas.each( function() {
|
||||
var value = parseInt( jQuery( this ).closest( '.imagify-chart' ).next( '.imagify-chart-value' ).text(), 10 );
|
||||
|
||||
new window.imagify.Chart( this, { // eslint-disable-line no-new
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
datasets: [ {
|
||||
data: [ value, 100 - value ],
|
||||
backgroundColor: [ '#00B3D3', '#D8D8D8' ],
|
||||
borderColor: '#fff',
|
||||
borderWidth: 1
|
||||
} ]
|
||||
},
|
||||
options: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
events: [],
|
||||
animation: {
|
||||
easing: 'easeOutBounce'
|
||||
},
|
||||
tooltips: {
|
||||
enabled: false
|
||||
},
|
||||
responsive: false
|
||||
}
|
||||
} );
|
||||
} );
|
||||
};
|
||||
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
w.imagify.modal = {
|
||||
|
||||
working: [],
|
||||
|
||||
/*
|
||||
* Init.
|
||||
*/
|
||||
init: function () {
|
||||
var $document = $( d ),
|
||||
$processing;
|
||||
|
||||
// Update the chart in the media modal when a media is selected, and the ones already printed.
|
||||
$( w ).on( 'canvasprinted.imagify', this.updateChart ).trigger( 'canvasprinted.imagify' );
|
||||
|
||||
// Toggle slide in custom column.
|
||||
$( '.imagify-datas-details' ).hide();
|
||||
|
||||
$document.on( 'click', '.imagify-datas-more-action a', this.toggleSlide );
|
||||
|
||||
// Optimize, restore, etc.
|
||||
$document.on( 'click', '.button-imagify-restore, .button-imagify-optimize, .button-imagify-manual-reoptimize, .button-imagify-optimize-missing-sizes, .button-imagify-generate-webp, .button-imagify-delete-webp', this.processOptimization );
|
||||
|
||||
$document.on( 'imagifybeat-send', this.addToImagifybeat );
|
||||
$document.on( 'imagifybeat-tick', this.processImagifybeat );
|
||||
|
||||
// Some items may be processed in background on page load.
|
||||
$processing = $( '.imagify-data-actions-container .button-imagify-processing' );
|
||||
|
||||
if ( $processing.length ) {
|
||||
// Some media are already being processed.
|
||||
// Lock the items, so we can check their status with Imagifybeat.
|
||||
$processing.closest( '.imagify-data-actions-container' ).each( function() {
|
||||
var $this = $( this ),
|
||||
id = w.imagify.modal.sanitizeId( $this.data( 'id' ) ),
|
||||
context = w.imagify.modal.sanitizeContext( $this.data( 'context' ) );
|
||||
|
||||
w.imagify.modal.lockItem( context, id );
|
||||
} );
|
||||
|
||||
// Fasten Imagifybeat.
|
||||
w.imagify.beat.interval( 15 );
|
||||
}
|
||||
},
|
||||
|
||||
// Charts ==================================================================================
|
||||
|
||||
/**
|
||||
* Update the chart in the media modal when a media is selected, and the ones already printed.
|
||||
*
|
||||
* @param {object} e Event.
|
||||
* @param {string} selector A CSS selector.
|
||||
*/
|
||||
updateChart: function( e, selector ) {
|
||||
var $canvas;
|
||||
|
||||
selector = selector || '.imagify-consumption-chart';
|
||||
$canvas = $( selector );
|
||||
|
||||
w.imagify.drawMeAChart( $canvas );
|
||||
|
||||
$canvas.closest( '.imagify-datas-list' ).siblings( '.imagify-datas-details' ).hide();
|
||||
},
|
||||
|
||||
// Optimization ============================================================================
|
||||
|
||||
/**
|
||||
* Process to one of these actions: restore, optimize, re-optimize, or optimize missing sizes.
|
||||
*
|
||||
* @param {object} e Event.
|
||||
*/
|
||||
processOptimization: function( e ) {
|
||||
var $obj = $( this ),
|
||||
$container = $obj.parents( '.imagify-data-actions-container' ),
|
||||
id = w.imagify.modal.sanitizeId( $container.data( 'id' ) ),
|
||||
context = w.imagify.modal.sanitizeContext( $container.data( 'context' ) ),
|
||||
href, processingTemplate;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if ( w.imagify.modal.isItemLocked( context, id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
w.imagify.modal.lockItem( context, id );
|
||||
|
||||
href = $obj.attr( 'href' );
|
||||
processingTemplate = w.imagify.template( 'imagify-button-processing' );
|
||||
|
||||
$container.html( processingTemplate( {
|
||||
label: $obj.data( 'processing-label' )
|
||||
} ) );
|
||||
|
||||
$.get( href.replace( 'admin-post.php', 'admin-ajax.php' ) )
|
||||
.done( function( response ) {
|
||||
if ( response.data && response.data.html ) {
|
||||
// The work is done.
|
||||
w.imagify.modal.displayProcessResult( context, id, response.data.html );
|
||||
} else {
|
||||
// Still processing in background: we're waiting for the result by poking Imagifybeat.
|
||||
// Set the Imagifybeat interval to 15 seconds.
|
||||
w.imagify.beat.interval( 15 );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
// Imagifybeat =============================================================================
|
||||
|
||||
/**
|
||||
* Send the media IDs and their status to Imagifybeat.
|
||||
*
|
||||
* @param {object} e Event object.
|
||||
* @param {object} data Object containing all Imagifybeat IDs.
|
||||
*/
|
||||
addToImagifybeat: function ( e, data ) {
|
||||
var $containers = $( '.imagify-data-actions-container' );
|
||||
|
||||
if ( ! $containers.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
data[ w.imagifyModal.imagifybeatID ] = {};
|
||||
|
||||
$containers.each( function() {
|
||||
var $this = $( this ),
|
||||
id = w.imagify.modal.sanitizeId( $this.data( 'id' ) ),
|
||||
context = w.imagify.modal.sanitizeContext( $this.data( 'context' ) ),
|
||||
locked = w.imagify.modal.isItemLocked( context, id ) ? 1 : 0;
|
||||
|
||||
data[ w.imagifyModal.imagifybeatID ][ context ] = data[ w.imagifyModal.imagifybeatID ][ context ] || {};
|
||||
data[ w.imagifyModal.imagifybeatID ][ context ][ '_' + id ] = locked;
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Listen for the custom event "imagifybeat-tick" on $(document).
|
||||
*
|
||||
* @param {object} e Event object.
|
||||
* @param {object} data Object containing all Imagifybeat IDs.
|
||||
*/
|
||||
processImagifybeat: function ( e, data ) {
|
||||
if ( typeof data[ w.imagifyModal.imagifybeatID ] === 'undefined' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.each( data[ w.imagifyModal.imagifybeatID ], function( contextId, htmlContent ) {
|
||||
var context, id;
|
||||
|
||||
context = $.trim( contextId ).match( /^(.+)_(\d+)$/ );
|
||||
|
||||
if ( ! context ) {
|
||||
return;
|
||||
}
|
||||
|
||||
id = w.imagify.modal.sanitizeId( context[2] );
|
||||
context = w.imagify.modal.sanitizeContext( context[1] );
|
||||
|
||||
w.imagify.modal.displayProcessResult( context, id, htmlContent );
|
||||
} );
|
||||
},
|
||||
|
||||
// DOM manipulation tools ==================================================================
|
||||
|
||||
/**
|
||||
* Display the process result.
|
||||
*
|
||||
* @param {string} context The media context.
|
||||
* @param {int} id The media ID.
|
||||
* @param {string} htmlContent The HTML to insert.
|
||||
*/
|
||||
displayProcessResult: function( context, id, htmlContent ) {
|
||||
var $containers = w.imagify.modal.getContainers( context, id );
|
||||
|
||||
$containers.html( htmlContent );
|
||||
w.imagify.modal.unlockItem( context, id );
|
||||
|
||||
if ( ! w.imagify.modal.working.length ) {
|
||||
// Work is done.
|
||||
// Open the last container being processed.
|
||||
w.imagify.modal.openSlide( $containers );
|
||||
// Reset Imagifybeat interval.
|
||||
w.imagify.beat.resetInterval();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Open a slide rapidly.
|
||||
*
|
||||
* @param {object} $containers A jQuery collection.
|
||||
*/
|
||||
openSlide: function( $containers ) {
|
||||
$containers.each( function() {
|
||||
var $container = $( this ),
|
||||
text = $container.find( '.imagify-datas-more-action a' ).data( 'close' );
|
||||
|
||||
$container.find( '.imagify-datas-more-action a' ).addClass( 'is-open' ).find( '.the-text' ).text( text );
|
||||
$container.find( '.imagify-datas-details' ).show().addClass( 'is-open' );
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle slide in custom column.
|
||||
*
|
||||
* @param {object} e Event.
|
||||
*/
|
||||
toggleSlide: function( e ) {
|
||||
var $this = $( this );
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if ( $this.hasClass( 'is-open' ) ) {
|
||||
$( $this.attr( 'href' ) ).slideUp( 300 ).removeClass( 'is-open' );
|
||||
$this.removeClass( 'is-open' ).find( '.the-text' ).text( $this.data( 'open' ) );
|
||||
} else {
|
||||
$( $this.attr( 'href' ) ).slideDown( 300 ).addClass( 'is-open' );
|
||||
$this.addClass( 'is-open' ).find( '.the-text' ).text( $this.data( 'close' ) );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get all containers matching the given context and id.
|
||||
*
|
||||
* @param {string} context The media context.
|
||||
* @param {int} id The media ID.
|
||||
* @return {object} A jQuery collection.
|
||||
*/
|
||||
getContainers: function( context, id ) {
|
||||
return $( '.imagify-data-actions-container[data-id="' + id + '"][data-context="' + context + '"]' );
|
||||
},
|
||||
|
||||
// Sanitization ============================================================================
|
||||
|
||||
/**
|
||||
* Sanitize a media ID.
|
||||
*
|
||||
* @param {int|string} id A media ID.
|
||||
* @return {int}
|
||||
*/
|
||||
sanitizeId: function( id ) {
|
||||
return parseInt( id, 10 );
|
||||
},
|
||||
|
||||
/**
|
||||
* Sanitize a media context.
|
||||
*
|
||||
* @param {string} context A media context.
|
||||
* @return {string}
|
||||
*/
|
||||
sanitizeContext: function( context ) {
|
||||
context = context.replace( '/[^a-z0-9_-]/gi', '' ).toLowerCase();
|
||||
return context ? context : 'wp';
|
||||
},
|
||||
|
||||
// Locks ===================================================================================
|
||||
|
||||
/**
|
||||
* Lock an item.
|
||||
*
|
||||
* @param {string} context The media context.
|
||||
* @param {int} id The media ID.
|
||||
*/
|
||||
lockItem: function( context, id ) {
|
||||
if ( ! this.isItemLocked( context, id ) ) {
|
||||
this.working.push( context + '_' + id );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Unlock an item.
|
||||
*
|
||||
* @param {string} context The media context.
|
||||
* @param {int} id The media ID.
|
||||
*/
|
||||
unlockItem: function( context, id ) {
|
||||
var name = context + '_' + id,
|
||||
i = _.indexOf( this.working, name );
|
||||
|
||||
if ( i > -1 ) {
|
||||
this.working.splice( i, 1 );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Tell if an item is locked.
|
||||
*
|
||||
* @param {string} context The media context.
|
||||
* @param {int} id The media ID.
|
||||
* @return {bool}
|
||||
*/
|
||||
isItemLocked: function( context, id ) {
|
||||
return _.indexOf( this.working, context + '_' + id ) > -1;
|
||||
}
|
||||
};
|
||||
|
||||
w.imagify.modal.init();
|
||||
|
||||
} )(jQuery, document, window);
|
||||
1
wp/wp-content/plugins/imagify/assets/js/media-modal.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/media-modal.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
window.imagify.drawMeAChart=function(i){i.each(function(){var i=parseInt(jQuery(this).closest(".imagify-chart").next(".imagify-chart-value").text(),10);new window.imagify.Chart(this,{type:"doughnut",data:{datasets:[{data:[i,100-i],backgroundColor:["#00B3D3","#D8D8D8"],borderColor:"#fff",borderWidth:1}]},options:{legend:{display:!1},events:[],animation:{easing:"easeOutBounce"},tooltips:{enabled:!1},responsive:!1}})})},function(s,a,d){d.imagify.modal={working:[],init:function(){var i=s(a);s(d).on("canvasprinted.imagify",this.updateChart).trigger("canvasprinted.imagify"),s(".imagify-datas-details").hide(),i.on("click",".imagify-datas-more-action a",this.toggleSlide),i.on("click",".button-imagify-restore, .button-imagify-optimize, .button-imagify-manual-reoptimize, .button-imagify-optimize-missing-sizes, .button-imagify-generate-webp, .button-imagify-delete-webp",this.processOptimization),i.on("imagifybeat-send",this.addToImagifybeat),i.on("imagifybeat-tick",this.processImagifybeat),(i=s(".imagify-data-actions-container .button-imagify-processing")).length&&(i.closest(".imagify-data-actions-container").each(function(){var i=s(this),a=d.imagify.modal.sanitizeId(i.data("id")),i=d.imagify.modal.sanitizeContext(i.data("context"));d.imagify.modal.lockItem(i,a)}),d.imagify.beat.interval(15))},updateChart:function(i,a){a=s(a=a||".imagify-consumption-chart");d.imagify.drawMeAChart(a),a.closest(".imagify-datas-list").siblings(".imagify-datas-details").hide()},processOptimization:function(i){var a,t=s(this),e=t.parents(".imagify-data-actions-container"),n=d.imagify.modal.sanitizeId(e.data("id")),o=d.imagify.modal.sanitizeContext(e.data("context"));i.preventDefault(),d.imagify.modal.isItemLocked(o,n)||(d.imagify.modal.lockItem(o,n),i=t.attr("href"),a=d.imagify.template("imagify-button-processing"),e.html(a({label:t.data("processing-label")})),s.get(i.replace("admin-post.php","admin-ajax.php")).done(function(i){i.data&&i.data.html?d.imagify.modal.displayProcessResult(o,n,i.data.html):d.imagify.beat.interval(15)}))},addToImagifybeat:function(i,e){var a=s(".imagify-data-actions-container");a.length&&(e[d.imagifyModal.imagifybeatID]={},a.each(function(){var i=s(this),a=d.imagify.modal.sanitizeId(i.data("id")),i=d.imagify.modal.sanitizeContext(i.data("context")),t=d.imagify.modal.isItemLocked(i,a)?1:0;e[d.imagifyModal.imagifybeatID][i]=e[d.imagifyModal.imagifybeatID][i]||{},e[d.imagifyModal.imagifybeatID][i]["_"+a]=t}))},processImagifybeat:function(i,a){void 0!==a[d.imagifyModal.imagifybeatID]&&s.each(a[d.imagifyModal.imagifybeatID],function(i,a){var t,i=s.trim(i).match(/^(.+)_(\d+)$/);i&&(t=d.imagify.modal.sanitizeId(i[2]),i=d.imagify.modal.sanitizeContext(i[1]),d.imagify.modal.displayProcessResult(i,t,a))})},displayProcessResult:function(i,a,t){var e=d.imagify.modal.getContainers(i,a);e.html(t),d.imagify.modal.unlockItem(i,a),d.imagify.modal.working.length||(d.imagify.modal.openSlide(e),d.imagify.beat.resetInterval())},openSlide:function(i){i.each(function(){var i=s(this),a=i.find(".imagify-datas-more-action a").data("close");i.find(".imagify-datas-more-action a").addClass("is-open").find(".the-text").text(a),i.find(".imagify-datas-details").show().addClass("is-open")})},toggleSlide:function(i){var a=s(this);i.preventDefault(),a.hasClass("is-open")?(s(a.attr("href")).slideUp(300).removeClass("is-open"),a.removeClass("is-open").find(".the-text").text(a.data("open"))):(s(a.attr("href")).slideDown(300).addClass("is-open"),a.addClass("is-open").find(".the-text").text(a.data("close")))},getContainers:function(i,a){return s('.imagify-data-actions-container[data-id="'+a+'"][data-context="'+i+'"]')},sanitizeId:function(i){return parseInt(i,10)},sanitizeContext:function(i){return(i=i.replace("/[^a-z0-9_-]/gi","").toLowerCase())||"wp"},lockItem:function(i,a){this.isItemLocked(i,a)||this.working.push(i+"_"+a)},unlockItem:function(i,a){i=_.indexOf(this.working,i+"_"+a);-1<i&&this.working.splice(i,1)},isItemLocked:function(i,a){return-1<_.indexOf(this.working,i+"_"+a)}},d.imagify.modal.init()}(jQuery,document,window);
|
||||
127
wp/wp-content/plugins/imagify/assets/js/notices.js
Normal file
127
wp/wp-content/plugins/imagify/assets/js/notices.js
Normal file
@@ -0,0 +1,127 @@
|
||||
// All notices =====================================================================================
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
/**
|
||||
* Close an Imagify notice.
|
||||
*/
|
||||
$( '.imagify-notice-dismiss' ).on( 'click.imagify', function( e ) {
|
||||
var $this = $( this ),
|
||||
$parent = $this.parents( '.imagify-welcome, .imagify-notice, .imagify-rkt-notice, .imagify-upsell, .imagify-upsell-admin-bar' ),
|
||||
href = $this.attr( 'href' );
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// Hide the notice.
|
||||
$parent.fadeTo( 100 , 0, function() {
|
||||
$( this ).slideUp( 100, function() {
|
||||
$( this ).remove();
|
||||
} );
|
||||
} );
|
||||
|
||||
// Save the dismiss notice.
|
||||
$.get( href.replace( 'admin-post.php', 'admin-ajax.php' ) );
|
||||
} );
|
||||
|
||||
} )(jQuery, document, window);
|
||||
|
||||
|
||||
// The "welcome steps" notice + "wrong API key" notice =============================================
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
/**
|
||||
* 1. Create a new Imagify account.
|
||||
*/
|
||||
$( '#imagify-signup' ).on( 'click.imagify', function( e ) {
|
||||
e.preventDefault();
|
||||
|
||||
// Display the sign up form.
|
||||
swal( {
|
||||
title: imagifyNotices.labels.signupTitle,
|
||||
html: imagifyNotices.labels.signupText,
|
||||
confirmButtonText: imagifyNotices.labels.signupConfirmButtonText,
|
||||
input: 'email',
|
||||
padding: 0,
|
||||
showLoaderOnConfirm: true,
|
||||
customClass: 'imagify-sweet-alert imagify-sweet-alert-signup',
|
||||
inputValidator: function( inputValue ) {
|
||||
return new Promise( function( resolve, reject ) {
|
||||
if ( $.trim( inputValue ) === '' || ! inputValue ) {
|
||||
reject( imagifyNotices.labels.signupErrorEmptyEmail );
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
} );
|
||||
},
|
||||
preConfirm: function( inputValue ) {
|
||||
return new Promise( function( resolve, reject ) {
|
||||
setTimeout( function() {
|
||||
$.get( ajaxurl + w.imagify.concat + 'action=imagify_signup&email=' + inputValue + '&imagifysignupnonce=' + $( '#imagifysignupnonce' ).val() )
|
||||
.done( function( response ) {
|
||||
if ( ! response.success ) {
|
||||
reject( response.data );
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
} );
|
||||
}, 2000 );
|
||||
} );
|
||||
},
|
||||
} ).then( function() {
|
||||
swal( {
|
||||
title: imagifyNotices.labels.signupSuccessTitle,
|
||||
html: imagifyNotices.labels.signupSuccessText,
|
||||
type: 'success',
|
||||
padding: 0,
|
||||
customClass: 'imagify-sweet-alert'
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
||||
/**
|
||||
* 2. Check and save the Imagify API Key.
|
||||
*/
|
||||
$( '#imagify-save-api-key' ).on( 'click.imagify', function( e ) {
|
||||
e.preventDefault();
|
||||
|
||||
// Display the API key form.
|
||||
swal( {
|
||||
title: imagifyNotices.labels.saveApiKeyTitle,
|
||||
html: imagifyNotices.labels.saveApiKeyText,
|
||||
confirmButtonText: imagifyNotices.labels.saveApiKeyConfirmButtonText,
|
||||
input: 'text',
|
||||
padding: 0,
|
||||
showLoaderOnConfirm: true,
|
||||
customClass: 'imagify-sweet-alert imagify-sweet-alert-signup',
|
||||
inputValidator: function( inputValue ) {
|
||||
return new Promise( function( resolve, reject ) {
|
||||
if ( $.trim( inputValue ) === '' || ! inputValue ) {
|
||||
reject( imagifyNotices.labels.ApiKeyErrorEmpty );
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
} );
|
||||
},
|
||||
preConfirm: function( inputValue ) {
|
||||
return new Promise( function( resolve, reject ) {
|
||||
$.get( ajaxurl + w.imagify.concat + 'action=imagify_check_api_key_validity&api_key=' + inputValue + '&imagifycheckapikeynonce=' + $( '#imagifycheckapikeynonce' ).val() )
|
||||
.done( function( response ) {
|
||||
if ( ! response.success ) {
|
||||
reject( response.data );
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
} );
|
||||
} );
|
||||
},
|
||||
} ).then( function() {
|
||||
swal( {
|
||||
title: imagifyNotices.labels.ApiKeyCheckSuccessTitle,
|
||||
html: imagifyNotices.labels.ApiKeyCheckSuccessText,
|
||||
type: 'success',
|
||||
padding: 0,
|
||||
customClass: 'imagify-sweet-alert'
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
||||
} )(jQuery, document, window);
|
||||
1
wp/wp-content/plugins/imagify/assets/js/notices.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/notices.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(n){n(".imagify-notice-dismiss").on("click.imagify",function(i){var e=n(this),t=e.parents(".imagify-welcome, .imagify-notice, .imagify-rkt-notice, .imagify-upsell, .imagify-upsell-admin-bar"),e=e.attr("href");i.preventDefault(),t.fadeTo(100,0,function(){n(this).slideUp(100,function(){n(this).remove()})}),n.get(e.replace("admin-post.php","admin-ajax.php"))})}(jQuery,(document,window)),function(n,a){n("#imagify-signup").on("click.imagify",function(i){i.preventDefault(),swal({title:imagifyNotices.labels.signupTitle,html:imagifyNotices.labels.signupText,confirmButtonText:imagifyNotices.labels.signupConfirmButtonText,input:"email",padding:0,showLoaderOnConfirm:!0,customClass:"imagify-sweet-alert imagify-sweet-alert-signup",inputValidator:function(t){return new Promise(function(i,e){""!==n.trim(t)&&t?i():e(imagifyNotices.labels.signupErrorEmptyEmail)})},preConfirm:function(i){return new Promise(function(e,t){setTimeout(function(){n.get(ajaxurl+a.imagify.concat+"action=imagify_signup&email="+i+"&imagifysignupnonce="+n("#imagifysignupnonce").val()).done(function(i){i.success?e():t(i.data)})},2e3)})}}).then(function(){swal({title:imagifyNotices.labels.signupSuccessTitle,html:imagifyNotices.labels.signupSuccessText,type:"success",padding:0,customClass:"imagify-sweet-alert"})})}),n("#imagify-save-api-key").on("click.imagify",function(i){i.preventDefault(),swal({title:imagifyNotices.labels.saveApiKeyTitle,html:imagifyNotices.labels.saveApiKeyText,confirmButtonText:imagifyNotices.labels.saveApiKeyConfirmButtonText,input:"text",padding:0,showLoaderOnConfirm:!0,customClass:"imagify-sweet-alert imagify-sweet-alert-signup",inputValidator:function(t){return new Promise(function(i,e){""!==n.trim(t)&&t?i():e(imagifyNotices.labels.ApiKeyErrorEmpty)})},preConfirm:function(i){return new Promise(function(e,t){n.get(ajaxurl+a.imagify.concat+"action=imagify_check_api_key_validity&api_key="+i+"&imagifycheckapikeynonce="+n("#imagifycheckapikeynonce").val()).done(function(i){i.success?e():t(i.data)})})}}).then(function(){swal({title:imagifyNotices.labels.ApiKeyCheckSuccessTitle,html:imagifyNotices.labels.ApiKeyCheckSuccessText,type:"success",padding:0,customClass:"imagify-sweet-alert"})})})}(jQuery,(document,window));
|
||||
993
wp/wp-content/plugins/imagify/assets/js/options.js
Normal file
993
wp/wp-content/plugins/imagify/assets/js/options.js
Normal file
@@ -0,0 +1,993 @@
|
||||
window.imagify = window.imagify || {};
|
||||
|
||||
(function($, d, w, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
/*
|
||||
* Process an API key check validity.
|
||||
*/
|
||||
var busy = false,
|
||||
xhr = false;
|
||||
|
||||
$( '#imagify-settings #api_key' ).on( 'blur.imagify', function() {
|
||||
var obj = $( this ),
|
||||
value = obj.val();
|
||||
|
||||
if ( $.trim( value ) === '' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $( '#check_api_key' ).val() === value ) {
|
||||
$( '#imagify-check-api-container' ).html( '<span class="dashicons dashicons-yes"></span> ' + imagifyOptions.labels.ValidApiKeyText );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( true === busy ) {
|
||||
xhr.abort();
|
||||
} else {
|
||||
$( '#imagify-check-api-container' ).remove();
|
||||
obj.after( '<span id="imagify-check-api-container"><span class="imagify-spinner"></span>' + imagifyOptions.labels.waitApiKeyCheckText + '</span>' );
|
||||
}
|
||||
|
||||
busy = true;
|
||||
|
||||
xhr = $.get( ajaxurl + w.imagify.concat + 'action=imagify_check_api_key_validity&api_key=' + obj.val() + '&imagifycheckapikeynonce=' + $( '#imagifycheckapikeynonce' ).val() )
|
||||
.done( function( response ) {
|
||||
if ( ! response.success ) {
|
||||
$( '#imagify-check-api-container' ).html( '<span class="dashicons dashicons-no"></span> ' + response.data );
|
||||
} else {
|
||||
// Success, the API key is valid.
|
||||
$( '#imagify-check-api-container' ).remove();
|
||||
swal( {
|
||||
title: imagifyOptions.labels.ApiKeyCheckSuccessTitle,
|
||||
html: imagifyOptions.labels.ApiKeyCheckSuccessText,
|
||||
type: 'success',
|
||||
padding: 0,
|
||||
customClass: 'imagify-sweet-alert'
|
||||
} ).then( function() {
|
||||
location.reload();
|
||||
} );
|
||||
}
|
||||
|
||||
busy = false;
|
||||
} );
|
||||
} );
|
||||
|
||||
/**
|
||||
* Check the boxes by clicking "labels" (aria-describedby items).
|
||||
*/
|
||||
$( '.imagify-options-line' ).css( 'cursor', 'pointer' ).on( 'click.imagify', function( e ) {
|
||||
if ( 'INPUT' === e.target.nodeName ) {
|
||||
return;
|
||||
}
|
||||
$( 'input[aria-describedby="' + $( this ).attr( 'id' ) + '"]' ).trigger( 'click.imagify' );
|
||||
} );
|
||||
|
||||
$( '.imagify-settings th span' ).on( 'click.imagify', function() {
|
||||
var $input = $( this ).parent().next( 'td' ).find( ':checkbox' );
|
||||
|
||||
if ( 1 === $input.length ) {
|
||||
$input.trigger( 'click.imagify' );
|
||||
}
|
||||
} );
|
||||
|
||||
/**
|
||||
* Auto check on options-line input value change.
|
||||
*/
|
||||
$( '.imagify-options-line' ).find( 'input' ).on( 'change.imagify focus.imagify', function() {
|
||||
var $checkbox;
|
||||
|
||||
if ( 'checkbox' === this.type && ! this.checked ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$checkbox = $( this ).closest( '.imagify-options-line' ).prev( 'label' ).prev( ':checkbox' );
|
||||
|
||||
if ( $checkbox.length && ! $checkbox[0].checked ) {
|
||||
$checkbox.prop( 'checked', true );
|
||||
}
|
||||
} );
|
||||
|
||||
/**
|
||||
* Imagify Backup alert.
|
||||
*/
|
||||
$( '[name="imagify_settings[backup]"]' ).on( 'change.imagify', function() {
|
||||
var $_this = $( this ),
|
||||
$backupMessage = $_this.siblings( '#backup-dir-is-writable' ),
|
||||
params = {
|
||||
'action': 'imagify_check_backup_dir_is_writable',
|
||||
'_wpnonce': $backupMessage.data( 'nonce' )
|
||||
};
|
||||
|
||||
if ( $_this.is( ':checked' ) ) {
|
||||
$.getJSON( ajaxurl, params )
|
||||
.done( function( r ) {
|
||||
if ( $.isPlainObject( r ) && r.success ) {
|
||||
if ( r.data.is_writable ) {
|
||||
// Hide the error message.
|
||||
$backupMessage.addClass( 'hidden' );
|
||||
} else {
|
||||
// Show the error message.
|
||||
$backupMessage.removeClass( 'hidden' );
|
||||
}
|
||||
}
|
||||
} );
|
||||
return;
|
||||
}
|
||||
|
||||
// Are you sure? No backup?
|
||||
swal( {
|
||||
title: imagifyOptions.labels.noBackupTitle,
|
||||
html: imagifyOptions.labels.noBackupText,
|
||||
type: 'warning',
|
||||
customClass: 'imagify-sweet-alert',
|
||||
padding: 0,
|
||||
showCancelButton: true,
|
||||
cancelButtonText: imagifySwal.labels.cancelButtonText,
|
||||
reverseButtons: true
|
||||
} ).then(
|
||||
function() {
|
||||
// Leave it unchecked, hide the error message.
|
||||
$backupMessage.addClass( 'hidden' );
|
||||
},
|
||||
function() {
|
||||
// Re-check.
|
||||
$_this.prop( 'checked', true );
|
||||
}
|
||||
);
|
||||
} );
|
||||
|
||||
/**
|
||||
* Fade CDN URL field.
|
||||
*/
|
||||
$( '[name="imagify_settings[display_webp_method]"]' ).on( 'change.imagify init.imagify', function( e ) {
|
||||
if ( 'picture' === e.target.value ) {
|
||||
$( e.target ).closest( '.imagify-radio-group' ).next( '.imagify-options-line' ).removeClass( 'imagify-faded' );
|
||||
} else {
|
||||
$( e.target ).closest( '.imagify-radio-group' ).next( '.imagify-options-line' ).addClass( 'imagify-faded' );
|
||||
}
|
||||
} ).filter( ':checked' ).trigger( 'init.imagify' );
|
||||
|
||||
} )(jQuery, document, window);
|
||||
|
||||
|
||||
// Display Imagify User data =======================================================================
|
||||
(function(w, d, $, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
if ( ! w.imagifyUser ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.getJSON( ajaxurl, w.imagifyUser )
|
||||
.done( function( r ) {
|
||||
if ( $.isPlainObject( r ) && r.success ) {
|
||||
r.data.id = null;
|
||||
r.data.plan_id = null;
|
||||
r.data.is = [];
|
||||
|
||||
$.each( r.data, function( k, v ) {
|
||||
var htmlClass = '.imagify-user-' + k.replace( /_/g, '-' );
|
||||
|
||||
if ( k.indexOf( 'is_' ) === 0 ) {
|
||||
if ( v ) {
|
||||
r.data.is.push( htmlClass );
|
||||
}
|
||||
} else if ( 'is' !== k ) {
|
||||
$( htmlClass ).text( v );
|
||||
}
|
||||
} );
|
||||
|
||||
r.data.is.push( 'best-plan' );
|
||||
|
||||
$( r.data.is.join( ',' ) ).removeClass( 'hidden' );
|
||||
}
|
||||
} );
|
||||
|
||||
} )(window, document, jQuery);
|
||||
|
||||
|
||||
// Files tree for "custom folders" =================================================================
|
||||
(function(w, d, $, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
if ( ! imagifyOptions.getFilesTree ) {
|
||||
return;
|
||||
}
|
||||
|
||||
function imagifyInsertFolderRow( value ) {
|
||||
var added = false,
|
||||
prevPath = null,
|
||||
valueTest, template, $wrap, $rows, $field;
|
||||
|
||||
if ( ! value ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$wrap = $( '#imagify-custom-folders-selected' );
|
||||
$rows = $wrap.find( '.imagify-custom-folder-line' );
|
||||
$field = $rows.find( '[value="' + value + '"]' );
|
||||
|
||||
if ( $field.length ) {
|
||||
// Shouldn't happen.
|
||||
return;
|
||||
}
|
||||
|
||||
// Path #///# Label.
|
||||
value = value.split( '#///#' );
|
||||
valueTest = value[1].replace( /\/+$/,'' ).toLowerCase();
|
||||
template = w.imagify.template( 'imagify-custom-folder' );
|
||||
|
||||
$rows.each( function() {
|
||||
var $this = $( this ),
|
||||
thisValueTest = $this.data( 'path' ).replace( /\/+$/,'' ).toLowerCase();
|
||||
|
||||
if ( '' !== thisValueTest && valueTest.indexOf( thisValueTest ) === 0 ) {
|
||||
// We try to add a sub-folder of an already selected folder. It shouldn't happen though, since it can't be selected.
|
||||
added = true;
|
||||
return false;
|
||||
} else if ( valueTest < thisValueTest ) {
|
||||
$this.before( template( {
|
||||
value: value[0],
|
||||
label: value[1]
|
||||
} ) );
|
||||
$rows = $wrap.find( '.imagify-custom-folder-line' );
|
||||
added = true;
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
|
||||
if ( ! added ) {
|
||||
$wrap.append( template( {
|
||||
value: value[0],
|
||||
label: value[1]
|
||||
} ) );
|
||||
$rows = $wrap.find( '.imagify-custom-folder-line' );
|
||||
}
|
||||
|
||||
// Remove sub-paths: if 'a/b/' and 'a/b/c/' are in the array, we keep only the "parent" 'a/b/'.
|
||||
if ( '' !== valueTest ) {
|
||||
$rows.each( function() {
|
||||
var $this = $( this ),
|
||||
thisPath = $this.data( 'path' ).toLowerCase();
|
||||
|
||||
if ( null !== prevPath && thisPath.indexOf( prevPath ) === 0 ) {
|
||||
$this.find( '.imagify-custom-folders-remove' ).trigger( 'click.imagify' );
|
||||
} else {
|
||||
prevPath = thisPath;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
// Display a message.
|
||||
$wrap.next( '.hidden' ).removeClass( 'hidden' );
|
||||
}
|
||||
|
||||
// Clicking the main button: fetch site's root folders and files, then display them in a modal.
|
||||
$( '#imagify-add-custom-folder' ).on( 'click.imagify', function() {
|
||||
var $button = $( this ),
|
||||
selected = [],
|
||||
$folders;
|
||||
|
||||
if ( $button.prop('disabled') ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$button.prop( 'disabled', true ).next( 'img' ).attr( 'aria-hidden', 'false' );
|
||||
|
||||
$folders = $( '#imagify-custom-folders-selected' );
|
||||
|
||||
$folders.find( 'input' ).each( function() {
|
||||
selected.push( this.value );
|
||||
} );
|
||||
|
||||
$.post( imagifyOptions.getFilesTree, {
|
||||
folder: '/',
|
||||
selected: selected
|
||||
}, null, 'json' )
|
||||
.done( function( response ) {
|
||||
if ( ! response.success ) {
|
||||
swal( {
|
||||
title: imagifyOptions.labels.error,
|
||||
html: response.data || '',
|
||||
type: 'error',
|
||||
padding: 0,
|
||||
customClass: 'imagify-sweet-alert'
|
||||
} );
|
||||
return;
|
||||
}
|
||||
|
||||
swal( {
|
||||
title: imagifyOptions.labels.filesTreeTitle,
|
||||
html: '<div class="imagify-swal-subtitle">' + imagifyOptions.labels.filesTreeSubTitle + '</div><div class="imagify-swal-content"><p class="imagify-folders-information"><i class="dashicons dashicons-info" aria-hidden="true"></i>' + imagifyOptions.labels.cleaningInfo + '</p><ul id="imagify-folders-tree" class="imagify-folders-tree">' + response.data + '</ul></div>',
|
||||
type: '',
|
||||
customClass: 'imagify-sweet-alert imagify-swal-has-subtitle imagify-folders-selection',
|
||||
showCancelButton: true,
|
||||
padding: 0,
|
||||
confirmButtonText: imagifyOptions.labels.confirmFilesTreeBtn,
|
||||
cancelButtonText: imagifySwal.labels.cancelButtonText,
|
||||
reverseButtons: true
|
||||
} ).then( function() {
|
||||
var values = $( '#imagify-folders-tree input' ).serializeArray(); // Don't do `$( '#imagify-folders-tree' ).find( 'input' )`, it won't work.
|
||||
|
||||
if ( ! values.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.each( values, function( i, v ) {
|
||||
imagifyInsertFolderRow( v.value );
|
||||
} );
|
||||
} ).catch( swal.noop );
|
||||
} )
|
||||
.fail( function() {
|
||||
swal( {
|
||||
title: imagifyOptions.labels.error,
|
||||
type: 'error',
|
||||
customClass: 'imagify-sweet-alert',
|
||||
padding: 0
|
||||
} );
|
||||
} )
|
||||
.always( function(){
|
||||
$button.prop( 'disabled', false ).next( 'img' ).attr( 'aria-hidden', 'true' );
|
||||
} );
|
||||
} );
|
||||
|
||||
// Clicking a folder icon in the modal: fetch the folder's sub-folders and files, then display them.
|
||||
$( d ).on( 'click.imagify', '#imagify-folders-tree [data-folder]', function() {
|
||||
var $button = $( this ),
|
||||
$tree = $button.nextAll( '.imagify-folders-sub-tree' ),
|
||||
selected = [];
|
||||
|
||||
if ( $button.prop('disabled') || $button.siblings( ':checkbox' ).is( ':checked' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$button.prop( 'disabled', true ).addClass( 'imagify-loading' );
|
||||
|
||||
if ( $tree.length ) {
|
||||
if ( $button.hasClass( 'imagify-is-open' ) ) {
|
||||
$tree.addClass( 'hidden' );
|
||||
$button.removeClass(' imagify-is-open' );
|
||||
} else {
|
||||
$tree.removeClass( 'hidden' );
|
||||
$button.addClass( 'imagify-is-open' );
|
||||
}
|
||||
$button.prop( 'disabled', false ).removeClass( 'imagify-loading' );
|
||||
return;
|
||||
}
|
||||
|
||||
$( '#imagify-custom-folders-selected' ).find( 'input' ).each( function() {
|
||||
selected.push( this.value );
|
||||
} );
|
||||
|
||||
$.post( imagifyOptions.getFilesTree, {
|
||||
folder: $button.data( 'folder' ),
|
||||
selected: selected
|
||||
}, null, 'json' )
|
||||
.done( function( response ) {
|
||||
if ( ! response.success ) {
|
||||
swal( {
|
||||
title: imagifyOptions.labels.error,
|
||||
html: response.data || '',
|
||||
type: 'error',
|
||||
padding: 0,
|
||||
customClass: 'imagify-sweet-alert'
|
||||
} );
|
||||
return;
|
||||
}
|
||||
|
||||
$button.addClass( 'imagify-is-open' ).parent().append( '<ul class="imagify-folders-sub-tree">' + response.data + '</ul>' );
|
||||
} )
|
||||
.fail( function(){
|
||||
swal( {
|
||||
title: imagifyOptions.labels.error,
|
||||
type: 'error',
|
||||
padding: 0,
|
||||
customClass: 'imagify-sweet-alert'
|
||||
} );
|
||||
} )
|
||||
.always( function(){
|
||||
$button.prop( 'disabled', false ).removeClass( 'imagify-loading' );
|
||||
} );
|
||||
} );
|
||||
|
||||
// Clicking a Remove folder button make it disappear.
|
||||
$( '#imagify-custom-folders' ).on( 'click.imagify', '.imagify-custom-folders-remove', function() {
|
||||
var $row = $( this ).closest( '.imagify-custom-folder-line' ).addClass( 'imagify-will-remove' );
|
||||
|
||||
w.setTimeout( function() {
|
||||
$row.remove();
|
||||
// Display a message.
|
||||
$( '#imagify-custom-folders-selected' ).siblings( '.imagify-success.hidden' ).removeClass( 'hidden' );
|
||||
}, 750 );
|
||||
} );
|
||||
|
||||
// Clicking the "add themes to folders" button.
|
||||
$( '#imagify-add-themes-to-custom-folder' ).on( 'click.imagify', function() {
|
||||
var $this = $( this );
|
||||
|
||||
imagifyInsertFolderRow( $this.data( 'theme' ) );
|
||||
imagifyInsertFolderRow( $this.data( 'theme-parent' ) );
|
||||
|
||||
// Remove clicked button.
|
||||
$this.replaceWith( '<p>' + imagifyOptions.labels.themesAdded + '</p>' );
|
||||
} );
|
||||
|
||||
} )(window, document, jQuery);
|
||||
|
||||
|
||||
// Generate missing WebP versions ==================================================================
|
||||
/* eslint-disable no-underscore-dangle, consistent-this */
|
||||
(function(w, d, $, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
if ( ! imagifyOptions.bulk ) {
|
||||
return;
|
||||
}
|
||||
|
||||
w.imagify.optionsBulk = {
|
||||
// Properties ==============================================================================
|
||||
/**
|
||||
* The current error ID or message.
|
||||
*
|
||||
* @var {string|bool} error False if no error.
|
||||
*/
|
||||
error: false,
|
||||
/**
|
||||
* Set to true at the beginning of the process.
|
||||
*
|
||||
* @var {bool} working
|
||||
*/
|
||||
working: false,
|
||||
/**
|
||||
* Set to true to stop the whole thing.
|
||||
*
|
||||
* @var {bool} processIsStopped
|
||||
*/
|
||||
processIsStopped: false,
|
||||
/**
|
||||
* The button.
|
||||
*
|
||||
* @var {jQuery}
|
||||
*/
|
||||
$button: null,
|
||||
/**
|
||||
* The progress bar wrapper.
|
||||
*
|
||||
* @var {jQuery}
|
||||
*/
|
||||
$progressWrap: null,
|
||||
/**
|
||||
* The progress bar.
|
||||
*
|
||||
* @var {jQuery}
|
||||
*/
|
||||
$progressBar: null,
|
||||
/**
|
||||
* The progress bar text (the %).
|
||||
*
|
||||
* @var {jQuery}
|
||||
*/
|
||||
$progressText: null,
|
||||
|
||||
// Methods =================================================================================
|
||||
|
||||
/*
|
||||
* Init.
|
||||
*/
|
||||
init: function () {
|
||||
var processed, progress;
|
||||
this.$missingWebpElement = $('.generate-missing-webp');
|
||||
this.$missingWebpMessage = $('.generate-missing-webp p');
|
||||
|
||||
this.$button = $( '#imagify-generate-webp-versions' );
|
||||
this.$progressWrap = this.$button.siblings( '.imagify-progress' );
|
||||
this.$progressBar = this.$progressWrap.find( '.bar' );
|
||||
this.$progressText = this.$progressBar.find( '.percent' );
|
||||
|
||||
// Enable/Disable the button when the "Convert to WebP" checkbox is checked/unchecked.
|
||||
$( '#imagify_convert_to_webp' )
|
||||
.on( 'change.imagify init.imagify', { imagifyOptionsBulk: this }, this.toggleButton )
|
||||
.trigger( 'init.imagify' );
|
||||
|
||||
// Launch optimization.
|
||||
this.$button.on( 'click.imagify', { imagifyOptionsBulk: this }, this.maybeLaunchMissingWebpProcess );
|
||||
|
||||
// Imagifybeat for optimization queue.
|
||||
$( d )
|
||||
.on( 'imagifybeat-send', { imagifyOptionsBulk: this }, this.addQueueImagifybeat )
|
||||
.on( 'imagifybeat-tick', { imagifyOptionsBulk: this }, this.processQueueImagifybeat )
|
||||
// Imagifybeat for requirements.
|
||||
.on( 'imagifybeat-send', this.addRequirementsImagifybeat )
|
||||
.on( 'imagifybeat-tick', { imagifyOptionsBulk: this }, this.processRequirementsImagifybeat );
|
||||
|
||||
if ( false !== imagifyOptions.bulk.progress_webp.total && false !== imagifyOptions.bulk.progress_webp.remaining ) {
|
||||
// Reset properties.
|
||||
w.imagify.optionsBulk.error = false;
|
||||
w.imagify.optionsBulk.working = true;
|
||||
w.imagify.optionsBulk.processIsStopped = false;
|
||||
|
||||
// Disable the button.
|
||||
this.$button.prop( 'disabled', true ).find( '.dashicons' ).addClass( 'rotate' );
|
||||
|
||||
// Fasten Imagifybeat: 1 tick every 15 seconds, and disable suspend.
|
||||
w.imagify.beat.interval( 15 );
|
||||
w.imagify.beat.disableSuspend();
|
||||
|
||||
this.$missingWebpMessage.hide().attr('aria-hidden', 'true');
|
||||
|
||||
processed = imagifyOptions.bulk.progress_webp.total - imagifyOptions.bulk.progress_webp.remaining;
|
||||
progress = Math.floor( processed / imagifyOptions.bulk.progress_webp.total * 100 );
|
||||
this.$progressBar.css( 'width', progress + '%' );
|
||||
this.$progressText.text( processed + '/' + imagifyOptions.bulk.progress_webp.total );
|
||||
|
||||
this.$progressWrap.slideDown().attr( 'aria-hidden', 'false' ).removeClass( 'hidden' );
|
||||
}
|
||||
},
|
||||
|
||||
// Event callbacks =========================================================================
|
||||
|
||||
/**
|
||||
* Enable/Disable the button when the "Convert to WebP" checkbox is checked/unchecked.
|
||||
*
|
||||
* @param {object} e Event object.
|
||||
*/
|
||||
toggleButton: function ( e ) {
|
||||
if ( ! this.checked ) {
|
||||
e.data.imagifyOptionsBulk.$button.prop( 'disabled', true );
|
||||
} else {
|
||||
e.data.imagifyOptionsBulk.$button.prop( 'disabled', false );
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Maybe launch the missing WebP generation process.
|
||||
*
|
||||
* @param {object} e Event object.
|
||||
*/
|
||||
maybeLaunchMissingWebpProcess: function ( e ) {
|
||||
if ( ! e.data.imagifyOptionsBulk || e.data.imagifyOptionsBulk.working ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( e.data.imagifyOptionsBulk.hasBlockingError( true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset properties.
|
||||
e.data.imagifyOptionsBulk.error = false;
|
||||
e.data.imagifyOptionsBulk.working = true;
|
||||
e.data.imagifyOptionsBulk.processIsStopped = false;
|
||||
|
||||
// Disable the button.
|
||||
e.data.imagifyOptionsBulk.$button.prop( 'disabled', true ).find( '.dashicons' ).addClass( 'rotate' );
|
||||
|
||||
// Fasten Imagifybeat: 1 tick every 15 seconds, and disable suspend.
|
||||
w.imagify.beat.interval( 15 );
|
||||
w.imagify.beat.disableSuspend();
|
||||
|
||||
// Launch missing WebP generation process
|
||||
e.data.imagifyOptionsBulk.launchProcess();
|
||||
},
|
||||
|
||||
// Imagifybeat =============================================================================
|
||||
|
||||
/**
|
||||
* Add a Imagifybeat ID on "imagifybeat-send" event to sync the optimization queue.
|
||||
*
|
||||
* @param {object} e Event object.
|
||||
* @param {object} data Object containing all Imagifybeat IDs.
|
||||
*/
|
||||
addQueueImagifybeat: function ( e, data ) {
|
||||
data[ imagifyOptions.bulk.imagifybeatIDs.progress ] = imagifyOptions.bulk.contexts;
|
||||
},
|
||||
|
||||
/**
|
||||
* Listen for the custom event "imagifybeat-tick" on $(document).
|
||||
* It allows to update various data periodically.
|
||||
*
|
||||
* @param {object} e Event object.
|
||||
* @param {object} data Object containing all Imagifybeat IDs.
|
||||
*/
|
||||
processQueueImagifybeat: function ( e, data ) {
|
||||
var images_status, processed, progress;
|
||||
|
||||
if ( e.data.imagifyOptionsBulk && typeof data[ imagifyOptions.bulk.imagifybeatIDs.progress ] === 'undefined' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( e.data.imagifyOptionsBulk.processIsStopped ) {
|
||||
e.data.imagifyOptionsBulk.processFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
images_status = data[ imagifyOptions.bulk.imagifybeatIDs.progress ];
|
||||
|
||||
if ( images_status.remaining === 0 ) {
|
||||
e.data.imagifyOptionsBulk.processFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
processed = images_status.total - images_status.remaining;
|
||||
progress = Math.floor( processed / images_status.total * 100 );
|
||||
e.data.imagifyOptionsBulk.$progressBar.css( 'width', progress + '%' );
|
||||
e.data.imagifyOptionsBulk.$progressText.text( processed + '/' + images_status.total );
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a Imagifybeat ID for requirements on "imagifybeat-send" event.
|
||||
*
|
||||
* @param {object} e Event object.
|
||||
* @param {object} data Object containing all Imagifybeat IDs.
|
||||
*/
|
||||
addRequirementsImagifybeat: function ( e, data ) {
|
||||
data[ imagifyOptions.bulk.imagifybeatIDs.requirements ] = 1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Listen for the custom event "imagifybeat-tick" on $(document).
|
||||
* It allows to update requirements status periodically.
|
||||
*
|
||||
* @param {object} e Event object.
|
||||
* @param {object} data Object containing all Imagifybeat IDs.
|
||||
*/
|
||||
processRequirementsImagifybeat: function ( e, data ) {
|
||||
if ( e.data.imagifyOptionsBulk && typeof data[ imagifyOptions.bulk.imagifybeatIDs.requirements ] === 'undefined' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
data = data[ imagifyOptions.bulk.imagifybeatIDs.requirements ];
|
||||
|
||||
imagifyOptions.bulk.curlMissing = data.curl_missing;
|
||||
imagifyOptions.bulk.editorMissing = data.editor_missing;
|
||||
imagifyOptions.bulk.extHttpBlocked = data.external_http_blocked;
|
||||
imagifyOptions.bulk.apiDown = data.api_down;
|
||||
imagifyOptions.bulk.keyIsValid = data.key_is_valid;
|
||||
imagifyOptions.bulk.isOverQuota = data.is_over_quota;
|
||||
},
|
||||
|
||||
// Optimization ============================================================================
|
||||
|
||||
/*
|
||||
* launch the missing WebP generation process.
|
||||
*/
|
||||
launchProcess: function () {
|
||||
var _this;
|
||||
|
||||
if ( this.processIsStopped ) {
|
||||
return;
|
||||
}
|
||||
|
||||
_this = this;
|
||||
|
||||
$.get( this.getAjaxUrl( 'MissingWebp', imagifyOptions.bulk.contexts ) )
|
||||
.done( function( response ) {
|
||||
var errorMessage;
|
||||
|
||||
if ( _this.processIsStopped ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( response.data && response.data.message ) {
|
||||
errorMessage = response.data.message;
|
||||
} else {
|
||||
errorMessage = imagifyOptions.bulk.ajaxErrorText;
|
||||
}
|
||||
|
||||
if ( ! response.success ) {
|
||||
// Error.
|
||||
if ( ! _this.error ) {
|
||||
_this.stopProcess( errorMessage );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 0 === response.data.total ) {
|
||||
// No media to process.
|
||||
_this.stopProcess( 'no-images' );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_this.$missingWebpMessage.hide().attr('aria-hidden', 'true');
|
||||
|
||||
// Reset and display the progress bar.
|
||||
_this.$progressText.text( '0' + ( response.data.total ? '/' + response.data.total : '' ) );
|
||||
_this.$progressWrap.slideDown().attr( 'aria-hidden', 'false' ).removeClass( 'hidden' );
|
||||
} )
|
||||
.fail( function() {
|
||||
// Error.
|
||||
if ( ! _this.error ) {
|
||||
_this.stopProcess( 'get-unoptimized-images' );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
/*
|
||||
* End.
|
||||
*/
|
||||
processFinished: function () {
|
||||
var errorArgs = {};
|
||||
|
||||
// Maybe display an error.
|
||||
if ( false !== this.error ) {
|
||||
if ( 'invalid-api-key' === this.error ) {
|
||||
errorArgs = {
|
||||
title: imagifyOptions.bulk.labels.invalidAPIKeyTitle,
|
||||
type: 'info'
|
||||
};
|
||||
}
|
||||
else if ( 'over-quota' === this.error ) {
|
||||
errorArgs = {
|
||||
title: imagifyOptions.bulk.labels.overQuotaTitle,
|
||||
html: $( '#tmpl-imagify-overquota-alert' ).html(),
|
||||
type: 'info',
|
||||
customClass: 'imagify-swal-has-subtitle imagify-swal-error-header',
|
||||
showConfirmButton: false
|
||||
};
|
||||
}
|
||||
else if ( 'get-unoptimized-images' === this.error ) {
|
||||
errorArgs = {
|
||||
title: imagifyOptions.bulk.labels.getUnoptimizedImagesErrorTitle,
|
||||
html: imagifyOptions.bulk.labels.getUnoptimizedImagesErrorText,
|
||||
type: 'info'
|
||||
};
|
||||
}
|
||||
else if ( 'no-images' === this.error ) {
|
||||
errorArgs = {
|
||||
title: imagifyOptions.bulk.labels.nothingToDoTitle,
|
||||
html: imagifyOptions.bulk.labels.nothingToDoText,
|
||||
type: 'info'
|
||||
};
|
||||
}
|
||||
else if ( 'no-backup' === this.error ) {
|
||||
errorArgs = {
|
||||
title: imagifyOptions.bulk.labels.nothingToDoTitle,
|
||||
html: imagifyOptions.bulk.labels.nothingToDoNoBackupText,
|
||||
type: 'info'
|
||||
};
|
||||
} else {
|
||||
errorArgs = {
|
||||
title: imagifyOptions.bulk.labels.error,
|
||||
html: this.error,
|
||||
type: 'info'
|
||||
};
|
||||
}
|
||||
|
||||
this.displayError( errorArgs );
|
||||
|
||||
// Reset the error.
|
||||
this.error = false;
|
||||
}
|
||||
|
||||
// Reset.
|
||||
this.working = false;
|
||||
this.processIsStopped = false;
|
||||
|
||||
// Reset Imagifybeat interval and enable suspend.
|
||||
w.imagify.beat.resetInterval();
|
||||
w.imagify.beat.enableSuspend();
|
||||
|
||||
// Reset the progress bar.
|
||||
this.$progressWrap.slideUp().attr( 'aria-hidden', 'true' ).addClass( 'hidden' );
|
||||
this.$progressText.text( '0' );
|
||||
this.$missingWebpElement.hide().attr('aria-hidden', 'true');
|
||||
this.$button.find( '.dashicons' ).removeClass( 'rotate' );
|
||||
},
|
||||
|
||||
// Tools ===================================================================================
|
||||
|
||||
/*
|
||||
* Tell if we have a blocking error. Can also display an error message in a swal.
|
||||
*
|
||||
* @param {bool} displayErrorMessage False to not display any error message.
|
||||
* @return {bool}
|
||||
*/
|
||||
hasBlockingError: function ( displayErrorMessage ) {
|
||||
displayErrorMessage = undefined !== displayErrorMessage && displayErrorMessage;
|
||||
|
||||
if ( imagifyOptions.bulk.curlMissing ) {
|
||||
if ( displayErrorMessage ) {
|
||||
this.displayError( {
|
||||
html: imagifyOptions.bulk.labels.curlMissing
|
||||
} );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( imagifyOptions.bulk.editorMissing ) {
|
||||
if ( displayErrorMessage ) {
|
||||
this.displayError( {
|
||||
html: imagifyOptions.bulk.labels.editorMissing
|
||||
} );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( imagifyOptions.bulk.extHttpBlocked ) {
|
||||
if ( displayErrorMessage ) {
|
||||
this.displayError( {
|
||||
html: imagifyOptions.bulk.labels.extHttpBlocked
|
||||
} );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( imagifyOptions.bulk.apiDown ) {
|
||||
if ( displayErrorMessage ) {
|
||||
this.displayError( {
|
||||
html: imagifyOptions.bulk.labels.apiDown
|
||||
} );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! imagifyOptions.bulk.keyIsValid ) {
|
||||
if ( displayErrorMessage ) {
|
||||
this.displayError( {
|
||||
title: imagifyOptions.bulk.labels.invalidAPIKeyTitle,
|
||||
type: 'info'
|
||||
} );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( imagifyOptions.bulk.isOverQuota ) {
|
||||
if ( displayErrorMessage ) {
|
||||
this.displayError( {
|
||||
title: imagifyOptions.bulk.labels.overQuotaTitle,
|
||||
html: $( '#tmpl-imagify-overquota-alert' ).html(),
|
||||
type: 'info',
|
||||
customClass: 'imagify-swal-has-subtitle imagify-swal-error-header',
|
||||
showConfirmButton: false
|
||||
} );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/*
|
||||
* Display an error message in a modal.
|
||||
*
|
||||
* @param {string} title The modal title.
|
||||
* @param {string} text The modal text.
|
||||
* @param {object} args Other less common args.
|
||||
*/
|
||||
displayError: function ( title, text, args ) {
|
||||
var def = {
|
||||
title: '',
|
||||
html: '',
|
||||
type: 'error',
|
||||
customClass: '',
|
||||
width: 620,
|
||||
padding: 0,
|
||||
showCloseButton: true,
|
||||
showConfirmButton: true
|
||||
};
|
||||
|
||||
if ( $.isPlainObject( title ) ) {
|
||||
args = $.extend( {}, def, title );
|
||||
} else {
|
||||
args = args || {};
|
||||
args = $.extend( {}, def, {
|
||||
title: title || '',
|
||||
html: text || ''
|
||||
}, args );
|
||||
}
|
||||
|
||||
args.title = args.title || imagifyOptions.bulk.labels.error;
|
||||
args.customClass += ' imagify-sweet-alert';
|
||||
|
||||
swal( args ).catch( swal.noop );
|
||||
},
|
||||
|
||||
/*
|
||||
* Get the URL used for ajax requests.
|
||||
*
|
||||
* @param {string} action An ajax action, or part of it.
|
||||
* @param {array} context The contexts.
|
||||
* @return {string}
|
||||
*/
|
||||
getAjaxUrl: function ( action, contexts ) {
|
||||
var url;
|
||||
|
||||
url = ajaxurl + w.imagify.concat + '_wpnonce=' + imagifyOptions.bulk.ajaxNonce;
|
||||
url += '&action=' + imagifyOptions.bulk.ajaxActions[ action ];
|
||||
url += '&context=' + contexts.join('_');
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
/*
|
||||
* Stop everything and set an error.
|
||||
*
|
||||
* @param {string} errorId An error ID.
|
||||
*/
|
||||
stopProcess: function ( errorId ) {
|
||||
this.processIsStopped = true;
|
||||
|
||||
this.error = errorId;
|
||||
|
||||
this.processFinished();
|
||||
}
|
||||
};
|
||||
|
||||
w.imagify.optionsBulk.init();
|
||||
|
||||
} )(window, document, jQuery);
|
||||
/* eslint-enable no-underscore-dangle, consistent-this */
|
||||
|
||||
|
||||
// "Select all" checkboxes =========================================================================
|
||||
(function(w, d, $, undefined) { // eslint-disable-line no-unused-vars, no-shadow, no-shadow-restricted-names
|
||||
|
||||
var jqPropHookChecked = $.propHooks.checked;
|
||||
|
||||
// Force `.prop()` to trigger a `change` event.
|
||||
$.propHooks.checked = {
|
||||
set: function( elem, value, name ) {
|
||||
var ret;
|
||||
|
||||
if ( undefined === jqPropHookChecked ) {
|
||||
ret = ( elem[ name ] = value );
|
||||
} else {
|
||||
ret = jqPropHookChecked( elem, value, name );
|
||||
}
|
||||
|
||||
$( elem ).trigger( 'change.imagify' );
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
// Check all checkboxes.
|
||||
$( '.imagify-select-all' ).on( 'click.imagify', function() {
|
||||
var $_this = $(this),
|
||||
action = $_this.data( 'action' ),
|
||||
$btns = $_this.closest( '.imagify-select-all-buttons' ),
|
||||
$group = $btns.prev( '.imagify-check-group' ),
|
||||
inactive = 'imagify-is-inactive';
|
||||
|
||||
if ( $_this.hasClass( inactive ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$btns.find( '.imagify-select-all' ).removeClass( inactive ).attr( 'aria-disabled', 'false' );
|
||||
$_this.addClass( inactive ).attr( 'aria-disabled', 'true' );
|
||||
|
||||
$group.find( '.imagify-row-check' )
|
||||
.prop( 'checked', function() {
|
||||
var $this = $( this );
|
||||
|
||||
if ( $this.is( ':hidden,:disabled' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( action === 'select' ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
// Change buttons status on checkboxes interation.
|
||||
$( '.imagify-check-group .imagify-row-check' ).on( 'change.imagify', function() {
|
||||
var $group = $( this ).closest( '.imagify-check-group' ),
|
||||
$checks = $group.find( '.imagify-row-check' ),
|
||||
could_be = $checks.filter( ':visible:enabled' ).length,
|
||||
are_checked = $checks.filter( ':visible:enabled:checked' ).length,
|
||||
$btns = $group.next( '.imagify-select-all-buttons' ),
|
||||
inactive = 'imagify-is-inactive';
|
||||
|
||||
// Toggle status of "check all" buttons.
|
||||
if ( are_checked === 0 ) {
|
||||
$btns.find( '[data-action="unselect"]' ).addClass( inactive ).attr( 'aria-disabled', 'true' );
|
||||
}
|
||||
if ( are_checked === could_be ) {
|
||||
$btns.find( '[data-action="select"]' ).addClass( inactive ).attr( 'aria-disabled', 'true' );
|
||||
}
|
||||
if ( are_checked !== could_be && are_checked > 0 ) {
|
||||
$btns.find( '.imagify-select-all' ).removeClass( inactive ).attr( 'aria-disabled', 'false' );
|
||||
}
|
||||
} );
|
||||
|
||||
} )(window, document, jQuery);
|
||||
1
wp/wp-content/plugins/imagify/assets/js/options.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/options.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1325
wp/wp-content/plugins/imagify/assets/js/pricing-modal.js
Normal file
1325
wp/wp-content/plugins/imagify/assets/js/pricing-modal.js
Normal file
File diff suppressed because it is too large
Load Diff
1
wp/wp-content/plugins/imagify/assets/js/pricing-modal.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/pricing-modal.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1641
wp/wp-content/plugins/imagify/assets/js/sweetalert2.js
Normal file
1641
wp/wp-content/plugins/imagify/assets/js/sweetalert2.js
Normal file
File diff suppressed because it is too large
Load Diff
1
wp/wp-content/plugins/imagify/assets/js/sweetalert2.min.js
vendored
Normal file
1
wp/wp-content/plugins/imagify/assets/js/sweetalert2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user