1

On my page, I block scripts and wanna load them after I pressed a button.

this already works wonderful with as example google recaptcha.

when i run myFunction the script is loaded.

the same goes for jquery and popper.js

But I think to use the bootstrap dropdown I need no reinitialize it. Is there a way to this for the hole dom? I can't find anything about it.

Here is the code:

    <script>
        function blockScript(origin) {
            const scripts = Array.from(document.getElementsByTagName("SCRIPT"));
            if (scripts.length > 0) {
                scripts.forEach((script) => {
                    if (script.src.includes(origin)) {
                        script.setAttribute('data-src', script.src);
                        script.removeAttribute("src");  
                    }
                })
            }
        }
    </script>
    <script>

      var json = [
{
    "name" : "Google Recaptcha", 
    "url"   : "code.jquery.com",
    "desc" : "Recaptcha",
    "rights": ""
},
{
    "name" : "Google Recaptcha", 
    "url"   : "www.google.com",
    "desc" : "Recaptcha",
    "rights": ""
},
{
    "name" : "Google Recaptcha", 
    "url"   : "cdnjs.cloudflare.com",
    "desc" : "Recaptcha",
    "rights": ""
}];
      if(!localStorage.getItem('cc-marketing') == 1){
            const observer = new MutationObserver((mutationsList, observer) => {
                for(let mutation of mutationsList) {
                    const addedNodes = Array.from(mutation.addedNodes);
                    if (addedNodes && addedNodes.some(n => n.nodeName === 'SCRIPT')) {
                      for(var i = 0; i < json.length; i++) {
        var obj = json[i];
        blockScript(obj.url);
    }
                    }
                }
            });

            observer.observe(document, { childList: true, subtree: true });
              }
    </script>

<script>
function myFunction() {
 // window.localStorage.setItem('cc-marketing', 1);
var elements = document.querySelectorAll("[data-src]");

Object.keys(elements).forEach(function(key) {
  console.log(elements[key].getAttribute('data-src'));
  elements[key].setAttribute('src', elements[key].getAttribute('data-src'));
  elements[key].removeAttribute("data-src");  
});
}
</script>

<script  integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous" src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script  integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous" src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://www.google.com/recaptcha/api.js?render=MYKEY"></script>
Mukyuu
  • 4,695
  • 7
  • 32
  • 51
lvollmer
  • 1,329
  • 1
  • 8
  • 24
  • can you explain what you are trying to achieve? for example, why do you need to load them later? – Rafael Herscovici Nov 17 '19 at 02:24
  • @Dementic It's for a school project. I wanna block the scripts i set in the json. i do this by rewrite the src attribute to a data-src attribute. When i click on the button the the data-src getting removed and the src is added again. Now the scripts are loaded, but my bootstrap dropdown isn't working. The whole thing is to end up being a kind of dynamic cookie banner that can also block scripts that are e.g. loaded by wordpress plugins etc. – lvollmer Nov 17 '19 at 02:29
  • Please see this question for an example how you can load a script dynamically: https://stackoverflow.com/questions/14521108/dynamically-load-js-inside-js – Rafael Herscovici Nov 17 '19 at 02:31
  • @Dementic thank you, but this still doesen't solve my problem cause i load the scripts after the dom is already finished – lvollmer Nov 17 '19 at 02:37

1 Answers1

1

The problem is not with refreshing the dom. When you load the script, it will add whatever listeners to your dom which is already loaded so it works fine.

What is wrong is that your bootstrap.min.js is loaded before your popper.min.js because you blocked popper but not bootstrap. According to the bootstrap documentation, bootstrap.min.js needs to be loaded last. (dependencies). Just add bootstrap.min.js to your json to block it as well, and it will work.

   <script>
        function blockScript(origin) {
            const scripts = Array.from(document.getElementsByTagName("SCRIPT"));
            if (scripts.length > 0) {
                scripts.forEach((script) => {
                    if (script.src.includes(origin)) {
                        script.setAttribute('data-src', script.src);
                        script.removeAttribute("src");  
                    }
                })
            }
        }
    </script>
    <script>

      var json = [
{
    "name" : "Google Recaptcha", 
    "url"   : "code.jquery.com",
    "desc" : "Recaptcha",
    "rights": ""
},
{
    "name" : "Google Recaptcha", 
    "url"   : "www.google.com",
    "desc" : "Recaptcha",
    "rights": ""
},
{
    "name" : "Google Recaptcha", 
    "url"   : "cdnjs.cloudflare.com",
    "desc" : "Recaptcha",
    "rights": ""
},
{
    "name" : "Bootstrap", 
    "url"   : "stackpath.bootstrapcdn.com",
    "desc" : "Bootstrap",
    "rights": ""
}];
      if(!localStorage.getItem('cc-marketing') == 1){
            const observer = new MutationObserver((mutationsList, observer) => {
                for(let mutation of mutationsList) {
                    const addedNodes = Array.from(mutation.addedNodes);
                    if (addedNodes && addedNodes.some(n => n.nodeName === 'SCRIPT')) {
                      for(var i = 0; i < json.length; i++) {
        var obj = json[i];
        blockScript(obj.url);
    }
                    }
                }
            });

            observer.observe(document, { childList: true, subtree: true });
              }
    </script>

<script>
function myFunction() {
 // window.localStorage.setItem('cc-marketing', 1);
var elements = document.querySelectorAll("[data-src]");

Object.keys(elements).forEach(function(key) {
  console.log(elements[key].getAttribute('data-src'));
  elements[key].setAttribute('src', elements[key].getAttribute('data-src'));
  elements[key].removeAttribute("data-src");  
});
}
</script>

<script  integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous" src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script  integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous" src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://www.google.com/recaptcha/api.js?render=MYKEY"></script>
peekolo
  • 272
  • 2
  • 7
  • awesome! Thank you so much. – lvollmer Nov 17 '19 at 03:32
  • 1
    There is a caveat though. Sometimes there is no guarantee that the scripts are loaded in order this way. I think there are reported issues (although not officially documented) in some browsers like Chrome. One way to ensure order is to destroy the script nodes and recreate them when you need. Then you can use the `onload` callback to ensure that the order is established. – peekolo Nov 17 '19 at 03:38
  • 1
    https://stackoverflow.com/questions/8996852/load-and-execute-order-of-scripts/8996894#8996894 – peekolo Nov 17 '19 at 03:39
  • 1
    I confirm it. I just tested the script on Chrome. If you click quickly, you will fail about 1 out of 5 tries. The `popper.min.js` will actually load later. I guess depending on a lot of factors! – peekolo Nov 17 '19 at 03:42
  • 1
    yeah tested it as well i will create a new script in order of the json! :) – lvollmer Nov 17 '19 at 03:44