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: ' ---';
}
Related
I have a nested HTML table. I would like to show parts of the nested table depending on the header clicked using javascript
http://jsfiddle.net/TtWTR/103/
so far it shows all three parts. I want to click header A and show only optionA, click headerB and only show optionB etc etc. Not sure if ive set it up right as all three are showing. thanks
To achieve expected result, use below option oh hide() and show() methods
$('.trigger').click(function() {
console.log($(this).text())
var selectedHdr = $(this).text();
$('.nested tr').hide();
$('.nested tr#'+selectedHdr).show();
});
https://codepen.io/nagasai/pen/vdabJQ
Usually I find it convenient to use CSS class selectors on the "root" element (in your case that would be .toptable) allowing you to toggle it to show and hide child elements.
<table class="toptable">
<tr class="accordion">
<td class="A trigger">A</td>
<td class="B trigger">B</td>
<td class="C trigger">C</td>
</tr>
<tr>
<td>
<table>
<tr class="content A">
<!-- will toggle using show-A -->
</tr>
</table
</td>
</tr>
</table>
Then you can make sure to hide the .content rows using CSS unless specific classes are set on the top table:
.content {
display: none; /* content hidden by default */
}
.show-A .A.content {
display: table; /* show when the parent table has .show-A set */
}
Now you just have to add event listeners to your triggers to toggle the classes for the different content rows:
const toptable = document.querySelector('.toptable');
['A', 'B', 'C'].forEach((group) => {
const trigger = document.querySelector(`.${group}.trigger`);
trigger.addEventListener('click', () => {
toptable.classList.toggle(`show-${group}`);
});
});
This can be done using the following script
$('.nested').hide();
$('tr .trigger').click(function() {
var target_id= "#"+$(this).attr('id')+"-table";
$('.nested').not(target_id).hide();
$(target_id).show();
});
and is shown in http://jsfiddle.net/TtWTR/152/
What I am trying to achieve: What I am trying to achieve is very simple I have a table with 2 table body tags. The first one gets shown as its just the main content. The last td element has an anchor tag, this anchor tag when clicked should show the next tbody tag using the jQuery method slideToggle().
Problem: The problem I am having is these are dynamically made tables using Angular.js. So if there are 5 items then there are 5 div elements each with a table that all have the same class for each tbody within the div. This makes sense as for each I would like the click function to show that specific tables second div if the user wants to see additional content related to that item.
Things tried:
$(this).next('.test').slideToggle();
$(this).closest('tbody').find('.test').slideToggle();
$(this).closest('.test').slideToggle();
$(this).closest('tr').find('.test').slideToggle();
Posts look into on StackOverflow for similar issue:
affect only the clicked element in jquery for multiple elements with same class
Using a class name in jQuery's .closest()
jQuery closest(); not working
Jquery adding click function to several spans with the same Class
Non Stack Overflow sites:
https://www.sitepoint.com/jquerys-closest-parents/
HTML:
<div class="productsList" ng-repeat="products in productListing.products">
<div class="productSection">
<div class="figureDiv">
<figure class="img">
<img ng-src="{{products.image}}" />
</figure>
</div>
<div class="description">
<h2 ng-bind="products.summary"></h2>
<summary ng-bind="products.description"></summary>
</div>
<table class="productTable">
<tbody>
<tr><td><b>Product Name</b></td><td ng-bind="product.merchantName"></td></tr>
<tr><td><b>Valid:</b></td><td>{{products.validityStart}} to {{products.valididtyEnd}}</td></tr>
<tr><td><b>Product Type:</b></td><td>Appliance</td></tr>
<tr><td><b>Testing:</b></td><td>Yes<a class="testLink" href="">Show More ></a></td></tr>
</tbody>
<tbody class="test">
<tr><td><b>Extra</b></td><td>Extra</td></tr>
<tr><td><b>Extra</b></td><td>Extra</td></tr>
<tr><td><b>Extra</b></td><td>Extra</td></tr>
<tr><td><b>Extra</b></td><td>Extra</td></tr>
</tbody>
</table>
</div>
</div>
jQuery (current implementation):
function init() {
jQuery(document).ready(function(){
$(document).on("click", ".productTable .testLink", function (ev) {
ev.stopImmediatePropagation();
$(this).closest('tr').find('.test').slideToggle();
$(".test").slideToggle();
});
}
Visually from Dynamic content (3 items):
Table class="productTable"
tbody
anchor tag class="testLink"
tbody class="test"
Table class="productTable"
tbody
anchor tag class="testLink"
tbody class="test"
Table class="productTable"
tbody
anchor tag class="testLink"
tbody class="test"
Ending
As you can see visually there are 3 tables created each having same classes. So for the first table if the user clicks the anchor tag then the body tag right after in that specific table will be displayed with toggle. Only that one should be shown not all of them which is the current problem.
I tried many solutions however nothing is working, every implementation is making all of them toggle which is horrible.
I think something like this.
$(".productTable .testLink").on("click", function() {
$(this).parents('.productTable').children('.test').slideToggle();
});
.testLink {
color: blue;
text-decoration: underline;
}
.test {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="productTable">
<tbody>
<tr>
<td><b>Product Name</b>
</td>
<td ng-bind="product.merchantName"></td>
</tr>
<tr>
<td><b>Valid:</b>
</td>
<td>{{products.validityStart}} to {{products.valididtyEnd}}</td>
</tr>
<tr>
<td><b>Product Type:</b>
</td>
<td>Appliance</td>
</tr>
<tr>
<td><b>Testing:</b>
</td>
<td>Yes<span class="testLink">Show More ></span>
</td>
</tr>
</tbody>
<tbody class="test">
<tr>
<td><b>Extra</b>
</td>
<td>Extra</td>
</tr>
<tr>
<td><b>Extra</b>
</td>
<td>Extra</td>
</tr>
<tr>
<td><b>Extra</b>
</td>
<td>Extra</td>
</tr>
<tr>
<td><b>Extra</b>
</td>
<td>Extra</td>
</tr>
</tbody>
</table>
I think the problem is in this line of your jQuery $(".test").slideToggle(); as it will execute slideToggle on all .test try removing it. Also update.closest('tr'); to .closest('table'); as the .test is in the table tag not the tr
From what I make out, you are looking for JQuery's .next() method. Just for the parent tbody and call .next()
Example would be
$('.testLink').parentsUntil('tbody').next().show();
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');
}
});
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.
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.