Jquery traversal not working with .closest(), .parent().parent() etc - javascript

I have an annoying problem whereby I can only get the top two parents of an element and it will not go beyond that. .closest() does not work either. When I look at the hierachy it should work according to the specifications outlined in the documentation.
Here is what I have:
<div id="telephonezone" class="bbox">
<table id="phones" cellspacing="0" width="100%">
<thead>
<tr><th width="70">Type</th><th>Phone number</th><th width="30"></th>
</tr></thead>
<tbody><tr style="background-color: rgb(255, 255, 255); background-position: initial initial; background-repeat: initial initial;">
<td class="primaryset">N/A</td>
<td class="primaryset">0208 989 8183</td>
<td class="primaryset">
<img data-id="0" data-dbid="1126" src="images/dandy-color/cancel.png" title="Delete."></td>
</tr>
</tbody>
</table>
</div>
My Jquery:
$('.bbox tr td img').live('click', function(){
id = $(this).attr('data-dbid') ;
cont = $(this).parent().parent().html() ;
alert(cont);
})
cont = $(this).parent().parent().html() ; gets me the contents of the < tr >, but if I try going higher than that I just get undefined. Same results with prevAll, prev, closest or any combination of them.
How do I select the ID of the div at line one when I click on that image inside the td?
html += '><img data-id="'+i+'" data-dbid="'+v[4]+'" src="images/dandy-color/cancel.png" title="Delete." /></td>' ;

Try specifying that you want the first div parent found in all ancestors.
$(this).parents("div:first").attr("id");

Probably you are trying to access deleted element parents. That's why traversal not working.
<a href="#" onclick="$(this).closest('tr').remove(); console.log('this should be null:' + $(this).closest('div'))">
In this example you can not access 'tr's parents since you have removed it from page.

Related

How to change the height of a `<Div>` and its parent `<Td>`

I have the following mark-up inside a third part application. now for this third part application, I can write custom JavaScript and custom css against the generated markup.
<td style="height:75px">
<div style="height: 75px; opacity: 0.99;" id="MSOPictureLibrarySlideshowWebPart_ctl00_ctl40_g_79ca5882_ef72_482a_9f70_94b4a8c6804e_text">
<span id="MSOPictureLibrarySlideshowWebPart_ctl00_ctl40_g_79ca5882_ef72_482a_9f70_94b4a8c6804e_title" class="ms-slideshow-title"></span><br>
</div>
</td>
So how I can modify the height property, for the <div> and its parent <td> from style="height:75px" to style="height:0px"??
This would select all <td> elements, and all <div> elements that are directly inside a <td> and make their height 0px
$("td, td > div").height(0);
Try this first, but, I suspect this will select more things than you intend it to depending on what else is on this page.
If all the div elements have an ID that begins with MSOPictureLibrarySlideshowWebPart then you can start from there by selecting all of those, and then finding the parent elements. Check the jquery docs for how to do partial attribute matching.
$("div[id^='MSOPictureLibrarySlideshowWebPart']").each(function() {
$(this).height(0).parent().height(0);
});
Use .css()!
You can find each <td>, and use .find() to get the <div> element inside of it.
$('td').each(function(){
$(this).css('height', '0px');
$(this).find('div').css('height', '0px');
});
You can use set max-height:0 to the elements to set height 0 using your parent class
Stack Snippet
td,
div {
background: red;
max-height: 0;
}
<td style="height:75px">
<div style="height: 75px; opacity: 0.99;" id="MSOPictureLibrarySlideshowWebPart_ctl00_ctl40_g_79ca5882_ef72_482a_9f70_94b4a8c6804e_text">
<span id="MSOPictureLibrarySlideshowWebPart_ctl00_ctl40_g_79ca5882_ef72_482a_9f70_94b4a8c6804e_title" class="ms-slideshow-title"></span><br>
</div>
</td>

onmouseout not triggering but onmouseover is

