Version Description
- added: CSS background image support for
- elements
- added: ExactDN + Lazy Load will auto-calculate dimensions for img elements without srcset/responsive markup
- added: ExactDN parses thumbnail url for personalization.com + WooCommerce integration
- added: ExactDN can use data-actual-width attribute for srcset generation
- added: ExactDN + Lazy Load uses devicePixelRatio to provide clearer background images
- fixed: Lazy Load for CSS background images misfires when display height is greater than width
- fixed: visitors without JS see Lazy Load placeholder + fallback image
Download this release
Release Info
Developer | nosilver4u |
Plugin | EWWW Image Optimizer |
Version | 4.7.1 |
Comparing to | |
See all releases |
Code changes from version 4.7.0 to 4.7.1
- bulk.php +6 -2
- changelog.txt +9 -0
- classes/class-ewwwio-lazy-load.php +56 -37
- classes/class-exactdn.php +39 -6
- common.php +10 -3
- ewww-image-optimizer.php +1 -1
- includes/lazysizes-post.js +45 -17
- includes/lazysizes.js +23 -16
- includes/lazysizes.min.js +1 -1
- includes/ls.unveilhooks.js +4 -1
- includes/resize_detection.js +5 -3
- readme.txt +10 -1
bulk.php
CHANGED
@@ -773,6 +773,11 @@ function ewww_image_optimizer_media_scan( $hook = '' ) {
|
|
773 |
$skipped_ids[] = $selected_id;
|
774 |
continue;
|
775 |
}
|
|
|
|
|
|
|
|
|
|
|
776 |
if ( empty( $attachment_meta[ $selected_id ]['meta'] ) ) {
|
777 |
ewwwio_debug_message( "empty meta for $selected_id" );
|
778 |
$meta = array();
|
@@ -1498,9 +1503,8 @@ function ewww_image_optimizer_bulk_loop( $hook = '', $delay = 0 ) {
|
|
1498 |
$output['new_nonce'] = '';
|
1499 |
}
|
1500 |
}
|
1501 |
-
$batch_image_limit = ( empty( $_REQUEST['ewww_batch_limit'] ) ? 999 : 1 );
|
1502 |
// Get the 'bulk attachments' with a list of IDs remaining.
|
1503 |
-
// $attachments = get_option( 'ewww_image_optimizer_bulk_attachments' );.
|
1504 |
$attachments = ewww_image_optimizer_get_queued_attachments( 'media', $batch_image_limit );
|
1505 |
if ( ! empty( $attachments ) && is_array( $attachments ) ) {
|
1506 |
$attachment = (int) $attachments[0];
|
773 |
$skipped_ids[] = $selected_id;
|
774 |
continue;
|
775 |
}
|
776 |
+
if ( ! empty( $attachment_meta[ $selected_id ]['file'] ) && false !== strpos( $attachment_meta[ $selected_id ]['file'], 'https://images-na.ssl-images-amazon.com' ) ) {
|
777 |
+
ewwwio_debug_message( "Cannot compress externally-hosted Amazon image $selected_id" );
|
778 |
+
$skipped_ids[] = $selected_id;
|
779 |
+
continue;
|
780 |
+
}
|
781 |
if ( empty( $attachment_meta[ $selected_id ]['meta'] ) ) {
|
782 |
ewwwio_debug_message( "empty meta for $selected_id" );
|
783 |
$meta = array();
|
1503 |
$output['new_nonce'] = '';
|
1504 |
}
|
1505 |
}
|
1506 |
+
$batch_image_limit = ( empty( $_REQUEST['ewww_batch_limit'] ) && ! class_exists( 'Amazon_S3_And_CloudFront' ) && ! class_exists( 'S3_Uploads' ) ? 999 : 1 );
|
1507 |
// Get the 'bulk attachments' with a list of IDs remaining.
|
|
|
1508 |
$attachments = ewww_image_optimizer_get_queued_attachments( 'media', $batch_image_limit );
|
1509 |
if ( ! empty( $attachments ) && is_array( $attachments ) ) {
|
1510 |
$attachment = (int) $attachments[0];
|
changelog.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
= 4.7.0 =
|
2 |
* added: lazy load (on ExactDN tab for now)
|
3 |
* added: JS WebP supports background images via lazy load (div elements only for now)
|
1 |
+
= 4.7.1 =
|
2 |
+
* added: CSS background image support for <li> elements
|
3 |
+
* added: ExactDN + Lazy Load will auto-calculate dimensions for img elements without srcset/responsive markup
|
4 |
+
* added: ExactDN parses thumbnail url for personalization.com + WooCommerce integration
|
5 |
+
* added: ExactDN can use data-actual-width attribute for srcset generation
|
6 |
+
* added: ExactDN + Lazy Load uses devicePixelRatio to provide clearer background images
|
7 |
+
* fixed: Lazy Load for CSS background images misfires when display height is greater than width
|
8 |
+
* fixed: visitors without JS see Lazy Load placeholder + fallback image
|
9 |
+
|
10 |
= 4.7.0 =
|
11 |
* added: lazy load (on ExactDN tab for now)
|
12 |
* added: JS WebP supports background images via lazy load (div elements only for now)
|
classes/class-ewwwio-lazy-load.php
CHANGED
@@ -41,8 +41,8 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
|
|
41 |
ewwwio_debug_message( 'you are doing it wrong' );
|
42 |
return 'you are doing it wrong';
|
43 |
}
|
44 |
-
|
45 |
-
|
46 |
add_filter( 'ewww_image_optimizer_filter_page_output', array( $this, 'filter_page_output' ), 15 );
|
47 |
|
48 |
if ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
@@ -198,40 +198,10 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
|
|
198 |
}
|
199 |
} // End foreach().
|
200 |
} // End if().
|
201 |
-
// Process background images on
|
202 |
-
$
|
203 |
-
|
204 |
-
|
205 |
-
foreach ( $divs as $index => $div ) {
|
206 |
-
ewwwio_debug_message( 'parsing a div' );
|
207 |
-
if ( false === strpos( $div, 'background:' ) && false === strpos( $div, 'background-image:' ) ) {
|
208 |
-
continue;
|
209 |
-
}
|
210 |
-
if ( false !== strpos( $div, $lazy_class ) ) {
|
211 |
-
continue;
|
212 |
-
}
|
213 |
-
if ( ! $this->validate_bgimage_tag( $div ) ) {
|
214 |
-
continue;
|
215 |
-
}
|
216 |
-
$style = $this->get_attribute( $div, 'style' );
|
217 |
-
if ( empty( $style ) ) {
|
218 |
-
continue;
|
219 |
-
}
|
220 |
-
ewwwio_debug_message( "checking style attr for background-image: $style" );
|
221 |
-
$bg_image_url = $this->get_background_image_url( $style );
|
222 |
-
if ( $bg_image_url ) {
|
223 |
-
$this->set_attribute( $div, 'class', $this->get_attribute( $div, 'class' ) . " $lazy_class", true );
|
224 |
-
$this->set_attribute( $div, 'data-bg', $bg_image_url );
|
225 |
-
$new_style = $this->remove_background_image( $style );
|
226 |
-
if ( $style !== $new_style ) {
|
227 |
-
$div = str_replace( $style, $new_style, $div );
|
228 |
-
}
|
229 |
-
}
|
230 |
-
if ( $div !== $divs[ $index ] ) {
|
231 |
-
$buffer = str_replace( $divs[ $index ], $div, $buffer );
|
232 |
-
}
|
233 |
-
}
|
234 |
-
}
|
235 |
// Images listed as picture/source elements. Mostly for NextGEN, but should work anywhere.
|
236 |
$pictures = $this->get_picture_tags_from_html( $buffer );
|
237 |
if ( ewww_image_optimizer_iterable( $pictures ) ) {
|
@@ -285,6 +255,46 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
|
|
285 |
return $buffer;
|
286 |
}
|
287 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
/**
|
289 |
* Checks if the tag is allowed to be lazy loaded.
|
290 |
*
|
@@ -355,7 +365,9 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
|
|
355 |
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
356 |
$exclusions = apply_filters(
|
357 |
'ewww_image_optimizer_lazy_bg_image_exclusions',
|
358 |
-
array(
|
|
|
|
|
359 |
$tag
|
360 |
);
|
361 |
foreach ( $exclusions as $exclusion ) {
|
@@ -379,6 +391,13 @@ class EWWWIO_Lazy_Load extends EWWWIO_Page_Parser {
|
|
379 |
return $use_lqip;
|
380 |
}
|
381 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
382 |
/**
|
383 |
* Load full lazysizes script when SCRIPT_DEBUG is enabled.
|
384 |
*/
|
41 |
ewwwio_debug_message( 'you are doing it wrong' );
|
42 |
return 'you are doing it wrong';
|
43 |
}
|
44 |
+
|
45 |
+
add_action( 'wp_head', array( $this, 'no_js_css' ) );
|
46 |
add_filter( 'ewww_image_optimizer_filter_page_output', array( $this, 'filter_page_output' ), 15 );
|
47 |
|
48 |
if ( class_exists( 'ExactDN' ) && ewww_image_optimizer_get_option( 'ewww_image_optimizer_exactdn' ) ) {
|
198 |
}
|
199 |
} // End foreach().
|
200 |
} // End if().
|
201 |
+
// Process background images on div elements.
|
202 |
+
$buffer = $this->parse_background_images( $buffer, 'div' );
|
203 |
+
// Process background images on li elements.
|
204 |
+
$buffer = $this->parse_background_images( $buffer, 'li' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
205 |
// Images listed as picture/source elements. Mostly for NextGEN, but should work anywhere.
|
206 |
$pictures = $this->get_picture_tags_from_html( $buffer );
|
207 |
if ( ewww_image_optimizer_iterable( $pictures ) ) {
|
255 |
return $buffer;
|
256 |
}
|
257 |
|
258 |
+
/**
|
259 |
+
* Parse elements of a given type for inline CSS background images.
|
260 |
+
*
|
261 |
+
* @param string $buffer The HTML content to parse.
|
262 |
+
* @param string $tag_type The type of HTML tag to look for.
|
263 |
+
* @return string The modified content with LL markup.
|
264 |
+
*/
|
265 |
+
function parse_background_images( $buffer, $tag_type ) {
|
266 |
+
$elements = $this->get_elements_from_html( $buffer, $tag_type );
|
267 |
+
if ( ewww_image_optimizer_iterable( $elements ) ) {
|
268 |
+
foreach ( $elements as $index => $element ) {
|
269 |
+
ewwwio_debug_message( "parsing a $tag_type" );
|
270 |
+
if ( false === strpos( $element, 'background:' ) && false === strpos( $element, 'background-image:' ) ) {
|
271 |
+
continue;
|
272 |
+
}
|
273 |
+
if ( ! $this->validate_bgimage_tag( $element ) ) {
|
274 |
+
continue;
|
275 |
+
}
|
276 |
+
$style = $this->get_attribute( $element, 'style' );
|
277 |
+
if ( empty( $style ) ) {
|
278 |
+
continue;
|
279 |
+
}
|
280 |
+
ewwwio_debug_message( "checking style attr for background-image: $style" );
|
281 |
+
$bg_image_url = $this->get_background_image_url( $style );
|
282 |
+
if ( $bg_image_url ) {
|
283 |
+
$new_style = $this->remove_background_image( $style );
|
284 |
+
if ( $style !== $new_style ) {
|
285 |
+
$this->set_attribute( $element, 'class', $this->get_attribute( $element, 'class' ) . ' lazyload', true );
|
286 |
+
$this->set_attribute( $element, 'data-bg', $bg_image_url );
|
287 |
+
$element = str_replace( $style, $new_style, $element );
|
288 |
+
}
|
289 |
+
}
|
290 |
+
if ( $element !== $elements[ $index ] ) {
|
291 |
+
$buffer = str_replace( $elements[ $index ], $element, $buffer );
|
292 |
+
}
|
293 |
+
}
|
294 |
+
}
|
295 |
+
return $buffer;
|
296 |
+
}
|
297 |
+
|
298 |
/**
|
299 |
* Checks if the tag is allowed to be lazy loaded.
|
300 |
*
|
365 |
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
366 |
$exclusions = apply_filters(
|
367 |
'ewww_image_optimizer_lazy_bg_image_exclusions',
|
368 |
+
array(
|
369 |
+
'lazyload',
|
370 |
+
),
|
371 |
$tag
|
372 |
);
|
373 |
foreach ( $exclusions as $exclusion ) {
|
391 |
return $use_lqip;
|
392 |
}
|
393 |
|
394 |
+
/**
|
395 |
+
* Adds a small CSS block to hide lazyload elements for no-JS browsers.
|
396 |
+
*/
|
397 |
+
function no_js_css() {
|
398 |
+
echo '<noscript><style>.lazyload[data-src]{display:none !important;}</style></noscript>';
|
399 |
+
}
|
400 |
+
|
401 |
/**
|
402 |
* Load full lazysizes script when SCRIPT_DEBUG is enabled.
|
403 |
*/
|
classes/class-exactdn.php
CHANGED
@@ -867,14 +867,20 @@ class ExactDN extends EWWWIO_Page_Parser {
|
|
867 |
$height = $filename_height;
|
868 |
}
|
869 |
// WP Attachment ID, if uploaded to this site.
|
870 |
-
|
|
|
|
|
|
|
|
|
871 |
if ( ! ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) && empty( $attachment_id ) ) {
|
872 |
ewwwio_debug_message( 'looking for attachment id' );
|
873 |
-
$attachment_id =
|
874 |
}
|
875 |
if ( ! ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) && ! empty( $attachment_id ) ) {
|
876 |
-
|
877 |
-
|
|
|
|
|
878 |
|
879 |
if ( $attachment_id ) {
|
880 |
ewwwio_debug_message( "detected attachment $attachment_id" );
|
@@ -1130,6 +1136,9 @@ class ExactDN extends EWWWIO_Page_Parser {
|
|
1130 |
if ( empty( $width ) || ! is_numeric( $width ) ) {
|
1131 |
$width = $filename_width;
|
1132 |
}
|
|
|
|
|
|
|
1133 |
if ( false !== strpos( $src, 'crop=' ) || false !== strpos( $src, '&h=' ) || false !== strpos( $src, '?h=' ) ) {
|
1134 |
$width = false;
|
1135 |
}
|
@@ -1148,6 +1157,10 @@ class ExactDN extends EWWWIO_Page_Parser {
|
|
1148 |
}
|
1149 |
} // End foreach().
|
1150 |
} // End if();
|
|
|
|
|
|
|
|
|
1151 |
if ( $this->filtering_the_page && ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ) {
|
1152 |
ewwwio_debug_message( 'rewriting all other wp_content urls' );
|
1153 |
if ( $this->exactdn_domain && $this->upload_domain ) {
|
@@ -1172,7 +1185,6 @@ class ExactDN extends EWWWIO_Page_Parser {
|
|
1172 |
$content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
|
1173 |
}
|
1174 |
}
|
1175 |
-
$content = $this->filter_bg_images( $content );
|
1176 |
ewwwio_debug_message( 'done parsing page' );
|
1177 |
$this->filtering_the_content = false;
|
1178 |
|
@@ -1189,7 +1201,7 @@ class ExactDN extends EWWWIO_Page_Parser {
|
|
1189 |
/**
|
1190 |
* Parse page content looking for elements with CSS background-image properties.
|
1191 |
*
|
1192 |
-
* @param string $content The HTML content
|
1193 |
* @return string The filtered HTML content.
|
1194 |
*/
|
1195 |
function filter_bg_images( $content ) {
|
@@ -1241,6 +1253,27 @@ class ExactDN extends EWWWIO_Page_Parser {
|
|
1241 |
return $content;
|
1242 |
}
|
1243 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1244 |
/**
|
1245 |
* Allow resizing of images for some admin-ajax requests.
|
1246 |
*
|
867 |
$height = $filename_height;
|
868 |
}
|
869 |
// WP Attachment ID, if uploaded to this site.
|
870 |
+
$attachment_id = $this->get_attribute( $images['img_tag'][ $index ], 'data-id' );
|
871 |
+
if ( empty( $attachment_id ) ) {
|
872 |
+
ewwwio_debug_message( 'data-id not found, looking for wp-image-x in class' );
|
873 |
+
preg_match( '#class=["|\']?[^"\']*wp-image-([\d]+)[^"\']*["|\']?#i', $images['img_tag'][ $index ], $attachment_id );
|
874 |
+
}
|
875 |
if ( ! ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) && empty( $attachment_id ) ) {
|
876 |
ewwwio_debug_message( 'looking for attachment id' );
|
877 |
+
$attachment_id = attachment_url_to_postid( $src );
|
878 |
}
|
879 |
if ( ! ewww_image_optimizer_get_option( 'exactdn_prevent_db_queries' ) && ! empty( $attachment_id ) ) {
|
880 |
+
if ( is_array( $attachment_id ) ) {
|
881 |
+
$attachment_id = intval( array_pop( $attachment_id ) );
|
882 |
+
}
|
883 |
+
ewwwio_debug_message( "using attachment id ($attachment_id) to get source image" );
|
884 |
|
885 |
if ( $attachment_id ) {
|
886 |
ewwwio_debug_message( "detected attachment $attachment_id" );
|
1136 |
if ( empty( $width ) || ! is_numeric( $width ) ) {
|
1137 |
$width = $filename_width;
|
1138 |
}
|
1139 |
+
if ( empty( $width ) || ! is_numeric( $width ) ) {
|
1140 |
+
$width = $this->get_attribute( $images['img_tag'][ $index ], 'data-actual-width' );
|
1141 |
+
}
|
1142 |
if ( false !== strpos( $src, 'crop=' ) || false !== strpos( $src, '&h=' ) || false !== strpos( $src, '?h=' ) ) {
|
1143 |
$width = false;
|
1144 |
}
|
1157 |
}
|
1158 |
} // End foreach().
|
1159 |
} // End if();
|
1160 |
+
$content = $this->filter_bg_images( $content );
|
1161 |
+
if ( $this->filtering_the_page ) {
|
1162 |
+
$content = $this->filter_prz_thumb( $content );
|
1163 |
+
}
|
1164 |
if ( $this->filtering_the_page && ewww_image_optimizer_get_option( 'exactdn_all_the_things' ) ) {
|
1165 |
ewwwio_debug_message( 'rewriting all other wp_content urls' );
|
1166 |
if ( $this->exactdn_domain && $this->upload_domain ) {
|
1185 |
$content = str_replace( '?wpcontent-bypass?', 'wp-content', $content );
|
1186 |
}
|
1187 |
}
|
|
|
1188 |
ewwwio_debug_message( 'done parsing page' );
|
1189 |
$this->filtering_the_content = false;
|
1190 |
|
1201 |
/**
|
1202 |
* Parse page content looking for elements with CSS background-image properties.
|
1203 |
*
|
1204 |
+
* @param string $content The HTML content to parse.
|
1205 |
* @return string The filtered HTML content.
|
1206 |
*/
|
1207 |
function filter_bg_images( $content ) {
|
1253 |
return $content;
|
1254 |
}
|
1255 |
|
1256 |
+
/**
|
1257 |
+
* Parse page content looking for thumburl from personalization.com.
|
1258 |
+
*
|
1259 |
+
* @param string $content The HTML content to parse.
|
1260 |
+
* @return string The filtered HTML content.
|
1261 |
+
*/
|
1262 |
+
function filter_prz_thumb( $content ) {
|
1263 |
+
if ( ! class_exists( 'WooCommerce' ) || false === strpos( $content, 'productDetailsForPrz' ) ) {
|
1264 |
+
return $content;
|
1265 |
+
}
|
1266 |
+
ewwwio_debug_message( '<b>' . __METHOD__ . '()</b>' );
|
1267 |
+
$prz_match = preg_match( '#productDetailsForPrz=[^<]+?thumbnailUrl:\'([^\']+?)\'[^<]+?</script>#', $content, $prz_detail_matches );
|
1268 |
+
if ( $prz_match && ! empty( $prz_detail_matches[1] ) && $this->validate_image_url( $prz_detail_matches[1] ) ) {
|
1269 |
+
$prz_thumb = $this->generate_url( $prz_detail_matches[1], apply_filters( 'exactdn_personalizationdotcom_thumb_args', '', $prz_detail_matches[1] ) );
|
1270 |
+
if ( $prz_thumb != $prz_detail_matches ) {
|
1271 |
+
$content = str_replace( "thumbnailUrl:'{$prz_detail_matches[1]}'", "thumbnailUrl:'$prz_thumb'", $content );
|
1272 |
+
}
|
1273 |
+
}
|
1274 |
+
return $content;
|
1275 |
+
}
|
1276 |
+
|
1277 |
/**
|
1278 |
* Allow resizing of images for some admin-ajax requests.
|
1279 |
*
|
common.php
CHANGED
@@ -10,7 +10,7 @@
|
|
10 |
* @package EWWW_Image_Optimizer
|
11 |
*/
|
12 |
|
13 |
-
// TODO: might be able to use the Custom Bulk Actions in 4.7 to support the bulk optimize drop-down menu.
|
14 |
// TODO: need to make the scheduler so it can resume without having to re-run the queue population, and then we can probably also flush the queue when scheduled opt starts, but later it would be nice to implement the bulk_loop as the aux_loop so that it could handle media properly.
|
15 |
// TODO: Add a custom async function for parallel mode to store image as pending and use the row ID instead of relative path.
|
16 |
// TODO: write some tests for AGR.
|
@@ -18,12 +18,11 @@
|
|
18 |
// TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
|
19 |
// TODO: can some of the bulk "fallbacks" be implemented for async processing?
|
20 |
// TODO: check to see if we can use PHP and WP core is_iterable and is_countable functions.
|
21 |
-
// TODO: ExactDN can use data-id attribute in 5.0 instead of trying to grok wp-image-1234 in the class.
|
22 |
if ( ! defined( 'ABSPATH' ) ) {
|
23 |
exit;
|
24 |
}
|
25 |
|
26 |
-
define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '
|
27 |
|
28 |
// Initialize a couple globals.
|
29 |
$ewww_debug = '';
|
@@ -6446,6 +6445,14 @@ function ewww_image_optimizer_custom_column( $column_name, $id, $meta = null, $r
|
|
6446 |
}
|
6447 |
$output .= "<div id='ewww-media-status-$id'>";
|
6448 |
$ewww_cdn = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6449 |
if ( is_array( $meta ) && ! empty( $meta['cloudinary'] ) ) {
|
6450 |
$output .= esc_html__( 'Cloudinary image', 'ewww-image-optimizer' ) . '</div>';
|
6451 |
if ( $return_output ) {
|
10 |
* @package EWWW_Image_Optimizer
|
11 |
*/
|
12 |
|
13 |
+
// TODO: might be able to use the Custom Bulk Actions in WP 4.7 to support the bulk optimize drop-down menu.
|
14 |
// TODO: need to make the scheduler so it can resume without having to re-run the queue population, and then we can probably also flush the queue when scheduled opt starts, but later it would be nice to implement the bulk_loop as the aux_loop so that it could handle media properly.
|
15 |
// TODO: Add a custom async function for parallel mode to store image as pending and use the row ID instead of relative path.
|
16 |
// TODO: write some tests for AGR.
|
18 |
// TODO: use this: https://codex.wordpress.org/AJAX_in_Plugins#The_post-load_JavaScript_Event .
|
19 |
// TODO: can some of the bulk "fallbacks" be implemented for async processing?
|
20 |
// TODO: check to see if we can use PHP and WP core is_iterable and is_countable functions.
|
|
|
21 |
if ( ! defined( 'ABSPATH' ) ) {
|
22 |
exit;
|
23 |
}
|
24 |
|
25 |
+
define( 'EWWW_IMAGE_OPTIMIZER_VERSION', '471.0' );
|
26 |
|
27 |
// Initialize a couple globals.
|
28 |
$ewww_debug = '';
|
6445 |
}
|
6446 |
$output .= "<div id='ewww-media-status-$id'>";
|
6447 |
$ewww_cdn = false;
|
6448 |
+
if ( is_array( $meta ) && ! empty( $meta['file'] ) && false !== strpos( $meta['file'], 'https://images-na.ssl-images-amazon.com' ) ) {
|
6449 |
+
$output .= esc_html__( 'Amazon-hosted image', 'ewww-image-optimizer' ) . '</div>';
|
6450 |
+
if ( $return_output ) {
|
6451 |
+
return $output;
|
6452 |
+
}
|
6453 |
+
echo $output;
|
6454 |
+
return;
|
6455 |
+
}
|
6456 |
if ( is_array( $meta ) && ! empty( $meta['cloudinary'] ) ) {
|
6457 |
$output .= esc_html__( 'Cloudinary image', 'ewww-image-optimizer' ) . '</div>';
|
6458 |
if ( $return_output ) {
|
ewww-image-optimizer.php
CHANGED
@@ -13,7 +13,7 @@ Plugin Name: EWWW Image Optimizer
|
|
13 |
Plugin URI: https://wordpress.org/plugins/ewww-image-optimizer/
|
14 |
Description: Reduce file sizes for images within WordPress including NextGEN Gallery and GRAND FlAGallery. Uses jpegtran, optipng/pngout, and gifsicle.
|
15 |
Author: Exactly WWW
|
16 |
-
Version: 4.7.
|
17 |
Author URI: https://ewww.io/
|
18 |
License: GPLv3
|
19 |
*/
|
13 |
Plugin URI: https://wordpress.org/plugins/ewww-image-optimizer/
|
14 |
Description: Reduce file sizes for images within WordPress including NextGEN Gallery and GRAND FlAGallery. Uses jpegtran, optipng/pngout, and gifsicle.
|
15 |
Author: Exactly WWW
|
16 |
+
Version: 4.7.1
|
17 |
Author URI: https://ewww.io/
|
18 |
License: GPLv3
|
19 |
*/
|
includes/lazysizes-post.js
CHANGED
@@ -1,38 +1,66 @@
|
|
1 |
lazysizesWebP('alpha', lazySizes.init);
|
2 |
-
function constrainSrc(
|
3 |
var regW = /w=(\d+)/;
|
4 |
var regFit = /fit=(\d+),(\d+)/;
|
5 |
var regResize = /resize=(\d+),(\d+)/;
|
6 |
-
if (
|
7 |
-
var
|
8 |
-
if(
|
9 |
-
return
|
10 |
}
|
11 |
-
var
|
12 |
-
if(
|
13 |
-
return
|
14 |
}
|
15 |
-
var
|
16 |
-
if(
|
17 |
-
return
|
18 |
}
|
19 |
if(!resultW && !resultFit && !resultResize){
|
20 |
-
|
21 |
-
|
22 |
}
|
23 |
-
if (
|
24 |
-
return
|
25 |
}
|
26 |
-
return
|
27 |
}
|
28 |
document.addEventListener('lazybeforeunveil', function(e){
|
29 |
var target = e.target;
|
30 |
//console.log('the target');
|
31 |
//console.log(target);
|
32 |
//console.log('loading an image');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
if(ewww_webp_supported) {
|
34 |
//console.log('we could load webp');
|
35 |
-
var srcset = target.getAttribute('data-srcset');
|
36 |
//console.log(srcset);
|
37 |
if (srcset && -1 < srcset.search('webp=1')){
|
38 |
//console.log('srcset already contains webp ' + srcset);
|
1 |
lazysizesWebP('alpha', lazySizes.init);
|
2 |
+
function constrainSrc(url,objectWidth,objectHeight){
|
3 |
var regW = /w=(\d+)/;
|
4 |
var regFit = /fit=(\d+),(\d+)/;
|
5 |
var regResize = /resize=(\d+),(\d+)/;
|
6 |
+
if (url.search('\\?') > 0 && url.search(ewww_lazy_vars.exactdn_domain) > 0){
|
7 |
+
var resultResize = regResize.exec(url);
|
8 |
+
if(resultResize && objectWidth < resultResize[1]){
|
9 |
+
return url.replace(regResize, 'resize=' + objectWidth + ',' + objectHeight);
|
10 |
}
|
11 |
+
var resultW = regW.exec(url);
|
12 |
+
if(resultW && objectWidth <= resultW[1]){
|
13 |
+
return url.replace(regW, 'resize=' + objectWidth + ',' + objectHeight);
|
14 |
}
|
15 |
+
var resultFit = regFit.exec(url);
|
16 |
+
if(resultFit && objectWidth < resultFit[1]){
|
17 |
+
return url.replace(regFit, 'resize=' + objectWidth + ',' + objectHeight);
|
18 |
}
|
19 |
if(!resultW && !resultFit && !resultResize){
|
20 |
+
return url + '&resize=' + objectWidth + ',' + objectHeight;
|
21 |
+
}
|
22 |
}
|
23 |
+
if (url.search('\\?') == -1 && url.search(ewww_lazy_vars.exactdn_domain) > 0){
|
24 |
+
return url + '?resize=' + objectWidth + ',' + objectHeight;
|
25 |
}
|
26 |
+
return url;
|
27 |
}
|
28 |
document.addEventListener('lazybeforeunveil', function(e){
|
29 |
var target = e.target;
|
30 |
//console.log('the target');
|
31 |
//console.log(target);
|
32 |
//console.log('loading an image');
|
33 |
+
var wrongSize = false;
|
34 |
+
var srcset = target.getAttribute('data-srcset');
|
35 |
+
if ( ! srcset && target.naturalWidth) {
|
36 |
+
console.log('we have something');
|
37 |
+
if ((target.naturalWidth > 1) && (target.naturalHeight > 1)) {
|
38 |
+
// For each image with a natural width which isn't
|
39 |
+
// a 1x1 image, check its size.
|
40 |
+
var dPR = (window.devicePixelRatio || 1);
|
41 |
+
var wrongWidth = (target.clientWidth * 1.25 < target.naturalWidth);
|
42 |
+
var wrongHeight = (target.clientHeight * 1.25 < target.naturalHeight);
|
43 |
+
if (wrongWidth || wrongHeight) {
|
44 |
+
console.log(Math.round(target.clientWidth * dPR) + "x" + Math.round(target.clientHeight * dPR) + ", natural is " +
|
45 |
+
target.naturalWidth + "x" + target.naturalHeight + "!");
|
46 |
+
var targetWidth = Math.round(target.offsetWidth * dPR);
|
47 |
+
var targetHeight = Math.round(target.offsetHeight * dPR);
|
48 |
+
|
49 |
+
var src = target.getAttribute('data-src');
|
50 |
+
var webpsrc = target.getAttribute('data-src-webp');
|
51 |
+
if(ewww_webp_supported && webpsrc && -1 == src.search('webp=1')){
|
52 |
+
console.log('using data-src-webp');
|
53 |
+
src = webpsrc;
|
54 |
+
}
|
55 |
+
var newSrc = constrainSrc(src,targetWidth,targetHeight);
|
56 |
+
if (newSrc && src != newSrc){
|
57 |
+
target.setAttribute('data-src', newSrc);
|
58 |
+
}
|
59 |
+
}
|
60 |
+
}
|
61 |
+
}
|
62 |
if(ewww_webp_supported) {
|
63 |
//console.log('we could load webp');
|
|
|
64 |
//console.log(srcset);
|
65 |
if (srcset && -1 < srcset.search('webp=1')){
|
66 |
//console.log('srcset already contains webp ' + srcset);
|
includes/lazysizes.js
CHANGED
@@ -303,10 +303,6 @@
|
|
303 |
|
304 |
var resetPreloading = function(e){
|
305 |
isLoading--;
|
306 |
-
if(e && e.target){
|
307 |
-
addRemoveLoadEvents(e.target, resetPreloading);
|
308 |
-
}
|
309 |
-
|
310 |
if(!e || isLoading < 0 || !e.target){
|
311 |
isLoading = 0;
|
312 |
}
|
@@ -361,6 +357,8 @@
|
|
361 |
docElem.clientHeight > 500 && docElem.clientWidth > 500 ? 500 : 370 :
|
362 |
lazySizesConfig.expand;
|
363 |
|
|
|
|
|
364 |
preloadExpand = defaultExpand * lazySizesConfig.expFactor;
|
365 |
hFac = lazySizesConfig.hFac;
|
366 |
isBodyHidden = null;
|
@@ -420,10 +418,18 @@
|
|
420 |
var throttledCheckElements = throttle(checkElements);
|
421 |
|
422 |
var switchLoadingClass = function(e){
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
427 |
};
|
428 |
var rafedSwitchLoadingClass = rAFIt(switchLoadingClass);
|
429 |
var rafSwitchLoadingClass = function(e){
|
@@ -477,12 +483,11 @@
|
|
477 |
|
478 |
event = {target: elem};
|
479 |
|
|
|
|
|
480 |
if(firesLoad){
|
481 |
-
addRemoveLoadEvents(elem, resetPreloading, true);
|
482 |
clearTimeout(resetPreloadingTimer);
|
483 |
resetPreloadingTimer = setTimeout(resetPreloading, 2500);
|
484 |
-
|
485 |
-
addClass(elem, lazySizesConfig.loadingClass);
|
486 |
addRemoveLoadEvents(elem, rafSwitchLoadingClass, true);
|
487 |
}
|
488 |
|
@@ -511,13 +516,15 @@
|
|
511 |
removeClass(elem, lazySizesConfig.lazyClass);
|
512 |
|
513 |
rAF(function(){
|
|
|
514 |
if( !firesLoad || (elem.complete && elem.naturalWidth > 1)){
|
515 |
-
if(firesLoad){
|
516 |
-
resetPreloading(event);
|
517 |
-
} else {
|
518 |
-
isLoading--;
|
519 |
-
}
|
520 |
switchLoadingClass(event);
|
|
|
|
|
|
|
|
|
|
|
|
|
521 |
}
|
522 |
}, true);
|
523 |
});
|
303 |
|
304 |
var resetPreloading = function(e){
|
305 |
isLoading--;
|
|
|
|
|
|
|
|
|
306 |
if(!e || isLoading < 0 || !e.target){
|
307 |
isLoading = 0;
|
308 |
}
|
357 |
docElem.clientHeight > 500 && docElem.clientWidth > 500 ? 500 : 370 :
|
358 |
lazySizesConfig.expand;
|
359 |
|
360 |
+
lazysizes._defEx = defaultExpand;
|
361 |
+
|
362 |
preloadExpand = defaultExpand * lazySizesConfig.expFactor;
|
363 |
hFac = lazySizesConfig.hFac;
|
364 |
isBodyHidden = null;
|
418 |
var throttledCheckElements = throttle(checkElements);
|
419 |
|
420 |
var switchLoadingClass = function(e){
|
421 |
+
var elem = e.target;
|
422 |
+
|
423 |
+
if (elem._lazyCache) {
|
424 |
+
delete elem._lazyCache;
|
425 |
+
return;
|
426 |
+
}
|
427 |
+
|
428 |
+
resetPreloading(e);
|
429 |
+
addClass(elem, lazySizesConfig.loadedClass);
|
430 |
+
removeClass(elem, lazySizesConfig.loadingClass);
|
431 |
+
addRemoveLoadEvents(elem, rafSwitchLoadingClass);
|
432 |
+
triggerEvent(elem, 'lazyloaded');
|
433 |
};
|
434 |
var rafedSwitchLoadingClass = rAFIt(switchLoadingClass);
|
435 |
var rafSwitchLoadingClass = function(e){
|
483 |
|
484 |
event = {target: elem};
|
485 |
|
486 |
+
addClass(elem, lazySizesConfig.loadingClass);
|
487 |
+
|
488 |
if(firesLoad){
|
|
|
489 |
clearTimeout(resetPreloadingTimer);
|
490 |
resetPreloadingTimer = setTimeout(resetPreloading, 2500);
|
|
|
|
|
491 |
addRemoveLoadEvents(elem, rafSwitchLoadingClass, true);
|
492 |
}
|
493 |
|
516 |
removeClass(elem, lazySizesConfig.lazyClass);
|
517 |
|
518 |
rAF(function(){
|
519 |
+
// Part of this can be removed as soon as this fix is older: https://bugs.chromium.org/p/chromium/issues/detail?id=7731 (2015)
|
520 |
if( !firesLoad || (elem.complete && elem.naturalWidth > 1)){
|
|
|
|
|
|
|
|
|
|
|
521 |
switchLoadingClass(event);
|
522 |
+
elem._lazyCache = true;
|
523 |
+
setTimeout(function(){
|
524 |
+
if ('_lazyCache' in elem) {
|
525 |
+
delete elem._lazyCache;
|
526 |
+
}
|
527 |
+
}, 9);
|
528 |
}
|
529 |
}, true);
|
530 |
});
|
includes/lazysizes.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
var ewww_webp_supported=!1;function lazysizesWebP(e,t){var a=new Image;a.onload=function(){ewww_webp_supported=0<a.width&&0<a.height,t()},a.onerror=function(){t()},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[e]}function constrainSrc(e,t,a){var i=/w=(\d+)/,n=/fit=(\d+),(\d+)/,r=/resize=(\d+),(\d+)/;if(0<e.search("\\?")&&0<e.search(ewww_lazy_vars.exactdn_domain)){var o=i.exec(e);if(o&&t<o[1])return e.replace(i,"w="+t);var s=n.exec(e);if(s&&t<s[1])return e.replace(n,"fit="+t+","+a);var l=r.exec(e);if(l&&t<l[1])return e.replace(r,"resize="+t+","+a);if(!o&&!s&&!l)return e+"&w="+t}return-1==e.search("\\?")&&0<e.search(ewww_lazy_vars.exactdn_domain)?e+"?w="+t:e}window.lazySizesConfig=window.lazySizesConfig||{},window.lazySizesConfig.init=!1,function(e,t){var a=function(i,f){"use strict";if(!f.getElementsByClassName)return;var g,z,v=f.documentElement,r=i.Date,n=i.HTMLPictureElement,o="addEventListener",m="getAttribute",t=i[o],u=i.setTimeout,a=i.requestAnimationFrame||u,s=i.requestIdleCallback,A=/^picture$/i,l=["load","error","lazyincluded","_lazyloaded"],d={},p=Array.prototype.forEach,c=function(e,t){return d[t]||(d[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),d[t].test(e[m]("class")||"")&&d[t]},y=function(e,t){c(e,t)||e.setAttribute("class",(e[m]("class")||"").trim()+" "+t)},h=function(e,t){var a;(a=c(e,t))&&e.setAttribute("class",(e[m]("class")||"").replace(a," "))},b=function(t,a,e){var i=e?o:"removeEventListener";e&&b(t,a),l.forEach(function(e){t[i](e,a)})},w=function(e,t,a,i,n){var r=f.createEvent("Event");return a||(a={}),a.instance=g,r.initEvent(t,!i,!n),r.detail=a,e.dispatchEvent(r),r},C=function(e,t){var a;!n&&(a=i.picturefill||z.pf)?(t&&t.src&&!e[m]("srcset")&&e.setAttribute("srcset",t.src),a({reevaluate:!0,elements:[e]})):t&&t.src&&(e.src=t.src)},E=function(e,t){return(getComputedStyle(e,null)||{})[t]},_=function(e,t,a){for(a=a||e.offsetWidth;a<z.minSize&&t&&!e._lazysizesWidth;)a=t.offsetWidth,t=t.parentNode;return a},x=(L=[],M=[],N=L,R=function(){var e=N;for(N=L.length?M:L,W=!(S=!0);e.length;)e.shift()();S=!1},Q=function(e,t){S&&!t?e.apply(this,arguments):(N.push(e),W||(W=!0,(f.hidden?u:a)(R)))},Q._lsFlush=R,Q),e=function(a,e){return e?function(){x(a)}:function(){var e=this,t=arguments;x(function(){a.apply(e,t)})}},B=function(e){var t,a,i=function(){t=null,e()},n=function(){var e=r.now()-a;e<99?u(n,99-e):(s||i)(i)};return function(){a=r.now(),t||(t=u(n,99))}};var S,W,L,M,N,R,Q;!function(){var e,t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};for(e in z=i.lazySizesConfig||i.lazysizesConfig||{},t)e in z||(z[e]=t[e]);i.lazySizesConfig=z,u(function(){z.init&&P()})}();var k=(se=/^img$/i,le=/^iframe$/i,de="onscroll"in i&&!/(gle|ing)bot/.test(navigator.userAgent),ce=0,ue=0,Ae=-1,fe=function(e){ue--,e&&e.target&&b(e.target,fe),(!e||ue<0||!e.target)&&(ue=0)},ge=function(e){return null==Z&&(Z="hidden"==E(f.body,"visibility")),Z||"hidden"!=E(e.parentNode,"visibility")&&"hidden"!=E(e,"visibility")},ze=function(e,t){var a,i=e,n=ge(e);for(V-=t,K+=t,X-=t,Y+=t;n&&(i=i.offsetParent)&&i!=f.body&&i!=v;)(n=0<(E(i,"opacity")||1))&&"visible"!=E(i,"overflow")&&(a=i.getBoundingClientRect(),n=Y>a.left&&X<a.right&&K>a.top-1&&V<a.bottom+1);return n},ve=function(){var e,t,a,i,n,r,o,s,l,d,c,u,A=g.elements;if((G=z.loadMode)&&ue<8&&(e=A.length)){for(t=0,Ae++,d=!z.expand||z.expand<1?500<v.clientHeight&&500<v.clientWidth?500:370:z.expand,c=d*z.expFactor,u=z.hFac,Z=null,ce<c&&ue<1&&2<Ae&&2<G&&!f.hidden?(ce=c,Ae=0):ce=1<G&&1<Ae&&ue<6?d:0;t<e;t++)if(A[t]&&!A[t]._lazyRace)if(de)if((s=A[t][m]("data-expand"))&&(r=1*s)||(r=ce),l!==r&&(q=innerWidth+r*u,j=innerHeight+r,o=-1*r,l=r),a=A[t].getBoundingClientRect(),(K=a.bottom)>=o&&(V=a.top)<=j&&(Y=a.right)>=o*u&&(X=a.left)<=q&&(K||Y||X||V)&&(z.loadHidden||ge(A[t]))&&(J&&ue<3&&!s&&(G<3||Ae<4)||ze(A[t],r))){if(Ce(A[t]),n=!0,9<ue)break}else!n&&J&&!i&&ue<4&&Ae<4&&2<G&&(H[0]||z.preloadAfterLoad)&&(H[0]||!s&&(K||Y||X||V||"auto"!=A[t][m](z.sizesAttr)))&&(i=H[0]||A[t]);else Ce(A[t]);i&&!n&&Ce(i)}},ee=ve,ae=0,ie=z.throttleDelay,ne=z.ricTimeout,re=function(){te=!1,ae=r.now(),ee()},oe=s&&49<ne?function(){s(re,{timeout:ne}),ne!==z.ricTimeout&&(ne=z.ricTimeout)}:e(function(){u(re)},!0),me=function(e){var t;(e=!0===e)&&(ne=33),te||(te=!0,(t=ie-(r.now()-ae))<0&&(t=0),e||t<9?oe():u(oe,t))},pe=function(e){y(e.target,z.loadedClass),h(e.target,z.loadingClass),b(e.target,he),w(e.target,"lazyloaded")},ye=e(pe),he=function(e){ye({target:e.target})},be=function(e){var t,a=e[m](z.srcsetAttr);(t=z.customMedia[e[m]("data-media")||e[m]("media")])&&e.setAttribute("media",t),a&&e.setAttribute("srcset",a)},we=e(function(e,t,a,i,n){var r,o,s,l,d,c;(d=w(e,"lazybeforeunveil",t)).defaultPrevented||(i&&(a?y(e,z.autosizesClass):e.setAttribute("sizes",i)),o=e[m](z.srcsetAttr),r=e[m](z.srcAttr),n&&(s=e.parentNode,l=s&&A.test(s.nodeName||"")),c=t.firesLoad||"src"in e&&(o||r||l),d={target:e},c&&(b(e,fe,!0),clearTimeout(O),O=u(fe,2500),y(e,z.loadingClass),b(e,he,!0)),l&&p.call(s.getElementsByTagName("source"),be),o?e.setAttribute("srcset",o):r&&!l&&(le.test(e.nodeName)?function(t,a){try{t.contentWindow.location.replace(a)}catch(e){t.src=a}}(e,r):e.src=r),n&&(o||l)&&C(e,{src:r})),e._lazyRace&&delete e._lazyRace,h(e,z.lazyClass),x(function(){(!c||e.complete&&1<e.naturalWidth)&&(c?fe(d):ue--,pe(d))},!0)}),Ce=function(e){var t,a=se.test(e.nodeName),i=a&&(e[m](z.sizesAttr)||e[m]("sizes")),n="auto"==i;(!n&&J||!a||!e[m]("src")&&!e.srcset||e.complete||c(e,z.errorClass)||!c(e,z.lazyClass))&&(t=w(e,"lazyunveilread").detail,n&&D.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,ue++,we(e,t,n,i,a))},Ee=function(){if(!J)if(r.now()-$<999)u(Ee,999);else{var e=B(function(){z.loadMode=3,me()});J=!0,z.loadMode=3,me(),t("scroll",function(){3==z.loadMode&&(z.loadMode=2),e()},!0)}},{_:function(){$=r.now(),g.elements=f.getElementsByClassName(z.lazyClass),H=f.getElementsByClassName(z.lazyClass+" "+z.preloadClass),t("scroll",me,!0),t("resize",me,!0),i.MutationObserver?new MutationObserver(me).observe(v,{childList:!0,subtree:!0,attributes:!0}):(v[o]("DOMNodeInserted",me,!0),v[o]("DOMAttrModified",me,!0),setInterval(me,999)),t("hashchange",me,!0),["focus","mouseover","click","load","transitionend","animationend","webkitAnimationEnd"].forEach(function(e){f[o](e,me,!0)}),/d$|^c/.test(f.readyState)?Ee():(t("load",Ee),f[o]("DOMContentLoaded",me),u(Ee,2e4)),g.elements.length?(ve(),x._lsFlush()):me()},checkElems:me,unveil:Ce}),D=(F=e(function(e,t,a,i){var n,r,o;if(e._lazysizesWidth=i,i+="px",e.setAttribute("sizes",i),A.test(t.nodeName||""))for(n=t.getElementsByTagName("source"),r=0,o=n.length;r<o;r++)n[r].setAttribute("sizes",i);a.detail.dataAttr||C(e,a.detail)}),U=function(e,t,a){var i,n=e.parentNode;n&&(a=_(e,n,a),(i=w(e,"lazybeforesizes",{width:a,dataAttr:!!t})).defaultPrevented||(a=i.detail.width)&&a!==e._lazysizesWidth&&F(e,n,i,a))},I=B(function(){var e,t=T.length;if(t)for(e=0;e<t;e++)U(T[e])}),{_:function(){T=f.getElementsByClassName(z.autosizesClass),t("resize",I)},checkElems:I,updateElem:U}),P=function(){P.i||(P.i=!0,D._(),k._())};var T,F,U,I;var H,J,O,G,$,q,j,V,X,Y,K,Z,ee,te,ae,ie,ne,re,oe,se,le,de,ce,ue,Ae,fe,ge,ze,ve,me,pe,ye,he,be,we,Ce,Ee;return g={cfg:z,autoSizer:D,loader:k,init:P,uP:C,aC:y,rC:h,hC:c,fire:w,gW:_,rAF:x}}(e,e.document);e.lazySizes=a,"object"==typeof module&&module.exports&&(module.exports=a)}(window),lazysizesWebP("alpha",lazySizes.init),document.addEventListener("lazybeforeunveil",function(e){var t=e.target;if(ewww_webp_supported){var a=t.getAttribute("data-srcset");if(a&&-1<a.search("webp=1"))return;if(a){var i=t.getAttribute("data-srcset-webp");i&&t.setAttribute("data-srcset",i)}var n=t.getAttribute("data-src");if(n&&-1<n.search("webp=1"))return;var r=t.getAttribute("data-src-webp");if(!r)return;t.setAttribute("data-src",r)}}),function(e,t){var a=function(){t(e.lazySizes),e.removeEventListener("lazyunveilread",a,!0)};t=t.bind(null,e,e.document),"object"==typeof module&&module.exports?t(require("lazysizes")):e.lazySizes?a():e.addEventListener("lazyunveilread",a,!0)}(window,function(e,i,n){"use strict";var r,o;i.addEventListener&&(r=function(e,t){var a=i.createElement("img");a.onload=function(){a.onload=null,a.onerror=null,a=null,t()},a.onerror=a.onload,a.src=e,a&&a.complete&&a.onload&&a.onload()},addEventListener("lazybeforeunveil",function(e){var t,a,i;e.detail.instance==n&&(e.defaultPrevented||("none"==e.target.preload&&(e.target.preload="auto"),(t=e.target.getAttribute("data-bg"))&&(ewww_webp_supported&&(a=e.target.getAttribute("data-bg-webp"))&&(t=a),t=constrainSrc(t,e.target.offsetWidth,e.target.offsetHeight),e.detail.firesLoad=!0,r(t,function(){e.target.style.backgroundImage="url("+(o.test(t)?JSON.stringify(t):t)+")",e.detail.firesLoad=!1,n.fire(e.target,"_lazyloaded",{},!0,!0)})),(i=e.target.getAttribute("data-poster"))&&(e.detail.firesLoad=!0,r(i,function(){e.target.poster=i,e.detail.firesLoad=!1,n.fire(e.target,"_lazyloaded",{},!0,!0)}))))},!(o=/\(|\)|\s|'/)))});
|
1 |
+
var ewww_webp_supported=!1;function lazysizesWebP(e,t){var a=new Image;a.onload=function(){ewww_webp_supported=0<a.width&&0<a.height,t()},a.onerror=function(){t()},a.src="data:image/webp;base64,"+{alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"}[e]}function constrainSrc(e,t,a){var i=/w=(\d+)/,n=/fit=(\d+),(\d+)/,r=/resize=(\d+),(\d+)/;if(0<e.search("\\?")&&0<e.search(ewww_lazy_vars.exactdn_domain)){var o=r.exec(e);if(o&&t<o[1])return e.replace(r,"resize="+t+","+a);var s=i.exec(e);if(s&&t<=s[1])return e.replace(i,"resize="+t+","+a);var l=n.exec(e);if(l&&t<l[1])return e.replace(n,"resize="+t+","+a);if(!s&&!l&&!o)return e+"&resize="+t+","+a}return-1==e.search("\\?")&&0<e.search(ewww_lazy_vars.exactdn_domain)?e+"?resize="+t+","+a:e}window.lazySizesConfig=window.lazySizesConfig||{},window.lazySizesConfig.init=!1,function(e,t){var a=function(i,A){"use strict";if(!A.getElementsByClassName)return;var g,z,h=A.documentElement,r=i.Date,n=i.HTMLPictureElement,o="addEventListener",v="getAttribute",t=i[o],u=i.setTimeout,a=i.requestAnimationFrame||u,s=i.requestIdleCallback,f=/^picture$/i,l=["load","error","lazyincluded","_lazyloaded"],d={},p=Array.prototype.forEach,c=function(e,t){return d[t]||(d[t]=new RegExp("(\\s|^)"+t+"(\\s|$)")),d[t].test(e[v]("class")||"")&&d[t]},m=function(e,t){c(e,t)||e.setAttribute("class",(e[v]("class")||"").trim()+" "+t)},y=function(e,t){var a;(a=c(e,t))&&e.setAttribute("class",(e[v]("class")||"").replace(a," "))},b=function(t,a,e){var i=e?o:"removeEventListener";e&&b(t,a),l.forEach(function(e){t[i](e,a)})},w=function(e,t,a,i,n){var r=A.createEvent("Event");return a||(a={}),a.instance=g,r.initEvent(t,!i,!n),r.detail=a,e.dispatchEvent(r),r},C=function(e,t){var a;!n&&(a=i.picturefill||z.pf)?(t&&t.src&&!e[v]("srcset")&&e.setAttribute("srcset",t.src),a({reevaluate:!0,elements:[e]})):t&&t.src&&(e.src=t.src)},_=function(e,t){return(getComputedStyle(e,null)||{})[t]},E=function(e,t,a){for(a=a||e.offsetWidth;a<z.minSize&&t&&!e._lazysizesWidth;)a=t.offsetWidth,t=t.parentNode;return a},W=(B=[],R=[],L=B,N=function(){var e=L;for(L=B.length?R:B,S=!(M=!0);e.length;)e.shift()();M=!1},Q=function(e,t){M&&!t?e.apply(this,arguments):(L.push(e),S||(S=!0,(A.hidden?u:a)(N)))},Q._lsFlush=N,Q),e=function(a,e){return e?function(){W(a)}:function(){var e=this,t=arguments;W(function(){a.apply(e,t)})}},x=function(e){var t,a,i=function(){t=null,e()},n=function(){var e=r.now()-a;e<99?u(n,99-e):(s||i)(i)};return function(){a=r.now(),t||(t=u(n,99))}};var M,S,B,R,L,N,Q;!function(){var e,t={lazyClass:"lazyload",loadedClass:"lazyloaded",loadingClass:"lazyloading",preloadClass:"lazypreload",errorClass:"lazyerror",autosizesClass:"lazyautosizes",srcAttr:"data-src",srcsetAttr:"data-srcset",sizesAttr:"data-sizes",minSize:40,customMedia:{},init:!0,expFactor:1.5,hFac:.8,loadMode:2,loadHidden:!0,ricTimeout:0,throttleDelay:125};for(e in z=i.lazySizesConfig||i.lazysizesConfig||{},t)e in z||(z[e]=t[e]);i.lazySizesConfig=z,u(function(){z.init&&k()})}();var P=(se=/^img$/i,le=/^iframe$/i,de="onscroll"in i&&!/(gle|ing)bot/.test(navigator.userAgent),ce=0,ue=0,fe=-1,Ae=function(e){ue--,(!e||ue<0||!e.target)&&(ue=0)},ge=function(e){return null==Z&&(Z="hidden"==_(A.body,"visibility")),Z||"hidden"!=_(e.parentNode,"visibility")&&"hidden"!=_(e,"visibility")},ze=function(e,t){var a,i=e,n=ge(e);for(V-=t,K+=t,X-=t,Y+=t;n&&(i=i.offsetParent)&&i!=A.body&&i!=h;)(n=0<(_(i,"opacity")||1))&&"visible"!=_(i,"overflow")&&(a=i.getBoundingClientRect(),n=Y>a.left&&X<a.right&&K>a.top-1&&V<a.bottom+1);return n},he=function(){var e,t,a,i,n,r,o,s,l,d,c,u,f=g.elements;if((G=z.loadMode)&&ue<8&&(e=f.length)){for(t=0,fe++,d=!z.expand||z.expand<1?500<h.clientHeight&&500<h.clientWidth?500:370:z.expand,g._defEx=d,c=d*z.expFactor,u=z.hFac,Z=null,ce<c&&ue<1&&2<fe&&2<G&&!A.hidden?(ce=c,fe=0):ce=1<G&&1<fe&&ue<6?d:0;t<e;t++)if(f[t]&&!f[t]._lazyRace)if(de)if((s=f[t][v]("data-expand"))&&(r=1*s)||(r=ce),l!==r&&(q=innerWidth+r*u,j=innerHeight+r,o=-1*r,l=r),a=f[t].getBoundingClientRect(),(K=a.bottom)>=o&&(V=a.top)<=j&&(Y=a.right)>=o*u&&(X=a.left)<=q&&(K||Y||X||V)&&(z.loadHidden||ge(f[t]))&&(J&&ue<3&&!s&&(G<3||fe<4)||ze(f[t],r))){if(Ce(f[t]),n=!0,9<ue)break}else!n&&J&&!i&&ue<4&&fe<4&&2<G&&(I[0]||z.preloadAfterLoad)&&(I[0]||!s&&(K||Y||X||V||"auto"!=f[t][v](z.sizesAttr)))&&(i=I[0]||f[t]);else Ce(f[t]);i&&!n&&Ce(i)}},ee=he,ae=0,ie=z.throttleDelay,ne=z.ricTimeout,re=function(){te=!1,ae=r.now(),ee()},oe=s&&49<ne?function(){s(re,{timeout:ne}),ne!==z.ricTimeout&&(ne=z.ricTimeout)}:e(function(){u(re)},!0),ve=function(e){var t;(e=!0===e)&&(ne=33),te||(te=!0,(t=ie-(r.now()-ae))<0&&(t=0),e||t<9?oe():u(oe,t))},pe=function(e){var t=e.target;t._lazyCache?delete t._lazyCache:(Ae(e),m(t,z.loadedClass),y(t,z.loadingClass),b(t,ye),w(t,"lazyloaded"))},me=e(pe),ye=function(e){me({target:e.target})},be=function(e){var t,a=e[v](z.srcsetAttr);(t=z.customMedia[e[v]("data-media")||e[v]("media")])&&e.setAttribute("media",t),a&&e.setAttribute("srcset",a)},we=e(function(e,t,a,i,n){var r,o,s,l,d,c;(d=w(e,"lazybeforeunveil",t)).defaultPrevented||(i&&(a?m(e,z.autosizesClass):e.setAttribute("sizes",i)),o=e[v](z.srcsetAttr),r=e[v](z.srcAttr),n&&(s=e.parentNode,l=s&&f.test(s.nodeName||"")),c=t.firesLoad||"src"in e&&(o||r||l),d={target:e},m(e,z.loadingClass),c&&(clearTimeout(O),O=u(Ae,2500),b(e,ye,!0)),l&&p.call(s.getElementsByTagName("source"),be),o?e.setAttribute("srcset",o):r&&!l&&(le.test(e.nodeName)?function(t,a){try{t.contentWindow.location.replace(a)}catch(e){t.src=a}}(e,r):e.src=r),n&&(o||l)&&C(e,{src:r})),e._lazyRace&&delete e._lazyRace,y(e,z.lazyClass),W(function(){(!c||e.complete&&1<e.naturalWidth)&&(pe(d),e._lazyCache=!0,u(function(){"_lazyCache"in e&&delete e._lazyCache},9))},!0)}),Ce=function(e){var t,a=se.test(e.nodeName),i=a&&(e[v](z.sizesAttr)||e[v]("sizes")),n="auto"==i;(!n&&J||!a||!e[v]("src")&&!e.srcset||e.complete||c(e,z.errorClass)||!c(e,z.lazyClass))&&(t=w(e,"lazyunveilread").detail,n&&H.updateElem(e,!0,e.offsetWidth),e._lazyRace=!0,ue++,we(e,t,n,i,a))},_e=function(){if(!J)if(r.now()-$<999)u(_e,999);else{var e=x(function(){z.loadMode=3,ve()});J=!0,z.loadMode=3,ve(),t("scroll",function(){3==z.loadMode&&(z.loadMode=2),e()},!0)}},{_:function(){$=r.now(),g.elements=A.getElementsByClassName(z.lazyClass),I=A.getElementsByClassName(z.lazyClass+" "+z.preloadClass),t("scroll",ve,!0),t("resize",ve,!0),i.MutationObserver?new MutationObserver(ve).observe(h,{childList:!0,subtree:!0,attributes:!0}):(h[o]("DOMNodeInserted",ve,!0),h[o]("DOMAttrModified",ve,!0),setInterval(ve,999)),t("hashchange",ve,!0),["focus","mouseover","click","load","transitionend","animationend","webkitAnimationEnd"].forEach(function(e){A[o](e,ve,!0)}),/d$|^c/.test(A.readyState)?_e():(t("load",_e),A[o]("DOMContentLoaded",ve),u(_e,2e4)),g.elements.length?(he(),W._lsFlush()):ve()},checkElems:ve,unveil:Ce}),H=(T=e(function(e,t,a,i){var n,r,o;if(e._lazysizesWidth=i,i+="px",e.setAttribute("sizes",i),f.test(t.nodeName||""))for(n=t.getElementsByTagName("source"),r=0,o=n.length;r<o;r++)n[r].setAttribute("sizes",i);a.detail.dataAttr||C(e,a.detail)}),F=function(e,t,a){var i,n=e.parentNode;n&&(a=E(e,n,a),(i=w(e,"lazybeforesizes",{width:a,dataAttr:!!t})).defaultPrevented||(a=i.detail.width)&&a!==e._lazysizesWidth&&T(e,n,i,a))},U=x(function(){var e,t=D.length;if(t)for(e=0;e<t;e++)F(D[e])}),{_:function(){D=A.getElementsByClassName(z.autosizesClass),t("resize",U)},checkElems:U,updateElem:F}),k=function(){k.i||(k.i=!0,H._(),P._())};var D,T,F,U;var I,J,O,G,$,q,j,V,X,Y,K,Z,ee,te,ae,ie,ne,re,oe,se,le,de,ce,ue,fe,Ae,ge,ze,he,ve,pe,me,ye,be,we,Ce,_e;return g={cfg:z,autoSizer:H,loader:P,init:k,uP:C,aC:m,rC:y,hC:c,fire:w,gW:E,rAF:W}}(e,e.document);e.lazySizes=a,"object"==typeof module&&module.exports&&(module.exports=a)}(window),lazysizesWebP("alpha",lazySizes.init),document.addEventListener("lazybeforeunveil",function(e){var t=e.target,a=t.getAttribute("data-srcset");if(!a&&t.naturalWidth&&(console.log("we have something"),1<t.naturalWidth&&1<t.naturalHeight)){var i=window.devicePixelRatio||1,n=1.25*t.clientWidth<t.naturalWidth,r=1.25*t.clientHeight<t.naturalHeight;if(n||r){console.log(Math.round(t.clientWidth*i)+"x"+Math.round(t.clientHeight*i)+", natural is "+t.naturalWidth+"x"+t.naturalHeight+"!");var o=Math.round(t.offsetWidth*i),s=Math.round(t.offsetHeight*i),l=t.getAttribute("data-src"),d=t.getAttribute("data-src-webp");ewww_webp_supported&&d&&-1==l.search("webp=1")&&(console.log("using data-src-webp"),l=d);var c=constrainSrc(l,o,s);c&&l!=c&&t.setAttribute("data-src",c)}}if(ewww_webp_supported){if(a&&-1<a.search("webp=1"))return;if(a){var u=t.getAttribute("data-srcset-webp");u&&t.setAttribute("data-srcset",u)}if((l=t.getAttribute("data-src"))&&-1<l.search("webp=1"))return;if(!(d=t.getAttribute("data-src-webp")))return;t.setAttribute("data-src",d)}}),function(e,t){var a=function(){t(e.lazySizes),e.removeEventListener("lazyunveilread",a,!0)};t=t.bind(null,e,e.document),"object"==typeof module&&module.exports?t(require("lazysizes")):e.lazySizes?a():e.addEventListener("lazyunveilread",a,!0)}(window,function(s,i,l){"use strict";var d,c;i.addEventListener&&(d=function(e,t){var a=i.createElement("img");a.onload=function(){a.onload=null,a.onerror=null,a=null,t()},a.onerror=a.onload,a.src=e,a&&a.complete&&a.onload&&a.onload()},addEventListener("lazybeforeunveil",function(e){var t,a,i;if(e.detail.instance==l&&!e.defaultPrevented){if("none"==e.target.preload&&(e.target.preload="auto"),t=e.target.getAttribute("data-bg")){ewww_webp_supported&&(a=e.target.getAttribute("data-bg-webp"))&&(t=a);var n=s.devicePixelRatio||1,r=Math.round(e.target.offsetWidth*n),o=Math.round(e.target.offsetHeight*n);t=constrainSrc(t,r,o),e.detail.firesLoad=!0,d(t,function(){e.target.style.backgroundImage="url("+(c.test(t)?JSON.stringify(t):t)+")",e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)})}(i=e.target.getAttribute("data-poster"))&&(e.detail.firesLoad=!0,d(i,function(){e.target.poster=i,e.detail.firesLoad=!1,l.fire(e.target,"_lazyloaded",{},!0,!0)}))}},!(c=/\(|\)|\s|'/)))});
|
includes/ls.unveilhooks.js
CHANGED
@@ -82,7 +82,10 @@ For background images, use data-bg attribute:
|
|
82 |
bg = bgWebP;
|
83 |
}
|
84 |
}
|
85 |
-
|
|
|
|
|
|
|
86 |
e.detail.firesLoad = true;
|
87 |
load = function(){
|
88 |
e.target.style.backgroundImage = 'url(' + (regBgUrlEscape.test(bg) ? JSON.stringify(bg) : bg ) + ')';
|
82 |
bg = bgWebP;
|
83 |
}
|
84 |
}
|
85 |
+
var dPR = (window.devicePixelRatio || 1);
|
86 |
+
var targetWidth = Math.round(e.target.offsetWidth * dPR);
|
87 |
+
var targetHeight = Math.round(e.target.offsetHeight * dPR);
|
88 |
+
bg = constrainSrc(bg,targetWidth,targetHeight);
|
89 |
e.detail.firesLoad = true;
|
90 |
load = function(){
|
91 |
e.target.style.backgroundImage = 'url(' + (regBgUrlEscape.test(bg) ? JSON.stringify(bg) : bg ) + ')';
|
includes/resize_detection.js
CHANGED
@@ -24,9 +24,10 @@ function checkImageScale(img) {
|
|
24 |
if ((img.naturalWidth != 1) && (img.naturalHeight != 1)) {
|
25 |
// For each image with a natural width which isn't
|
26 |
// a 1x1 image, check its size.
|
27 |
-
|
28 |
-
|
29 |
-
|
|
|
30 |
img.classList.add('scaled-image');
|
31 |
img.title = "Forced to wrong size: " +
|
32 |
img.clientWidth + "x" + img.clientHeight + ", natural is " +
|
@@ -43,5 +44,6 @@ function clearScaledImages() {
|
|
43 |
}
|
44 |
document.addEventListener('lazyloaded', function(e){
|
45 |
e.target.classList.remove('scaled-image');
|
|
|
46 |
checkImageScale(e.target);
|
47 |
});
|
24 |
if ((img.naturalWidth != 1) && (img.naturalHeight != 1)) {
|
25 |
// For each image with a natural width which isn't
|
26 |
// a 1x1 image, check its size.
|
27 |
+
var dPR = (window.devicePixelRatio || 1);
|
28 |
+
var wrongWidth = (img.clientWidth * 1.5 * dPR < img.naturalWidth);
|
29 |
+
var wrongHeight = (img.clientHeight * 1.5 * dPR < img.naturalHeight);
|
30 |
+
if (wrongWidth || wrongHeight) {
|
31 |
img.classList.add('scaled-image');
|
32 |
img.title = "Forced to wrong size: " +
|
33 |
img.clientWidth + "x" + img.clientHeight + ", natural is " +
|
44 |
}
|
45 |
document.addEventListener('lazyloaded', function(e){
|
46 |
e.target.classList.remove('scaled-image');
|
47 |
+
e.target.title = '';
|
48 |
checkImageScale(e.target);
|
49 |
});
|
readme.txt
CHANGED
@@ -5,7 +5,7 @@ Tags: image, compress, resize, optimize, optimization, lossless, lossy, seo, web
|
|
5 |
Requires at least: 4.9
|
6 |
Tested up to: 5.1
|
7 |
Requires PHP: 5.6
|
8 |
-
Stable tag: 4.7.
|
9 |
License: GPLv3
|
10 |
|
11 |
Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
|
@@ -174,6 +174,15 @@ http://developer.yahoo.com/performance/rules.html#opt_images
|
|
174 |
* Feature requests can be viewed and submitted at https://github.com/nosilver4u/ewww-image-optimizer/labels/enhancement
|
175 |
* If you would like to help translate this plugin in your language, get started here: https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/
|
176 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
= 4.7.0 =
|
178 |
* added: lazy load (on ExactDN tab for now)
|
179 |
* added: JS WebP supports background images via lazy load (div elements only for now)
|
5 |
Requires at least: 4.9
|
6 |
Tested up to: 5.1
|
7 |
Requires PHP: 5.6
|
8 |
+
Stable tag: 4.7.1
|
9 |
License: GPLv3
|
10 |
|
11 |
Speed up your website and improve your visitors' experience by automatically compressing and resizing images and PDFs. Boost SEO and improve sales.
|
174 |
* Feature requests can be viewed and submitted at https://github.com/nosilver4u/ewww-image-optimizer/labels/enhancement
|
175 |
* If you would like to help translate this plugin in your language, get started here: https://translate.wordpress.org/projects/wp-plugins/ewww-image-optimizer/
|
176 |
|
177 |
+
= 4.7.1 =
|
178 |
+
* added: CSS background image support for <li> elements
|
179 |
+
* added: ExactDN + Lazy Load will auto-calculate dimensions for img elements without srcset/responsive markup
|
180 |
+
* added: ExactDN parses thumbnail url for personalization.com + WooCommerce integration
|
181 |
+
* added: ExactDN can use data-actual-width attribute for srcset generation
|
182 |
+
* added: ExactDN + Lazy Load uses devicePixelRatio to provide clearer background images
|
183 |
+
* fixed: Lazy Load for CSS background images misfires when display height is greater than width
|
184 |
+
* fixed: visitors without JS see Lazy Load placeholder + fallback image
|
185 |
+
|
186 |
= 4.7.0 =
|
187 |
* added: lazy load (on ExactDN tab for now)
|
188 |
* added: JS WebP supports background images via lazy load (div elements only for now)
|