PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.76
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.76
51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 51.1.47 51.1.49 All 37 releases
king-addons / includes / extensions / Image_Optimizer / assets / optimizer.js

optimizer.js in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.76, at includes/extensions/Image_Optimizer/assets/optimizer.js

161 lines 5.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * King Addons - Image Optimizer Core
3 *
4 * Browser-based image conversion using Canvas API (WebP only).
5 *
6 * @package King_Addons
7 */
8
9 (function($) {
10 'use strict';
11
12 // Check if kingImageOptimizer is defined
13 if (typeof kingImageOptimizer === 'undefined') {
14 console.error('King Image Optimizer: Configuration not found');
15 return;
16 }
17
18 /**
19 * King Image Optimizer Class
20 */
21 class KingImageOptimizer {
22 constructor(config) {
23 this.config = config;
24 this.settings = config.settings || {};
25 this.strings = config.strings || {};
26 }
27
28 /**
29 * Initialize the optimizer
30 */
31 init() {
32 // no-op (canvas-only)
33 }
34
35 /**
36 * Optimize an image
37 *
38 * @param {Object} imageData - Image data object
39 * @param {Object} options - Optimization options
40 * @returns {Promise<Object>} - Optimized image result
41 */
42 async optimize(imageData, options = {}) {
43 const defaults = {
44 quality: this.settings.quality || 82,
45 resize: this.settings.resize_enabled || false,
46 maxWidth: this.settings.max_width || 2048
47 };
48
49 const opts = { ...defaults, ...options };
50
51 // Canvas-only WebP conversion
52 return this.optimizeWithCanvas(imageData, opts);
53 }
54
55 /**
56 * Optimize using Canvas API (FREE)
57 */
58 async optimizeWithCanvas(imageData, options) {
59 return new Promise((resolve, reject) => {
60 const img = new Image();
61 img.crossOrigin = 'anonymous';
62
63 img.onload = () => {
64 try {
65 let { width, height } = img;
66
67 // Resize if needed
68 if (options.resize && width > options.maxWidth) {
69 const ratio = options.maxWidth / width;
70 width = options.maxWidth;
71 height = Math.round(height * ratio);
72 }
73
74 // Create canvas
75 const canvas = document.createElement('canvas');
76 canvas.width = width;
77 canvas.height = height;
78
79 const ctx = canvas.getContext('2d');
80 ctx.drawImage(img, 0, 0, width, height);
81
82 // WebP output only
83 const mimeType = 'image/webp';
84 const extension = 'webp';
85
86 // Convert quality to 0-1 range
87 const quality = options.quality / 100;
88
89 // Export to data URL
90 const dataUrl = canvas.toDataURL(mimeType, quality);
91
92 // Calculate sizes
93 const base64Data = dataUrl.split(',')[1];
94 const optimizedSize = Math.round(base64Data.length * 0.75); // Approximate binary size
95 const originalSize = imageData.filesize || 0;
96 const savedBytes = Math.max(0, originalSize - optimizedSize);
97
98 resolve({
99 success: true,
100 data: dataUrl,
101 originalSize: originalSize,
102 optimizedSize: optimizedSize,
103 savedBytes: savedBytes,
104 savingsPercent: originalSize > 0 ? Math.round((savedBytes / originalSize) * 100) : 0,
105 format: extension,
106 width: width,
107 height: height,
108 method: 'canvas'
109 });
110
111 } catch (error) {
112 reject({
113 success: false,
114 error: error.message
115 });
116 }
117 };
118
119 img.onerror = () => {
120 reject({
121 success: false,
122 error: 'Failed to load image'
123 });
124 };
125
126 // Load image from URL
127 if (imageData.url) {
128 img.src = imageData.url;
129 } else if (imageData.data) {
130 img.src = imageData.data;
131 } else {
132 reject({
133 success: false,
134 error: 'No image source provided'
135 });
136 }
137 });
138 }
139
140 /**
141 * Format bytes to human readable
142 */
143 static formatBytes(bytes, decimals = 2) {
144 if (bytes === 0) return '0 B';
145
146 const k = 1024;
147 const dm = decimals < 0 ? 0 : decimals;
148 const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
149 const i = Math.floor(Math.log(bytes) / Math.log(k));
150
151 return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
152 }
153 }
154
155 // Initialize and export
156 window.KingImageOptimizer = KingImageOptimizer;
157 window.kingOptimizer = new KingImageOptimizer(kingImageOptimizer);
158 window.kingOptimizer.init();
159
160 })(jQuery);
161