JQuery: select element that contains an element with specific ID - javascript

Apologies if this is a duplicate. It probably is, but I've searched for this specific question and haven't been able to find it.
Let's say I have HTML like so:
<tr>
<td>
<input id="hello">
</td>
<td>
Hello
</td>
</tr>
Using JQuery or Javascript, I want to select the <tr> that contains an input with id="hello".
Here's my attempt so far:
var id = "hello";
var tr = $("tr:has('#" + id + "')");
However, this neither searches for inputs specifically nor seems to work. If you can shed some light on this I'd be very grateful.

Jasper, as haxxxton mentioned in the comments, the .closest() jQuery method is the quickest and simplest method to acheive this.
$('#hello').closest('tr');
$('input[id="hello"]').closest('tr'); // more efficient method than escaping dots if say, your id attribute had periods.

This can be done using the parents() method:
var tr = $('#hello').parents('tr');

Take a look at JQuery's closest() method here.
It traverses up the DOM tree (starting at the current element) until it hits a element which matches the given selector.
Example for your case:
$("#hello").closest("tr")

You can try to get the element by id and then closest() the parent of that element. This seems to be the prefered way in the documentation. Be aware that there can only be one id per page.
Here's an example and a link to the documentation:
var yourElement = $("#hello").closest("tr");
If you browse through the documentation you will find multiple ways of achieving the same result. Hope it helps.

Related

targeting inner html of second element child of a table

I am trying to target the second child element of my table. In this case, I would want to write the inner HTML of the second cell of the row, which is "Travolta." I've used the firstChildElement and lastChildElement with success, but having trouble targeting the second one. Any help would be appreciated! Example code can be found below:
HTML:
<tr class="table-row">
<td>John</td>
<td>Travolta</td>
<td>j.travolta#gmail.com</td>
</tr>
Javascript:
var rowTag = document.getElementsByClassName("table-row");
document.write(rowTag[0].firstElementChild.innerHTML);
--> returns "John"
document.write(rowTag[0].lastElementChild.innerHTML);
--> returns "j.travolta#gmail.com"
Since it's the second element child, perhaps use children[1] (it's a 0-based collection):
var text = rowTag[0].children[1].innerHTML;
Note that firstElementChild and children are supported on modern browsers, but if you have to support IE8, you're stuck with writing a function to skip past non-element nodes.
Get innerHTML like this
var tr = document.getElementsByClassName('table-row');
alert(tr[0].getElementsByTagName('td')[1].innerHTML);
Perhaps rowTag[0].firstElementChild.nextElementSibling.innerHTML
There is a CSS selector, nth-child().
Just put the child number inside the parenthesis.
Using JQuery, here's how this would solve your problem:
$('tr.table-row>td:nth-child(2)') is a straightforward selector to retrieve the required element using JQuery. To set its HTML is simply a matter of using the html() function like this:
$("tr.table-row>td:nth-child(2)").html("SET HTML HERE");

How to clone elements and generate dynamic ids

I am cloning some form elements and want to generate for them dynamic ids so I can acces their content later on, but I don't really know how to do that, I'm a noob with Jquery/Javascript, by the way.
My html:
<tr>
<td>
<label for="ability">Ability</label><br>
<div id="rank_ability" name="rank_ability">
<select name="ability" id="ability">
<option value=""></option>
<option value="hexa">Test</option>
</select><br>
<label for="range_ability_min">Range:</label>
<input type="textbox" name="range_ability_min" id="range_ability_min" class="small_text" value="0" /> -
<input type="textbox" mame="range_ability_max" id="range_ability_max" class="small_text" value="0" /><br>
</div>
Add Ability<br><br>
</td>
</tr>
My JS:
$(document).ready(function () {
var element, ele_nr, new_id;
$('.rank_clone').click( function() {
element = $(this).prev();
ele_nr = $('div[name="'+element.attr('name')+'"]').length;
new_id = element.attr('name') + ele_nr;
element.clone().attr('id', new_id).attr('name', new_id).insertAfter(element);
});
});
I setup a jsfiddle with what I got here: http://jsfiddle.net/xjoo4q96/
Now, I am using .prev() to select the element to clone which leads to those repeated 1 in the id/name attributes, how could I select it in another way (to mention: I really need to use 'this' because I need this little script in like 3 places, so I don't want to write it for an element with a specific id/class).
Also, I am counting only the element with the base name attribute so .lenght yelds 1 all the time, how would I go around counting all of them ? I guess I have to place them in another div or something but I don't know how would I go around couting them even then.
And, at last, how would I go around changing all the name/id attributes of the elements I have in the div ?
I'd appreciate any help. Thanks.
you can put the template in a hidden div like #tmpl, then clone and set the id attr, e.g.
$('#tmpl').children().first().clone().appendTo('#target').attr('id', 'the_generated_id');
Update
Demo of the template way: http://jsfiddle.net/xjoo4q96/1/, though it would be quite easy to adjust the code to clone the first component that already existed.
BTW, principally, id should be unique, thus the sub-element in the cloned component should use other attribute, like class or certain data- attribute, like those used in the updated fiddle.
Also you might want to call event.preventDefault() as you're clicking an <a>
You are searching already with the wrong name, since it still has the number attached. So delete it first, search for element which have a name attribute starting with this name and then use this base name to create a new one.
$(document).ready(function () {
var element, ele_nr, new_id, base_name;
$('.rank_clone').click( function() {
element = $(this).prev();
base_name = element.attr('name').replace(/[0-9]/g, '');
ele_nr = $('div[name^="'+base_name+'"]').length;
new_id = base_name + ele_nr;
element.clone().attr('id', new_id).attr('name', new_id).insertAfter(element);
});
});
And to answer your last question: you can not go around changing all ids of inner elements, it would be invalid HTML. In principal you can do the same with every id, like adding a number. If you have to do the same with all the name attributes depends on what you want to do exactly. If you have to distinguish between the first and second input, which I suggest, you have to change them too.
try to use cloneJs, it's clone ids, names input, and parametre inside functions ids of input must be like id_foo_1, id_foo_2 ,,,, and name be like inputName[0][foo], inputName[1][foo] https://github.com/yagami271/clonejs

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

Pass variable and DOM element to jquery each

I've been struggling with this for a while, and have tried many searches, but haven't found the right solution, nor words for the issue I have.
I wish to traverse the <tr>'s in <table id="Listeners"> with jQuery, and set the rows to either Even or Odd class.
The is yet saved in a variable and passed to the function, as follows:
<table id="Listeners">
<tr><td>1</td></tr>
<tr><td>2</td></tr>
</table>
And my jQuery:
var Element = $("#Listeners");
$(Element+" tr").each(function(index) {
if (index%2 == 0) {
$(this).addClass("Even");
}
});
But that doesn't work, any thoughts on how to solve this?
You can use find() method and :even selector:
Selects even elements, zero-indexed.
var $element = $("#Listeners");
$element.find("tr:even").addClass("Even");
// or $element.find("tr").filter(':even').addClass("Even")
There are many ways to do this. This should work:
$('#Listeners tr:nth-child(even)').addClass("Even");
See: http://api.jquery.com/nth-child-selector/
Even this:
$('#Listeners tr:even').addClass("Even");
See it working here: http://jsfiddle.net/zm2nN/

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
});

Categories

Resources