PageSourceSearch

https://hongngochospital.vn/cache-buster-1784260272/statics/js/optimize/home-optimize.js

js hongngochospital.vn collected 2026-09-24 18:41:52 UTC 13,553 bytes, 474 lines download raw bytes

1// home-optimize.js — home banner slick, lazy sections, deferred booking modals
2(function () {
3  if (!document.getElementById("home")) {
4    return;
5  }
6
7  function activateDeferredIframe(iframe) {
8    if (!iframe || iframe.src) {
9      return;
10    }
11    var url = iframe.getAttribute("data-src");
12    if (!url) {
13      return;
14    }
15    iframe.src = url;
16    iframe.removeAttribute("data-src");
17  }
18
19  var sections = document.querySelectorAll(".js-home-lazy-section[data-script-src]");
20  if (sections.length) {
21    var isDesktop = window.matchMedia && window.matchMedia("(min-width: 1024px)").matches;
22    var defaultMargin = isDesktop ? "900px 0px" : "400px 0px";
23    var observer = new IntersectionObserver(
24      function (entries) {
25        entries.forEach(function (entry) {
26          if (!entry.isIntersecting) {
27            return;
28          }
29          var section = entry.target;
30          var src = section.getAttribute("data-script-src");
31          observer.unobserve(section);
32          var deferredIframe = section.querySelector("iframe[data-src]");
33          if (deferredIframe) {
34            if (typeof window.hnActivateDeferredIframe === "function") {
35              window.hnActivateDeferredIframe(deferredIframe);
36            } else {
37              activateDeferredIframe(deferredIframe);
38            }
39          }
40          if (src && typeof window.hnLoadScriptOnce === "function") {
41            window.hnLoadScriptOnce(src).catch(function () {});
42          }
43        });
44      },
45      {
46        rootMargin:
47          (sections[0] && sections[0].getAttribute("data-lazy-root-margin")) ||
48          defaultMargin,
49      }
50    );
51    sections.forEach(function (section) {
52      observer.observe(section);
53    });
54  }
55
56  var stackLoaded = false;
57  var stackLoading = false;
58  var stackQueue = [];
59  var authModalSelector = window.hnAuthModalTriggerSelector || "";
60
61  function runQueue() {
62    var queue = stackQueue.slice();
63    stackQueue = [];
64    queue.forEach(function (fn) {
65      fn();
66    });
67  }
68
69  function ensureFormStack() {
70    if (stackLoaded || typeof window.hnLoadDeferredHomeFormAssets !== "function") {
71      return Promise.resolve();
72    }
73    if (stackLoading) {
74      return new Promise(function (resolve) {
75        stackQueue.push(resolve);
76      });
77    }
78    stackLoading = true;
79    return window
80      .hnLoadDeferredHomeFormAssets()
81      .then(function () {
82        stackLoaded = true;
83        stackLoading = false;
84        runQueue();
85      })
86      .catch(function () {
87        stackLoading = false;
88        runQueue();
89      });
90  }
91
92  document.addEventListener(
93    "click",
94    function (event) {
95      var trigger = event.target.closest('[data-bs-toggle="modal"]');
96      if (!trigger) {
97        return;
98      }
99      if (authModalSelector && trigger.matches(authModalSelector)) {
100        return;
101      }
102      var target = trigger.getAttribute("data-bs-target") || trigger.getAttribute("href");
103      if (!target || target.charAt(0) !== "#" || stackLoaded) {
104        return;
105      }
106      event.preventDefault();
107      event.stopImmediatePropagation();
108      ensureFormStack().then(function () {
109        window.hnOpenBootstrapModal(target);
110      });
111    },
112    true
113  );
114
115  var bannerHydrated = false;
116  var bannerQueuedDirection = null;
117  var bannerInitStarted = false;
118
119  function escapeHtml(value) {
120    return String(value == null ? "" : value)
121      .replace(/&/g, "&")
122      .replace(/</g, "&lt;")
123      .replace(/>/g, "&gt;")
124      .replace(/"/g, "&quot;");
125  }
126
127  function buildDeferredSlideHtml(slide) {
128    var href = escapeHtml(slide.href || "#");
129    var alt = escapeHtml(slide.alt || "");
130    var translateClass = slide.translate ? " translateImageAi" : "";
131    var desktop = slide.desktop || null;
132    var mobile = slide.mobile || null;
133    var fallback = desktop || mobile || {
134      imgSm: slide.imgSm || slide.img || "",
135      srcset: slide.srcset || "",
136      w: slide.w || 1600,
137      h: slide.h || 522
138    };
139    if (window.matchMedia && window.matchMedia("(max-width: 1023px)").matches && mobile) {
140      fallback = mobile;
141    }
142    var fallbackSm = escapeHtml(fallback.imgSm || fallback.img || "");
143    var fallbackSrcset = escapeHtml(fallback.srcset || "");
144    var fallbackW = fallback.w || 1600;
145    var fallbackH = fallback.h || 522;
146    var sourcesHtml = "";
147    if (mobile) {
148      sourcesHtml +=
149        '<source media="(max-width: 1023px)" data-srcset="' +
150        escapeHtml(mobile.srcset || "") +
151        '" data-sizes="100vw">';
152    }
153    if (desktop) {
154      sourcesHtml +=
155        '<source media="(min-width: 1024px)" data-srcset="' +
156        escapeHtml(desktop.srcset || "") +
157        '" data-sizes="100vw">';
158    }
159    return (
160      '<div class="--item homeBanner__item">' +
161      '<div class="--img' +
162      translateClass +
163      '">' +
164      '<a href="' +
165      href +
166      '" class="--link homeBanner__link">' +
167      "<picture>" +
168      sourcesHtml +
169      '<img data-lazy="' +
170      fallbackSm +
171      '"' +
172      (fallbackSrcset ? ' data-srcset="' + fallbackSrcset + '"' : "") +
173      ' data-sizes="100vw" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" loading="lazy" decoding="async" alt="' +
174      alt +
175      '" width="' +
176      fallbackW +
177      '" height="' +
178      fallbackH +
179      '">' +
180      "</picture></a></div></div>"
181    );
182  }
183
184  function readDeferredSlides() {
185    var node = document.getElementById("hnHomeBannerSlides");
186    if (!node || !node.textContent) {
187      return [];
188    }
189    try {
190      var data = JSON.parse(node.textContent);
191      return Array.isArray(data) ? data : [];
192    } catch (e) {
193      return [];
194    }
195  }
196
197  function hydrateDeferredBannerSlides($slider) {
198    if (bannerHydrated) {
199      return;
200    }
201    bannerHydrated = true;
202    var slides = readDeferredSlides();
203    slides.forEach(function (slide) {
204      $slider.slick("slickAdd", buildDeferredSlideHtml(slide));
205    });
206    var jsonNode = document.getElementById("hnHomeBannerSlides");
207    if (jsonNode) {
208      jsonNode.remove();
209    }
210    if (bannerQueuedDirection === "next") {
211      $slider.slick("slickNext");
212    } else if (bannerQueuedDirection === "prev") {
213      $slider.slick("slickPrev");
214    }
215    bannerQueuedDirection = null;
216  }
217
218  function enableBannerAutoplay($slider) {
219    if (!$slider || !$slider.hasClass("slick-initialized")) {
220      return;
221    }
222    $slider.slick("slickSetOption", "autoplay", true, true);
223    $slider.slick("slickPlay");
224  }
225
226  function scheduleBannerAutoplay($slider) {
227    var started = false;
228    var start = function () {
229      if (started) {
230        return;
231      }
232      started = true;
233      hydrateDeferredBannerSlides($slider);
234      enableBannerAutoplay($slider);
235    };
236    window.setTimeout(start, 15000);
237    document.addEventListener("pointerdown", start, { once: true, passive: true });
238    document.addEventListener("scroll", start, { once: true, passive: true });
239  }
240
241  function bindHomeBannerArrows() {
242    var arrows = document.getElementById("homeBannerArrows");
243    if (!arrows || arrows.hasAttribute("data-hn-banner-bound")) {
244      return;
245    }
246    arrows.setAttribute("data-hn-banner-bound", "1");
247    arrows.addEventListener("click", function (event) {
248      var btn = event.target.closest(".--arrow");
249      if (!btn || !arrows.contains(btn)) {
250        return;
251      }
252      event.preventDefault();
253      var goNext = btn.classList.contains("slick-next");
254      bannerQueuedDirection = goNext ? "next" : "prev";
255      var sliderEl = document.getElementById("homeBannerSlider");
256      if (!sliderEl || typeof jQuery === "undefined") {
257        scheduleBannerInit(true);
258        return;
259      }
260      var $slider = jQuery(sliderEl);
261      if (!$slider.hasClass("slick-initialized")) {
262        scheduleBannerInit(true);
263        return;
264      }
265      if (!bannerHydrated) {
266        hydrateDeferredBannerSlides($slider);
267        return;
268      }
269      if (goNext) {
270        $slider.slick("slickNext");
271      } else {
272        $slider.slick("slickPrev");
273      }
274      bannerQueuedDirection = null;
275    });
276  }
277
278  function initHomeBannerSlick() {
279    var sliderEl = document.getElementById("homeBannerSlider");
280    if (!sliderEl || !sliderEl.querySelector(".homeBanner__item") || typeof jQuery === "undefined" || !jQuery.fn.slick) {
281      return;
282    }
283    if (jQuery(sliderEl).hasClass("slick-initialized")) {
284      return;
285    }
286    var $slider = jQuery(sliderEl);
287    bindHomeBannerArrows();
288    $slider.on("lazyLoaded", function (event, slick, image) {
289      var img = image && image.jquery ? image[0] : image;
290      if (!img || typeof img.getAttribute !== "function") {
291        return;
292      }
293      var srcset = img.getAttribute("data-srcset");
294      var sizes = img.getAttribute("data-sizes");
295      if (srcset) {
296        img.setAttribute("srcset", srcset);
297        img.removeAttribute("data-srcset");
298      }
299      if (sizes) {
300        img.setAttribute("sizes", sizes);
301        img.removeAttribute("data-sizes");
302      }
303      var picture = img.parentNode;
304      if (picture && picture.tagName === "PICTURE") {
305        var sources = picture.querySelectorAll("source[data-srcset]");
306        for (var i = 0; i < sources.length; i++) {
307          var source = sources[i];
308          source.setAttribute("srcset", source.getAttribute("data-srcset"));
309          source.removeAttribute("data-srcset");
310          var sourceSizes = source.getAttribute("data-sizes");
311          if (sourceSizes) {
312            source.setAttribute("sizes", sourceSizes);
313            source.removeAttribute("data-sizes");
314          }
315        }
316      }
317    });
318    $slider.slick({
319      slidesToShow: 1,
320      slidesToScroll: 1,
321      dots: false,
322      arrows: false,
323      autoplay: false,
324      autoplaySpeed: 6000,
325      infinite: true,
326      fade: true,
327      lazyLoad: "ondemand",
328      adaptiveHeight: false,
329      accessibility: true,
330      responsive: [{ breakpoint: 768, settings: { adaptiveHeight: false } }],
331    });
332    if (bannerQueuedDirection) {
333      hydrateDeferredBannerSlides($slider);
334    }
335    scheduleBannerAutoplay($slider);
336  }
337
338  function scheduleBannerInit(immediate) {
339    if (bannerInitStarted && !immediate) {
340      return;
341    }
342    if (bannerInitStarted && immediate) {
343      initHomeBannerSlick();
344      return;
345    }
346    bannerInitStarted = true;
347    var run = function () {
348      initHomeBannerSlick();
349    };
350    if (immediate) {
351      run();
352      return;
353    }
354    if ("requestIdleCallback" in window) {
355      window.requestIdleCallback(run, { timeout: 4000 });
356    } else {
357      window.setTimeout(run, 500);
358    }
359  }
360
361  function initDeferredHomeSlicks() {
362    if (typeof jQuery === "undefined" || !jQuery.fn.slick) {
363      return;
364    }
365    var $prize = jQuery(".Prize .--listPrize");
366    if ($prize.length && !$prize.hasClass("slick-initialized")) {
367      $prize.slick({
368        lazyLoad: "ondemand",
369        dots: false,
370        infinite: true,
371        speed: 300,
372        slidesToShow: 3,
373        autoplay: true,
374        autoPlaySpeed: 3000,
375        slidesToScroll: 1,
376        arrows: false,
377        focusOnSelect: true,
378        centerMode: false,
379        centerPadding: 0,
380        pauseOnHover: false,
381        responsive: [
382          {
383            breakpoint: 768,
384            settings: {
385              slidesToShow: 1,
386              centerPadding: "20px",
387              variableWidth: true,
388              slidesToScroll: 1,
389            },
390          },
391        ],
392      });
393    }
394    if (window.innerWidth < 1023) {
395      var $why = jQuery(".homeWhy .--listWhy");
396      if ($why.length && !$why.hasClass("slick-initialized")) {
397        $why.slick({
398          lazyLoad: "ondemand",
399          slidesToShow: 1,
400          slidesToScroll: 1,
401          infinite: true,
402          dots: false,
403          arrows: false,
404          variableWidth: true,
405        });
406      }
407      var $ads = jQuery(".homeAds .row");
408      if ($ads.length && !$ads.hasClass("slick-initialized")) {
409        $ads.slick({
410          lazyLoad: "ondemand",
411          slidesToShow: 1,
412          slidesToScroll: 1,
413          dots: true,
414          arrows: false,
415          autoplay: true,
416          autoPlaySpeed: 3000,
417          infinite: true,
418          fade: true,
419        });
420      }
421    }
422  }
423
424  function observeHomeSlicks() {
425    var targets = document.querySelectorAll(".Prize, .homeWhy, .homeAds");
426    if (!targets.length) {
427      return;
428    }
429    if (!("IntersectionObserver" in window)) {
430      initDeferredHomeSlicks();
431      return;
432    }
433    var started = false;
434    var io = new IntersectionObserver(
435      function (entries) {
436        entries.forEach(function (entry) {
437          if (!entry.isIntersecting || started) {
438            return;
439          }
440          started = true;
441          io.disconnect();
442          initDeferredHomeSlicks();
443        });
444      },
445      { rootMargin: "200px 0px" }
446    );
447    targets.forEach(function (el) {
448      io.observe(el);
449    });
450  }
451
452  function bootHomePageSliders() {
453    bindHomeBannerArrows();
454    observeHomeSlicks();
455    if (document.readyState === "complete") {
456      scheduleBannerInit();
457      return;
458    }
459    window.addEventListener("load", scheduleBannerInit, { once: true });
460    document.addEventListener(
461      "pointerdown",
462      function () {
463        scheduleBannerInit();
464      },
465      { once: true, passive: true }
466    );
467  }
468
469  if (typeof jQuery !== "undefined") {
470    jQuery(bootHomePageSliders);
471  } else {
472    document.addEventListener("DOMContentLoaded", bootHomePageSliders);
473  }
474})();

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.