Javascript not working for specific iPhone safari versions

I have javascript code on my web page, It works for desktop, android,
However it’s not working for some iPhones, each part of my code, input events, click event

Works for this iPhone models and versions:

  1. Iphone 13 safari version 16.6

  2. Iphone 12 safari version 16.6

  3. Iphone 13 safari version 16.5.1

  4. Iphone 11 safari version 16.5

But my code doesn’t work for this types of iPhone:

  1. Iphone 11 safari version 16.1

  2. Iphone 11 safari version 16.3.1

  3. Iphone XS Max safari version 16.5.1

  4. Iphone Xr safari version 16.5.1

  5. Iphone XR safari version 16.3.1

This is my code:

document.addEventListener("DOMContentLoaded", function() {
    const header = document.querySelector(".header");
    const langSelect = document.querySelector("#lang_select");
    const langList = document.querySelector(".lang_list");

    header.addEventListener("click", function(event) {
      langList.style.display = langList.style.display === "none" ? "block" : "none";
      event.stopPropagation();
    });

    document.addEventListener("click", function(event) {
      if (!langSelect.contains(event.target)) {
        langList.style.display = "none";
      }
    });

    const fieldInputs = document.querySelectorAll(".field input");

fieldInputs.forEach(function(input) {
  input.addEventListener("focus", function() {
    this.parentElement.classList.add("active");
  });

  input.addEventListener("blur", function() {
    if (this.value === "") {
      this.parentElement.classList.remove("active");
    }
  });
});

let isFirstOpen = false;
  const firstBtn = document.querySelector("#firstBtn");
  const firstDrop = document.querySelector("#firstDrop");

  firstBtn.addEventListener("click", function(event) {
    isFirstOpen = !isFirstOpen;

    if (isFirstOpen) {
      firstDrop.style.display = "block";
    } else {
      firstDrop.style.display = "none";
    }

    event.stopPropagation();
  });

  document.addEventListener("click", function(event) {
  if (
    !event.target.closest("#firstBtn") &&
    !event.target.closest("#firstDrop")
  ) {
    const firstDropElement = document.querySelector("#firstDrop");
    if (firstDropElement.style.display !== "none") {
      firstDropElement.style.display = "none";
      isFirstOpen = false;
    }
  }
});

  



 

      

  document.querySelector("#firstInput input").addEventListener("input", function() {
  const inputVal = this.value;
  let num = inputVal.replace(/[^0-9.]+/g, "");
  let regex = /^[+-]?(\d*\.\d+|\d+\.\d*)([eE][+-]?\d+)?$/;

  if (!regex.test(num)) {
    if (num === ".") {
      num = "";
    } else {
      num = num.replace(/(?<=\..*)\./, "");
    }
  }

  this.value = num;

  const firstCryptoCurrencySymbol = document.querySelector("#currency1 a").dataset.cur;
  const secondCryptoCurrencySymbol = document.querySelector("#currency2 a").dataset.cur;

  fetch("/calculateExchangeRate", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      firstCryptoCurrencySymbol: firstCryptoCurrencySymbol,
      secondCryptoCurrencySymbol: secondCryptoCurrencySymbol
    })
  })
  .then(res => res.json())
  .then(data => {
    const exchangeRate = data.rate;
    document.querySelector("#secondInput input").value = num * exchangeRate;
  });
});



document.querySelector("#secondInput input").addEventListener("input", function() {
  const inputVal = this.value;
  let num = inputVal.replace(/[^0-9.]+/g, "");
  let regex = /^[+-]?(\d*\.\d+|\d+\.\d*)([eE][+-]?\d+)?$/;

  if (!regex.test(num)) {
    if (num === ".") {
      num = "";
    } else {
      num = num.replace(/(?<=\..*)\./, "");
    }
  }

  this.value = num;

  const firstCryptoCurrencySymbol = document.querySelector("#currency1 a").dataset.cur;
  const secondCryptoCurrencySymbol = document.querySelector("#currency2 a").dataset.cur;

  fetch("/calculateExchangeRate", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      firstCryptoCurrencySymbol: firstCryptoCurrencySymbol,
      secondCryptoCurrencySymbol: secondCryptoCurrencySymbol
    })
  })
    .then(res => res.json())
    .then(data => {
      const exchangeRate = data.rate;
      document.querySelector("#firstInput input").value = num / exchangeRate;
    });
});




         
const optionElements = document.querySelectorAll(".option");

