| 1 |
(function(){ |
| 2 |
; |
| 3 |
(function($) { |
| 4 |
"use strict"; |
| 5 |
var JLTMA_ImageOptimizerBase = { |
| 6 |
settings: {}, |
| 7 |
i18n: {}, |
| 8 |
isPremium: false, |
| 9 |
/** |
| 10 |
* Initialize base module |
| 11 |
*/ |
| 12 |
init: function() { |
| 13 |
var config = typeof jltmaImageOptimizerBase !== "undefined" ? jltmaImageOptimizerBase : {}; |
| 14 |
this.settings = config.settings || {}; |
| 15 |
this.i18n = config.i18n || {}; |
| 16 |
this.isPremium = config.isPremium || false; |
| 17 |
this.initMediaLibraryDisplay(); |
| 18 |
this.initTooltips(); |
| 19 |
}, |
| 20 |
/** |
| 21 |
* Initialize media library display |
| 22 |
* Sets up observation for attachment panels |
| 23 |
*/ |
| 24 |
initMediaLibraryDisplay: function() { |
| 25 |
var self = this; |
| 26 |
self.observeMediaLibrary(); |
| 27 |
}, |
| 28 |
/** |
| 29 |
* Initialize tooltips using event delegation (works in all contexts) |
| 30 |
*/ |
| 31 |
initTooltips: function() { |
| 32 |
$(document).on("mouseenter", ".jltma-tooltip", function() { |
| 33 |
var $tooltipText = $(this).find(".jltma-tooltip-text"); |
| 34 |
$tooltipText.css({ |
| 35 |
"visibility": "visible", |
| 36 |
"opacity": "1" |
| 37 |
}); |
| 38 |
}).on("mouseleave", ".jltma-tooltip", function() { |
| 39 |
var $tooltipText = $(this).find(".jltma-tooltip-text"); |
| 40 |
$tooltipText.css({ |
| 41 |
"visibility": "hidden", |
| 42 |
"opacity": "0" |
| 43 |
}); |
| 44 |
}); |
| 45 |
}, |
| 46 |
/** |
| 47 |
* Observe media library for DOM changes |
| 48 |
*/ |
| 49 |
observeMediaLibrary: function() { |
| 50 |
var self = this; |
| 51 |
self.customizeAllOriginalLinks(); |
| 52 |
var observer = new MutationObserver(function(mutations) { |
| 53 |
self.customizeAllOriginalLinks(); |
| 54 |
}); |
| 55 |
observer.observe(document.body, { |
| 56 |
childList: true, |
| 57 |
subtree: true |
| 58 |
}); |
| 59 |
}, |
| 60 |
/** |
| 61 |
* Customize "Original image" links in media modal |
| 62 |
*/ |
| 63 |
customizeAllOriginalLinks: function() { |
| 64 |
$("p, span, div").each(function() { |
| 65 |
var $el = $(this); |
| 66 |
if ($el.data("jltma-original-processed")) return; |
| 67 |
var directText = $el.contents().filter(function() { |
| 68 |
return this.nodeType === 3; |
| 69 |
}).text(); |
| 70 |
if (directText.indexOf("Original image") === -1) return; |
| 71 |
var $link = $el.find("a").first(); |
| 72 |
if (!$link.length) return; |
| 73 |
$el.data("jltma-original-processed", true); |
| 74 |
$link.text("View Original").attr("target", "_blank"); |
| 75 |
var $editImage = $el.siblings().filter(function() { |
| 76 |
return $(this).text().trim() === "Edit Image" || $(this).hasClass("edit-attachment"); |
| 77 |
}).first(); |
| 78 |
if ($editImage.length) { |
| 79 |
$el.remove(); |
| 80 |
$editImage.after('<span class="jltma-separator"> | </span>'); |
| 81 |
$editImage.next(".jltma-separator").after($link); |
| 82 |
} |
| 83 |
}); |
| 84 |
}, |
| 85 |
/** |
| 86 |
* Format file size for display |
| 87 |
*/ |
| 88 |
formatFileSize: function(bytes) { |
| 89 |
if (!bytes || bytes === 0) return "0 B"; |
| 90 |
var k = 1024; |
| 91 |
var sizes = ["B", "KB", "MB", "GB"]; |
| 92 |
var i = Math.floor(Math.log(bytes) / Math.log(k)); |
| 93 |
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i]; |
| 94 |
}, |
| 95 |
/** |
| 96 |
* Build upsell card HTML (for free version) |
| 97 |
* Shows potential savings with upgrade prompt |
| 98 |
*/ |
| 99 |
buildUpsellCardHTML: function(data) { |
| 100 |
var savingsPercent = data.savingsPercent || 70; |
| 101 |
var originalSize = data.originalSize || 0; |
| 102 |
var potentialSize = Math.round(originalSize * (1 - savingsPercent / 100)); |
| 103 |
var pricingUrl = data.pricingUrl || "https://master-addons.com/pricing/"; |
| 104 |
var html = '<div class="jltma-optimization-card jltma-upsell-card" style="display: block; margin: 8px 0; padding: 10px 12px; background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); border: 1px solid #fbbf24; border-radius: 8px; font-family: -apple-system, BlinkMacSystemFont, sans-serif;">'; |
| 105 |
if (originalSize > 0) { |
| 106 |
html += '<div style="display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 12px; color: #92400e;">'; |
| 107 |
html += '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" style="flex-shrink: 0;"><circle cx="12" cy="12" r="10" stroke="#d97706" stroke-width="2"/><path d="M12 6v6l4 2" stroke="#d97706" stroke-width="2" stroke-linecap="round"/></svg>'; |
| 108 |
html += '<span style="font-weight: 600;">Save ~' + savingsPercent + "%</span>"; |
| 109 |
html += '<span style="color: #b45309;">(' + this.formatFileSize(originalSize) + " → ~" + this.formatFileSize(potentialSize) + ")</span>"; |
| 110 |
html += "</div>"; |
| 111 |
} else { |
| 112 |
html += '<div style="font-size: 12px; color: #92400e; font-weight: 600;">'; |
| 113 |
html += "Auto-optimize images on upload"; |
| 114 |
html += "</div>"; |
| 115 |
} |
| 116 |
html += '<a href="' + pricingUrl + '" target="_blank" style="display: inline-flex; align-items: center; gap: 4px; margin-top: 6px; font-size: 11px; font-weight: 600; color: #d97706; text-decoration: none;">'; |
| 117 |
html += '<span class="dashicons dashicons-star-filled" style="font-size: 12px; width: 12px; height: 12px;"></span>'; |
| 118 |
html += "Upgrade to Pro"; |
| 119 |
html += "</a>"; |
| 120 |
html += "</div>"; |
| 121 |
return html; |
| 122 |
}, |
| 123 |
/** |
| 124 |
* Build optimized card HTML (compact version - matches screenshot) |
| 125 |
*/ |
| 126 |
buildOptimizedCardHTML: function(data) { |
| 127 |
var timeDisplay = ""; |
| 128 |
if (data.processingTime) { |
| 129 |
timeDisplay = data.processingTime >= 1e3 ? (data.processingTime / 1e3).toFixed(1) + " sec" : data.processingTime + " ms"; |
| 130 |
} |
| 131 |
var outputFormat = (data.outputFormat || "webp").toUpperCase(); |
| 132 |
var percentage = data.percentage || 0; |
| 133 |
var html = '<div class="jltma-optimization-card" style="display: block; clear: both; margin: 16px 0;">'; |
| 134 |
html += '<div style="display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; color: #1e1e1e; margin-bottom: 8px;">'; |
| 135 |
html += "<span>MA Optimization</span>"; |
| 136 |
html += '<span class="jltma-tooltip" style="position: relative; display: inline-flex; align-items: center; vertical-align: middle; margin-left: 2px;"><span class="dashicons dashicons-info-outline" style="font-size: 16px; width: 16px; height: 16px; color: #9ca3af; cursor: help; vertical-align: middle;"></span><span class="jltma-tooltip-text" style="visibility: hidden; opacity: 0; position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%); background: #1e1e1e; color: #fff; padding: 6px 10px; border-radius: 4px; font-size: 12px; font-weight: 400; white-space: nowrap; z-index: 9999999; transition: opacity 0.2s; pointer-events: none;">Optimized by Master Addons</span></span>'; |
| 137 |
html += "</div>"; |
| 138 |
html += '<div class="jltma-optimized-card" style="padding: 16px 20px; background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; font-family: -apple-system, BlinkMacSystemFont, sans-serif; text-align: center;">'; |
| 139 |
html += '<div style="display: flex; align-items: center; justify-content: center; gap: 8px; margin-bottom: 8px; white-space: nowrap;">'; |
| 140 |
html += '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" style="flex-shrink: 0;"><circle cx="12" cy="12" r="11" fill="#22c55e"/><path d="M8 12l3 3 5-6" stroke="#fff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg>'; |
| 141 |
html += '<span style="font-weight: 700; color: #16a34a; font-size: 16px;">Saved ' + percentage + "%</span>"; |
| 142 |
html += "</div>"; |
| 143 |
html += '<div style="margin-bottom: 6px; white-space: nowrap;">'; |
| 144 |
html += '<span style="color: #374151; font-size: 13px;">(' + data.originalFormatted + " → " + data.optimizedFormatted + ")</span>"; |
| 145 |
html += "</div>"; |
| 146 |
var metaParts = ["→ " + outputFormat]; |
| 147 |
if (timeDisplay) { |
| 148 |
metaParts.push(timeDisplay); |
| 149 |
} |
| 150 |
html += '<div style="font-size: 12px; color: #16a34a; white-space: nowrap;">' + metaParts.join(" · ") + "</div>"; |
| 151 |
html += "</div>"; |
| 152 |
html += "</div>"; |
| 153 |
return html; |
| 154 |
} |
| 155 |
}; |
| 156 |
window.JLTMA_ImageOptimizerBase = JLTMA_ImageOptimizerBase; |
| 157 |
$(document).ready(function() { |
| 158 |
JLTMA_ImageOptimizerBase.init(); |
| 159 |
}); |
| 160 |
})(jQuery); |
| 161 |
})(); |
| 162 |
|