Here is a simplified fiddle
I have a table with sub-groupings inside of it. I want these sub-groupings to be hidden until the user clicks the sub-header row, which looks like this:
<tr class="title" name="titleGroup"
onmouseover='this.innerHTML=this.innerHTML.replace("---","+++");'
onmouseout='this.innerHTML=this.innerHTML.replace("+++","---");'
onclick="$('.Group').toggle();">
<td colspan="2">--- Group ---</td>
</tr>
So, onmouseover, should change the row to look like: +++ Group +++
and onmouseout should change it back to: --- Group ---
However, only the onmouseover triggers and I cannot get the text to go back.
I initially had the mouse over/out calling a function, but that has the same result. Also note that this page is dynamically generated so the text is not always "Group".
What am I doing wrong and how can I get onmouseout to reset the text?
Maybe you wanted to use onmouseleave event? :)
The proper use of replace function in your case and onmouseleave event:
<table width="550px">
<tr class="title" name="titleGroup" >
<td
onmouseover='this.innerHTML=this.innerHTML.replace(/-{3}/g,"+");'
onmouseleave='this.innerHTML=this.innerHTML.replace(/\+{3}/g,"-");'
onclick="$('.Group').toggle();"
colspan="2">--- Group ---</td>
</tr>
<tr class="Group" style="display:none;">
<td>
<b>Group</b>
HCS:</td>
<td>
<input type="checkbox" name="did4" />
</td>
</tr>
<tr class="Group" style="display:none;">
<td>
<b>Group</b>
NCD:</td>
<td>
<input type="checkbox" checked="" name="did5" />
</td>
</tr>
</table>
ANOTHER EDIT:
Firefox doesn't support onmouseleave event on TR marks! Move those events deffinition to
<td>
Building off of adeneo's fiddle, using jQuery with mouseleave is the way to go. However, the text could include a - or + so I had to update a bit to specifically look for 3 in a row.
Here is the final jQuery:
$('.title').on('mouseenter mouseleave', function(e) {
$('td', this).text(function(_,txt) {
return txt.replace(/[+]{3}|[-]{3}/g, function(x) {
return x=='---' ? '+++' : '---';
});
});
});
http://jsfiddle.net/jQRR7/29/
Checkout http://jsfiddle.net/jQRR7/30/
This works (at least in webkit browsers, Firefox still to be done)
onmouseover='this.innerHTML=this.innerHTML.replace(/-/g,"+");'
onmouseleave='this.innerHTML=this.innerHTML.replace(/\+/g,"-");'
It contains 2 issues:
a) replace() will replace only 1x, unless you hand over a regular expression (attention: do not surround the regex by quotes!) More about replace() can be found at http://devdocs.io/javascript/global_objects/string/replace DevDocs.io JS replace()
b) mouse over seems to be called, but mouseout just 1x,so only 1 time +++ will be replaced
Can you switch to CSS3 (pseudo elements like :after are supported by all major browser version) or do you need to stick on js?
take a look at http://jsfiddle.net/jQRR7/31/
HTML
<table>
<tr class="title" name="titleGroup" style="background: #c3c3c3" onclick="$('.Group').toggle();">
<td colspan="2">Group with CSS3</td>
</tr>
</table>
CSS
.title td {
font-weight: bold;
text-align: center;
cursor: pointer;
}
td:before{
content: '+++ ';
}
td:after{
content: ' +++';
}
tr:hover td:before{
content: '--- ';
}
tr:hover td:after{
content: ' ---';
}

Using each() for checking which class is clicked