optionElements.forEach(function(option) {
  option.addEventListener("click", function(event) {
    if ('ontouchstart' in window || navigator.maxTouchPoints) {
      event.preventDefault();
    }

    let dataCur = this.dataset.cur;
    let imageUrl = this.querySelector(".pm_select_img img").src;
    let optionText = this.querySelector("span").textContent;

    document.querySelector("#firstBtn .pm_select_img img").src = imageUrl;
    document.querySelector("#firstBtn span").textContent = optionText;
    document.querySelector("#firstBtn").dataset.cur = dataCur;

    document.querySelector("#currency1 .pm_select_child").dataset.cur = dataCur;
    document.querySelector("#currency1 .pm_select_child").textContent = dataCur;

    document.querySelector("#hiddenInput").value = dataCur;

    document.querySelector("#amount_send1").dataset.cur = dataCur;
    document.querySelector("#amount_send1 ~ .addons").textContent = dataCur;

    const secondDataCur = document.querySelector("#currency2 a").dataset.cur;

    fetch("/calculateExchangeRate", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        firstCryptoCurrencySymbol: dataCur,
        secondCryptoCurrencySymbol: secondDataCur
      })
    })
    .then(res => res.json())
    .then(data => {
      const exchangeRate = data.rate;
      document.querySelector(".rate_info").textContent = `1 ${dataCur} = ${exchangeRate} ${secondDataCur}`;
    });

   
    event.stopPropagation();
  });
});

document.addEventListener("click", function() {
  document.querySelector("#firstDrop").style.display = "none";
});



const optionElementsFirst = document.querySelectorAll(".option1");

optionElementsFirst.forEach(function (option) {
  option.addEventListener("click", function (event) {
    if ("ontouchstart" in window || navigator.maxTouchPoints) {
      event.preventDefault();
    }

    let dataCur = this.dataset.cur;
    let imageUrl = this.querySelector(".pm_select_img img").src;
    let optionText = this.querySelector("span").textContent;

    document.querySelector("#secondBtn .pm_select_img img").src = imageUrl;
    document.querySelector("#secondBtn span").textContent = optionText;
    document.querySelector("#secondBtn").dataset.cur = dataCur;

    document.querySelector("#currency2 .pm_select_child").dataset.cur = dataCur;
    document.querySelector("#currency2 .pm_select_child").textContent = dataCur;

    document.querySelector("#hiddenInput2").value = dataCur;

    document.querySelector("#amount_send2").dataset.cur = dataCur;
    document.querySelector("#amount_send2 ~ .addons").textContent = dataCur;

    const secondDataCur = document.querySelector("#currency1 a").dataset.cur;

    fetch("/calculateExchangeRate", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        firstCryptoCurrencySymbol: dataCur,
        secondCryptoCurrencySymbol: secondDataCur,
      }),
    })
      .then((res) => res.json())
      .then((data) => {
        const exchangeRate = data.rate;
        document.querySelector(".rate_info").textContent = `1 ${dataCur} = ${exchangeRate} ${secondDataCur}`;
      });

    document.querySelector("#secondDrop").style.display = "none";

    
    event.stopPropagation();
  });
});

document.addEventListener("click", function () {
  document.querySelector("#secondDrop").style.display = "none";
});


let isOpen = false;
const secondBtn = document.querySelector("#secondBtn");
const secondDrop = document.querySelector("#secondDrop");

secondBtn.addEventListener("click", function(event) {
  isOpen = !isOpen;

  if (isOpen) {
    secondDrop.style.display = "block";
  } else {
    secondDrop.style.display = "none";
  }

  event.stopPropagation();
});


document.addEventListener("click", function(event) {
  const secondBtn = document.querySelector("#secondBtn");
  const secondDrop = document.querySelector("#secondDrop");
  const isOpen = secondDrop.style.display !== "none";

  if (
    !event.target.closest("#secondBtn") &&
    !event.target.closest("#secondDrop")
  ) {
    if (isOpen) {
      secondDrop.style.display = "none";
    }
  }
});


  })
  • I was checking if I have syntax errors but, I don’t have any
  • I was thinking that I use some advanced functions and I remade my code with bubble but it didn’t helped
  • I was thinking that there is issue with click event so I added ever touch event but it didn’t helped
  • I tried using simulation on Mac, but in them code worked perfectly
  • I used simulation in browser stack and there were my problems

Js isn’t my thing but my old Safari shows an error here.

num = num.replace(/(?<=\..*)\./, "");

Invalid regular expression: invalid group specifier name /(?<=\/)([^#]+)(?=#*)/

Look behind only supported in 16.4 and up.

It may have nothing to do with the problem but worth finding a way around it.

Well that would do it. Javascript’s an everything-is-fatal language; and it falls (mostly) on the line of demarcation of failure for the user.

checking the console is Step 1 of “my javascript doesnt work” debugging.

You lookbehind a couple times in the code, but this:
num = num.replace(/(?<=\..*)\./, "");
Would be replaced by splitting the string on ., joining segments 0 and 1 on ., and then joining the rest on “”. (this is a dangerous operation, unless you know for a fact your website wont be used by a country that uses periods as thousands separators instead of decimilization points.)

I get the impression you’ve copy and pasted this code from somewhere, because your regex doesnt make sense with your code flow. What are you trying to do there?

1 Like

In general:

  • Browser Stack isn’t 100% reliable. To be sure, use the real devices.
  • It’s of little or no use testing in 16.1 through 16.6 because iOS devices update themselves to the latest version by default. There are devices that no longer update themselves, but they are much older. See here: https://iosref.com/ios.