Executing ≪Script≫ Injected by Innerhtml After Ajax Call

Executing script injected by innerHTML after AJAX call

JavaScript inserted as DOM text will not execute. However, you can use the dynamic script pattern to accomplish your goal. The basic idea is to move the script that you want to execute into an external file and create a script tag when you get your Ajax response. You then set the src attribute of your script tag and voila, it loads and executes the external script.

This other StackOverflow post may also be helpful to you: Can scripts be inserted with innerHTML?.

Starting newly-inserted script after AJAX call and stopping removed script after another AJAX call

You can wrap around the setTimeout before eval() the script. When removed the script, you can unregister the tasks.

function mockInternal() {
const setTimeout = window.setTimeout;
const setInterval = window.setInterval;
// window.setImmediate
// window.addEventListener

const setTimeoutHandlers = [];
const setIntervalHandlers = [];

window.setTimeout = function mock_setTimeout(callback, delay) {
const h = setTimeout(callback, delay);
setTimeoutHandlers.push(h);
return h;
}

window.setInterval = function mock_setInterval(callback, delay) {
const h = setInterval(callback, delay);
setIntervalHandlers.push(h);
return h;
}

return function clearMockInternal() {
window.setTimeout = setTimeout;
window.setInterval = setInterval;
setTimeoutHandlers.forEach(h => clearTimeout(h));
setIntervalHandlers.forEach(h => clearInterval(h));
}
}

const clearMockInternal = mockInternal();
eval(`setInterval(() => console.log(new Date()), 1000);`);

setTimeout(() => {
clearMockInternal();
console.log("should not log Date from now");
}, 6000);

Executing script elements inserted with .innerHTML

The OP's script doesn't work in IE 7. With help from SO, here's a script that does:

exec_body_scripts: function(body_el) {
// Finds and executes scripts in a newly added element's body.
// Needed since innerHTML does not run scripts.
//
// Argument body_el is an element in the dom.

function nodeName(elem, name) {
return elem.nodeName && elem.nodeName.toUpperCase() ===
name.toUpperCase();
};

function evalScript(elem) {
var data = (elem.text || elem.textContent || elem.innerHTML || "" ),
head = document.getElementsByTagName("head")[0] ||
document.documentElement,
script = document.createElement("script");

script.type = "text/javascript";
try {
// doesn't work on ie...
script.appendChild(document.createTextNode(data));
} catch(e) {
// IE has funky script nodes
script.text = data;
}

head.insertBefore(script, head.firstChild);
head.removeChild(script);
};

// main section of function
var scripts = [],
script,
children_nodes = body_el.childNodes,
child,
i;

for (i = 0; children_nodes[i]; i++) {
child = children_nodes[i];
if (nodeName(child, "script" ) &&
(!child.type || child.type.toLowerCase() === "text/javascript")) {
scripts.push(child);
}
}

for (i = 0; scripts[i]; i++) {
script = scripts[i];
if (script.parentNode) {script.parentNode.removeChild(script);}
evalScript(scripts[i]);
}
};

Can scripts be inserted with innerHTML?

You have to use eval() to execute any script code that you've inserted as DOM text.

MooTools will do this for you automatically, and I'm sure jQuery would as well (depending on the version. jQuery version 1.6+ uses eval). This saves a lot of hassle of parsing out <script> tags and escaping your content, as well as a bunch of other "gotchas".

Generally if you're going to eval() it yourself, you want to create/send the script code without any HTML markup such as <script>, as these will not eval() properly.

script tag is shown in ajax response and executed?

By default, the <script> tag is meant to have display: none using the User Agent Stylesheet:

Sample Image

I strongly believe if you inspect the element, you will find that in the Computed Styles as I shown above, it will be inheriting display styles somehow. That's the reason.

Find something like:

.divClass * {display: block;}

Coz, no one targets <script> tag! :P



Related Topics



Leave a reply



Submit