Explain Codes LogoExplain Codes Logo

Executing <script> injected by innerHTML after AJAX call

javascript
ajax
script-execution
dynamic-content
Alex KataevbyAlex Kataev·Dec 12, 2024
TLDR

Here's a rapid-fire, tidy solution to execute scripts from AJAX innerHTML: we create and append script nodes manually. Yes, you gotta get your hands dirty.

function executeInlineScripts(containerId, html) { var container = document.getElementById(containerId); container.innerHTML = html; // Throwing those AJAX goodies into the DOM var scripts = Array.from(container.getElementsByTagName('script')); scripts.forEach((oldScript) => { var newScript = document.createElement('script'); newScript.text = oldScript.text; // The ole switcheroo oldScript.parentNode.replaceChild(newScript, oldScript); }); }

Congrats. You've dumped the HTML to your container and gave life to the scripts right off the AJAX response.

Understanding innerHTML's limitations

So, here's the kick. When you use innerHTML to add HTML into the DOM, any inline <script> tags you'd expect to run, well, just won't. Because of security measures in place, browsers will flat out refuse to execute <script> tags inserted via innerHTML. To overcome this obstacle, refer back to our Fast answer section.

Handling external scripts

Still with me? Great. Now, let's level up and handle external scripts or those <script src="yourJavascriptFile.js"> lying around. The approach stays the same, only now we will set the src attribute and append the script to the document:

function loadExternalScript(src) { var script = document.createElement('script'); script.src = src; script.async = false; // Keeps the speed demons at bay and preserves execution order document.body.appendChild(script); }

Good work, Agent. Keep this in mind: setting async=false ensures that even if you load multiple scripts, they'll stop elbowing each other and follow the queue.

Using jQuery to lighten your load

Got the power of jQuery in your arsenal? It's showtime! jQuery's .ajax() method, and helpers like .load(), can do the heavy lifting of loading and executing scripts for you. Here's how:

$('#containerId').load('url-to-fetch.html', function(response, status, xhr) { if (status == 'error') { // Handle error, maybe go Hulk smash? console.error(xhr.status + ': ' + xhr.statusText); } });

jQuery, like magic, parses the script tags and runs them. A word of caution: with great power...

Security considerations

Yes, you guessed it right: it's time for the villain of our story, eval(). Although it can execute scripts from an AJAX call, using eval() is akin to hanging out with a ticking time-bomb due to the associated security risks. All it takes is one wrong script and boom!

Remember, Uncle Ben's words: always consider the source of your scripts and sanitize eval.

Practical Variations

Three different but commonly faced scenarios to broaden your arsenal:

1. Inline script laced AJAX response: This echo's the Fast answer where we dynamically create and replace script nodes for immediate execution.

2. Deferred execution: When you don't feel like dancing to the tunes just yet:

function deferScriptExecution(scriptText) { setTimeout(function() { var deferredScript = document.createElement('script'); deferredScript.text = scriptText; document.body.appendChild(deferredScript); }, 5000); // Let's snooze for 5 seconds before the next act. }

3. The safe place: For the times when you want to let others run the show but from a safe distance:

function executeScriptInSandbox(html) { var iframe = document.createElement('iframe'); iframe.style.display = 'none'; document.body.appendChild(iframe); iframe.contentWindow.document.open(); iframe.contentWindow.document.write(html); // In you go, run wild... within limits. iframe.contentWindow.document.close(); }

Handling dynamic content post-AJAX

We've now jumped over to a future where dynamic content is the rage. To get your scripts to conform, you've got to remember:

  • Dynamic script loading is just like first time page load.
  • Scripts appended must not break existing functionality.
  • Hulk Smash the errors with robust error handling.