I want to get a DOM element by clicking on it. The script looks like this:
document.onclick = function(e) {
e.target.style.backgroundColor = "green";
e.target.style.color = "white";
alert(e.target.tagName);
for (let attr of e.target.attributes) {
alert( `${attr.name} = ${attr.value}` );
};
};
The script works fine for the HTML elements, but it does not work for the elements generated by script. Actually nothing happens while I am clicking on the dropdown and selecting a value from it (no alert appears). Google Dev tools displays the element and some of its attributes including its id as far as I can see is autogenerated. I even can use its autogenerated id for doing automation job with this element. But is their any way to catch the element with my script?
Unfortunately I am not able to provide the original web page as it is internal company product, but I have found something similar that can be checked and by the way in this case it looks like the reason of not working script is different that those I have with auto generated elements in my original application. As you can see for the general Google page the script does not work for any element located on the page, but for the Google URL shown on the second image the same script works fine for all elements located on the page. And the shovn element itself is differnt (represented by div on the first image and by img on the second)
The reason it does not work for dynamically generated elements is simply because event listener is bound upfront on pre-existing elements.
You should have a function that re-binds the event every time a new element is added to the DOM. The function should be either targeted for the single element, or whole page.
window.onElementAdded = (element) = >{
element.onclick = ...
}
This function needs to be invoked every time an element is added to the DOM from your code.
Related
My issue is just the opposite from the previous posting labled:
How do I prevent a parent's onclick event from firing when a child anchor is clicked?
I have a 'Parent' page which will dynamically load a DIV's innerHTML with an 'external' HTML document. That works fine.
I also have a Search function which looks into the text of all of the 'external' HTML documents to see if it finds one (or more) which contain the SearchText.
If it finds one (or more) it then creates a new HTML page: SearchResults.htm.
Within that SearchResults.htm it lists the 'found' documents as links - each with its own onclick() method and then displays that new SearchResults HTML document in the same DIV's innerHTML.
The display itself works fine.
'Child' Page Link Example:
<a href = "#" onclick = "DisplayDocument('1-Disposition-4-Generate
Single Letter.htm')" href = "#">Disposition-Generate Single Letter</a>
However the js function DisplayDocument() is resident in the 'Parent' page.
My problem is that when I click on the 'Child' page link it seems as though it begins looking for the js function within the 'Child' page where there are NO js functions at all and it never seems to attempt to find it in the 'Parent' page.
How can I:
1) Prevent the onclick from looking within the 'Child' page?
2) Ensure that a 'Parent's onclick event will be fired when a child anchor is clicked?
Thank you
Well once again it looks like I will have to answer my own question.
When I was
dynamically loading a DIV's innerHTML with an 'external' HTML document.
I was putting the SearchResults HTML document code into an HTML Object and then putting the Object into the innerHTML.
That worked just fine when I was loading the 'external' HTML documents, but it was not working for the SearchResults document which had links in it - each with their own onClick().
Well I found out that instead of creating a SearchResults document, I just needed to load the 'raw' HTML code (representing the SearchResults) into the innerHTML without it being within an HTML Object,
Then I was able to successfully execute the js code on the SearchResults links.
Hopefully this might help someone else facing the same problem.
i'm generating some anchor tags dynamically and use them to redirect to other page by using their id's. I've done it through inline scripts many times but unfortunately chrome extensions doesn't supports inline scripts.
var profileUid is generated dynamically and i make them as id's to anchor tag each time<a id='+profileUid+'>'link</a> so each link have different id's, when i click these links that should call following function
$(function() {
$('a').click(function() {
console.log(this.id);
alert(this.id);
chrome.tabs.create({url:'https://plus.google.com/'+this.id+'/posts'});
});
to redirect to new pages, it works fine with static elements(anchor tags) but not for dynamically generated elements. this is driving me insane, let me get some help to get out of here.
When you execute $('a').click(handler);, it first finds all matching elements, and then binds to their events. So, it only works for elements already existing at the time of invocation.
So, when you later add an <a> element to the DOM, you need to take care of its events separately.
function handler() {/* ... */}
// Bind to static elements
$(function() {
$('a').click(handler);
});
// Create an elemet
var element = $('<a>');
element.attr('id', profileUid);
element.text("Whatever");
element.click(handler);
element.appendTo(parent);
I'm new to Javascript, and trying to design a form with elements that are created and deleted by clicks on links without submitting a form.
The script depends on getting the unique id of a clicked button (css and <a> link), and calculating the id of the row containing the link, and then deleting the entire <tr> element.
For this, I'm trying to get the id of a clicked link. The link and the elements it is embedded in, is itself generated by javascript on clicking another button.
I tried the following:
var btnDel=document.createElement("a");
btnDel.id="NS_D"+count;
btnDel.className="btn btn-danger";
btnDel.addEventListener('click', function()
{
alert(e.id);
}, false);
var btnText=document.createElement("span");
btnText.className="btn-label";
btnText.innerHTML="Delete";
btnDel.appendChild(btnText);
td.appendChild(btnDel);
Though the button is generated, I'm not getting an alert as expected. Where can I have gone wrong?
You need use this rather than e:
alert(this.id);
in your event handler.
Demo here.
(You also need to get used to running your code with the Console visible - that would have told you that the reason you weren't seeing your alert is that e doesn't exist.)
In the event handler, this refers to the element, so you can do:
alert(this.id);
To get to the <tr> you can go up the tree using parentNode:
console.log(this.parentNode.parentNode);
MDN docs
I have a situation where I have nested divs. I have a parent div (that has an onclick() event) and a few divs inside that are being dynamically populated. I'm given to understand that through 'bubbling,' the onclick() event should propagate up through the DOM, triggering the onclick() event in all parents. All of the research I have done has shown a bunch of people who are trying to PREVENT this, whereas I can't get it to work. The only way I can get the onclick() to work, is to click near the edges of the div, presumably where the child divs don't exist, and I'm clicking directly on the parent.
I've included the applicable code below. There can be as many as 9 of these, so-called "widgets" on the page, but I have removed all code except that referencing the first "widget".
Update: When I try to pull everything out of the JavaScript function, and put it directly in to the HTML code, it works as I would expect. However, doing this would force me to drop desired functionality, so I'm going to try to avoid that workaround.
There is a new fiddle below that shows essentially what I'm going for, even though the events are not calling the JS functions as I would expect.
Update #2: I have created a fiddle (#5 below) that mimics the response I'm seeing in the code. When using the fiddle, you'll notice that no alert is given when clicking in the center of the div, but when you click near the outer boundaries of the div, you finally get a response.
PROBLEM SOLVED:
Per Racheet's answer below, this problem has been solved. I have created a final Fiddle with the fully-functioning code for reference:
http://jsfiddle.net/v3MGX/8/
JAVASCRIPT:
function initializeWidgets(){
var widget1 = "Professional";
widget1 =
"<div class='outer'><div class='middle'>
<div class='inner'><h1>" + widget1 + "</h1></div></div></div>";
document.getElementById("widget1").innerHTML = widget1;
}
function hoverWidgets(widgetID){
var w = new Array();
w[0] = "Work Experience, Educational History, and Resume Download";
w[widgetID-1] = "<div class='outer'><div class='middle'>
<div class='inner'><h2>" + w[widgetID-1] + "</h2></div></div></div>";
document.getElementById("widget"+widgetID).innerHTML = w[widgetID-1];
}
APPLICABLE HTML:
<div class="widget" id="widget1" onclick="alert(1);" onmouseover="hoverWidgets('1')"
onmouseout="initializeWidgets()"></div>
CURRENT FIDDLE:
http://jsfiddle.net/v3MGX/5/
FINAL FIDDLE:
http://jsfiddle.net/v3MGX/8/
I've played with your example a fair bit and worked out the problem. Here is my solution:
http://jsfiddle.net/v3MGX/7/
window.initializeWidgets = (function() {
/*THIS SECTION IS YOUR WIDGET CONSTRUCTOR*/
//Set up your constants for this widget
var widget1 = "Professional";
var widget2 = "Work Experience, Educational History, and Resume Download";
//first you grab your old element
var widgetSmallElement = document.getElementById("widget1");
//then you make your new elements
var outer = document.createElement("div");
outer.setAttribute('class','middleSmall');
var inner = document.createElement("div");
inner.setAttribute('class','innerSmall');
var heading = document.createElement("h1");
heading.innerHTML = widget1;
var subHeading = document.createElement("h2");
subHeading.innerHTML = widget2;
//now you chain the above and then add them to the document
inner.appendChild(heading);
outer.appendChild(inner);
widgetSmallElement.appendChild(outer);
//This is your new, simplified hoverWidgets handler
window.hoverWidgets = function (widgetID) {
inner.replaceChild(subHeading,inner.firstChild);
};
/*THIS SECTION IS THE RETURN VALUE FROM YOUR CONSTRUCTOR*/
return function() {
//this is the function actually given to the onClick and onMouseout handler as the initializeWidgets funciton.
inner.replaceChild(heading,inner.firstChild);
};
})();
The problem you're having is due to the way you are creating your inner divs. When you create a html element in javascript by writing html as a string into a DOM node's innerHTML property the old node that was there is deleted, and a new one is created to replace it.
When that old node is deleted the event handlers that were attached to it are also deleted, so when your mouseovers are running, they're actually deleting and re-creating the various inner divs, and their existing event handlers. Because of this, the onclick handler you assigned in the html doesn't exist for those inner nodes.
It's usually a bad idea to add html to a document by directly writing into the innerHTML property.
I've rewritten the solution so that it creates the nodes natively in JavaScript, and then re-written the initializeWidgets and hoverWidgets functions to simply swap between the <h1> and <h2> nodes inside the inner div.
I've put the whole thing inside a closure to stop it polluting the global scope with anything but the initializeWidgets and hoverWidgets functions. This implementation will only work if it's registered as a handler for the onLoad function, since the constructor part of it will need to run and create those two functions before the html tries to attach them as event handlers.
If you find this solution to complex for your needs, you should still be able to create your own solution by using javascript to create and manipulate the divs and h1/h2 tags natively rather than doing it by writing directly into the innerHTML property.
Here's a guide on how to do that
If your on-click isn't somehow referencing the DIV specifically, could always add the onclick to the other nested divs.... otherwise, you need to post more of your html.
I use PHP and javascript via prototype.
i have a threaded comments page that on open
by default via javascript call to a PHP file data returned via JSON, only parent comments are retrieved in the db. (in short only parent comments are fetched from db and displayed)
then the parents are loaded and formatted to be shown on the page with a link to get and display its child comments, link example:
<span id="moreparent8351" onclick="insertChildDiv('parent8351')">1 Replies and more</span>
the span link above calls the javascript function "insertChildDiv()" that basically gets comments whose parent_id=parent8351, also using a PHP file that returns data via JSON to the javascript that dynamically inserts this child comments nested under its parent comment.
then the span link above using prototype transforms into:
<span id="moreparent8351" onclick="$('childparent8351').toggle()">1 Replies and more</span>
now here is the problem, this inserted content inside this div with id=childparent8351 wont respond to the hide/show toggle ONLY in IE v6,v7 and v8. other browsers work fine.
it looks like IE cannot apply the hide/show toggle to a dynamically inserted content.
I tried hardcoding the inserted content that i see in fogbugz to the page and testing it again on IE, guess what? toggle works!
I dont want to fetch all the comments both parent and child and then hide the child comments, that is a waste of resources on something that we are not sure is important or to be read by the users.
Is there a workaround? if there is none, then i hope this post will help others on their design stage for something similar.
Element.toggle() should work fine with dynamically generated content. Your problem most likely lies within the method you use to generate this content.
You stated:
then the span link above using
prototype transforms into:
<span id="moreparent8351" onclick="$('childparent8351').toggle()">1 Replies and more</span>
How exactly are you changing the onclick attribute of the span element?
First of all, I definately would not recommend changing an onclick event on-the-fly. It is probably better to use one function that checks the current state of what you are trying to do and executes the appropriate code.
Be sure not to "transform" your span element, including the onclick attribute using innerHTML. Chances are the DOM is still trying to reference a function that you have just removed. If updating your onclick attribute at all, do it like this:
var element = $('moreparent8351');
// this automatically removes previous onclick handlers set in this manner
element.onclick = function() { // do stuff };
...or, when you want to it the Prototype way:
var element = $('moreparent8351');
// OPTIONAL: remove previous handler, if set
element.stopObserving('click', my_cool_function());
// attach new handler
element.observe('click', function() { // do stuff });