jquery affect all instances of a table id - javascript

I have a table that's generated through php. Whenever "bob" is the name of the person who this data belongs to, I generate a tr id to denote that:
<tr id="0bob">...</tr>
<td>...</td>
<tr id="0bob">...</tr>
<tr id="0bob">...</tr>
<tr id="0bob">...</tr>
<tr id="0bob">...</tr>
The data inside each of the tds inside of the trs is different, and the user has to select which of these rows they want, using this checkbox:
print "<input type=\"checkbox\" id=\"check\" data-border=\"$border\" data-z=\"$z\" data-x=\"$x\" data-pn=\"$pn\" value=\"\">";
Then, in my JavaScript, I have the following line which is supposed to dim all of these lines whenever one of the checkboxes in these trs is clicked.
var pn = this.dataset.pn;
var x = this.dataset.x;
//anytime a checkbox with the id 'check' is clicked, (this is every checkbox on the page)
$('input[type="checkbox"][id="check"]').change(function() {
$( "#" + x + PN ).fadeTo( "slow" , 0.7, function() { });
}
The code, in my mind, is accurate - I'm asking for any td with the id of 0bob to be faded to 70%. The issue is that while the code "works," it only fades the first instance of this, then stops, like so:
It always fades the first instance, (red in this example,) regardless of which color the user selects, (blue, pink, or yellow).
I also can't use a tr class because I'm already using the class to change other aspects of the formatting. What am I doing wrong here?

You must use class. Ids must be unique and the browser will get angry if you duplicate them. You can pass multiple classes as follows:
<element id="some-id" class="class1 class2 class3">
From JavaScript classes can be added or removed using classList. JQuery has https://api.jquery.com/addclass/ method.

You should be using data-* attribute since ID is meant to occur once in the document. You can however work around this limitation by using an attribute selector like $('[id=0bob]'). See for example http://jsfiddle.net/Lk7dqbp6/

Your problem is that id attributes must be unique.
And the browser does that: finds the first element with that id and stops there, as it should.
Using repeated ids is invalid HTML and must be avoided like plague.
There are many alternatives for this.
I will only write the HTML structure for this.
Solution 1: a data-* attribute
You already use those, so, just use another one!
<tr data-user="bob"></tr>
These were made with the goal of providing aditional data about an element.
Solution 2: another class
You can have multiple classes per element.
Just make sure they are separated by a space:
<tr class="user-bob another-class more classes"></tr>
This may be harder to use.
Solution 3: another id schema
If you have a primary key on your SQL, you can use it to identify the user:
<tr id="user_bob_0"></tr>
<tr id="user_bob_1"></tr>
<tr id="user_bob_2"></tr>
This may be a bad idea in some situations but it will have all the data ready to use without many troubles.
Outside the scope of the answer, you have another problem:
You have this code:
var pn = this.dataset.pn;
var x = this.dataset.x;
//anytime a checkbox with the id 'check' is clicked, (this is every checkbox on the page)
$('input[type="checkbox"][id="check"]').change(function() {
$( "#" + x + PN ).fadeTo( "slow" , 0.7, function() { });
}
You see the comment?
Same problem: non-unique ids...
For this one, you would be better off using classes.
Instead of
$('input[type="checkbox"][id="check"]')
You would use
$('input.check')
Or
$('.check')
This is the right way to do it.
Also, the performance gain will be HUGE!
Attribute selectors (like [type="checkbox"] and [id="check"]) are one of the slowest selectors!
The only selectors slower than these are the pseudo-element selectors (:before, :after, ::selection, ...).
You can read more here: Is CSS faster when you are specific?
You may be thinking that this won't affect jQuery, but it will.
jQuery uses document.querySelectorAll() which runs a CSS selector in the DOM to select Javascript objects. (When it fails or isn't available, jQuery uses other methods)
Imagine your jQuery looking for over 300 elements for the selector in each of them.
Now imagine a basic table with the classes, where a few elements are connected to an entry.
See the difference?
This is the difference between your code taking 200ms and 30ms (non-measured).

Related

document.getElementById variable change value of class with jquery

I am using this code:
table_div = document.getElementById('exporttbl');
Now I need to use jquery to change all values of th and td with specific class? (but just in variable table_div. And not on the page.)
Example:
I need to put this
<th class="one">AAA<th><td class="one">BBB<td>
into this
<th class="one">RRR<th><td class="one">RRR<td>
In the next step I am using
var table_html = table_div.outerHTML.replace(/ /g, '%20');
so I would like to be able to use it.
Since your using jQuery you can do a .find(".one") on the element with the id exporttbl and change the text like so:
$("#exporttbl").find(".one").text("AAA");
Also note you need to close your <th> and <hr> elements. This would work for a table that looks like so:
<table id="exporttbl">
<th class="one">AAA</th><td class="one">BBB</td>
<th class="one">CCC</th><td class="one">DDD</td>
</table>
Here is an example.
For more information see jQuery documentation - https://api.jquery.com/find/
I think that some of the confusion here is that you are using
table_div = document.getElementById('exporttbl');
which is pure javascript but then you say that you want to use jQuery.
"Now I need to use jquery to change all values of th and td with specific class? (but just in variable table_div. And not on the page.)"
This will return the jQuery object for that table.
$('#exporttbl')
For all of the th, just add a find:
$('#exporttbl').find('th.one')
and for all of the td:
$('#exporttbl').find('td.one')
These will find all of the th/td with class = 'one' inside of the table with id = 'exporttbl'. Then you can do whatever you want with them. It sounds like you want to change the text so the following would work:
$('#exporttbl').find('th.one').text('RRR');
$('#exporttbl').find('td.one').text('RRR');
You could use
$("#exporttbl").find(".one").text("AAA");
as suggested but that will find all items with class = "one" inside of the table. That's fine as long as the th/td you want are the only items with that class. If there is anything else with that class then you'll need to be more specific, as I was.
Also, using a selector like 'th.one' is typically faster than just '.one' which may or may not be an issue depending on the size of the application.

Get value of a Custom Attribute using Javascript

<tr>
<td colspan="2">
<div>
<table id="dataTable">
<tbody>
<tr></tr>
<tr id="row_1"></tr>
<tr id="row_2"></tr>
<tr id="row_3"></tr>
</tbody>
</table>
</div>
</td>
</tr>
How can I get the value of a id in tr using jQuery? I have tried .attr but failed.
var row = jQuery('<tr>').attr("id", "row_" + item.autoID);
row.append(jQuery('<td>').append(jQuery('<input>').attr('type', 'checkbox', 'javascript:deleteChecked(' + item.autoID + ');').attr('id', 'check_id_')));
<input type="button" value="Delete" id="delete_check" disabled onclick="deleteChecked()"/>
I'm trying to get the tr attribute 'row_' + id. I have a checkbox. If you select the checkbox and then hit delete. It should delete the row with the specific id or all the checked rows.
So far I have got:
jQuery(document).on('click', '#check_id_', function(id){
jQuery('#delete_check').attr("disabled",!jQuery('#check_id_').is(":checked"));
//var row = jQuery(this).closest('tbody').find('tr').attr('id');
// console.log(row); //doesn't work
});
function deleteChecked(id){
//grab the checked row ids
}
Any help appreciated.
If I understand your requirement correctly, I would suggest approaching this problem in a slightly different way.
You simple cannot have duplicate IDs in your HTML. ID lookups use a fast lookup dictionary that can only store one element per id value so only the first is ever found.
Avoid using inline event handlers (like onclick="") at all costs in jQuery. It separates the handler registration from the handler response for no benefit and does not allow some of the additional cool event features jQuery provides (e.g. multiple handlers).
Use delegated event handler for your delete operations. This simplifies the HTML and allows for dynamic elements/rows in a far simpler way.
The way your question reads, it seems odd to use checkboxes instead of buttons for the delete. Use buttons instead unless you have good reason not to.
The rows do not need ID's unless those IDs are used for some other purpose. Just delete the row closest to the delete button that is clicked.
Use the $('<htmltag>', {'prop': 'value', 'prop2', 'value2'}) syntax to create new elements with properties. It is shorter and easier to read.
So, putting all that together, you get the following to create a new row:
var row = $('<tr>', {
"id": "row_" + item.autoID,
text: "NEW ROW"
});
row.append($('<td>').append($('<input>', {
'type': 'button',
'value': 'X',
'class': 'deleteme'
})));
$('#dataTable').append(row);
and this simple code to delete the row that has its deleteme 'X' button pressed:
$('#dataTable').on('click', '.deleteme', function(){
$(this).closest('tr').remove();
});
This is a delegated event handler. It delegates responsibility for listening for the click event to a non-changing ancestor element. When a click event bubble up to that element, it then applies the jQuery selector (in this case the class deleteme) and then runs your callback function against any matching elements that caused the event in the first place. The upshot is that the deleteme buttons only need to exist at event time for this to work.
Clean and simple.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/k5rh82cz/
Now if you actual aim is different, you need to explain how you want it to appear too :)
To iterate the rows with checked checkboxes in them and fetch their ID's, something like this should do the trick:
$('#dataTable')
.find('input[type="checkbox"]:checked')
.closest('tr')
.each(function(ind, ele){
var id = $(ele).attr('id');
//do something with the id here
});
See this demo fiddle
HTH,
-Ted

select html object without id

Edit: one missing piece of information - I can't use the class selector because there are more divs with the same class. I already thought of that, but I forgot to mention it. I have no idea why my post got downvoted, but it seems awfully silly considering I provided a lot of information, gave it honest effort, and tried to be verbose with code examples. People on this forum are ridiculous sometimes.
I'm trying to set the id of a div that doesn't have one and there's no way I can give it one upon generation of the page. I've tried using jquery (.each, .contains, .find, .filter, etc.) and I can't seem to get it right. I know a ton of people have asked this question, but none of the answers made sense to me.
I have the ability to set the text (html?) of the div, but nothing else. It ends up looking like this:
<div class="dhxform_note" style="width: 300px;">Remaining letters: 500</div>
I want a handle to the div object so I can show the user how many more letters they can type by updating the text.
Using this:
$("div")
returns a list of all divs on the page. I can see the target div in the list, but I can't get jquery to return a single object.
I know it can also be done with something like this:
var divs = document.getElementsByTagName("div");
for(var i = 0; i < divs.length; i++) {
if( /^Remaining letters/.test(divs[i].innerText) )
divs[i].id = "kudosMsgNote"
}
}
but I was hoping to complete this with a cleaner looking solution involving jquery. I also simply want to know how to do it with jquery, aesthetics not withstanding.
Use a class selector.
var theDivViaTheClass = $(".dhxform_note");
Class Selector (“.class”)
Description: Selects all elements with the given class.
version added: 1.0
jQuery( ".class" )
class: A class to search for. An
element can have multiple classes; only one of them must match.
For class selectors, jQuery uses JavaScript's native
getElementsByClassName() function if the browser supports it.
You seem to be targeting the <div> by its text. Try using the :contains selector:
$("div").filter(':contains("Remaining letters")').first().attr("id", "kudosMsgNote");
The .first() is to make sure you don't set the same id for multiple elements, in case multiple elements contain the text "Remaining letters".
Here's the docs for the :contains selector: http://api.jquery.com/contains-selector/
Be careful, the text you're looking for is case sensitive when using :contains!
Is that div the only one with the class dhxform_note? If so, you can use the class selector:
$('.dhxform_note').html();
With jQuery, you can specify any css selector to get at the div:
$(".dhxform_note").attr("id", "kudosMsgNote");
will get you this element as well.
Selecting on inner text can be a bit dicey, so I might recommend that if you have control over the rendering of that HTML element, you instead render it like this:
<div name="remainingLetters" class="dhxform_note" style="width: 300px">Remaining Letters: 500</div>
And get it like this:
$("[name=remainingLetters]").attr("id", "kudosMsgNote");
However, it's possible that you really need to select this based on the inner text. In that case, you'll need to do the following:
$("div").each(function() {
if ( /^Remaining letters/.test($(this).html()) ) {
$(this).attr("id", "kudosMsgNote");
}
});
If you cannot set id for whatever reason, I will assume you cannot set class either. Maybe you also don't have the exclusive list of classes there could be. If all those assumptions really apply, then you can consider down your path, otherwise please use class selector.
With that said:
$("div").filter(function() {
return /^Remaining letters/.test($(this).text())
}).attr('id', 'id of your choice');
For situations where there are multiple divs with the class dhxform_note and where you do not know the exact location of said div:
$("div.dhxform_note").each(function(){
var text = $(this).text();
if(/^Remaining letters/.test(text)){
$(this).attr("id", "kudosMsgNote");
}
});
EXAMPLE
If, however, you know that the div will always be the 2nd occurrence of dhxform_note then you can do the following:
$("div.dhxform_note").get(1).id = "kudosMsgNote";
EXAMPLE
Or do a contains search:
$("div.dhxform_note:contains('Remaining letters')").first().attr("id", "kudosMsgNote");
EXAMPLE

Javascript to change class of an Element

This is heavily trimmed down source code from a webpage I'm working on right now.
<!--// GRID ENTRY //-->
<li class="entry" id="sjDDulC8wt">
<div class="entry_actions">
<ul class="entry_actions">
<li class='have_it'>
<a href='javascript: haveItem("name", "id", "none")' target='_self' title='Have It' class='have_it'>%</a></li>
</ul>
</div>
</li>
Inside the haveItem() function I'm trying to change the class of the <a> element from 'have_it' to 'have_it selected' to change the appearance of the element. The reason for the id is because I have dozens of these elements on the page. The javascript I'm currently using is:
var targetA = document.getElementbyID(sjDDulC8wt).getElementsbyTitle("Have_it");
targetA.removeClass("have_it").addClass("have_it selected");
When I click the link, the haveItem() function runs, but it doesn't change the class. How can I change my script so that clicking the link will change the class?
I am assuming you are using jQuery since you are using removeClass() and addClass. Otherwise, I would recommend you link to jQuery so that the code below works, or stick with only JavaScript.
var targetA = $('#sjDDulC8wt .have_it');
targetA.addClass('selected');
For future reference, here are some things about your code that you can improve:
getElementById() accepts the id of the element you want to retrieve as a string. Basically, you should wrap your ID in ' or "
Be careful where you are putting spaces and underscores. They are not the same thing. Your list item has the title Have It, while your JavaScript has Have_it.
Capitalization matters. Have_It is not the same thing as Have_it. Be careful with this when you try to get elements by ID.
A class with spaces in it is actually multiple classes. have_it selected actually has both the have_it class and the selected class. Therefore it not necessary to remove have_it and then add have_it selected - you can go straight to adding the selected class.
The function getElementbyTitle() does not currently exist in JavaScript. Also, be careful again about capitalization. Typically, the first letter of every word in a function is capitalized. Thus, if it did exist it would be called getElementByTitle() (notice the B instead of b).
Here:
var anchor = document.querySelector( '#sjDDulC8wt [title="Have It"]' );
if ( anchor ) anchor.classList.add( 'selected' );
Live demo: http://jsfiddle.net/UZfnh/
(Won't work in older browsers.)
This should do the task for you:
<a title="Have It" class="have_it" onclick="this.className+=' selected'">%</a>
However, you should learn about the DOM. None of the methods you used (getElementbyID, getElementsbyTitle, removeClass and addClass) exists.
When you successfully find the element, you can do one of these:
element.classList.add("selected");
It uses a fairly new classList feature available for FF 3.6, IE 10, Chrome 8, Opera 11.50, Safari 5.1 and above. It the the most preferred way to do it once you are sure your clients will have one of those browsers (near future).
element.className += " selected";
className doc. This works and is probably the easiest way. Not so nice as the classList thing, but available for all browsers.
If you can't use jQuery then you can change the classname of an element using className:
var element = document.getElementById("elementId");
element.className = "have_it selected";
Note also this function: getElementsByClassName (HTML5).
As has been pointed out, you have some other issues selecting your element. From your example, it looks like you want to use:
var element = document.getElementById("sjDDulC8wt");
var children = element.getElementsByClassName("have_it");
children[0].className = "have_it selected";
Note that there's no error handling/null checks here. And this handles a simple case of only changing the first child with the specified class, assuming that it exists.
But prefer jQuery if you can use that. From your use of addClass/removeClass it appears that you already expect jQuery.

jQuery: I have a class, I'm iterating it with each. The result is different each turn. How to use the this and access the value?

I'm a beginner and this is my first time encountering problem like this.
I'm iterating a class using the each method provided by jQuery. The page have many class with the same name. So we can expect that it may be 15 iterations.
Each iteration have different value.
$(".book").each(function(n) {
var result = $(this
I have to get the last TD with the value List. So my option is to use
$(".book tbody tr:last")
But I think this thing wouldn't work in the each environment because it won't know which context it is currently processing.
The $(this tbody tr:last) wouldn't work also. How can I devised a selector that will work?
<div class = "book">
<p class = "chapter">
<table>
<tbody>
<tr>
<td>General</td>
<td>
<b>Buck</b>
</td>
</tr>
<tr>
<td>General</td>
<td>List</td>
</tr>
</tbody>
</table>
</p>
</div>
Assuming the HTML you posted there is a single book and there are many others exactly like it, and you want access to the last <tr> in each one of them, this should work:
$('div.book tbody tr:last-child').each(function() {
var value = $(this).find('td').eq(1).text();
});
value would then be "List" with the HTML above, and if you have several <div>s it would iterate as you might expect through the last <tr> of each one of them.
The key here is that we are using last-child instead of simply last. The last documentation says that it will match the last selected element; we don't want that. What we want instead is what last-child describes: Matches all elements that are the last child of their parent. This distinction is important in this particular case as we only want the last child of the particular table we're currently in, we don't want the last result overall.
If you wanted the last <td> in each last <tr>, we could even do this:
$('div.book tbody tr:last-child td:last-child').each(function() {
var value = $(this).text();
});
This selector would select each last child <tr> and select its appropiate last-child <td>. This would be best if you don't care what the value of the first <td> is. If you do then you want to use the first one.
If you're only looping over the tr:last elements, Paolo's answer should work for you. However, if you're need to run more than one query against each div.book, try this instead:
$("div.book").each(function() {
$("tbody tr:last", this).doStuff();
$("p.chapter", this).doOtherStuff();
}
The second argument to the dollar function is the "context node" and defaults to document (i.e. it "searches" the entire DOM).

Categories

Resources