Display/Hide DIVs on tablecell hover (javascript) - javascript

I built a table with about 20 cells. Next to the table I want to display a <div> with a description, which should be displayed on hover or on click. There are heaps of solutions available on the web, but none really fits.
I already know I do need JavaScript, so i have my table cell
<td class="des1">Content</td>
and
<div id="des1">my Description1</div>
I add a class to the cells because some descriptions are called by more than one cell.
So, I need a JavaScript function to show the div "des1" on hover/click of all cells of class "des1", and also hide all other descriptions shown before. And that is my problem.
All my descriptions are wrapped in on other div so can I hide all divs in the wrapper and then display the right description. What is the best way to do this (event handling? inline?) Should I use CSS in Addition?
I do not have much experience in Javascript so I would appreciate any help or tips.

There are two basic parts to what you are trying to achieve:
event handling (to do things in response to the user hovering/clicking)
DOM manipulation (to change the description).
I would strongly advise using the jQuery library to help facilitate both of these.
Using jQuery you can easily "bind" an event handler which will do something in response to a cell being clicked or hovered over. For instance:
$('.des1').click(function() {
// Whatever you put here will be triggered when the user clicks on an element
// with class "des1"
});
The hover handler is similar, although slightly more complicated because it lets you specify both what happens when the user starts hovering and when they stop:
$('.des1').hover(function() {
// Whatever you put here will be triggered when the user hovers over an element
// with class "des1"
}, function() {
// Whatever you put here will be triggered when the user stops hovering over an
// element with class "des1"
});
Inside the handlers you'll want to add logic to modify the text of the element with the appropriate ID, which you can do using jQuery's text method:
$('#des1').text('My Description #1');
Combining the two, and sharing a function between them, you get something like:
var showDescription1 = function() {
// Whatever you put here will be triggered when the user clicks on an element
// with class "des1"
};
$('.des1').click(showDescription1)
$('.des1').hover(showDescription1, function() {
// if you want to change the description back when the user stops hovering, you'd
// add that logic here
});

<style>
div.des {
display: none;
}
</style>
<table>
<tr>
<td class="des1">Content 1</td>
</tr>
<tr>
<td class="des2">Content 2</td>
</tr>
<tr>
<td class="des3">Content 3</td>
</tr>
</table>
<div id="des1" class="des">Description 1</div>
<div id="des2" class="des">Description 2</div>
<div id="des3" class="des">Description 3</div>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
$('table td').on('click', function() {
var $des = $('#' + $(this).attr('class')),
visible = $des.hasClass('active');
$('div').hide();
if(visible) {
return;
}
$des
.addClass('active')
.show();
});
</script>

Related

