1const x13pricehistory = { 2 chartInstance: null, 3 chartStyles: { 4 chart: "bar", 5 modern_chart: "line", 6 modern_chart_light: "line_v2", 7 }, 8 getCurrency: function (number) { 9 let value = new Intl.NumberFormat(prestashop.language.locale, { 10 style: "currency", 11 currency: prestashop.currency.iso_code, 12 }).format(number); 13 14 return value; 15 }, 16 drawGradient: function (chart, additionalStep = false) { 17 const top = isNaN(chart.chartArea?.top) ? 0 : chart.chartArea.top; 18 const bottom = isNaN(chart.chartArea?.bottom) 19 ? 300 20 : chart.chartArea.bottom; 21 let { canvas, ctx } = chart; 22 let gradient = ctx.createLinearGradient(0, top, 0, bottom); 23 24 gradient.addColorStop(0, `${x13pricehistoryChartBackground}88`); 25 26 if (additionalStep) { 27 gradient.addColorStop(0.85, `${x13pricehistoryChartBackground}00`); 28 } 29 30 gradient.addColorStop(1, `${x13pricehistoryChartBackground}00`); 31 32 return gradient; 33 }, 34 generateData: function (parent) { 35 let labels = []; 36 let data = []; 37 let lowest = 0; 38 let json = parent.querySelector(".x13pricehistory-json"); 39 json = JSON.parse(json.textContent); 40 41 Object.values(json).forEach((value) => { 42 labels = [...labels, value.date_add]; 43 data = [...data, value.price]; 44 45 if (value.lowest) { 46 lowest = value.date_add; 47 } 48 }); 49 50 return { labels, data, lowest }; 51 }, 52 generateChart: function (parent, { labels, data, lowest }) {
53 let chart = parent.querySelector(".x13pricehistory-chart"); 54 let chartStyle = x13pricehistory.chartStyles[chart.dataset.style]; 55 let ctx = chart.getContext("2d"); 56 57 const type = { 58 line: { 59 labels: labels, 60 datasets: [ 61 { 62 fill: true, 63 lineTension: 0, 64 backgroundColor: function (context) { 65 return x13pricehistory.drawGradient(context.chart); 66 }, 67 borderColor: x13pricehistoryChartBackground, 68 pointBackgroundColor: labels.map((label) => { 69 if (label == lowest) { 70 return x13pricehistoryChartBackgroundLowest; 71 } 72 73 return x13pricehistoryChartBackground; 74 }), 75 data: data, 76 }, 77 ], 78 }, 79 line_v2: { 80 labels: labels, 81 datasets: [ 82 { 83 fill: true, 84 lineTension: 0, 85 backgroundColor: function (context) { 86 return x13pricehistory.drawGradient(context.chart, true); 87 }, 88 borderWidth: 2, 89 borderColor: x13pricehistoryChartBackground, 90 pointRadius: 5, 91 pointBorderWidth: 2,
92 pointBackgroundColor: labels.map((label) => { 93 if (label == lowest) return "#fff"; 94 95 return "rgba(0, 0, 0, 0)"; 96 }), 97 pointHoverRadius: 5, 98 pointBorderColor: labels.map((label) => { 99 if (label == lowest) { 100 return x13pricehistoryChartBackgroundLowest; 101 } 102 103 return "rgba(0, 0, 0, 0)"; 104 }), 105 pointHoverBackgroundColor: labels.map((label) => { 106 if (label == lowest) { 107 return x13pricehistoryChartBackgroundLowest; 108 } 109 110 return x13pricehistoryChartBackground; 111 }), 112 pointHoverBorderColor: labels.map((label) => { 113 if (label == lowest) { 114 return x13pricehistoryChartBackgroundLowest; 115 } 116 117 return x13pricehistoryChartBackground; 118 }), 119 data: data, 120 }, 121 ], 122 }, 123 bar: { 124 labels: labels, 125 datasets: [ 126 { 127 fill: true, 128 backgroundColor: labels.map((label) => { 129 if (label == lowest) { 130 return x13pricehistoryChartBackgroundLowest; 131 } 132 133 return x13pricehistoryChartBackground; 134 }), 135 data: data, 136 }, 137 ], 138 }, 139 }; 140 141 let tooltipStyle = 142 chartStyle !== "bar" 143 ? { 144 backgroundColor: "rgba(255, 255, 255, 0.8)", 145 titleFontSize: 11, 146 titleFontColor: "#000", 147 titleFontStyle: "400", 148 bodyFontColor: x13pricehistoryChartBackground, 149 bodyFontStyle: "700", 150 } 151 : {}; 152 153 let options = { 154 legend: { 155 display: false, 156 }, 157 tooltips: { 158 mode: "index", 159 intersect: false, 160 ...tooltipStyle, 161 callbacks: { 162 label: function (tooltipItem, data) { 163 let label = parseFloat(tooltipItem.value); 164 return x13pricehistory.getCurrency(label); 165 }, 166 labelTextColor: function (tooltipItem, data) { 167 if (chartStyle === "bar") return "#fff"; 168 if (lowest == tooltipItem.label) { 169 return x13pricehistoryChartBackgroundLowest; 170 } 171 172 return x13pricehistoryChartBackground; 173 }, 174 }, 175 }, 176 hover: { 177 mode: "index", 178 intersect: false, 179 animationDuration: 0, 180 }, 181 scales: { 182 yAxes: [ 183 { 184 ticks: { 185 min: 0, 186 callback: function (value, index, ticks) { 187 return x13pricehistory.getCurrency(value); 188 }, 189 }, 190 }, 191 ], 192 }, 193 }; 194 195 if (chartStyle === "line_v2") { 196 options.scales.yAxes[0].ticks.fontColor = "#A1A2A7"; 197 options.scales.yAxes[0].gridLines = { 198 color: "#FBFBFB", 199 zeroLineColor: "#FBFBFB", 200 }; 201 options.scales.xAxes = [ 202 { 203 gridLines: { 204 color: "#FBFBFB", 205 zeroLineColor: "#FBFBFB", 206 }, 207 ticks: { fontColor: "#A1A2A7" }, 208 }, 209 ]; 210 options.tooltips.displayColors = false; 211 } 212 213 x13pricehistory.chartInstance = new Chart(ctx, { 214 type: chartStyle === "line_v2" ? "line" : chartStyle, 215 data: type[chartStyle], 216 options: options, 217 plugins: 218 chartStyle === "line_v2" 219 ? [ 220 { 221 afterDatasetUpdate: function (chart) { 222 chart.pluginTooltips = []; 223 224 chart.config.data.datasets.forEach(function (dataset, i) { 225 chart.getDatasetMeta(i).data.forEach(function (sector, j) { 226 if (sector._index === labels.indexOf(lowest)) { 227 chart.pluginTooltips.push( 228 new Chart.Tooltip( 229 { 230 _chart: chart.chart, 231 _chartInstance: chart, 232 _data: chart.data, 233 _options: chart.options.tooltips, 234 _active: [sector], 235 }, 236 chart 237 ) 238 ); 239 } 240 }); 241 }); 242 }, 243 afterDraw: function (chart, easing) { 244 const activeTooltip = chart.tooltip._active; 245 const firstOpenActiveTooltipId = 246 chart?.pluginTooltips[0]._active[0]._index; 247 const currentActiveTooltipId = 248 !!activeTooltip && activeTooltip.length > 0 249 ? activeTooltip[0]?._index 250 : firstOpenActiveTooltipId; 251 252 if (firstOpenActiveTooltipId === currentActiveTooltipId) { 253 Chart.helpers.each( 254 chart.pluginTooltips, 255 function (tooltip) { 256 tooltip.initialize(); 257 tooltip.update(); 258 tooltip.pivot(); 259 tooltip.transition(easing).draw(); 260 x13pricehistory.renderLine(chart, tooltip); 261 } 262 ); 263 } 264 265 if (!!activeTooltip && activeTooltip.length > 0) { 266 x13pricehistory.renderLine(chart, activeTooltip[0]); 267 } 268 }, 269 }, 270 ] 271 : [], 272 }); 273 274 if (x13pricehistory.chartInstance.config.data.datasets.length === 0) return; 275 if (x13pricehistory.chartInstance.options.scales.yAxes.length === 0) return; 276 277 let maxValue = parseInt( 278 Math.max(...x13pricehistory.chartInstance.config.data.datasets[0].data) * 279 1.12 280 ); 281 282 x13pricehistory.chartInstance.options.scales.yAxes[0].ticks.suggestedMax = 283 maxValue;
284 x13pricehistory.chartInstance.update(); 285 }, 286 renderLine: (chart, active) => { 287 let left = active._model.caretX ?? active._model.x; 288 chart.ctx.beginPath(); 289 chart.ctx.lineWidth = 0.5; 290 chart.ctx.strokeStyle = "rgba(0, 0, 0, 0.35)"; 291 chart.ctx.setLineDash([5, 5]); 292 chart.ctx.moveTo(left, chart.chartArea.top); 293 chart.ctx.lineTo(left, chart.chartArea.bottom); 294 chart.ctx.stroke(); 295 chart.ctx.beginPath(); 296 chart.ctx.setLineDash([0, 0]); 297 }, 298}; 299 300document.addEventListener("click", (e) => { 301 if (!e.target.classList.contains("x13pricehistory__button")) return; 302 303 let parent = e.target.closest(".x13pricehistory"); 304 let chart = parent.querySelector(".x13pricehistory-chart"); 305 let modal = document.querySelector(".x13pricehistory-modal"); 306 307 if (!parent.classList.contains("inited")) { 308 parent.classList.add("inited"); 309 let data = x13pricehistory.generateData(parent); 310 311 let html = $(".x13pricehistory-modal-body-replace").html(); 312 $(".x13pricehistory-modal .modal-body").html(html); 313 314 if (chart !== null) { 315 x13pricehistory.generateChart(modal, data); 316 } 317 } 318 319 // jQuery + Bootstrap Modal 320 $(".x13pricehistory-modal").modal("show"); 321});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.