3

My goal is to load javascript in the <head> only if a certain element exists in the <body>.

However, I have a problem: I am loading a Web Component, which is just a <script> hosted elsewhere and is pulled in as:

<script src="https://someurl.com/some-web-component.min.js"></script>

This web component file is huge, so I don't want to pull it in unless it is inserted into body by our Content Management System (CMS).

The constraints I am working under are:

• The <head> is shared between pages, so I need conditional logic

• I have no control over the <body> inserted by the CMS, which will potentially contain the <my-web-component> tag

• I NEED the script to load the web component, so I can't use jQuery's $(document).ready, at least I think I can't - an error will be thrown because the browser won't know the element exists

This plunker partially shows my problem, minus all the web component complexity:

https://plnkr.co/edit/GGif2RNHX1iLAvSk1nUw?utm_source=next&utm_medium=banner&utm_campaign=next&p=preview

Any way around this?

VSO
  • 11,546
  • 25
  • 99
  • 187
  • What does that script do? Does any other script depends on it, or it depends on anything? Is this a library? Any inline script in body uses it? – Munim Munna Apr 23 '18 at 21:25
  • The script defines the custom element, which is html/javascript which pulls in the form.io library and data from an API and then displays it to the user. – VSO Apr 24 '18 at 00:49

2 Answers2

7

You can use DOMContentLoaded event.

The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.

In this case you can look for the Component and add the script with something like the following

document.addEventListener("DOMContentLoaded", function(event) {
  if(document.querySelector('Component')){
    var script = document.createElement('script');
    script.src = 'https://someurl.com/some-web-component.min.js';
    document.head.appendChild(script)
  }
});

Probably a better approach though would be to add the script in the head with async attribute and later remove it if the component is not found. Something like this

<script async src = "https://someurl.com/some-web-component.min.js"> </script> 
<script >
  document.addEventListener("DOMContentLoaded", function(event) {
    if (document.querySelector('Component') == null) {
      var script = document.querySelector('script[src="https://someurl.com/some-web-component.min.js"]')
      document.head.removeChild(script)
    }
  }); 
</script>

More about DOM lifecycle events
More about async script loading

Moti Korets
  • 3,738
  • 2
  • 26
  • 35
  • This does seem to work, thank you. Testing in detail now. I still don't understand this: "The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading." - what does 'parsed' mean here? – VSO Apr 24 '18 at 14:25
  • 1
    @VSO, it means all the elements have been rendered in short. Which means your `querySelector` will be able to find the tag you are interested in – Tarun Lalwani Apr 24 '18 at 15:22
0

I am using $(document).ready and inside this method checking if element exists or not. It is working completely fine for me. Below is code:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>jQuery Test Element Exists or Not</title>
  <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
  <script type="text/javascript">
    $(document).ready(function() {
      var elem = document.querySelector('h1');
      var isElemPresent = !!elem;
      console.log('Is the element present: ', isElemPresent);
    });
  </script>
</head>

<body>
  <h1>Hello Plunker!</h1>

  <script>
    var elem = document.querySelector('h1');
    var isElemPresent = !!elem;
    console.log('Oh NOW it works...: ', isElemPresent);
  </script>
</body>

</html>

I am not sure where you are facing issue while using jQuery. There might be some other issue. Above approach is good enough to load script after checking if element is present.

Plunker link: https://run.plnkr.co/preview/cjgczwlzt000knneldv5d52ea/

Vikasdeep Singh
  • 20,983
  • 15
  • 78
  • 104
  • The example is limited. I mentioned in the question that I need to load a custom html element / tag. Document ready will fail, because the script won't be available to define the tag. – VSO Apr 24 '18 at 01:52