Attach dynamically loaded javascript event handler to dynamically loaded HTML [duplicate] - javascript

This question already has answers here:
Executing <script> injected by innerHTML after AJAX call
(12 answers)
Closed 5 years ago.
I have a site which loads content through AJAX. I need to attach onclick handler to some div which was dynamically loaded. It works fine if my event handler is already defined in my main javascript file (whether I attach it through markup via attribute onclick="myFunc" on by more pedantic addEventListener ).
However, I would like this event handler to be defined in a <script> tag of the dynamically loaded content. Then it doesn't work, whether <script>function myHandler(){}</script> is before or after the <div onclick='myHandler();'>.
I tried to attach it at the end of the XmlHttpRequest:
contentDiv.innerHTML = xhr.responseText;
var handlerName = getItFrom(xhr.responseText);
var clickFn = window[handlerName];
loadedDiv.addEventListener('click', clickFn);
Doesn't work neither: handlerName is correct, but clickFn remains undefined...
I prefer a pure js answer but jquery is ok if I can easily translate it.

It's doable if you're willing to use jQuery, here I assign an event handler from a script tag of a html string. A couple of things, the parameter you pass into .html has to be a jQuery object of your string, and you'll need to replace </script> with <\/script> within the string (could use .replace).
$('#content').html($("<span>before</span><script>$('#testo').click(function () { alert('infunc');});<\/script><span>after</span>"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='content'></div>
<button id='testo'>Click</button>

If getItFrom(xhr.responseText); returns a function defined in the global scope try to add quotes like this:
var clickFn = window['handlerName'];
Because console says:
var luck = function(){}; window[luck];
> undefined
var luck = function(){}; window['luck'];
> function luck()

Related

Inserting Javascript code into HTML via Javascript [duplicate]

This question already has answers here:
Dynamically adding script element to a div does not execute the script
(2 answers)
Closed 5 years ago.
I am trying to insert Javascript code into HTML via Javascript.
Inserting this code into HTML does not work, the code is not executed :
<script>
function callAlert(){
alert('test');
}
</script>
This code is executed :
<img src="xxx" onerror="alert('test')">
This does not call the function so the alert is not executed :
<img src="xxx" onerror="callAlert();">
Why onerror alert is executed and onerror calling function not?
You can no longer insert a <script> tag using el.innerHTML. This is a security issue that has been added fairly recently.
Go to this page:
https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML
and scroll down to the Security considerations section.
It mentions that you can not add a <script> tag but it is not fool proof. Things like you describe can still cause script to run:
const name = "<img src='x' onerror='alert(1)'>";
el.innerHTML = name; // shows the alert
If you really need to add new JavaScript from existing JavaScript you will need to do something like the following:
var s = document.createElement('script');
s.textContent = 'function callAlert(){alert(\'test\');}';
document.head.appendChild(s);
callAlert();
Try putting the script into the head of the page, it could be that the function is executed before it's defiend.
If this isn't working please tell what error your console returns.

Difference between 'onclick's within javascript vs. html [duplicate]

This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 8 years ago.
<script type="text/javascript">
function translateIt() {
Microsoft.Translator.Widget.Translate("en", "es");
}
</script>
<button onclick="translateIt()">Translate</button>
<script type="text/javascript">
document.getElementById("btn").onclick = function () {
Microsoft.Translator.Widget.Translate("en", "es");
}
</script>
<button id="btn">Translate3</button>
This html block contains two buttons that should perform the exact same function. As such, the top button works but the bottom button doesn't. What is the difference between the 'onclick' implementation within html vs. within javascript?
The difference isn't with the click handler, the difference is the order of execution. In the first example you define something (the function) then reference it (in the HTML). In the second example you reference something (the HTML element) and then define it.
So in the second example the call to getElementById("btn") doesn't find anything, because at the time it executes that element doesn't exist yet.
HTML and JavaScript execute in the order in which they exist on the page as the page is being rendered. From the top of the document to the bottom.
If your second script example appears before the button, the getElementById will find no element.
By moving the script tag to after the element, it will work like normal.
<button id="btn">Translate3</button>
<script type="text/javascript">
document.getElementById("btn").onclick = function () {
Microsoft.Translator.Widget.Translate("en", "es");
}
</script>

Does "innerHTML" depend on eventhandlers? [duplicate]

This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 9 years ago.
first one:
function change(){
document.getElementById("clr").style.backgroundColor="red";
document.getElementById("test1").innerHTML="hwllo world";
}
second one:
document.getElementById("test1").innerHTML="hwllo world";
The first one is working fine. But the second one is not working when the file is loaded.
Javascript and HTML rendering are executed in the sequence they are found in the file. So if you're executing a piece of JS before an HTML element is rendered then the JS code wouldn't work.
This will fail:
<script>
document.getElementById("test1").innerHTML="hwllo world";
</script>
<div id="test1"></div>
This will work as expected:
<div id="test1"></div>
<script>
document.getElementById("test1").innerHTML="hwllo world";
</script>
Alternatively you can use the various onload and dom ready events to make sure that your script executes after all the HTML have been rendered:
<script>
window.onload = function(){
document.getElementById("test1").innerHTML="hwllo world";
}
</script>
<div id="test1"></div>
And what error is in console? May be you are trying to set innerHTML of not existing node? If you want to manipulate with divs, you have to do it after the page is loaded, so typically call this as body event onLoad:
<script>
function init() {
document.getElementById("test1").innerHTML="hello world";
}
</script>
<body onload="init();">
<div id="test1"></div>
...
As James Allardice said in his comment, the code is probably executed before the DOM is ready. Your code could then fail as the element might not be there. This is a known problem, but there is also a known solution. The most used solution is probably to use jQuery, which has an easy way to allow a function to only be executed after the document is ready. To use this method, first you need to include jQuery as a script reference and then modify your code as follows:
$(document).ready(function() {
document.getElementById("clr").style.backgroundColor="red";
document.getElementById("test1").innerHTML="hwllo world";
});
Now if you are using jQuery anyways, you can also rewrite your code to use jQuery selectors and make it a bit more compact:
$(document).ready(function() {
$("#clr").css("backgroundColor", "red");
$("#test1").html("hwllo world");
});
Both pieces of code are functionally equivalent.

Div is not created before javascript run

I have a question about javascript/html.
First, I have this:
var post = document.body.getElementsByClassName("post");
var x=post[i].getElementsByClassName("MyDiv")[0].innerHTML;
I get from the debugger that x is not defined, it doesn't exists.
This javascript function runs onload of the body. I am sure that I gave the right classnames in my javascript, so it should find my div.
So, I read somewhere that sometimes javascript does not find an element because it is not yet there, it is not yet created in the browser ( whatever that means).
Is it possible that my function can't find the div with that classname because of this reason?
Is there a solution?
So, I read somewhere that sometimes javascript does not find an element because it is not yet there, it is not yet created in the browser ( whatever that means).
Browsers create the DOM progressively as they get the markup. When a script element is encountered, all processing of the markup stops (except where defer and async have an effect) while the script is run. If the script attempts to access an element that hasn't been created yet (probably because its markup hasn't been processed yet) then it won't be found.
This javascript function runs onload of the body.
If that means you are using something like:
<body onload="someFn()"...>
or perhaps
<script>
window.onload = function() {
someFn();
...
}
</script>
then when the function is called, all DOM nodes are available. Some, like images, may not be fully loaded, but their elements have been created.
If it means you have the script in the body and aren't using the load event, you should move the script to the bottom of the page (e.g. just before the closing body tag) and see if that fixes the issue.
Okay, instead of calling functions with
body onload, use jQuery's ready() function, or, if you don't want to use jQuery, you can use pure javascript, but this is up to you:
// jQuery
$(document).ready(function() {
var post = document.getElementsByClassName("post"),
x = post[i].getElementsByClassName("MyDiv")[0].innerHTML;
});
// JavaScript
window.onload = function initialization() {
var post = document.getElementsByClassName("post"),
x = post[i].getElementsByClassName("MyDiv")[0].innerHTML;
}
A few side notes, I don't know what the use of innerHTML
is, and also if you're doing a for loop with i then definitely
post that code, that's kind of important.
After some discussion, my answer seems to have worked for you, but you can also place your script at the end of your body tag as #RobG has suggested.

onload not getting called for object element [duplicate]

This question already has answers here:
Load event not fired on Safari when reloading page
(2 answers)
Closed 4 years ago.
I have an object element in my html with a blank data attribute which is then set later upon a ajax response. Now I want to get the event when the DOM for the object content document is ready.
If I use onload on the object element it works in firefox and Opera but it does not work in Webkit based browser.
How can I have the onload event trigger in all the browsers
The html looks like this
<object id="myobj" data="" />
the javascript that works in FF but not in WebKit is
e = doc.getElementById("myobj")
e.onload = function(){}
e.data="http://myurl"
In theory onload is strictly for the body element. If certain browsers allow it for other elements more power to them but it's not required.
Also: is your semicolon key broken?
I've tried the code with Safari 5.0.2 and it worked. You can verify by alerting after assigning the new value. When you view the source it isn't there but the newly assigned value can be accessed from any method.
e.data="http://myurl";
alert(e.data);
ie:
function doThis() {
var data = document.getElementById("myobj");
alert('retrieved from a method ' + data.data);
}
In jQuery, to call something on page load, all you have to do is use:
$(document).ready(function()
{
//your code here to populate your object's data attributes
});
This will work in all browsers.

Categories