0

I'm creating a small thing for practice with JavaScript and I get an error which I can't understand why is happening.

The browser (chrome, firefox) gives me the following error message in the console: "Uncaught TypeError: Cannot read property 'querySelectorAll' of null at script.js:12", but when I try the code in JSFiddle everything is working as expected. JavaScript is allowed in the browser, so normally it should work fine.

According to HTML DOM querySelectorAll() Method normally, the browser should display correctly the code.

Browser error in console

The other question is: How can I avoid typing so many if's? If I want to use a JavaScript switch, how should I write it?

//find the url of the page
// const findUrl = window.location.href;
const findUrl = "https://www.example.com/en/";
console.log(findUrl);

if (findUrl.match(/en/)) {
  console.log("The match has been found!");
  //select the paragraph inside the div with id #texts
  let findP = document.getElementById("texts").querySelectorAll("p");
  //define a variable with the new text
  let newtxtEN = "A very long text in English to replace the lorem ipsum";
  //replace the lorem ipsum text
  findP[0].innerText = newtxtEN;
}

if(findUrl.match(/fr/)) {
   console.log("The match has been found!");
  //select the paragraph inside the div with id #texts
  let findP = document.getElementById("texts").querySelectorAll("p");
  //define a variable with the new text
  let newtxtFR = "Je ne parle pas français";
  //replace the lorem ipsum text
  findP[0].innerText = newtxtFR;
}

if(findUrl.match(/de/)) {
   console.log("The match has been found!");
  //select the paragraph inside the div with id #texts
  let findP = document.getElementById("texts").querySelectorAll("p");
  //define a variable with the new text
  let newtxtDE = "Ich bin kein Deutscher";
  //replace the lorem ipsum text
  findP[0].innerText = newtxtDE;
}
#texts {
  border: 1px solid black;
  margin: 5px;
  padding: 5px;
  color: blue;
}
p {
  padding: 10px;
  font-family: Arial, Helvetica, sans-serif;
}
<div id="texts">
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit.
    Ut,consequuntur.
  </p>
</div>
JustMe
  • 307
  • 1
  • 8
  • I can't say why you are getting that error, but I can say that your approach is extremely out of date and will hurt the performance of your page. If all you are interested in is the first `p` in a given element use `.querySelector("p")` instead of `getElementsByTagName("p")` and then later indexing the result with `[0]`. [**Don't use live node lists.**](https://stackoverflow.com/questions/54952088/how-to-modify-style-to-html-elements-styled-externally-with-css-using-js/54952474#54952474) – Scott Marcus Sep 09 '20 at 21:28
  • Please keep questions to a single topic. Re: `if` statements; don't you just want a simple object with translations, regardless of how that's generated? (Manually, library, ...) – Dave Newton Sep 09 '20 at 21:29
  • @ScottMarcus I'm quite a beginner but thanks for the tip! – JustMe Sep 09 '20 at 21:34
  • The accepted answer gets part of the way there, but: since this is a known string, using a regex isn't necessary--you just get the first portion of the URL after the host (e.g., `en`, `de`, etc. That can be used to look it up directly in an object, e.g., `translations[language]`, rather than iterating over an array and doing a regex match. – Dave Newton Sep 09 '20 at 22:11

2 Answers2

1

You can avoid all the repetitive code using an array of objects.

//find the url of the page
// const findUrl = window.location.href;
const findUrl = "https://www.example.com/en/";
console.log(findUrl);

const langs = [{
    pattern: /en/,
    text: "A very long text in English to replace the lorem ipsum"
  },
  {
    pattern: /fr/,
    text: "Je ne parle pas français"
  },
  {
    pattern: /de/,
    text: "Ich bin kein Deutscher"
  }
];

let found = false;
for (let i = 0; i < langs.length; i++) {
  if (findUrl.match(langs[i].pattern)) {
    console.log("The match has been found!");
    let findP = document.getElementById("texts").querySelectorAll("p");
    findP[0].innerText = langs[i].text;
    found = true;
    break;
  }
}
if (!found) {
  console.log("The match was not found");
}
#texts {
  border: 1px solid black;
  margin: 5px;
  padding: 5px;
  color: blue;
}

p {
  padding: 10px;
  font-family: Arial, Helvetica, sans-serif;
}
<div id="texts">
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut,consequuntur.
  </p>
</div>

As for why you're getting that error, see Why does jQuery or a DOM method such as getElementById not find the element?

Barmar
  • 596,455
  • 48
  • 393
  • 495
  • I am deeply grateful for the elegant solution provided and the link for explaining why the error was appearing in the browser. I moved the script down near the `

    ` and error disappeared. THANK YOU!

    – JustMe Sep 09 '20 at 21:52
0

We can't reproduce your issue here and the code works as you intend, so we probably won't be able to give you a concise answer.

However, your code is very outdated and because you are using .getElementsByTagName() you are using a "live" node list, which can hurt performance of your page and really shouldn't be used. Additionally, since you are only interested in the first found element within the node list, collecting all the matches only to throw all but the first one away also is a waste.

Lastly, you've got a bunch of duplicated code that need not be there. See the code below for a more proper solution.

//find the url of the page
// const findUrl = window.location.href;
const findUrl = "https://www.example.com/en/";
console.log(findUrl);

let matchFound = "not ";

// You only need to do this once, not in each of your if statements
// since the result isn't going to change. And use .querySelector(),
// not .getElementsByTagName().
let findP = document.getElementById("texts").querySelector("p");

// Instead of 3 separate if statements, use else if so that once you
// have a true condition, the other statemens won't be processed.
if (findUrl.match(/en/)) {
  findP.textContent = "A very long text in English to replace the lorem ipsum";
  matchFound = "";
} else if(findUrl.match(/fr/)) {
  findP.textContent = "Je ne parle pas français";
  matchFound = "";
} else if(findUrl.match(/de/)) {
  findP.textContent = "Ich bi)n kein Deutscher";
  matchFound = "";
}

console.log("The match was " + matchFound + "found."); 
#texts {
  border: 1px solid black;
  margin: 5px;
  padding: 5px;
  color: blue;
}
p {
  padding: 10px;
  font-family: Arial, Helvetica, sans-serif;
}
<div id="texts">
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit.
    Ut,consequuntur.
  </p>
</div>
Scott Marcus
  • 57,085
  • 6
  • 34
  • 54