1window.getCodeMirrorTheme = function getCodeMirrorTheme() { 2 let theme = jQuery(document.documentElement).attr("data-bs-theme"); 3 return theme === "dark" ? "ayu-dark" : "xq-light"; 4}; 5 6// Pulisce l'HTML incollato (Word/LibreOffice/browser) appiattendolo in una 7// sequenza PIATTA di blocchi validi: <p>, <h1>-<h6>, <ul>/<ol>. I <div> sono 8// solo contenitori (li attraversiamo senza emettere tag: altrimenti div 9// annidati â <p> annidati = HTML malformato), il contenuto inline viene 10// raccolto e avvolto in <p>. Dando a SunEditor solo blocchi già formati si 11// evita anche che lui auto-wrappi l'inline "nudo" aggiungendo un <br> spurio. 12function cleanOdtHtml(htmlString) { 13 const parser = new DOMParser(); 14 const doc = parser.parseFromString(htmlString, 'text/html'); 15 16 const blocks = []; // sequenza piatta di blocchi finiti 17 let inlineBuf = ''; // contenuto inline in attesa di essere avvolto in <p> 18 19 function esc(t) { 20 return t.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); 21 } 22 23 function wrap(e, b, it, u, s) { 24 if (s) e = '<s>' + e + '</s>'; 25 if (u) e = '<u>' + e + '</u>'; 26 if (it) e = '<i>' + e + '</i>'; 27 if (b) e = '<b>' + e + '</b>'; 28 return e; 29 } 30 31 function styleFlags(node, b, it, u, s) { 32 const tag = node.tagName.toLowerCase(); 33 const style = node.getAttribute('style') || ''; 34 if (tag === 'b' || tag === 'strong') b = true; 35 if (tag === 'i' || tag === 'em') it = true; 36 if (tag === 'u') u = true; 37 if (tag === 's' || tag === 'del' || tag === 'strike') s = true; 38 if (/font-weight\s*:\s*(bold|700)/i.test(style)) b = true; 39 if (/font-weight\s*:\s*normal/i.test(style)) b = false; 40 if (/font-style\s*:\s*italic/i.test(style)) it = true; 41 if (/font-style\s*:\s*normal/i.test(style)) it = false; 42 if (/text-decoration\s*:[^;]*underline/i.test(style)) u = true; 43 if (/text-decoration\s*:[^;]*line-through/i.test(style)) s = true; 44 return [b, it, u, s]; 45 } 46 47 // Rende il contenuto INLINE di un nodo (testo, <span>, <b>, <i>, <a>, <br>...). 48 function inlineOf(node, b, it, u, s) { 49 if (node.nodeType === 3) return wrap(esc(node.textContent), b, it, u, s); 50 if (node.nodeType !== 1) return ''; 51 const tag = node.tagName.toLowerCase(); 52 if (tag === 'br') return '<br>'; 53 [b, it, u, s] = styleFlags(node, b, it, u, s); 54 if (tag === 'a') { 55 const href = node.getAttribute('href') || '#'; 56 return '<a href="' + esc(href) + '">' + childrenInline(node, b, it, u, s) + '</a>'; 57 } 58 return childrenInline(node, b, it, u, s); // span/font/altro inline: trasparente 59 } 60 61 function childrenInline(node, b, it, u, s) { 62 let r = ''; 63 for (const child of node.childNodes) r += inlineOf(child, b, it, u, s); 64 return r; 65 } 66 67 // Contenuto di un <li>: inline + eventuali liste annidate (mantenute valide). 68 function liContent(li) { 69 let inline = '', nested = ''; 70 for (const child of li.childNodes) { 71 const t = child.nodeType === 1 ? child.tagName.toLowerCase() : ''; 72 if (t === 'ul' || t === 'ol') nested += listHtml(child); 73 else inline += inlineOf(child, false, false, false, false); 74 } 75 return inline + nested; 76 } 77 78 function listHtml(node) { 79 const tag = node.tagName.toLowerCase(); 80 let lis = ''; 81 for (const li of node.childNodes) { 82 if (li.nodeType === 1 && li.tagName.toLowerCase() === 'li') { 83 lis += '<li>' + liContent(li) + '</li>'; 84 } 85 } 86 return lis ? '<' + tag + '>' + lis + '</' + tag + '>' : ''; 87 } 88 89 function flushInline() { 90 const inner = inlineBuf.replace(/^(?:\s|<br>)+/, '').replace(/(?:\s|<br>)+$/, ''); 91 inlineBuf = ''; 92 if (inner) blocks.push('<p>' + inner + '</p>'); 93 } 94 95 // Processa un nodo in CONTESTO BLOCCO (corpo del documento o dentro un <div>). 96 function processBlock(node) { 97 if (node.nodeType === 3) { inlineBuf += esc(node.textContent); return; } 98 if (node.nodeType !== 1) return; 99 const tag = node.tagName.toLowerCase(); 100 101 if (tag === 'div') { // contenitore trasparente: ricorri senza emettere tag 102 for (const child of node.childNodes) processBlock(child); 103 return; 104 } 105 if (tag === 'p' || /^h[1-6]$/.test(tag)) { 106 flushInline(); 107 blocks.push('<' + tag + '>' + childrenInline(node, false, false, false, false) + '</' + tag + '>'); 108 return; 109 } 110 if (tag === 'ul' || tag === 'ol') { 111 flushInline(); 112 const h = listHtml(node); 113 if (h) blocks.push(h); 114 return; 115 } 116 inlineBuf += inlineOf(node, false, false, false, false); // span/font/b/a/testo â inline 117 } 118 119 for (const child of doc.body.childNodes) processBlock(child); 120 flushInline(); 121 122 return blocks.join('') 123 .replace(/<\/b><b>/g, '').replace(/<\/i><i>/g, '') 124 .replace(/<\/u><u>/g, '').replace(/<\/s><s>/g, ''); 125} 126 127function createHtmlarea(htmlarea) { 128 let defaultPlugins = [ 129 ["undo", "redo"], 130 ["formatBlock", "bold", "underline", "italic", "strike"], 131 ["align", "list", "table", "link"], 132 ["removeFormat", "codeView", "showBlocks"], 133 ]; 134 135 let element = jQuery( 136 "#" + htmlarea.replaceAll("[", "\\[").replaceAll("]", "\\]") 137 ); 138 let valueElement = jQuery('[name="' + htmlarea + '"]'); 139 let plugins = element.attr("plugins"); 140 buttonList = plugins != "" ? JSON.parse(plugins) : defaultPlugins; 141 142 let lang = jQuery("html").attr("lang"); 143 144 let htmlareaObject = SUNEDITOR.create(htmlarea, { 145 buttonList: buttonList, 146 lang: SUNEDITOR_LANG[lang], 147 height: "30vh", 148 minHeight: "300px", 149 width: "100%", 150 linkProtocol: "/", 151 codeMirror: { 152 src: CodeMirror, 153 options: { 154 mode: "htmlmixed", 155 lineNumbers: true,
156 theme: getCodeMirrorTheme(), // Usa la funzione per ottenere il tema 157 }, 158 }, 159 }); 160 161 if (!window.SUNEDITOR_INSTANCES) { 162 window.SUNEDITOR_INSTANCES = {}; 163 } 164 165 window.SUNEDITOR_INSTANCES[htmlarea] = htmlareaObject; 166 167 const wysiwygEl = htmlareaObject.core.context.element.wysiwyg; 168 169 if (wysiwygEl) { 170 wysiwygEl.addEventListener('paste', function(e) { 171 const html = e.clipboardData.getData('text/html'); 172 if (!html) return; 173 e.stopImmediatePropagation(); 174 e.preventDefault(); 175 htmlareaObject.insertHTML(cleanOdtHtml(html), true, false); 176 }, true); 177 } 178 179 let whitelist = htmlareaObject.util.createTagsWhitelist( 180 "a|b|blockquote|br|caption|cite|code|del|dt|em|h1|h2|h3|h4|h5|h6|hr|i|li|ol|p|pre|strong|sub|sup|table|tbody|td|tfoot|th|thead|tr|u|ul" 181 ); 182 let blacklist = null; 183 184 element.closest("form").on("submit", function () { 185 if (htmlareaObject.core._variable.isCodeView) { 186 htmlareaObject.core.toggleCodeView(); 187 } 188 let content = htmlareaObject.getContents(); 189 content = htmlareaObject.core.cleanHTML(content, whitelist, blacklist); 190 valueElement.val(content.replace(/<p>\s?<br>\s?<\/p>/g, "")); 191 }); 192} 193 194// ok 195function bindActions() { 196 let elements = jQuery("[action-method]").not("[js-bind]"); 197 elements.each(function (index, element) { 198 let actionMethod = jQuery(element).attr("action-method"); 199 let actionUrl = jQuery(element).attr("action-url"); 200 let actionConfirm = jQuery(element).attr("action-confirm"); 201 202 let ajaxCommand = jQuery(element).attr("ajax-command"); 203 204 if (ajaxCommand !== undefined) { 205 bindIfNecessary(element, "click", function () { 206 let ajaxParams = { 207 url: actionUrl, 208 success: function (response) { 209 let command = ajaxCommand.replaceAll("<AJR>", "response"); 210 eval(command); 211 bindActions(); 212 }, 213 }; 214 215 if (actionMethod == "location") { 216 ajaxParams.type = "get"; 217 } else { 218 ajaxParams.type = actionMethod; 219 220 let form = jQuery(element).closest("form"); 221 222 let serializedFormParams = null; 223 if (form.length > 0) { 224 serializedFormParams = form.serialize(); 225 if (serializedFormParams != null) { 226 ajaxParams.data = serializedFormParams; 227 } 228 } 229 } 230 231 if (actionConfirm != undefined) { 232 if (confirm(actionConfirm)) { 233 jQuery.ajax(ajaxParams); 234 } 235 } else { 236 jQuery.ajax(ajaxParams); 237 } 238 }); 239 } else { 240 if (actionMethod == "location") { 241 if (actionConfirm != undefined) { 242 bindIfNecessary(element, "click", function () { 243 if (confirm(actionConfirm)) { 244 window.location = actionUrl; 245 } 246 }); 247 } else { 248 bindIfNecessary(element, "click", function () { 249 window.location = actionUrl; 250 }); 251 } 252 } else if (actionMethod == "post" || actionMethod == "get") { 253 let form = jQuery(element).closest("form"); 254 if (form.length == 0) { 255 form = jQuery("<form onthefly>"); 256 } 257 if (actionConfirm != undefined) { 258 bindIfNecessary(element, "click", function () { 259 if (confirm(actionConfirm)) { 260 form.attr("method", actionMethod); 261 form.attr("action", actionUrl); 262 if (form.attr("onthefly") !== undefined) { 263 form.appendTo("body"); 264 } 265 form.submit(); 266 } 267 }); 268 } else { 269 bindIfNecessary(element, "click", function (e) { 270 e.target.disabled = true; 271 form.attr("method", actionMethod); 272 form.attr("action", actionUrl); 273 if (form.attr("onthefly") !== undefined) { 274 form.appendTo("body"); 275 } 276 form.submit(); 277 }); 278 } 279 } 280 } 281 }); 282 283 // previene l'invio di form alla pressione di Enter in un campo di testo 284 jQuery("form").each(function (i, formElement) { 285 let acceptFieldEnterKeyButton = jQuery(formElement).find( 286 "button[submit-on-enter]" 287 ); 288 jQuery(formElement) 289 .find("input") 290 .each(function (j, inputElement) { 291 if (acceptFieldEnterKeyButton.length > 0) { 292 jQuery(inputElement).on("keydown", function (event) { 293 if (event.originalEvent.key == "Enter") { 294 event.preventDefault(); 295 acceptFieldEnterKeyButton.click(); 296 } 297 }); 298 } else { 299 bindIfNecessary(inputElement, "keydown", function (event) { 300 return event.key != "Enter"; 301 }); 302 } 303 }); 304 }); 305} 306 307/*function bindActions() { 308 let elements = jQuery('[action-method]'); 309 elements.each(function (index, element) { 310 let actionMethod = jQuery(element).attr('action-method'); 311 let actionUrl = jQuery(element).attr('action-url'); 312 let actionConfirm = jQuery(element).attr('action-confirm'); 313 let ajaxCommand = jQuery(element).attr('ajax-command'); 314 let executeJs = jQuery(element).attr('execute-js'); 315 316 if (ajaxCommand !== undefined) { 317 318 bindIfNecessary(element, 'click', function () { 319 let ajaxParams = { 320 url: actionUrl, 321 success: function (response) { 322 let command = ajaxCommand.replace('<AJR>', 'response'); 323 eval(command); 324 bindActions(); 325 } 326 }; 327 328 if (actionMethod == 'location') { 329 ajaxParams.type = 'get'; 330 } else { 331 ajaxParams.type = actionMethod; 332 333 let form = jQuery(element).closest('form'); 334 335 let serializedFormParams = null; 336 if (form.length > 0) { 337 serializedFormParams = form.serialize(); 338 if (serializedFormParams != null) { 339 ajaxParams.data = serializedFormParams; 340 } 341 } 342 } 343 344 jQuery.ajax(ajaxParams); 345 }); 346 347 } else { 348 if (actionMethod == 'location') { 349 if (actionConfirm != undefined) { 350 351 bindIfNecessary(element, 'click', function () { 352 if (confirm(actionConfirm)) { 353 window.location = actionUrl; 354 } 355 }); 356 357 } else { 358 359 bindIfNecessary(element, 'click', function () { 360 window.location = actionUrl; 361 }); 362 } 363 } else if (actionMethod == 'post' || actionMethod == 'get') { 364 let form = jQuery(element).closest('form'); 365 if (form.length == 0) { 366 form = jQuery('<form onthefly>'); 367 } 368 if (actionConfirm != undefined) { 369 370 bindIfNecessary(element, 'click', function () { 371 if (confirm(actionConfirm)) { 372 form.attr('method', actionMethod); 373 form.attr('action', actionUrl); 374 if (form.attr('onthefly') !== undefined) { 375 form.appendTo('body'); 376 } 377 form.submit(); 378 } 379 }); 380 381 } else { 382 383 bindIfNecessary(element, 'click', function () { 384 form.attr('method', actionMethod); 385 form.attr('action', actionUrl); 386 if (form.attr('onthefly') !== undefined) { 387 form.appendTo('body'); 388 } 389 form.submit(); 390 }); 391 } 392 } 393 } 394 }); 395 396 // previene l'invio di form alla pressione di Enter in un campo di testo 397 jQuery('form').each(function (index, element) { 398 bindIfNecessary(element, 'keydown', function (event) { 399 return event.key != 'Enter'; 400 }); 401 }); 402} 403*/ 404 405// ok 406function bindIfNecessary(element, event, callback) { 407 var events = jQuery._data(element, "events"); 408 if (events == undefined) { 409 jQuery(element).on(event, callback); 410 } else { 411 jQuery.each(events, function (index, value) { 412 if (index != event) { 413 jQuery(element).on(event, callback); 414 } 415 }); 416 } 417} 418 419// ok 420function bindPager() { 421 if (jQuery("nav.pager").length > 0) { 422 423 let pagerType = jQuery("nav.pager").attr("pager-type"); 424 425 let elements = jQuery("[page]"); 426 427 elements.each(function (index, element) { 428 let page = jQuery(this).attr("page"); 429 let relativeUrl = ''; 430 431 bindIfNecessary(element, "click", function () { 432 433 let currentUrl = new URL(window.location.href); 434 435 /*if (pagerType == 'catalog') { 436 437 // IL CATALOG NON VIENE GESTITO IN JS, MA TRAMITE DEGLI <a href="url"> nell'html del pager in modo che Google 438 // possa seguire i link e indicizzare anche le pagine dopo la prima 439 440 // catalogo: listing paginato senza filtraggio di una sequenza di nodi (no query string, solo page num) 441 relativeUrl = currentUrl.pathname.replace(/\/page\d+$/, '') + '/page' + parseInt(page); 442 } else {*/ 443 444 // admin o dynamic: pager con query string. Se sito => aggiunge dynamic, se admin lascia così, url mvc 445 let searchParams = currentUrl.searchParams; 446 searchParams.set("page", page); 447 currentUrl.search = searchParams.toString(); 448 relativeUrl = currentUrl.pathname + currentUrl.search; 449 if (pagerType == 'dynamic') { 450 relativeUrl = (!currentUrl.pathname.match('^/dynamic') ? '/dynamic' : '') + relativeUrl; 451 } 452 window.location.href = relativeUrl; 453 }); 454 }); 455 } 456} 457 458function scrollToElement(selector) { 459 var el = jQuery(selector); 460 if (el.length === 0) return; 461 462 // Altezza di eventuale header fisso 463 var headerHeight = 0; 464 jQuery("*").each(function () { 465 var thisElement = jQuery(this); 466 if ( 467 thisElement.css("position") === "fixed" && 468 thisElement.css("top") === "0px" && 469 thisElement.is(":visible") 470 ) { 471 headerHeight = Math.max(headerHeight, thisElement.outerHeight()); 472 } 473 }); 474 475 // Calcola target tenendo conto dell'header 476 var targetTop = el.offset().top - headerHeight; 477 478 // Scroll immediato 479 window.scrollTo(0, targetTop); 480} 481 482function bindPagerAjax() { 483 let elements = jQuery("[page-ajax]"); 484 485 elements.each(function (index, element) { 486 let page = jQuery(this).attr("page-ajax"); 487 bindIfNecessary(element, "click", function () { 488 let currentUrl = jQuery(this).closest("nav").attr("ajax-action-url"); 489 let searchParams = 490 jQuery("#" + jQuery(this).closest("nav").attr("form-id")).serialize() + 491 "&page=" + 492 page; 493 let resultId = jQuery(this).closest("nav").attr("results-id"); 494 495 jQuery.ajax({ 496 url: currentUrl, 497 type: "get", 498 data: searchParams, 499 success: function (response) { 500 jQuery("#" + resultId).html(response); 501 scrollToElement("#" + resultId); 502 }, 503 }); 504 }); 505 }); 506} 507 508// ok 509function bindOrderBy() { 510 let elements = jQuery("[sort]"); 511 elements.each(function (index, element) { 512 bindIfNecessary(element, "click", function () { 513 let currentUrl = new URL(window.location.href); 514 let searchParams = currentUrl.searchParams; 515 let qsSort = searchParams.get("sort"); 516 let qsOrder = searchParams.get("order"); 517 518 let element = jQuery(this); 519 let sort = element.attr("sort"); 520 let order = "asc"; 521 522 if (qsSort == sort) { 523 if (qsOrder == "asc") { 524 order = "desc"; 525 } 526 } else { 527 order = "asc"; 528 } 529 530 // aggiorna l'url 531 searchParams.set("sort", sort); 532 searchParams.set("order", order); 533 currentUrl.search = searchParams.toString(); 534 window.location.href = currentUrl.toString(); 535 }); 536 }); 537} 538 539// ok 540jQuery(document).ready(function () { 541 bindActions(); 542 bindPager(); 543 bindPagerAjax(); 544 bindOrderBy(); 545 jQuery("body").on("change", "[data-bs-theme]", function () {
546 let theme = getCodeMirrorTheme(); 547 jQuery(".CodeMirror").each(function () { 548 this.CodeMirror.setOption("theme", theme); 549 }); 550 }); 551}); 552 553jQuery(document).on("ajaxComplete", function () { 554 loadRequiredJavascriptForComponents(); 555 bindActions(); 556 bindPagerAjax(); 557 activeComponents(); 558}); 559 560// ok 561class Autocomplete { 562 constructor(config) { 563 if (config == undefined) { 564 return; 565 } 566 567 this.fieldName = config.fieldName; 568 this.autocompleteContainerSelector = 569 config.autocompleteContainerSelector == undefined 570 ? "#autocomplete" 571 : config.autocompleteContainerSelector; 572 this.containerElement = jQuery(this.autocompleteContainerSelector); 573 this.serviceUrl = config.serviceUrl; 574 this.minChars = config.minChars == undefined ? 3 : config.minChars; 575 this.appendTo = config.appendTo == undefined ? "body" : config.appendTo; 576 this.afterSelect = 577 config.afterSelect == undefined || config.afterSelect == "" 578 ? null 579 : config.afterSelect; 580 this.onSelectSpecific = 581 config.onSelectSpecific == undefined || config.onSelectSpecific == "" 582 ? null 583 : config.onSelectSpecific; 584 this.params = config.params == undefined ? {} : config.params; 585 this.inputAutocomplete = null; 586 587 let self = this; 588 589 this.init = function () { 590 this.attachAutocomplete(); 591 jQuery(document).on( 592 "click", 593 this.autocompleteContainerSelector + " button", 594 function () { 595 self.toggleObjectPartial("search", null); 596 if (self.afterSelect !== null) { 597 window[self.afterSelect](null); 598 } 599 } 600 ); 601 }; 602 603 this.attachAutocomplete = function () { 604 this.inputAutocomplete = this.containerElement.find( 605 "input:not([readonly])" 606 ); 607 this.inputAutocomplete.autocomplete({ 608 noCache: true, 609 width: "flex", 610 orientation: "auto", 611 serviceUrl: this.serviceUrl, 612 params: this.params, 613 minChars: this.minChars, 614 appendTo: this.appendTo, 615 onSelect: function (suggestion) { 616 if (self.onSelectSpecific != null) { 617 window[self.onSelectSpecific](suggestion.data); 618 } 619 self.toggleObjectPartial("show", suggestion); 620 if (self.afterSelect != null) { 621 window[self.afterSelect](suggestion.data); 622 } 623 }, 624 }); 625 }; 626 627 // Selettore per id come attributo: un fieldName con parentesi quadre 628 // (es. SystemService[bind_zone_id]) dentro "#..." verrebbe letto da jQuery 629 // come filtro d'attributo e non troverebbe mai l'elemento. 630 this.fieldSelector = function (prefix) { 631 return " [id='" + prefix + this.fieldName + "']"; 632 }; 633 634 this.toggleObjectPartial = function (status, suggestion) { 635 if (status == "show") { 636 jQuery( 637 this.autocompleteContainerSelector + " [show]" + this.fieldSelector("ac-") 638 ).val(suggestion.value); 639 jQuery( 640 this.autocompleteContainerSelector + " [show]" + this.fieldSelector("ac-") 641 ).attr("disabled", true); 642 jQuery( 643 this.autocompleteContainerSelector + " [show]" + this.fieldSelector("") 644 ).val(suggestion.data); 645 jQuery(this.autocompleteContainerSelector + " [show]").show(); 646 jQuery(this.autocompleteContainerSelector + " [search]").hide(); 647 } else { 648 jQuery( 649 this.autocompleteContainerSelector + " [show]" + this.fieldSelector("ac-") 650 ).val(""); 651 jQuery( 652 this.autocompleteContainerSelector + " [show]" + this.fieldSelector("ac-") 653 ).attr("disabled", false); 654 jQuery( 655 this.autocompleteContainerSelector + " [show]" + this.fieldSelector("") 656 ).val(""); 657 jQuery(this.autocompleteContainerSelector + " [show]").hide(); 658 jQuery(this.autocompleteContainerSelector + " [search] input").val(""); 659 jQuery(this.autocompleteContainerSelector + " [search]").show(); 660 } 661 }; 662 } 663} 664 665// caricamento automatico dei componenti 666 667function loadRequiredJavascriptForComponents() { 668 let componentLibs = { 669 htmlarea: [ 670 '<link href="/default/js/suneditor/dist/css/suneditor.min.css" rel="stylesheet"></link>', 671 '<link href="/default/js/suneditor/dist/css/codemirror.min.css" rel="stylesheet"></link>', 672 '<link rel="stylesheet" href="/default/js/suneditor/dist/css/theme/ayu-dark.css">', 673 '<link rel="stylesheet" href="/default/js/suneditor/dist/css/theme/xq-light.css">', 674 '<script src="/default/js/suneditor/dist/suneditor.min.js" htmlarea></script>', 675 '<script src="/default/js/suneditor/dist/codemirror.min.js" htmlarea></script>', 676 '<script src="/default/js/suneditor/dist/htmlmixed.js" htmlarea></script>', 677 '<script src="/default/js/suneditor/dist/xml.min.js" htmlarea></script>', 678 '<script src="/default/js/suneditor/src/lang/it.js"></script>', 679 ], 680 autocomplete: [ 681 '<script src="/default/js/jquery-autocomplete/jquery.autocomplete.js" autocomplete></script>', 682 '<link href="/default/js/jquery-autocomplete/styles.css" rel="stylesheet"></link>', 683 ], 684 datepicker: [ 685 '<script src="/default/js/daterangepicker/moment.min.js"></script>', 686 '<script src="/default/js/daterangepicker/daterangepicker.js" datepicker></script>', 687 '<link href="/default/js/daterangepicker/daterangepicker.css" rel="stylesheet"></link>', 688 ], 689 recaptcha: [ 690 '
vendor: 89 bytes, line 690
690<script src="https://www.google.com/recaptcha/api.js?render=SITE-KEY" recaptcha></script>
690', 691 ], 692 uploadfile: [ 693 '<link href="/default/js/uploadfile/uploader.css" rel="stylesheet" />', 694 '<link href="/default/css/fancybox.css" rel="stylesheet" />', 695 '<script src="/default/js/uploadfile/simpleupload.js" type="text/javascript" uploadfile></script>', 696 '<script src="/default/js/fancybox.umd.js" type="text/javascript"></script>', 697 //'<script src="/default/js/uploadfile/uploader.min.js" type="text/javascript"></script>', 698 '<script src="/default/js/uploadfile/uploader.js" type="text/javascript"></script>', 699 ], 700 siteUploadfile: [ 701 '<link href="/default/js/uploadfile/site-uploader.css" rel="stylesheet" />', 702 '<link href="/default/css/fancybox.css" rel="stylesheet" />', 703 '<script src="/default/js/uploadfile/simpleupload.js" type="text/javascript" siteUploadfile></script>', 704 '<script src="/default/js/fancybox.umd.js" type="text/javascript"></script>', 705 '<script src="/default/js/uploadfile/uploader.js" type="text/javascript"></script>', 706 ], 707 fancybox: [ 708 '<link href="/default/css/fancybox.css" rel="stylesheet" />', 709 '<script src="/default/js/fancybox.umd.js" type="text/javascript"></script>', 710 '<script>Fancybox.bind("[data-fancybox=gallery]", {});</script>', 711 '<script>Fancybox.bind("[data-fancybox=videogallery]", {});</script>', 712 ], 713 leaflet: [ 714 '<link rel="stylesheet" href="/default/js/leaflet/leaflet.css" />', 715 '<script src="/default/js/leaflet/leaflet.js"></script>', 716 ], 717 apexcharts: [ 718 '<script src="/default/js/apexcharts.min.js"></script>', 719 ], 720 }; 721 722 jQuery("[js-load]").each(function (index, element) { 723 let jsLoad = jQuery(element).attr("js-load"); 724 if (jQuery("head script[" + jsLoad + "]").length == 0) { 725 if (componentLibs[jsLoad] !== undefined) { 726 console.log("Load " + jsLoad + " component"); 727 // reCaptcha needs a token to function 728 if (jsLoad == "recaptcha") { 729 let siteKey = jQuery(element).attr("site-key"); 730 componentLibs[jsLoad][0] = componentLibs[jsLoad][0].replace( 731 "SITE-KEY", 732 siteKey 733 ); 734 } 735 // put the script tag in the head 736 jQuery("head").append(componentLibs[jsLoad].join("")); 737 } 738 } 739 }); 740} 741 742let calllbackCachedFuntions = []; 743 744function activeComponents() { 745 jQuery("[js-load]").each(function (index, element) { 746 let jsLoad = jQuery(element).attr("js-load"); 747 748 let calllbackFuntions = []; 749 for (let i in window) { 750 if (i == 'sharedStorage') continue; // fix per evitare errore google page speed perché sharedStorage è stato deprecato 751 if ( 752 (typeof window[i]).toString() == "function" && 753 window[i].name.indexOf("JsAfterLoad_") != -1 754 ) { 755 let jsLoad = window[i].name.split("JsAfterLoad_")[0]; 756 if (calllbackFuntions[jsLoad] === undefined) { 757 calllbackFuntions[jsLoad] = []; 758 } 759 calllbackFuntions[jsLoad].push(window[window[i].name]); 760 } 761 } 762 763 // execute the JsAfterLoad_ function 764 if (calllbackFuntions[jsLoad] !== undefined) { 765 for (let i in calllbackFuntions[jsLoad]) { 766 if ( 767 calllbackCachedFuntions.indexOf(calllbackFuntions[jsLoad][i]) == -1 768 ) { 769 //console.log(calllbackFuntions[jsLoad][i]); 770 calllbackFuntions[jsLoad][i].call(); 771 calllbackCachedFuntions.push(calllbackFuntions[jsLoad][i]); 772 } 773 } 774 } 775 }); 776} 777 778// login in resctricted area 779 780function sendFormOfRestrictedAreaLogin(button) { 781 let action = button.attr('action-url'); 782 jQuery.post(action, button.closest('form').serialize(), function (afterLoginRedirect) { 783 if (afterLoginRedirect == 0) { 784 afterLoginRedirect = '_|ERROR|_'; 785 } 786 try { 787 let url = new URL('https://www.domain.net' + afterLoginRedirect); 788 if (window.eventTracking && window.eventTracking.track) { 789 window.eventTracking.track('login', {}, {}); // event-tracking: login riuscito (GA4-only) 790 } 791 window.location = afterLoginRedirect; 792 } catch (_) { 793 jQuery('#restricted-area-user-loginn-feedback').show(); 794 button.closest('form').find('input').val(''); 795 jQuery('#restricted-area-user-loginn-feedback').fadeOut(5000); 796 } 797 }); 798} 799 800jQuery(document).on('click', '[js-bind="restricted-area-logout"]', function (e) { 801 e.preventDefault(); 802 let button = jQuery(this); 803 let action = button.attr('action-url'); 804 let data = { afterLogoutRedirectNodeUniqueLabel: button.attr('afterLogoutRedirectNodeUniqueLabel') }; 805 jQuery.post(action, data, function (afterLogoutRedirect) { 806 if (afterLogoutRedirect == 0) { 807 afterLogoutRedirect = '_|ERROR|_'; 808 } 809 try { 810 let url = new URL('https://www.domain.net' + afterLogoutRedirect); 811 window.location = afterLogoutRedirect.replace('/dynamic', ''); 812 } catch (_) { 813 jQuery('#restricted-area-user-loginn-feedback').show(); 814 button.closest('form').find('input').val(''); 815 jQuery('#restricted-area-user-loginn-feedback').fadeOut(5000); 816 } 817 }); 818});
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.