0

I am trying to use setInterval or setTimeout but the primary element getting removed.

Code without Javascript delay : Working fine

const selectAllWithAttributeAdStatus = document.querySelectorAll("[data-ad-status]");
selectAllWithAttributeAdStatus.forEach(ad => {
  if ((ad.getAttribute("data-ad-status")) === "unfilled") {
     document.write("<h1>Unfilled</h1>");
  } else {
      document.write("<h1>Filled</h1>");
  };
})
<div class="adsbygoogle" style="display:inline-block;width:336px;height:280px" data-ad-client="ca-pub-1714167228247329" data-ad-slot="8611448539" data-adsbygoogle-status="done" data-ad-status="unfilled"> <img src="https://place-hold.it/338x280" /></div>

<div class="adsbygoogle" style="display:inline-block;width:336px;height:280px" data-ad-client="ca-pub-1714167228247329" data-ad-slot="8611448539" data-adsbygoogle-status="done" data-ad-status="somethingelse"><img src="https://place-hold.it/338x280" /></div>

Code with Javascript delay : Working fine but the element getting removed

const selecteAd = () => {
const selectAllWithAttributeAdStatus = document.querySelectorAll("[data-ad-status]");
selectAllWithAttributeAdStatus.forEach(ad => {
  if ((ad.getAttribute("data-ad-status")) === "unfilled") {
     document.write("<h1>Unfilled</h1>");
  } else {
      document.write("<h1>Filled</h1>");
  };
})
}
    const myTimeout = setTimeout(selecteAd, 2000);
  //const myTimeout = setInterval(selecteAd, 2000);
<div class="adsbygoogle" style="display:inline-block;width:336px;height:280px" data-ad-client="ca-pub-1714167228247329" data-ad-slot="8611448539" data-adsbygoogle-status="done" data-ad-status="unfilled"> <img src="https://place-hold.it/338x280" /></div>

<div class="adsbygoogle" style="display:inline-block;width:336px;height:280px" data-ad-client="ca-pub-1714167228247329" data-ad-slot="8611448539" data-adsbygoogle-status="done" data-ad-status="somethingelse"><img src="https://place-hold.it/338x280" /></div>

I want to delay JavaScript without getting element removed.

Sted
  • 111
  • 6
  • 1
    For your second example you put the JavaScript in the CSS box. Please fix it. – Jesse Sep 17 '22 at 07:40
  • 1
    @Jesse fixed. Thanks for informing – Sted Sep 17 '22 at 07:43
  • The code shows it's working as expected. Which element is being removed in your mean? – Huy Pham Sep 17 '22 at 07:55
  • @HuyPham in example 2 code. The image getting removed and it getting replaced with the text from javascript. – Sted Sep 17 '22 at 07:58
  • 1
    Does this answer your question? [Why is document.write considered a "bad practice"?](https://stackoverflow.com/questions/802854/why-is-document-write-considered-a-bad-practice) – gre_gor Sep 17 '22 at 08:04
  • @HuyPham The class of the image tags in the example is `adsbygoogle` so they're likely getting blocked by an ad blocker. I had the same problem initially. I had to disable it. – Jesse Sep 17 '22 at 08:12

3 Answers3

3

Do not use document.write as it can have very strange behaviour and it can affect the state of HTML parser, so your DOM elements might be removed.

https://developer.mozilla.org/en-US/docs/Web/API/Document/write

Instead, you can make 2 paragraphs on your page for example, hide them both, and show them after 2 seconds.

One more thing, do not use inline css, always keep css outsourced in the seperate file.

I adapted your code snippet below. Keep in mind this can be written much smarter and cleaner with toggling classes in css instead of changing css directly with javascript (which you should avoid when possible), but for the sake of you question, I did it this way.

const selecteAd = () => {
const selectAllWithAttributeAdStatus = document.querySelectorAll("[data-ad-status]");
selectAllWithAttributeAdStatus.forEach(ad => {
  if ((ad.getAttribute("data-ad-status")) === "unfilled") {
     document.querySelector(".unfilledText").style.display = 'block';
  } else {
      document.querySelector(".filledText").style.display = 'block';
  };
})
}
    const myTimeout = setTimeout(selecteAd, 2000);
  //const myTimeout = setInterval(selecteAd, 2000);
<div class="adsbygoogle" style="display:inline-block;width:336px;height:280px" data-ad-client="ca-pub-1714167228247329" data-ad-slot="8611448539" data-adsbygoogle-status="done" data-ad-status="unfilled"> <img src="https://place-hold.it/338x280" /></div>

<div class="adsbygoogle" style="display:inline-block;width:336px;height:280px" data-ad-client="ca-pub-1714167228247329" data-ad-slot="8611448539" data-adsbygoogle-status="done" data-ad-status="somethingelse"><img src="https://place-hold.it/338x280" /></div>

<p class='unfilledText' style="display: none;">Unfilled</p>
<p class='filledText' style="display: none;">Filled</p>
Just Alex
  • 457
  • 4
  • 6
  • I got it. How to make like small square `Red box` for `unfilled` and `green box` for `filled` instead of texts paragraph. – Sted Sep 17 '22 at 07:59
  • You can just replace the paragraphs I made with divs, and just give them some border and custom styling to match the colors you want. :) – Just Alex Sep 17 '22 at 08:01
2

The problem here is with the document.write method. To summarize the documentation, document.write has different behavior when the document is loading versus when it's been loaded. In your first example, the script is running while the document is in the "loading" state. This writes the given text to the DOM, keeping what is already written to it. However, once the page has been fully loaded like in your second example, this method will replace everything in the DOM with whatever you give it. Also according to the aforementioned documentation, it's a very bad idea to use this method period.

A better idea would be to use document.append instead. This will always add the element(s) to the DOM without replacing anything. Unfortunately you can't just pass the HTML in as a string, but it's still pretty simple to use.

const selecteAd = () => {
  const selectAllWithAttributeAdStatus = document.querySelectorAll("[data-ad-status]");
  selectAllWithAttributeAdStatus.forEach(ad => {
    var elem = document.createElement('h1')
    if ((ad.getAttribute("data-ad-status")) === "unfilled") {
      elem.innerText = 'Unfilled'
    } else {
      elem.innerText = 'Filled'
    }
    document.body.append(elem);
  })
}
const myTimeout = setTimeout(selecteAd, 2000);
<div class="adsbygoogle" style="display:inline-block;width:336px;height:280px" data-ad-client="ca-pub-1714167228247329" data-ad-slot="8611448539" data-adsbygoogle-status="done" data-ad-status="unfilled"> <img src="https://place-hold.it/338x280" /></div>

<div class="adsbygoogle" style="display:inline-block;width:336px;height:280px" data-ad-client="ca-pub-1714167228247329" data-ad-slot="8611448539" data-adsbygoogle-status="done" data-ad-status="somethingelse"><img src="https://place-hold.it/338x280" /></div>
Jesse
  • 1,386
  • 3
  • 9
  • 23
-1

document.write overwrites complete document content if called after loading document. Use div element and add text content to it

Tyler2P
  • 2,324
  • 26
  • 22
  • 31