checkbox selected addclass to a child - javascript

I'm trying to add a new class "ok" to an <a href> when it's checked.
I'm using bootstrap, jquery and bootstrap table from http://wenzhixin.net.cn/p/bootstrap-table.
the jsfiddle : http://jsfiddle.net/x0wegnhs/1/
Can you help me to release that ?
<tr>
<td class="bs-checkbox"><input data-index="0" name="btSelectItem" type="checkbox"></td>
<td style="text-align: left; ">file 1</td>
</tr>

Use closest to find the nearest tr, then find to find the anchor link. Use toggleClass with a boolean value to turn on/off that ok class based on the checked state.
http://jsfiddle.net/TrueBlueAussie/x0wegnhs/6/
$(':checkbox').change(function () {
$(this).closest('tr').find('td a').toggleClass('ok', $(this).is(':checked'));
});
Side notes on jQuery vs direct access:
As #Karl-André Gagnon points out this can, apparently, be shortened a little by going RAW JS for the checked property like this:
$(':checkbox').change(function () {
$(this).closest('tr').find('td a').toggleClass('ok', this.checked));
});
However, I would normally have had a variable for the $(this) element and my selector constants, so:
$this.is(checkedSelector)
becomes the following when minified:
t.is(c)
which is then actually shorter than:
this.checked
because this and the checked property cannot be minified :)

You do not need to find closest tr as somebody mentioned. You must do for each loop with jquery. When you do that, you are positioned at input tag (your "this" let me say it like that is referenced to input field when you loop). So you need first go out your input tag because you can't use next() because there is no other tags except parent tags after that input tag in that hierarchy position. That's why you need to use first parent() (to get outside where you are), so you could be positioned in td parent tag. Then you use next() to go to next td tag, and then you use find("a") to find your a tag and add to it class "ok".
$(document).ready(function(){
$("input[name=btSelectItem]").each(function () {
if (this.checked){
$(this).parent().next().find("a").addClass("ok");
}
});
});
You asked for the solution of this:
I'm trying to add a new class "ok" to an when it's checked.
You can find it here - with piece of code I described, class will be added on any a tag next to it's checkbox. You can inspect the source and see for yourself that class ok is added to checked checkbox.
http://jsfiddle.net/upquya6p/2/

Related

Unable to toggle class via javascript

I've got a set of tr tags in a table and some of them have a class of collapsible-parent. When I click on an element in the row it calls this javascript method:
function toggle() {
$(this).closest("tr").nextUntil(".collapsible-parent").toggleClass("open");
}
But none of the rows inbetween are having the open class added. So the HTML is something like so:
<tr class="collapsible-parent">
<td>
<span onclick="toggle()"><i class="fa fa-chevron-circle-right"></i></span>
</td>
...
</tr>
<tr>....</tr>
<tr>....</tr>
<tr class="collapsible-parent">....</tr>
so if I trigger that method on the first tr shown, I'd want the second and third tr to have the open class added to them.
What have I done wrong?
I just now realised that you have fixed your problem, though I will keep the answer for future reference as it is a tricky bug.
The onclick event listener is not captured correctly by jQuery. I have managed to run this successfully by adding an id on the span element and then adding an .on("click") listener using jQuery.
Add an id on the span element:
<span id="btn"><i class="fa fa-chevron-circle-right"></i></span>
and add a listener using jQuery:
$("#btn").on("click", function() {
$(this).closest("tr").nextUntil(".collapsible-parent").toggleClass("open");
});

jquery affect all instances of a table id

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).

How to set the highlight of a table row with jquery from a javascript function call from an onclick in the table row?

