Simple jQuery selector isn't working - javascript

I'm trying to parse this HTML:
<tr id="a">
<td class="classA">
<span class="classB">Toronto</span>
</td>
<td class="classC">
<span class="classD">Winnipeg</span>
</td>
</tr>
<tr id="b">
<td class="classA">
<span class="classB">Montreal</span>
</td>
<td class="classC">
<span class="classD">Calgary</span>
</td>
</tr>
I have a variable team. I want to find the <span> that contains team. Then I want to navigate up to the <tr> and pull the id from it.
I tried:
var team = "Toronto";
var id = $("span:contains(" + team + ")").parent().parent().attr('id');
But it comes back undefined. I know the selector is right, because $("span:contains(" + team + ")").attr('class') comes back with classB. So I can't figure out what's wrong with my query. Can anyone help?
Edit: Here's the JSFiddle.

Your html is invalid but your selector is correct, you need to put tr in table tag for valid html. You better use closest("tr") instead of .parent().parent()
Live Demo
<table>
<tr id="a">
<td class="classA"> <span class="classB">Toronto</span>
</td>
<td class="classC"> <span class="classD">Winnipeg</span>
</td>
</tr>
<tr id="b">
<td class="classA"> <span class="classB">Montreal</span>
</td>
<td class="classC"> <span class="classD">Calgary</span>
</td>
</tr>
</table>

It's not working becuase the browser's automatically fixing your HTML. You can't have a TR without a table so it's just throwing it away. All that's actually part of the DOM by the time your JavaScript runs is the spans.
Wrap it in a <table> and your code will work. Even better wrap it in <table><tbody> because the browser will still be making a tbody for you with just a table & that might cause confusion next (If you look at the parent of the TR).

Currently your HTML markup is invalid, you need to wrap <tr> element inside <table>:
<table>
<tr id="a">
<td class="classA"> <span class="classB">Toronto</span>
</td>
<td class="classC"> <span class="classD">Winnipeg</span>
</td>
</tr>
<tr id="b">
<td class="classA"> <span class="classB">Montreal</span>
</td>
<td class="classC"> <span class="classD">Calgary</span>
</td>
</tr>
</table>
Also, it's better to use .closest() as well as .prop() instead of .parent() and .attr()
var id = $("span:contains(" + team + ")").closest('tr').prop('id');
Fiddle Demo

try:
var id = $("span:contains(" + team + ")").parent('td').parent('tr').attr('id');

Your code works good.Just wrap your code into <table></table>
HTML
<table>
<tr id="a">
<td class="classA">
<span class="classB">Toronto</span>
</td>
<td class="classC">
<span class="classD">Winnipeg</span>
</td>
</tr>
<tr id="b">
<td class="classA">
<span class="classB">Montreal</span>
</td>
<td class="classC">
<span class="classD">Calgary</span>
</td>
</tr>
</table>
Script
var team = "Toronto";
var id = $("span:contains(" + team + ")").closest('tr').prop('id');
console.log(id)
http://jsfiddle.net/7Eh7L/
Better use closest()
$("span:contains(" + team + ")").closest('tr').prop('id');

Related

Copy some <tr> in html by js

