PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.7.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.7.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / js / wpo-images-view.js

wpo-images-view.js in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.7.0, at js/wpo-images-view.js

548 lines 15.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 WP_Optimize_Images_View = function(settings) {
2
3 var $ = jQuery,
4 defaults = {
5 container: '',
6 image_container_class: 'wpo_unused_image',
7 image_container_custom_classes: 'wpo_unused_image_row',
8 image_container_blog_class_prefix: 'wpo_unused_image_site_',
9 view_image_btn_link_class: 'wpo_unused_image_view_link',
10 view_image_btn_text: wpoptimize.view_image_link_text,
11 row_selector: '.wpo_unused_image_row',
12 row_id_class: 'wpo_unused_images_row_id',
13 row_thumb_class: 'wpo_unused_images_row_thumb',
14 row_file_class: 'wpo_unused_images_row_file',
15 row_action_class: 'wpo_unused_images_row_action',
16 /**
17 * Array with buttons shown in the list view mode.
18 *
19 * [
20 * {
21 * 'class': 'button_class',
22 * 'title': 'Button title',
23 * 'hint': 'Tooltip text'
24 * },
25 * ...
26 * ]
27 */
28 row_action_buttons: [],
29 label_class: 'wpo_unused_image_thumb_label',
30 loader_additional_html: '',
31 action_btn_text: 'Remove',
32 action_btn_class: 'button button-primary wpo_unused_images_remove_single',
33 checkbox_class: 'wpo_unused_image__input',
34 list_mode_class: 'wpo_unused_image_list_view',
35 no_images_found_message: 'No images found',
36 related_elements: [],
37 action_buttons: [],
38 hide_when_empty: [],
39 load_next_page_callback: null,
40 onclear: null
41 },
42 options = jQuery.extend({}, defaults, settings),
43 IMAGES_VIEW_MODE = {
44 GRID: 'grid',
45 LIST: 'list'
46 },
47 images_view_mode = IMAGES_VIEW_MODE.GRID,
48 images_view_container = options.container,
49 image_container_selector = '.' + options.image_container_class,
50 checkbox_selector = '.' + options.checkbox_class,
51 last_clicked_image_id = '',
52 images_loaded_count = {};
53
54 /**
55 * Handle scroll in the images container.
56 */
57 images_view_container.on('scroll mousewheel', function() {
58 load_next_page_if_need();
59 update_loader_position();
60 });
61
62 /**
63 * Handle Shift key state.
64 */
65 var ctrl_shift_on_image_held = false;
66
67 images_view_container.on('mousedown', options.row_selector, function (e) {
68 ctrl_shift_on_image_held = e.shiftKey || e.ctrlKey;
69 });
70
71 images_view_container.on('mouseup', options.row_selector, function (e) {
72 ctrl_shift_on_image_held = e.shiftKey || e.ctrlKey;
73 });
74
75
76 /**
77 * Handle checked status changed for single unused image.
78 */
79 images_view_container.on('click' , '.'+options.image_container_class , function(e) {
80
81 var check_box = $(this).find('.'+options.checkbox_class);
82 var image_id = check_box.attr('id');
83
84 // Toggle class on image container
85 if (true === check_box.prop('checked')) {
86 $(this).addClass('selected');
87 } else {
88 $(this).removeClass('selected');
89 }
90 if (ctrl_shift_on_image_held) {
91
92 if (true === check_box.prop('checked')) {
93 $(this).removeClass('selected');
94 check_box.prop('checked',false);
95 } else {
96 $(this).addClass('selected');
97 check_box.prop('checked',true);
98 }
99 if (1 <= get_selected_images().length) {
100 if (true === $("#"+last_clicked_image_id).prop('checked')) {
101 select_images(last_clicked_image_id, image_id, true === check_box.prop('checked'));
102 }
103
104 }
105 }
106 last_clicked_image_id = image_id;
107 disable_action_buttons(0 == get_selected_images().length);
108
109 });
110
111 /**
112 * Select or deselect images from #first_id to #last_id in the lis of unused images
113 *
114 * @param {string} first_id - first image id in the list
115 * @param {string} last_id - last image id in the list
116 * @param {bool} checked - select or deselect images
117 *
118 * @return void
119 */
120 function select_images(first_id, last_id, checked) {
121 var image_id = first_id,
122 index1,
123 index2,
124 current,
125 first,
126 last,
127 done = false;
128
129 // if set first and last ids then go through the list.
130 if (last_id && first_id) {
131 // get positions in then list.
132 index1 = $(checkbox_selector).index($('#' + first_id));
133 index2 = $(checkbox_selector).index($('#' + last_id));
134
135 // check if both item exists. (possibly one of them was deleted)
136 if (-1 == index1) index1 = index2;
137 if (-1 == index2) index2 = index1;
138
139 // get correct first and last item.
140 if (index1 < index2) {
141 current = $(checkbox_selector).eq(index1).closest(image_container_selector);
142 last_id = $(checkbox_selector).eq(index2).attr('id');
143 } else {
144 current = $(checkbox_selector).eq(index2).closest(image_container_selector);
145 last_id = $(checkbox_selector).eq(index1).attr('id');
146 }
147
148 // select images.
149 while (!done) {
150 if (checked) {
151 current.addClass('selected');
152 $(checkbox_selector, current).prop('checked', checked);
153 } else {
154 current.removeClass('selected');
155 $(checkbox_selector, current).prop('checked', checked);
156 }
157
158 if ($(checkbox_selector, current).attr('id') == last_id) done = true;
159
160 current = current.next();
161 }
162 } else {
163 // if just one the first id passed then change just the first element state.
164 if (checked) {
165 $('#' + image_id).closest(image_container_selector).addClass('selected');
166 } else {
167 $('#' + image_id).closest(image_container_selector).removeClass('selected');
168 }
169 }
170
171 disable_action_buttons(0 == get_selected_images().length);
172 }
173
174 /**
175 * Disable/enable controls.
176 *
177 * @param {boolean} disabled
178 */
179 function disable_action_buttons(disabled) {
180 if (!options.action_buttons) return;
181
182 $.each(options.action_buttons, function(i, el) {
183 el.prop('disabled', disabled)
184 });
185 }
186
187 /**
188 * Update view in case when then images list is empty.
189 */
190 function hide_when_empty_elements() {
191 if (options.hide_when_empty) {
192 var images_count = $(['.', options.image_container_class,':visible'].join(''), images_view_container).length;
193
194 if (0 === images_count) {
195 // show message - no images found.
196 if (0 == $('.wpo-images-view-empty', images_view_container).length) {
197 images_view_container.append($('<div class="wpo-images-view-empty wpo-fieldgroup" />').text(options.no_images_found_message));
198 }
199
200 $('.wpo-images-view-empty', images_view_container).show();
201 } else {
202 $('.wpo-images-view-empty', images_view_container).hide();
203 }
204
205 $.each(options.hide_when_empty, function(i, el) {
206 if (images_count > 0) {
207 el.show();
208 } else {
209 el.hide();
210 }
211 });
212 }
213 }
214
215 /**
216 * Update view when images are changed.
217 */
218 function update_view() {
219 if (!is_visible()) return;
220
221 hide_when_empty_elements();
222 disable_action_buttons(0 == get_selected_images().length);
223 }
224
225 /**
226 * Load the next part images if images container scrolled to the bottom.
227 */
228 function load_next_page_if_need() {
229 if (images_view_container.scrollTop() + images_view_container.height() + 100 > images_view_container[0].scrollHeight) {
230 if ('function' == typeof options.load_next_page_callback) {
231 options.load_next_page_callback();
232 }
233 }
234 }
235
236 /**
237 * Append an image to the list.
238 *
239 * @param {int} blog_id image blog id
240 * @param {string} value value that will returned if image selected
241 * @param {string} href url opened when image clicked
242 * @param {string} thumbnail_url url to the image thumbnail
243 * @param {string} title image title
244 * @param {string} row_file_text text for displaying near image in the list view mode
245 */
246 function append_image(blog_id, value, href, thumbnail_url, title, row_file_text) {
247 var random_id = 'image_' + (((1+Math.random())*0x10000)|0).toString(16).substring(1),
248 row_actions_html = '',
249 i;
250
251 // build button
252 if (options.row_action_buttons) {
253 for (i in options.row_action_buttons) {
254
255 if (!options.row_action_buttons.hasOwnProperty(i)) continue;
256
257 row_actions_html += [
258 '<button href="javascript: ;" class="',(options.row_action_buttons[i].class ? options.row_action_buttons[i].class : ''),'"',
259 ' title="',(options.row_action_buttons[i].hint ? options.row_action_buttons[i].hint : ''),'">',(options.row_action_buttons[i].title ? options.row_action_buttons[i].title : ''),'</button>'
260 ].join('');
261 }
262 }
263
264 // count added image.
265 if (!images_loaded_count.hasOwnProperty(blog_id)) images_loaded_count[blog_id] = 0;
266 images_loaded_count[blog_id]++;
267
268 images_view_container.append(['\
269 <div class="',options.image_container_class,' ',options.image_container_custom_classes,' ',options.image_container_blog_class_prefix,blog_id,'">\
270 <a class="button ',options.view_image_btn_link_class,'" href="',href,'" target="_blank">',
271 options.view_image_btn_text,
272 '</a>',
273 '<div class="',options.row_id_class,'">\
274 <input id="',random_id,'" type="checkbox" class="',options.checkbox_class,'" value="',value,'">\
275 </div>\
276 <div class="',options.row_thumb_class,'">\
277 <a href="',href,'" target="_blank">\
278 <img class="lazyload" src="data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-src="',thumbnail_url,'" title="',title,'" alt="',title,'">\
279 </a>\
280 </div>\
281 <div class="',options.row_file_class,'">\
282 <a href="',href,'" target="_blank">',row_file_text,'</a>\
283 </div>\
284 <div class="',options.row_action_class,'">',row_actions_html,'</div>\
285 <label for="',random_id,'" class="',options.label_class,'">\
286 <div class="thumbnail">\
287 <img class="lazyload" src="data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" data-src="',thumbnail_url,'" title="',title,'" alt="',title,'">\
288 </div>\
289 </label>\
290 </div>'
291 ].join(''));
292
293 $('img:not(.error-event-attached)', images_view_container).each(function() {
294 $(this).on('error', function() {
295 // WordPress dashicons format-image icon.
296 $(this).attr('src', 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+PHJlY3QgeD0iMCIgZmlsbD0ibm9uZSIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIi8+PGc+PHBhdGggZmlsbD0iI0FBQUFBQSIgZD0iTTIuMjUgMWgxNS41Yy42OSAwIDEuMjUuNTYgMS4yNSAxLjI1djE1LjVjMCAuNjktLjU2IDEuMjUtMS4yNSAxLjI1SDIuMjVDMS41NiAxOSAxIDE4LjQ0IDEgMTcuNzVWMi4yNUMxIDEuNTYgMS41NiAxIDIuMjUgMXpNMTcgMTdWM0gzdjE0aDE0ek0xMCA2YzAtMS4xLS45LTItMi0ycy0yIC45LTIgMiAuOSAyIDIgMiAyLS45IDItMnptMyA1czAtNiAzLTZ2MTBjMCAuNTUtLjQ1IDEtMSAxSDVjLS41NSAwLTEtLjQ1LTEtMVY4YzIgMCAzIDQgMyA0czEtMyAzLTMgMyAyIDMgMnoiLz48L2c+PC9zdmc+');
297 }).addClass('error-event-attached');
298 });
299 }
300
301 /**
302 * Show only images for the selected blog.
303 *
304 * @param {int} blog_id
305 */
306 function filter_by_site(blog_id) {
307 $(image_container_selector, images_view_container).hide();
308 $(['.',options.image_container_blog_class_prefix, blog_id].join(''), images_view_container).show();
309 update_view();
310 }
311
312 /**
313 * Get count of loaded images for the selected blog.
314 *
315 * @param {int} blog_id
316 *
317 * @return {number}
318 */
319 function get_images_count(blog_id) {
320 if (!images_loaded_count.hasOwnProperty(blog_id)) return 0;
321
322 return images_loaded_count[blog_id];
323 }
324
325 /**
326 * Get count of loaded images currently displayed in the view container.
327 *
328 * @param {int} blog_id
329 */
330 function get_visible_images_count(blog_id) {
331 return $(['.',options.image_container_blog_class_prefix, blog_id].join(''), images_view_container).length;
332 }
333
334 /**
335 * Switch view mode grid/list.
336 *
337 * @param mode
338 */
339 function switch_view_mode(mode) {
340 if (mode === images_view_mode) return;
341
342 images_view_mode = mode;
343
344 if (mode === IMAGES_VIEW_MODE.GRID) {
345 images_view_container.removeClass(options.list_mode_class);
346 }
347
348 if (mode === IMAGES_VIEW_MODE.LIST) {
349 images_view_container.addClass(options.list_mode_class);
350 }
351 }
352
353 /**
354 * Get list of selected images.
355 *
356 * @return {Array}
357 */
358 function get_selected_images() {
359 var selected_images = [];
360
361 // if no any selected images then exit.
362 if (0 == $('input[type="checkbox"]', images_view_container).length) return selected_images;
363
364 // build list of visible selected images .
365 $(['.',options.image_container_class,':visible input:checked'].join(''), images_view_container).each(function() {
366 selected_images.push($(this).val());
367 });
368
369 return selected_images;
370 }
371
372 /**
373 * Remove selected images.
374 */
375 function remove_selected_images() {
376 var image_container_selector = ['.',options.image_container_class].join('');
377 $([image_container_selector,':visible input:checked'].join(''), images_view_container).each(function() {
378 $(this).closest(image_container_selector).remove();
379 });
380 }
381
382 /**
383 * Show images container.
384 */
385 function show() {
386 images_view_container.show();
387
388 $(options.related_elements).each(function() {
389 $(this).show();
390 });
391
392 update_view();
393
394 load_next_page_if_need();
395 }
396
397 /**
398 * Hide images container.
399 */
400 function hide() {
401 images_view_container.hide();
402
403 $(options.related_elements).each(function() {
404 $(this).hide();
405 });
406 }
407
408 /**
409 * Check if images container element is visible.
410 *
411 * @return {boolean}
412 */
413 function is_visible() {
414 return images_view_container.is(':visible');
415 }
416
417 /**
418 * Show loader.
419 */
420 function show_loader() {
421 show_custom_loader(wpoptimize.loading_data, '', options.loader_additional_html);
422 }
423
424 /**
425 * Show loader with custom content.
426 *
427 * @param {string} title
428 * @param {string} message
429 * @param {string} custom_html
430 */
431 function show_custom_loader(title, message, custom_html) {
432 message = message ? message : '';
433 custom_html = custom_html ? custom_html : '';
434
435 images_view_container.css({ 'min-height' : '220px' });
436 images_view_container.append([
437 '<div class="wpo_shade">',
438 '<div class="wpo_shade_inner">',
439 '<span class="dashicons dashicons-update-alt wpo-rotate"></span>',
440 '<h4>',title,'</h4>',
441 '<p class="wpo-shade-progress-message">',message,'</p>',
442 custom_html,
443 '</div>',
444 '</div>',
445 ].join(''));
446
447 update_loader_position();
448 }
449
450 /**
451 * Hide loader.
452 */
453 function hide_loader() {
454 images_view_container.css('min-height', 'initial');
455 $('.wpo_shade', images_view_container).remove();
456 }
457
458 /**
459 * Update top property for shade div with loader.
460 */
461 function update_loader_position() {
462 $('.wpo_shade', images_view_container).css('top', images_view_container.scrollTop() + 'px');
463 }
464
465 /**
466 * Set message for under loader icon.
467 *
468 * @param {string} message
469 */
470 function loader_message(message) {
471 $('.wpo-shade-progress-message', images_view_container).html(message);
472 }
473
474 /**
475 * Select all images.
476 */
477 function select_all() {
478 $('.wpo_unused_image__input').each(function() {
479 if (!$(this).prop('checked')) {
480 $(this).closest('.wpo_unused_image').addClass('selected');
481 $(this).prop('checked', true);
482 last_clicked_image_id = null;
483 disable_action_buttons(0 == get_selected_images().length);
484
485 }
486 });
487 }
488
489 /**
490 * Deselect all images.
491 */
492 function select_none() {
493 $('.wpo_unused_image__input').each(function() {
494 if ($(this).prop('checked')) {
495 $(this).closest('.wpo_unused_image').removeClass('selected');
496 $(this).prop('checked', false);
497 last_clicked_image_id = null;
498 disable_action_buttons(0 == get_selected_images().length);
499 }
500 });
501 }
502
503 /**
504 * Clear images container.
505 */
506 function clear() {
507 $(['.', options.image_container_class].join(''), images_view_container).remove();
508 images_loaded_count = {};
509 disable_action_buttons(true);
510
511 // if defined on clear event then call it.
512 if ('function' === typeof options.onclear) {
513 options.onclear();
514 }
515 }
516
517 /**
518 * Reload view items.
519 */
520 function reload() {
521 clear();
522 load_next_page_if_need();
523 }
524
525 return {
526 show: show,
527 hide: hide,
528 clear: clear,
529 reload: reload,
530 show_loader: show_loader,
531 show_custom_loader: show_custom_loader,
532 hide_loader: hide_loader,
533 loader_message: loader_message,
534 append_image: append_image,
535 get_selected_images: get_selected_images,
536 remove_selected_images: remove_selected_images,
537 get_images_count: get_images_count,
538 get_visible_images_count: get_visible_images_count,
539 load_next_page_if_need: load_next_page_if_need,
540 filter_by_site: filter_by_site,
541 switch_view_mode: switch_view_mode,
542 select_all: select_all,
543 select_none: select_none,
544 is_visible: is_visible,
545 update_view: update_view
546 }
547 };
548