I'd like to add a nice light yellow highlight to the table row that the user is interacting with. They click on an 'A' link with an 'onclick' function call that uses jquery to do stuff (not important). The onclick is in an 'A' tag and in a table cell 'TD'.
Here is the table cell:
<td>
<a href="javascript:void(0);"
onclick="deleteSchedule('Ajax/Admin_Delete_Schedule.cfm?SID=12345');"
title="Delete User"><img src="images/Delete_x16_.png" border="0"></a>
</td>
How do I get the reference for the table row and then set the background color?
Do I need to give each table row a unique ID?
Since the answers are so detailed and excelelnt, I'll add this:
I'd like to do this within my function but I'm not sure how to do it with 'this'.
Thanks!! and OMG! stackoverflow is the greatest!!!
I could not get the below closest or parent examples to work but I did get this to work:
$(".rowClick").on("click", function() {
$(this).closest("tr").css('backgroundColor', '#FFFF99');
});
and of course I added the class 'rowClick' to the 'A' tag. The problem now is when the user clicks on another row the result is two rows highlighted. Any suggestions to remove the highlight from the previously selected row. (I'm guessing to change the background color on all the table rows then set the one clicked on.) - Thanks Again!
I recommend giving the anchors a class name, ie "rowClick", and use JavaScript to toggle a class to the TR.
<tr>
<td>
...
<a class="rowClick">
...
</td>
</tr>
A CSS definition:
.bgYellow{ background-color: #FFFF00; }
And here's an example using jQuery:
$(".rowClick").on("click", function() {
$(this).closest("tr").addClass("bgYellow");
});
Depending on what you're doing, you can modify the function to instead toggleClass or other misc. options.
First of all, do not use an inline onclick method for this. Set up a proper jQuery event delegation function. So do something like this:
$(function(){
$('td a').click(function(e){
// 'e' refers to the event target here
var row = $(e.target).closest('tr');
// Insert whatever color value where yellow is
$(row).css('backgroundColor', 'yellow')
})
})
Even better would be to create a css class like
.tr-highlighted { background: yellow; transition: 200ms linear; }
Then add/remove the class with the class toggle function
$(function(){
$('td a').click(function(e){
// 'e' refers to the event target here
var row = $(e.target).parent();
// Insert whatever color value where yellow is
$(row).toggleClass('tr-highlighted')
})
})
If you must use an inline onclick declaration, the above should still apply, however you will need to access this within your function to refer to the event target, instead of e being passed as an argument.
Alternatively, you can do this with no JS at all if you only want it highlighted while the person is hovering over the table row
tr:hover { background: yellow; transition: 200ms linear; }
To accomplish this, you can use the jQuery .closest() function.
$("td").click(function(e){
$(e.target).closest("tr").css("background-color","yellow");
$(e.target).closest("tr").siblings().css("background-color","white");
});
This code in plain English would be something like:
For each table cell that is clicked:
Find the nearest row and change its background color to yellow.
Find all of the other rows in the table and change their background colors to white.
http://jsfiddle.net/ogzankse/2/
EDIT: I changed the code to better reflect your situation. Instead of attaching the click event listener to the row itself, I added anchor tags inside of each row and attached the listener to that. I added a class to the anchor tag so that anchors outside of the table are ignored. The code now searches for the <td> that the clicked <a> tag is inside of, and then finds the nearest row and applies the CSS. The code is now:
$("a.intable").click(function(e){
$(e.target).parent().closest("tr").css("background-color","yellow");
$(e.target).parent().closest("tr").siblings().css("background-color","white");
});
http://jsfiddle.net/ogzankse/3/

Use jQuery to find a <tr> that is after a row with specific atribute in it

I don't know if the Title of this post makes sense, but here's a sample of what I'm working with:
<tbody>
<tr class="classRow" bgcolor="#EFE5D3" style="font-weight: bold;">
<td width="35px"><a class="classEditLink" name="33" href="#">Edit</a></td>
<td width="20px"><input type="checkbox" class="chkSelectToDelete" name="deleteClasses[]" value="33" /></td>
<td>CLASS1234</td>
<td>Class description</td>
</tr>
<tr class="classDocsRow noDocs">
<td colspan="4">
<strong>No documents are currently associated with this class.</strong>
</td>
</tr>
</tbody>
I need to remove the second row by finding it using the previous row's first <td>'s <a>'s name attribute. The psuedo code would be something like
$('.classRow a[name="' + classID + '"]').parent().parent().next().remove()
I don't know if that's proper jQuery syntax (as is, it doesn't work), but hopefully you get the point: the "starting point" of the selector is the name attribute of the <a> tag and I need to remove the following row. The <a> tag's name attribute is the only unique attribute in a given <tbody> on the page (not inlcuding the third and fourth <td>s in that row, but you get the point).
What is a properly formatted/syntaxed jQuery selector to do that?
If I understand your question correctly:
$('tr:has(a[name="33"]) + tr').remove();
Links to the corresponding JQuery documentation:
:has() Selector
Attribute Equals Selector
Next Adjacent Selector
If I've understood your question correctly, then you want something like this:
$(".classRow a[name=" + className + "]").closest("tr").next().remove();
See an example fiddle here.
you can try
$('.classRow a[name="' + classID + '"]').parents("tr").next().remove();
if it doesn't work please alert the classID to check if it's ok
Your sample works, just make sure that classID is set: working fiddle
This doesn't necessarily answer your question directly, but just a word of advice... If you have a table listing classes in each row, then it makes more sense to put everything about each individual class within the same row. So, the documents container really belongs within the class row that the documents are associated with.
The benefits to that are:
Semantic meaning and relationship association
Much easier way to reference parent/sibling/child elements
Then all you'd have to do is something like this:
$('.classRow a[name="' + classID + '"]').parent('classRow').find('.classDocs').remove();
This code works for me (tested on your HTML above):
$('.classRow a[name="' + classID + '"]')
.closest('tr')
.next()
.remove();
Also I'm not sure exactly where this code is executed in your example, but if it's supposed to happen "on load" you need to wait for the DOM to be ready:
$(function() {
// the code snippet here
});

Can this jQuery code snippet be shortened?

I have just started using jQuery and although following code gets the job done, I have a feeling that it can be shortened.
var accountAddress = $(document.createElement("input")).addClass("readOnly")
.attr("contentEditable", "false").attr("id", "d_accountAddress");
$("#customerid_c").next().next().next().append(accountAddress);
If it is not clear - what I'm doing is creating new input tag, assigning class and making it read-only, then positioning new input two TD's to the right of some known text.
Update:
This is simplified HTML that I'm modifying. The place where I add content is marked with ##1## and ##2##.
<TD id=customerid_c>
<LABEL for=customerid>Customer</LABEL>
</TD>
<TD id=customerid_d></TD>
<TD class=ms-crm-Field-Normal>
<LABEL>##1##</LABEL>
</TD>
<TD>##2##</TD>
Yes, it can.
$('#customerid_c').nextAll().eq(2)
.append('<input class="readOnly" id="d_accountAddress" />');
In jQuery 1.4.2, you can write
$('#customerid_c~:eq(2)')
.append('<input class="readOnly" id="d_accountAddress" />');
This selector, which does not work correctly in earlier versions of jQuery, uses the Next Siblings Selector (~) to select all sibling elements following #customerid_c, then uses the :eq selector to select the third (zero-based) element matched by the other selector.
jQuery has a large variety of selectors that can probably replace the indexed sibling. If you show us your HTML, we can find you one.
Other notes:
You can set multiple attributes in one call:
$(something).attr({ id: 'd_accountAddress', type: 'text' });

Categories

Resources