bulk-optimization.js
285 lines
| 1 | (function() { |
| 2 | const processedItems = []; |
| 3 | var parallelCompressions = 5; |
| 4 | |
| 5 | function updateProgressBar(successFullCompressions) { |
| 6 | var totalToOptimize = parseInt(jQuery('div#compression-progress-bar').data('number-to-optimize'), 10); |
| 7 | |
| 8 | var optimizedSoFar = parseInt(jQuery('#optimized-so-far').text(), 10); |
| 9 | jQuery('#optimized-so-far').html(successFullCompressions + optimizedSoFar); |
| 10 | |
| 11 | var percentage = '100%'; |
| 12 | if (totalToOptimize > 0) { |
| 13 | percentage = Math.round((successFullCompressions + optimizedSoFar) / totalToOptimize * 100, 1) + '%'; |
| 14 | } |
| 15 | jQuery('div#compression-progress-bar #progress-size').css('width', percentage); |
| 16 | jQuery('div#compression-progress-bar #percentage').html('(' + percentage + ')'); |
| 17 | |
| 18 | var numberToOptimize = parseInt(jQuery('#optimizable-image-sizes').html(), 10); |
| 19 | jQuery('#optimizable-image-sizes').html(numberToOptimize - successFullCompressions); |
| 20 | } |
| 21 | |
| 22 | function updateSavings(successFullCompressions, successFullSaved, newHumanReadableLibrarySize) { |
| 23 | window.currentLibraryBytes = window.currentLibraryBytes + successFullSaved; |
| 24 | |
| 25 | var imagesSizedOptimized = parseInt(jQuery('#optimized-image-sizes').text(), 10) + successFullCompressions; |
| 26 | var initialLibraryBytes = parseInt(jQuery('#unoptimized-library-size').data('bytes'), 10); |
| 27 | var percentage = (1 - window.currentLibraryBytes / initialLibraryBytes); |
| 28 | var chartSize = jQuery('div#optimization-chart').data('full-circle-size'); |
| 29 | |
| 30 | jQuery('#optimized-image-sizes').html(imagesSizedOptimized); |
| 31 | jQuery('#optimized-library-size').attr('data-bytes', window.currentLibraryBytes); |
| 32 | jQuery('#optimized-library-size').html(newHumanReadableLibrarySize); |
| 33 | jQuery('#savings-percentage').html(Math.round(percentage * 1000) / 10 + '%'); |
| 34 | jQuery('div#optimization-chart svg circle.main').css('stroke-dasharray', '' + (chartSize * percentage) + ' ' + chartSize); |
| 35 | } |
| 36 | |
| 37 | function handleCancellation() { |
| 38 | jQuery('div#bulk-optimization-actions').hide(); |
| 39 | jQuery('div.progress').css('animation', 'none'); |
| 40 | } |
| 41 | |
| 42 | function updateRowAfterCompression(row, data) { |
| 43 | var successFullCompressions = parseInt(data.success, 10); |
| 44 | var successFullSaved = parseInt(data.size_change, 10); |
| 45 | var newHumanReadableLibrarySize = data.human_readable_library_size; |
| 46 | if (successFullCompressions === 0) { |
| 47 | row.addClass('no-action'); |
| 48 | row.find('.status').html('<span class="icon dashicons dashicons-no alert"></span>' + tinyCompress.L10nNoActionTaken).attr('data-status', 'no-action-taken'); |
| 49 | } else { |
| 50 | row.addClass('success'); |
| 51 | const rowResultElement = row.find('.status'); |
| 52 | rowResultElement.attr('data-status', 'compressed'); |
| 53 | const icon = '<span class="icon dashicons dashicons-yes success"></span>'; |
| 54 | |
| 55 | let successHTML = ''; |
| 56 | if (data.image_sizes_compressed > 0) { |
| 57 | successHTML += `<p>${icon} ${data.image_sizes_compressed} ${tinyCompress.L10nCompressed}</p>`; |
| 58 | } |
| 59 | |
| 60 | if (data.image_sizes_converted > 0) { |
| 61 | successHTML += `<p>${icon} ${data.image_sizes_converted} ${tinyCompress.L10nConverted}</p>`; |
| 62 | } |
| 63 | |
| 64 | rowResultElement.html(successHTML); |
| 65 | |
| 66 | updateProgressBar(successFullCompressions); |
| 67 | updateSavings(successFullCompressions, successFullSaved, newHumanReadableLibrarySize); |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | function bulkOptimizationCallback(error, data, items, i) { |
| 72 | if (window.optimizationCancelled) { |
| 73 | handleCancellation(); |
| 74 | } |
| 75 | |
| 76 | var row = jQuery('#optimization-items tr').eq(parseInt(i, 10)+1); |
| 77 | |
| 78 | if (error) { |
| 79 | row.addClass('failed'); |
| 80 | row.find('.status').html(tinyCompress.L10nInternalError + '<br>' + error.toString()); |
| 81 | row.find('.status').attr('title', error.toString()); |
| 82 | row.find('.status').attr('data-status', 'error'); |
| 83 | data = {}; |
| 84 | } else if (data == null) { |
| 85 | row.addClass('failed'); |
| 86 | row.find('.status').html(tinyCompress.L10nError); |
| 87 | row.find('.status').attr('data-status', 'error'); |
| 88 | data = {}; |
| 89 | } else if (data.error) { |
| 90 | row.addClass('failed'); |
| 91 | row.find('.status').html(tinyCompress.L10nError + '<br>' + data.error); |
| 92 | row.find('.status').attr('title', data.error); |
| 93 | row.find('.status').attr('data-status', 'error'); |
| 94 | } else if (data.failed > 0) { |
| 95 | row.addClass('failed'); |
| 96 | row.find('.status').html('<span class=\'icon dashicons dashicons-no error\'></span><span class=\'message\'>' + tinyCompress.L10nLatestError + ': ' + data.message + '</span>'); |
| 97 | row.find('.status').attr('title', data.message); |
| 98 | row.find('.status').attr('data-status', 'error'); |
| 99 | } else { |
| 100 | updateRowAfterCompression(row, data); |
| 101 | } |
| 102 | |
| 103 | row.find('.name').html(items[i].post_title + '<button class=\'toggle-row\' type=\'button\'><span class=\'screen-reader-text\'>' + tinyCompress.L10nShowMoreDetails + '</span></button>'); |
| 104 | |
| 105 | if (!data.image_sizes_compressed) { |
| 106 | data.image_sizes_compressed = '-'; |
| 107 | } |
| 108 | if (!data.initial_total_size) { |
| 109 | data.initial_total_size = '-'; |
| 110 | } |
| 111 | if (!data.optimized_total_size) { |
| 112 | data.optimized_total_size = '-'; |
| 113 | } |
| 114 | if (!data.savings || data.savings === 0) { |
| 115 | data.savings = '-'; |
| 116 | } else { |
| 117 | data.savings += '%'; |
| 118 | } |
| 119 | |
| 120 | row.find('.thumbnail').html(data.thumbnail); |
| 121 | row.find('.sizes-compressed').html(data.image_sizes_compressed); |
| 122 | row.find('.initial-size').html(data.initial_total_size); |
| 123 | row.find('.optimized-size').html(data.optimized_total_size); |
| 124 | row.find('.savings').html(data.savings); |
| 125 | |
| 126 | var totalToOptimize = jQuery('td.status[data-status="waiting"],td.status[data-status="compressing"]').length; |
| 127 | var nextImage; |
| 128 | |
| 129 | if (jQuery('td.status[data-status="waiting"]').length > 0) { |
| 130 | nextImage = jQuery('tr.media-item').index(jQuery('td.status[data-status="waiting"]:first').parents('tr')); |
| 131 | } |
| 132 | if (nextImage !== undefined && items[nextImage]) { |
| 133 | if (!window.optimizationCancelled) { |
| 134 | drawSomeRows(items, 1); |
| 135 | } |
| 136 | bulkOptimizeItem(items, nextImage); |
| 137 | } else if (totalToOptimize === 0) { |
| 138 | var message = jQuery('<div class=\'updated\'><p></p></div>'); |
| 139 | message.find('p').html(tinyCompress.L10nAllDone); |
| 140 | message.insertAfter(jQuery('#tiny-bulk-optimization h1')); |
| 141 | jQuery('div#optimization-spinner').css('display', 'none'); |
| 142 | jQuery('div#bulk-optimization-actions').hide(); |
| 143 | jQuery('div.progress').css('animation', 'none'); |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | function bulkOptimizeItem(items, i) { |
| 148 | if (window.optimizationCancelled) { |
| 149 | return; |
| 150 | } |
| 151 | |
| 152 | const itemID = items[i].ID; |
| 153 | if (processedItems.includes(itemID)) { |
| 154 | const row = jQuery('#optimization-items tr').eq(parseInt(i, 10) + 1); |
| 155 | row.find('.status') |
| 156 | .attr('data-status', 'skipped-duplicate') |
| 157 | .html('<span class="icon dashicons dashicons-no alert"></span>' + tinyCompress.L10nDuplicate); |
| 158 | } |
| 159 | |
| 160 | var row = jQuery('#optimization-items tr').eq(parseInt(i, 10)+1); |
| 161 | row.find('.status').removeClass('todo'); |
| 162 | row.find('.status').html('<span class="icon spinner"></span>' + tinyCompress.L10nCompressing).attr('data-status', 'compressing'); |
| 163 | jQuery.ajax({ |
| 164 | url: ajaxurl, |
| 165 | type: 'POST', |
| 166 | dataType: 'json', |
| 167 | data: { |
| 168 | _nonce: tinyCompress.nonce, |
| 169 | action: 'tiny_compress_image_for_bulk', |
| 170 | id: itemID, |
| 171 | current_size: window.currentLibraryBytes |
| 172 | }, |
| 173 | success: function(data) { bulkOptimizationCallback(null, data, items, i); }, |
| 174 | error: function(xhr, textStatus, errorThrown) { bulkOptimizationCallback(errorThrown, null, items, i, parallelCompressions); } |
| 175 | }); |
| 176 | processedItems.push(itemID); |
| 177 | jQuery('#tiny-progress span').html(i + 1); |
| 178 | } |
| 179 | |
| 180 | function prepareBulkOptimization(items) { |
| 181 | window.allBulkOptimizationItems = items; |
| 182 | updateProgressBar(0); |
| 183 | } |
| 184 | |
| 185 | function startBulkOptimization(items) { |
| 186 | window.optimizationCancelled = false; |
| 187 | window.totalRowsDrawn = 0; |
| 188 | window.currentLibraryBytes = parseInt(jQuery('#optimized-library-size').data('bytes'), 10); |
| 189 | processedItems.splice(0, processedItems.length); |
| 190 | |
| 191 | jQuery('div.progress').css('animation', 'progress-bar 80s linear infinite'); |
| 192 | jQuery('div#optimization-spinner').css('display', 'inline-block'); |
| 193 | updateProgressBar(0); |
| 194 | drawSomeRows(items, 5 + parallelCompressions); |
| 195 | |
| 196 | for (var i = 0; i < parallelCompressions; i++) { |
| 197 | if (items.length >= i+1) { |
| 198 | bulkOptimizeItem(items, i); |
| 199 | } |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | function drawSomeRows(items, rowsToDraw) { |
| 204 | const list = jQuery('#optimization-items tbody'); |
| 205 | let drawNow = window.totalRowsDrawn; |
| 206 | for(let i = drawNow;i < Math.min(rowsToDraw + window.totalRowsDrawn, items.length); i++) { |
| 207 | const tableRow = `<tr class="media-item"> |
| 208 | <td class="thumbnail" /> |
| 209 | <td class="column-primary name">${items[i].post_title}</th> |
| 210 | <td class="column-author initial-size" data-colname="${tinyCompress.L10nInitialSize}" /> |
| 211 | <td class="column-author optimized-size" data-colname="${tinyCompress.L10nCurrentSize}" /> |
| 212 | <td class="column-author savings" data-colname="${tinyCompress.L10nSavings}" /> |
| 213 | <td class="column-author status" data-testid="bulk-item-status-${i}" data-colname="${tinyCompress.L10nStatus}" data-status="waiting">${tinyCompress.L10nWaiting}</td> |
| 214 | </tr>`; |
| 215 | list.append(tableRow); |
| 216 | drawNow = i; |
| 217 | } |
| 218 | window.totalRowsDrawn = drawNow; |
| 219 | } |
| 220 | |
| 221 | function cancelOptimization() { |
| 222 | window.optimizationCancelled = true; |
| 223 | jQuery('div#optimization-spinner').css('display', 'none'); |
| 224 | jQuery(jQuery('#optimization-items tr td.status.todo')).html(tinyCompress.L10nCancelled).attr('data-status', 'cancelled'); |
| 225 | jQuery('div#bulk-optimization-actions input').removeClass('visible'); |
| 226 | jQuery('div#bulk-optimization-actions input#id-cancelling').addClass('visible'); |
| 227 | } |
| 228 | |
| 229 | jQuery('.tiny-bulk-optimization .upgrade-account-notice a#hide-warning').click(function() { |
| 230 | jQuery('.tiny-bulk-optimization .upgrade-account-notice').hide(); |
| 231 | jQuery('.tiny-bulk-optimization .optimize').children().show(); |
| 232 | }); |
| 233 | |
| 234 | jQuery('div#bulk-optimization-actions input').click(function() { |
| 235 | if ((jQuery(this).attr('id') === 'id-start') && jQuery(this).hasClass('visible')) { |
| 236 | jQuery('div#bulk-optimization-actions input#id-start').removeClass('visible'); |
| 237 | jQuery('div#bulk-optimization-actions input#id-optimizing').addClass('visible'); |
| 238 | startBulkOptimization(window.allBulkOptimizationItems); |
| 239 | } |
| 240 | if ((jQuery(this).attr('id') === 'id-cancel') && jQuery(this).hasClass('visible')) { |
| 241 | cancelOptimization(); |
| 242 | } |
| 243 | }); |
| 244 | |
| 245 | jQuery('div#bulk-optimization-actions input').hover(function() { |
| 246 | if ((jQuery(this).attr('id') === 'id-optimizing') && jQuery(this).hasClass('visible')) { |
| 247 | window.lastActiveButton = jQuery('div#bulk-optimization-actions input.visible'); |
| 248 | window.lastActiveButton.removeClass('visible'); |
| 249 | jQuery('div#bulk-optimization-actions input#id-cancel').addClass('visible'); |
| 250 | } |
| 251 | }, function() { |
| 252 | if ((jQuery(this).attr('id') === 'id-cancel') && jQuery(this).hasClass('visible')) { |
| 253 | window.lastActiveButton.addClass('visible'); |
| 254 | jQuery('div#bulk-optimization-actions input#id-cancel').removeClass('visible'); |
| 255 | } |
| 256 | }); |
| 257 | |
| 258 | function attachToolTipEventHandlers() { |
| 259 | var tooltip = '#tiny-bulk-optimization div.tooltip'; |
| 260 | var tip = 'div.tip'; |
| 261 | var toolTipTimeout = null; |
| 262 | jQuery(tooltip).mouseleave(function(){ |
| 263 | var that = this; |
| 264 | toolTipTimeout = setTimeout(function() { |
| 265 | if (jQuery(that).find(tip).is(':visible')) { |
| 266 | jQuery(tooltip).find(tip).hide(); |
| 267 | } |
| 268 | }, 100); |
| 269 | }); |
| 270 | jQuery(tooltip).mouseenter(function(){ |
| 271 | jQuery(this).find(tip).show(); |
| 272 | clearTimeout(toolTipTimeout); |
| 273 | }); |
| 274 | jQuery(tooltip).find(tip).mouseenter(function(){ |
| 275 | clearTimeout(toolTipTimeout); |
| 276 | }); |
| 277 | } |
| 278 | |
| 279 | attachToolTipEventHandlers(); |
| 280 | |
| 281 | window.bulkOptimizationAutorun = startBulkOptimization; |
| 282 | window.bulkOptimization = prepareBulkOptimization; |
| 283 | |
| 284 | }).call(); |
| 285 |