Changeset 3483393
- Timestamp:
- 03/16/2026 04:33:56 AM (2 weeks ago)
- Location:
- ever-compare
- Files:
-
- 26 edited
- 1 copied
-
tags/1.3.5 (copied) (copied from ever-compare/trunk)
-
tags/1.3.5/assets/js/frontend.js (modified) (9 diffs)
-
tags/1.3.5/assets/js/frontend.min.js (modified) (1 diff)
-
tags/1.3.5/ever-compare.php (modified) (4 diffs)
-
tags/1.3.5/includes/classes/Admin/Settings_APi.php (modified) (1 diff)
-
tags/1.3.5/includes/classes/Ajax.php (modified) (3 diffs)
-
tags/1.3.5/includes/classes/Assets.php (modified) (1 diff)
-
tags/1.3.5/includes/classes/Frontend/Manage_Compare.php (modified) (8 diffs)
-
tags/1.3.5/includes/classes/Frontend/Shortcode.php (modified) (3 diffs)
-
tags/1.3.5/includes/helper-functions.php (modified) (3 diffs)
-
tags/1.3.5/includes/templates/evercompare-button-add.php (modified) (1 diff)
-
tags/1.3.5/includes/templates/evercompare-count.php (modified) (2 diffs)
-
tags/1.3.5/includes/templates/evercompare-table.php (modified) (3 diffs)
-
tags/1.3.5/readme.txt (modified) (2 diffs)
-
trunk/assets/js/frontend.js (modified) (9 diffs)
-
trunk/assets/js/frontend.min.js (modified) (1 diff)
-
trunk/ever-compare.php (modified) (4 diffs)
-
trunk/includes/classes/Admin/Settings_APi.php (modified) (1 diff)
-
trunk/includes/classes/Ajax.php (modified) (3 diffs)
-
trunk/includes/classes/Assets.php (modified) (1 diff)
-
trunk/includes/classes/Frontend/Manage_Compare.php (modified) (8 diffs)
-
trunk/includes/classes/Frontend/Shortcode.php (modified) (3 diffs)
-
trunk/includes/helper-functions.php (modified) (3 diffs)
-
trunk/includes/templates/evercompare-button-add.php (modified) (1 diff)
-
trunk/includes/templates/evercompare-count.php (modified) (2 diffs)
-
trunk/includes/templates/evercompare-table.php (modified) (3 diffs)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
ever-compare/tags/1.3.5/assets/js/frontend.js
r3108021 r3483393 1 1 ;(function($){ 2 2 "use strict"; 3 3 4 4 var $body = $('body'), 5 $popup = $('.htcompare-popup'); 6 7 $body.append(`<div id="htcompare-error-modal" class="htcompare-error-modal" style="display:none"> 8 <div class="htcompare-error-modal-content"> 9 <button class="htcompare-error-modal-close">×</button> 10 <div class="htcompare-error-modal-body"></div> 11 </div> 12 </div>`); 13 const $htcompareErrorModal = $("#htcompare-error-modal"); 5 $popup = $('.htcompare-popup'), 6 cachedNonce = null, 7 noncePromise = null; 8 9 // Cookie helper: read compare list from cookie 10 function getCompareListFromCookie() { 11 var cookieName = evercompare.cookie_name; 12 var cookies = document.cookie.split(';'); 13 for (var i = 0; i < cookies.length; i++) { 14 var cookie = cookies[i].trim(); 15 if (cookie.indexOf(cookieName + '=') === 0) { 16 var value = decodeURIComponent(cookie.substring(cookieName.length + 1)); 17 try { 18 var parsed = JSON.parse(value); 19 if (Array.isArray(parsed)) { 20 return parsed.map(function(id) { return parseInt(id, 10); }).filter(function(id) { return id > 0; }); 21 } 22 } catch(e) {} 23 } 24 } 25 return []; 26 } 27 28 // Deferred nonce: fetch on first interaction, cache in memory 29 function getNonce() { 30 if (cachedNonce) { 31 return $.Deferred().resolve(cachedNonce).promise(); 32 } 33 if (noncePromise) { 34 return noncePromise; 35 } 36 noncePromise = $.ajax({ 37 url: evercompare.ajaxurl, 38 data: { action: 'ever_compare_get_nonce' }, 39 dataType: 'json', 40 method: 'GET', 41 }).then(function(response) { 42 cachedNonce = response.nonce; 43 noncePromise = null; 44 return cachedNonce; 45 }).fail(function() { 46 noncePromise = null; 47 }); 48 return noncePromise; 49 } 50 51 // Sync button states from cookie on DOM ready 52 function syncButtonStates() { 53 var compareList = getCompareListFromCookie(); 54 $('a.htcompare-btn').each(function() { 55 var $btn = $(this); 56 var productId = parseInt($btn.data('product_id'), 10); 57 if (compareList.indexOf(productId) >= 0) { 58 $btn.addClass('added'); 59 $btn.html('<span class="htcompare-btn-text">' + $btn.data('added-text') + '</span>'); 60 } 61 }); 62 } 63 64 // Sync counter from cookie on DOM ready 65 function syncCounter() { 66 var compareList = getCompareListFromCookie(); 67 $body.find('.htcompare-counter').html(compareList.length); 68 } 69 70 // Load compare table via AJAX for cookie-based pages 71 function loadCompareTable() { 72 var $tables = $('.htcompare-table[data-ajax-load]'); 73 if ($tables.length === 0) return; 74 75 var compareList = getCompareListFromCookie(); 76 if (compareList.length === 0) { 77 // Show empty state — fetch table with no IDs to get proper empty template 78 $.ajax({ 79 url: evercompare.ajaxurl, 80 data: { 81 action: 'ever_compare_get_table', 82 ids: '', 83 }, 84 dataType: 'json', 85 method: 'GET', 86 success: function(response) { 87 if (typeof response.table !== 'undefined') { 88 $tables.each(function() { 89 $(this).replaceWith(response.table || '<div class="htcompare-table htcompare-empty"></div>'); 90 }); 91 bindShareableLinkHandler(); 92 } 93 } 94 }); 95 return; 96 } 97 98 $.ajax({ 99 url: evercompare.ajaxurl, 100 data: { 101 action: 'ever_compare_get_table', 102 ids: compareList.join(','), 103 }, 104 dataType: 'json', 105 method: 'GET', 106 success: function(response) { 107 if (response.table) { 108 $tables.each(function() { 109 $(this).replaceWith(response.table); 110 }); 111 bindShareableLinkHandler(); 112 } 113 } 114 }); 115 } 116 117 function bindShareableLinkHandler() { 118 $('.evercompare-copy-link').on('click', function(e) { 119 evercompareCopyToClipboard($(this).closest('.ever-compare-shareable-link').find('.evercompare-share-link'), this); 120 }); 121 } 122 123 // Error modal 124 $body.append('<div id="htcompare-error-modal" class="htcompare-error-modal" style="display:none"><div class="htcompare-error-modal-content"><button class="htcompare-error-modal-close">×</button><div class="htcompare-error-modal-body"></div></div></div>'); 125 var $htcompareErrorModal = $("#htcompare-error-modal"); 14 126 $('.htcompare-error-modal-close').on('click', function() { 15 127 $htcompareErrorModal.css('display', 'none'); 16 }) 128 }); 17 129 $(window).on('click', function(e) { 18 130 if(e.target == $htcompareErrorModal[0]) { 19 131 $htcompareErrorModal.css('display', 'none'); 20 132 } 21 }) 22 $('a.htcompare-btn').each(function() { 23 const $this = $(this); 24 if($this.hasClass('added')) { 25 $this.html('<span class="htcompare-btn-text">'+$this.data('added-text')+'</span>'); 26 } 27 }); 133 }); 134 135 // Sync states on DOM ready 136 syncButtonStates(); 137 syncCounter(); 138 loadCompareTable(); 28 139 29 140 // Notification Markup 30 const notificationMarkup = `<div class="htcompare-notification"> 31 <div class="htcompare-notification-text">${evercompare.option_data.success_added_notification_text}</div> 32 <span class="htcompare-notification-close">close</span> 33 </div>` 34 // Insert Notification Markup in body & notification close method if notification is enabled 141 var notificationMarkup = '<div class="htcompare-notification"><div class="htcompare-notification-text">' + evercompare.option_data.success_added_notification_text + '</div><span class="htcompare-notification-close">close</span></div>'; 35 142 if(evercompare.option_data.enable_success_notification === 'on') { 36 143 $body.append(notificationMarkup); … … 40 147 } 41 148 // Notification Show Function 42 const ShowNotification = (message) =>{149 var ShowNotification = function(message) { 43 150 if(evercompare.option_data.enable_success_notification === 'on') { 44 151 $body.find('.htcompare-notification-text').html(message); … … 47 154 setTimeout(function() { 48 155 $body.find('.htcompare-notification').removeClass('open'); 49 }, +evercompare.option_data.removed_notification_after * 1000) 50 } 51 } 52 } 156 }, +evercompare.option_data.removed_notification_after * 1000); 157 } 158 } 159 }; 53 160 54 161 // Add product in compare table … … 73 180 $this.addClass('loading'); 74 181 75 $.ajax({ 76 url: evercompare.ajaxurl, 77 data: { 78 action: 'ever_compare_add_to_compare', 79 nonce: evercompare.nonce, 80 id: id, 81 }, 82 dataType: 'json', 83 method: 'GET', 84 success: function ( response ) { 85 const $products = typeof response.products === 'array' ? response.products : Object.values(response.products); 86 if ( response.table && $products.indexOf(id.toString()) >= 0 ) { 87 updateCompareData( response ); 88 $popup.addClass('open'); 89 } else { 90 $('.htcompare-error-modal-body').html(response.limitReached) 91 $htcompareErrorModal.css('display', 'flex'); 92 console.log( 'Something wrong loading compare data' ); 93 } 94 $body.find('.htcompare-counter').html( response.count ); 95 }, 96 error: function ( data ) { 97 console.log('Something wrong with AJAX response.'); 98 }, 99 complete: function (res) { 100 $this.removeClass('loading'); 101 const $products = typeof res.responseJSON.products === 'array' ? res.responseJSON.products : Object.values(res.responseJSON.products); 102 if($products.indexOf(id.toString()) >= 0) { 103 $this.addClass('added'); 104 $this.html('<span class="htcompare-btn-text">'+addedText+'</span>'); 105 } 106 ShowNotification(success_message); 107 }, 182 getNonce().then(function(nonce) { 183 $.ajax({ 184 url: evercompare.ajaxurl, 185 data: { 186 action: 'ever_compare_add_to_compare', 187 nonce: nonce, 188 id: id, 189 }, 190 dataType: 'json', 191 method: 'GET', 192 success: function ( response ) { 193 if ( !response || !response.products ) { 194 $body.find('.htcompare-counter').html( response ? response.count : 0 ); 195 return; 196 } 197 var $products = typeof response.products === 'object' ? Object.values(response.products) : response.products; 198 var productStrings = $products.map(function(p) { return p.toString(); }); 199 if ( response.table && productStrings.indexOf(id.toString()) >= 0 ) { 200 updateCompareData( response ); 201 $popup.addClass('open'); 202 } else { 203 $('.htcompare-error-modal-body').html(response.limitReached); 204 $htcompareErrorModal.css('display', 'flex'); 205 } 206 $body.find('.htcompare-counter').html( response.count ); 207 }, 208 error: function ( data ) { 209 console.log('Something wrong with AJAX response.'); 210 }, 211 complete: function (res) { 212 $this.removeClass('loading'); 213 if (res.responseJSON && res.responseJSON.products) { 214 var $products = typeof res.responseJSON.products === 'object' ? Object.values(res.responseJSON.products) : res.responseJSON.products; 215 var productStrings = $products.map(function(p) { return p.toString(); }); 216 if(productStrings.indexOf(id.toString()) >= 0) { 217 $this.addClass('added'); 218 $this.html('<span class="htcompare-btn-text">'+addedText+'</span>'); 219 ShowNotification(success_message); 220 } 221 } 222 }, 223 }); 224 }).fail(function() { 225 $this.removeClass('loading'); 108 226 }); 109 227 … … 117 235 success_message = evercompare.option_data.success_removed_notification_text.replace('{product_name}', $this.data('product_title')); 118 236 $this.addClass('loading'); 237 getNonce().then(function(nonce) { 238 jQuery.ajax({ 239 url: evercompare.ajaxurl, 240 data: { 241 action: 'ever_compare_remove_from_compare', 242 nonce: nonce, 243 id: id, 244 }, 245 dataType: 'json', 246 method: 'GET', 247 success: function (response) { 248 if (response) { 249 $body.find('.htcompare-counter').html( response.count ); 250 } else { 251 console.log( 'Something wrong loading compare data' ); 252 } 253 }, 254 error: function (data) { 255 console.log('Something wrong with AJAX response.'); 256 }, 257 complete: function (res) { 258 $this.removeClass('loading added').html('<span class="htcompare-btn-text">'+$this.data('text')+'</span>'); 259 if (res.responseJSON && res.responseJSON.count !== undefined) { 260 ShowNotification(success_message); 261 } 262 }, 263 }); 264 }).fail(function() { 265 $this.removeClass('loading'); 266 }); 267 }); 268 } 269 270 // Remove data from compare table 271 $body.on('click', 'a.htcompare-remove', function (e) { 272 var $table = $('.htcompare-table'); 273 274 e.preventDefault(); 275 var $this = $(this), 276 id = $this.data('product_id'), 277 success_message = evercompare.option_data.success_removed_notification_text.replace('{product_name}', $this.data('product_title')); 278 279 $table.addClass('loading'); 280 $this.addClass('loading'); 281 282 getNonce().then(function(nonce) { 119 283 jQuery.ajax({ 120 284 url: evercompare.ajaxurl, 121 285 data: { 122 286 action: 'ever_compare_remove_from_compare', 123 nonce: evercompare.nonce,287 nonce: nonce, 124 288 id: id, 125 289 }, … … 127 291 method: 'GET', 128 292 success: function (response) { 129 if (response ) {130 $body.find('.htcompare-counter').html( response.count);293 if (response.table) { 294 updateCompareData(response); 131 295 } else { 132 296 console.log( 'Something wrong loading compare data' ); 133 297 } 298 $('a.htcompare-btn').each(function() { 299 if($(this).data('product_id') === id) { 300 $(this).removeClass('added'); 301 $(this).html('<span class="htcompare-btn-text">'+$(this).data('text')+'</span>'); 302 } 303 }); 304 $body.find('.htcompare-counter').html( response.count ); 134 305 }, 135 306 error: function (data) { 136 307 console.log('Something wrong with AJAX response.'); 137 308 }, 138 complete: function () { 139 $this.removeClass('loading added').html('<span class="htcompare-btn-text">'+$this.data('text')+'</span>'); 140 ShowNotification(success_message); 309 complete: function (res) { 310 $table.removeClass('loading'); 311 $this.removeClass('loading'); 312 if (res.responseJSON && res.responseJSON.table) { 313 ShowNotification(success_message); 314 } 141 315 }, 142 316 }); 143 }); 144 } 145 146 // Remove data from compare table 147 $body.on('click', 'a.htcompare-remove', function (e) { 148 var $table = $('.htcompare-table'); 149 150 e.preventDefault(); 151 var $this = $(this), 152 id = $this.data('product_id'), 153 success_message = evercompare.option_data.success_removed_notification_text.replace('{product_name}', $this.data('product_title')); 154 155 $table.addClass('loading'); 156 $this.addClass('loading'); 157 158 jQuery.ajax({ 159 url: evercompare.ajaxurl, 160 data: { 161 action: 'ever_compare_remove_from_compare', 162 nonce: evercompare.nonce, 163 id: id, 164 }, 165 dataType: 'json', 166 method: 'GET', 167 success: function (response) { 168 if (response.table) { 169 updateCompareData(response); 170 } else { 171 console.log( 'Something wrong loading compare data' ); 172 } 173 $('a.htcompare-btn').each(function() { 174 if($(this).data('product_id') === id) { 175 $(this).removeClass('added'); 176 $(this).html('<span class="htcompare-btn-text">'+$(this).data('text')+'</span>'); 177 } 178 }) 179 $body.find('.htcompare-counter').html( response.count ); 180 }, 181 error: function (data) { 182 console.log('Something wrong with AJAX response.'); 183 }, 184 complete: function () { 185 $table.removeClass('loading'); 186 $this.addClass('loading'); 187 ShowNotification(success_message); 188 }, 317 }).fail(function() { 318 $table.removeClass('loading'); 319 $this.removeClass('loading'); 189 320 }); 190 321 … … 195 326 if ( $('.htcompare-table').length > 0 ) { 196 327 $('.htcompare-table').replaceWith( data.table ); 197 $('.evercompare-copy-link').on('click',function(e){ 198 evercompareCopyToClipboard( $(this).closest('.ever-compare-shareable-link').find('.evercompare-share-link') , this ); 199 }); 328 bindShareableLinkHandler(); 200 329 } 201 330 } … … 208 337 209 338 // Copy Shareable link 210 $('.evercompare-copy-link').on('click',function(e){ 211 evercompareCopyToClipboard( $(this).closest('.ever-compare-shareable-link').find('.evercompare-share-link') , this ); 212 }); 339 bindShareableLinkHandler(); 213 340 function evercompareCopyToClipboard( element, button ) { 214 341 var $tempdata = $("<input>"); … … 218 345 $tempdata.remove(); 219 346 $(button).text( $(button).data('copytext') ); 220 setTimeout(function() { 347 setTimeout(function() { 221 348 $( button ).text( $(button).data('btntext') ); 222 349 }, 1000); -
ever-compare/tags/1.3.5/assets/js/frontend.min.js
r3108021 r3483393 1 !function(t){"use strict";var o=t("body"),e=t(".htcompare-popup");o.append(`<div id="htcompare-error-modal" class="htcompare-error-modal" style="display:none"> 2 <div class="htcompare-error-modal-content"> 3 <button class="htcompare-error-modal-close">×</button> 4 <div class="htcompare-error-modal-body"></div> 5 </div> 6 </div>`);let a=t("#htcompare-error-modal");t(".htcompare-error-modal-close").on("click",function(){a.css("display","none")}),t(window).on("click",function(t){t.target==a[0]&&a.css("display","none")}),t("a.htcompare-btn").each(function(){let o=t(this);o.hasClass("added")&&o.html('<span class="htcompare-btn-text">'+o.data("added-text")+"</span>")});let n=`<div class="htcompare-notification"> 7 <div class="htcompare-notification-text">${evercompare.option_data.success_added_notification_text}</div> 8 <span class="htcompare-notification-close">close</span> 9 </div>`;"on"===evercompare.option_data.enable_success_notification&&(o.append(n),o.on("click",".htcompare-notification-close",function(){o.find(".htcompare-notification").removeClass("open")}));let c=t=>{"on"===evercompare.option_data.enable_success_notification&&(o.find(".htcompare-notification-text").html(t),o.find(".htcompare-notification").addClass("open"),+evercompare.option_data.removed_notification_after>-1&&setTimeout(function(){o.find(".htcompare-notification").removeClass("open")},1e3*+evercompare.option_data.removed_notification_after))};function i(o){t(".htcompare-table").length>0&&(t(".htcompare-table").replaceWith(o.table),t(".evercompare-copy-link").on("click",function(o){r(t(this).closest(".ever-compare-shareable-link").find(".evercompare-share-link"),this)}))}function r(o,e){var a=t("<input>");t("body").append(a),a.val(t(o).text()).select(),document.execCommand("copy"),a.remove(),t(e).text(t(e).data("copytext")),setTimeout(function(){t(e).text(t(e).data("btntext"))},1e3)}o.on("click","a.htcompare-btn",function(n){var r=t(this),d=r.data("product_id"),s=r.data("added-text"),p=evercompare.option_data.success_added_notification_text.replace("{product_name}",r.data("product_title"));if("yes"===evercompare.popup&&"off"===evercompare.option_data.remove_on_click){if(n.preventDefault(),r.hasClass("added"))return o.find(".htcompare-popup").addClass("open"),!0}else if(r.hasClass("added"))return!0;n.preventDefault(),r.addClass("loading"),t.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_add_to_compare",nonce:evercompare.nonce,id:d},dataType:"json",method:"GET",success:function(n){let c="array"==typeof n.products?n.products:Object.values(n.products);n.table&&c.indexOf(d.toString())>=0?(i(n),e.addClass("open")):(t(".htcompare-error-modal-body").html(n.limitReached),a.css("display","flex"),console.log("Something wrong loading compare data")),o.find(".htcompare-counter").html(n.count)},error:function(t){console.log("Something wrong with AJAX response.")},complete:function(t){r.removeClass("loading");let o="array"==typeof t.responseJSON.products?t.responseJSON.products:Object.values(t.responseJSON.products);o.indexOf(d.toString())>=0&&(r.addClass("added"),r.html('<span class="htcompare-btn-text">'+s+"</span>")),c(p)}})}),evercompare.option_data.remove_on_click&&"on"===evercompare.option_data.remove_on_click&&o.on("click","a.htcompare-btn.added",function(e){e.preventDefault();var a=t(this),n=a.data("product_id"),i=evercompare.option_data.success_removed_notification_text.replace("{product_name}",a.data("product_title"));a.addClass("loading"),jQuery.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_remove_from_compare",nonce:evercompare.nonce,id:n},dataType:"json",method:"GET",success:function(t){t?o.find(".htcompare-counter").html(t.count):console.log("Something wrong loading compare data")},error:function(t){console.log("Something wrong with AJAX response.")},complete:function(){a.removeClass("loading added").html('<span class="htcompare-btn-text">'+a.data("text")+"</span>"),c(i)}})}),o.on("click","a.htcompare-remove",function(e){var a=t(".htcompare-table");e.preventDefault();var n=t(this),r=n.data("product_id"),d=evercompare.option_data.success_removed_notification_text.replace("{product_name}",n.data("product_title"));a.addClass("loading"),n.addClass("loading"),jQuery.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_remove_from_compare",nonce:evercompare.nonce,id:r},dataType:"json",method:"GET",success:function(e){e.table?i(e):console.log("Something wrong loading compare data"),t("a.htcompare-btn").each(function(){t(this).data("product_id")===r&&(t(this).removeClass("added"),t(this).html('<span class="htcompare-btn-text">'+t(this).data("text")+"</span>"))}),o.find(".htcompare-counter").html(e.count)},error:function(t){console.log("Something wrong with AJAX response.")},complete:function(){a.removeClass("loading"),n.addClass("loading"),c(d)}})}),o.on("click",".htcompare-popup-close",function(o){t(this).parent(".htcompare-popup.open").removeClass("open"),e.removeClass("open")}),t(".evercompare-copy-link").on("click",function(o){r(t(this).closest(".ever-compare-shareable-link").find(".evercompare-share-link"),this)})}(jQuery); 1 !function(e){"use strict";var o=e("body"),t=e(".htcompare-popup"),a=null,n=null;function r(){for(var e=evercompare.cookie_name,o=document.cookie.split(";"),t=0;t<o.length;t++){var a=o[t].trim();if(0===a.indexOf(e+"=")){var n=decodeURIComponent(a.substring(e.length+1));try{var r=JSON.parse(n);if(Array.isArray(r))return r.map(function(e){return parseInt(e,10)}).filter(function(e){return e>0})}catch(e){}}}return[]}function c(){return a?e.Deferred().resolve(a).promise():n||(n=e.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_get_nonce"},dataType:"json",method:"GET"}).then(function(e){return a=e.nonce,n=null,a}).fail(function(){n=null}))}function i(){e(".evercompare-copy-link").on("click",function(o){var t,a,n;t=e(this).closest(".ever-compare-shareable-link").find(".evercompare-share-link"),a=this,n=e("<input>"),e("body").append(n),n.val(e(t).text()).select(),document.execCommand("copy"),n.remove(),e(a).text(e(a).data("copytext")),setTimeout(function(){e(a).text(e(a).data("btntext"))},1e3)})}o.append('<div id="htcompare-error-modal" class="htcompare-error-modal" style="display:none"><div class="htcompare-error-modal-content"><button class="htcompare-error-modal-close">×</button><div class="htcompare-error-modal-body"></div></div></div>');var s,d=e("#htcompare-error-modal");e(".htcompare-error-modal-close").on("click",function(){d.css("display","none")}),e(window).on("click",function(e){e.target==d[0]&&d.css("display","none")}),s=r(),e("a.htcompare-btn").each(function(){var o=e(this),t=parseInt(o.data("product_id"),10);s.indexOf(t)>=0&&(o.addClass("added"),o.html('<span class="htcompare-btn-text">'+o.data("added-text")+"</span>"))}),function(){var e=r();o.find(".htcompare-counter").html(e.length)}(),function(){var o=e(".htcompare-table[data-ajax-load]");if(0!==o.length){var t=r();0!==t.length?e.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_get_table",ids:t.join(",")},dataType:"json",method:"GET",success:function(t){t.table&&(o.each(function(){e(this).replaceWith(t.table)}),i())}}):e.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_get_table",ids:""},dataType:"json",method:"GET",success:function(t){void 0!==t.table&&(o.each(function(){e(this).replaceWith(t.table||'<div class="htcompare-table htcompare-empty"></div>')}),i())}})}}();var p='<div class="htcompare-notification"><div class="htcompare-notification-text">'+evercompare.option_data.success_added_notification_text+'</div><span class="htcompare-notification-close">close</span></div>';"on"===evercompare.option_data.enable_success_notification&&(o.append(p),o.on("click",".htcompare-notification-close",function(){o.find(".htcompare-notification").removeClass("open")}));var l=function(e){"on"===evercompare.option_data.enable_success_notification&&(o.find(".htcompare-notification-text").html(e),o.find(".htcompare-notification").addClass("open"),+evercompare.option_data.removed_notification_after>-1&&setTimeout(function(){o.find(".htcompare-notification").removeClass("open")},1e3*+evercompare.option_data.removed_notification_after))};function m(o){e(".htcompare-table").length>0&&(e(".htcompare-table").replaceWith(o.table),i())}o.on("click","a.htcompare-btn",function(a){var n=e(this),r=n.data("product_id"),i=n.data("added-text"),s=evercompare.option_data.success_added_notification_text.replace("{product_name}",n.data("product_title"));if("yes"===evercompare.popup&&"off"===evercompare.option_data.remove_on_click){if(a.preventDefault(),n.hasClass("added"))return o.find(".htcompare-popup").addClass("open"),!0}else if(n.hasClass("added"))return!0;a.preventDefault(),n.addClass("loading"),c().then(function(a){e.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_add_to_compare",nonce:a,id:r},dataType:"json",method:"GET",success:function(a){if(a&&a.products){var n=("object"==typeof a.products?Object.values(a.products):a.products).map(function(e){return e.toString()});a.table&&n.indexOf(r.toString())>=0?(m(a),t.addClass("open")):(e(".htcompare-error-modal-body").html(a.limitReached),d.css("display","flex")),o.find(".htcompare-counter").html(a.count)}else o.find(".htcompare-counter").html(a?a.count:0)},error:function(e){console.log("Something wrong with AJAX response.")},complete:function(e){(n.removeClass("loading"),e.responseJSON&&e.responseJSON.products)&&(("object"==typeof e.responseJSON.products?Object.values(e.responseJSON.products):e.responseJSON.products).map(function(e){return e.toString()}).indexOf(r.toString())>=0&&(n.addClass("added"),n.html('<span class="htcompare-btn-text">'+i+"</span>"),l(s)))}})}).fail(function(){n.removeClass("loading")})}),evercompare.option_data.remove_on_click&&"on"===evercompare.option_data.remove_on_click&&o.on("click","a.htcompare-btn.added",function(t){t.preventDefault();var a=e(this),n=a.data("product_id"),r=evercompare.option_data.success_removed_notification_text.replace("{product_name}",a.data("product_title"));a.addClass("loading"),c().then(function(e){jQuery.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_remove_from_compare",nonce:e,id:n},dataType:"json",method:"GET",success:function(e){e?o.find(".htcompare-counter").html(e.count):console.log("Something wrong loading compare data")},error:function(e){console.log("Something wrong with AJAX response.")},complete:function(e){a.removeClass("loading added").html('<span class="htcompare-btn-text">'+a.data("text")+"</span>"),e.responseJSON&&void 0!==e.responseJSON.count&&l(r)}})}).fail(function(){a.removeClass("loading")})}),o.on("click","a.htcompare-remove",function(t){var a=e(".htcompare-table");t.preventDefault();var n=e(this),r=n.data("product_id"),i=evercompare.option_data.success_removed_notification_text.replace("{product_name}",n.data("product_title"));a.addClass("loading"),n.addClass("loading"),c().then(function(t){jQuery.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_remove_from_compare",nonce:t,id:r},dataType:"json",method:"GET",success:function(t){t.table?m(t):console.log("Something wrong loading compare data"),e("a.htcompare-btn").each(function(){e(this).data("product_id")===r&&(e(this).removeClass("added"),e(this).html('<span class="htcompare-btn-text">'+e(this).data("text")+"</span>"))}),o.find(".htcompare-counter").html(t.count)},error:function(e){console.log("Something wrong with AJAX response.")},complete:function(e){a.removeClass("loading"),n.removeClass("loading"),e.responseJSON&&e.responseJSON.table&&l(i)}})}).fail(function(){a.removeClass("loading"),n.removeClass("loading")})}),o.on("click",".htcompare-popup-close",function(o){e(this).parent(".htcompare-popup.open").removeClass("open"),t.removeClass("open")}),i()}(jQuery); -
ever-compare/tags/1.3.5/ever-compare.php
r3331136 r3483393 6 6 * Author: HasTheme 7 7 * Author URI: https://hasthemes.com/ 8 * Version: 1.3. 48 * Version: 1.3.5 9 9 * License: GPL2 or later 10 10 * License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 26 26 * @var string 27 27 */ 28 const version = '1.3. 4';28 const version = '1.3.5'; 29 29 30 30 /** … … 58 58 add_action( 'plugins_loaded', [ $this, 'init_plugin' ] ); 59 59 60 // Compatible With WooCommerce Custom Order Tables60 // Compatible With WooCommerce Features 61 61 add_action( 'before_woocommerce_init', function() { 62 62 if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) { 63 63 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', EVERCOMPARE_FILE, true ); 64 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', EVERCOMPARE_FILE, true ); 65 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'product_block_editor', EVERCOMPARE_FILE, true ); 64 66 } 65 67 } ); … … 107 109 EverCompare\Assets::instance(); 108 110 109 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {110 EverCompare\Ajax::instance();111 }112 113 111 if ( is_admin() ) { 114 112 $this->admin_notices(); 115 113 EverCompare\Admin::instance(); 116 114 } 115 116 if ( ! ever_compare_woocommerce_installed() ) { 117 return; 118 } 119 120 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { 121 EverCompare\Ajax::instance(); 122 } 123 117 124 EverCompare\Frontend::instance(); 118 125 -
ever-compare/tags/1.3.5/includes/classes/Admin/Settings_APi.php
r3314387 r3483393 27 27 * Enqueue scripts and styles 28 28 */ 29 function admin_enqueue_scripts() { 29 function admin_enqueue_scripts( $hook ) { 30 if ( false === strpos( $hook, 'evercompare' ) ) { 31 return; 32 } 30 33 wp_enqueue_style( 'wp-color-picker' ); 31 34 wp_enqueue_media(); -
ever-compare/tags/1.3.5/includes/classes/Ajax.php
r3144815 r3483393 36 36 add_action( 'wp_ajax_nopriv_ever_compare_remove_from_compare', [ $this,'remove_from_compare' ] ); 37 37 38 // Get Nonce endpoint (no nonce verification needed) 39 add_action( 'wp_ajax_ever_compare_get_nonce', [ $this, 'get_nonce' ] ); 40 add_action( 'wp_ajax_nopriv_ever_compare_get_nonce', [ $this, 'get_nonce' ] ); 41 42 // Get Table endpoint 43 add_action( 'wp_ajax_ever_compare_get_table', [ $this, 'get_table' ] ); 44 add_action( 'wp_ajax_nopriv_ever_compare_get_table', [ $this, 'get_table' ] ); 45 38 46 } 39 47 … … 44 52 check_ajax_referer('ever_compare_nonce', 'nonce'); 45 53 if(!empty($_GET['id'])) { 46 $id = sanitize_text_field( wp_unslash($_GET['id']));54 $id = absint( $_GET['id'] ); 47 55 \EverCompare\Frontend\Manage_Compare::instance()->add_to_compare( $id ); 48 56 } … … 56 64 check_ajax_referer('ever_compare_nonce', 'nonce'); 57 65 if(!empty($_GET['id'])) { 58 $id = sanitize_text_field( wp_unslash($_GET['id']));66 $id = absint( $_GET['id'] ); 59 67 \EverCompare\Frontend\Manage_Compare::instance()->remove_from_compare( $id ); 60 68 } 61 69 } 62 70 71 /** 72 * [get_nonce] Return a fresh nonce for AJAX operations 73 * @return [void] 74 */ 75 public function get_nonce(){ 76 wp_send_json( array( 77 'nonce' => wp_create_nonce( 'ever_compare_nonce' ), 78 ) ); 79 } 80 81 /** 82 * [get_table] Return compare table HTML for given product IDs 83 * @return [void] 84 */ 85 public function get_table(){ 86 $ids = array(); 87 if ( ! empty( $_GET['ids'] ) ) { 88 $raw_ids = sanitize_text_field( wp_unslash( $_GET['ids'] ) ); 89 $ids = array_filter( array_map( 'absint', explode( ',', $raw_ids ) ) ); 90 $ids = array_slice( $ids, 0, \EverCompare\Frontend\Manage_Compare::instance()->max_limit ); 91 } 92 93 if ( empty( $ids ) ) { 94 wp_send_json( array( 95 'table' => '', 96 'count' => 0, 97 ) ); 98 } 99 100 $cookie_name = \EverCompare\Frontend\Manage_Compare::instance()->get_cookie_name(); 101 $_COOKIE[ $cookie_name ] = wp_json_encode( $ids ); 102 103 ob_start(); 104 \EverCompare\Frontend\Manage_Compare::instance()->get_response_html(); 105 $table_html = ob_get_clean(); 106 107 wp_send_json( array( 108 'table' => $table_html, 109 'count' => count( $ids ), 110 'products' => $ids, 111 ) ); 112 } 113 63 114 } -
ever-compare/tags/1.3.5/includes/classes/Assets.php
r3108021 r3483393 116 116 'removed_notification_after' => ever_compare_get_option( 'removed_notification_after', 'ever_compare_settings_general', -1 ), 117 117 ); 118 $cookie_name = 'ever_compare_compare_list'; 119 if ( is_multisite() ) { 120 $cookie_name .= '_' . get_current_blog_id(); 121 } 118 122 $localize_data = array( 119 'ajaxurl' => admin_url( 'admin-ajax.php' ), 120 'nonce' => wp_create_nonce('ever_compare_nonce'), 121 'popup' => ( ever_compare_get_option( 'open_popup', 'ever_compare_settings_tabs', 'on' ) === 'on' ) ? 'yes' : 'no', 122 'option_data' => $option_data, 123 'ajaxurl' => admin_url( 'admin-ajax.php' ), 124 'cookie_name' => $cookie_name, 125 'compare_page_url' => esc_url( get_permalink( ever_compare_get_option( 'compare_page', 'ever_compare_table_settings_tabs' ) ) ), 126 'popup' => ( ever_compare_get_option( 'open_popup', 'ever_compare_settings_tabs', 'on' ) === 'on' ) ? 'yes' : 'no', 127 'option_data' => $option_data, 123 128 ); 124 129 -
ever-compare/tags/1.3.5/includes/classes/Frontend/Manage_Compare.php
r3314387 r3483393 126 126 } 127 127 128 /**129 * Manage maximum product added message130 */131 if( isset( $_COOKIE[ 'ever_compare_max_limit' ] ) && $_COOKIE[ 'ever_compare_max_limit' ] == 'yes' ) {132 setcookie( 'ever_compare_max_limit', 'no', 0, COOKIEPATH, COOKIE_DOMAIN, false, false );133 $this->reached_max_limit = true;134 }135 128 136 129 … … 171 164 */ 172 165 public function pop_up_html(){ 173 echo '<div class="htcompare-popup"><div class="htcompare-popup-content-area"><span class="htcompare-popup-close"> </span> '.do_shortcode( '[evercompare_table]' ).'</div></div>';166 echo '<div class="htcompare-popup"><div class="htcompare-popup-content-area"><span class="htcompare-popup-close"> </span><div class="htcompare-table" data-ajax-load="true"></div></div></div>'; 174 167 } 175 168 … … 201 194 $ids = $this->get_compared_products(); 202 195 203 if ( isset( $_GET['evcompare'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended196 if ( ! empty( $_GET['evcompare'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended 204 197 $query_perametter_ids = sanitize_text_field( wp_unslash($_GET['evcompare']) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended 205 198 if( !empty( $query_perametter_ids ) ){ 206 $ids = explode( ',', $query_perametter_ids);199 $ids = array_filter( array_map( 'absint', explode( ',', $query_perametter_ids ) ) ); 207 200 } 208 201 } … … 238 231 // Reached Maximum Limit 239 232 if( $this->reached_max_limit() ) { 240 setcookie( 'ever_compare_max_limit', 'yes', 0, COOKIEPATH, COOKIE_DOMAIN, false, false );241 233 $this->compare_json_response(); 242 234 } … … 289 281 } 290 282 } 283 284 $products = array_values( $products ); 291 285 292 286 if ( empty( $products ) ) { … … 338 332 // For shareable link 339 333 $shareable_link = ever_compare_get_option('enable_shareable_link','ever_compare_table_settings_tabs','off'); 340 if ( ( $shareable_link === 'on' ) && isset( $_GET['evcompare'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended334 if ( ( $shareable_link === 'on' ) && ! empty( $_GET['evcompare'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended 341 335 $query_perametter_ids = sanitize_text_field( wp_unslash($_GET['evcompare']) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended 342 336 if( !empty( $query_perametter_ids ) ){ 343 $ids = explode( ',', $query_perametter_ids);337 $ids = array_filter( array_map( 'absint', explode( ',', $query_perametter_ids ) ) ); 344 338 } 345 339 } … … 606 600 public function is_product_in_compare( $id ) { 607 601 $list = $this->get_compared_products(); 608 return in_array( strval($id), $list, true );602 return in_array( absint($id), $list, true ); 609 603 } 610 604 … … 616 610 $cookie_name = $this->get_cookie_name(); 617 611 if(!empty( $_COOKIE[ $cookie_name ] )) { 618 return json_decode( sanitize_text_field(wp_unslash( $_COOKIE[ $cookie_name ] )), true ); 612 $decoded = json_decode( sanitize_text_field(wp_unslash( $_COOKIE[ $cookie_name ] )), true ); 613 if ( is_array( $decoded ) ) { 614 return array_filter( array_map( 'absint', $decoded ) ); 615 } 619 616 } 620 617 return []; -
ever-compare/tags/1.3.5/includes/classes/Frontend/Shortcode.php
r3041668 r3483393 89 89 } else { 90 90 $button_added_text = '<span class="evercompare-btn-text">'.$button_remove_text.'</span>'; 91 }92 93 if(\EverCompare\Frontend\Manage_Compare::instance()->is_product_in_compare( $product_id )) {94 $button_class[] = 'added';95 91 } 96 92 … … 118 114 */ 119 115 public function table_shortcode( $atts, $content = '' ){ 120 116 121 117 wp_enqueue_style( 'evercompare-frontend' ); 122 118 wp_enqueue_script( 'evercompare-frontend' ); 123 119 124 /* Fetch From option data */ 125 $empty_compare_text = ever_compare_get_option('empty_table_text','ever_compare_table_settings_tabs'); 126 $return_shop_button = ever_compare_get_option('shop_button_text','ever_compare_table_settings_tabs','Return to shop'); 127 128 /* Product and Field */ 129 $products = Manage_Compare::instance()->get_compared_products_data(); 130 $fields = Manage_Compare::instance()->get_compare_fields(); 131 132 $custom_heading = !empty( ever_compare_get_option( 'table_heading', 'ever_compare_table_settings_tabs' ) ) ? ever_compare_get_option( 'table_heading', 'ever_compare_table_settings_tabs' ) : array(); 133 134 $default_atts = array( 135 'evercompare' => Manage_Compare::instance(), 136 'products' => $products, 137 'fields' => $fields, 138 'return_shop_button'=> $return_shop_button, 139 'heading_txt' => $custom_heading, 140 'empty_compare_text'=> $empty_compare_text, 141 ); 142 143 $atts = shortcode_atts( $default_atts, $atts, $content ); 144 return Manage_Compare::instance()->table_html( $atts ); 120 // Shareable link via query param — render server-side (not cached due to query param) 121 if ( ! empty( $_GET['evcompare'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended 122 /* Fetch From option data */ 123 $empty_compare_text = ever_compare_get_option('empty_table_text','ever_compare_table_settings_tabs'); 124 $return_shop_button = ever_compare_get_option('shop_button_text','ever_compare_table_settings_tabs','Return to shop'); 125 126 /* Product and Field */ 127 $products = Manage_Compare::instance()->get_compared_products_data(); 128 $fields = Manage_Compare::instance()->get_compare_fields(); 129 130 $custom_heading = !empty( ever_compare_get_option( 'table_heading', 'ever_compare_table_settings_tabs' ) ) ? ever_compare_get_option( 'table_heading', 'ever_compare_table_settings_tabs' ) : array(); 131 132 $default_atts = array( 133 'evercompare' => Manage_Compare::instance(), 134 'products' => $products, 135 'fields' => $fields, 136 'return_shop_button'=> $return_shop_button, 137 'heading_txt' => $custom_heading, 138 'empty_compare_text'=> $empty_compare_text, 139 ); 140 141 $atts = shortcode_atts( $default_atts, $atts, $content ); 142 return Manage_Compare::instance()->table_html( $atts ); 143 } 144 145 // Cookie-based: render placeholder that JS will populate via AJAX 146 return '<div class="htcompare-table" data-ajax-load="true"></div>'; 145 147 146 148 } … … 159 161 160 162 $default_atts = array( 161 'count' => count(Manage_Compare::instance()->get_compared_products()),163 'count' => 0, 162 164 'page_url' => Manage_Compare::instance()->get_compare_page_url(), 163 165 ); -
ever-compare/tags/1.3.5/includes/helper-functions.php
r3108021 r3483393 21 21 function ever_compare_update_option( $section, $option_key, $new_value ){ 22 22 $options_data = get_option( $section ); 23 if( isset( $options_data[$option_key] ) ){ 24 $options_data[$option_key] = $new_value; 25 }else{ 26 $options_data = array( $option_key => $new_value ); 27 } 23 if ( ! is_array( $options_data ) ) { 24 $options_data = array(); 25 } 26 $options_data[ $option_key ] = $new_value; 28 27 update_option( $section, $options_data ); 29 28 } … … 44 43 $options = array(); 45 44 $options['0'] = __('Select','ever-compare'); 46 $perpage = -1;45 $perpage = 200; 47 46 $all_post = array( 'posts_per_page' => $perpage, 'post_type'=> $post_type ); 48 47 $post_terms = get_posts( $all_post ); … … 88 87 89 88 if ( $args && is_array( $args ) ) { 90 extract( $args ); 89 $evercompare_args = $args; 90 // Backward compat: if template is overridden in theme, extract for legacy support 91 $default_path = EVERCOMPARE_PATH . '/includes/templates/' . $tmp_name; 92 if ( $located !== $default_path ) { 93 extract( $args, EXTR_SKIP ); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract 94 } 91 95 } 92 96 -
ever-compare/tags/1.3.5/includes/templates/evercompare-button-add.php
r3108021 r3483393 1 <span class="htcompare-button-area"><a href="<?php echo esc_url( $ button_url ); ?>" class="<?php echo esc_attr($button_class); ?>" data-text="<?php echo esc_attr( $button_text ); ?>" data-added-text="<?php echo esc_attr( $button_added_text); ?>" data-product_id="<?php echo esc_attr( $product_id ); ?>" data-product_title="<?php echo esc_attr( $product_title ); ?>" ><?php echo wp_kses($button_text, get_allowed_tags_for_svg()); ?></a></span>1 <span class="htcompare-button-area"><a href="<?php echo esc_url( $evercompare_args['button_url'] ); ?>" class="<?php echo esc_attr($evercompare_args['button_class']); ?>" data-text="<?php echo esc_attr( $evercompare_args['button_text'] ); ?>" data-added-text="<?php echo esc_attr( $evercompare_args['button_added_text']); ?>" data-product_id="<?php echo esc_attr( $evercompare_args['product_id'] ); ?>" data-product_title="<?php echo esc_attr( $evercompare_args['product_title'] ); ?>" ><?php echo wp_kses($evercompare_args['button_text'], get_allowed_tags_for_svg()); ?></a></span> -
ever-compare/tags/1.3.5/includes/templates/evercompare-count.php
r2927305 r3483393 1 <a href="<?php echo esc_url( $ page_url);?>" class="htcompare-counter-area">1 <a href="<?php echo esc_url( $evercompare_args['page_url'] );?>" class="htcompare-counter-area"> 2 2 <span class="htcompare-counter-icon"> 3 3 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 471.701 471.701" height="20px" width="20px" > … … 6 6 </span> 7 7 <?php 8 echo '<span class="htcompare-counter">'.esc_html( $ count).'</span>';8 echo '<span class="htcompare-counter">'.esc_html( $evercompare_args['count'] ).'</span>'; 9 9 ?> 10 10 </a> -
ever-compare/tags/1.3.5/includes/templates/evercompare-table.php
r3108021 r3483393 3 3 // do_action( 'ever_compare_before_table' ); 4 4 5 if ( ! empty( $products ) ) { 5 if ( ! empty( $evercompare_args['products'] ) ) { 6 $products = $evercompare_args['products']; 6 7 array_unshift( $products, array() ); 7 foreach ( $ fieldsas $field_id => $field ) {8 if ( ! $evercompare ->is_products_have_field( $field_id, $products ) ) {8 foreach ( $evercompare_args['fields'] as $field_id => $field ) { 9 if ( ! $evercompare_args['evercompare']->is_products_have_field( $field_id, $products ) ) { 9 10 continue; 10 11 } 11 12 12 13 // Generate Filed name 13 $name = $evercompare ->field_name( $field );14 if( array_key_exists( $field_id, $ heading_txt ) && !empty( $heading_txt[$field_id] ) ){15 $name = $evercompare ->field_name( $heading_txt[$field_id], true );14 $name = $evercompare_args['evercompare']->field_name( $field ); 15 if( array_key_exists( $field_id, $evercompare_args['heading_txt'] ) && !empty( $evercompare_args['heading_txt'][$field_id] ) ){ 16 $name = $evercompare_args['evercompare']->field_name( $evercompare_args['heading_txt'][$field_id], true ); 16 17 } 17 18 … … 21 22 <?php if ( ! empty( $product ) ) : ?> 22 23 <div class="htcompare-col htcolumn-value" data-title="<?php echo esc_attr( $name ); ?>"> 23 <?php $evercompare ->compare_display_field( $field_id, $product ); ?>24 <?php $evercompare_args['evercompare']->compare_display_field( $field_id, $product ); ?> 24 25 </div> 25 26 <?php else: ?> … … 32 33 <?php 33 34 } 34 echo '<div class="htcompare-table-loader"></div>'; 35 echo '<div class="htcompare-table-loader"></div>'; 35 36 } else { 36 if ( $e mpty_compare_text){37 echo '<div class="htcompare-empty-page-text">'.wp_kses_post( $e mpty_compare_text).'</div>';37 if ( $evercompare_args['empty_compare_text'] ){ 38 echo '<div class="htcompare-empty-page-text">'.wp_kses_post( $evercompare_args['empty_compare_text'] ).'</div>'; 38 39 } 39 40 40 if( $ return_shop_button){41 echo '<div class="htcompare-return-to-shop"><a href="'.esc_url( wc_get_page_permalink( 'shop' ) ).'" class="button">'.esc_html( $ return_shop_button).'</a></div>';41 if( $evercompare_args['return_shop_button'] ){ 42 echo '<div class="htcompare-return-to-shop"><a href="'.esc_url( wc_get_page_permalink( 'shop' ) ).'" class="button">'.esc_html( $evercompare_args['return_shop_button'] ).'</a></div>'; 42 43 } 43 44 } -
ever-compare/tags/1.3.5/readme.txt
r3407749 r3483393 4 4 Requires at least: 5.0 5 5 Tested up to: 6.9 6 Stable tag: 1.3. 46 Stable tag: 1.3.5 7 7 License: GPLv2 or later 8 8 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 90 90 91 91 == Changelog == 92 93 = Version: 1.3.5 - Date: 2026-03-16 = 94 * Fixed: Empty evcompare query parameter no longer generates broken shareable links. 95 * Improved: Cache compatibility for compare page using cookie-based AJAX loading. 92 96 93 97 = Version: 1.3.4 - Date: 2025-07-21 = -
ever-compare/trunk/assets/js/frontend.js
r3108021 r3483393 1 1 ;(function($){ 2 2 "use strict"; 3 3 4 4 var $body = $('body'), 5 $popup = $('.htcompare-popup'); 6 7 $body.append(`<div id="htcompare-error-modal" class="htcompare-error-modal" style="display:none"> 8 <div class="htcompare-error-modal-content"> 9 <button class="htcompare-error-modal-close">×</button> 10 <div class="htcompare-error-modal-body"></div> 11 </div> 12 </div>`); 13 const $htcompareErrorModal = $("#htcompare-error-modal"); 5 $popup = $('.htcompare-popup'), 6 cachedNonce = null, 7 noncePromise = null; 8 9 // Cookie helper: read compare list from cookie 10 function getCompareListFromCookie() { 11 var cookieName = evercompare.cookie_name; 12 var cookies = document.cookie.split(';'); 13 for (var i = 0; i < cookies.length; i++) { 14 var cookie = cookies[i].trim(); 15 if (cookie.indexOf(cookieName + '=') === 0) { 16 var value = decodeURIComponent(cookie.substring(cookieName.length + 1)); 17 try { 18 var parsed = JSON.parse(value); 19 if (Array.isArray(parsed)) { 20 return parsed.map(function(id) { return parseInt(id, 10); }).filter(function(id) { return id > 0; }); 21 } 22 } catch(e) {} 23 } 24 } 25 return []; 26 } 27 28 // Deferred nonce: fetch on first interaction, cache in memory 29 function getNonce() { 30 if (cachedNonce) { 31 return $.Deferred().resolve(cachedNonce).promise(); 32 } 33 if (noncePromise) { 34 return noncePromise; 35 } 36 noncePromise = $.ajax({ 37 url: evercompare.ajaxurl, 38 data: { action: 'ever_compare_get_nonce' }, 39 dataType: 'json', 40 method: 'GET', 41 }).then(function(response) { 42 cachedNonce = response.nonce; 43 noncePromise = null; 44 return cachedNonce; 45 }).fail(function() { 46 noncePromise = null; 47 }); 48 return noncePromise; 49 } 50 51 // Sync button states from cookie on DOM ready 52 function syncButtonStates() { 53 var compareList = getCompareListFromCookie(); 54 $('a.htcompare-btn').each(function() { 55 var $btn = $(this); 56 var productId = parseInt($btn.data('product_id'), 10); 57 if (compareList.indexOf(productId) >= 0) { 58 $btn.addClass('added'); 59 $btn.html('<span class="htcompare-btn-text">' + $btn.data('added-text') + '</span>'); 60 } 61 }); 62 } 63 64 // Sync counter from cookie on DOM ready 65 function syncCounter() { 66 var compareList = getCompareListFromCookie(); 67 $body.find('.htcompare-counter').html(compareList.length); 68 } 69 70 // Load compare table via AJAX for cookie-based pages 71 function loadCompareTable() { 72 var $tables = $('.htcompare-table[data-ajax-load]'); 73 if ($tables.length === 0) return; 74 75 var compareList = getCompareListFromCookie(); 76 if (compareList.length === 0) { 77 // Show empty state — fetch table with no IDs to get proper empty template 78 $.ajax({ 79 url: evercompare.ajaxurl, 80 data: { 81 action: 'ever_compare_get_table', 82 ids: '', 83 }, 84 dataType: 'json', 85 method: 'GET', 86 success: function(response) { 87 if (typeof response.table !== 'undefined') { 88 $tables.each(function() { 89 $(this).replaceWith(response.table || '<div class="htcompare-table htcompare-empty"></div>'); 90 }); 91 bindShareableLinkHandler(); 92 } 93 } 94 }); 95 return; 96 } 97 98 $.ajax({ 99 url: evercompare.ajaxurl, 100 data: { 101 action: 'ever_compare_get_table', 102 ids: compareList.join(','), 103 }, 104 dataType: 'json', 105 method: 'GET', 106 success: function(response) { 107 if (response.table) { 108 $tables.each(function() { 109 $(this).replaceWith(response.table); 110 }); 111 bindShareableLinkHandler(); 112 } 113 } 114 }); 115 } 116 117 function bindShareableLinkHandler() { 118 $('.evercompare-copy-link').on('click', function(e) { 119 evercompareCopyToClipboard($(this).closest('.ever-compare-shareable-link').find('.evercompare-share-link'), this); 120 }); 121 } 122 123 // Error modal 124 $body.append('<div id="htcompare-error-modal" class="htcompare-error-modal" style="display:none"><div class="htcompare-error-modal-content"><button class="htcompare-error-modal-close">×</button><div class="htcompare-error-modal-body"></div></div></div>'); 125 var $htcompareErrorModal = $("#htcompare-error-modal"); 14 126 $('.htcompare-error-modal-close').on('click', function() { 15 127 $htcompareErrorModal.css('display', 'none'); 16 }) 128 }); 17 129 $(window).on('click', function(e) { 18 130 if(e.target == $htcompareErrorModal[0]) { 19 131 $htcompareErrorModal.css('display', 'none'); 20 132 } 21 }) 22 $('a.htcompare-btn').each(function() { 23 const $this = $(this); 24 if($this.hasClass('added')) { 25 $this.html('<span class="htcompare-btn-text">'+$this.data('added-text')+'</span>'); 26 } 27 }); 133 }); 134 135 // Sync states on DOM ready 136 syncButtonStates(); 137 syncCounter(); 138 loadCompareTable(); 28 139 29 140 // Notification Markup 30 const notificationMarkup = `<div class="htcompare-notification"> 31 <div class="htcompare-notification-text">${evercompare.option_data.success_added_notification_text}</div> 32 <span class="htcompare-notification-close">close</span> 33 </div>` 34 // Insert Notification Markup in body & notification close method if notification is enabled 141 var notificationMarkup = '<div class="htcompare-notification"><div class="htcompare-notification-text">' + evercompare.option_data.success_added_notification_text + '</div><span class="htcompare-notification-close">close</span></div>'; 35 142 if(evercompare.option_data.enable_success_notification === 'on') { 36 143 $body.append(notificationMarkup); … … 40 147 } 41 148 // Notification Show Function 42 const ShowNotification = (message) =>{149 var ShowNotification = function(message) { 43 150 if(evercompare.option_data.enable_success_notification === 'on') { 44 151 $body.find('.htcompare-notification-text').html(message); … … 47 154 setTimeout(function() { 48 155 $body.find('.htcompare-notification').removeClass('open'); 49 }, +evercompare.option_data.removed_notification_after * 1000) 50 } 51 } 52 } 156 }, +evercompare.option_data.removed_notification_after * 1000); 157 } 158 } 159 }; 53 160 54 161 // Add product in compare table … … 73 180 $this.addClass('loading'); 74 181 75 $.ajax({ 76 url: evercompare.ajaxurl, 77 data: { 78 action: 'ever_compare_add_to_compare', 79 nonce: evercompare.nonce, 80 id: id, 81 }, 82 dataType: 'json', 83 method: 'GET', 84 success: function ( response ) { 85 const $products = typeof response.products === 'array' ? response.products : Object.values(response.products); 86 if ( response.table && $products.indexOf(id.toString()) >= 0 ) { 87 updateCompareData( response ); 88 $popup.addClass('open'); 89 } else { 90 $('.htcompare-error-modal-body').html(response.limitReached) 91 $htcompareErrorModal.css('display', 'flex'); 92 console.log( 'Something wrong loading compare data' ); 93 } 94 $body.find('.htcompare-counter').html( response.count ); 95 }, 96 error: function ( data ) { 97 console.log('Something wrong with AJAX response.'); 98 }, 99 complete: function (res) { 100 $this.removeClass('loading'); 101 const $products = typeof res.responseJSON.products === 'array' ? res.responseJSON.products : Object.values(res.responseJSON.products); 102 if($products.indexOf(id.toString()) >= 0) { 103 $this.addClass('added'); 104 $this.html('<span class="htcompare-btn-text">'+addedText+'</span>'); 105 } 106 ShowNotification(success_message); 107 }, 182 getNonce().then(function(nonce) { 183 $.ajax({ 184 url: evercompare.ajaxurl, 185 data: { 186 action: 'ever_compare_add_to_compare', 187 nonce: nonce, 188 id: id, 189 }, 190 dataType: 'json', 191 method: 'GET', 192 success: function ( response ) { 193 if ( !response || !response.products ) { 194 $body.find('.htcompare-counter').html( response ? response.count : 0 ); 195 return; 196 } 197 var $products = typeof response.products === 'object' ? Object.values(response.products) : response.products; 198 var productStrings = $products.map(function(p) { return p.toString(); }); 199 if ( response.table && productStrings.indexOf(id.toString()) >= 0 ) { 200 updateCompareData( response ); 201 $popup.addClass('open'); 202 } else { 203 $('.htcompare-error-modal-body').html(response.limitReached); 204 $htcompareErrorModal.css('display', 'flex'); 205 } 206 $body.find('.htcompare-counter').html( response.count ); 207 }, 208 error: function ( data ) { 209 console.log('Something wrong with AJAX response.'); 210 }, 211 complete: function (res) { 212 $this.removeClass('loading'); 213 if (res.responseJSON && res.responseJSON.products) { 214 var $products = typeof res.responseJSON.products === 'object' ? Object.values(res.responseJSON.products) : res.responseJSON.products; 215 var productStrings = $products.map(function(p) { return p.toString(); }); 216 if(productStrings.indexOf(id.toString()) >= 0) { 217 $this.addClass('added'); 218 $this.html('<span class="htcompare-btn-text">'+addedText+'</span>'); 219 ShowNotification(success_message); 220 } 221 } 222 }, 223 }); 224 }).fail(function() { 225 $this.removeClass('loading'); 108 226 }); 109 227 … … 117 235 success_message = evercompare.option_data.success_removed_notification_text.replace('{product_name}', $this.data('product_title')); 118 236 $this.addClass('loading'); 237 getNonce().then(function(nonce) { 238 jQuery.ajax({ 239 url: evercompare.ajaxurl, 240 data: { 241 action: 'ever_compare_remove_from_compare', 242 nonce: nonce, 243 id: id, 244 }, 245 dataType: 'json', 246 method: 'GET', 247 success: function (response) { 248 if (response) { 249 $body.find('.htcompare-counter').html( response.count ); 250 } else { 251 console.log( 'Something wrong loading compare data' ); 252 } 253 }, 254 error: function (data) { 255 console.log('Something wrong with AJAX response.'); 256 }, 257 complete: function (res) { 258 $this.removeClass('loading added').html('<span class="htcompare-btn-text">'+$this.data('text')+'</span>'); 259 if (res.responseJSON && res.responseJSON.count !== undefined) { 260 ShowNotification(success_message); 261 } 262 }, 263 }); 264 }).fail(function() { 265 $this.removeClass('loading'); 266 }); 267 }); 268 } 269 270 // Remove data from compare table 271 $body.on('click', 'a.htcompare-remove', function (e) { 272 var $table = $('.htcompare-table'); 273 274 e.preventDefault(); 275 var $this = $(this), 276 id = $this.data('product_id'), 277 success_message = evercompare.option_data.success_removed_notification_text.replace('{product_name}', $this.data('product_title')); 278 279 $table.addClass('loading'); 280 $this.addClass('loading'); 281 282 getNonce().then(function(nonce) { 119 283 jQuery.ajax({ 120 284 url: evercompare.ajaxurl, 121 285 data: { 122 286 action: 'ever_compare_remove_from_compare', 123 nonce: evercompare.nonce,287 nonce: nonce, 124 288 id: id, 125 289 }, … … 127 291 method: 'GET', 128 292 success: function (response) { 129 if (response ) {130 $body.find('.htcompare-counter').html( response.count);293 if (response.table) { 294 updateCompareData(response); 131 295 } else { 132 296 console.log( 'Something wrong loading compare data' ); 133 297 } 298 $('a.htcompare-btn').each(function() { 299 if($(this).data('product_id') === id) { 300 $(this).removeClass('added'); 301 $(this).html('<span class="htcompare-btn-text">'+$(this).data('text')+'</span>'); 302 } 303 }); 304 $body.find('.htcompare-counter').html( response.count ); 134 305 }, 135 306 error: function (data) { 136 307 console.log('Something wrong with AJAX response.'); 137 308 }, 138 complete: function () { 139 $this.removeClass('loading added').html('<span class="htcompare-btn-text">'+$this.data('text')+'</span>'); 140 ShowNotification(success_message); 309 complete: function (res) { 310 $table.removeClass('loading'); 311 $this.removeClass('loading'); 312 if (res.responseJSON && res.responseJSON.table) { 313 ShowNotification(success_message); 314 } 141 315 }, 142 316 }); 143 }); 144 } 145 146 // Remove data from compare table 147 $body.on('click', 'a.htcompare-remove', function (e) { 148 var $table = $('.htcompare-table'); 149 150 e.preventDefault(); 151 var $this = $(this), 152 id = $this.data('product_id'), 153 success_message = evercompare.option_data.success_removed_notification_text.replace('{product_name}', $this.data('product_title')); 154 155 $table.addClass('loading'); 156 $this.addClass('loading'); 157 158 jQuery.ajax({ 159 url: evercompare.ajaxurl, 160 data: { 161 action: 'ever_compare_remove_from_compare', 162 nonce: evercompare.nonce, 163 id: id, 164 }, 165 dataType: 'json', 166 method: 'GET', 167 success: function (response) { 168 if (response.table) { 169 updateCompareData(response); 170 } else { 171 console.log( 'Something wrong loading compare data' ); 172 } 173 $('a.htcompare-btn').each(function() { 174 if($(this).data('product_id') === id) { 175 $(this).removeClass('added'); 176 $(this).html('<span class="htcompare-btn-text">'+$(this).data('text')+'</span>'); 177 } 178 }) 179 $body.find('.htcompare-counter').html( response.count ); 180 }, 181 error: function (data) { 182 console.log('Something wrong with AJAX response.'); 183 }, 184 complete: function () { 185 $table.removeClass('loading'); 186 $this.addClass('loading'); 187 ShowNotification(success_message); 188 }, 317 }).fail(function() { 318 $table.removeClass('loading'); 319 $this.removeClass('loading'); 189 320 }); 190 321 … … 195 326 if ( $('.htcompare-table').length > 0 ) { 196 327 $('.htcompare-table').replaceWith( data.table ); 197 $('.evercompare-copy-link').on('click',function(e){ 198 evercompareCopyToClipboard( $(this).closest('.ever-compare-shareable-link').find('.evercompare-share-link') , this ); 199 }); 328 bindShareableLinkHandler(); 200 329 } 201 330 } … … 208 337 209 338 // Copy Shareable link 210 $('.evercompare-copy-link').on('click',function(e){ 211 evercompareCopyToClipboard( $(this).closest('.ever-compare-shareable-link').find('.evercompare-share-link') , this ); 212 }); 339 bindShareableLinkHandler(); 213 340 function evercompareCopyToClipboard( element, button ) { 214 341 var $tempdata = $("<input>"); … … 218 345 $tempdata.remove(); 219 346 $(button).text( $(button).data('copytext') ); 220 setTimeout(function() { 347 setTimeout(function() { 221 348 $( button ).text( $(button).data('btntext') ); 222 349 }, 1000); -
ever-compare/trunk/assets/js/frontend.min.js
r3108021 r3483393 1 !function(t){"use strict";var o=t("body"),e=t(".htcompare-popup");o.append(`<div id="htcompare-error-modal" class="htcompare-error-modal" style="display:none"> 2 <div class="htcompare-error-modal-content"> 3 <button class="htcompare-error-modal-close">×</button> 4 <div class="htcompare-error-modal-body"></div> 5 </div> 6 </div>`);let a=t("#htcompare-error-modal");t(".htcompare-error-modal-close").on("click",function(){a.css("display","none")}),t(window).on("click",function(t){t.target==a[0]&&a.css("display","none")}),t("a.htcompare-btn").each(function(){let o=t(this);o.hasClass("added")&&o.html('<span class="htcompare-btn-text">'+o.data("added-text")+"</span>")});let n=`<div class="htcompare-notification"> 7 <div class="htcompare-notification-text">${evercompare.option_data.success_added_notification_text}</div> 8 <span class="htcompare-notification-close">close</span> 9 </div>`;"on"===evercompare.option_data.enable_success_notification&&(o.append(n),o.on("click",".htcompare-notification-close",function(){o.find(".htcompare-notification").removeClass("open")}));let c=t=>{"on"===evercompare.option_data.enable_success_notification&&(o.find(".htcompare-notification-text").html(t),o.find(".htcompare-notification").addClass("open"),+evercompare.option_data.removed_notification_after>-1&&setTimeout(function(){o.find(".htcompare-notification").removeClass("open")},1e3*+evercompare.option_data.removed_notification_after))};function i(o){t(".htcompare-table").length>0&&(t(".htcompare-table").replaceWith(o.table),t(".evercompare-copy-link").on("click",function(o){r(t(this).closest(".ever-compare-shareable-link").find(".evercompare-share-link"),this)}))}function r(o,e){var a=t("<input>");t("body").append(a),a.val(t(o).text()).select(),document.execCommand("copy"),a.remove(),t(e).text(t(e).data("copytext")),setTimeout(function(){t(e).text(t(e).data("btntext"))},1e3)}o.on("click","a.htcompare-btn",function(n){var r=t(this),d=r.data("product_id"),s=r.data("added-text"),p=evercompare.option_data.success_added_notification_text.replace("{product_name}",r.data("product_title"));if("yes"===evercompare.popup&&"off"===evercompare.option_data.remove_on_click){if(n.preventDefault(),r.hasClass("added"))return o.find(".htcompare-popup").addClass("open"),!0}else if(r.hasClass("added"))return!0;n.preventDefault(),r.addClass("loading"),t.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_add_to_compare",nonce:evercompare.nonce,id:d},dataType:"json",method:"GET",success:function(n){let c="array"==typeof n.products?n.products:Object.values(n.products);n.table&&c.indexOf(d.toString())>=0?(i(n),e.addClass("open")):(t(".htcompare-error-modal-body").html(n.limitReached),a.css("display","flex"),console.log("Something wrong loading compare data")),o.find(".htcompare-counter").html(n.count)},error:function(t){console.log("Something wrong with AJAX response.")},complete:function(t){r.removeClass("loading");let o="array"==typeof t.responseJSON.products?t.responseJSON.products:Object.values(t.responseJSON.products);o.indexOf(d.toString())>=0&&(r.addClass("added"),r.html('<span class="htcompare-btn-text">'+s+"</span>")),c(p)}})}),evercompare.option_data.remove_on_click&&"on"===evercompare.option_data.remove_on_click&&o.on("click","a.htcompare-btn.added",function(e){e.preventDefault();var a=t(this),n=a.data("product_id"),i=evercompare.option_data.success_removed_notification_text.replace("{product_name}",a.data("product_title"));a.addClass("loading"),jQuery.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_remove_from_compare",nonce:evercompare.nonce,id:n},dataType:"json",method:"GET",success:function(t){t?o.find(".htcompare-counter").html(t.count):console.log("Something wrong loading compare data")},error:function(t){console.log("Something wrong with AJAX response.")},complete:function(){a.removeClass("loading added").html('<span class="htcompare-btn-text">'+a.data("text")+"</span>"),c(i)}})}),o.on("click","a.htcompare-remove",function(e){var a=t(".htcompare-table");e.preventDefault();var n=t(this),r=n.data("product_id"),d=evercompare.option_data.success_removed_notification_text.replace("{product_name}",n.data("product_title"));a.addClass("loading"),n.addClass("loading"),jQuery.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_remove_from_compare",nonce:evercompare.nonce,id:r},dataType:"json",method:"GET",success:function(e){e.table?i(e):console.log("Something wrong loading compare data"),t("a.htcompare-btn").each(function(){t(this).data("product_id")===r&&(t(this).removeClass("added"),t(this).html('<span class="htcompare-btn-text">'+t(this).data("text")+"</span>"))}),o.find(".htcompare-counter").html(e.count)},error:function(t){console.log("Something wrong with AJAX response.")},complete:function(){a.removeClass("loading"),n.addClass("loading"),c(d)}})}),o.on("click",".htcompare-popup-close",function(o){t(this).parent(".htcompare-popup.open").removeClass("open"),e.removeClass("open")}),t(".evercompare-copy-link").on("click",function(o){r(t(this).closest(".ever-compare-shareable-link").find(".evercompare-share-link"),this)})}(jQuery); 1 !function(e){"use strict";var o=e("body"),t=e(".htcompare-popup"),a=null,n=null;function r(){for(var e=evercompare.cookie_name,o=document.cookie.split(";"),t=0;t<o.length;t++){var a=o[t].trim();if(0===a.indexOf(e+"=")){var n=decodeURIComponent(a.substring(e.length+1));try{var r=JSON.parse(n);if(Array.isArray(r))return r.map(function(e){return parseInt(e,10)}).filter(function(e){return e>0})}catch(e){}}}return[]}function c(){return a?e.Deferred().resolve(a).promise():n||(n=e.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_get_nonce"},dataType:"json",method:"GET"}).then(function(e){return a=e.nonce,n=null,a}).fail(function(){n=null}))}function i(){e(".evercompare-copy-link").on("click",function(o){var t,a,n;t=e(this).closest(".ever-compare-shareable-link").find(".evercompare-share-link"),a=this,n=e("<input>"),e("body").append(n),n.val(e(t).text()).select(),document.execCommand("copy"),n.remove(),e(a).text(e(a).data("copytext")),setTimeout(function(){e(a).text(e(a).data("btntext"))},1e3)})}o.append('<div id="htcompare-error-modal" class="htcompare-error-modal" style="display:none"><div class="htcompare-error-modal-content"><button class="htcompare-error-modal-close">×</button><div class="htcompare-error-modal-body"></div></div></div>');var s,d=e("#htcompare-error-modal");e(".htcompare-error-modal-close").on("click",function(){d.css("display","none")}),e(window).on("click",function(e){e.target==d[0]&&d.css("display","none")}),s=r(),e("a.htcompare-btn").each(function(){var o=e(this),t=parseInt(o.data("product_id"),10);s.indexOf(t)>=0&&(o.addClass("added"),o.html('<span class="htcompare-btn-text">'+o.data("added-text")+"</span>"))}),function(){var e=r();o.find(".htcompare-counter").html(e.length)}(),function(){var o=e(".htcompare-table[data-ajax-load]");if(0!==o.length){var t=r();0!==t.length?e.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_get_table",ids:t.join(",")},dataType:"json",method:"GET",success:function(t){t.table&&(o.each(function(){e(this).replaceWith(t.table)}),i())}}):e.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_get_table",ids:""},dataType:"json",method:"GET",success:function(t){void 0!==t.table&&(o.each(function(){e(this).replaceWith(t.table||'<div class="htcompare-table htcompare-empty"></div>')}),i())}})}}();var p='<div class="htcompare-notification"><div class="htcompare-notification-text">'+evercompare.option_data.success_added_notification_text+'</div><span class="htcompare-notification-close">close</span></div>';"on"===evercompare.option_data.enable_success_notification&&(o.append(p),o.on("click",".htcompare-notification-close",function(){o.find(".htcompare-notification").removeClass("open")}));var l=function(e){"on"===evercompare.option_data.enable_success_notification&&(o.find(".htcompare-notification-text").html(e),o.find(".htcompare-notification").addClass("open"),+evercompare.option_data.removed_notification_after>-1&&setTimeout(function(){o.find(".htcompare-notification").removeClass("open")},1e3*+evercompare.option_data.removed_notification_after))};function m(o){e(".htcompare-table").length>0&&(e(".htcompare-table").replaceWith(o.table),i())}o.on("click","a.htcompare-btn",function(a){var n=e(this),r=n.data("product_id"),i=n.data("added-text"),s=evercompare.option_data.success_added_notification_text.replace("{product_name}",n.data("product_title"));if("yes"===evercompare.popup&&"off"===evercompare.option_data.remove_on_click){if(a.preventDefault(),n.hasClass("added"))return o.find(".htcompare-popup").addClass("open"),!0}else if(n.hasClass("added"))return!0;a.preventDefault(),n.addClass("loading"),c().then(function(a){e.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_add_to_compare",nonce:a,id:r},dataType:"json",method:"GET",success:function(a){if(a&&a.products){var n=("object"==typeof a.products?Object.values(a.products):a.products).map(function(e){return e.toString()});a.table&&n.indexOf(r.toString())>=0?(m(a),t.addClass("open")):(e(".htcompare-error-modal-body").html(a.limitReached),d.css("display","flex")),o.find(".htcompare-counter").html(a.count)}else o.find(".htcompare-counter").html(a?a.count:0)},error:function(e){console.log("Something wrong with AJAX response.")},complete:function(e){(n.removeClass("loading"),e.responseJSON&&e.responseJSON.products)&&(("object"==typeof e.responseJSON.products?Object.values(e.responseJSON.products):e.responseJSON.products).map(function(e){return e.toString()}).indexOf(r.toString())>=0&&(n.addClass("added"),n.html('<span class="htcompare-btn-text">'+i+"</span>"),l(s)))}})}).fail(function(){n.removeClass("loading")})}),evercompare.option_data.remove_on_click&&"on"===evercompare.option_data.remove_on_click&&o.on("click","a.htcompare-btn.added",function(t){t.preventDefault();var a=e(this),n=a.data("product_id"),r=evercompare.option_data.success_removed_notification_text.replace("{product_name}",a.data("product_title"));a.addClass("loading"),c().then(function(e){jQuery.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_remove_from_compare",nonce:e,id:n},dataType:"json",method:"GET",success:function(e){e?o.find(".htcompare-counter").html(e.count):console.log("Something wrong loading compare data")},error:function(e){console.log("Something wrong with AJAX response.")},complete:function(e){a.removeClass("loading added").html('<span class="htcompare-btn-text">'+a.data("text")+"</span>"),e.responseJSON&&void 0!==e.responseJSON.count&&l(r)}})}).fail(function(){a.removeClass("loading")})}),o.on("click","a.htcompare-remove",function(t){var a=e(".htcompare-table");t.preventDefault();var n=e(this),r=n.data("product_id"),i=evercompare.option_data.success_removed_notification_text.replace("{product_name}",n.data("product_title"));a.addClass("loading"),n.addClass("loading"),c().then(function(t){jQuery.ajax({url:evercompare.ajaxurl,data:{action:"ever_compare_remove_from_compare",nonce:t,id:r},dataType:"json",method:"GET",success:function(t){t.table?m(t):console.log("Something wrong loading compare data"),e("a.htcompare-btn").each(function(){e(this).data("product_id")===r&&(e(this).removeClass("added"),e(this).html('<span class="htcompare-btn-text">'+e(this).data("text")+"</span>"))}),o.find(".htcompare-counter").html(t.count)},error:function(e){console.log("Something wrong with AJAX response.")},complete:function(e){a.removeClass("loading"),n.removeClass("loading"),e.responseJSON&&e.responseJSON.table&&l(i)}})}).fail(function(){a.removeClass("loading"),n.removeClass("loading")})}),o.on("click",".htcompare-popup-close",function(o){e(this).parent(".htcompare-popup.open").removeClass("open"),t.removeClass("open")}),i()}(jQuery); -
ever-compare/trunk/ever-compare.php
r3331136 r3483393 6 6 * Author: HasTheme 7 7 * Author URI: https://hasthemes.com/ 8 * Version: 1.3. 48 * Version: 1.3.5 9 9 * License: GPL2 or later 10 10 * License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 26 26 * @var string 27 27 */ 28 const version = '1.3. 4';28 const version = '1.3.5'; 29 29 30 30 /** … … 58 58 add_action( 'plugins_loaded', [ $this, 'init_plugin' ] ); 59 59 60 // Compatible With WooCommerce Custom Order Tables60 // Compatible With WooCommerce Features 61 61 add_action( 'before_woocommerce_init', function() { 62 62 if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) { 63 63 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', EVERCOMPARE_FILE, true ); 64 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', EVERCOMPARE_FILE, true ); 65 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'product_block_editor', EVERCOMPARE_FILE, true ); 64 66 } 65 67 } ); … … 107 109 EverCompare\Assets::instance(); 108 110 109 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {110 EverCompare\Ajax::instance();111 }112 113 111 if ( is_admin() ) { 114 112 $this->admin_notices(); 115 113 EverCompare\Admin::instance(); 116 114 } 115 116 if ( ! ever_compare_woocommerce_installed() ) { 117 return; 118 } 119 120 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { 121 EverCompare\Ajax::instance(); 122 } 123 117 124 EverCompare\Frontend::instance(); 118 125 -
ever-compare/trunk/includes/classes/Admin/Settings_APi.php
r3314387 r3483393 27 27 * Enqueue scripts and styles 28 28 */ 29 function admin_enqueue_scripts() { 29 function admin_enqueue_scripts( $hook ) { 30 if ( false === strpos( $hook, 'evercompare' ) ) { 31 return; 32 } 30 33 wp_enqueue_style( 'wp-color-picker' ); 31 34 wp_enqueue_media(); -
ever-compare/trunk/includes/classes/Ajax.php
r3144815 r3483393 36 36 add_action( 'wp_ajax_nopriv_ever_compare_remove_from_compare', [ $this,'remove_from_compare' ] ); 37 37 38 // Get Nonce endpoint (no nonce verification needed) 39 add_action( 'wp_ajax_ever_compare_get_nonce', [ $this, 'get_nonce' ] ); 40 add_action( 'wp_ajax_nopriv_ever_compare_get_nonce', [ $this, 'get_nonce' ] ); 41 42 // Get Table endpoint 43 add_action( 'wp_ajax_ever_compare_get_table', [ $this, 'get_table' ] ); 44 add_action( 'wp_ajax_nopriv_ever_compare_get_table', [ $this, 'get_table' ] ); 45 38 46 } 39 47 … … 44 52 check_ajax_referer('ever_compare_nonce', 'nonce'); 45 53 if(!empty($_GET['id'])) { 46 $id = sanitize_text_field( wp_unslash($_GET['id']));54 $id = absint( $_GET['id'] ); 47 55 \EverCompare\Frontend\Manage_Compare::instance()->add_to_compare( $id ); 48 56 } … … 56 64 check_ajax_referer('ever_compare_nonce', 'nonce'); 57 65 if(!empty($_GET['id'])) { 58 $id = sanitize_text_field( wp_unslash($_GET['id']));66 $id = absint( $_GET['id'] ); 59 67 \EverCompare\Frontend\Manage_Compare::instance()->remove_from_compare( $id ); 60 68 } 61 69 } 62 70 71 /** 72 * [get_nonce] Return a fresh nonce for AJAX operations 73 * @return [void] 74 */ 75 public function get_nonce(){ 76 wp_send_json( array( 77 'nonce' => wp_create_nonce( 'ever_compare_nonce' ), 78 ) ); 79 } 80 81 /** 82 * [get_table] Return compare table HTML for given product IDs 83 * @return [void] 84 */ 85 public function get_table(){ 86 $ids = array(); 87 if ( ! empty( $_GET['ids'] ) ) { 88 $raw_ids = sanitize_text_field( wp_unslash( $_GET['ids'] ) ); 89 $ids = array_filter( array_map( 'absint', explode( ',', $raw_ids ) ) ); 90 $ids = array_slice( $ids, 0, \EverCompare\Frontend\Manage_Compare::instance()->max_limit ); 91 } 92 93 if ( empty( $ids ) ) { 94 wp_send_json( array( 95 'table' => '', 96 'count' => 0, 97 ) ); 98 } 99 100 $cookie_name = \EverCompare\Frontend\Manage_Compare::instance()->get_cookie_name(); 101 $_COOKIE[ $cookie_name ] = wp_json_encode( $ids ); 102 103 ob_start(); 104 \EverCompare\Frontend\Manage_Compare::instance()->get_response_html(); 105 $table_html = ob_get_clean(); 106 107 wp_send_json( array( 108 'table' => $table_html, 109 'count' => count( $ids ), 110 'products' => $ids, 111 ) ); 112 } 113 63 114 } -
ever-compare/trunk/includes/classes/Assets.php
r3108021 r3483393 116 116 'removed_notification_after' => ever_compare_get_option( 'removed_notification_after', 'ever_compare_settings_general', -1 ), 117 117 ); 118 $cookie_name = 'ever_compare_compare_list'; 119 if ( is_multisite() ) { 120 $cookie_name .= '_' . get_current_blog_id(); 121 } 118 122 $localize_data = array( 119 'ajaxurl' => admin_url( 'admin-ajax.php' ), 120 'nonce' => wp_create_nonce('ever_compare_nonce'), 121 'popup' => ( ever_compare_get_option( 'open_popup', 'ever_compare_settings_tabs', 'on' ) === 'on' ) ? 'yes' : 'no', 122 'option_data' => $option_data, 123 'ajaxurl' => admin_url( 'admin-ajax.php' ), 124 'cookie_name' => $cookie_name, 125 'compare_page_url' => esc_url( get_permalink( ever_compare_get_option( 'compare_page', 'ever_compare_table_settings_tabs' ) ) ), 126 'popup' => ( ever_compare_get_option( 'open_popup', 'ever_compare_settings_tabs', 'on' ) === 'on' ) ? 'yes' : 'no', 127 'option_data' => $option_data, 123 128 ); 124 129 -
ever-compare/trunk/includes/classes/Frontend/Manage_Compare.php
r3314387 r3483393 126 126 } 127 127 128 /**129 * Manage maximum product added message130 */131 if( isset( $_COOKIE[ 'ever_compare_max_limit' ] ) && $_COOKIE[ 'ever_compare_max_limit' ] == 'yes' ) {132 setcookie( 'ever_compare_max_limit', 'no', 0, COOKIEPATH, COOKIE_DOMAIN, false, false );133 $this->reached_max_limit = true;134 }135 128 136 129 … … 171 164 */ 172 165 public function pop_up_html(){ 173 echo '<div class="htcompare-popup"><div class="htcompare-popup-content-area"><span class="htcompare-popup-close"> </span> '.do_shortcode( '[evercompare_table]' ).'</div></div>';166 echo '<div class="htcompare-popup"><div class="htcompare-popup-content-area"><span class="htcompare-popup-close"> </span><div class="htcompare-table" data-ajax-load="true"></div></div></div>'; 174 167 } 175 168 … … 201 194 $ids = $this->get_compared_products(); 202 195 203 if ( isset( $_GET['evcompare'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended196 if ( ! empty( $_GET['evcompare'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended 204 197 $query_perametter_ids = sanitize_text_field( wp_unslash($_GET['evcompare']) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended 205 198 if( !empty( $query_perametter_ids ) ){ 206 $ids = explode( ',', $query_perametter_ids);199 $ids = array_filter( array_map( 'absint', explode( ',', $query_perametter_ids ) ) ); 207 200 } 208 201 } … … 238 231 // Reached Maximum Limit 239 232 if( $this->reached_max_limit() ) { 240 setcookie( 'ever_compare_max_limit', 'yes', 0, COOKIEPATH, COOKIE_DOMAIN, false, false );241 233 $this->compare_json_response(); 242 234 } … … 289 281 } 290 282 } 283 284 $products = array_values( $products ); 291 285 292 286 if ( empty( $products ) ) { … … 338 332 // For shareable link 339 333 $shareable_link = ever_compare_get_option('enable_shareable_link','ever_compare_table_settings_tabs','off'); 340 if ( ( $shareable_link === 'on' ) && isset( $_GET['evcompare'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended334 if ( ( $shareable_link === 'on' ) && ! empty( $_GET['evcompare'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended 341 335 $query_perametter_ids = sanitize_text_field( wp_unslash($_GET['evcompare']) ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended 342 336 if( !empty( $query_perametter_ids ) ){ 343 $ids = explode( ',', $query_perametter_ids);337 $ids = array_filter( array_map( 'absint', explode( ',', $query_perametter_ids ) ) ); 344 338 } 345 339 } … … 606 600 public function is_product_in_compare( $id ) { 607 601 $list = $this->get_compared_products(); 608 return in_array( strval($id), $list, true );602 return in_array( absint($id), $list, true ); 609 603 } 610 604 … … 616 610 $cookie_name = $this->get_cookie_name(); 617 611 if(!empty( $_COOKIE[ $cookie_name ] )) { 618 return json_decode( sanitize_text_field(wp_unslash( $_COOKIE[ $cookie_name ] )), true ); 612 $decoded = json_decode( sanitize_text_field(wp_unslash( $_COOKIE[ $cookie_name ] )), true ); 613 if ( is_array( $decoded ) ) { 614 return array_filter( array_map( 'absint', $decoded ) ); 615 } 619 616 } 620 617 return []; -
ever-compare/trunk/includes/classes/Frontend/Shortcode.php
r3041668 r3483393 89 89 } else { 90 90 $button_added_text = '<span class="evercompare-btn-text">'.$button_remove_text.'</span>'; 91 }92 93 if(\EverCompare\Frontend\Manage_Compare::instance()->is_product_in_compare( $product_id )) {94 $button_class[] = 'added';95 91 } 96 92 … … 118 114 */ 119 115 public function table_shortcode( $atts, $content = '' ){ 120 116 121 117 wp_enqueue_style( 'evercompare-frontend' ); 122 118 wp_enqueue_script( 'evercompare-frontend' ); 123 119 124 /* Fetch From option data */ 125 $empty_compare_text = ever_compare_get_option('empty_table_text','ever_compare_table_settings_tabs'); 126 $return_shop_button = ever_compare_get_option('shop_button_text','ever_compare_table_settings_tabs','Return to shop'); 127 128 /* Product and Field */ 129 $products = Manage_Compare::instance()->get_compared_products_data(); 130 $fields = Manage_Compare::instance()->get_compare_fields(); 131 132 $custom_heading = !empty( ever_compare_get_option( 'table_heading', 'ever_compare_table_settings_tabs' ) ) ? ever_compare_get_option( 'table_heading', 'ever_compare_table_settings_tabs' ) : array(); 133 134 $default_atts = array( 135 'evercompare' => Manage_Compare::instance(), 136 'products' => $products, 137 'fields' => $fields, 138 'return_shop_button'=> $return_shop_button, 139 'heading_txt' => $custom_heading, 140 'empty_compare_text'=> $empty_compare_text, 141 ); 142 143 $atts = shortcode_atts( $default_atts, $atts, $content ); 144 return Manage_Compare::instance()->table_html( $atts ); 120 // Shareable link via query param — render server-side (not cached due to query param) 121 if ( ! empty( $_GET['evcompare'] ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended 122 /* Fetch From option data */ 123 $empty_compare_text = ever_compare_get_option('empty_table_text','ever_compare_table_settings_tabs'); 124 $return_shop_button = ever_compare_get_option('shop_button_text','ever_compare_table_settings_tabs','Return to shop'); 125 126 /* Product and Field */ 127 $products = Manage_Compare::instance()->get_compared_products_data(); 128 $fields = Manage_Compare::instance()->get_compare_fields(); 129 130 $custom_heading = !empty( ever_compare_get_option( 'table_heading', 'ever_compare_table_settings_tabs' ) ) ? ever_compare_get_option( 'table_heading', 'ever_compare_table_settings_tabs' ) : array(); 131 132 $default_atts = array( 133 'evercompare' => Manage_Compare::instance(), 134 'products' => $products, 135 'fields' => $fields, 136 'return_shop_button'=> $return_shop_button, 137 'heading_txt' => $custom_heading, 138 'empty_compare_text'=> $empty_compare_text, 139 ); 140 141 $atts = shortcode_atts( $default_atts, $atts, $content ); 142 return Manage_Compare::instance()->table_html( $atts ); 143 } 144 145 // Cookie-based: render placeholder that JS will populate via AJAX 146 return '<div class="htcompare-table" data-ajax-load="true"></div>'; 145 147 146 148 } … … 159 161 160 162 $default_atts = array( 161 'count' => count(Manage_Compare::instance()->get_compared_products()),163 'count' => 0, 162 164 'page_url' => Manage_Compare::instance()->get_compare_page_url(), 163 165 ); -
ever-compare/trunk/includes/helper-functions.php
r3108021 r3483393 21 21 function ever_compare_update_option( $section, $option_key, $new_value ){ 22 22 $options_data = get_option( $section ); 23 if( isset( $options_data[$option_key] ) ){ 24 $options_data[$option_key] = $new_value; 25 }else{ 26 $options_data = array( $option_key => $new_value ); 27 } 23 if ( ! is_array( $options_data ) ) { 24 $options_data = array(); 25 } 26 $options_data[ $option_key ] = $new_value; 28 27 update_option( $section, $options_data ); 29 28 } … … 44 43 $options = array(); 45 44 $options['0'] = __('Select','ever-compare'); 46 $perpage = -1;45 $perpage = 200; 47 46 $all_post = array( 'posts_per_page' => $perpage, 'post_type'=> $post_type ); 48 47 $post_terms = get_posts( $all_post ); … … 88 87 89 88 if ( $args && is_array( $args ) ) { 90 extract( $args ); 89 $evercompare_args = $args; 90 // Backward compat: if template is overridden in theme, extract for legacy support 91 $default_path = EVERCOMPARE_PATH . '/includes/templates/' . $tmp_name; 92 if ( $located !== $default_path ) { 93 extract( $args, EXTR_SKIP ); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract 94 } 91 95 } 92 96 -
ever-compare/trunk/includes/templates/evercompare-button-add.php
r3108021 r3483393 1 <span class="htcompare-button-area"><a href="<?php echo esc_url( $ button_url ); ?>" class="<?php echo esc_attr($button_class); ?>" data-text="<?php echo esc_attr( $button_text ); ?>" data-added-text="<?php echo esc_attr( $button_added_text); ?>" data-product_id="<?php echo esc_attr( $product_id ); ?>" data-product_title="<?php echo esc_attr( $product_title ); ?>" ><?php echo wp_kses($button_text, get_allowed_tags_for_svg()); ?></a></span>1 <span class="htcompare-button-area"><a href="<?php echo esc_url( $evercompare_args['button_url'] ); ?>" class="<?php echo esc_attr($evercompare_args['button_class']); ?>" data-text="<?php echo esc_attr( $evercompare_args['button_text'] ); ?>" data-added-text="<?php echo esc_attr( $evercompare_args['button_added_text']); ?>" data-product_id="<?php echo esc_attr( $evercompare_args['product_id'] ); ?>" data-product_title="<?php echo esc_attr( $evercompare_args['product_title'] ); ?>" ><?php echo wp_kses($evercompare_args['button_text'], get_allowed_tags_for_svg()); ?></a></span> -
ever-compare/trunk/includes/templates/evercompare-count.php
r2927305 r3483393 1 <a href="<?php echo esc_url( $ page_url);?>" class="htcompare-counter-area">1 <a href="<?php echo esc_url( $evercompare_args['page_url'] );?>" class="htcompare-counter-area"> 2 2 <span class="htcompare-counter-icon"> 3 3 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 471.701 471.701" height="20px" width="20px" > … … 6 6 </span> 7 7 <?php 8 echo '<span class="htcompare-counter">'.esc_html( $ count).'</span>';8 echo '<span class="htcompare-counter">'.esc_html( $evercompare_args['count'] ).'</span>'; 9 9 ?> 10 10 </a> -
ever-compare/trunk/includes/templates/evercompare-table.php
r3108021 r3483393 3 3 // do_action( 'ever_compare_before_table' ); 4 4 5 if ( ! empty( $products ) ) { 5 if ( ! empty( $evercompare_args['products'] ) ) { 6 $products = $evercompare_args['products']; 6 7 array_unshift( $products, array() ); 7 foreach ( $ fieldsas $field_id => $field ) {8 if ( ! $evercompare ->is_products_have_field( $field_id, $products ) ) {8 foreach ( $evercompare_args['fields'] as $field_id => $field ) { 9 if ( ! $evercompare_args['evercompare']->is_products_have_field( $field_id, $products ) ) { 9 10 continue; 10 11 } 11 12 12 13 // Generate Filed name 13 $name = $evercompare ->field_name( $field );14 if( array_key_exists( $field_id, $ heading_txt ) && !empty( $heading_txt[$field_id] ) ){15 $name = $evercompare ->field_name( $heading_txt[$field_id], true );14 $name = $evercompare_args['evercompare']->field_name( $field ); 15 if( array_key_exists( $field_id, $evercompare_args['heading_txt'] ) && !empty( $evercompare_args['heading_txt'][$field_id] ) ){ 16 $name = $evercompare_args['evercompare']->field_name( $evercompare_args['heading_txt'][$field_id], true ); 16 17 } 17 18 … … 21 22 <?php if ( ! empty( $product ) ) : ?> 22 23 <div class="htcompare-col htcolumn-value" data-title="<?php echo esc_attr( $name ); ?>"> 23 <?php $evercompare ->compare_display_field( $field_id, $product ); ?>24 <?php $evercompare_args['evercompare']->compare_display_field( $field_id, $product ); ?> 24 25 </div> 25 26 <?php else: ?> … … 32 33 <?php 33 34 } 34 echo '<div class="htcompare-table-loader"></div>'; 35 echo '<div class="htcompare-table-loader"></div>'; 35 36 } else { 36 if ( $e mpty_compare_text){37 echo '<div class="htcompare-empty-page-text">'.wp_kses_post( $e mpty_compare_text).'</div>';37 if ( $evercompare_args['empty_compare_text'] ){ 38 echo '<div class="htcompare-empty-page-text">'.wp_kses_post( $evercompare_args['empty_compare_text'] ).'</div>'; 38 39 } 39 40 40 if( $ return_shop_button){41 echo '<div class="htcompare-return-to-shop"><a href="'.esc_url( wc_get_page_permalink( 'shop' ) ).'" class="button">'.esc_html( $ return_shop_button).'</a></div>';41 if( $evercompare_args['return_shop_button'] ){ 42 echo '<div class="htcompare-return-to-shop"><a href="'.esc_url( wc_get_page_permalink( 'shop' ) ).'" class="button">'.esc_html( $evercompare_args['return_shop_button'] ).'</a></div>'; 42 43 } 43 44 } -
ever-compare/trunk/readme.txt
r3407749 r3483393 4 4 Requires at least: 5.0 5 5 Tested up to: 6.9 6 Stable tag: 1.3. 46 Stable tag: 1.3.5 7 7 License: GPLv2 or later 8 8 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 90 90 91 91 == Changelog == 92 93 = Version: 1.3.5 - Date: 2026-03-16 = 94 * Fixed: Empty evcompare query parameter no longer generates broken shareable links. 95 * Improved: Cache compatibility for compare page using cookie-based AJAX loading. 92 96 93 97 = Version: 1.3.4 - Date: 2025-07-21 =
Note: See TracChangeset
for help on using the changeset viewer.