1/******/ (function() { // webpackBootstrap 2/******/ "use strict"; 3/******/ var __webpack_modules__ = ({ 4
5/***/ "./js/components/SwiperEditorConfig.js": 6/*!*********************************************!*\ 7 !*** ./js/components/SwiperEditorConfig.js ***! 8 \*********************************************/ 9/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { 10 11/* harmony export */ __webpack_require__.d(__webpack_exports__, { 12/* harmony export */ getSliderParams: function() { return /* binding */ getSliderParams; } 13/* harmony export */ }); 14/* harmony import */ var _helper_CSS__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../helper/CSS */ "./js/helper/CSS.js"); 15 16function getSliderParams(widget) { 17 let slidesPerViewInline = widget.style.getPropertyValue('--slides-per-view'); 18 let slidesPerView = slidesPerViewInline !== "" ? parseInt(slidesPerViewInline) : getComputedStyle(widget).getPropertyValue('--slides-per-view'); 19 let spaceBetween = getComputedStyle(widget).getPropertyValue('--slides-space-between'); 20 let autoplay = getComputedStyle(widget).getPropertyValue('--autoplay'); 21 slidesPerView = slidesPerView ? parseInt(slidesPerView) : 3; 22 spaceBetween = spaceBetween ? parseInt(spaceBetween) : 30; 23 let autoplayConfig = false; 24 if (autoplay && autoplay !== 'false') { 25 if (/s/.test(autoplay)) { 26 const valueInfo = (0,_helper_CSS__WEBPACK_IMPORTED_MODULE_0__.getValueInfos)(autoplay); 27 autoplay = (0,_helper_CSS__WEBPACK_IMPORTED_MODULE_0__.convertUnitByInfo)(valueInfo.value, 'ms', { 28 computed: valueInfo.value, 29 ...valueInfo 30 }); 31 } 32 autoplay = parseInt(autoplay); 33 if (autoplay < 1000) { 34 autoplay *= 1000; 35 } 36 autoplayConfig = { 37 delay: autoplay 38 }; 39 } 40 return { 41 slidesPerView, 42 spaceBetween, 43 autoplayConfig, 44 autoplayRaw: autoplay, 45 // On garde la valeur brute pour comparaison 46 isInline: !!slidesPerViewInline 47 }; 48} 49 50 51/***/ }), 52
53/***/ "./js/helper/CSS.js": 54/*!**************************!*\ 55 !*** ./js/helper/CSS.js ***! 56 \**************************/ 57/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { 58 59/* harmony export */ __webpack_require__.d(__webpack_exports__, { 60/* harmony export */ convertUnitByInfo: function() { return /* binding */ convertUnitByInfo; }, 61/* harmony export */ getValueInfos: function() { return /* binding */ getValueInfos; } 62/* harmony export */ }); 63/* unused harmony exports cleanValuePropsCSS, getFontNameFromFontFamily, getValueOnEm, getValueOnRem, getBackgroundImageValue, DEFAULT_CLIP_TEXT_GRADIENT, convertBackgroundPositionToString, getPseudoFormatByName, getDefaultValueCss, cssComputedCache, getShortValueCss, getDecodeShortValue, expandShorthandToLonghands, isTargetedShorthand, normalizeDeclarations, normalizeCSSRuleStore, getInfoFromMultiProps, getUnit, getPropRefForPercent, getComputedByInfo, getTranslateValues, getPercentFromTwoValue, getValueWithoutPrefix, verifAndGetValueWithPrefix, getBorderColor, getBorderStyle, getDefaultUnit, addHistoryRemoveFromProps, getCSSQuery, getCSSQueryAllStatus, getCSSQuerySaveKeys, getStatusToClassAndPseudoClass, generatePositionValue, getInitialValue, convertTime, calcMsToUnit, calcToMs, getValueViewWidth, getDefaultDisplayValue, getMediaQuery, getMediaQueryCss, getBackgroundPositionInfo, getBackgroundPositionString, getBackgroundSizeInfo, hasInitialValue, getDefaultTransformItem, getTransformValue, generateTransformValue, decomposeMatrix2d, getTransformOriginValue, generateTransformOriginValue, parseGradient, generateGradient, getBackgroundLayers, generateBackgroundLonghands, getShadowValue, generateShadowValue, getDefaultShadowItem */ 64/* harmony import */ var _Math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Math */ "./js/helper/Math.js"); 65/* harmony import */ var _String__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./String */ "./js/helper/String.js"); 66 67 68 69 70const regexFunctionCss = /([a-z]{3,}\((?:(?:\()[a-z]{3,}\([^\)]*\)|[^()]+)\)|([a-z]{3,}\(.*\)))|([^\s]+)/; 71const regexFunctionCssGlobal = new RegExp(regexFunctionCss.source, 'g'); 72const minisite = document.querySelector('#minisite'); 73function pxToEm(valuePixel, fontSize) { 74 return parseFloat(valuePixel) / parseFloat(fontSize).toFixed(2); 75} 76function emToPx(valueEm, fontSize) { 77 return parseFloat(valueEm) * parseFloat(fontSize); 78} 79 80/** 81 * 82 * @param elementSelector 83 * @param value 84 * @returns {*} 85 */ 86const getValueOnEm = function (elementSelector, value) { 87 let valueFontSize = window.getComputedStyle(elementSelector, null).getPropertyValue('font-size'); 88 if (/px/.test(value)) { 89 value = pxToEm(value, valueFontSize); 90 } 91 return secureValueShow(value, 0); 92}; 93const getValueOnRem = function (elementSelector, value) { 94 let valueFontSize = window.getComputedStyle(elementSelector.ownerDocument.documentElement, null).getPropertyValue('font-size'); 95 if (/px/.test(value)) { 96 value = pxToEm(value, valueFontSize); 97 } 98 return secureValueShow(value, 0); 99}; 100const getValueWithoutPrefix = function (value) { 101 let match = /((?:[-0-9.]+)?|auto)[\S]+/.exec(value); 102 if (match) { 103 value = _Math__WEBPACK_IMPORTED_MODULE_0__["default"].cleanFloatValue(parseFloat(match[1])); 104 } 105 return value; 106}; 107const getValueViewWidth = function (value, context) { 108 const valueInfo = getValueInfos(value.computed); 109 const valuepx = convertUnitByInfo(valueInfo.value, 'px', value); 110 const width100vwInPx = context.width; 111 112 // vw 113 return valuepx / width100vwInPx * 100; 114}; 115const getFontNameFromFontFamily = function (value) { 116 let regexFontFamily = /(?:"?([\w\d][\w\d-\s]+[\w\d])"?,?)/gm; 117 let fontArray = regexFontFamily.exec(value); 118 let font = value; 119 if (fontArray) { 120 font = fontArray[1]; 121 } 122 return font; 123}; 124const cleanValuePropsCSS = function (propName, value) { 125 switch (propName) { 126 case 'font-family': 127 value = getFontNameFromFontFamily(value); 128 break; 129 case 'letter-spacing': 130 if (/normal/.test(value)) { 131 value = '0em'; 132 } 133 break; 134 case 'line-height': 135 if (/normal/.test(value)) { 136 value = '1.2'; 137 } 138 break; 139 } 140 return value; 141}; 142const propDontViewport = ['line-height']; 143 144/**
145 * Cache pour les valeurs CSS computées. 146 * Stocke les résultats de getComputedStyle par élément et par état DOM 147 * pour éviter les reflows répétés (layout thrashing). 148 * 149 * Supporte plusieurs éléments actifs simultanément (Map<element, session>), 150 * pour pouvoir batcher également les lectures parent/offsetParent. 151 * 152 * Usage : 153 * cssComputedCache.begin(element, null, props) â ouvre une session pour un élément 154 * getDefaultValueCss(...) â utilise le cache automatiquement 155 * cssComputedCache.end(element) â ferme la session de cet élément 156 * cssComputedCache.end() â ferme TOUTES les sessions actives 157 */ 158const cssComputedCache = (() => { 159 // Map<element, sessionState> 160 // sessionState = { pseudo, props, cache, windowWidthInfo, windowHeightInfo, windowHeightAuto } 161 const _sessions = new Map(); 162 163 /** 164 * Lit toutes les props enregistrées pour un état donné. 165 * Appelé une seule fois par état (lazy, au premier get() pour cet état). 166 * = 1 seul reflow par état, quel que soit le nombre de props. 167 */ 168 function _readState(element, pseudo, state) { 169 const session = _sessions.get(element); 170 if (!session) return; 171 if (session.cache[state]) return; // déjà lu 172 173 const props = session.props; 174 session.cache[state] = {}; 175 switch (state) { 176 case 'normal': 177 { 178 const computed = window.getComputedStyle(element, pseudo); 179 props.forEach(p => { 180 session.cache[state][p] = computed.getPropertyValue(p); 181 }); 182 break; 183 } 184 case 'hidden': 185 { 186 element.style.display = 'none'; 187 const computed = window.getComputedStyle(element, pseudo); 188 props.forEach(p => { 189 session.cache[state][p] = computed.getPropertyValue(p); 190 }); 191 element.style.removeProperty('display'); 192 break; 193 } 194 case 'vw': 195 { 196 session.windowWidthInfo = session.windowWidthInfo || getValueInfos(document.body.style.getPropertyValue('--minisite-width')); 197 document.body.style.setProperty('--minisite-width', session.windowWidthInfo.value - 2 + 'px'); 198 const computed = window.getComputedStyle(element, pseudo); 199 props.forEach(p => { 200 session.cache[state][p] = computed.getPropertyValue(p); 201 }); 202 document.body.style.setProperty('--minisite-width', session.windowWidthInfo.value + 'px'); 203 break; 204 } 205 case 'vh': 206 { 207 session.windowHeightInfo = session.windowHeightInfo || getValueInfos(document.body.style.getPropertyValue('--minisite-height')); 208 session.windowHeightAuto = session.windowHeightInfo.value !== ''; 209 if (session.windowHeightAuto) { 210 document.body.style.setProperty('--minisite-height', session.windowHeightInfo.value - 2 + 'px'); 211 } else { 212 document.body.style.setProperty('--minisite-height', window.innerHeight - 2 + 'px'); 213 } 214 const computed = window.getComputedStyle(element, pseudo); 215 props.forEach(p => { 216 session.cache[state][p] = computed.getPropertyValue(p); 217 }); 218 if (session.windowHeightAuto) { 219 document.body.style.setProperty('--minisite-height', session.windowHeightInfo.value + 'px'); 220 } else { 221 document.body.style.removeProperty('--minisite-height'); 222 } 223 break; 224 } 225 } 226 } 227 return { 228 /** 229 * Ouvre une session de cache pour un élément. 230 * Lazy : aucune lecture DOM n'est faite ici. 231 * Plusieurs éléments peuvent être actifs simultanément. 232 */ 233 begin(element, pseudoElement = null, props = []) { 234 if (!element) return; 235 _sessions.set(element, { 236 pseudo: pseudoElement, 237 props: props, 238 cache: {}, 239 windowWidthInfo: null, 240 windowHeightInfo: null, 241 windowHeightAuto: false 242 }); 243 }, 244 /** 245 * Ferme la session de cache. 246 * end(element) : ferme la session de cet élément spécifique. 247 * end() : ferme TOUTES les sessions actives. 248 */ 249 end(element) { 250 if (typeof element === 'undefined') { 251 _sessions.clear(); 252 } else { 253 _sessions.delete(element); 254 } 255 }, 256 /** 257 * Vérifie si le cache est actif pour cet élément. 258 */ 259 isActive(element) { 260 return _sessions.has(element); 261 }, 262 /** 263 * Invalide le cache des valeurs lues (les états seront re-lus au prochain get).
264 * à appeler quand l'état DOM de l'élément change (ajout/retrait de classe, etc.). 265 * invalidate(element) : invalide une session spécifique. 266 * invalidate() : invalide toutes les sessions. 267 */ 268 invalidate(element) { 269 const reset = session => { 270 session.cache = {}; 271 session.windowWidthInfo = null; 272 session.windowHeightInfo = null; 273 session.windowHeightAuto = false; 274 }; 275 if (typeof element === 'undefined') { 276 _sessions.forEach(reset); 277 } else { 278 const session = _sessions.get(element); 279 if (session) reset(session); 280 } 281 }, 282 /** 283 * Récupère une valeur depuis le cache pour un état donné. 284 * Au premier appel pour un état, lit TOUTES les props en une passe (1 reflow). 285 * Les appels suivants pour le même état sont gratuits. 286 */ 287 get(element, pseudoElement, prop, state = 'normal') { 288 const session = _sessions.get(element); 289 if (!session) return null; 290 291 // Lazy : lire toutes les props pour cet état si pas encore fait 292 if (!session.cache[state]) { 293 _readState(element, pseudoElement, state); 294 } 295 296 // Si la prop est dans le cache, la retourner 297 if (prop in session.cache[state]) { 298 return session.cache[state][prop]; 299 } 300 301 // Prop pas dans la liste initiale : lecture individuelle (fallback) 302 switch (state) { 303 case 'hidden': 304 element.style.display = 'none'; 305 session.cache[state][prop] = window.getComputedStyle(element, pseudoElement).getPropertyValue(prop); 306 element.style.removeProperty('display'); 307 break; 308 case 'vw': 309 session.windowWidthInfo = session.windowWidthInfo || getValueInfos(document.body.style.getPropertyValue('--minisite-width')); 310 document.body.style.setProperty('--minisite-width', session.windowWidthInfo.value - 2 + 'px'); 311 session.cache[state][prop] = window.getComputedStyle(element, pseudoElement).getPropertyValue(prop); 312 document.body.style.setProperty('--minisite-width', session.windowWidthInfo.value + 'px'); 313 break; 314 case 'vh': 315 session.windowHeightInfo = session.windowHeightInfo || getValueInfos(document.body.style.getPropertyValue('--minisite-height')); 316 session.windowHeightAuto = session.windowHeightInfo.value !== ''; 317 if (session.windowHeightAuto) { 318 document.body.style.setProperty('--minisite-height', session.windowHeightInfo.value - 2 + 'px'); 319 } else { 320 document.body.style.setProperty('--minisite-height', window.innerHeight - 2 + 'px'); 321 } 322 session.cache[state][prop] = window.getComputedStyle(element, pseudoElement).getPropertyValue(prop); 323 if (session.windowHeightAuto) { 324 document.body.style.setProperty('--minisite-height', session.windowHeightInfo.value + 'px'); 325 } else { 326 document.body.style.removeProperty('--minisite-height'); 327 } 328 break; 329 default: 330 session.cache[state][prop] = window.getComputedStyle(element, pseudoElement).getPropertyValue(prop); 331 break; 332 } 333 return session.cache[state][prop]; 334 } 335 }; 336})(); 337 338/** 339 * Whitelist des props pour lesquelles `getDefaultValueCss(..., origin=true)` 340 * apporte une vraie valeur (détection vw/vh, lecture en display:none). 341 * Les autres props (color, font-family, font-weight, etc.) ont une valeur 342 * identique en mode origin et normal â la version origin=true ouvre la 343 * branche hidden+vw+vh qui force des reflows inutiles (Option I). 344 */ 345const viewportConvertibleProps = new Set([ 346// Dimensions 347'width', 'height', 'min-width', 'max-width', 'min-height', 'max-height', 348// Positionnement 349'top', 'left', 'bottom', 'right', 350// Espacement 351'margin-top', 'margin-right', 'margin-bottom', 'margin-left', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 'gap', 'row-gap', 'column-gap', 352// Typographie sensible aux unités 353'font-size', 'line-height', 'letter-spacing', 'word-spacing', 'text-indent', 354// Bordures 355'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width', 'border-top-left-radius', 'border-top-right-radius', 'border-bottom-left-radius', 'border-bottom-right-radius', 356// Autres 357'outline-width', 'outline-offset', 'background-position', 'background-position-x', 'background-position-y', 'background-size', 'transform', 'transform-origin']); 358const getDefaultValueCss = function (element, pseudoElement, prop, origin = false) { 359 while (element && element.nodeName !== "HTML") { 360 // Si le cache est actif pour cet élément, utiliser le cache 361 if (cssComputedCache.isActive(element)) { 362 let value; 363 if (origin && prop !== 'display') {
364 // Lire la valeur avec display:none (pour récupérer les %) 365 value = cssComputedCache.get(element, pseudoElement, prop, 'hidden'); 366 } else { 367 value = cssComputedCache.get(element, pseudoElement, prop, 'normal'); 368 } 369 if (origin) { 370 if (/px/.test(value) && !/\s/.test(value) && !/calc\(/.test(value) && propDontViewport.indexOf(prop) === -1) { 371 let valueTemp = cssComputedCache.get(element, pseudoElement, prop, 'normal'); 372 let valueViewWidth = cssComputedCache.get(element, pseudoElement, prop, 'vw'); 373 let valueInfos = getValueInfos(valueTemp, prop); 374 let valueViewWidthInfos = getValueInfos(valueViewWidth, prop); 375 let isCalculate = false; 376 if (valueViewWidth !== 'auto' && valueTemp !== valueViewWidth && (0,_Math__WEBPACK_IMPORTED_MODULE_0__.valueEqualtoWithinOnePercent)(valueInfos.value, valueViewWidthInfos.value)) { 377 value = convertUnit(element, pseudoElement, prop, valueInfos, 'vw') + 'vw'; 378 isCalculate = true; 379 } 380 if (!isCalculate) { 381 let valueViewHeight = cssComputedCache.get(element, pseudoElement, prop, 'vh'); 382 let valueViewHeightInfos = getValueInfos(valueViewHeight, prop); 383 if (valueViewHeight !== 'auto' && valueTemp !== valueViewHeight && (0,_Math__WEBPACK_IMPORTED_MODULE_0__.valueEqualtoWithinOnePercent)(valueInfos.value, valueViewHeightInfos.value)) { 384 value = convertUnit(element, pseudoElement, prop, valueInfos, 'vh') + 'vh'; 385 } 386 } 387 } 388 } 389 if (deviceRatioProps.includes(prop)) { 390 value = convertDevicePixelRatio(value); 391 } 392 return cleanValuePropsCSS(prop, value); 393 } 394 395 // Pas de cache actif : comportement original 396 if (origin && prop !== 'display') { 397 element.style.display = 'none'; 398 } 399 let value = window.getComputedStyle(element, pseudoElement).getPropertyValue(prop); 400 if (origin) { 401 element.style.removeProperty('display'); 402 if (/px/.test(value) && !/\s/.test(value) && !/calc\(/.test(value) && propDontViewport.indexOf(prop) === -1) { 403 let windowWidthInfo = getValueInfos(document.body.style.getPropertyValue('--minisite-width')); 404 let windowHeightInfo = getValueInfos(document.body.style.getPropertyValue('--minisite-height')); 405 let valueTemp = window.getComputedStyle(element, pseudoElement).getPropertyValue(prop); 406 document.body.style.setProperty('--minisite-width', windowWidthInfo.value - 2 + 'px'); 407 // minisite.style.width = window.innerWidth - 2 + 'px'; 408 let valueViewWidth = window.getComputedStyle(element, pseudoElement).getPropertyValue(prop); 409 let valueInfos = getValueInfos(valueTemp, prop); 410 let valueViewWidthInfos = getValueInfos(valueViewWidth, prop); 411 let isCalculate = false; 412 // vérifier si value à un valeur proche de valueViewWidth à 2% près 413 414 if (valueViewWidth !== 'auto' && valueTemp !== valueViewWidth && (0,_Math__WEBPACK_IMPORTED_MODULE_0__.valueEqualtoWithinOnePercent)(valueInfos.value, valueViewWidthInfos.value)) { 415 // convertir en viewport 416 value = convertUnit(element, pseudoElement, prop, valueInfos, 'vw') + 'vw'; 417 isCalculate = true; 418 } 419 document.body.style.setProperty('--minisite-width', windowWidthInfo.value + 'px'); 420 // minisite.style.width = ''; 421 422 const windowHeightAuto = windowHeightInfo.value !== ''; 423 if (windowHeightAuto) { 424 document.body.style.setProperty('--minisite-height', windowHeightInfo.value - 2 + 'px'); 425 } else { 426 document.body.style.setProperty('--minisite-height', window.innerHeight - 2 + 'px'); 427 } 428 let valueViewHeight = window.getComputedStyle(element, pseudoElement).getPropertyValue(prop); 429 let valueViewHeightInfos = getValueInfos(valueViewHeight, prop); 430 if (!isCalculate && valueViewHeight !== 'auto' && valueTemp !== valueViewHeight && (0,_Math__WEBPACK_IMPORTED_MODULE_0__.valueEqualtoWithinOnePercent)(valueInfos.value, valueViewHeightInfos.value)) {
431 // convertir en viewport 432 value = convertUnit(element, pseudoElement, prop, valueInfos, 'vh') + 'vh'; 433 } 434 if (windowHeightAuto) { 435 document.body.style.setProperty('--minisite-height', windowHeightInfo.value + 'px'); 436 } else { 437 document.body.style.removeProperty('--minisite-height'); 438 } 439 } 440 } 441 if (deviceRatioProps.includes(prop)) { 442 value = convertDevicePixelRatio(value); 443 } 444 return cleanValuePropsCSS(prop, value); 445 } 446 return ''; 447}; 448const deviceRatioProps = ['border-width']; 449function convertDevicePixelRatio(computedValue) { 450 if (/px/.test(computedValue) && !/\s/.test(computedValue) && !/calc\(/.test(computedValue) && window.devicePixelRatio !== 1) { 451 const valueInfoOnRatio = getValueInfos(computedValue); 452 computedValue = (0,_Math__WEBPACK_IMPORTED_MODULE_0__.cleanFloatValueForView)(valueInfoOnRatio.value * window.devicePixelRatio) + valueInfoOnRatio.unit; 453 } 454 return computedValue; 455} 456const regexMultiProps = { 457 'border': /^(border)-(color|width|style|radius)/, 458 'margin': /^(margin)/, 459 'padding': /^(padding)/, 460 'inset': /^(inset)/, 461 'borderImage': /^(border-image-(outset|slice|width))/ 462}; 463const positionProps = ['top', 'left', 'bottom', 'right']; 464const anglePositionProps = ['top-left', 'top-right', 'bottom-right', 'bottom-left']; 465function getInfoFromMultiProps(prop) { 466 let poss = positionProps; 467 let propWithPos = prop; 468 let listProps = []; 469 let match = null; 470 switch (true) { 471 case regexMultiProps.border.test(prop): 472 match = regexMultiProps.border.exec(prop); 473 propWithPos = match[1] + '-' + '{{pos}}' + '-' + match[2]; 474 if (match[2] === "radius") { 475 poss = anglePositionProps; 476 } 477 break; 478 case regexMultiProps.margin.test(prop): 479 propWithPos = 'margin' + '-' + '{{pos}}'; 480 break; 481 case regexMultiProps.padding.test(prop): 482 propWithPos = 'padding' + '-' + '{{pos}}'; 483 break; 484 case regexMultiProps.borderImage.test(prop): 485 propWithPos = 'border-image' + '-' + '{{pos}}'; 486 break; 487 case regexMultiProps.inset.test(prop): 488 propWithPos = '{{pos}}'; 489 break; 490 default: 491 poss = ['']; 492 propWithPos = prop; 493 break; 494 } 495 listProps = poss.map(x => propWithPos.replace('{{pos}}', x)); 496 return { 497 'positions': poss, 498 'propWithPos': propWithPos, 499 'props': listProps 500 }; 501} 502function getAllValuePos(element, pseudoElement, prop) { 503 let p = 0; 504 let value = ''; 505 let valueRender = ''; 506 let infosMulti = getInfoFromMultiProps(prop); 507 let propWithPos = infosMulti.propWithPos; 508 let poss = infosMulti.positions; 509 let match = null; 510 let unit = null; 511 let parentComputed = ''; 512 let othersProps = {}; 513 514 // Construire la liste des props à lire (ex: margin-top, margin-right, etc.) 515 let allProps = poss.map(p => propWithPos.replace('{{pos}}', p)); 516 517 // === Phase 1 : lectures sans modification DOM (état normal) === 518 // Un seul getComputedStyle pour toutes les positions 519 const computedNormal = window.getComputedStyle(element, pseudoElement); 520 let fontSize = computedNormal.getPropertyValue('font-size'); 521 522 // Lire toutes les valeurs en px (état normal = visible) 523 let normalValues = {}; 524 allProps.forEach(p => { 525 let val = computedNormal.getPropertyValue(p); 526 if (deviceRatioProps.includes(prop)) { 527 val = convertDevicePixelRatio(val); 528 } 529 normalValues[p] = val; 530 }); 531 if (prop !== 'inset') { 532 parentComputed = computedNormal.getPropertyValue(getPropRefForPercent(prop)); 533 parentComputed = convertDevicePixelRatio(parentComputed); 534 } 535 if (prop === 'inset') { 536 othersProps['transform'] = getTranslateValues(element); 537 othersProps['transformTranslateX'] = getPercentFromTwoValue(othersProps['transform'].x, element.offsetWidth) + '%'; 538 } 539 540 // === Phase 2 : lecture avec display:none (valeurs d'origine, %) === 541 // Un seul toggle display:none pour toutes les positions 542 element.style.display = 'none'; 543 const computedHidden = window.getComputedStyle(element, pseudoElement); 544 let hiddenValues = {}; 545 allProps.forEach(p => { 546 let val = computedHidden.getPropertyValue(p); 547 if (deviceRatioProps.includes(prop)) { 548 val = convertDevicePixelRatio(val); 549 } 550 hiddenValues[p] = val; 551 }); 552 element.style.removeProperty('display'); 553 554 // === Phase 3 : traitement des résultats (sans reflow) === 555 let unitValues = null, 556 PosvalueInfos = {}; 557 poss.forEach(function (p) { 558 let thisProps = propWithPos.replace('{{pos}}', p);
559 let valuePos = hiddenValues[thisProps]; // valeur avec display:none (%) 560 let valuePosPixel = normalValues[thisProps]; // valeur normale (px) 561 562 if (prop === 'inset') { 563 if (element.offsetParent !== null) { 564 const positionElement = getDefaultValueCss(element, null, getPropRefForPercent('position')); 565 let offsetParent = element.parentNode; 566 switch (positionElement) { 567 case 'static': 568 case 'relative': 569 offsetParent = element.parentNode; 570 break; 571 default: 572 offsetParent = element.offsetParent; 573 break; 574 } 575 const sizeParent = window.getComputedStyle(offsetParent, null).getPropertyValue(getPropRefForPercent(thisProps)); 576 switch (true) { 577 case thisProps === 'left': 578 case thisProps === 'right': 579 const paddingLeft = getValueInfos(getDefaultValueCss(offsetParent, null, 'padding-left')); 580 const paddingRight = getValueInfos(getDefaultValueCss(offsetParent, null, 'padding-right')); 581 const parentWidth = getValueInfos(sizeParent); 582 parentComputed += (parentComputed === '' ? '' : ' ') + (parentWidth.value - paddingLeft.value - paddingRight.value) + parentWidth.unit; 583 break; 584 case thisProps === 'top': 585 case thisProps === 'bottom': 586 const paddingTop = getValueInfos(getDefaultValueCss(offsetParent, null, 'padding-top')); 587 const paddingBottom = getValueInfos(getDefaultValueCss(offsetParent, null, 'padding-bottom')); 588 const parentHeight = getValueInfos(sizeParent); 589 parentComputed += (parentComputed === '' ? '' : ' ') + (parentHeight.value - paddingTop.value - paddingBottom.value) + parentHeight.unit; 590 break; 591 default: 592 parentComputed += (parentComputed === '' ? '' : ' ') + sizeParent; 593 break; 594 } 595 } 596 } 597 // on se base sur la premier unité trouvé (px, em, %) 598 let valueInfos = getValueInfos(valuePos, prop); 599 if (valueInfos.unit !== null && unitValues === null) { 600 unitValues = valueInfos.unit; 601 } 602 PosvalueInfos[thisProps] = { 603 'valueInfos': valueInfos, 604 'value': valuePos, 605 'valuePx': valuePosPixel 606 }; 607 }); 608 unitValues = unitValues === null ? 'px' : unitValues; 609 for (let p in PosvalueInfos) { 610 let valueInfos = PosvalueInfos[p].valueInfos; 611 let valuePosPixel = PosvalueInfos[p].valuePx; 612 if (valueInfos.unit === null) { 613 valueInfos.unit = unitValues; 614 } 615 switch (true) { 616 default: 617 value += (value === '' ? '' : ' ') + valueInfos.origin; 618 break; 619 } 620 valueRender += (valuePosPixel === '' ? '' : ' ') + valuePosPixel; 621 } 622 return { 623 'origin': value, 624 'computed': valueRender, 625 'fontSize': fontSize, 626 'parentComputed': parentComputed, 627 'othersProps': othersProps 628 }; 629} 630const getShortValueCss = function (element, pseudoElement, prop, unitDefault = null) { 631 switch (true) { 632 case /border|margin$|padding$|inset$/.test(prop): 633 return getAllValuePos(element, pseudoElement, prop); 634 default: 635 let value = getDefaultValueCss(element, pseudoElement, prop); 636 let parentComputed; 637 let parentWidth; 638 let parentHeight; 639 const positionElement = getDefaultValueCss(element, null, getPropRefForPercent('position')); 640 let offsetParent = element.parentNode; 641 switch (positionElement) { 642 case 'static': 643 case 'relative': 644 offsetParent = element.parentNode; 645 break; 646 default: 647 offsetParent = element.offsetParent; 648 break; 649 } 650 switch (prop) { 651 case 'top': 652 case 'bottom': 653 const paddingTop = getValueInfos(getDefaultValueCss(offsetParent, null, 'padding-top')); 654 const paddingBottom = getValueInfos(getDefaultValueCss(offsetParent, null, 'padding-bottom')); 655 parentHeight = getValueInfos(parentComputed); 656 parentComputed = parentHeight.value - paddingTop.value - paddingBottom.value + parentHeight.unit; 657 break; 658 case 'left': 659 case 'right': 660 const paddingLeft = getValueInfos(getDefaultValueCss(offsetParent, null, 'padding-left')); 661 const paddingRight = getValueInfos(getDefaultValueCss(offsetParent, null, 'padding-right')); 662 parentWidth = getValueInfos(parentComputed); 663 parentComputed = parentWidth.value - paddingLeft.value - paddingRight.value + parentWidth.unit; 664 break; 665 default: 666 parentComputed = getDefaultValueCss(element.nodeName === 'BODY' ? element : element.parentNode, null, getPropRefForPercent(prop)); 667 break; 668 } 669 let fontSize = getDefaultValueCss(element, pseudoElement, 'font-size'); 670
671 // Option I : seuls les props convertibles en viewport (px â vw/vh) 672 // nécessitent la branche origin=true (qui lit en display:none + states vw/vh). 673 // Pour color/font-family/etc., origin === value â on évite N reflows inutiles. 674 let origin; 675 if (viewportConvertibleProps.has(prop)) { 676 origin = getDefaultValueCss(element, pseudoElement, prop, true); 677 } else { 678 origin = value; 679 } 680 let originInfo = getValueInfos(origin, prop); 681 if (unitDefault !== null && originInfo.unit !== unitDefault) { 682 origin = convertUnit(element, pseudoElement, prop, value, unitDefault) + unitDefault; 683 } 684 return { 685 'origin': origin, 686 'computed': value, 687 'fontSize': fontSize, 688 'parentComputed': parentComputed, 689 'othersProps': {} 690 }; 691 } 692}; 693function getValuesByPosition(prop, value) { 694 let p = 0; 695 let infosMulti = getInfoFromMultiProps(prop); 696 let propWithPos = infosMulti.propWithPos; 697 let poss = infosMulti.positions; 698 let values = {}; 699 if (typeof value === "undefined" || value === '' || value === null) { 700 value = '0 0 0 0'; 701 } 702 value = value.trim(); 703 let splitValue = []; 704 if (regexFunctionCss.test(value)) { 705 splitValue = value.match(regexFunctionCssGlobal); 706 } else { 707 splitValue = value.split(' '); 708 } 709 let matchValue = new Array(4); 710 splitValue.forEach(function (val, index) { 711 matchValue[index] = val; 712 }); 713 714 // on nettoie les valeurs pour être sur de ne pas avoir de valeur indéfini 715 // Boucle indexée obligatoire : `new Array(4)` est un tableau CREUX et forEach 716 // saute les trous â la complétion ci-dessous ne s'exécutait donc jamais pour 717 // les positions absentes, et la fonction renvoyait moins de 4 clés (d'où un 718 // panneau rendu avec 2 inputs au lieu de 4). 719 // Borne sur `poss` et non sur 4 : une prop non positionnelle a poss = [''] et 720 // ne doit produire qu'une seule clé, comme avant. 721 for (let index = 0; index < poss.length; index++) { 722 let x = matchValue[index]; 723 if (typeof x === "undefined") { 724 if (index) { 725 switch (index) { 726 case 1: 727 // Si les valeurs la valeur suivante et indéfini, on prend la premiere valeur 728 // Pour la simplifier du type : padding: 20px; 729 matchValue[index] = typeof matchValue[2] === "undefined" ? matchValue[0] : 0; 730 break; 731 case 2: 732 matchValue[index] = matchValue[0]; 733 break; 734 case 3: 735 matchValue[index] = matchValue[1]; 736 break; 737 } 738 } else { 739 matchValue[index] = 0; 740 } 741 } 742 let propName = propWithPos.replace('{{pos}}', poss[index]); 743 values[propName] = matchValue[index]; 744 } 745 return values; 746} 747const getDecodeShortValue = function (prop, value) { 748 return getValuesByPosition(prop, value); 749}; 750 751/* ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 752 * Expansion des shorthands CSS en longhands 753 * 754 * Le panneau design repose sur un invariant : le store (CSSRule/CSSRuleTemp) ne 755 * contient que des longhands. Une clé shorthand (`border`, `margin`â¦) y est 756 * orpheline : aucun tool ne la vise, `propReset` ne peut pas l'effacer et le 757 * `delete` du commit â qui opère par clé exacte â ne l'atteint jamais. Elle est 758 * donc régénérée indéfiniment. Ces helpers rétablissent l'invariant. 759 * 760 * â ï¸ Ne PAS confondre avec getValuesByPosition ci-dessus : celui-ci décode le 761 * format *interne* de l'éditeur, dont l'ordre est celui de `positionProps` 762 * (top/left/bottom/right). Les fonctions qui suivent parsent du CSS *réel*, 763 * dont l'ordre est top/right/bottom/left. Les deux ordres diffèrent : réutiliser 764 * l'un pour l'autre intervertit gauche et droite. 765 * ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ */ 766 767// Ordres du CSS réel (â positionProps / anglePositionProps, qui sont internes) 768const cssSidesOrder = ['top', 'right', 'bottom', 'left']; 769const cssCornersOrder = ['top-left', 'top-right', 'bottom-right', 'bottom-left']; 770 771// Mots-clés de border-style : seul discriminant fiable des composants d'un `border:` 772const borderStyleKeywords = new Set(['none', 'hidden', 'solid', 'dashed', 'dotted', 'double', 'groove', 'ridge', 'inset', 'outset']); 773const borderWidthKeywords = new Set(['thin', 'medium', 'thick']); 774 775// Valeurs globales : expansion impossible sans connaître le contexte de cascade 776const cssGlobalValues = new Set(['inherit', 'initial', 'unset', 'revert', 'revert-layer']); 777 778// Shorthands positionnels : une valeur, quatre côtés/coins de la MÃME propriété 779const positionalShorthands = { 780 'margin': { 781 'template': 'margin-{{pos}}', 782 'order': cssSidesOrder 783 }, 784 'padding': { 785 'template': 'padding-{{pos}}', 786 'order': cssSidesOrder 787 }, 788 'inset': { 789 'template': '{{pos}}', 790 'order': cssSidesOrder 791 }, 792 'border-width': { 793 'template': 'border-{{pos}}-width', 794 'order': cssSidesOrder 795 }, 796 'border-radius': { 797 'template': 'border-{{pos}}-radius', 798 'order': cssCornersOrder 799 }, 800 // border-color / border-style sont positionnels en CSS, mais le panneau les 801 // édite via un tool ATOMIQUE (clé littérale, appliquée aux 4 côtés). Ils ne 802 // sont éclatés que si la valeur est réellement non-uniforme : cf. _expandBorderSideProp. 803 'border-color': { 804 'template': 'border-{{pos}}-color', 805 'order': cssSidesOrder 806 }, 807 'border-style': { 808 'template': 'border-{{pos}}-style', 809 'order': cssSidesOrder 810 } 811}; 812 813/** 814 * Découpe une valeur CSS en tokens sans casser les fonctions (rgba(), var(), calc()â¦). 815 * @param {string} value 816 * @returns {string[]} 817 */ 818function tokenizeCssValue(value) { 819 const tokens = String(value).trim().match(regexFunctionCssGlobal); 820 return tokens === null ? [] : tokens.filter(token => token !== ''); 821} 822 823/** 824 * Applique la règle CSS 1/2/3/4 valeurs, en ordre CSS réel (top right bottom left). 825 * @param {string[]} tokens 826 * @returns {string[]|null} les 4 valeurs, ou null si le nombre de tokens est invalide 827 */ 828function spreadPositionalTokens(tokens) { 829 switch (tokens.length) { 830 case 1: 831 return [tokens[0], tokens[0], tokens[0], tokens[0]]; 832 case 2: 833 return [tokens[0], tokens[1], tokens[0], tokens[1]]; 834 case 3: 835 return [tokens[0], tokens[1], tokens[2], tokens[1]]; 836 case 4: 837 return [tokens[0], tokens[1], tokens[2], tokens[3]]; 838 default: 839 return null; 840 } 841} 842 843/** 844 * Nature d'un token d'un shorthand `border` : 'width', 'style', 'color' ou null si ambigu. 845 * @param {string} token 846 * @returns {string|null} 847 */ 848function getBorderComponentType(token) { 849 const lower = token.toLowerCase(); 850 if (borderStyleKeywords.has(lower)) { 851 return 'style'; 852 } 853 if (borderWidthKeywords.has(lower)) { 854 return 'width'; 855 } 856 // var() peut porter aussi bien une largeur qu'une couleur : indécidable ici 857 if (/^var\(/i.test(lower)) { 858 return null; 859 } 860 if (/^calc\(/i.test(lower)) { 861 return 'width'; 862 } 863 // Longueur : un nombre suivi d'une unité valide (ou nu, cas du 0) 864 const matchUnit = regexUnit.exec(token); 865 if (matchUnit !== null && typeof matchUnit[1] !== "undefined" && (typeof matchUnit[2] === "undefined" || isValidCSSUnit(matchUnit[2]))) { 866 return 'width'; 867 } 868 if (/^(#[0-9a-f]{3,8}|(rgba?|hsla?|color|color-mix)\(|transparent$|currentcolor$|[a-z]+$)/i.test(lower)) { 869 return 'color'; 870 } 871 return null; 872} 873 874/** 875 * Expanse un `border-color` / `border-style` isolé. 876 * Collapse vers la clé atomique quand les 4 côtés sont identiques : c'est ce 877 * qu'écrit le tool du panneau, et le seul format qu'il sait relire et réinitialiser. 878 * @param {string} prop 879 * @param {string} value 880 * @returns {object|null} 881 */ 882function expandBorderSideProp(prop, value) { 883 const tokens = tokenizeCssValue(value); 884 const spread = spreadPositionalTokens(tokens); 885 if (spread === null) { 886 return null; 887 } 888 if (new Set(spread).size === 1) { 889 const atomic = {}; 890 atomic[prop] = spread[0]; 891 return atomic; 892 } 893 const config = positionalShorthands[prop]; 894 const expanded = {}; 895 config.order.forEach(function (pos, index) { 896 expanded[config.template.replace('{{pos}}', pos)] = spread[index]; 897 }); 898 return expanded; 899} 900 901/** 902 * Vrai si la propriété est un shorthand du périmètre traité (familles éditées en 903 * longhand par le panneau design). Sert à ne signaler que les cas pertinents. 904 * @param {string} prop 905 * @returns {boolean} 906 */ 907function isTargetedShorthand(prop) { 908 if (typeof prop !== 'string') { 909 return false;
910 } 911 return /^border(-(top|right|bottom|left))?$/.test(prop) || positionalShorthands.hasOwnProperty(prop); 912} 913 914/** 915 * Décompose une propriété CSS shorthand en ses longhands. 916 * 917 * Périmètre : les familles que le panneau design édite en longhand â `border`, 918 * `border-<côté>`, `border-width`, `border-style`, `border-color`, `border-radius`, 919 * `margin`, `padding`, `inset`. Volontairement pas `background`/`font`/`flex`. 920 * 921 * Renvoie null (et non une expansion approximative) dès qu'un doute existe : 922 * valeur globale, rayons elliptiques, token indécidable, composant en double. 923 * L'appelant conserve alors la déclaration telle quelle plutôt que de la fausser. 924 * 925 * @param {string} prop 926 * @param {string} value 927 * @returns {object|null} map longhand â valeur, ou null si non décomposable 928 */ 929function expandShorthandToLonghands(prop, value) { 930 if (typeof prop !== 'string' || typeof value !== 'string') { 931 return null; 932 } 933 const cleanValue = value.trim(); 934 if (cleanValue === '' || cleanValue === 'remove' || cssGlobalValues.has(cleanValue.toLowerCase())) { 935 return null; 936 } 937 938 // border-color / border-style : atomiques tant que la valeur est uniforme 939 if (prop === 'border-color' || prop === 'border-style') { 940 return expandBorderSideProp(prop, cleanValue); 941 } 942 943 // Shorthands positionnels 944 if (positionalShorthands.hasOwnProperty(prop)) { 945 // Rayons elliptiques (`border-radius: 10px / 20px`) : hors périmètre 946 if (prop === 'border-radius' && cleanValue.indexOf('/') !== -1) { 947 return null; 948 } 949 const spread = spreadPositionalTokens(tokenizeCssValue(cleanValue)); 950 if (spread === null) { 951 return null; 952 } 953 const config = positionalShorthands[prop]; 954 const expanded = {}; 955 config.order.forEach(function (pos, index) { 956 expanded[config.template.replace('{{pos}}', pos)] = spread[index]; 957 }); 958 return expanded; 959 } 960 961 // Shorthands composites `border` / `border-<côté>` : width | style | color, ordre libre 962 const matchBorderSide = /^border(?:-(top|right|bottom|left))?$/.exec(prop); 963 if (matchBorderSide === null) { 964 return null; 965 } 966 const components = {}; 967 const tokens = tokenizeCssValue(cleanValue); 968 if (tokens.length === 0 || tokens.length > 3) { 969 return null; 970 } 971 const ambiguous = []; 972 for (const token of tokens) { 973 const type = getBorderComponentType(token); 974 if (type === null) { 975 ambiguous.push(token); 976 continue; 977 } 978 // Deux tokens de même nature : valeur mal formée, on ne devine pas 979 if (components.hasOwnProperty(type)) { 980 return null; 981 } 982 components[type] = token; 983 } 984 985 // Un token indécidable (typiquement var()) se résout par élimination, mais 986 // seulement s'il ne reste qu'une seule nature possible. 987 if (ambiguous.length) { 988 const remaining = ['width', 'style', 'color'].filter(type => !components.hasOwnProperty(type)); 989 if (ambiguous.length !== 1 || remaining.length !== 1) { 990 return null; 991 } 992 components[remaining[0]] = ambiguous[0]; 993 } 994 const expanded = {}; 995 const side = matchBorderSide[1]; 996 if (side) { 997 // Un seul côté concerné : les trois longhands existent tels quels 998 Object.keys(components).forEach(function (type) { 999 expanded['border-' + side + '-' + type] = components[type]; 1000 }); 1001 return expanded; 1002 } 1003 1004 // `border` uniforme : la largeur s'écrit par côté (format du tool border-width), 1005 // le style et la couleur restent atomiques (format de leurs tools respectifs). 1006 if (components.hasOwnProperty('width')) { 1007 cssSidesOrder.forEach(function (pos) { 1008 expanded['border-' + pos + '-width'] = components.width; 1009 }); 1010 } 1011 if (components.hasOwnProperty('style')) { 1012 expanded['border-style'] = components.style; 1013 } 1014 if (components.hasOwnProperty('color')) { 1015 expanded['border-color'] = components.color; 1016 } 1017 return expanded; 1018} 1019 1020/** 1021 * Normalise les déclarations d'un sélecteur : expanse les shorthands du périmètre 1022 * et supprime leur clé, de sorte que seuls des longhands subsistent. 1023 * 1024 * La cascade est reproduite par l'ordre d'insertion des clés â le même que celui 1025 * utilisé pour générer le CSS final (`for (let prop in â¦)` dans _saveStyleSheet), 1026 * donc le seul qui reflète quelle déclaration l'emporte réellement. Réaffecter une 1027 * clé existante en JS change sa valeur sans déplacer sa position : une passe unique 1028 * suffit à obtenir « dernière déclaration gagne ». 1029 *
1030 * Ex. {margin:'10px', margin-top:'0', margin-right:'0'} â top 0, right 0, bottom 10px, left 10px. 1031 * à l'inverse, un longhand placé AVANT le shorthand est écrasé par celui-ci : ce 1032 * n'est pas un défaut, c'est la cascade CSS rendue fidèlement. 1033 * 1034 * Une déclaration non décomposable est conservée intacte (on ne perd jamais de style). 1035 * 1036 * @param {object} declarations map prop â valeur d'un sélecteur 1037 * @returns {object} nouvelle map, longhands uniquement 1038 */ 1039function normalizeDeclarations(declarations) { 1040 if (declarations === null || typeof declarations !== 'object' || Array.isArray(declarations)) { 1041 return declarations; 1042 } 1043 const normalized = {}; 1044 for (const prop in declarations) { 1045 if (!declarations.hasOwnProperty(prop)) { 1046 continue; 1047 } 1048 const value = declarations[prop]; 1049 const expanded = isTargetedShorthand(prop) ? expandShorthandToLonghands(prop, value) : null; 1050 if (expanded === null) { 1051 normalized[prop] = value; 1052 continue; 1053 } 1054 for (const longhand in expanded) { 1055 if (expanded.hasOwnProperty(longhand)) { 1056 normalized[longhand] = expanded[longhand]; 1057 } 1058 } 1059 } 1060 return normalized; 1061} 1062 1063/** 1064 * Applique normalizeDeclarations à un store complet CSSRule[taille][sélecteur]. 1065 * Mute l'objet reçu (les stores sont partagés par référence) et le retourne. 1066 * @param {object} cssRule 1067 * @returns {object} le store normalisé 1068 */ 1069function normalizeCSSRuleStore(cssRule) { 1070 if (cssRule === null || typeof cssRule !== 'object') { 1071 return cssRule; 1072 } 1073 for (const sizeResponsive in cssRule) { 1074 if (!cssRule.hasOwnProperty(sizeResponsive) || cssRule[sizeResponsive] === null || typeof cssRule[sizeResponsive] !== 'object') { 1075 continue; 1076 } 1077 for (const selector in cssRule[sizeResponsive]) { 1078 if (!cssRule[sizeResponsive].hasOwnProperty(selector)) { 1079 continue; 1080 } 1081 cssRule[sizeResponsive][selector] = normalizeDeclarations(cssRule[sizeResponsive][selector]); 1082 } 1083 } 1084 return cssRule; 1085} 1086 1087/** 1088 * 1089 * @param value 1090 * @returns {{yOffset: string, xOffset: string, yPos: string, xPos: string}} 1091 */ 1092const getBackgroundPositionInfo = function (value) { 1093 let regexValueOneWord = /^([a-z]+)$/gi; 1094 let regexValueAll = /^(?:(?<xPos>[a-z]+)?\s?(?<xOffset>[0-9-.]+[a-z%]{0,5})?)\s(?:(?<yPos>[a-z]+)?\s?(?<yOffset>[0-9-.]+[a-z%]{0,5})?)/gi; 1095 let m = regexValueAll.exec(value); 1096 let info = { 1097 xPos: '', 1098 xOffset: '', 1099 yPos: '', 1100 yOffset: '' 1101 }; 1102 if (m) { 1103 let values = m.groups; 1104 let positionX = null, 1105 positionY = null; 1106 let newValue = ''; 1107 if (!values.xPos && values.xOffset) { 1108 switch (values.xOffset) { 1109 case '0%': 1110 positionX = 'left'; 1111 values.xOffset = ''; 1112 break; 1113 case '50%': 1114 positionX = 'center'; 1115 values.xOffset = ''; 1116 break; 1117 case '100%': 1118 positionX = 'right'; 1119 values.xOffset = ''; 1120 break; 1121 } 1122 } 1123 if (positionX === null) { 1124 positionX = values.xPos ?? 'left'; 1125 } 1126 if (!values.yPos && values.yOffset) { 1127 switch (values.yOffset) { 1128 case '0%': 1129 positionY = 'top'; 1130 values.yOffset = ''; 1131 break; 1132 case '50%': 1133 positionY = 'center'; 1134 values.yOffset = ''; 1135 break; 1136 case '100%': 1137 positionY = 'bottom'; 1138 values.yOffset = ''; 1139 break; 1140 } 1141 } 1142 if (positionY === null) { 1143 positionY = values.yPos ?? 'top'; 1144 } 1145 info.xPos = positionX; 1146 info.xOffset = values.xOffset ?? ''; 1147 info.yPos = positionY; 1148 info.yOffset = values.yOffset ?? ''; 1149 } else { 1150 m = regexValueOneWord.exec(value); 1151 if (m) { 1152 info.xPos = info.yPos = m[1]; 1153 } 1154 } 1155 return info; 1156}; 1157function getBackgroundPositionString(info) { 1158 let value = ''; 1159 if (info.xPos) { 1160 value += info.xPos; 1161 if (info.xOffset) { 1162 value += ' ' + info.xOffset; 1163 } 1164 } 1165 if (info.yPos) { 1166 value += ' ' + info.yPos; 1167 if (info.yOffset) { 1168 value += ' ' + info.yOffset; 1169 } 1170 } 1171 return value; 1172} 1173 1174/**
1175 * Valeur CSS de Background Position 1176 * Permet de concervertir par exemple "0% 0%" en "left top" 1177 * @param value 1178 * @returns {string} 1179 */ 1180const convertBackgroundPositionToString = function (value) { 1181 let info = getBackgroundPositionInfo(value); 1182 return info.xPos + ' ' + info.yPos; 1183}; 1184 1185/** 1186 * 1187 * @param value 1188 * @returns {{ySize: string, xSize: string, keyword: string}} 1189 */ 1190const getBackgroundSizeInfo = function (value) { 1191 let regexValueAll = /^(?:(?<xSize>(?:(?:[0-9-.]+[a-z%]{0,5})|auto))?\s(?:(?<ySize>(?:(?:[0-9-.]+[a-z%]{0,5})|auto))?)|(?<keyword>contain|cover)|(?:(?<xySize>(?:(?:[0-9-.]+[a-z%]{0,5})|auto))?))$/gi; 1192 let m = regexValueAll.exec(value); 1193 let info = { 1194 xSize: 'auto', 1195 ySize: 'auto', 1196 keyword: '' 1197 }; 1198 if (m) { 1199 let values = m.groups; 1200 info.xSize = values.xSize ?? 'auto'; 1201 info.ySize = values.ySize ?? 'auto'; 1202 info.keyword = values.keyword ?? ''; 1203 if (values.xySize) { 1204 info.xSize = info.ySize = values.xySize; 1205 } 1206 return info; 1207 } 1208 return info; 1209}; 1210 1211/** 1212 * Dégradé par défaut appliqué au fond quand l'outil ToolsDesign "background-clip" 1213 * (rognage du texte) est activé sans fond image existant. 1214 * @type {string} 1215 */ 1216const DEFAULT_CLIP_TEXT_GRADIENT = 'linear-gradient(90deg, rgb(148, 225, 198) 11%, rgb(72, 61, 139) 32%, rgb(148, 225, 198) 54%, rgb(72, 61, 139) 77%, rgb(148, 225, 198) 100%)'; 1217 1218/** 1219 * Récupére les différentes valeurs d'un valeur Background Image 1220 * @param {string} originalValue 1221 * @returns {Array} 1222 */ 1223const getBackgroundImageValue = function (originalValue) { 1224 if (!originalValue || !originalValue.trim()) return []; 1225 1226 // Découpe top-level en respectant la profondeur de parenthèses (gradient()/rgba()/url()).
1227 // splitTopLevel (déclaré plus bas, hoisté) remplace l'ancienne regex qui tronquait 1228 // le dernier calque contenant un rgba(...) suivi d'autres stops. 1229 const parts = splitTopLevel(originalValue, ',').map(function (s) { 1230 return s.trim(); 1231 }).filter(Boolean); 1232 const results = []; 1233 parts.forEach(function (part) { 1234 const match = part.match(/^([a-zA-Z-]+)\(([\s\S]*)\)$/); 1235 if (!match) return; 1236 // value = contenu interne ; on retire d'éventuels guillemets (cas url("...")). 1237 const value = match[2].trim().replace(/^["']|["']$/g, ''); 1238 results.push({ 1239 'origin': part, 1240 'type': match[1], 1241 'value': value 1242 }); 1243 }); 1244 return results; 1245}; 1246 1247/** 1248 * Utilitaire interne : split top-level. 1249 * Découpe `str` sur `sep` en ignorant les séparateurs à l'intérieur de parenthèses. 1250 * Exemple : splitTopLevel("rgba(0,0,0,.5) 0%, red 100%") â ["rgba(0,0,0,.5) 0%", " red 100%"] 1251 * @param {string} str 1252 * @param {string} sep séparateur (default ',') 1253 * @returns {string[]} 1254 */ 1255function splitTopLevel(str, sep = ',') { 1256 const parts = []; 1257 let depth = 0; 1258 let current = ''; 1259 for (let i = 0; i < str.length; i++) { 1260 const ch = str[i]; 1261 if (ch === '(') { 1262 depth++; 1263 current += ch; 1264 } else if (ch === ')') { 1265 depth--; 1266 current += ch; 1267 } else if (depth === 0 && str.startsWith(sep, i)) { 1268 parts.push(current); 1269 current = ''; 1270 i += sep.length - 1; 1271 } else { 1272 current += ch; 1273 } 1274 } 1275 parts.push(current); 1276 return parts; 1277} 1278 1279/** 1280 * Parse les stops d'un gradient. 1281 * Chaque stop est "<color> <pos>" ou "<color>" (pos optionnel). 1282 * Gère les couleurs fonctionnelles (rgba(...), hsl(...), etc.) via splitTopLevel. 1283 * @param {string[]} rawStops segments top-level déjà splittés 1284 * @returns {{color: string, pos: string}[]} 1285 */ 1286function parseGradientStops(rawStops) { 1287 return rawStops.map(function (stop) { 1288 const s = stop.trim(); 1289 // Cherche une position à la fin : <nombre><unité> ou <nombre>% (éventuellement précédé d'un espace) 1290 const posMatch = s.match(/\s+([\d.]+(?:%|px|em|rem|vw|vh|pt|cm|mm|in|turn|deg|grad|rad))\s*$/i); 1291 if (posMatch) { 1292 return { 1293 color: s.slice(0, s.length - posMatch[0].length).trim(), 1294 pos: posMatch[1] 1295 }; 1296 } 1297 return { 1298 color: s, 1299 pos: '' 1300 }; 1301 }); 1302} 1303 1304/** 1305 * Parse la valeur intérieure d'un gradient CSS (ce qu'il y a entre les parenthèses). 1306 * Reçoit une entrée {type, value} issue de getBackgroundImageValue où type est *-gradient. 1307 * 1308 * Retourne pour linear-gradient : {angle, stops} 1309 * Retourne pour radial-gradient : {shape, size, position, stops} 1310 * Retourne pour conic-gradient : {angle, position, stops} 1311 * 1312 * Heuristique pour distinguer le préfixe géométrique des stops : 1313 * - linear : 1er segment top-level est l'angle s'il matche /^(to\s|[\d.]+(deg|grad|rad|turn))/i 1314 * - radial : 1er segment est le préfixe s'il contient circle|ellipse|at |from |closest|farthest 1315 * ET ne commence pas par une syntaxe de couleur 1316 * - conic : même heuristique que radial (from ⦠at â¦) 1317 * 1318 * @param {{type: string, value: string}} typedEntry 1319 * @returns {Object} 1320 */ 1321const parseGradient = function (typedEntry) { 1322 const type = typedEntry.type; 1323 const segments = splitTopLevel(typedEntry.value, ','); 1324 if (type === 'linear-gradient') { 1325 // Heuristique : le 1er segment est l'angle s'il matche to <dir> ou une valeur angulaire 1326 const first = segments[0].trim(); 1327 const isAngle = /^(to\s|[\d.]+(deg|grad|rad|turn))/i.test(first); 1328 let angle = '180deg'; 1329 let stopSegments; 1330 if (isAngle) { 1331 angle = first; 1332 stopSegments = segments.slice(1); 1333 } else { 1334 stopSegments = segments; 1335 } 1336 return { 1337 angle, 1338 stops: parseGradientStops(stopSegments) 1339 }; 1340 } 1341 if (type === 'radial-gradient') { 1342 // Heuristique : 1er segment est le préfixe géométrique s'il contient des mots-clés de forme/taille/position 1343 const first = segments[0].trim(); 1344 const isGeometric = /^(circle|ellipse)\b/i.test(first) || /\bat\b/i.test(first) || /^(closest-side|closest-corner|farthest-side|farthest-corner)\b/i.test(first); 1345 let stopSegments; 1346 let shape = 'ellipse'; 1347 let size = ''; 1348 let position = ''; 1349 if (isGeometric) { 1350 stopSegments = segments.slice(1); 1351 // Sépare la partie avant "at" (shape + size) de la position après "at" 1352 const atIdx = first.search(/\bat\b/i); 1353 let shapeSize = atIdx !== -1 ? first.slice(0, atIdx).trim() : first; 1354 if (atIdx !== -1) { 1355 position = first.slice(atIdx + 2).trim(); 1356 } 1357 // shape = circle | ellipse (premier mot si présent) 1358 const shapeMatch = shapeSize.match(/^(circle|ellipse)/i); 1359 if (shapeMatch) { 1360 shape = shapeMatch[1].toLowerCase(); 1361 shapeSize = shapeSize.slice(shapeMatch[0].length).trim(); 1362 } 1363 // size = tout ce qui reste après le shape (longueur explicite ou mot-clé, ex "1000px 600px", "closest-side", "") 1364 size = shapeSize.trim(); 1365 } else { 1366 stopSegments = segments; 1367 } 1368 return { 1369 shape, 1370 size, 1371 position, 1372 stops: parseGradientStops(stopSegments) 1373 }; 1374 } 1375 if (type === 'conic-gradient') { 1376 const first = segments[0].trim(); 1377 const isGeometric = /\bfrom\b/i.test(first) || /\bat\b/i.test(first); 1378 let stopSegments; 1379 let angle = ''; 1380 let position = ''; 1381 if (isGeometric) { 1382 stopSegments = segments.slice(1); 1383 // from <angle> 1384 const fromMatch = first.match(/\bfrom\s+([\d.]+(?:deg|grad|rad|turn))/i); 1385 if (fromMatch) { 1386 angle = fromMatch[1]; 1387 } 1388 // at <position> 1389 const atMatch = first.match(/\bat\s+(.+)$/i); 1390 if (atMatch) { 1391 position = atMatch[1].trim(); 1392 } 1393 } else { 1394 stopSegments = segments; 1395 } 1396 return { 1397 angle, 1398 position, 1399 stops: parseGradientStops(stopSegments) 1400 }; 1401 } 1402 1403 // Type inconnu : retour minimal 1404 return { 1405 stops: [] 1406 }; 1407}; 1408 1409/** 1410 * Génère la chaîne CSS complète d'un gradient depuis un objet calque. 1411 * Inverse de parseGradient â garantit un round-trip stable. 1412 * 1413 * @param {{type: string, angle?: string, shape?: string, size?: string, position?: string, stops: {color: string, pos: string}[]}} layer 1414 * @returns {string} ex: "linear-gradient(90deg, red 0%, blue 100%)" 1415 */ 1416const generateGradient = function (layer) { 1417 const sortedStops = (layer.stops || []).slice().sort(function (a, b) { 1418 return (parseFloat(a.pos) || 0) - (parseFloat(b.pos) || 0); 1419 }); 1420 const stopsStr = sortedStops.map(function (stop) { 1421 return stop.pos ? stop.color + ' ' + stop.pos : stop.color; 1422 }).join(', '); 1423 if (layer.type === 'linear-gradient') { 1424 const anglePart = layer.angle ? layer.angle + ', ' : ''; 1425 return 'linear-gradient(' + anglePart + stopsStr + ')'; 1426 } 1427 if (layer.type === 'radial-gradient') { 1428 const parts = []; 1429 if (layer.shape) parts.push(layer.shape); 1430 if (layer.size) parts.push(layer.size); 1431 if (layer.position) parts.push('at ' + layer.position); 1432 const prefix = parts.length ? parts.join(' ') + ', ' : ''; 1433 return 'radial-gradient(' + prefix + stopsStr + ')'; 1434 } 1435 if (layer.type === 'conic-gradient') { 1436 const parts = []; 1437 if (layer.angle) parts.push('from ' + layer.angle); 1438 if (layer.position) parts.push('at ' + layer.position); 1439 const prefix = parts.length ? parts.join(' ') + ', ' : ''; 1440 return 'conic-gradient(' + prefix + stopsStr + ')'; 1441 } 1442 return ''; 1443}; 1444 1445/** 1446 * Décompose les propriétés CSS background multi-calques en un tableau de calques alignés. 1447 * Chaque calque contient les infos image (type, url ou données gradient parsées) 1448 * et les options communes (position, size, repeat, attachment). 1449 * 1450 * Le nombre de calques est déterminé par le nombre d'entrées de background-image.
1451 * Les autres listes sont allongées/tronquées en conséquence avec des défauts CSS. 1452 * 1453 * @param {{ 1454 * 'background-image'?: string, 1455 * 'background-position'?: string, 1456 * 'background-size'?: string, 1457 * 'background-repeat'?: string, 1458 * 'background-attachment'?: string 1459 * }} values 1460 * @returns {Object[]} 1461 */ 1462const getBackgroundLayers = function (values, opts) { 1463 const rawImages = !!(opts && opts.rawImages); 1464 const imageEntries = getBackgroundImageValue(values['background-image'] || ''); 1465 1466 // Nombre de calques = nombre d'images (minimum 1 si tout est vide) 1467 const count = imageEntries.length || 1; 1468 1469 // Découpe top-level des autres props (peut être multi-valeurs séparées par virgule) 1470 const splitProp = function (rawValue) { 1471 if (!rawValue) return []; 1472 return splitTopLevel(rawValue, ',').map(function (s) { 1473 return s.trim(); 1474 }); 1475 }; 1476 const positions = splitProp(values['background-position']); 1477 const sizes = splitProp(values['background-size']); 1478 const repeats = splitProp(values['background-repeat']); 1479 const attachments = splitProp(values['background-attachment']); 1480 const getAt = function (arr, i, fallback) { 1481 return arr[i] !== undefined && arr[i] !== '' ? arr[i] : fallback; 1482 }; 1483 const layers = []; 1484 for (let i = 0; i < count; i++) { 1485 const entry = imageEntries[i]; 1486 const posStr = getAt(positions, i, 'left top'); 1487 const sizeStr = getAt(sizes, i, 'auto'); 1488 const layer = { 1489 type: entry ? entry.type : 'url', 1490 positionInfo: getBackgroundPositionInfo(posStr), 1491 sizeInfo: getBackgroundSizeInfo(sizeStr), 1492 repeat: getAt(repeats, i, 'no-repeat'), 1493 attachment: getAt(attachments, i, 'scroll') 1494 }; 1495 if (entry) { 1496 const isKnownGradient = /^(linear|radial|conic)-gradient$/.test(entry.type); 1497 if (entry.type === 'url') { 1498 layer.url = entry.value; 1499 } else if (rawImages || !isKnownGradient) { 1500 // Image non décomposable (repeating-*, formes complexes, ou mode forcé) : 1501 // on conserve la chaîne d'origine telle quelle pour un rendu fidèle. 1502 layer.type = 'raw'; 1503 layer.rawImage = entry.origin; 1504 } else { 1505 // Gradient connu : merge des propriétés parsées dans le calque 1506 const gradientData = parseGradient(entry); 1507 Object.assign(layer, gradientData); 1508 } 1509 } else { 1510 layer.url = ''; 1511 } 1512 layers.push(layer); 1513 } 1514 return layers; 1515}; 1516 1517/** 1518 * Génère les 5 propriétés CSS background longhand depuis un tableau de calques. 1519 * INVARIANT : les 5 listes ont exactement layers.length entrées (CSS sinon répète/tronque silencieusement). 1520 * Inverse de getBackgroundLayers â garantit un round-trip stable. 1521 * 1522 * @param {Object[]} layers tableau de calques (la clé `uid` est ignorée) 1523 * @returns {{ 1524 * 'background-image': string, 1525 * 'background-position': string, 1526 * 'background-size': string, 1527 * 'background-repeat': string, 1528 * 'background-attachment': string 1529 * }} 1530 */ 1531const generateBackgroundLonghands = function (layers) { 1532 const images = []; 1533 const positions = []; 1534 const sizesList = []; 1535 const repeatsList = []; 1536 const attachList = []; 1537 for (let i = 0; i < layers.length; i++) { 1538 const layer = layers[i]; 1539 1540 // --- background-image --- 1541 if (layer.type === 'url') { 1542 images.push('url("' + (layer.url || '') + '")'); 1543 } else if (layer.type === 'raw') { 1544 images.push(layer.rawImage || ''); 1545 } else { 1546 images.push(generateGradient(layer)); 1547 } 1548 1549 // --- background-position --- 1550 const posStr = layer.positionInfo ? getBackgroundPositionString(layer.positionInfo) : '0% 0%'; 1551 positions.push(posStr || '0% 0%'); 1552 1553 // --- background-size --- 1554 let sizeStr = 'auto'; 1555 if (layer.sizeInfo) { 1556 if (layer.sizeInfo.keyword) { 1557 sizeStr = layer.sizeInfo.keyword; 1558 } else { 1559 const x = layer.sizeInfo.xSize || 'auto'; 1560 const y = layer.sizeInfo.ySize || 'auto'; 1561 sizeStr = x + ' ' + y; 1562 } 1563 } 1564 sizesList.push(sizeStr); 1565 1566 // --- background-repeat --- 1567 repeatsList.push(layer.repeat || 'no-repeat'); 1568 1569 // --- background-attachment --- 1570 attachList.push(layer.attachment || 'scroll'); 1571 } 1572 return { 1573 'background-image': images.join(', '), 1574 'background-position': positions.join(', '), 1575 'background-size': sizesList.join(', '), 1576 'background-repeat': repeatsList.join(', '), 1577 'background-attachment': attachList.join(', ') 1578 }; 1579}; 1580const defaultPositionType = { 1581 "top": 0, 1582 "right": 0, 1583 "bottom": 0,
1584 "left": 0 1585}; 1586const generatePositionValue = function (data) { 1587 let value = ''; 1588 let first = true; 1589 const values = Object.assign({ 1590 ...defaultPositionType 1591 }, data); 1592 value += Object.values(values).join(' '); 1593 return value; 1594}; 1595const PSEUDO_ELEMENT = ['after', 'backdrop', 'before', 'cue', 'first-letter', 'first-line', 'grammar-error', 'marker', 'part', 'placeholder', 'selection', 'slotted', 'spelling-error']; 1596const PSEUDO_CLASS = ['active', 'any-link', 'blank', 'checked', 'current', 'default', 'defined', 'dir', 'disabled', 'drop', 'empty', 'enabled', 'first', 'first-child', 'first-of-type', 'fullscreen', 'future', 'focus', 'focus-visible', 'focus-within', 'has', 'host', 'host-context', 'hover', 'inderterminate', 'in-range', 'invalid', 'is', 'lang', 'last-child', 'last-of-type', 'left', 'link', 'local-link', 'not', 'nth-child', 'nth-col', 'nth-last-child', 'nth-last-col', 'nth-last-of-type', 'nth-of-type', 'only-child', 'only-of-type', 'optional', 'out-of-range', 'past', 'placeholder-shown', 'read-only', 'read-write', 'required', 'right', 'root', 'scope', 'target', 'target-within', 'user-invalid', 'valid', 'visited', 'where']; 1597const DISPLAY_VALUES = ['block', 'inline', 'run-in', 'flow', 'flow-root', 'table', 'flex', 'grid', 'list-item', 'table-row-group', 'table-header-group', 'table-footer-group', 'table-row', 'table-cell', 'table-cell', 'table-column-group', 'table-column', 'table-caption', 'contents', 'none', 'inline-block', 'inline-table', 'inline-flex', 'inline-grid']; 1598const regexDisplayValue = new RegExp(DISPLAY_VALUES.join('|')); 1599function getDefaultDisplayValue(originalValue) { 1600 switch (true) { 1601 case typeof originalValue === 'string' && regexDisplayValue.test(originalValue): 1602 return originalValue; 1603 case typeof originalValue === 'object' && originalValue.hasOwnProperty('display'): 1604 return originalValue.display; 1605 default: 1606 return 'block'; 1607 } 1608} 1609const regexPseudoElement = new RegExp(PSEUDO_ELEMENT.join('|')); 1610const regexPseudoClass = new RegExp(PSEUDO_CLASS.join('|')); 1611 1612/** 1613 * 1614 * @param pseudo string 1615 * @returns string 1616 */ 1617function getPseudoFormatByName(pseudo) { 1618 switch (true) { 1619 case regexPseudoElement.test(pseudo): 1620 return '::' + pseudo; 1621 case regexPseudoClass.test(pseudo): 1622 return ':' + pseudo; 1623 default: 1624 return false; 1625 } 1626} 1627const regexUnit = /(?:^([-0-9.,]+)([^0-9.,-]+)?)|(auto)/; 1628 1629// Unités CSS valides (longueur, temps, fréquence, résolution, pourcentage, sans unité) 1630const validCSSUnits = new Set([ 1631// Longueur absolue 1632'px', 'cm', 'mm', 'in', 'pt', 'pc', 'Q', 1633// Longueur relative 1634'em', 'rem', 'ex', 'rex', 'cap', 'rcap', 'ch', 'rch', 'ic', 'ric', 'lh', 'rlh', 'vw', 'vh', 'vmin', 'vmax', 'vi', 'vb', 'svw', 'svh', 'lvw', 'lvh', 'dvw', 'dvh', 'cqw', 'cqh', 'cqi', 'cqb', 'cqmin', 'cqmax', 1635// Pourcentage 1636'%', 1637// Temps 1638's', 'ms', 1639// Fréquence 1640'Hz', 'kHz', 1641// Résolution 1642'dpi', 'dpcm', 'dppx', 'x', 1643// Angle 1644'deg', 'grad', 'rad', 'turn', 1645// Flex 1646'fr', 1647// Sans unité (interne éditeur) 1648'ratio', 'int']); 1649function isValidCSSUnit(unit) { 1650 return typeof unit === 'string' && validCSSUnits.has(unit); 1651} 1652 1653/** 1654 * Trouvé l'unité d'une valeur, exemple : '12px', renvoie 'px'; 1655 * @param value 1656 * @returns {string|null} 1657 */ 1658function getUnit(value) { 1659 let match = regexUnit.exec(value); 1660 if (match && isValidCSSUnit(match[2])) { 1661 return match[2]; 1662 } 1663 return 'px'; 1664} 1665function getValueInfos(value, prop, unitDefault) { 1666 if (typeof value === 'object' && value.hasOwnProperty('computed')) { 1667 value = value.origin; 1668 } 1669 if (typeof value === 'object' && value.hasOwnProperty('value')) { 1670 value = value.value; 1671 } 1672 let defaultUnit = typeof unitDefault === "undefined" ? getDefaultUnit(prop) : unitDefault; 1673 value = typeof value === "undefined" ? '' : value; 1674 let match = regexUnit.exec(value); 1675 if (match !== null) { 1676 let unit = typeof match[2] === "undefined" || !isValidCSSUnit(match[2]) ? defaultUnit : match[2]; 1677 return { 1678 'value': typeof match[1] === "undefined" ? match[3] : _Math__WEBPACK_IMPORTED_MODULE_0__["default"].cleanStringInputToNumber(match[1]), 1679 'unit': unit, 1680 'origin': _Math__WEBPACK_IMPORTED_MODULE_0__["default"].cleanStringInputToNumber(match[0]) 1681 }; 1682 } 1683 return { 1684 'value': value, 1685 'unit': defaultUnit, 1686 'origin': value 1687 }; 1688} 1689function getPercentFromTwoValue(value, compareValue) { 1690 let valuePercent = parseFloat(value / compareValue * 100).toFixed(2); 1691 return valuePercent == parseInt(valuePercent) ? parseInt(valuePercent) : valuePercent; 1692} 1693function convertUnit(element, pseudoElement, prop, valueInfos, unit, withUnit = false) { 1694 valueInfos = typeof valueInfos === "string" ? getValueInfos(valueInfos, prop) : valueInfos; 1695 let returnValue = 0; 1696 switch (valueInfos.origin) { 1697 case 'auto': 1698 return valueInfos.origin; 1699 // removed by dead control flow 1700{} 1701 } 1702 if (valueInfos === null) return 0; 1703 if (parseFloat(valueInfos.value) === 0) return 0; 1704 1705 // On récupére la valeur calculé par le navigateur 1706 // Si l'élément est bien dans le DOM est visible, on aura la valeur en pixel 1707 let valueOnPx = window.getComputedStyle(element, pseudoElement).getPropertyValue(prop); 1708 let propRef, parentOnPx; 1709 switch (unit) { 1710 case 'px': 1711 returnValue = valueOnPx; 1712 break; 1713 case 'em': 1714 switch (valueInfos.unit) { 1715 case 'px': 1716 returnValue = getValueOnEm(element, valueInfos.origin); 1717 break; 1718 case '%': 1719 returnValue = getValueOnEm(element, valueOnPx); 1720 break; 1721 } 1722 break; 1723 case 'rem': 1724 switch (valueInfos.unit) { 1725 case 'px': 1726 returnValue = getValueOnRem(element, valueInfos.origin); 1727 break; 1728 case '%': 1729 returnValue = getValueOnRem(element, valueOnPx); 1730 break; 1731 } 1732 break; 1733 case '%': 1734 propRef = getPropRefForPercent(prop); 1735 parentOnPx = window.getComputedStyle(element.parentNode, pseudoElement).getPropertyValue(propRef); 1736 parentOnPx = getValueWithoutPrefix(parentOnPx); 1737 returnValue = getPercentFromTwoValue(getValueWithoutPrefix(valueOnPx), parentOnPx); 1738 break; 1739 case 'vh': 1740 const viewHeight = element.ownerDocument.defaultView.innerHeight; 1741 returnValue = getPercentFromTwoValue(getValueWithoutPrefix(valueOnPx), viewHeight); 1742 break; 1743 case 'vw': 1744 const viewWidth = element.ownerDocument.defaultView.innerWidth; 1745 returnValue = getPercentFromTwoValue(getValueWithoutPrefix(valueOnPx), viewWidth); 1746 break; 1747 } 1748 return secureValueShow(returnValue); 1749} 1750function secureValueShow(value, valueDefault) { 1751 valueDefault = typeof valueDefault === "undefined" ? 0 : valueDefault; 1752 switch (true) { 1753 case isNaN(value): 1754 return valueDefault; 1755 case !isFinite(value): 1756 return valueDefault; 1757 default: 1758 return value; 1759 } 1760} 1761let infosDataDefault = { 1762 'unit': '', 1763 'computed': '', 1764 'fontSize': '', 1765 'parentComputed': '', 1766 'othersProps': {}, 1767 'viewHeight': 0, 1768 'viewWidth': 0, 1769 'fontSizeHtml': '16px'
1770}; 1771function convertUnitByInfo(value, unit, data, prop) { 1772 let infos = Object.assign(infosDataDefault, data); 1773 prop = typeof prop === "undefined" ? false : prop; 1774 switch (value) { 1775 case 'auto': 1776 return value; 1777 // removed by dead control flow 1778{} 1779 } 1780 value = parseFloat(value); 1781 if (isNaN(value)) return 0; 1782 if (value === 0) return 0; 1783 let computedInfo = getValueInfos(infos.computed, prop); 1784 let computed = getValueWithoutPrefix(infos.computed); 1785 switch (unit) { 1786 case 'px': 1787 switch (computedInfo.unit) { 1788 case 'px': 1789 return computedInfo.value; 1790 case 'em': 1791 return emToPx(computedInfo.value, getValueWithoutPrefix(infos.fontSize)); 1792 case 'rem': 1793 return emToPx(computedInfo.value, getValueWithoutPrefix(infos.fontSizeHtml)); 1794 } 1795 break; 1796 case 'em': 1797 switch (prop) { 1798 case 'font-size': 1799 return pxToEm(computed, getValueWithoutPrefix(infos.parentComputed)); 1800 default: 1801 return pxToEm(computed, getValueWithoutPrefix(infos.fontSize)); 1802 } 1803 case 'rem': 1804 return pxToEm(computed, getValueWithoutPrefix(infos.fontSizeHtml)); 1805 case '%': 1806 return getPercentFromTwoValue(computed, getValueWithoutPrefix(infos.parentComputed)); 1807 case 'vh': 1808 return getPercentFromTwoValue(computed, infos.viewHeight); 1809 case 'vw': 1810 return getPercentFromTwoValue(computed, infos.viewHeight); 1811 case 'ms': 1812 case 's': 1813 return convertTime(value, data.unit, unit); 1814 } 1815 return 0; 1816} 1817function calcToMs(value, unit) { 1818 switch (unit) { 1819 case 's': 1820 return value * 1000; 1821 case 'ms': 1822 return value; 1823 } 1824} 1825function calcMsToUnit(valueMs, unit) { 1826 switch (unit) { 1827 case 's': 1828 return valueMs / 1000; 1829 case 'ms': 1830 return valueMs; 1831 } 1832} 1833function convertTime(value, fromUnit, toUnit) { 1834 const valueMs = calcToMs(value, fromUnit); 1835 return calcMsToUnit(valueMs, toUnit); 1836} 1837function getComputedByInfo(newValue, data, prop) { 1838 let infos = Object.assign(infosDataDefault, data); 1839 switch (newValue) { 1840 case 'auto': 1841 return newValue; 1842 // removed by dead control flow 1843{} 1844 } 1845 let value = parseFloat(newValue); 1846 let oldValue = null; 1847 let computed = getValueWithoutPrefix(infos.computed); 1848 if (isNaN(value)) return newValue; 1849 if (value === 0) return 0; 1850 if (infos.unit === null || infos.unit === '') return infos.origin; 1851 let newComputed = 0; 1852 switch (infos.unit) { 1853 case '%': 1854 oldValue = getPercentFromTwoValue(computed, getValueWithoutPrefix(infos.parentComputed)); 1855 newComputed = _Math__WEBPACK_IMPORTED_MODULE_0__["default"].cleanFloatValue(parseFloat(value / oldValue * computed).toFixed(2)); 1856 return newComputed + 'px'; 1857 case 'vw': 1858 oldValue = getPercentFromTwoValue(computed, infos.viewWidth); 1859 newComputed = _Math__WEBPACK_IMPORTED_MODULE_0__["default"].cleanFloatValue(parseFloat(value / oldValue * computed).toFixed(2)); 1860 return newComputed + 'px'; 1861 case 'vh': 1862 oldValue = getPercentFromTwoValue(computed, infos.viewHeight); 1863 newComputed = _Math__WEBPACK_IMPORTED_MODULE_0__["default"].cleanFloatValue(parseFloat(value / oldValue * computed).toFixed(2)); 1864 return newComputed + 'px'; 1865 case 'em': 1866 switch (prop) { 1867 case 'font-size': 1868 oldValue = pxToEm(computed, getValueWithoutPrefix(infos.parentComputed)); 1869 break; 1870 default: 1871 oldValue = pxToEm(computed, getValueWithoutPrefix(infos.fontSize)); 1872 break; 1873 } 1874 newComputed = _Math__WEBPACK_IMPORTED_MODULE_0__["default"].cleanFloatValue(parseFloat(value / oldValue * computed).toFixed(2)); 1875 return newComputed + 'px'; 1876 case 'rem': 1877 oldValue = emToPx(value, getValueWithoutPrefix(infos.fontSizeHtml)); 1878 return oldValue + 'px'; 1879 default: 1880 return _Math__WEBPACK_IMPORTED_MODULE_0__["default"].cleanFloatValue(value) + 'px'; 1881 } 1882 return 0; 1883} 1884function getPropRefForPercent(prop) { 1885 switch (true) { 1886 case regexMultiProps.margin.test(prop): 1887 case regexMultiProps.padding.test(prop): 1888 case prop === 'left': 1889 case prop === 'right': 1890 return 'width'; 1891 case prop === 'top': 1892 case prop === 'bottom': 1893 return 'height';
1894 default: 1895 return prop; 1896 } 1897} 1898 1899/** 1900 * https://zellwk.com/blog/css-translate-values-in-javascript/ 1901 * Gets computed translate values 1902 * @param {HTMLElement} element 1903 * @returns {Object} 1904 */ 1905function getTranslateValues(element) { 1906 const style = window.getComputedStyle(element); 1907 const matrix = style['transform'] || style.webkitTransform || style.mozTransform; 1908 1909 // No transform property. Simply return 0 values. 1910 if (matrix === 'none' || typeof matrix === 'undefined') { 1911 return { 1912 x: 0, 1913 y: 0, 1914 z: 0 1915 }; 1916 } 1917 1918 // Can either be 2d or 3d transform 1919 const matrixType = matrix.includes('3d') ? '3d' : '2d'; 1920 const matrixValues = matrix.match(/matrix.*\((.+)\)/)[1].split(', '); 1921 1922 // 2d matrices have 6 values 1923 // Last 2 values are X and Y. 1924 // 2d matrices does not have Z value. 1925 if (matrixType === '2d') { 1926 return { 1927 x: matrixValues[4], 1928 y: matrixValues[5], 1929 z: 0 1930 }; 1931 } 1932 1933 // 3d matrices have 16 values 1934 // The 13th, 14th, and 15th values are X, Y, and Z 1935 if (matrixType === '3d') { 1936 return { 1937 x: matrixValues[12], 1938 y: matrixValues[13], 1939 z: matrixValues[14] 1940 }; 1941 } 1942} 1943 1944// --- Transform (outil ToolsDesign) --- 1945 1946const defaultTransformItems = { 1947 'rotate': { 1948 type: 'rotate', 1949 angle: '0deg' 1950 }, 1951 'translate': { 1952 type: 'translate', 1953 x: '0px', 1954 y: '0px', 1955 z: '0px' 1956 }, 1957 'scale': { 1958 type: 'scale', 1959 value: '1' 1960 } 1961}; 1962 1963/** 1964 * Item transform par défaut pour un type donné (rotate | translate | scale) 1965 * @param {string} type 1966 * @returns {Object} 1967 */ 1968function getDefaultTransformItem(type) { 1969 return Object.assign({}, defaultTransformItems[type]); 1970} 1971 1972/** 1973 * Normalise une composante de longueur/angle : nombre + unité, NaN â 0 1974 * @param {string} value ex: '10px', '45', '-50%' 1975 * @param {string} defaultUnit unité si absente 1976 * @returns {string} ex: '10px', '45deg', '0px' 1977 */ 1978function normalizeTransformLength(value, defaultUnit = 'px') { 1979 const infos = getValueInfos(value, null, defaultUnit); 1980 const num = parseFloat(infos.value); 1981 if (isNaN(num)) { 1982 return '0' + defaultUnit; 1983 } 1984 return num + infos.unit; 1985} 1986 1987/** 1988 * Décompose une matrice 2D en items translate + rotate + scale. 1989 * Décomposition NORMALISANTE : ordre fixe, skew ignoré, scale uniforme. 1990 * Matrice dégénérée (déterminant 0) â []. 1991 * @param {Array<number>} values [a, b, c, d, e, f] 1992 * @returns {Array<Object>} 1993 */ 1994function decomposeMatrix2d(values) { 1995 const [a, b, c, d, e, f] = values; 1996 const det = a * d - b * c; 1997 if (det === 0 || isNaN(det)) { 1998 return []; 1999 } 2000 const items = []; 2001 if (e !== 0 || f !== 0) { 2002 items.push({ 2003 type: 'translate', 2004 x: (0,_Math__WEBPACK_IMPORTED_MODULE_0__.cleanFloatValueForView)(e) + 'px', 2005 y: (0,_Math__WEBPACK_IMPORTED_MODULE_0__.cleanFloatValueForView)(f) + 'px', 2006 z: '0px' 2007 }); 2008 } 2009 const angle = Math.atan2(b, a) * (180 / Math.PI); 2010 if (angle !== 0) { 2011 items.push({ 2012 type: 'rotate', 2013 angle: (0,_Math__WEBPACK_IMPORTED_MODULE_0__.cleanFloatValueForView)(angle) + 'deg' 2014 }); 2015 } 2016 const scaleX = Math.sqrt(a * a + b * b); 2017 const scaleY = det / scaleX; 2018 // Scale uniforme : moyenne si égaux à 1 % près, sinon scaleX 2019 const scale = (0,_Math__WEBPACK_IMPORTED_MODULE_0__.valueEqualtoWithinOnePercent)(scaleX, scaleY) ? (scaleX + scaleY) / 2 : scaleX; 2020 if (!(0,_Math__WEBPACK_IMPORTED_MODULE_0__.valueEqualtoWithinOnePercent)(scale, 1)) { 2021 items.push({ 2022 type: 'scale', 2023 value: String((0,_Math__WEBPACK_IMPORTED_MODULE_0__.cleanFloatValueForView)(scale)) 2024 }); 2025 } 2026 return items; 2027} 2028 2029/** 2030 * Parse une valeur CSS transform en tableau d'items {type, ...}. 2031 * - liste de fonctions â items (rotate/rotateZ, translate*, scale/scale3d) 2032 * - matrix(â¦) â décomposition 2D (fallback lossy) 2033 * - matrix3d(â¦) â translate seul 2034 * - none / vide / fonctions inconnues â ignoré 2035 * @param {string} value 2036 * @returns {Array<Object>} 2037 */ 2038function getTransformValue(value) { 2039 if (typeof value !== 'string' || value === '' || value === 'none') { 2040 return []; 2041 } 2042 const items = []; 2043 const regex = /([a-zA-Z0-9]+)\(([^)]*)\)/g; 2044 let m; 2045 while ((m = regex.exec(value)) !== null) { 2046 const fn = m[1]; 2047 const args = m[2].split(',').map(arg => arg.trim()); 2048 switch (fn) { 2049 case 'rotate': 2050 case 'rotateZ': 2051 items.push({ 2052 type: 'rotate', 2053 angle: normalizeTransformLength(args[0], 'deg') 2054 }); 2055 break; 2056 case 'translate': 2057 items.push({ 2058 type: 'translate', 2059 x: normalizeTransformLength(args[0]), 2060 y: normalizeTransformLength(args.length > 1 ? args[1] : '0px'), 2061 z: '0px' 2062 }); 2063 break; 2064 case 'translateX': 2065 items.push({ 2066 type: 'translate', 2067 x: normalizeTransformLength(args[0]), 2068 y: '0px', 2069 z: '0px' 2070 }); 2071 break; 2072 case 'translateY': 2073 items.push({ 2074 type: 'translate', 2075 x: '0px', 2076 y: normalizeTransformLength(args[0]), 2077 z: '0px' 2078 }); 2079 break; 2080 case 'translateZ': 2081 items.push({ 2082 type: 'translate', 2083 x: '0px', 2084 y: '0px', 2085 z: normalizeTransformLength(args[0]) 2086 }); 2087 break; 2088 case 'translate3d': 2089 items.push({ 2090 type: 'translate', 2091 x: normalizeTransformLength(args[0]), 2092 y: normalizeTransformLength(args[1]), 2093 z: normalizeTransformLength(args[2]) 2094 }); 2095 break; 2096 case 'scale': 2097 case 'scale3d': 2098 { 2099 const num = parseFloat(args[0]); 2100 items.push({ 2101 type: 'scale', 2102 value: isNaN(num) ? '1' : String(num) 2103 }); 2104 break; 2105 } 2106 case 'matrix': 2107 items.push(...decomposeMatrix2d(args.map(arg => parseFloat(arg)))); 2108 break; 2109 case 'matrix3d': 2110 { 2111 // Translate seul (composantes 13-15) ; rotation/scale 3D non représentables dans l'UI 2112 const x = parseFloat(args[12]) || 0; 2113 const y = parseFloat(args[13]) || 0; 2114 const z = parseFloat(args[14]) || 0; 2115 if (x !== 0 || y !== 0 || z !== 0) { 2116 items.push({ 2117 type: 'translate', 2118 x: (0,_Math__WEBPACK_IMPORTED_MODULE_0__.cleanFloatValueForView)(x) + 'px', 2119 y: (0,_Math__WEBPACK_IMPORTED_MODULE_0__.cleanFloatValueForView)(y) + 'px', 2120 z: (0,_Math__WEBPACK_IMPORTED_MODULE_0__.cleanFloatValueForView)(z) + 'px' 2121 }); 2122 } 2123 break; 2124 } 2125 default:
2126 // Fonction non gérée (skew, rotateX/Y, perspectiveâ¦) : ignorée silencieusement 2127 break; 2128 } 2129 } 2130 return items; 2131} 2132 2133/** 2134 * Sérialise un tableau d'items en valeur CSS transform. 2135 * Tableau vide â 'none'. Jamais de CSS invalide (NaN â défauts). 2136 * @param {Array<Object>} items 2137 * @returns {string} 2138 */ 2139function generateTransformValue(items) { 2140 if (!Array.isArray(items) || items.length === 0) { 2141 return 'none'; 2142 } 2143 const value = items.map(item => { 2144 switch (item.type) { 2145 case 'rotate': 2146 return 'rotate(' + normalizeTransformLength(item.angle, 'deg') + ')'; 2147 case 'translate': 2148 return 'translate3d(' + normalizeTransformLength(item.x) + ', ' + normalizeTransformLength(item.y) + ', ' + normalizeTransformLength(item.z) + ')'; 2149 case 'scale': 2150 { 2151 const num = parseFloat(item.value); 2152 return 'scale(' + (isNaN(num) ? 1 : num) + ')'; 2153 } 2154 default: 2155 return ''; 2156 } 2157 }).filter(fn => fn !== '').join(' '); 2158 return value === '' ? 'none' : value; 2159} 2160 2161// --- Shadow (box-shadow / text-shadow, outil ToolsDesign) --- 2162 2163/** 2164 * Tokenise un segment d'ombre sur les espaces, en ignorant ceux à l'intérieur 2165 * des parenthèses (ex. 'rgba(0, 0, 0, .5) 2px 2px 4px' â 4 tokens, pas 7). 2166 * @param {string} str 2167 * @returns {string[]} 2168 */ 2169function splitShadowTokens(str) { 2170 const tokens = []; 2171 let depth = 0; 2172 let current = ''; 2173 for (let i = 0; i < str.length; i++) { 2174 const ch = str[i]; 2175 if (ch === '(') { 2176 depth++; 2177 current += ch; 2178 } else if (ch === ')') { 2179 depth--; 2180 current += ch; 2181 } else if (depth === 0 && /\s/.test(ch)) { 2182 if (current !== '') { 2183 tokens.push(current); 2184 current = ''; 2185 } 2186 } else { 2187 current += ch; 2188 } 2189 } 2190 if (current !== '') { 2191 tokens.push(current); 2192 } 2193 return tokens; 2194} 2195const shadowLengthTokenRegex = /^-?(\d+\.?\d*|\.\d+)[a-z%]*$/i; 2196 2197/** 2198 * Un token ressemble-t-il à une longueur CSS ('2px', '-3', '.5em', '10%') ? 2199 * Tout ce qui n'est ni 'inset' ni une longueur est classé comme couleur. 2200 * @param {string} token 2201 * @returns {boolean} 2202 */ 2203function isShadowLengthToken(token) { 2204 return shadowLengthTokenRegex.test(token); 2205} 2206 2207/** 2208 * Normalise une composante de longueur d'ombre : nombre + unité, NaN â '0' + unité par défaut. 2209 * @param {string} value 2210 * @param {string} defaultUnit 2211 * @returns {string} 2212 */ 2213function normalizeShadowLength(value, defaultUnit = 'px') { 2214 const infos = getValueInfos(value, null, defaultUnit); 2215 const num = parseFloat(infos.value); 2216 if (isNaN(num)) { 2217 return '0' + defaultUnit; 2218 } 2219 return num + infos.unit; 2220} 2221 2222/** 2223 * Item d'ombre par défaut (pour « Ajouter une ombre » et pour compléter les 2224 * composantes absentes lors du parsing). 2225 * @param {string} mode 'box' | 'text' 2226 * @returns {Object} 2227 */ 2228function getDefaultShadowItem(mode = 'box') { 2229 const base = { 2230 'offset-x': '0px', 2231 'offset-y': '0px', 2232 'blur-radius': '0px', 2233 'color': 'rgba(0,0,0,0.5)' 2234 }; 2235 if (mode === 'box') { 2236 base['spread-radius'] = '0px'; 2237 base.inset = false; 2238 } 2239 return base; 2240} 2241 2242/** 2243 * Parse une valeur CSS box-shadow / text-shadow en tableau d'items. 2244 * Tokenizer robuste par classification (pas par position fixe) : gère la 2245 * couleur en tête (legacy) ou en fin (standard), et 'inset' en tête ou en fin. 2246 * '' / 'none' / non-string â []. 2247 * @param {string} value 2248 * @param {{mode?: string}} options mode: 'box' (défaut) | 'text' 2249 * @returns {Array<Object>} 2250 */ 2251function getShadowValue(value, options = {}) { 2252 const mode = options.mode === 'text' ? 'text' : 'box'; 2253 2254 // '' / 'none' / 'remove' (sentinelle de réinitialisation ToolsDesign) â aucune ombre. 2255 if (typeof value !== 'string' || value.trim() === '' || value.trim() === 'none' || value.trim() === 'remove') { 2256 return []; 2257 } 2258 const segments = splitTopLevel(value.trim(), ',').map(segment => segment.trim()).filter(segment => segment !== ''); 2259 const lengthKeys = mode === 'text' ? ['offset-x', 'offset-y', 'blur-radius'] : ['offset-x', 'offset-y', 'blur-radius', 'spread-radius']; 2260 return segments.map(segment => { 2261 const tokens = splitShadowTokens(segment); 2262 const lengths = [];
2263 let color = ''; 2264 let inset = false; 2265 tokens.forEach(token => { 2266 if (/^inset$/i.test(token)) { 2267 // Mot-clé 'inset' : pris en compte en mode box, ignoré (pas la couleur) en mode text. 2268 if (mode === 'box') { 2269 inset = true; 2270 } 2271 return; 2272 } 2273 if (isShadowLengthToken(token)) { 2274 lengths.push(token); 2275 return; 2276 } 2277 // Ni 'inset' ni une longueur : couleur (#hex, rgb/rgba/hsl/hsla(...), var(...), nom CSSâ¦) 2278 color = token; 2279 }); 2280 const item = Object.assign({}, getDefaultShadowItem(mode)); 2281 lengthKeys.forEach((key, index) => { 2282 if (typeof lengths[index] !== 'undefined') { 2283 item[key] = normalizeShadowLength(lengths[index]); 2284 } 2285 }); 2286 if (color !== '') { 2287 item.color = color; 2288 } 2289 if (mode === 'box') { 2290 item.inset = inset; 2291 } 2292 return item; 2293 }); 2294} 2295 2296/** 2297 * Sérialise un tableau d'items en valeur CSS box-shadow / text-shadow. 2298 * Tableau vide â 'none'. Ordre canonique : 2299 * text â offset-x offset-y blur-radius [color] 2300 * box â [inset ]offset-x offset-y blur-radius spread-radius [color] 2301 * @param {Array<Object>} items 2302 * @param {{mode?: string}} options mode: 'box' (défaut) | 'text' 2303 * @returns {string} 2304 */ 2305function generateShadowValue(items, options = {}) { 2306 const mode = options.mode === 'text' ? 'text' : 'box'; 2307 2308 // Aucune ombre â chaîne vide (le composant écrira la sentinelle 'remove' pour 2309 // SUPPRIMER la propriété plutôt que forcer une valeur 'none'). 2310 if (!Array.isArray(items) || items.length === 0) { 2311 return ''; 2312 } 2313 const value = items.map(item => { 2314 const offsetX = normalizeShadowLength(item['offset-x']); 2315 const offsetY = normalizeShadowLength(item['offset-y']); 2316 const blur = normalizeShadowLength(item['blur-radius']); 2317 const color = item.color || ''; 2318 if (mode === 'text') { 2319 const parts = [offsetX, offsetY, blur]; 2320 if (color !== '') { 2321 parts.push(color); 2322 } 2323 return parts.join(' '); 2324 } 2325 const spread = normalizeShadowLength(item['spread-radius']); 2326 const parts = []; 2327 if (item.inset) { 2328 parts.push('inset'); 2329 } 2330 parts.push(offsetX, offsetY, blur, spread); 2331 if (color !== '') { 2332 parts.push(color); 2333 } 2334 return parts.join(' '); 2335 }).join(', '); 2336 return value; 2337} 2338const transformOriginKeywordX = { 2339 'left': '0%', 2340 'center': '50%', 2341 'right': '100%' 2342}; 2343const transformOriginKeywordY = { 2344 'top': '0%', 2345 'center': '50%', 2346 'bottom': '100%' 2347}; 2348 2349/** 2350 * Parse une valeur CSS transform-origin en {x, y}. 2351 * Mots-clés convertis en %, valeurs px/% gardées. Défaut : 50% 50%. 2352 * @param {string} value ex: '50% 50%', 'top left', '100px 20px' 2353 * @returns {{x: string, y: string}} 2354 */ 2355function getTransformOriginValue(value) { 2356 const origin = { 2357 x: '50%', 2358 y: '50%' 2359 }; 2360 if (typeof value !== 'string' || value.trim() === '') { 2361 return origin; 2362 } 2363 let parts = value.trim().split(/\s+/).slice(0, 2); 2364 2365 // Mot-clé seul d'axe vertical : 'top' â '50% 0%' 2366 if (parts.length === 1 && /^(top|bottom)$/.test(parts[0])) { 2367 parts = ['center', parts[0]]; 2368 } 2369 2370 // Mots-clés donnés dans l'ordre inverse : 'top left' â 'left top' 2371 if (parts.length === 2 && (/^(top|bottom)$/.test(parts[0]) || /^(left|right)$/.test(parts[1]))) { 2372 parts = [parts[1], parts[0]]; 2373 } 2374 const rawX = parts[0]; 2375 const rawY = parts.length > 1 ? parts[1] : '50%'; 2376 origin.x = transformOriginKeywordX.hasOwnProperty(rawX) ? transformOriginKeywordX[rawX] : normalizeTransformLength(rawX, '%'); 2377 origin.y = transformOriginKeywordY.hasOwnProperty(rawY) ? transformOriginKeywordY[rawY] : normalizeTransformLength(rawY, '%'); 2378 return origin; 2379} 2380 2381/** 2382 * Sérialise {x, y} en valeur CSS transform-origin. 2383 * @param {{x: string, y: string}} origin 2384 * @returns {string} 2385 */ 2386function generateTransformOriginValue(origin) { 2387 const values = Object.assign({ 2388 x: '50%', 2389 y: '50%' 2390 }, origin); 2391 return normalizeTransformLength(values.x, '%') + ' ' + normalizeTransformLength(values.y, '%'); 2392} 2393 2394/** 2395 * 2396 * @param value 2397 * @param unit 2398 * @returns {*} 2399 * @todo rajouter les calc 2400 */ 2401function verifAndGetValueWithPrefix(value, unit) { 2402 switch (value) { 2403 case 'auto': 2404 return value; 2405 case '': 2406 return value; 2407 default: 2408 switch (unit) { 2409 case 'ratio': 2410 case 'int': 2411 return value; 2412 default: 2413 return value + unit; 2414 // removed by dead control flow 2415{} 2416 } 2417 } 2418} 2419function getBorderColor(element, pseudoElement) { 2420 let p = 0, 2421 value = ''; 2422 let color = window.getComputedStyle(element, pseudoElement).getPropertyValue('color'); 2423 let values = []; 2424 do { 2425 values.push(window.getComputedStyle(element, pseudoElement).getPropertyValue('border-' + positionProps[p] + '-color')); 2426 p++; 2427 } while (p < positionProps.length); 2428 let setValues = new Set(values); 2429 if (setValues.size > 1) { 2430 // on supprime la couleur de typographie, qui est hérité sur les border-color 2431 setValues.delete(color); 2432 // on supprime les 'none' 2433 setValues.delete('none'); 2434 2435 // Si il y a plus de valeur, c'est que c'était la couleur de police à minima 2436 if (setValues.size) { 2437 // on récupére ensuite la première couleur en ignorant les autres 2438 let itV = setValues.values(); 2439 value = itV.next().value; 2440 } else { 2441 value = color; 2442 } 2443 } else { 2444 value = values.shift(); 2445 } 2446 return value; 2447} 2448function getBorderStyle(element, pseudoElement) { 2449 let p = 0, 2450 value = ''; 2451 p = 0; 2452 do { 2453 value = window.getComputedStyle(element, pseudoElement).getPropertyValue('border-' + positionProps[p] + '-style'); 2454 if (value !== '' && value !== 'none') { 2455 break; 2456 } // si on trouve une valeur on s'arrete là 2457 p++; 2458 } while (p < positionProps.length); 2459 return value; 2460} 2461const propUnitDefault = { 2462 'number': 'ratio', 2463 'number-int': 'int', 2464 'opacity': 'ratio', 2465 'border-image-slice': 'ratio', 2466 'line-height': 'ratio', 2467 'z-index': 'ratio', 2468 'order': 'ratio', 2469 'letter-spacing': 'em', 2470 'border-width': 'px', 2471 'width': 'px', 2472 'min-width': 'px', 2473 'max-width': 'px', 2474 'height': 'px', 2475 'min-height': 'px', 2476 'max-height': 'px', 2477 'margin': 'px', 2478 'padding': 'px', 2479 'font-size': 'px', 2480 'box-shadow': 'px', 2481 'background-size': '%', 2482 'background-size-x': '%', 2483 'background-size-y': '%', 2484 'time': 'ms' 2485}; 2486function getDefaultUnit(prop) { 2487 if (!!prop && propUnitDefault.hasOwnProperty(prop)) { 2488 return propUnitDefault[prop]; 2489 } else { 2490 return 'px'; 2491 } 2492} 2493function addHistoryRemoveFromProps(newJSONOrigin, oldJSONOrigin) { 2494 let oldJSON = Object.assign({}, oldJSONOrigin); 2495 let newJSON = Object.assign({}, newJSONOrigin); 2496 2497 // Media Query ? 2498 for (let sizeResponsive in oldJSON) { 2499 if (!(sizeResponsive in newJSON)) { 2500 newJSON[sizeResponsive] = {}; 2501 } 2502 for (let selector in oldJSON[sizeResponsive]) { 2503 if (!(selector in newJSON[sizeResponsive])) { 2504 newJSON[sizeResponsive][selector] = {}; 2505 } 2506 for (let prop in oldJSON[sizeResponsive][selector]) { 2507 if (!(prop in newJSON[sizeResponsive][selector])) { 2508 newJSON[sizeResponsive][selector][prop] = 'remove'; 2509 } 2510 } 2511 } 2512 } 2513 return newJSON; 2514} 2515function getStatusToClassAndPseudoClass(status) { 2516 let regex = /(?<selector>(?:(?::scope)|\.?[^:\s>]+)+)|(?<pseudoClass>:{1,2}(?<pseudoClassName>[^.:()\s]+(?:\([^\)]+\))?))|(?<child>[\s>])/g; 2517 let result = null; 2518 const returnValue = { 2519 'selector': '', 2520 'selectorWithScope': status, 2521 'pseudo-class': '', 2522 'original': status, 2523 'with-child': false 2524 };
2525 let withChild = false; 2526 let beforeSelector = ''; 2527 let beforeType = 'selector'; 2528 while ((result = regex.exec(status)) !== null) { 2529 // This is necessary to avoid infinite loops with zero-width matches 2530 if (result.index === regex.lastIndex) { 2531 regex.lastIndex++; 2532 } 2533 const pseudoClassGood = typeof result.groups.pseudoClassName === 'undefined' ? '' : getPseudoFormatByName(result.groups.pseudoClassName); 2534 const pseudoClass = typeof result.groups.pseudoClass === 'undefined' ? '' : result.groups.pseudoClass; 2535 const isLoopChild = typeof result.groups.child !== 'undefined' && (result.groups.child === ' ' || result.groups.child === '>'); 2536 if (isLoopChild) { 2537 withChild = true; 2538 returnValue['selector'] += result.groups.child; 2539 } 2540 2541 // on corrige le pseudo élement ou pseudo class 2542 if (pseudoClass !== '') { 2543 status = status.replace(pseudoClass, pseudoClassGood); 2544 } 2545 returnValue['selector'] += typeof result.groups.selector === 'undefined' || result.groups.selector === '' ? '' : result.groups.selector; 2546 returnValue['pseudo-class'] = pseudoClassGood === '' ? returnValue['pseudo-class'] : pseudoClassGood; 2547 if (pseudoClassGood !== '' && /selector|pseudoClass/.test(beforeType)) { 2548 returnValue['pseudo-class-selector'] = pseudoClassGood === '' && /selector|pseudoClass/.test(beforeType) ? '' : beforeSelector; 2549 } 2550 beforeSelector = typeof result.groups.selector === 'undefined' || result.groups.selector === '' ? beforeSelector : result.groups.selector; 2551 beforeType = 'selector'; 2552 if (isLoopChild) { 2553 beforeType = 'child'; 2554 } 2555 if (pseudoClass !== '') { 2556 beforeType = 'pseudoClass'; 2557 } 2558 } 2559 returnValue['with-child'] = withChild; 2560 return returnValue; 2561} 2562; 2563function getCSSQueryAllStatus(CSSquery, allStatus = false) { 2564 if (allStatus) { 2565 switch (typeof allStatus) { 2566 case "object": 2567 let query = ''; 2568 let separator = ''; 2569 for (let type in allStatus) { 2570 if (allStatus.hasOwnProperty(type)) { 2571 query += separator + getCSSQuery(CSSquery, allStatus[type], type); 2572 separator = ','; 2573 } 2574 } 2575 return query; 2576 default: 2577 const status = CSSHelper.getStatusToClassAndPseudoClass(allStatus); 2578 return getCSSQuery(CSSquery, status); 2579 } 2580 } else { 2581 return getCSSQuery(CSSquery, allStatus); 2582 } 2583} 2584function getCSSQuery(CSSquery, statusQuery = false, type = 'element', onlyElement = false) { 2585 let selectorsArray = CSSquery.split(','); 2586 let selectors = CSSquery; 2587 let statusArray = []; 2588 switch (typeof statusQuery) { 2589 case "string": 2590 statusArray = statusQuery.split(','); 2591 break; 2592 case "object": 2593 if (statusQuery === null) { 2594 statusArray.push(''); 2595 } else { 2596 statusArray.push(statusQuery); 2597 } 2598 break; 2599 } 2600 if (statusQuery) { 2601 selectors = ''; 2602 let separator = ''; 2603 selectorsArray.forEach(function (selector) { 2604 statusArray.forEach(function (thisStatus) { 2605 let status = typeof thisStatus === "string" ? getStatusToClassAndPseudoClass(thisStatus) : thisStatus; 2606 const statusType = onlyElement ? 'selector' : 'original'; 2607 switch (type) { 2608 case 'parent': 2609 let selectorParent = (status ? status[statusType].trim() : '') + ' ' + selector; 2610 const classesParentSelector = status.selector.match(/[#.][^#.\s]+/g) || []; 2611 if (classesParentSelector.length > 0) { 2612 classesParentSelector.forEach(part => { 2613 const regex = new RegExp((0,_String__WEBPACK_IMPORTED_MODULE_1__.escapeRegExp)(part)); 2614 if (regex.test(selector)) { 2615 selectorParent = selector.replace(regex, status[statusType].trim()); 2616 } 2617 }); 2618 } 2619 selectors += separator + selectorParent; 2620 break; 2621 case 'child': 2622 if (status && status[statusType].includes(':scope')) { 2623 selectors += separator + status[statusType].replace(':scope', selector).trim(); 2624 } else { 2625 selectors += separator + selector + (status ? ' ' + status[statusType].trim() : ''); 2626 } 2627 break; 2628 case 'custom': 2629 selectors += separator + (status ? status[statusType] : ''); 2630 break; 2631 case 'element': 2632 default: 2633 const thisStatus = status ? status[statusType].trim().replace(':scope', '') : ''; 2634 selectors += separator + selector + thisStatus; 2635 break; 2636 } 2637 separator = ','; 2638 }); 2639 }); 2640 } 2641 return selectors; 2642} 2643 2644/** 2645 * Clés de sélecteur sous lesquelles addChangeCssByType/_saveStyleLive enregistrent les valeurs 2646 * utilisateur (CSSRule/CSSRuleTemp) : une clé par type de status ET par sous-status (split sur ','), 2647 * chacune passée par getCSSQuery. Sans status, la clé est le sélecteur de base. 2648 * Toute relecture d'une valeur utilisateur doit interroger CES clés (pas le sélecteur de base seul), 2649 * sinon un onglet d'état (ex. « Survolé ») relit la valeur de l'état normal. 2650 * @param {string} CSSquery 2651 * @param {object|string|false} allStatus 2652 * @returns {string[]} 2653 */ 2654function getCSSQuerySaveKeys(CSSquery, allStatus = false) { 2655 const keys = []; 2656 const pushKeysForStatus = function (statusString, type) { 2657 String(statusString).split(',').forEach(function (thisStatus) { 2658 keys.push(thisStatus === '' ? CSSquery : getCSSQuery(CSSquery, thisStatus, type)); 2659 }); 2660 }; 2661 switch (typeof allStatus) { 2662 case "object": 2663 if (allStatus !== null) { 2664 for (let type in allStatus) { 2665 if (allStatus.hasOwnProperty(type)) { 2666 pushKeysForStatus(allStatus[type], type); 2667 } 2668 } 2669 } 2670 break; 2671 case "string": 2672 if (allStatus !== '') { 2673 pushKeysForStatus(allStatus, 'element'); 2674 } 2675 break; 2676 } 2677 if (!keys.length) { 2678 keys.push(CSSquery); 2679 } 2680 return keys; 2681} 2682const initialValueByProps = { 2683 'background': 'none', 2684 'background-image': 'none', 2685 'background-color': 'transparent', 2686 'border-image-source': 'none', 2687 'color': 'inherit' 2688}; 2689function hasInitialValue(prop) { 2690 return initialValueByProps.hasOwnProperty(prop); 2691} 2692function getInitialValue(prop, context = document.body) { 2693 if (initialValueByProps.hasOwnProperty(prop)) { 2694 return initialValueByProps[prop]; 2695 } else { 2696 return window.getComputedStyle(document.body, null).getPropertyValue(prop); 2697 } 2698} 2699function getMediaQueryCss(min, max, type = 'up') { 2700 return '@media ' + getMediaQuery(min, max, type); 2701} 2702function getMediaQuery(min, max, type = 'up') { 2703 switch (type) { 2704 case 'up': 2705 return "(min-width:" + min + ")"; 2706 case 'down': 2707 return "(max-width:" + max + ")"; 2708 case 'only': 2709 return "(min-width:" + min + ") and (max-width:" + max + ")"; 2710 case 'all': 2711 return "screen"; 2712 } 2713} 2714 2715const CSSHelper = { 2716 cleanValuePropsCSS, 2717 getFontNameFromFontFamily, 2718 getValueOnEm, 2719 getValueOnREm: getValueOnRem,
2720 getBackgroundImageValue, 2721 convertBackgroundPositionToString, 2722 getPseudoFormatByName, 2723 getDefaultValueCss, 2724 cssComputedCache, 2725 getShortValueCss, 2726 getDecodeShortValue, 2727 expandShorthandToLonghands, 2728 isTargetedShorthand, 2729 normalizeDeclarations, 2730 normalizeCSSRuleStore, 2731 getInfoFromMultiProps, 2732 getUnit, 2733 getValueInfos, 2734 getPropRefForPercent, 2735 convertUnitByInfo, 2736 getComputedByInfo, 2737 getTranslateValues, 2738 getPercentFromTwoValue, 2739 getValueWithoutPrefix, 2740 verifAndGetValueWithPrefix, 2741 getBorderColor, 2742 getBorderStyle, 2743 getDefaultUnit, 2744 addHistoryRemoveFromProps, 2745 getCSSQuery, 2746 getCSSQueryAllStatus, 2747 getCSSQuerySaveKeys, 2748 getStatusToClassAndPseudoClass, 2749 generatePositionValue, 2750 getInitialValue, 2751 convertTime, 2752 calcMsToUnit, 2753 calcToMs, 2754 getValueViewWidth, 2755 getDefaultDisplayValue, 2756 getDefaultTransformItem, 2757 getTransformValue, 2758 generateTransformValue, 2759 decomposeMatrix2d, 2760 getTransformOriginValue, 2761 generateTransformOriginValue, 2762 parseGradient, 2763 generateGradient, 2764 getBackgroundLayers, 2765 generateBackgroundLonghands, 2766 getShadowValue, 2767 generateShadowValue, 2768 getDefaultShadowItem 2769}; 2770/* unused harmony default export */ var __WEBPACK_DEFAULT_EXPORT__ = (CSSHelper); 2771 2772/***/ }), 2773
2774/***/ "./js/helper/Math.js": 2775/*!***************************!*\ 2776 !*** ./js/helper/Math.js ***! 2777 \***************************/ 2778/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { 2779 2780/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2781/* harmony export */ cleanFloatValueForView: function() { return /* binding */ cleanFloatValueForView; }, 2782/* harmony export */ valueEqualtoWithinOnePercent: function() { return /* binding */ valueEqualtoWithinOnePercent; } 2783/* harmony export */ }); 2784/* unused harmony exports cleanFloatValue, cleanStringInputToNumber, parseFloatCssValue, getPercent, toFixedCeil, toFixedFloor, ROUND_TYPE_ROUND, ROUND_TYPE_UP, ROUND_TYPE_DOWN */ 2785function cleanFloatValue(value) { 2786 return value == parseInt(value) ? parseInt(value) : parseFloat(value); 2787} 2788const ROUND_TYPE_ROUND = 'round'; 2789const ROUND_TYPE_UP = 'up'; 2790const ROUND_TYPE_DOWN = 'down'; 2791function cleanFloatValueForView(value, fractionDigits = 2, typeRound = ROUND_TYPE_ROUND) { 2792 if (value === "") { 2793 return value; 2794 } 2795 if (Number.isInteger(value)) { 2796 return value; 2797 } else { 2798 switch (typeRound) { 2799 case ROUND_TYPE_ROUND: 2800 return cleanFloatValue(parseFloat(value).toFixed(fractionDigits)); 2801 case ROUND_TYPE_UP: 2802 return cleanFloatValue(toFixedFloor(parseFloat(value), fractionDigits)); 2803 case ROUND_TYPE_DOWN: 2804 return cleanFloatValue(toFixedCeil(parseFloat(value), fractionDigits)); 2805 } 2806 } 2807} 2808 2809/** 2810 * 2811 * @param value string 2812 * @returns string 2813 */ 2814function cleanStringInputToNumber(value) { 2815 if (typeof value === 'string' && /,/.test(value)) { 2816 return value.replace(',', '.'); 2817 } 2818 return value; 2819} 2820 2821/** 2822 * 2823 * @param value string 2824 * @returns string 2825 */ 2826function parseFloatCssValue(value) { 2827 let parseValue = parseFloat(value); 2828 if (isNaN(parseValue)) { 2829 parseValue = 0; 2830 } 2831 return parseValue; 2832} 2833function getPercent(value, base, fractionDigits = 4) { 2834 return cleanFloatValueForView(value / base * 100, fractionDigits); 2835} 2836function toFixedCeil(number, n) { 2837 var k = Math.pow(10, n); 2838 return Math.ceil(number * k) / k; 2839} 2840function toFixedFloor(number, n) { 2841 var k = Math.pow(10, n); 2842 return Math.floor(number * k) / k; 2843} 2844function valueEqualtoWithinOnePercent(value1, value2) { 2845 const difference = Math.abs(value1 - value2); 2846 const OnePercentValue1 = 0.01 * Math.abs(value1); 2847 return difference < OnePercentValue1; 2848} 2849 2850const MathHelper = { 2851 cleanFloatValue: cleanFloatValue, 2852 cleanFloatValueForView: cleanFloatValueForView, 2853 cleanStringInputToNumber: cleanStringInputToNumber, 2854 parseFloatCssValue: parseFloatCssValue 2855}; 2856/* harmony default export */ __webpack_exports__["default"] = (MathHelper); 2857 2858/***/ }), 2859
2860/***/ "./js/helper/String.js": 2861/*!*****************************!*\ 2862 !*** ./js/helper/String.js ***! 2863 \*****************************/ 2864/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { 2865 2866/* harmony export */ __webpack_require__.d(__webpack_exports__, { 2867/* harmony export */ escapeRegExp: function() { return /* binding */ escapeRegExp; } 2868/* harmony export */ }); 2869/* unused harmony exports camelize, decamelize, unicodeToHtml, safeBase64Encode, safeBase64Decode */ 2870function escapeRegExp(string) { 2871 return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 2872} 2873 2874/** 2875 * Camelize a string, cutting the string by multiple separators like 2876 * hyphens, underscores and spaces. 2877 * 2878 * @param {text} string Text to camelize 2879 * @return string Camelized text 2880 */ 2881function camelize(text) { 2882 return text.replace(/^([A-Z])|[\s-_]+(\w)/g, function (match, p1, p2, offset) { 2883 if (p2) return p2.toUpperCase(); 2884 return p1.toLowerCase(); 2885 }); 2886} 2887 2888/** 2889 * Decamelizes a string with/without a custom separator (underscore by default). 2890 * 2891 * @param str String in camelcase 2892 * @param separator Separator for the new decamelized string. 2893 */ 2894function decamelize(str, separator = '-') { 2895 return str.replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2').replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2').toLowerCase(); 2896} 2897function unicodeToHtml(unicode) { 2898 var html = ''; 2899 // On supprime l'anti-slash de l'unicode 2900 // convertie l'unicode Hexa en decimal 2901 var unicodeDecimal = parseInt(unicode, 16); 2902 // cree le caractere html 2903 html += '&#' + unicodeDecimal + ';'; 2904 return html; 2905} 2906 2907// Fonctions utilitaires sécurisées pour l'encodage Base64 avec Unicode 2908function safeBase64Encode(str) { 2909 try { 2910 // Méthode moderne avec TextEncoder (supporte Unicode) 2911 if (typeof TextEncoder !== 'undefined') { 2912 const encoder = new TextEncoder(); 2913 const bytes = encoder.encode(str); 2914 return btoa(String.fromCharCode(...bytes)); 2915 } 2916 2917 // Fallback : encoder en UTF-8 puis base64 2918 return btoa(unescape(encodeURIComponent(str))); 2919 } catch (error) { 2920 console.error(error); 2921 // Fallback ultime : JSON.stringify + btoa (peut échouer avec émojis) 2922 try { 2923 return btoa(JSON.stringify(str)); 2924 } catch (fallbackError) { 2925 console.error('Fallback encodage échoué:', fallbackError); 2926 return btoa('ERROR_ENCODING'); 2927 } 2928 } 2929} 2930function safeBase64Decode(str) { 2931 try { 2932 // Méthode moderne avec TextDecoder (supporte Unicode) 2933 if (typeof TextDecoder !== 'undefined') { 2934 const decoded = atob(str); 2935 const bytes = new Uint8Array(decoded.length); 2936 for (let i = 0; i < decoded.length; i++) { 2937 bytes[i] = decoded.charCodeAt(i); 2938 } 2939 const decoder = new TextDecoder(); 2940 return decoder.decode(bytes); 2941 } 2942 2943 // Fallback : decoder base64 puis UTF-8 2944 return decodeURIComponent(escape(atob(str))); 2945 } catch (error) { 2946 console.error(error); 2947 // Fallback ultime : JSON.parse + atob 2948 try { 2949 return JSON.parse(atob(str)); 2950 } catch (fallbackError) { 2951 console.error('Fallback decodage échoué:', fallbackError); 2952 return 'ERROR_DECODING'; 2953 } 2954 } 2955} 2956 2957const StringHelper = { 2958 "escapeRegExp": escapeRegExp, 2959 "camelize": camelize, 2960 "decamelize": decamelize 2961}; 2962/* unused harmony default export */ var __WEBPACK_DEFAULT_EXPORT__ = (StringHelper); 2963 2964/***/ }), 2965
vendor: 4,214 bytes, lines 2966-3106
2966/***/ "./node_modules/beekube-dom/BaseApp/Component.js": 2967/*!*******************************************************!*\ 2968 !*** ./node_modules/beekube-dom/BaseApp/Component.js ***! 2969 \*******************************************************/ 2970/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 2971 2972/* harmony import */ var _DOMModule_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./DOMModule.js */ "./node_modules/beekube-dom/BaseApp/DOMModule.js"); 2973/* harmony import */ var _Helper_Object_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Helper/Object.js */ "./node_modules/beekube-dom/Helper/Object.js"); 2974/* harmony import */ var js_struct_compare__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! js-struct-compare */ "./node_modules/js-struct-compare/src/index.mjs"); 2975 2976 2977 2978 2979 2980/** 2981 * A node in the DOM tree. 2982 * 2983 * @external Node 2984 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node Node} 2985 */ 2986 2987/** 2988 * Composent, permet de générer un template à partir d'un JSON qu'il faut retourner dans la fonction "render" 2989 * 2990 */ 2991class Component { 2992 DOMModule = null; 2993 states = {}; 2994 2995 /** 2996 * @param {object} states état initial du composant 2997 * @param {external:Node} element nÅud parent dans lequel monter le composant 2998 * @param {number|null} index position d'insertion (null = append) 2999 */ 3000 constructor(states, element, index = null) { 3001 3002 this.states = Object.assign(this.states, states); 3003 this.renderTemplate = (0,_DOMModule_js__WEBPACK_IMPORTED_MODULE_0__.getAssignKeyTemplate)(this.render()); 3004 3005 this.beforeMount(); 3006 3007 this.DOMModule = new _DOMModule_js__WEBPACK_IMPORTED_MODULE_0__["default"]({ 3008 parentNode: element, 3009 index: index 3010 }, this.renderTemplate, this.states); 3011 3012 this.afterMount(); 3013 } 3014 3015 getProp(variable, index) { 3016 let prop = function () { 3017 return (typeof index !== "undefined" ? this.props[variable][index] : this.props[variable]); 3018 }; 3019 return prop.bind(this); 3020 } 3021 3022 /** 3023 * 3024 * @param value Object 3025 */ 3026 set props(value) { 3027 let cloneStatesModule = (0,_Helper_Object_js__WEBPACK_IMPORTED_MODULE_1__.cloneObject)(this.states); 3028 Object.assign(cloneStatesModule, value); 3029 3030 for (let nameProps in cloneStatesModule) { 3031 if (cloneStatesModule.hasOwnProperty(nameProps)) { 3032 this.DOMModule.variables[nameProps] = cloneStatesModule[nameProps]; 3033 } 3034 } 3035 3036 try { 3037 this.beforeRender(); 3038 3039 let thisRender = (0,_DOMModule_js__WEBPACK_IMPORTED_MODULE_0__.getAssignKeyTemplate)(this.render()); 3040 let templateCompare = (0,js_struct_compare__WEBPACK_IMPORTED_MODULE_2__["default"])(this.renderTemplate, thisRender); 3041 3042 this.DOMModule.render(null, {'compare': templateCompare, 'template': thisRender}); 3043 3044 // On ne mémorise le nouveau template de référence qu'APRÃS une mise à jour 3045 // réussie : si render() lève, on évite de désynchroniser template et DOM. 3046 this.renderTemplate = thisRender; 3047 3048 this.afterRender(); 3049 } catch (error) { 3050 // Garde de fiabilité : une exception dans render()/diff ne doit pas 3051 // casser l'ensemble de l'application. Le DOM est conservé en l'état. 3052 console.error('[beekube-dom] Ãchec de la mise à jour du composant ; DOM conservé en l\'état.', error); 3053 } 3054 } 3055 3056 get props() { 3057 return Object.assign({}, this.states); 3058 } 3059 3060 render() { 3061 return []; 3062 } 3063 3064 beforeRender() { 3065 3066 } 3067 3068 afterRender() { 3069 3070 } 3071 3072 beforeMount() { 3073 3074 } 3075 3076 afterMount() { 3077 3078 } 3079 3080 beforeDestroy() { 3081 3082 } 3083 3084 destroy() { 3085 3086 this.beforeDestroy(); 3087 3088 // Remove All DOM 3089 if (this.DOMModule) { 3090 this.DOMModule.deleteDOM(); 3091 // On libère la référence au module (le `delete this` précédent était un no-op). 3092 this.DOMModule = null; 3093 } 3094 } 3095 3096 setProps(states) { 3097 this.props = states; 3098 } 3099 3100} 3101 3102/* harmony default export */ __webpack_exports__["default"] = (Component); 3103 3104 3105/***/ }), 3106
vendor: 36,032 bytes, lines 3107-4167
3107/***/ "./node_modules/beekube-dom/BaseApp/DOMModule.js": 3108/*!*******************************************************!*\ 3109 !*** ./node_modules/beekube-dom/BaseApp/DOMModule.js ***! 3110 \*******************************************************/ 3111/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 3112 3113/* harmony export */ __webpack_require__.d(__webpack_exports__, { 3114/* harmony export */ getAssignKeyTemplate: function() { return /* binding */ getAssignKeyTemplate; } 3115/* harmony export */ }); 3116/* harmony import */ var _DOM_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../DOM.js */ "./node_modules/beekube-dom/DOM.js"); 3117/* harmony import */ var _Helper_Object_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Helper/Object.js */ "./node_modules/beekube-dom/Helper/Object.js"); 3118/* harmony import */ var _Helper_String_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Helper/String.js */ "./node_modules/beekube-dom/Helper/String.js"); 3119/* harmony import */ var js_struct_compare__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! js-struct-compare */ "./node_modules/js-struct-compare/src/index.mjs"); 3120/* harmony import */ var _Component_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Component.js */ "./node_modules/beekube-dom/BaseApp/Component.js"); 3121 3122 3123 3124 3125 3126 3127/** 3128 * Permet de générer du DOM HTML à partir d'une template JSON 3129 * Les événements sont pris également en compte et appliquer 3130 * Le paramètre parent indique dans quel élement du DOM, il sera insérer 3131 * 3132 * Les Variables sont une simple JSON (nom, valeur), exemple : {"name": "Damien"} 3133 * 3134 * Voici un exemple de template : 3135 * [{ 3136 'p': { 3137 'textContent': 'Bonjour {{name}}' 3138 }, 3139 }, { 3140 'div': { 3141 'children': [ 3142 { 3143 "label": { 3144 "textContent": "Nom" 3145 }, 3146 "input": { 3147 "type": "text", 3148 "value": "{{name}}", 3149 "change": { 3150 'listener': this.onChange, 3151 'useCapture': false 3152 }, 3153 "keyup": this.onChange 3154 } 3155 } 3156 ] 3157 } 3158 }] 3159 */ 3160function DOMModule(parentNode, template, variables) { 3161 3162 let parentNodeOption = Object.assign({ 3163 parentNode: null, 3164 index: null 3165 }, parentNode); 3166 3167 this.template = template; 3168 this.parentNode = parentNodeOption.parentNode; 3169 this.nodeIndex = parentNodeOption.index; 3170 this.variables = variables; 3171 this.DOMElement = null; 3172 this.elements = []; 3173 3174 this.getTemplateVariables(); 3175 this.render(); 3176} 3177 3178DOMModule.prototype.getTemplateVariables = function () { 3179 this._variableRender = getVariableInJSONTemplate(this.template); 3180}; 3181 3182const regexVariable = /\{\{(.*?)\}\}/gm; 3183 3184function getVariableInJSONTemplate(json) { 3185 var JSONVariable = {}; 3186 3187 for (let dataKey in json) { 3188 if (json.hasOwnProperty(dataKey)) { 3189 let jsonData = json[dataKey]; 3190 switch (typeof jsonData) { 3191 case 'object': 3192 JSONVariable[dataKey] = getVariableInJSONTemplate(jsonData); 3193 break; 3194 case 'function': 3195 JSONVariable[dataKey] = jsonData; 3196 break; 3197 case 'string': 3198 let m; 3199 while ((m = regexVariable.exec(jsonData)) !== null) { 3200 // This is necessary to avoid infinite loops with zero-width matches 3201 if (m.index === regexVariable.lastIndex) { 3202 regexVariable.lastIndex++; 3203 } 3204 3205 if (!JSONVariable.hasOwnProperty(dataKey)) { 3206 JSONVariable[dataKey] = []; 3207 } 3208 3209 JSONVariable[dataKey].push(m[1]); 3210 } 3211 3212 break; 3213 default: 3214 break; 3215 } 3216 } 3217 } 3218 3219 return JSONVariable; 3220} 3221 3222 3223function getAssignKeyTemplate(json, setKey = true) { 3224 var template = {}; 3225 3226 for (let dataKey in json) { 3227 if (json.hasOwnProperty(dataKey)) { 3228 let jsonData = json[dataKey]; 3229 switch (typeof jsonData) { 3230 case 'object': 3231 if (setKey) { 3232 for (let elementType in jsonData) { 3233 let element = jsonData[elementType]; 3234 const newKey = element.hasOwnProperty('key') ? element.key : `${elementType}-${dataKey}`; 3235 template[newKey] = {}; 3236 template[newKey][elementType] = element; 3237 template[newKey] = getAssignKeyTemplate(template[newKey], false); 3238 } 3239 } else { 3240 switch (dataKey) { 3241 case 'class': 3242 template[dataKey] = jsonData; 3243 break; 3244 default: 3245 template[dataKey] = getAssignKeyTemplate(jsonData, dataKey === 'children'); 3246 break; 3247 } 3248 3249 } 3250 3251 break; 3252 default: 3253 template[dataKey] = jsonData; 3254 break; 3255 } 3256 } 3257 } 3258 3259 return template; 3260} 3261 3262function assignVariableTemplate(context) { 3263 return recursiveAssignVariables(context.template, context._variableRender, context, context.DOMElement, null); 3264} 3265 3266 3267function recursiveAssignVariables(templateCurrent, templateRenderCurrent, context, DOMElementCurrent, elementParent = null) { 3268 3269 let newTemplateArray = {}; 3270 let DOMElement = DOMElementCurrent === null ? null : (0,_Helper_Object_js__WEBPACK_IMPORTED_MODULE_1__.cloneObject)(DOMElementCurrent); 3271 let template = (0,_Helper_Object_js__WEBPACK_IMPORTED_MODULE_1__.cloneObject)(templateCurrent); 3272 let templateRender = (0,_Helper_Object_js__WEBPACK_IMPORTED_MODULE_1__.cloneObject)(templateRenderCurrent); 3273 3274 // On boucle sur la template JSON 3275 for (let elementIndex in templateRender) { 3276 if (templateRender.hasOwnProperty(elementIndex) && template.hasOwnProperty(elementIndex)) { 3277 // let newTemplate = JSON.parse(JSON.stringify(template[elementIndex])); 3278 3279 let newTemplate = (0,_Helper_Object_js__WEBPACK_IMPORTED_MODULE_1__.cloneObject)(template[elementIndex]); 3280 newTemplateArray[elementIndex] = newTemplate; 3281 3282 // Dans le cas d'un composant, on transmet le parent, et les propriétés 3283 3284 if (typeof newTemplate === "function") { 3285 let element = null; 3286 if (elementParent === null) { 3287 if (DOMElement !== null) { 3288 element = DOMElement.DOM[elementIndex]; 3289 } else { 3290 element = null; 3291 } 3292 } else { 3293 element = elementParent[elementIndex]; 3294 } 3295 setVariableOnComponent( 3296 element, 3297 context 3298 ) 3299 } 3300 3301 // On boucle sur les élements DOM 3302 for (let elementName in templateRender[elementIndex]) { 3303 if (templateRender[elementIndex].hasOwnProperty(elementName)) { 3304 // On cherche l'element du DOM existant dans la page 3305 // Dans le cas contraire on met null sur element 3306 let element = null; 3307 if (elementParent === null) { 3308 if (DOMElement !== null) { 3309 element = DOMElement.DOM[elementIndex][elementName]; 3310 } else { 3311 element = null; 3312 } 3313 } else { 3314 switch (true) { 3315 case elementParent[elementIndex] === undefined: 3316 // Désynchronisation template / mapping DOM : on n'écrase pas le DOM, 3317 // setVariable retombera en mode string. à investiguer si ce warn apparaît. 3318 console.warn('DOMModule: élément "' + elementIndex + '" absent du mapping DOM', elementParent); 3319 element = null; 3320 break; 3321 case elementName === "Component": 3322 element = elementParent[elementIndex]; 3323 break; 3324 default: 3325 element = elementParent[elementIndex][elementName]; 3326 break; 3327 } 3328 } 3329 3330 3331 let JSONElement = templateRender[elementIndex][elementName]; 3332 let JSONElementTemplate = newTemplateArray[elementIndex][elementName]; 3333 3334 // On boucle sur les attributs de l'élément du DOM 3335 for (let attributeRender in JSONElement) { 3336 if (JSONElement.hasOwnProperty(attributeRender)) { 3337 let variableNames = JSONElement[attributeRender]; 3338 let attributeTemplate = JSONElementTemplate[attributeRender]; 3339 switch (attributeRender) { 3340 // On boucle sur les enfants pour créer aussi les variables 3341 case 'children': 3342 newTemplateArray[elementIndex][elementName][attributeRender] = recursiveAssignVariables( 3343 attributeTemplate, 3344 variableNames, 3345 context, 3346 !!element && element.hasOwnProperty('DOM') ? element : null, 3347 !element ? null : element.children, 3348 ); 3349 break; 3350 default: 3351 newTemplateArray[elementIndex][elementName][attributeRender] = setVariable( 3352 element && element.hasOwnProperty('DOM') ? element.DOM : element, 3353 attributeRender, 3354 attributeTemplate, 3355 variableNames, 3356 context); 3357 break; 3358 } 3359 } 3360 } 3361 } 3362 } 3363 } 3364 } 3365 3366 return newTemplateArray; 3367} 3368 3369const SET_VARIABLE_STRING = 1; 3370const SET_VARIABLE_DOM = 2; 3371 3372/** 3373 * Transmettre les propriétés au Composent enfant 3374 * @param _component 3375 * @param _context 3376 */ 3377function setVariableOnComponent(_component, _context) { 3378 // passe maintenant par autre part 3379 3380} 3381 3382/** 3383 * Changement proprement les variables 3384 * Si le DOM existe, seulement changer la valeur nécessaire pour éviter de reconstruire le DOM 3385 * @param element 3386 * @param attributeName 3387 * @param attributeValue 3388 * @param variablesName 3389 * @param context 3390 * @returns {*} 3391 */ 3392function setVariable(element, attributeName, attributeValue, variablesName, context) { 3393 let type = element === null ? SET_VARIABLE_STRING : SET_VARIABLE_DOM; 3394 let value = attributeValue; 3395 3396 if (!Array.isArray(variablesName)) { 3397 if(typeof attributeValue === "function" && attributeName === "function") { 3398 setVariableOnComponent( 3399 attributeValue, 3400 element 3401 ) 3402 } 3403 return attributeValue; 3404 }; 3405 3406 variablesName.forEach(function (nameVariable) { 3407 if (context.variables.hasOwnProperty(nameVariable)) { 3408 let variableValue = ''; 3409 // On vérifie si la valeur est une function 3410 // Si oui, on l'execute 3411 switch (typeof context.variables[nameVariable]) { 3412 case 'function': 3413 variableValue = context.variables[nameVariable](); 3414 break; 3415 default: 3416 variableValue = context.variables[nameVariable]; 3417 break; 3418 } 3419 3420 // Sécurité pour les valeurs null, car le remplace parse le null en string 3421 variableValue = variableValue === null ? '' : variableValue; 3422 3423 // split/join : remplace TOUTES les occurrences et n'interprète PAS les motifs 3424 // spéciaux de String.replace ($&, $1, ...) qui pourraient être présents dans la valeur. 3425 value = value.split('{{' + nameVariable + '}}').join(String(variableValue)); 3426 } 3427 }); 3428 if (type === SET_VARIABLE_DOM) { 3429 switch (attributeName) { 3430 case 'textContent': 3431 element.textContent = (0,_Helper_String_js__WEBPACK_IMPORTED_MODULE_2__.getContentVariable)(value); 3432 break; 3433 case 'value': 3434 element.value = (0,_Helper_String_js__WEBPACK_IMPORTED_MODULE_2__.getContentVariable)(value); 3435 break; 3436 case 'function': 3437 break; 3438 default: 3439 // Note : `value`/`checked` ont leurs cas dédiés plus haut. L'ancienne condition 3440 // `typeof element.hasAttribute(...) === 'string'` était toujours fausse (branche morte). 3441 element.setAttribute(attributeName, value); 3442 break; 3443 } 3444 } 3445 3446 return value; 3447} 3448 3449 3450function getFirstLevelDOMElements(render) { 3451 if (!render || !render.DOMElement || !render.DOMElement.DOM) { 3452 return []; 3453 } 3454 const firstLevelKeys = Object.keys(render.DOMElement.DOM); 3455 3456 return firstLevelKeys.map(key => { 3457 const element = render.DOMElement.DOM[key]; 3458 if (!element || typeof element !== 'object') { 3459 return null; 3460 } 3461 // Composant de premier niveau : on expose son premier nÅud DOM si disponible. 3462 if (element instanceof _Component_js__WEBPACK_IMPORTED_MODULE_4__["default"]) { 3463 const els = element.DOMModule && element.DOMModule.elements; 3464 return els && els.length ? els[0] : null; 3465 } 3466 const tagName = Object.keys(element)[0]; 3467 const tagNode = tagName ? element[tagName] : null; 3468 return tagNode && tagNode.DOM ? tagNode.DOM : null; 3469 }).filter(Boolean); 3470} 3471 3472 3473/** 3474 * Rendu de la template 3475 * @param context 3476 * @param templateCompare {'compare': Difference[], template: {}} 3477 */ 3478DOMModule.prototype.render = function (context = null, templateCompare = null) { 3479 context = context === null ? this : context; 3480 if (templateCompare !== null) { 3481 if (templateCompare.hasOwnProperty('compare') && templateCompare.hasOwnProperty('template')) { 3482 context = updateTemplate(context, templateCompare.compare, templateCompare.template); 3483 this.getTemplateVariables(); // Mise à jour des données sur les variables 3484 } 3485 } 3486 3487 let templateWithVariables = assignVariableTemplate(context); 3488 if (context.DOMElement === null) { 3489 context.DOMElement = new _DOM_js__WEBPACK_IMPORTED_MODULE_0__["default"](templateWithVariables, context.parentNode, null, context.nodeIndex); 3490 } 3491 3492 // Passe de réconciliation keyée : un pur réordonnancement d'une liste keyée n'émet 3493 // aucune Difference (js-struct-compare est insensible à l'ordre des clés). Cette passe 3494 // additive réaligne donc l'ordre du DOM sur l'ordre VOULU du template, uniquement via 3495 // insertBefore sur des nÅuds existants (préserve l'état natif), de façon idempotente. 3496 // L'ordre voulu vient du template fourni au render (templateCompare.template) car, faute 3497 // de Difference, context.template n'est PAS mis à jour lors d'un réordre. 3498 if (context.DOMElement && context.DOMElement.DOM) { 3499 const desiredTemplate = (templateCompare && templateCompare.template) 3500 ? templateCompare.template 3501 : context.template; 3502 reconcileKeyedOrder(desiredTemplate, context.DOMElement.DOM); 3503 } 3504 3505 // Toujours rafraîchir la liste des nÅuds racine : auparavant figée au premier rendu, 3506 // elle devenait périmée après chaque mise à jour (cause de crashs dans afterRender/afterMount). 3507 context.elements = getFirstLevelDOMElements(context); 3508}; 3509 3510/** 3511 * Réconciliation keyée : réordonne le DOM pour coller à l'ordre des clés du template. 3512 * Parcourt récursivement les groupes d'enfants keyés et n'émet que des insertBefore sur 3513 * des nÅuds existants. Ne crée ni ne supprime rien (le diff s'en charge déjà ). Idempotente. 3514 * @param templateGroup objet keyé { cle: { tag: {...children} } | { Component: {...} } } 3515 * @param domGroup map DOM keyée correspondante (context.DOMElement.DOM) 3516 */ 3517function reconcileKeyedOrder(templateGroup, domGroup) { 3518 if (!templateGroup || !domGroup || typeof templateGroup !== 'object') { 3519 return; 3520 } 3521 // 1. Réordonner les frères de CE groupe selon l'ordre du template 3522 reorderKeyedGroup(templateGroup, domGroup); 3523 // 2. Descendre récursivement dans les sous-groupes 'children' 3524 for (const key in templateGroup) { 3525 if (!templateGroup.hasOwnProperty(key)) continue; 3526 const childTemplate = getTemplateChildren(templateGroup[key]); 3527 const childDom = getDomChildren(domGroup[key]); 3528 if (childTemplate && childDom) { 3529 reconcileKeyedOrder(childTemplate, childDom); 3530 } 3531 } 3532} 3533 3534/** Récupère le sous-objet keyé `children` d'une entrée de template (forme élément). */ 3535function getTemplateChildren(templateEntry) { 3536 if (!templateEntry || typeof templateEntry !== 'object') return null; 3537 for (const tag in templateEntry) { 3538 if (!templateEntry.hasOwnProperty(tag)) continue; 3539 const node = templateEntry[tag]; 3540 if (node && typeof node === 'object' && node.children && typeof node.children === 'object') { 3541 return node.children; 3542 } 3543 } 3544 return null; 3545} 3546 3547/** Récupère la sous-map DOM `children` d'une entrée de la map DOM (forme élément). */ 3548function getDomChildren(domEntry) { 3549 if (!domEntry || typeof domEntry !== 'object' || domEntry instanceof _Component_js__WEBPACK_IMPORTED_MODULE_4__["default"]) { 3550 return null; 3551 } 3552 const tag = Object.keys(domEntry)[0]; 3553 const node = tag ? domEntry[tag] : null; 3554 return node && node.children && typeof node.children === 'object' ? node.children : null; 3555} 3556 3557/** 3558 * Résout une entrée de la map DOM en son/ses nÅud(s) DOM réel(s). 3559 * Gère les 3 formes : Component (multi-racines), élément { tag: { DOM } }, et le 3560 * wrapper CreateElementDOM (créé lors d'un ajout via le diff). 3561 * @returns {Element[]|null} 3562 */ 3563function resolveKeyNodes(domEntry) { 3564 if (domEntry == null || typeof domEntry !== 'object') return null; 3565 3566 if (domEntry instanceof _Component_js__WEBPACK_IMPORTED_MODULE_4__["default"]) { 3567 const els = domEntry.DOMModule && domEntry.DOMModule.elements; 3568 return els && els.length ? els.filter(Boolean) : null; 3569 } 3570 3571 if (domEntry instanceof _DOM_js__WEBPACK_IMPORTED_MODULE_0__["default"]) { 3572 let nodes = []; 3573 for (const k in domEntry.DOM) { 3574 const sub = resolveKeyNodes(domEntry.DOM[k]); 3575 if (sub) nodes = nodes.concat(sub); 3576 } 3577 return nodes.length ? nodes : null; 3578 } 3579 3580 const tag = Object.keys(domEntry)[0]; 3581 const node = tag ? domEntry[tag] : null; 3582 return node && node.DOM ? [node.DOM] : null; 3583} 3584 3585/** 3586 * Réordonne les nÅuds d'un groupe keyé pour coller à l'ordre des clés du template. 3587 * N'émet que des insertBefore, et MINIMISE le nombre de déplacements via la plus longue 3588 * sous-suite croissante (LIS) : les nÅuds déjà dans le bon ordre relatif ne bougent pas. 3589 * Idempotent (DOM déjà ordonné â 0 déplacement). 3590 */ 3591function reorderKeyedGroup(templateGroup, domGroup) { 3592 // L'ordre voulu est l'ordre d'énumération des clés du template (= ordre d'insertion). 3593 // LIMITATION : pour des clés ENTIÃRES ("0","1",â¦) JS énumère en ordre numérique croissant, 3594 // pas en ordre d'insertion â l'ordre voulu serait faux. Utiliser des clés `key` explicites 3595 // NON numériques (ex. "Item"+uid), comme le fait l'usage réel. Voir RESEARCH-keyed-reconciliation.md. 3596 const desired = []; 3597 const blocks = {}; 3598 for (const key in templateGroup) { 3599 if (!templateGroup.hasOwnProperty(key)) continue; 3600 if (domGroup[key] == null) continue; 3601 const nodes = resolveKeyNodes(domGroup[key]); 3602 if (nodes && nodes.length) { 3603 desired.push(key); 3604 blocks[key] = nodes; 3605 } 3606 } 3607 if (desired.length < 2) return; 3608 3609 const parent = blocks[desired[0]][0].parentNode; 3610 if (!parent) return; 3611 3612 // Ne garder que les blocs dont le premier nÅud est bien un enfant direct du parent commun. 3613 const keys = desired.filter(k => blocks[k][0].parentNode === parent); 3614 if (keys.length < 2) return; 3615 3616 // Ordre DOM courant : position de chaque clé (par son premier nÅud) parmi les enfants du parent. 3617 const posByKey = new Map(); 3618 const firstNodeToKey = new Map(); 3619 for (const k of keys) firstNodeToKey.set(blocks[k][0], k); 3620 let idx = 0; 3621 for (let n = parent.firstChild; n; n = n.nextSibling) { 3622 const k = firstNodeToKey.get(n); 3623 if (k !== undefined) posByKey.set(k, idx++); 3624 } 3625 3626 // seq[i] = position DOM courante de la i-ème clé VOULUE (permutation de 0..n-1). 3627 const seq = keys.map(k => posByKey.get(k)); 3628 3629 // LIS sur seq : indices (dans `keys`) des blocs déjà en ordre relatif â on ne les déplace PAS. 3630 const keepIdx = longestIncreasingSubsequenceIndices(seq); 3631 let j = keepIdx.length - 1; 3632 3633 // Parcours arrière : l'ancre est le premier nÅud du bloc suivant (déjà placé). 3634 for (let i = keys.length - 1; i >= 0; i--) { 3635 const anchor = (i + 1 < keys.length) ? blocks[keys[i + 1]][0] : null; 3636 if (j >= 0 && i === keepIdx[j]) { 3637 j--; // dans la LIS : reste en place 3638 continue; 3639 } 3640 const block = blocks[keys[i]]; 3641 // Itération AVANT : avec une ancre fixe, insérer dans l'ordre préserve l'ordre interne 3642 // du bloc (cas des composants multi-racines). 3643 for (let b = 0; b < block.length; b++) { 3644 const node = block[b]; 3645 if (node.parentNode !== parent) continue; 3646 parent.insertBefore(node, anchor); 3647 } 3648 } 3649} 3650 3651/** 3652 * Indices de la plus longue sous-suite strictement croissante de `arr` (O(n log n)). 3653 * `arr` est une permutation d'entiers distincts. Renvoie les indices (dans `arr`), croissants. 3654 */ 3655function longestIncreasingSubsequenceIndices(arr) { 3656 const n = arr.length; 3657 const predecessor = new Array(n).fill(-1); 3658 const tails = []; // tails[k] = index dans arr du plus petit "tail" d'une sous-suite de longueur k+1 3659 for (let i = 0; i < n; i++) { 3660 let lo = 0; 3661 let hi = tails.length; 3662 while (lo < hi) { 3663 const mid = (lo + hi) >> 1; 3664 if (arr[tails[mid]] < arr[i]) { 3665 lo = mid + 1; 3666 } else { 3667 hi = mid; 3668 } 3669 } 3670 if (lo > 0) predecessor[i] = tails[lo - 1]; 3671 tails[lo] = i; 3672 } 3673 const result = []; 3674 let k = tails.length ? tails[tails.length - 1] : -1; 3675 while (k >= 0) { 3676 result.push(k); 3677 k = predecessor[k]; 3678 } 3679 result.reverse(); 3680 return result; 3681} 3682 3683 3684function filterDeleted(value) { 3685 return value.get_type() === js_struct_compare__WEBPACK_IMPORTED_MODULE_3__.Difference.TYPE_DELETED; 3686} 3687 3688function filterOther(value) { 3689 return value.get_type() !== js_struct_compare__WEBPACK_IMPORTED_MODULE_3__.Difference.TYPE_DELETED; 3690} 3691 3692/** 3693 * 3694 * @param context 3695 * @param differenceList Difference[] 3696 * @param template object 3697 */ 3698function updateTemplate(context, differenceList, template) { 3699 3700 let deleted = differenceList.filter(filterDeleted); 3701 let others = differenceList.filter(filterOther); 3702 3703 let list = [...deleted, ...others]; 3704 3705 for (let diff in list) { 3706 if (list.hasOwnProperty(diff) && list[diff] instanceof js_struct_compare__WEBPACK_IMPORTED_MODULE_3__.Difference) { 3707 context = editTemplate(context, list[diff], template); 3708 } 3709 } 3710 3711 return context; 3712} 3713 3714/** 3715 * 3716 * @param context 3717 * @param diff 3718 * @param template 3719 */ 3720function editTemplate(context, diff, template) { 3721 return updateValue(context, diff.get_path(), diff.get_right_value(), diff.get_left_value(), diff.get_type(), template); 3722} 3723 3724const TYPE_NODELIST = 1; 3725const TYPE_ELEMENT = 2; 3726const TYPE_ATTRIBUTE = 3; 3727const TYPE_ATTRIBUTE_LIST = 4; 3728const TYPE_COMPONENT = 5; 3729 3730/** 3731 * 3732 * @param type 3733 * @param key 3734 * @returns {number} 3735 */ 3736function incrementType(type, key) { 3737 switch (type) { 3738 case TYPE_NODELIST: 3739 if (key === 'Component') { 3740 return TYPE_COMPONENT; 3741 } else { 3742 return TYPE_ELEMENT 3743 } 3744 case TYPE_ELEMENT: 3745 if (key === 'Component') { 3746 return TYPE_COMPONENT; 3747 } else { 3748 return TYPE_ATTRIBUTE 3749 } 3750 case TYPE_ATTRIBUTE: 3751 if (key === 'children') { 3752 return TYPE_NODELIST; 3753 } 3754 3755 if (key === 'class') { 3756 return TYPE_ATTRIBUTE_LIST; 3757 } 3758 3759 return TYPE_ATTRIBUTE; 3760 3761 case TYPE_ATTRIBUTE_LIST: 3762 return TYPE_ATTRIBUTE_LIST; 3763 case TYPE_COMPONENT: 3764 return TYPE_COMPONENT; 3765 } 3766 return TYPE_NODELIST; 3767} 3768 3769function deleteChildElement(name, element) { 3770 3771 switch (true) { 3772 // Composant 3773 case element instanceof _Component_js__WEBPACK_IMPORTED_MODULE_4__["default"]: 3774 element.destroy(); 3775 break; 3776 // Create DOM Element 3777 case element instanceof _DOM_js__WEBPACK_IMPORTED_MODULE_0__["default"]: 3778 if (element.hasOwnProperty('DOM')) { 3779 for (const indexChild in element.DOM) { 3780 const child = element.DOM[indexChild]; 3781 if (child instanceof _Component_js__WEBPACK_IMPORTED_MODULE_4__["default"]) { 3782 child.destroy(); 3783 } else { 3784 for (let elementName in child) { 3785 if (child.hasOwnProperty(elementName) && child[elementName].hasOwnProperty('DOM')) { 3786 child[elementName].DOM.remove(); 3787 } 3788 } 3789 } 3790 } 3791 } 3792 break; 3793 3794 // DOM 3795 case !element.hasOwnProperty('DOM'): 3796 for (let elementName in element) { 3797 if (element.hasOwnProperty(elementName)) { 3798 if (element[elementName].hasOwnProperty('DOM') && element[elementName].DOM instanceof Element) { 3799 element[elementName].DOM.remove(); 3800 } 3801 } 3802 } 3803 break; 3804 // String 3805 case typeof name === "string": 3806 if (element.DOM.hasOwnProperty(name)) { 3807 deleteChildElement(name, element.DOM[name]); 3808 } else { 3809 element.DOM.remove(); 3810 } 3811 3812 3813 break; 3814 default: 3815 element['children'][name].DOM.remove(); 3816 break; 3817 } 3818 3819} 3820 3821/** 3822 * Normalise une valeur de classe (string "a b", tableau ["a","b"], undefined/null) 3823 * en une liste de jetons exploitable par classList. Ãvite `undefined.split`/`array.split`. 3824 * @param v 3825 * @returns {string[]} 3826 */ 3827function toClassTokens(v) { 3828 if (Array.isArray(v)) { 3829 return v.filter(Boolean); 3830 } 3831 if (typeof v === 'string') { 3832 return v.split(' ').filter(Boolean); 3833 } 3834 return []; 3835} 3836 3837function updateValueInDOM(oldValue, value, typeDiff, name, typeIndex, element, parentElement, lastPathCurrentRight) { 3838 let elementDOM = !!element && element.hasOwnProperty('DOM') ? element.DOM : parentElement; 3839 3840 let thisElement; 3841 switch (true) { 3842 case !!element && element.hasOwnProperty(name): 3843 thisElement = element[name]; 3844 break; 3845 case !!element && elementDOM.hasOwnProperty(name): 3846 thisElement = elementDOM[name]; 3847 break; 3848 default: 3849 thisElement = element; 3850 break; 3851 } 3852 3853 3854 const REMOVE_OLD = typeDiff === js_struct_compare__WEBPACK_IMPORTED_MODULE_3__.Difference.TYPE_DELETED || typeDiff === js_struct_compare__WEBPACK_IMPORTED_MODULE_3__.Difference.TYPE_CHANGED; 3855 const ADD_NEW = typeDiff === js_struct_compare__WEBPACK_IMPORTED_MODULE_3__.Difference.TYPE_ADDED || typeDiff === js_struct_compare__WEBPACK_IMPORTED_MODULE_3__.Difference.TYPE_CHANGED; 3856 3857 switch (typeIndex) { 3858 case TYPE_NODELIST: 3859 if (REMOVE_OLD) { 3860 3861 for (const indexChild in element[name]) { 3862 const child = element[name][indexChild]; 3863 // Suppression Ancienne éléments 3864 if (child instanceof _DOM_js__WEBPACK_IMPORTED_MODULE_0__["default"]) { 3865 child.destroy(); 3866 } else if (child.hasOwnProperty('DOM')) { 3867 child.DOM.remove(); 3868 } else { 3869 // Format map {tag: {DOM, children}} (sémantique du render initial) 3870 deleteChildElement(indexChild, child); 3871 } 3872 } 3873 element[name] = []; 3874 3875 } 3876 3877 // Création du nouvelle élément 3878 // On stocke la map keyée (.DOM) pour rester cohérent avec le render initial 3879 // (cf. CreateElementDOM : thisDOM[typeElementKey]['children'] = children.DOM) 3880 if (ADD_NEW) { 3881 element[name] = new _DOM_js__WEBPACK_IMPORTED_MODULE_0__["default"](value, elementDOM).DOM; 3882 } 3883 3884 break; 3885 3886 case TYPE_ELEMENT: 3887 // Suppression de l'ancien élément 3888 3889 if (REMOVE_OLD) { 3890 // Suppression Ancienne éléments 3891 deleteChildElement(name, thisElement); 3892 delete element[name]; 3893 } 3894 3895 // Création du nouvelle élément 3896 if (ADD_NEW) { 3897 let DOMJSON = {}; 3898 DOMJSON[name] = value; 3899 const newElement = new _DOM_js__WEBPACK_IMPORTED_MODULE_0__["default"](DOMJSON, elementDOM); 3900 element[name] = newElement.DOM[name]; 3901 } 3902 3903 break; 3904 case TYPE_COMPONENT: 3905 3906 if(name === 'states') { 3907 if(element.hasOwnProperty('DOM')) { 3908 elementDOM.setProps(value); 3909 } else { 3910 element.setProps(value); 3911 } 3912 3913 } else { 3914 if (REMOVE_OLD) { 3915 deleteChildElement(name, thisElement); 3916 delete element[name]; 3917 } 3918 // Création du nouvelle élément 3919 if (ADD_NEW) { 3920 let component = null; 3921 3922 if (lastPathCurrentRight.hasOwnProperty(name)) { 3923 component = lastPathCurrentRight[name]; 3924 } 3925 let DOMJSON = {}; 3926 DOMJSON[name] = component; 3927 element[name] = new _DOM_js__WEBPACK_IMPORTED_MODULE_0__["default"](DOMJSON, elementDOM, null, name); 3928 } 3929 } 3930 3931 3932 break; 3933 case TYPE_ATTRIBUTE: 3934 switch (name) { 3935 case 'children': 3936 break; 3937 default: 3938 switch (name) { 3939 case 'class': { 3940 const removeTokens = toClassTokens(oldValue); 3941 const addTokens = toClassTokens(value); 3942 if (REMOVE_OLD && removeTokens.length) { 3943 elementDOM.classList.remove(...removeTokens); 3944 } 3945 if (ADD_NEW && addTokens.length) { 3946 elementDOM.classList.add(...addTokens); 3947 } 3948 break; 3949 } 3950 case 'textContent': 3951 if (REMOVE_OLD) { 3952 elementDOM.textContent = ''; 3953 } 3954 if (ADD_NEW) { 3955 elementDOM.textContent = value; 3956 } 3957 break; 3958 case 'innerHTML': 3959 if (REMOVE_OLD) { 3960 elementDOM.innerHTML = ''; 3961 } 3962 if (ADD_NEW) { 3963 elementDOM.innerHTML = value; 3964 } 3965 break; 3966 default: 3967 if (REMOVE_OLD) { 3968 elementDOM.removeAttribute(name); 3969 } 3970 if (ADD_NEW) { 3971 elementDOM.setAttribute(name, value); 3972 } 3973 break; 3974 } 3975 break; 3976 } 3977 break; 3978 case TYPE_ATTRIBUTE_LIST: 3979 switch (name) { 3980 case 'class': { 3981 const removeTokens = toClassTokens(oldValue); 3982 const addTokens = toClassTokens(value); 3983 if (REMOVE_OLD && removeTokens.length) { 3984 elementDOM.classList.remove(...removeTokens); 3985 } 3986 if (ADD_NEW && addTokens.length) { 3987 elementDOM.classList.add(...addTokens); 3988 } 3989 break; 3990 } 3991 default: 3992 break; 3993 } 3994 break; 3995 } 3996 3997 return element; 3998} 3999 4000 4001function recursiveUpdateValuePath(contextTemplate, template, currentDOM, paths, right_value, left_value, typeIndex, typeDiff, parentElement = null, lastKey = null) { 4002 4003 let last = paths.length === 1; 4004 const currentPath = paths.slice(); 4005 const keypath = currentPath.shift(); 4006 4007 switch (true) { 4008 case keypath === 'class': 4009 case typeIndex === TYPE_COMPONENT && contextTemplate.hasOwnProperty('states'): 4010 last = true; 4011 break; 4012 } 4013 let DOM = (0,_Helper_Object_js__WEBPACK_IMPORTED_MODULE_1__.cloneObject)(currentDOM); 4014 4015 let currentContextTemplate = (0,_Helper_Object_js__WEBPACK_IMPORTED_MODULE_1__.cloneObject)(contextTemplate); 4016 let currentTemplate = (0,_Helper_Object_js__WEBPACK_IMPORTED_MODULE_1__.cloneObject)(template); 4017 const currentParentElement = DOM.hasOwnProperty('DOM') ? DOM.DOM : parentElement; 4018 4019 4020 const keyTypeElement = currentTemplate[keypath] !== "undefined" && typeof currentTemplate[keypath] === "object" && currentTemplate[keypath].hasOwnProperty('Component') ? 'Component' : keypath; 4021 typeIndex = incrementType(typeIndex, keyTypeElement); 4022 4023 4024 // L'élement n'existe pas encore dans la template 4025 if (currentContextTemplate[keypath] === undefined && currentTemplate[keypath] === undefined) { 4026 if (typeDiff === js_struct_compare__WEBPACK_IMPORTED_MODULE_3__.Difference.TYPE_DELETED) { 4027 return { 4028 DOM, 4029 'contextTemplate': currentContextTemplate, 4030 'template': currentTemplate 4031 }; 4032 } else { 4033 right_value = keypath === 'children' ? getAssignKeyTemplate([right_value], true) : right_value; 4034 DOM = updateValueInDOM(left_value, right_value, typeDiff, keypath, typeIndex, DOM, parentElement, currentTemplate, lastKey); 4035 currentTemplate[keypath] = right_value; 4036 } 4037 } else { 4038 4039 4040 if (last) { 4041 4042 switch (true) { 4043 case keypath === 'states': 4044 DOM = updateValueInDOM(currentContextTemplate[keypath], currentTemplate[keypath], typeDiff, keypath, typeIndex, DOM, parentElement, currentTemplate, lastKey); 4045 currentContextTemplate[keypath] = currentTemplate[keypath]; 4046 break; 4047 case typeDiff === js_struct_compare__WEBPACK_IMPORTED_MODULE_3__.Difference.TYPE_DELETED: 4048 DOM = updateValueInDOM(left_value, right_value, typeDiff, keypath, typeIndex, DOM, parentElement, currentTemplate, lastKey); 4049 switch (keypath) { 4050 case 'class': 4051 const keyclass = currentPath.shift(); 4052 if (currentContextTemplate.hasOwnProperty(keypath)) { 4053 if (typeof currentContextTemplate[keypath] === 'string') { 4054 currentContextTemplate[keypath] = currentContextTemplate[keypath].replace(left_value, ''); 4055 } 4056 if (Array.isArray(currentContextTemplate[keypath])) { 4057 currentContextTemplate[keypath].hasOwnProperty(keyclass) ? delete currentContextTemplate[keypath][keyclass] : ''; 4058 } 4059 } 4060 4061 break; 4062 default: 4063 delete currentContextTemplate[keypath]; 4064 break; 4065 } 4066 break; 4067 default: 4068 DOM = updateValueInDOM(left_value, right_value, typeDiff, keypath, typeIndex, DOM, parentElement, currentTemplate, lastKey); 4069 currentContextTemplate[keypath] = right_value; 4070 break; 4071 } 4072 4073 4074 } else { 4075 4076 switch (true) { 4077 case DOM.hasOwnProperty(keypath): 4078 currentDOM = DOM[keypath]; 4079 break; 4080 case keypath === "Component" && currentDOM.hasOwnProperty('DOM'): 4081 //currentDOM = currentParentElement; 4082 for(const componentKey in currentDOM.DOM) { 4083 currentDOM = currentDOM.DOM[componentKey]; 4084 } 4085 4086 break; 4087 } 4088 4089 const dataChild = recursiveUpdateValuePath(currentContextTemplate[keypath], currentTemplate[keypath], currentDOM, currentPath, right_value, left_value, typeIndex, typeDiff, currentParentElement, keypath); 4090 DOM[keypath] = dataChild.DOM; 4091 currentContextTemplate[keypath] = dataChild.contextTemplate; 4092 currentTemplate[keypath] = dataChild.template; 4093 4094 } 4095 4096 } 4097 4098 return { 4099 DOM, 4100 'contextTemplate': currentContextTemplate, 4101 'template': currentTemplate 4102 } 4103 4104} 4105 4106function updateValue(context, paths, right_value, left_value, typeDiff, template) { 4107 4108 const data = recursiveUpdateValuePath(context.template, template, context.DOMElement.DOM, paths, right_value, left_value, TYPE_NODELIST, typeDiff, context.parentNode); 4109 4110 context.template = data.contextTemplate; 4111 context.DOMElement.DOM = data.DOM; 4112 4113 return context; 4114} 4115 4116/** 4117 * 4118 * @param DOM 4119 */ 4120function deleteRecursiveDOM(DOM) { 4121 for (const index in DOM) { 4122 const element = DOM[index]; 4123 if (element === null || typeof element !== 'object') { 4124 continue; 4125 } 4126 4127 // Composant enfant : on délègue à son propre cycle de destruction 4128 // (qui retire ses écouteurs et détruit ses propres enfants). 4129 if (element instanceof _Component_js__WEBPACK_IMPORTED_MODULE_4__["default"]) { 4130 element.destroy(); 4131 continue; 4132 } 4133 4134 for (let name in element) { 4135 const node = element[name]; 4136 if (node === null || typeof node !== 'object') { 4137 continue; 4138 } 4139 if (node instanceof _Component_js__WEBPACK_IMPORTED_MODULE_4__["default"]) { 4140 node.destroy(); 4141 continue; 4142 } 4143 // Descente récursive pour détruire d'éventuels composants imbriqués 4144 // avant de retirer le nÅud parent. 4145 if (node.children) { 4146 deleteRecursiveDOM(node.children); 4147 } 4148 if (node.hasOwnProperty('DOM') && node.DOM && typeof node.DOM.remove === 'function') { 4149 node.DOM.remove(); 4150 } 4151 } 4152 } 4153} 4154 4155DOMModule.prototype.deleteDOM = function () { 4156 if (this.DOMElement.DOM !== null) { 4157 this.DOMElement.removeEvent(); 4158 deleteRecursiveDOM(this.DOMElement.DOM); 4159 } 4160}; 4161 4162/* harmony default export */ __webpack_exports__["default"] = (DOMModule); 4163 4164 4165 4166/***/ }), 4167
vendor: 8,764 bytes, lines 4168-4416
4168/***/ "./node_modules/beekube-dom/DOM.js": 4169/*!*****************************************!*\ 4170 !*** ./node_modules/beekube-dom/DOM.js ***! 4171 \*****************************************/ 4172/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 4173 4174/* harmony import */ var _Helper_String_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Helper/String.js */ "./node_modules/beekube-dom/Helper/String.js"); 4175 4176 4177/** 4178 * Créer un élement DOM en JSON 4179 * Et créer les évenements si nécessaire 4180 * @param dataJson object 4181 * @param parentElement element 4182 * @constructor 4183 * 4184 * * Voici un exemple de template : 4185 * [{ 4186 'p': { 4187 'textContent': 'Remplir le formulaire ci-dessous' 4188 }, 4189 }, { 4190 'div': { 4191 'children': [ 4192 { 4193 "label": { 4194 "textContent": "Nom" 4195 }, 4196 "input": { 4197 "type": "text", 4198 "value": "", 4199 "change": { 4200 'listener': this.onChange, 4201 'useCapture': false 4202 }, 4203 "keyup": this.onChange 4204 } 4205 } 4206 ] 4207 } 4208 }] 4209 * 4210 */ 4211function CreateElementDOM(dataJson, parentElement, type, indexInsert) { 4212 parentElement = typeof parentElement === "undefined" ? null : parentElement; 4213 type = typeof type === "undefined" ? null : type; 4214 indexInsert = typeof indexInsert === "undefined" ? null : indexInsert; 4215 4216 this.event = []; 4217 this.DOM = {}; 4218 4219 let _this = this; 4220 4221 for(const key in dataJson) { 4222 let element = dataJson[key]; 4223 let thisDOM = {}; 4224 4225 if (typeof element === "function") { 4226 _this.DOM[key] = new element(parentElement, indexInsert); 4227 return true; 4228 } 4229 4230 for (let typeElementKey in element) { 4231 if (element.hasOwnProperty(typeElementKey)) { 4232 let thisType = 'html'; 4233 let elemJSON = element[typeElementKey]; 4234 4235 const typeElement = !elemJSON.hasOwnProperty('typeElement') ? typeElementKey : elemJSON.typeElement; 4236 4237 if (typeElement === "Component") { 4238 if (elemJSON.hasOwnProperty('function')) { 4239 if(elemJSON.hasOwnProperty('states')) { 4240 _this.DOM[key] = new elemJSON.function(elemJSON.states, parentElement, indexInsert); 4241 } else { 4242 _this.DOM[key] = new elemJSON.function(parentElement, indexInsert); 4243 } 4244 4245 } 4246 continue; 4247 } 4248 4249 if (type === 'svg') { 4250 thisType = type 4251 } else { 4252 if (typeElement === 'svg') { 4253 thisType = typeElement; 4254 } else { 4255 thisType = 'html'; 4256 } 4257 } 4258 let elem; 4259 if (thisType === 'svg') { 4260 elem = document.createElementNS("http://www.w3.org/2000/svg", typeElement); 4261 } else { 4262 elem = document.createElement(typeElement); 4263 } 4264 4265 4266 thisDOM[typeElementKey] = { 4267 'DOM': elem 4268 }; 4269 4270 4271 for (let attribute in elemJSON) { 4272 if (elemJSON.hasOwnProperty(attribute)) { 4273 switch (attribute) { 4274 case 'children': 4275 let children = new CreateElementDOM(elemJSON[attribute], elem, thisType); 4276 // concat() retourne un NOUVEAU tableau : il faut réassigner, 4277 // sinon les écouteurs des enfants ne sont jamais collectés (fuite). 4278 _this.event = _this.event.concat(children.event); 4279 thisDOM[typeElementKey]['children'] = children.DOM; 4280 break; 4281 case 'textContent': 4282 elem.textContent = (0,_Helper_String_js__WEBPACK_IMPORTED_MODULE_0__.getContentVariable)(elemJSON[attribute]); 4283 break; 4284 case 'innerHTML': 4285 elem.innerHTML = elemJSON[attribute]; 4286 break; 4287 case 'class': 4288 let classes = []; 4289 if (typeof elemJSON[attribute] === "object") { 4290 classes = elemJSON[attribute] 4291 } else { 4292 classes = elemJSON[attribute].split(' '); 4293 } 4294 4295 for (let thisClass in classes) { 4296 if (classes[thisClass]) { 4297 elem.classList.add(classes[thisClass]); 4298 } 4299 } 4300 4301 break; 4302 default: 4303 // Réassignation indispensable (concat ne mute pas) pour 4304 // pouvoir retirer ces écouteurs via removeEvent(). 4305 _this.event = _this.event.concat( 4306 setAttribute(elem, attribute, elemJSON[attribute]) 4307 ); 4308 break; 4309 } 4310 } 4311 } 4312 4313 if (parentElement) { 4314 if (indexInsert === null || !parentElement.children.hasOwnProperty(indexInsert)) { 4315 parentElement.appendChild(elem); 4316 } else { 4317 parentElement.insertBefore(elem, parentElement.children[indexInsert]); 4318 } 4319 } 4320 4321 _this.DOM[key] = thisDOM; 4322 } 4323 } 4324 } 4325} 4326 4327CreateElementDOM.prototype.removeEvent = function () { 4328 this.event.forEach(function (event) { 4329 let element = event.element; 4330 if (element.removeEventListener) { 4331 element.removeEventListener(event.type, event.listener, event.options); 4332 } 4333 }); 4334}; 4335 4336const regexAttributeNamespace = /([^:]*):([^:]*)/; 4337 4338const namespaceLink = { 4339 'xlink' : "http://www.w3.org/1999/xlink" 4340} 4341function nameSpaceXmlLink(namespace) { 4342 if(namespaceLink.hasOwnProperty(namespace)) { 4343 return namespaceLink[namespace]; 4344 } else { 4345 return namespace; 4346 } 4347} 4348/** 4349 * SetAttribute element and return event 4350 * @param element 4351 * @param attributeName 4352 * @param attributeValue 4353 * @returns {Array} 4354 */ 4355function setAttribute(element, attributeName, attributeValue) { 4356 4357 let event = []; 4358 4359 switch (typeof attributeValue) { 4360 4361 case 'string': 4362 case 'number': 4363 let withNamespace = regexAttributeNamespace.exec(attributeName); 4364 if(withNamespace) { 4365 element.setAttributeNS(nameSpaceXmlLink(withNamespace[1]), withNamespace[2], attributeValue); 4366 } else { 4367 element.setAttribute(attributeName, attributeValue); 4368 } 4369 4370 break; 4371 4372 case 'function': 4373 element.addEventListener(attributeName, attributeValue, false); 4374 // On enregistre aussi les écouteurs passés sous forme de fonction, 4375 // sinon removeEvent() ne peut pas les retirer (fuite mémoire). 4376 event.push({ 4377 'element': element, 4378 'type': attributeName, 4379 'listener': attributeValue, 4380 'options': false 4381 }); 4382 break; 4383 4384 case 'object': 4385 let listener = attributeValue.hasOwnProperty('listener') ? attributeValue.listener : function () { 4386 }; 4387 let useCapture = attributeValue.hasOwnProperty('useCapture') ? attributeValue.useCapture : null; 4388 let options = false; 4389 4390 if (useCapture === null) { 4391 options = attributeValue.hasOwnProperty('options') ? attributeValue.options : false; 4392 } 4393 4394 element.addEventListener(attributeName, listener, options); 4395 4396 event.push({ 4397 'element': element, 4398 'type': attributeName, 4399 'listener': listener, 4400 'options': options 4401 }); 4402 4403 break; 4404 4405 default: 4406 break; 4407 } 4408 4409 return event; 4410} 4411 4412/* harmony default export */ __webpack_exports__["default"] = (CreateElementDOM); 4413 4414 4415/***/ }), 4416
vendor: 6,216 bytes, lines 4417-4630
4417/***/ "./node_modules/beekube-dom/Helper/Event.js": 4418/*!**************************************************!*\ 4419 !*** ./node_modules/beekube-dom/Helper/Event.js ***! 4420 \**************************************************/ 4421/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 4422 4423/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4424/* harmony export */ EventOn: function() { return /* binding */ EventOn; }, 4425/* harmony export */ defaultEventOptions: function() { return /* binding */ defaultEventOptions; } 4426/* harmony export */ }); 4427/* unused harmony exports EventOff, EventFire, eventIsOnSelector */ 4428/* harmony import */ var _Object_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Object.js */ "./node_modules/beekube-dom/Helper/Object.js"); 4429// Gestionnaire d'evenement 4430 4431 4432const EVENT_ON = 1; 4433const EVENT_OFF = 0; 4434 4435 4436 4437function dispatchTypeEvent(status, eventObject) { 4438 if (!eventObject.element || typeof eventObject.element.addEventListener !== 'function') { 4439 return; 4440 } 4441 switch (status) { 4442 case EVENT_ON: 4443 eventObject.element.addEventListener(eventObject.type, eventObject.listener, eventObject.options); 4444 break; 4445 case EVENT_OFF: 4446 eventObject.element.removeEventListener(eventObject.type, eventObject.listener, eventObject.options); 4447 break; 4448 } 4449} 4450 4451/** 4452 * @param status 4453 * @param eventObject object 4454 * @returns {*} 4455 * 4456 * 4457 */ 4458function configureEvent(status, eventObject) { 4459 4460 eventObject = Object.assign({}, defaultEventOptions, eventObject); 4461 4462 if (eventObject.element === null) { 4463 return false; 4464 } 4465 4466 switch(true) { 4467 4468 case eventObject.element instanceof eventObject.context.NodeList: 4469 case eventObject.element instanceof Array: 4470 4471 let elements = Array.from(eventObject.element); 4472 elements.forEach(function (element) { 4473 let eventObjectClone = { 4474 'element': element, 4475 'type': eventObject.type, 4476 'listener': eventObject.listener, 4477 'options': eventObject.options, 4478 }; 4479 4480 dispatchTypeEvent(status, eventObjectClone); 4481 }); 4482 4483 break; 4484 case eventObject.element instanceof eventObject.context.Element: 4485 dispatchTypeEvent(status, eventObject); 4486 break; 4487 default: 4488 dispatchTypeEvent(status, eventObject); 4489 break; 4490 } 4491 4492 4493 4494 return true; 4495} 4496 4497 4498const matchEventType = { 4499 'FocusEvent': ['focus', 'blur', 'focusin', 'focusout'], 4500 'MouseEvent': ['click', 'dblclick', 'mouseup', 'mousedown'], 4501 'TouchEvent': ['touchstart', 'touchend', 'touchmove', 'touchcancel'], 4502 'KeyboardEvent': ['keydown', 'keypress', 'keyup'], 4503}; 4504 4505const matchEventObject = { 4506 'FocusEvent': typeof FocusEvent === "undefined" ? Event : FocusEvent, 4507 'MouseEvent': typeof MouseEvent === "undefined" ? Event : MouseEvent, 4508 'TouchEvent': typeof TouchEvent === "undefined" ? Event : TouchEvent, 4509 'KeyboardEvent': typeof KeyboardEvent === "undefined" ? Event : KeyboardEvent, 4510} 4511 4512function getEventObject(eventName) { 4513 for( let event in matchEventType ) { 4514 4515 if(matchEventType[event].indexOf(eventName) !== -1) { 4516 return matchEventObject[event]; 4517 } 4518 } 4519 return Event; 4520} 4521 4522 4523/** 4524 * @param obj 4525 * @param evts 4526 * @param data 4527 * @param options 4528 * @returns {boolean} 4529 */ 4530function fireEventElement(obj, evts, data = false, options = {"bubbles":true, "cancelable":true}) { 4531 var t, evt; 4532 4533 if (obj === null || typeof obj === "undefined") { 4534 return false; 4535 } 4536 // on verifie si il y a plusieurs élements 4537 evts = (evts || "").match(/\S+/g) || [""]; 4538 // on les comptes 4539 t = evts.length; 4540 // On créé chaque évenement un par un 4541 while (t--) { 4542 evt = evts[t]; 4543 if (typeof Event === 'function' || !document.fireEvent) { 4544 var eventClass = getEventObject(evt, options); 4545 var event = new eventClass(evt, options); 4546 4547 if(data) { 4548 Object.assign(event, data); 4549 } 4550 4551 obj.dispatchEvent(event); 4552 } else { 4553 obj.fireEvent('on' + evt); 4554 } 4555 } 4556} 4557 4558/** 4559 * @param objs 4560 * @param evts 4561 * @param data 4562 * @param options 4563 * @returns {boolean} 4564 */ 4565function fireEvent(objs, evts, data = false, options = {"bubbles":true, "cancelable":true}) { 4566 4567 4568 if (objs === null || typeof objs === "undefined") { 4569 return false; 4570 } 4571 4572 objs = objs instanceof NodeList || (0,_Object_js__WEBPACK_IMPORTED_MODULE_0__.isNodeList)(objs) || Array.isArray(objs) ? Array.from(objs) : [objs]; 4573 objs.forEach(obj => { 4574 fireEventElement(obj, evts, data, options); 4575 }); 4576 4577 return true; 4578} 4579 4580//Returns true if it is a DOM element 4581function isElement(o) { 4582 // `o != null` est indispensable : `typeof null === "object"`, donc sans cette garde 4583 // l'accès à `o.nodeType` lèverait une TypeError sur une cible nulle. 4584 return ( 4585 o != null && typeof o === "object" && o.nodeType === 1 && typeof o.nodeName === "string" 4586 ); 4587} 4588 4589function eventIsOnSelector(event, selector) { 4590 if (!isElement(event.target)) { 4591 return false; 4592 } 4593 var DOM = event.target.matches(selector) ? event.target : event.target.closest(selector); 4594 if (DOM === null) { 4595 return false; 4596 } 4597 4598 return DOM; 4599} 4600 4601 4602 4603const EventOn = configureEvent.bind(null, EVENT_ON); 4604const EventOff = configureEvent.bind(null, EVENT_OFF); 4605const EventFire = fireEvent; 4606 4607const defaultEventOptions = { 4608 'element': null, 4609 'type': 'click', 4610 'listener': function () {}, 4611 'options': false, 4612 // Garde : éviter une ReferenceError au chargement du module en environnement sans `window` 4613 // (Node/SSR). Les fonctions d'événements ne sont de toute façon utiles que côté navigateur. 4614 'context': typeof window !== 'undefined' ? window : undefined 4615}; 4616 4617const HelperEvent = { 4618 on: EventOn, 4619 off: EventOff, 4620 fire: EventFire, 4621 eventIsOnSelector: eventIsOnSelector, 4622 defaultEventOptions: defaultEventOptions 4623}; 4624 4625 4626/* unused harmony default export */ var __WEBPACK_DEFAULT_EXPORT__ = (HelperEvent); 4627 4628 4629/***/ }), 4630
vendor: 2,555 bytes, lines 4631-4701
4631/***/ "./node_modules/beekube-dom/Helper/Object.js": 4632/*!***************************************************!*\ 4633 !*** ./node_modules/beekube-dom/Helper/Object.js ***! 4634 \***************************************************/ 4635/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 4636 4637/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4638/* harmony export */ cloneObject: function() { return /* binding */ cloneObject; }, 4639/* harmony export */ isNodeList: function() { return /* binding */ isNodeList; } 4640/* harmony export */ }); 4641/* unused harmony export isObject */ 4642/* harmony import */ var _BaseApp_Component_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../BaseApp/Component.js */ "./node_modules/beekube-dom/BaseApp/Component.js"); 4643 4644 4645function isObject(obj) { 4646 let type = typeof obj; 4647 return type === 'object' && !!obj; 4648} 4649 4650// Détecte un élément DOM sans référencer un global `window` non garanti (SSR / tests Node). 4651function isDomElement(o) { 4652 if (o === null || typeof o !== 'object') return false; 4653 if (typeof Element !== 'undefined' && o instanceof Element) return true; 4654 const doc = o.ownerDocument; 4655 if (doc && doc.defaultView && o instanceof doc.defaultView.Element) return true; 4656 return false; 4657} 4658 4659function cloneObject(src) { 4660 // Fonctions : retournées telles quelles 4661 if (typeof src === "function") return src; 4662 4663 // null / primitives : rien à cloner. 4664 // Garde indispensable : sans elle, `null.ownerDocument` lève TypeError, ce qui 4665 // fait planter tout cycle de diff de liste (chemins ADDED/DELETED asymétriques). 4666 if (src === null || typeof src !== "object") return src; 4667 4668 // Ãléments DOM et composants : on conserve la référence (pas de clone profond) 4669 if (isDomElement(src)) return src; 4670 if (src instanceof _BaseApp_Component_js__WEBPACK_IMPORTED_MODULE_0__["default"]) return src; 4671 4672 let target = Array.isArray(src) ? [] : {}; 4673 4674 for (let prop in src) { 4675 if (src.hasOwnProperty(prop)) { 4676 // if the value is a nested object, recursively copy all it's properties 4677 if (isObject(src[prop])) { 4678 target[prop] = cloneObject(src[prop]); 4679 } else { 4680 target[prop] = src[prop]; 4681 } 4682 } 4683 } 4684 4685 return target; 4686} 4687 4688function isNodeList(el) { 4689 return el != null 4690 && typeof el.length == 'number' 4691 && typeof el.item == 'function' 4692 && typeof el.nextNode == 'function' 4693 && typeof el.reset == 'function'; 4694} 4695 4696 4697 4698 4699 4700/***/ }), 4701
vendor: 790 bytes, lines 4702-4728
4702/***/ "./node_modules/beekube-dom/Helper/String.js": 4703/*!***************************************************!*\ 4704 !*** ./node_modules/beekube-dom/Helper/String.js ***! 4705 \***************************************************/ 4706/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 4707 4708/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4709/* harmony export */ getContentVariable: function() { return /* binding */ getContentVariable; } 4710/* harmony export */ }); 4711 4712function getContentVariable(element) { 4713 let content = ''; 4714 switch (typeof element) { 4715 case 'function': 4716 content = element(); 4717 break; 4718 default : 4719 content = element; 4720 break; 4721 } 4722 return content; 4723} 4724 4725 4726 4727/***/ }), 4728
vendor: 4,606 bytes, lines 4729-4861
4729/***/ "./node_modules/js-struct-compare/src/Comparator.mjs": 4730/*!***********************************************************!*\ 4731 !*** ./node_modules/js-struct-compare/src/Comparator.mjs ***! 4732 \***********************************************************/ 4733/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 4734 4735/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4736/* harmony export */ "default": function() { return /* binding */ Comparator; } 4737/* harmony export */ }); 4738/* harmony import */ var _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Difference.mjs */ "./node_modules/js-struct-compare/src/Difference.mjs"); 4739/* harmony import */ var _utils_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.mjs */ "./node_modules/js-struct-compare/src/utils.mjs"); 4740 4741 4742 4743/** 4744 * Compares two (JSON-serializable) structures and returns their differences. 4745 * @constructor 4746 */ 4747function Comparator() { 4748} 4749 4750/** 4751 * Compares two structures and returns an array of their differences. 4752 * 4753 * @param {*} left 4754 * @param {*} right 4755 * @return {Difference[]} 4756 */ 4757Comparator.prototype.compare = function (left, right) { 4758 return this.compare_values(left, right, []); 4759}; 4760 4761/** 4762 * Compares two values at the same path. 4763 * 4764 * @param {*} left 4765 * @param {*} right 4766 * @param {Array} path 4767 * @return {Difference[]} 4768 * @private 4769 */ 4770Comparator.prototype.compare_values = function (left, right, path) { 4771 let left_is_array, right_is_array, left_is_object, right_is_object; 4772 4773 left_is_array = Array.isArray(left); 4774 right_is_array = Array.isArray(right); 4775 left_is_object = left_is_array === false && (0,_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.is_object)(left); 4776 right_is_object = right_is_array === false && (0,_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.is_object)(right); 4777 4778 if (left_is_array && right_is_array) { 4779 return this.compare_arrays(left, right, path); 4780 } else if (left_is_object && right_is_object) { 4781 return this.compare_objects(left, right, path); 4782 } 4783 4784 if (left !== right) { 4785 return [ new _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__["default"](path, _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__["default"].TYPE_CHANGED, left, right) ]; 4786 } else { 4787 return []; 4788 } 4789}; 4790 4791/** 4792 * Compares the elements in two objects at the same path. 4793 * 4794 * @param {Object} left 4795 * @param {Object} right 4796 * @param {Array} path 4797 * @return {Difference[]} 4798 * @private 4799 */ 4800Comparator.prototype.compare_objects = function (left, right, path) { 4801 let self = this, differences = []; 4802 4803 for (let left_key in left) { 4804 if (left.hasOwnProperty(left_key)) { 4805 const element_path = path.concat(left_key); 4806 const left_value = left[left_key]; 4807 if (typeof right[left_key] === "undefined") { 4808 differences.push(new _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__["default"](element_path, _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__["default"].TYPE_DELETED, left_value, undefined)); 4809 } else { 4810 differences = differences.concat(self.compare_values(left_value, right[left_key], element_path)); 4811 } 4812 } 4813 } 4814 4815 for (let right_key in right) { 4816 if (right.hasOwnProperty(right_key)) { 4817 const element_path = path.concat(right_key); 4818 const right_value = right[right_key]; 4819 if (typeof left[right_key] === "undefined") { 4820 differences.push(new _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__["default"](element_path, _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__["default"].TYPE_ADDED, undefined, right_value)); 4821 } 4822 } 4823 } 4824 4825 return differences; 4826}; 4827 4828/** 4829 * Compares the elements in two arrays at the same path. 4830 * 4831 * @param {Array} left 4832 * @param {Array} right 4833 * @param {Array} path 4834 * @return {Difference[]} 4835 * @private 4836 */ 4837Comparator.prototype.compare_arrays = function (left, right, path) { 4838 let self = this, differences = []; 4839 4840 left.forEach(function (left_value, left_index) { 4841 const element_path = path.concat(left_index); 4842 if (typeof right[left_index] === "undefined") { 4843 differences.push(new _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__["default"](element_path, _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__["default"].TYPE_DELETED, left_value, undefined)); 4844 } else { 4845 differences = differences.concat(self.compare_values(left_value, right[left_index], element_path)); 4846 } 4847 }); 4848 4849 right.forEach(function (right_value, right_index) { 4850 const element_path = path.concat(right_index); 4851 if (typeof left[right_index] === "undefined") { 4852 differences.push(new _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__["default"](element_path, _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__["default"].TYPE_ADDED, undefined, right_value)); 4853 } 4854 }); 4855 4856 return differences; 4857}; 4858 4859 4860/***/ }), 4861
vendor: 2,151 bytes, lines 4862-4948
4862/***/ "./node_modules/js-struct-compare/src/Difference.mjs": 4863/*!***********************************************************!*\ 4864 !*** ./node_modules/js-struct-compare/src/Difference.mjs ***! 4865 \***********************************************************/ 4866/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 4867 4868/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4869/* harmony export */ "default": function() { return /* binding */ Difference; } 4870/* harmony export */ }); 4871/** 4872 * @param {Array} path 4873 * @param {String} type 4874 * @param {*} left_value 4875 * @param {*} right_value 4876 * @constructor 4877 */ 4878function Difference(path, type, left_value, right_value) { 4879 /** @private */ 4880 this.path = path; 4881 /** @private */ 4882 this.type = type; 4883 /** @private */ 4884 this.left_value = left_value; 4885 /** @private */ 4886 this.right_value = right_value; 4887} 4888 4889/** 4890 * Indicates that the element was added in the transition from 'left' to 'right' structure 4891 * @const {String} 4892 */ 4893Difference.TYPE_ADDED = "added"; 4894 4895/** 4896 * Indicates that the element was deleted in the transition from 'left' to 'right' structure 4897 * @const {String} 4898 */ 4899Difference.TYPE_DELETED = "deleted"; 4900 4901/** 4902 * Indicates that the element was changed in the transition from 'left' to 'right' structure 4903 * @const {String} 4904 */ 4905Difference.TYPE_CHANGED = "changed"; 4906 4907/** 4908 * Returns the path to the element where the difference is located. 4909 * 4910 * @return {Array} 4911 */ 4912Difference.prototype.get_path = function () { 4913 return this.path; 4914}; 4915 4916/** 4917 * Returns the type of difference. Should be one of the Difference.TYPE_* 4918 * constants. 4919 * 4920 * @return {String} 4921 */ 4922Difference.prototype.get_type = function () { 4923 return this.type; 4924}; 4925 4926/** 4927 * Returns the value of the element in the 'left' structure, or undefined if the 4928 * element is missing there. 4929 * 4930 * @return {*} 4931 */ 4932Difference.prototype.get_left_value = function () { 4933 return this.left_value; 4934}; 4935 4936/** 4937 * Returns the value of the element in the 'left' structure, or undefined if the 4938 * element is missing there. 4939 * 4940 * @return {*} 4941 */ 4942Difference.prototype.get_right_value = function () { 4943 return this.right_value; 4944}; 4945 4946 4947/***/ }), 4948
vendor: 1,003 bytes, lines 4949-4976
4949/***/ "./node_modules/js-struct-compare/src/compare.mjs": 4950/*!********************************************************!*\ 4951 !*** ./node_modules/js-struct-compare/src/compare.mjs ***! 4952 \********************************************************/ 4953/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 4954 4955/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4956/* harmony export */ "default": function() { return /* binding */ compare; } 4957/* harmony export */ }); 4958/* harmony import */ var _Comparator_mjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Comparator.mjs */ "./node_modules/js-struct-compare/src/Comparator.mjs"); 4959 4960 4961const comparator = new _Comparator_mjs__WEBPACK_IMPORTED_MODULE_0__["default"](); 4962 4963/** 4964 * Compares two structures and returns an array of their differences. 4965 * 4966 * @param {*} left 4967 * @param {*} right 4968 * @return {Difference[]} 4969 */ 4970function compare(left, right) { 4971 return comparator.compare(left, right); 4972}; 4973 4974 4975/***/ }), 4976
vendor: 1,212 bytes, lines 4977-4996
4977/***/ "./node_modules/js-struct-compare/src/index.mjs": 4978/*!******************************************************!*\ 4979 !*** ./node_modules/js-struct-compare/src/index.mjs ***! 4980 \******************************************************/ 4981/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 4982 4983/* harmony export */ __webpack_require__.d(__webpack_exports__, { 4984/* harmony export */ Difference: function() { return /* reexport safe */ _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__["default"]; }, 4985/* harmony export */ "default": function() { return /* reexport safe */ _compare_mjs__WEBPACK_IMPORTED_MODULE_2__["default"]; } 4986/* harmony export */ }); 4987/* harmony import */ var _Difference_mjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Difference.mjs */ "./node_modules/js-struct-compare/src/Difference.mjs"); 4988/* harmony import */ var _Comparator_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Comparator.mjs */ "./node_modules/js-struct-compare/src/Comparator.mjs"); 4989/* harmony import */ var _compare_mjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./compare.mjs */ "./node_modules/js-struct-compare/src/compare.mjs"); 4990 4991 4992 4993 4994 4995/***/ }), 4996
vendor: 575 bytes, lines 4997-5012
4997/***/ "./node_modules/js-struct-compare/src/utils.mjs": 4998/*!******************************************************!*\ 4999 !*** ./node_modules/js-struct-compare/src/utils.mjs ***! 5000 \******************************************************/ 5001/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) { 5002 5003/* harmony export */ __webpack_require__.d(__webpack_exports__, { 5004/* harmony export */ is_object: function() { return /* binding */ is_object; } 5005/* harmony export */ }); 5006function is_object(obj) { 5007 return obj === Object(obj); 5008} 5009 5010 5011/***/ }), 5012
vendor: 23,853 bytes, lines 5013-5785
5013/***/ "./node_modules/mustache/mustache.mjs": 5014/*!********************************************!*\ 5015 !*** ./node_modules/mustache/mustache.mjs ***! 5016 \********************************************/ 5017/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__) { 5018 5019/*! 5020 * mustache.js - Logic-less {{mustache}} templates with JavaScript 5021 * http://github.com/janl/mustache.js 5022 */ 5023 5024var objectToString = Object.prototype.toString; 5025var isArray = Array.isArray || function isArrayPolyfill (object) { 5026 return objectToString.call(object) === '[object Array]'; 5027}; 5028 5029function isFunction (object) { 5030 return typeof object === 'function'; 5031} 5032 5033/** 5034 * More correct typeof string handling array 5035 * which normally returns typeof 'object' 5036 */ 5037function typeStr (obj) { 5038 return isArray(obj) ? 'array' : typeof obj; 5039} 5040 5041function escapeRegExp (string) { 5042 return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'); 5043} 5044 5045/** 5046 * Null safe way of checking whether or not an object, 5047 * including its prototype, has a given property 5048 */ 5049function hasProperty (obj, propName) { 5050 return obj != null && typeof obj === 'object' && (propName in obj); 5051} 5052 5053/** 5054 * Safe way of detecting whether or not the given thing is a primitive and 5055 * whether it has the given property 5056 */ 5057function primitiveHasOwnProperty (primitive, propName) { 5058 return ( 5059 primitive != null 5060 && typeof primitive !== 'object' 5061 && primitive.hasOwnProperty 5062 && primitive.hasOwnProperty(propName) 5063 ); 5064} 5065 5066// Workaround for https://issues.apache.org/jira/browse/COUCHDB-577 5067// See https://github.com/janl/mustache.js/issues/189 5068var regExpTest = RegExp.prototype.test; 5069function testRegExp (re, string) { 5070 return regExpTest.call(re, string); 5071} 5072 5073var nonSpaceRe = /\S/; 5074function isWhitespace (string) { 5075 return !testRegExp(nonSpaceRe, string); 5076} 5077 5078var entityMap = { 5079 '&': '&', 5080 '<': '<', 5081 '>': '>', 5082 '"': '"', 5083 "'": ''', 5084 '/': '/', 5085 '`': '`', 5086 '=': '=' 5087}; 5088 5089function escapeHtml (string) { 5090 return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap (s) { 5091 return entityMap[s]; 5092 }); 5093} 5094 5095var whiteRe = /\s*/; 5096var spaceRe = /\s+/; 5097var equalsRe = /\s*=/; 5098var curlyRe = /\s*\}/; 5099var tagRe = /#|\^|\/|>|\{|&|=|!/; 5100 5101/** 5102 * Breaks up the given `template` string into a tree of tokens. If the `tags` 5103 * argument is given here it must be an array with two string values: the 5104 * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of 5105 * course, the default is to use mustaches (i.e. mustache.tags). 5106 * 5107 * A token is an array with at least 4 elements. The first element is the 5108 * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag 5109 * did not contain a symbol (i.e. {{myValue}}) this element is "name". For 5110 * all text that appears outside a symbol this element is "text". 5111 * 5112 * The second element of a token is its "value". For mustache tags this is 5113 * whatever else was inside the tag besides the opening symbol. For text tokens 5114 * this is the text itself. 5115 * 5116 * The third and fourth elements of the token are the start and end indices, 5117 * respectively, of the token in the original template. 5118 * 5119 * Tokens that are the root node of a subtree contain two more elements: 1) an 5120 * array of tokens in the subtree and 2) the index in the original template at 5121 * which the closing tag for that section begins. 5122 * 5123 * Tokens for partials also contain two more elements: 1) a string value of 5124 * indendation prior to that tag and 2) the index of that tag on that line - 5125 * eg a value of 2 indicates the partial is the third tag on this line. 5126 */ 5127function parseTemplate (template, tags) { 5128 if (!template) 5129 return []; 5130 var lineHasNonSpace = false; 5131 var sections = []; // Stack to hold section tokens 5132 var tokens = []; // Buffer to hold the tokens 5133 var spaces = []; // Indices of whitespace tokens on the current line 5134 var hasTag = false; // Is there a {{tag}} on the current line? 5135 var nonSpace = false; // Is there a non-space char on the current line? 5136 var indentation = ''; // Tracks indentation for tags that use it 5137 var tagIndex = 0; // Stores a count of number of tags encountered on a line 5138 5139 // Strips all whitespace tokens array for the current line 5140 // if there was a {{#tag}} on it and otherwise only space. 5141 function stripSpace () { 5142 if (hasTag && !nonSpace) { 5143 while (spaces.length) 5144 delete tokens[spaces.pop()]; 5145 } else { 5146 spaces = []; 5147 } 5148 5149 hasTag = false; 5150 nonSpace = false; 5151 } 5152 5153 var openingTagRe, closingTagRe, closingCurlyRe; 5154 function compileTags (tagsToCompile) { 5155 if (typeof tagsToCompile === 'string') 5156 tagsToCompile = tagsToCompile.split(spaceRe, 2); 5157 5158 if (!isArray(tagsToCompile) || tagsToCompile.length !== 2) 5159 throw new Error('Invalid tags: ' + tagsToCompile); 5160 5161 openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*'); 5162 closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1])); 5163 closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1])); 5164 } 5165 5166 compileTags(tags || mustache.tags); 5167 5168 var scanner = new Scanner(template); 5169 5170 var start, type, value, chr, token, openSection; 5171 while (!scanner.eos()) { 5172 start = scanner.pos; 5173 5174 // Match any text between tags. 5175 value = scanner.scanUntil(openingTagRe); 5176 5177 if (value) { 5178 for (var i = 0, valueLength = value.length; i < valueLength; ++i) { 5179 chr = value.charAt(i); 5180 5181 if (isWhitespace(chr)) { 5182 spaces.push(tokens.length); 5183 indentation += chr; 5184 } else { 5185 nonSpace = true; 5186 lineHasNonSpace = true; 5187 indentation += ' '; 5188 } 5189 5190 tokens.push([ 'text', chr, start, start + 1 ]); 5191 start += 1; 5192 5193 // Check for whitespace on the current line. 5194 if (chr === '\n') { 5195 stripSpace(); 5196 indentation = ''; 5197 tagIndex = 0; 5198 lineHasNonSpace = false; 5199 } 5200 } 5201 } 5202 5203 // Match the opening tag. 5204 if (!scanner.scan(openingTagRe)) 5205 break; 5206 5207 hasTag = true; 5208 5209 // Get the tag type. 5210 type = scanner.scan(tagRe) || 'name'; 5211 scanner.scan(whiteRe); 5212 5213 // Get the tag value. 5214 if (type === '=') { 5215 value = scanner.scanUntil(equalsRe); 5216 scanner.scan(equalsRe); 5217 scanner.scanUntil(closingTagRe); 5218 } else if (type === '{') { 5219 value = scanner.scanUntil(closingCurlyRe); 5220 scanner.scan(curlyRe); 5221 scanner.scanUntil(closingTagRe); 5222 type = '&'; 5223 } else { 5224 value = scanner.scanUntil(closingTagRe); 5225 } 5226 5227 // Match the closing tag. 5228 if (!scanner.scan(closingTagRe)) 5229 throw new Error('Unclosed tag at ' + scanner.pos); 5230 5231 if (type == '>') { 5232 token = [ type, value, start, scanner.pos, indentation, tagIndex, lineHasNonSpace ]; 5233 } else { 5234 token = [ type, value, start, scanner.pos ]; 5235 } 5236 tagIndex++; 5237 tokens.push(token); 5238 5239 if (type === '#' || type === '^') { 5240 sections.push(token); 5241 } else if (type === '/') { 5242 // Check section nesting. 5243 openSection = sections.pop(); 5244 5245 if (!openSection) 5246 throw new Error('Unopened section "' + value + '" at ' + start); 5247 5248 if (openSection[1] !== value) 5249 throw new Error('Unclosed section "' + openSection[1] + '" at ' + start); 5250 } else if (type === 'name' || type === '{' || type === '&') { 5251 nonSpace = true; 5252 } else if (type === '=') { 5253 // Set the tags for the next time around. 5254 compileTags(value); 5255 } 5256 } 5257 5258 stripSpace(); 5259 5260 // Make sure there are no open sections when we're done. 5261 openSection = sections.pop(); 5262 5263 if (openSection) 5264 throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos); 5265 5266 return nestTokens(squashTokens(tokens)); 5267} 5268 5269/** 5270 * Combines the values of consecutive text tokens in the given `tokens` array 5271 * to a single token. 5272 */ 5273function squashTokens (tokens) { 5274 var squashedTokens = []; 5275 5276 var token, lastToken; 5277 for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { 5278 token = tokens[i]; 5279 5280 if (token) { 5281 if (token[0] === 'text' && lastToken && lastToken[0] === 'text') { 5282 lastToken[1] += token[1]; 5283 lastToken[3] = token[3]; 5284 } else { 5285 squashedTokens.push(token); 5286 lastToken = token; 5287 } 5288 } 5289 } 5290 5291 return squashedTokens; 5292} 5293 5294/** 5295 * Forms the given array of `tokens` into a nested tree structure where 5296 * tokens that represent a section have two additional items: 1) an array of 5297 * all tokens that appear in that section and 2) the index in the original 5298 * template that represents the end of that section. 5299 */ 5300function nestTokens (tokens) { 5301 var nestedTokens = []; 5302 var collector = nestedTokens; 5303 var sections = []; 5304 5305 var token, section; 5306 for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { 5307 token = tokens[i]; 5308 5309 switch (token[0]) { 5310 case '#': 5311 case '^': 5312 collector.push(token); 5313 sections.push(token); 5314 collector = token[4] = []; 5315 break; 5316 case '/': 5317 section = sections.pop(); 5318 section[5] = token[2]; 5319 collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens; 5320 break; 5321 default: 5322 collector.push(token); 5323 } 5324 } 5325 5326 return nestedTokens; 5327} 5328 5329/** 5330 * A simple string scanner that is used by the template parser to find 5331 * tokens in template strings. 5332 */ 5333function Scanner (string) { 5334 this.string = string; 5335 this.tail = string; 5336 this.pos = 0; 5337} 5338 5339/** 5340 * Returns `true` if the tail is empty (end of string). 5341 */ 5342Scanner.prototype.eos = function eos () { 5343 return this.tail === ''; 5344}; 5345 5346/** 5347 * Tries to match the given regular expression at the current position. 5348 * Returns the matched text if it can match, the empty string otherwise. 5349 */ 5350Scanner.prototype.scan = function scan (re) { 5351 var match = this.tail.match(re); 5352 5353 if (!match || match.index !== 0) 5354 return ''; 5355 5356 var string = match[0]; 5357 5358 this.tail = this.tail.substring(string.length); 5359 this.pos += string.length; 5360 5361 return string; 5362}; 5363 5364/** 5365 * Skips all text until the given regular expression can be matched. Returns 5366 * the skipped string, which is the entire tail if no match can be made. 5367 */ 5368Scanner.prototype.scanUntil = function scanUntil (re) { 5369 var index = this.tail.search(re), match; 5370 5371 switch (index) { 5372 case -1: 5373 match = this.tail; 5374 this.tail = ''; 5375 break; 5376 case 0: 5377 match = ''; 5378 break; 5379 default: 5380 match = this.tail.substring(0, index); 5381 this.tail = this.tail.substring(index); 5382 } 5383 5384 this.pos += match.length; 5385 5386 return match; 5387}; 5388 5389/** 5390 * Represents a rendering context by wrapping a view object and 5391 * maintaining a reference to the parent context. 5392 */ 5393function Context (view, parentContext) { 5394 this.view = view; 5395 this.cache = { '.': this.view }; 5396 this.parent = parentContext; 5397} 5398 5399/** 5400 * Creates a new context using the given view with this context 5401 * as the parent. 5402 */ 5403Context.prototype.push = function push (view) { 5404 return new Context(view, this); 5405}; 5406 5407/** 5408 * Returns the value of the given name in this context, traversing 5409 * up the context hierarchy if the value is absent in this context's view. 5410 */ 5411Context.prototype.lookup = function lookup (name) { 5412 var cache = this.cache; 5413 5414 var value; 5415 if (cache.hasOwnProperty(name)) { 5416 value = cache[name]; 5417 } else { 5418 var context = this, intermediateValue, names, index, lookupHit = false; 5419 5420 while (context) { 5421 if (name.indexOf('.') > 0) { 5422 intermediateValue = context.view; 5423 names = name.split('.'); 5424 index = 0; 5425 5426 /** 5427 * Using the dot notion path in `name`, we descend through the 5428 * nested objects. 5429 * 5430 * To be certain that the lookup has been successful, we have to 5431 * check if the last object in the path actually has the property 5432 * we are looking for. We store the result in `lookupHit`. 5433 * 5434 * This is specially necessary for when the value has been set to 5435 * `undefined` and we want to avoid looking up parent contexts. 5436 * 5437 * In the case where dot notation is used, we consider the lookup 5438 * to be successful even if the last "object" in the path is 5439 * not actually an object but a primitive (e.g., a string, or an 5440 * integer), because it is sometimes useful to access a property 5441 * of an autoboxed primitive, such as the length of a string. 5442 **/ 5443 while (intermediateValue != null && index < names.length) { 5444 if (index === names.length - 1) 5445 lookupHit = ( 5446 hasProperty(intermediateValue, names[index]) 5447 || primitiveHasOwnProperty(intermediateValue, names[index]) 5448 ); 5449 5450 intermediateValue = intermediateValue[names[index++]]; 5451 } 5452 } else { 5453 intermediateValue = context.view[name]; 5454 5455 /** 5456 * Only checking against `hasProperty`, which always returns `false` if 5457 * `context.view` is not an object. Deliberately omitting the check 5458 * against `primitiveHasOwnProperty` if dot notation is not used. 5459 * 5460 * Consider this example: 5461 * ``` 5462 * Mustache.render("The length of a football field is {{#length}}{{length}}{{/length}}.", {length: "100 yards"}) 5463 * ``` 5464 * 5465 * If we were to check also against `primitiveHasOwnProperty`, as we do 5466 * in the dot notation case, then render call would return: 5467 * 5468 * "The length of a football field is 9." 5469 * 5470 * rather than the expected: 5471 * 5472 * "The length of a football field is 100 yards." 5473 **/ 5474 lookupHit = hasProperty(context.view, name); 5475 } 5476 5477 if (lookupHit) { 5478 value = intermediateValue; 5479 break; 5480 } 5481 5482 context = context.parent; 5483 } 5484 5485 cache[name] = value; 5486 } 5487 5488 if (isFunction(value)) 5489 value = value.call(this.view); 5490 5491 return value; 5492}; 5493 5494/** 5495 * A Writer knows how to take a stream of tokens and render them to a 5496 * string, given a context. It also maintains a cache of templates to 5497 * avoid the need to parse the same template twice. 5498 */ 5499function Writer () { 5500 this.templateCache = { 5501 _cache: {}, 5502 set: function set (key, value) { 5503 this._cache[key] = value; 5504 }, 5505 get: function get (key) { 5506 return this._cache[key]; 5507 }, 5508 clear: function clear () { 5509 this._cache = {}; 5510 } 5511 }; 5512} 5513 5514/** 5515 * Clears all cached templates in this writer. 5516 */ 5517Writer.prototype.clearCache = function clearCache () { 5518 if (typeof this.templateCache !== 'undefined') { 5519 this.templateCache.clear(); 5520 } 5521}; 5522 5523/** 5524 * Parses and caches the given `template` according to the given `tags` or 5525 * `mustache.tags` if `tags` is omitted, and returns the array of tokens 5526 * that is generated from the parse. 5527 */ 5528Writer.prototype.parse = function parse (template, tags) { 5529 var cache = this.templateCache; 5530 var cacheKey = template + ':' + (tags || mustache.tags).join(':'); 5531 var isCacheEnabled = typeof cache !== 'undefined'; 5532 var tokens = isCacheEnabled ? cache.get(cacheKey) : undefined; 5533 5534 if (tokens == undefined) { 5535 tokens = parseTemplate(template, tags); 5536 isCacheEnabled && cache.set(cacheKey, tokens); 5537 } 5538 return tokens; 5539}; 5540 5541/** 5542 * High-level method that is used to render the given `template` with 5543 * the given `view`. 5544 * 5545 * The optional `partials` argument may be an object that contains the 5546 * names and templates of partials that are used in the template. It may 5547 * also be a function that is used to load partial templates on the fly 5548 * that takes a single argument: the name of the partial. 5549 * 5550 * If the optional `config` argument is given here, then it should be an 5551 * object with a `tags` attribute or an `escape` attribute or both. 5552 * If an array is passed, then it will be interpreted the same way as 5553 * a `tags` attribute on a `config` object. 5554 * 5555 * The `tags` attribute of a `config` object must be an array with two 5556 * string values: the opening and closing tags used in the template (e.g. 5557 * [ "<%", "%>" ]). The default is to mustache.tags. 5558 * 5559 * The `escape` attribute of a `config` object must be a function which 5560 * accepts a string as input and outputs a safely escaped string. 5561 * If an `escape` function is not provided, then an HTML-safe string 5562 * escaping function is used as the default. 5563 */ 5564Writer.prototype.render = function render (template, view, partials, config) { 5565 var tags = this.getConfigTags(config); 5566 var tokens = this.parse(template, tags); 5567 var context = (view instanceof Context) ? view : new Context(view, undefined); 5568 return this.renderTokens(tokens, context, partials, template, config); 5569}; 5570 5571/** 5572 * Low-level method that renders the given array of `tokens` using 5573 * the given `context` and `partials`. 5574 * 5575 * Note: The `originalTemplate` is only ever used to extract the portion 5576 * of the original template that was contained in a higher-order section. 5577 * If the template doesn't use higher-order sections, this argument may 5578 * be omitted. 5579 */ 5580Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate, config) { 5581 var buffer = ''; 5582 5583 var token, symbol, value; 5584 for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { 5585 value = undefined; 5586 token = tokens[i]; 5587 symbol = token[0]; 5588 5589 if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate, config); 5590 else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate, config); 5591 else if (symbol === '>') value = this.renderPartial(token, context, partials, config); 5592 else if (symbol === '&') value = this.unescapedValue(token, context); 5593 else if (symbol === 'name') value = this.escapedValue(token, context, config); 5594 else if (symbol === 'text') value = this.rawValue(token); 5595 5596 if (value !== undefined) 5597 buffer += value; 5598 } 5599 5600 return buffer; 5601}; 5602 5603Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate, config) { 5604 var self = this; 5605 var buffer = ''; 5606 var value = context.lookup(token[1]); 5607 5608 // This function is used to render an arbitrary template 5609 // in the current context by higher-order sections. 5610 function subRender (template) { 5611 return self.render(template, context, partials, config); 5612 } 5613 5614 if (!value) return; 5615 5616 if (isArray(value)) { 5617 for (var j = 0, valueLength = value.length; j < valueLength; ++j) { 5618 buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate, config); 5619 } 5620 } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') { 5621 buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate, config); 5622 } else if (isFunction(value)) { 5623 if (typeof originalTemplate !== 'string') 5624 throw new Error('Cannot use higher-order sections without the original template'); 5625 5626 // Extract the portion of the original template that the section contains. 5627 value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender); 5628 5629 if (value != null) 5630 buffer += value; 5631 } else { 5632 buffer += this.renderTokens(token[4], context, partials, originalTemplate, config); 5633 } 5634 return buffer; 5635}; 5636 5637Writer.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate, config) { 5638 var value = context.lookup(token[1]); 5639 5640 // Use JavaScript's definition of falsy. Include empty arrays. 5641 // See https://github.com/janl/mustache.js/issues/186 5642 if (!value || (isArray(value) && value.length === 0)) 5643 return this.renderTokens(token[4], context, partials, originalTemplate, config); 5644}; 5645 5646Writer.prototype.indentPartial = function indentPartial (partial, indentation, lineHasNonSpace) { 5647 var filteredIndentation = indentation.replace(/[^ \t]/g, ''); 5648 var partialByNl = partial.split('\n'); 5649 for (var i = 0; i < partialByNl.length; i++) { 5650 if (partialByNl[i].length && (i > 0 || !lineHasNonSpace)) { 5651 partialByNl[i] = filteredIndentation + partialByNl[i]; 5652 } 5653 } 5654 return partialByNl.join('\n'); 5655}; 5656 5657Writer.prototype.renderPartial = function renderPartial (token, context, partials, config) { 5658 if (!partials) return; 5659 var tags = this.getConfigTags(config); 5660 5661 var value = isFunction(partials) ? partials(token[1]) : partials[token[1]]; 5662 if (value != null) { 5663 var lineHasNonSpace = token[6]; 5664 var tagIndex = token[5]; 5665 var indentation = token[4]; 5666 var indentedValue = value; 5667 if (tagIndex == 0 && indentation) { 5668 indentedValue = this.indentPartial(value, indentation, lineHasNonSpace); 5669 } 5670 var tokens = this.parse(indentedValue, tags); 5671 return this.renderTokens(tokens, context, partials, indentedValue, config); 5672 } 5673}; 5674 5675Writer.prototype.unescapedValue = function unescapedValue (token, context) { 5676 var value = context.lookup(token[1]); 5677 if (value != null) 5678 return value; 5679}; 5680 5681Writer.prototype.escapedValue = function escapedValue (token, context, config) { 5682 var escape = this.getConfigEscape(config) || mustache.escape; 5683 var value = context.lookup(token[1]); 5684 if (value != null) 5685 return (typeof value === 'number' && escape === mustache.escape) ? String(value) : escape(value); 5686}; 5687 5688Writer.prototype.rawValue = function rawValue (token) { 5689 return token[1]; 5690}; 5691 5692Writer.prototype.getConfigTags = function getConfigTags (config) { 5693 if (isArray(config)) { 5694 return config; 5695 } 5696 else if (config && typeof config === 'object') { 5697 return config.tags; 5698 } 5699 else { 5700 return undefined; 5701 } 5702}; 5703 5704Writer.prototype.getConfigEscape = function getConfigEscape (config) { 5705 if (config && typeof config === 'object' && !isArray(config)) { 5706 return config.escape; 5707 } 5708 else { 5709 return undefined; 5710 } 5711}; 5712 5713var mustache = { 5714 name: 'mustache.js', 5715 version: '4.2.0', 5716 tags: [ '{{', '}}' ], 5717 clearCache: undefined, 5718 escape: undefined, 5719 parse: undefined, 5720 render: undefined, 5721 Scanner: undefined, 5722 Context: undefined, 5723 Writer: undefined, 5724 /** 5725 * Allows a user to override the default caching strategy, by providing an 5726 * object with set, get and clear methods. This can also be used to disable 5727 * the cache by setting it to the literal `undefined`. 5728 */ 5729 set templateCache (cache) { 5730 defaultWriter.templateCache = cache; 5731 }, 5732 /** 5733 * Gets the default or overridden caching object from the default writer. 5734 */ 5735 get templateCache () { 5736 return defaultWriter.templateCache; 5737 } 5738}; 5739 5740// All high-level mustache.* functions use this writer. 5741var defaultWriter = new Writer(); 5742 5743/** 5744 * Clears all cached templates in the default writer. 5745 */ 5746mustache.clearCache = function clearCache () { 5747 return defaultWriter.clearCache(); 5748}; 5749 5750/** 5751 * Parses and caches the given template in the default writer and returns the 5752 * array of tokens it contains. Doing this ahead of time avoids the need to 5753 * parse templates on the fly as they are rendered. 5754 */ 5755mustache.parse = function parse (template, tags) { 5756 return defaultWriter.parse(template, tags); 5757}; 5758 5759/** 5760 * Renders the `template` with the given `view`, `partials`, and `config` 5761 * using the default writer. 5762 */ 5763mustache.render = function render (template, view, partials, config) { 5764 if (typeof template !== 'string') { 5765 throw new TypeError('Invalid template! Template should be a "string" ' + 5766 'but "' + typeStr(template) + '" was given as the first ' + 5767 'argument for mustache#render(template, view, partials)'); 5768 } 5769 5770 return defaultWriter.render(template, view, partials, config); 5771}; 5772 5773// Export the escaping function so that the user may override it. 5774// See https://github.com/janl/mustache.js/issues/244 5775mustache.escape = escapeHtml; 5776 5777// Export these mainly for testing, but also for advanced usage. 5778mustache.Scanner = Scanner; 5779mustache.Context = Context; 5780mustache.Writer = Writer; 5781 5782/* harmony default export */ __webpack_exports__["default"] = (mustache); 5783 5784 5785/***/ })
5785 5786 5787/******/ }); 5788/************************************************************************/ 5789/******/ // The module cache 5790/******/ var __webpack_module_cache__ = {}; 5791/******/ 5792/******/ // The require function 5793/******/ function __webpack_require__(moduleId) { 5794/******/ // Check if module is in cache 5795/******/ var cachedModule = __webpack_module_cache__[moduleId]; 5796/******/ if (cachedModule !== undefined) { 5797/******/ return cachedModule.exports; 5798/******/ } 5799/******/ // Create a new module (and put it into the cache) 5800/******/ var module = __webpack_module_cache__[moduleId] = { 5801/******/ // no module.id needed 5802/******/ // no module.loaded needed 5803/******/ exports: {} 5804/******/ }; 5805/******/ 5806/******/ // Execute the module function 5807/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 5808/******/ 5809/******/ // Return the exports of the module 5810/******/ return module.exports; 5811/******/ } 5812/******/ 5813/************************************************************************/ 5814/******/ /* webpack/runtime/define property getters */ 5815/******/ !function() { 5816/******/ // define getter functions for harmony exports 5817/******/ __webpack_require__.d = function(exports, definition) { 5818/******/ for(var key in definition) { 5819/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 5820/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 5821/******/ } 5822/******/ } 5823/******/ }; 5824/******/ }(); 5825/******/ 5826/******/ /* webpack/runtime/hasOwnProperty shorthand */ 5827/******/ !function() { 5828/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } 5829/******/ }(); 5830/******/ 5831/************************************************************************/ 5832var __webpack_exports__ = {}; 5833// This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk. 5834!function() { 5835/*!*************************************!*\ 5836 !*** ./js/design/paniercommande.js ***! 5837 \*************************************/ 5838/* harmony import */ var _components_SwiperEditorConfig__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../components/SwiperEditorConfig */ "./js/components/SwiperEditorConfig.js"); 5839/* harmony import */ var beekube_dom_Helper_Event__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! beekube-dom/Helper/Event */ "./node_modules/beekube-dom/Helper/Event.js"); 5840/* harmony import */ var mustache__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! mustache */ "./node_modules/mustache/mustache.mjs"); 5841 5842 5843 5844$(document).ready(function () { 5845 var sticky = null, 5846 stickyStep2 = null; 5847 setTimeout(function () { 5848 sticky = new Sticky('.block-info-payment__sticky'); 5849 stickyStep2 = new Sticky('.block-info-commande__sticky'); 5850 }); 5851 var $formOrder = $('[name="form-order"]'); 5852 if ($formOrder.length) { 5853 var dateBrowserInfo = new Date(); 5854 $formOrder.append($('<input />', { 5855 'type': 'hidden', 5856 'name': 'browser_info[color_depth]', 5857 'value': screen.colorDepth 5858 })).append($('<input />', { 5859 'type': 'hidden', 5860 'name': 'browser_info[screen_height]', 5861 'value': screen.height 5862 })).append($('<input />', { 5863 'type': 'hidden', 5864 'name': 'browser_info[screen_width]', 5865 'value': screen.width 5866 })).append($('<input />', { 5867 'type': 'hidden', 5868 'name': 'browser_info[timezone_offset_minutes_utc]', 5869 'value': dateBrowserInfo.getTimezoneOffset() 5870 })); 5871 } 5872 var cart_step_1 = $('.cart-step-1'), 5873 cart_step_2 = $('.cart-step-2'), 5874 cart_step_3 = $('.cart-step-3'), 5875 haveUniqShipping = false, 5876 $body = $('body'), 5877 options_price = 0.00, 5878 options_price_currency = 0.00, 5879 vitesse_scroll = 400, 5880 hasTrackedBeginCheckout = false; 5881 var sidebar = new sideMenu('.steps-panier', { 5882 sidebar: '.stepper-tabs', 5883 onClick: function (event, link) { 5884 $(link).closest('ul').children('li').removeClass('active').removeClass('step-done').find('a').removeClass('step-done'); 5885 $(link).closest('li').addClass('active').prevAll().addClass('step-done').find('a').addClass('step-done'); 5886 if (stickyStep2 !== null) { 5887 stickyStep2.destroy(); 5888 } 5889 if (sticky !== null) { 5890 sticky.destroy(); 5891 } 5892 stickyStep2 = new Sticky('.block-info-commande__sticky'); 5893 sticky = new Sticky('.block-info-payment__sticky'); 5894 if (typeof $($(link).attr('href')).offset() !== "undefined") { 5895 $('html,body').animate({ 5896 scrollTop: $($(link).attr('href')).offset().top 5897 }, vitesse_scroll); 5898 } 5899 } 5900 }); 5901 setTimeout(function () { 5902 loadCarriers(); 5903 }, 1); 5904 setTimeout(function () { 5905 if (typeof currencyIsoCode !== "undefined" && typeof amountProductDefaultCurrency !== "undefined") { 5906 refreshPaymentMode({ 5907 'currencyIsoCode': currencyIsoCode, 5908 'amountProductDefaultCurrency': amountProductDefaultCurrency 5909 }); 5910 } 5911 }, 1); 5912 let swiper = null; 5913 let giftDiscountHeightAlign = null; 5914 let giftDiscountResizeBound = false;
5915 5916 // Position à réappliquer à la prochaine création du slider, relevée avant que le 5917 // rechargement Ajax ne remplace le HTML du bloc. 5918 let pendingGiftDiscountIndex = 0; 5919 5920 // Dernier rendu serveur appliqué au bloc cadeaux. Un ajout de cadeau déclenche deux 5921 // rechargements du panier (celui du bouton, puis celui de loadCarriers), qui renvoient 5922 // le même HTML : sans cette comparaison, le slider est détruit et recréé une seconde 5923 // fois près d'une seconde après le clic, ce qui se voit à l'écran. 5924 let lastGiftDiscountHtml = null; 5925 5926 // Valeurs du dernier rendu du slider, pour ne le recréer que si la config change. 5927 // Volontairement hors de loadGiftDiscountSwiper() : cette fonction est rappelée à 5928 // chaque rechargement Ajax du bloc cadeaux, et des valeurs locales seraient 5929 // réinitialisées à null à chaque fois (donc destroy + new Swiper systématiques). 5930 let prevGiftDiscountParams = { 5931 slidesPerView: null, 5932 spaceBetween: null, 5933 autoplayRaw: null 5934 }; 5935 function resetGiftDiscountParams() { 5936 prevGiftDiscountParams = { 5937 slidesPerView: null, 5938 spaceBetween: null, 5939 autoplayRaw: null 5940 }; 5941 } 5942 5943 /** 5944 * Détruit l'instance Swiper des cadeaux et retourne la position courante. 5945 * à appeler AVANT de remplacer le HTML du bloc : après remplacement, l'instance 5946 * pointe sur un DOM détaché et ne peut plus être nettoyée. 5947 * @returns {number} index réel (hors slides clonées) au moment de la destruction 5948 */ 5949 function destroyGiftDiscountSwiper() { 5950 let realIndex = 0; 5951 if (swiper) { 5952 realIndex = swiper.realIndex || 0; 5953 swiper.destroy(true, true); 5954 swiper = null; 5955 resetGiftDiscountParams(); 5956 } 5957 return realIndex; 5958 } 5959 function giftDiscountParamsChanged(newParams) { 5960 return newParams.slidesPerView !== prevGiftDiscountParams.slidesPerView || newParams.spaceBetween !== prevGiftDiscountParams.spaceBetween || newParams.autoplayRaw !== prevGiftDiscountParams.autoplayRaw; 5961 } 5962 function createOrUpdateGiftDiscountSwiper() { 5963 let giftDiscountAdvanced = document.querySelector('.gift-discount__item__products'); 5964 if (giftDiscountAdvanced === null || document.querySelector('.gift-discount__swiper') === null) { 5965 return; 5966 } 5967 let params = (0,_components_SwiperEditorConfig__WEBPACK_IMPORTED_MODULE_0__.getSliderParams)(giftDiscountAdvanced); 5968 5969 // Vérifier si les paramètres ont changé avant de mettre à jour 5970 if (swiper && !giftDiscountParamsChanged(params)) { 5971 return; 5972 } 5973 5974 // Mémoriser les nouvelles valeurs 5975 prevGiftDiscountParams.slidesPerView = params.slidesPerView; 5976 prevGiftDiscountParams.spaceBetween = params.spaceBetween; 5977 prevGiftDiscountParams.autoplayRaw = params.autoplayRaw; 5978 5979 // Position conservée : celle de l'instance vivante (redimensionnement), sinon 5980 // celle relevée avant le remplacement du HTML. Elle est passée à la création via 5981 // initialSlide : un slideTo posé après l'init produit un déplacement visible. 5982 const realSlideCount = giftDiscountAdvanced.querySelectorAll('.gift-discount__swiper .swiper-slide:not(.swiper-slide-duplicate)').length; 5983 const wantedIndex = swiper ? swiper.realIndex || 0 : pendingGiftDiscountIndex; 5984 let swiperProductSliderConfiguration = { 5985 initialSlide: realSlideCount > 0 ? Math.min(Math.max(wantedIndex, 0), realSlideCount - 1) : 0, 5986 slidesPerView: params.slidesPerView, 5987 spaceBetween: params.spaceBetween, 5988 wrapperClass: 'gift-discount__swiper-wrapper', 5989 loop: true, 5990 preloadImages: false, 5991 lazy: true, 5992 // Le module A11y de Swiper deplace le slider des qu'un element recoit le 5993 // focus dans une slide differente de la slide active : cliquer sur le bouton 5994 // d'un cadeau visible mais non actif provoquait un slideTo parasite. Avec 5995 // watchSlidesProgress, Swiper connait visibleSlides et n'agit plus que si la 5996 // slide focalisee est reellement hors champ. 5997 watchSlidesProgress: true 5998 }; 5999 if (giftDiscountAdvanced.querySelector('.swiper-pagination') !== null) { 6000 swiperProductSliderConfiguration['pagination'] = { 6001 el: '.swiper-pagination', 6002 type: 'bullets', 6003 clickable: true 6004 }; 6005 } 6006 if (giftDiscountAdvanced.querySelector('.swiper-button-next') && giftDiscountAdvanced.querySelector('.swiper-button-prev')) { 6007 swiperProductSliderConfiguration['navigation'] = { 6008 nextEl: '.swiper-button-next', 6009 prevEl: '.swiper-button-prev' 6010 }; 6011 } 6012 6013 // Si un Swiper existe déjà , le détruire avant d'en créer un nouveau 6014 if (swiper) { 6015 swiper.destroy(true, true); 6016 swiper = null; 6017 } 6018 6019 // Créer une nouvelle instance avec les paramètres mis à jour 6020 swiper = new Swiper('.gift-discount__swiper', swiperProductSliderConfiguration); 6021 } 6022 6023 // Ãcouter les changements de taille de fenêtre avec debounce 6024 const updateGiftDiscountSwiperOnResize = CmonSite.debounce(function () { 6025 createOrUpdateGiftDiscountSwiper(); 6026 }, 250); 6027 6028 /** 6029 * (Ré)initialise le bloc cadeaux : slider, alignement des hauteurs, écouteurs. 6030 * @param {number} [restoreIndex] position à restaurer, retournée par destroyGiftDiscountSwiper() 6031 */ 6032 function loadGiftDiscountSwiper(restoreIndex) { 6033 const giftDiscountAdvanced = document.querySelector('.gift-discount__item__products'); 6034 const giftDiscountAdvancedSwiper = document.querySelector('.gift-discount__swiper'); 6035 if (giftDiscountAdvanced === null || giftDiscountAdvancedSwiper === null) { 6036 // Le nouveau rendu n'a plus de slider (moins de cadeaux qu'avant) : 6037 // ne pas garder une instance qui pointe sur un DOM disparu. 6038 destroyGiftDiscountSwiper(); 6039 if (giftDiscountAdvanced !== null && giftDiscountHeightAlign !== null) { 6040 document.body.dispatchEvent(new Event('heightAlign.refresh')); 6041 } 6042 return; 6043 } 6044 pendingGiftDiscountIndex = typeof restoreIndex === 'number' && restoreIndex > 0 ? restoreIndex : 0; 6045 createOrUpdateGiftDiscountSwiper(); 6046 pendingGiftDiscountIndex = 0; 6047 6048 // Ãcouteur global : posé une seule fois, sinon un simple redimensionnement 6049 // déclencherait autant de réinitialisations que de rechargements du bloc. 6050 if (!giftDiscountResizeBound) { 6051 window.addEventListener('resize', updateGiftDiscountSwiperOnResize); 6052 giftDiscountResizeBound = true; 6053 } 6054 6055 // Porté par l'élément lui-même, remplacé à chaque rechargement : pas d'accumulation. 6056 (0,beekube_dom_Helper_Event__WEBPACK_IMPORTED_MODULE_1__.EventOn)(Object.assign({}, beekube_dom_Helper_Event__WEBPACK_IMPORTED_MODULE_1__.defaultEventOptions, { 6057 'element': giftDiscountAdvanced, 6058 'type': 'changeCSS', 6059 'listener': updateGiftDiscountSwiperOnResize 6060 })); 6061 6062 // heightAlign relit ses éléments à chaque rafraîchissement : une instance suffit 6063 // pour toute la page, même après remplacement du HTML. 6064 if (giftDiscountHeightAlign === null) { 6065 giftDiscountHeightAlign = new heightAlign('.gift-discount__item__product', { 6066 "elementChild": [".gift-discount__item__product__title", ".gift-discount__item__product__button"], 6067 "nombreBlocsLigne": 1000 6068 }); 6069 } else { 6070 document.body.dispatchEvent(new Event('heightAlign.refresh')); 6071 } 6072 } 6073 loadGiftDiscountSwiper(); 6074 $('[name="form-order"]').validationEngine(); 6075 if ($('.step-finish').is('.active')) { 6076 $('.step-finish').siblings('span').addClass('active'); 6077 } 6078 $body.on('touchstart click', 'a.step-finish', function () { 6079 loadCarriers(); 6080 }).on('click', '[name="product_gift_discount_add"]', function () { 6081 var $self = $(this),
6082 product = $self.val(), 6083 id_discount = $self.attr('data-id'), 6084 $discountItem = $self.closest('.gift-discount__item'); 6085 $discountItem.waitMe(); 6086 $.ajax({ 6087 type: "POST", 6088 url: "/ajax/minisite/panier/add_discount_advanced_gift.php", 6089 data: { 6090 'id_discount': id_discount, 6091 'product': product 6092 }, 6093 dataType: 'json', 6094 success: function (response) { 6095 if (response.hasOwnProperty('reload')) { 6096 location.reload(); 6097 } 6098 $discountItem.waitMe('hide'); 6099 flag = false; 6100 setTimeout(function () { 6101 if (response.reload_cart) { 6102 reloadResumeAndPaymentCart(response.resume_cart, response.payment_cart, response.gift_discount_advanced); 6103 } 6104 reloadBlockReductionCode(); 6105 loadCarriers(); 6106 }, 0); 6107 } 6108 }); 6109 }).on('click', '.show-modal-information-oney', function () { 6110 var $self = $(this), 6111 $modalInformationOney = $('#modal-information-oney'), 6112 country = $('[name=pays]').val(), 6113 modalType = $self.attr('data-type'); 6114 if ($modalInformationOney.length === 0) { 6115 /* Créer la modal */ 6116 $modalInformationOney = $('<div />', { 6117 'class': 'modal fade modal-information-oney', 6118 'id': 'modal-information-oney', 6119 'tabindex': '-1', 6120 'role': 'dialog' 6121 }).append($('<div />', { 6122 'class': 'modal-dialog modal-lg', 6123 'role': 'document' 6124 }).append($('<div />', { 6125 'class': 'modal-content' 6126 }).append($('<div />', { 6127 'class': 'modal-header' 6128 }).append($('<button />', { 6129 'type': 'button', 6130 'class': 'close', 6131 'data-dismiss': 'modal', 6132 'aria-label': 'Close' 6133 }).append($('<span />', { 6134 'aria-hidden': 'true', 6135 'html': '×' 6136 }))).append($('<span />', { 6137 'class': 'modal-information-oney__title', 6138 'html': _lang.get('Simulation pour un paiement via Oney') 6139 }))).append($('<div />', { 6140 'class': 'modal-body' 6141 })))); 6142 $('#main-conteneur').append($modalInformationOney); 6143 } 6144 if (modalType === undefined) { 6145 modalType = null; 6146 $modalInformationOney.find('.modal-dialog').addClass('modal-lg'); 6147 } else { 6148 $modalInformationOney.find('.modal-dialog').removeClass('modal-lg'); 6149 } 6150 var amountCarrier = -1, 6151 amountCarrierInsurance = 0, 6152 $containerCarriers = $('.content-carriers__item'); 6153 if ($containerCarriers.length) { 6154 var amountCarrierTmp = 0, 6155 haveCarrierChecked = false; 6156 $containerCarriers.each(function (index, itemCarrier) { 6157 var $itemCarrier = $(itemCarrier), 6158 $radioCarrierChecked = $itemCarrier.find('.radio_carrier:checked'), 6159 $insuranceItem; 6160 if ($radioCarrierChecked.length) { 6161 haveCarrierChecked = true; 6162 amountCarrierTmp += parseFloat($radioCarrierChecked.attr('data-price')); 6163 $insuranceItem = $('[name=insurance_' + $radioCarrierChecked.attr('data-product-group') + '_' + $radioCarrierChecked.val() + ']:checked'); 6164 if ($insuranceItem.length) { 6165 amountCarrierInsurance += parseFloat($insuranceItem.attr('data-price')); 6166 } 6167 } 6168 }); 6169 if (haveCarrierChecked) { 6170 amountCarrier = amountCarrierTmp; 6171 } 6172 } 6173 $modalInformationOney.modal(); 6174 var $modalBody = $modalInformationOney.find('.modal-body'); 6175 $modalBody.waitMe(); 6176 $.ajax({ 6177 type: "POST", 6178 url: "/ajax/minisite/panier/payplug_oney_simulation.php", 6179 data: { 6180 'country': country, 6181 'modalType': modalType, 6182 'amountCarrier': amountCarrier, 6183 'amountCarrierInsurance': amountCarrierInsurance, 6184 'options_price': options_price 6185 }, 6186 dataType: 'json', 6187 success: function (json) { 6188 if (json.hasOwnProperty('reload')) { 6189 location.reload(); 6190 } 6191 $modalBody.waitMe('hide'); 6192 $modalBody.html(json.html); 6193 } 6194 }); 6195 }).on('keyup', '[name="nom_societe"]', function () { 6196 var $self = $(this), 6197 $block = $('.information-society'); 6198 if ($self.val() === '') { 6199 $block.hide(); 6200 } else { 6201 $block.show(); 6202 } 6203 }).on('change', '.block_address .change_address', function () { 6204 var self = $(this), 6205 $block = self.closest('.block_address'), 6206 $container = $('.block-info-commande'), 6207 $item = self.find('option[value="' + self.val() + '"]'); 6208 if ($block.hasClass('billing_address')) { 6209 $block.find('[name="nom"]').val($item.attr('data-nom')); 6210 $block.find('[name="prenom"]').val($item.attr('data-prenom')); 6211 $block.find('[name="tel"]').val($item.attr('data-tel')); 6212 $block.find('[name="adresse"]').val($item.attr('data-adresse')); 6213 $block.find('[name="cp"]').val($item.attr('data-code-postal')); 6214 $block.find('[name="ville"]').val($item.attr('data-ville')); 6215 $block.find('[name="pays"]').val($item.attr('data-pays')); 6216 $block.find('[name="commentaires"]').val($item.attr('data-commentaires')); 6217 } else { 6218 $block.find('[name="nom_livraison"]').val($item.attr('data-nom')); 6219 $block.find('[name="prenom_livraison"]').val($item.attr('data-prenom')); 6220 $block.find('[name="societe_livraison"]').val($item.attr('data-societe')); 6221 $block.find('[name="tel_livraison"]').val($item.attr('data-tel')); 6222 $block.find('[name="adresse_livraison"]').val($item.attr('data-adresse')); 6223 $block.find('[name="cp_livraison"]').val($item.attr('data-code-postal')); 6224 $block.find('[name="ville_livraison"]').val($item.attr('data-ville')); 6225 $block.find('[name="pays_livraison"]').val($item.attr('data-pays')); 6226 $block.find('[name="commentaires_livraison"]').val($item.attr('data-commentaires')); 6227 } 6228 loadCarriers(); 6229 }).on('change', '.block_address [name="pays"], .block_address [name="pays_livraison"]', function () { 6230 loadCarriers(); 6231 }); 6232 6233 //Fonction pour afficher / cacher les réduction 6234 $body.on('click', '.block-reduc-deploy', function () { 6235 var self = $(this), 6236 $blockPromo = self.nextAll('ul'); 6237 $blockPromo.stop().slideToggle(200); 6238 }); 6239 $body.on('touchstart click', 'a.next-step', function () { 6240 var self = $(this), 6241 href = $(self).attr('href'); 6242 if ($(self).hasClass('step-1')) { 6243 changeSideBar(href); 6244 if (!hasTrackedBeginCheckout && trackCartStepEvent('begin_checkout')) { 6245 hasTrackedBeginCheckout = true; 6246 } 6247 } 6248 if ($(self).hasClass('step-2')) { 6249 if (validFormAddress()) { 6250 var $addressRgpd = $('#address_rgpd_checkbox'); 6251 6252 /* Tester la validation de l'adresse RGPD */ 6253 if ($addressRgpd.length && !$addressRgpd.is(':checked')) {
6254 $addressRgpd.validationEngine('validate'); 6255 return false; 6256 } 6257 var $blockInvoiceAddress = $('#infoscommande .billing_address'), 6258 $blockDeliveryAddress = $('#infoscommande .delivery_address'); 6259 /* Enlever l'espace sur un code postal fr (facture)*/ 6260 if ($blockInvoiceAddress.find('[name="pays"]').val() === 'France') { 6261 var $zipCodeInvoice = $blockInvoiceAddress.find('[name="cp"]'), 6262 zipCodeInvoice = $zipCodeInvoice.val(); 6263 zipCodeInvoice = zipCodeInvoice.replace(/\s/g, ''); 6264 $zipCodeInvoice.val(zipCodeInvoice); 6265 } 6266 /* Enlever l'espace sur un code postal fr (livraison)*/ 6267 if ($blockDeliveryAddress.find('[name="pays_livraison"]').val() === 'France') { 6268 var $zipCodeDelivery = $blockDeliveryAddress.find('[name="cp_livraison"]'), 6269 zipCodeDelivery = $zipCodeDelivery.val(); 6270 zipCodeDelivery = zipCodeDelivery.replace(/\s/g, ''); 6271 $zipCodeDelivery.val(zipCodeDelivery); 6272 } 6273 setTimeout(function () { 6274 saveAddr(function () { 6275 loadCarriers(); 6276 changeSideBar(href); 6277 }); 6278 }, 1); 6279 } 6280 } 6281 return false; 6282 }); 6283 $body.on('change', '[name=address_billing_same_delivery]', function () { 6284 var value = $(this).val(); 6285 if (value === '1') { 6286 $('.block_delivery_address').hide(); 6287 } else { 6288 $('.block_delivery_address').show(); 6289 } 6290 }); 6291 $('[name=form-order] input').on('keyup keypress', function (e) { 6292 var code = e.keyCode || e.which, 6293 self = $(this); 6294 if (code == 13) { 6295 switch (true) { 6296 case self.closest('.inscription').length > 0: 6297 $('[name=submit-inscription]').trigger('click'); 6298 break; 6299 case self.closest('.connexion').length > 0: 6300 $('[name=submit-connexion]').trigger('click'); 6301 break; 6302 } 6303 e.preventDefault(); 6304 return false; 6305 } 6306 }); 6307 function changePrice(radio, calculatePriceParams) { 6308 var $self = $(radio), 6309 price = $self.attr('data-price'), 6310 price_format = $self.attr('data-price-format'), 6311 value = $self.val(), 6312 $item = $self.closest('.content-carriers__item'); 6313 $item.find('.line_carrier label').removeClass('selected').parent().removeClass('selected'); 6314 $self.closest('label').addClass('selected').closest('li').addClass('selected').closest('ul').addClass('group-selected'); 6315 $self.closest('li').addClass('selected').closest('ul').addClass('group-selected'); 6316 // 6317 // if (price === '0') { 6318 // cart_step_1.find('.content-payment-product-global').hide(); 6319 // cart_step_1.find('.content-payment-carrier-ttc').hide(); 6320 // cart_step_1.find('.content-payment-carrier-ttc').hide(); 6321 // cart_step_1.find('.total-global').html(cart_step_1.find('.total-product-global').html()); 6322 // 6323 // 6324 // cart_step_3.find('.content-payment-product-global').hide(); 6325 // cart_step_3.find('.content-payment-carrier-ttc').hide(); 6326 // cart_step_3.find('.content-payment-carrier-ttc').hide(); 6327 // cart_step_3.find('.total-global').html(cart_step_3.find('.total-product-global').html()); 6328 // 6329 // 6330 // } else { 6331 // cart_step_3.find('.total-carrier-ttc').html(price_format); 6332 // 6333 // if (haveUniqShipping) { 6334 // cart_step_1.find('.total-carrier-ttc').html(price_format); 6335 // } 6336 // 6337 // 6338 // var total_product_global = cart_step_3.find('.total-product-global').html(); 6339 // 6340 // float_price_carrier = parseFloat(price.replace(",", ".")); 6341 // float_total_product_global = parseFloat(total_product_global.replace(",", ".")); 6342 // 6343 // global_price = float_price_carrier + float_total_product_global; 6344 // 6345 // global_price = Math.round(global_price * 100) / 100; 6346 // 6347 // cart_step_3.find('.total-global').html(global_price.toFixed(2)); 6348 // cart_step_3.find('.content-payment-product-global').show(); 6349 // cart_step_3.find('.content-payment-carrier-ttc').show(); 6350 // 6351 // if (haveUniqShipping) { 6352 // cart_step_1.find('.total-global').html(global_price.toFixed(2)); 6353 // cart_step_1.find('.content-payment-product-global').show(); 6354 // cart_step_1.find('.content-payment-carrier-ttc').show(); 6355 // } 6356 // } 6357 6358 $('[name="relay_id_' + $self.attr('data-product-group') + '"]').remove(); 6359 $item.find('.change_relay').parent().remove(); 6360 $item.find('.change_colissimo_relay').parent().remove(); 6361 $item.find('.change_chronopost_relay').parent().remove(); 6362 $item.find('.change_mondialrelay_relay').parent().remove(); 6363 $item.find('.change_disponibility').parent().remove(); 6364 $item.find('.information-relay').hide().html(); 6365 if (typeof calculatePriceParams === 'undefined') { 6366 calculatePriceParams = {}; 6367 } 6368 calculatePrice(calculatePriceParams); 6369 loadFancyboxRelay($self); 6370 } 6371 $body.on('change', '.radio_carrier', function (event, params) { 6372 var $self = $(this), 6373 name = $self.attr('name'), 6374 $item = $self.closest('.content-carriers__item'), 6375 productGroup = $self.attr('data-product-group'), 6376 $insurance = $item.find('[name=insurance_' + productGroup + '_' + $('[name="' + name + '"]:checked').val() + ']'); 6377 $item.find('.insurance-block').each(function (index, value) { 6378 $(value).find('.checkbox_insurance').prop('checked', false); 6379 }); 6380 $item.find('.insurance-block').hide(); 6381 if ($insurance.length > 0) { 6382 $insurance.parents('.insurance-block').show(); 6383 } 6384 if (event && event.originalEvent) { 6385 var $lineCarrier = $self.closest('.line_carrier'), 6386 shippingTier = $.trim($lineCarrier.find('.carrier_name span').first().text()) || $self.val(); 6387 trackCartStepEvent('add_shipping_info', { 6388 shipping_tier: shippingTier 6389 }); 6390 } 6391 if (typeof params === 'undefined') { 6392 params = {}; 6393 } 6394 changePrice(this, params.hasOwnProperty('calculatePriceParams') ? params.calculatePriceParams : {}); 6395 }); 6396 $body.on('click', '.change_relay', function () { 6397 var self; 6398 changePrice($(this).parents('.line_carrier').find('.radio_carrier')); 6399 return false;
6400 }); 6401 $body.on('click', '.change_colissimo_relay', function () { 6402 var self; 6403 changePrice($(this).parents('.line_carrier').find('.radio_carrier')); 6404 return false; 6405 }); 6406 $body.on('click', '.change_chronopost_relay', function () { 6407 var self; 6408 changePrice($(this).parents('.line_carrier').find('.radio_carrier')); 6409 return false; 6410 }); 6411 $body.on('click', '.change_disponibility', function () { 6412 var self; 6413 changePrice($(this).parents('.line_carrier').find('.radio_carrier')); 6414 return false; 6415 }); 6416 $body.on('click', '.change_mondialrelay_relay', function () { 6417 var self; 6418 changePrice($(this).parents('.line_carrier').find('.radio_carrier')); 6419 return false; 6420 }); 6421 function loadFancyboxRelay($inputCarrier) { 6422 /* Verifier si on a des points relay pour faire selectionner le point au client */ 6423 var $carrier = $inputCarrier, 6424 relay = $carrier.attr('data-relay'), 6425 colissimo = $carrier.attr('data-colissimo'), 6426 mondialrelay = $carrier.attr('data-mondialrelay'), 6427 chronopostrelay = $carrier.attr('data-chronopostrelay'), 6428 choiceDisponibility = $carrier.attr('data-choice-disponibility'); 6429 var lastname_delivery = $('[name=nom]').val(), 6430 firstname_delivery = $('[name=prenom]').val(), 6431 address_delivery = $('[name=adresse]').val(), 6432 zip_code_delivery = $('[name=cp]').val(), 6433 city_delivery = $('[name=ville]').val(), 6434 country_delivery = $('[name=pays]').val(), 6435 iso_code_country_delivery = $('[name=pays] option[value="' + country_delivery + '"]').attr('data-iso-code'); 6436 if ($('[name=address_billing_same_delivery]:checked').val() === '0') { 6437 lastname_delivery = $('[name=nom_livraison]').val(); 6438 firstname_delivery = $('[name=prenom_livraison]').val(); 6439 address_delivery = $('[name=adresse_livraison]').val(); 6440 zip_code_delivery = $('[name=cp_livraison]').val(); 6441 city_delivery = $('[name=ville_livraison]').val(); 6442 country_delivery = $('[name=pays_livraison]').val(), iso_code_country_delivery = $('[name=pays_livraison] option[value="' + country_delivery + '"]').attr('data-iso-code'); 6443 } 6444 switch (true) { 6445 case typeof relay !== typeof undefined && relay !== false: 6446 $.fancybox.open({ 6447 href: '/page/choice_relay.php?relay=' + relay + '&address=' + address_delivery + '&zip_code=' + zip_code_delivery + '&city=' + city_delivery + '&country=' + country_delivery + '&t=' + new Date().getTime(), 6448 type: 'iframe', 6449 padding: 5, 6450 beforeClose: function () { 6451 var contentIframe = $("iframe.fancybox-iframe").contents(), 6452 radio_relay = $(contentIframe).find('[name=relay]:checked'), 6453 addressRelay = $(radio_relay).parents('.line_relay').find('.information-relay-address').html(); 6454 $('[name=form-order]').append($('<input />').attr({ 6455 'name': 'relay_id_' + $inputCarrier.attr('data-product-group'), 6456 'type': 'hidden', 6457 'value': $(radio_relay).val() 6458 })); 6459 $inputCarrier.parents('.line_carrier').find('.information-relay').show().html(addressRelay); 6460 $($('<span />', { 6461 'style': 'display: block;' 6462 }).html($('<a />').attr({ 6463 'href': '#', 6464 'class': 'change_relay' 6465 }).html('Changer de relais'))).insertAfter($inputCarrier.parents('.line_carrier').find('.carrier_name > span')); 6466 } 6467 }); 6468 break; 6469 case typeof colissimo !== typeof undefined && colissimo === '1': 6470 $.fancybox.open({ 6471 href: '/page/choice_relay_colissimo.php?value=' + $carrier.val() + 'address=' + address_delivery + '&zip_code=' + zip_code_delivery + '&city=' + city_delivery + '&country=' + country_delivery + '&t=' + new Date().getTime(), 6472 type: 'iframe', 6473 padding: 5, 6474 beforeClose: function () { 6475 var contentIframe = $("iframe.fancybox-iframe").contents(), 6476 radio_relay = $(contentIframe).find('[name=relay]:checked'), 6477 addressRelay = $(radio_relay).closest('.block-colissimo__list__item__label').find('.block-colissimo__list__item__label__address').html(); 6478 $('[name=form-order] [name="colissimo_id_' + $inputCarrier.attr('data-product-group') + '"]').remove(); 6479 $('[name=form-order]').append($('<input />').attr({ 6480 'name': 'colissimo_id_' + $inputCarrier.attr('data-product-group'), 6481 'type': 'hidden', 6482 'value': $(radio_relay).val() 6483 })); 6484 $inputCarrier.closest('.line_carrier').find('.information-relay').show().html(addressRelay); 6485 if ($inputCarrier.parents('.line_carrier').find('.change_colissimo_relay').length) { 6486 $inputCarrier.parents('.line_carrier').find('.change_colissimo_relay').parent().remove(); 6487 } 6488 $($('<span />', { 6489 'style': 'display: block;' 6490 }).html($('<a />').attr({ 6491 'href': '#', 6492 'class': 'change_colissimo_relay' 6493 }).html('Changer de relais'))).insertAfter($inputCarrier.parents('.line_carrier').find('.carrier_name > span')); 6494 } 6495 }); 6496 break; 6497 case typeof chronopostrelay !== typeof undefined && chronopostrelay === '1': 6498 $.fancybox.open({ 6499 href: '/page/choice_relay_chronopost.php?value=' + $carrier.val() + 'address=' + address_delivery + '&zip_code=' + zip_code_delivery + '&city=' + city_delivery + '&country=' + country_delivery + '&t=' + new Date().getTime(), 6500 type: 'iframe', 6501 padding: 5, 6502 beforeClose: function () { 6503 var contentIframe = $("iframe.fancybox-iframe").contents(), 6504 radio_relay = $(contentIframe).find('[name=relay]:checked'), 6505 addressRelay = $(radio_relay).closest('.block-chronopost__list__item__label').find('.block-chronopost__list__item__label__address').html(); 6506 $('[name=form-order] [name="chronopost_id_' + $inputCarrier.attr('data-product-group') + '"]').remove(); 6507 $('[name=form-order]').append($('<input />').attr({ 6508 'name': 'chronopost_id_' + $inputCarrier.attr('data-product-group'), 6509 'type': 'hidden', 6510 'value': $(radio_relay).val() 6511 })); 6512 $inputCarrier.closest('.line_carrier').find('.information-relay').show().html(addressRelay); 6513 if ($inputCarrier.parents('.line_carrier').find('.change_chronopost_relay').length) { 6514 $inputCarrier.parents('.line_carrier').find('.change_chronopost_relay').parent().remove(); 6515 } 6516 $($('<span />', { 6517 'style': 'display: block;' 6518 }).html($('<a />').attr({ 6519 'href': '#', 6520 'class': 'change_chronopost_relay' 6521 }).html('Changer de relais'))).insertAfter($inputCarrier.parents('.line_carrier').find('.carrier_name > span')); 6522 } 6523 }); 6524 break; 6525 case typeof mondialrelay !== typeof undefined && mondialrelay === '1': 6526 $.fancybox.open({ 6527 href: '/page/choice_relay_mondialrelay.php?value=' + $carrier.val() + '&address=' + address_delivery + '&zip_code=' + zip_code_delivery + '&city=' + city_delivery + '&country=' + country_delivery + '&t=' + new Date().getTime(), 6528 type: 'iframe', 6529 padding: 5, 6530 beforeClose: function () { 6531 var contentIframe = $("iframe.fancybox-iframe").contents(), 6532 radio_relay = $(contentIframe).find('[name=relay]:checked'), 6533 addressRelay = $(radio_relay).closest('.block-mondialrelay__list__item__label').find('.block-mondialrelay__list__item__label__address').html(); 6534 $('[name=form-order] [name="mondialrelay_id_' + $inputCarrier.attr('data-product-group') + '"]').remove(); 6535 $('[name=form-order]').append($('<input />').attr({ 6536 'name': 'mondialrelay_id_' + $inputCarrier.attr('data-product-group'), 6537 'type': 'hidden', 6538 'value': $(radio_relay).val() 6539 })); 6540 $inputCarrier.closest('.line_carrier').find('.information-relay').show().html(addressRelay); 6541 if ($inputCarrier.parents('.line_carrier').find('.change_mondialrelay_relay').length) { 6542 $inputCarrier.parents('.line_carrier').find('.change_mondialrelay_relay').parent().remove(); 6543 } 6544 $($('<span />', { 6545 'style': 'display: block;' 6546 }).html($('<a />').attr({ 6547 'href': '#', 6548 'class': 'change_mondialrelay_relay' 6549 }).html('Changer de relais'))).insertAfter($inputCarrier.parents('.line_carrier').find('.carrier_name > span')); 6550 } 6551 }); 6552 break; 6553 case typeof choiceDisponibility !== typeof undefined && choiceDisponibility === '1': 6554 $.fancybox.open({ 6555 href: '/page/choice_disponibility.php?value=' + $carrier.val() + '&t=' + new Date().getTime(), 6556 type: 'iframe', 6557 padding: 5, 6558 beforeClose: function () { 6559 var contentIframe = $("iframe.fancybox-iframe").contents(), 6560 $radio_disponibility = $(contentIframe).find('[name=disponibility]:checked'), 6561 information_disponibility = $radio_disponibility.attr('data-label-hour'); 6562 $('[name=form-order] [name="disponibility_' + $inputCarrier.attr('data-product-group') + '"]').remove(); 6563 $('[name=form-order]').append($('<input />').attr({ 6564 'name': 'disponibility_' + $inputCarrier.attr('data-product-group'), 6565 'type': 'hidden', 6566 'value': $radio_disponibility.val() 6567 })); 6568 $inputCarrier.closest('.line_carrier').find('.information-relay').show().html(information_disponibility); 6569 if ($inputCarrier.parents('.line_carrier').find('.change_disponibility').length) { 6570 $inputCarrier.parents('.line_carrier').find('.change_disponibility').parent().remove(); 6571 } 6572 $($('<span />', { 6573 'style': 'display: block;' 6574 }).html($('<a />').attr({ 6575 'href': '#', 6576 'class': 'change_disponibility' 6577 }).html('Changer de créneau'))).insertAfter($inputCarrier.parents('.line_carrier').find('.carrier_name > span')); 6578 } 6579 }); 6580 break; 6581 } 6582 } 6583 let loadCarriers = debounce(function () { 6584 if ($('#finish').length == 0) { 6585 return false;
6586 } 6587 cart_step_3.find('.content-payment-carrier-ttc').hide(); 6588 cart_step_3.find('.content-payment-carrier-ttc .total-carrier-ttc').html(''); 6589 cart_step_3.find('.content-payment-carrier-ttc .total-carrier-insurance').html(''); 6590 var society_delivery = $('[name=nom_societe]').val(), 6591 lastname_delivery = $('[name=nom]').val(), 6592 firstname_delivery = $('[name=prenom]').val(), 6593 address_delivery = $('[name=adresse]').val(), 6594 zip_code_delivery = $('[name=cp]').val(), 6595 city_delivery = $('[name=ville]').val(), 6596 country_delivery = $('[name=pays]').val(), 6597 iso_code_country_delivery = $('[name=pays] option[value="' + country_delivery + '"]').attr('data-iso-code'); 6598 if ($('[name=address_billing_same_delivery]:checked').val() == 0) { 6599 lastname_delivery = $('[name=nom_livraison]').val(); 6600 society_delivery = $('[societe_livraison]').val(); 6601 firstname_delivery = $('[name=prenom_livraison]').val(); 6602 address_delivery = $('[name=adresse_livraison]').val(); 6603 zip_code_delivery = $('[name=cp_livraison]').val(); 6604 city_delivery = $('[name=ville_livraison]').val(); 6605 country_delivery = $('[name=pays_livraison]').val(), iso_code_country_delivery = $('[name=pays_livraison] option[value="' + country_delivery + '"]').attr('data-iso-code'); 6606 } 6607 var content_loader = $('<div />', { 6608 'class': 'bloc-total-loader', 6609 'html': $('<i />', { 6610 'class': 'fa fa-spinner fa-spin' 6611 }) 6612 }); 6613 $('.content-carriers').html(content_loader).removeClass('content-carriers-none'); 6614 $.ajax({ 6615 type: "POST", 6616 url: "/ajax/minisite/panier/get_carrier.php", 6617 data: { 6618 'society_delivery': society_delivery, 6619 'lastname_delivery': lastname_delivery, 6620 'firstname_delivery': firstname_delivery, 6621 'address_delivery': address_delivery, 6622 'zip_code_delivery': zip_code_delivery, 6623 'city_delivery': city_delivery, 6624 'country_delivery': country_delivery, 6625 'iso_code_country_delivery': iso_code_country_delivery 6626 }, 6627 dataType: 'json', 6628 success: function (json) { 6629 if (json.hasOwnProperty('reload')) { 6630 location.reload(); 6631 } 6632 if (json.hasOwnProperty('carriers') && json.carriers.length > 0) { 6633 var tplCarriers = '', 6634 priceCarrier, 6635 aInformationCarrierProducts = [], 6636 canAutoSelected = json.hasOwnProperty('haveUniqShipping') && json.haveUniqShipping; 6637 haveUniqShipping = json.hasOwnProperty('haveUniqShipping') && json.haveUniqShipping; 6638 var isChecked = false; 6639 $('.content-carriers').html(''); 6640 var iterator = 0; 6641 $.each(json.carriers, function (indexCarrierGroup, item) { 6642 tplCarriers += '<div class="content-carriers__item">'; 6643 iterator++; 6644 if (json.carriers.length > 1) { 6645 aInformationCarrierProducts = []; 6646 if (json.hasOwnProperty('products') && json.products[indexCarrierGroup]) { 6647 $.each(json.products[indexCarrierGroup], function (productKey, productLabel) { 6648 aInformationCarrierProducts.push(productLabel); 6649 }); 6650 } 6651 tplCarriers += '<div class="content-carriers__label"><i class="fa fa-truck"></i> ' + _lang.get('Livraison') + ' ' + iterator + ' :</div>'; 6652 if (aInformationCarrierProducts.length) { 6653 tplCarriers += '<div class="content-carriers__products">' + aInformationCarrierProducts.join(', ') + '</div>'; 6654 } 6655 } 6656 tplCarriers += '<ul>'; 6657 $.each(item, function (index, value) { 6658 var data_attr = '', 6659 optionsInput = ''; 6660 if (Object.keys(value._dateAttr).length > 0) { 6661 $.each(value._dateAttr, function (index, value) { 6662 data_attr += ' data-' + index + '="' + value + '"'; 6663 }); 6664 } 6665 if (Object.keys(value._dataOptions).length > 0) { 6666 $.each(value._dataOptions, function (index, value) { 6667 optionsInput += ' ' + index + '="' + value + '"'; 6668 }); 6669 } 6670 if (value._isCmonSiteRelay) { 6671 data_attr += ' data-cmonsite-relay="1"'; 6672 } else { 6673 data_attr += ' data-cmonsite-relay="0"'; 6674 } 6675 var logoTransporteur, 6676 insuranceBlock = ''; 6677 if (value._logo) { 6678 logoTransporteur = '<div class="logo-carrier" style="background-image: url(' + value._logo + ');"></div>'; 6679 } else { 6680 logoTransporteur = '<div class="logo-carrier-none"><i class="fa fa-truck"></i></div>'; 6681 } 6682 if (value._hasInsurance) { 6683 insuranceBlock += '' + '<div class="insurance-block col s12" style="margin: 0;display:none;">' + '<div class="insurance-block__label row">' + '<div class="col s2"> ' + '</div>' + '<div class="col s7">' + '<input class="checkbox_insurance" value="1" style="margin-top: 2px;display: inline-block" type="checkbox" name="insurance_' + indexCarrierGroup + '_' + value._id + '" data-price="' + value._priceInsurance + '" data-price-format="' + value._priceInsuranceFormat + '" />' + lang_assurer_mon_colis + (value._detailInsurance !== '' ? ' ( ' + value._detailInsurance + ' )' : '') + ' ' + '</div>' + '<div class="col s3" style="text-align: right""><span style="padding-right: 11px;"> + ' + value._priceInsuranceFormat + ' </span></div>' + '</label>' + '</div>'; 6684 } 6685 priceCarrier = value._priceFormat; 6686 6687 /* Reduction "frais de port" d'un code Pro : annoncer l'avantage sur la ligne, 6688 avant meme que le transporteur soit selectionne. Renseigne par
6689 ajax/minisite/panier/get_carrier.php, uniquement sur un envoi unique. */ 6690 var priceCarrierBlock, 6691 discountCarrierMessage = ''; 6692 if (value._priceAfterDiscountFormat) { 6693 priceCarrierBlock = '<span class="carrier_price__before" style="text-decoration: line-through;">' + priceCarrier.toString().replace('.00', '') + '</span>' + '<span class="carrier_price__after">' + value._priceAfterDiscountFormat.toString().replace('.00', '') + '</span>'; 6694 /* Pas de rangee grid vide quand le prix remise se suffit a lui-meme */ 6695 if (value._discountShippingLabel) { 6696 discountCarrierMessage = '<div class="col s12 carrier-discount-message">' + value._discountShippingLabel + '</div>'; 6697 } 6698 } else { 6699 priceCarrierBlock = '<span>' + (value._price == null ? '' : priceCarrier.toString().replace('.00', '')) + '</span>'; 6700 } 6701 tplCarriers += '<li class="line_carrier">' + '<label>' + '<div class="col xs3 s2"><input class="radio_carrier" data-product-group="' + indexCarrierGroup + '" ' + (isChecked ? 'checked' : '') + ' ' + optionsInput + ' ' + data_attr + ' type="radio" data-price="' + value._price + '" data-price-format="' + value._priceFormat + '" name="carrier[' + indexCarrierGroup + ']" value="' + value._id + '" />' + logoTransporteur + '</div>' + '<div class="col xs9 s7 carrier_name"><span>' + value._name + '</span>' + '</div>' + '<div class="col s3 carrier_price">' + priceCarrierBlock + '</div>' + insuranceBlock + '<div class="col s12 transporteur-message">' + value._message + '</div>' + '<div class="col s12 information-relay" style="display:none;"></div>' + '</label>' + '</li>'; 6702 }); 6703 tplCarriers += '</ul>'; 6704 tplCarriers += '</div>'; 6705 $('.content-carriers').append(tplCarriers); 6706 tplCarriers = ''; 6707 }); 6708 if (haveUniqShipping) { 6709 var $radioCarrierUniq = $('.content-carriers').find('.radio_carrier'); 6710 if ($radioCarrierUniq.length === 1) { 6711 var $container = $('.block-info-commande'), 6712 $optionCountry = $container.find('[name="pays"] option[value="' + $container.find('[name="pays"]').val() + '"]'); 6713 if ($('[name="address_billing_same_delivery"]:checked').val() === '0') { 6714 $optionCountry = $container.find('[name="pays_livraison"] option[value="' + $container.find('[name="pays_livraison"]').val() + '"]'); 6715 } 6716 $radioCarrierUniq.prop('checked', true).trigger('change', [{ 6717 'calculatePriceParams': { 6718 'countryIsoTax': $optionCountry.attr('data-iso-code') 6719 } 6720 }]); 6721 isChecked = true; 6722 } 6723 } 6724 } else { 6725 $('.content-carriers').html($('<p />').html(MessageNoTransporteur)).addClass('content-carriers-none'); 6726 //$('.block-payment-mode').hide(); 6727 //$('#finish [type="submit"]').prop('disabled', true); 6728 } 6729 if (!isChecked) { 6730 var $containerInfoCommande = $('.block-info-commande'), 6731 $optionCountryInfoCommande = $containerInfoCommande.find('[name="pays"] option[value="' + $containerInfoCommande.find('[name="pays"]').val() + '"]'); 6732 if ($('[name="address_billing_same_delivery"]:checked').val() === '0') { 6733 $optionCountryInfoCommande = $containerInfoCommande.find('[name="pays_livraison"] option[value="' + $containerInfoCommande.find('[name="pays_livraison"]').val() + '"]'); 6734 } 6735 calculatePrice({ 6736 'countryIsoTax': $optionCountryInfoCommande.attr('data-iso-code') 6737 }); 6738 } 6739 } 6740 }); 6741 }, 500); 6742 $(".template_flux_panier .various").on('click', function () { 6743 var $item = $(this); 6744 if ($item.hasClass('fancybox.iframe')) { 6745 var urlApi = null, 6746 url = $item.attr('href'); 6747 switch (true) { 6748 case /^\/(?![\/])/.test(url): 6749 urlApi = new URL(url, window.location.origin); 6750 break; 6751 case url.indexOf(window.location.origin) === 0: 6752 urlApi = new URL(url); 6753 break; 6754 } 6755 if (urlApi !== null) { 6756 if (urlApi.search === '') { 6757 urlApi.search = '?isIframe=1'; 6758 } else { 6759 urlApi.search = '&isIframe=1'; 6760 } 6761 $.fancybox({ 6762 'minHeight': '400', 6763 'type': 'iframe', 6764 'href': urlApi.pathname + urlApi.search 6765 }); 6766 return false;
6767 } 6768 } 6769 $item.fancybox({ 6770 minHeight: '400' 6771 }); 6772 return false; 6773 }); 6774 $body.on('click', '.line_carrier .insurance-block__label', function (e) { 6775 var $self = $(this), 6776 $checkbox = $self.find('.checkbox_insurance'); 6777 if ($(e.target).hasClass('checkbox_insurance')) { 6778 calculatePrice(); 6779 return true; 6780 } 6781 if ($checkbox.is(':checked')) { 6782 $checkbox.prop('checked', false); 6783 } else { 6784 $checkbox.prop('checked', true); 6785 } 6786 calculatePrice(); 6787 }); 6788 const optionOrderSubmit = { 6789 'PayPalCardFields': null 6790 }; 6791 async function formOrderSubmit(...parameters) { 6792 const e = parameters.pop(); 6793 const optionParameter = parameters.pop(); 6794 const option = Object.assign({}, optionOrderSubmit, optionParameter); 6795 var $form = $('[name=form-order]'), 6796 resultValidFormOrder = validFormOrder(); 6797 if ($('.block-payment-mode').hasClass('hide')) { 6798 return resultValidFormOrder; 6799 } 6800 switch (true) { 6801 case window.paypal && window.paypal.Buttons && typeof PayPalUseInContext !== 'undefined' && PayPalUseInContext && $('[name=moyenspaiements]:checked').val() === 'paypal_api': 6802 if (!resultValidFormOrder) { 6803 e.preventDefault(); 6804 } 6805 return resultValidFormOrder; 6806 // removed by dead control flow 6807{} 6808 case window.paypal && window.paypal.HostedFields && option.PayPalCardFields !== null && $('[name=moyenspaiements]:checked').val() === 'paypal_cb': 6809 var state = option.PayPalCardFields.getState(); 6810 var formValid = Object.keys(state.fields).every(function (key) { 6811 return state.fields[key].isValid; 6812 }); 6813 if (resultValidFormOrder && formValid) { 6814 $('.flux-panier-container').waitMe(); 6815 if ($form.find('.block-payment-mode').hasClass('hide')) { 6816 return true; 6817 } 6818 e.preventDefault(); 6819 option.PayPalCardFields.submit({ 6820 contingencies: ['SCA_ALWAYS'] 6821 }).then(function (payload) { 6822 var formData = new FormData(); 6823 formData.append('paypal_id_order', paypalHostedFieldsOrderId); 6824 return fetch('/ajax/minisite/payment/paypal/capture.php', { 6825 method: 'post', 6826 body: formData 6827 }).then(function (res) { 6828 return res.json(); 6829 }).then(function (response) { 6830 switch (response.status) { 6831 case 'success': 6832 location.href = response.href; 6833 break; 6834 default: 6835 switch (true) { 6836 case response.hasOwnProperty('paypalIssueError'): 6837 $('.flux-panier-container').waitMe('hide'); 6838 var $dangerPayPalError = $('<div />', { 6839 'class': 'alert alert-danger text-center', 6840 'html': response.error 6841 }), 6842 $paiementchoix = $('#paiementchoix'); 6843 $paiementchoix.prepend($dangerPayPalError); 6844 $("html, body").animate({ 6845 scrollTop: $paiementchoix.offset().top - 180 6846 }, 500, 'swing'); 6847 setTimeout(function () { 6848 $dangerPayPalError.slideUp('slow', function () { 6849 $(this).remove(); 6850 }); 6851 }, 5000); 6852 break; 6853 case response.hasOwnProperty('href'): 6854 location.href = response.href; 6855 break; 6856 default: 6857 $('.flux-panier-container').waitMe('hide'); 6858 var $item = $('<div />', { 6859 'class': 'item', 6860 'html': response.error 6861 }); 6862 $('.payment_item_information__paypal_cb__notification').prepend($item); 6863 setTimeout(function () { 6864 $item.slideUp('slow', function () { 6865 $(this).remove(); 6866 }); 6867 }, 8000); 6868 } 6869 } 6870 }); 6871 }).catch(error => {
6872 $('.flux-panier-container').waitMe('hide'); 6873 var $dangerPayPalError = $('<div />', { 6874 'class': 'alert alert-danger text-center', 6875 'html': _lang.get('Nous n\'arrivons pas à finaliser le paiement via ce mode de paiement, nous vous conseillons d\'utiliser un autre mode de mode de paiement.') 6876 }), 6877 $paymentItemPayPalCbNotification = $('.payment_item_information__paypal_cb__notification'); 6878 $paymentItemPayPalCbNotification.prepend($dangerPayPalError); 6879 setTimeout(function () { 6880 $paymentItemPayPalCbNotification.slideUp(function () { 6881 $(this).html(''); 6882 }); 6883 }, 6000); 6884 }); 6885 } 6886 e.preventDefault(); 6887 return false; 6888 // removed by dead control flow 6889{} 6890 case typeof mollie_compoment !== 'undefined' && mollie_compoment && $('[name=moyenspaiements]:checked').val() === 'mollie_creditcard': 6891 if (resultValidFormOrder) { 6892 $('.flux-panier-container').waitMe(); 6893 if ($form.find('.block-payment-mode').hasClass('hide')) { 6894 return true; 6895 } 6896 e.preventDefault(); 6897 var $containerNotification = $form.find('.payment_item_information__mollie_creditcard__notification'); 6898 $containerNotification.html(''); 6899 const { 6900 token, 6901 error 6902 } = await mollie.createToken(); 6903 if (error) { 6904 // Something wrong happened while creating the token. Handle this situation gracefully. 6905 $containerNotification.html($('<div />', { 6906 'class': 'alert alert-danger', 6907 'html': error.message 6908 })); 6909 $('.flux-panier-container').waitMe('hide'); 6910 return false; 6911 } 6912 $.ajax({ 6913 url: "/paniercommande.php", 6914 data: $form.serialize() + '&submit=1&ajax=1', 6915 method: 'POST', 6916 dataType: 'json', 6917 success: function (data) { 6918 switch (data.status) { 6919 case 'reload': 6920 location.reload(); 6921 break; 6922 case 'success': 6923 $.ajax({ 6924 url: '/ajax/minisite/payment/mollie/valid.php', 6925 type: 'POST', 6926 dataType: 'json', 6927 data: { 6928 'reference': data.reference, 6929 'token_acompte': data.token_acompte, 6930 'token': token 6931 }, 6932 success: function (response) { 6933 switch (response.status) { 6934 case 'requires_action': 6935 break; 6936 case 'success': 6937 location.href = response.redirect; 6938 break; 6939 case 'redirect': 6940 location.href = response.redirect; 6941 break; 6942 case 'error': 6943 $('.flux-panier-container').waitMe('hide'); 6944 $containerNotification.html($('<div />', { 6945 'class': 'alert alert-danger', 6946 'html': response.error 6947 })); 6948 break; 6949 } 6950 } 6951 }); 6952 break; 6953 case 'cancel': 6954 location.href = data.url; 6955 break; 6956 case 'error': 6957 location.href = '/paniercommande.php#information'; 6958 break; 6959 } 6960 }, 6961 error: function (e) {} 6962 }); 6963 } 6964 e.preventDefault(); 6965 return false; 6966 // removed by dead control flow 6967{} 6968 default: 6969 if (resultValidFormOrder) { 6970 $('.flux-panier-container').waitMe(); 6971 } 6972 } 6973 if (!resultValidFormOrder) { 6974 e.preventDefault(); 6975 } 6976 return resultValidFormOrder; 6977 } 6978 $body.on('submit', '[name=form-order]', formOrderSubmit); 6979 6980 // $body.on('submit', '[name=form-order]', function (event) { 6981 // 6982 // }); 6983 6984 var $moyenspaiements_checked = $('[name=moyenspaiements]:checked'); 6985 if ($moyenspaiements_checked.length) { 6986 $moyenspaiements_checked.trigger('change'); 6987 } 6988 if (window.paypal && window.paypal.HostedFields) { 6989 var paypalHostedFieldsOrderId; 6990 paypal.HostedFields.render({ 6991 createOrder: function (data, actions) { 6992 var formOrder = new FormData(document.querySelector('[name=form-order]')); 6993 formOrder.append('submit', '1'); 6994 formOrder.append('ajax', '1'); 6995 return fetch('/paniercommande.php', { 6996 method: "POST", 6997 body: formOrder 6998 }).then(function (res) { 6999 return res.json(); 7000 }).then(function (orderData) { 7001 paypalHostedFieldsOrderId = orderData.token; 7002 return orderData.token; 7003 }); 7004 }, 7005 styles: { 7006 '.valid': { 7007 color: 'green' 7008 }, 7009 '.invalid': { 7010 color: 'red' 7011 } 7012 }, 7013 fields: { 7014 number: { 7015 selector: "#paypal-card-number", 7016 placeholder: "4111 1111 1111 1111" 7017 }, 7018 cvv: { 7019 selector: "#paypal-card-cvc", 7020 placeholder: "123" 7021 }, 7022 expirationDate: { 7023 selector: "#paypal-card-expiry", 7024 placeholder: "MM/YY" 7025 } 7026 } 7027 }).then(function (cardFields) { 7028 $body.off('submit', '[name=form-order]', formOrderSubmit); 7029 $body.on('submit', '[name=form-order]', formOrderSubmit.bind(null, { 7030 'PayPalCardFields': cardFields 7031 })); 7032 }); 7033 } 7034 if (window.paypal && window.paypal.Buttons && typeof PayPalUseInContext !== 'undefined' && PayPalUseInContext) { 7035 paypal.Buttons({ 7036 style: { 7037 layout: 'horizontal', 7038 pill: 'pill', 7039 label: 'pay' 7040 }, 7041 onInit: function (data, actions) { 7042 // Disable the buttons 7043 actions.disable(); 7044 if (validFormOrder(false)) { 7045 actions.enable(); 7046 } 7047 7048 // Listen for changes to the checkbox 7049 document.querySelector('[name="form-order"]').addEventListener('change', function (event) { 7050 if (validFormOrder(false)) { 7051 actions.enable(); 7052 } else { 7053 actions.disable(); 7054 } 7055 }); 7056 }, 7057 onClick: function () { 7058 $('[name="form-order"]').trigger('change'); 7059 validFormOrder(); 7060 }, 7061 onCancel: function (data) { 7062 var formData = new FormData(); 7063 formData.append('paypal_id_order', data.orderID); 7064 return fetch('/ajax/minisite/payment/paypal/cancel.php', { 7065 method: 'post', 7066 body: formData 7067 }).then(function (res) { 7068 return res.json(); 7069 }).then(function (response) { 7070 if (response.hasOwnProperty('href')) { 7071 location.href = response.href; 7072 } else {
7073 $('.flux-panier-container').waitMe('hide'); 7074 } 7075 }); 7076 }, 7077 onError: function (err) { 7078 location.href = '/paiement-site/error/'; 7079 }, 7080 // Call your server to set up the transaction 7081 createOrder: function (data, actions) { 7082 $('.flux-panier-container').waitMe(); 7083 var formOrder = new FormData(document.querySelector('[name=form-order]')); 7084 formOrder.append('submit', '1'); 7085 formOrder.append('ajax', '1'); 7086 return fetch('/paniercommande.php', { 7087 method: "POST", 7088 body: formOrder 7089 }).then(function (res) { 7090 return res.json(); 7091 }).then(function (orderData) { 7092 switch (true) { 7093 case orderData.hasOwnProperty('status') && orderData.status === 'error': 7094 //alert(orderData.data.msg_error); 7095 return null; 7096 // removed by dead control flow 7097{} 7098 } 7099 return orderData.token; 7100 }); 7101 }, 7102 onApprove: function (data, actions) { 7103 var formData = new FormData(); 7104 formData.append('paypal_id_order', data.orderID); 7105 formData.append('payer_id', data.payerID); 7106 return fetch('/ajax/minisite/payment/paypal/capture.php', { 7107 method: 'post', 7108 body: formData 7109 }).then(function (res) { 7110 return res.json(); 7111 }).then(function (response) { 7112 if (response.hasOwnProperty('paypalIssueError')) { 7113 $('.flux-panier-container').waitMe('hide'); 7114 var $dangerPayPalError = $('<div />', { 7115 'class': 'alert alert-danger text-center', 7116 'html': response.error 7117 }), 7118 $paiementchoix = $('#paiementchoix'); 7119 $paiementchoix.prepend($dangerPayPalError); 7120 $("html, body").animate({ 7121 scrollTop: $paiementchoix.offset().top - 180 7122 }, 500, 'swing'); 7123 setTimeout(function () { 7124 $dangerPayPalError.slideUp('slow', function () { 7125 $(this).remove(); 7126 }); 7127 }, 5000); 7128 } else { 7129 location.href = response.href; 7130 } 7131 }); 7132 } 7133 }).render('#paypal-button-container'); 7134 } 7135 $body.on('change', '[name=moyenspaiements]', function (event) { 7136 var $self = $(this), 7137 $parent = $self.closest('.line_payment'), 7138 value = $self.val(), 7139 $btn_PAYPAL = $('#paypal-button-container'), 7140 $order_confirm = $('#confirmBtn'); 7141 if (event && event.originalEvent) { 7142 trackCartStepEvent('add_payment_info', { 7143 payment_type: value 7144 }); 7145 } 7146 $('#paiementchoix label').removeClass('selected').parent().removeClass('selected'); 7147 $self.parent('label').addClass('selected').closest('li').addClass('selected').closest('ul').addClass('group-selected'); 7148 $('.line_payment').removeClass('line_payment__checked'); 7149 $parent.addClass('line_payment__checked'); 7150 switch (value) { 7151 case 'paypal_api': 7152 if (window.paypal && window.paypal.Buttons && typeof PayPalUseInContext !== 'undefined' && PayPalUseInContext) { 7153 $btn_PAYPAL.show(); 7154 $order_confirm.hide(); 7155 } 7156 break; 7157 case 'mollie_creditcard': 7158 mollieMountComponents(); 7159 if (window.paypal && window.paypal.Buttons && typeof PayPalUseInContext !== 'undefined' && PayPalUseInContext) { 7160 $btn_PAYPAL.hide(); 7161 $order_confirm.show(); 7162 } 7163 break; 7164 default: 7165 if (window.paypal && window.paypal.Buttons && typeof PayPalUseInContext !== 'undefined' && PayPalUseInContext) { 7166 $btn_PAYPAL.hide(); 7167 $order_confirm.show(); 7168 } 7169 } 7170 }); 7171 function validFormOrder(showAlert) { 7172 if (typeof showAlert === 'undefined') { 7173 showAlert = true; 7174 } 7175 7176 /* valider les champs */ 7177 var radio_payment_mode = $('[name=moyenspaiements]:checked'), 7178 checkbox_cgv = $('[name=cgv]'), 7179 $containerCarrier = $('.content-carriers__item'), 7180 resultShipping = true; 7181 7182 /* Tester si on utilise la livraison */ 7183 if ($useShipping > 0) { 7184 $containerCarrier.each(function (index, itemCarrier) { 7185 var $itemCarrier = $(itemCarrier), 7186 $radioCarriers = $itemCarrier.find('.radio_carrier'), 7187 $radioCarrierChecked = $itemCarrier.find('.radio_carrier:checked'); 7188 if ($radioCarriers.length > 0 && $radioCarrierChecked.length === 0) { 7189 resultShipping = false;
7190 } 7191 }); 7192 } 7193 if (resultShipping === false) { 7194 if (showAlert) { 7195 $("html, body").animate({ 7196 scrollTop: $('.block-info-payment_carriers').offset().top - 100 7197 }, 500, 'swing'); 7198 alert('Veuillez sélectionner un moyen de livraison.'); 7199 } 7200 return false; 7201 } 7202 if ($('[name=moyenspaiements]').length > 0 && radio_payment_mode.length === 0) { 7203 if (showAlert) { 7204 $("html, body").animate({ 7205 scrollTop: $('.block-payment-mode').offset().top - 100 7206 }, 500, 'swing'); 7207 alert('Veuillez sélectionner un moyen de paiement.'); 7208 } 7209 return false; 7210 } 7211 if (checkbox_cgv.length > 0 && !checkbox_cgv.is(':checked')) { 7212 if (showAlert) { 7213 alert('Veuillez valider les conditions génénerales de vente.'); 7214 } 7215 return false; 7216 } 7217 if (!$('[name="form-order"]').validationEngine('validate')) { 7218 if (!showAlert) { 7219 $('[name="form-order"]').validationEngine('hide'); 7220 } 7221 return false; 7222 } 7223 let formOrderQuery = document.querySelector('[name="form-order"]'); 7224 if (!formOrderQuery.checkValidity()) { 7225 if (showAlert) { 7226 formOrderQuery.reportValidity(); 7227 } 7228 return false; 7229 } 7230 if (checkbox_cgv.length === 0 || $(checkbox_cgv).length > 0 && checkbox_cgv.is(':checked')) { 7231 if (typeof fbq === 'function') { 7232 var facebookParameter = {}; 7233 fbq('track', 'InitiateCheckout'); 7234 } 7235 if (typeof pintrk === 'function') { 7236 //pintrk('track', 'custom', {value: 'initiatecheckout'}); 7237 } 7238 return true; 7239 } 7240 return false; 7241 } 7242 function trackCartProductEvent(eventName, product, quantity) { 7243 if (!window.CmonSiteTracking || !product) { 7244 return; 7245 } 7246 var qty = Math.abs(quantity), 7247 price = parseFloat(product.price) || 0, 7248 item = { 7249 item_id: product.id, 7250 item_name: product.title_without_variation, 7251 item_category: product.category, 7252 quantity: qty, 7253 price: price 7254 }; 7255 7256 /* Cles optionnelles GA4 : omises plutot que null */ 7257 if (product.brand) { 7258 item.item_brand = product.brand; 7259 } 7260 if (product.variation) { 7261 item.item_variant = product.variation; 7262 } 7263 window.CmonSiteTracking.event(eventName, { 7264 currency: product.currency, 7265 value: +(price * qty).toFixed(2), 7266 items: [item] 7267 }); 7268 } 7269 function trackCartStepEvent(eventName, extraParams) { 7270 if (!window.CmonSiteTracking || !window.CmonSiteTrackingCart || !window.CmonSiteTrackingCart.items || !window.CmonSiteTrackingCart.items.length) { 7271 return false; 7272 } 7273 window.CmonSiteTracking.event(eventName, $.extend({}, window.CmonSiteTrackingCart, extraParams || {})); 7274 return true; 7275 } 7276 function changeQuantityProduct(idProduct, idProductAttribute, quantity) { 7277 $.ajax({ 7278 type: "POST", 7279 url: "/ajax/minisite/panier/add_product_quantity.php", 7280 data: { 7281 'id_product': idProduct, 7282 'id_product_attribute': idProductAttribute, 7283 'quantity': quantity 7284 }, 7285 dataType: 'json', 7286 success: function (json) { 7287 if (json.hasOwnProperty('reload')) { 7288 location.reload(); 7289 } 7290 reloadResumeAndPaymentCartAjax(); 7291 reloadBlockReductionCode(); 7292 calculatePrice(); 7293 } 7294 }); 7295 } 7296 function changeQuantityProductByKey(key, quantity) { 7297 $('.resume-cart-products.table').waitMe(); 7298 $.ajax({ 7299 type: "POST", 7300 url: "/ajax/minisite/panier/add_product_quantity.php", 7301 data: { 7302 'key': key, 7303 'quantity': quantity 7304 }, 7305 dataType: 'json', 7306 success: function (json) { 7307 if (json.hasOwnProperty('reload')) { 7308 location.reload(); 7309 } 7310 setTimeout(function () { 7311 $('.resume-cart-products.table').waitMe('hide'); 7312 }, 500); 7313 if (json.hasOwnProperty('product') && json.product !== null) { 7314 trackCartProductEvent(quantity < 0 ? 'remove_from_cart' : 'add_to_cart', json.product, quantity); 7315 } 7316 reloadResumeAndPaymentCartAjax(); 7317 reloadBlockReductionCode(); 7318 loadCarriers(); 7319 $('#panier').trigger('reload'); 7320 } 7321 }); 7322 } 7323 function changeQuantityProductBookingByKey(key, quantity) { 7324 $('.resume-cart-products.table').waitMe(); 7325 $.ajax({ 7326 type: "POST", 7327 url: "/ajax/minisite/panier/add_booking_quantity.php", 7328 data: { 7329 'key': key, 7330 'quantity': quantity 7331 }, 7332 dataType: 'json', 7333 success: function (response) { 7334 setTimeout(function () { 7335 $('.resume-cart-products.table').waitMe('hide'); 7336 }, 500); 7337 switch (true) { 7338 case response.hasOwnProperty('status') && response.status === 'reload': 7339 location.reload(); 7340 break; 7341 case response.hasOwnProperty('status') && response.status === 'error': 7342 break; 7343 case response.hasOwnProperty('status') && response.status === 'success': 7344 reloadResumeAndPaymentCartAjax(); 7345 reloadBlockReductionCode(); 7346 calculatePrice(); 7347 $('#panier').trigger('reload'); 7348 break; 7349 } 7350 } 7351 }); 7352 } 7353 function deleteProduct(idProduct, idProductAttribute) { 7354 $.ajax({ 7355 type: "POST", 7356 url: "/ajax/minisite/panier/remove_product.php", 7357 data: { 7358 'id_product': idProduct, 7359 'id_product_attribute': idProductAttribute 7360 }, 7361 dataType: 'json', 7362 success: function (json) { 7363 if (json.hasOwnProperty('reload')) { 7364 location.reload(); 7365 } 7366 $('.content-payment-product-ht .total-product-ht').html(json.total_product_ht); 7367 $('.content-payment-tva .total-product-tva').html(json.tva); 7368 $('.content-payment-product-global .total-product-global').html(json.total_product_ttc); 7369 $('.content-payment-global .total-global').html(json.total_global); 7370 $useShipping = json.useShipping; 7371 if ($useShipping == 0) { 7372 $('.use_shipping').hide(); 7373 } 7374 reloadBlockReductionCode(); 7375 reloadResumeAndPaymentCartAjax(); 7376 calculatePrice(); 7377 } 7378 }); 7379 } 7380 function deleteProductByKey(key) { 7381 $('.resume-cart-products.table').waitMe(); 7382 $.ajax({ 7383 type: "POST", 7384 url: "/ajax/minisite/panier/remove_product.php", 7385 data: { 7386 'key': key 7387 }, 7388 dataType: 'json', 7389 success: function (json) { 7390 if (json.hasOwnProperty('reload')) { 7391 location.reload(); 7392 } 7393 if (json.hasOwnProperty('productData') && json.productData !== null) { 7394 trackCartProductEvent('remove_from_cart', json.productData, json.productData.quantity); 7395 } 7396 $('.content-payment-product-ht .total-product-ht').html(json.total_product_ht); 7397 $('.content-payment-tva .total-product-tva').html(json.tva); 7398 $('.content-payment-product-global .total-product-global').html(json.total_product_ttc); 7399 $('.content-payment-global .total-global').html(json.total_global); 7400 $useShipping = json.useShipping; 7401 if ($useShipping == 0) { 7402 $('.use_shipping').hide(); 7403 } 7404 setTimeout(function () { 7405 $('.resume-cart-products.table').waitMe('hide'); 7406 }, 500); 7407 reloadBlockReductionCode(); 7408 reloadResumeAndPaymentCartAjax(); 7409 loadCarriers(); 7410 calculatePrice(); 7411 $('#panier').trigger('reload'); 7412 } 7413 }); 7414 } 7415 var can_calculate_price = true; 7416 function calculatePrice(params) { 7417 if (!can_calculate_price) { 7418 return; 7419 } 7420 can_calculate_price = false;
7421 var haveInformationToCarrierPrice = false, 7422 amountCarrier = -1, 7423 amountCarrierInsurance = 0; 7424 $('.bloc-total-loader').show(); 7425 $('.bloc-total').hide(); 7426 if (typeof params === 'undefined') { 7427 params = {}; 7428 } 7429 var $containerCarriers = $('.content-carriers__item'); 7430 if ($containerCarriers.length) { 7431 var amountCarrierTmp = 0, 7432 haveCarrierChecked = false, 7433 carriers = []; 7434 $containerCarriers.each(function (index, itemCarrier) { 7435 var $itemCarrier = $(itemCarrier), 7436 $radioCarrierChecked = $itemCarrier.find('.radio_carrier:checked'), 7437 $insuranceItem; 7438 if ($radioCarrierChecked.length) { 7439 haveCarrierChecked = true; 7440 amountCarrierTmp += parseFloat($radioCarrierChecked.attr('data-price')); 7441 $insuranceItem = $('[name=insurance_' + $radioCarrierChecked.attr('data-product-group') + '_' + $radioCarrierChecked.val() + ']:checked'); 7442 carriers.push({ 7443 'carrier': $radioCarrierChecked.val(), 7444 'amount': parseFloat($radioCarrierChecked.attr('data-price')) 7445 }); 7446 if ($insuranceItem.length) { 7447 amountCarrierInsurance += parseFloat($insuranceItem.attr('data-price')); 7448 } 7449 } 7450 }); 7451 if (haveCarrierChecked) { 7452 amountCarrier = amountCarrierTmp; 7453 } else { 7454 /* Tester si nous avons seulement un groupe de transporteur */ 7455 if ($containerCarriers.length === 1) { 7456 $containerCarriers.each(function (index, itemCarrier) { 7457 var $itemCarrier = $(itemCarrier), 7458 $radioCarrier = $itemCarrier.find('.radio_carrier'); 7459 if ($radioCarrier.length === 1) { 7460 if (priceShippingEstimatedWithClickAndCollect || !priceShippingEstimatedWithClickAndCollect && $radioCarrier.attr('data-cmonsite-relay') === '0') { 7461 haveUniqShipping = true; 7462 } else { 7463 $radioCarrier = null; 7464 } 7465 } else { 7466 if (showShippingEstimatedWithSeveralCarrier) { 7467 if (priceShippingEstimatedWithClickAndCollect) { 7468 $radioCarrier = $itemCarrier.find('.radio_carrier').first(); 7469 } else { 7470 $radioCarrier = $itemCarrier.find('.radio_carrier[data-cmonsite-relay="0"]').first(); 7471 } 7472 if ($radioCarrier.length) { 7473 haveInformationToCarrierPrice = true; 7474 } 7475 } else { 7476 $radioCarrier = null; 7477 } 7478 } 7479 if ($radioCarrier !== null && $radioCarrier.length) { 7480 /* Faire comme si le client avais sélectionné ce transporteur */ 7481 amountCarrier = parseFloat($radioCarrier.attr('data-price')); 7482 carriers.push({ 7483 'carrier': $radioCarrier.val(), 7484 'amount': parseFloat($radioCarrier.attr('data-price')) 7485 }); 7486 } 7487 }); 7488 } 7489 } 7490 } 7491 $.ajax({ 7492 type: "POST", 7493 url: "/ajax/minisite/panier/calculate_price.php", 7494 data: { 7495 'carriers': carriers, 7496 'amountCarrier': amountCarrier, 7497 'amountCarrierInsurance': amountCarrierInsurance, 7498 'options_price': options_price, 7499 'options_price_currency': options_price_currency, 7500 'force_country_tax': params.hasOwnProperty('countryIsoTax') ? params.countryIsoTax : null 7501 }, 7502 dataType: 'json', 7503 success: function (json) { 7504 can_calculate_price = true; 7505 if (json.hasOwnProperty('reload')) { 7506 location.reload(); 7507 } 7508 if (json.haveMinOrderAmount) { 7509 cart_step_1.find('.block-min-order-amount').html(json.minOrderAmountText); 7510 cart_step_1.find('.block-min-order-amount').show(); 7511 cart_step_1.find('.block-order-btn').hide(); 7512 $('.side-tabs.etapes').hide(); 7513 } else { 7514 cart_step_1.find('.block-min-order-amount').html(''); 7515 cart_step_1.find('.block-min-order-amount').hide(); 7516 cart_step_1.find('.block-order-btn').show(); 7517 $('.side-tabs.etapes').show(); 7518 } 7519 cart_step_1.find('.content-payment-reduction').hide(); 7520 cart_step_1.find('.content-payment-carrier-ttc').hide(); 7521 cart_step_1.find('.content-payment-product-global').hide(); 7522 cart_step_2.find('.content-payment-reduction').hide(); 7523 cart_step_2.find('.content-payment-carrier-ttc').hide(); 7524 cart_step_2.find('.content-payment-product-global').hide(); 7525 $('.content-payment-reduction-carrier').hide(); 7526 if (json.have_discount_code) { 7527 cart_step_3.find('.content-payment-reduction').show(); 7528 cart_step_3.find('.content-payment-product-global').show(); 7529 if (haveUniqShipping) { 7530 cart_step_1.find('.content-payment-reduction').show(); 7531 cart_step_1.find('.content-payment-product-global').show(); 7532 cart_step_2.find('.content-payment-reduction').show(); 7533 cart_step_2.find('.content-payment-product-global').show(); 7534 } 7535 if (amountCarrier === -1 && json.discount_code_type === 'fdp') { 7536 cart_step_3.find('.content-payment-reduction .total-reduction').html('Vous devez sélectionner un transporteur.'); 7537 if (haveUniqShipping) { 7538 cart_step_1.find('.content-payment-reduction .total-reduction').html('Vous devez sélectionner un transporteur.'); 7539 cart_step_2.find('.content-payment-reduction .total-reduction').html('Vous devez sélectionner un transporteur.'); 7540 } 7541 } else { 7542 if (json.have_discount_code_without_shipping || amountC
7542arrier >= 0) { 7543 cart_step_1.find('.content-payment-reduction').show(); 7544 cart_step_1.find('.content-payment-product-global').show(); 7545 cart_step_1.find('.content-payment-reduction .total-reduction').html(json.reduction_whitout_shipping); 7546 cart_step_2.find('.content-payment-reduction').show(); 7547 cart_step_2.find('.content-payment-product-global').show(); 7548 cart_step_2.find('.content-payment-reduction .total-reduction').html(json.reduction_whitout_shipping); 7549 } 7550 if (json.discount_code_type === 'fdp') { 7551 cart_step_1.find('.content-payment-reduction').show(); 7552 cart_step_1.find('.content-payment-reduction .total-reduction').html('Vous devez sélectionner un transporteur.'); 7553 cart_step_2.find('.content-payment-reduction').show(); 7554 cart_step_2.find('.content-payment-reduction .total-reduction').html('Vous devez sélectionner un transporteur.'); 7555 } 7556 7557 /* PRD 32 R6 : la ligne "Réduction" ne porte plus la réduction sur le port */ 7558 cart_step_3.find('.content-payment-reduction .total-reduction').html(json.reduction_whitout_shipping); 7559 if (!json.have_discount_code_without_shipping) { 7560 cart_step_3.find('.content-payment-reduction').hide(); 7561 } 7562 if (haveUniqShipping || haveInformationToCarrierPrice) { 7563 cart_step_1.find('.content-payment-reduction .total-reduction').html(json.reduction_whitout_shipping); 7564 cart_step_2.find('.content-payment-reduction .total-reduction').html(json.reduction_whitout_shipping); 7565 if (!json.have_discount_code_without_shipping) { 7566 cart_step_1.find('.content-payment-reduction').hide(); 7567 cart_step_2.find('.content-payment-reduction').hide(); 7568 } 7569 } 7570 7571 /* PRD 32 R6 : ligne dédiée "Réduction frais de port", même condition que la ligne port */ 7572 if (json.have_discount_code_carrier && amountCarrier >= 0) { 7573 cart_step_3.find('.content-payment-reduction-carrier').show(); 7574 cart_step_3.find('.content-payment-reduction-carrier .total-reduction-carrier').html(json.reduction_carrier); 7575 if (haveUniqShipping || haveInformationToCarrierPrice) { 7576 cart_step_1.find('.content-payment-reduction-carrier').show(); 7577 cart_step_1.find('.content-payment-reduction-carrier .total-reduction-carrier').html(json.reduction_carrier); 7578 cart_step_2.find('.content-payment-reduction-carrier').show(); 7579 cart_step_2.find('.content-payment-reduction-carrier .total-reduction-carrier').html(json.reduction_carrier); 7580 } 7581 } 7582 } 7583 } else { 7584 $('.content-payment-reduction').hide(); 7585 $('.content-payment-reduction-carrier').hide(); 7586 $("#code_reduc").removeAttr("disabled"); 7587 $('#submit_reduc_code').show(); 7588 $('#submit_remove_reduc_code').hide(); 7589 } 7590 if (amountCarrier >= 0) { 7591 cart_step_1.find('.content-payment-carrier-ttc').show(); 7592 cart_step_2.find('.content-payment-carrier-ttc').show(); 7593 cart_step_3.find('.content-payment-carrier-ttc').show(); 7594 7595 /* Port entierement offert : une seule ligne "Frais de port" avec le montant 7596 barre, au lieu d'une ligne port et d'une ligne reduction qui s'annulent. 7597 Une reduction partielle garde les deux lignes. */ 7598 var amountCarrierHtml = json.amountCarrier; 7599 if (json.carrier_fully_discounted) { 7600 amountCarrierHtml = '<span class="total-carrier-ttc__before" style="text-decoration: line-through;">' + json.amountCarrier + '</span>' + '<span class="total-carrier-ttc__after">' + json.amountCarrierAfterDiscount + '</span>'; 7601 $('.content-payment-reduction-carrier').hide(); 7602 } 7603 cart_step_1.find('.total-carrier-ttc').html(amountCarrierHtml); 7604 cart_step_2.find('.total-carrier-ttc').html(amountCarrierHtml); 7605 cart_step_3.find('.total-carrier-ttc').html(amountCarrierHtml); 7606 } else { 7607 cart_step_1.find('.content-payment-carrier-ttc').hide(); 7608 cart_step_2.find('.content-payment-carrier-ttc').hide(); 7609 cart_step_3.find('.content-payment-carrier-ttc').hide(); 7610 } 7611 7612 /* Etape 1 */ 7613 cart_step_1.find('.content-payment-product-ht .total-product-ht').html(json.total_product_ht); 7614 cart_step_1.find('.content-payment-tva .total-product-tva').html(json.tva); 7615 cart_step_1.find('.content-payment-product-global .total-product-global').html(json.total_product_ttc); 7616 cart_step_1.find('.content-payment-global .total-global').html(json.total_global_without_shipping); 7617 if (cart_step_1.find('.content-payment-advance-payment').length) { 7618 cart_step_1.find('.content-payment-advance-payment .total-advance-payment').html(json.total_advance_payment); 7619 } 7620 if (haveUniqShipping || haveInformationToCarrierPrice) { 7621 cart_step_1.find('.content-payment-global .total-global').html(json.total_global); 7622 } 7623 cart_step_1.find('.content-payment-carrier-ttc .total-carrier-insurance').html(''); 7624 7625 /* Etape 2 */ 7626 cart_step_2.find('.content-payment-product-ht .total-product-ht').html(json.total_product_ht); 7627 cart_step_2.find('.content-payment-tva .total-product-tva').html(json.tva); 7628 cart_step_2.find('.content-payment-product-global .total-product-global').html(json.total_product_ttc); 7629 cart_step_2.find('.content-payment-global .total-global').html(json.total_global_without_shipping); 7630 if (cart_step_2.find('.content-payment-advance-payment').length) { 7631 cart_step_2.find('.content-payment-advance-payment .total-advance-payment').html(json.total_advance_payment); 7632 } 7633 if (haveUniqShipping || haveInformationToCarrierPrice) { 7634 cart_step_2.find('.content-payment-global .total-global').html(json.total_global); 7635 } 7636 cart_step_2.find('.content-payment-carrier-ttc .total-carrier-insurance').html(''); 7637 7638 /* Etape 3 */ 7639 cart_step_3.find('.content-payment-product-ht .total-product-ht').html(json.total_product_ht); 7640 cart_step_3.find('.content-payment-tva .total-product-tva').html(json.tva); 7641 cart_step_3.find('.content-payment-product-global .total-product-global').html(json.total_product_ttc); 7642 cart_step_3.find('.content-payment-global .total-global').html(json.total_global); 7643 if (cart_step_1.find('.content-payment-advance-payment').length) { 7644 cart_step_3.find('.content-payment-advance-payment .total-advance-payment').html(json.total_advance_payment); 7645 } 7646 cart_step_3.find('.content-payment-carrier-ttc .total-carrier-insurance').html(''); 7647 if (amountCarrierInsurance > 0) { 7648 cart_step_3.find('.content-payment-carrier-ttc .total-carrier-insurance').html(' + ' + json.amountC
7648arrierInsurance); 7649 } 7650 var $itemPaymentMode = cart_step_3.find('.block-payment-mode'); 7651 if (!json.show_payment_mode) { 7652 $itemPaymentMode.addClass('hide'); 7653 var $firstPaymentMode = $itemPaymentMode.find('[name="moyenspaiements"]').filter(function () { 7654 var $self = $(this); 7655 switch ($self.val()) { 7656 case 'alma2': 7657 case 'alma3': 7658 case 'alma4': 7659 case 'payplugOneyX3': 7660 case 'payplugOneyX4': 7661 return false; 7662 // removed by dead control flow 7663{} 7664 default: 7665 return true; 7666 } 7667 }).first(); 7668 if ($firstPaymentMode.length) { 7669 $firstPaymentMode.prop('checked', true); 7670 $firstPaymentMode.trigger('change'); 7671 } 7672 } else { 7673 $itemPaymentMode.removeClass('hide'); 7674 } 7675 $('.bloc-total-loader').hide(); 7676 $('.bloc-total').show(); 7677 if (stickyStep2 !== null) { 7678 stickyStep2.destroy(); 7679 } 7680 if (sticky !== null) { 7681 sticky.destroy(); 7682 } 7683 stickyStep2 = new Sticky('.block-info-commande__sticky'); 7684 sticky = new Sticky('.block-info-payment__sticky'); 7685 var optionsPaymentMode = { 7686 'currencyIsoCode': json.current_currency_iso_code, 7687 'amountProductDefaultCurrency': json.total_ttc_product_on_default_currency 7688 }; 7689 refreshPaymentMode(optionsPaymentMode); 7690 if (json.hasOwnProperty('resume_cart') && json.hasOwnProperty('payment_cart') && json.hasOwnProperty('gift_discount_advanced')) { 7691 reloadResumeAndPaymentCart(json.resume_cart, json.payment_cart, json.gift_discount_advanced); 7692 } 7693 7694 /* */ 7695 if (window.paypal && window.paypal.Messages) { 7696 if (cart_step_1.find('.pp-pay-later-message').length === 0) { 7697 $('<div />', { 7698 'class': 'pp-pay-later-message' 7699 }).insertAfter(cart_step_1.find('.container-order-btn')); 7700 } 7701 if (cart_step_3.find('.pp-pay-later-message-payment').length === 0) { 7702 $('<div />', { 7703 'class': 'pp-pay-later-message-payment' 7704 }).insertAfter(cart_step_3.find('.container-order-btn')); 7705 } 7706 window.paypal.Messages({ 7707 amount: json.total_ttc_product_on_current_currency, 7708 placement: 'cart', 7709 style: { 7710 layout: "text", 7711 text: { 7712 align: 'center', 7713 color: ppStyleTextColor, 7714 size: 14 7715 } 7716 } 7717 }).render(".pp-pay-later-message"); 7718 window.paypal.Messages({ 7719 amount: json.total_ttc_product_on_current_currency, 7720 placement: 'payment', 7721 style: { 7722 layout: "text", 7723 text: { 7724 align: 'center', 7725 color: ppStyleTextColor, 7726 size: 14 7727 } 7728 } 7729 }).render(".pp-pay-later-message-payment"); 7730 } 7731 if (typeof mountAlmaPayMessage === "function") { 7732 mountAlmaPayMessage(Math.round(json.total_ttc_product_on_current_currency * 100)); 7733 } 7734 const freeShippingProgress = document.querySelectorAll('.free-shipping-progress'); 7735 freeShippingProgress.forEach(element => { 7736 element.innerHTML = ''; 7737 }); 7738 if (json.hasOwnProperty('free_shipping_progress_added')) { 7739 if (json.free_shipping_progress_added.status) { 7740 const view = { 7741 title: json.free_shipping_progress_added.title, 7742 percentage: json.free_shipping_progress_added.data.percentage, 7743 reached: json.free_shipping_progress_added.data.reached, 7744 message: json.free_shipping_progress_added.message, 7745 success_message: json.free_shipping_progress_added.success_message 7746 }; 7747 freeShippingProgress.forEach(element => { 7748 element.insertAdjacentHTML('beforeend', mustache__WEBPACK_IMPORTED_MODULE_2__["default"].render(json.free_shipping_progress_added.template, view)); 7749 }); 7750 } else {} 7751 } 7752 if (json.hasOwnProperty('free_shipping_progress')) { 7753 if (json.free_shipping_progress.status) { 7754 const view = { 7755 title: json.free_shipping_progress.title, 7756 percentage: json.free_shipping_progress.data.percentage, 7757 reached: json.free_shipping_progress.data.reached, 7758 message: json.free_shipping_progress.message, 7759 success_message: json.free_shipping_progress.success_message 7760 }; 7761 freeShippingProgress.forEach(element => { 7762 element.insertAdjacentHTML('beforeend', mustache__WEBPACK_IMPORTED_MODULE_2__["default"].render(json.free_shipping_progress.template, view)); 7763 }); 7764 } else {} 7765 } 7766 } 7767 }); 7768 } 7769 7770 /** 7771 * Rafraichir les modes de paiement 7772 * @param options 7773 * @return {boolean} 7774 */ 7775 function refreshPaymentMode(options) { 7776 if (typeof options === 'undefined') { 7777 return false;
7778 } 7779 if (!options.hasOwnProperty('currencyIsoCode')) { 7780 return false; 7781 } 7782 if (!options.hasOwnProperty('amountProductDefaultCurrency')) { 7783 return false; 7784 } 7785 var countryBilling = $('[name=pays]').val(), 7786 isoCodeCountryBilling = $('[name=pays] option[value="' + countryBilling + '"]').attr('data-iso-code'), 7787 countryDelivery = countryBilling, 7788 isoCodeCountryDelivery = isoCodeCountryBilling; 7789 if ($('[name=address_billing_same_delivery]:checked').val() == 0) { 7790 countryDelivery = $('[name=pays_livraison]').val(); 7791 isoCodeCountryDelivery = $('[name=pays_livraison] option[value="' + countryDelivery + '"]').attr('data-iso-code'); 7792 } 7793 var $paymentModeCheckbox = $('[name="moyenspaiements"]'); 7794 if ($paymentModeCheckbox.length) { 7795 $paymentModeCheckbox.each(function (index, checkbox) { 7796 var $checkbox = $(checkbox), 7797 $itemCheckbox = $checkbox.closest('li'), 7798 minAmount = $checkbox.attr('data-min-amount'), 7799 maxAmount = $checkbox.attr('data-max-amount'), 7800 countryAvailable = null; 7801 if (typeof $checkbox.attr('data-country-available') !== 'undefined') { 7802 countryAvailable = JSON.parse($checkbox.attr('data-country-available')); 7803 } 7804 switch ($checkbox.val()) { 7805 case 'alma2': 7806 case 'alma3': 7807 case 'alma4': 7808 if (options.currencyIsoCode === 'EUR') { 7809 if (typeof minAmount !== 'undefined' && typeof maxAmount !== "undefined") { 7810 if (minAmount <= options.amountProductDefaultCurrency && options.amountProductDefaultCurrency <= maxAmount) { 7811 $itemCheckbox.removeClass('hide'); 7812 } else { 7813 $itemCheckbox.addClass('hide'); 7814 } 7815 } 7816 } else { 7817 $itemCheckbox.addClass('hide'); 7818 } 7819 break; 7820 case 'stripe-afterpay': 7821 if (countryAvailable !== null && countryAvailable.includes(isoCodeCountryBilling)) { 7822 if (typeof minAmount !== 'undefined' && typeof maxAmount !== "undefined") { 7823 if (minAmount <= options.amountProductDefaultCurrency && options.amountProductDefaultCurrency <= maxAmount) { 7824 $itemCheckbox.removeClass('hide'); 7825 } else { 7826 $itemCheckbox.addClass('hide'); 7827 } 7828 } 7829 } else { 7830 $itemCheckbox.addClass('hide'); 7831 } 7832 break; 7833 default: 7834 if (typeof minAmount !== 'undefined' && typeof maxAmount !== "undefined") { 7835 if (minAmount <= options.amountProductDefaultCurrency && options.amountProductDefaultCurrency <= maxAmount) { 7836 $itemCheckbox.removeClass('hide'); 7837 } else { 7838 $itemCheckbox.addClass('hide'); 7839 } 7840 } 7841 } 7842 }); 7843 } 7844 } 7845 $body.on('click', '#resume .up-quantity-booking-service,#resume .down-quantity-booking-service', function () { 7846 var $self = $(this), 7847 sign = $self.attr('data-sign'), 7848 key = $self.attr('data-key'); 7849 $('.resume-cart-products.table').waitMe(); 7850 $.ajax({ 7851 type: 'POST', 7852 url: '/ajax/minisite/panier/add_booking_quantity.php', 7853 dataType: 'json', 7854 data: { 7855 key: key, 7856 sign: sign, 7857 quantity: '1' 7858 }, 7859 success: function (response) { 7860 setTimeout(function () { 7861 $('.resume-cart-products.table').waitMe('hide'); 7862 }, 500); 7863 switch (true) { 7864 case response.hasOwnProperty('status') && response.status === 'reload': 7865 location.reload(); 7866 break; 7867 case response.hasOwnProperty('status') && response.status === 'error': 7868 break; 7869 case response.hasOwnProperty('status') && response.status === 'success': 7870 reloadResumeAndPaymentCartAjax(); 7871 reloadBlockReductionCode(); 7872 calculatePrice(); 7873 $('#panier').trigger('reload'); 7874 break; 7875 } 7876 } 7877 }); 7878 }); 7879 function debounce(func, wait, immediate) { 7880 var timeout; 7881 return function () { 7882 var context = this, 7883 args = arguments; 7884 var later = function () { 7885 timeout = null;
7886 if (!immediate) func.apply(context, args); 7887 }; 7888 var callNow = immediate && !timeout; 7889 clearTimeout(timeout); 7890 timeout = setTimeout(later, wait); 7891 if (callNow) func.apply(context, args); 7892 }; 7893 } 7894 ; 7895 var $lastInputQuantity = null; 7896 var debounceResumeUpdateQtyCart = debounce(function updateQtyCart(val, el) { 7897 var prefix = "#resume "; 7898 var $el = $(el), 7899 id = $el.attr('name'), 7900 key = $el.attr('data-key'), 7901 productType = $el.attr('data-product-type'); 7902 var exp = new RegExp("^[0-9]+$"); 7903 var $input = $(prefix + 'input[name=' + id + ']'); 7904 $lastInputQuantity = $input; 7905 if (val !== '') { 7906 if (exp.test(val) === true) { 7907 var hidden = $(prefix + 'input[name=' + id + '_hidden]').val(), 7908 input = $input.val(); 7909 var QtyToUp = parseInt(input) - parseInt(hidden); 7910 if (QtyToUp !== 0) { 7911 if (productType === 'booking') { 7912 changeQuantityProductBookingByKey(key, QtyToUp); 7913 } else { 7914 changeQuantityProductByKey(key, QtyToUp); 7915 } 7916 } 7917 } else { 7918 $input.val($(prefix + 'input[name=' + id + '_hidden]').val()); 7919 } 7920 } 7921 }, 850); 7922 $body.on('reloadResumeAndPaymentCart', function () { 7923 if ($lastInputQuantity !== null) { 7924 var elem = $('#resume [name="' + $lastInputQuantity.attr('name') + '"]')[0], 7925 caretPos = 99; 7926 if (elem) { 7927 if (typeof elem.createTextRange !== 'undefined') { 7928 var range = elem.createTextRange(); 7929 range.move('character', caretPos); 7930 range.select(); 7931 } else { 7932 if (typeof elem.selectionStart !== 'undefined') elem.selectionStart = caretPos; 7933 elem.focus(); 7934 } 7935 } 7936 $lastInputQuantity = null; 7937 } 7938 }).on('keydown paste cut input', '#resume .resume_quantity_input', function () { 7939 var $self = $(this); 7940 debounceResumeUpdateQtyCart($self.val(), $self); 7941 }); 7942 $body.on('click', '#resume .up-quantity', function () { 7943 var self = $(this), 7944 key = $(self).attr('data-key'); 7945 changeQuantityProductByKey(key, +1); 7946 }); 7947 $body.on('click', '#resume .down-quantity', function () { 7948 var self = $(this), 7949 key = $(self).attr('data-key'); 7950 if (parseInt($('#resume .label-quantity').text()) < 1) { 7951 deleteProductByKey(key); 7952 } else { 7953 changeQuantityProductByKey(key, -1); 7954 } 7955 }); 7956 $body.on('click', '#resume .remove-product', function () { 7957 var self = $(this), 7958 key = $(self).attr('data-key'); 7959 deleteProductByKey(key); 7960 }); 7961 $body.on('touchstart click', '#resume #submit_remove_reduc_code', function () { 7962 $.ajax({ 7963 type: "POST", 7964 url: "/ajax/minisite/panier/remove_discount_code.php", 7965 dataType: 'json', 7966 success: function (json) { 7967 $('#code_reduc').removeAttr('disabled'); 7968 $("#code_reduc").val(''); 7969 $('#submit_reduc_code').show(); 7970 $('#submit_remove_reduc_code').hide(); 7971 $("#code_reponse").empty(); 7972 $("#code_reponse").removeAttr('style'); 7973 calculatePrice(); 7974 } 7975 }); 7976 }); 7977 var flag = false; 7978 $('.template-panier-1').css('display', 'none'); 7979 var $payment_mode = $('#paiementchoix [name="moyenspaiements"]'); 7980 if ($payment_mode.length === 1) { 7981 $payment_mode.prop('checked', true); 7982 $payment_mode.trigger('change'); 7983 } 7984 7985 /* Panier Responsive */ 7986 var responsive_livraison_status = false; 7987 $(window).on('load', function () { 7988 function generateResponsiveTable() { 7989 if ($(window).width() < 484) { 7990 if (!responsive_livraison_status) { 7991 var tables = $(document.getElementById('resume')).find('.resume-cart-products'); 7992 tables.each(function (t, table) { 7993 table = $(table); 7994 var line = table.find('.resume-cart-item'); 7995 var head = table.find('.resume-cart-legend .row'); 7996 head.children('.col').each(function (index, elem) { 7997 var text = $(elem).text(); 7998 line.each(function (i, tr) { 7999 var td = $(tr).children('.col').eq(index); 8000 if (text !== '') { 8001 td.html('<span class="panier-entete">
8001' + text + ': </span>' + td.html()); 8002 } 8003 }); 8004 }); 8005 }); 8006 responsive_livraison_status = true; 8007 } 8008 } else { 8009 $('span.panier-entete').remove(); 8010 responsive_livraison_status = false; 8011 } 8012 } 8013 generateResponsiveTable(); 8014 $(document.getElementById('resume')).on('isUpdate', function () { 8015 responsive_livraison_status = false; 8016 generateResponsiveTable(); 8017 }); 8018 $(window).resize(function () { 8019 generateResponsiveTable(); 8020 }); 8021 }); 8022 function getModalConfirmConvertPoints() { 8023 var $modalConfirmConvertPoints = $('#modal-confirm-convert-points'); 8024 if ($modalConfirmConvertPoints.length === 0) { 8025 $modalConfirmConvertPoints = $('<div />', { 8026 'class': 'modal fade', 8027 'id': 'modal-confirm-convert-points', 8028 'tabindex': '-1', 8029 'role': 'dialog' 8030 }).append($('<div />', { 8031 'class': 'modal-dialog', 8032 'role': 'document' 8033 }).append($('<div />', { 8034 'class': 'modal-content' 8035 }).append($('<div />', { 8036 'class': 'modal-header' 8037 }).append($('<button />', { 8038 'type': 'button', 8039 'class': 'close', 8040 'data-dismiss': 'modal', 8041 'aria-label': 'Close', 8042 'html': $('<span />', { 8043 'aria-hidden': 'true', 8044 'html': '×' 8045 }) 8046 })).append($('<h4 />', { 8047 'class': 'modal-title' 8048 }))).append($('<div />', { 8049 'class': 'modal-body' 8050 })))); 8051 $body.find('#main-conteneur').append($modalConfirmConvertPoints); 8052 } 8053 return $modalConfirmConvertPoints; 8054 } 8055 function getModalGiftProductFidelityPoints() { 8056 var $modalGiftProductFidelityPoints = $('#modal-gift-product-fidelity-points'); 8057 if ($modalGiftProductFidelityPoints.length === 0) { 8058 $modalGiftProductFidelityPoints = $('<div />', { 8059 'class': 'modal fade', 8060 'id': 'modal-gift-product-fidelity-points', 8061 'tabindex': '-1', 8062 'role': 'dialog' 8063 }).append($('<div />', { 8064 'class': 'modal-dialog', 8065 'role': 'document' 8066 }).append($('<div />', { 8067 'class': 'modal-content' 8068 }).append($('<form />', { 8069 'name': 'form-gift-product' 8070 }).append($('<div />', { 8071 'class': 'modal-header' 8072 }).append($('<button />', { 8073 'type': 'button', 8074 'class': 'close', 8075 'data-dismiss': 'modal', 8076 'aria-label': 'Close', 8077 'html': $('<span />', { 8078 'aria-hidden': 'true', 8079 'html': '×' 8080 }) 8081 })).append($('<h4 />', { 8082 'class': 'modal-title', 8083 'html': '' 8084 }))).append($('<div />', { 8085 'class': 'modal-body' 8086 }))))); 8087 $body.find('#main-conteneur').append($modalGiftProductFidelityPoints); 8088 } 8089 return $modalGiftProductFidelityPoints; 8090 } 8091 $body.on('click', '.convert-fidelity-points', function () { 8092 var $self = $(this), 8093 $container = $('.block-reduction'), 8094 $modalConfirmConvertPoints = getModalConfirmConvertPoints(); 8095 $.ajax({ 8096 url: "/ajax/minisite/fidelity/getNbPoints.php", 8097 type: "GET", 8098 dataType: "json", 8099 success: function (response) { 8100 $container.waitMe('hide'); 8101 if (response.hasOwnProperty('status')) { 8102 switch (true) { 8103 case response.status === 'reload': 8104 location.reload(); 8105 break; 8106 case response.status === 'error': 8107 alert(response.error); 8108 break; 8109 case response.status === 'success': 8110 $modalConfirmConvertPoints.find('.modal-title').html(_lang.get('Convertir vos') + ' ' + response.labelPoint + ' ' + _lang.get('en bon d\'achat')); 8111 var $modalConfirmConvertPointsBody = $modalConfirmConvertPoints.find('.modal-body'), 8112 information = _lang.get('Souhaitez-vous convertir vos {{points}} en bon d\'achat ?'); 8113 information = information.replace('{{points}}', response.nbPoints + ' ' + response.labelPoint); 8114 $modalConfirmConvertPointsBody.html(''); 8115 $modalConfirmConvertPointsBody.append($('<div />', { 8116 'class': 'modal__convert-points__information' 8117 }).html(information)); 8118 $modalConfirmConvertPointsBody.append($('<div />', { 8119 'class': 'modal__convert-points__btn' 8120 }).append($('<button />', { 8121 'type': 'button', 8122 'class': 'button confirm-convert-points', 8123 'html': _lang.get('Convertir vos') + ' ' + response.labelPoint 8124 }))); 8125 $modalConfirmConvertPoints.modal(); 8126 break; 8127 } 8128 } 8129 } 8130 }); 8131 }).on('click', '#modal-confirm-convert-points .confirm-convert-points', function () { 8132 var $container = getModalConfirmConvertPoints().find('.modal
8132-content'); 8133 $container.waitMe(); 8134 $.ajax({ 8135 url: "/ajax/minisite/fidelity/convertPoints.php", 8136 type: "GET", 8137 dataType: "json", 8138 success: function (response) { 8139 $container.waitMe('hide'); 8140 if (response.hasOwnProperty('status')) { 8141 switch (true) { 8142 case response.status === 'reload': 8143 location.reload(); 8144 break; 8145 case response.status === 'error': 8146 alert(response.error); 8147 break; 8148 case response.status === 'success': 8149 getModalConfirmConvertPoints().modal('hide'); 8150 setTimeout(function () { 8151 $.ajax({ 8152 type: "POST", 8153 url: "/ajax/minisite/panier/add_discount_code.php", 8154 dataType: 'json', 8155 data: { 8156 code_reduc: response.code 8157 }, 8158 success: function (response) { 8159 flag = false; 8160 setTimeout(function () { 8161 reloadBlockReductionCode(function () { 8162 if (response.reload_cart) { 8163 reloadResumeAndPaymentCart(response.resume_cart, response.payment_cart, response.gift_discount_advanced); 8164 } 8165 loadCarriers(); 8166 }); 8167 }, 0); 8168 } 8169 }); 8170 }, 0); 8171 break; 8172 } 8173 } 8174 } 8175 }); 8176 }).on('click', '.gitf-product-fidelity-points', function () { 8177 var $self = $(this), 8178 $container = $('.block-reduction'), 8179 $modalGiftProductFidelityPoints = getModalGiftProductFidelityPoints(); 8180 $container.waitMe(); 8181 $.ajax({ 8182 url: "/ajax/minisite/fidelity/getListGiftProducts.php", 8183 type: "GET", 8184 dataType: "json", 8185 success: function (response) { 8186 $container.waitMe('hide'); 8187 if (response.hasOwnProperty('status')) { 8188 switch (true) { 8189 case response.status === 'reload': 8190 location.reload(); 8191 break; 8192 case response.status === 'error': 8193 alert(response.error); 8194 break; 8195 case response.status === 'success': 8196 var $modalGiftProductFidelityPointsBody = $modalGiftProductFidelityPoints.find('.modal-body'); 8197 $modalGiftProductFidelityPoints.find('.modal-title').html(_lang.get('Choisissez votre cadeau (solde : {{nbPoints}})').replace('{{nbPoints}}', response.nbPoints + ' ' + response.labelPoint)); 8198 $modalGiftProductFidelityPointsBody.html(''); 8199 if (response.giftProducts.length === 0) {} else { 8200 var $contentGiftProducts = $('<div />', { 8201 'class': 'container-gift-products' 8202 }), 8203 information = _lang.get('Vous disposez de {{points}}.'); 8204 information = information.replace('{{points}}', response.nbPoints + ' ' + response.labelPoint); 8205 $.each(response.giftProducts, function (index, giftProduct) { 8206 var $radioId = $('<input />', { 8207 'type': 'radio', 8208 'id': 'gift_product_id_' + giftProduct.id, 8209 'name': 'giftProduct[id]', 8210 'value': giftProduct.id, 8211 'required': 'required' 8212 }); 8213 if (!giftProduct.available) { 8214 $radioId.prop('disabled', true); 8215 } 8216 $contentGiftProducts.append($('<div />', { 8217 'class': 'gift-product__item', 8218 'for': 'gift_product_id_' + giftProduct.id 8219 }).append($('<div />', { 8220 'class': 'gift-product__item__img' 8221 }).append($('<a />', { 8222 'target': '_blank', 8223 'href': giftProduct.link 8224 }).append($('<div />', { 8225 'class': 'product-img-square' 8226 }).append($('<span />', { 8227 'class': 'img-square' 8228 }).append($('<span />', { 8229 'class': 'img-square__content', 8230 'html': $('<img />', { 8231 'src': giftProduct.img 8232 }) 8233 })))))).append($('<div />', { 8234 'class': 'gift-product__item__title' 8235 }).append($('<div />', { 8236 'html': giftProduct.label 8237 })).append($('<div />', { 8238 'html': giftProduct.points 8239 })).append($('<div />', { 8240 'html': $('<button />', { 8241 'class': 'button', 8242 'name': 'giftProduct[btn]', 8243 'type': 'button', 8244 'value': giftProduct.id, 8245 'html': _lang.get('Choisir ce cadeau') 8246 }) 8247 })))); 8248 if (!giftProduct.available) { 8249 $contentGiftProducts.find('[name="giftProduct[btn]"][value="' + giftProduct.id + '"]').prop('disabled', true); 8250 } 8251 }); 8252 $modalGiftProductFidelityPointsBody.append($contentGiftProducts); 8253 8254 // $modalGiftProductFidelityPointsBody.append( 8255 // $('<div />', {'class': 'gift-product__btn'}) 8256 // .append($('<button />', {'type': 'submit', 'class': 'button', 'name': 'giftProduct[submit]', 'value': '1', 'html': _lang.get('Choisir votre cadeau')})) 8257 // ); 8258 } 8259 $modalGiftProductFidelityPoints.modal(); 8260 break; 8261 } 8262 } 8263 } 8264 }); 8265 }).on('click', '[name="giftProduct[btn]"]', function () { 8266 var $self = $(this), 8267 $form = $self.closest('.modal-body'); 8268 if ($self.is(':disabled')) { 8269 return false;
8270 } 8271 $form.waitMe(); 8272 $.ajax({ 8273 url: "/ajax/minisite/fidelity/giftProductPoints.php", 8274 type: "POST", 8275 data: { 8276 id: $self.val() 8277 }, 8278 dataType: "json", 8279 success: function (response) { 8280 $form.waitMe('hide'); 8281 if (response.hasOwnProperty('status')) { 8282 switch (true) { 8283 case response.status === 'reload': 8284 location.reload(); 8285 break; 8286 case response.status === 'error': 8287 alert(response.error); 8288 break; 8289 case response.status === 'success': 8290 getModalGiftProductFidelityPoints().modal('hide'); 8291 setTimeout(function () { 8292 $.ajax({ 8293 type: "POST", 8294 url: "/ajax/minisite/panier/add_discount_code.php", 8295 dataType: 'json', 8296 data: { 8297 code_reduc: response.code 8298 }, 8299 success: function (response) { 8300 flag = false; 8301 if (response.status === 'success') { 8302 reloadBlockReductionCode(function () { 8303 if (response.reload_cart) { 8304 reloadResumeAndPaymentCart(response.resume_cart, response.payment_cart, response.gift_discount_advanced); 8305 } 8306 loadCarriers(); 8307 }); 8308 } 8309 } 8310 }); 8311 }, 0); 8312 break; 8313 } 8314 } 8315 } 8316 }); 8317 return false; 8318 }).on('click', '[name=submit_code_reduc]', function () { 8319 var $block = $(this).closest('.block-reduction-code'); 8320 var code_reduc = $block.find('[name=code_reduc]'); 8321 if (!flag) { 8322 flag = true; 8323 var block_code_reduction_notification = $block.find(".block-code-reduction-notification"); 8324 block_code_reduction_notification.html(''); 8325 if (code_reduc.val() === "") { 8326 flag = false; 8327 block_code_reduction_notification.append($('<div />', { 8328 'class': 'alert alert-danger', 8329 'html': "Veuillez entrer un code !", 8330 'style': 'margin-top:10px;' 8331 })); 8332 } else { 8333 $.ajax({ 8334 type: "POST", 8335 url: "/ajax/minisite/panier/add_discount_code.php", 8336 dataType: 'json', 8337 data: { 8338 code_reduc: code_reduc.val() 8339 }, 8340 success: function (response) { 8341 flag = false; 8342 if (response.status === 'success') { 8343 reloadBlockReductionCode(function () { 8344 if (response.reload_cart) { 8345 reloadResumeAndPaymentCart(response.resume_cart, response.payment_cart, response.gift_discount_advanced); 8346 } 8347 loadCarriers(); 8348 }); 8349 } else { 8350 block_code_reduction_notification.append($('<div />', { 8351 'class': 'alert alert-danger', 8352 'html': response.msg, 8353 'style': 'margin-top:10px;' 8354 })); 8355 } 8356 } 8357 }); 8358 } 8359 } 8360 return false; 8361 }).on('click', '.add_code_reduc', function () { 8362 var self = $(this), 8363 id_code = self.attr('data-id'); 8364 if (!flag) { 8365 flag = true; 8366 var block_code_reduction_notification = $(".block-code-reduction-notification"); 8367 block_code_reduction_notification.html(''); 8368 $.ajax({ 8369 type: "POST", 8370 url: "/ajax/minisite/panier/add_discount_by_id_code.php", 8371 dataType: 'json', 8372 data: { 8373 id_code: id_code 8374 }, 8375 success: function (response) { 8376 flag = false; 8377 if (response.status == 'success') { 8378 if (response.reload_cart) { 8379 reloadResumeAndPaymentCart(response.resume_cart, response.payment_cart, response.gift_discount_advanced); 8380 } 8381 reloadBlockReductionCode(); 8382 loadCarriers(); 8383 } else { 8384 block_code_reduction_notification.append($('<div />', { 8385 'class': 'alert alert-danger', 8386 'html': response.msg, 8387 'style': 'margin-top:10px;' 8388 })); 8389 } 8390 } 8391 }); 8392 } 8393 }).on('click', '.remove_code_reduc', function () { 8394 var self = $(this), 8395 id_code = self.attr('data-id'); 8396 if (!flag) { 8397 flag = true; 8398 var block_code_reduction_notification = $(".block-code-reduction-notification"); 8399 block_code_reduction_notification.html(''); 8400 $.ajax({ 8401 type: "POST", 8402 url: "/ajax/minisite/panier/remove_discount_by_id_code.php", 8403 dataType: 'json', 8404 data: { 8405 id_code: id_code 8406 }, 8407 success: function (response) { 8408 flag = false;
8409 if (response.status == 'success') { 8410 if (response.reload_cart) { 8411 reloadResumeAndPaymentCart(response.resume_cart, response.payment_cart, response.gift_discount_advanced); 8412 } 8413 reloadBlockReductionCode(function () { 8414 var block_code_reduction_notification = $(".block-code-reduction-notification"); 8415 var alert = $('<div />', { 8416 'class': 'alert alert-success', 8417 'html': response.msg, 8418 'style': 'margin-top:10px;' 8419 }); 8420 block_code_reduction_notification.append(alert); 8421 setTimeout(function () { 8422 alert.remove(); 8423 }, 4000); 8424 }); 8425 loadCarriers(); 8426 } else { 8427 block_code_reduction_notification.append($('<div />', { 8428 'class': 'alert alert-danger', 8429 'html': response.msg, 8430 'style': 'margin-top:10px;' 8431 })); 8432 } 8433 } 8434 }); 8435 } 8436 }); 8437 function reloadResumeAndPaymentCartAjax() { 8438 $.ajax({ 8439 type: "POST", 8440 url: "/ajax/minisite/panier/reload_block_resume_payment_cart.php", 8441 dataType: 'json', 8442 success: function (response) { 8443 if (response.status == 'success') { 8444 if (response.tracking_cart) { 8445 window.CmonSiteTrackingCart = response.tracking_cart; 8446 } 8447 reloadResumeAndPaymentCart(response.resume_cart, response.payment_cart, response.gift_discount_advanced); 8448 } 8449 } 8450 }); 8451 } 8452 var panier = $(document.getElementById('panier')), 8453 isFirstUpdate = true; 8454 panier.on('isUpdate', function () { 8455 if (!isFirstUpdate) { 8456 reloadBlockReductionCode(); 8457 reloadResumeAndPaymentCartAjax(); 8458 loadCarriers(); 8459 } 8460 isFirstUpdate = false; 8461 }); 8462 function reloadResumeAndPaymentCart(resume_cart, payment_cart, gift_discount_advanced) { 8463 var $block_resume_cart = $('.block-resume-cart'); 8464 var $block_payment_cart = $('.block-payment-cart'); 8465 $block_resume_cart.html(resume_cart); 8466 $block_payment_cart.html(payment_cart); 8467 if ($('.block-resume-cart .resume-cart-item').length == 0) { 8468 location.reload(); 8469 } 8470 if (typeof gift_discount_advanced !== 'undefined' && gift_discount_advanced !== lastGiftDiscountHtml) { 8471 lastGiftDiscountHtml = gift_discount_advanced; 8472 8473 // Le slider doit être détruit tant que son DOM est encore attaché, et sa 8474 // position relue pour la restaurer après le nouveau rendu du serveur. 8475 var giftDiscountIndex = destroyGiftDiscountSwiper(); 8476 $('.gift-discount-advanced').html(gift_discount_advanced); 8477 loadGiftDiscountSwiper(giftDiscountIndex); 8478 } 8479 $body.trigger('reloadResumeAndPaymentCart'); 8480 } 8481 function reloadBlockReductionCode(callback) { 8482 if (typeof callback == 'undefined') { 8483 callback = function () {}; 8484 } 8485 $.ajax({ 8486 type: "POST", 8487 url: "/ajax/minisite/panier/reload_block_reduction_code.php", 8488 dataType: 'json', 8489 success: function (response) { 8490 if (response.status === 'success') { 8491 $('.block-reduction').html(response.html); 8492 callback(); 8493 } 8494 } 8495 }); 8496 } 8497 function validFormAddress() { 8498 $('.form-group').removeClass('error'); 8499 var fieldAddressBilling = ['nom', 'prenom', 'tel', 'adresse', 'cp', 'ville', 'pays'], 8500 fieldAddressDelivery = ['nom_livraison', 'prenom_livraison', 'tel_livraison', 'adresse_livraison', 'email_livraison', 'cp_livraison', 'ville_livraison', 'pays_livraison'], 8501 fieldAddressBillingError = [], 8502 fieldAddressDeliveryError = []; 8503 $.each(fieldAddressBilling, function (index, value) { 8504 if ($('[name=' + value + ']').validationEngine('validate')) { 8505 fieldAddressBillingError.push(value); 8506 } 8507 }); 8508 if ($('[name=address_billing_same_delivery]:checked').val() == 0) { 8509 $.each(fieldAddressDelivery, function (index, value) { 8510 if ($('[name=' + value + ']').validationEngine('validate')) { 8511 fieldAddressDeliveryError.push(value); 8512 } 8513 }); 8514 } 8515 if (fieldAddressBillingError.length == 0 && fieldAddressDeliveryError.length == 0) { 8516 return true; 8517 } 8518 $.each(fieldAddressBillingError, function (index, value) { 8519 $('[name=' + value + ']').parents('.form-group').addClass('error'); 8520 }); 8521 $.each(fieldAddressDeliveryError, function (index, value) { 8522 $('[name=' + value + ']').parents('.form-group').addClass('error'); 8523 }); 8524 var $firstBlockError = $('.cart-step-2').find('.form-group.error').first(); 8525 if ($firstBlockError.length > 0) { 8526 $('html, body').animate({ 8527 scrollTop: $firstBlockError.offset().top - 150 8528 }, 500); 8529 } 8530 return false;
8531 } 8532 function changeSideBar(href) { 8533 if ($(href).length > 0) { 8534 $('.contents-tabs .content-tab').removeClass('active'); 8535 $(href).addClass('active'); 8536 $('.side-tabs .element-sidebar, .side-tabs li').removeClass('active', 'step-done'); 8537 $('.element-sidebar[href="' + href + '"]').addClass('active').closest('li').addClass('active').prevAll('li').addClass('step-done'); 8538 $('html,body').animate({ 8539 scrollTop: $(href).offset().top 8540 }, vitesse_scroll, function () { 8541 if (history.pushState) { 8542 history.pushState(null, null, href); 8543 } else { 8544 location.hash = href; 8545 } 8546 }); 8547 return false; 8548 } 8549 return false; 8550 } 8551 function saveAddr(callback) { 8552 cart_step_2.waitMe(); 8553 $.ajax({ 8554 type: "POST", 8555 url: "/ajax/minisite/panier/save_addr.php", 8556 data: { 8557 'order_as_guest': $('.cart-step-2 [name="order_as_quest"]').length ? $('.cart-step-2 [name="order_as_quest"]').val() : 0, 8558 'birthday': $('.cart-step-2 #birthday').val(), 8559 'address_rgpd_checkbox': $('.cart-step-2 [name="address_rgpd_checkbox"]').is(':checked') ? 1 : null, 8560 'address_billing_same_delivery': $('.cart-step-2 [name="address_billing_same_delivery"]:checked').val(), 8561 'billing_address': { 8562 'billing_nom': $('.cart-step-2 #nom').val(), 8563 'billing_prenom': $('.cart-step-2 #prenom').val(), 8564 'billing_telephone': $('.cart-step-2 #tel').val(), 8565 'billing_adresse': $('.cart-step-2 #adresse').val(), 8566 'billing_code_postal': $('.cart-step-2 #cp').val(), 8567 'billing_ville': $('.cart-step-2 #ville').val(), 8568 'billing_pays': $('.cart-step-2 [name="pays"]').val(), 8569 'billing_commentaire': $('.cart-step-2 #commentaires').val() 8570 }, 8571 'delivery_address': { 8572 'delivery_nom': $('.cart-step-2 #nom_livraison').val(), 8573 'delivery_societe': $('.cart-step-2 #societe_livraison').val(), 8574 'delivery_prenom': $('.cart-step-2 #prenom_livraison').val(), 8575 'delivery_telephone': $('.cart-step-2 #tel_livraison').val(), 8576 'delivery_adresse': $('.cart-step-2 #adresse_livraison').val(), 8577 'delivery_code_postal': $('.cart-step-2 #cp_livraison').val(), 8578 'delivery_ville': $('.cart-step-2 #ville_livraison').val(), 8579 'delivery_pays': $('.cart-step-2 [name="pays_livraison"]').val(), 8580 'delivery_commentaire': $('.cart-step-2 #commentaires_livraison').val() 8581 } 8582 }, 8583 dataType: 'json', 8584 success: function (json) { 8585 if (json.hasOwnProperty('reload')) { 8586 location.reload(); 8587 } 8588 var $addressNotification = $('.address-notification'); 8589 $addressNotification.html(''); 8590 switch (true) { 8591 case json.hasOwnProperty('reload'): 8592 location.reload(); 8593 break; 8594 case json.hasOwnProperty('error'): 8595 cart_step_2.waitMe('hide'); 8596 $addressNotification.html($('<div />', { 8597 'class': 'alert alert-danger', 8598 'html': json.error 8599 })); 8600 $('html, body').animate({ 8601 scrollTop: $addressNotification.offset().top - 150 8602 }, 500); 8603 break; 8604 case json.hasOwnProperty('status') && json.status === 'success': 8605 if (json.hasOwnProperty('billing_pays')) { 8606 $('.cart-step-2 [name="pays"]').val(json.billing_pays); 8607 } 8608 if (json.hasOwnProperty('delivery_pays')) { 8609 $('.cart-step-2 [name="pays_livraison"]').val(json.delivery_pays); 8610 } 8611 cart_step_2.waitMe('hide'); 8612 if (typeof callback === 'function') { 8613 callback(); 8614 } 8615 reloadResumeAndPaymentCartAjax(); 8616 break; 8617 } 8618 } 8619 }); 8620 } 8621 $body.on('change', '.form-option-price', function () { 8622 calculOptions(); 8623 }); 8624 $body.on('click', '.payment_item__payment-token-remove', function () { 8625 var $self = $(this), 8626 $item = $self.closest('.payment_item'); 8627 var $modalConfirmPaymentTokenRemove = getModalConfirmPaymentTokenRemove(); 8628 $modalConfirmPaymentTokenRemove.find('[name="id_payment_token_remove"]').val($self.attr('data-token')); 8629 $modalConfirmPaymentTokenRemove.modal(); 8630 }).on('submit', '[name="form-payment-token-remove"]', function (event) { 8631 event.preventDefault(); 8632 var $form = $(this), 8633 token = $form.find('[name="id_payment_token_remove"]').val(); 8634 $.ajax({ 8635 type: "POST", 8636 url: "/ajax/minisite/payment_token/remove.php", 8637 data: { 8638 'token': $form.find('[name="id_payment_token_remove"]').val(), 8639 'page': 'order' 8640 }, 8641 dataType: 'json', 8642 success: function (json) { 8643 switch (true) { 8644 case json.status === 'reload': 8645 location.reload(); 8646 break; 8647 case json.status === 'redirect': 8648 location.href = json.redirect; 8649 break; 8650 case json.status === 'success': 8651 $('#paiementchoix .payment_item .payment_item__payment-token-remove[data-token="' + token + '"]').closest('.line_payment').remove(); 8652 $form.waitMe('hide'); 8653 var $modalConfirmPaymentTokenRemove = getModalConfirmPaymentTokenRemove(); 8654 $modalConfirmPaymentTokenRemove.modal('hide'); 8655 break; 8656 } 8657 } 8658 }); 8659 }); 8660 function getModalConfirmPaymentTokenRemove() {
8661 var $modalConfirmPaymentTokenRemove = $('#modal-confirm-payment-token-remove'); 8662 if ($modalConfirmPaymentTokenRemove.length === 0) { 8663 $modalConfirmPaymentTokenRemove = $('<div />', { 8664 'class': 'modal fade', 8665 'id': 'modal-confirm-payment-token-remove', 8666 'tabindex': '-1', 8667 'role': 'dialog' 8668 }).append($('<div />', { 8669 'class': 'modal-dialog', 8670 'role': 'document' 8671 }).append($('<div />', { 8672 'class': 'modal-content' 8673 }).append($('<div />', { 8674 'class': 'modal-header' 8675 }).append($('<button />', { 8676 'type': 'button', 8677 'class': 'close', 8678 'data-dismiss': 'modal', 8679 'aria-label': 'Close', 8680 'html': $('<span />', { 8681 'aria-hidden': 'true', 8682 'html': '×' 8683 }) 8684 })).append($('<h4 />', { 8685 'class': 'modal-title', 8686 'html': _lang.get('Supprimer mes informations de paiement') 8687 }))).append($('<div />', { 8688 'class': 'modal-body' 8689 }).append($('<form />', { 8690 'method': 'post', 8691 'name': 'form-payment-token-remove' 8692 }).append($('<input />', { 8693 'type': 'hidden', 8694 'name': 'id_payment_token_remove', 8695 'value': '' 8696 })).append($('<div />', { 8697 'class': 'text-center', 8698 'html': _lang.get('Souhaitez-vous supprimer ces informations de paiement ?') 8699 })).append($('<div />', { 8700 'class': 'text-center' 8701 }).append($('<button />', { 8702 'name': 'submit_form', 8703 'value': 1, 8704 'class': 'button', 8705 'html': _lang.get('Supprimer') 8706 }))))))); 8707 $body.find('#main-conteneur').append($modalConfirmPaymentTokenRemove); 8708 } 8709 return $modalConfirmPaymentTokenRemove; 8710 } 8711 function calculOptions() { 8712 var checkbox = $('[type="checkbox"].form-option-price:checked'), 8713 /* Selectioner les checkbox */ 8714 select = $('select.form-option-price'), 8715 /* Selectioner les select */ 8716 radio = $('[type="radio"].form-option-price:checked'), 8717 price = 0, 8718 price_currency = 0; 8719 /* Selectioner les radio */ 8720 8721 $.each(checkbox, function (index, value) { 8722 var $value = $(value), 8723 attr = $value.attr('data-price'), 8724 price_value, 8725 attr_currency = $value.attr('data-price-convert'), 8726 price_value_currency; 8727 if (typeof attr !== typeof undefined && attr !== false) { 8728 price_value = attr; 8729 price_value = parseFloat(price_value) || 0.00; 8730 price_value_currency = attr_currency; 8731 price_value_currency = parseFloat(price_value_currency) || 0.00; 8732 if (price_value > 0) { 8733 price += price_value; 8734 } 8735 if (price_value_currency > 0) { 8736 price_currency += price_value_currency; 8737 } 8738 } 8739 }); 8740 $.each(radio, function (index, value) { 8741 var $value = $(value), 8742 attr = $value.attr('data-price'), 8743 price_value, 8744 attr_currency = $value.attr('data-price-convert'), 8745 price_value_currency; 8746 if (typeof attr !== typeof undefined && attr !== false) { 8747 price_value = attr; 8748 price_value = parseFloat(price_value) || 0.00; 8749 price_value_currency = attr_currency; 8750 price_value_currency = parseFloat(price_value_currency) || 0.00; 8751 if (price_value > 0) { 8752 price += price_value; 8753 } 8754 if (price_value_currency > 0) { 8755 price_currency += price_value_currency; 8756 } 8757 } 8758 }); 8759 $.each(select, function (index, value) { 8760 var $value = $(value), 8761 price_value, 8762 price_value_currency; 8763 if ($value.val() > 0) { 8764 var $opt = $value.find('option[value="' + $value.val() + '"]'), 8765 attr = $opt.attr('data-price'), 8766 attr_currency = $opt.attr('data-price-convert'); 8767 if ($opt.length == 1 && typeof attr !== typeof undefined && attr !== false) { 8768 price_value = attr; 8769 price_value = parseFloat(price_value) || 0.00; 8770 price_value_currency = attr_currency; 8771 price_value_currency = parseFloat(price_value_currency) || 0.00; 8772 if (price_value > 0) { 8773 price += price_value; 8774 } 8775 if (price_value_currency > 0) { 8776 price_currency += price_value_currency; 8777 } 8778 } 8779 } 8780 }); 8781 options_price = price; 8782 options_price_currency = price_currency; 8783 calculatePrice(); 8784 } 8785}); 8786}(); 8787/******/ })() 8788; 8789//# sourceMappingURL=../paniercommande.js.map
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.