1function ALERTSWEET($) { 2 3 4 5 var template = '<style> /* ============================================================ WELCOME MODAL â Instituto Crandon Sin dependencias externas (ni SweetAlert ni jQuery) Bot-prevention: solo se cierra con el botón ============================================================ */ :root { --cr-overlay-bg: rgba(10,14,26,.72); --cr-surface: #ffffff; --cr-border: #e2e8f0; --cr-navy: #1a2744; --cr-navy-2: #2a3d6b; --cr-gold: #c8a53a; --cr-gold-lt: #e8c85a; --cr-text: #1e293b; --cr-text-2: #64748b; --cr-radius: 20px; --cr-shadow: 0 28px 72px rgba(0,0,0,.50); } *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; } /* ââ Overlay ââ */ .cr-overlay { position: fixed; inset: 0; z-index: 99999; background: var(--cr-overlay-bg); backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px); display: flex; align-items: center; justify-content: center; padding: 20px; animation: crFadeIn .30s ease; } @keyframes crFadeIn { from { opacity:0; } to { opacity:1; } } @keyframes crFadeOut { from { opacity:1; } to { opacity:0; } } /* ââ Panel ââ */ .cr-panel { width: 100%; max-width: 420px; background: var(--cr-surface); border-radius: var(--cr-radius); box-shadow: var(--cr-shadow); overflow: hidden;
5 animation: crSlideUp .38s cubic-bezier(.34,1.40,.64,1); } @keyframes crSlideUp { from { transform: translateY(36px) scale(.94); opacity: 0; } to { transform: none; opacity: 1; } } /* ââ Header navy/dorado ââ */ .cr-header { background: linear-gradient(140deg, #111e38 0%, #1e3060 60%, #243878 100%); border-bottom: 3px solid var(--cr-gold); padding: 20px 28px 16px; text-align: center; position: relative; } .cr-header::after { content: \'\'; position: absolute; bottom: -6px; left: 50%; transform: translateX(-50%); width: 40px; height: 3px; background: var(--cr-gold-lt); border-radius: 999px; opacity: .6; } .cr-header-eyebrow { font-size: 10px; font-weight: 800; letter-spacing: .22em; text-transform: uppercase; color: var(--cr-gold); margin-bottom: 7px; font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif; } .cr-header-title { font-size: 21px; font-weight: 800; color: #ffffff; letter-spacing: .06em; text-transform: uppercase; font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif; text-shadow: 0 2px 10px rgba(0,0,0,.30); } /* ââ Imagen ââ */ .cr-image-wrap { line-height: 0; background: #f0f4f8; border-bottom: 1px solid var(--cr-border); } .cr-image-wrap img { width: 100%; height: auto; max-height: 210px; object-fit: cover; display: block; } /* ââ Body ââ */ .cr-body { padding: 22px 28px 26px; text-align: center; font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif; } .cr-body-sub { font-size: 13px; color: var(--cr-text-2); line-height: 1.6; margin-bottom: 20px; letter-spacing: .01em; } /* ââ Botón ââ */ .cr-btn { width: 100%; height: 50px; background: linear-gradient(135deg, var(--cr-navy) 0%, var(--cr-navy-2) 100%); color: #fff; border: none; border-radius: 14px; font-size: 15px; font-weight: 700; letter-spacing: .05em; cursor: pointer; font-family: inherit; box-shadow: 0 5px 18px rgba(26,39,68,.35); display: inline-flex; align-items: center; justify-content: center; gap: 9px; transition: opacity .15s, transform .12s, box-shadow .15s; -webkit-appearance: none; position: relative; overflow: hidden; } .cr-btn::before { content: \'\'; position: absolute; inset: 0; background: linear-gradient(135deg, rgba(255,255,255,.10) 0%, transparent 60%); border-radius: inherit; } .cr-btn:hover { opacity:.92; transform:translateY(-1px); box-shadow:0 8px 24px rgba(26,39,68,.45); } .cr-btn:active { opacity:.85; transform:none; box-shadow:0 3px 10px rgba(26,39,68,.30); } .cr-btn i { font-size: 16px; } /* ââ Separador dorado decorativo ââ */ .cr-divider { height: 2px; background: linear-gradient(to right, transparent, var(--cr-gold), transparent); opacity: .35; margin: 0 28px 18px; } /* ââ Responsive ââ */ @media (max-width: 460px) { .cr-panel { border-radius: 16px; } .cr-header { padding: 16px 20px 14px; } .cr-header-title { font-size: 18px; } .cr-body { padding: 18px 20px 22px; } .cr-btn { height: 46px; font-size: 14px; border-radius: 12px; } } @media (max-height: 580px) { .cr-image-wrap img { max-height: 130px; } .cr-body { padding: 14px 20px 18px; } }</style><div class=\"cr-overlay\" id=\"crOverlay\"> <div class=\"cr-panel\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"crTitle\"> <div class=\"cr-header\"> <div class=\"cr-header-eyebrow\">Bienvenido/a</div> <div class=\"cr-header-title\" id=\"crTitle\">Instituto Crandon</div> </div> <div class=\"cr-image-wrap\"> <img src=\"{{URLIMAGEN}}\" id=\"crImg\" alt=\"Tickets Electrónicos â Instituto Crandon\" /> </div> <div class=\"cr-body\"> <div class=\"cr-divider\"></div> <p class=\"cr-body-sub\">Sistema de Tickets Electrónicos</p> <button class=\"cr-btn\" id=\"crConfirmBtn\" type=\"button\"> <i class=\"fas fa-sign-in-alt\"></i> Ingresar al sistema </button> </div> </div></div>'; 6 Mustache.parse(template); 7 var $container; 8 this.show = function() { 9 $container = $(this.getContainerControl()); 10 11 // Raise before show scripts 12 13 14 //if (this.IsPostBack) 15 this.setHtml(Mustache.render(template, this)); 16 this.renderChildContainers(); 17 18 19 20 // Raise after show scripts 21 this.Autocomplete(); 22 } 23 24 this.Scripts = []; 25 26 this.Autocomplete = function() { 27 28 /* Font Awesome */ 29 if (!document.querySelector('link[href*="font-awesome"],link[href*="fontawesome"]')) { 30 var _fa = document.createElement('link'); 31 _fa.rel = 'stylesheet'; 32 _fa.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css'; 33 document.head.appendChild(_fa); 34 } 35 36 /* Imagen dinámica desde property */ 37 (function() { 38 var _img = document.getElementById('crImg'); 39 if (_img && this.URLIMAGEN) _img.src = this.URLIMAGEN; 40 }).call(this); 41 42 /* Init único â bot prevention */ 43 if (!window._crWelcomeInit) { 44 window._crWelcomeInit = true; 45 46 /* Bloquear ESC â no puede cerrarse con teclado */ 47 document.addEventListener('keydown', function(e) { 48 var _ov = document.getElementById('crOverlay'); 49 if (_ov && _ov.style.display !== 'none') { 50 if (e.key === 'Escape' || e.keyCode === 27 || e.key === 'Tab') { 51 e.preventDefault(); e.stopImmediatePropagation(); 52 } 53 } 54 }, true); 55 56 /* Bloquear click fuera del panel */ 57 document.addEventListener('click', function(e) { 58 var _ov = document.getElementById('crOverlay'); 59 if (_ov && _ov.style.display !== 'none' && e.target === _ov) { 60 e.preventDefault(); e.stopImmediatePropagation(); 61 } 62 }, true); 63 64 /* Cerrar solo con el botón â event delegation: 65 funciona aunque GeneXus re-renderice el DOM tras error de login */ 66 document.addEventListener('click', function(e) { 67 if (e.target.closest && e.target.closest('#crConfirmBtn')) { 68 var _ov = document.getElementById('crOverlay'); 69 if (!_ov) return; 70 _ov.style.animation = 'crFadeOut .22s ease forwards'; 71 setTimeout(function() { _ov.style.display = 'none'; }, 210); 72 } 73 }, true); 74 } 75 76 } 77 78 79 80 this.autoToggleVisibility = true; 81 82 var childContainers = {}; 83 this.renderChildContainers = function () { 84 $container 85 .find("[data-slot][data-parent='" + this.ContainerName + "']") 86 .each((function (i, slot) { 87 var $slot = $(slot), 88 slotName = $slot.attr('data-slot'), 89 slotContentEl; 90
91 slotContentEl = childContainers[slotName]; 92 if (!slotContentEl) { 93 slotContentEl = this.getChildContainer(slotName) 94 childContainers[slotName] = slotContentEl; 95 slotContentEl.parentNode.removeChild(slotContentEl); 96 } 97 $slot.append(slotContentEl); 98 $(slotContentEl).show(); 99 }).closure(this)); 100 }; 101 102}
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.