1<!doctype html> 2<html lang="en"> 3 4<head> 5 <meta name="viewport" content="width=1300, max-width=1300"> 6 <meta name="google-site-verification" content="l_kBGVByEFuQBNvWwVoARudBcFDIGjXjDZ9cFhfwagg" /> 7 8 9 10 11 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 12<meta http-equiv="Cache-Control" content="Public" /> 13<meta name="robots" content="index, follow" /> 14 15 16 17 <title>La Alondra Hotel in Corrientes: Your unique and cozy retreat</title> 18 <meta name="description" content="Discover La Alondra hotel in Corrientes. Book your stay at our boutique hotel for a peaceful experience. Learn more here!"> 19 20 <meta property="og:title" content="La Alondra Hotel in Corrientes: Your unique and cozy retreat" /> 21 <meta property="og:description" content="Discover La Alondra hotel in Corrientes. Book your stay at our boutique hotel for a peaceful experience. Learn more here!" /> 22 <meta property="og:type" content="website" /> 23 <meta property="og:url" content="https://www.laalondra.com.ar/en/" /> 24 <link rel="canonical" href="https://www.laalondra.com.ar/en/" /> 25 <meta property="og:image" content="https://images-new.pxsol.com/S7__QL9gXpz5nVioeuTyNxCcoa1VnPu2WGenKEwXdq4/rs:fill:630:430:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F2798375230422747de42b379cd2293ecc8c10fdb9ad.jpg@jpg" /> 26 <meta property="og:image:type" content="image/jpeg" /> 27 <meta property="og:image:width" content="1200" /> 28 <meta property="og:image:height" content="630" /> 29 <meta property="og:image:alt" content="La Alondra Hotel in Corrientes: Your unique and cozy retreat" /> 30 <meta name="keywords" content="hotel in Corrientes, accommodation in Corrientes, boutique hotel in Corrientes, where to stay in Corrientes?, hotel with pool in Corrientes, hotel with restaurant in Corrientes?" /> 31 <meta property="" content="La Alondra Hotel in Corrientes: Your unique and cozy retreat" /> 32 <meta property="" content="Discover La Alondra hotel in Corrientes. Book your stay at our boutique hotel for a peaceful experience. Learn more here!" /> 33 <meta property="" content="https://www.laalondra.com.ar/en/" /> 34 <meta property="" content="hotel in Corrientes, accommodation in Corrientes, boutique hotel in Corrientes, where to stay in Corrientes?, hotel with pool in Corrientes, hotel with restaurant in Corrientes?" /> 35 36 <link rel="alternate" hreflang="es-AR" href="https://www.laalondra.com.ar/" /> 37 <link rel="alternate" hreflang="en-US" href="https://www.laalondra.com.ar/en/" /> 38 <link rel="alternate" hreflang="pt-BR" href="https://www.laalondra.com.ar/pt/" /> 39 <link rel="alternate" hreflang="x-default" href="https://www.laalondra.com.ar/" /> 40 41<link rel="icon" type="image/png" sizes="16x16" href="https://images-new.pxsol.com/zaoi_PF3iX4kQvXUw_44GJj9QYz3zqwP6aDHmlDJ_h4/rs:fill:16:16:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 42<link rel="icon" type="image/png" sizes="32x32" href="https://images-new.pxsol.com/PPtOSTN4RscSUKpVNX39zhT65sxr5oF7vv6Ps-VGpJo/rs:fill:32:32:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 43<link rel="icon" type="image/png" sizes="48x48" href="https://images-new.pxsol.com/AWmafr5SDCRq-1c5kTGDaybx9AH--HnuFInGDiW3fMI/rs:fill:48:48:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 44<link rel="icon" type="image/png" sizes="96x96" href="https://images-new.pxsol.com/D3WkMZH69It8whFv6vm3SEGqhbiaEaxvpt6CYqNttZM/rs:fill:96:96:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 45<link rel="shortcut icon" href="https://files-p.pxsol.com/23292/company/library/user/1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png" /> 46 47<link rel="apple-touch-icon" sizes="57x57" href="https://images-new.pxsol.com/leXBfS2jOIizEHlq8kBQZFod9439Dmwm2VH7X7B0LaU/rs:fill:57:57:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 48<link rel="apple-touch-icon" sizes="72x72" href="https://images-new.pxsol.com/cVOiufcOC3UAfrK5_M45c7fZRuiZwPx_WUiy3l8fqN4/rs:fill:72:72:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 49<link rel="apple-touch-icon" sizes="76x76" href="https://images-new.pxsol.com/ksZ6z7U98QaJnblIhPzj6By0Z9zGF19uyD5fhSSZspw/rs:fill:76:76:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 50<link rel="apple-touch-icon" sizes="114x114" href="https://images-new.pxsol.com/TXhP3y5OpMfssEex25v6-xYlZ2RC4dzhRPN-Z6KnyRE/rs:fill:114:114:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 51<link rel="apple-touch-icon" sizes="120x120" href="https://images-new.pxsol.com/4pfSwHk4AwwCk6yu5wVBT5aCNIWraTUyTmmftXifFj8/rs:fill:120:120:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 52<link rel="apple-touch-icon" sizes="144x144" href="https://images-new.pxsol.com/nT8izY8DdC9j8vv25IbjUV3pbQKmk1dOXcFVb22PQ3o/rs:fill:144:144:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 53<link rel="apple-touch-icon" sizes="152x152" href="https://images-new.pxsol.com/ER1EONJmhNhP0NSuSrCLxjNI9ISO1IXiOzLXEodg_1k/rs:fill:152:152:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 54<link rel="apple-touch-icon" sizes="180x180" href="https://images-new.pxsol.com/HK32dT6Qs1Cn6FTgeNNNg4vr79I8K8_Nr_2QfakRXH0/rs:fill:180:180:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 55 56<link rel="icon" sizes="192x192" href="https://images-new.pxsol.com/cOQNKcVPn-7mnitgpAPRFQxvtoy14klSW4pqPcz7aRU/rs:fill:192:192:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 57<link rel="icon" sizes="512x512" href="https://images-new.pxsol.com/Qj9Jlzozf0mu_hDLhnPaU0IXv9y1GCJb3g6_m5jvFfA/rs:fill:512:512:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 58 59 <link rel="manifest" href="/manifest.json?pos=LaAlondraCasadehuespedes"> 60 61<meta name="theme-color" content="#000000"> 62 63<meta property="og:site_name" content="Inicio - La Alondra Casa de huéspedes" /> 64<meta name="twitter:card" content="summary"> 65<meta name="twitter:site" content="Inicio - La Alondra Casa de huéspedes"> 66<meta name="twitter:title" content="Inicio - La Alondra Casa de huéspedes"> 67<meta name="twitter:description" content="La Alondra âCasa de Huéspedesâ, un hotel de Diseño, ubicado en la Ciudad de Corrientes."> 68<meta name="twitter:creator" content="PXSOL"> 69<meta name="twitter:image" content="https://images-new.pxsol.com/S7__QL9gXpz5nVioeuTyNxCcoa1VnPu2WGenKEwXdq4/rs:fill:630:430:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F2798375230422747de42b379cd2293ecc8c10fdb9ad.jpg@jpg"> 70 71 72 73<style> 74 .neo_bgcolor_primary, .MuiButton-containedSecondary { 75background-color: #000000 !important; 76} 77 78.MuiButton-containedSecondary.MuiButton-contained.Mui-disabled { 79 box-shadow: none !important; 80 background-color: rgba(0, 0, 0, 0.12) !important; 81} 82 83.neo_color_primary { 84color: #000000; 85} 86 87.cta_webcheckin_px:not(.btn_sesion) { 88background-color: #000000 !important; 89color: white !important; 90border: none !important;
91font-weight: bold; 92right: 0; 93display: flex; 94align-items: center; 95font-size: 13px !important; 96padding: 7px 8px !important; 97line-height: 1.2; 98text-align: left; 99} 100 101.cta_webcheckin_px.btn_sesion { 102border: none !important; 103font-weight: bold; 104right: 0; 105display: flex; 106align-items: center; 107font-size: 13px !important; 108padding: 7px 8px !important; 109line-height: 1.2; 110text-align: left; 111} 112 113.cta_webcheckin_px * { 114color: inherit !important; 115} 116 117.cta_webcheckin_px.btn_sesion > i { 118 color: #000000 !important; 119} 120 121.cta_webcheckin_px { 122background-color: #333333; 123} 124.cta_webcheckin_px i { 125margin-right: 10px; 126font-size: 15px; 127} 128 129.neo_bgcolor_primary:hover, .MuiButton-containedSecondary:hover { 130background-color: #333333; 131} 132.px-sm-inputcontainer:hover label { 133color: #000000 !important; 134} 135div.ui-datepicker#ui-datepicker-div .ui-state-active, div.ui-datepicker#ui-datepicker-div .ui-widget-content .ui-state-active, div.ui-datepicker#ui-datepicker-div .ui-widget-header .ui-state-active, div.ui-datepicker#ui-datepicker-div td:not(.ui-datepicker-today) .ui-state-highlight, div.ui-datepicker#ui-datepicker-div .ui-widget-content .ui-state-highlight, div.ui-datepicker#ui-datepicker-div .ui-widget-header .ui-state-highlight { 136background-color: #000000 !important; 137} 138 139.px-mk-iconchangesearch { 140color: #000000 !important; 141} 142 143.px-mk-locationdropdown>*:hover .px-mk-locationimg { 144fill: #000000 !important; 145} 146 147.neo_mobile_supratop .neo_supratop_selector i { 148color: #000000 !important; 149} 150 151.standard_cta { 152padding: 10px 15px; 153box-sizing: border-box; 154border-radius: 5px; 155display: flex; 156justify-content: center; 157text-align: center; 158align-items: center; 159background: #000000 !important; 160color: #FFFFFF; 161transition: .2s ease-out; 162color: white; 163text-decoration: none; 164font-size: 18px; 165border: none; 166transition: .25s ease-out; 167cursor: pointer; 168} 169 170.standard_cta:hover { 171background-color: #4d4d4d; 172} 173.standard_cta:disabled { 174opacity: .5; 175cursor: not-allowed; 176} 177 178.neo_cta_naked {
179font-weight: bold; 180text-decoration: none; 181color: #000000; 182display: inline-flex; 183background-color: transparent; 184border: none; 185cursor: pointer; 186transition: .2s ease-out; 187} 188 189.neo_cta_naked.gray { 190color: darkgray; 191} 192 193.neo_cta_naked:hover { 194color: #000000; 195} 196 197.neo_cta_standard { 198border: none; 199border-radius: 10px; 200padding: 12px 20px; 201font-size: 18px; 202display: flex; 203align-items: center; 204justify-content: space-between; 205font-weight: bold; 206cursor: pointer; 207transition: .25s ease-out; 208box-sizing: border-box; 209text-decoration: none; 210} 211 212.neo_cta_standard.smaller { 213font-size: 16px; 214padding: 7px 13px; 215} 216 217.neo_cta_standard.shadow { 218box-shadow: 0px -1px 15px rgba(0,0,0,.3); 219} 220 221.neo_cta_standard.lowpadding { 222padding: 12px; 223} 224.neo_cta_standard.lowpadding > i { 225margin: 0; 226} 227 228.neo_cta_standard:disabled { 229opacity: .5; 230cursor: not-allowed; 231} 232 233.neo_cta_standard.primary { 234background: #000000; 235color: #FFFFFF; 236} 237.neo_cta_standard.white_cta { 238background: white; 239color: black; 240} 241.neo_cta_standard.primary:hover { 242background-color: #000000; 243color: #FFFFFF; 244} 245.neo_cta_standard.primary:active { 246background-color: #000000; 247color: #FFFFFF; 248} 249 250.neo_cta_standard > i { 251margin-left: 10px; 252} 253 254.neo_cta_standard:disabled, .neo_cta_standard[disabled] {
255cursor: not-allowed; 256filter: saturate(.3); 257opacity: 0.8; 258} 259 260.neo_cta_standard.v_disabled { 261background-color: #1e1e1e; 262} 263 264.neo_cta_standard .loading-text, .neo_cta_standard .success-text { 265display:none; 266} 267 268.neo_cta_standard.v_loading { 269pointer-events: none; 270} 271.neo_cta_standard.v_loading { 272position: relative; 273} 274.neo_cta_standard .loading-text { 275display:none; 276} 277.neo_cta_standard.v_loading > *:not(i,.loading-text) { 278display:none; 279} 280.neo_cta_standard.v_loading > i { 281position: relative; 282height: 20px; 283width: 20px; 284} 285 286.neo_cta_standard.v_loading > i:before { 287content: none; 288} 289 290.neo_cta_standard.v_loading > i::after { 291content: ""; 292position: absolute; 293width: 100%; 294height: 100%; 295box-sizing: border-box; 296top: 0; 297left: 0; 298right: 0; 299bottom: 0; 300margin: auto; 301border: 0.25rem solid transparent; 302border-top-color: #ffffff; 303border-right-color: #ffffff; 304border-radius: 50%; 305animation: spinner .6s linear infinite; 306} 307.neo_cta_standard.v_loading .loading-text { 308display:block; 309} 310 311.neo_cta_standard.v_success { 312background-color: #00a651; 313} 314.neo_cta_standard.v_success > *:not(.success-text) { 315display:none; 316} 317.neo_cta_standard.v_success .success-text { 318display:block; 319} 320@keyframes button-loading-spinner { 321from { 322transform: rotate(0turn); 323} 324 325to { 326transform: rotate(1turn); 327} 328} 329 330@keyframes spinner { 331to { 332transform: rotate(360deg); 333} 334} 335 336#innerLoader, .innerLoader { 337height: 100%; 338display: flex; 339justify-content: center; 340align-items: center; 341min-height: 200px; 342} 343.neo_spin_loader { 344height: 60px; 345width: 60px; 346margin-bottom: 20px; 347} 348.neo_spin_loader:before { 349content: ""; 350box-sizing: border-box; 351position: absolute; 352width: 60px; 353height: 60px; 354border-radius: 50%; 355border: 3px solid #ccc; 356border-top-color: #000000; 357animation: spinner 1s linear infinite; 358} 359.neo_bgcolor_primary { 360background-color: #000000; 361} 362 363.neo_button_partyselector { 364border: 1px solid #000000; 365height: 40px; 366width: 40px; 367display: flex; 368justify-content: center; 369align-items: center; 370text-align: center; 371background: transparent; 372color: #000000; 373margin: 10px 0; 374transition: .2s ease-out; 375border-radius: 10px; 376font-size: 18px; 377cursor: pointer; 378 379} 380 381.neo_button_partyselector:hover { 382background-color: #999999; 383} 384 385.neo_button_partyselector:focus { 386box-shadow: 0 0 0 3px #cccccc; 387} 388 389.neo_button_partyselector:active { 390color: #FFFFFF; 391background: #000000; 392} 393 394.neo_partyselector_quantity { 395padding: 15px 10px; 396font-size: 18px; 397} 398 399.ChildrensAgeSelect { 400width: 100%; 401box-sizing: border-box; 402padding: 10px; 403margin-bottom: 10px; 404border-radius: 10px; 405border-color: #ccc; 406} 407 408.PartyTypeSimulator .px-mk-inputicon svg { 409height: 1.2em; 410width: 1.2em; 411fill: #aaa; 412} 413.neo_bgcolor_primary_text { 414color: #FFFFFF; 415} 416 417.neo_pxuser_mainbtn { 418height: 3.5rem; 419max-height: 100%; 420overflow: hidden; 421transition: .2s ease-out; 422border-radius: .5rem; 423cursor: pointer; 424padding: 0 0.5rem; 425background-color: white; 426color: black !important; 427} 428 429.neo_pxuser_mainbtn * { 430color: black !important; 431} 432 433.neo_pxuser_mainbtn:hover { 434background-color: #f2f2f2; 435} 436 437.neo_pxuser_avatar_container { 438height: 100%; 439width: 3rem; 440display: flex; 441justify-content: center; 442align-items: center; 443} 444 445.neo_pxuser_avatar_container img { 446height: 80%; 447border-radius: 2rem; 448} 449 450.neo_pxuser_text_block { 451padding: .5rem .5rem .5rem .5rem; 452box-sizing: border-box; 453height: 100%; 454justify-content: center; 455line-height: 1.5; 456} 457 458.neo_pxuser_icon_dd { 459padding: .5rem; 460box-sizing: border-box; 461} 462 463.neo_pxuser_dropdown { 464position: absolute; 465right: 0; 466top: 100% !important; 467background: white; 468border-radius: .25rem; 469min-width: 110%; 470box-shadow: 0 3px 6px rgba(0,0,0,.5); 471text-align: left; 472display: none !important; 473} 474 475.neo_pxuser_dropdown * { 476color: black !important; 477} 478 479.neo_pxuser_dropdown.open { 480display: flex !important; 481top: 100% !important; 482} 483 484.neo_pxuser_dd_button { 485padding: 1rem; 486transition: .2s ease-out; 487cursor: pointer; 488text-decoration: none; 489color: black; 490} 491 492.neo_pxuser_dd_button > .mdi { 493font-size: 1.2rem; 494line-height: 1; 495vertical-align: middle; 496display: inline-flex; 497width: 2rem; 498justify-content: center; 499align-items: center; 500height: 2rem; 501} 502 503.neo_pxuser_dd_button > span { 504padding: .5rem; 505display: inline-flex; 506flex-grow: 1; 507width: calc(100% - 3rem); 508} 509 510.neo_pxuser_dd_button:hover { 511background-color: #f2f2f2; 512border-radius: .25rem; 513} 514 515.neo_pxuser_email { 516 max-width: 8rem; 517 overflow: hidden; 518 text-overflow: ellipsis; 519} 520 521@media only screen and (max-width: 468px) { 522 523 .neo_pxuser_mainbtn { 524 flex-flow: row-reverse; 525 flex-grow: 1; 526 } 527 528 .neo_pxuser_icon_dd { 529 display: none; 530 } 531 532 .neo_pxuser_text_block { 533 text-align: right; 534 text-transform: none; 535 letter-spacing: initial; 536 color: black; 537 line-height: 1; 538 max-width: 50%; 539 } 540 541 .neo_pxuser_email { 542 display: none; 543 } 544 545 .neo_pxuser_container { 546 text-transform: initial; 547 letter-spacing: initial; 548 font-weight: normal; 549 font-size: .8rem; 550 } 551 552 .neo_pxuser_name { 553 font-weight: bold; 554 text-align: left; 555 white-space: nowrap; 556 overflow: hidden; 557 text-overflow: ellipsis; 558 display: flex; 559 align-items: center; 560 } 561 562 .neo_pxuser_name strong { 563 display: inline-block; 564 max-width: 150px; 565 overflow: hidden; 566 white-space: nowrap; 567 text-overflow: ellipsis; 568 vertical-align: middle; 569 line-height: 1.2; 570 } 571 572 .neo_pxuser_dd_button { 573 padding: .5rem; 574 } 575 576 577}</style> 578 579 580
581<script type="application/ld+json" defer async> 582{ 583 "url" : "https:\/\/www.laalondra.com.ar\/", 584 "telephone": "+54 379 443 0555", 585 "description" : "La Alondra \u201cCasa de Hu\u00e9spedes\u201d, un hotel de Dise\u00f1o, ubicado en la Ciudad de Corrientes.", 586 "name" : "Inicio - La Alondra Casa de hu\u00e9spedes", 587 "logo" : "https:\/\/images-new.pxsol.com\/Qj9Jlzozf0mu_hDLhnPaU0IXv9y1GCJb3g6_m5jvFfA\/rs:fill:512:512:1\/q:80\/plain\/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png", 588 "image" : "https:\/\/images-new.pxsol.com\/S7__QL9gXpz5nVioeuTyNxCcoa1VnPu2WGenKEwXdq4\/rs:fill:630:430:1\/q:80\/plain\/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F2798375230422747de42b379cd2293ecc8c10fdb9ad.jpg@jpg", 589 "aggregateRating" : { 590 "reviewCount" : 27, 591 "@type" : "AggregateRating", 592 "bestRating" : 10, 593 "ratingValue" : 9.7 }, 594 "@type" : "Hotel", 595 "address" : { 596 "postalCode" : "W3400", 597 "streetAddress" : "Av. 3 de Abril 827, W3400AII Corrientes, Argentina, W3400 Capital, Corrientes, Argentina", 598 "addressCountry" : "Argentina", 599 "addressRegion" : "Corrientes", 600 "addressLocality" : "Capital", 601 "@type" : "PostalAddress" 602 }, 603 "geo": { 604 "@type": "GeoCoordinates", 605 "latitude": -27.474845,
606 "longitude": -58.84072 }, 607 "@context" : "http://schema.org" 608 } 609</script>
609 610 611<!-- Organization Schema for Brand/Logo SEO -->
612<script type="application/ld+json"> 613{ 614 "@context": "https://schema.org", 615 "@type": "Organization", 616 "name": "Inicio - La Alondra Casa de hu\u00e9spedes", 617 "url": "https:\/\/www.laalondra.com.ar\/", 618 "logo": "https:\/\/images-new.pxsol.com\/Qj9Jlzozf0mu_hDLhnPaU0IXv9y1GCJb3g6_m5jvFfA\/rs:fill:512:512:1\/q:80\/plain\/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png", 619 "image": "https:\/\/images-new.pxsol.com\/Qj9Jlzozf0mu_hDLhnPaU0IXv9y1GCJb3g6_m5jvFfA\/rs:fill:512:512:1\/q:80\/plain\/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"} 620</script>
620 621 622 623 624 <link rel="icon" sizes="192x192" href="https://images-new.pxsol.com/cOQNKcVPn-7mnitgpAPRFQxvtoy14klSW4pqPcz7aRU/rs:fill:192:192:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png@png"> 625 <link rel="icon" type="image/png" href="https://files-p.pxsol.com/23292/company/library/user/1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png" /> 626 <!-- CustomHTMLHead (SiteJson) --><link rel="preconnect" href="https://fonts.googleapis.com"> 627<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 628<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400..800;1,400..800&display=swap" rel="stylesheet"> <!-- Pos->Type: hotel.css --> 629 630<!-- Google tag (gtag.js) GA4 PXSOL TODOS LOS HOTELES -->
631<script> 632 window.dataLayer = window.dataLayer || []; 633 function gtag(){dataLayer.push(arguments);} 634 gtag('js', new Date()); 635</script>
vendor: 64 bytes, lines 635-636
635 636<script async src="https://www.googletagmanager.com/gtag/js?id=
636G-SYSQR6EL6E
vendor: 12 bytes, line 636
636"></script>
637<script> 638 let globalSessionGA4Config = { 639 'pos': 'LaAlondraCasadehuespedes', 640 'product_id': '24325', 641 'product_name': 'La Alondra Casa de huéspedes', 642 'product_country': 'Argentina', 643 'product_state': 'Corrientes', 644 'product_plaza': 'Capital', 645 'product_score': '96.88' 646 }; 647 648 649 gtag('config', 'G-SYSQR6EL6E', globalSessionGA4Config); 650 651 652 // Mirror page_view into dataLayer for GTM debug (guard to avoid duplicates) 653 if (!window.__dl_page_view_pushed) { 654 window.dataLayer.push({ event: 'page_view' }); 655 window.__dl_page_view_pushed = true; 656 } 657 658 659</script>
659 660 661<!-- Global site tag (gtag.js) -->
vendor: 64 bytes, lines 661-662
661 662<script async src="https://www.googletagmanager.com/gtag/js?id=
662UA-34517567-10
vendor: 12 bytes, line 662
662"></script>
663<script> 664 window.dataLayer = window.dataLayer || []; 665 666 function gtag() { 667 dataLayer.push(arguments); 668 try { 669 var args = Array.prototype.slice.call(arguments); 670 if (args[0] === 'event') { 671 var dlEventName = args[1]; 672 var dlParams = (args.length > 2 && typeof args[2] === 'object') ? args[2] : {}; 673 var dlObject = {}; 674 for (var key in dlParams) { 675 if (Object.prototype.hasOwnProperty.call(dlParams, key)) { 676 dlObject[key] = dlParams[key]; 677 } 678 } 679 dlObject.event = dlEventName; 680 window.dataLayer.push(dlObject); 681 682 // Intercept add_to_cart and fire form_success after it 683 if (dlEventName === 'add_to_cart') { 684 setTimeout(function() { 685 console.log('%c[pxTrack] ð FIRING form_success for add_to_cart', 'color: #4CAF50; font-weight: bold;'); 686 window.pxTrack('form_success', { 687 form_id: 'add_to_cart', 688 lead_id: null, 689 transaction_id: null 690 }); 691 }, 100); 692 } 693 } 694 } catch (e) {} 695 } 696 gtag('js', new Date()); 697 698 699 gtag('config', 'UA-34517567-10'); 700 701 702 </script>
702 703 704<!-- Pxsol Data Layer utilities and event wiring -->
705<script> 706 (function() { 707 // DEBUG: Confirm script is loaded and updated 708 console.log('%c[pxTrack] Script loaded - Version: 2025-01-15-no-inventory-v3-rate-limit-fix', 'color: #4CAF50; font-weight: bold; font-size: 12px;'); 709 710 // Define manual scan function globally FIRST (before any other code that might fail) 711 window.__px_manual_no_inventory_scan = function() { 712 console.log('[pxTrack] Manual scan triggered'); 713 if (window.__px_no_inventory_scan_func) { 714 return window.__px_no_inventory_scan_func(); 715 } else { 716 console.warn('[pxTrack] Watcher not initialized yet. Performing basic scan...'); 717 // Perform basic scan even if watcher not initialized 718 try { 719 var hasNoInventory = false; 720 var detectionMethod = ''; 721 722 // Check DOM elements 723 var noInventoryContainer = document.querySelector('#no-inventory-container'); 724 var noInventoryElement = document.querySelector('#no-inventory'); 725 if (noInventoryContainer || noInventoryElement) { 726 hasNoInventory = true; 727 detectionMethod = 'DOM element (ID)'; 728 console.log('[pxTrack] â Found #no-inventory-container or #no-inventory'); 729 } 730 731 // Check px_jsonQuery 732 if (!hasNoInventory && typeof window.px_jsonQuery !== 'undefined' && window.px_jsonQuery) { 733 var jsonQuery = window.px_jsonQuery; 734 if (jsonQuery.ProductList && Array.isArray(jsonQuery.ProductList) && jsonQuery.ProductList.length > 0) { 735 var allZero = true; 736 for (var i = 0; i < jsonQuery.ProductList.length; i++) { 737 var product = jsonQuery.ProductList[i]; 738 var productAvail = product.Availability || 0; 739 if (product.SkuList && Array.isArray(product.SkuList) && product.SkuList.length > 0) { 740 for (var j = 0; j < product.SkuList.length; j++) { 741 if (product.SkuList[j].Availability && product.SkuList[j].Availability > 0) { 742 allZero = false; 743 break; 744 } 745 } 746 } else if (productAvail > 0) { 747 allZero = false; 748 } 749 if (!allZero) break; 750 } 751 if (allZero) { 752 hasNoInventory = true; 753 detectionMethod = 'Json_Query'; 754 console.log('[pxTrack] â All products have Availability === 0'); 755 } 756 } 757 } 758 759 if (hasNoInventory && !window.__px_no_inventory_pushed) { 760 console.log('[pxTrack] ð FIRING no_inventory event manually - Method:', detectionMethod); 761 window.__px_no_inventory_pushed = true; 762 var params = {}; 763 try { 764 // Try to get search params 765 var startRaw = (document.querySelector('#fechaingreso') || {}).value || ''; 766 var endRaw = (document.querySelector('#fechaegreso') || {}).value || ''; 767 params.start_date = startRaw; 768 params.end_date = endRaw; 769 params.no_inventory = true; 770 } catch(e) {} 771 window.pxTrack('no_inventory', params); 772 773 // Fire form_success for search form after no_inventory 774 setTimeout(function() { 775 console.log('%c[pxTrack] ð FIRING form_success for search form (after manual no_inventory)', 'color: #4CAF50; font-weight: bold;'); 776 window.pxTrack('form_success', { 777 form_id: 'pxmk_searchform', 778 lead_id: null, 779 transaction_id: null 780 }); 781 }, 100); 782 783 return { fired: true, method: detectionMethod, params: params }; 784 } else if (hasNoInventory) { 785 return { already_fired: true, method: detectionMethod }; 786 } else { 787 return { no_inventory_detected: false, px_jsonQuery_exists: typeof window.px_jsonQuery !== 'undefined' }; 788 } 789 } catch(e) { 790 console.error('[pxTrack] Error in manual scan:', e); 791 return { error: 'Scan failed', message: e.message }; 792 } 793 } 794 }; 795 796 window.dataLayer = window.dataLayer || []; 797 798 // Helper that tracks to both GA4 and dataLayer 799 if (!window.pxTrack) { 800 window.pxTrack = function(eventName, params) { 801 params = params || {}; 802 try { gtag('event', eventName, params); } catch(e) {} 803 try { 804 var dl = {}; 805 for (var k in params) if (Object.prototype.hasOwnProperty.call(params, k)) dl[k] = params[k]; 806 dl.event = eventName; 807 window.dataLayer.push(dl); 808 } catch(e) {} 809 }; 810 } 811 812 // Privacy-safe booleans for PII presence 813 function bool(val) { return !!val; } 814 815 // Read URL param 816 function getUrlParam(name) {
817 try { 818 var params = new URLSearchParams(location.search); 819 return params.get(name) || ''; 820 } catch (e) { return ''; } 821 } 822 823 // Normalize common date formats to YYYY-MM-DD (best-effort) 824 function normalizeDate(value) { 825 try { 826 if (!value) return ''; 827 var v = String(value).trim(); 828 // dd/mm/yyyy -> yyyy-mm-dd 829 if (/^\d{2}\/\d{2}\/\d{4}$/.test(v)) { 830 var p = v.split('/'); 831 return [p[2], p[1].padStart(2, '0'), p[0].padStart(2, '0')].join('-'); 832 } 833 // Already ISO 834 if (/^\d{4}-\d{2}-\d{2}$/.test(v)) return v; 835 return v; 836 } catch (e) { 837 return String(value || ''); 838 } 839 } 840 841 // Session id generator 842 function getPxSessionId() { 843 try { 844 var key = 'px_session_id'; 845 var match = document.cookie.match(new RegExp('(^| )' + key + '=([^;]+)')); 846 if (match) return match[2]; 847 var id = (crypto && crypto.randomUUID) ? crypto.randomUUID() : String(Date.now()) + '_' + Math.floor(Math.random()*1e9); 848 document.cookie = key + '=' + id + ';path=/;max-age=' + (60*60*24*365).toString(); 849 return id; 850 } catch(e) { 851 return 'sid_' + String(Date.now()); 852 } 853 } 854 855 // Expose chat helpers (to be called from chat widget) 856 window.pxChatOpen = function(payload) { window.pxTrack('chat_open', payload || {}); }; 857 window.pxChatMessage = function(payload) { window.pxTrack('chat_message', payload || {}); }; 858 window.pxChatClose = function(payload) { window.pxTrack('chat_close', payload || {}); }; 859 window.pxFormSuccess = function(payload) { window.pxTrack('form_success', payload || {}); }; 860 window.pxNoInventory = function(payload) { window.pxTrack('no_inventory', payload || { no_inventory: true }); }; 861 862 // Context payload from PHP (best-effort) 863 var pxContext = { 864 pos: 'LaAlondraCasadehuespedes', 865 product_id: '24325', 866 product_name: 'La Alondra Casa de huéspedes', 867 product_country: 'Argentina', 868 product_state: 'Corrientes', 869 product_plaza: 'Capital', 870 search_id: '', 871 start_date: '', 872 end_date: '', 873 transaction_id: '', 874 value: null, 875 currency: '', 876 page_url: location.href, 877 session_id: getPxSessionId() 878 }; 879 880 // --- External engine redirect auto event when engine is disabled --- 881 882 883 // Adults/children/rooms best-effort totals from PHP when available 884 pxContext.adults = 0; 885 pxContext.children = 0; 886 pxContext.rooms = 0; 887 888 // Push context for GTM usage 889 try { window.dataLayer.push(Object.assign({ event: 'px_context' }, pxContext)); } catch(e) {} 890 891 // Boot event para validar integración en DebugView/GTM 892 if (!window.__px_boot_pushed) { 893 window.__px_boot_pushed = true; 894 window.pxTrack('px_layer_ready', { 895 session_id: pxContext.session_id, 896 page_url: pxContext.page_url, 897 pos: pxContext.pos || '', 898 product_id: pxContext.product_id || '', 899 search_id: pxContext.search_id || '', 900 ts: Date.now() 901 }); 902 } 903 904 // ----- Search events wiring (V3/V8) ----- 905 function getSearchParamsFromDOM() { 906 var startRaw = (document.querySelector('.neo_marketplace_buscador_v3 #fechaingreso') || 907 document.querySelector('#fechaingreso') || 908 document.querySelector('[name="Start"]') || 909 document.querySelector('#Start') || { }).value || pxContext.start_date || ''; 910 var endRaw = (document.querySelector('.neo_marketplace_buscador_v3 #fechaegreso') || 911 document.querySelector('#fechaegreso') || 912 document.querySelector('[name="End"]') || 913 document.querySelector('#End') || { }).value || pxContext.end_date || ''; 914 var sidRaw = (document.querySelector('#SearchID') || { }).value || getUrlParam('SearchID') || pxContext.search_id || ''; 915 var params = { 916 start_date: normalizeDate(startRaw) || '', 917 end_date: normalizeDate(endRaw) || '', 918 pos: pxContext.pos || '', 919 hotel_id: pxContext.product_id || '', 920 page_url: location.href, 921 session_id: pxContext.session_id 922 };
923 if (sidRaw) params.search_id = sidRaw; 924 // Adults/children from UI if present 925 try { 926 var adultsEl = document.querySelector('.neo_partyselector_quantity[party-type="adults"]'); 927 var childrenEl = document.querySelector('.neo_partyselector_quantity[party-type="children"]'); 928 if (adultsEl) params.adults = Number(adultsEl.getAttribute('val') || adultsEl.textContent) || pxContext.adults || 0; 929 if (childrenEl) params.children = Number(childrenEl.getAttribute('val') || childrenEl.textContent) || pxContext.children || 0; 930 // Fallback from hidden GroupsForm if exists 931 if ((!params.adults || !params.children) && document.querySelector('#GroupsForm')) { 932 var gf = document.querySelector('#GroupsForm').value || ''; 933 var rooms = 0, adults = 0, children = 0; 934 if (gf) { 935 gf.split(';').forEach(function(groupStr){ 936 if (!groupStr) return; 937 rooms += 1; 938 var parts = groupStr.split(':'); 939 if (parts.length < 2) return; 940 var trio = parts[1].split(','); 941 var a = parseInt(trio[0] || '0', 10); 942 adults += isNaN(a) ? 0 : a; 943 var childrenAges = (trio[1] || '0'); 944 if (childrenAges && childrenAges !== '0') { 945 children += childrenAges.split('.').filter(Boolean).length; 946 } 947 }); 948 if (!params.adults) params.adults = adults; 949 if (!params.children) params.children = children; 950 if (!params.rooms) params.rooms = rooms; 951 } 952 } 953 } catch(e) {} 954 return params; 955 } 956 957 // -- Estado COMPARTIDO del throttle de `search_modify` -------------------------------- 958 // Vive FUERA de las funciones de cableado a proposito: `wireSearchEventsWhenReady()` puede 959 // re-ejecutar `wireSearchEvents()` varias veces hasta enganchar el buscador que llega por 960 // AJAX, y con el throttle dentro del cierre cada invocacion tenia su propia ventana de 1 s 961 // => dos cableados equivalentes podian emitir el mismo cambio dos veces. 962 var pxLastModifyMs = 0; 963 var pxLastSnapshot = null; 964 965 function getModifySnapshot() { 966 var p = getSearchParamsFromDOM(); 967 return { 968 start_date: p.start_date || '', 969 end_date: p.end_date || '', 970 rooms: (p.rooms*1) || 0, 971 adults: (p.adults*1) || 0, 972 children: (p.children*1) || 0 973 }; 974 } 975 function pushModifyFlagsIfChanged(prevSnap, nextSnap) { 976 try { 977 if (!prevSnap) return true; 978 var changes = {}; 979 if (nextSnap.start_date !== prevSnap.start_date) changes.start_date = true; 980 if (nextSnap.end_date !== prevSnap.end_date) changes.end_date = true; 981 if ((nextSnap.rooms*1) !== (prevSnap.rooms*1)) changes.rooms = true; 982 if ((nextSnap.adults*1) !== (prevSnap.adults*1)) changes.adults = true; 983 if ((nextSnap.children*1) !== (prevSnap.children*1)) changes.children = true; 984 if (Object.keys(changes).length) return true; 985 } catch (e) {} 986 return false; 987 } 988 function throttledModifyFire() { 989 var now = Date.now(); 990 if (now - pxLastModifyMs < 1000) return; // throttle to 1s 991 pxLastModifyMs = now; 992 var current = getModifySnapshot(); 993 // Push GA/DataLayer event with current values 994 window.pxTrack('search_modify', getSearchParamsFromDOM()); 995 // Also push a probe event with the current values for GTM debug 996 try { 997 window.dataLayer.push({ 998 event: 'px_search_modify_probe', 999 search_modify: current, 1000 ts: Date.now() 1001 }); 1002 } catch(e) {} 1003 // Update snapshot only if something changed 1004 if (pushModifyFlagsIfChanged(pxLastSnapshot, current)) { 1005 pxLastSnapshot = current; 1006 } 1007 } 1008 1009 /** 1010 * Respaldos de `search_modify` que NO dependen de que el buscador exista en el DOM: 1011 * listeners DELEGADOS en `document` (captura) + un poller de 400 ms sobre 1012 * `#fechaingreso`/`#fechaegreso`/`#GroupsForm`. 1013 * 1014 * OJO: se instalan SIEMPRE en el init, sin pasar por `searchDomPresent()` ni por el tope de 1015 * 20 s del watcher -- que es exactamente como se instalaban antes, cuando `wireSearchEvents()` 1016 * se llamaba incondicionalmente. Justamente por ser delegados/poll son los que hacen que 1017 * `search_modify` funcione sobre un buscador inyectado por AJAX: meterlos detras del 1018 * reintento dejaba sin ningun listener a las sesiones donde el buscador tarda mas de 20 s 1019 * (telefono con red lenta), que ANTES si los tenian. 1020 */ 1021 function wireSearchFallbacks() { 1022 if (window.__px_search_fallbacks_wired) return; 1023 window.__px_search_fallbacks_wired = true; 1024 pxLastSnapshot = getModifySnapshot(); 1025 // Debug: signal that search watchers are alive
1026 try { 1027 window.dataLayer.push({ 1028 event: 'px_search_watchers_ready', 1029 ts: Date.now() 1030 }); 1031 } catch(e) {} 1032 // Listeners delegados (capturan aunque el DOM se re-renderice) 1033 try { 1034 if (!window.__px_global_search_listeners) { 1035 window.__px_global_search_listeners = true; 1036 var selectorList = ['#fechaingreso','#fechaegreso','.AdultsSelect','.ChildrensSelect','.neo_partyselector_quantity','.ChildrensAgeSelect']; 1037 function matchesTracked(el) { 1038 try { return selectorList.some(function(sel){ return el && el.matches && el.matches(sel); }); } catch(e) { return false; } 1039 } 1040 document.addEventListener('change', function(e){ if (matchesTracked(e.target)) throttledModifyFire(); }, true); 1041 document.addEventListener('input', function(e){ if (matchesTracked(e.target)) throttledModifyFire(); }, true); 1042 document.addEventListener('click', function(e){ 1043 var t = e.target; 1044 if (t && t.classList && t.classList.contains('neo_button_partyselector')) throttledModifyFire(); 1045 }, true); 1046 } 1047 } catch(e) {} 1048 // Robust watchers for datepicker-driven value changes and hidden GroupsForm updates 1049 try { 1050 if (!window.__px_modify_watchers_started) { 1051 window.__px_modify_watchers_started = true; 1052 var lastIn = (document.querySelector('#fechaingreso') || {}).value || ''; 1053 var lastOut = (document.querySelector('#fechaegreso') || {}).value || ''; 1054 var lastGF = (document.querySelector('#GroupsForm') || {}).value || ''; 1055 setInterval(function(){ 1056 try { 1057 var inEl = document.querySelector('#fechaingreso'); 1058 var outEl = document.querySelector('#fechaegreso'); 1059 var gfEl = document.querySelector('#GroupsForm'); 1060 var curIn = inEl ? inEl.value : ''; 1061 var curOut = outEl ? outEl.value : ''; 1062 var curGF = gfEl ? gfEl.value : ''; 1063 if (curIn !== lastIn || curOut !== lastOut || curGF !== lastGF) { 1064 lastIn = curIn; lastOut = curOut; lastGF = curGF; 1065 throttledModifyFire(); 1066 } 1067 } catch(e) {} 1068 }, 400); 1069 } 1070 } catch(e) {} 1071 } 1072 1073 /** 1074 * SOLO los cableados que necesitan el nodo del buscador en el DOM: `search_open` (existe el 1075 * contenedor) y `search_submit` (existe el form). Los reintenta `wireSearchEventsWhenReady()`. 1076 * 1077 * OJO: ya NO cuelga listeners de `search_modify` del contenedor. Eran un duplicado EXACTO de 1078 * los delegados de `wireSearchFallbacks()` (la misma lista de 6 selectores y el mismo click 1079 * sobre `.neo_button_partyselector`). Mientras esta funcion corria una sola vez compartian el 1080 * cierre -- y con el el throttle -- asi que no se notaba; con el reintento podian quedar en 1081 * invocaciones distintas y contar el mismo cambio dos veces. 1082 */ 1083 function wireSearchEvents() { 1084 var searchForm = document.querySelector('.neo_marketplace_buscador_v3 #pxmk_searchform') || document.querySelector('#search_form'); 1085 var searchContainer = document.querySelector('.neo_marketplace_buscador_v3') || document.querySelector('.px-mk-buscador-container') || document.querySelector('#search_form') || document.querySelector('.PartyTypeSimulatorContainer'); 1086 1087 if (searchContainer && !window.__px_search_container_bound) { 1088 window.__px_search_container_bound = true; 1089 // fire search_open once 1090 if (!window.__px_search_open_pushed) { 1091 window.__px_search_open_pushed = true; 1092 window.pxTrack('search_open', { page_url: location.href }); 1093 } 1094 } 1095 1096 if (searchForm && !window.__px_search_form_bound) { 1097 window.__px_search_form_bound = true; 1098 searchForm.addEventListener('submit', function() { 1099 window.pxTrack('search_submit', getSearchParamsFromDOM()); 1100 }, true); 1101 var searchBtn = document.querySelector('.neo_marketplace_buscador_v3 #PxMkAcion_Search') || document.querySelector('#Acion_Search'); 1102 if (searchBtn) { 1103 searchBtn.addEventListener('click', function() {
1104 window.pxTrack('search_submit', getSearchParamsFromDOM()); 1105 }, true); 1106 } 1107 } 1108 } 1109 1110 /** 1111 * El buscador NO existe al DOMContentLoaded en NINGUNA `lp.html`: lo inyecta por AJAX 1112 * `neo_modules/lp_cart.php` (CargarModulo) cientos de ms despues. `wireSearchEvents()` se 1113 * cableaba UNA sola vez, asi que sus dos gates de DOM evaluaban null y no se emitian nunca 1114 * `search_open` (gate `if (searchContainer)`) ni `search_submit` (gate `if (searchForm)`), 1115 * ni `start_search`/`egreso_search` (`wireDatePickers`). Sólo disparaban en las HOME 1116 * server-rendered, donde el buscador viene en el HTML inicial. 1117 * 1118 * Medido en vivo el 2026-08-21 sobre `fincaogawa.reservadirecto.com/lp.html`: los 6 1119 * selectores del buscador estan en 0 en DOMContentLoaded (1389 ms) y en load (2369 ms), y 1120 * recien aparecen a los ~3010 ms; un click en el submit real (`#Acion_Search`) generaba 1121 * SearchID y `has_inventory`, pero CERO `search_submit`. 1122 * 1123 * `has_inventory`/`no_inventory` nunca sufrieron esto porque cuelgan de una cascada de scans 1124 * + MutationObserver (`wireNoInventoryWatcher` / `observeAvailabilityContainers`), no de un 1125 * cableado one-shot. Esta funcion aplica esa MISMA tecnica a la fam
1125ilia de busqueda. 1126 * 1127 * Se apaga sola en cuanto engancha el contenedor y el form (los dos productores de 1128 * `search_open`/`search_submit`), con tope duro de 20 s. Cada bind es idempotente por su 1129 * propia guarda global, asi que re-correr no duplica ni un listener ni un evento. 1130 */ 1131 function searchDomPresent() { 1132 try { 1133 return !!(document.querySelector('.neo_marketplace_buscador_v3') 1134 || document.querySelector('.px-mk-buscador-container') 1135 || document.querySelector('#search_form') 1136 || document.querySelector('.PartyTypeSimulatorContainer') 1137 || document.querySelector('#fechaingreso')); 1138 } catch (e) { return false; } 1139 } 1140 function wireSearchEventsWhenReady() { 1141 if (window.__px_search_ready_watcher) return; 1142 window.__px_search_ready_watcher = true; 1143 var mo = null; 1144 var stopped = false; 1145 function stop() { 1146 if (stopped) return; 1147 stopped = true; 1148 if (mo) { try { mo.disconnect(); } catch (e) {} mo = null; } 1149 } 1150 function attempt() { 1151 if (stopped) return; 1152 // Chequeo barato primero: sin buscador en el DOM no se toca nada. Evita correr 1153 // `wireSearchEvents()` (que lee bastante DOM) en cada mutacion de una pagina sin motor. 1154 if (!searchDomPresent()) return; 1155 if (!window.__px_search_container_bound || !window.__px_search_form_bound) { 1156 try { wireSearchEvents(); } catch (e) {} 1157 } 1158 if (!window.__px_date_pickers_bound) { 1159 try { wireDatePickers(); } catch (e) {} 1160 } 1161 if (window.__px_search_container_bound && window.__px_search_form_bound) stop(); 1162 } 1163 attempt(); 1164 if (stopped) return; 1165 [200, 500, 1000, 2000, 3000, 5000, 8000, 12000].forEach(function(ms){ 1166 setTimeout(attempt, ms); 1167 }); 1168 setTimeout(stop, 20000); 1169 if ('MutationObserver' in window && document.body) { 1170 try { 1171 mo = new MutationObserver(function(){ 1172 if (stopped || mo.__px_scheduled) return; 1173 mo.__px_scheduled = true; 1174 setTimeout(function(){ if (mo) { mo.__px_scheduled = false; } attempt(); }, 100); 1175 }); 1176 mo.observe(document.body, { childList: true, subtree: true }); 1177 } catch (e) { mo = null; } 1178 } 1179 } 1180 1181 // ----- Form events wiring (generic) ----- 1182 function wireFormEvents() { 1183 var forms = Array.prototype.slice.call(document.querySelectorAll('form:not([data-px-ignore="true"])')); 1184 var observed = new WeakSet(); 1185 1186 // form_view when enters viewport first time 1187 if ('IntersectionObserver' in window) { 1188 var io = new IntersectionObserver(function(entries) { 1189 entries.forEach(function(entry) { 1190 if (entry.isIntersecting && !observed.has(entry.target)) { 1191 observed.add(entry.target); 1192 window.pxTrack('form_view', { 1193 form_id: entry.target.id || entry.target.getAttribute('name') || 'form', 1194 page_url: location.href 1195 }); 1196 } 1197 }); 1198 }, { threshold: 0.2 }); 1199 forms.forEach(function(f){ io.observe(f); }); 1200 } else { 1201 forms.forEach(function(f){ 1202 window.pxTrack('form_view', { form_id: f.id || f.getAttribute('name') || 'form', page_url: location.href }); 1203 }); 1204 } 1205 1206 // form_interaction on field focus 1207 document.addEventListener('focusin', function(e) { 1208 var field = e.target; 1209 var form = field.form; 1210 if (!form) return; 1211 var fieldName = field.name || field.id || field.type || 'field'; 1212 try { 1213 if (field.classList && field.classList.contains('neo_partyselector_quantity')) { 1214 var pt = field.getAttribute('party-type'); 1215 if (pt) fieldName = 'party_' + pt; 1216 } 1217 } catch(e) {} 1218 window.pxTrack('form_interaction', { 1219 form_id: form.id || form.getAttribute('name') || 'form', 1220 field_name: fieldName 1221 }); 1222 }); 1223 1224 // form_submit with privacy-safe flags 1225 forms.forEach(function(form) { 1226 form.addEventListener('submit', function() { 1227 var email = form.querySelector('input[type="email"]'); 1228 var phone = form.querySelector('input[type="tel"], input[name*="phone"], input[name*="telefono"]'); 1229 var required = Array.prototype.slice.call(form.querySelectorAll('[required]')); 1230 var incomplete = required.some(function(el){ return !el.value; }); 1231 window.pxTrack('form_submit', { 1232 form_id: form.id || form.getAttribute('name') || 'form', 1233 page_url: location.href, 1234 fields_status: incomplete ? 'incompletos' : 'completos', 1235 email_provided: bool(email && email.value), 1236 phone_provided: bool(phone && phone.value), 1237 session_id: pxContext.session_id 1238 }); 1239 }, true); 1240 }); 1241 } 1242 // Extra: map clicks/changes on party selector controls to meaningful field_name 1243 (function wirePartySelectorInteractions(){
1244 try { 1245 var lastMs = 0; 1246 function pushPartyInteraction(partyType) { 1247 var now = Date.now(); 1248 if (now - lastMs < 400) return; 1249 lastMs = now; 1250 var form = document.querySelector('#search_form') || document.querySelector('.neo_marketplace_buscador_v3 #pxmk_searchform'); 1251 window.pxTrack('form_interaction', { 1252 form_id: form ? (form.id || form.getAttribute('name') || 'form') : 'form', 1253 field_name: partyType ? ('party_' + partyType) : 'party_selector' 1254 }); 1255 } 1256 document.addEventListener('click', function(e){ 1257 var t = e.target; 1258 if (t && t.classList && t.classList.contains('neo_button_partyselector')) { 1259 pushPartyInteraction(t.getAttribute('party-type') || ''); 1260 } 1261 }, true); 1262 document.addEventListener('change', function(e){ 1263 var t = e.target; 1264 if (t && t.classList && t.classList.contains('neo_partyselector_quantity')) { 1265 pushPartyInteraction(t.getAttribute('party-type') || ''); 1266 } 1267 }, true); 1268 document.addEventListener('input', function(e){ 1269 var t = e.target; 1270 if (t && t.classList && t.classList.contains('neo_partyselector_quantity')) { 1271 pushPartyInteraction(t.getAttribute('party-type') || ''); 1272 } 1273 }, true); 1274 } catch(e) {} 1275 })(); 1276 1277 // Fire specific date interactions (optional) 1278 function wireDatePickers() { 1279 if (window.__px_date_pickers_bound) return; 1280 var inEl = document.querySelector('.neo_marketplace_buscador_v3 #fechaingreso'); 1281 var outEl = document.querySelector('.neo_marketplace_buscador_v3 #fechaegreso'); 1282 // Todavia no llego el buscador: NO se marca como cableado, lo reintenta 1283 // `wireSearchEventsWhenReady()`. 1284 if (!inEl && !outEl) return; 1285 window.__px_date_pickers_bound = true; 1286 if (inEl) inEl.addEventListener('change', function(){ window.pxTrack('start_search', { start_search: inEl.value || '', page_url: location.href }); }); 1287 if (outEl) outEl.addEventListener('change', function(){ window.pxTrack('egreso_search', { egreso_search: outEl.value || '', page_url: location.href }); }); 1288 } 1289 1290 // ----- WhatsApp click tracking (GA4/dataLayer + Meta Pixel "Contact") ----- 1291 // El cliente pidió medir el clic en el botón de WhatsApp como una conversión más. 1292 // Se replica el patrón del resto de los eventos (window.pxTrack -> gtag + dataLayer) y, 1293 // si el POS tiene el pixel cargado (FacebookPixelID), se dispara el evento estándar "Contact". 1294 function wireWhatsappClick() { 1295 if (window.__px_whatsapp_wired) return; 1296 window.__px_whatsapp_wired = true; 1297 1298 var companyId = ''; 1299 var lastWaMs = 0; 1300 1301 function extractPhone(href) { 1302 try { 1303 var m = href.match(/[?&]phone=(\+?\d+)/i); 1304 if (m) return m[1]; 1305 m = href.match(/wa\.me\/(\+?\d+)/i); 1306 if (m) return m[1]; 1307 } catch (e) {} 1308 return ''; 1309 } 1310 1311 // Cualquier <a> hacia WhatsApp (api./web.whatsapp.com o wa.me), incluidos los botones 1312 // flotantes .wsp_floating (neo_social_links / standard_lp_motor) y #checkout_wsp_floating. 1313 function findWhatsappLink(el) { 1314 try { 1315 if (!el || !el.closest) return null; 1316 var a = el.closest('a'); 1317 if (!a) return null; 1318 var href = (a.getAttribute('href') || '').toLowerCase(); 1319 if (/(?:api\.|web\.)?whatsapp\.com|wa\.me/.test(href)) return a; 1320 if (a.closest('.wsp_floating') || a.closest('#checkout_wsp_floating')) return a; 1321 } catch (e) {} 1322 return null; 1323 } 1324 1325 // Delegado en captura: se dispara aunque el módulo re-renderice el botón (los .wsp_floating 1326 // se re-inyectan/mueven al body). target="_blank" mantiene la página viva para los beacons. 1327 document.addEventListener('click', function (e) { 1328 var link = findWhatsappLink(e.target); 1329 if (!link) return; 1330 var now = Date.now(); 1331 if (now - lastWaMs < 800) return; // dedupe de doble-disparo 1332 lastWaMs = now; 1333 1334 var href = link.getAttribute('href') || ''; 1335 var phone = extractPhone(href); 1336 var payload = { 1337 phone: phone, 1338 destination_url: href, 1339 pos: pxContext.pos || '', 1340 product_id: pxContext.product_id || '', 1341 product_name: pxContext.product_name || '', 1342 company_id: companyId || '', 1343 search_id: pxContext.search_id || '', 1344 currency: pxContext.currency || '', 1345 page_url: location.href, 1346 session_id: pxContext.session_id 1347 }; 1348 1349 // GA4 + dataLayer (Google y GTM) 1350 window.pxTrack('whatsapp_click', payload); 1351 1352 // Meta Pixel: evento estándar "Contact". fbq solo existe si el POS tiene FacebookPixelID 1353 // (se inicializa en Conversion_SearchOK.php / PageView), asà que este typeof es el guard. 1354 try { 1355 if (typeof window.fbq === 'function') { 1356 window.fbq('track', 'Contact', { content_name: 'whatsapp', content_category: 'whatsapp_click' }); 1357 } 1358 } catch (e) {} 1359 }, true); 1360 } 1361
1362 // Enrich context from hidden inputs present in LP/consultas templates 1363 function enhanceContextFromHiddenInputs() { 1364 var startRaw = (document.querySelector('#Start') || 1365 document.querySelector('#fechaingreso') || 1366 document.querySelector('[name="Start"]') || { }).value || ''; 1367 var endRaw = (document.querySelector('#End') || 1368 document.querySelector('#fechaegreso') || 1369 document.querySelector('[name="End"]') || { }).value || ''; 1370 var start = normalizeDate(startRaw); 1371 var end = normalizeDate(endRaw); 1372 var sid = (document.querySelector('#SearchID') || {}).value || ''; 1373 var gf = (document.querySelector('#GroupsForm') || {}).value || ''; 1374 var rooms = 0, adults = 0, children = 0; 1375 if (gf) { 1376 gf.split(';').forEach(function(groupStr){ 1377 if (!groupStr) return; 1378 rooms += 1; 1379 var parts = groupStr.split(':'); 1380 if (parts.length < 2) return; 1381 var trio = parts[1].split(','); 1382 var a = parseInt(trio[0] || '0', 10); 1383 adults += isNaN(a) ? 0 : a; 1384 var childrenAges = (trio[1] || '0'); 1385 if (childrenAges && childrenAges !== '0') { 1386 children += childrenAges.split('.').filter(Boolean).length; 1387 } 1388 }); 1389 } 1390 var updated = {}; 1391 if (start && start !== pxContext.start_date) { pxContext.start_date = start; updated.start_date = start; } 1392 if (end && end !== pxContext.end_date) { pxContext.end_date = end; updated.end_date = end; } 1393 if (sid && sid !== pxContext.search_id) { pxContext.search_id = sid; updated.search_id = sid; } 1394 if (adults && adults !== pxContext.adults) { pxContext.adults = adults; updated.adults = adults; } 1395 if (children && children !== pxContext.children) { pxContext.children = children; updated.children = children; } 1396 if (rooms && rooms !== pxContext.rooms) { pxContext.rooms = rooms; updated.rooms = rooms; } 1397 if (Object.keys(updated).length) { 1398 try { window.dataLayer.push(Object.assign({ event: 'px_context_update' }, updated)); } catch(e) {} 1399 } 1400 } 1401 1402 // Parse GroupsForm like "1:2,0,0;1:1,5.7,0" into {rooms, adults, children} 1403 function parseGroupsForm(gf) { 1404 var out = { rooms: 0, adults: 0, children: 0 };
1405 try { 1406 if (!gf) return out; 1407 String(gf).split(';').forEach(function(groupStr){ 1408 if (!groupStr) return; 1409 out.rooms += 1; 1410 var parts = groupStr.split(':'); 1411 if (parts.length < 2) return; 1412 var trio = parts[1].split(','); 1413 var a = parseInt(trio[0] || '0', 10); 1414 out.adults += isNaN(a) ? 0 : a; 1415 var childrenAges = (trio[1] || '0'); 1416 if (childrenAges && childrenAges !== '0') { 1417 out.children += childrenAges.split('.').filter(Boolean).length; 1418 } 1419 // Babies are not counted in children 1420 }); 1421 } catch (e) {} 1422 return out; 1423 } 1424 1425 // Enrich context from px_jsonQuery (server-rendered Json_Query) when available 1426 function enhanceContextFromPxJson() { 1427 try { 1428 var q = (typeof window !== 'undefined' && window.px_jsonQuery) ? window.px_jsonQuery : (typeof px_jsonQuery !== 'undefined' ? px_jsonQuery : null); 1429 if (!q) return; 1430 var updated = {}; 1431 // SearchID 1432 if (q.SearchID && String(q.SearchID) !== String(pxContext.search_id || '')) { 1433 pxContext.search_id = String(q.SearchID); 1434 updated.search_id = pxContext.search_id; 1435 } 1436 // Dates 1437 var start = normalizeDate(q.Start || ''); 1438 var end = normalizeDate(q.End || ''); 1439 if (start && start !== pxContext.start_date) { pxContext.start_date = start; updated.start_date = start; } 1440 if (end && end !== pxContext.end_date) { pxContext.end_date = end; updated.end_date = end; } 1441 // Pax/rooms from GroupsForm or Group array 1442 var paxParsed = null; 1443 if (q.GroupsForm) { 1444 paxParsed = parseGroupsForm(q.GroupsForm); 1445 } else if (q.Group && Array.isArray(q.Group)) { 1446 paxParsed = { rooms: 0, adults: 0, children: 0 }; 1447 q.Group.forEach(function(g){ 1448 paxParsed.rooms += 1; 1449 paxParsed.adults += (g.Adults*1) || 0; 1450 paxParsed.children += (g.Childs*1) || 0; 1451 }); 1452 } 1453 if (paxParsed) { 1454 if (paxParsed.adults && paxParsed.adults !== pxContext.adults) { pxContext.adults = paxParsed.adults; updated.adults = paxParsed.adults; } 1455 if (paxParsed.children && paxParsed.children !== pxContext.children) { pxContext.children = paxParsed.children; updated.children = paxParsed.children; } 1456 if (paxParsed.rooms && paxParsed.rooms !== pxContext.rooms) { pxContext.rooms = paxParsed.rooms; updated.rooms = paxParsed.rooms; } 1457 } 1458 if (Object.keys(updated).length) { 1459 try { window.dataLayer.push(Object.assign({ event: 'px_context_update' }, updated)); } catch(e) {} 1460 } 1461 } catch (e) {} 1462 } 1463 1464 // Process API payloads to enrich context 1465 function processApiData(url, data) { 1466 try { 1467 if (!data) return; 1468 // avoid reprocessing same SearchID repeatedly 1469 window.__px_processed_sids = window.__px_processed_sids || {}; 1470 var updated = {}; 1471 var payload = data && data.Json_Query ? data.Json_Query : data; 1472 // SearchID present? 1473 if (typeof payload.SearchID !== 'undefined' && String(payload.SearchID)) { 1474 var sid = String(payload.SearchID); 1475 if (window.__px_processed_sids[sid]) return; 1476 if (sid && sid !== String(pxContext.search_id || '')) { pxContext.search_id = sid; updated.search_id = sid; } 1477 window.__px_processed_sids[sid] = true; 1478 } 1479 // Start / End can exist either top-level or nested 1480 var start = payload.Start || (data && data.Start) || ''; 1481 var end = payload.End || (data && data.End) || ''; 1482 start = normalizeDate(start); 1483 end = normalizeDate(end); 1484 if (start && start !== pxContext.start_date) { pxContext.start_date = start; updated.start_date = start; } 1485 if (end && end !== pxContext.end_date) { pxContext.end_date = end; updated.end_date = end; } 1486 // GroupsForm could be present 1487 var gf = payload.GroupsForm || (data && data.GroupsForm) || ''; 1488 if (gf) { 1489 var parsed = parseGroupsForm(gf); 1490 if (parsed.adults && parsed.adults !== pxContext.adults) { pxContext.adults = parsed.adults; updated.adults = parsed.adults; } 1491 if (parsed.children && parsed.children !== pxContext.children) { pxContext.children = parsed.children; updated.children = parsed.children; } 1492 if (parsed.rooms && parsed.rooms !== pxContext.rooms) { pxContext.rooms = parsed.rooms; updated.rooms = parsed.rooms; } 1493 } 1494 // Some APIs include Group arrays; attempt totals 1495 if (payload.Group && Array.isArray(payload.Group)) { 1496 var aT = 0, cT = 0, rT = 0; 1497 payload.Group.forEach(function(g){ 1498 if (!g) return; 1499 rT += 1; 1500 aT += (g.Adults*1) || 0; 1501 cT += (g.Childs*1) || 0; 1502 }); 1503 if (aT && aT !== pxContext.adults) { pxContext.adults = aT; updated.adults = aT; } 1504 if (cT && cT !== pxContext.children) { pxContext.children = cT; updated.children = cT; } 1505 if (rT && rT !== pxContext.rooms) { pxContext.rooms = rT; updated.rooms = rT; } 1506 } 1507 if (Object.keys(updated).length) { 1508 try { window.dataLayer.push(Object.assign({ event: 'px_context_update' }, updated)); } catch(e) {} 1509 } 1510 } catch(e) {} 1511 } 1512 1513 // Intercept fetch/XHR to learn from API responses 1514 (function installNetworkTaps(){
1515 try { 1516 var origFetch = window.fetch; 1517 if (origFetch && !window.__px_fetch_hooked) { 1518 window.__px_fetch_hooked = true; 1519 window.fetch = function(input, init) { 1520 var p = origFetch(input, init); 1521 try { 1522 var url = typeof input === 'string' ? input : (input && input.url) || ''; 1523 p.then(function(res){ 1524 try { 1525 var ct = (res.headers && res.headers.get && res.headers.get('content-type')) || ''; 1526 if (ct && ct.indexOf('application/json') !== -1 && (/\/query\/list/i.test(url) || /\/search\/info/i.test(url))) { 1527 res.clone().json().then(function(json){ processApiData(url, json); }).catch(function(){}); 1528 } 1529 } catch(e) {} 1530 }).catch(function(){}); 1531 } catch(e) {} 1532 return p; 1533 }; 1534 } 1535 } catch(e) {} 1536 try { 1537 if (!window.__px_xhr_hooked && window.XMLHttpRequest) { 1538 window.__px_xhr_hooked = true; 1539 var XHR = window.XMLHttpRequest; 1540 var open = XHR.prototype.open; 1541 var send = XHR.prototype.send; 1542 XHR.prototype.open = function(method, url) { 1543 this.__px_url = url; 1544 return open.apply(this, arguments); 1545 }; 1546 XHR.prototype.send = function(body) { 1547 try { 1548 this.addEventListener('load', function() { 1549 try { 1550 var url = this.__px_url || ''; 1551 var ct = this.getResponseHeader && this.getResponseHeader('content-type') || ''; 1552 if (ct && ct.indexOf('application/json') !== -1 && (/\/query\/list/i.test(url) || /\/search\/info/i.test(url))) { 1553 var txt = this.responseText; 1554 try { processApiData(url, JSON.parse(txt)); } catch(e) {} 1555 } 1556 } catch(e) {} 1557 }); 1558 } catch(e) {} 1559 return send.apply(this, arguments); 1560 }; 1561 } 1562 } catch(e) {} 1563 })(); 1564 1565 // If we have SearchID but missing details, fetch /search/info 1566 function fetchSearchInfoIfNeeded() { 1567 try { 1568 var sid = pxContext.search_id || getUrlParam('SearchID') || (document.querySelector('#SearchID')||{}).value || ''; 1569 var needsDates = !(pxContext.start_date && pxContext.end_date); 1570 var needsPaxs = !((pxContext.adults*1) > 0 || (pxContext.children*1) > 0); 1571 if (sid && (needsDates || needsPaxs)) { 1572 fetchSearchInfoForSid(sid); 1573 } 1574 } catch(e) {} 1575 } 1576 1577 // Cached fetch per SearchID 1578 function fetchSearchInfoForSid(sid) { 1579 try { 1580 window.__px_sid_promises = window.__px_sid_promises || {}; 1581 if (window.__px_sid_promises[sid]) return window.__px_sid_promises[sid]; 1582 var endpoint = 'https://api-1-eb-web.pxsol.io/search/info?SearchID=' + encodeURIComponent(sid); 1583 var pr = fetch(endpoint, { credentials: 'omit' }).then(function(res){ 1584 if (!res.ok) return; 1585 var ct = (res.headers && res.headers.get && res.headers.get('content-type')) || ''; 1586 if (ct.indexOf('application/json') === -1) return; 1587 return res.json(); 1588 }).then(function(json){ 1589 if (json) processApiData(endpoint, json); 1590 return true; 1591 }).catch(function(){ return false; }); 1592 window.__px_sid_promises[sid] = pr; 1593 return pr; 1594 } catch(e) { return Promise.resolve(false); } 1595 } 1596 1597 // Ensure dates/paxs are ready before firing a callback 1598 function ensureContextReady(cb) { 1599 try { 1600 // Try quick enrichments first 1601 enhanceContextFromHiddenInputs(); 1602 enhanceContextFromPxJson(); 1603 var sid = pxContext.search_id || getUrlParam('SearchID') || (document.querySelector('#SearchID')||{}).value || ''; 1604 var hasDates = !!(pxContext.start_date && pxContext.end_date); 1605 var hasPaxs = ((pxContext.adults*1) > 0) || ((pxContext.children*1) > 0); 1606 if (hasDates && hasPaxs) { cb(); return; } 1607 if (sid) { 1608 fetchSearchInfoForSid(sid).finally(function(){ cb(); }); 1609 return; 1610 } 1611 // Last resort: try to enrich from DOM then run
1612 enhanceContextFromHiddenInputs(); 1613 cb(); 1614 } catch(e) { cb(); } 1615 } 1616 1617 // Detect "No hay resultados" to push no_inventory automatically 1618 function wireNoInventoryWatcher() { 1619 console.log('%c[pxTrack] ð Initializing no_inventory watcher...', 'color: #2196F3; font-weight: bold; font-size: 14px;'); 1620 console.log('[pxTrack] wireNoInventoryWatcher() called at:', new Date().toISOString()); 1621 var scanCount = 0; 1622 var lastScanResult = null; 1623 var lastSearchID = null; // Track SearchID to detect new searches 1624 var lastScanTime = 0; // For throttling scans 1625 var SCAN_THROTTLE_MS = 1000; // Maximum 1 scan per second 1626 var EVENT_COOLDOWN_MS = 5000; // Minimum 5 seconds between events of the same type 1627 var lastEventTime = {}; // Track last time each event type was fired 1628 var MAX_SCANS_PER_SEARCH = 30; // Maximum scans per search to prevent excessive polling 1629 var __px_has_inventory_pushed = false; // Flag para has_inventory (opuesto de no_inventory) 1630 1631 // Log immediately to confirm function is executing 1632 console.log('[pxTrack] â wireNoInventoryWatcher() is executing - scan function will be defined'); 1633 1634 // Expose scan function to global manual trigger 1635 window.__px_no_inventory_scan_func = function() { 1636 console.log('[pxTrack] Manual scan triggered via global function'); 1637 scan(); 1638 return lastScanResult; 1639 }; 1640 1641 function checkJsonQueryAvailability() { 1642 try { 1643 // Check if px_jsonQuery is available 1644 if (typeof window.px_jsonQuery === 'undefined' || !window.px_jsonQuery) { 1645 return false; 1646 } 1647 1648 var jsonQuery = window.px_jsonQuery; 1649 1650 // Log full structure on first check (for debugging) 1651 if (!window.__px_jsonQuery_logged) { 1652 window.__px_jsonQuery_logged = true; 1653 try { 1654 console.log('[pxTrack] ð¦ px_jsonQuery structure detected:', { 1655 hasProductList: !!(jsonQuery.ProductList), 1656 productListIsArray: Array.isArray(jsonQuery.ProductList), 1657 productListLength: jsonQuery.ProductList ? jsonQuery.ProductList.length : 0, 1658 sampleProduct: jsonQuery.ProductList && jsonQuery.ProductList.length > 0 ? { 1659 hasAvailability: typeof jsonQuery.ProductList[0].Availability !== 'undefined', 1660 availability: jsonQuery.ProductList[0].Availability, 1661 hasSkuList: !!(jsonQuery.ProductList[0].SkuList), 1662 skuListLength: jsonQuery.ProductList[0].SkuList ? jsonQuery.ProductList[0].SkuList.length : 0 1663 } : null 1664 }); 1665 // Log first product details if available 1666 if (jsonQuery.ProductList && jsonQuery.ProductList.length > 0) { 1667 var firstProduct = jsonQuery.ProductList[0]; 1668 console.log('[pxTrack] First product sample:', { 1669 Availability: firstProduct.Availability, 1670 hasSkuList: !!(firstProduct.SkuList), 1671 SkuList: firstProduct.SkuList ? firstProduct.SkuList.map(function(sku) { 1672 return { Availability: sku.Availability }; 1673 }).slice(0, 3) : null 1674 }); 1675 } 1676 } catch(e) { 1677 console.error('[pxTrack] Error logging Json_Query structure:', e); 1678 } 1679 } 1680 1681 // Check if ProductList exists and is an array 1682 if (!jsonQuery.ProductList) { 1683 // ProductList might not be loaded yet, but object exists 1684 return false; 1685 } 1686 1687 if (!Array.isArray(jsonQuery.ProductList)) { 1688 console.warn('[pxTrack] px_jsonQuery.ProductList exists but is not an array:', typeof jsonQuery.ProductList); 1689 return false; 1690 } 1691 1692 if (jsonQuery.ProductList.length === 0) { 1693 // Empty ProductList might indicate no inventory, but we need at least one product to check 1694 return false; 1695 } 1696 1697 // Check if ALL products have Availability === 0 1698 var allZeroAvailability = true; 1699 var availabilityDetails = []; 1700 1701 for (var i = 0; i < jsonQuery.ProductList.length; i++) { 1702 var product = jsonQuery.ProductList[i]; 1703 // Check Availability property (could be at product level or in SkuList) 1704 var productAvailability = product.Availability || 0; 1705 var productHasAvailability = typeof product.Availability !== 'undefined'; 1706 1707 // If product has SkuList, check all SKUs 1708 if (product.SkuList && Array.isArray(product.SkuList) && product.SkuList.length > 0) { 1709 var allSkusZero = true; 1710 var skuAvailabilities = []; 1711 for (var j = 0; j < product.SkuList.length; j++) { 1712 var sku = product.SkuList[j]; 1713 var skuAvail = sku.Availability || 0; 1714 skuAvailabilities.push(skuAvail); 1715 if (sku.Availability && sku.Availability > 0) { 1716 allSkusZero = false;
1717 break; 1718 } 1719 } 1720 availabilityDetails.push({ 1721 productIndex: i, 1722 hasProductAvailability: productHasAvailability, 1723 productAvailability: productAvailability, 1724 hasSkuList: true, 1725 skuAvailabilities: skuAvailabilities, 1726 allSkusZero: allSkusZero 1727 }); 1728 if (!allSkusZero) { 1729 allZeroAvailability = false; 1730 break; 1731 } 1732 } else { 1733 // Product-level availability check 1734 availabilityDetails.push({ 1735 productIndex: i, 1736 hasProductAvailability: productHasAvailability, 1737 productAvailability: productAvailability, 1738 hasSkuList: false 1739 }); 1740 if (productAvailability > 0) { 1741 allZeroAvailability = false; 1742 break; 1743 } 1744 } 1745 } 1746 1747 // Log availability details when checking (first time or when all zero) 1748 if (allZeroAvailability || !window.__px_availability_details_logged) { 1749 window.__px_availability_details_logged = true; 1750 console.log('[pxTrack] Availability check result:', { 1751 allZeroAvailability: allZeroAvailability, 1752 totalProducts: jsonQuery.ProductList.length, 1753 details: availabilityDetails.slice(0, 3) // Show first 3 products 1754 }); 1755 } 1756 1757 return allZeroAvailability; 1758 } catch(e) { 1759 console.error('[pxTrack] Error checking Json_Query availability:', e); 1760 return false; 1761 } 1762 } 1763 1764 function checkJsonQueryHasAvailability() { 1765 try { 1766 // Check if px_jsonQuery is available 1767 if (typeof window.px_jsonQuery === 'undefined' || !window.px_jsonQuery) { 1768 return { hasAvailability: false, totalAvailability: 0, availabilityDetails: null }; 1769 } 1770 1771 var jsonQuery = window.px_jsonQuery; 1772 1773 // Check if ProductList exists and is an array 1774 if (!jsonQuery.ProductList || !Array.isArray(jsonQuery.ProductList) || jsonQuery.ProductList.length === 0) { 1775 return { hasAvailability: false, totalAvailability: 0, availabilityDetails: null }; 1776 } 1777 1778 var totalAvailability = 0; 1779 var hasAnyAvailability = false; 1780 var availabilityDetails = []; 1781 1782 for (var i = 0; i < jsonQuery.ProductList.length; i++) { 1783 var product = jsonQuery.ProductList[i]; 1784 var productAvailability = product.Availability || 0; 1785 var productTotal = 0; 1786 1787 // If product has SkuList, sum all SKU availabilities 1788 if (product.SkuList && Array.isArray(product.SkuList) && product.SkuList.length > 0) { 1789 for (var j = 0; j < product.SkuList.length; j++) { 1790 var sku = product.SkuList[j]; 1791 var skuAvail = sku.Availability || 0; 1792 productTotal += skuAvail; 1793 if (skuAvail > 0) { 1794 hasAnyAvailability = true; 1795 } 1796 } 1797 } else { 1798 // Product-level availability 1799 productTotal = productAvailability; 1800 if (productAvailability > 0) { 1801 hasAnyAvailability = true; 1802 } 1803 } 1804 1805 totalAvailability += productTotal; 1806 availabilityDetails.push({ 1807 productIndex: i, 1808 productAvailability: productAvailability, 1809 productTotal: productTotal, 1810 hasSkuList: !!(product.SkuList && Array.isArray(product.SkuList) && product.SkuList.length > 0) 1811 }); 1812 } 1813 1814 return { 1815 hasAvailability: hasAnyAvailability, 1816 totalAvailability: totalAvailability, 1817 availabilityDetails: availabilityDetails, 1818 productCount: jsonQuery.ProductList.length 1819 }; 1820 } catch(e) { 1821 console.error('[pxTrack] Error checking Json_Query for availability:', e); 1822 return { hasAvailability: false, totalAvailability: 0, availabilityDetails: null }; 1823 } 1824 } 1825 1826 function scan() { 1827 // THROTTLING: Evitar escaneos muy frecuentes 1828 var now = Date.now(); 1829 if (now - lastScanTime < SCAN_THROTTLE_MS) { 1830 console.debug('[pxTrack] scan() throttled (too soon after last scan)'); 1831 return; 1832 } 1833 lastScanTime = now; 1834 1835 // Check if SearchID changed (new search) - if so, reset the flag 1836 try { 1837 var currentSearchID = null; 1838 if (typeof window.px_jsonQuery !== 'undefined' && window.px_jsonQuery && window.px_jsonQuery.SearchID) { 1839 currentSearchID = String(window.px_jsonQuery.SearchID); 1840 } else { 1841 var searchIDEl = document.querySelector('#SearchID'); 1842 if (searchIDEl && searchIDEl.value) { 1843 currentSearchID = String(searchIDEl.value); 1844 } else { 1845 try {
1846 var urlParams = new URLSearchParams(location.search); 1847 currentSearchID = urlParams.get('SearchID') || null; 1848 } catch(e) {} 1849 } 1850 } 1851 1852 // If SearchID changed, reset the flags for new search 1853 if (currentSearchID && currentSearchID !== lastSearchID && lastSearchID !== null) { 1854 console.log('[pxTrack] ð New search detected (SearchID: ' + lastSearchID + ' â ' + currentSearchID + '), resetting flags'); 1855 window.__px_no_inventory_pushed = false; 1856 __px_has_inventory_pushed = false; 1857 scanCount = 0; // Reset scan count 1858 lastScanTime = 0; // Reset throttling for new search 1859 } 1860 1861 // Update lastSearchID 1862 if (currentSearchID) { 1863 lastSearchID = currentSearchID; 1864 } 1865 } catch(e) { 1866 console.error('[pxTrack] Error checking SearchID:', e); 1867 } 1868 1869 // Don't scan if event already fired (unless we just reset it) 1870 if (window.__px_no_inventory_pushed) { 1871 console.debug('[pxTrack] scan() called but event already fired, skipping'); 1872 return; 1873 } 1874 1875 // LÃmite máximo de escaneos por búsqueda 1876 if (scanCount >= MAX_SCANS_PER_SEARCH) { 1877 console.debug('[pxTrack] scan() skipped - maximum scans per search reached (' + MAX_SCANS_PER_SEARCH + ')'); 1878 return; 1879 } 1880 1881 scanCount++; 1882 // Log first few scans to confirm function is working 1883 if (scanCount <= 5) { 1884 console.log('[pxTrack] scan() executing - Scan #' + scanCount); 1885 } 1886 var shouldFire = false; 1887 var detectionMethod = ''; 1888 var debugInfo = { 1889 scanNumber: scanCount, 1890 px_jsonQuery_exists: typeof window.px_jsonQuery !== 'undefined' && !!window.px_jsonQuery, 1891 productList_length: 0, 1892 productList_details: [] 1893 }; 1894 1895 // Method 1: Check px_jsonQuery.ProductList for all Availability === 0 1896 try { 1897 if (typeof window.px_jsonQuery !== 'undefined' && window.px_jsonQuery) { 1898 debugInfo.productList_length = (window.px_jsonQuery.ProductList && Array.isArray(window.px_jsonQuery.ProductList)) ? window.px_jsonQuery.ProductList.length : 0; 1899 1900 if (checkJsonQueryAvailability()) { 1901 shouldFire = true; 1902 detectionMethod = 'Json_Query'; 1903 try { 1904 console.log('%c[pxTrack] â no_inventory DETECTED via Json_Query (all Availability === 0) - Scan #' + scanCount, 'color: #FF5722; font-weight: bold;'); 1905 } catch(_e){} 1906 } else { 1907 // Log details about why it didn't fire 1908 try { 1909 if (window.px_jsonQuery.ProductList && Array.isArray(window.px_jsonQuery.ProductList)) { 1910 var productDetails = []; 1911 for (var idx = 0; idx < Math.min(window.px_jsonQuery.ProductList.length, 3); idx++) { 1912 var p = window.px_jsonQuery.ProductList[idx]; 1913 var prodAvail = p.Availability || 0; 1914 var skuAvail = 'N/A'; 1915 if (p.SkuList && Array.isArray(p.SkuList) && p.SkuList.length > 0) { 1916 var skuAvails = []; 1917 for (var skuIdx = 0; skuIdx < p.SkuList.length; skuIdx++) { 1918 skuAvails.push(p.SkuList[skuIdx].Availability || 0); 1919 } 1920 skuAvail = skuAvails.join(','); 1921 } 1922 productDetails.push({productAvail: prodAvail, skuAvail: skuAvail}); 1923 } 1924 debugInfo.productList_details = productDetails; 1925 } 1926 } catch(e) {} 1927 } 1928 } 1929 } catch(e) { 1930 console.error('[pxTrack] Error in Json_Query availability check:', e); 1931 } 1932 1933 // Method 2: Check for specific DOM elements (most reliable) 1934 if (!shouldFire) { 1935 try { 1936 // Check for #no-inventory-container or #no-inventory (from sindispo.php) 1937 var noInventoryContainer = document.querySelector('#no-inventory-container'); 1938 var noInventoryElement = document.querySelector('#no-inventory'); 1939 if (noInventoryContainer || noInventoryElement) { 1940 shouldFire = true; 1941 detectionMethod = 'DOM element (ID)'; 1942 try { 1943 console.log('%c[pxTrack] â no_inventory DETECTED via DOM element (#no-inventory-container or #no-inventory) - Scan #' + scanCount, 'color: #FF5722; font-weight: bold;'); 1944 console.log('[pxTrack] DOM elements found:', { 1945 hasContainer: !!noInventoryContainer, 1946 hasElement: !!noInventoryElement, 1947 containerVisible: noInventoryContainer ? (noInventoryContainer.offsetParent !== null) : false, 1948 elementText: noInventoryElement ? (noInventoryElement.textContent || noInventoryElement.innerText || '').substring(0, 50) : '' 1949 }); 1950 } catch(_e){} 1951 } else if (scanCount <= 3 || scanCount % 10 === 0) { 1952 // Log when elements are not found (for debugging) 1953 try { 1954 console.debug('[pxTrack] DOM check: #no-inventory-container and #no-inventory not found (scan #' + scanCount + ')'); 1955 } catch(_e){} 1956 } 1957 } catch(e) { 1958 console.error('[pxTrack] Error in DOM element check:', e); 1959 } 1960 } 1961 1962 // Method 3: Fallback - Check DOM text for "No hay resultados" or "No results" 1963 if (!shouldFire) { 1964 try { 1965 var candidates = Array.prototype.slice.call(document.querySelectorAll('body *')); 1966 for (var i=0; i<candidates.length; i++) { 1967 var t = (candidates[i].innerText || '').trim(); 1968 if (!t) continue; 1969 if (t.indexOf('No hay resultados') !== -1 || t.indexOf('No results') !== -1) { 1970 shouldFire = true; 1971 detectionMethod = 'DOM text'; 1972 try { 1973 console.log('%c[pxTrack] â no_inventory DETECTED via DOM text - Scan #' + scanCount, 'color: #FF5722; font-weight: bold;'); 1974 } catch(_e){} 1975 break; 1976 } 1977 } 1978 } catch(e) { 1979 console.error('[pxTrack] Error in DOM text check:', e); 1980 } 1981 } 1982 1983 // Store last scan result for debugging 1984 lastScanResult = { 1985 shouldFire: shouldFire, 1986 method: detectionMethod, 1987 scanCount: scanCount, 1988 px_jsonQuery_exists: debugInfo.px_jsonQuery_exists, 1989 productList_length: debugInfo.productList_length, 1990 productList_details: debugInfo.productList_details 1991 }; 1992 1993 // Log scan details every 5th scan or when px_jsonQuery becomes available 1994 if (scanCount % 5 === 0 || (debugInfo.px_jsonQuery_exists && scanCount <= 3)) { 1995 try { 1996 console.log('[pxTrack] no_inventory scan #' + scanCount + ':', { 1997 px_jsonQuery_exists: debugInfo.px_jsonQuery_exists, 1998 productList_length: debugInfo.productList_length, 1999 shouldFire: shouldFire, 2000 method: detectionMethod 2001 }); 2002 if (debugInfo.productList_details.length > 0) { 2003 console.log('[pxTrack] Sample product availability:', debugInfo.productList_details); 2004 } 2005 } catch(_e){} 2006 } 2007 2008 if (shouldFire && !window.__px_no_inventory_pushed) { 2009 // COOLDOWN: Verificar que no se haya disparado recientemente 2010 var eventType = 'no_inventory'; 2011 var now = Date.now(); 2012 if (lastEventTime[eventType] && (now - lastEventTime[eventType] < EVENT_COOLDOWN_MS)) { 2013 console.log('[pxTrack] â¸ï¸ Event cooldown active, skipping no_inventory event (last fired ' + Math.round((now - lastEventTime[eventType]) / 1000) + 's ago)'); 2014 return; 2015 } 2016 2017 window.__px_no_inventory_pushed = true; 2018 lastEventTime[eventType] = now; // Registrar tiempo del evento 2019 2020 // Ensure dates/paxs are enriched before sending 2021 ensureContextReady(function(){ 2022 var params = getSearchParamsFromDOM(); 2023 params.no_inventory = true; 2024 try { 2025 console.log('%c[pxTrack] ð FIRING no_inventory event - Detection method: ' + detectionMethod + ' - Scan #' + scanCount, 'color: #4CAF50; font-weight: bold; font-size: 14px;'); 2026 console.log('[pxTrack] no_inventory payload:', params); 2027 console.log('[pxTrack] Last scan result:', lastScanResult); 2028 } catch(_e){} 2029 window.pxTrack('no_inventory', params); 2030 2031 // Fire form_success for search form after no_inventory 2032 setTimeout(function() { 2033 console.log('%c[pxTrack] ð FIRING form_success for search form (after no_inventory)', 'color: #4CAF50; font-weight: bold;'); 2034 window.pxTrack('form_success', { 2035 form_id: 'pxmk_searchform', 2036 lead_id: null, 2037 transaction_id: null 2038 }); 2039 }, 100); 2040 }); 2041 } 2042 2043 // OPPOSITE: Check if there IS availability (has_inventory) 2044 // Only check if no_inventory was NOT detected and has_inventory hasn't been fired yet 2045 if (!shouldFire && !__px_has_inventory_pushed && !window.__px_no_inventory_pushed) { 2046 try { 2047 // Also verify that no "no inventory" DOM elements are present 2048 var noInventoryContainer = document.querySelector('#no-inventory-container'); 2049 var noInventoryElement = document.querySelector('#no-inventory'); 2050 var hasNoInventoryDOM = !!(noInventoryContainer || noInventoryElement); 2051 2052 if (hasNoInventoryDOM) { 2053 console.debug('[pxTrack] has_inventory blocked - no inventory DOM elements present'); 2054 } else { 2055 var availabilityInfo = checkJsonQueryHasAvailability(); 2056 2057 if (availabilityInfo.hasAvailability) { 2058 // COOLDOWN: Verificar que no se haya disparado recientemente 2059 var eventType = 'has_inventory'; 2060 var now = Date.now(); 2061 if (lastEventTime[eventType] && (now - lastEventTime[eventType] < EVENT_COOLDOWN_MS)) { 2062 console.log('[pxTrack] â¸ï¸ Event cooldown active, skipping has_inventory event (last fired ' + Math.round((now - lastEventTime[eventType]) / 1000) + 's ago)'); 2063 } else { 2064 2065 __px_has_inventory_pushed = true; 2066 lastEventTime[eventType] = now; 2067 2068 // Ensure dates/paxs are enriched before sending 2069 ensureContextReady(function(){ 2070 var params = getSearchParamsFromDOM(); 2071 params.has_availability = true; 2072 params.availability = availabilityInfo.totalAvailability; 2073 params.product_count = availabilityInfo.productC
2073ount || 0; 2074 2075 // Add SearchID if available 2076 try { 2077 if (typeof window.px_jsonQuery !== 'undefined' && window.px_jsonQuery && window.px_jsonQuery.SearchID) { 2078 params.search_id = String(window.px_jsonQuery.SearchID); 2079 } 2080 } catch(e) {} 2081 2082 // Add availability details (first 3 products for debugging) 2083 if (availabilityInfo.availabilityDetails && availabilityInfo.availabilityDetails.length > 0) { 2084 params.availability_details = availabilityInfo.availabilityDetails.slice(0, 3).map(function(detail) { 2085 return { 2086 product_index: detail.productIndex, 2087 availability: detail.productTotal, 2088 has_skus: detail.hasSkuList 2089 }; 2090 }); 2091 } 2092 2093 try { 2094 console.log('%c[pxTrack] ð FIRING has_inventory event (availability detected) - Scan #' + scanCount, 'color: #4CAF50; font-weight: bold; font-size: 14px;'); 2095 console.log('[pxTrack] has_inventory payload:', params); 2096 console.log('[pxTrack] Availability info:', { 2097 totalAvailability: availabilityInfo.totalAvailability, 2098 productCount: availabilityInfo.productCount, 2099 hasAvailability: availabilityInfo.hasAvailability 2100 }); 2101 } catch(_e){} 2102 window.pxTrack('has_inventory', params); 2103 2104 // Fire form_success for search form after has_inventory 2105 setTimeout(function() { 2106 console.log('%c[pxTrack] ð FIRING form_success for search form (after has_inventory)', 'color: #4CAF50; font-weight: bold;'); 2107 window.pxTrack('form_success', { 2108 form_id: 'pxmk_searchform', 2109 lead_id: null, 2110 transaction_id: null 2111 }); 2112 }, 100); 2113 }); 2114 } 2115 } 2116 } 2117 } catch(e) { 2118 console.error('[pxTrack] Error checking for availability (has_inventory):', e); 2119 } 2120 } 2121 } 2122 2123 // Try to intercept px_jsonQuery assignment (works if px_jsonQuery is undefined) 2124 try { 2125 if (typeof window.px_jsonQuery === 'undefined') { 2126 try { 2127 var _px_jsonQuery_value = undefined; 2128 var _px_jsonQuery_lastTrigger = 0; 2129 Object.defineProperty(window, 'px_jsonQuery', { 2130 get: function() { return _px_jsonQuery_value; }, 2131 set: function(newValue) { 2132 _px_jsonQuery_value = newValue; 2133 if (newValue) { 2134 try { 2135 // Throttle interceptor triggers (máximo 1 cada 1 segundo) 2136 var now = Date.now(); 2137 if (now - _px_jsonQuery_lastTrigger < 1000) { 2138 console.debug('[pxTrack] px_jsonQuery interceptor throttled'); 2139 return; 2140 } 2141 _px_jsonQuery_lastTrigger = now; 2142 console.log('[pxTrack] px_jsonQuery was set via Object.defineProperty, triggering scan'); 2143 setTimeout(function() { scan(); }, 150); 2144 } catch(e) { 2145 console.error('[pxTrack] Error in triggerScan:', e); 2146 } 2147 } 2148 }, 2149 configurable: true, 2150 enumerable: true 2151 }); 2152 } catch(e) { 2153 console.error('[pxTrack] Object.defineProperty failed for px_jsonQuery:', e); 2154 } 2155 } 2156 } catch(e) { 2157 console.error('[pxTrack] Error setting up px_jsonQuery interception:', e); 2158 } 2159 2160 // Multiple initial scans with increasing delays (for Chrome compatibility) 2161 function runInitialScans() { 2162 console.log('%c[pxTrack] Starting initial scans for no_inventory detection...', 'color: #FF9800; font-weight: bold;'); 2163 console.log('[pxTrack] runInitialScans() called - will execute multiple scans'); 2164 // Immediate scan 2165 console.log('[pxTrack] Executing immediate scan...'); 2166 scan(); 2167 // Delayed scans to catch px_jsonQuery if it loads later AND DOM elements that load dynamically 2168 setTimeout(function() { scan(); }, 200); 2169 setTimeout(function() { scan(); }, 500); 2170 setTimeout(function() { scan(); }, 1000); 2171 setTimeout(function() { scan(); }, 2000); 2172 setTimeout(function() { scan(); }, 3000); 2173 setTimeout(function() { scan(); }, 5000); 2174 } 2175 2176 // Run initial scans after DOM is ready 2177 if (document.readyState === 'loading') { 2178 console.log('[pxTrack] DOM is loading, will wait for DOMContentLoaded'); 2179 document.addEventListener('DOMContentLoaded', function() { 2180 console.log('[pxTrack] DOMContentLoaded fired, scheduling runInitialScans() in 100ms'); 2181 setTimeout(function() { 2182 console.log('[pxTrack] Executing runInitialScans() now...'); 2183 runInitialScans(); 2184 }, 100); 2185 }); 2186 } else { 2187 console.log('[pxTrack] DOM already ready, scheduling runInitialScans() in 100ms'); 2188 setTimeout(function() { 2189 console.log('[pxTrack] Executing runInitialScans() now...'); 2190 runInitialScans(); 2191 }, 100); 2192 } 2193 2194 // Also use requestAnimationFrame for Chrome (ensures DOM is painted) 2195 if (window.requestAnimationFrame) { 2196 requestAnimationFrame(function() { 2197 setTimeout(function() { scan(); }, 500); 2198 }); 2199 } 2200 2201 // Watch for px_jsonQuery availability (reduced polling frequency to prevent rate limiting) 2202 var jsonQueryCheckStart = Date.now(); 2203 var jsonQueryCheckTimeout = 20000; // 20 seconds 2204 var jsonQueryCheckInterval = setInterval(function() { 2205 // Stop if timeout reached 2206 if (Date.now() - jsonQueryCheckStart > jsonQueryCheckTimeout) { 2207 clearInterval(jsonQueryCheckInterval); 2208 try { 2209 console.log('[pxTrack] no_inventory px_jsonQuery polling timed out after', scanCount, 'scans'); 2210 console.log('[pxTrack] Last scan result:', lastScanResult); 2211 } catch(_e){} 2212 return; 2213 } 2214 2215 // Stop if event already fired 2216 if (window.__px_no_inventory_pushed) { 2217 clearInterval(jsonQueryCheckInterval); 2218 return; 2219 } 2220 2221 // Check if px_jsonQuery is now available and scan 2222 if (typeof window.px_jsonQuery !== 'undefined' && window.px_jsonQuery) { 2223 scan(); 2224 } 2225 }, 1000); // Reduced to 1 second to prevent rate limiting 2226 2227 // Watch DOM changes and specifically look for #no-inventory-container or #no-inventory
2228 try { 2229 var mo = new MutationObserver(function(mutations) { 2230 if (window.__px_no_inventory_pushed) return; 2231 2232 // Throttling más agresivo para MutationObserver (2 segundos mÃnimo) 2233 var now = Date.now(); 2234 if (mo.__px_lastScan && (now - mo.__px_lastScan < 2000)) { 2235 return; 2236 } 2237 2238 // Check if any of the mutations added our target elements 2239 var foundTarget = false; 2240 for (var i = 0; i < mutations.length; i++) { 2241 var mutation = mutations[i]; 2242 if (mutation.addedNodes && mutation.addedNodes.length > 0) { 2243 for (var j = 0; j < mutation.addedNodes.length; j++) { 2244 var node = mutation.addedNodes[j]; 2245 if (node.nodeType === 1) { // Element node 2246 // Check if the added node is our target or contains it 2247 if (node.id === 'no-inventory-container' || node.id === 'no-inventory' || 2248 node.querySelector && (node.querySelector('#no-inventory-container') || node.querySelector('#no-inventory'))) { 2249 foundTarget = true; 2250 break; 2251 } 2252 } 2253 } 2254 } 2255 if (foundTarget) break; 2256 } 2257 2258 // If target found or if enough time passed, scan 2259 if (foundTarget || !mo.__px_lastScan || Date.now() - mo.__px_lastScan > 2000) { 2260 mo.__px_lastScan = Date.now(); 2261 if (foundTarget) { 2262 console.log('[pxTrack] MutationObserver detected #no-inventory-container or #no-inventory added to DOM'); 2263 } 2264 scan(); 2265 } 2266 }); 2267 mo.observe(document.body, { childList: true, subtree: true }); 2268 } catch(e) { 2269 console.error('[pxTrack] MutationObserver failed for no_inventory:', e); 2270 } 2271 2272 // Additional polling specifically for DOM elements (reduced frequency to prevent rate limiting) 2273 var domPollingStart = Date.now(); 2274 var domPollingTimeout = 15000; // 15 seconds 2275 var domPollingInterval = setInterval(function() { 2276 if (Date.now() - domPollingStart > domPollingTimeout) { 2277 clearInterval(domPollingInterval); 2278 return; 2279 } 2280 2281 if (window.__px_no_inventory_pushed) { 2282 clearInterval(domPollingInterval); 2283 return; 2284 } 2285 2286 // Quick check for target elements 2287 var noInventoryContainer = document.querySelector('#no-inventory-container'); 2288 var noInventoryElement = document.querySelector('#no-inventory'); 2289 if (noInventoryContainer || noInventoryElement) { 2290 console.log('[pxTrack] DOM polling detected #no-inventory-container or #no-inventory'); 2291 scan(); 2292 clearInterval(domPollingInterval); 2293 } 2294 }, 1000); // Reduced to 1 second to prevent rate limiting 2295 2296 // Confirm watcher is fully initialized 2297 console.log('%c[pxTrack] â no_inventory watcher fully initialized and ready', 'color: #4CAF50; font-weight: bold; font-size: 14px;'); 2298 console.log('[pxTrack] wireNoInventoryWatcher() completed at:', new Date().toISOString()); 2299 console.log('[pxTrack] All watchers, observers, and polling intervals are now active'); 2300 } 2301 2302 // Observe availability containers to re-enrich context after dynamic updates 2303 function observeAvailabilityContainers() { 2304 try { 2305 var targets = []; 2306 var el1 = document.querySelector('#neo_cart_results_list'); 2307 var el2 = document.querySelector('#neo_cart_pedido_container'); 2308 if (el1) targets.push(el1); 2309 if (el2) targets.push(el2); 2310 if (!targets.length || !('MutationObserver' in window)) return; 2311 var refresh = function() { 2312 enhanceContextFromHiddenInputs(); 2313 enhanceContextFromPxJson(); 2314 }; 2315 var mo = new MutationObserver(function(muts) { 2316 // throttle bursts 2317 if (mo.__px_scheduled) return; 2318 mo.__px_scheduled = true;
2319 setTimeout(function(){ mo.__px_scheduled = false; refresh(); }, 100); 2320 }); 2321 targets.forEach(function(t){ mo.observe(t, { childList: true, subtree: true }); }); 2322 // initial pass 2323 refresh(); 2324 } catch (e) {} 2325 } 2326 2327 // Init after DOM ready - LOG EARLY AND OFTEN 2328 console.log('%c[pxTrack] STEP 1: Checking DOM readyState...', 'color: #9C27B0; font-weight: bold; font-size: 14px;'); 2329 console.log('[pxTrack] document.readyState:', document.readyState); 2330 console.log('[pxTrack] wireNoInventoryWatcher function exists:', typeof wireNoInventoryWatcher); 2331 2332 if (document.readyState === 'loading') { 2333 console.log('%c[pxTrack] STEP 2: DOM is loading, setting up DOMContentLoaded listener', 'color: #9C27B0; font-weight: bold;'); 2334 document.addEventListener('DOMContentLoaded', function() { 2335 console.log('%c[pxTrack] STEP 3: DOMContentLoaded fired!', 'color: #9C27B0; font-weight: bold; font-size: 16px;'); 2336 console.log('[pxTrack] DOMContentLoaded fired, initializing watchers...'); 2337 try { 2338 wireSearchFallbacks(); 2339 wireSearchEventsWhenReady(); 2340 wireFormEvents(); 2341 wireWhatsappClick(); 2342 if (typeof wireCheckoutForm === 'function') { 2343 wireCheckoutForm(); 2344 } else { 2345 console.log('[pxTrack] wireCheckoutForm() not available (may be conditional)'); 2346 } 2347 wireDatePickers(); 2348 enhanceContextFromHiddenInputs(); 2349 enhanceContextFromPxJson(); 2350 fetchSearchInfoIfNeeded(); 2351 console.log('%c[pxTrack] STEP 4: About to call wireNoInventoryWatcher()...', 'color: #FF5722; font-weight: bold; font-size: 16px;'); 2352 try { 2353 wireNoInventoryWatcher(); 2354 console.log('%c[pxTrack] STEP 5: wireNoInventoryWatcher() completed successfully!', 'color: #4CAF50; font-weight: bold; font-size: 16px;'); 2355 } catch(e) { 2356 console.error('[pxTrack] ERROR calling wireNoInventoryWatcher():', e); 2357 console.error('[pxTrack] Error stack:', e.stack); 2358 } 2359 observeAvailabilityContainers(); 2360 // delayed retries in case modules/scripts load late 2361 setTimeout(function(){ enhanceContextFromHiddenInputs(); enhanceContextFromPxJson(); }, 500); 2362 setTimeout(function(){ enhanceContextFromHiddenInputs(); enhanceContextFromPxJson(); }, 1500); 2363 // checkout success detector (thank-you page) - multiple attempts with delays 2364 if (typeof maybePushFormSuccess === 'function') { 2365 maybePushFormSuccess(); // Immediate 2366 setTimeout(function(){ maybePushFormSuccess(); }, 500); // After 500ms 2367 setTimeout(function(){ maybePushFormSuccess(); }, 1500); // After 1.5s 2368 setTimeout(function(){ maybePushFormSuccess(); }, 3000); // After 3s (for slow loading pages) 2369 } 2370 } catch(e) { 2371 console.error('[pxTrack] Error during initialization:', e); 2372 } 2373 }); 2374 } else { 2375 console.log('%c[pxTrack] STEP 2: DOM already ready, initializing immediately', 'color: #9C27B0; font-weight: bold;'); 2376 console.log('[pxTrack] DOM already ready, initializing watchers immediately...'); 2377 try { 2378 wireSearchFallbacks(); 2379 wireSearchEventsWhenReady(); 2380 wireFormEvents(); 2381 wireWhatsappClick(); 2382 if (typeof wireCheckoutForm === 'function') { 2383 wireCheckoutForm(); 2384 } else { 2385 console.log('[pxTrack] wireCheckoutForm() not available (may be conditional)'); 2386 } 2387 wireDatePickers(); 2388 enhanceContextFromHiddenInputs(); 2389 enhanceContextFromPxJson(); 2390 fetchSearchInfoIfNeeded(); 2391 console.log('%c[pxTrack] STEP 4: About to call wireNoInventoryWatcher()...', 'color: #FF5722; font-weight: bold; font-size: 16px;'); 2392 try { 2393 wireNoInventoryWatcher(); 2394 console.log('%c[pxTrack] STEP 5: wireNoInventoryWatcher() completed successfully!', 'color: #4CAF50; font-weight: bold; font-size: 16px;'); 2395 } catch(e) { 2396 console.error('[pxTrack] ERROR calling wireNoInventoryWatcher():', e); 2397 console.error('[pxTrack] Error stack:', e.stack); 2398 } 2399 observeAvailabilityContainers();
2400 setTimeout(function(){ enhanceContextFromHiddenInputs(); enhanceContextFromPxJson(); }, 500); 2401 setTimeout(function(){ enhanceContextFromHiddenInputs(); enhanceContextFromPxJson(); }, 1500); 2402 // checkout success detector (thank-you page) - multiple attempts with delays 2403 if (typeof maybePushFormSuccess === 'function') { 2404 maybePushFormSuccess(); // Immediate 2405 setTimeout(function(){ maybePushFormSuccess(); }, 500); // After 500ms 2406 setTimeout(function(){ maybePushFormSuccess(); }, 1500); // After 1.5s 2407 setTimeout(function(){ maybePushFormSuccess(); }, 3000); // After 3s (for slow loading pages) 2408 } 2409 } catch(e) { 2410 console.error('[pxTrack] Error during initialization:', e); 2411 console.error('[pxTrack] Error stack:', e.stack); 2412 } 2413 } 2414 })(); 2415</script>
2415 2416 2417 2418<!-- Google Tag Manager -->
2419<script>
vendor: 436 bytes, lines 2419-2433
2419 2420 (function(w, d, s, l, i) { 2421 w[l] = w[l] || []; 2422 w[l].push({ 2423 'gtm.start': new Date().getTime(), 2424 event: 'gtm.js' 2425 }); 2426 var f = d.getElementsByTagName(s)[0], 2427 j = d.createElement(s), 2428 dl = l != 'dataLayer' ? '&l=' + l : ''; 2429 j.async = true; 2430 j.src = 2431 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; 2432 f.parentNode.insertBefore(j, f); 2433 })(window, document, 'script', 'dataLayer', '
2433GTM-TPTNCNX
vendor: 4 bytes, line 2433
2433');
2434</script>
2434 2435<!-- End Google Tag Manager --> 2436 2437 2438 2439 2440</head> 2441 2442<body> 2443 <!-- Google Tag Manager (noscript) -->
vendor: 69 bytes, lines 2443-2444
2443 2444 <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
2444GTM-TPTNCNX
vendor: 84 bytes, lines 2444-2445
2444" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> 2445
2445<!-- End Google Tag Manager (noscript) --> 2446 2447 2448 2449 2450 <div class="neo_loader"> 2451 <style> 2452 .linear-activity { 2453 overflow: hidden; 2454 width: 100%; 2455 height: 4px; 2456 background-color: #B3E5FC; 2457 margin: 0 2458 } 2459 2460 .determinate { 2461 position: relative; 2462 max-width: 100%; 2463 height: 100%; 2464 -webkit-transition: width .5s ease-out 1s; 2465 -moz-transition: width .5s ease-out 1s; 2466 -o-transition: width .5s ease-out 1s; 2467 transition: width .5s ease-out 1s; 2468 background-color: #03A9F4 2469 } 2470 2471 .indeterminate { 2472 position: relative; 2473 width: 100%; 2474 height: 100% 2475 } 2476 2477 .indeterminate:after, 2478 .indeterminate:before { 2479 content: ''; 2480 position: absolute; 2481 height: 100% 2482 } 2483 2484 .indeterminate:before { 2485 background-color: #03A9F4; 2486 animation: indeterminate_first 1.5s infinite ease-out 2487 } 2488 2489 .indeterminate:after { 2490 background-color: #4FC3F7; 2491 animation: indeterminate_second 1.5s infinite ease-in 2492 } 2493 2494 @keyframes indeterminate_first { 2495 0% { 2496 left: -100%; 2497 width: 100% 2498 } 2499 2500 100% { 2501 left: 100%; 2502 width: 10% 2503 } 2504 } 2505 2506 @keyframes indeterminate_second { 2507 0% { 2508 left: -150%; 2509 width: 100% 2510 } 2511 2512 100% { 2513 left: 100%; 2514 width: 10% 2515 } 2516 } 2517 2518 .neo_loader { 2519 position: fixed; 2520 top: 0; 2521 left: 0; 2522 right: 0; 2523 bottom: 0; 2524 z-index: 9999999999999999999999; 2525 background: #fff; 2526 height: 100vh; 2527 width: 100vw; 2528 display: flex; 2529 flex-direction: column; 2530 justify-content: center; 2531 align-items: center; 2532 padding: 40px; 2533 box-sizing: border-box; 2534 text-align: center; 2535 } 2536 2537 .neo_loader .loaderline { 2538 width: 400px; 2539 margin: 40px; 2540 max-width: 90vw 2541 } 2542 2543 .loadername { 2544 color: #bbb; 2545 font-family: Helvetica, Arial, sans-serif; 2546 margin: 10px auto 15px 2547 } 2548 2549 .linear-activity.gray { 2550 background-color: #eaeaea 2551 } 2552 2553 .gray .indeterminate:after, 2554 .gray .indeterminate:before { 2555 background-color: #bbb 2556 } 2557 2558 .neo_megacontainer { 2559 display: none 2560 } 2561 </style> 2562 2563 <img loading="lazy" style=" max-height: 200px; max-width: 200px; object-fit: contain; margin-bottom: 20px;" src="https://files-p.pxsol.com/23292/company/library/user/1752590028009a5ad0ff8a8337360e43ebd1a7a455d.png" alt="La Alondra Casa de huéspedes"> 2564 <div class="loadername"> 2565 La Alondra Casa de huéspedes </div> 2566 <div class="loaderline"> 2567 <div class="linear-activity gray"> 2568 <div class="indeterminate"></div> 2569 </div> 2570 </div> 2571 </div> 2572 2573 <div class="neo_megacontainer index"> 2574 2575 2576 2577 2578 2579<div class="main_wraper_top" id="main_wraper_top"> 2580 2581 2582<div class="neo_template_container neo_template_ computer"> 2583 2584 2585<div id='normalheader' class="navbar-fullwidth normalheader" ><div class="fullwidth flex flex-m-sb flex-s-center padding-xs-5" ><div class='xs-50' ><div class='pxModule_include ModuloWrap_idiomas '><div id="top_menu"> 2586 2587 <div id="contenedor_top"> 2588 <div id="menu_div_top"> 2589 <div class="nav_top flex flex-s-center"> 2590 2591 2592 <div class="selectidiomaymoneda"> 2593 <div class="currency_module_container" > 2594 <input type="hidden" id='ModuloIdioma_DefaultCurrency' value="USD"> 2595 <input type="hidden" id="ModuloIdioma_BookingEngineVersion" value="8"> 2596 <div class="texto_idiomaymoneda"> 2597 Currency - </div> 2598 <div id="deploymoneda" class="pointer deploymoneda" > 2599 <div class="monedaactual hidden" cur="USD"> 2600 USD $ </div> 2601 <div class="monedaactual hidden" cur="ARS"> 2602 ARS $ </div> 2603 </div> 2604 <div id="monedasshow" class="monedasshow"> 2605 <div class="titlemenujs"> 2606 Choose the currency of your preference </div> 2607 <div class="monedaitem changeCurrency hidden" cur="USD"> 2608 <strong>USD $</strong> 2609 <div class="monedasname"> 2610 Dólar americano </div> 2611 </div> 2612 <div class="monedaitem changeCurrency hidden" cur="ARS"> 2613 <strong>ARS $</strong> 2614 <div class="monedasname"> 2615 Peso argentino </div> 2616 </div> 2617 </div> 2618 2619 </div> 2620 <div class="texto_idiomaymoneda"> 2621 Language - </div> 2622 2623 2624 <div id="deployidioma" class="deployidioma"> 2625 <img alt="flag" style="object-fit: contain;" class="bandera" src="/css/images/bnd_en.png" height="24px" width="24px" /> 2626 </div> 2627 2628 2629 <div id="idiomasshow" class="idiomasshow"> 2630 <div class="titlemenujs"> 2631 Choose the language of your preference </div> 2632 <div class="idiomaitem"> 2633 <a class="idiomalink" lng="es" href="/?lng=es" ignorar-vista="true" style="width: 100%;"> 2634 <img class="bandera" style="object-fit: contain;" src="/css/images/bnd_es.png" height="20" width="20" alt="es" /> 2635 <span class="nameidioma"> 2636 Español </span> 2637 </a> 2638 </div> 2639 <div class="idiomaitem"> 2640 <a class="idiomalink" lng="pt" href="/pt/?lng=pt" ignorar-vista="true" style="width: 100%;"> 2641 <img class="bandera" style="object-fit: contain;" src="/css/images/bnd_pt.png" height="20" width="20" alt="pt" /> 2642 <span class="nameidioma"> 2643 Português </span> 2644 </a> 2645 </div> 2646 </div>
2647 </div> 2648 2649 2650 <a href="https://app.reservadirecto.com/auth_web?return_url=https%3A%2F%2Fwww.laalondra.com.ar%2Fauthorize.php%3Fredirect_url%3Dhttps%253A%252F%252Fwww.laalondra.com.ar%252F&origin_pos=LaAlondraCasadehuespedes" ignorar-vista="true" class="btn_sesion cta_webcheckin_px margin-sm-right-10" style="text-decoration: none"> 2651 <i class="mdi mdi-account" aria-hidden="true"></i> 2652 <span> 2653 Log in </span> 2654 </a> 2655 2656
2656<script src="https://accounts.google.com/gsi/intermediate"></script>
2656 2657
2657<script src="https://accounts.google.com/gsi/intermediatesupport"></script>
2657 2658 2659 <div id="g_id_intermediate_iframe" data-src="https://eva.reservadirecto.com/core/includes/google_one_tap_intermediate_iframe.php?origin=https%3A%2F%2Fwww.laalondra.com.ar&redirect_url=https%3A%2F%2Fwww.laalondra.com.ar%2F&pos=LaAlondraCasadehuespedes"> 2660 </div> 2661 2662 <style> 2663 .neo_login_incentive { 2664 position: fixed; 2665 top: 10rem; 2666 right: calc(1rem + 10px); 2667 width: 375px; 2668 text-align: left; 2669 z-index: 1; 2670 } 2671 2672 .neo_login_incentive>div { 2673 margin: 0; 2674 border-radius: 10px; 2675 } 2676 2677 iframe#onetap_google_intermediate_iframe, 2678 #credential_picker_container, 2679 #credential_picker_container iframe, 2680 iframe[src*="google_one_tap_intermediate_iframe"] { 2681 top: 18.5rem !important; 2682 right: 1rem !important; 2683 } 2684 2685 @media only screen and (max-width: 468px) { 2686 .neo_login_incentive { 2687 display: none !important; 2688 bottom: 0rem; 2689 top: initial; 2690 left: 0; 2691 right: 0; 2692 position: fixed; 2693 width: 100%; 2694 text-transform: initial; 2695 letter-spacing: normal; 2696 font-weight: initial; 2697 } 2698 2699 iframe#onetap_google_intermediate_iframe, 2700 #credential_picker_container, 2701 #credential_picker_container iframe, 2702 iframe[src*="google_one_tap_intermediate_iframe"] { 2703 top: initial !important; 2704 bottom: 5rem !important; 2705 right: initial !important; 2706 z-index: 1; 2707 } 2708 } 2709 </style> 2710
2710<script> 2711 (function() { 2712 var repositioned = false; 2713 var attempts = 0; 2714 var timer = setInterval(function() { 2715 if (repositioned || ++attempts > 60) { clearInterval(timer); return; } 2716 var el = document.getElementById('credential_picker_container') 2717 || document.querySelector('iframe[src*="google_one_tap_intermediate_iframe"]') 2718 || document.getElementById('onetap_google_intermediate_iframe'); 2719 if (el) { 2720 var target = (el.tagName === 'IFRAME' && el.parentElement && el.parentElement.style.position === 'fixed') ? el.parentElement : el; 2721 var isMobile = window.innerWidth <= 468; 2722 if (isMobile) { 2723 target.style.setProperty('top', 'initial', 'important'); 2724 target.style.setProperty('bottom', '5rem', 'important'); 2725 target.style.setProperty('right', 'initial', 'important'); 2726 } else { 2727 target.style.setProperty('top', '18.5rem', 'important'); 2728 target.style.setProperty('right', '1rem', 'important'); 2729 } 2730 repositioned = true; 2731 clearInterval(timer); 2732 } 2733 }, 100); 2734 })(); 2735 </script>
2735 2736 2737 </div> 2738 </div> 2739 </div> 2740 2741</div> 2742</div></div></div><div class="navbar-fullwidth navbar-top" ><ul class='nav-list' ><li class='' ><a class="item-list" href="/en/index.html" target="">The hotel</a></li><li class='' ><a class="item-list" href="/en/habitaciones.html" target="">Rooms</a></li><li class='' ><a class="item-list" href="/en/servicios.html" target="">Services</a></li></ul><div class="loguito" > <img loading="lazy" class="" lazy-src="https://files-p.pxsol.com/23292/company/library/user/122470399310b60a3f3e2b3539f6352ae0c53144521.png" alt="LaAlondraCasadehuespedes" > </image></div><ul class='nav-list' ><li class='' ><a class="item-list" href="/en/promos.html" target="">Promotions</a></li><li class='' ><a class="item-list" href="/en/contacto.html" target="">Location and contact</a></li><li class='item-submenu' ><a class="item-list" target='_blank' href="/en#" target="">Further..</a><ul class='submenu-links' ><li class='' ><a class="" target='_blank' href="https://www.laalondrai.com/" target="">The Lark</a></li><li class='' ><a class="" target='_blank' href="https://vacacion.com.ar/" target="">Vacation</a></li></ul></li></ul></div></div> 2743 2744 2745<div class="container-search" ><div id='normalsearch' class="normalsearch" ><div class='' ListSelector='false' ProductSelector='false' LocationSearch='false' BuscadorVertical='false' OwnLP='false'> 2746 <div class="neo_template_block neo_marketplace_buscador_v3 pxModule_include ModuloWrap_marketplace_buscador_v3" id="marketplace_buscador_v3" > 2747 2748 2749 <div class="px-mk-buscador-container buscar_lp "> 2750 2751 2752 2753 <form px-endpoint="https://api-1-eb-web.pxsol.io" action="https://api-1-eb-web.pxsol.io/search/insert" ajax-action="search/insert" method="post" name="pxmk_searchform" id="pxmk_searchform" class="px-mk-searchform marketplace_searchform_computer" target="_self"> 2754 <label class="error px-mk-generalerror nodisplay">An error has occurred, please try again</label> 2755 2756 2757 2758 2759 2760 <div class="fechas_ancho_entrada px-sm-inputcontainer w-padding px-mk-fixedwidth-inputcontainer"> 2761 <label class="px-mk-inputicon" for="fechaingreso"> 2762 <?xml version="1.0" encoding="iso-8859-1"?> 2763<svg version="1.1" id="Capa_1" 2764 xmlns="http://www.w3.org/2000/svg" 2765 xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 426.667 426.667" style="enable-background:new 0 0 426.667 426.667;" xml:space="preserve"> 2766 <g> 2767 <g> 2768 <g> 2769 <rect x="213.333" y="234.667" width="106.667" height="106.667"/> 2770 <path d="M362.667,42.667h-21.333V0h-42.667v42.667H128V0H85.333v42.667H64c-23.573,0-42.453,19.093-42.453,42.667L21.333,384 c0,23.573,19.093,42.667,42.667,42.667h298.667c23.573,0,42.667-19.093,42.667-42.667V85.333 C405.333,61.76,386.24,42.667,362.667,42.667z M362.667,384H64V149.333h298.667V384z"/> 2771 </g> 2772 </g> 2773 </g> 2774</svg> </label> 2775 <label class="px-mk-labelinput" for="fechaingreso"> 2776 Arrival </label> 2777 <input name="Start" type="text" style="font-size: 16px !important;" onfocus="return false;" readonly id="fechaingreso" class="" value="26/09/2026" placeholder="Check In" data-testid="date-start" /> 2778 </div> 2779 2780 <div class=" fechas_ancho_salida px-sm-inputcontainer w-padding px-mk-fixedwidth-inputcontainer"> 2781 <label class="px-mk-inputicon" for="fechaegreso"> 2782 <?xml version="1.0" encoding="iso-8859-1"?> 2783<svg version="1.1" id="Capa_1" 2784 xmlns="http://www.w3.org/2000/svg" 2785 xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 426.667 426.667" style="enable-background:new 0 0 426.667 426.667;" xml:space="preserve"> 2786 <g> 2787 <g> 2788 <g> 2789 <rect x="213.333" y="234.667" width="106.667" height="106.667"/> 2790 <path d="M362.667,42.667h-21.333V0h-42.667v42.667H128V0H85.333v42.667H64c-23.573,0-42.453,19.093-42.453,42.667L21.333,384 c0,23.573,19.093,42.667,42.667,42.667h298.667c23.573,0,42.667-19.093,42.667-42.667V85.333 C405.333,61.76,386.24,42.667,362.667,42.667z M362.667,384H64V149.333h298.667V384z"/> 2791 </g> 2792 </g> 2793 </g> 2794</svg> </label> 2795 <label class="px-mk-labelinput" for="fechaegreso"> 2796 Departure date </label> 2797 <input name="End" type="text" style="font-size: 16px !important;" onfocus="return false;" readonly id="fechaegreso" size="10" value="27/09/2026" class="relative maxzindex pointer" placeholder="Check-out" data-testid="date-end" /> 2798 </div> 2799 2800 2801 <div id="NochesError" class="error" style="display:none"></div> 2802 2803 2804 <div class="codigopromocional px-sm-inputcontainer w-padding px-mk-fixedwidth-inputcontainer"> 2805 <label class="px-mk-inputicon" for="fechaegreso"> 2806 <?xml version="1.0" encoding="iso-8859-1"?> 2807<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> 2808<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" 2809 viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"> 2810<g> 2811 <g> 2812 <path d="M32,271.692v192c0,17.664,14.368,32,32,32h160v-224H32z"/> 2813 </g> 2814</g> 2815<g> 2816 <g> 2817 <path d="M480,143.692H378.752c7.264-4.96,13.504-9.888,17.856-14.304c25.824-25.952,25.824-68.192,0-94.144 2818 c-25.088-25.28-68.8-25.216-93.856,0c-13.888,13.92-50.688,70.592-45.6,108.448h-2.304c5.056-37.856-31.744-94.528-45.6-108.448 2819 c-25.088-25.216-68.8-25.216-93.856,0C89.6,61.196,89.6,103.436,115.36,129.388c4.384,4.416,10.624,9.344,17.888,14.304H32 2820 c-17.632,0-32,14.368-32,32v48c0,8.832,7.168,16,16,16h208v-64h64v64h208c8.832,0,16-7.168,16-16v-48 2821 C512,158.06,497.664,143.692,480,143.692z M222.112,142.636c0,0-1.344,1.056-5.92,1.056c-22.112,0-64.32-22.976-78.112-36.864 2822 c-13.408-13.504-13.408-35.52,0-49.024c6.496-6.528,15.104-10.112,24.256-10.112c9.12,0,17.728,3.584,24.224,10.112 2823 C208.128,79.5,229.568,134.924,222.112,142.636z M295.776,143.692c-4.544,0-5.888-1.024-5.888-1.056 2824 c-7.456-7.712,13.984-63.136,35.552-84.832c12.896-13.024,35.456-13.088,48.48,0c13.44,13.504,13.44,35.52,0,49.024 2825 C360.128,120.716,317.92,143.692,295.776,143.692z"/> 2826 </g> 2827</g> 2828<g> 2829 <g> 2830 <path d="M288,271.692v224h160c17.664,0,32-14.336,32-32v-192H288z"/> 2831 </g> 2832</g> 2833<g> 2834</g> 2835<g> 2836</g> 2837<g> 2838</g> 2839<g> 2840</g> 2841<g> 2842</g> 2843<g> 2844</g> 2845<g> 2846</g> 2847<g> 2848</g> 2849<g> 2850</g> 2851<g> 2852</g> 2853<g> 2854</g> 2855<g> 2856</g> 2857<g> 2858</g> 2859<g> 2860</g> 2861<g> 2862</g> 2863</svg> 2864 </label> 2865 <label class="px-mk-labelinput" for="PromoCode"> 2866 Promotional code </label> 2867 <input name="Code" type="text" id="PromoCode" size="6" class="relative maxzindex pointer" data-testid="promo-code" /> 2868 </div> 2869 2870 2871 2872 <div class="nodisplay" id="Combinations">[{"Adults":1,"Childs":0,"Babies":0},{"Adults":1,"Childs":1,"Babies":0},{"Adults":1,"Childs":1,"Babies":1},{"Adults":1,"Childs":0,"Babies":1},{"Adults":2,"Childs":0,"Babies":1},{"Adults":2,"Childs":0,"Babies":0}]</div> 2873 2874<style> 2875 /* Quitar flechitas de inputs number en Chrome, Safari, Edge, Opera */ 2876 .neo_partyselector_quantity::-webkit-outer-spin-button, 2877 .neo_partyselector_quantity::-webkit-inner-spin-button { 2878 -webkit-appearance: none; 2879 margin: 0; 2880 } 2881 2882 /* Desktop - mantener original, todo en una lÃnea */ 2883 .txtPartyGroup .guests-row, 2884 .txtPartyGroup .rooms-row { 2885 display: inline; 2886 } 2887 2888 /* Nacionalidad label - desktop #000, mobile #333 */ 2889 .nacionalidad-label { 2890 color: #000 !important; 2891 } 2892 2893 @media only screen and (max-width: 650px) { 2894 .nacionalidad-label { 2895 color: #333 !important; 2896 } 2897 } 2898 2899 .txtPartyGroup .party-number { 2900 margin-right: 4px; 2901 } 2902 2903 .txtPartyGroup .party-separator { 2904 color: #999; 2905 margin: 0 4px; 2906 } 2907 2908 /* Mobile - formato de dos lÃneas mejorado */ 2909 @media only screen and (max-width: 650px) { 2910 2911 /* Ocultar separador entre huéspedes y habitaciones en mobile */ 2912 .txtPartyGroup .rooms-separator { 2913 display: none; 2914 } 2915 2916 .txtPartyGroup { 2917 display: flex; 2918 flex-direction: column; 2919 align-items: flex-start; 2920 gap: 2px; 2921 font-size: 15px; 2922 line-height: 1.4;
2923 color: #555; 2924 } 2925 2926 .txtPartyGroup .guests-row { 2927 display: flex; 2928 align-items: center; 2929 flex-wrap: wrap; 2930 } 2931 2932 .txtPartyGroup .party-item { 2933 display: inline-flex; 2934 align-items: baseline; 2935 white-space: nowrap; 2936 } 2937 2938 .txtPartyGroup .party-number { 2939 font-weight: 700; 2940 color: #333; 2941 margin-right: 4px; 2942 } 2943 2944 .txtPartyGroup .party-label { 2945 color: #666; 2946 } 2947 2948 .txtPartyGroup .party-separator { 2949 color: #ccc; 2950 margin: 0 8px; 2951 } 2952 2953 .txtPartyGroup .rooms-row { 2954 display: block; 2955 color: #666; 2956 margin: 0; 2957 padding: 0; 2958 text-align: left; 2959 } 2960 2961 .SelectorInitial { 2962 min-height: 65px; 2963 padding: 12px 45px 12px 14px; 2964 display: flex; 2965 align-items: center; 2966 } 2967 2968 .PartyTypeSimulatorContainer { 2969 overflow: visible; 2970 } 2971 2972 /* Ajuste para los labels del selector */ 2973 .neo_party_selector>div:first-child { 2974 display: flex; 2975 flex-direction: column; 2976 min-width: 0; 2977 } 2978 2979 .neo_party_selector>div:first-child>div { 2980 white-space: nowrap; 2981 overflow: visible; 2982 font-size: 14px; 2983 font-weight: 500; 2984 } 2985 2986 .neo_party_selector>div:first-child>div:last-child { 2987 font-size: 12px; 2988 color: #888; 2989 margin-top: 3px; 2990 white-space: nowrap; 2991 font-weight: 400; 2992 } 2993 2994 /* Asegurar que en mobile los controles sigan alineados a la derecha */ 2995 .neo_party_selector { 2996 display: flex; 2997 justify-content: space-between; 2998 align-items: center; 2999 width: 100%; 3000 margin-bottom: 14px; 3001 padding-bottom: 14px; 3002 border-bottom: 1px solid #f0f0f0; 3003 } 3004 3005 .neo_party_selector:last-of-type { 3006 border-bottom: none; 3007 margin-bottom: 0; 3008 padding-bottom: 0; 3009 } 3010 3011 .neo_party_selector>div:last-child { 3012 display: flex; 3013 align-items: center; 3014 justify-content: flex-end; 3015 flex-shrink: 0; 3016 margin-left: 15px; 3017 } 3018 3019 .neo_party_selector .flex.flex-s-center { 3020 display: flex; 3021 align-items: center; 3022 gap: 4px; 3023 } 3024 } 3025 3026 /* Estilos para alinear correctamente los controles numéricos */ 3027 .neo_party_selector { 3028 display: flex !important; 3029 justify-content: space-between !important; 3030 align-items: center !important; 3031 width: 100% !important; 3032 margin-bottom: 15px !important; 3033 } 3034 3035 .neo_party_selector>div:first-child { 3036 flex: 1 !important; 3037 min-width: 0 !important; 3038 } 3039 3040 .neo_party_selector>div:last-child { 3041 display: flex !important; 3042 align-items: center !important; 3043 justify-content: flex-end !important; 3044 flex-shrink: 0 !important; 3045 margin-left: 15px !important; 3046 } 3047 3048 /* Asegurar que los botones y input estén alineados correctamente */ 3049 .neo_party_selector .flex.flex-s-center { 3050 display: flex !important; 3051 align-items: center !important; 3052 gap: 3px !important; 3053 } 3054</style> 3055 3056<div class="relative PartyTypeSimulatorContainer"> 3057 <div class="PartyTypeSimulator px-sm-inputcontainer w-padding" style="border-right: none" maxadult="4" maxchild="0" maxrooms="4"> 3058 <div class="SelectorInitial" data-testid="guest-selector-trigger"> 3059 <span class="txtPartyGroup" style="align-items: flex-start !important;"> 3060 <span class="guests-row"> 3061 <span class="party-item txtAdults"> 3062 <span class="party-number numberAdults">2</span> 3063 <span class="party-label txtAdultsTxt" plural="Adults" singular="adult"> 3064 Adults </span> 3065 </span> 3066 <span class="party-item txtChildren" style="display:none;"> 3067 <span class="party-separator">â¢</span> 3068 <span class="party-number numberChildren">0</span> 3069 <span class="party-label txtChildrenTxt" plural="Children" singular="boy"> 3070 boy </span> 3071 </span> 3072 <span class="party-item txtBabies" style="display:none;"> 3073 <span class="party-separator">â¢</span> 3074 <span class="party-number numberBabies">0</span> 3075 <span class="party-label txtBabiesTxt" plural="bebés" singular="bebé"> 3076 bebé </span> 3077 </span> 3078 </span> 3079 <span class="rooms-separator party-separator">â¢</span> 3080 <span class="rooms-row txtRooms"> 3081 <span class="party-number numberRooms">1</span> 3082 <span 3083 class="party-label txtRoomsTxt" 3084 plural="rooms" 3085 singular="room"> 3086 room </span> 3087 </span> 3088 </span> 3089 <label class='ignoreclick px-mk-inputicon'> 3090 <?xml version="1.0" encoding="iso-8859-1"?> 3091<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> 3092<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" 3093 viewBox="0 0 426.667 426.667" style="enable-background:new 0 0 426.667 426.667;" xml:space="preserve"> 3094<g> 3095 <g> 3096 <g> 3097 <path d="M309.333,213.333c29.44,0,53.12-23.893,53.12-53.333s-23.68
3097-53.333-53.12-53.333S256,130.56,256,160 3098 S279.893,213.333,309.333,213.333z"/> 3099 <path d="M149.333,192c35.307,0,63.787-28.693,63.787-64c0-35.307-28.48-64-63.787-64s-64,28.693-64,64 3100 C85.333,163.307,114.027,192,149.333,192z"/> 3101 <path d="M149.333,234.667C99.52,234.667,0,259.627,0,309.333v53.333h149.333v-48c0-18.133,7.147-49.813,50.56-74.027 3102 C181.333,236.693,163.307,234.667,149.333,234.667z"/> 3103 <path d="M309.333,256C270.187,256,192,275.627,192,314.667v48h234.667v-48C426.667,275.627,348.48,256,309.333,256z"/> 3104 </g> 3105 </g> 3106</g> 3107<g> 3108</g> 3109<g> 3110</g> 3111<g> 3112</g> 3113<g> 3114</g> 3115<g> 3116</g> 3117<g> 3118</g> 3119<g> 3120</g> 3121<g> 3122</g> 3123<g> 3124</g> 3125<g> 3126</g> 3127<g> 3128</g> 3129<g> 3130</g> 3131<g> 3132</g> 3133<g> 3134</g> 3135<g> 3136</g> 3137</svg> 3138 </label> 3139 </div> 3140 </div> 3141 <div class="PartyTypeSimulatorSelect nodisplay padding-xs-20"> 3142 <div class="flex-column full"> 3143 <div class="neo_party_selector neo_adults_selector flex flex-m-sb flex-s-center"> 3144 <div> 3145 <div>Adults</div> 3146 <div style="font-size: 11px; color: #888; margin-top: 2px;"> 3147 13 años o más </div> 3148 </div> 3149 <div class="flex flex-s-center"> 3150 <button onclick="alterPartyGroup(this);" class="neo_button_partyselector neo_minus_button" type='button' party-type="adults" action-type='minus' data-testid="adults-minus">-</button> 3151 <input type="number" inputmode="numeric" query-default="2" class="neo_partyselector_quantity" party-type="adults" val="2" value="2" onchange="handlePartyInputChange(this);" min="1" max="4" style="background-color: #f8f8f8 !important; border-radius: 10px !important; width: 50px !important; height: 42px !important; margin: 0 3px !important; padding: 0 !important; border: none; text-align: center !important; -moz-appearance: textfield !important;" data-testid="adults-input" /> 3152 <button onclick="alterPartyGroup(this);" class="neo_button_partyselector neo_plus_button" type='button' party-type="adults" action-type='plus' data-testid="adults-plus">+</button> 3153 </div> 3154 </div> 3155 <div class="neo_party_selector neo_adults_selector flex flex-m-sb flex-s-center"> 3156 <div>Rooms</div> 3157 <div class="flex flex-s-center"> 3158 <button onclick="alterPartyGroup(this);" class="neo_button_partyselector neo_minus_button" type='button' party-type="rooms" action-type='minus' data-testid="rooms-minus">-</button> 3159 <input type="number" inputmode="numeric" class="neo_partyselector_quantity" party-type="rooms" val="1" value="1" onchange="handlePartyInputChange(this);" min="1" max="4" style="background-color: #f8f8f8 !important; border-radius: 10px !important; width: 50px !important; height: 42px !important; margin: 0 3px !important; padding: 0 !important; border: none; text-align: center !important; -moz-appearance: textfield !important;" data-testid="rooms-input" /> 3160 <button onclick="alterPartyGroup(this);" class="neo_button_partyselector neo_plus_button" type='button' party-type="rooms" action-type='plus' data-testid="rooms-plus">+</button> 3161 </div> 3162 </div> 3163 </div> 3164 <div class="ChildrenAgesContainer nodisplay"> 3165 <div class="flex-column"> 3166 <div class="texto padding-xs-bottom-20" style="font-size: 12px !important;">How old are the children you are traveling with?</div> 3167 <div class="ChildrensAges" child-id="0" style="max-height: 200px !important; overflow-y: auto !important; padding-right: 5px !important;"> 3168 <div class="ChildrensAgesSelectContainer" child-id="0" style="margin-bottom: 10px !important;"> 3169 <select class="ChildrensAgeSelect" child-id="0" onchange="alterPartyGroup()" style="color: #444 !important; background-color: transparent !important; padding: 10px 8px !important; border: 1px solid #ddd !important; border-radius: 8px !important; width: 100% !important;" data-testid="child-age-select"> 3170 <option value="" disabled selected>Age on check-out day</option> 3171 <option value="0">0 years</option> 3172 <option value="1">1 year</option> 3173 <option value="2">2 years</option> 3174 <option value="3">3 years</option> 3175 <option value="4">4 years</option> 3176 <option value="5">5 years</option> 3177 <option value="6">6 years</option> 3178 <option value="7">7 years</option> 3179 <option value="8">8 years</option> 3180 <option value="9">9 years</option> 3181 <option value="10">10 years</option> 3182 <option value="11">11 years</option> 3183 <option value="12">12 years</option> 3184 </select> 3185 </div>
3186 </div> 3187 <div class="NotValidChildrens nodisplay animated shake"><i class="fa fa-exclamation" aria-hidden="true"></i> Select age of minors please</div> 3188 </div> 3189 </div> 3190 3191 3192 3193 </div> 3194 3195</div> 3196
3197<script> 3198 // Global flag to track if ages have been initialized 3199 var childrenAgesInitialized = false; 3200 3201 // Function to initialize children ages from GroupsForm 3202 function initializeChildrenAgesFromGroupsForm(force) { 3203 // Only initialize once unless forced 3204 if (childrenAgesInitialized && !force) { 3205 return; 3206 } 3207 3208 try { 3209 } catch (e) { 3210 console.error('Error initializing children ages:', e); 3211 } 3212 } 3213 3214 // Call initialization on page load (in case selects already exist) 3215 $(document).ready(function() { 3216 // Wait a bit to ensure selects are created 3217 setTimeout(function() { 3218 initializeChildrenAgesFromGroupsForm(); 3219 }, 100); 3220 }); 3221</script>
3221 3222 <input name="MaxRooms" type="hidden" id="MaxRooms" value="4" /> 3223 <input name="Nights" type="hidden" id="Nights" /> 3224 <input name="Channel" type="hidden" id="Channel" value="2" /> 3225 <input name="RateType" type="hidden" id="RateType" value="auto" /> 3226 <input name="Pos" type="hidden" id="Pos" value='LaAlondraCasadehuespedes' /> 3227 <input name="Lng" type="hidden" id="Lng" value='en' /> 3228 <input name="Currency" type="hidden" id="Currency" value="USD" /> 3229 <input name="MaxAgeChildrenNumber" type="hidden" id="MaxAgeChildrenNumber" value="12" /> 3230 <input name="MaxAgeBabiesNumber" type="hidden" id="MaxAgeBabiesNumber" value="3" /> 3231 <input name="MaxBabiesNumber" type="hidden" id="MaxBabiesNumber" value="2" /> 3232 <input name="ReturnUrl" type="hidden" id="ReturnUrl" value="https://www.laalondra.com.ar/en/lp.html" /> 3233 3234 <input name="FromUrl" type="hidden" id="FromUrl" value="https://www.laalondra.com.ar/" /> 3235 <input name="Tag" type="hidden" id="Tag" value="" /> 3236 <input name="Source" id="Source" type="hidden" value="Contact Form"> 3237 3238 <input name="ProductTimezone" id="ProductTimezone" type="hidden" value="America/Argentina/Buenos_Aires"> 3239 <input name="GlobalDaysModifier" id="GlobalDaysModifier" type="hidden" value="0"> 3240 3241 <input name="SearchID" type="hidden" id="SearchID" value="0" /> 3242 3243 <input name="FromPID" type="hidden" id="FromPID" value="24325" /> 3244 3245 <input name="Type" type="hidden" id="Type" value="Hotel" /> 3246 3247 3248 <input name="ProductID" type="hidden" id="ProductID" value="24325" /> 3249 3250 <input name="ListID" type="hidden" id="ListID" value="0" /> 3251 3252 <input name="Location" type="hidden" id="Location" value="" /> 3253 3254 <input name="Device" type="hidden" id="Device" value="Computer" /> 3255 <input name="UserID" type="hidden" id="UserID" value="0" /> 3256 <input name="tag" type="hidden" id="tag" class="tag_cookie" value="" /> 3257 <input name="Email" type="hidden" id="Email" value="" /> 3258 <input name="UserType" type="hidden" id="UserType" value="" /> 3259 <input name="AgreementType" type="hidden" id="AgreementType" value="" /> 3260 3261 <input name="GroupsForm" type="hidden" id="GroupsForm" value="1:2,0,0" /> 3262 3263 3264 3265 3266 3267 3268 <input name="SkuID" type="hidden" id="SkuID" value="" /> 3269 3270 3271 <div class="nodisplay" id="MinNightsError"> 3272 The minimum number of nights must be greater than or equal to 0 </div> 3273 3274 <input name="MinNights" type="hidden" id="MinNights" value="0" /> 3275 3276 <div name="PxMkAcion_Search" id="PxMkAcion_Search" class="px-sm-searchbtn px-sm-inputcontainer w-padding px-mk-fixedwith-inputcontainer cta_webcheckin_px" btntxt="Check Rates" loadingbtntxt="Searching" data-testid="search-button"> 3277 <span class="update-search-span">Check Rates</span> 3278 <label for="" class="px-mk-searchicon px-mk-inputicon ignoreclick"> 3279 <?xml version="1.0" encoding="iso-8859-1"?> 3280<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> 3281<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" 3282 viewBox="0 0 373.12 373.12" style="enable-background:new 0 0 373.12 373.12;" xml:space="preserve"> 3283<g> 3284 <g> 3285 <path d="M266.667,234.667h-16.96l-5.867-5.867c20.907-24.213,33.493-55.68,33.493-90.133C277.333,62.08,215.253,0,138.667,0 3286 S0,62.08,0,138.667s62.08,138.667,138.667,138.667c34.453,0,65.92-12.587,90.133-33.387l5.867,5.867v16.853L341.333,373.12 3287 l31.787-31.787L266.667,234.667z M138.667,234.667c-53.013,0-96-42.987-96-96c0-53.013,42.987-96,96-96c53.013,0,96,42.987,96,96 3288 C234.667,191.68,191.68,234.667,138.667,234.667z"/> 3289 </g> 3290</g> 3291<g> 3292</g> 3293<g> 3294</g> 3295<g> 3296</g> 3297<g> 3298</g> 3299<g> 3300</g> 3301<g> 3302</g> 3303<g> 3304</g> 3305<g> 3306</g> 3307<g> 3308</g> 3309<g> 3310</g> 3311<g> 3312</g> 3313<g> 3314</g> 3315<g> 3316</g> 3317<g> 3318</g> 3319<g> 3320</g> 3321</svg> 3322 </label> 3323 <label for="" class="px-mk-searchloader px-mk-inputicon nodisplay ignoreclick"> 3324 <?xml version="1.0" encoding="iso-8859-1"?> 3325<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> 3326<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 3327<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" 3328 width="26.349px" height="26.35px" viewBox="0 0 26.349 26.35" style="enable-background:new 0 0 26.349 26.35;" 3329 xml:space="preserve"> 3330<g> 3331 <g> 3332 <circle cx="13.792" cy="3.082" r="3.082"/> 3333 <circle cx="13.792" cy="24.501" r="1.849"/> 3334 <circle cx="6.219" cy="6.218" r="2.774"/> 3335 <circle cx="21.365" cy="21.363" r="1.541"/> 3336 <circle cx="3.082" cy="13.792" r="2.465"/> 3337 <circle cx="24.501" cy="13.791" r="1.232"/> 3338 <path d="M4.694,19.84c-0.843,0.843-0.843,2.207,0,3.05c0.842,0.843,2.208,0.843,3.05,0c0.843-0.843,0.843-2.207,0-3.05 3339 C6.902,18.996,5.537,18.988,4.694,19.84z"/> 3340 <circle cx="21.364" cy="6.218" r="0.924"/> 3341 </g> 3342</g> 3343<g> 3344</g> 3345<g> 3346</g> 3347<g> 3348</g> 3349<g> 3350</g> 3351<g> 3352</g> 3353<g> 3354</g> 3355<g> 3356</g> 3357<g> 3358</g> 3359<g> 3360</g> 3361<g> 3362</g> 3363<g> 3364</g> 3365<g> 3366</g> 3367<g> 3368</g> 3369<g> 3370</g> 3371<g> 3372</g> 3373</svg> 3374 </label>
3375 </div> 3376 3377 </form> 3378 3379 <input type="hidden" id="MainPos" value="LaAlondraCasadehuespedes"> 3380 3381 3382 </div> 3383 3384 3385 3386<div id="dataconfig" product-timezone="America/Argentina/Buenos_Aires" urldispo="id=24325&RateID=49863&start=2026-09-26" class="nodisplay" lng="en" DatePickerStart="0"></div> 3387 3388<link rel="stylesheet" href="https://unpkg.com/tippy.js@6/animations/scale.css" />
3389<script src="https://unpkg.com/@popperjs/core@2"></script>
vendor: 1 bytes, line 3389
3389
3390<script src="https://unpkg.com/tippy.js@6"></script>
3390 3391
3391<script defer src="/neo_modules/marketplace_buscador_v8/js.js?filev=1778144039" type="text/javascript"></script>
3391 3392<style>/* ------------ VARIABLES ------------ */ 3393@import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"); 3394.px-mk-buscador-container { 3395 font-size: 12px; 3396} 3397 3398#MinNightsError { 3399 float: left; 3400 width: calc(100% - 22px); 3401 padding: 10px; 3402 border: 1px solid #982828; 3403 line-height: 20px; 3404 background: #f3e8e8; 3405 color: #000; 3406} 3407 3408.NotValidChildrens { 3409 width: 100%; 3410 float: left; 3411 text-align: center; 3412 color: #800; 3413 font-size: 1em; 3414 font-weight: bold; 3415 padding: 10px 0px; 3416} 3417 3418.update-search-span { 3419 font-weight: 400; 3420 margin-right: 10px; 3421} 3422 3423.ChildrensAgesSelect.notvalid { 3424 border: 1px solid #b51212 !important; 3425} 3426 3427.buscar_lp .buscar_lp_beforerate { 3428 display: none; 3429} 3430 3431.buscar_lp .NochesError { 3432 display: none; 3433} 3434 3435#NochesError { 3436 background: white; 3437 border-right: 1px solid #ccc; 3438 display: flex; 3439 justify-content: center; 3440 align-items: center; 3441} 3442 3443.buscar_lp .TextoFormulario { 3444 float: left; 3445 width: auto; 3446 margin-right: 10px; 3447 text-transform: capitalize; 3448 padding-top: 5px; 3449 font-size: 13px; 3450} 3451 3452.buscar_lp .imput_text_rooms { 3453 font-size: 1em; 3454 padding: 4px 2px; 3455 border: 1px solid #eaeaea; 3456 margin-right: 10px; 3457 float: left; 3458 max-width: 35px; 3459} 3460 3461.buscar_lp .roomtypecontariner { 3462 float: left; 3463 width: auto; 3464} 3465 3466.buscar_lp .bucle { 3467 float: left; 3468 width: auto; 3469} 3470 3471.button_bucar { 3472 float: right; 3473 width: auto; 3474 border: 1px solid #999; 3475 font-size: 14px; 3476 padding: 4px 10px; 3477 background: #eaeaea; 3478 color: #000; 3479} 3480 3481.button_bucar:hover { 3482 background: #999; 3483 color: #fff; 3484 cursor: pointer; 3485} 3486 3487.ContenidoHab { 3488 overflow: hidden; 3489 width: 100%; 3490 margin-bottom: 5px; 3491} 3492 3493.px-mk-buscador-container.buscar_lp .SelectorInitial { 3494 padding: 1em; 3495 margin: 0; 3496 cursor: pointer; 3497 border: none; 3498 box-sizing: border-box; 3499 font-size: 1.1em; 3500 text-overflow: ellipsis; 3501 overflow: hidden; 3502 min-width: 150px; 3503 text-align: left; 3504 padding-right: 2rem !important; 3505 width: 100%; 3506 height: 100%; 3507 display: flex; 3508 background: transparent !important; 3509 align-items: center; 3510} 3511.px-mk-buscador-container.buscar_lp .SelectorInitial .texto { 3512 font-weight: bold; 3513} 3514 3515.px-mk-buscador-container.buscar_lp .RoomsSelectContainer { 3516 width: 100%; 3517 padding-bottom: 5px; 3518 margin-bottom: 5px; 3519 border-bottom: 1px dotted #ccc; 3520 display: flex; 3521 align-items: center; 3522} 3523.px-mk-buscador-container.buscar_lp .RoomsSelectContainer .RoomNameContainer { 3524 width: calc(40% - 10px); 3525 margin-right: 10px; 3526 text-transform: capitalize; 3527 font-size: 1em; 3528 color: #444; 3529} 3530.px-mk-buscador-container.buscar_lp .RoomsSelectContainer .texto { 3531 float: left; 3532 width: 100%; 3533 padding-bottom: 3px; 3534 font-size: 14px; 3535 color: #444; 3536} 3537.px-mk-buscador-container.buscar_lp .RoomsSelectContainer select { 3538 border: 1px solid #d0d0d0; 3539 width: 100%; 3540 border-radius: 4px; 3541 padding: 2px; 3542 color: #666; 3543 font-size: 11px; 3544 margin-bottom: 5px; 3545 cursor: pointer; 3546} 3547.px-mk-buscador-container.buscar_lp .RoomsSelectContainer .hostContainer { 3548 width: 60%; 3549} 3550.px-mk-buscador-container.buscar_lp .RoomsSelectContainer .hostContainer .hostPeopleContainer .AdultsContainer, 3551.px-mk-buscador-container.buscar_lp .RoomsSelectContainer .hostContainer .hostPeopleContainer .ChildrensContainers { 3552 display: flex; 3553 flex-direction: column; 3554 justify-content: center; 3555 align-items: center; 3556 flex: 1; 3557 margin: 3px; 3558} 3559.px-mk-buscador-container.buscar_lp .RoomsSelectContainer .hostContainer .hostPeopleContainer .AdultsContainer > *, 3560.px-mk-buscador-container.buscar_lp .RoomsSelectContainer .hostContainer .hostPeopleContainer .ChildrensContainers > * { 3561 flex-grow: 1; 3562 width: 100%; 3563} 3564.px-mk-buscador-container.buscar_lp .RoomsSelectContainer .hostContainer .ChildrensAges { 3565 float: left; 3566 width: 100%; 3567 margin-top: 5px; 3568} 3569.px-mk-buscador-container.buscar_lp .RoomsSelectContainer .hostContainer .ChildrensAges .ChildrensAgesSelect { 3570 float: left; 3571 width: calc(50% - 5px) !important; 3572 margin-right: 5px; 3573 margin-bottom: 5px; 3574} 3575.px-mk-buscador-container.buscar_lp .RoomsSelectContainer .hostContainer .ChildrensAges .ChildrensAgesSelect:nth-child(even) { 3576 float: right !important; 3577 margin-right: 0px; 3578} 3579.px-mk-buscador-container.buscar_lp .RoomsSelectContainer .hostContainer .ChildrensAges .texto { 3580 float: left; 3581 width: 100%; 3582 padding-bottom: 3px; 3583 font-size: 14px; 3584 color: #444; 3585} 3586 3587.px-mk-buscador-container.buscar_lp .px-mk-addnewroom, 3588.px-mk-buscador-container.buscar_lp .px-mk-removeroom { 3589 flex: 1; 3590 cursor: pointer; 3591 margin: 3px; 3592} 3593.px-mk-buscador-container.buscar_lp .px-mk-addnewroom.nodisplay, 3594.px-mk-buscador-container.buscar_lp .px-mk-removeroom.nodisplay { 3595 display: none; 3596} 3597.px-mk-buscador-container.buscar_lp .px-mk-addnewroom svg, 3598.px-mk-buscador-container.buscar_lp .px-mk-removeroom svg { 3599 height: 18px; 3600 width: 18px; 3601 fill: currentColor; 3602 margin-left: 3px; 3603} 3604.px-mk-buscador-container.buscar_lp .px-mk-addnewroom button, 3605.px-mk-buscador-container.buscar_lp .px-mk-removeroom button { 3606 width: 100%; 3607 display: flex; 3608 align-items: center; 3609 justify-content: center; 3610 text-align: center; 3611 background: #f3f3f3; 3612 border: 1px solid #ccc; 3613 padding: 5px 0px; 3614 box-sizing: border-box; 3615 border-radius: 30px; 3616 color: #444; 3617 font-size: 0.9em; 3618 text-transform: capitalize; 3619 cursor: pointer; 3620} 3621.px-mk-buscador-container.buscar_lp .px-mk-addnewroom button span, 3622.px-mk-buscador-container.buscar_lp .px-mk-removeroom button span { 3623 text-transform: capitalize; 3624 line-height: 1; 3625} 3626 3627.px-mk-buscador-container.buscar_lp { 3628 display: flex; 3629 align-items: center; 3630 height: 100%; 3631 padding: 3px; 3632 box-sizing: border-box; 3633 transition: 0.3s ease-out; 3634} 3635.px-mk-buscador-container.buscar_lp #MultiplePartySelect { 3636 float: left; 3637 flex-direction: column; 3638 display: flex; 3639 width: calc(100% - 12px); 3640 padding: 5px; 3641 background: #fff; 3642 border: 1px solid #ddd; 3643 margin: 0px; 3644 position: absolute; 3645 top: 100%; 3646 min-width: 250px; 3647 z-index: 11; 3648 box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08); 3649} 3650.px-mk-buscador-container.buscar_lp #MultiplePartySelect.nodisplay { 3651 display: none; 3652} 3653.px-mk-buscador-container.buscar_lp .PartyTypeSimulatorSelect { 3654 background: #fff; 3655 border: 1px solid #ddd; 3656 margin: 0px; 3657 position: absolute; 3658 top: 100%; 3659 left: 0; 3660 display: flex; 3661 z-index: 99; 3662 flex-direction: column; 3663} 3664.px-mk-buscador-container.buscar_lp .PartyTypeSimulatorSelect .px-sm-inputcontainer { 3665 height: 50px;
3666 border-right: none; 3667 border-bottom: 1px solid #ccc; 3668 cursor: pointer; 3669 padding: 1em 4em 1em 1em; 3670 box-sizing: border-box; 3671} 3672.px-mk-buscador-container.buscar_lp .PartyTypeSimulatorSelect .px-sm-inputcontainer:last-child { 3673 border-bottom: none; 3674} 3675.px-mk-buscador-container.buscar_lp .PartyTypeSimulatorSelect .px-sm-inputcontainer .texto { 3676 padding: 0px; 3677 display: flex; 3678 align-items: center; 3679 text-align: left; 3680 font-size: 14px; 3681 color: #888; 3682} 3683.px-mk-buscador-container.buscar_lp .PartyTypeSimulatorSelect .px-sm-inputcontainer .texto:hover { 3684 color: #444; 3685} 3686.px-mk-buscador-container.buscar_lp .PartyTypeSimulatorSelect.nodisplay { 3687 display: none; 3688} 3689.px-mk-buscador-container.buscar_lp .px-mk-searchform { 3690 float: none; 3691 width: auto; 3692 display: flex; 3693 align-items: center; 3694 height: 60px; 3695 box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08); 3696} 3697.px-mk-buscador-container.buscar_lp .px-mk-searchform > * { 3698 height: 100%; 3699 margin: 0; 3700 float: none; 3701 position: relative; 3702 flex-shrink: 0; 3703 flex-grow: 1; 3704} 3705.px-mk-buscador-container.buscar_lp .px-mk-searchform .px-sm-searchbtn { 3706 min-width: 18em; 3707} 3708 3709.ModuloWrap_marketplace_buscador_v3.isolate::after { 3710 content: ""; 3711 position: fixed; 3712 top: 0; 3713 left: 0; 3714 width: 100vw; 3715 height: 100vh; 3716 background: rgba(0, 0, 0, 0.3); 3717 z-index: -1; 3718 bottom: 0; 3719 right: 0; 3720 -webkit-backdrop-filter: blur(5px); 3721 backdrop-filter: blur(5px); 3722 animation: appearIsolate 1s cubic-bezier(0.165, 0.84, 0.44, 1) forwards; 3723} 3724 3725@keyframes appearIsolate { 3726 from { 3727 opacity: 0; 3728 } 3729 to { 3730 opacity: 1; 3731 } 3732} 3733.px-sm-inputcontainer { 3734 display: flex; 3735 position: relative; 3736 border-right: 1px solid #ccc; 3737 transition: 0.3s ease-out; 3738 cursor: pointer; 3739 flex-direction: column; 3740 justify-content: center; 3741 align-items: flex-start; 3742 text-align: left; 3743 box-sizing: border-box; 3744 background-color: white; 3745} 3746.px-sm-inputcontainer .hasDatepicker { 3747 cursor: pointer !important; 3748} 3749.px-sm-inputcontainer input { 3750 border-bottom: none !important; 3751 box-shadow: none !important; 3752} 3753.px-sm-inputcontainer label.error { 3754 background: #bf0000; 3755 float: none; 3756 min-width: 100%; 3757 margin: 0px; 3758 left: 0; 3759 padding: 10px 20px; 3760 box-sizing: border-box; 3761 top: 100%; 3762 bottom: initial; 3763 right: auto; 3764 transform: translatey(0); 3765 color: white; 3766 font-weight: 400; 3767 text-transform: uppercase; 3768 font-size: 10px; 3769 letter-spacing: 2px; 3770 position: absolute; 3771 line-height: 1.6em; 3772} 3773.px-sm-inputcontainer.px-mk-fixedwidth-inputcontainer { 3774 width: 11em; 3775} 3776.px-sm-inputcontainer.px-mk-fixedwidth-inputcontainer-max { 3777 width: 18em; 3778} 3779.px-sm-inputcontainer.w-padding { 3780 padding: 0.6em 1em; 3781} 3782.px-sm-inputcontainer .px-mk-labelinput { 3783 margin-bottom: 3px; 3784 font-size: 13px; 3785 opacity: 1; 3786 cursor: pointer; 3787 margin-top: 3px; 3788} 3789.px-sm-inputcontainer .px-mk-inputicon { 3790 position: absolute; 3791 z-index: 2; 3792 right: 1.2em; 3793 color: #aaa; 3794 top: 50%; 3795 transform: translatey(-50%); 3796 font-size: 1.2em; 3797 transition: 0.3s ease-out; 3798 cursor: pointer; 3799} 3800.px-sm-inputcontainer .px-mk-inputicon svg { 3801 height: 1.2em; 3802 width: 1.2em; 3803 fill: currentColor; 3804} 3805.px-sm-inputcontainer.nodisplay { 3806 display: none; 3807} 3808.px-sm-inputcontainer:last-child { 3809 border-right: none; 3810} 3811.px-sm-inputcontainer input, 3812.px-sm-inputcontainer select, 3813.px-sm-inputcontainer textarea { 3814 position: relative; 3815 -webkit-appearance: none; 3816 -moz-appearance: none; 3817 border: none; 3818 box-sizing: border-box; 3819 font-size: 1.1em; 3820 text-overflow: ellipsis; 3821 height: auto; 3822 transition: inherit; 3823 background-color: transparent; 3824 max-width: 100%; 3825 width: 100%; 3826} 3827.px-sm-inputcontainer input option, 3828.px-sm-inputcontainer select option, 3829.px-sm-inputcontainer textarea option { 3830 background-color: #fff; 3831} 3832.px-sm-inputcontainer input[type=text]:not(.hasDatepicker), 3833.px-sm-inputcontainer select[type=text]:not(.hasDatepicker), 3834.px-sm-inputcontainer textarea[type=text]:not(.hasDatepicker) { 3835 cursor: text; 3836} 3837.px-sm-inputcontainer input { 3838 padding: 0px; 3839 margin: 0px !important; 3840} 3841.px-sm-inputcontainer > select { 3842 padding: 1em 4em 1em 1em; 3843 height: 100%; 3844 width: 100%; 3845 cursor: pointer; 3846 white-space: initial; 3847} 3848.px-sm-inputcontainer > select::-ms-expand { 3849 display: none; 3850 /* hide the default arrow in ie10 and ie11 */ 3851} 3852.px-sm-inputcontainer:hover { 3853 background-color: #f0f0f0; 3854} 3855.px-sm-inputcontainer:hover label {
3856 color: #e0ae1b; 3857} 3858 3859.px-mk-searchinfo + .px-mk-buscador-container .px-mk-searchform { 3860 width: 100%; 3861} 3862.px-mk-searchinfo .px-mk-searchinfo-inner { 3863 width: 100%; 3864 height: 40px; 3865 background: #fafafa; 3866 box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08); 3867 border-radius: 2px; 3868 text-transform: uppercase; 3869 font-size: 1em; 3870 box-sizing: border-box; 3871 font-weight: 600; 3872} 3873.px-mk-searchinfo .px-mk-searchinfo-inner > div { 3874 text-align: center; 3875 border-right: 1px solid #ccc; 3876 padding: 0 20px; 3877 box-sizing: border-box; 3878 height: 100%; 3879} 3880.px-mk-searchinfo .px-mk-searchinfo-inner i { 3881 color: goldenrod; 3882 margin-right: 10px; 3883 font-size: 20px; 3884} 3885.px-mk-searchinfo .px-mk-searchinfo-inner > .searchinfo-title { 3886 flex-grow: 0; 3887 background: #eee; 3888 color: #000; 3889} 3890.px-mk-searchinfo .px-mk-searchinfo-inner > .px-sm-searchbtn { 3891 width: auto; 3892 font-weight: 400; 3893 text-align: center; 3894 justify-content: center; 3895} 3896.px-mk-searchinfo .px-mk-searchinfo-inner.px-mk-searchinfo-column { 3897 height: auto; 3898 flex-wrap: wrap; 3899 width: 100%; 3900} 3901.px-mk-searchinfo .px-mk-searchinfo-inner.px-mk-searchinfo-column > * { 3902 height: 3em; 3903 border-bottom: 1px solid #ccc; 3904 padding: 1em; 3905 width: 50%; 3906 text-align: left; 3907 line-height: 1.2; 3908} 3909.px-mk-searchinfo .px-mk-searchinfo-inner.px-mk-searchinfo-column > * .px-mk-iconchangesearch { 3910 height: 1.2em; 3911 width: 1.2em; 3912} 3913 3914.px-mk-iconchangesearch { 3915 color: goldenrod; 3916 height: 1.5em; 3917 width: 1.5em; 3918 margin-right: 0.5em; 3919} 3920.px-mk-iconchangesearch svg { 3921 fill: currentColor; 3922 height: 100%; 3923 width: 100%; 3924} 3925 3926div.ui-datepicker#ui-datepicker-div .ui-widget-header { 3927 background: transparent !important; 3928 border: none !important; 3929} 3930div.ui-datepicker#ui-datepicker-div .ui-datepicker-next, 3931div.ui-datepicker#ui-datepicker-div .ui-datepicker-prev { 3932 border-radius: 40px !important; 3933 cursor: pointer !important; 3934} 3935div.ui-datepicker#ui-datepicker-div .ui-state-default, 3936div.ui-datepicker#ui-datepicker-div .ui-widget-content .ui-state-default, 3937div.ui-datepicker#ui-datepicker-div .ui-widget-header .ui-state-default { 3938 border-radius: 8px; 3939 border: none; 3940 background-color: rgba(0, 0, 0, 0.02); 3941 text-align: center; 3942 display: inline-flex; 3943 justify-content: center; 3944 align-items: center; 3945 width: 90%; 3946 font-size: 1em; 3947 transition: 0.3s ease-out; 3948 border: 1px solid #eee; 3949} 3950div.ui-datepicker#ui-datepicker-div .ui-state-focus, 3951div.ui-datepicker#ui-datepicker-div .ui-state-hover, 3952div.ui-datepicker#ui-datepicker-div .ui-widget-content .ui-state-focus, 3953div.ui-datepicker#ui-datepicker-div .ui-widget-content .ui-state-hover, 3954div.ui-datepicker#ui-datepicker-div .ui-widget-header .ui-state-focus, 3955div.ui-datepicker#ui-datepicker-div .ui-widget-header .ui-state-hover { 3956 background: white; 3957 border: 1px solid #000 !important; 3958} 3959div.ui-datepicker#ui-datepicker-div .ui-state-active, 3960div.ui-datepicker#ui-datepicker-div .ui-widget-content .ui-state-active, 3961div.ui-datepicker#ui-datepicker-div .ui-widget-header .ui-state-active, 3962div.ui-datepicker#ui-datepicker-div .ui-state-highlight, 3963div.ui-datepicker#ui-datepicker-div .ui-widget-content .ui-state-highlight, 3964div.ui-datepicker#ui-datepicker-div .ui-widget-header .ui-state-highlight { 3965 background: #000; 3966 color: white; 3967} 3968div.ui-datepicker#ui-datepicker-div td { 3969 text-align: center; 3970} 3971 3972.px-mk-searchloader { 3973 animation: spinStep steps(1) 1s infinite; 3974 height: 1em; 3975 width: 1em; 3976 transform-origin: top; 3977} 3978 3979.neo_m_buscador .neo_marketplace_buscador_v3 { 3980 padding: 30px 20px; 3981 justify-content: center; 3982 align-items: center; 3983} 3984 3985@keyframes spinStep { 3986 0% { 3987 transform: translatey(-50%); 3988 } 3989 12.5% { 3990 transform: rotate(45deg) translatey(-50%); 3991 } 3992 25% { 3993 transform: rotate(90deg) translatey(-50%); 3994 } 3995 37.5% { 3996 transform: rotate(135deg) translatey(-50%); 3997 } 3998 50% { 3999 transform: rotate(180deg) translatey(-50%); 4000 } 4001 62.5% { 4002 transform: rotate(225deg) translatey(-50%); 4003 } 4004 75% { 4005 transform: rotate(270deg) translatey(-50%); 4006 } 4007 87.5% { 4008 transform: rotate(315deg) translatey(-50%); 4009 } 4010 100% { 4011 transform: rotate(360deg) translatey(-50%); 4012 } 4013} 4014.px-sm-searchbtn { 4015 height: 100%; 4016 box-sizing: border-box; 4017 display: flex; 4018 text-align: left; 4019 align-items: flex-start; 4020 justify-content: center; 4021 text-transform: uppercase; 4022 font-size: 1em; 4023 letter-spacing: 1px; 4024 line-height: 1; 4025 background-color: #000; 4026 color: white; 4027 cursor: pointer; 4028 transition: 0.3s ease-out; 4029 border: none; 4030 width: 11em; 4031 padding: 1em 4em 1em 1em; 4032 flex: 1; 4033} 4034.px-sm-searchbtn .px-mk-inputicon svg { 4035 height: 1em; 4036 width: 1em; 4037 fill: white !important; 4038} 4039.px-sm-searchbtn:hover { 4040 background-color: #a37a00; 4041} 4042 4043.ModuloWrap_marketplace_list { 4044 width: 100%; 4045} 4046 4047.buscar_lp:not(.px-mk-buscador-vertical) .PartyTypeSimulator { 4048 height: 100%; 4049} 4050 4051.buscar_lp.px-mk-buscador-vertical { 4052 box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08); 4053 border-radius: 2px; 4054 padding: 0; 4055 margin: 3px; 4056 height: auto; 4057 width: auto; 4058} 4059.buscar_lp.px-mk-buscador-vertical .px-mk-searchform { 4060 transition: 1s cubic-bezier(0.17, 0.84, 0.44, 1); 4061 height: auto; 4062 width: 100%; 4063 flex-wrap: wrap; 4064} 4065.buscar_lp.px-mk-buscador-vertical .px-mk-searchform > * { 4066 width: 100%; 4067 height: 4.5em; 4068}
4069.buscar_lp.px-mk-buscador-vertical .px-mk-searchform .wrap_PartyTypeSimulator { 4070 height: auto; 4071 min-height: 4.5em; 4072 width: 50%; 4073 box-sizing: border-box; 4074} 4075.buscar_lp.px-mk-buscador-vertical .px-mk-searchform .wrap_PartyTypeSimulator .SelectorInitial { 4076 min-height: 4.5em; 4077 padding: 0.6em 1em; 4078} 4079.buscar_lp.px-mk-buscador-vertical .px-mk-searchform .wrap_PartyTypeSimulator .PartyTypeSimulatorSelect, 4080.buscar_lp.px-mk-buscador-vertical .px-mk-searchform .wrap_PartyTypeSimulator #MultiplePartySelect { 4081 position: static; 4082 background: rgba(248, 248, 248, 0.9725490196); 4083} 4084.buscar_lp.px-mk-buscador-vertical .px-sm-inputcontainer { 4085 border-bottom: 1px solid #ccc; 4086 border-right: none; 4087 max-width: none; 4088 width: 100%; 4089} 4090.buscar_lp.px-mk-buscador-vertical .px-sm-inputcontainer.fechas_ancho_entrada, .buscar_lp.px-mk-buscador-vertical .px-sm-inputcontainer.fechas_ancho_salida { 4091 width: 100%; 4092 box-sizing: border-box; 4093 margin: 0px; 4094} 4095.buscar_lp.px-mk-buscador-vertical .px-sm-inputcontainer.fechas_ancho_salida { 4096 border-left: 1px solid #ccc; 4097} 4098.buscar_lp.px-mk-buscador-vertical .px-sm-inputcontainer.px-mk-productidhidden { 4099 height: 0px; 4100 width: 100%; 4101} 4102.buscar_lp.px-mk-buscador-vertical .px-sm-inputcontainer input, 4103.buscar_lp.px-mk-buscador-vertical .px-sm-inputcontainer select, 4104.buscar_lp.px-mk-buscador-vertical .px-sm-inputcontainer textarea { 4105 max-width: 100%; 4106} 4107 4108.px-mk-filter-disabled { 4109 pointer-events: none !important; 4110 opacity: 0.5 !important; 4111} 4112 4113.px-mk-buscador-vertical.px-mk-searchform .px-sm-inputcontainer:last-child, 4114.px-mk-buscador-vertical .px-sm-inputcontainer:last-child { 4115 border-bottom: none; 4116 border-right: none; 4117} 4118 4119.px-mk-hidesearchform { 4120 opacity: 0; 4121 pointer-events: none; 4122 max-height: 0px; 4123 overflow: hidden; 4124} 4125 4126.ignoreclick { 4127 pointer-events: none; 4128} 4129 4130.px-sm-searchbtn > i { 4131 font-size: 20px; 4132 position: relative; 4133 left: 0; 4134 top: -1px; 4135 margin-right: 20px; 4136 margin-left: -10px; 4137} 4138 4139.btn-searching span { 4140 opacity: 0; 4141 max-width: 0px; 4142 overflow: hidden; 4143 transition: 0.3s ease-out; 4144} 4145 4146#ProductID option { 4147 text-transform: none; 4148} 4149 4150#ProductID option[value=everyproduct] { 4151 font-weight: 600; 4152} 4153 4154#ProductID option[value=""][disabled] { 4155 background-color: #eee; 4156 color: #555; 4157} 4158 4159.px-mk-disabled-temp { 4160 background-color: #eee; 4161 cursor: not-allowed; 4162 pointer-events: none; 4163 color: #bbb; 4164} 4165 4166.px-mk-productid.px-sm-inputcontainer.px-mk-productidhidden { 4167 opacity: 0; 4168 max-width: 0px; 4169 pointer-events: none; 4170 padding: 0px; 4171 margin: 0px; 4172 border: none; 4173} 4174 4175.px-mk-productid.px-sm-inputcontainer { 4176 max-width: 300px; 4177 transition: 0.3s ease; 4178 overflow: hidden; 4179} 4180 4181.px-mk-locationdropdown { 4182 position: absolute; 4183 top: calc(100% + 0.1em); 4184 left: 0; 4185 padding: 0; 4186 line-height: 1.2; 4187 background: white; 4188 box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08); 4189 z-index: 999; 4190 border-radius: 0 0 4px 4px; 4191 max-height: 50vh; 4192 overflow: auto; 4193 transition: 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); 4194 opacity: 0; 4195 pointer-events: none; 4196 transform: translateY(-1em); 4197 width: 100%; 4198} 4199.px-mk-locationdropdown.activeAC { 4200 transform: none; 4201 pointer-events: initial; 4202 opacity: 1; 4203} 4204.px-mk-locationdropdown > * { 4205 padding: 1.2em 1.5em; 4206 white-space: nowrap; 4207 max-width: 400px; 4208 overflow: hidden; 4209 text-overflow: ellipsis; 4210 width: 100%; 4211 cursor: pointer; 4212 display: flex; 4213 align-items: center; 4214 justify-content: flex-start; 4215 box-sizing: border-box; 4216} 4217.px-mk-locationdropdown > *.suggestion_hover { 4218 background-color: #f2f2f2; 4219} 4220.px-mk-locationdropdown > *:hover { 4221 background-color: #f2f2f2; 4222} 4223.px-mk-locationdropdown > *:hover .px-mk-locationimg { 4224 fill: goldenrod; 4225} 4226.px-mk-locationdropdown > * .px-mk-locationtxt { 4227 width: 100%; 4228 overflow: hidden; 4229 text-overflow: ellipsis; 4230} 4231.px-mk-locationdropdown > * .px-mk-locationimg { 4232 height: 1.1em; 4233 width: 1.1em; 4234 margin-right: 0.6em; 4235 flex-shrink: 0; 4236 fill: #aaa; 4237 margin-right: 0.8em; 4238} 4239.px-mk-locationdropdown > * .px-mk-locationimg svg { 4240 height: 100%; 4241 width: 100%; 4242 -o-object-fit: contain; 4243 object-fit: contain; 4244} 4245 4246.px-mk-locationautocomplete { 4247 height: 100%; 4248 width: 100%; 4249 box-sizing: border-box; 4250 padding-right: 2em; 4251} 4252.px-mk-locationautocomplete input { 4253 height: 100%; 4254 padding: 0em 1em; 4255 width: 100%; 4256} 4257 4258.ui-datepicker { 4259 font-size: 16px !important; 4260 box-shadow: 0 2px 20px rgba(0, 0, 0, 0.2); 4261 width: auto; 4262 border-radius: 0px !important; 4263 padding: 5px !important; 4264 width: auto !important; 4265 box-sizing: border-box; 4266} 4267 4268.ui-datepicker td { 4269 margin: 0px !important; 4270 padding: 0px; 4271} 4272 4273.ui-datepicker td > * { 4274 height: 40px; 4275 width: 40px !important; 4276 border-radius: 0px !important; 4277 border: 1px solid transparent !important; 4278 box-sizing: border-box; 4279} 4280 4281.ui-datepicker table { 4282 margin: 0px !important; 4283} 4284 4285.neo_marketplace_buscador_v3 * { 4286 font-size: 13px !important; 4287} 4288 4289.neo_marketplace_buscador_v3 input, .neo_marketplace_buscador_v3 select { 4290 font-size: 16px !important; 4291} 4292 4293.neo_modules_cart_hotel_v2 .cart_top_hotel_v2 .PartyTypeSimulator { 4294 width: 100%; 4295} 4296 4297.neo_marketplace_buscador_v3 .PartyTypeSimulatorSelect { 4298 position: absolute; 4299 z-index: 999; 4300 top: 55px; 4301 left: 0px; 4302 padding: 5px; 4303 background: #fff; 4304 margin: 0px; 4305 box-shadow: 0 2px 16px rgba(0, 0, 0, 0.15); 4306 padding: 20px 25px; 4307 line-height: 1.5; 4308 box-sizing: border-box; 4309 width: 300px; 4310 max-width: 100vw; 4311} 4312 4313.txtPartyGroup { 4314 white-space: nowrap; 4315 overflow: hidden; 4316 text-overflow: ellipsis; 4317 margin-right: auto; 4318 padding-right: 30px; 4319} 4320 4321input.neo_partyselector_quantity { 4322 padding: 15px 10px; 4323 font-size: 18px; 4324 text-align: center; 4325 border: none; 4326 background: transparent; 4327 width: 60px; 4328 -moz-appearance: textfield; 4329} 4330input.neo_partyselector_quantity::-webkit-outer-spin-button, 4331input.neo_partyselector_quantity::-webkit-inner-spin-button { 4332 -webkit-appearance: none; 4333 margin: 0; 4334} 4335input.neo_partyselector_quantity:focus { 4336 outline: none; 4337 background-color: rgba(0, 0, 0, 0.03); 4338 border-radius: 5px; 4339} 4340 4341.ChildrensAges { 4342 max-height: 180px; 4343 overflow-y: auto; 4344 overflow-x: hidden; 4345 padding-right: 5px; 4346} 4347.ChildrensAges::-webkit-scrollbar {
4348 width: 6px; 4349} 4350.ChildrensAges::-webkit-scrollbar-track { 4351 background: #f1f1f1; 4352 border-radius: 10px; 4353} 4354.ChildrensAges::-webkit-scrollbar-thumb { 4355 background: #888; 4356 border-radius: 10px; 4357} 4358.ChildrensAges::-webkit-scrollbar-thumb:hover { 4359 background: #555; 4360} 4361 4362@media only screen and (max-width: 650px) { 4363 .PartyTypeSimulatorContainer { 4364 height: auto !important; 4365 } 4366 .PartyTypeSimulatorContainer .PartyTypeSimulatorSelect { 4367 position: static !important; 4368 width: 100%; 4369 } 4370 .px-mk-locationdropdown { 4371 width: 100%; 4372 box-shadow: 0 4px 9px rgba(0, 0, 0, 0.5); 4373 } 4374 .neo_marketplace_buscador_v3 * { 4375 font-size: 15px !important; 4376 } 4377 .neo_marketplace_buscador_v3 input, .neo_marketplace_buscador_v3 select { 4378 font-size: 16px !important; 4379 } 4380 .neo_marketplace_buscador_v3 { 4381 width: 100%; 4382 display: flex; 4383 } 4384 .ui-datepicker { 4385 font-size: 19px !important; 4386 z-index: 1000 !important; 4387 width: calc(100vw - 30px) !important; 4388 left: 10px !important; 4389 box-shadow: 0 2px 20px rgba(0, 0, 0, 0.5); 4390 padding: 10px !important; 4391 box-sizing: border-box; 4392 } 4393 4394 /* Ajustes para el selector de party en mobile */ 4395 .neo_marketplace_buscador_v3 .txtPartyGroup, 4396 .PartyTypeSimulator .txtPartyGroup, 4397 .SelectorInitial .txtPartyGroup { 4398 white-space: normal !important; 4399 overflow: visible !important; 4400 text-overflow: clip !important; 4401 padding-right: 10px !important; 4402 font-size: 10px !important; 4403 line-height: 1.4 !important; 4404 display: flex !important; 4405 flex-wrap: wrap !important; 4406 align-items: center !important; 4407 gap: 2px !important; 4408 max-width: calc(100% - 40px) !important; 4409 } 4410 4411 .neo_marketplace_buscador_v3 .txtPartyGroup span, 4412 .PartyTypeSimulator .txtPartyGroup span, 4413 .SelectorInitial .txtPartyGroup span { 4414 white-space: nowrap !important; 4415 font-size: 15px !important; 4416 } 4417 4418 .neo_marketplace_buscador_v3 .txtPartyGroup .mdi-circle-small, 4419 .PartyTypeSimulator .txtPartyGroup .mdi-circle-small, 4420 .SelectorInitial .txtPartyGroup .mdi-circle-small { 4421 font-size: 12px !important; 4422 margin: 0 -3px !important; 4423 } 4424 4425 .neo_marketplace_buscador_v3 .SelectorInitial, 4426 .PartyTypeSimulator .SelectorInitial { 4427 min-height: 55px !important; 4428 padding: 8px 40px 8px 10px !important; 4429 display: flex !important; 4430 align-items: center !important; 4431 } 4432 4433 .neo_marketplace_buscador_v3 .PartyTypeSimulatorContainer, 4434 .PartyTypeSimulatorContainer { 4435 overflow: visible !important; 4436 } 4437 4438 .px-mk-buscador-container { 4439 font-size: 16px; 4440 } 4441 .px-mk-buscador-container select, 4442 .px-mk-buscador-container textarea, 4443 .px-mk-buscador-container input[type=text], 4444 .px-mk-buscador-container input[type=password], 4445 .px-mk-buscador-container input[type=datetime], 4446 .px-mk-buscador-container input[type=datetime-local], 4447 .px-mk-buscador-container input[type=date], 4448 .px-mk-buscador-container input[type=month], 4449 .px-mk-buscador-container input[type=time], 4450 .px-mk-buscador-container input[type=week], 4451 .px-mk-buscador-container input[type=number], 4452 .px-mk-buscador-container input[type=email], 4453 .px-mk-buscador-container input[type=url], 4454 .px-mk-buscador-container input[type=search], 4455 .px-mk-buscador-container input[type=tel], 4456 .px-mk-buscador-container input[type=color] { 4457 font-size: 1em; 4458 } 4459}/*# sourceMappingURL=css.css.map */</style>
4460<script> 4461 (function() { 4462 function run() { 4463 try { 4464 var span = document.querySelector('#PxMkAcion_Search .update-search-span'); 4465 var btn = document.getElementById('PxMkAcion_Search'); 4466 if (!span) return; 4467 4468 var themeHex = '#000000'; 4469 4470 function parseHex(hex) { 4471 if (!hex) return null; 4472 hex = String(hex).trim(); 4473 if (hex.startsWith('#')) hex = hex.slice(1); 4474 if (hex.length === 3) { 4475 hex = hex.split('').map(function(ch) { 4476 return ch + ch; 4477 }).join(''); 4478 } 4479 if (hex.length !== 6) return null; 4480 var r = parseInt(hex.slice(0, 2), 16); 4481 var g = parseInt(hex.slice(2, 4), 16); 4482 var b = parseInt(hex.slice(4, 6), 16); 4483 if ([r, g, b].some(function(v) { 4484 return isNaN(v); 4485 })) return null; 4486 return { 4487 r: r, 4488 g: g, 4489 b: b 4490 }; 4491 } 4492 4493 function relL(rgb) { 4494 function toLin(c) { 4495 c = c / 255; 4496 return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); 4497 } 4498 var R = toLin(rgb.r), 4499 G = toLin(rgb.g), 4500 B = toLin(rgb.b); 4501 return 0.2126 * R + 0.7152 * G + 0.0722 * B; 4502 } 4503 4504 function contrast(L1, L2) { 4505 var a = Math.max(L1, L2); 4506 var b = Math.min(L1, L2); 4507 return (a + 0.05) / (b + 0.05); 4508 } 4509 4510 var rgb = parseHex(themeHex); 4511 if (!rgb) { 4512 if (btn) { 4513 var bg = window.getComputedStyle(btn).backgroundColor; // rgb(a) 4514 var m = bg && bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/i); 4515 if (m) { 4516 rgb = { 4517 r: parseInt(m[1], 10), 4518 g: parseInt(m[2], 10), 4519 b: parseInt(m[3], 10) 4520 }; 4521 } 4522 } 4523 } 4524 if (!rgb) return; 4525 4526 var Lbg = relL(rgb); 4527 var Lwhite = relL({ 4528 r: 255, 4529 g: 255, 4530 b: 255 4531 }); 4532 var Lblack = relL({ 4533 r: 0, 4534 g: 0, 4535 b: 0 4536 }); 4537 var cWhite = contrast(Lbg, Lwhite); 4538 var cBlack = contrast(Lbg, Lblack); 4539 4540 var textColor = cBlack >= cWhite ? '#000000' : '#FFFFFF'; 4541 span.style.setProperty('color', textColor, 'important'); 4542 if (btn) { 4543 btn.style.setProperty('color', textColor, 'important'); 4544 4545 // Recolor inline SVG icons (search and loading) to match the contrast color 4546 function paintInlineSVG(container, color) { 4547 try { 4548 var svgs = container.querySelectorAll('svg'); 4549 svgs.forEach(function(svg) { 4550 // Support SVGs that use currentColor 4551 svg.style.setProperty('color', color, 'important'); 4552 svg.setAttribute('color', color); 4553 // Force fill/stroke via style to override inline attrs 4554 svg.style.setProperty('fill', color, 'important'); 4555 svg.style.setProperty('stroke', color, 'important'); 4556 // Update common shape elements 4557 svg.querySelectorAll('path, circle, rect, polygon, line, polyline, ellipse, g').forEach(function(node) { 4558 node.style.setProperty('fill', color, 'important'); 4559 node.style.setProperty('stroke', color, 'important'); 4560 }); 4561 // Also override attributes for stubborn icons 4562 svg.querySelectorAll('[fill]').forEach(function(node) { 4563 node.setAttribute('fill', color); 4564 }); 4565 svg.querySelectorAll('[stroke]').forEach(function(node) { 4566 node.setAttribute('stroke', color); 4567 }); 4568 }); 4569 } catch (e) { 4570 /* ignore */ 4571 } 4572 } 4573 4574 var iconLabel = btn.querySelector('.px-mk-searchicon'); 4575 var loaderLabel = btn.querySelector('.px-mk-searchloader'); 4576 if (iconLabel) paintInlineSVG(iconLabel, textColor); 4577 if (loaderLabel) paintInlineSVG(loaderLabel, textColor); 4578 } 4579 } catch (e) { 4580 /* ignore */ 4581 } 4582 } 4583 4584 if (document.readyState === 'loading') { 4585 document.addEventListener('DOMContentLoaded', run); 4586 } else { 4587 run(); 4588 } 4589 })(); 4590</script>
4590 4591
4591<script> 4592 if (localStorage.getItem('tradename')) { 4593 localStorage.removeItem('tradename'); 4594 } 4595 </script>
4595 4596 4597<!-- Scripts para el mapa -->
4598<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
vendor: 1 bytes, line 4598
4598
4599<script> 4600 (function() { 4601 // Desactivar logs dentro de este módulo (solo en este scope) 4602 var console = { 4603 log: function() {}, 4604 warn: function() {}, 4605 error: function() {} 4606 }; 4607 // Variables para el mapa 4608 let map; 4609 let marker; 4610 let selectedLat = 0; 4611 let selectedLng = 0; 4612 let radiusCircle; // Variable para el cÃrculo del radio 4613 const defaultZoom = 13; 4614 // Coordenadas por defecto: Mendoza, Argentina 4615 const DEFAULT_LAT = -32.889458; 4616 const DEFAULT_LNG = -68.845839; 4617 const DEFAULT_RADIUS = 50000; // 50km en metros 4618 4619 // Elementos del DOM 4620 const mapModal = document.getElementById('map-modal'); 4621 const mapBtn = document.getElementById('map-search-btn'); 4622 const closeBtn = document.querySelector('.map-close'); 4623 const confirmBtn = document.getElementById('confirm-location'); 4624 const enableLocationGuideBtn = document.getElementById('enable-location-guide'); 4625 const centerLocationBtn = document.getElementById('center-location'); 4626 const locationPermissionsGuide = document.getElementById('location-permissions-guide'); 4627 const browserGuideContent = document.getElementById('browser-guide-content'); 4628 const closeGuideBtn = document.getElementById('close-guide'); 4629 const latitudeInput = document.getElementById('webroot_latitude'); 4630 const longitudeInput = document.getElementById('webroot_longitude'); 4631 const radiusInput = document.getElementById('webroot_distance_radius'); 4632 const locationInput = document.getElementById('webroot_location_search'); 4633 const locationGoogleSearch = document.getElementById('location_google_search'); 4634 4635 // Variables para rastrear estado de permisos 4636 let locationPermissionsDenied = false; 4637 let locationPermissionsEnabled = false; 4638 4639 // Función para detectar el navegador 4640 function detectBrowser() { 4641 const userAgent = navigator.userAgent.toLowerCase(); 4642 if (userAgent.includes('chrome') && !userAgent.includes('edg')) return 'chrome'; 4643 if (userAgent.includes('firefox')) return 'firefox'; 4644 if (userAgent.includes('safari') && !userAgent.includes('chrome')) return 'safari'; 4645 if (userAgent.includes('edg')) return 'edge'; 4646 return 'chrome'; 4647 } 4648 4649 // Función para obtener el contenido de la guÃa según el navegador 4650 function getBrowserGuideContent(browser) { 4651 const guides = { 4652 chrome: { 4653 title: 'Google Chrome', 4654 steps: [ 4655 'Haz clic en el icono de candado en la barra de direcciones', 4656 'Selecciona "Configuración del sitio" o "Permisos"', 4657 'Cambia "Ubicación" de "Bloquear" a "Permitir"', 4658 'Recarga la página' 4659 ], 4660 link: 'https://support.google.com/chrome/answer/142065' 4661 }, 4662 firefox: { 4663 title: 'Mozilla Firefox', 4664 steps: [ 4665 'Haz clic en el icono de escudo en la barra de direcciones', 4666 'Selecciona "Configuración mejorada de seguimiento"', 4667 'Habilita los permisos de ubicación para este sitio', 4668 'Recarga la página' 4669 ], 4670 link: 'https://support.mozilla.org/es/kb/compartir-ubicacion-con-sitios-web' 4671 }, 4672 safari: { 4673 title: 'Safari', 4674 steps: [ 4675 'Ve a Safari > Preferencias > Sitios web', 4676 'Selecciona "Ubicación" en la barra lateral', 4677 'Encuentra este sitio y cambia a "Permitir"', 4678 'Recarga la página' 4679 ], 4680 link: 'https://support.apple.com/es-es/guide/safari/ibrw1056/mac' 4681 }, 4682 edge: { 4683 title: 'Microsoft Edge', 4684 steps: [ 4685 'Haz clic en el icono de candado en la barra de direcciones', 4686 'Selecciona "Permisos para este sitio"', 4687 'Cambia "Ubicación" a "Permitir"', 4688 'Recarga la página' 4689 ], 4690 link: 'https://support.microsoft.com/es-es/microsoft-edge/ubicaci%C3%B3n-y-privacidad-en-microsoft-edge-31b5d9e7-bb24-43a0-8b0e-d9f4b38f6cf5' 4691 } 4692 }; 4693 return guides[browser] || guides.chrome; 4694 } 4695 4696 // Función para mostrar la guÃa de permisos 4697 function showLocationPermissionsGuide() { 4698 const browser = detectBrowser(); 4699 const guide = getBrowserGuideContent(browser); 4700 4701 let content = ` 4702 <div style="margin: 10px 0; padding: 15px; background: white; border-radius: 6px; border: 1px solid #e5e7eb;"> 4703 <h5 style="margin: 0 0 8px 0; color: #374151; font-size: 16px; font-weight: 600;">Instrucciones para ${guide.title}</h5> 4704 <p style="margin: 0 0 12px 0; color: #6b7280; font-size: 13px;">Sigue estos pasos para habilitar los permisos:</p> 4705 <ol style="margin: 8px 0 8px 20px; padding: 0;"> 4706 `; 4707 4708 guide.steps.forEach(step => { 4709 content += `<li style="margin: 6px 0; font-size: 14px; color: #4b5563;">${step}</li>`; 4710 }); 4711 4712 content += ` 4713 </ol> 4714 <a href="${guide.link}" target="_blank" style="display: inline-block; margin-top: 10px; color: #3b82f6; text-decoration: none; font-size: 13px;"> 4715 Ver guÃa oficial de ${guide.title} â 4716 </a> 4717 </div> 4718 `; 4719 4720 if (browserGuideContent) { 4721 browserGuideContent.innerHTML = content; 4722 } 4723 4724 if (locationPermissionsGuide) { 4725 locationPermissionsGuide.style.display = 'block'; 4726 } 4727 } 4728 4729 // Función para ocultar la guÃa de permisos 4730 function hideLocationPermissionsGuide() { 4731 if (locationPermissionsGuide) { 4732 locationPermissionsGuide.style.display = 'none'; 4733 } 4734 } 4735 4736 // Función para centrar el mapa en la ubicación actual 4737 function centerMapOnCurrentLocation() { 4738 if (!navigator.geolocation) { 4739 alert('Tu navegador no soporta geolocalización.'); 4740 return; 4741 } 4742 4743 // Mostrar loader en el botón centrar 4744 if (centerLocationBtn) { 4745 const loader = centerLocationBtn.querySelector('.center-btn-loader'); 4746 const text = centerLocationBtn.querySelector('.center-btn-text'); 4747 if (loader && text) { 4748 loader.style.display = 'inline-block'; 4749 text.style.display = 'none'; 4750 } 4751 centerLocationBtn.disabled = true; 4752 } 4753 4754 navigator.geolocation.getCurrentPosition( 4755 async function(position) { 4756 const lat = position.coords.latitude; 4757 const lng = position.coords.longitude; 4758 4759 // Centrar el mapa en la nueva ubicación 4760 if (map) {
4761 map.setView([lat, lng], defaultZoom); 4762 4763 // Remover marcador anterior si existe 4764 if (marker) { 4765 map.removeLayer(marker); 4766 } 4767 4768 // Añadir nuevo marcador 4769 marker = L.marker([lat, lng], { 4770 draggable: true 4771 }).addTo(map); 4772 4773 // Actualizar posición del cÃrculo 4774 if (radiusCircle) { 4775 radiusCircle.setLatLng([lat, lng]); 4776 } else { 4777 // Si por alguna razón no existe, crearlo 4778 const radiusSelect = document.getElementById('radius-select'); 4779 const currentRadius = radiusSelect ? parseInt(radiusSelect.value) : DEFAULT_RADIUS; 4780 radiusCircle = L.circle([lat, lng], { 4781 color: '#3388ff', 4782 fillColor: '#3388ff', 4783 fillOpacity: 0.2, 4784 radius: currentRadius 4785 }).addTo(map); 4786 } 4787 4788 // Actualizar coordenadas seleccionadas 4789 selectedLat = lat; 4790 selectedLng = lng; 4791 4792 // Obtener información de ubicación para el marcador 4793 try { 4794 const locationName = await getAddressFromCoordinates(lat, lng); 4795 if (locationName && !locationName.includes(lat.toString())) { 4796 marker.bindPopup(locationName).openPopup(); 4797 } 4798 } catch (error) { 4799 console.log('â ï¸ No se pudo obtener información de ubicación para el marcador'); 4800 } 4801 4802 // Actualizar coordenadas al arrastrar el marcador 4803 marker.on('dragend', async function(e) { 4804 const position = marker.getLatLng(); 4805 selectedLat = position.lat; 4806 selectedLng = position.lng; 4807 4808 // Actualizar posición del cÃrculo 4809 if (radiusCircle) { 4810 radiusCircle.setLatLng(position); 4811 } 4812 4813 // Actualizar popup al arrastrar 4814 try { 4815 const newLocationName = await getAddressFromCoordinates(selectedLat, selectedLng); 4816 if (newLocationName && !newLocationName.includes(selectedLat.toString())) { 4817 marker.setPopupContent(newLocationName); 4818 } 4819 } catch (error) { 4820 console.log('â ï¸ No se pudo actualizar información al arrastrar'); 4821 } 4822 }); 4823 4824 // Actualizar coordenadas al arrastrar el marcador 4825 marker.on('dragend', async function(e) { 4826 const position = marker.getLatLng(); 4827 selectedLat = position.lat; 4828 selectedLng = position.lng; 4829 4830 // Actualizar popup al arrastrar 4831 try { 4832 const newLocationName = await getAddressFromCoordinates(selectedLat, selectedLng); 4833 if (newLocationName && !newLocationName.includes(selectedLat.toString())) { 4834 marker.setPopupContent(newLocationName); 4835 } 4836 } catch (error) { 4837 console.log('â ï¸ No se pudo actualizar información al arrastrar'); 4838 } 4839 }); 4840 } 4841 4842 // Ocultar loader del botón 4843 if (centerLocationBtn) { 4844 const loader = centerLocationBtn.querySelector('.center-btn-loader'); 4845 const text = centerLocationBtn.querySelector('.center-btn-text'); 4846 if (loader && text) { 4847 loader.style.display = 'none'; 4848 text.style.display = 'inline-block'; 4849 } 4850 centerLocationBtn.disabled = false; 4851 } 4852 }, 4853 function(error) { 4854 console.log('Error al obtener ubicación actual:', error); 4855 alert('No se pudo obtener tu ubicación actual. Verifica que los permisos estén habilitados.'); 4856 4857 // Ocultar loader del botón 4858 if (centerLocationBtn) { 4859 const loader = centerLocationBtn.querySelector('.center-btn-loader'); 4860 const text = centerLocationBtn.querySelector('.center-btn-text'); 4861 if (loader && text) { 4862 loader.style.display = 'none'; 4863 text.style.display = 'inline-block'; 4864 } 4865 centerLocationBtn.disabled = false; 4866 } 4867 } 4868 ); 4869 } 4870 4871 console.log('Botón de mapa:', mapBtn); // Debug para verificar que el botón existe 4872 4873 // Asegurar que el modal existe en el DOM 4874 if (!mapModal) { 4875 console.error('Modal de mapa no encontrado en el DOM'); 4876 // Añadir el modal al final del body si no existe 4877 const modalHTML = ` 4878 <div id="map-modal" class="map-modal"> 4879 <div class="map-modal-content"> 4880 <span class="map-close">×</span> 4881 <h3>Selecciona una ubicación en el mapa</h3> 4882 <div id="map-container"></div> 4883 <div class="map-footer">
4884 <div class="map-footer-controls"> 4885 <button id="center-location" style="display: none; padding: 6px 12px; color: white; background-color: #10b981; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; margin-right: 10px;"> 4886 <span class="center-btn-loader" style="display: none; width: 12px; height: 12px; border: 2px solid rgba(255, 255, 255, 0.3); border-radius: 50%; border-top-color: white; animation: spin 1s ease-in-out infinite; margin-right: 6px;"></span> 4887 <span class="center-btn-text">Localizarme</span> 4888 </button> 4889 <div class="radius-selector"> 4890 <label for="radius-select" style="margin-right: 5px; font-weight: bold;">Radio:</label> 4891 <select id="radius-select" style="padding: 8px; border-radius: 4px; border: 1px solid #ccc;"> 4892 <option value="10000">10 km</option> 4893 <option value="30000">30 km</option> 4894 <option value="50000" selected>50 km</option> 4895 <option value="100000">100 km</option> 4896 </select> 4897 </div> 4898 </div> 4899 <button id="confirm-location" class="neo_bgcolor_primary"> 4900 <span class="btn-loader"></span> 4901 <span class="btn-text">Buscar en esta zona</span> 4902 </button> 4903 </div> 4904 </div> 4905 </div> 4906 `; 4907 document.body.insertAdjacentHTML('beforeend', modalHTML); 4908 } 4909 4910 // Función para inicializar el mapa 4911 function initMap(lat, lng) { 4912 // Limpiar mapa existente de manera segura 4913 if (map) { 4914 try { 4915 map.remove(); 4916 } catch (e) { 4917 console.log('Error al remover mapa:', e); 4918 } 4919 map = null; 4920 } 4921 4922 // Reset marker 4923 marker = null; 4924 4925 // Coordenadas por defecto (si no hay seleccionadas): Mendoza 4926 lat = (typeof lat === 'number' ? lat : null) ?? DEFAULT_LAT; 4927 lng = (typeof lng === 'number' ? lng : null) ?? DEFAULT_LNG; 4928 4929 // Crear mapa con un timeout para asegurar que el contenedor está visible 4930 setTimeout(() => { 4931 try { 4932 // Verificar que el contenedor principal existe 4933 const mapContainer = document.getElementById('map-container'); 4934 if (!mapContainer) { 4935 console.error('Contenedor del mapa no encontrado'); 4936 return; 4937 } 4938 4939 // Crear un nuevo contenedor para evitar el error de "already initialized" 4940 const mapId = 'map-instance-' + Date.now(); 4941 mapContainer.innerHTML = `<div id="${mapId}" style="height: 100%; width: 100%;"></div>`; 4942 4943 // Crear el mapa en el nuevo contenedor 4944 map = L.map(mapId, { 4945 scrollWheelZoom: true 4946 }).setView([lat, lng], defaultZoom); 4947 4948 // Invalidar tamaño inmediatamente para asegurar renderizado correcto 4949 map.invalidateSize(); 4950 4951 // Añadir capa de mapa base (OpenStreetMap) 4952 L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { 4953 attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' 4954 }).addTo(map); 4955 4956 // Añadir marcador SIEMPRE (incluido Mendoza por defecto) y preparar comportamiento 4957 marker = L.marker([lat, lng], { 4958 draggable: true 4959 }).addTo(map); 4960 4961 // Dibujar cÃrculo de radio inicial 4962 const radiusSelect = document.getElementById('radius-select'); 4963 const initialRadius = radiusSelect ? parseInt(radiusSelect.value) : DEFAULT_RADIUS; 4964 4965 radiusCircle = L.circle([lat, lng], { 4966 color: '#3388ff', 4967 fillColor: '#3388ff', 4968 fillOpacity: 0.2, 4969 radius: initialRadius 4970 }).addTo(map); 4971 4972 // Evento para actualizar el radio cuando cambia el select 4973 if (radiusSelect) { 4974 // Remover listeners anteriores para evitar duplicados 4975 const newRadiusSelect = radiusSelect.cloneNode(true); 4976 radiusSelect.parentNode.replaceChild(newRadiusSelect, radiusSelect); 4977 4978 newRadiusSelect.addEventListener('change', function() { 4979 const newRadius = parseInt(this.value); 4980 if (radiusCircle) { 4981 radiusCircle.setRadius(newRadius); 4982 } 4983 }); 4984 } 4985 4986 // Obtener información de ubicación para el marcador inicial 4987 (async () => { 4988 try { 4989 const locationName = await getAddressFromCoordinates(lat, lng); 4990 if (locationName && !locationName.includes(lat.toString())) { 4991 marker.bindPopup(locationName);
4992 console.log('ð Información inicial del marcador:', locationName); 4993 } 4994 } catch (error) { 4995 console.log('â ï¸ No se pudo obtener información inicial del marcador'); 4996 } 4997 })(); 4998 4999 // Actualizar coordenadas al arrastrar el marcador 5000 marker.on('dragend', async function(e) { 5001 const position = marker.getLatLng(); 5002 selectedLat = position.lat; 5003 selectedLng = position.lng; 5004 5005 // Actualizar posición del cÃrculo 5006 if (radiusCircle) { 5007 radiusCircle.setLatLng(position); 5008 } 5009 5010 // Actualizar popup al arrastrar 5011 try { 5012 const newLocationName = await getAddressFromCoordinates(selectedLat, selectedLng); 5013 if (newLocationName && !newLocationName.includes(selectedLat.toString())) { 5014 marker.setPopupContent(newLocationName); 5015 } 5016 } catch (error) { 5017 console.log('â ï¸ No se pudo actualizar información al arrastrar'); 5018 } 5019 }); 5020 5021 selectedLat = lat; 5022 selectedLng = lng; 5023 5024 // Añadir evento de clic al mapa 5025 map.on('click', async function(e) { 5026 // Si ya existe un marcador, lo eliminamos 5027 if (marker) { 5028 map.removeLayer(marker); 5029 } 5030 5031 // Añadir nuevo marcador en la posición del clic 5032 marker = L.marker(e.latlng, { 5033 draggable: true 5034 }).addTo(map); 5035 5036 // Actualizar posición del cÃrculo 5037 if (radiusCircle) { 5038 radiusCircle.setLatLng(e.latlng); 5039 } else { 5040 // Si por alguna razón no existe, crearlo 5041 const radiusSelect = document.getElementById('radius-select'); 5042 const currentRadius = radiusSelect ? parseInt(radiusSelect.value) : DEFAULT_RADIUS; 5043 radiusCircle = L.circle(e.latlng, { 5044 color: '#3388ff', 5045 fillColor: '#3388ff', 5046 fillOpacity: 0.2, 5047 radius: currentRadius 5048 }).addTo(map); 5049 } 5050 5051 // Guardar coordenadas seleccionadas 5052 selectedLat = e.latlng.lat; 5053 selectedLng = e.latlng.lng; 5054 5055 // Intentar obtener y mostrar información de ubicación en el marcador 5056 try { 5057 const locationName = await getAddressFromCoordinates(selectedLat, selectedLng); 5058 if (locationName && !locationName.includes(selectedLat.toString())) { 5059 marker.bindPopup(locationName).openPopup(); 5060 console.log('ð Información del marcador establecida:', locationName); 5061 } 5062 } catch (error) { 5063 console.log('â ï¸ No se pudo obtener información de ubicación para el marcador'); 5064 } 5065 5066 // Actualizar coordenadas al arrastrar el marcador 5067 marker.on('dragend', async function(e) { 5068 const position = marker.getLatLng(); 5069 selectedLat = position.lat; 5070 selectedLng = position.lng; 5071 5072 // Actualizar posición del cÃrculo 5073 if (radiusCircle) { 5074 radiusCircle.setLatLng(position); 5075 } 5076 5077 // Actualizar popup al arrastrar 5078 try { 5079 const newLocationName = await getAddressFromCoordinates(selectedLat, selectedLng); 5080 if (newLocationName && !newLocationName.includes(selectedLat.toString())) { 5081 marker.setPopupContent(newLocationName); 5082 } 5083 } catch (error) { 5084 console.log('â ï¸ No se pudo actualizar información al arrastrar'); 5085 } 5086 }); 5087 }); 5088 5089 // Invalidar tamaño para asegurar que se renderiza correctamente 5090 setTimeout(() => { 5091 if (map) { 5092 map.invalidateSize(); 5093 } 5094 }, 100); 5095 // Segundo intento para móviles lentos 5096 setTimeout(() => { 5097 if (map) { 5098 map.invalidateSize(); 5099 } 5100 }, 500); 5101 } catch (e) { 5102 console.error('Error al inicializar el mapa:', e); 5103 } 5104 }, 500); // Aumentar timeout para dar más tiempo al modal 5105 } 5106 5107 // Evento clic en botón de mapa (consolidado en un único listener) 5108 if (mapBtn) { 5109 console.log('Asignando evento click al botón de mapa'); 5110 5111 function openMapModalHandler(e) { 5112 console.log('Botón de mapa clickeado'); 5113 e.preventDefault(); 5114 e.stopPropagation(); 5115 mapModal.style.display = 'flex'; 5116 5117 // Resetear estado de permisos y ocultar elementos al abrir el modal 5118 locationPermissionsDenied = false;
5119 locationPermissionsEnabled = false; 5120 if (enableLocationGuideBtn) enableLocationGuideBtn.style.display = 'none'; 5121 if (centerLocationBtn) centerLocationBtn.style.display = 'none'; 5122 hideLocationPermissionsGuide(); 5123 5124 // Si ya hay coordenadas guardadas, las usamos 5125 const currentLat = latitudeInput.value ? parseFloat(latitudeInput.value) : null; 5126 const currentLng = longitudeInput.value ? parseFloat(longitudeInput.value) : null; 5127 5128 if (currentLat && currentLng) { 5129 initMap(currentLat, currentLng); 5130 } else { 5131 // Inicializar inmediatamente con Mendoza para evitar mapa en blanco 5132 initMap(DEFAULT_LAT, DEFAULT_LNG); 5133 5134 // Mostrar botón de centrar si la geolocalización está disponible en el navegador 5135 if (navigator.geolocation) { 5136 if (centerLocationBtn) centerLocationBtn.style.display = 'inline-block'; 5137 } 5138 } 5139 return false; 5140 } 5141 5142 // Agregar un único listener 5143 mapBtn.addEventListener('click', openMapModalHandler); 5144 } else { 5145 console.error('El botón de mapa no se encontró en el DOM'); 5146 } 5147 5148 // Event listeners para los botones de la guÃa 5149 if (enableLocationGuideBtn) { 5150 enableLocationGuideBtn.addEventListener('click', function() { 5151 showLocationPermissionsGuide(); 5152 }); 5153 } 5154 5155 if (closeGuideBtn) { 5156 closeGuideBtn.addEventListener('click', function() { 5157 hideLocationPermissionsGuide(); 5158 }); 5159 } 5160 5161 // Event listener para el botón "Centrar" 5162 if (centerLocationBtn) { 5163 centerLocationBtn.addEventListener('click', function() { 5164 centerMapOnCurrentLocation(); 5165 }); 5166 } 5167 5168 // Cerrar modal 5169 if (closeBtn) { 5170 closeBtn.addEventListener('click', function() { 5171 mapModal.style.display = 'none'; 5172 // Resetear estado al cerrar 5173 locationPermissionsDenied = false; 5174 locationPermissionsEnabled = false; 5175 if (enableLocationGuideBtn) enableLocationGuideBtn.style.display = 'none'; 5176 if (centerLocationBtn) centerLocationBtn.style.display = 'none'; 5177 hideLocationPermissionsGuide(); 5178 // Limpiar mapa al cerrar 5179 if (map) { 5180 try { 5181 map.remove(); 5182 } catch (e) { 5183 console.log('Error al limpiar mapa:', e); 5184 } 5185 map = null; 5186 marker = null; 5187 } 5188 }); 5189 } 5190 5191 // Cerrar modal al hacer clic fuera del contenido 5192 window.addEventListener('click', function(event) { 5193 if (event.target === mapModal) { 5194 mapModal.style.display = 'none'; 5195 // Resetear estado al cerrar 5196 locationPermissionsDenied = false; 5197 locationPermissionsEnabled = false; 5198 if (enableLocationGuideBtn) enableLocationGuideBtn.style.display = 'none'; 5199 if (centerLocationBtn) centerLocationBtn.style.display = 'none'; 5200 hideLocationPermissionsGuide(); 5201 // Limpiar mapa al cerrar 5202 if (map) { 5203 try { 5204 map.remove(); 5205 } catch (e) { 5206 console.log('Error al limpiar mapa:', e); 5207 } 5208 map = null; 5209 marker = null; 5210 } 5211 } 5212 }); 5213 5214 // Confirmar ubicación seleccionada 5215 if (confirmBtn) { 5216 confirmBtn.addEventListener('click', async function() { 5217 if (selectedLat && selectedLng) { 5218 // Mostrar loader y deshabilitar botón 5219 confirmBtn.classList.add('loading'); 5220 confirmBtn.disabled = true; 5221 5222 try { 5223 // Guardar coordenadas en los campos hidden 5224 latitudeInput.value = selectedLat; 5225 longitudeInput.value = selectedLng; 5226 const radiusSelect = document.getElementById('radius-select'); 5227 radiusInput.value = radiusSelect ? radiusSelect.value : DEFAULT_RADIUS; 5228 5229 // Intentar obtener información del marcador primero 5230 let address = ''; 5231 5232 // Verificar si el marcador tiene información de ubicación 5233 if (marker && marker.getPopup && marker.getPopup()) { 5234 const popupContent = marker.getPopup().getContent(); 5235 if (popupContent && typeof popupContent === 'string' && popupContent.trim() !== '') { 5236 address = popupContent; 5237 console.log('ð Usando información del marcador:', address); 5238 } 5239 } 5240 5241 // Si el mapa no proporcionó información, hacer reverse geocoding 5242 if (!address || address.includes('lat') || address.includes('lng')) { 5243 console.log('ðºï¸ Obteniendo dirección para coordenadas:', selectedLat, selectedLng); 5244 address = await getAddressFromCoordinates(selectedLat, selectedLng); 5245 console.log('ðï¸ Dirección obtenida via geocoding:', address); 5246 } 5247 5248 locationInput.value = address; 5249 5250 // Si existe el campo visible de búsqueda, también lo actualizamos 5251 if (locationGoogleSearch) { 5252 console.log('ð Actualizando campo visible con:', address); 5253 locationGoogleSearch.value = address; 5254 } 5255 5256 // Definimos el tipo de búsqueda 5257 const searchTypeInput = document.getElementById('SearchType'); 5258 if (searchTypeInput) { 5259 searchTypeInput.value = 'lat_lng'; 5260 } 5261 5262 // Pequeña pausa para mostrar que el proceso se completó 5263 await new Promise(resolve => setTimeout(resolve, 500)); 5264 5265 // Cerrar el modal 5266 mapModal.style.display = 'none'; 5267 5268 // Limpiar mapa después de confirmar 5269 if (map) { 5270 try { 5271 map.remove(); 5272 } catch (e) { 5273 console.log('Error al limpiar mapa después de confirmar:', e); 5274 } 5275 map = null; 5276 marker = null; 5277 } 5278 } catch (error) { 5279 console.error('Error al procesar la ubicación:', error); 5280 alert('Error al procesar la ubicación. Por favor, inténtelo de nuevo.'); 5281 } finally { 5282 // Ocultar loader y rehabilitar botón 5283 confirmBtn.classList.remove('loading'); 5284 confirmBtn.disabled = false;
5285 } 5286 } else { 5287 alert('Por favor, seleccione una ubicación en el mapa antes de confirmar.'); 5288 } 5289 }); 5290 } 5291 5292 // Función para obtener la dirección aproximada a partir de coordenadas 5293 async function getAddressFromCoordinates(lat, lng) { 5294 try { 5295 console.log('ð Solicitando dirección para:', lat, lng); 5296 5297 // Intentar con el servicio que ya está funcionando en el autocomplete 5298 const response = await fetch(`https://ipapi.co/${lat},${lng}/json/`); 5299 5300 if (!response.ok) { 5301 throw new Error(`HTTP ${response.status}`); 5302 } 5303 5304 const data = await response.json(); 5305 console.log('ð¥ Respuesta de ipapi.co:', data); 5306 5307 if (data && !data.error) { 5308 let locationName = ''; 5309 5310 // Extraer información útil en orden de preferencia 5311 if (data.city) { 5312 locationName = data.city; 5313 } else if (data.region) { 5314 locationName = data.region; 5315 } 5316 5317 // Agregar región/estado si existe y es diferente 5318 if (data.region && data.region !== locationName && locationName) { 5319 locationName += `, ${data.region}`; 5320 } 5321 5322 // Agregar paÃs si existe 5323 if (data.country_name) { 5324 locationName += locationName ? `, ${data.country_name}` : data.country_name; 5325 } 5326 5327 const finalResult = locationName || `${lat.toFixed(4)}, ${lng.toFixed(4)}`; 5328 console.log('â Dirección procesada:', finalResult); 5329 return finalResult; 5330 } else { 5331 throw new Error('No data received or API error'); 5332 } 5333 } catch (error) { 5334 console.warn('â ï¸ Error con ipapi.co, intentando con método alternativo:', error); 5335 5336 // Fallback: usar reverse geocoding simplificado 5337 try { 5338 // Intentar con un servicio público que sà permite CORS 5339 const response = await fetch(`https://api.bigdatacloud.net/data/reverse-geocode-client?latitude=${lat}&longitude=${lng}&localityLanguage=es`); 5340 const data = await response.json(); 5341 console.log('ð¥ Respuesta de BigDataCloud:', data); 5342 5343 if (data) { 5344 let locationName = ''; 5345 5346 if (data.city) { 5347 locationName = data.city; 5348 } else if (data.locality) { 5349 locationName = data.locality; 5350 } else if (data.principalSubdivision) { 5351 locationName = data.principalSubdivision; 5352 } 5353 5354 // Agregar paÃs 5355 if (data.countryName && locationName) { 5356 locationName += `, ${data.countryName}`; 5357 } else if (data.countryName) { 5358 locationName = data.countryName; 5359 } 5360 5361 const finalResult = locationName || `${lat.toFixed(4)}, ${lng.toFixed(4)}`; 5362 console.log('â Dirección obtenida con BigDataCloud:', finalResult); 5363 return finalResult; 5364 } 5365 } catch (secondError) { 5366 console.error('ð¥ Error con ambos servicios:', secondError); 5367 } 5368 5369 // Si todo falla, devolver coordenadas simplificadas 5370 const errorResult = `${lat.toFixed(4)}, ${lng.toFixed(4)}`; 5371 console.log('ð¯ Usando coordenadas como último recurso:', errorResult); 5372 return errorResult; 5373 } 5374 } 5375 5376 // Mover el modal de mapa al final del body para evitar problemas de desbordamiento 5377 document.addEventListener("DOMContentLoaded", function() { 5378 if (mapModal && document.body) { 5379 document.body.appendChild(mapModal); 5380 } 5381 }); 5382 })(); 5383</script>
5383 5384 5385<!-- Script independiente para limpiar modal si no hay botón de mapa -->
5386<script> 5387 (function() { 5388 // Función robusta para limpiar el modal 5389 function cleanupMapModal() { 5390 try { 5391 // Verificar si existe el botón del mapa 5392 const mapBtn = document.getElementById('map-search-btn'); 5393 5394 if (!mapBtn) { 5395 console.log('ðï¸ Botón del mapa no encontrado - removiendo modal del mapa...'); 5396 // Si no existe el botón, remover el modal del mapa 5397 const mapModal = document.getElementById('map-modal'); 5398 if (mapModal) { 5399 mapModal.remove(); 5400 console.log('â Modal del mapa removido correctamente'); 5401 return true; // Indica que se completó la limpieza 5402 } 5403 } else { 5404 console.log('â Botón del mapa encontrado - modal del mapa disponible'); 5405 return true; // Indica que se completó la verificación 5406 } 5407 } catch (error) { 5408 console.error('Error al limpiar modal del mapa:', error); 5409 } 5410 return false; // Indica que no se pudo completar 5411 } 5412 5413 // Estrategia 1: Ejecutar inmediatamente si el DOM ya está listo 5414 if (document.readyState === 'loading') { 5415 // El DOM aún se está cargando, usar múltiples eventos 5416 let cleaned = false; 5417 5418 // Función que se ejecuta una sola vez 5419 function tryCleanup() { 5420 if (!cleaned && cleanupMapModal()) { 5421 cleaned = true; 5422 } 5423 } 5424 5425 // Estrategia 2: Múltiples eventos para garantizar ejecución 5426 document.addEventListener('DOMContentLoaded', tryCleanup); 5427 document.addEventListener('readystatechange', function() { 5428 if (document.readyState === 'interactive' || document.readyState === 'complete') { 5429 tryCleanup(); 5430 } 5431 }); 5432 window.addEventListener('load', tryCleanup); 5433 5434 // Estrategia 3: Verificación periódica como respaldo 5435 let attempts = 0; 5436 const maxAttempts = 20; // Máximo 2 segundos 5437 const checkInterval = setInterval(function() { 5438 attempts++; 5439 if (cleaned || attempts >= maxAttempts) { 5440 clearInterval(checkInterval); 5441 return; 5442 } 5443 5444 // Verificar si el DOM está listo 5445 if (document.readyState === 'interactive' || document.readyState === 'complete') { 5446 if (cleanupMapModal()) { 5447 cleaned = true; 5448 clearInterval(checkInterval); 5449 } 5450 } 5451 }, 100); 5452 5453 } else { 5454 // El DOM ya está listo, ejecutar inmediatamente 5455 cleanupMapModal(); 5456 } 5457 })(); 5458</script>
vendor: 1 bytes, line 5458
5458
5459<script> 5460 (function() { 5461 function run() { 5462 try { 5463 var span = document.querySelector('#PxMkAcion_Search .update-search-span'); 5464 var btn = document.getElementById('PxMkAcion_Search'); 5465 if (!span) return; 5466 5467 var themeHex = '#000000'; 5468 5469 function parseHex(hex) { 5470 if (!hex) return null; 5471 hex = String(hex).trim(); 5472 if (hex.startsWith('#')) hex = hex.slice(1); 5473 if (hex.length === 3) { 5474 hex = hex.split('').map(function(ch) { 5475 return ch + ch; 5476 }).join(''); 5477 } 5478 if (hex.length !== 6) return null; 5479 var r = parseInt(hex.slice(0, 2), 16); 5480 var g = parseInt(hex.slice(2, 4), 16); 5481 var b = parseInt(hex.slice(4, 6), 16); 5482 if ([r, g, b].some(function(v) { 5483 return isNaN(v); 5484 })) return null; 5485 return { 5486 r: r, 5487 g: g, 5488 b: b 5489 }; 5490 } 5491 5492 function relL(rgb) { 5493 function toLin(c) { 5494 c = c / 255; 5495 return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); 5496 } 5497 var R = toLin(rgb.r), 5498 G = toLin(rgb.g), 5499 B = toLin(rgb.b); 5500 return 0.2126 * R + 0.7152 * G + 0.0722 * B; 5501 } 5502 5503 function contrast(L1, L2) { 5504 var a = Math.max(L1, L2); 5505 var b = Math.min(L1, L2); 5506 return (a + 0.05) / (b + 0.05); 5507 } 5508 5509 var rgb = parseHex(themeHex); 5510 if (!rgb) { 5511 if (btn) { 5512 var bg = window.getComputedStyle(btn).backgroundColor; // rgb(a) 5513 var m = bg && bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/i); 5514 if (m) { 5515 rgb = { 5516 r: parseInt(m[1], 10), 5517 g: parseInt(m[2], 10), 5518 b: parseInt(m[3], 10) 5519 }; 5520 } 5521 } 5522 } 5523 if (!rgb) return; 5524 5525 var Lbg = relL(rgb); 5526 var Lwhite = relL({ 5527 r: 255, 5528 g: 255, 5529 b: 255 5530 }); 5531 var Lblack = relL({ 5532 r: 0, 5533 g: 0, 5534 b: 0 5535 }); 5536 var cWhite = contrast(Lbg, Lwhite); 5537 var cBlack = contrast(Lbg, Lblack); 5538 5539 var textColor = cBlack >= cWhite ? '#000000' : '#FFFFFF'; 5540 span.style.setProperty('color', textColor, 'important'); 5541 if (btn) { 5542 btn.style.setProperty('color', textColor, 'important'); 5543 5544 // Recolor inline SVG icons (search and loading) to match contrast color 5545 function paintInlineSVG(container, color) { 5546 try { 5547 var svgs = container.querySelectorAll('svg'); 5548 svgs.forEach(function(svg) { 5549 // Support SVGs that use currentColor 5550 svg.style.setProperty('color', color, 'important'); 5551 svg.setAttribute('color', color); 5552 // Force fill/stroke 5553 svg.style.setProperty('fill', color, 'important'); 5554 svg.style.setProperty('stroke', color, 'important'); 5555 // Update common shape elements 5556 svg.querySelectorAll('path, circle, rect, polygon, line, polyline, ellipse, g').forEach(function(node) { 5557 node.style.setProperty('fill', color, 'important'); 5558 node.style.setProperty('stroke', color, 'important'); 5559 }); 5560 5561 // Override attributes if they exist 5562 svg.querySelectorAll('[fill]').forEach(function(node) { 5563 node.setAttribute('fill', color); 5564 }); 5565 svg.querySelectorAll('[stroke]').forEach(function(node) { 5566 node.setAttribute('stroke', color); 5567 }); 5568 }); 5569 } catch (e) { 5570 /* ignore */ 5571 } 5572 } 5573 5574 var iconLabel = btn.querySelector('.px-mk-searchicon'); 5575 var loaderLabel = btn.querySelector('.px-mk-searchloader'); 5576 if (iconLabel) paintInlineSVG(iconLabel, textColor); 5577 if (loaderLabel) paintInlineSVG(loaderLabel, textColor); 5578 } 5579 } catch (e) { 5580 /* ignore */ 5581 } 5582 } 5583 5584 if (document.readyState === 'loading') { 5585 document.addEventListener('DOMContentLoaded', run); 5586 } else { 5587 run(); 5588 } 5589 })(); 5590</script>
5590 </div> 5591 </div><div id='toggleMenu' class="btn-toggle-menu" onclick='toggleMenu()'><div class="rallita" ></div></div></div></div> 5592 5593 5594<div id='Overlay' class="" ></div> 5595 5596</div> 5597 5598</div> 5599 <div class="main_wraper_content" id="main_wraper_content"> 5600 5601 5602<div class="neo_template_container neo_template_ computer"> 5603 5604 5605<div class="content-bg-color" ><div class="bg-color top" ></div><div class="bg-color bottom" ></div></div> 5606 5607 5608<div class="content-background" ><div class="background" ><div class='container-neo-slider' Slide='HomePage' Width='1900' Height='1000' Loop='true' Delay='5' Effect='fade' Speed='2000'> 5609 <div class="neo_template_block neo_neo_swiper pxModule_include ModuloWrap_neo_swiper" id="neo_swiper" > 5610 5611 5612<!-- Module Start --> 5613 5614<div class="megacontainer-neo-swiper"> 5615 <div class="swiper-container-3154"> <!-- le asignamos el numero random al contenedor --> 5616 5617 <div class="swiper-wrapper"> 5618 <div class="swiper-slide slide-one-pic"> 5619 <img src="https://images-new.pxsol.com/r0bEr9hCe0l8BE9lfKIUYIY5GOGpHTi3Nem_GYaqMGQ/rs:fill:1900:1000:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F2798375230422747de42b379cd2293ecc8c10fdb9ad.jpg@jpg" 5620 width="1900" 5621 height="1000" 5622 style="aspect-ratio: 1900/1000;" 5623 alt="The Lark Guest House"> 5624 </div> 5625 </div> 5626 <!-- Add Arrows --> 5627 5628 </div> 5629 <!-- Asà mismo para dataconfig-swiper le pasamos el numero random para identificarlo de otros --> 5630 <div class="dataconfig-swiper" data-id="3154" data-loop="true" data-speed=2000 data-effect="fade" data-delay=5000 style="display:none" ></div> 5631</div> 5632 5633 5634 </div> 5635 </div></div> <img loading="lazy" class="hidden-desktop logo-top-mobile" lazy-src="https://files-p.pxsol.com/23292/company/library/user/122470399310b60a3f3e2b3539f6352ae0c53144521.png" alt="LaAlondraCasadehuespedes" > </image></div> 5636 5637 5638<div class="flex flex-wrap container-cards" ><div class="xs-100 sm-50 md-25 card" ><a class="content-items" href="/en/habitaciones.html" target=""><span class='place' >Rooms</span><div class="btn-gral" >Walk</div><div class='container-neo-slider' Slide='TopHabitaciones' Width='500' Height='500' Loop='true' Effect='Fade '> 5639 <div class="neo_template_block neo_neo_swiper pxModule_include ModuloWrap_neo_swiper" id="neo_swiper" > 5640 5641 5642<!-- Module Start --> 5643 5644<div class="megacontainer-neo-swiper"> 5645 <div class="swiper-container-4773"> <!-- le asignamos el numero random al contenedor --> 5646 5647 <div class="swiper-wrapper"> 5648 <div class="swiper-slide slide-one-pic"> 5649 <img src="https://images-new.pxsol.com/WDbzIOK7jMyuzbs7ypp6Bg4v0f5QgrqPv3r5ZqBcQeE/rs:fill:500:500:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F12242898094ddc115a5d1e2e7d33db048e76f10dbbf.jpg@jpg" 5650 width="500" 5651 height="500" 5652 style="aspect-ratio: 500/500;" 5653 alt="The Lark Guest House"> 5654 </div> 5655 </div> 5656 <!-- Add Arrows --> 5657 5658 </div> 5659 <!-- Asà mismo para dataconfig-swiper le pasamos el numero random para identificarlo de otros --> 5660 <div class="dataconfig-swiper" data-id="4773" data-loop="true" data-speed=800 data-effect="fade" data-delay=5000 style="display:none" ></div> 5661</div> 5662 5663 5664 </div> 5665 </div></a></div><div class="xs-100 sm-50 md-25 card" ><a class="content-items" href="/en/servicios.html" target=""><span class='place' >Services</span><div class="btn-gral" >Known</div><div class='container-neo-slider' Slide='TopServicios' Width='500' Height='500' Loop='true' Effect='Fade '> 5666 <div class="neo_template_block neo_neo_swiper pxModule_include ModuloWrap_neo_swiper" id="neo_swiper" > 5667 5668 5669<!-- Module Start --> 5670 5671<div class="megacontainer-neo-swiper"> 5672 <div class="swiper-container-1078"> <!-- le asignamos el numero random al contenedor --> 5673 5674 <div class="swiper-wrapper"> 5675 <div class="swiper-slide slide-one-pic"> 5676 <img src="https://images-new.pxsol.com/dKmgkKcCwuWQAS1EDVa-GAVlbnL6Vc4A
5676kvJpOVrLJAA/rs:fill:500:500:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F15740868231b76c95d808f3984a02b8c60810d08f70.jpg@jpg" 5677 width="500" 5678 height="500" 5679 style="aspect-ratio: 500/500;" 5680 alt="The Lark Guest House"> 5681 </div> 5682 </div> 5683 <!-- Add Arrows --> 5684 5685 </div> 5686 <!-- Asà mismo para dataconfig-swiper le pasamos el numero random para identificarlo de otros --> 5687 <div class="dataconfig-swiper" data-id="1078" data-loop="true" data-speed=800 data-effect="fade" data-delay=5000 style="display:none" ></div> 5688</div> 5689 5690 5691 </div> 5692 </div></a></div><div class="xs-100 sm-50 md-25 card" ><a class="content-items" href="/en/contacto.html" target=""><span class='place' >Location and Contact</span><div class="btn-gral" >Discover</div><div class='container-neo-slider' Slide='TopContacto' Width='1900' Height='900' Loop='true' Effect='Fade '> 5693 <div class="neo_template_block neo_neo_swiper pxModule_include ModuloWrap_neo_swiper" id="neo_swiper" > 5694 5695 5696<!-- Module Start --> 5697 5698<div class="megacontainer-neo-swiper"> 5699 <div class="swiper-container-1385"> <!-- le asignamos el numero random al contenedor --> 5700 5701 <div class="swiper-wrapper"> 5702 <div class="swiper-slide slide-one-pic"> 5703 <img src="https://images-new.pxsol.com/wZyVgr8FdTskJnNqWrAXSk0r4-kUoWQQJFDcLCeDnio/rs:fill:1900:900:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F52469535990a1b193d93db850763157a972331f1a5.jpg@jpg" 5704 width="1900" 5705 height="900" 5706 style="aspect-ratio: 1900/900;" 5707 alt="The Lark Guest House"> 5708 </div> 5709 </div> 5710 <!-- Add Arrows --> 5711 5712 </div> 5713 <!-- Asà mismo para dataconfig-swiper le pasamos el numero random para identificarlo de otros --> 5714 <div class="dataconfig-swiper" data-id="1385" data-loop="true" data-speed=800 data-effect="fade" data-delay=5000 style="display:none" ></div> 5715</div> 5716 5717 5718 </div> 5719 </div></a></div><div class="xs-100 sm-50 md-25 card" ><a class="content-items" href="/en/promos.html" target=""><span class='place' >Promotions</span><div class="btn-gral" >Enjoy</div><div class='container-neo-slider' Slide='TopPromos' Width='1900' Height='900' Loop='true' Effect='Fade '> 5720 <div class="neo_template_block neo_neo_swiper pxModule_include ModuloWrap_neo_swiper" id="neo_swiper" > 5721 5722 5723<!-- Module Start --> 5724 5725<div class="megacontainer-neo-swiper"> 5726 <div class="swiper-container-4793"> <!-- le asignamos el numero random al contenedor --> 5727 5728 <div class="swiper-wrapper"> 5729 <div class="swiper-slide"> 5730 <img data-src="https://images-new.pxsol.com/a-rMUkX1qM6MlX1rCM7kyKrqoQrzR9gXeZ-fnRykmOM/rs:fill:1900:900:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F10493907126724d13892be79374dfe75664d0248221.jpg@jpg" class="swiper-lazy" 5731 width="1900" 5732 height="900" 5733 style="aspect-ratio: 1900/900;" 5734 alt="The Lark Guest House"> 5735 <div class="swiper-lazy-preloader"></div> 5736 </div> 5737 <div class="swiper-slide"> 5738 <img data-src="https://images-new.pxsol.com/MQXou2LW_AsquUIgJFhPIZ3ZGpfJ8qIJn9JHMFCgQLM/rs:fill:1900:900:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F209878146608fba72f44753e3979407bbbbdb61efcc.jpg@jpg" class="swiper-lazy" 5739 width="1900" 5740 height="900" 5741 style="aspect-ratio: 1900/900;" 5742 alt="The Lark Guest House"> 5743 <div class="swiper-lazy-preloader"></div> 5744 </div> 5745 <div class="swiper-slide"> 5746 <img data-src="https://images-new.pxsol.com/P1xB2GQ1bJoVFFyB07YdRcTASjmk0b
5746ka_YyeCpBymkU/rs:fill:1900:900:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F27983754800543647273fb7c5551f9d42f0a790265e.jpg@jpg" class="swiper-lazy" 5747 width="1900" 5748 height="900" 5749 style="aspect-ratio: 1900/900;" 5750 alt="The Lark Guest House"> 5751 <div class="swiper-lazy-preloader"></div> 5752 </div> 5753 </div> 5754 <!-- Add Arrows --> 5755 <div class="swiper-button-next swiper-button-next-4793"></div> <!-- igualmente el numero random va para las flechas de cambio de imágenes --> 5756 <div class="swiper-button-prev swiper-button-prev-4793"></div> 5757 5758 </div> 5759 <!-- Asà mismo para dataconfig-swiper le pasamos el numero random para identificarlo de otros --> 5760 <div class="dataconfig-swiper" data-id="4793" data-loop="true" data-speed=800 data-effect="fade" data-delay=5000 style="display:none" ></div> 5761</div> 5762 5763 5764 </div> 5765 </div></a></div></div> 5766 5767 5768<div class="info-container-2 padding-xs-50" ><div class="container" ><div class="desc-hotel" ><span class='' >welcome to</span><h1 class='' >The Lark Guest House</h1><div class="desc-hotel-down" ><p class='' >La Alondra is not only a hotel, it is also a refuge for modern nomads who travel the world and miss home. <br />In the heart of Corrientes, on the edge of the historic center and a 5-minute drive from the river, an old house was transformed into a Design Hotel with fifteen unique rooms, each with its own soul, inviting you to rest, where the details are the protagonists. <br />Strategically located 20 minutes from Corrientes City Airport and 40 minutes from Resistencia International Airport. <br />La Alondra is divided into two worlds: <br />â¢The Guest House, with its seven rooms that look out onto the leafy patio, mango trees and a pool that embraces the silence. <br />â¢El Salvador, an old factory shed that was once a butcher shop and today breathes romance and industrial
5768character. There, eight bedrooms, an exclusive living room âEl Galpónâ, a gym, and a massage room create an intimate, almost secret atmosphere.<br />The soul of the house extends to the Bistro, our restaurant open to the public, where the bread and pasta are homemade, the products are seasonal, and the desserts honor those with a sweet tooth.<br /> The team is professional, but above all hospitable. They welcome guests with the joy of someone waiting for a friend who has come from afar.<br />Today, La Alondra is an icon of the city.<br />And also, the perfect gateway to discover the Iberá Wetlands.<br />Because whoever passes through Corrientes and does not know La Alondra, leaves without knowing its true essence.<br />There is a myth: ¨ You always return to La Alondra¨<br /></p></div></div><div class="img-hotel " > <img loading="lazy" class="" lazy-src="https://files-p.pxsol.com/23292/company/library/user/2798375230422747de42b379cd2293ecc8c10fdb9ad.jpg" alt="LaAlondraCasadehuespedes" > </image></div></div></div> 5769 5770 5771<div id='indexGallery' class="full diplo_indexgal relative" ><div class='slider-index flex flex-m-center full' Slide='Destacado' Width='1900' Height='600' Loop='false' Effect='fade'> 5772 <div class="neo_template_block neo_neo_swiper pxModule_include ModuloWrap_neo_swiper" id="neo_swiper" > 5773 5774 5775<!-- Module Start --> 5776 5777<div class="megacontainer-neo-swiper"> 5778 <div class="swiper-container-828"> <!-- le asignamos el numero random al contenedor --> 5779 5780 <div class="swiper-wrapper"> 5781 <div class="swiper-slide slide-one-pic"> 5782 <img src="https://images-new.pxsol.com/P7QF7sNBmotkASKbrcR4vK5pgTfP1JtID3T5z-uHvt4/rs:fill:1900:600:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F19238830897d9a163eec8c08e2cc1e867579de3da8a.jpg@jpg" 5783 width="1900" 5784 height="600" 5785 style="aspect-ratio: 1900/600;" 5786 alt="The Lark Guest House"> 5787 </div> 5788 </div> 5789 <!-- Add Arrows --> 5790 5791 </div> 5792 <!-- Asà mismo para dataconfig-swiper le pasamos el numero random para identificarlo de otros --> 5793 <div class="dataconfig-swiper" data-id="828" data-loop="false" data-speed=800 data-effect="fade" data-delay=5000 style="display:none" ></div> 5794</div> 5795 5796 5797 </div> 5798 </div><div class="diplo_indexgal_overlay flex flex-center" ><div class="diplo_contentblock flex-column flex-m-center flex-s-start" ><div class="diplo_heading_lower fontsize-35px fontsize-lg-60px diplo_white padding-bottom-20 lineh-120" style='max-width: 12em;'>Discover our hotel</div><div class="diplo_white diplo_paragraphs margin-bottom-20" ><p class='textleft diplo_white ' >We invite you to visit our facilities and surroundings.</p></div><a class="diplo_cta cta_white_outline cta_autoh padding-20 pointerInitial" href="/en/galeria.html" target=""><div class="mdi mdi-image-multiple margin-right-10 fontsize-18px" ></div><div class="" >See Gallery</div></a></div></div></div> 5799 5800 5801<div id='heroDiploTwo' class="full" ><div class="diplo_hero_half autoheight full flex flex-center padding-top-20 padding-bottom-70" ><div class="diplo_main_herotxt full flex flex-center" ><div class="diplo_contentblock padding-top-25 padding-bottom-25 padding-lg-top-50 padding-lg-bottom-50" ><div class='full' Slides='3'> 5802 <div class="neo_template_block neo_neo_social_proof pxModule_include ModuloWrap_neo_social_proof" id="neo_social_proof" > 5803 5804 5805 5806<div class="swiper-socialproof-initializer" slides="3" swiperid="neosocialproof_1889963772"></div> 5807 5808<div class="neo_socialproof_slider_titulo">Our guests say</div> 5809 5810<div class="neo_promoswiper_container swiper-container" id="neosocialproof_1889963772"> 5811 5812<div class="neo_socialproof_slider_container swiper-wrapper"> 5813 5814 5815 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_514574"> 5816 5817 <div class="neo_socialproof_score"> 5818 9.7 </div> 5819 5820 <div class="neo_socialproof_subtitle"> 5821 The best of the hotel: 5822 </div> 5823 <div class="neo_socialproof_slide_besttxt">
5824 Los ambientes son excelentes, cada detalle muy bien cuidado y pensado. La habitación muy cómoda, la gente muy amable, una muy buena experiencia, recomendable. </div> 5825 <div class="neo_socialproof_slide_name"> 5826 JoseÌ Edison </div> 5827 </a> 5828 5829 </div> 5830 5831 5832 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_514388"> 5833 5834 <div class="neo_socialproof_score"> 5835 10 </div> 5836 5837 <div class="neo_socialproof_subtitle"> 5838 The best of the hotel: 5839 </div> 5840 <div class="neo_socialproof_slide_besttxt"> 5841 La atención es espectacular!la buena onda y la comida muy muy buena </div> 5842 <div class="neo_socialproof_slide_name"> 5843 JoseÌ Edison </div> 5844 </a> 5845 5846 </div> 5847 5848 5849 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_514385"> 5850 5851 <div class="neo_socialproof_score"> 5852 9.4 </div> 5853 5854 <div class="neo_socialproof_subtitle"> 5855 The best of the hotel: 5856 </div> 5857 <div class="neo_socialproof_slide_besttxt"> 5858 Excelente el diseño de interiores, un placer ..y genera calidez </div> 5859 <div class="neo_socialproof_slide_name"> 5860 JoseÌ Edison </div> 5861 </a> 5862 5863 </div> 5864 5865 5866 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_461341"> 5867 5868 <div class="neo_socialproof_score"> 5869 8.9 </div> 5870 5871 <div class="neo_socialproof_subtitle"> 5872 The best of the hotel: 5873 </div> 5874 <div class="neo_socialproof_slide_besttxt"> 5875 Quiero felicitar a todo el equipo de La Alondra, que una vez más nos trató de maravilla, especialmente en el restaurante, con una carta muy bien elaborada y, sobre todo, con bebidas (vinos) a precios muy razonables. El desayuno fue excelente, con una gran selección de frutas, yogur, panes y bollerÃa. </div> 5876 <div class="neo_socialproof_slide_name"> 5877 Maksimilian Kiefer, Brazil </div> 5878 </a> 5879 5880 </div> 5881 5882 5883 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_460284"> 5884 5885 <div class="neo_socialproof_score"> 5886 10 </div> 5887 5888 <div class="neo_socialproof_subtitle"> 5889 The best of the hotel: 5890 </div> 5891 <div class="neo_socialproof_slide_besttxt"> 5892 muy buena predisposición y amabilidad de todo el personal </div> 5893 <div class="neo_socialproof_slide_name"> 5894 Paola, Argentina </div> 5895 </a> 5896 5897 </div> 5898 5899 5900 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_456005"> 5901 5902 <div class="neo_socialproof_score"> 5903 10 </div> 5904 5905 <div class="neo_socialproof_subtitle"> 5906 The best of the hotel: 5907 </div> 5908 <div class="neo_socialproof_slide_besttxt"> 5909 Excelente atencion, me senti muy comoda y muy a gusto </div> 5910 <div class="neo_socialproof_slide_name"> 5911 Maria Constanza, Argentina </div> 5912 </a> 5913 5914 </div> 5915 5916 5917 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_454805"> 5918 5919 <div class="neo_socialproof_score"> 5920 10 </div> 5921 5922 <div class="neo_socialproof_subtitle"> 5923 The best of the hotel: 5924 </div> 5925 <div class="neo_socialproof_slide_besttxt"> 5926 Muy buena atención es la primera vez pero muy conforme con todo expectacular </div> 5927 <div class="neo_socialproof_slide_name"> 5928 Jose Luis, Argentina </div> 5929 </a> 5930 5931 </div> 5932 5933 5934 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_454594"> 5935 5936 <div class="neo_socialproof_score"> 5937 9.9 </div> 5938 5939 <div class="neo_socialproof_subtitle"> 5940 The best of the hotel: 5941 </div> 5942 <div class="neo_socialproof_slide_besttxt"> 5943 Sin dudas el mejor lugar para alejarse en Capital. Tiene magia! </div> 5944 <div class="neo_socialproof_slide_name"> 5945 Carolina, Argentina </div> 5946 </a> 5947 5948 </div> 5949 5950 5951 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_453674"> 5952 5953 <div class="neo_socialproof_score"> 5954 9.6 </div> 5955 5956 <div class="neo_socialproof_subtitle"> 5957 The best of the hotel: 5958 </div> 5959 <div class="neo_socialproof_slide_besttxt"> 5960 bien equipado el gimnasio </div> 5961 <div class="neo_socialproof_slide_name"> 5962 Florencia, Argentina </div> 5963 </a> 5964 5965 </div> 5966 5967 5968 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_452647"> 5969 5970 <div class="neo_socialproof_score"> 5971 9.1 </div> 5972 5973 <div class="neo_socialproof_subtitle"> 5974 The best of the hotel: 5975 </div> 5976 <div class="neo_socialproof_slide_besttxt"> 5977 La habitación número 3 me encantó en comparación con las otras en las que he estado ? </div> 5978 <div class="neo_socialproof_slide_name"> 5979 Patricia, Argentina </div> 5980 </a> 5981 5982 </div> 5983 5984 5985 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_452360"> 5986 5987 <div class="neo_socialproof_score"> 5988 9.9 </div> 5989 5990 <div class="neo_socialproof_subtitle"> 5991 The best of the hotel: 5992 </div> 5993 <div class="neo_socialproof_slide_besttxt"> 5994 La atención de todo el personal me hacen sentir verdaderamente como en mi casa. Impecables todos. </
5994div> 5995 <div class="neo_socialproof_slide_name"> 5996 Gonzalo , Argentina </div> 5997 </a> 5998 5999 </div> 6000 6001 6002 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_452129"> 6003 6004 <div class="neo_socialproof_score"> 6005 8.7 </div> 6006 6007 <div class="neo_socialproof_subtitle"> 6008 The best of the hotel: 6009 </div> 6010 <div class="neo_socialproof_slide_besttxt"> 6011 La atención es excelente, y el hotel hermoso. La comida riquÃsima, muy recomendable! </div> 6012 <div class="neo_socialproof_slide_name"> 6013 Daniela, Argentina </div> 6014 </a> 6015 6016 </div> 6017 6018 6019 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_424842"> 6020 6021 <div class="neo_socialproof_score"> 6022 10 </div> 6023 6024 <div class="neo_socialproof_subtitle"> 6025 The best of the hotel: 6026 </div> 6027 <div class="neo_socialproof_slide_besttxt"> 6028 Incredible hotel. You never wanted to leave. The restaurant was the best in Corrientes. The breakfast was a 10. The attention from each and every staff member was unbeatable. I would come back again and again. </div> 6029 <div class="neo_socialproof_slide_name"> 6030 Rodrigo </div> 6031 </a> 6032 6033 </div> 6034 6035 6036 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_424841"> 6037 6038 <div class="neo_socialproof_score"> 6039 10 </div> 6040 6041 <div class="neo_socialproof_subtitle"> 6042 The best of the hotel: 6043 </div> 6044 <div class="neo_socialproof_slide_besttxt"> 6045 Excellent place. From the staff's attention, to the cleanliness, to the breakfast and lunch. Plus, the atmosphere makes it a unique place to stay. 10 points. </div> 6046 <div class="neo_socialproof_slide_name"> 6047 Ariel </div> 6048 </a> 6049 6050 </div> 6051 6052 6053 <div class="neo_socialproof_slide_item swiper-slide" id="neosocial_item_424840"> 6054 6055 <div class="neo_socialproof_score"> 6056 10 </div> 6057 6058 <div class="neo_socialproof_subtitle"> 6059 The best of the hotel: 6060 </div> 6061 <div class="neo_socialproof_slide_besttxt"> 6062 Located in the center of Corrientes, La Alondra is a hotel that exudes peace and tranquility. The rooms retain much of the building's original structure, with exposed brick walls and wood, creating a harmonious and beautiful combination. The staff is friendly and warm. This is a very good restaurant. A place to return to time and time again. </div> 6063 <div class="neo_socialproof_slide_name"> 6064 Laura </div> 6065 </a> 6066 6067 </div> 6068 6069 6070</div> 6071 6072 6073<button type="button" class="swiper-socialproof-nav swiper-prev"><i class="mdi mdi-chevron-left"></i></button> 6074<button type="button" class="swiper-socialproof-nav swiper-next"><i class="mdi mdi-chevron-right"></i></button> 6075 6076 6077</div> 6078 6079 </div> 6080 </div></div></div></div><div class='container-neo-slider' Slide='FondoComentarios' Width='1900' Height='900' Loop='true' Effect='Fade '> 6081 <div class="neo_template_block neo_neo_swiper pxModule_include ModuloWrap_neo_swiper" id="neo_swiper" > 6082 6083 6084<!-- Module Start --> 6085 6086<div class="megacontainer-neo-swiper"> 6087 <div class="swiper-container-1913"> <!-- le asignamos el numero random al contenedor --> 6088 6089 <div class="swiper-wrapper"> 6090 <div class="swiper-slide slide-one-pic"> 6091 <img src="https://images-new.pxsol.com/b4RsUUS3KVvh4CcSutb0nRaaHMyYwGsD1swhT8y7EjE/rs:fill:1900:900:1/q:80/plain/https%3A%2F%2Ffiles-p.pxsol.com%2F23292%2Fcompany%2Flibrary%2Fuser%2F1049391254411533aff2485629eb79495a8f92e4060.jpg@jpg" 6092 width="1900" 6093 height="900" 6094 style="aspect-ratio: 1900/900;" 6095 alt="The Lark Guest House"> 6096 </div> 6097 </div> 6098 <!-- Add Arrows --> 6099 6100 </div> 6101 <!-- Asà mismo para dataconfig-swiper le pasamos el numero random para identificarlo de otros --> 6102 <div class="dataconfig-swiper" data-id="1913" data-loop="true" data-speed=800 data-effect="fade" data-delay=5000 style="display:none" ></div> 6103</div> 6104 6105 6106 </div> 6107 </div></div> 6108 6109</div> 6110 6111 </div> 6112 6113 6114 6115 <div class="main_wraper_footer" id="main_wraper_footer"> 6116 6117 6118<div class="neo_template_container neo_template_ computer"> 6119 6120 6121<div class="megacontainer-footer" ><div class="container-info-footer" ><div class="contact" ><div class='' > 6122 <div class="neo_template_block neo_neo_contact_info pxModule_include ModuloWrap_neo_contact_info" id="neo_contact_info" > 6123 6124<div class="neo-contact-container"> 6125 <h4 class="neo-contact-title"> 6126 La Alondra Casa de huéspedes </h4> 6127 <ul> 6128 6129 <li> 6130 <a href="tel:+54 379 443 0555"> 6131 <i class="mdi mdi-phone-in-talk"></i> 6132 +54 379 443 0555 </a> 6133 </li> 6134 6135 <li> 6136 <a href="tel: +54 379 443 0555"> 6137 <i class="mdi mdi-phone-in-talk"></i> 6138 +54 379 443 0555 6139 </a> 6140 </li> 6141 6142 <li>
6143 <a href="https://api.whatsapp.com/send?phone=543794282950" target="_blank"> 6144 <i class="mdi mdi-whatsapp"></i> 6145 +54 379 428 2950 </a> 6146 </li> 6147 6148 <li> 6149 <a href="https://www.google.com/maps/search/La Alondra Casa de huéspedes, Av. 3 de Abril 827, W3400AII Corrientes, Argentina Corrientes - Argentina" target="_blank"> 6150 <i class="mdi mdi-map-marker"></i> 6151 Av. 3 de Abril 827, W3400AII Corrientes, Argentina </a> 6152 </li> 6153 6154 <li> 6155 <a href="/cdn-cgi/l/email-protection#e89a8d9b8d9a9e899ba88489898487868c9a89c68b8785c6899a"> 6156 <i class="mdi mdi-email"></i> 6157 <span class="__cf_email__" data-cfemail="364453455344405745765a57575a59585244571855595b185744">[email protected]</span> </a> 6158 </li> 6159 </ul> 6160</div> 6161 </div> 6162 </div></div><div class="logo_content flex flex-column flex-center" ><div class="logo" > <img loading="lazy" class="" lazy-src="https://files-p.pxsol.com/23292/company/library/user/122470399310b60a3f3e2b3539f6352ae0c53144521.png" alt="LaAlondraCasadehuespedes" > </image></div></div><div class="social" ><div class="flex social-links" ><div class='' > 6163 <div class="neo_template_block neo_neo_social_links pxModule_include ModuloWrap_neo_social_links" id="neo_social_links" > 6164 6165 6166<div class="neo_social_links_container social_block"> 6167 <ul class="neo_links_list"> 6168 <li class="facebook_page"> 6169 <a href="https://www.facebook.com/laalondracasadehuespedes/?locale=es_LA" target="_blank"> 6170 <i class="mdi mdi-facebook"></i> 6171 </a> 6172 </li> 6173 <li class="instagram_page"> 6174 <a href="https://www.google.com/search?q=la+alondra+instagram&oq=la+alondra+insta&gs_lcrp=EgZjaHJvbWUqBwgBECEYoAEyBggAEEUYOTIHCAEQIRigAdIBCDY2MTFqMGo0qAIIsAIB8QVUUDBTBLEV0A&sourceid=chrome&ie=UTF-8" target="_blank"> 6175 <i class="mdi mdi-instagram"></i> 6176 </a> 6177 </li> 6178 </ul> 6179</div> 6180 <div class="wsp_floating"> 6181 <a href="https://api.whatsapp.com/send?phone=543794282950" target="_blank"> 6182 <i class="mdi mdi-whatsapp"></i> 6183 </a> 6184 </div> 6185 </div> 6186 </div><a class="vcn" href="https://www.instagram.com/vacacionoficial/" target=""><i class='mdi mdi-instagram' ></i><p class='' style='font-size: 1.3rem;'>VCN</p></a></div><div class="cv-container" ><div class='hidden' ><div class='pxModule_include ModuloWrap_newsletter '><div id="content_news"> 6187 <div class="left full titlenewsletter">SUBSCRIBE TO OUR NEWSLETTER</div> 6188 <form id="form_suscribe" name="form_suscribe" method="post" action="/contact/newsletter"> 6189 <div class="wrap_imputs"> 6190 <div class="wrap_emails"> 6191 <input name="email" type="text" id="email" class="input_newsletter" value="" placeholder="Enter your Email" /> 6192 </div> 6193 <div class="SuscribeTitle"> 6194 <div id="newsletter-recaptcha" data-sitekey="6LfWJEIUAAAAANStHukodcdKv4tnwSFLknAMB_FM"></div> 6195 <button type="submit" onClick="ga('send','event','click','boton_suscribirse','form_suscribirse');" class="boton_newsletter" id="Import">to subscribe</button> 6196 <input name="company_id" type="hidden" id="company_id" value="23292" /> 6197 </div> 6198 </div> 6199 </form> 6200</div> 6201</div></div><p class='' >Would you like to join our team?</p><a class="" href="/cdn-cgi/l/email-protection#ee9c8b9d8b9c988f9dae828f8f8281808a9c8fc08d8183c08f9c" target="">Send CV</a></div></div></div></div> 6202 6203</div> 6204 6205 <div id="footer_px" class="noprint footer_px_fix" style="max-width: 100vw; box-sizing: border-box; overflow-x: hidden;"> 6206 <div class="wraper_footerpx flex-column flex-center"> 6207 6208 6209 <div class="texto_footerpx"> 6210 By using this website, you agree to the use of cookies. <a target="_blank" rel="nofollow" href="/cookiespolicies.php?pos=LaAlondraCasadehuespedes" class="footer_link">Cookies policy</a> | <a target="_blank" rel="nofollow" href="/terms.php?pos=LaAlondraCasadehuespedes" class="footer_link">Terminos y Condiciones</a> | <a target="_blank" rel="nofollow" href="/policies.php?pos=LaAlondraCasadehuespedes" class="footer_link">Privacy Policy</a> | <span>Cache: 6211 2026-09-26 12:28:07 | </span><a href="" rel="nofollow" target="_blank">Textos</a> | <span class="framework_f">Framework: 3 | <span class="framework_f">Tag: <span class="tag_cookie">..</span> </span> </span> 6212 </div> 6213 6214 <div class="pxsol_link_f"> 6215 <a style="text-decoration: underline !important;" target="_blank" href="https://www.pxsol.com/pos_source=LaAlondraCasadehuespedes" class="footer_link">Sistema Hotelero</a> 6216 por <a href="/" target="_blank" class="footer_link footer_logo_svg" title="Sistema Hotelero"> 6217 <?xml version="1.0" encoding="UTF-8" standalone="no"?> 6218<svg 6219 xmlns:dc="http://purl.org/dc/elements/1.1/" 6220 xmlns:cc="http://creativecommons.org/ns#" 6221 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 6222 xmlns:svg="http://www.w3.org/2000/svg" 6223 xmlns="http://www.w3.org/2000/svg" 6224 viewBox="0 0 752.42535 358.37866" 6225 height="50px" 6226 width="23px" 6227 xml:space="preserve" 6228 id="svg2" 6229 version="1.1"><metadata 6230 id="metadata8"><rdf:RDF><cc:Work 6231 rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type 6232 rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs 6233 id="defs6"><clipPath 6234 id="clipPath18" 6235 clipPathUnits="userSpaceOnUse"><path 6236 id="path16" 6237 d="M 0,268.784 H 564.319 V 0 H 0 Z" /></clipPath></defs><g 6238 transform="matrix(1.3333333,0,0,-1.3333333,0,358.37867)" 6239 id="g10"><g 6240 id="g12"><g 6241 clip-path="url(#clipPath18)" 6242 id="g14"><g 6243 transform="translate(23.3438,154.8828)" 6244 id="g20"><path 6245 id="path22" 6246 style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none" 6247 d="m 0,0 h 12.405 c 11.978,0 20.768,1.891 26.369,5.674 5.601,3.781 8.4,9.691 8.4,17.728 0,7.447 -2.507,13.002 -7.521,16.666 -5.013,3.664 -12.828,5.496 -23.44,5.496 H 0 Z m 71.202,24.112 c 0,-13.534 -4.884,-23.905 -14.65,-31.115 -9.768,-7.21 -23.67,-10.814 -41.707,-10.814 H 0 V -66.309 H -23.344 V 63.294 h 41.118 c 17.841,0 31.207,-3.311 40.097,-9.929 8.886,-6.619 13.331,-16.37 13.331,-29.253" /></g><g 6248 transform="translate(325.4336,123.7686)" 6249 id="g24"><path 6250 id="path26" 6251 style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none"
6252 d="m 0,0 c 0,-11.524 -4.59,-20.565 -13.773,-27.126 -9.179,-6.561 -21.846,-9.84 -37.994,-9.84 -16.149,0 -29.367,2.274 -39.653,6.824 v 20.036 c 6.509,-2.78 13.43,-4.964 20.754,-6.56 7.327,-1.596 14.147,-2.392 20.462,-2.392 9.246,0 16.068,1.594 20.462,4.785 4.396,3.191 6.595,7.475 6.595,12.853 0,4.847 -2.02,8.956 -6.057,12.323 -4.039,3.369 -12.372,7.358 -25.005,11.968 -13.023,4.787 -22.204,10.252 -27.542,16.4 -5.341,6.145 -8.01,13.532 -8.01,22.161 0,10.815 4.233,19.324 12.698,25.53 8.463,6.205 19.827,9.308 34.087,9.308 13.675,0 27.284,-2.719 40.829,-8.156 L -9.572,70.829 c -12.697,4.844 -24.028,7.269 -33.99,7.269 -7.555,0 -13.285,-1.494 -17.19,-4.477 -3.906,-2.985 -5.86,-6.93 -5.86,-11.834 0,-3.369 0.781,-6.25 2.344,-8.644 1.563,-2.393 4.134,-4.653 7.716,-6.782 3.58,-2.127 10.026,-4.935 19.339,-8.421 10.484,-3.959 18.166,-7.654 23.05,-11.08 4.884,-3.429 8.464,-7.3 10.745,-11.613 C -1.14,10.933 0,5.85 0,0" /></g><g 6253 transform="translate(355.8486,153.5532)" 6254 id="g28"><path 6255 id="path30" 6256 style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none" 6257 d="m 0,0 c 0,-15.956 3.547,-28.057 10.646,-36.299 7.097,-8.245 17.614,-12.369 31.548,-12.369 13.87,0 24.335,4.08 31.401,12.235 7.064,8.155 10.598,20.3 10.598,36.433 0,15.897 -3.501,27.953 -10.5,36.168 C 66.693,44.382 56.26,48.49 42.39,48.49 28.391,48.49 17.826,44.382 10.694,36.168 3.564,27.953 0,15.897 0,0 m 109.001,0 c 0,-21.097 -5.811,-37.498 -17.434,-49.198 C 79.946,-60.901 63.486,-66.75 42.194,-66.75 c -21.553,0 -38.108,5.806 -49.667,17.418 -11.558,11.613 -17.334,28.116 -17.334,49.509 0,21.394 5.81,37.823 17.433,49.288 11.622,11.464 28.21,17.198 49.764,17.198 21.227,0 37.635,-5.822 49.227,-17.464 C 103.205,37.556 109.001,21.156 109.001,0" /></g><g 6258 transform="translate(480.5166,88.5742)" 6259 id="g32"><path 6260 id="path34" 6261 style="fill:#231f20;fill-opacity:1;fill-rule:nonzero;stroke:none" 6262 d="M 0,0 V 129.603 H 23.342 V 18.175 H 83.803 V 0 Z" /></g><g 6263 transform="translate(95.5459,218.4404)" 6264 id="g36"><path 6265 id="path38" 6266 style="fill:#ee2735;fill-opacity:1;fill-rule:nonzero;stroke:none" 6267 d="m 0,0 42.967,-58.803 -68.085,-93.3 30.263,-9.074 56.235,77.141 87.961,-120.538 46.28,-13.866 L 79.583,-59.091 159.441,50.344 112.198,36.084 60.982,-33.892 29.65,9.046 Z" /></g></g></g></g></svg> </a> 6268 </div> 6269 6270 </div> 6271</div>
vendor: 111 bytes, lines 6271-6274
6271 6272 6273 6274<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
6274<script> 6275 function loadPxChatWidget() { 6276 const posToGetApiKey = 'LaAlondraCasadehuespedes'; 6277 const timestamp = '1787696497'; 6278 const urlToGetApiKey = `https://px-chat-widget-prod.pxsol.com/company-widget/apiKey/${posToGetApiKey}?v=${timestamp}`; 6279 6280 fetch(urlToGetApiKey, { 6281 method: 'GET', 6282 headers: { 6283 'Content-Type': 'application/json', 6284 } 6285 }) 6286 .then(response => { 6287 if (!response.ok) { 6288 throw new Error(`HTTP error! status: ${response.status}`); 6289 } 6290 return response.json(); 6291 }) 6292 .then(data => { 6293 const internalKey = data?.data?.api_key; 6294 if (!internalKey) { 6295 throw new Error('API key not found in response'); 6296 } 6297 6298 const script = document.createElement('script'); 6299 script.src = `https://cdn.pxsol.com/dist/chat-widget.min.js?k=${internalKey}&v=${timestamp}`; 6300 script.async = true; 6301 script.onload = () => { 6302 console.log('PxChat widget loaded successfully'); 6303 }; 6304 script.onerror = (error) => { 6305 console.error('Failed to load PxChat widget:', error); 6306 }; 6307 document.body.appendChild(script); 6308 }) 6309 .catch(error => { 6310 console.error('PxChat widget initialization failed:', error.message); 6311 }); 6312 } 6313 document.addEventListener("DOMContentLoaded", loadPxChatWidget); 6314 </script>
6314 6315 6316<style> 6317 /* El botón flotante de WhatsApp (.wsp_floating) y el launcher del widget de chat (pxChat) 6318 se ubican ambos en la esquina inferior derecha y chocan entre sÃ. Cuando el chat está 6319 activo/montado, ocultamos el botón de WhatsApp para evitar la superposición. */ 6320 body.px-chat-widget-active .wsp_floating { display: none !important; } 6321</style>
6322<script> 6323 (function () { 6324 // El widget pxChat monta su launcher/panel bajo #px-widget-root (clase .widget-launcher-button). 6325 function chatWidgetPresent() { 6326 return !!( 6327 document.getElementById('px-widget-root') || 6328 document.querySelector('.widget-launcher-button, [class*="widget-launcher"]') 6329 ); 6330 } 6331 var applied = false; 6332 var observer = null; 6333 var fallbackTimer = null; 6334 function apply() { 6335 if (applied || !document.body || !chatWidgetPresent()) return; 6336 document.body.classList.add('px-chat-widget-active'); 6337 applied = true; 6338 if (observer) observer.disconnect(); 6339 if (fallbackTimer) clearTimeout(fallbackTimer); 6340 } 6341 function start() { 6342 apply(); 6343 if (applied || !('MutationObserver' in window) || !document.body) return; 6344 // El widget carga async (fetch de apiKey + inyección del
6344<script>), asà que observamos 6345 // el DOM hasta que aparezca. Si a los 20s no montó, dejamos de observar. 6346 observer = new MutationObserver(apply); 6347 observer.observe(document.body, { childList: true, subtree: true }); 6348 fallbackTimer = setTimeout(function () { 6349 if (observer) observer.disconnect(); 6350 }, 20000); 6351 } 6352 if (document.readyState === 'loading') { 6353 document.addEventListener('DOMContentLoaded', start); 6354 } else { 6355 start(); 6356 } 6357 })(); 6358</script>
6358 6359
6360<script src="https://cdn.pxsol.com/js/domready.js"></script>
vendor: 1 bytes, line 6360
6360
6361<script> 6362 var head = document.getElementsByTagName('head')[0]; 6363 6364 function initializeFontAwesome() { 6365 var link = document.createElement('link'); 6366 link.id = "fawesome"; 6367 link.rel = 'stylesheet'; 6368 link.type = 'text/css'; 6369 link.href = 'https://use.fontawesome.com/releases/v5.7.1/css/all.css'; 6370 head.appendChild(link); 6371 } 6372 6373 function initializeMDI() { 6374 var link = document.createElement('link'); 6375 link.id = "fawesome"; 6376 link.rel = 'stylesheet'; 6377 link.type = 'text/css'; 6378 link.href = '/css/materialdesignicons.min.css'; 6379 head.appendChild(link); 6380 } 6381 6382 function initializeToast() { 6383 // check if jquery is loaded 6384 if (typeof jQuery == 'function') { 6385 let link = document.createElement('link'); 6386 link.id = "jqToastCss"; 6387 link.rel = 'stylesheet'; 6388 link.type = 'text/css'; 6389 link.href = '/includes/toast/jquery.toast.min.css'; 6390 head.appendChild(link); 6391 let script = document.createElement('script'); 6392 script.id = "jqToastJs"; 6393 script.type = 'text/javascript'; 6394 script.defer = true; 6395 script.async = true; 6396 script.src = '/includes/toast/jquery.toast.min.js'; 6397 head.appendChild(script); 6398 } else { 6399 console.log('jQuery is not loaded. Toast could not be initialized.'); 6400 } 6401 } 6402 6403 DomReady.ready(function() { 6404 var link = document.createElement('link'); 6405 link.id = "siteCss"; 6406 link.rel = 'stylesheet'; 6407 link.type = 'text/css'; 6408 6409 link.href = 6410 '/css_3.css?pos=LaAlondraCasadehuespedes&device=computer&posv=1787696497_2025-08-05T15:10:11.000Z&filev=1782498034'; 6411 head.appendChild(link); 6412 6413 if (typeof deferFontAwesome !== "undefined") { 6414 if (!deferFontAwesome) { 6415 initializeFontAwesome(); 6416 } 6417 } else { 6418 initializeFontAwesome(); 6419 } 6420 6421 if (typeof deferMDI !== "undefined") { 6422 if (!deferMDI) { 6423 initializeMDI(); 6424 } 6425 } else { 6426 initializeMDI(); 6427 } 6428 6429 if (typeof deferToast !== "undefined") { 6430 if (!deferToast) { 6431 initializeToast(); 6432 } 6433 } else { 6434 initializeToast(); 6435 } 6436 6437 }); 6438</script>
vendor: 1 bytes, line 6438
6438
6439<script> 6440 (function(){ 6441 console.log('%c[pxChat] ð Chat tracking script loaded (Chromium optimized)', 'color: #4CAF50; font-weight: bold; font-size: 14px;'); 6442 window.dataLayer = window.dataLayer || []; 6443 function generateId(prefix){ 6444 const rnd = ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => 6445 (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) 6446 ); 6447 return (prefix || 'id_') + rnd; 6448 } 6449 function getPxContext(){ 6450 try { return window.pxContext || {}; } catch(e){ return {}; } 6451 } 6452 function getSessionId(){ 6453 const ctx = getPxContext(); 6454 if (ctx.session_id) return ctx.session_id; 6455 let sid = sessionStorage.getItem('px_session_id'); 6456 if (!sid){ sid = generateId('s_'); sessionStorage.setItem('px_session_id', sid); } 6457 return sid; 6458 } 6459 function getChatSessionId(){ 6460 let cid = sessionStorage.getItem('px_chat_session_id'); 6461 if (!cid){ cid = generateId('c_'); sessionStorage.setItem('px_chat_session_id', cid); } 6462 return cid; 6463 } 6464 function basePayload(){ 6465 const ctx = getPxContext(); 6466 const pos = (ctx.pos || 'LaAlondraCasadehuespedes') || null; 6467 const hotelId = (ctx.product_id || '24325') || null; 6468 return { 6469 session_id: getSessionId(), 6470 search_id: ctx.search_id || ctx.SearchID || null, 6471 pos: pos, 6472 post: pos, 6473 hotel_id: hotelId, 6474 page_url: location.href 6475 }; 6476 } 6477 function pushEvent(name, extra){ 6478 const params = Object.assign({}, basePayload(), extra || {}); 6479 // Dedupe: evita repetidos en ±1s por sesión/mensaje 6480 try { 6481 const keyId = params.chat_session_id || params.chat_id || ''; 6482 const key = name + '|' + String(keyId); 6483 const now = Date.now(); 6484 window.__px_evt_dedupe = window.__px_evt_dedupe || {}; 6485 const last = window.__px_evt_dedupe[key] || 0; 6486 if (now - last < 1000) { 6487 return; 6488 } 6489 window.__px_evt_dedupe[key] = now; 6490 } catch(_e){ 6491 console.error('[pxChat] Error in pushEvent dedupe:', _e); 6492 } 6493 // Evitar duplicados: si pxTrack existe, delegamos y NO empujamos a dataLayer aquà 6494 if (typeof window.pxTrack === 'function') { 6495 try { 6496 console.log('[pxChat] ð¤ Calling pxTrack for', name, 'with params:', params); 6497 window.pxTrack(name, params); 6498 console.log('%c[pxChat] â ' + name + ' event dispatched successfully', 'color: #4CAF50; font-weight: bold;'); 6499 } catch(e){ 6500 console.error('[pxChat] â Error calling window.pxTrack for', name, ':', e); 6501 } 6502 return; 6503 } 6504 const payload = Object.assign({ event: name }, params); 6505 console.log('[pxChat] ð¤ Pushing to dataLayer:', payload); 6506 window.dataLayer.push(payload); 6507 console.log('%c[pxChat] â ' + name + ' event pushed to dataLayer', 'color: #4CAF50; font-weight: bold;'); 6508 } 6509 let chatOpenTsMs = null; 6510 let chatIsOpen = false; 6511 let lastOpenPushMs = 0; 6512 let closeGuardTimer = null; 6513 let lastStateChangeMs = 0; 6514 let lastCloseCallMs = 0; // Guard para prevenir múltiples llamadas rápidas a handleChatClose 6515 let lastOpenCallMs = 0; // Guard para prevenir múltiples llamadas rápidas a handleChatOpen 6516 let MIN_CHAT_DURATION_MS = 3000; // MÃnimo 3 segundos entre chat_open y chat_close (previene falsos positivos en Chrome) 6517 let OPEN_DEBOUNCE_MS = 300; // Debounce para chat_open (300ms - solo para múltiples llamadas rápidas) 6518 let CLOSE_DEBOUNCE_MS = 400; // Debounce para chat_close (400ms - solo para múltiples llamadas rápidas) 6519 let pendingOpenTimer = null; // Timer para debounce de open 6520 let pendingCloseTimer = null; // Timer para debounce de close 6521 let openCallCount = 0; // Contador de llamadas rápidas a open 6522 let closeCallCount = 0; // Contador de llamadas rápidas a close 6523 function syncChatState(){ 6524 try { 6525 // Guard mÃnimo: no sincronizar si acabamos de cambiar estado hace menos de 200ms 6526 const now = Date.now(); 6527 if (now - lastStateChangeMs < 200) { 6528 console.log('[pxChat] syncChatState throttled (' + (now - lastStateChangeMs) + 'ms ago)'); 6529 return; 6530 } 6531 // Priorizar estado del launcher: clase --open 6532 // Buscar el botón con múltiples selectores 6533 const btn = document.querySelector('.widget-launcher-button') || 6534 document.querySelector('[class*="widget-launcher"]') || 6535 document.querySelector('[class*="launcher-button"]'); 6536 if (btn && btn.classList) { 6537 const isOpenBtn = btn.classList.contains('widget-launcher-button--open') || 6538 btn.classList.toString().indexOf('--open') !== -1; 6539 console.log('[pxChat] syncChatState: button state check:', { 6540 isOpenBtn: isOpenBtn, 6541 chatIsOpen: chatIsOpen,
6542 buttonClasses: btn.className 6543 }); 6544 if (isOpenBtn && !chatIsOpen) { 6545 console.log('[pxChat] syncChatState: button is open but chatIsOpen is false, calling handleChatOpen'); 6546 lastStateChangeMs = now; 6547 return handleChatOpen(); 6548 } 6549 if (!isOpenBtn && chatIsOpen) { 6550 // Guard mÃnimo: no cerrar si el chat se abrió hace menos de 3 segundos 6551 const startMs = chatOpenTsMs || lastOpenPushMs || null; 6552 if (startMs && (now - startMs < 3000)) { 6553 console.log('[pxChat] syncChatState: chat_close blocked - chat opened too recently (' + Math.round((now - startMs) / 1000) + 's ago, minimum 3s)'); 6554 return; 6555 } 6556 // CRÃTICO: Esperar y verificar nuevamente que el botón realmente está cerrado 6557 // Esto previene disparos prematuros cuando el DOM aún se está actualizando 6558 setTimeout(function() { 6559 const btnCheck = document.querySelector('.widget-launcher-button') || 6560 document.querySelector('[class*="widget-launcher"]') || 6561 document.querySelector('[class*="launcher-button"]'); 6562 const isStillOpen = btnCheck && btnCheck.classList && ( 6563 btnCheck.classList.contains('widget-launcher-button--open') || 6564 btnCheck.classList.toString().indexOf('--open') !== -1 6565 ); 6566 const ifrCheck = findChatIframe(); 6567 const isIframeVisible = isElementVisible(ifrCheck); 6568 6569 console.log('[pxChat] syncChatState: delayed verification after button close:', { 6570 isStillOpen: isStillOpen, 6571 isIframeVisible: isIframeVisible, 6572 chatIsOpen: chatIsOpen 6573 }); 6574 6575 if (isStillOpen) { 6576 console.log('[pxChat] syncChatState: chat_close CANCELLED - button still shows as open after delay'); 6577 return; 6578 } 6579 if (isIframeVisible) { 6580 console.log('[pxChat] syncChatState: chat_close CANCELLED - iframe still visible after delay'); 6581 return; 6582 } 6583 if (!chatIsOpen) { 6584 console.log('[pxChat] syncChatState: chat_close CANCELLED - chatIsOpen is already false'); 6585 return; 6586 } 6587 6588 console.log('[pxChat] syncChatState: button confirmed closed after delay, calling handleChatClose'); 6589 lastStateChangeMs = Date.now(); 6590 handleChatClose(); 6591 }, 600); // Esperar 600ms para confirmar que el DOM se actualizó completamente 6592 return; 6593 } 6594 } 6595 // CRÃTICO: NO usar iframe como fallback si hay un botón disponible 6596 // El iframe puede no ser visible incluso cuando el chat está abierto 6597 // Solo confiar en el botón launcher para determinar el estado 6598 if (!btn) { 6599 // Solo si NO hay botón, intentar buscar el botón de nuevo con un selector más amplio 6600 const btnRetry = document.querySelector('.widget-launcher-button, [class*="widget-launcher"], [class*="launcher-button"]'); 6601 if (btnRetry && btnRetry.classList) { 6602 const isOpenBtnRetry = btnRetry.classList.contains('widget-launcher-button--open') || 6603 btnRetry.classList.toString().indexOf('--open') !== -1; 6604 console.log('[pxChat] syncChatState: retry button found:', { 6605 isOpenBtnRetry: isOpenBtnRetry, 6606 chatIsOpen: chatIsOpen, 6607 buttonClasses: btnRetry.className 6608 }); 6609 if (isOpenBtnRetry && !chatIsOpen) { 6610 console.log('[pxChat] syncChatState: retry button is open but chatIsOpen is false, calling handleChatOpen'); 6611 lastStateChangeMs = now; 6612 return handleChatOpen(); 6613 } 6614 if (!isOpenBtnRetry && chatIsOpen) { 6615 // Guard mÃnimo: no cerrar si el chat se abrió hace menos de 3 segundos 6616 const startMs = chatOpenTsMs || lastOpenPushMs || null; 6617 if (startMs && (now - startMs < 3000)) { 6618 console.log('[pxChat] syncChatState: chat_close blocked - chat opened too recently (' + Math.round((now - startMs) / 1000) + 's ago, minimum 3s)'); 6619 return; 6620 } 6621 // Verificar nuevamente antes de cerrar 6622 setTimeout(function() { 6623 const btnCheck = document.querySelector('.widget-launcher-button, [class*="widget-launcher"], [class*="launcher-button"]'); 6624 const isStillOpen = btnCheck && (btnCheck.classList.contains('widget-launcher-button--open') || 6625 btnCheck.classList.toString().indexOf('--open') !== -1); 6626 6627 if (isStillOpen || !chatIsOpen) { 6628 console.log('[pxChat] syncChatState: chat_close CANCELLED - button still open or chatIsOpen is false'); 6629 return; 6630 } 6631 6632 console.log('[pxChat] syncChatState: retry button confirmed closed after delay, calling handleChatClose'); 6633 lastStateChangeMs = Date.now(); 6634 handleChatClose(); 6635 }, 600); 6636 return; 6637 } 6638 } 6639 6640 // ÃLTIMO RECURSO: Solo usar iframe si NO hay botón Y el chat está abierto 6641 // Y solo para abrir, NUNCA para cerrar (el iframe no es confiable para cerrar) 6642 const ifr = findChatIframe(); 6643 const visible = isElementVisible(ifr); 6644 console.log('[pxChat] syncChatState: iframe LAST RESORT check (only for opening):', { 6645 visible: visible, 6646 chatIsOpen: chatIsOpen, 6647 hasIframe: !!ifr 6648 }); 6649 // Solo usar iframe para detectar apertura, NUNCA para cerrar 6650 if (visible && !chatIsOpen) { 6651 console.log('[pxChat] syncChatState: iframe visible but chatIsOpen is false, calling handleChatOpen'); 6652 lastStateChangeMs = now; 6653 return handleChatOpen(); 6654 } 6655 // NO usar iframe para cerrar - solo confiar en el botón 6656 if (!visible && chatIsOpen) { 6657 console.log('[pxChat] syncChatState: iframe not visible but chatIsOpen is true - IGNORING (iframe not reliable for closing)'); 6658 return; // NO hacer nada - solo el botón puede cerrar 6659 } 6660 } 6661 } catch(_e){ 6662 console.error('[pxChat] syncChatState error:', _e); 6663 } 6664 } 6665 function handleChatOpen(meta){ 6666 console.log('[pxChat] handleChatOpen called:', { chatIsOpen: chatIsOpen, meta: meta }); 6667 6668 // Si ya está abierto, no hacer nada 6669 if (chatIsOpen) { 6670 console.log('[pxChat] handleChatOpen skipped - chat already open'); 6671 return; 6672 } 6673 6674 const now = Date.now(); 6675
6676 // Guard mÃnimo: no abrir si se cerró hace menos de 500ms (solo para prevenir toggle extremo) 6677 if (lastCloseCallMs && (now - lastCloseCallMs < 500)) { 6678 console.log('[pxChat] handleChatOpen blocked - chat closed too recently (' + (now - lastCloseCallMs) + 'ms ago)'); 6679 return; 6680 } 6681 6682 // Throttling mÃnimo: solo prevenir llamadas duplicadas en menos de 200ms 6683 if (now - lastOpenCallMs < 200) { 6684 console.log('[pxChat] handleChatOpen throttled (too soon)'); 6685 return; 6686 } 6687 6688 lastOpenCallMs = now; 6689 6690 // Cancelar cualquier close pendiente 6691 if (pendingCloseTimer) { 6692 clearTimeout(pendingCloseTimer); 6693 pendingCloseTimer = null; 6694 console.log('[pxChat] handleChatOpen: cancelled pending close'); 6695 } 6696 6697 // Disparar inmediatamente (sin debounce para Chromium) 6698 console.log('[pxChat] handleChatOpen: calling doChatOpen immediately'); 6699 doChatOpen(meta); 6700 } 6701 6702 function doChatOpen(meta) { 6703 // Verificar estado del botón (prioridad máxima para Chromium) 6704 // Buscar el botón con múltiples selectores 6705 const btn = document.querySelector('.widget-launcher-button') || 6706 document.querySelector('[class*="widget-launcher"]') || 6707 document.querySelector('[class*="launcher-button"]'); 6708 const isActuallyOpen = btn && btn.classList && ( 6709 btn.classList.contains('widget-launcher-button--open') || 6710 btn.classList.toString().indexOf('--open') !== -1 6711 ); 6712 const ifr = findChatIframe(); 6713 const isIframeVisible = isElementVisible(ifr); 6714 6715 // Log detallado para debugging en Chromium 6716 console.log('[pxChat] doChatOpen called:', { 6717 isActuallyOpen: isActuallyOpen, 6718 isIframeVisible: isIframeVisible, 6719 chatIsOpen: chatIsOpen, 6720 hasButton: !!btn, 6721 buttonClasses: btn ? btn.className : 'no button' 6722 }); 6723 6724 // Si el botón existe y dice que está abierto, proceder 6725 // Si no hay botón pero el iframe es visible, también proceder 6726 if (!isActuallyOpen && !isIframeVisible && btn) { 6727 console.warn('[pxChat] doChatOpen: button exists but not showing as open, proceeding anyway'); 6728 } 6729 6730 // Guardar timestamp ANTES de cambiar el estado (importante para Chrome) 6731 const now = Date.now(); 6732 chatOpenTsMs = now; 6733 lastOpenPushMs = now; 6734 chatIsOpen = true; 6735 const chat_session_id = (meta && (meta.chat_session_id || meta.session_id)) || getChatSessionId(); 6736 6737 // Log para debugging 6738 console.log('[pxChat] ð FIRING chat_open event:', { 6739 chatOpenTsMs: chatOpenTsMs, 6740 lastOpenPushMs: lastOpenPushMs, 6741 timestamp: now, 6742 chat_session_id: chat_session_id 6743 }); 6744 pushEvent('chat_open', { chat_session_id }); 6745 } 6746 function handleChatMessage(meta){ 6747 const chat_id = meta && (meta.chat_id || meta.message_id) || null; 6748 const message_type = meta && (meta.message_type || meta.type) || null; 6749 const payload = { chat_id, message_type }; 6750 pushEvent('chat_message', payload); 6751 } 6752 function handleChatClose(meta){ 6753 console.log('[pxChat] handleChatClose called:', { chatIsOpen: chatIsOpen, meta: meta }); 6754 6755 // Si ya está cerrado, no hacer nada 6756 if (!chatIsOpen) { 6757 console.log('[pxChat] handleChatClose skipped - chat already closed'); 6758 return; 6759 } 6760 6761 const now = Date.now(); 6762 6763 // Guard crÃtico: prevenir que chat_close se dispare inmediatamente después de chat_open 6764 // Aumentado a 3 segundos para evitar disparos prematuros 6765 const startMs = chatOpenTsMs || lastOpenPushMs || null; 6766 if (startMs && (now - startMs < 3000)) { 6767 console.log('[pxChat] handleChatClose blocked - chat opened too recently (' + Math.round((now - startMs) / 1000) + 's ago, minimum 3s required)'); 6768 return; 6769 } 6770 6771 // Verificación adicional: asegurarse de que el botón realmente está cerrado 6772 // Buscar el botón con múltiples selectores 6773 const btn = document.querySelector('.widget-launcher-button') || 6774 document.querySelector('[class*="widget-launcher"]') || 6775 document.querySelector('[class*="launcher-button"]'); 6776 const isActuallyOpen = btn && btn.classList && ( 6777 btn.classList.contains('widget-launcher-button--open') || 6778 btn.classList.toString().indexOf('--open') !== -1 6779 ); 6780 if (isActuallyOpen) { 6781 console.log('[pxChat] handleChatClose blocked - button still shows as open'); 6782 return; 6783 } 6784 6785 // Throttling mÃnimo: solo prevenir llamadas duplicadas en menos de 200ms 6786 if (now - lastCloseCallMs < 200) { 6787 console.log('[pxChat] handleChatClose throttled (too soon)'); 6788 return; 6789 } 6790 6791 lastCloseCallMs = now; 6792 6793 // Cancelar cualquier open pendiente 6794 if (pendingOpenTimer) { 6795 clearTimeout(pendingOpenTimer); 6796 pendingOpenTimer = null; 6797 console.log('[pxChat] handleChatClose: cancelled pending open'); 6798 } 6799 6800 // Disparar inmediatamente (sin debounce para Chromium)
6801 console.log('[pxChat] handleChatClose: calling doChatClose immediately'); 6802 doChatClose(meta, startMs); 6803 } 6804 6805 function doChatClose(meta, startMs) { 6806 // Verificar estado del botón (prioridad máxima para Chromium) 6807 // Buscar el botón con múltiples selectores 6808 const btn = document.querySelector('.widget-launcher-button') || 6809 document.querySelector('[class*="widget-launcher"]') || 6810 document.querySelector('[class*="launcher-button"]'); 6811 const isActuallyOpen = btn && btn.classList && ( 6812 btn.classList.contains('widget-launcher-button--open') || 6813 btn.classList.toString().indexOf('--open') !== -1 6814 ); 6815 const ifr = findChatIframe(); 6816 const isIframeVisible = isElementVisible(ifr); 6817 6818 // Log detallado para debugging en Chromium 6819 console.log('[pxChat] doChatClose called:', { 6820 isActuallyOpen: isActuallyOpen, 6821 isIframeVisible: isIframeVisible, 6822 chatIsOpen: chatIsOpen, 6823 hasButton: !!btn, 6824 buttonClasses: btn ? btn.className : 'no button', 6825 startMs: startMs 6826 }); 6827 6828 // CRÃTICO: Solo proceder si el chat realmente está cerrado 6829 // Si hay un botón, confiar solo en el botón (no en el iframe) 6830 if (btn) { 6831 if (isActuallyOpen) { 6832 console.warn('[pxChat] doChatClose BLOCKED - button still shows as open'); 6833 return; 6834 } 6835 // Si hay botón y no está abierto, proceder (ignorar iframe) 6836 console.log('[pxChat] doChatClose: button exists and is closed, proceeding'); 6837 } else { 6838 // Solo si NO hay botón, verificar iframe 6839 if (isIframeVisible) { 6840 console.warn('[pxChat] doChatClose BLOCKED - iframe still visible (no button found)'); 6841 return; 6842 } 6843 console.log('[pxChat] doChatClose: no button found, iframe not visible, proceeding'); 6844 } 6845 6846 // Guardar timestamp ANTES de cambiar el estado (importante para Chrome) 6847 const now = Date.now(); 6848 const endMs = now; 6849 // Calcular duración antes de resetear variables 6850 const duration_sec = startMs ? Math.max(0, Math.round((endMs - startMs) / 1000)) : null; 6851 // Ahora sà cambiar el estado 6852 chatIsOpen = false; 6853 const chat_session_id = (meta && (meta.chat_session_id || meta.session_id)) || getChatSessionId(); 6854 6855 // Log para debugging 6856 console.log('[pxChat] ð FIRING chat_close event:', { 6857 startMs: startMs, 6858 endMs: endMs, 6859 duration_sec: duration_sec, 6860 chatOpenTsMs: chatOpenTsMs, 6861 lastOpenPushMs: lastOpenPushMs, 6862 calculated: endMs - startMs + 'ms', 6863 chat_session_id: chat_session_id 6864 }); 6865 pushEvent('chat_close', { chat_session_id, duration_sec }); 6866 // Resetear timestamp inmediatamente (ya calculamos la duración) 6867 chatOpenTsMs = null; 6868 lastOpenPushMs = 0; 6869 } 6870 function isElementVisible(el){ 6871 if (!el) return false; 6872 const cs = window.getComputedStyle ? window.getComputedStyle(el) : null; 6873 if (!cs || cs.display === 'none' || cs.visibility === 'hidden' || cs.opacity === '0') return false; 6874 const r = el.getBoundingClientRect(); 6875 return !!(r.width && r.height); 6876 } 6877 function findChatIframe(){ 6878 try { 6879 const ifrs = document.querySelectorAll('iframe'); 6880 for (let i = 0; i < ifrs.length; i++){ 6881 const n = ifrs[i]; 6882 if (isChatIframe(n)) return n; 6883 } 6884 } catch(_e){} 6885 return null; 6886 } 6887 // Detect launcher button presence (instala watcher; no toggle directo) 6888 document.addEventListener('click', function(ev){ 6889 try { 6890 // Detectar click en el botón de cerrar del header 6891 let closeBtn = null; 6892 if (ev.composedPath) { 6893 const path = ev.composedPath(); 6894 for (let i = 0; i < path.length; i++) { 6895 const n = path[i]; 6896 if (n && n.classList && n.classList.contains && n.classList.contains('widget-header-close')) { 6897 closeBtn = n; 6898 break; 6899 } 6900 } 6901 } 6902 if (!closeBtn && ev.target && ev.target.closest) { 6903 closeBtn = ev.target.closest('.widget-header-close'); 6904 } 6905 6906 // Si se hizo click en el botón de cerrar, esperar a que el DOM se actualice 6907 if (closeBtn && chatIsOpen) { 6908 console.log('[pxChat] Close button clicked, waiting for DOM update...'); 6909 // Esperar más tiempo para que el widget actualice el estado del botón 6910 setTimeout(function() { 6911 const launcherBtn = document.querySelector('.widget-launcher-button'); 6912 const isStillOpen = launcherBtn && launcherBtn.classList && launcherBtn.classList.contains('widget-launcher-button--open'); 6913 console.log('[pxChat] After close button click, launcher state:', { 6914 isStillOpen: isStillOpen, 6915 chatIsOpen: chatIsOpen 6916 }); 6917 if (!isStillOpen && chatIsOpen) { 6918 console.log('[pxChat] Close button clicked and launcher is now closed, calling handleChatClose'); 6919 handleChatClose(); 6920 } 6921 }, 500); // Esperar 500ms para que el DOM se actualice 6922 return; 6923 } 6924 6925 // Detectar click en el botón launcher 6926 let btn = null; 6927 if (ev.composedPath) { 6928 const path = ev.composedPath(); 6929 for (let i = 0; i < path.length; i++) { 6930 const n = path[i]; 6931 if (n && n.classList && n.classList.contains && n.classList.contains('widget-launcher-button')) { btn = n; break; } 6932 } 6933 } 6934 if (!btn && ev.target && ev.target.closest) { 6935 btn = ev.target.closest('.widget-launcher-button'); 6936 } 6937 if (btn) { 6938 installButtonListener(btn); 6939 // Si el botón tiene --open, está abierto; si no, está cerrado 6940 const isOpen = btn.classList.contains('widget-launcher-button--open'); 6941 if (isOpen && !chatIsOpen) { 6942 // Chat se está abriendo 6943 console.log('[pxChat] Launcher button clicked (opening), calling handleChatOpen'); 6944 setTimeout(function() { handleChatOpen(); }, 300); 6945 } else if (!isOpen && chatIsOpen) { 6946 // Chat se está cerrando 6947 console.log('[pxChat] Launcher button clicked (closing), waiting for DOM update...'); 6948 setTimeout(function() { 6949 const launcherBtn = document.querySelector('.widget-launcher-button'); 6950 const isStillOpen = launcherBtn && launcherBtn.classList && launcherBtn.classList.contains('widget-launcher-button--open'); 6951 if (!isStillOpen && chatIsOpen) { 6952 console.log('[pxChat] Launcher button clicked and confirmed closed, calling handleChatClose'); 6953 handleChatClose(); 6954 } 6955 }, 500); // Esperar 500ms para confirmar que está cerrado 6956 } 6957 } 6958 } catch(_e){ 6959 console.error('[pxChat] Error in click listener:', _e); 6960 } 6961 }, true); 6962 // Keyboard open on launcher 6963 document.addEventListener('keydown', function(ev){ 6964 try { 6965 if (ev.key !== 'Enter' && ev.key !== ' ') return; 6966 let btn = null; 6967 if (ev.composedPath) { 6968 const path = ev.composedPath(); 6969 for (let i = 0; i < path.length; i++) { 6970 const n = path[i]; 6971 if (n && n.classList && n.classList.contains && n.classList.contains('widget-launcher-button')) { btn = n; break; } 6972 } 6973 } 6974 if (!btn && ev.target && ev.target.closest) { 6975 btn = ev.target.closest('.widget-launcher-button'); 6976 } 6977 if (btn) { 6978 installButtonListener(btn); 6979 // Delay mÃnimo para dar tiempo al widget a actualizar la clase (Chromium) 6980 setTimeout(syncChatState, 200); 6981 } 6982 } catch(_e){} 6983 }, true); 6984 // Bridge postMessage events from the widget iframe 6985 window.addEventListener('message', function(ev){ 6986 const d = ev.data; 6987 try { 6988 if (!d) return; 6989 if (typeof d === 'object') { 6990 const type = d.type || d.event || d.name || d.px_chat_event; 6991 if (!type) return; 6992 const payload = d.payload || d.meta || d; 6993 switch (String(type)) { 6994 case 'chat_opened': 6995 case 'widget_opened': 6996 case 'open': 6997 return handleChatOpen(payload); 6998 case 'message_sent': 6999 case 'chat_message': 7000 case 'message': 7001 case 'message_received': 7002 case 'new_message': 7003 // Extraer message_id del payload 7004 const messageId = payload && (payload.message_id || payload.messageId || payload.id || payload.chat_id); 7005 const messageType = payload && (payload.type || payload.message_type || 'text'); 7006 const from = payload && (payload.from || payload.user_id || payload.userId); 7007 if (messageId) { 7008 detectChatMessage(messageId, messageType, from); 7009 } else { 7010 return handleChatMessage(payload); 7011 } 7012 return; 7013 case 'chat_closed': 7014 case 'widget_closed': 7015 case 'close': 7016 return handleChatClose(payload); 7017 } 7018 // También buscar en propiedades del objeto directamente 7019 if (d.message_id || d.messageId || d.id) { 7020 const messageId = d.message_id || d.messageId || d.id; 7021 const messageType = d.type || d.message_type || 'text'; 7022 const from = d.from || d.user_id || d.userId; 7023 detectChatMessage(messageId, messageType, from); 7024 } 7025 } 7026 if (typeof d === 'string' && d.indexOf('px-chat:') === 0) { 7027 const parts = d.split(':'); 7028 const type = parts[1]; 7029 let payload = null; 7030 if (parts[2]) { try { payload = JSON.parse(parts.slice(2).join(':')); } catch(_e){} } 7031 if (type === 'open') return handleChatOpen(payload); 7032 if (type === 'message') { 7033 if (payload && (payload.message_id || payload.messageId || payload.id)) { 7034 detectChatMessage(payload.message_id || payload.messageId || payload.id, payload.type || 'text', payload.from); 7035 } else { 7036 return handleChatMessage(payload); 7037 } 7038 return; 7039 } 7040 if (type === 'close') return handleChatClose(payload); 7041 } 7042 } catch(_e){} 7043 }); 7044 // Message detection: interceptar mensajes del widget 7045 let lastMessageIds = new Set(); // Track mensajes ya procesados para evitar duplicados 7046 let lastMessageTime = 0; 7047 const MESSAGE_THROTTLE_MS = 500; // Máximo 1 mensaje cada 500ms 7048 7049 function detectChatMessage(messageId, messageType, from) { 7050 if (!messageId) { 7051 console.debug('[pxChat] detectChatMessage: no messageId provided'); 7052 return; 7053 } 7054 7055 // Evitar duplicados usando messageId (verificar primero) 7056 if (messageId && lastMessageIds.has(messageId)) { 7057 console.debug('[pxChat] detectChatMessage: message already processed', messageId); 7058 return; 7059 } 7060 7061 // Throttling: evitar procesar mensajes muy rápidos 7062 const now = Date.now(); 7063 const timeSinceLast = now - lastMessageTime; 7064 if (timeSinceLast < MESSAGE_THROTTLE_MS) { 7065 console.debug('[pxChat] detectChatMessage: throttled', timeSinceLast, 'ms since last'); 7066 return; 7067 } 7068 7069 // Permitir trackear mensajes incluso si el chat no está visualmente abierto 7070 // Los mensajes pueden llegar cuando el chat está minimizado pero activo 7071 // En Chromium, el chat puede estar activo sin que chatIsOpen sea true 7072 const hasChatSession = getChatSessionId() !== null; 7073 const shouldProcess = hasChatSession || chatIsOpen; 7074 7075 if (!shouldProcess) { 7076 // Si no hay sesión y el chat no está abierto, intentar una vez más después de un delay 7077 console.debug('[pxChat] detectChatMessage: no session/open, will retry', { hasChatSession, chatIsOpen }); 7078 setTimeout(function() { 7079 const retryHasSession = getChatSessionId() !== null; 7080 const retryIsOpen = chatIsOpen; 7081 if ((retryHasSession || retryIsOpen) && messageId && !lastMessageIds.has(messageId)) { 7082 console.debug('[pxChat] detectChatMessage: retry after delay', { retryHasSession, retryIsOpen }); 7083 detectChatMessage(messageId, messageType, from); 7084 } else { 7085 console.debug('[pxChat] detectChatMessage: retry failed - conditions not met'); 7086 } 7087 }, 1500); // Aumentado a 1.5s para dar más tiempo en Chromium 7088 return; 7089 } 7090
7091 // Limpiar Set si tiene más de 100 mensajes (evitar memory leak) 7092 if (lastMessageIds.size > 100) { 7093 lastMessageIds.clear(); 7094 } 7095 7096 if (messageId) { 7097 lastMessageIds.add(messageId); 7098 } 7099 lastMessageTime = now; 7100 7101 // Disparar evento 7102 try { 7103 const payload = { 7104 chat_id: messageId, 7105 message_type: messageType || 'text', 7106 from: from 7107 }; 7108 console.debug('[pxChat] detectChatMessage: processing message', payload); 7109 handleChatMessage(payload); 7110 } catch(e) { 7111 console.error('[pxChat] â Error processing message:', e); 7112 } 7113 } 7114 7115 // Listener para eventos personalizados que el widget podrÃa disparar 7116 document.addEventListener('px-chat-message', function(ev) { 7117 try { 7118 const data = ev.detail || ev.data || {}; 7119 detectChatMessage(data.message_id || data.messageId || data.id, data.type || data.message_type, data.from); 7120 } catch(_e){} 7121 }); 7122 7123 // Interceptar logs de console.log para detectar mensajes de Pusher 7124 // El widget loguea mensajes con formato especÃfico que podemos interceptar 7125 try { 7126 const originalConsoleLog = console.log; 7127 let isProcessing = false; // Flag para evitar recursión 7128 let processedMessageIds = new Set(); // Track mensajes ya procesados por el interceptor 7129 7130 console.log = function(...args) { 7131 // Llamar al console.log original primero (siempre) 7132 originalConsoleLog.apply(console, args); 7133 7134 // Evitar procesamiento recursivo 7135 if (isProcessing) return; 7136 7137 try { 7138 isProcessing = true; 7139 7140 let detectedMessageId = null; 7141 let detectedMessageType = 'text'; 7142 let detectedFrom = null; 7143 7144 // Buscar message_id en los argumentos directamente (mejorado para Chromium) 7145 for (let i = 0; i < args.length; i++) { 7146 const arg = args[i]; 7147 if (typeof arg === 'object' && arg !== null && !Array.isArray(arg)) { 7148 // Buscar directamente en el objeto 7149 if (arg.message_id || arg.messageId || arg.id) { 7150 detectedMessageId = arg.message_id || arg.messageId || arg.id; 7151 detectedMessageType = arg.type || arg.message_type || 'text'; 7152 detectedFrom = arg.from || arg.user_id || arg.userId || null; 7153 break; 7154 } 7155 // Buscar en rawData (estructura anidada común en Pusher) 7156 if (arg.rawData && typeof arg.rawData === 'object') { 7157 if (arg.rawData.message_id || arg.rawData.messageId || arg.rawData.id) { 7158 detectedMessageId = arg.rawData.message_id || arg.rawData.messageId || arg.rawData.id; 7159 detectedMessageType = arg.rawData.type || arg.rawData.message_type || 'text'; 7160 detectedFrom = arg.rawData.from || arg.rawData.user_id || arg.rawData.userId || null; 7161 break; 7162 } 7163 } 7164 // Buscar en propiedades anidadas (para Chromium que puede tener estructura diferente) 7165 try { 7166 for (let key in arg) { 7167 if (arg.hasOwnProperty(key) && typeof arg[key] === 'object' && arg[key] !== null) { 7168 if (arg[key].message_id || arg[key].messageId || arg[key].id) { 7169 detectedMessageId = arg[key].message_id || arg[key].messageId || arg[key].id; 7170 detectedMessageType = arg[key].type || arg[key].message_type || 'text'; 7171 detectedFrom = arg[key].from || arg[key].user_id || arg[key].userId || null; 7172 break; 7173 } 7174 } 7175 } 7176 if (detectedMessageId) break; 7177 } catch(_e) {} 7178 } 7179 } 7180 7181 // Si no encontramos en objetos, buscar en strings (solo si contiene patrones de Pusher) 7182 if (!detectedMessageId) { 7183 const logStr = args.map(arg => { 7184 if (typeof arg === 'string') return arg; 7185 if (typeof arg === 'object' && arg !== null) { 7186 try { return JSON.stringify(arg); } catch(_e) { return String(arg); } 7187 } 7188 return String(arg); 7189 }).join(' '); 7190 7191 // Solo procesar si contiene patrones especÃficos de Pusher 7192 if ((logStr.indexOf('[Pusher] ð¨ MENSAJE RECIBIDO') !== -1 || 7193 logStr.indexOf('[Pusher] ð¨ Mensaje recibido') !== -1 || 7194 logStr.indexOf('[Pusher] Body completo:') !== -1 || 7195 logStr.indexOf('[Pusher]') !== -1) && 7196 (logStr.indexOf('message_id') !== -1 || logStr.indexOf('messageId') !== -1)) { 7197 7198 // Intentar extraer message_id del string (múltiples formatos) 7199 try { 7200 // Formato: "message_id": "xxx" 7201 let messageIdMatch = logStr.match(/["']message_id["']\s*:\s
7201*["']([^"']+)["']/); 7202 if (!messageIdMatch) { 7203 // Formato: messageId: "xxx" 7204 messageIdMatch = logStr.match(/["']messageId["']\s*:\s*["']([^"']+)["']/); 7205 } 7206 if (!messageIdMatch) { 7207 // Formato: message_id: xxx (sin comillas) 7208 messageIdMatch = logStr.match(/message_id["']?\s*:\s*["']?([a-zA-Z0-9\-_]+)/); 7209 } 7210 if (messageIdMatch && messageIdMatch[1]) { 7211 detectedMessageId = messageIdMatch[1]; 7212 console.debug('[pxChat] Detected message_id from log string:', detectedMessageId); 7213 } 7214 } catch(_e) {} 7215 } 7216 } 7217 7218 // Procesar solo si encontramos un messageId y no lo hemos procesado antes 7219 if (detectedMessageId && !processedMessageIds.has(detectedMessageId)) { 7220 processedMessageIds.add(detectedMessageId); 7221 // Limpiar Set si tiene más de 50 mensajes 7222 if (processedMessageIds.size > 50) { 7223 processedMessageIds.clear(); 7224 } 7225 7226 console.debug('[pxChat] Detected message from Pusher log:', { 7227 messageId: detectedMessageId, 7228 messageType: detectedMessageType, 7229 from: detectedFrom 7230 }); 7231 7232 setTimeout(function() { 7233 detectChatMessage(detectedMessageId, detectedMessageType, detectedFrom); 7234 }, 300); // Aumentado a 300ms para dar tiempo a que se establezca la sesión 7235 } 7236 } catch(e) { 7237 // Silenciar errores en el interceptor para no romper otros logs 7238 console.debug('[pxChat] Error in console.log interceptor:', e); 7239 } finally { 7240 isProcessing = false; 7241 } 7242 }; 7243 7244 originalConsoleLog('[pxChat] Console.log interceptor installed for Pusher message detection'); 7245 } catch(e) { 7246 console.error('[pxChat] Error setting up console.log interceptor:', e); 7247 } 7248 7249 // MutationObserver para detectar mensajes en el DOM del chat (dentro del iframe) 7250 // Nota: Esto solo funciona si tenemos acceso al contenido del iframe (mismo origen) 7251 try { 7252 const chatMessageObserver = new MutationObserver(function(mutations) { 7253 if (!chatIsOpen) return; 7254 7255 for (let i = 0; i < mutations.length; i++) { 7256 const mutation = mutations[i]; 7257 if (mutation.addedNodes && mutation.addedNodes.length > 0) { 7258 for (let j = 0; j < mutation.addedNodes.length; j++) { 7259 const node = mutation.addedNodes[j]; 7260 if (node.nodeType === 1) { // Element node 7261 // Buscar elementos que parezcan mensajes de chat 7262 // Selectores comunes: .message, .chat-message, [data-message-id], etc. 7263 const messageEl = node.classList && ( 7264 node.classList.contains('message') || 7265 node.classList.contains('chat-message') || 7266 node.classList.contains('msg') || 7267 node.getAttribute('data-message-id') 7268 ) ? node : (node.querySelector && ( 7269 node.querySelector('.message') || 7270 node.querySelector('.chat-message') || 7271 node.querySelector('[data-message-id]') 7272 )); 7273 7274 if (messageEl) { 7275 const messageId = messageEl.getAttribute('data-message-id') || 7276 messageEl.getAttribute('data-id') || 7277 messageEl.id || 7278 null; 7279 const messageType = messageEl.getAttribute('data-type') || 7280 messageEl.getAttribute('data-message-type') || 7281 'text'; 7282 const from = messageEl.getAttribute('data-from') || null; 7283 7284 if (messageId) { 7285 detectChatMessage(messageId, messageType, from); 7286 } 7287 } 7288 } 7289 } 7290 } 7291 } 7292 }); 7293 7294 // Observar el iframe del chat cuando esté disponible 7295 function observeChatIframe() { 7296 const ifr = findChatIframe(); 7297 if (ifr && ifr.contentDocument && ifr.contentDocument.body) { 7298 try { 7299 chatMessageObserver.observe(ifr.contentDocument.body, { 7300 childList: true, 7301 subtree: true 7302 }); 7303 console.debug('[pxChat] Message observer installed on chat iframe'); 7304 } catch(e) { 7305 // Cross-origin: no podemos acceder al contenido del iframe 7306 console.debug('[pxChat] Cannot observe iframe content (cross-origin)'); 7307 } 7308 } 7309 } 7310 7311 // Intentar observar cuando el iframe se carga 7312 const ifr = findChatIframe(); 7313 if (ifr) { 7314 if (ifr.contentDocument && ifr.contentDocument.body) { 7315 observeChatIframe(); 7316 } else { 7317 ifr.addEventListener('load', observeChatIframe); 7318 } 7319 } 7320 7321 // También intentar cuando se detecta un nuevo iframe
7322 const iframeObserver = new MutationObserver(function() { 7323 const ifr = findChatIframe(); 7324 if (ifr && !ifr.__px_chat_message_observed) { 7325 ifr.__px_chat_message_observed = true; 7326 if (ifr.contentDocument && ifr.contentDocument.body) { 7327 observeChatIframe(); 7328 } else { 7329 ifr.addEventListener('load', observeChatIframe); 7330 } 7331 } 7332 }); 7333 iframeObserver.observe(document.body, { childList: true, subtree: true }); 7334 } catch(e) { 7335 console.error('[pxChat] Error setting up message observer:', e); 7336 } 7337 7338 // Expose helpers for manual triggers if needed 7339 window.pxChatOpen = function(meta){ handleChatOpen(meta || {}); }; 7340 window.pxChatMessage = function(meta){ handleChatMessage(meta || {}); }; 7341 window.pxChatClose = function(meta){ handleChatClose(meta || {}); }; 7342 // Expose message detection function for external use 7343 window.pxChatDetectMessage = function(messageId, messageType, from) { 7344 detectChatMessage(messageId, messageType, from); 7345 }; 7346 // Robust DOM observer: button presence and iframe lifecycle 7347 const observedIframes = new Set(); 7348 function isChatIframe(node){ 7349 if (!node || node.nodeName !== 'IFRAME') return false; 7350 try { 7351 const src = node.getAttribute('src') || ''; 7352 return /pxsol|chat|widget/i.test(src); 7353 } catch(_e){ return false; } 7354 } 7355 function installButtonListener(btn){ 7356 if (!btn || btn.__px_chat_hooked) return; 7357 btn.__px_chat_hooked = true; 7358 try { 7359 btn.__px_open_state = !!(btn.classList && btn.classList.contains('widget-launcher-button--open')); 7360 // NO sincronizar estado inicial aquà - solo observar cambios futuros 7361 let buttonChangeTimer = null; 7362 const ob = new MutationObserver(function(muts){ 7363 for (let i = 0; i < muts.length; i++){ 7364 const m = muts[i]; 7365 if (m.type === 'attributes' && m.attributeName === 'class') { 7366 const isOpen = btn.classList.contains('widget-launcher-button--open'); 7367 // Solo disparar si realmente cambió el estado 7368 if (isOpen !== btn.__px_open_state) { 7369 const now = Date.now(); 7370 if (now - lastStateChangeMs < 300) { 7371 console.debug('[pxChat] MutationObserver: change throttled'); 7372 return; // Ignorar cambios muy rápidos 7373 } 7374 7375 // Procesar inmediatamente (sin debounce para Chromium) 7376 if (buttonChangeTimer) { 7377 clearTimeout(buttonChangeTimer); 7378 } 7379 // Delay mÃnimo solo para asegurar que el DOM se actualizó 7380 buttonChangeTimer = setTimeout(function() { 7381 processButtonStateChange(btn, now); 7382 buttonChangeTimer = null; 7383 }, 50); // Delay mÃnimo de 50ms para Chromium 7384 } 7385 } 7386 } 7387 }); 7388 ob.observe(btn, { attributes: true, attributeFilter: ['class'] }); 7389 btn.__px_chat_observer = ob; 7390 } catch(_e){} 7391 } 7392 7393 function processButtonStateChange(btn, timestamp) { 7394 // Verificar que el estado realmente cambió 7395 const currentIsOpen = btn.classList.contains('widget-launcher-button--open') || 7396 btn.classList.toString().indexOf('--open') !== -1; 7397 console.log('[pxChat] processButtonStateChange:', { 7398 currentIsOpen: currentIsOpen, 7399 previousState: btn.__px_open_state, 7400 chatIsOpen: chatIsOpen 7401 }); 7402 7403 if (currentIsOpen === btn.__px_open_state) { 7404 console.log('[pxChat] MutationObserver: state unchanged, skipping'); 7405 return; 7406 } 7407 7408 btn.__px_open_state = currentIsOpen; 7409 lastStateChangeMs = timestamp || Date.now(); 7410 7411 if (currentIsOpen) { 7412 console.log('[pxChat] MutationObserver: button opened, calling handleChatOpen'); 7413 handleChatOpen(); 7414 } else { 7415 // Verificar que chatIsOpen es true antes de intentar cerrar 7416 if (!chatIsOpen) { 7417 console.log('[pxChat] MutationObserver: button closed but chatIsOpen is already false, skipping'); 7418 return; 7419 } 7420 // Guard mÃnimo: no cerrar si el chat se abrió hace menos de 3 segundos 7421 const finalNow = Date.now(); 7422 const startMs = chatOpenTsMs || lastOpenPushMs || null; 7423 if (startMs && (finalNow - startMs < 3000)) { 7424 console.log('[pxChat] MutationObserver: chat_close blocked - chat opened too recently (' + Math.round((finalNow - startMs) / 1000) + 's ago, minimum 3s)'); 7425 return; 7426 } 7427 7428 // CRÃTICO: Esperar y verificar nuevamente que el botón realmente perdió la clase --open 7429 // Esto previene disparos prematuros cuando el DOM aún se está actualizando 7430 setTimeout(function() { 7431 const btnCheck = document.querySelector('.widget-launcher-button') || 7432 document.querySelector('[class*="widget-launcher"]') || 7433 document.querySelector('[class*="launcher-button"]'); 7434 const isStillOpen = btnCheck && btnCheck.classList && ( 7435 btnCheck.classList.contains('widget-launcher-button--open') || 7436 btnCheck.classList.toString().indexOf('--open') !== -1 7437 ); 7438 7439 console.log('[pxChat] MutationObserver: delayed verification after button close:', { 7440 isStillOpen: isStillOpen, 7441 chatIsOpen: chatIsOpen, 7442 hasButton: !!btnCheck 7443 }); 7444 7445 // Solo proceder si el botón realmente está cerrado 7446 // Si hay botón, confiar solo en el botón (no en el iframe) 7447 if (isStillOpen) { 7448 console.log('[pxChat] MutationObserver: chat_close CANCELLED - button still shows as open after delay'); 7449 return; 7450 } 7451 // Solo verificar iframe si NO hay botón 7452 if (!btnCheck) { 7453 const ifr = findChatIframe(); 7454 const isIframeVisible = isElementVisible(ifr); 7455 if (isIframeVisible) { 7456 console.log('[pxChat] MutationObserver: chat_close CANCELLED - iframe still visible after delay (no button found)'); 7457 return; 7458 } 7459 } 7460 if (!chatIsOpen) { 7461 console.log('[pxChat] MutationObserver: chat_close CANCELLED - chatIsOpen is already false'); 7462 return; 7463 } 7464 7465 console.log('[pxChat] MutationObserver: button confirmed closed after delay, calling handleChatClose'); 7466 handleChatClose(); 7467 }, 600); // Esperar 600ms para confirmar que el DOM se actualizó completamente 7468 } 7469 } 7470
7471 function scanExisting(){ 7472 try { 7473 const btn = document.querySelector('.widget-launcher-button'); 7474 if (btn) installButtonListener(btn); 7475 document.querySelectorAll('iframe').forEach(function(ifr){ 7476 if (isChatIframe(ifr) && !observedIframes.has(ifr)) { 7477 observedIframes.add(ifr); 7478 // Delay más largo para evitar falsos positivos 7479 setTimeout(syncChatState, 800); 7480 } 7481 }); 7482 } catch(_e){} 7483 } 7484 const mo = new MutationObserver(function(mutations){ 7485 let anyRemoval = false; 7486 for (const m of mutations) { 7487 if (m.type === 'childList') { 7488 // Added nodes 7489 m.addedNodes && m.addedNodes.forEach(function(n){ 7490 try { 7491 if (!(n instanceof Element)) return; 7492 if (n.classList && n.classList.contains('widget-launcher-button')) { 7493 installButtonListener(n); 7494 } 7495 if (isChatIframe(n) && !observedIframes.has(n)) { observedIframes.add(n); setTimeout(syncChatState, 800); } 7496 // Deep scan 7497 n.querySelectorAll && n.querySelectorAll('.widget-launcher-button,iframe').forEach(function(x){ 7498 if (x.classList && x.classList.contains('widget-launcher-button')) installButtonListener(x); 7499 if (isChatIframe(x) && !observedIframes.has(x)) { observedIframes.add(x); setTimeout(syncChatState, 800); } 7500 }); 7501 } catch(_e){} 7502 }); 7503 // Removed nodes 7504 if (m.removedNodes && m.removedNodes.length) { 7505 anyRemoval = true; 7506 } 7507 } 7508 }
7509 if (anyRemoval) { 7510 // Check if any observed iframe is gone 7511 const still = new Set(); 7512 observedIframes.forEach(function(ifr){ 7513 if (document.body && document.body.contains(ifr)) { 7514 still.add(ifr); 7515 } else { 7516 // Delay más largo cuando se remueve el iframe (chat cerrado) 7517 setTimeout(syncChatState, 500); 7518 } 7519 }); 7520 observedIframes.clear(); 7521 still.forEach(function(x){ observedIframes.add(x); }); 7522 } 7523 }); 7524 // Poller de respaldo acotado: solo durante una ventana corta post-load 7525 // para evitar loops eternos si no aparece el botón. 7526 const CHAT_FALLBACK_POLL_INTERVAL_MS = 500; 7527 const CHAT_FALLBACK_POLL_MAX_MS_AFTER_LOAD = 2000; 7528 let chatFallbackPollIntervalId = null; 7529 let chatFallbackPollStartMs = null; 7530 7531 function stopChatFallbackPoller(reason) { 7532 if (!chatFallbackPollIntervalId) return; 7533 clearInterval(chatFallbackPollIntervalId); 7534 chatFallbackPollIntervalId = null; 7535 console.log('[pxChat] Polling stopped:', reason); 7536 } 7537 7538 function runChatFallbackPollTick() { 7539 const btn = document.querySelector('.widget-launcher-button') || 7540 document.querySelector('[class*="widget-launcher"]') || 7541 document.querySelector('[class*="launcher-button"]'); 7542 // Solo ejecutar syncChatState si NO hay botón (el botón tiene su propio observer) 7543 if (!btn) { 7544 console.log('[pxChat] Polling syncChatState (no button found)'); 7545 syncChatState(); 7546 return; 7547 } 7548 7549 console.debug('[pxChat] Polling skipped - button found, using MutationObserver instead'); 7550 stopChatFallbackPoller('button found'); 7551 } 7552 7553 function startChatFallbackPoller() { 7554 if (chatFallbackPollIntervalId) return; 7555 chatFallbackPollStartMs = Date.now(); 7556 runChatFallbackPollTick(); // Tick inicial inmediato 7557 chatFallbackPollIntervalId = setInterval(function() { 7558 if (Date.now() - chatFallbackPollStartMs > CHAT_FALLBACK_POLL_MAX_MS_AFTER_LOAD) { 7559 stopChatFallbackPoller('load + ' + CHAT_FALLBACK_POLL_MAX_MS_AFTER_LOAD + 'ms timeout'); 7560 return; 7561 } 7562 runChatFallbackPollTick(); 7563 }, CHAT_FALLBACK_POLL_INTERVAL_MS); 7564 } 7565 7566 // Ejecutar solo post-load (o inmediatamente si la página ya terminó de cargar) 7567 if (document.readyState === 'complete') { 7568 startChatFallbackPoller(); 7569 } else { 7570 window.addEventListener('load', function onLoadStartChatFallbackPoller() { 7571 window.removeEventListener('load', onLoadStartChatFallbackPoller); 7572 startChatFallbackPoller(); 7573 }); 7574 } 7575 try { 7576 mo.observe(document.documentElement || document, { childList: true, subtree: true }); 7577 // Initial scan after load tick 7578 if (document.readyState === 'loading') { 7579 document.addEventListener('DOMContentLoaded', scanExisting); 7580 } else { 7581 setTimeout(scanExisting, 0); 7582 } 7583 } catch(_e){} 7584 })(); 7585</script>
vendor: 1 bytes, line 7585
7585
7586<script> 7587 // Override para evitar espejo de chat_* al dataLayer y evitar doble track 7588 (function(){ 7589 if (typeof window.gtag === 'function') { 7590 window.gtag = function(){ 7591 try { window.dataLayer.push(arguments); } catch(_e){} 7592 }; 7593 } 7594 // Redefinir pxTrack: usa gtag si existe; sino, dataLayer 7595 window.pxTrack = function(eventName, params){ 7596 params = params || {}; 7597 if (typeof window.gtag === 'function') { 7598 try { window.gtag('event', eventName, params); } catch(_e){} 7599 } else { 7600 try { window.dataLayer.push(Object.assign({ event: eventName }, params)); } catch(_e){} 7601 } 7602 }; 7603 })(); 7604</script>
7604 7605</script>
7605 </div> 7606 7607 7608 <div id="ContainerRD" class="nodisplay"> 7609 <div class="flex flex-center fullheight"> 7610 <div id="ContainerRDInner"> 7611 <div id="Loader" class="fullheight flex flex-center"> 7612 <img class="animated slideInUp" src="https://cdn.pxsol.com/css/images/logo_loginrd.png" /> 7613 </div> 7614 <div id="CloseRDContainer"><i class="fa fa-times" aria-hidden="true"></i></div> 7615 <iframe style="width: 100%; height: 100%" src="" id="IframeRD" scrolling="no"> 7616 7617 </iframe> 7618 </div> 7619 </div> 7620 </div> 7621 7622 <div id="CortinaCargando" align="center" class="Loading nodisplay"> 7623 <div class="linear-activity"> 7624 <div class="indeterminate"></div> 7625 </div> 7626 </div> 7627 7628 <div id="dialogBox" title="..." class="nodisplay"> 7629 <p><span class="ui-icon ui-icon-alert alerticon"></span>...</p> 7630 </div> 7631 7632
7632<script src='/js_3.js?pos=LaAlondraCasadehuespedes&device=computer&filev=1790284695&posv=1787696497_2025-08-05T15:10:11.000Z_2025-08-05T15:10:11.000Z' defer="true" async></script>
7632 7633 7634 <div id="diccionario"> 7635 </div> 7636 7637 </div>
7637<script> 7638 window.currentContent = "index"; 7639 window.currentDevice = "desktop"; 7640 console.log('CurrentState', window.currentContent, window.currentDevice); 7641</script>
7641 7642 7643
7643<script src="/neo_modules/neo_popup/js.js?v=121790284695"></script>
7643 7644<!-- End Popup code --> 7645<div class="EndError left full" style="max-width: 100vw; overflow: auto;"> 7646 </div> 7647 7648
7649<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"a45a839acb7441e89693439ba23c4112","r":1,"spa":2}' crossorigin="anonymous"></script>
7649 7650</body> 7651<div id="dialogBox" title="..." class="nodisplay"> 7652 <p><span class="ui-icon ui-icon-alert alerticon"></span>...</p> 7653</div> 7654 7655 7656 7657 7658</html> 7659 7660
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.