So here's my problem, I'm new to jQuery. What I am trying to do here is check for user to click on a certain table cell/row and it would then display a div named popup of an index the same as the table cell votes. Without having to make separate functions of all the rows in my table.
Using some numerical value will display all the dialogs from a click of the cell of the same value the first time and from the second time only the correct one.
I bet there's some other way to do it and maybe there's just a stupid error.
Using the index value in the click and dialog function won't work.
I am open to suggestions on improvement also.
The scripts:
<script type='text/javascript'>
$(document).ready( function() {
$('.votes').each(function(index) {
$('.votes:eq(index)').click(function() {
$('.popup:eq(index)').dialog();
});
});
});
</script>
HTML for the table part, only a snippet
<td class='votes'>5</td>
<td class='votes'>15</td>
<td class='votes'>25</td>
HTML for the div part, only a snippet of the div:
<div class='popup'>
<ul>
<li>John Johnsson</li>
<li>John Doe</li>
</ul>
</div>
<div class='popup'>
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
jsFiddle Demo
You don't have to iterate using each for .click, that will happen internally. You can use .index() to get the index of the element clicked with reference to its parent.
$('.votes').click(function() {
$('.popup').eq($(this).index()).dialog();
});
Initially, the main problem is that you are not using string concatenation to apply the index to the selector (demo):
$('.votes:eq(index)')
// the Sizzle selector engine doesn't know what the string "index" is.
instead of
$('.votes:eq(' + index + ')')
// using concatenation calls the .toString() method of index to apply "0" (or "1", "2", etc.)
// so that the parsed string becomes '.votes:eq(0)' which the Sizzle selector engine understands
Once the Sizzle selector engine understands which elements to target (demo), the second problem is how jQueryUI changes the DOM with the .dialog method.
Inital markup:
<table>
<tbody>
<tr>
<td class="votes">5</td>
<td class="votes">15</td>
<td class="votes">25</td>
</tr>
</tbody>
</table>
<div class="popup">
<ul>
<li>John Johnsson</li>
<li>John Doe</li>
</ul>
</div>
<div class="popup">
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
Once the first click event is handled, one of the div.popup elements is transformed into a jQueryUI Dialog and is appended to the body, removing it from its initial position, like so:
<table>
<tbody>
<tr>
<td class="votes">5</td>
<td class="votes">15</td>
<td class="votes">25</td>
</tr>
</tbody>
</table>
<div class="popup">
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
<div class="ui-dialog ui-widget ..."> ... </div>
So your initial indexes no longer apply. Fortunately, there are several solutions to both problems (a few of which I've listed below).
Solutions to Problem 1:
Use string concatenation as described above.
Use the .eq method instead, which will accept the index variable as-is
Use a delegate handler instead and grab the index from within the handler:
Example of 2:
$('.votes').eq(index);
Example of 3:
$('table').on('click', '.votes', function (e) {
var vote = $(this),
index = vote.parent().index(vote);
});
Solutions to Problem 2:
Create all of the dialogs initially and open them as needed.
Create the dialogs using a deep clone of the div element. (Not recommended)
Remove the td element to match the removed and re-appended div element. (Not recommended)
Example of 1:
var popups = [];
$('.popup').each(function (i, elem) {
var popup = $(elem).data('index', i).dialog({
"autoOpen": false
});
popups.push(popup)
});
$('table').on('click', '.votes', function (e) {
var vote = $(this),
index = vote.index();
popups[index].dialog('open');
});
I'm sure there are other solutions as well, but these are the ones I thought of of the top of my head.
Functional demo: http://jsfiddle.net/2ChvX/2/
UPDATE:
With your chosen table structure, you're actually looking for the index of the parent tr element as that is what corresponds with the div.popup element. To get the index of the parent tr element, change the line that gets the index from:
index = vote.index();
to:
index = vote.parent().index();
Updated fiddle: http://jsfiddle.net/AZpUQ/1/
Updated
FWIW, here's an example using the jQueryUI dialog (which I presume you are using?) and javascript sectionRowIndex and cellIndex.
Reusable code allowing you to identify the cell the user clicked in and perform appropriate action.
http://jsfiddle.net/KbgcL/1/
HTML:
<table id="myTable">
<tr>
<th>Label:</th>
<th>Washington</th>
<th>Idaho</th>
<th>California</th>
</tr>
<tr>
<td class='label'>Votes</td>
<td class='votes'>5</td>
<td class='votes'>15</td>
<td class='votes'>25</td>
</tr>
<tr>
<td class='label'>Voters</td>
<td class='voters'>5,000</td>
<td class='voters'>15,000</td>
<td class='voters'>25,000</td>
</tr>
</table>
<div id="msg"></div>
jQuery/javascript:
var myTr;
$('#msg').dialog({
autoOpen:false,
title: 'Report:'
});
$('#myTable tr td').click(function() {
myTr = $(this).closest('td').parent()[0].sectionRowIndex;
myCell = this.cellIndex;
myState = $('#myTable').find('tr:eq(0)').find('th:eq(' +myCell+ ')').html();
myVoters = $('#myTable').find('tr:eq(' +myTr+ ')').find('td:eq(' +myCell+ ')').html();
if (myTr==2 && myCell==3){
//California
$('#msg').html('There are ' +myVoters+ ' voters in ' +myState);
$('#msg').dialog('open');
}else if(myTr==1 && myCell==1){
$('#msg').html('There were ' +myVoters+ ' votes made in ' +myState);
$('#msg').dialog('open');
}
});

How to change HTML element value using javascript?

I have DIV and inside div it has table. I want to change the one of the column value of table using java script. I can do it by getting the element id of column, but there is no any id assigned to any table's column. Below is the example.
<div id="usersec">
<TABLE style="TEXT-ALIGN: center; WIDTH: 279px; HEIGHT: 70px">
<TBODY>
<TR>
<TD style="FONT-FAMILY: Verdana" vAlign=center align=middle>Talk to me </TD></TR></TBODY></TABLE>
</div>
Is it possible to change the "Talk to me" text using javascript?
If your userbase is IE8+, you can safely use querySelector:
var container = document.getElementById('usersec');
var td = container.querySelector('tr:first-child > td');
if(td){
td.innerHTML = "New Text!";
}
Here's a JSFIDDLE: http://jsfiddle.net/rgthree/YkhwE/
querySelector (or querySelectorAll) allow you to target elements in the DOM via CSS syntax, which is very useful. It's very well supported, in every current and previous browser. (via Can I Use)
Yes, you need to get the element and then set a new value to element.innerHTML. It's easiest if you give an id to the element that you want to change but you don't need to
jsFiddle
<script type="text/javascript">
var usersec = document.getElementById('usersec');
var td = usersec.getElementsByTagName('td')[0];
td.innerHTML = 'New value';
</script>
You can assign an id to the TD, and use that;
<div id="usersec">
<TABLE style="TEXT-ALIGN: center; WIDTH: 279px; HEIGHT: 70px">
<TBODY>
<TR>
<TD style="FONT-FAMILY: Verdana" vAlign=center align=middle id="cellToChange">Talk to me</TD>
</TR></TBODY></TABLE>
</div>
<script type="text/javascript">
document.getElementById("cellToChange").innerText = "Go on, talk to me please!";
</script>

jQuery .next() elements

This change from mootools drives me crazy.
HTML
<tr class="teamicon">
<td style="text-align: center;" width="100%" valign="middle">
//Blahblah
</td>
</tr>
<tr class="teamval">
<td valign="middle" width="100%">
//Blahblah
</td>
</tr>
What I want to achieve. When with class "teamicon" is clicked I want to show/hide tr with class teamval with animation. However, I can't make it animate properly. Looks like inside "teamval" must be animated first (or am I wrong?).
My try:
jQuery(document).ready(function(){
$('.teamval').slideUp(400);
$('.teamicon').click(function(){
if ($(this).next('tr').is(":hidden"))
{
$(this).next('tr.teamval').$('td').slideDown(400, function(){
$(this).next('tr.teamval').slideDown(400);
});
}
else
{
$(this).next('tr.teamval').$('td').slideUp(400, function(){
$(this).next('tr.teamval').slideUp(400);
});
}
});
});
OFC. This is wrong ("$(this).next('tr.teamval').$('td')" returns error in firebug). How can I achieve this?
I can't swap to div though.
You could do one of:
$(this).next('tr.teamval').slideDown(...) // whole tr
$(this).next('tr.teamval').find('td').slideDown(...) // td descendant
The error is because you are trying to access a $ property on the jQuery element set, which doesn't exist. Instead we can use find, which searches for matching descendants of elements in the current set.
EDIT:
Okay, I think you want:
if ($(this).next('tr').is(":hidden"))
{
var nextTeamval = $(this).next('tr.teamval');
nextTeamval.find('td').slideDown(400, function(){
nextTeamval.slideDown(400);
});
}
The only potential problem is if teamval contains a td within a td (nested table). You can try this jsFiddle demo.

Categories

Resources