Adding JavaScript to every occurrence of a certain HTML element - javascript

I was wondering if there was a way of adding JavaScript in every occurrence of a certain HTML tag, e.g.
<td onmousedown="">
At the moment I just have it in every single one of my td tags in my table, but there must be a cleaner way. Something like adding JavaScript in the way CSS adds formatting.

What your looking for is most likely "event binding." This can be done via your script rather than embedded in the HTML code. There are lots of different ways to accomplish such a task, here is one of them using "td" as in your example.
var items = document.getElementsByTagName("td");
for (var i=0; i<items.length; i++) {
items[i].onmousedown = YourMouseDownFunction;
}

You want jQuery. See http://jQuery.org This can be accomplished using a "selector" (jquery term)

Add an event listener (See also: Quirks Mode on events and on event listeners) to your document looking for mousedown events and filter it on the basis of the originating element.
There is a good answer here on Stackoverflow as well.

Related

Performance issues with appendTo() to create tables dynamically

After debugging my tables seemed to load slow (I assumed it was my server), I found that it was actually the front-end javascript, not the backend PHP. The server is responding in 3-4ms while the javascript handling is taking up to 350ms.
After reading this article, I found the culprit:
Article snippet:
var arr = reallyLongArray;
$.each(arr, function(count, item) {
var newTd = $('<td></td>').html(item).attr('name','pieTD');
var newTr = $('<tr></tr>');
newTr.append(newTd);
$('table').append(newTr);
});
The difference is I am using appendTo() instead of append. This is because my rows have dynamic jquery elements to them - click handlers, .data(), etc.
The solution in the article is basically to concatenate your rows and then run one .append() at the end instead of one for each row.
Is there a similar solution for appendTo()? Perhaps appending to some sort of ghost element and then inserting the whole element at the end? Would this increase performance?
Perhaps appending to some sort of ghost element and then inserting the whole element at the end?
Exactly. You can create your rows and append them to a disconnected tbody element, then append that tbody element to your table. That way there's a single live DOM manipulation, not hundreds of them.

Javascript/Jquery How to catch the use of a CSS class

I am using a Javascript plugin (several lines of code) that from times to times is released a new version.
For this reason I am trying to avoid changing the original source code in order to affect my wishes.
One way that is "half" working for me is to find all the elements that are using a specific CSS class (or group of classes) and them I am removing it (or do something else with them) in order to do what I want.
The part that is not working is the "trigger/event" to process this action. During the execution of this plugin new elements are created and removed and once again I am having "wrong" entries once again.
My question: How can I "catch" all the elements that are "from a moment to the other" using the CSS class XXX? and then execute my own code.
Notes: I was reading the Jquery .on() but I need to specify an event, however the issue is that I do not know the many "places/events" from the original source code are processing this.
Update:
At this point I am "manually" calling my function:
function MyOverrideAction(){
$.each( $( ".sch-gantt-terminal" ), function( key, value ) {
// here I have all my logic.... based on several rules (non relevant to my stackoverflow question)
});
}
I just want that this function is executed every instance when some HTML element is using my target css class.
It is much easier to redefine the CSS class after the original definition. One way to do it is to attach an inline style tag at the bottom of the document which redefines the style. You can use jQuery.append for this. For example see this.
Maybe you search something like this:
https://stackoverflow.com/a/3219767/5035890
If you listen a change in the DOM you can apply all actions that you need. With MutationObserver you can achieve it. Please, consider of the compatibility.
Good luck

Set inline dblclick() listener to element

I have an table, which is contructed in js and then appended to div on the page.
Each line has an inline event listener onclick()
var table = '<table>';
for (var i =0; i< 10; i++) {
table += '<tr onclick="myfunction()"><td></td></tr>'
}
table += '</table>'
$('#myDiv').html(table);
How can I use doulbe click event instead of single click in this construction?
EDIT:
I don't use delegation in this case because I have lot's of arguments (uniq for each row) which also constructed inline on each row. Table refreshes about 50 times a second, so it much easier to once construct inline function with all arguments, then setting noumerous listeners after table was appended to DOM.
I've tried both ways and inline in my case works much faster and is much cleaner to inderstand what should happen onclick.
Just change onclick to ondblclick.
But, using inline js is a bad idea.
Since you are using jquery, you can use event delegations.
Since one of the tags in your question is jQuery, I would resort to use jQuery for this task and would not hook up your event handlers directly in your DOM element.
$('#generatedTable').on('dblclick', 'tr', function() {
alert('tr is clicked');
});
Where generatedTable is the id of your table.
Using on will allow to respond to all double click of the generated trs
FIDDLE
The attribute you're looking for is called ondblclick, however do allow me to point out that it's bad to use event attributes like this, to quote MDN:
This way should be avoided. This makes the markup bigger and less readable. Concerns of content/structure and behavior are not well-separated, making a bug harder to find.
Source: https://developer.mozilla.org/en/docs/Web/API/Event#HTML_attribute

How to use common js function for two divs containig elements of identical ids?

