PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.83
51.1.84 51.1.85 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 All 39 releases
← All changes | includes/widgets/Charts/script.js +415 -0 51.1.251.1.83 View file →
@@ -1,0 +1,415 @@
1 +// noinspection JSUnresolvedReference
2 +
3 +"use strict";
4 +(function ($) {
5 + $(window).on("elementor/frontend/init", function () {
6 + elementorFrontend.hooks.addAction(
7 + "frontend/element_ready/king-addons-charts.default",
8 + function ($scope) {
9 + const BaseHandler = elementorModules.frontend.handlers.Base.extend({
10 + onInit() {
11 + const $container = this.$element.find(".king-addons-charts-container");
12 + const chartSettings = JSON.parse($container.attr("data-settings"));
13 + const labels = chartSettings.chart_labels;
14 + const customDatasets = chartSettings.chart_datasets
15 + ? JSON.parse(chartSettings.chart_datasets)
16 + : "";
17 +
18 + // Helper for common grid/ticks setup
19 + const axisConfig = (axis, gridColor, lineWidth, dashed = false) => ({
20 + display: chartSettings[`display_${axis}_axis`],
21 + drawBorder: chartSettings[`display_${axis}_axis`],
22 + drawOnChartArea: chartSettings[`display_${axis}_axis`],
23 + drawTicks: chartSettings[`display_${axis}_axis`],
24 + color: gridColor,
25 + borderDash: dashed
26 + ? [chartSettings[`border_dash_length_${axis[0]}`], chartSettings[`border_dash_spacing_${axis[0]}`]]
27 + : undefined,
28 + borderDashOffset: dashed
29 + ? chartSettings[`border_dash_offset_${axis[0]}`]
30 + : undefined,
31 + lineWidth: lineWidth,
32 + });
33 +
34 + // Reusable tick/font setup
35 + const tickConfig = (axis) => ({
36 + stepSize: chartSettings[`${axis}_step_size`],
37 + display: chartSettings[`display_${axis}_ticks`],
38 + padding: chartSettings[`ticks_padding_${axis}`],
39 + autoSkip: false,
40 + maxRotation: chartSettings[`rotation_${axis}`],
41 + minRotation: chartSettings[`rotation_${axis}`],
42 + color: chartSettings[`ticks_color_${axis}`],
43 + font: {
44 + size: chartSettings[`ticks_font_size_${axis}`],
45 + family: chartSettings[`ticks_font_family_${axis}`],
46 + style: chartSettings[`ticks_font_style_${axis}`],
47 + weight: chartSettings[`ticks_font_weight_${axis}`],
48 + },
49 + });
50 +
51 + // Configure scales based on chart type
52 + const scales =
53 + ["bar", "bar_horizontal", "line"].includes(chartSettings.chart_type)
54 + ? {
55 + x: {
56 + reverse: chartSettings.reverse_x === "yes",
57 + stacked: chartSettings.stacked_bar_chart === "yes",
58 + type:
59 + chartSettings.chart_type === "bar_horizontal"
60 + ? chartSettings.data_type
61 + : "category",
62 + min: chartSettings.min_value || null,
63 + max: chartSettings.max_value || null,
64 + grid: axisConfig("x", chartSettings.axis_grid_line_color_x, chartSettings.grid_line_width_x, true),
65 + title: {
66 + display: chartSettings.display_x_axis_title,
67 + text: chartSettings.x_axis_title,
68 + color: chartSettings.axis_title_color_x,
69 + font: {
70 + size: chartSettings.axis_title_font_size_x,
71 + family: chartSettings.axis_title_font_family_x,
72 + style: chartSettings.axis_title_font_style_x,
73 + weight: chartSettings.axis_title_font_weight_x,
74 + },
75 + },
76 + ticks: {
77 + stepSize:
78 + chartSettings.chart_type === "bar_horizontal"
79 + ? chartSettings.x_step_size
80 + : "",
81 + ...tickConfig("x"),
82 + },
83 + },
84 + y: {
85 + reverse: chartSettings.reverse_y === "yes",
86 + stacked: chartSettings.stacked_bar_chart === "yes",
87 + type:
88 + ["bar", "line"].includes(chartSettings.chart_type)
89 + ? chartSettings.data_type
90 + : "category",
91 + min: chartSettings.min_value || null,
92 + max: chartSettings.max_value || null,
93 + grid: axisConfig("y", chartSettings.axis_grid_line_color_y, chartSettings.grid_line_width_y, true),
94 + title: {
95 + display: chartSettings.display_y_axis_title,
96 + text: chartSettings.y_axis_title,
97 + color: chartSettings.axis_title_color_y,
98 + font: {
99 + size: chartSettings.axis_title_font_size_y,
100 + family: chartSettings.axis_title_font_family_y,
101 + style: chartSettings.axis_title_font_style_y,
102 + weight: chartSettings.axis_title_font_weight_y,
103 + },
104 + },
105 + ticks: tickConfig("y"),
106 + },
107 + }
108 + : {};
109 +
110 + // Global options
111 + const globalOptions = {
112 + responsive: true,
113 + showLine: chartSettings.show_lines,
114 + animation: chartSettings.chart_animation === "yes",
115 + animations: {
116 + tension: {
117 + duration: chartSettings.chart_animation_duration,
118 + easing: chartSettings.animation_transition_type,
119 + from: 1,
120 + to: 0,
121 + loop: chartSettings.chart_animation_loop === "yes",
122 + },
123 + },
124 + events: [
125 + chartSettings.trigger_tooltip_on,
126 + chartSettings.exclude_dataset_on_click === "yes" ? "click" : "",
127 + ],
128 + interaction: {
129 + mode: chartSettings.chart_interaction_mode || "nearest",
130 + },
131 + elements: {
132 + point: {
133 + radius:
134 + chartSettings.line_dots === "yes"
135 + ? window.innerWidth >= 768
136 + ? chartSettings.line_dots_radius
137 + : chartSettings.line_dots_radius_mobile
138 + : 0,
139 + },
140 + },
141 + scales,
142 + plugins: {
143 + datalabels: {
144 + color: chartSettings.inner_datalabels_color,
145 + font: {
146 + size: chartSettings.inner_datalabels_font_size,
147 + style: chartSettings.inner_datalabels_font_style,
148 + weight: chartSettings.inner_datalabels_font_weight,
149 + },
150 + },
151 + legend: {
152 + onHover: (event) => {
153 + event.native.target.style.cursor = "pointer";
154 + },
155 + onLeave: (event) => {
156 + event.native.target.style.cursor = "default";
157 + },
158 + onClick: (e, legendItem, legend) => {
159 + if (
160 + ["bar", "bar_horizontal", "line"].includes(chartSettings.chart_type) ||
161 + chartSettings.chart_type === "radar"
162 + ) {
163 + const ci = legend.chart;
164 + const index = legendItem.datasetIndex;
165 + legendItem.hidden
166 + ? (ci.show(index), (legendItem.hidden = false))
167 + : (ci.hide(index), (legendItem.hidden = true));
168 + }
169 + },
170 + reverse: chartSettings.reverse_legend === "yes",
171 + display: chartSettings.show_chart_legend === "yes",
172 + position: chartSettings.legend_position || "top",
173 + align: chartSettings.legend_align || "center",
174 + labels: {
175 + usePointStyle: chartSettings.legend_shape === "point",
176 + padding: chartSettings.legend_padding,
177 + boxWidth: chartSettings.legend_box_width,
178 + boxHeight: chartSettings.legend_font_size,
179 + color: chartSettings.legend_text_color,
180 + font: {
181 + family: chartSettings.legend_font_family,
182 + size: chartSettings.legend_font_size,
183 + style: chartSettings.legend_font_style,
184 + weight: chartSettings.legend_font_weight,
185 + },
186 + },
187 + },
188 + title: {
189 + display: chartSettings.show_chart_title === "yes",
190 + text: chartSettings.chart_title,
191 + align: chartSettings.chart_title_align || "center",
192 + position: chartSettings.chart_title_position || "top",
193 + color: chartSettings.chart_title_color || "#000",
194 + padding: chartSettings.title_padding,
195 + font: {
196 + family: chartSettings.title_font_family,
197 + size: chartSettings.title_font_size,
198 + style: chartSettings.title_font_style,
199 + weight: chartSettings.title_font_weight,
200 + },
201 + },
202 + tooltip: {
203 + callbacks: {
204 + footer(tooltipItems) {
205 + let sum = 0;
206 + tooltipItems.forEach((item) => {
207 + sum += item.parsed.y;
208 + });
209 + if (chartSettings.chart_type === "bar_horizontal") {
210 + sum = 0;
211 + tooltipItems.forEach((item) => {
212 + sum += item.parsed.x;
213 + });
214 + }
215 + if (
216 + ["radar", "pie", "doughnut", "polarArea"].includes(
217 + chartSettings.chart_type
218 + )
219 + ) {
220 + return false;
221 + }
222 + return "Sum: " + sum;
223 + },
224 + },
225 + enabled: chartSettings.show_chart_tooltip === "yes",
226 + position: chartSettings.tooltip_position || "nearest",
227 + padding: chartSettings.tooltip_padding || 10,
228 + caretSize:
229 + window.innerWidth >= 768
230 + ? chartSettings.tooltip_caret_size
231 + : chartSettings.chart_tooltip_caret_size_mobile,
232 + backgroundColor:
233 + chartSettings.chart_tooltip_bg_color || "rbga(0, 0, 0, 0.2)",
234 + titleColor: chartSettings.chart_tooltip_title_color || "#FFF",
235 + titleFont: {
236 + family: chartSettings.chart_tooltip_title_font,
237 + size: chartSettings.chart_tooltip_title_font_size,
238 + },
239 + titleAlign: chartSettings.chart_tooltip_title_align,
240 + titleMarginBottom: chartSettings.chart_tooltip_title_margin_bottom,
241 + bodyColor: chartSettings.chart_tooltip_item_color || "#FFF",
242 + bodyFont: {
243 + family: chartSettings.chart_tooltip_item_font,
244 + size: chartSettings.chart_tooltip_item_font_size,
245 + },
246 + bodyAlign: chartSettings.chart_tooltip_item_align,
247 + bodySpacing: chartSettings.chart_tooltip_item_spacing,
248 + boxPadding: 3,
249 + },
250 + },
251 + };
252 +
253 + // Adjust scales for non-standard chart types
254 + if (
255 + !["bar", "bar_horizontal", "line"].includes(chartSettings.chart_type) &&
256 + !["doughnut", "pie", "polarArea"].includes(chartSettings.chart_type)
257 + ) {
258 + globalOptions.scales = {
259 + r: {
260 + angleLines: { color: chartSettings.angle_lines_color },
261 + pointLabels: {
262 + color: chartSettings.point_labels_color_r,
263 + font: {
264 + size: chartSettings.point_labels_font_size_r,
265 + family: chartSettings.point_labels_font_family_r,
266 + style: chartSettings.point_labels_font_style_r,
267 + weight: chartSettings.point_labels_font_weight_r,
268 + },
269 + },
270 + ticks: {
271 + stepSize: chartSettings.r_step_size,
272 + display: chartSettings.display_r_ticks,
273 + backdropColor: chartSettings.axis_labels_bg_color,
274 + backdropPadding: +chartSettings.axis_labels_padding,
275 + color: chartSettings.axis_labels_color,
276 + },
277 + grid: axisConfig("r", chartSettings.axis_grid_line_color_r, chartSettings.grid_line_width_r, true),
278 + },
279 + };
280 + }
281 +
282 + // Chart creation
283 + let config;
284 + if (chartSettings.data_source === "custom") {
285 + const data = {
286 + labels,
287 + datasets: JSON.parse(chartSettings.chart_datasets),
288 + };
289 + config = {
290 + type:
291 + chartSettings.chart_type === "bar_horizontal"
292 + ? "bar"
293 + : chartSettings.chart_type,
294 + data,
295 + options: globalOptions,
296 + plugins: chartSettings.inner_datalabels ? [ChartDataLabels] : [],
297 + };
298 + if (chartSettings.chart_type === "bar_horizontal") {
299 + config.options.indexAxis = "y";
300 + }
301 + if (
302 + chartSettings.tooltips_percent ||
303 + ["pie", "doughnut", "polarArea"].includes(chartSettings.chart_type)
304 + ) {
305 + config.options.plugins.tooltip.callbacks.label = (data) => {
306 + let prefix = data.dataset.label + ": ";
307 + if (["pie", "doughnut", "polarArea"].includes(chartSettings.chart_type)) {
308 + prefix = `${data.label} (${data.dataset.label}): `;
309 + }
310 + const total = data.dataset.data.reduce(
311 + (sum, val) => parseFloat(sum) + parseFloat(val),
312 + 0
313 + );
314 + const percentage = ((data.formattedValue / total) * 100).toPrecision(3);
315 + return prefix + (chartSettings.tooltips_percent ? percentage + "%" : data.formattedValue);
316 + };
317 + }
318 + new Chart($scope.find(".king-addons-chart"), config);
319 + } else {
320 + // Handle CSV data source or errors
321 + if (chartSettings.url && (["bar", "bar_horizontal", "line", "radar"].includes(chartSettings.chart_type))) {
322 + $.ajax({
323 + url: chartSettings.url,
324 + type: "GET",
325 + success(res) {
326 + $scope.find(".king-addons-rotating-plane").remove();
327 + renderCSVChart(res);
328 + },
329 + error(err) {
330 + // console.error(err);
331 + },
332 + });
333 + } else {
334 + $scope.find(".king-addons-rotating-plane").remove();
335 + const errorMsg =
336 + !chartSettings.url
337 + ? '<p class="king-addons-charts-error-notice">Provide a csv file or remote URL</p>'
338 + : '<p class="king-addons-charts-error-notice">doughnut, pie and polarArea charts only work with custom data source</p>';
339 + $scope.find(".king-addons-charts-container").html(errorMsg);
340 + }
341 + }
342 +
343 + // Window resize handler
344 + $(window).resize(() => {
345 + const newRadius =
346 + window.innerWidth >= 768
347 + ? chartSettings.line_dots_radius
348 + : chartSettings.line_dots_radius_mobile;
349 + config.options.elements.point.radius = newRadius;
350 + config.options.plugins.tooltip.caretSize =
351 + window.innerWidth >= 768
352 + ? chartSettings.tooltip_caret_size
353 + : chartSettings.chart_tooltip_caret_size_mobile;
354 + });
355 +
356 + // Render chart from CSV data
357 + function renderCSVChart(csvData) {
358 + const ctx = $scope.find(".king-addons-chart");
359 + const rows = csvData.split(/\r?\n|\r/);
360 + const csvLabels = rows.shift().split(chartSettings.separator);
361 + const data = { labels: csvLabels, datasets: [] };
362 + const csvConfig = {
363 + type: chartSettings.chart_type === "bar_horizontal" ? "bar" : chartSettings.chart_type,
364 + data,
365 + options: globalOptions,
366 + plugins: [
367 + ...(chartSettings.inner_datalabels ? [ChartDataLabels] : []),
368 + {
369 + beforeInit(chart) {
370 + chart.legend.afterFit = function () {
371 + this.height += 50;
372 + };
373 + },
374 + },
375 + ],
376 + };
377 + if (chartSettings.chart_type === "bar_horizontal") {
378 + csvConfig.options.indexAxis = "y";
379 + }
380 + if (chartSettings.tooltips_percent) {
381 + csvConfig.options.plugins.tooltip.callbacks.label = (data) => {
382 + let prefix = data.dataset.label + ": ";
383 + if (["pie", "doughnut", "polarArea"].includes(chartSettings.chart_type)) {
384 + prefix = `${data.label} (${data.dataset.label}): `;
385 + }
386 + const total = data.dataset.data.reduce(
387 + (sum, val) => parseFloat(sum) + parseFloat(val),
388 + 0
389 + );
390 + const percentage = ((data.formattedValue / total) * 100).toPrecision(3);
391 + return prefix + (chartSettings.tooltips_percent ? percentage + "%" : data.formattedValue);
392 + };
393 + }
394 + const csvChart = new Chart(ctx, csvConfig);
395 + rows.forEach((row, idx) => {
396 + if (row) {
397 + const dataset = { data: row.split(chartSettings.separator) };
398 + if (customDatasets[idx]) {
399 + Object.assign(dataset, customDatasets[idx]);
400 + }
401 + data.datasets.push(dataset);
402 + csvChart.update();
403 + }
404 + });
405 + }
406 + },
407 + });
408 +
409 + elementorFrontend.elementsHandler.addHandler(BaseHandler, {
410 + $element: $scope,
411 + });
412 + }
413 + );
414 + });
415 +})(jQuery);