I'm need to copy some tr with inputs when onclick event is triggered, by clean JavaScript, not jQuery or something else, and generate ids for inputs. I attached my html. I'm new in js, whole what I found its copy one element. I'm be gradfull for any help.
<tr id='needToCopy'>
<tr style='height:16.5pt'>
<td></td>
<td colspan="" class="s4">
Label
</td>
</tr>
<tr style='height:18pt'>
<td></td>
<td colspan="3" class="s17">
Label1
</td>
<td class="s6">
<input id="firstID"/>
</td>
</tr>
<tr style='height:60.0pt'>
<td></td>
<td class="s15" colspan="3">
label2
</td>
<td class="s14">
<input id="secondID"/>
</td>
</tr>
<tr style='height:18.0pt'>
<td></td>
<td class="s15" colspan="3">
label3
</td>
<td class="s14">
<input id=thirdId"/>
</td>
</tr>
</tr>
<button onclick="copy()">Press Me</button>
If you are looking to copy the entire contents of the table, you can do it with a small bit of javascript. As mentioned in the comments, you can't have a table row inside a table row, so I'm not sure if you wanted your labels as table tds? For demo purposes I changed the surround <tr> to <table> tags. You can see the 'copy' functionality working in the snippet. I also added an id to your button.
EDIT: 2nd version is probably closer to what you're looking for (layout wise)
document.getElementById('copybtn').addEventListener('click', copybtn, false);
function copy() {
var html = $('#needToCopy').html();
$('#needToCopy tr:last').after("<tr>" + html + "</tr>");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<!--<table id='needToCopy'>
<tr style='height:16.5pt'>
<td></td>
<td colspan="" class="s4">
Label
</td>
</tr>
<tr style='height:18pt'>
<td></td>
<td colspan="3" class="s17">
Label1
</td>
<td class="s6">
<input id="firstID" />
</td>
</tr>
<tr style='height:60.0pt'>
<td></td>
<td class="s15" colspan="3">
label2
</td>
<td class="s14">
<input id="secondID" />
</td>
</tr>
<tr style='height:18.0pt'>
<td></td>
<td class="s15" colspan="3">
label3
</td>
<td class="s14">
<input id="thirdId" />
</td>
</tr>
</table>-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<h2>Labels</h2>
<table id='needToCopy'>
<tr style='height:18pt'>
<td>Label 1</td>
<td>Label 2</td>
<td>Label 3</td>
</tr>
<tr style='height:60.0pt'>
<td class="s6">
<input id="firstID">
</td>
<td class="s15">
<input id="secondID" />
</td>
<td class="s14">
<input id="thirdId" />
</td>
</tr>
</table>
<button id="copybtn" onclick="copy()">Press Me</button>
cloneNode if you want to make copy of same node in html.
var div = document.getElementById('div_id'),
clone = div.cloneNode(true); // true means clone all childNodes and all event handlers
clone.id = "some_id";
document.body.appendChild(clone);
It's quite simple if you want to copy a element inside
just use this code:
$("#IDTag").clone();
if you wish to prepend or append it, you can do that too by using:
$('#td').prependTo('#IDTag');
Be sure to give a ID to your element before you expect the results!

removing the td with JavaScript

Is there a way to remove the td(please see commented td"to be removed") from this table without editing the HTML.
Also, not using only the classes as I have the same classes in another tables that I don't need to be removed, so targeting the span id as well. Thanks in advance!
<div id="pnlPersonalDetails2">
</div><table cellpadding="0" cellspacing="0" border="0" class="surveyquestions">
<tbody><tr>
<td colspan="2" class="pd_question">
<span id="lbl2"></span>
</td>
</tr><tr>
<td class="pd_label">FIRST NAME<span class="red"> *</span></td>
<td>
<input name="Name微statictext_2" type="text" id="Name微statictext_2" class="pd_textbox">
</td>
<!-- To be removed
<td class="error_label">
<span id="ctl03" style="visibility:hidden;">Required Field</span>
</td>-->
</tr>
</tbody></table>
<div id="pnlPersonalDetails3">
</div><table cellpadding="0" cellspacing="0" border="0" class="surveyquestions">
<tbody><tr>
<!-- To be removed
<td colspan="2" class="pd_question">
<span id="lbl3"></span>
</td>-->
</tr><tr>
<td class="pd_label">LAST NAME<span class="red"> *</span></td>
<td>
<input name="Name微statictext_3" type="text" id="Name微statictext_3" class="pd_textbox">
</td>
<td class="error_label">
<span id="ctl04" style="visibility:hidden;">Required Field</span>
</td>
</tr>
This is how it looks now
enter image description here
This is how I want to look after removing the commented td's
enter image description here
I have attached the entire code here https://codepen.io/duicug/pen/VGreQZ
<td id="hideTD" class="error_label" style="visibility: hidden;">
<span id="ctl03" style="visibility:hidden;">Required Field</span>
</td>
<script>
document.getElementById("hideTD").style.visibility = "hidden";
</script>
You can refer this website , good sample https://www.w3schools.com/jsref/prop_style_display.asp
Hope that can help you.
<td class="error_label">
<span id="ctl03" style="visibility:hidden;">Required Field</span>
</td>
<td colspan="2" class="pd_question">
<span id="lbl3"></span>
</td>
<script>
document.getElementById("ctl03").parentElement.remove();
document.getElementById("lbl3").parentElement.remove();
</script>
You could use querySelector to find the class such:
var target = document.querySelector("#pnlPersonalDetails2 .error_label");
There are then multiple ways to remove it from the DOM.
You could leave it in memory so that you can easily show it again later:
target.style.display = "none"; //Undo by setting to "" or to previous value
Or you could make it invisible which leaves it in memory and change the layout of surrounding contents:
target.style.visibility = "hidden"; //Undo by setting to "" or to previous value
Or you could completely remove it from the DOM:
target.parent.removeChild(target);
try it with jquery:
$("#lbl2").toggle();
maybe this will help you?
var el = document.getElementById('lbl2');
el.parentElement.hidden = true;
or remove td
var el = document.getElementById('ctl03');
el.parentElement.remove();

Click event on AJAX generated content

I have a link in my HTML that I want to trigger using a click event in jQuery. This content is generated with AJAX. I know that I'm supposed to use .on, so that's what I'm doing. My code does fire on the td when I use this code:
$(".onestepcheckout-summary").on("click", ".wider", function() {
alert('success');
return false;
});
But it's supposed to fire on the anchor tag with the class addsqty. I've tried multiple things like changing the .wider to .wider > a and .wider > .addsqty or simple .addsqty. Why doesn't this work?
Here is my HTML. The AJAX loaded content starts with <table class="onestepcheckout-summary">.
<div class="onestepcheckout-summary">
<table class="onestepcheckout-summary">
<thead>
<tr>
<th class="name" colspan="2">Artikel</th>
<th class="qty">Stück</th>
<th></th>
<th class="total">Zwischensumme</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name">
Simpel product </td>
<td class="editcart">
-
</td>
<td class="qty" nowrap="">
<input type="hidden" value="5" id="qty_46" name="cart[46][qty]" class="qtyinput" size="1">
5 </td>
<td class="editcart wider" nowrap="">
+
</td>
<td class="total">
<span class="price">€ 10,00</span> </td>
</tr>
</tbody></table>
<table class="onestepcheckout-totals">
<tbody><tr>
<td style="" class="a-right" colspan="1">
Zwischensumme </td>
<td style="" class="a-right">
<span class="price">€ 145,00</span> </td>
</tr>
<tr>
<td style="" class="a-right" colspan="1">
<strong>Gesamtbetrag</strong>
</td>
<td style="" class="a-right">
<strong id="total-price"><span class="price">€ 145,00</span></strong>
</td>
</tr>
</tbody></table>
</div>
dynamic content never got the click event :
for this you need to use on , bind and delegate:
i always prefer Delegate. Try This :
$("body").delegate(".wider", "click", function() {
alert('success');
return false;
});
You could try in such a way also
$(document).on("click", '.onestepcheckout-summary',function (event) {
// whatever u want ...
});
Change parent div classname also , it seems like both have same class name.
<div class="div-class">
<table class="table-class">
......
</table>
</div>
$('.div-class').on("click", '.onestepcheckout-summary',function (event) {
// whatever u want ...
});

Jquery DIV count

I am trying to count the number of elements under a parent but its giving me an incorrect count. The result should be 2, where as its returning me 4.
My HTML structure is:
<div style="overflow: hidden;" id="parentDiv" class="scroll">
<div id="3">
<table id="t3" class="Table">
<tbody>
<tr>
<td id="b3" class="bY"><table id="inner1" width="100%" cellpadding="3">
<tbody>
<tr>
<td class="code" id="code3" width="172"></td>
<td class="Num" id="Num3" width="50"></td>
<td colspan="2" class="Name" id="Name"></td>
</tr>
<tr>
<td class="code" width="172"></td>
<td> </td>
<td class="serial" width="110"></td>
<td class="serial" width="322"></td>
</tr>
</tbody>
</table></td>
</tr>
</tbody>
</table>
</div>
<div id="4" >
<table id="t4" class="Table">
<tbody>
<tr>
<td id="b4" class="bY"><table id="inner1" width="100%" cellpadding="3">
<tbody>
<tr>
<td class="code" id="code4" width="172"></td>
<td class="Num" id="Num4" width="50"></td>
<td colspan="2" class="Name" id="Name"></td>
</tr>
<tr>
<td class="code" width="172"> </td>
<td> </td>
<td class="serial" width="110"></td>
<td class="serial" width="322"></td>
</tr>
</tbody>
</table></td>
</tr>
</tbody>
</table>
</div>
and the code I am using to count is:
var numofDivs = $("#parentDiv div").size();
alert(numofDivs);
and if I am using the following code, the result is coming 1 (which is incorrect too).
var numofDivs = $("#parentDiv > div").size();
alert(numofDivs);
Hi you should use the function children()
$("#parentDiv").children("div").length
the function gives you an array and ten you can get the length.
and in the children function you can specify what tags to filter, but you can also leave it blank and it will give you all the children
check the API
With the give HTML code, your code to count the elements is correct, and both ways should return two.
So, the conclusion is that the HTML code doesn't actually look the way that you describe it. A structure that would give that result could for example look like this:
<div id="parentDiv">
<div>
<div></div>
<div></div>
</div>
<p>
<div>
</div>
</p>
</div>
If you want to count the first level of div elements that you encounter, you would have to do it recursively, i.e. for each child element check if it's a div element or count the number of first level div elements it contains:
function countDivs(element) {
var cnt = 0;
$(element).children().each(function(){
cnt += this.tagName === 'DIV' ? 1 : countDivs(this);
})
return cnt;
}
$(function(){
alert(countDivs($('#parentDiv').get(0)));
});

jQuery Traversing

My page has this design.
<tr id="master">
<td id="row1"> <textbot> </td>
<td id="row2"> <linkbutton> </td>
</tr>
I am cloning the same TR onclick of the link button and the current link button will be hidden. so a new row will be created.
consider I have cloned thrice
<tr id="master">
<td id="row1"> <textbot> </td>
<td id="row2"> <linkbutton> </td>
</tr>
<tr id="master">
<td id="row1"> <textbot> </td>
<td id="row2"> <linkbutton> </td>
</tr>
<tr id="master">
<td id="row1"> <textbot> </td>
<td id="row2"> <linkbutton> </td>
</tr>
Now I want to show the second row's link button.
I am trying with
$(this).parents('#master :last').prev().children('#row2).show();
But its not working.
You can't/shouldn't clone elements that have IDs, because IDs are supposed to be unique in a document. Although a browser will happily let you have the same ID twice, Javascript and jQuery do not forgive you for this and things will not work as expected. The proper way to group elements is by classes.
So if you switch your code to this:
<tr class="master">
<td class="row1"> <textbot> </td>
<td class="row2"> <linkbutton> </td>
</tr>
Your selector might look like this:
$('tr.master').eq(1).find('td.row2').show();
you know, ID must be unique .. so i recommend to change all id to class.
i think the syntax for parrent should :
$('#master:parent');

Categories

Resources