PageSourceSearch

https://www.mobily.com.sa/web/ar/home/resources/6e6ee81a-04d7-40f5-9a7a-f9c959064fcf/main-mobily+%282%29.js

js mobily.com.sa collected 2026-09-24 09:22:16 UTC 22,456 bytes, 674 lines download raw bytes

1      const menu1Toggle = document.getElementById("menu1Toggle");
2      const navMenu1 = document.getElementById("navMenu1");
3
4
5// Initialize button with selected or first item
6document.addEventListener("DOMContentLoaded", () => {
7  const selectedItem =
8    navMenu1.querySelector(".selected a") || navMenu1.querySelector("li a");
9  if (selectedItem) {
10    menu1Toggle.querySelector(".label").textContent = selectedItem.textContent;
11  }
12});
13
14// Toggle dropdown open/close
15const menuOverlay = document.getElementById("menuOverlay");
16
17// Close dropdown if overlay is clicked
18menuOverlay.addEventListener("click", () => {
19  navMenu1.classList.remove("active");
20  menuOverlay.classList.remove("active");
21  document.body.style.overflow = "";
22  const selectedItem = navMenu1.querySelector(".selected a");
23  if (selectedItem) {
24    menu1Toggle.querySelector(".label").textContent = selectedItem.textContent;
25  }
26  menu1Toggle.classList.remove("active");
27  menuOverlay.classList.remove("active");
28});
29
30// Handle selection safely
31navMenu1.addEventListener("click", (e) => {
32  if (e.target.tagName === "A") {
33    const href = e.target.getAttribute("href")?.trim();
34
35    // Allow real navigation if link has a valid non-empty/non-placeholder href
36    if (href && href !== "#" && href !== "") {
37      // But still close dropdown visually before navigating
38      navMenu1.classList.remove("active");
39      menuOverlay.classList.remove("active");
40      menu1Toggle.classList.remove("active");
41      return; // Let browser follow the link
42    }
43
44    // Otherwise handle it as a dropdown selection (no navigation)
45    e.preventDefault();
46    navMenu1.querySelectorAll("li").forEach((li) => li.classList.remove("selected"));
47    e.target.parentElement.classList.add("selected");
48    menu1Toggle.querySelector(".label").textContent = e.target.textContent;
49
50    navMenu1.classList.remove("active");
51    menuOverlay.classList.remove("active");
52    menu1Toggle.classList.remove("active");
53  }
54});
55
56// Toggle open/close
57menu1Toggle.addEventListener("click", () => {
58  navMenu1.classList.toggle("active");
59  menuOverlay.classList.toggle("active");
60  menu1Toggle.classList.toggle("active");
61});
62
63
64
65 document.addEventListener("DOMContentLoaded", () => {
66        // Utility: normalize strings for fallback comparisons
67        const normalize = (s) =>
68          String(s || "")
69            .trim()
70            .toLowerCase()
71            .replace(/\s+/g, " ");
72
73        // When opening a dropdown, highlight first item and show matching column2
74        function openDropdown(dropdown) {
75          // get first column1 item
76          const firstItem = dropdown.querySelector(".column1 ul li");
77          if (!firstItem) return;
78
79          // mark active
80          dropdown
81            .querySelectorAll(".column1 ul li")
82            .forEach((li) => li.classList.remove("active"));
83          firstItem.classList.add("active");
84
85          // determine lookup value (prefer explicit data-target on li)
86          const lookup =
87            firstItem.dataset.target || normalize(firstItem.textContent);
88
89          // hide all column2, then show best match
90          const cols = dropdown.querySelectorAll(".column2");
91          cols.forEach((c) => (c.style.display = "none"));
92
93          // First try exact data-name match (preferred)
94          let matched = null;
95          if (lookup) {
96            matched = Array.from(cols).find((c) => {
97              const dataName = c.dataset.name;
98              if (typeof dataName !== "undefined") {
99                return (
100                  dataName === lookup ||
101                  normalize(dataName) === normalize(lookup)
102                );
103              }
104              return false;
105            });
106          }
107
108          // Fallback: try to match by id (normalized). This will work even when id has capitals
109          if (!matched) {
110            matched = Array.from(cols).find((c) => {
111              if (c.id) {
112                return normalize(c.id) === normalize(lookup);
113              }
114              return false;
115            });
116          }
117
118          // Final fallback: show first .column2 if nothing matched
119          if (!matched && cols.length) matched = cols[0];
120
121          if (matched) matched.style.display = "flex";
122        }
123
124        // Click handlers for third-menu top items (to open dropdown)
125const menuItems = document.querySelectorAll(".third-menu > li > a");
126const allDropdowns = document.querySelectorAll(".menu-dropdown");
127
128menuItems.forEach((menuItem) => {
129  menuItem.addEventListener("click", function (e) {
130    const href = menuItem.getAttribute("href")?.trim();
131
132    // ✅ Only prevent default if href is empty, blank, or '#'
133    if (!href || href === "#" || href === "") {
134      e.preventDefault();
135    } else {
136      // Allow navigation, but close any open dropdowns first
137      allDropdowns.forEach((d) => (d.style.display = "none"));
138      document
139        .querySelectorAll(".third-menu > li")
140        .forEach((li) => li.classList.remove("open"));
141      return; // Let browser follow the link
142    }
143
144    // Existing dropdown logic for non-link items
145    if (window.matchMedia("(max-width: 820px)").matches) {
146      document.querySelector(".secondary-menu").style.display = "none";
147    }
148
149    const li = menuItem.closest("li");
150    const dropdown =
151      li.querySelector(".menu-dropdown") ||
152      (li.nextElementSibling &&
153      li.nextElementSibling.classList.contains("menu-dropdown")
154        ? li.nextElementSibling
155        : null);
156
157    // Close all dropdowns and remove open class
158    allDropdowns.forEach((d) => (d.style.display = "none"));
159    document
160      .querySelectorAll(".third-menu > li")
161      .forEach((li) => li.classList.remove("open"));
162
163    // Mobile view behavior
164    if (window.innerWidth <= 820) {
165      const thirdMenu = document.querySelector(".third-menu");
166
167      // Hide sibling li including current one
168      thirdMenu.classList.add("hide-siblings");
169      li.classList.add("open");
170
171      // Show dropdown below clicked item
172      if (dropdown) {
173        dropdown.style.display = "block";
174
175        // Hide all column2 sections on mobile open
176        dropdown.querySelectorAll(".column2").forEach((col) => {
177          col.style.display = "none";
178        });
179
180        // Update dropdown header text dynamically
181        const titleEl = dropdown.querySelector(".dropdown-title");
182        if (titleEl) titleEl.textContent = menuItem.textContent.trim();
183
184        // Back button behavior
185        const backBtn = dropdown.querySelector(".back-button");
186        if (backBtn) {
187          backBtn.onclick = () => {
188            dropdown.style.display = "none";
189            li.classList.remove("open");
190            thirdMenu.classList.remove("hide-siblings");
191
192            document.querySelector(".secondary-menu").style.display = "block";
193            document.querySelector(".primary-menu").style.display = "block";
194            document
195              .querySelectorAll(".third-menu>li")
196              .forEach((ele) => (ele.style.display = "flex"));
197          };
198        }
199
200        if (window.matchMedia("(max-width: 820px)").matches) {
201          dropdown.querySelectorAll(".menu-dropdown .content").forEach((ele) => {
202            ele.addEventListener("click", () => {
203              ele.classList.toggle("open");
204              ele.classList.toggle("close");
205            });
206          });
207        }
208        openDropdown(dropdown);
209      }
210    } else {
211      // Desktop behavior
212      if (dropdown) {
213        const isShown = dropdown.style.display === "flex";
214        dropdown.style.display = isShown ? "none" : "flex";
215
216        if (!isShown) {
217          li.classList.add("open");
218          openDropdown(dropdown);
219        } else {
220          li.classList.remove("open");
221        }
222      }
223    }
224  });
225});
226
227
228        // Click handlers for column1 items (choose column2)
229        document
230          .querySelectorAll(".menu-dropdown .column1 ul li")
231          .forEach((item) => {
232            item.addEventListener("click", (e) => {
233              e.stopPropagation(); // prevent outer close
234              const parentDropdown = item.closest(".menu-dropdown");
235              if (!parentDropdown) return;
236             if (window.innerWidth <= 820) {
237                document.querySelector(".secondary-menu").style.display =
238                  "none";
239                document
240                  .querySelectorAll("ul.third-menu>li")
241                  .forEach((item) => (item.style.display = "none"));
242              }
243 
244              // Above 2 lines are added by ayushi
245              // toggle active class
246              parentDropdown
247                .querySelectorAll(".column1 ul li")
248                .forEach((li) => li.classList.remove("active"));
249              item.classList.add("active");
250
251              // lookup value (prefer explicit data-target)
252              const lookup = item.dataset.target || normalize(item.textContent);
253
254              // hide all column2 and find best match
255              const cols = parentDropdown.querySelectorAll(".column2");
256              cols.forEach((c) => (c.style.display = "none"));
257
258              // try data-name match
259              let matched = Array.from(cols).find((c) => {
260                const dataName = c.dataset.name;
261                if (typeof dataName !== "undefined") {
262                  return (
263                    dataName === lookup ||
264                    normalize(dataName) === normalize(lookup)
265                  );
266                }
267                return false;
268              });
269
270              // fallback to id normalized
271              if (!matched) {
272                matched = Array.from(cols).find(
273                  (c) => c.id && normalize(c.id) === normalize(lookup)
274                );
275              }
276
277              if (!matched && cols.length) matched = cols[0];
278              if (matched) matched.style.display = "flex";
279              //From  here added by ayushi
280              if (matched)
281                matched.style.setProperty("display", "block", "important");
282              if (matched)
283                matched.style.setProperty("display", "block", "important");
284              if (window.matchMedia("(max-width: 820px)").matches) {
285                if (window.matchMedia("(max-width: 820px)").matches) {
286                  document.querySelector(
287                    ".menu-dropdown .dropdown-header .dropdown-title"
288                  ).innerText = matched.getAttribute("data-name");
289                  document.querySelector(
290                    ".menu-dropdown .dropdown-header .dropdown-title"
291                  ).innerText = matched.getAttribute("data-name");
292                  document.querySelector(
293                    ".menu-dropdown .column1"
294                  ).style.display = "none";
295                  document.querySelector(
296                    ".menu-dropdown .column1"
297                  ).style.display = "none";
298                  document
299                    .querySelector(".back-button")
300                    .classList.add("back-button-1");
301                  document
302                    .querySelector(".back-button")
303                    .classList.add("back-button-1");
304                  const backButtonHandler = () => {
305                    console.log("coming here");
306                    document.querySelector(
307                      ".menu-dropdown .column1"
308                    ).style.display = "block";
309                    document
310                      .querySelector(".back-button")
311                      .classList.remove("back-button-1");
312                    document.querySelector("#mobily-plans").style.display =
313                      "block";
314                    document.querySelector(".primary-menu").style.display =
315                      "none";
316                      
317                    document.querySelector(
318                      "#mobily-plans .dropdown-title"
319                    ).innerText = document.querySelector("#mobily-plans .dropdown-title")
320                      .parentElement.parentElement.getAttribute('id')
321                      .split("-").map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
322
323                    document.querySelector(".menu-dropdown .column2").removeAttribute("style")
324
325                    // Remove the listener
326                    document
327                      .querySelector(".back-button")
328                      .removeEventListener("click", backButtonHandler);
329                  };
330                  if (document.querySelector(".back-button-1") != undefined) {
331                    document
332                      .querySelector(".back-button-1")
333                      .addEventListener("click", backButtonHandler);
334                  }
335                }
336              }
337              // Above lines are added by ayushi
338            });
339          });
340        if (document.querySelector(".back-button-1") != undefined) {
341          document
342            .querySelector(".back-button-1")
343            .addEventListener("click", () => {
344              document.querySelector(".menu-dropdown .column1").style.display =
345                "block";
346            });
347        }
348
349        // Close when clicking outside
350        document.addEventListener("click", (e) => {
351          const clickedInsideDropdown = e.target.closest(".menu-dropdown");
352          const clickedMenuItem = e.target.closest(".third-menu > li");
353
354          if (!clickedInsideDropdown && !clickedMenuItem) {
355            allDropdowns.forEach((d) => (d.style.display = "none"));
356            document
357              .querySelectorAll(".third-menu > li")
358              .forEach((li) => li.classList.remove("open"));
359          }
360        });
361      });
362	  
363	  
364	  
365
366
367
368
369document.addEventListener("DOMContentLoaded", () => {
370  const slides = document.querySelectorAll(".carousel-slide");
371  const indicatorsContainer = document.getElementById("carouselIndicators");
372  if (!indicatorsContainer) return;
373  let current = 0;
374  const slideInterval = 3000; // 5 seconds
375  let autoSlide;
376 
377  // Create indicators dynamically
378  slides.forEach((slide, i) => {
379    const indicator = document.createElement("button");
380    indicator.name = slide.getElementsByTagName('img')[0].alt   
381    if (i === 0) indicator.classList.add("active");
382    indicator.addEventListener("click", () => showSlide(i, true));
383    indicatorsContainer.appendChild(indicator);
384  });
385 
386  const indicators = indicatorsContainer.querySelectorAll("button");
387 
388  function showSlide(index, userClick = false) {
389    slides.forEach((slide, i) => {
390      slide.classList.toggle("active", i === index);
391    });
392    indicators.forEach((dot, i) => {
393      dot.classList.toggle("active", i === index);
394    });
395    current = index;
396    if (userClick) {
397      restartAutoSlide();
398    }
399  }
400 
401  function nextSlide() {
402    current = (current + 1) % slides.length;
403    showSlide(current);
404  }
405 
406  function startAutoSlide() {
407    autoSlide = setInterval(nextSlide, slideInterval);
408  }
409 
410  function restartAutoSlide() {
411    clearInterval(autoSlide);
412    startAutoSlide();
413  }
414 
415  // Start automatic slide
416  startAutoSlide();
417});
418
419
420
421
422document.addEventListener("DOMContentLoaded", () => {
423        const header = document.querySelector("header");
424        const thirdMenu = document.querySelector(".third-menu.float-start");
425        const carousel = document.querySelector(".hero-carousel");
426
427        // Remove 'holder' class from the section that contains .hero-carousel on mobile
428        const holderSection = carousel?.closest("section.holder");
429        if (holderSection && window.innerWidth < 768) {
430          holderSection.classList.remove("holder");
431        }
432
433        // function adjustHeroHeight() {
434        //   const headerHeight = header?.offsetHeight || 0;
435        //   const menuHeight = thirdMenu?.offsetHeight
436        //     ? thirdMenu?.offsetHeight + 20
437        //     : 0;
438        //   const viewportHeight = window.innerHeight;
439
440        //   carousel.style.height =
441        //     window.innerWidth >= 768 && window.innerWidth < 1280
442        //       ? " 654px"
443        //       : `${viewportHeight - headerHeight - menuHeight}px`;
444        // }
445
446        // adjustHeroHeight();
447        // window.addEventListener("resize", adjustHeroHeight);
448      });
449	  
450	  
451	  
452	  
453document.addEventListener("DOMContentLoaded", () => {
454  const carousel = document.getElementById("cardCarousel");
455  const prevBtn = document.getElementById("cardPrev");
456  const nextBtn = document.getElementById("cardNext");
457  const nav = document.querySelector(".carousel-nav");
458//  const el = document.getElementsByClassName("card-carousel")[0];
459  
460  if (!carousel || !prevBtn || !nextBtn || !nav) return;
461 
462  const checkOverflow = () => {
463    const hasOverflow = carousel.scrollWidth > carousel.clientWidth;
464    nav.classList.toggle("visible", hasOverflow);
465  };
466 
467  const scrollAmount = 300; // adjust per design
468 
469  prevBtn.addEventListener("click", () => {
470    carousel.scrollBy({ left: -scrollAmount, behavior: "smooth" });
471  });
472 
473  nextBtn.addEventListener("click", () => {
474    carousel.scrollBy({ left: scrollAmount, behavior: "smooth" });
475  });
476 
477  // Check on load and resize
478  checkOverflow();
479  window.addEventListener("resize", checkOverflow);
480
481// Swipe support
482let sx = 0,
483sy = 0,
484st = 0;
485
486carousel.addEventListener(
487        "touchstart",
488        (e) => {
489          const t = e.touches[0];
490          sx = t.clientX;
491          sy = t.clientY;
492          st = Date.now();
493        },
494        { passive: true }
495      );
496
497
498carousel.addEventListener(
499        "touchend",
500        (e) => {
501          const t = e.changedTouches[0];
502          const dx = t.clientX - sx;
503          const dy = t.clientY - sy;
504          const dt = Date.now() - st;
505
506          const ax = Math.abs(dx),
507            ay = Math.abs(dy);
508          let direction = null;
509
510          if (dt > 100) {
511            if (ax > ay && ax >= 30 && ay <= 100) {
512              direction = dx < 0 ? "left" : "right";
513            } else if (ay >= 30 && ax <= 100) {
514              direction = dy < 0 ? "up" : "down";
515            }
516          }
517
518          if (direction) {
519            carousel.dispatchEvent(
520              new CustomEvent("swipe", {
521                detail: { direction, dx, dy, duration: dt },
522              })
523            );
524          }
525        },
526        { passive: true }
527      );
528
529// Your listener:
530      carousel.addEventListener("swipe", (e) => {
531        const { direction, dx, dy } = e.detail;
532        if (direction === "left") {
533          carousel.scrollBy({ left: scrollAmount, behavior: "smooth" });
534        } else {
535          carousel.scrollBy({ left: -scrollAmount, behavior: "smooth" });
536        }
537      });
538
539});
540
541
542
543window.addEventListener("load", function() {
544  const generatedImages = document.getElementById("generated-images");
545  if (!generatedImages) return;
546
547  const generatedDivs = generatedImages.querySelectorAll(":scope > div");
548  generatedDivs.forEach(genDiv => {
549    const imgId = genDiv.id?.toLowerCase().replace(/[-_]/g, "");
550    const img = genDiv.querySelector("img");
551    if (!img || !imgId) return;
552
553    const imgSrc = img.src;
554    document.querySelectorAll("div[id]").forEach(target => {
555      const deviceId = target.id?.toLowerCase().replace(/[-_]/g, "");
556      if (deviceId === imgId) {
557        const thumb = target.querySelector(".img-thumb, #img-thumb");
558        if (thumb) {
559          Object.assign(thumb.style, {
560            backgroundImage: `url("${imgSrc}")`
561          });
562        }
563      }
564    });
565  });
566
567  // now safely remove after processing
568  generatedImages.remove();
569
570  // hide beyond 5
571  document.querySelectorAll("#landing-devices-carousel .owl-stage .owl-item")
572    .forEach((item, i) => i > 5 && (item.style.display = "none"));
573});
574
575
576document.addEventListener("DOMContentLoaded", () => {
577  const container = document.querySelector("#footerID");
578  const elements = Array.from(container.children);
579  const grouped = [];
580  let currentGroup = null;
581
582  elements.forEach(el => {
583    if (el.tagName === "H2") {
584      if (currentGroup) grouped.push(currentGroup);
585      currentGroup = { header: el, items: [] };
586    } else if (el.tagName === "LI" && currentGroup) {
587      currentGroup.items.push(el);
588    }
589  });
590  if (currentGroup) grouped.push(currentGroup);
591
592  // Clear original nodes
593  container.innerHTML = "";
594
595  // Rebuild structured layout
596  grouped.forEach(group => {
597    const column = document.createElement("div");
598    column.className = "column";
599
600    const ul = document.createElement("ul");
601
602    // Move elements (not clone)
603    column.appendChild(group.header);
604    group.items.forEach(li => ul.appendChild(li));
605    column.appendChild(ul);
606
607    container.appendChild(column);
608  });
609});
610const searchToggleBtn = document.getElementById('searchID');
611if (searchToggleBtn) {
612  searchToggleBtn.addEventListener('click', function(e) {
613    e.preventDefault();
614    const modal = document.getElementById('mobily-search');
615    if (modal) modal.style.display = 'block';
616  });
617}
618
619const closeSearchBtn = document.getElementById('mobile-l1-close-btn');
620if (closeSearchBtn) {
621  closeSearchBtn.addEventListener('click', function() {
622    const searchDiv = document.getElementById('mobily-search');
623    if (searchDiv) searchDiv.style.display = 'none';
624  });
625}
626
627// cookie setting for sign-in
628
629function getCookie() {
630  let decodedCookie = decodeURIComponent(document.cookie);
631cookiearray = decodedCookie.split(';');
632for(var i=0; i<cookiearray.length; i++) {
633 name = cookiearray[i].split('=');
634if(name.includes("url")){
635var vu = name.replace("url,", '');
636var uu = vu.replaceAll(',','=');
637}
638}
639if(uu == "" || uu == null){
640location.href = "/web/en/personal/route-menu/mobile-app";
641}
642else{
643location.href = uu;
644}
645}
646function checkCookie() {
647getCookie();
648}
649function setCookie(name, value, days, secure = false, httpOnly = false, sameSite = 'Lax') {
650    let expires = "";
651    if (days) {
652        const date = new Date();
653        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
654        expires = "; expires=" + date.toUTCString();
655    }
656    
657    let cookieString = `${name}=${value || ""}${expires}; path=/`;
658
659    //if (secure) {
660       // cookieString += "; Secure"; // Ensures the cookie is only sent over HTTPS
661   // }
662
663    if (sameSite) {
664        cookieString += `; SameSite=${sameSite}`; // Helps prevent CSRF attacks
665    }
666
667    if (httpOnly) {
668        cookieString += "; HttpOnly"; // Prevents JavaScript from accessing the cookie (Note: HttpOnly can only be set server-side)
669    }
670
671    document.cookie = cookieString;
672}
673
674

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.