2

I'm trying to implement dynatrace in my react app, and this works fine if I just add the required script tag manually in my index.html header.

However I want to make use of dynatraces api which returns the whole script tag element (so I can use for different environments).

How can I add the script tag to my index.html after calling the api? Creating a script element from code won't work because the response of the api call is a script tag itself (which is returned as string).

I tried creating a div element and adding the script as innerHtml, then append it to the document. But scripts don't get executed in innerHtml text.

const wrapperDiv = document.createElement("div");
wrapperDiv.innerHTML = "<script>alert('simple test')</script>";
document.head.appendChild(wrapperDiv.firstElementChild);

Can this be done?

I found a roundabout way of doing this:

const wrapperDiv = document.createElement("div");
const scriptElement = document.createElement("script");
wrapperDiv.innerHTML = "<script src=... type=...></script>";
for(let i = 0; i < wrapperDiv.firstElementChild.attributes.length; i++){
    const attr = wrapperDiv.firstElementChild.attributes[i];
    scriptElement.setAttribute(attr.name, attr.value);
}
document.head.appendChild(scriptElement);

in this example of the script i'm only using a src but this can be done with the value as well. If there is any better way for doing this pls let me know

Kupi
  • 903
  • 1
  • 10
  • 16

2 Answers2

1

This can be achieved without use of eval() :

const source = "alert('simple test')";
const wrapperScript = document.createElement("script");
wrapperScript.src = URL.createObjectURL(new Blob([source], { type: 'text/javascript' }));
document.head.appendChild(wrapperScript);

In the code above you basically create Blob, containing your script, in order to create Object URL (representation of File or Blob object in browser memory). This solution is based on idea that dynamically added <script> is evaluated by browser in case it has src property.

Update:

Since endpoint returns you <script> tag with some useful attributes, the best solution would be to clone attributes (including src) - your current approach is pretty good.

akrn
  • 748
  • 5
  • 7
  • In you example the source only contains only the javascript code of the script tag, does this work with a complete script tag? Because that is how the api call returns it. – Kupi Feb 05 '18 at 13:54
  • @Kupi So you actually get only `` without body? – akrn Feb 05 '18 at 14:06
  • There are different endpoint to choose from, you can get a script with a src attribute or a script with a body, but there will always be some attributes on those scripts that are important. Now I just choose the one that gives me a script without body, only attributes. Then copy them into the created element – Kupi Feb 05 '18 at 14:15
  • thanks for the help, i'll let the question stay open for now in case someone has something better. I'll close it after a bit – Kupi Feb 05 '18 at 15:19
0

I found a roundabout way of doing this:

const wrapperDiv = document.createElement("div");

const scriptElement = document.createElement("script");
wrapperDiv.innerHTML = "<script src=... type=...></script>";
for(let i = 0; i < wrapperDiv.firstElementChild.attributes.length; i++){
    const attr = wrapperDiv.firstElementChild.attributes[i];
    scriptElement.setAttribute(attr.name, attr.value);
}
document.head.appendChild(scriptElement);

in this example of the script i'm only using a src but this can be done with the value as well

Kupi
  • 903
  • 1
  • 10
  • 16