I have common jQuery function and two div tags. Both div tags have different names but both containing elements of identical ids now i want to use this common Jquery function for them both?
I have implemented common function but it's not working for both.
Here's link to my jsfiddle -jsfiddle.net/xS7zF/1/
In my jsfiddle there are two div tags namely example1 and example2 and both tags have elements of identical ids. Function is working fine for first div but not for second.
please help me to sort out this.
Yeah, under the hood, jQuery selection on an ID will use the Document.GetElementById() function implemented by the browser, which is really fast, but (i guess depending on the browser) will stop after it finds the first element, since ID's should be unique and no further searching is needed after the first one is found.
For instance, rename the divs with id="eb" to class="eb" and you can still target specific elements using $("#example1 .eb") and $("#example2 .eb")
UPDATE:
Using your new Fiddle I created this: http://jsfiddle.net/xS7zF/5/
I cleaned up a lot of code and hopefully you can see what I have done. I changed all elements that appear twice from id to class. Now, when you attach an event to an element using $(".classname").click(), it attaches to all the elements. In the handler function where you set HTML and do your show()/hide(), you don't target a specific element using it's ID, but you find it relative to the element that does the event. You can do this using parent(), parentsUntil(), next(), find(), etc. Check jQuery docs for all possibilities. So for instance, the change-handler attaches to all inputs with name=Assets. But instead of doing $("#b1").show(), I go to the parent of the specific input that fires using $(this).parent(). Then I find the element with a class=".b1", which it will only find the one that is next to this specific input and I set the HTML to just that element.
Since there is another input, the same actions happen when THAT input changes, but instead it finds IT's parent, and finds the element with class=".b1" that is next to IT. So both divs with input are contained since they act on elements relative to itself and not across the document.
For extra fun and to show you how flexible this way of programming is, here is a fiddle with the Javascript-code unchanged, but with the exact same question-div copied 8 times. No matter how many times you repeat this, the same code will act on as many divs as you create since everything works relative. http://jsfiddle.net/xS7zF/7/
Hopefully this helps, the rest is up to you!
ID's must be unique, you should not repeat them. You could replace id with class and in the jQuery function do (".ub").each() or manually referencing the object using eq(x). e.g. (".ub").eq(1).
You shouldn't assign same id's to different elements.
You CAN but you SHOULDN'T. Instead of giving the same id, use class
IDs must be unique, try fix this, change to classes.
You can try something like this:
$("div div:first-child")
instead of
$("#eb")
But depends of the rest of your page code. So, change to classes first and use
$(".eb")
when jQuery / javascript find the first ID it would ignore the rest, please read more about it
http://www.w3schools.com/tags/att_global_id.asp

onclick event not firing javascript

EDIT #2:
Made a JS Fiddle... http://jsfiddle.net/N2p6G/ (I hardcoded some stuff that I'm certain works correctly, but the problem is still there)
Original:
So, I have written tens of thousands of lines of javascript, and used code that look like this a hundreds of times and I don't understand what's going on.
blacklistitembutton.onclick = function() {
console.log("clicked.");
}
The above code does not seem to be working... and I can't figure out why
In fact, I use the same method earlier in the same file... and it works fine!
settings.onclick = function() {
settings_popup.toggle();
}
EDIT:
Might it have something to do with the fact that it's being executed in a for loop?
Here is the code...
var blacklistButton = document.createElement('input');
blacklistButton.type = 'button';
blacklistButton.value = "Add Current Site to Blacklist";
blacklistButton.onclick = function() {
console.log('blacklistButton clicked');
}
for (var i=0;i<blacklist.length;i++) {
var blacklistitembutton = document.createElement('div');
blacklistitembutton.type = 'button';
blacklistitembutton.blacklistValue = blacklist[i];
blacklistitembutton.value = "X";
blacklistitembutton.onclick = function() {
console.log("clicked.");
}
}
Then both blacklistButton and all of the blacklistitembuttons are put into the document through element.appendChild (and they all show up successfully!)
The blacklistButton onclick fires just fine, and the blacklistitembutton onclick does not.
document.addEventListener('click', function(){
console.log('clicked');
}, false);
Edit:
Here is a re-write of your code in a fiddle: http://jsfiddle.net/N2p6G/1/
There are a lot of things in your code that worry me. Hopefully from my re-write you can see there are better ways to handle some things.
1) I'm not sure why you are using document.write() at the beginning. That has very little purpose.
2) You are modifying the DOM way too much. Some of the DOM elements you are creating in code are better-served as just being target locations in html. Only the dynamically-created input button elements need to be done in javascript. Remember, modifying the DOM should be done as little as possible.
3) Don't assign events using the onclick, onsubmit, onhover, etc syntax. Events should only be bound to DOM elements using addEventListener. The other benefit of doing it the proper way is that you can assign multiple events of the same type, if need be, to the same element. Also, with some extra state code that I haven't included, you can selectively remove particular events later if you need to.
4) There was a debate several years ago about whether using innerHTML and string templates was faster/better than using DOM creation methods. For a while, the best solution was to use documentFragments and a combination of the two methods. These days, it doesn't really matter anymore since all browsers are pretty damn fast, so for simplicity's sake is good to just go with innerHTML.
This also goes back to the rule of "don't touch the DOM too much". If you look at my code, you can see that I'm assembling the final html simply as an array of elements that gets joined as a single string at the end. Its then rendered to the DOM with a single innerHTML statement. I'm only touching the DOM one time, instead of multiple times.
5) The last bit goes into events again. At the beginning and end of the code you can see where and how I've added the events for the DOM elements. Indeed, the addEventListener at the beginning could be moved to the end to group all the event declarations together, but it doesn't really matter. I left it at the top to help you understand what's going on better.
Hope this helps.
For unlimited event bindings, either use addEventListener or attachEvent method. You cannot add more than one event of the same type using that traditional method.
I don't know if it's a typo in what you put here, but in the loop you are creating a "div" and then assigning it a type of "button". Does that work or is it throwing an error? If it is then that explains why the event handler is not getting the function. Try making it an "input" and see if it now works.
Fixed it!
blacklistitem.innerHTML += blacklist[i];
^ was messing it up, at this point in the code blacklistitem is still a javascript item, not yet appended to its to-be parent element in the document
So I just stuck blacklist[i] into a span tag and appended as a child and now it works fine :)

Categories