I have a PHP script that generates links - I want to use addEventListener to pick up arguments on these links but what ever I try seems to fail.
It's very old code that used to work with onClick events but I'm updating the code and beleived that addEventListener is the way to go.
I've taken my code back to basics to test the best code solution.
So I have links like so
<a href="#" id="1" data-un-str="miguel" class="nameClick" >Alert Name1</a>
</br>
<a href="#" id="2" data-un-str="sarah" class="nameClick" >Alert Name 2</a>
</br>
and a function
function buildlink(e)
{
var e = window.e || e;
if (e.target.tagName !== 'A')
return;
alert(e.id);
}
and event handler like this.
window.onload=function(){
if (document.addEventListener)
document.addEventListener('click', buildlink, false);
The event handler works, and picks up the clicks on the links.
I just don't understand how to pick up the arg data in id, but most of all I'd like to know how to pick up the args in data-un-str too.
E.g. "miguel" or "sarah"
I presume it is possible as I've seen it done elsewhere, I just couldn't work out how it had been done. I used to code JS a lot more about 10+ years ago, but I'm a bit lost now on DOM stuff and things seem to have changed alot.
For the code above when it tries to alert the id of the link clicked I just get 'undefined' in my alert.
Any advice would be great. Thanks
The event.target (where event is the first parameter passed to the handler) will refer to the clicked element, and you can get the data-un-str attribute by checking the target's .dataset.unStr property:
function buildlink(event) {
const { target } = event;
if (target.tagName !== 'A') {
return;
}
const { id, dataset } = target;
const { unStr } = dataset;
console.log(id, unStr);
}
window.onload = function() {
if (document.addEventListener)
document.addEventListener('click', buildlink, false);
}
Alert Name1
<br>
Alert Name 2
<br>
I am developing a web bot using WinForms WebBrowser control. Everything is working fine except for the second click() call in following code:
function SaveRecordClick() {
try {
var menuButton = $('#s_at_m_4');
menuButton.click(); //<-- This is working
var x = $('#s_at_m_4-menu li')[5];
var saveLink = $(x).find('a')[0];
if (saveLink != null){
saveLink.click(); //<-- This is not working
return "1";
}
}
catch (err) {
alert(err.message);
}
return "0";
}
saveLink is not null. I know this because I placed an alert() call inside the condition.
Updated code with suggested solutions
function SaveRecordClick() {
try {
var menuButton = $('#s_at_m_4');
menuButton.click();
var x = $('#s_at_m_4-menu li').eq(5);
var saveLink = x.find('a').eq(0);
if (saveLink != null) {
alert(saveLink.html());
saveLink.click();
return "1";
}
}
catch (err) {
alert(err.message);
}
return "0";
}
But still the same problem. 'alert()' is working fine but html() is showing inner text instead of HTML of the anchor.
HTML Code
<li data-caption="Save Record [Ctrl+S]" class="sbui-appletmenu-item ui-menu-item" role="presentation">
Save Record [Ctrl+S]
</li>
ID of the anchor tag is dynamically generated.
Also, click() is triggering when the same code is executed from Google Chrome Console. So, could it be the issue with the WebBrowser control?
Update
I think guys its a problem with the webrowser control that inherits Internet Explorer. So now I am shifting to another browser control and testing the code on it. Will let you know if it works there.
You have to wrap your object with jQuery in order to make it work:
var saveLink = $($(x).find('a')[0]);
Try with Below condition's:
trigger('click') instead of click
Change the if condition validation with if(saveLink) .Its validate both null,undefined all false statement
Return with number=> 0 instead of sting =>'0'
anchor tag redirection use with window.location.href and get the href value from anchor try with attr('href')
function SaveRecordClick() {
try {
var menuButton = $('#s_at_m_4');
menuButton.trigger('click');
var x = $('#s_at_m_4-menu li').eq(5);
var saveLink = x.find('a').eq(0);
if (saveLink) {
alert(saveLink.html());
window.location.href=saveLink.attr('href');
return 1;
}
} catch (err) {
alert(err.message);
}
return 0;
}
working example
function SaveRecordClick() {
try {
var menuButton = $('#s_at_m_4');
menuButton.trigger('click');
var x = $('#s_at_m_4-menu li').eq(5);
var saveLink = x.find('a').eq(0);
if (saveLink) {
alert(saveLink.html());
window.location.href=saveLink.attr('href');
return 1;
}
} catch (err) {
alert(err.message);
}
return 0;
}
SaveRecordClick()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="s_at_m_4-menu">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li data-caption="Save Record [Ctrl+S]" class="sbui-appletmenu-item ui-menu-item" role="presentation">
Save Record [Ctrl+S]
</li>
<li></li>
</ul>
saveLink will never be null, since find/eq will always return a jQuery object, regardless of whether the element or elements exist or not.
Instead, try using the length property to check for existence:
if (saveLink.length)
function SaveRecordClick() {
try {
var menuButton = $('#s_at_m_4');
menuButton.click();
var x = $('#s_at_m_4-menu li').eq(5);
var saveLink = x.find('a').eq(0);
if (saveLink != null) {
alert(saveLink.html());
saveLink.live('click');//Use live click
return "1";
}
}
catch (err) {
alert(err.message);
}
return "0";
}
savelink should be dom element for null check
var saveLink = $(x).find('a:first')[0];
or
var saveLink = $(x).find('a').eq(0)[0];
or
var saveLink = $(x).find('a').first()[0];
I did not understand
Do you need to click or add function in the click?
Add function :
jQuery('teste').click(function(){console.log('teste')});
Click:
jQuery('teste').trigger('click');
Teste utilized jQuery.
jQuery(saveLink).click(function(){
console.log('click!');
});
try this
$(document).on('click',$(saveLink),function(event){
///your code
})
Best way to fire an event from JavaScript
$( "#ID" ).trigger( "click" );
I hope it will work for you.
Your updated code with suggested solutions is good, but the .html() method gets the content of an HTML element. Thus, you need to use saveLink.parent().html() to get outer HTML of the anchor.
If there is other elements in the parent container, you could create temporary element to get only hiperlink HTML:
var anchorHTML = $('<div>').append(saveLink.clone()).html();
To click on saveLink using Javascript try to use x.find('a')[0].click() instead of saveLink.click().
I used URL of your profile in href attribute for visual clarity. If you run the snippet below, then user click on the link will be simulated and your profile page will be displayed.
function SaveRecordClick() {
try {
var x = $('#s_at_m_4-menu li').eq(5);
var saveLink = x.find('a').eq(0);
if (saveLink != null) {
var anchorHTML = $('<div>').append(saveLink.clone()).html();
alert(anchorHTML);
saveLink[0].click();
return "1";
}
} catch (err) {
alert(err.message);
}
return "0";
}
console.log(SaveRecordClick());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="s_at_m_4-menu">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li data-caption="Save Record [Ctrl+S]" class="sbui-appletmenu-item ui-menu-item" role="presentation">
Save Record [Ctrl+S]
</li>
<li></li>
</ul>
Remember one thing javascript and javascript frameworks are event driven,so please don't try to implement the functional programming concepts
$(document).ready(function(){
$("#s_at_m_4").click(function(){
// put your code here
});
});
What my theory about this is that the click function was not actually bound to the element. This can be due to the html was not yet in the page when the script or binding of click is executed. Try checking the binded click in saveLink.click();
try to make it in the format
$(body).delegate(saveLink, 'click', function() {
//try alert here to check
});
Thank you everyone for your answers and comments.
After spending a week in researching the third party website, today I finally found the solution to my problem. Actually the problem was not with JavaScript or HTML but the way the website validate the form I am trying to autofill using my bot.
I awarded bounty to the answer whose conversation in comments gave me some hints.
The click on saveLink was not firing because I was programmatically setting a value of a text box using .val() but for some reason the website was not saving values directly set using this function. But when I changed the value using a combo box that loads value for the textbox from the server (Although the value set from server or using val() function are exactly same.), then the click successfully fired after that.
I also used setTimeout() at various places because the code was executing too fast before the value can be set in some form fields.
So in future if someone faces a similar problem then make sure you study the behavior of the page or form you are trying to submit.
In jQuery there is .on() which can be used as:
$(document).on('click', '.foo', function() { /* ... */ });
This listens for click events on all DOM elements with the class .foo.
However, this also listens for any eventual elements added to the DOM later, so it is not equal to:
var elements = document.getElementsByClassName('foo');
for (var element in elements) {
element.addEventListener('click', function() { /* ... */ });
}
How do I do this in plain JavaScript? Am I supposed to use a MutationObserver? If so, then how? If not, then what?
That called event delegation, in the pure javascript you could attach the click event to the parent element then on click check if the clicked element match the target you want to click and perform the action you want ,like the example below :
document.getElementById("parent-item").addEventListener("click", function(e) {
// e.target is the clicked element!
// If it was an item with class 'foo'
if(e.target && e.target.className == "foo") {
console.log("foo "+e.target.innerText+" was clicked!");
}
});
Hope this helps.
document.getElementById("parent-item").innerHTML += "<li class='foo'>Item 3</li>";
document.getElementById("parent-item").addEventListener("click", function(e) {
if(e.target && e.target.className == "foo") {
console.log("foo "+e.target.innerText+" was clicked!");
}
});
<ul id="parent-item">
<li class='foo'>Item 1</li>
<li class='foo'>Item 2</li>
</ul>
I've scoured the web for a straightforward answer and I have not been able to find it. Spent too long trying to figure this out, but I'd appreciate any help or the right direction.
HTML
<ul id="main-li">
<li>item1</li>
<li>item1</li>
<li>item1</li>
</ul>
JavaScript:
document.getElementById('main-li').addEventListener("click", function(e) {
if (e.target && e.target.nodeName === "LI") {
e.target.classList.add("active-class");
}
});
JSFiddle
https://jsfiddle.net/kw0rr3fv/1/
According to David Wash: https://davidwalsh.name/event-delegate
Event delegation allows you to avoid adding event listeners to
specific nodes; instead, the event listener is added to one parent.
That event listener analyzes bubbled events to find a match on child
elements
What is the best way to remove the previous active-class while attaching the class to the selected element?
The only way that exists to remove a class to each child of the UL, is to iterate over them.
If you wish to avoid frameworks like jQuery, you can simply achieve it with a very short code:
document.getElementById('main-li').addEventListener("click", function(e) {
if (e.target && e.target.nodeName === "LI") {
let elements = document.getElementById('main-li').children;
for (let i = 0; i < elements.length; ++i) {
elements[i].classList.remove("active-class");
}
e.target.classList.add("active-class");
}
}, true);
As you see I just added a very short loop to your code that removes the class (it won't block in case the element doesn't have the class).
In the last line of code you may notice I have added a true value: this is the use capture and is used to suggest that UL event must be captured by LI childrens.
I found this to be more challenging than I expected. Is this a common
way to set an active class?
You can use a framework like jQuery which will help you do it faster and in cross-browser fashion.
What is the best way to remove the previous active-class while
attaching it to the selected element?
Check the updated fiddle
document.getElementById('main-li').addEventListener("click", function(e) {
console.log(e);
Array.prototype.slice.call(document.querySelectorAll('#main-li li')).forEach( function( obj ){
obj.classList.remove("active-class");
});
if (e.target && e.target.nodeName === "LI") {
e.target.classList.add("active-class");
}
});
You need to remove the class from all li's first and then go ahead with adding the active-class
I think should be focus only tag "li" and add event listener as my simple code and easy to read below.
var elementsLi = document.querySelectorAll('ul#main-li > li');
for (var i = 0; i < elementsLi.length; i++) {
elementsLi[i].addEventListener('click', function(e) {
// console.log(e.currentTarget); // for see the current element
if (e.currentTarget.classList.contains('active-class')) {
// do something if already have class "active-class"
// remove class or blah blah blah
}
else {
e.currentTarget.classList.add('active-class')
}
});
}
Hope your success :)
Created page which add class "active" on every "li" element click.
<style>
.active { color: red; }
</style>
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
<script>
var arr = document.getElementsByTagName("li");
for(var i=0; i<arr.length; i++){
arr[i].addEventListener("click", function(){
for(var j=0; j<document.getElementsByTagName("li").length; j++){
document.getElementsByTagName("li")[j].className = "";
event.target.className = "";
};
event.target.className = "active"
});
}
</script>
You can also use Jquery for this. which is fast and shorter than your code.
$(document).ready(function(){
$('#main-li').on('click',function(){
$(this).addClass('active-class').siblings().removeClass('active-class');
});
});
Is there any way to get the ID of the element that fires an event?
I'm thinking something like:
$(document).ready(function() {
$("a").click(function() {
var test = caller.id;
alert(test.val());
});
});
<script type="text/javascript" src="starterkit/jquery.js"></script>
<form class="item" id="aaa">
<input class="title"></input>
</form>
<form class="item" id="bbb">
<input class="title"></input>
</form>
Except of course that the var test should contain the id "aaa", if the event is fired from the first form, and "bbb", if the event is fired from the second form.
In jQuery event.target always refers to the element that triggered the event, where event is the parameter passed to the function. http://api.jquery.com/category/events/event-object/
$(document).ready(function() {
$("a").click(function(event) {
alert(event.target.id);
});
});
Note also that this will also work, but that it is not a jQuery object, so if you wish to use a jQuery function on it then you must refer to it as $(this), e.g.:
$(document).ready(function() {
$("a").click(function(event) {
// this.append wouldn't work
$(this).append(" Clicked");
});
});
For reference, try this! It works!
jQuery("classNameofDiv").click(function() {
var contentPanelId = jQuery(this).attr("id");
alert(contentPanelId);
});
Though it is mentioned in other posts, I wanted to spell this out:
$(event.target).id is undefined
$(event.target)[0].id gives the id attribute.
event.target.id also gives the id attribute.
this.id gives the id attribute.
and
$(this).id is undefined.
The differences, of course, is between jQuery objects and DOM objects. "id" is a DOM property so you have to be on the DOM element object to use it.
(It tripped me up, so it probably tripped up someone else)
For all events, not limited to just jQuery you can use
var target = event.target || event.srcElement;
var id = target.id
Where event.target fails it falls back on event.srcElement for IE.
To clarify the above code does not require jQuery but also works with jQuery.
You can use (this) to reference the object that fired the function.
'this' is a DOM element when you are inside of a callback function (in the context of jQuery), for example, being called by the click, each, bind, etc. methods.
Here is where you can learn more: http://remysharp.com/2007/04/12/jquerys-this-demystified/
I generate a table dynamically out a database, receive the data in JSON and put it into a table. Every table row got a unique ID, which is needed for further actions, so, if the DOM is altered you need a different approach:
$("table").delegate("tr", "click", function() {
var id=$(this).attr('id');
alert("ID:"+id);
});
Element which fired event we have in event property
event.currentTarget
We get DOM node object on which was set event handler.
Most nested node which started bubbling process we have in
event.target
Event object is always first attribute of event handler, example:
document.querySelector("someSelector").addEventListener(function(event){
console.log(event.target);
console.log(event.currentTarget);
});
More about event delegation You can read in http://maciejsikora.com/standard-events-vs-event-delegation/
The source element as a jQuery object should be obtained via
var $el = $(event.target);
This gets you the source of the click, rather than the element that the click function was assigned too. Can be useful when the click event is on a parent object
EG.a click event on a table row, and you need the cell that was clicked
$("tr").click(function(event){
var $td = $(event.target);
});
this works with most types of elements:
$('selector').on('click',function(e){
log(e.currentTarget.id);
});
You can try to use:
$('*').live('click', function() {
console.log(this.id);
return false;
});
Use can Use .on event
$("table").on("tr", "click", function() {
var id=$(this).attr('id');
alert("ID:"+id);
});
In the case of delegated event handlers, where you might have something like this:
<ul>
<li data-id="1">
<span>Item 1</span>
</li>
<li data-id="2">
<span>Item 2</span>
</li>
<li data-id="3">
<span>Item 3</span>
</li>
<li data-id="4">
<span>Item 4</span>
</li>
<li data-id="5">
<span>Item 5</span>
</li>
</ul>
and your JS code like so:
$(document).ready(function() {
$('ul').on('click li', function(event) {
var $target = $(event.target),
itemId = $target.data('id');
//do something with itemId
});
});
You'll more than likely find that itemId is undefined, as the content of the LI is wrapped in a <span>, which means the <span> will probably be the event target. You can get around this with a small check, like so:
$(document).ready(function() {
$('ul').on('click li', function(event) {
var $target = $(event.target).is('li') ? $(event.target) : $(event.target).closest('li'),
itemId = $target.data('id');
//do something with itemId
});
});
Or, if you prefer to maximize readability (and also avoid unnecessary repetition of jQuery wrapping calls):
$(document).ready(function() {
$('ul').on('click li', function(event) {
var $target = $(event.target),
itemId;
$target = $target.is('li') ? $target : $target.closest('li');
itemId = $target.data('id');
//do something with itemId
});
});
When using event delegation, the .is() method is invaluable for verifying that your event target (among other things) is actually what you need it to be. Use .closest(selector) to search up the DOM tree, and use .find(selector) (generally coupled with .first(), as in .find(selector).first()) to search down it. You don't need to use .first() when using .closest(), as it only returns the first matching ancestor element, while .find() returns all matching descendants.
This works on a higher z-index than the event parameter mentioned in above answers:
$("#mydiv li").click(function(){
ClickedElement = this.id;
alert(ClickedElement);
});
This way you will always get the id of the (in this example li) element. Also when clicked on a child element of the parent..
$(".classobj").click(function(e){
console.log(e.currentTarget.id);
})
var buttons = document.getElementsByTagName('button');
var buttonsLength = buttons.length;
for (var i = 0; i < buttonsLength; i++){
buttons[i].addEventListener('click', clickResponse, false);
};
function clickResponse(){
// do something based on button selection here...
alert(this.id);
}
Working JSFiddle here.
Just use the this reference
$(this).attr("id")
or
$(this).prop("id")
this.element.attr("id") works fine in IE8.
Pure JS is simpler
aaa.onclick = handler;
bbb.onclick = handler;
function handler() {
var test = this.id;
console.log(test)
}
aaa.onclick = handler;
bbb.onclick = handler;
function handler() {
var test = this.id;
console.log(test)
}
<form class="item" id="aaa">
<input class="title"/>
</form>
<form class="item" id="bbb">
<input class="title"/>
</form>
Both of these work,
jQuery(this).attr("id");
and
alert(this.id);
You can use the function to get the id and the value for the changed item(in my example, I've used a Select tag.
$('select').change(
function() {
var val = this.value;
var id = jQuery(this).attr("id");
console.log("value changed" + String(val)+String(id));
}
);
I'm working with
jQuery Autocomplete
I tried looking for an event as described above, but when the request function fires it doesn't seem to be available. I used this.element.attr("id") to get the element's ID instead, and it seems to work fine.
In case of Angular 7.x you can get the native element and its id or properties.
myClickHandler($event) {
this.selectedElement = <Element>$event.target;
console.log(this.selectedElement.id)
this.selectedElement.classList.remove('some-class');
}
html:
<div class="list-item" (click)="myClickHandler($event)">...</div>
There's plenty of ways to do this and examples already, but if you need take it a further step and need to prevent the enter key on forms, and yet still need it on a multi-line textarea, it gets more complicated. The following will solve the problem.
<script>
$(document).ready(function() {
$(window).keydown(function(event){
if(event.keyCode == 13) {
//There are 2 textarea forms that need the enter key to work.
if((event.target.id=="CommentsForOnAir") || (event.target.id=="CommentsForOnline"))
{
// Prevent the form from triggering, but allowing multi-line to still work.
}
else
{
event.preventDefault();
return false;
}
}
});
});
</script>
<textarea class="form-control" rows="10" cols="50" id="CommentsForOnline" name="CommentsForOnline" type="text" size="60" maxlength="2000"></textarea>
It could probably be simplified more, but you get the concept.
Simply you can use either:
$(this).attr("id");
Or
$(event.target).attr("id");
But $(this).attr("id") will return the ID of the element to which the Event Listener is attached to.
Whereas when we use $(event.target).attr("id") this will return the ID of the element that was clicked.
For example in a <div> if we have a <p> element then if we click on 'div' $(event.target).attr("id") will return the ID of <div>, if we click on 'p' then $(event.target).attr("id") will return ID of <p>.
So use it as per your need.