Dynamically insert/remove table rows (including how to give ID's to added rows)

I'm trying to implement a dynamically growing/shrinking table as in the picture. I know I need to use the insertRow() function, but I'm confused about how to dynamically give ID's to the rows. I need to be able to disable the end date input field if the checkbox is checked (that's why the need to give ID's). I need to be able to insert rows and delete rows. I'm fairly experienced in programming concepts but new to JavaScript and web development in general. If anyone could point me to sample code or explain if there is another efficient way of doing it, I'd greatly appreciate it.
http://imgur.com/68t3dH2
An example whitout id, working for each line control,
like you screenshot (id's are just a way among others...)
You can't have multiple identical id's, then
Assuming your action button's are called by their respective classname,
".add" and ".del"
For Removing
$(".del").on("click", function()
{
// removing the line of element clicked
$(this).parents("tr").remove();
});
For a New line
$(".add").on("click", function()
{
var line = $(this).parents("tr"); // get the line of element clicked
var lineOffset = line.index(); // get the offset position of this line
// and using css selector, you can simply add line after another
$("table tr:eq("+lineOffset+")").after(line.clone(true));
// line.clone(true) is an example, but you can put directly your html like "<tr>.... what you want</tr>"
});
Table test
<table>
<tr id="a_0"><td>test0</td><td><span class="del">[X]</span><span class="add">[o]</span></td></tr>
<tr id="a_1"><td>test1</td><td><span class="del">[X]</span><span class="add">[o]</span></td></tr>
<tr id="a_2"><td>test2</td><td><span class="del">[X]</span><span class="add">[o]</span></td></tr>
</table>
(function() {
$(".del").on("click", function() {
// removing the line of element clicked
$(this).parents("tr").remove();
});
$(".add").on("click", function() {
var line = $(this).parents("tr"); // get the line of element clicked
var lineOffset = line.index(); // get the offset position of this line
// and using css selector, you can simply add line after another
$("table tr:eq(" + lineOffset + ")").after(line.clone(true));
// line.clone(true) is an example, but you can put directly your html like "<tr>.... what you want</tr>"
});
})()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<table>
<tr id="a_0">
<td>test0</td>
<td><span class="del">[X]</span><span class="add">[o]</span>
</td>
</tr>
<tr id="a_1">
<td>test1</td>
<td><span class="del">[X]</span><span class="add">[o]</span>
</td>
</tr>
<tr id="a_2">
<td>test2</td>
<td><span class="del">[X]</span><span class="add">[o]</span>
</td>
</tr>
</table>
However, you can see in my example, the ID's beginning by a_*
are not used (yes, it's not necessary and relative as your case)
And another way to make that is to use the jquery method .index()
to get the line offset clicked and.. remove or copy it!
Note :
If you realy need to use a line ID,
well, you can proceed by using css selectors like that:
$("tr[id^='a_']")
IF EMPTIED TABLE
$(".del").on("click", function()
{
// removing the line of element clicked
$(this).parents("tr").remove();
if($("table tr").length == 1) // the only one remaining is the hidden_control (if you doesn't use a external button but a row)
$("#hidden_control").show(); // or .css("display", "block");
});
$("#hidden_control").on("click", function()
{
$("table").append("<tr><td>...</tr>"); // add a new first line
$(this).hide(); // and hide it directly until next reinit
});
// hidden button at top (or bottom) of table (not in the table)
<input type="button" id="hidden_control" value="Refill new data">
// or, hidden row solution (where colspan=6 depend the number of cell you have:
<tr id='hidden_control'><td colspan='6'><button>Refill new data</button></td></tr>
// CSS class for hidden_control
#hidden_control
{ display: none; }
Documentation :
Go on https://api.jquery.com/, and search for "parents", "after", "remove", "append", "html", "index"
Wrap each row with a class or row.
if you want to add:
var form="<div> <input type='text'></div>";
$(document).on('click', ".add", function(){
$(form).insertAfter($(this).closest("#fields"));
});
delete:
$(document).on('click', ".remove", function(){
$(this).closest('div').remove();
});
jsFiddle demo
You don't need ID's for that. The JavaScript handler for the checkbox can locate the End Date field by navigating the DOM tree. Starting at the checkbox, walk up the DOM tree (e.g. parent()) to find the cell (<TD>), then walking the siblings (next() twice), and down to the input field (e.g. find('input')).
As for adding a new row, you can follow the advice of this answer:
$('#myTable tr:last').after('<tr>...</tr><tr>...</tr>');
And you remove a row by calling remove() on the <TR>.

How exactly does this JQuery script work? and how can I modify it to select a specific object?

I am absolutly new in JavaScript and jQuery and I have the following problem.
I have the following jQuery script:
$(document).ready(function () {
$("thead.opening").click(function () {
$(this).next().slideToggle('slow', function () {
$(this).prev("thead.opening").toggleClass("active");
$("thead.opening").find(".imgAccordion").attr("src", "img/arrow.gif");
$("thead.active").find(".imgAccordion").attr("src", "img/arrow_down.gif");
});
return false;
});
});
and in my HTML I have something like this:
<table class="standard-table-cls table-header-cls">
<thead class="opening active">
<tr>
<th>
<img class="imgAccordion" src="img/arrow_down.gif"/>
Ricerca Flussi (la funzione e' consentita per flussi inferiori alle 300 fatture)
</th>
</tr>
</thead>
<tbody class="expanded">
<tr>
<td style="width: 100em;">
SHOW SOMETHING
</td>
</tr>
</tbody>
</table>
...........................................................
...........................................................
...........................................................
<table class="standard-table-cls table-header-cls">
<thead class="opening">
<tr>
<th>
<img class="imgAccordion" src="img/arrow.gif"/>
Ricerca Fatture
</th>
</tr>
</thead>
<tbody class="expanded" style="display: none;">
<tr>
<td style="width: 100em;">
SHOW SOMETHING ELSE
</td>
</tr>
</tbody>
<table>
As you can see in my code there is 2 different tables both having the same classes (standard-table-cls table-header-cls).
When I click on the thead of one of these table it seems to me that the previous script is perfromed (it is right or am I saying wrong assertion?).
I think so because this statment:
$("thead.opening").click(function () {.......
means something like: perform the body of the defined function() when the user click on any thead element having class=opening.
Is it my reasoning correct?
No my doubt (and also the related problem) is: how jQuery know what is the specific thead.opening clicked by the user (the one related to the first table or the one related to the second table)?
What exactly represent the $(this) element in the previous script? (it is the selected object or what?)
And finally, how can I modify the previous script to obtain the reference of the inner tbody of the same table of the thead.opening clicked?
Tnx
I'll keep this as short as possible but this is the scope in the current function. In elements, its an element. So for you?
$("thead.opening").click
runs a function. So the $(this) is the thread.opening that was actually clicked.
Post
this statment ... perform the body of the defined function() when the user click on any thead element having class=opening.
yes that is correct.
how JQuery know what is the specific thead.opening clicked by the user
the answer lies in: $(this).next().slideToggle('slow', function ()....
What exactly represent the $(this) element in the previous script?
the object which is clicked.
obtain the reference of the inner tbody of the same table of the thead.opening clicked
use something similar to the following in the click handler:
$(this).closest('.standard-table-cls').children('tbody')
reference: here and here
hope this helps.
When I click on the thead of one of these table it seems to me that
the previous script is perfromed (it is right or am I saying wrong
assertion?).
You are right
Is it my reasoning correct?
This is correct
What exactly represent the $(this) element in the previous script? (it
it the selected object or what?)
$(this) referes to the element invoking the function $("thead.opening").click(function () {});, so $(this) is equal to $("thead.opening"), where thead.opening is the exact element clicked (not the other thead.opening in your document).
And finnally, how can modify the previous script to obtain the
reference of the inner tbody of the same table of the thead.opening
clicked?
$(this).next() (which is used in your exemple) is the selector to target the tbody. $(this).next()means this (clicked thead), find next sibling element (tbody).
$("thead.opening") returns a array of elements that match the selector, in your case the two separate table headers that have the class opening added to them.
the .click() assigns a click event handler to each of the elements returned by the selector. In your case to both the table headers.
$(this) refers to element which invoked the event in the event handler.
The code $(this).next().slideToggle( is already referencing the next sibling of the thead - in your HTMLs case, the tbody.
You will have to change your script and change selectors. Current $("thead.opening") will for example select all <thead class="opening"> tags, so it would have to be similar to this:
$(document).ready(function () {
$("thead.opening").click(function () {
var thisThead = $(this);
var thisTbody = thisThead.next();
thisTbody.slideToggle('slow', function () {
thisThead.toggleClass("active");
thisThead.find(".imgAccordion").attr("src", thisThead.is('.active') ? "http://placehold.it/30/ffffff/000000" : "http://placehold.it/30/000000/ffffff");
});
});
});
Check this Fiddle with 2 tables.

hiding part of table using javascript without changing the table layout

EDIT: okay I put everything in the script tag in a
$(document).ready(function) {
So now the evenTd's do hide.
I have a table and the code is below
<table>
<tr>
<td>itemOne</td>
<td class="evenTd">itemTwo</td>
</tr>
</table>
Now, I want it so that at the beggining, the first td is the only td which is visible (anything in evenTd should not be visible). After that, I want it so that when you click the first td (itemOne) then itemTwo slides and appears. So far I have
$(document).ready(function() {
$('.evenTd').hide();
});
and it is hiding the evenTd's, however, now the td's which don't have the evenTd class are taking up the entire screen. How do I make it so that the layout doesn't change?
If this is the entirety of your code, and this appears before the relevant elements (whether in the head or body elements, the problem is that the script is run before the DOM nodes exist.
Therefore, you can either place this in $(document).ready():
<script>
$(document).ready(function(){
$('.evenTd').hide();
});
</script>
Or place the script after the elements, in the HTML, upon which you want to act.
<body>
<table>
<tr>
<td>itemOne</td>
<td class="evenTd">itemTwo</td>
</tr>
</table>
<script>
$('.evenTd').hide();
</script>
</body>
Do bear in mind, though, that adding and removing individual table cells is likely to cause layout problems, it's probably better to hide the descendant elements of the relevant td, rather than the td itself.
For example, given the current HTML:
<table>
<tr>
<td>itemOne</td>
<td class="evenTd"><div>itemTwo</div></td>
</tr>
</table>
And:
$(document).ready(function(){
$('.evenTd').hide();
});
This gives: demo, causing the single visible td to take up the whole row-space.
Using the above HTML with the following jQuery:
$(document).ready(function(){
$('.evenTd div').hide();
});
This gives: demo, which still demonstrates layout-changes (because there's no visual content to show inside of the td), but the td remains visible (so it's a marginally-smaller change).
The following jQuery simply makes the content of the td 'hidden' (so it's not visible on the page, but is still 'there' taking up space in the document's flow):
$(document).ready(function(){
$('.evenTd div').css('visibility','hidden');
});
This gives: demo.
I would, however, prefer, certainly if this visibility is to be restored at some point, to add, or remove, a class on the td itself, and use CSS to address the specifics of each state:
$(document).ready(function(){
$('.evenTd').addClass('hidden');
$('tr').on('click', 'td.evenTd', function(){
$(this).toggleClass('hidden');
});
});
JS Fiddle demo.
You need to wait for DOM, before doing any Action:
<script type="JavaScript">
jQuery(document).ready(function(){
jQuery('td').hide().click(function(){
jQuery('td.visible').toggle().removeClass('visible');
jQuery(this).toggle().addClass('visible');
});
jQuery('td')[1].show().addClass('visible');
</script>
To show and hide elements you can use toggle() method.
<td id="cell32">cell data</td>
cell32 = document.getElementById("cell32");
cell32.style.display = "none";

jquery moving rows dynamically with .on

I'm attempting to move rows between two tables, but I cannot get it to keep the click event bound to it. I'm confused on the selector part on the .on event I'm not sure what I'm supposed to be targeting with that.
Basically I can get it to move to one table, and back but then it losses the click property. Not sure why.
I've attached a fiddle(http://jsfiddle.net/Yjqkn/216/) to make the problem clearer. The approve button moves it down, and the waitlist button moves it back, but then it loses all event listeners do I need to rebind them with .bind What is the best way to solve this.
I tried : .on("click","button.remove-participant",function() didn't work
Javascript
$( ":button" ).on("click",function(){
if($(this).hasClass('remove-participant')) {
$(this).removeClass('remove-participant').addClass('add-participant');
$(this).html('Approve');
var current_row = $(this).closest('tr').html();
$('.table_2 > tbody:last').append('<tr>'+current_row+'</tr>');
$(this).closest('tr').remove();
$( ".table_2 .add-participant" ).bind( "click", function() {
$(this).removeClass('add-participant').addClass('remove-participant');
var current_row = $(this).closest('tr').html();
$(this).html('Waitlist');
$('.table_1 > tbody:last').append('<tr>'+current_row+'</tr>');
$(this).closest('tr').remove();
});
}
});
HTML
<table class="table_1">
<tr>
<th>Info Header 1</th><th>Info Header 2</th>
</tr>
<tbody>
<tr><td>Don</td>
<td><button class="remove-participant" name="">Remove</button></td>
</tr>
</tbody>
</table>
<table class="table_2">
<tr>
<th>Info Header 1</th><th>Info Header 2</th>
</tr>
<tbody>
<tr></tr>
</tbody>
</table>
You should use:
$(".table_1").on("click", "button.remove_participant", function() {
...
});
The general idea with event delegation is that you bind the handler to some element(s) that are static in the DOM and will contain all the dynamically added elements. Then the selector argument should specify the more specific dynamic elements that you want to delegate to.
It also doesn't look right that you're binding a click handler to .table_2 .add_participant within the button.remove_participant click handler. Every time you remove a participant, it's going to add another click handler to every .add_participant element, so when you click on those elements the handler will run multiple times. You should delegate the handler just once -- the whole point of delegation is that it picks up dynamic changes so you don't need to redo it every time you modify the DOM.
BTW,
.removeClass('class1').addClass('class2');
can be combined into:
toggleClass('class1 class2');
In my opinion your code is not working is because of your logic. You are here doing this: In table 1, you are removing the class.
$(this).removeClass('remove-participant').addClass('add-participant');
When you click on table 2, and do the same thing. But you never go back and add the remove-participant class in table 1. So the click in Table 1 doesnt not work because class is set to 'add-participant' and not changed back.

Use Jquery to find the parent table, of a table, of a td

I am customising Sage CRM, so I have no control over the HTML that is written and can't add IDs or class's to the table layouts the CRM spits out. I want to hide a higher (not top) level table based on a users selection of a select dropdown. I can only get a jQuery selector hooked onto the title row of a table within the table I want to hide.
The DOM goes something like:
//Lots of other table structures above this in the DOM....
<table> <---- this is the table I want to show or hide based on the users selection
<tbody>
<tr>
<td>
<table>
<tbody>
<tr>
<td class="PANEREPEAT"> <---- this is the node I can get selector to
Valuation information
////
So I do the below client side javascript:
var val_information_screen;
$('.PANEREPEAT').filter(function () {
//Find the valuation information screen
return $(this).text() == 'Valuation information';
}).each(function () { //iterate through all of these (there should only be one!)
val_information_screen = $(this);
});
var sel_ofee_type = $('#ofee_type');
if (sel_ofee_type.val() == '006') {
val_information_screen.closest('table').parents("table:first").show();
} else {
val_information_screen.closest('table').parents("table:first").hide();
}
It does work, it just is not particularly beautiful. The bit that I really detest is below. Is there a better way to traverse up the DOM using jQuery?
val_information_screen.closest('table').parents("table:first").show();
val_information_screen.closest('table').parents("table:first").hide();
If you are sure that it has fixed structure, then you can use this,
$(td-selector).parents("table").eq(1).hide();
In your case,
val_information_screen.parents("table").eq(1).hide();
If your DOM (specifically starting from table you want to hide till the td you have as selector) is pretty much fixed, then the below selector can be used.
$('#element').parents('table').eq(1)

Categories